Project

General

Profile

Download (37.8 KB) Statistics
| Branch: | Tag: | Revision:
1 417fc5c4 Scott Ullrich
<?php 
2
/*
3 5b237745 Scott Ullrich
	util.inc
4 417fc5c4 Scott Ullrich
	part of the pfSense project (http://www.pfsense.com)
5 98bbf05a Scott Ullrich
6 417fc5c4 Scott Ullrich
	originally part of m0n0wall (http://m0n0.ch/wall)
7 5b237745 Scott Ullrich
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9 98bbf05a Scott Ullrich
10 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12 98bbf05a Scott Ullrich
13 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15 98bbf05a Scott Ullrich
16 5b237745 Scott Ullrich
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19 98bbf05a Scott Ullrich
20 5b237745 Scott Ullrich
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31
32 523855b0 Scott Ullrich
/*
33
	pfSense_BUILDER_BINARIES:	/bin/ps	/bin/kill	/usr/bin/killall	/sbin/ifconfig	/usr/bin/netstat
34
	pfSense_BUILDER_BINARIES:	/usr/bin/awk	/sbin/dmesg		/sbin/ping /usr/local/sbin/gzsig	/usr/sbin/arp
35
	pfSense_BUILDER_BINARIES:	/sbin/conscontrol	/sbin/devd	/bin/ps
36
	pfSense_MODULE:	utils
37
*/
38
39 5b237745 Scott Ullrich
/* kill a process by pid file */
40
function killbypid($pidfile) {
41 435a418f Ermal
	return sigkillbypid($pidfile, "TERM");
42 5b237745 Scott Ullrich
}
43
44 53aca1fd Scott Ullrich
function isvalidpid($pid) {
45 0e604b3a Ermal
	$output = "";
46 29b97efa Ermal
	exec("/bin/pgrep -nF {$pid}", $output, $retval);
47 0e604b3a Ermal
48 5bbd08e1 Warren Baker
	return (intval($retval) == 0);
49 53aca1fd Scott Ullrich
}
50
51 6dc3a5c2 Ermal Lu?i
function is_process_running($process) {
52 01d4b621 Ermal
	$output = "";
53 29b97efa Ermal
	exec("/bin/pgrep -anx {$process}", $output, $retval);
54 6dc3a5c2 Ermal Lu?i
55 5bbd08e1 Warren Baker
	return (intval($retval) == 0);
56 6dc3a5c2 Ermal Lu?i
}
57
58 53aca1fd Scott Ullrich
function isvalidproc($proc) {
59 ba8495f0 Ermal
	return is_process_running($proc);
60 53aca1fd Scott Ullrich
}
61
62 5b237745 Scott Ullrich
/* sigkill a process by pid file */
63 53aca1fd Scott Ullrich
/* return 1 for success and 0 for a failure */
64 5b237745 Scott Ullrich
function sigkillbypid($pidfile, $sig) {
65 ba8495f0 Ermal
	if (is_file($pidfile))
66
		return mwexec("/bin/pkill -{$sig} -F {$pidfile}", true);
67
68 53aca1fd Scott Ullrich
	return 0;
69
}
70
71
/* kill a process by name */
72
function sigkillbyname($procname, $sig) {
73
	if(isvalidproc($procname))
74 73239086 Seth Mos
		return mwexec("/usr/bin/killall -{$sig} " . escapeshellarg($procname), true);
75 5b237745 Scott Ullrich
}
76
77
/* kill a process by name */
78
function killbyname($procname) {
79 123f030c Chris Buechler
	if(isvalidproc($procname)) 
80 53aca1fd Scott Ullrich
		mwexec("/usr/bin/killall " . escapeshellarg($procname));
81 5b237745 Scott Ullrich
}
82
83 a368a026 Ermal Lu?i
function is_subsystem_dirty($subsystem = "") {
84
	global $g;
85
86
	if ($subsystem == "")
87
		return false;
88
89
	if (file_exists("{$g['varrun_path']}/{$subsystem}.dirty"))
90
		return true;
91
92
	return false;
93
}
94
95
function mark_subsystem_dirty($subsystem = "") {
96
	global $g;
97
98
	if (!file_put_contents("{$g['varrun_path']}/{$subsystem}.dirty", "DIRTY"))
99
		log_error("WARNING: Could not mark subsystem: {$subsytem} dirty");
100
}
101
102
function clear_subsystem_dirty($subsystem = "") {
103
	global $g;
104
105
	@unlink("{$g['varrun_path']}/{$subsystem}.dirty");
106
}
107
108 0027de0a Ermal Lu?i
function config_lock() {
109
	return;
110
}
111
function config_unlock() {
112
	return;
113
}
114
115
/* lock configuration file */
116 b6c34bfc Ermal
function lock($lock, $op = LOCK_SH) {
117 9e7ef1a5 Scott Ullrich
	global $g, $cfglckkeyconsumers;
118
	if (!$lock)
119
		die("WARNING: You must give a name as parameter to lock() function.");
120
	if (!file_exists("{$g['tmp_path']}/{$lock}.lock"))
121
		@touch("{$g['tmp_path']}/{$lock}.lock");
122
	$cfglckkeyconsumers++;
123 b6c34bfc Ermal
	if ($fp = fopen("{$g['tmp_path']}/{$lock}.lock", "w")) {
124
		if (flock($fp, $op))
125 9e7ef1a5 Scott Ullrich
			return $fp;
126 b6c34bfc Ermal
		else
127
			fclose($fp);
128 9e7ef1a5 Scott Ullrich
	}
129 0027de0a Ermal Lu?i
}
130
131
/* unlock configuration file */
132
function unlock($cfglckkey = 0) {
133 9e7ef1a5 Scott Ullrich
	global $g, $cfglckkeyconsumers;
134
	flock($cfglckkey, LOCK_UN);
135 cb6fd90b Ermal Lu?i
	fclose($cfglckkey);
136 9e7ef1a5 Scott Ullrich
	return;
137 0027de0a Ermal Lu?i
}
138
139 0ae6daf8 Ermal
function send_event($cmd) {
140
	global $g;
141
142 1015b3a9 Warren Baker
	if(!isset($g['event_address']))
143
		$g['event_address'] = "unix:///var/run/check_reload_status";
144
		
145 838feb14 Ermal
	$try = 0;
146
	while ($try < 3) {
147
		$fd = @fsockopen($g['event_address']);
148
		if ($fd) {
149
			fwrite($fd, $cmd);
150
			$resp = fread($fd, 4096);
151
			if ($resp != "OK\n")
152
				log_error("send_event: sent {$cmd} got {$resp}");
153
			fclose($fd);
154
			$try = 3;
155
		} else
156
			mwexec_bg("/usr/bin/nice -n20 /usr/local/sbin/check_reload_status");
157
		$try++;
158 0ae6daf8 Ermal
	}
159
}
160
161
function send_multiple_events($cmds) {
162 1015b3a9 Warren Baker
	global $g;
163 0ae6daf8 Ermal
164 1015b3a9 Warren Baker
	if(!isset($g['event_address']))
165
		$g['event_address'] = "unix:///var/run/check_reload_status";
166
			
167 0ae6daf8 Ermal
	if (!is_array($cmds))
168
		return;
169 e5d8aeb6 Ermal
170
	foreach ($cmds as $cmd)
171
		send_event($cmd);
172 0ae6daf8 Ermal
}
173
174 ef3af02e Ermal Lu?i
function refcount_init($reference) {
175 e1b068d7 Ermal
	$shmid = @shmop_open($reference, "c", 0644, 10);
176
	@shmop_write($shmid, 0, 0);
177
	@shmop_close($shmid);
178 ef3af02e Ermal Lu?i
}
179
180
function refcount_reference($reference) {
181 e1b068d7 Ermal
	try {
182
		$shmid = @shmop_open($reference, "w", 0, 0);
183
		if (!$shmid) {
184
			refcount_init($reference);
185
			$shmid = @shmop_open($reference, "w", 0, 0);
186
		}
187
		$shm_data = @shmop_read($shmid, 0, 10);
188 8420f4fe Ermal
		if (intval($shm_data) < 0)
189
			$shm_data = 0;
190 e1b068d7 Ermal
		$shm_data = intval($shm_data) + 1;
191
		@shmop_write($shmid, $shm_data, 0);
192
		@shmop_close($shmid);
193
	} catch (Exception $e) {
194
		log_error($e->getMessage());
195 a45e27ba Ermal
	}
196 e1b068d7 Ermal
		
197 ef3af02e Ermal Lu?i
	return $shm_data;
198
}
199
200
function refcount_unreference($reference) {
201 e1b068d7 Ermal
	try {
202
		/* We assume that the shared memory exists. */
203
		$shmid = @shmop_open($reference, "w", 0, 0);
204
		$shm_data = @shmop_read($shmid, 0, 10);
205
		$shm_data = intval($shm_data) - 1;
206
		if ($shm_data < 0) {
207 582934a9 Ermal
			//log_error("MISUAGE OF REFCOUNT_API: trace " . print_r(debug_backtrace(), true));
208 e1b068d7 Ermal
			log_error("Reference {$reference} is going negative, not doing unreference.");
209
		} else
210
			@shmop_write($shmid, $shm_data, 0);
211
		@shmop_close($shmid);
212
	} catch (Exception $e) {
213
		log_error($e->getMessage());
214
	}
215 f2f0a748 Ermal Lu?i
	
216
	return $shm_data;
217 ef3af02e Ermal Lu?i
}
218
219 1ab56363 Ermal Lu?i
function is_module_loaded($module_name) {
220 de5de07c Ermal Lu?i
	$running = `/sbin/kldstat | grep {$module_name} | /usr/bin/grep -v grep | /usr/bin/wc -l`;
221 1ab56363 Ermal Lu?i
	if (intval($running) >= 1)
222
		return true;
223
	else
224
		return false;
225
}
226
227 5b237745 Scott Ullrich
/* return the subnet address given a host address and a subnet bit count */
228
function gen_subnet($ipaddr, $bits) {
229
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
230
		return "";
231 98bbf05a Scott Ullrich
232 5b237745 Scott Ullrich
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
233
}
234
235
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
236
function gen_subnet_max($ipaddr, $bits) {
237
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
238
		return "";
239 98bbf05a Scott Ullrich
240 96033063 Erik Fonnesbeck
	return long2ip32(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
241 5b237745 Scott Ullrich
}
242
243
/* returns a subnet mask (long given a bit count) */
244
function gen_subnet_mask_long($bits) {
245
	$sm = 0;
246
	for ($i = 0; $i < $bits; $i++) {
247
		$sm >>= 1;
248
		$sm |= 0x80000000;
249
	}
250
	return $sm;
251
}
252
253
/* same as above but returns a string */
254
function gen_subnet_mask($bits) {
255
	return long2ip(gen_subnet_mask_long($bits));
256
}
257
258 96033063 Erik Fonnesbeck
/* Convert long int to IP address, truncating to 32-bits. */
259
function long2ip32($ip) {
260
	return long2ip($ip & 0xFFFFFFFF);
261
}
262
263
/* Convert IP address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. */
264
function ip2long32($ip) {
265
	return ( ip2long($ip) & 0xFFFFFFFF );
266
}
267
268 ecd1f2d9 jim-p
/* Convert IP address to unsigned long int. */
269
function ip2ulong($ip) {
270 96033063 Erik Fonnesbeck
	return sprintf("%u", ip2long32($ip));
271 ecd1f2d9 jim-p
}
272
273
/* Find out how many IPs are contained within a given IP range
274
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
275
 */
276
function ip_range_size($startip, $endip) {
277
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
278
		// Operate as unsigned long because otherwise it wouldn't work
279
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
280
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
281
	}
282
	return -1;
283
}
284
285
/* Find the smallest possible subnet mask which can contain a given number of IPs
286
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
287
 */
