Project

General

Profile

Download (38.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php 
2
/*
3
	util.inc
4
	part of the pfSense project (http://www.pfsense.com)
5

    
6
	originally part of m0n0wall (http://m0n0.ch/wall)
7
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9

    
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12

    
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15

    
16
	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

    
20
	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
/*
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
/* kill a process by pid file */
40
function killbypid($pidfile) {
41
	return sigkillbypid($pidfile, "TERM");
42
}
43

    
44
function isvalidpid($pid) {
45
	$output = "";
46
	exec("/bin/pgrep -nF {$pid}", $output, $retval);
47

    
48
	return (intval($retval) == 0);
49
}
50

    
51
function is_process_running($process) {
52
	$output = "";
53
	exec("/bin/pgrep -anx {$process}", $output, $retval);
54

    
55
	return (intval($retval) == 0);
56
}
57

    
58
function isvalidproc($proc) {
59
	return is_process_running($proc);
60
}
61

    
62
/* sigkill a process by pid file */
63
/* return 1 for success and 0 for a failure */
64
function sigkillbypid($pidfile, $sig) {
65
	if (is_file($pidfile))
66
		return mwexec("/bin/pkill -{$sig} -F {$pidfile}", true);
67

    
68
	return 0;
69
}
70

    
71
/* kill a process by name */
72
function sigkillbyname($procname, $sig) {
73
	if(isvalidproc($procname))
74
		return mwexec("/usr/bin/killall -{$sig} " . escapeshellarg($procname), true);
75
}
76

    
77
/* kill a process by name */
78
function killbyname($procname) {
79
	if(isvalidproc($procname)) 
80
		mwexec("/usr/bin/killall " . escapeshellarg($procname));
81
}
82

    
83
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
function config_lock() {
109
	return;
110
}
111
function config_unlock() {
112
	return;
113
}
114

    
115
/* lock configuration file */
116
function lock($lock, $op = LOCK_SH) {
117
	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
	if ($fp = fopen("{$g['tmp_path']}/{$lock}.lock", "w")) {
124
		if (flock($fp, $op))
125
			return $fp;
126
		else
127
			fclose($fp);
128
	}
129
}
130

    
131
/* unlock configuration file */
132
function unlock($cfglckkey = 0) {
133
	global $g, $cfglckkeyconsumers;
134
	flock($cfglckkey, LOCK_UN);
135
	fclose($cfglckkey);
136
	return;
137
}
138

    
139
function send_event($cmd) {
140
	global $g;
141

    
142
	if(!isset($g['event_address']))
143
		$g['event_address'] = "unix:///var/run/check_reload_status";
144
		
145
	$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
	}
159
}
160

    
161
function send_multiple_events($cmds) {
162
	global $g;
163

    
164
	if(!isset($g['event_address']))
165
		$g['event_address'] = "unix:///var/run/check_reload_status";
166
			
167
	if (!is_array($cmds))
168
		return;
169

    
170
	foreach ($cmds as $cmd)
171
		send_event($cmd);
172
}
173

    
174
function refcount_init($reference) {
175
	$shmid = @shmop_open($reference, "c", 0644, 10);
176
	@shmop_write($shmid, 0, 0);
177
	@shmop_close($shmid);
178
}
179

    
180
function refcount_reference($reference) {
181
	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
		if (intval($shm_data) < 0)
189
			$shm_data = 0;
190
		$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
	}
196
		
197
	return $shm_data;
198
}
199

    
200
function refcount_unreference($reference) {
201
	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
			//log_error("MISUAGE OF REFCOUNT_API: trace " . print_r(debug_backtrace(), true));
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
	} catch (Exception $e) {
213
		log_error($e->getMessage());
214
	}
215
	
216
	return $shm_data;
217
}
218

    
219
function is_module_loaded($module_name) {
220
	$running = `/sbin/kldstat | grep {$module_name} | /usr/bin/grep -v grep | /usr/bin/wc -l`;
221
	if (intval($running) >= 1)
222
		return true;
223
	else
224
		return false;
225
}
226

    
227
/* 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

    
232
	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

    
240
	return long2ip32(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
241
}
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
/* 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
/* Convert IP address to unsigned long int. */
269
function ip2ulong($ip) {
270
	return sprintf("%u", ip2long32($ip));
271
}
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
	return long2ip32(ip2long($ip)-1);
