Project

General

Profile

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