288
function find_smallest_cidr($number) {
289
	$smallest = 1;
290
	for ($b=32; $b > 0; $b--) {
291
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
292
	}
293
	return (32-$smallest);
294
}
295
296
/* Return the previous IP address before the given address */
297
function ip_before($ip) {
298 96033063 Erik Fonnesbeck
	return long2ip32(ip2long($ip)-1);
299 ecd1f2d9 jim-p
}
300
301
/* Return the next IP address after the given address */
302
function ip_after($ip) {
303 96033063 Erik Fonnesbeck
	return long2ip32(ip2long($ip)+1);
304 ecd1f2d9 jim-p
}
305
306
/* Return true if the first IP is 'before' the second */
307
function ip_less_than($ip1, $ip2) {
308
	// Compare as unsigned long because otherwise it wouldn't work when
309
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
310
	return ip2ulong($ip1) < ip2ulong($ip2);
311
}
312
313
/* Return true if the first IP is 'after' the second */
314
function ip_greater_than($ip1, $ip2) {
315
	// Compare as unsigned long because otherwise it wouldn't work
316
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
317
	return ip2ulong($ip1) > ip2ulong($ip2);
318
}
319
320
/* Convert a range of IPs to an array of subnets which can contain the range. */
321
function ip_range_to_subnet_array($startip, $endip) {
322
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
323
		return array();
324
	}
325
326
	// Container for subnets within this range.
327
	$rangesubnets = array();
328
329
	// Figure out what the smallest subnet is that holds the number of IPs in the given range.
330
	$cidr = find_smallest_cidr(ip_range_size($startip, $endip));
331
332
	// Loop here to reduce subnet size and retest as needed. We need to make sure
333
	//   that the target subnet is wholly contained between $startip and $endip.
334
	for ($cidr; $cidr <= 32; $cidr++) {
335
		// Find the network and broadcast addresses for the subnet being tested.
336
		$targetsub_min = gen_subnet($startip, $cidr);
337
		$targetsub_max = gen_subnet_max($startip, $cidr);
338
339
		// Check best case where the range is exactly one subnet.
340
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
341
			// Hooray, the range is exactly this subnet!
342
			return array("{$startip}/{$cidr}");
343
		}
344
345
		// These remaining scenarios will find a subnet that uses the largest
346
		//  chunk possible of the range being tested, and leave the rest to be
347
		//  tested recursively after the loop.
348
349
		// Check if the subnet begins with $startip and ends before $endip
350
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
351
			break;
352
		}
353
354
		// Check if the subnet ends at $endip and starts after $startip
355
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
356
			break;
357
		}
358
359
		// Check if the subnet is between $startip and $endip
360
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
361
			break;
362
		}
363
	}
364
365
	// Some logic that will recursivly search from $startip to the first IP before the start of the subnet we just found.
366
	// NOTE: This may never be hit, the way the above algo turned out, but is left for completeness.
367
	if ($startip != $targetsub_min) {
368
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array($startip, ip_before($targetsub_min)));
369
	}
370
371
	// Add in the subnet we found before, to preserve ordering
372
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
373
374
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
375
	if ($endip != $targetsub_max) {
376
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
377
	}
378
	return $rangesubnets;