299
}
300

    
301
/* Return the next IP address after the given address */
302
function ip_after($ip) {
303
	return long2ip32(ip2long($ip)+1);
304
}
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
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

    
398
	$ip_long = ip2long($ipaddr);
399
	$ip_reverse = long2ip32($ip_long);
400

    
401
	if ($ipaddr == $ip_reverse)
402
		return true;
403
	else
404
		return false;
405
}
406

    
407
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
408
function is_ipaddroralias($ipaddr) {
409
	global $config;
410

    
411
	if (is_alias($ipaddr)) {
412
		if (is_array($config['aliases']['alias'])) {
413
			foreach ($config['aliases']['alias'] as $alias) {
414
				if ($alias['name'] == $ipaddr && $alias['type'] != "port")
415
					return true;
416
			}
417
		}
418
		return false;
419
	} else
420
		return is_ipaddr($ipaddr);
421

    
422
}
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

    
429
	list($hp,$np) = explode('/', $subnet);
430

    
431
	if (!is_ipaddr($hp))
432
		return false;
433

    
434
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
435
		return false;
436

    
437
	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

    
444
	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

    
455
	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
		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

    
466
	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
		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
	return preg_match('/^[0-9A-F]{2}(?:[:][0-9A-F]{2}){5}$/i', $macaddr) == 1 ? true : false;
475
}
476

    
477
/* returns true if $name is a valid name for an alias */
478
/* returns NULL if a reserved word is used */
479
function is_validaliasname($name) {
480
	/* Array of reserved words */
481
	$reserved = array("port", "pass");
482
	if (in_array($name, $reserved, true))
483
		return; /* return NULL */
484
	if (!preg_match("/[^a-zA-Z0-9_]/", $name) && (strlen($name) < 32))
485
		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
	$tmpports = explode(":", $port);
493
	foreach($tmpports as $tmpport) {
494
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
495
			continue;
496
		if (!ctype_digit($tmpport))
497
			return false;
498
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
499
			return false;
500
	}
501
	return true;
502
}
503

    
504
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
505
function is_portrange($portrange) {
506
	$ports = explode(":", $portrange);
507

    
508
	if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
509
		return true;
510
	else
511
		return false;
512
}
513

    
514
/* returns true if $port is a valid port number or an alias thereof */
515
function is_portoralias($port) {
516
	global $config;
517

    
518
	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
}
529

    
530
/* returns true if $val is a valid shaper bandwidth value */
531
function is_valid_shaperbw($val) {
532
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
533
}
534

    
535
/* 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
		$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

    
554
	return $iflist;
555
}
556

    
557
/* return the configured IP aliases list */
558
function get_configured_ip_aliases_list() {
559
	global $config;
560

    
561
	$alias_list=array();
562

    
563
	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

    
572
	return $alias_list;
573
}
574

    
575

    
576
/* 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
/* return the configured interfaces list. */
593
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
594
	global $config;
595

    
596
	$iflist = array();
597

    
598
	if(!is_array($config['interfaces']))
599
		$config = parse_config(true);
600

    
601
	/* if list */
602
	foreach($config['interfaces'] as $if => $ifdetail) {
603
		if ($only_opt && ($if == "wan" || $if == "lan"))
604
			continue;
605
		if (isset($ifdetail['enable']) || $withdisabled == true)
606
			$iflist[$if] = $if;
607
	}
608

    
609
	return $iflist;
610
}
611

    
612
/* return the configured interfaces list. */
613
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
614
	global $config;
615

    
616
	$iflist = array();
617

    
618
	/* 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
			$tmpif = get_real_interface($if);
624
			if (!empty($tmpif))
625
				$iflist[$tmpif] = $if;
626
		}
627
	}
628

    
629
	return $iflist;
630
}
631

    
632
/* return the configured interfaces list with their description. */
633
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
634
	global $config;
635

    
636
	$iflist = array();
637

    
638
	/* if list */
639
	foreach($config['interfaces'] as $if => $ifdetail) {
640
		if ($only_opt && ($if == "wan" || $if == "lan"))
641
			continue;
642
		if (isset($ifdetail['enable']) || $withdisabled == true) {
643
			if(empty($ifdetail['descr']))
644
				$iflist[$if] = strtoupper($if);
645
			else
646
				$iflist[$if] = strtoupper($ifdetail['descr']);
647
		}
648
	}
649

    
650
	return $iflist;
651
}
652

    
653
/*
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
	if(is_array($interfaces)) {
663
		foreach($interfaces as $int) {
664
			$ipaddr = get_interface_ip($int);
665
			$ip_array[$int] = $ipaddr;
666
		}
667
	}
668
	$interfaces = get_configured_carp_interface_list();
669
	if(is_array($interfaces)) 
670
		foreach($interfaces as $int => $ipaddr) 
671
			$ip_array[$int] = $ipaddr;
672
	return $ip_array;
673
}
674

    
675
/*
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
        global $config;
685
	$upints = array();
686
        /* get a list of virtual interface types */
687
        if(!$vfaces) {
688
		$vfaces = array (
689
				'bridge',
690
				'ppp',
691
				'pppoe',
692
				'pptp',
693
				'l2tp',
694
				'sl',
695
				'gif',
696
				'gre',
697
				'faith',
698
				'lo',
699
				'ng',
700
				'_vlan',
701
				'_wlan',
702
				'pflog',
703
				'plip',
704
				'pfsync',
705
				'enc',
706
				'tun',
707
				'carp',
708
				'lagg',
709
				'vip',
710
				'ipfw'
711
		);
712
	}
713
	switch($mode) {
714
	case "active":
715
                $upints = pfSense_interface_listget(IFF_UP);
716
        	break;
717
	case "media":
718
		$intlist = pfSense_interface_listget();
719
                $ifconfig = "";
720
                exec("/sbin/ifconfig -a", $ifconfig);
721
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
722
                $ifstatus = preg_grep('/status:/', $ifconfig);
723
		foreach($ifstatus as $status) {
724
			$int = array_shift($intlist);
725
			if(stristr($status, "active")) $upints[] = $int;
726
		}
727
		break;
728
	default:
729
		$upints = pfSense_interface_listget();
730
		break;
731
	}
732
        /* build interface list with netstat */
733
        $linkinfo = "";
734
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
735
        array_shift($linkinfo);
736
	/* build ip address list with netstat */
737
	$ipinfo = "";
738
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
739
	array_shift($ipinfo);
740
	foreach($linkinfo as $link) {
741
		$friendly = "";
742
		$alink = explode(" ", $link);
743
		$ifname = rtrim(trim($alink[0]), '*');
744
		/* trim out all numbers before checking for vfaces */
745
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces) &&
746
			!stristr($ifname, "_vlan") && !stristr($ifname, "_wlan")) {
747
			$toput = array(
748
					"mac" => trim($alink[1]),
749
					"up" => in_array($ifname, $upints)
750
				);
751
			foreach($ipinfo as $ip) {
752
				$aip = explode(" ", $ip);
753
				if($aip[0] == $ifname) {
754
					$toput['ipaddr'] = $aip[1];
755
				}
756
			}
757
			if (is_array($config['interfaces'])) {
758
				foreach($config['interfaces'] as $name => $int)
759
					if($int['if'] == $ifname) $friendly = $name;
760
			}
761
			switch($keyby) {
762
			case "physical":
763
				if($friendly != "") {
764
					$toput['friendly'] = $friendly;
765
				}
766
				$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
				$iflist[$ifname] = $toput;
771
				break;
772
			case "ppp":
773
				
774
			case "friendly":
775
				if($friendly != "") {
776
					$toput['if'] = $ifname;
777
					$iflist[$friendly] = $toput;
778
				}
779
				break;
780
			}
781
		}
782
	}
783
	return $iflist;