379
}
380
381
function is_iprange($range) {
382
	if (substr_count($range, '-') != 1) {
383
		return false;
384
	}
385
	list($ip1, $ip2) = explode ('-', $range);
386
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
387
}
388
389 5b237745 Scott Ullrich
function is_numericint($arg) {
390
	return (preg_match("/[^0-9]/", $arg) ? false : true);
391
}
392
393
/* returns true if $ipaddr is a valid dotted IPv4 address */
394
function is_ipaddr($ipaddr) {
395
	if (!is_string($ipaddr))
396
		return false;
397 98bbf05a Scott Ullrich
398 5b237745 Scott Ullrich
	$ip_long = ip2long($ipaddr);
399 96033063 Erik Fonnesbeck
	$ip_reverse = long2ip32($ip_long);
400 98bbf05a Scott Ullrich
401 5b237745 Scott Ullrich
	if ($ipaddr == $ip_reverse)
402
		return true;
403
	else
404
		return false;
405
}
406
407 87f0be87 Chris Buechler
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
408 5b237745 Scott Ullrich
function is_ipaddroralias($ipaddr) {
409 1e578a7f Ermal Lu?i
	global $config;
410 87f0be87 Chris Buechler
411 1e578a7f Ermal Lu?i
	if (is_alias($ipaddr)) {
412
		if (is_array($config['aliases']['alias'])) {
413
			foreach ($config['aliases']['alias'] as $alias) {
414 5bbd08e1 Warren Baker
				if ($alias['name'] == $ipaddr && $alias['type'] != "port")
415 1e578a7f Ermal Lu?i
					return true;
416
			}
417 5bbd08e1 Warren Baker
		}
418 1e578a7f Ermal Lu?i
		return false;
419
	} else
420 87f0be87 Chris Buechler
		return is_ipaddr($ipaddr);
421
422 5b237745 Scott Ullrich
}
423
424
/* returns true if $subnet is a valid subnet in CIDR format */
425
function is_subnet($subnet) {
426
	if (!is_string($subnet))
427
		return false;
428 98bbf05a Scott Ullrich
429 5b237745 Scott Ullrich
	list($hp,$np) = explode('/', $subnet);
430 98bbf05a Scott Ullrich
431 5b237745 Scott Ullrich
	if (!is_ipaddr($hp))
432
		return false;
433 98bbf05a Scott Ullrich
434 5b237745 Scott Ullrich
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
435
		return false;
436 98bbf05a Scott Ullrich
437 5b237745 Scott Ullrich
	return true;
438
}
439
440
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
441
function is_subnetoralias($subnet) {
442
	global $aliastable;
443 98bbf05a Scott Ullrich
444 5b237745 Scott Ullrich
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
445
		return true;
446
	else
447
		return is_subnet($subnet);
448
}
449
450
/* returns true if $hostname is a valid hostname */
451
function is_hostname($hostname) {
452
	if (!is_string($hostname))
453
		return false;
454 98bbf05a Scott Ullrich
455 88efcf04 Erik Fonnesbeck
	if (preg_match('/^(?:(?:[a-z0-9_]|[a-z0-9_][a-z0-9_\-]*[a-z0-9_])\.)*(?:[a-z0-9_]|[a-z0-9_][a-z0-9_\-]*[a-z0-9_])$/i', $hostname))
456 5b237745 Scott Ullrich
		return true;
457
	else
458
		return false;
459
}
460
461
/* returns true if $domain is a valid domain name */
462
function is_domain($domain) {
463
	if (!is_string($domain))
464
		return false;
465 98bbf05a Scott Ullrich
466 88efcf04 Erik Fonnesbeck
	if (preg_match('/^(?:(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$/i', $domain))
467 5b237745 Scott Ullrich
		return true;
468
	else
469
		return false;
470
}
471
472
/* returns true if $macaddr is a valid MAC address */
473
function is_macaddr($macaddr) {
474 56f25370 Erik Fonnesbeck
	return preg_match('/^[0-9A-F]{2}(?:[:][0-9A-F]{2}){5}$/i', $macaddr) == 1 ? true : false;
475 5b237745 Scott Ullrich
}
476
477 3caa8aa1 Bill Marquette
/* returns true if $name is a valid name for an alias */
478 9499c2d2 Bill Marquette
/* returns NULL if a reserved word is used */
479 5b237745 Scott Ullrich
function is_validaliasname($name) {
480 beeef1f0 Bill Marquette
	/* Array of reserved words */
481 0c2badde Colin Smith
	$reserved = array("port", "pass");
482
	if (in_array($name, $reserved, true))
483 9499c2d2 Bill Marquette
		return; /* return NULL */
484 bac9941b jim-p
	if (!preg_match("/[^a-zA-Z0-9_]/", $name) && (strlen($name) < 32))
485 5b237745 Scott Ullrich
		return true;
486
	else
487
		return false;
488
}
489
490
/* returns true if $port is a valid TCP/UDP port */
491
function is_port($port) {
492 231e0606 Ermal Lu?i
	$tmpports = explode(":", $port);
493
	foreach($tmpports as $tmpport) {
494
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
495 5bbd08e1 Warren Baker
			continue;
496 231e0606 Ermal Lu?i
		if (!ctype_digit($tmpport))
497
			return false;
498 b52f883a Ermal Lu?i
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
499 231e0606 Ermal Lu?i
			return false;
500
	}
501
	return true;
502 5b237745 Scott Ullrich
}
503
504 5a1eebc7 Scott Ullrich
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
505
function is_portrange($portrange) {
506 5bbd08e1 Warren Baker
	$ports = explode(":", $portrange);
507 5a1eebc7 Scott Ullrich
508 5bbd08e1 Warren Baker
	if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
509
		return true;
510
	else
511
		return false;
512 5a1eebc7 Scott Ullrich
}
513
514 1e578a7f Ermal Lu?i
/* returns true if $port is a valid port number or an alias thereof */
515
function is_portoralias($port) {
516
	global $config;
517
518 5bbd08e1 Warren Baker
	if (is_alias($port)) {
519
		if (is_array($config['aliases']['alias'])) {
520
			foreach ($config['aliases']['alias'] as $alias) {
521
				if ($alias['name'] == $port && $alias['type'] == "port")
522
					return true;
523
				}
524
			}
525
			return false;
526
	} else
527
		return is_port($port);
528 1e578a7f Ermal Lu?i
}
529
530 b8014f9d Scott Ullrich
/* returns true if $val is a valid shaper bandwidth value */
531
function is_valid_shaperbw($val) {
532 eaa37259 Ermal Luçi
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
533 b8014f9d Scott Ullrich
}
534
535 abcb2bed Ermal Lu?i
/* return the configured carp interface list */
536
function get_configured_carp_interface_list() {
537
	global $config;
538
539
	$iflist = array();
540
541
	if(is_array($config['virtualip']['vip'])) {
542 5bbd08e1 Warren Baker
		$viparr = &$config['virtualip']['vip'];
543
		foreach ($viparr as $vip) {
544
			switch ($vip['mode']) {
545
				case "carp":
546
				case "carpdev-dhcp":
547
					$vipif = "vip" . $vip['vhid'];
548
					$iflist[$vipif] = $vip['subnet'];
549
					break;
550
			}
551
		}
552
	}
553 abcb2bed Ermal Lu?i
554
	return $iflist;
555
}
556
557 67b0902f pierrepomes
/* return the configured IP aliases list */
558
function get_configured_ip_aliases_list() {
559 5bbd08e1 Warren Baker
	global $config;
560 67b0902f pierrepomes
561 5bbd08e1 Warren Baker
	$alias_list=array();
562 67b0902f pierrepomes
563 5bbd08e1 Warren Baker
	if(is_array($config['virtualip']['vip'])) {
564
		$viparr = &$config['virtualip']['vip'];
565
		foreach ($viparr as $vip) {
566
			if ($vip['mode']=="ipalias") {
567
				$alias_list[$vip['subnet']] = $vip['interface'];
568
			}
569
		}
570
	}
571 67b0902f pierrepomes
572 5bbd08e1 Warren Baker
	return $alias_list;
573 67b0902f pierrepomes
}
574
575
576 88bc2760 Erik Fonnesbeck
/* comparison function for sorting by the order in which interfaces are normally created */
577
function compare_interface_friendly_names($a, $b) {
578
	if ($a == $b)
579
		return 0;
580
	else if ($a == 'wan')
581
		return -1;
582
	else if ($b == 'wan')
583
		return 1;
584
	else if ($a == 'lan')
585
		return -1;
586
	else if ($b == 'lan')
587
		return 1;
588
589
	return strnatcmp($a, $b);
590
}
591
592 c8abe1d4 Ermal Luçi
/* return the configured interfaces list. */
593 3ad5e089 Ermal Luçi
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
594 c8abe1d4 Ermal Luçi
	global $config;