784
}
785

    
786
/****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
	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
}
802

    
803
/****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
	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
}
819

    
820
/****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
	$output = array();
832
	exec($command . ' 2>&1 ', $output);
833
	return(implode("\n", $output));
834
}
835

    
836
/* wrapper for exec() */
837
function mwexec($command, $mute = false) {
838
	global $g;
839

    
840
	if ($g['debug']) {
841
		if (!$_SERVER['REMOTE_ADDR'])
842
			echo "mwexec(): $command\n";
843
	}
844
	$oarr = array();
845
	$retval = 0;
846
	$garbage = exec("$command 2>&1", $oarr, $retval);
847

    
848
	if(isset($config['system']['developerspew']))
849
		$mute = false;
850
	if(($retval <> 0) && ($mute === false)) {
851
		$output = implode(" ", $oarr);
852
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
853
	}
854
	return $retval;
855
}
856

    
857
/* wrapper for exec() in background */
858
function mwexec_bg($command) {
859
	global $g;
860

    
861
	if ($g['debug']) {
862
		if (!$_SERVER['REMOTE_ADDR'])
863
			echo "mwexec(): $command\n";
864
	}
865

    
866
	exec("nohup $command > /dev/null 2>&1 &");
867
}
868

    
869
/* unlink a file, if it exists */
870
function unlink_if_exists($fn) {
871
	$to_do = glob($fn);
872
	if(is_array($to_do)) {
873
		foreach($to_do as $filename)
874
			@unlink($filename);
875
	} else {
876
		@unlink($fn);
877
	}
878
}
879
/* make a global alias table (for faster lookups) */
880
function alias_make_table($config) {
881
	global $aliastable;
882

    
883
	$aliastable = array();
884

    
885
	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

    
896
	return isset($aliastable[$name]);
897
}
898

    
899
/* expand a host or network alias, if necessary */
900
function alias_expand($name) {
901
	global $aliastable;
902

    
903
	if (isset($aliastable[$name]))
904
		return "\${$name}";
905
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
906
		return "{$name}";
907
	else
908
		return null;
909
}
910

    
911
function alias_expand_urltable($name) {
912
	global $config;
913
	$urltable_prefix = "/var/db/aliastables/";
914
	$urltable_filename = $urltable_prefix . $name . ".txt";
915

    
916
	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
		}
923
	}
924
	return null;
925
}
926

    
927
/* 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

    
940
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
941
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
942

    
943
	if ($sn1 == $sn2)
944
		return true;
945
	else
946
		return false;
947
}
948

    
949
/* compare two IP addresses */
950
function ipcmp($a, $b) {
951
	if (ip_less_than($a, $b))
952
		return -1;
953
	else if (ip_greater_than($a, $b))
954
		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
	$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
963
	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
	if(!file_exists("/usr/local/sbin/gzsig"))
971
		return 4;
972

    
973
	return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname));
974
}
975

    
976
/* obtain MAC address given an IP address by looking at the ARP table */
977
function arp_get_mac_by_ip($ip) {
978
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
979
	$arpoutput = "";
980
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
981

    
982
	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

    
991
	return false;
992
}
993

    
994
/* return a fieldname that is safe for xml usage */
995
function xml_safe_fieldname($fieldname) {
996
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
997
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
998
			 ':', ',', '.', '\'', '\\'
999
		);
1000
	return strtolower(str_replace($replace, "", $fieldname));
1001
}
1002

    
1003
function mac_format($clientmac) {
1004
    global $config;
1005

    
1006
    $mac = explode(":", $clientmac);
1007
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
1008

    
1009
    switch($mac_format) {
1010
        case 'singledash':
1011
		return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
1012

    
1013
        case 'ietf':
1014
		return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
1015

    
1016
        case 'cisco':
1017
		return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
1018

    
1019
        case 'unformatted':
1020
		return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
1021

    
1022
        default:
1023
		return $clientmac;
1024
    }
1025
}
1026

    
1027
function resolve_retry($hostname, $retries = 5) {
1028

    
1029
	if (is_ipaddr($hostname))
1030
		return $hostname;
1031

    
1032
	for ($i = 0; $i < $retries; $i++) {
1033
		$ip = gethostbyname($hostname);
1034

    
1035
		if ($ip && $ip != $hostname) {
1036
			/* success */
1037
			return $ip;
1038
		}
1039

    
1040
		sleep(1);
1041
	}
1042

    
1043
	return false;
1044
}
1045

    
1046
function format_bytes($bytes) {
1047
	if ($bytes >= 1073741824) {
1048
		return sprintf("%.2f GB", $bytes/1073741824);
1049
	} else if ($bytes >= 1048576) {
1050
		return sprintf("%.2f MB", $bytes/1048576);
1051
	} else if ($bytes >= 1024) {
1052
		return sprintf("%.0f KB", $bytes/1024);
1053
	} else {
1054
		return sprintf("%d bytes", $bytes);
1055
	}
1056
}
1057

    
1058
function update_filter_reload_status($text) {
1059
	global $g;
1060

    
1061
	file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1062
}
1063

    
1064
/****f* util/return_dir_as_array
1065
 * NAME
1066
 *   return_dir_as_array - Return a directory's contents as an array.
1067
 * INPUTS
1068
 *   $dir       - string containing the path to the desired directory.
1069
 * RESULT
1070
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1071
 ******/
1072
function return_dir_as_array($dir) {
1073
	$dir_array = array();
1074
	if (is_dir($dir)) {
1075
		if ($dh = opendir($dir)) {
1076
			while (($file = readdir($dh)) !== false) {
1077
				$canadd = 0;
1078
				if($file == ".") $canadd = 1;
1079
				if($file == "..") $canadd = 1;
1080
				if($canadd == 0)
1081
					array_push($dir_array, $file);
1082
			}
1083
			closedir($dh);
1084
		}
1085
	}
1086
	return $dir_array;
1087
}
1088

    
1089
function run_plugins($directory) {
1090
	global $config, $g;
1091

    
1092
	/* process packager manager custom rules */
1093
	$files = return_dir_as_array($directory);
1094
	if (is_array($files)) {
1095
		foreach ($files as $file) {
1096
			if (stristr($file, ".sh") == true)
1097
				mwexec($directory . $file . " start");
1098
			else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1099
				require_once($directory . "/" . $file);
1100
		}
1101
	}
1102
}
1103

    
1104
/*
1105
 *    safe_mkdir($path, $mode = 0755)
1106
 *    create directory if it doesn't already exist and isn't a file!
1107
 */
1108
function safe_mkdir($path, $mode=0755) {
1109
	global $g;
1110

    
1111
	if (!is_file($path) && !is_dir($path)) {
1112
		return @mkdir($path, $mode, true);
1113
	} else {
1114
		return false;
1115
	}
1116
}
1117

    
1118
/*
1119
 * make_dirs($path, $mode = 0755)
1120
 * create directory tree recursively (mkdir -p)
1121
 */
1122
function make_dirs($path, $mode = 0755) {
1123
	$base = '';
1124
	foreach (explode('/', $path) as $dir) {
1125
		$base .= "/$dir";
1126
		if (!is_dir($base)) {
1127
			if (!@mkdir($base, $mode))
1128
				return false;
1129
		}
1130
	}
1131
	return true;
1132
}
1133

    
1134
/*
1135
 * get_sysctl($names)
1136
 * Get values of sysctl OID's listed in $names (accepts an array or a single
1137
 * name) and return an array of key/value pairs set for those that exist
1138
 */
1139
function get_sysctl($names) {
1140
	if (empty($names))
1141
		return array();
1142

    
1143
	if (is_array($names)) {
1144
		$name_list = array();
1145
		foreach ($names as $name) {
1146
			$name_list[] = escapeshellarg($name);
1147
		}
1148
	} else
1149
		$name_list = array(escapeshellarg($names));
1150

    
1151
	exec("/sbin/sysctl -i " . implode(" ", $name_list), $output);
1152
	$values = array();
1153
	foreach ($output as $line) {
1154
		$line = explode(": ", $line, 2);
1155
		if (count($line) == 2)
1156
			$values[$line[0]] = $line[1];
1157
	}
1158

    
1159
	return $values;
1160
}
1161

    
1162
/*
1163
 * set_sysctl($value_list)
1164
 * Set sysctl OID's listed as key/value pairs and return
1165
 * an array with keys set for those that succeeded
1166
 */