595
596
	$iflist = array();
597 14f49fd0 Erik Fonnesbeck
598 263aeb4b Scott Ullrich
	if(!is_array($config['interfaces']))
599 94436824 Scott Ullrich
		$config = parse_config(true);
600
601 c8abe1d4 Ermal Luçi
	/* if list */
602 8735afe8 Erik Fonnesbeck
	foreach($config['interfaces'] as $if => $ifdetail) {
603
		if ($only_opt && ($if == "wan" || $if == "lan"))
604 42c9d20e Ermal Luçi
			continue;
605 47c8b036 Ermal Lu?i
		if (isset($ifdetail['enable']) || $withdisabled == true)
606 c8abe1d4 Ermal Luçi
			$iflist[$if] = $if;
607 42c9d20e Ermal Luçi
	}
608 c8abe1d4 Ermal Luçi
609
	return $iflist;
610
}
611
612 bb34737f Ermal Lu?i
/* return the configured interfaces list. */
613
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
614 8735afe8 Erik Fonnesbeck
	global $config;
615 bb34737f Ermal Lu?i
616 8735afe8 Erik Fonnesbeck
	$iflist = array();
617 bb34737f Ermal Lu?i
618 8735afe8 Erik Fonnesbeck
	/* if list */
619
	foreach($config['interfaces'] as $if => $ifdetail) {
620
		if ($only_opt && ($if == "wan" || $if == "lan"))
621
			continue;
622
		if (isset($ifdetail['enable']) || $withdisabled == true) {
623 bb34737f Ermal Lu?i
			$tmpif = get_real_interface($if);
624
			if (!empty($tmpif))
625
				$iflist[$tmpif] = $if;
626
		}
627 8735afe8 Erik Fonnesbeck
	}
628 bb34737f Ermal Lu?i
629 8735afe8 Erik Fonnesbeck
	return $iflist;
630 bb34737f Ermal Lu?i
}
631
632 c8abe1d4 Ermal Luçi
/* return the configured interfaces list with their description. */
633 3ad5e089 Ermal Luçi
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
634 a42d1da2 Scott Ullrich
	global $config;
635 c8abe1d4 Ermal Luçi
636 a42d1da2 Scott Ullrich
	$iflist = array();
637 c8abe1d4 Ermal Luçi
638 a42d1da2 Scott Ullrich
	/* if list */
639
	foreach($config['interfaces'] as $if => $ifdetail) {
640 8735afe8 Erik Fonnesbeck
		if ($only_opt && ($if == "wan" || $if == "lan"))
641
			continue;
642 47c8b036 Ermal Lu?i
		if (isset($ifdetail['enable']) || $withdisabled == true) {
643 8735afe8 Erik Fonnesbeck
			if(empty($ifdetail['descr']))
644 8e74cb8d Ermal Luçi
				$iflist[$if] = strtoupper($if);
645 a42d1da2 Scott Ullrich
			else
646 44b0ec83 Scott Ullrich
				$iflist[$if] = strtoupper($ifdetail['descr']);
647 0e218dc1 Ermal Luçi
		}
648 42c9d20e Ermal Luçi
	}
649 c8abe1d4 Ermal Luçi
650 a42d1da2 Scott Ullrich
	return $iflist;
651 c8abe1d4 Ermal Luçi
}
652
653 4fe9c2dc Scott Ullrich
/*
654
 *   get_configured_ip_addresses() - Return a list of all configured
655
 *   interfaces IP Addresses
656
 *
657
 */
658
function get_configured_ip_addresses() {
659
	require_once("interfaces.inc");
660
	$ip_array = array();
661
	$interfaces = get_configured_interface_list();
662 d9114ce0 Scott Ullrich
	if(is_array($interfaces)) {
663
		foreach($interfaces as $int) {
664
			$ipaddr = get_interface_ip($int);
665
			$ip_array[$int] = $ipaddr;
666
		}
667 4fe9c2dc Scott Ullrich
	}
668 19f101d7 Scott Ullrich
	$interfaces = get_configured_carp_interface_list();
669 d9114ce0 Scott Ullrich
	if(is_array($interfaces)) 
670
		foreach($interfaces as $int => $ipaddr) 
671
			$ip_array[$int] = $ipaddr;
672 4fe9c2dc Scott Ullrich
	return $ip_array;
673
}
674 c8abe1d4 Ermal Luçi
675 36f546e9 Scott Ullrich
/*
676
 *   get_interface_list() - Return a list of all physical interfaces
677
 *   along with MAC and status.
678
 *
679
 *   $mode = "active" - use ifconfig -lu
680
 *           "media"  - use ifconfig to check physical connection
681
 *			status (much slower)
682
 */
683
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
684 20203646 Colin Smith
        global $config;
685 65bed2d2 Scott Ullrich
	$upints = array();
686 20203646 Colin Smith
        /* get a list of virtual interface types */
687 36f546e9 Scott Ullrich
        if(!$vfaces) {
688 9ce38409 Scott Ullrich
		$vfaces = array (
689
				'bridge',
690
				'ppp',
691 27c0c7c6 Ermal Lu?i
				'pppoe',
692
				'pptp',
693
				'l2tp',
694 9ce38409 Scott Ullrich
				'sl',
695
				'gif',
696 613571ea Ermal Luçi
				'gre',
697 9ce38409 Scott Ullrich
				'faith',
698
				'lo',
699
				'ng',
700 27616d6e Seth Mos
				'_vlan',
701 7c53bc7b Erik Fonnesbeck
				'_wlan',
702 9ce38409 Scott Ullrich
				'pflog',
703 a42d1da2 Scott Ullrich
				'plip',
704 9ce38409 Scott Ullrich
				'pfsync',
705
				'enc',
706
				'tun',
707 0a140d2e Ermal Luçi
				'carp',
708 1fb2bf25 Ermal Lu?i
				'lagg',
709 1fd35e95 Ermal
				'vip',
710
				'ipfw'
711 9ce38409 Scott Ullrich
		);
712 36f546e9 Scott Ullrich
	}
713 20203646 Colin Smith
	switch($mode) {
714
	case "active":
715
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
716
        	break;
717
	case "media":
718
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
719 767a716e Scott Ullrich
                $ifconfig = "";
720 20203646 Colin Smith
                exec("/sbin/ifconfig -a", $ifconfig);
721
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
722
                $ifstatus = preg_grep('/status:/', $ifconfig);
723 49149b86 Colin Smith
		foreach($ifstatus as $status) {
724 bb3b9159 Colin Smith
			$int = array_shift($intlist);
725 5bbd08e1 Warren Baker
			if(stristr($status, "active")) $upints[] = $int;
726 49149b86 Colin Smith
		}
727 20203646 Colin Smith
		break;
728 72993196 Ermal
	default:
729
		$upints = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
730
		break;
731 20203646 Colin Smith
	}