1167
function set_sysctl($values) {
1168
	if (empty($values))
1169
		return array();
1170

    
1171
	$value_list = array();
1172
	foreach ($values as $key => $value) {
1173
		$value_list[] = escapeshellarg($key) . "=" . escapeshellarg($value);
1174
	}
1175

    
1176
	exec("/sbin/sysctl -i " . implode(" ", $value_list), $output, $success);
1177

    
1178
	/* Retry individually if failed (one or more read-only) */
1179
	if ($success <> 0 && count($value_list) > 1) {
1180
		foreach ($value_list as $value) {
1181
			exec("/sbin/sysctl -i " . $value, $output);
1182
		}
1183
	}
1184

    
1185
	$ret = array();
1186
	foreach ($output as $line) {
1187
		$line = explode(": ", $line, 2);
1188
		if (count($line) == 2)
1189
			$ret[$line[0]] = true;
1190
	}
1191

    
1192
	return $ret;
1193
}
1194

    
1195
/*
1196
 *     get_memory()
1197
 *     returns an array listing the amount of
1198
 *     memory installed in the hardware
1199
 *     [0]real and [1]available
1200
 */
1201
function get_memory() {
1202
	$matches = "";
1203
	if(file_exists("/var/log/dmesg.boot"))
1204
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1205
	else
1206
		$mem = `dmesg -a | grep memory`;			
1207
	if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1208
		return array($matches[1][0], $matches[1][0]);
1209
	if(!$real && !$avail) {
1210
		$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1211
		$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1212
		/* convert from bytes to megabytes */
1213
		return array(($real/1048576),($avail/1048576));
1214
	}
1215
}
1216

    
1217
function mute_kernel_msgs() {
1218
	global $config;
1219
	// Do not mute serial console.  The kernel gets very very cranky
1220
	// and will start dishing you cannot control tty errors.
1221
	if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1222
		return;
1223
	if($config['system']['enableserial']) 
1224
		return;			
1225
	exec("/sbin/conscontrol mute on");
1226
}
1227

    
1228
function unmute_kernel_msgs() {
1229
	global $config;
1230
	// Do not mute serial console.  The kernel gets very very cranky
1231
	// and will start dishing you cannot control tty errors.
1232
	if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1233
		return;
1234
	exec("/sbin/conscontrol mute off");
1235
}
1236

    
1237
function start_devd() {
1238
	global $g;
1239

    
1240
	exec("/sbin/devd");
1241
	sleep(1);
1242
}
1243

    
1244
function is_interface_vlan_mismatch() {
1245
	global $config, $g;
1246

    
1247
	if (is_array($config['vlans']['vlan'])) {
1248
		foreach ($config['vlans']['vlan'] as $vlan) {
1249
			if (does_interface_exist($vlan['if']) == false)
1250
				return true;
1251
		}
1252
	}
1253

    
1254
	return false;
1255
}
1256

    
1257
function is_interface_mismatch() {
1258
	global $config, $g;
1259

    
1260
	$do_assign = false;
1261
	$i = 0;
1262
	if (is_array($config['interfaces'])) {
1263
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
1264
			if (preg_match("/^enc|^cua|^tun|^l2tp|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1265
				// Do not check these interfaces.
1266
				$i++;
1267
				continue;
1268
			}
1269
			else if (does_interface_exist($ifcfg['if']) == false) {
1270
				$do_assign = true;
1271
			} else
1272
				$i++;
1273
		}
1274
	}
1275

    
1276
	if ($g['minimum_nic_count'] > $i) {
1277
		$do_assign = true;
1278
	} else if (file_exists("{$g['tmp_path']}/assign_complete"))
1279
	$do_assign = false;
1280

    
1281
	return $do_assign;
1282
}
1283

    
1284
/* sync carp entries to other firewalls */
1285
function carp_sync_client() {
1286
	global $g;
1287
	send_event("filter sync");
1288
}
1289

    
1290
/****f* util/isAjax
1291
 * NAME
1292
 *   isAjax - reports if the request is driven from prototype
1293
 * INPUTS
1294
 *   none
1295
 * RESULT
1296
 *   true/false
1297
 ******/
1298
function isAjax() {
1299
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1300
}
1301

    
1302
/****f* util/timeout
1303
 * NAME
1304
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1305
 * INPUTS
1306
 *   optional, seconds to wait before timeout. Default 9 seconds.
1307
 * RESULT
1308
 *   returns 1 char of user input or null if no input.
1309
 ******/
1310
function timeout($timer = 9) {
1311
	while(!isset($key)) {
1312
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1313
		else { echo chr(8). "{$timer}"; }
1314
		`/bin/stty -icanon min 0 time 25`;
1315
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1316
		`/bin/stty icanon`;
1317
		if ($key == '')
1318
			unset($key);
1319
		$timer--;
1320
		if ($timer == 0)
1321
			break;
1322
	}
1323
	return $key;	
1324
}
1325

    
1326
/****f* util/msort
1327
 * NAME
1328
 *   msort - sort array
1329
 * INPUTS
1330
 *   $array to be sorted, field to sort by, direction of sort
1331
 * RESULT
1332
 *   returns newly sorted array
1333
 ******/
1334
function msort($array, $id="id", $sort_ascending=true) {
1335
	$temp_array = array();
1336
	while(count($array)>0) {
1337
		$lowest_id = 0;
1338
		$index=0;
1339
		foreach ($array as $item) {
1340
			if (isset($item[$id])) {
1341
				if ($array[$lowest_id][$id]) {
1342
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1343
						$lowest_id = $index;
1344
					}
1345
				}
1346
			}
1347
			$index++;
1348
		}
1349
		$temp_array[] = $array[$lowest_id];
1350
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1351
	}
1352
	if ($sort_ascending) {
1353
		return $temp_array;
1354
	} else {
1355
    	return array_reverse($temp_array);
1356
	}
1357
}
1358

    
1359
/****f* util/color
1360
 * NAME
1361
 *   color - outputs a color code to the ansi terminal if supported
1362
 * INPUTS
1363
 *   color code or color name
1364
 * RESULT
1365
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1366
 ******/
1367
function color($color = "0m") {
1368
	/*
1369
		Color codes available:
1370
		 0m reset; clears all colors and styles (to white on black)
1371
		 1m bold on (see below)
1372
		 3m italics on
1373
		 4m underline on
1374
		 7m inverse on; reverses foreground & background colors
1375
		 9m strikethrough on
1376
		 22m bold off (see below)
1377
		 23m italics off
1378
		 24m underline off
1379
		 27m inverse off
1380
		 29m strikethrough off
1381
		 30m set foreground color to black
1382
		 31m set foreground color to red
1383
		 32m set foreground color to green
1384
		 33m set foreground color to yellow
1385
		 34m set foreground color to blue
1386
		 35m set foreground color to magenta (purple)
1387
		 36m set foreground color to cyan
1388
		 37m set foreground color to white
1389
		 40m  set background color to black
1390
		 41m set background color to red
1391
		 42m set background color to green
1392
		 43m set background color to yellow
1393
		 44m set background color to blue
1394
		 45m set background color to magenta (purple)
1395
		 46m set background color to cyan
1396
		 47m set background color to white
1397
		 49m set background color to default (black)
1398
	*/	
1399
	// Allow caching of TERM to 
1400
	// speedup subequence requests.
1401
	global $TERM;
1402
	if(!$TERM) 
1403
		$TERM=`/usr/bin/env | grep color`;
1404
	if(!$TERM)
1405
		$TERM=`/usr/bin/env | grep cons25`;
1406
	if($TERM) {
1407
		$ESCAPE=chr(27);
1408
		switch ($color) {
1409
			case "black":
1410
				return "{$ESCAPE}[30m"; 
1411
			case "red":
1412
				return "{$ESCAPE}[31m"; 
1413
			case "green":
1414
				return "{$ESCAPE}[32m"; 
1415
			case "yellow":
1416
				return "{$ESCAPE}[33m"; 
1417
			case "blue":
1418
				return "{$ESCAPE}[34m"; 
1419
			case "magenta":
1420
				return "{$ESCAPE}[35m"; 
1421
			case "cyan":
1422
				return "{$ESCAPE}[36m"; 
1423
			case "white":
1424
				return "{$ESCAPE}[37m"; 
1425
			case "default":
1426
				return "{$ESCAPE}[39m"; 
1427
		}
1428
		return "{$ESCAPE}[{$color}";
1429
	}
1430
}
1431

    
1432
/****f* util/is_URL
1433
 * NAME
1434
 *   is_URL
1435
 * INPUTS
1436
 *   string to check
1437
 * RESULT
1438
 *   Returns true if item is a URL
1439
 ******/