732
        /* build interface list with netstat */
733 767a716e Scott Ullrich
        $linkinfo = "";
734 89d1f0f2 Scott Ullrich
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
735 20203646 Colin Smith
        array_shift($linkinfo);
736 89d1f0f2 Scott Ullrich
	/* build ip address list with netstat */
737 767a716e Scott Ullrich
	$ipinfo = "";
738 89d1f0f2 Scott Ullrich
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
739
	array_shift($ipinfo);
740
	foreach($linkinfo as $link) {
741
		$friendly = "";
742 5bbd08e1 Warren Baker
		$alink = explode(" ", $link);
743
		$ifname = rtrim(trim($alink[0]), '*');
744
		/* trim out all numbers before checking for vfaces */
745 494be6e8 Ermal Lu?i
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces) &&
746 7c53bc7b Erik Fonnesbeck
			!stristr($ifname, "_vlan") && !stristr($ifname, "_wlan")) {
747 20203646 Colin Smith
			$toput = array(
748
					"mac" => trim($alink[1]),
749
					"up" => in_array($ifname, $upints)
750
				);
751 89d1f0f2 Scott Ullrich
			foreach($ipinfo as $ip) {
752
				$aip = explode(" ", $ip);
753
				if($aip[0] == $ifname) {
754
					$toput['ipaddr'] = $aip[1];
755
				}
756
			}
757 72993196 Ermal
			if (is_array($config['interfaces'])) {
758
				foreach($config['interfaces'] as $name => $int)
759
					if($int['if'] == $ifname) $friendly = $name;
760 20203646 Colin Smith
			}
761
			switch($keyby) {
762
			case "physical":
763 89d1f0f2 Scott Ullrich
				if($friendly != "") {
764
					$toput['friendly'] = $friendly;
765
				}
766 a296c95d Seth Mos
				$dmesg_arr = array();
767
				exec("/sbin/dmesg |grep $ifname | head -n1", $dmesg_arr);
768
				preg_match_all("/<(.*?)>/i", $dmesg_arr[0], $dmesg);
769
				$toput['dmesg'] = $dmesg[1][0];
770 20203646 Colin Smith
				$iflist[$ifname] = $toput;
771 3154d7ed Colin Smith
				break;
772 4aca19b3 Scott Ullrich
			case "ppp":
773
				
774 20203646 Colin Smith
			case "friendly":
775 89d1f0f2 Scott Ullrich
				if($friendly != "") {
776
					$toput['if'] = $ifname;
777
					$iflist[$friendly] = $toput;
778
				}
779 3154d7ed Colin Smith
				break;
780
			}
781 5bbd08e1 Warren Baker
		}
782
	}
783
	return $iflist;
784 5b237745 Scott Ullrich
}
785
786 2b4d37de Ermal Lu?i
/****f* util/log_error
787
* NAME
788
*   log_error  - Sends a string to syslog.
789
* INPUTS
790
*   $error     - string containing the syslog message.
791
* RESULT
792
*   null
793
******/
794
function log_error($error) {
795 5bbd08e1 Warren Baker
	global $g;
796
	$page = $_SERVER['SCRIPT_NAME'];
797
	syslog(LOG_WARNING, "$page: $error");
798
	if ($g['debug'])
799
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
800
	return;
801 2b4d37de Ermal Lu?i
}
802
803 3aba1835 Scott Ullrich
/****f* util/log_auth
804
* NAME
805
*   log_error  - Sends a string to syslog as LOG_AUTH facility
806
* INPUTS
807
*   $error     - string containing the syslog message.
808
* RESULT
809
*   null
810
******/
811
function log_auth($error) {
812 5bbd08e1 Warren Baker
	global $g;
813
	$page = $_SERVER['SCRIPT_NAME'];
814
	syslog(LOG_AUTH, "$page: $error");
815
	if ($g['debug'])
816
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
817
	return;
818 3aba1835 Scott Ullrich
}
819
820 83bc3749 Ermal Lu?i
/****f* util/exec_command
821
 * NAME
822
 *   exec_command - Execute a command and return a string of the result.
823
 * INPUTS
824
 *   $command   - String of the command to be executed.
825
 * RESULT
826
 *   String containing the command's result.
827
 * NOTES
828
 *   This function returns the command's stdout and stderr.
829
 ******/
830
function exec_command($command) {
831 5bbd08e1 Warren Baker
	$output = array();
832
	exec($command . ' 2>&1 ', $output);
833
	return(implode("\n", $output));
834 83bc3749 Ermal Lu?i
}
835
836 5b237745 Scott Ullrich
/* wrapper for exec() */
837 12169c92 Seth Mos
function mwexec($command, $mute = false) {
838 5b237745 Scott Ullrich
	global $g;
839 435a418f Ermal
840 5b237745 Scott Ullrich
	if ($g['debug']) {
841
		if (!$_SERVER['REMOTE_ADDR'])
842
			echo "mwexec(): $command\n";
843 f9db3cda Seth Mos
	}
844 435a418f Ermal
	$oarr = array();
845
	$retval = 0;
846
	$garbage = exec("$command 2>&1", $oarr, $retval);
847
848 61c6b6c1 Chris Buechler
	if(isset($config['system']['developerspew']))
849 5bbd08e1 Warren Baker
		$mute = false;
850 12169c92 Seth Mos
	if(($retval <> 0) && ($mute === false)) {
851 f9db3cda Seth Mos
		$output = implode(" ", $oarr);
852 4cc0d38a Seth Mos
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
853 5b237745 Scott Ullrich
	}
854 98bbf05a Scott Ullrich
	return $retval;
855 5b237745 Scott Ullrich
}
856
857
/* wrapper for exec() in background */
858
function mwexec_bg($command) {
859
	global $g;
860 98bbf05a Scott Ullrich
861 5b237745 Scott Ullrich
	if ($g['debug']) {
862
		if (!$_SERVER['REMOTE_ADDR'])
863
			echo "mwexec(): $command\n";
864
	}
865 98bbf05a Scott Ullrich
866 5b237745 Scott Ullrich
	exec("nohup $command > /dev/null 2>&1 &");
867
}
868
869
/* unlink a file, if it exists */
870
function unlink_if_exists($fn) {
871 336cb718 Scott Ullrich
	$to_do = glob($fn);
872 3b378be5 Scott Ullrich
	if(is_array($to_do)) {
873 336cb718 Scott Ullrich
		foreach($to_do as $filename)
874 9ff926a2 Colin Smith
			@unlink($filename);
875 336cb718 Scott Ullrich
	} else {
876 9ff926a2 Colin Smith
		@unlink($fn);
877 336cb718 Scott Ullrich
	}
878 5b237745 Scott Ullrich
}
879
/* make a global alias table (for faster lookups) */
880 918a884d Bill Marquette
function alias_make_table($config) {
881
	global $aliastable;
882 98bbf05a Scott Ullrich
883 5b237745 Scott Ullrich
	$aliastable = array();
884 98bbf05a Scott Ullrich
885 5b237745 Scott Ullrich
	if (is_array($config['aliases']['alias'])) {
886
		foreach ($config['aliases']['alias'] as $alias) {
887
			if ($alias['name'])
888
				$aliastable[$alias['name']] = $alias['address'];
889
		}
890
	}
891
}
892
/* check if an alias exists */
893
function is_alias($name) {
894
	global $aliastable;
895 98bbf05a Scott Ullrich
896 5b237745 Scott Ullrich
	return isset($aliastable[$name]);
897 b8014f9d Scott Ullrich
}
898 27ff8a3c Scott Ullrich
899 5b237745 Scott Ullrich
/* expand a host or network alias, if necessary */
900
function alias_expand($name) {
901
	global $aliastable;
902 98bbf05a Scott Ullrich
903 87f0be87 Chris Buechler
	if (isset($aliastable[$name]))
904 4335dc87 Bill Marquette
		return "\${$name}";
905 a584475a Ermal Lu?i
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
906 57989da5 Scott Ullrich
		return "{$name}";
907 87f0be87 Chris Buechler
	else
908 5b237745 Scott Ullrich
		return null;
909
}
910
911 c7de8be4 jim-p
function alias_expand_urltable($name) {
912
	global $config;
913
	$urltable_prefix = "/var/db/aliastables/";
914
	$urltable_filename = $urltable_prefix . $name . ".txt";
915
916 df58fd46 Ermal
	foreach ($config['aliases']['alias'] as $alias) {
917
		if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
918
			if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
919
				return $urltable_filename;
920
			else if (process_alias_urltable($name, $alias["url"], 0, true))
921
				return $urltable_filename;
922 c7de8be4 jim-p
		}
923
	}