1440
function is_URL($url) {
1441
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1442
	if($match)
1443
		return true;	
1444
	return false;
1445
}
1446

    
1447
function is_file_included($file = "") {
1448
	$files = get_included_files();
1449
	if (in_array($file, $files))
1450
		return true;
1451
	
1452
	return false;
1453
}
1454

    
1455
/*
1456
	This function was borrowed from a comment on PHP.net at the following URL:
1457
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
1458
 */
1459
function array_merge_recursive_unique($array0, $array1) {
1460

    
1461
	$arrays = func_get_args();
1462
	$remains = $arrays;
1463

    
1464
	// We walk through each arrays and put value in the results (without
1465
	// considering previous value).
1466
	$result = array();
1467

    
1468
	// loop available array
1469
	foreach($arrays as $array) {
1470

    
1471
		// The first remaining array is $array. We are processing it. So
1472
		// we remove it from remaing arrays.
1473
        array_shift($remains);
1474

    
1475
		// We don't care non array param, like array_merge since PHP 5.0.
1476
		if(is_array($array)) {
1477
			// Loop values
1478
			foreach($array as $key => $value) {
1479
				if(is_array($value)) {
1480
					// we gather all remaining arrays that have such key available
1481
					$args = array();
1482
					foreach($remains as $remain) {
1483
						if(array_key_exists($key, $remain)) {
1484
							array_push($args, $remain[$key]);
1485
						}
1486
					}
1487

    
1488
					if(count($args) > 2) {
1489
						// put the recursion
1490
						$result[$key] = call_user_func_array(__FUNCTION__, $args);
1491
					} else {
1492
						foreach($value as $vkey => $vval) {
1493
							$result[$key][$vkey] = $vval;
1494
						}
1495
					}
1496
				} else {
1497
					// simply put the value
1498
					$result[$key] = $value;
1499
				}
1500
			}
1501
		}
1502
	}
1503
	return $result;
1504
}
1505

    
1506
function get_staticroutes($returnsubnetsonly = false) {
1507
	global $config;
1508
	require_once('filter.inc');
1509
	$allstaticroutes = array();
1510
	$allsubnets = array();
1511

    
1512
	/* Bail if there are no routes, but return an array always so callers don't have to check. */
1513
	if (!is_array($config['staticroutes']['route']))
1514
		return array();
1515

    
1516
	/* Loop through routes and expand aliases as we find them. */
1517
	foreach ($config['staticroutes']['route'] as $route) {
1518
		if (is_alias($route['network'])) {
1519
			$subnets = filter_expand_alias_array($route['network']);
1520
			foreach ($subnets as $net) {
1521
				if (is_ipaddr($net))
1522
					$net .= "/32";
1523
				/* This must be a hostname, we can't use it. */
1524
				if (!is_subnet($net))
1525
					continue;
1526
				$temproute = $route;
1527
				$temproute['network'] = $net;
1528
				$allstaticroutes[] = $temproute;
1529
				$allsubnets[] = $net;
1530
			}
1531
		} elseif (is_subnet($route['network'])) {
1532
			$allstaticroutes[] = $route;
1533
			$allsubnets[] = $route['network'];
1534
		}
1535
	}
1536
	if ($returnsubnetsonly) {
1537
		return $allsubnets;
1538
	} else {
1539
		return $allstaticroutes;
1540
	}
1541
}
1542
?>
(50-50/62)