924
	return null;
925
}
926
927 5b237745 Scott Ullrich
/* find out whether two subnets overlap */
928
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
929
930
	if (!is_numeric($bits1))
931
		$bits1 = 32;
932
	if (!is_numeric($bits2))
933
		$bits2 = 32;
934
935
	if ($bits1 < $bits2)
936
		$relbits = $bits1;
937
	else
938
		$relbits = $bits2;
939 98bbf05a Scott Ullrich
940 5b237745 Scott Ullrich
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
941
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
942 98bbf05a Scott Ullrich
943 5b237745 Scott Ullrich
	if ($sn1 == $sn2)
944
		return true;
945
	else
946
		return false;
947
}
948
949
/* compare two IP addresses */
950
function ipcmp($a, $b) {
951 96033063 Erik Fonnesbeck
	if (ip_less_than($a, $b))
952 5b237745 Scott Ullrich
		return -1;
953 96033063 Erik Fonnesbeck
	else if (ip_greater_than($a, $b))
954 5b237745 Scott Ullrich
		return 1;
955
	else
956
		return 0;
957
}
958
959
/* return true if $addr is in $subnet, false if not */
960
function ip_in_subnet($addr,$subnet) {
961
	list($ip, $mask) = explode('/', $subnet);
962 96033063 Erik Fonnesbeck
	$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
963 5b237745 Scott Ullrich
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
964
}
965
966
/* verify (and remove) the digital signature on a file - returns 0 if OK */
967
function verify_digital_signature($fname) {
968
	global $g;
969
970 c50da179 Scott Ullrich
	if(!file_exists("/usr/local/sbin/gzsig"))
971 9f007e8c Chris Buechler
		return 4;
972 c50da179 Scott Ullrich
973 f024f52d Scott Ullrich
	return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname));
974 5b237745 Scott Ullrich
}
975
976
/* obtain MAC address given an IP address by looking at the ARP table */
977
function arp_get_mac_by_ip($ip) {
978 f3ebffee Ermal Lu?i
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
979 767a716e Scott Ullrich
	$arpoutput = "";
980 5b237745 Scott Ullrich
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
981 98bbf05a Scott Ullrich
982 5b237745 Scott Ullrich
	if ($arpoutput[0]) {
983
		$arpi = explode(" ", $arpoutput[0]);
984
		$macaddr = $arpi[3];
985
		if (is_macaddr($macaddr))
986
			return $macaddr;
987
		else
988
			return false;
989
	}
990 98bbf05a Scott Ullrich
991 5b237745 Scott Ullrich
	return false;
992
}
993
994 98bbf05a Scott Ullrich
/* return a fieldname that is safe for xml usage */
995
function xml_safe_fieldname($fieldname) {
996 87f0be87 Chris Buechler
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
997
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
998 ddce8ef2 Colin Smith
			 ':', ',', '.', '\'', '\\'
999
		);
1000
	return strtolower(str_replace($replace, "", $fieldname));
1001 98bbf05a Scott Ullrich
}
1002
1003 4129df39 Scott Ullrich
function mac_format($clientmac) {
1004
    $mac =explode(":", $clientmac);
1005
1006
    global $config;
1007
1008
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
1009
1010
    switch($mac_format) {
1011
1012
        case 'singledash':
1013
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
1014
1015
        case 'ietf':
1016
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
1017
1018
        case 'cisco':
1019
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
1020
1021
        case 'unformatted':
1022
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
1023
1024
        default:
1025
        return $clientmac;
1026
    }
1027
}
1028
1029 979cd6db Scott Ullrich
function resolve_retry($hostname, $retries = 5) {
1030
1031 5bbd08e1 Warren Baker
	if (is_ipaddr($hostname))
1032
		return $hostname;
1033 979cd6db Scott Ullrich
1034 5bbd08e1 Warren Baker
	for ($i = 0; $i < $retries; $i++) {
1035
		$ip = gethostbyname($hostname);
1036 979cd6db Scott Ullrich
1037 5bbd08e1 Warren Baker
		if ($ip && $ip != $hostname) {
1038
			/* success */
1039
			return $ip;
1040
		}
1041 979cd6db Scott Ullrich
1042 5bbd08e1 Warren Baker
		sleep(1);
1043
	}
1044 979cd6db Scott Ullrich
1045 5bbd08e1 Warren Baker
	return false;
1046 979cd6db Scott Ullrich
}
1047
1048 44bfd1fa Scott Ullrich
function format_bytes($bytes) {
1049
	if ($bytes >= 1073741824) {
1050
		return sprintf("%.2f GB", $bytes/1073741824);
1051
	} else if ($bytes >= 1048576) {
1052
		return sprintf("%.2f MB", $bytes/1048576);
1053
	} else if ($bytes >= 1024) {
1054
		return sprintf("%.0f KB", $bytes/1024);
1055
	} else {
1056
		return sprintf("%d bytes", $bytes);
1057
	}
1058
}
1059
1060 2b4d37de Ermal Lu?i
function update_filter_reload_status($text) {
1061 5bbd08e1 Warren Baker
	global $g;
1062 2b4d37de Ermal Lu?i
1063 5bbd08e1 Warren Baker
	file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1064 2b4d37de Ermal Lu?i
}
1065
1066
/****f* util/return_dir_as_array
1067
 * NAME
1068
 *   return_dir_as_array - Return a directory's contents as an array.
1069
 * INPUTS
1070
 *   $dir       - string containing the path to the desired directory.
1071
 * RESULT
1072
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1073
 ******/
1074
function return_dir_as_array($dir) {
1075 5bbd08e1 Warren Baker
	$dir_array = array();
1076
	if (is_dir($dir)) {
1077
		if ($dh = opendir($dir)) {
1078
			while (($file = readdir($dh)) !== false) {
1079
				$canadd = 0;
1080
				if($file == ".") $canadd = 1;
1081
				if($file == "..") $canadd = 1;
1082
				if($canadd == 0)
1083
					array_push($dir_array, $file);
1084
			}
1085
			closedir($dh);
1086
		}
1087
	}
1088
	return $dir_array;
1089 2b4d37de Ermal Lu?i
}
1090
1091
function run_plugins($directory) {
1092 5bbd08e1 Warren Baker
	global $config, $g;
1093
1094
	/* process packager manager custom rules */
1095
	$files = return_dir_as_array($directory);
1096
	if (is_array($files)) {
1097
		foreach ($files as $file) {
1098
			if (stristr($file, ".sh") == true)
1099
				mwexec($directory . $file . " start");
1100
			else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1101
				require_once($directory . "/" . $file);
1102 2990acf8 Scott Ullrich
		}
1103 5bbd08e1 Warren Baker
	}
1104 2b4d37de Ermal Lu?i
}
1105
1106
/*
1107
 *    safe_mkdir($path, $mode = 0755)
1108
 *    create directory if it doesn't already exist and isn't a file!
1109
 */
1110
function safe_mkdir($path, $mode=0755) {
1111 5bbd08e1 Warren Baker
	global $g;
1112 2b4d37de Ermal Lu?i
1113 5bbd08e1 Warren Baker
	if (!is_file($path) && !is_dir($path)) {
1114
		return @mkdir($path, $mode, true);
1115
	} else {
1116
		return false;
1117
	}
1118 2b4d37de Ermal Lu?i
}
1119
1120
/*
1121
 * make_dirs($path, $mode = 0755)
1122
 * create directory tree recursively (mkdir -p)
1123
 */
1124
function make_dirs($path, $mode = 0755) {
1125 5bbd08e1 Warren Baker
	$base = '';
1126
	foreach (explode('/', $path) as $dir) {
1127
		$base .= "/$dir";
1128
		if (!is_dir($base)) {
1129
			if (!@mkdir($base, $mode))
1130
				return false;
1131
		}
1132
	}
1133
	return true;
1134 2b4d37de Ermal Lu?i
}
1135
1136 aa4f498d Erik Fonnesbeck
/*
1137
 * get_sysctl($names)
1138
 * Get values of sysctl OID's listed in $names (accepts an array or a single
1139
 * name) and return an array of key/value pairs set for those that exist
1140
 */
1141
function get_sysctl($names) {
1142
	if (empty($names))
1143
		return array();
1144
1145
	if (is_array($names)) {
1146
		$name_list = array();
1147
		foreach ($names as $name) {
1148
			$name_list[] = escapeshellarg($name);
1149
		}
1150
	} else
1151
		$name_list = array(escapeshellarg($names));
1152
1153
	exec("/sbin/sysctl -i " . implode(" ", $name_list), $output);
1154
	$values = array();
1155
	foreach ($output as $line) {
1156
		$line = explode(": ", $line, 2);
1157
		if (count($line) == 2)
1158
			$values[$line[0]] = $line[1];
1159
	}
1160
1161
	return $values;
1162
}
1163
1164
/*
1165
 * set_sysctl($value_list)
1166
 * Set sysctl OID's listed as key/value pairs and return
1167
 * an array with keys set for those that succeeded
1168
 */
1169
function set_sysctl($values) {
1170
	if (empty($values))
1171
		return array();
1172
1173
	$value_list = array();
1174
	foreach ($values as $key => $value) {
1175
		$value_list[] = escapeshellarg($key) . "=" . escapeshellarg($value);
1176
	}
1177
1178
	exec("/sbin/sysctl -i " . implode(" ", $value_list), $output, $success);
1179
1180
	/* Retry individually if failed (one or more read-only) */
1181
	if ($success <> 0 && count($value_list) > 1) {
1182
		foreach ($value_list as $value) {
1183
			exec("/sbin/sysctl -i " . $value, $output);
1184
		}
1185
	}
1186
1187
	$ret = array();
1188
	foreach ($output as $line) {
1189
		$line = explode(": ", $line, 2);
1190
		if (count($line) == 2)
1191
			$ret[$line[0]] = true;
1192
	}
1193
1194
	return $ret;
1195
}
1196
1197 2b4d37de Ermal Lu?i
/*
1198
 *     get_memory()
1199
 *     returns an array listing the amount of
1200
 *     memory installed in the hardware
1201
 *     [0]real and [1]available
1202
 */
1203
function get_memory() {
1204 5bbd08e1 Warren Baker
	$matches = "";
1205
	if(file_exists("/var/log/dmesg.boot"))
1206
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1207
	else
1208
		$mem = `dmesg -a | grep memory`;			
1209
	if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1210
		return array($matches[1][0], $matches[1][0]);
1211
	if(!$real && !$avail) {
1212
		$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1213
		$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1214
		/* convert from bytes to megabytes */
1215
		return array(($real/1048576),($avail/1048576));
1216
	}
1217 2b4d37de Ermal Lu?i
}
1218
1219
function mute_kernel_msgs() {
1220 5bbd08e1 Warren Baker
	global $config;
1221
	// Do not mute serial console.  The kernel gets very very cranky
1222
	// and will start dishing you cannot control tty errors.
1223 3c6d704a Andrew Thompson
	if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1224
		return;
1225 5bbd08e1 Warren Baker
	if($config['system']['enableserial']) 
1226
		return;			
1227
	exec("/sbin/conscontrol mute on");
1228 2b4d37de Ermal Lu?i
}
1229
1230
function unmute_kernel_msgs() {
1231 5bbd08e1 Warren Baker
	global $config;
1232
	// Do not mute serial console.  The kernel gets very very cranky
1233
	// and will start dishing you cannot control tty errors.
1234 3c6d704a Andrew Thompson
	if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1235
		return;
1236 5bbd08e1 Warren Baker
	exec("/sbin/conscontrol mute off");
1237 2b4d37de Ermal Lu?i
}
1238
1239
function start_devd() {
1240 6955830f Ermal Lu?i
	global $g;
1241
1242 5bbd08e1 Warren Baker
	exec("/sbin/devd");
1243
	sleep(1);
1244 2b4d37de Ermal Lu?i
}
1245
1246 66bcba1b Ermal
function is_interface_vlan_mismatch() {
1247 5bbd08e1 Warren Baker
	global $config, $g;
1248 66bcba1b Ermal
1249 5bbd08e1 Warren Baker
	if (is_array($config['vlans']['vlan'])) {
1250
		foreach ($config['vlans']['vlan'] as $vlan) {
1251
			if (does_interface_exist($vlan['if']) == false)
1252 66bcba1b Ermal
				return true;
1253 5bbd08e1 Warren Baker
		}
1254
	}
1255 66bcba1b Ermal
1256
	return false;
1257
}
1258
1259 2b4d37de Ermal Lu?i
function is_interface_mismatch() {
1260 857da904 Scott Ullrich
	global $config, $g;
1261 2b4d37de Ermal Lu?i
1262 857da904 Scott Ullrich
	$do_assign = false;
1263
	$i = 0;
1264 72993196 Ermal
	if (is_array($config['interfaces'])) {
1265 857da904 Scott Ullrich
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
1266
			if (preg_match("/^enc|^cua|^tun|^l2tp|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1267
				// Do not check these interfaces.
1268
				$i++;
1269
				continue;
1270
			}
1271
			else if (does_interface_exist($ifcfg['if']) == false) {
1272 72993196 Ermal
				$do_assign = true;
1273 857da904 Scott Ullrich
			} else
1274
				$i++;
1275
		}
1276 72993196 Ermal
	}
1277 2b4d37de Ermal Lu?i
1278 857da904 Scott Ullrich
	if ($g['minimum_nic_count'] > $i) {
1279
		$do_assign = true;
1280
	} else if (file_exists("{$g['tmp_path']}/assign_complete"))
1281
	$do_assign = false;
1282 2b4d37de Ermal Lu?i
1283 857da904 Scott Ullrich
	return $do_assign;
1284 2b4d37de Ermal Lu?i
}
1285
1286 6e8f7b53 Ermal Lu?i
/* sync carp entries to other firewalls */
1287
function carp_sync_client() {
1288 e14d1c01 Ermal Lu?i
	global $g;
1289 0ae6daf8 Ermal
	send_event("filter sync");
1290 6e8f7b53 Ermal Lu?i
}
1291
1292 6dc88d53 Ermal Luci
/****f* util/isAjax
1293
 * NAME
1294
 *   isAjax - reports if the request is driven from prototype
1295
 * INPUTS
1296
 *   none
1297
 * RESULT
1298
 *   true/false
1299
 ******/
1300
function isAjax() {
1301 5bbd08e1 Warren Baker
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1302 6dc88d53 Ermal Luci
}
1303
1304 dad2b40e Tim Allender
/****f* util/timeout
1305
 * NAME
1306
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1307
 * INPUTS
1308
 *   optional, seconds to wait before timeout. Default 9 seconds.
1309
 * RESULT
1310
 *   returns 1 char of user input or null if no input.
1311
 ******/
1312
function timeout($timer = 9) {
1313
	while(!isset($key)) {
1314
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1315
		else { echo chr(8). "{$timer}"; }
1316
		`/bin/stty -icanon min 0 time 25`;
1317
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1318
		`/bin/stty icanon`;
1319
		if ($key == '')
1320
			unset($key);
1321
		$timer--;
1322
		if ($timer == 0)
1323
			break;
1324
	}
1325
	return $key;	
1326
}
1327 6dc88d53 Ermal Luci
1328 fdf3af3f Scott Ullrich
/****f* util/msort
1329
 * NAME
1330
 *   msort - sort array
1331
 * INPUTS
1332
 *   $array to be sorted, field to sort by, direction of sort
1333
 * RESULT
1334
 *   returns newly sorted array
1335
 ******/
1336 4a8bc5a2 Scott Ullrich
function msort($array, $id="id", $sort_ascending=true) {
1337
	$temp_array = array();
1338
	while(count($array)>0) {
1339
		$lowest_id = 0;
1340
		$index=0;
1341
		foreach ($array as $item) {
1342
			if (isset($item[$id])) {
1343
				if ($array[$lowest_id][$id]) {
1344
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1345
						$lowest_id = $index;
1346
					}
1347
				}
1348
			}
1349
			$index++;
1350
		}
1351
		$temp_array[] = $array[$lowest_id];
1352
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1353
	}
1354
	if ($sort_ascending) {
1355
		return $temp_array;
1356
	} else {
1357
    	return array_reverse($temp_array);
1358
	}
1359
}
1360
1361 fdf3af3f Scott Ullrich
/****f* util/color
1362
 * NAME
1363
 *   color - outputs a color code to the ansi terminal if supported
1364
 * INPUTS
1365 6028a72d Scott Ullrich
 *   color code or color name
1366 fdf3af3f Scott Ullrich
 * RESULT
1367
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1368
 ******/
1369
function color($color = "0m") {
1370
	/*
1371
		Color codes available:
1372
		 0m reset; clears all colors and styles (to white on black)
1373
		 1m bold on (see below)
1374
		 3m italics on
1375
		 4m underline on
1376
		 7m inverse on; reverses foreground & background colors
1377
		 9m strikethrough on
1378
		 22m bold off (see below)
1379
		 23m italics off
1380
		 24m underline off
1381
		 27m inverse off
1382
		 29m strikethrough off
1383
		 30m set foreground color to black
1384
		 31m set foreground color to red
1385
		 32m set foreground color to green
1386
		 33m set foreground color to yellow
1387
		 34m set foreground color to blue
1388
		 35m set foreground color to magenta (purple)
1389
		 36m set foreground color to cyan
1390
		 37m set foreground color to white
1391
		 40m  set background color to black
1392
		 41m set background color to red
1393
		 42m set background color to green
1394
		 43m set background color to yellow
1395
		 44m set background color to blue
1396
		 45m set background color to magenta (purple)
1397
		 46m set background color to cyan
1398
		 47m set background color to white
1399
		 49m set background color to default (black)
1400 b927a013 Scott Ullrich
	*/	
1401 fdf3af3f Scott Ullrich
	// Allow caching of TERM to 
1402
	// speedup subequence requests.
1403
	global $TERM;
1404
	if(!$TERM) 
1405
		$TERM=`/usr/bin/env | grep color`;
1406 78e0b65c Scott Ullrich
	if(!$TERM)
1407
		$TERM=`/usr/bin/env | grep cons25`;
1408 b927a013 Scott Ullrich
	if($TERM) {
1409 6028a72d Scott Ullrich
		$ESCAPE=chr(27);
1410 b927a013 Scott Ullrich
		switch ($color) {
1411 6028a72d Scott Ullrich
			case "black":
1412
				return "{$ESCAPE}[30m"; 
1413
			case "red":
1414
				return "{$ESCAPE}[31m"; 
1415
			case "green":
1416
				return "{$ESCAPE}[32m"; 
1417
			case "yellow":
1418
				return "{$ESCAPE}[33m"; 
1419
			case "blue":
1420
				return "{$ESCAPE}[34m"; 
1421
			case "magenta":
1422
				return "{$ESCAPE}[35m"; 
1423
			case "cyan":
1424
				return "{$ESCAPE}[36m"; 
1425
			case "white":
1426
				return "{$ESCAPE}[37m"; 
1427
			case "default":
1428
				return "{$ESCAPE}[39m"; 
1429 b927a013 Scott Ullrich
		}
1430 385a3a31 Scott Ullrich
		return "{$ESCAPE}[{$color}";
1431 b927a013 Scott Ullrich
	}
1432 fdf3af3f Scott Ullrich
}
1433
1434 5e9dd72a sullrich
/****f* util/is_URL
1435
 * NAME
1436
 *   is_URL
1437
 * INPUTS
1438
 *   string to check
1439
 * RESULT
1440
 *   Returns true if item is a URL
1441
 ******/
1442
function is_URL($url) {
1443
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1444
	if($match)
1445
		return true;	
1446
	return false;
1447
}
1448
1449 ab94ba00 Ermal Lu?i
function is_file_included($file = "") {
1450
	$files = get_included_files();
1451
	if (in_array($file, $files))
1452
		return true;
1453
	
1454
	return false;
1455
}
1456
1457 0d90fcaf jim-p
/*
1458
	This function was borrowed from a comment on PHP.net at the following URL:
1459
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
1460
 */
1461 5bbd08e1 Warren Baker
function array_merge_recursive_unique($array0, $array1) {
1462
1463
	$arrays = func_get_args();
1464
	$remains = $arrays;
1465 0d90fcaf jim-p
1466 5bbd08e1 Warren Baker
	// We walk through each arrays and put value in the results (without
1467
	// considering previous value).
1468
	$result = array();
1469 0d90fcaf jim-p
1470 5bbd08e1 Warren Baker
	// loop available array
1471
	foreach($arrays as $array) {
1472 0d90fcaf jim-p
1473 5bbd08e1 Warren Baker
		// The first remaining array is $array. We are processing it. So
1474
		// we remove it from remaing arrays.
1475 0d90fcaf jim-p
        array_shift($remains);
1476
1477 5bbd08e1 Warren Baker
		// We don't care non array param, like array_merge since PHP 5.0.
1478
		if(is_array($array)) {
1479
			// Loop values
1480
			foreach($array as $key => $value) {
1481
				if(is_array($value)) {
1482
					// we gather all remaining arrays that have such key available
1483
					$args = array();
1484
					foreach($remains as $remain) {
1485
						if(array_key_exists($key, $remain)) {
1486
							array_push($args, $remain[$key]);
1487
						}
1488
					}
1489
1490
					if(count($args) > 2) {
1491
						// put the recursion
1492
						$result[$key] = call_user_func_array(__FUNCTION__, $args);
1493
					} else {
1494
						foreach($value as $vkey => $vval) {
1495
							$result[$key][$vkey] = $vval;
1496
						}
1497
					}
1498
				} else {
1499
					// simply put the value
1500
					$result[$key] = $value;
1501
				}
1502
			}
1503
		}
1504
	}
1505
	return $result;
1506 0d90fcaf jim-p
}
1507
1508 e1b068d7 Ermal
?>