Project

General

Profile

Download (39.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
		@chmod("{$g['tmp_path']}/{$lock}.lock", 0666);
123
	}
124
	$cfglckkeyconsumers++;
125
	if ($fp = fopen("{$g['tmp_path']}/{$lock}.lock", "w")) {
126
		if (flock($fp, $op))
127
			return $fp;
128
		else
129
			fclose($fp);
130
	}
131
}
132

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

    
141
function send_event($cmd) {
142
	global $g;
143

    
144
	if(!isset($g['event_address']))
145
		$g['event_address'] = "unix:///var/run/check_reload_status";
146
		
147
	$try = 0;
148
	while ($try < 3) {
149
		$fd = @fsockopen($g['event_address']);
150
		if ($fd) {
151
			fwrite($fd, $cmd);
152
			$resp = fread($fd, 4096);
153
			if ($resp != "OK\n")
154
				log_error("send_event: sent {$cmd} got {$resp}");
155
			fclose($fd);
156
			$try = 3;
157
		} else if (!is_process_running("check_reload_status"))
158
			mwexec_bg("/usr/bin/nice -n20 /usr/local/sbin/check_reload_status");
159
		$try++;
160
	}
161
}
162

    
163
function send_multiple_events($cmds) {
164
	global $g;
165

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

    
172
	foreach ($cmds as $cmd)
173
		send_event($cmd);
174
}
175

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

    
182
function refcount_reference($reference) {
183
	try {
184
		$shmid = @shmop_open($reference, "w", 0, 0);
185
		if (!$shmid) {
186
			refcount_init($reference);
187
			$shmid = @shmop_open($reference, "w", 0, 0);
188
		}
189
		$shm_data = @shmop_read($shmid, 0, 10);
190
		if (intval($shm_data) < 0)
191
			$shm_data = 0;
192
		$shm_data = intval($shm_data) + 1;
193
		@shmop_write($shmid, $shm_data, 0);
194
		@shmop_close($shmid);
195
	} catch (Exception $e) {
196
		log_error($e->getMessage());
197
	}
198
		
199
	return $shm_data;
200
}
201

    
202
function refcount_unreference($reference) {
203
	try {
204
		/* We assume that the shared memory exists. */
205
		$shmid = @shmop_open($reference, "w", 0, 0);
206
		$shm_data = @shmop_read($shmid, 0, 10);
207
		$shm_data = intval($shm_data) - 1;
208
		if ($shm_data < 0) {
209
			//log_error("MISUAGE OF REFCOUNT_API: trace " . print_r(debug_backtrace(), true));
210
			log_error("Reference {$reference} is going negative, not doing unreference.");
211
		} else
212
			@shmop_write($shmid, $shm_data, 0);
213
		@shmop_close($shmid);
214
	} catch (Exception $e) {
215
		log_error($e->getMessage());
216
	}
217
	
218
	return $shm_data;
219
}
220

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

    
229
/* return the subnet address given a host address and a subnet bit count */
230
function gen_subnet($ipaddr, $bits) {
231
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
232
		return "";
233

    
234
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
235
}
236

    
237
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
238
function gen_subnet_max($ipaddr, $bits) {
239
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
240
		return "";
241

    
242
	return long2ip32(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
243
}
244

    
245
/* returns a subnet mask (long given a bit count) */
246
function gen_subnet_mask_long($bits) {
247
	$sm = 0;
248
	for ($i = 0; $i < $bits; $i++) {
249
		$sm >>= 1;
250
		$sm |= 0x80000000;
251
	}
252
	return $sm;
253
}
254

    
255
/* same as above but returns a string */
256
function gen_subnet_mask($bits) {
257
	return long2ip(gen_subnet_mask_long($bits));
258
}
259

    
260
/* Convert long int to IP address, truncating to 32-bits. */
261
function long2ip32($ip) {
262
	return long2ip($ip & 0xFFFFFFFF);
263
}
264

    
265
/* Convert IP address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. */
266
function ip2long32($ip) {
267
	return ( ip2long($ip) & 0xFFFFFFFF );
268
}
269

    
270
/* Convert IP address to unsigned long int. */
271
function ip2ulong($ip) {
272
	return sprintf("%u", ip2long32($ip));
273
}
274

    
275
/* Find out how many IPs are contained within a given IP range
276
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
277
 */
278
function ip_range_size($startip, $endip) {
279
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
280
		// Operate as unsigned long because otherwise it wouldn't work
281
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
282
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
283
	}
284
	return -1;
285
}
286

    
287
/* Find the smallest possible subnet mask which can contain a given number of IPs
288
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
289
 */
290
function find_smallest_cidr($number) {
291
	$smallest = 1;
292
	for ($b=32; $b > 0; $b--) {
293
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
294
	}
295
	return (32-$smallest);
296
}
297

    
298
/* Return the previous IP address before the given address */
299
function ip_before($ip) {
300
	return long2ip32(ip2long($ip)-1);
301
}
302

    
303
/* Return the next IP address after the given address */
304
function ip_after($ip) {
305
	return long2ip32(ip2long($ip)+1);
306
}
307

    
308
/* Return true if the first IP is 'before' the second */
309
function ip_less_than($ip1, $ip2) {
310
	// Compare as unsigned long because otherwise it wouldn't work when
311
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
312
	return ip2ulong($ip1) < ip2ulong($ip2);
313
}
314

    
315
/* Return true if the first IP is 'after' the second */
316
function ip_greater_than($ip1, $ip2) {
317
	// Compare as unsigned long because otherwise it wouldn't work
318
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
319
	return ip2ulong($ip1) > ip2ulong($ip2);
320
}
321

    
322
/* Convert a range of IPs to an array of subnets which can contain the range. */
323
function ip_range_to_subnet_array($startip, $endip) {
324
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
325
		return array();
326
	}
327

    
328
	// Container for subnets within this range.
329
	$rangesubnets = array();
330

    
331
	// Figure out what the smallest subnet is that holds the number of IPs in the given range.
332
	$cidr = find_smallest_cidr(ip_range_size($startip, $endip));
333

    
334
	// Loop here to reduce subnet size and retest as needed. We need to make sure
335
	//   that the target subnet is wholly contained between $startip and $endip.
336
	for ($cidr; $cidr <= 32; $cidr++) {
337
		// Find the network and broadcast addresses for the subnet being tested.
338
		$targetsub_min = gen_subnet($startip, $cidr);
339
		$targetsub_max = gen_subnet_max($startip, $cidr);
340

    
341
		// Check best case where the range is exactly one subnet.
342
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
343
			// Hooray, the range is exactly this subnet!
344
			return array("{$startip}/{$cidr}");
345
		}
346

    
347
		// These remaining scenarios will find a subnet that uses the largest
348
		//  chunk possible of the range being tested, and leave the rest to be
349
		//  tested recursively after the loop.
350

    
351
		// Check if the subnet begins with $startip and ends before $endip
352
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
353
			break;
354
		}
355

    
356
		// Check if the subnet ends at $endip and starts after $startip
357
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
358
			break;
359
		}
360

    
361
		// Check if the subnet is between $startip and $endip
362
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
363
			break;
364
		}
365
	}
366

    
367
	// Some logic that will recursivly search from $startip to the first IP before the start of the subnet we just found.
368
	// NOTE: This may never be hit, the way the above algo turned out, but is left for completeness.
369
	if ($startip != $targetsub_min) {
370
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array($startip, ip_before($targetsub_min)));
371
	}
372

    
373
	// Add in the subnet we found before, to preserve ordering
374
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
375

    
376
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
377
	if ($endip != $targetsub_max) {
378
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
379
	}
380
	return $rangesubnets;
381
}
382

    
383
function is_iprange($range) {
384
	if (substr_count($range, '-') != 1) {
385
		return false;
386
	}
387
	list($ip1, $ip2) = explode ('-', $range);
388
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
389
}
390

    
391
function is_numericint($arg) {
392
	return (preg_match("/[^0-9]/", $arg) ? false : true);
393
}
394

    
395
/* returns true if $ipaddr is a valid dotted IPv4 address */
396
function is_ipaddr($ipaddr) {
397
	if (!is_string($ipaddr))
398
		return false;
399

    
400
	$ip_long = ip2long($ipaddr);
401
	$ip_reverse = long2ip32($ip_long);
402

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

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

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

    
424
}
425

    
426
/* returns true if $subnet is a valid subnet in CIDR format */
427
function is_subnet($subnet) {
428
	if (!is_string($subnet))
429
		return false;
430

    
431
	list($hp,$np) = explode('/', $subnet);
432

    
433
	if (!is_ipaddr($hp))
434
		return false;
435

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

    
439
	return true;
440
}
441

    
442
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
443
function is_subnetoralias($subnet) {
444
	global $aliastable;
445

    
446
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
447
		return true;
448
	else
449
		return is_subnet($subnet);
450
}
451

    
452
/* returns true if $hostname is a valid hostname */
453
function is_hostname($hostname) {
454
	if (!is_string($hostname))
455
		return false;
456

    
457
	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))
458
		return true;
459
	else
460
		return false;
461
}
462

    
463
/* returns true if $domain is a valid domain name */
464
function is_domain($domain) {
465
	if (!is_string($domain))
466
		return false;
467

    
468
	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))
469
		return true;
470
	else
471
		return false;
472
}
473

    
474
/* returns true if $macaddr is a valid MAC address */
475
function is_macaddr($macaddr) {
476
	return preg_match('/^[0-9A-F]{2}(?:[:][0-9A-F]{2}){5}$/i', $macaddr) == 1 ? true : false;
477
}
478

    
479
/* returns true if $name is a valid name for an alias */
480
/* returns NULL if a reserved word is used */
481
function is_validaliasname($name) {
482
	/* Array of reserved words */
483
	$reserved = array("port", "pass");
484
	if (in_array($name, $reserved, true))
485
		return; /* return NULL */
486
	if (!preg_match("/[^a-zA-Z0-9_]/", $name) && (strlen($name) < 32))
487
		return true;
488
	else
489
		return false;
490
}
491

    
492
/* returns true if $port is a valid TCP/UDP port */
493
function is_port($port) {
494
	$tmpports = explode(":", $port);
495
	foreach($tmpports as $tmpport) {
496
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
497
			continue;
498
		if (!ctype_digit($tmpport))
499
			return false;
500
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
501
			return false;
502
	}
503
	return true;
504
}
505

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

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

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

    
520
	if (is_alias($port)) {
521
		if (is_array($config['aliases']['alias'])) {
522
			foreach ($config['aliases']['alias'] as $alias) {
523
				if ($alias['name'] == $port && $alias['type'] == "port")
524
					return true;
525
				}
526
			}
527
			return false;
528
	} else
529
		return is_port($port);
530
}
531

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

    
537
/* return the configured carp interface list */
538
function get_configured_carp_interface_list() {
539
	global $config;
540

    
541
	$iflist = array();
542

    
543
	if(is_array($config['virtualip']['vip'])) {
544
		$viparr = &$config['virtualip']['vip'];
545
		foreach ($viparr as $vip) {
546
			switch ($vip['mode']) {
547
				case "carp":
548
				case "carpdev-dhcp":
549
					$vipif = "vip" . $vip['vhid'];
550
					$iflist[$vipif] = $vip['subnet'];
551
					break;
552
			}
553
		}
554
	}
555

    
556
	return $iflist;
557
}
558

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

    
563
	$alias_list=array();
564

    
565
	if(is_array($config['virtualip']['vip'])) {
566
		$viparr = &$config['virtualip']['vip'];
567
		foreach ($viparr as $vip) {
568
			if ($vip['mode']=="ipalias") {
569
				$alias_list[$vip['subnet']] = $vip['interface'];
570
			}
571
		}
572
	}
573

    
574
	return $alias_list;
575
}
576

    
577

    
578
/* comparison function for sorting by the order in which interfaces are normally created */
579
function compare_interface_friendly_names($a, $b) {
580
	if ($a == $b)
581
		return 0;
582
	else if ($a == 'wan')
583
		return -1;
584
	else if ($b == 'wan')
585
		return 1;
586
	else if ($a == 'lan')
587
		return -1;
588
	else if ($b == 'lan')
589
		return 1;
590

    
591
	return strnatcmp($a, $b);
592
}
593

    
594
/* return the configured interfaces list. */
595
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
596
	global $config;
597

    
598
	$iflist = array();
599

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

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

    
611
	return $iflist;
612
}
613

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

    
618
	$iflist = array();
619

    
620
	/* if list */
621
	foreach($config['interfaces'] as $if => $ifdetail) {
622
		if ($only_opt && ($if == "wan" || $if == "lan"))
623
			continue;
624
		if (isset($ifdetail['enable']) || $withdisabled == true) {
625
			$tmpif = get_real_interface($if);
626
			if (!empty($tmpif))
627
				$iflist[$tmpif] = $if;
628
		}
629
	}
630

    
631
	return $iflist;
632
}
633

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

    
638
	$iflist = array();
639

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

    
652
	return $iflist;
653
}
654

    
655
/*
656
 *   get_configured_ip_addresses() - Return a list of all configured
657
 *   interfaces IP Addresses
658
 *
659
 */
660
function get_configured_ip_addresses() {
661
	require_once("interfaces.inc");
662
	$ip_array = array();
663
	$interfaces = get_configured_interface_list();
664
	if(is_array($interfaces)) {
665
		foreach($interfaces as $int) {
666
			$ipaddr = get_interface_ip($int);
667
			$ip_array[$int] = $ipaddr;
668
		}
669
	}
670
	$interfaces = get_configured_carp_interface_list();
671
	if(is_array($interfaces)) 
672
		foreach($interfaces as $int => $ipaddr) 
673
			$ip_array[$int] = $ipaddr;
674
	return $ip_array;
675
}
676

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

    
788
/****f* util/log_error
789
* NAME
790
*   log_error  - Sends a string to syslog.
791
* INPUTS
792
*   $error     - string containing the syslog message.
793
* RESULT
794
*   null
795
******/
796
function log_error($error) {
797
	global $g;
798
	$page = $_SERVER['SCRIPT_NAME'];
799
	syslog(LOG_WARNING, "$page: $error");
800
	if ($g['debug'])
801
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
802
	return;
803
}
804

    
805
/****f* util/log_auth
806
* NAME
807
*   log_error  - Sends a string to syslog as LOG_AUTH facility
808
* INPUTS
809
*   $error     - string containing the syslog message.
810
* RESULT
811
*   null
812
******/
813
function log_auth($error) {
814
	global $g;
815
	$page = $_SERVER['SCRIPT_NAME'];
816
	syslog(LOG_AUTH, "$page: $error");
817
	if ($g['debug'])
818
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
819
	return;
820
}
821

    
822
/****f* util/exec_command
823
 * NAME
824
 *   exec_command - Execute a command and return a string of the result.
825
 * INPUTS
826
 *   $command   - String of the command to be executed.
827
 * RESULT
828
 *   String containing the command's result.
829
 * NOTES
830
 *   This function returns the command's stdout and stderr.
831
 ******/
832
function exec_command($command) {
833
	$output = array();
834
	exec($command . ' 2>&1 ', $output);
835
	return(implode("\n", $output));
836
}
837

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

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

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

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

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

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

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

    
885
	$aliastable = array();
886

    
887
	if (is_array($config['aliases']['alias'])) {
888
		foreach ($config['aliases']['alias'] as $alias) {
889
			if ($alias['name'])
890
				$aliastable[$alias['name']] = $alias['address'];
891
		}
892
	}
893
}
894
/* check if an alias exists */
895
function is_alias($name) {
896
	global $aliastable;
897

    
898
	return isset($aliastable[$name]);
899
}
900

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

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

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

    
918
	foreach ($config['aliases']['alias'] as $alias) {
919
		if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
920
			if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
921
				return $urltable_filename;
922
			else if (process_alias_urltable($name, $alias["url"], 0, true))
923
				return $urltable_filename;
924
		}
925
	}
926
	return null;
927
}
928

    
929
/* find out whether two subnets overlap */
930
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
931

    
932
	if (!is_numeric($bits1))
933
		$bits1 = 32;
934
	if (!is_numeric($bits2))
935
		$bits2 = 32;
936

    
937
	if ($bits1 < $bits2)
938
		$relbits = $bits1;
939
	else
940
		$relbits = $bits2;
941

    
942
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
943
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
944

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

    
951
/* compare two IP addresses */
952
function ipcmp($a, $b) {
953
	if (ip_less_than($a, $b))
954
		return -1;
955
	else if (ip_greater_than($a, $b))
956
		return 1;
957
	else
958
		return 0;
959
}
960

    
961
/* return true if $addr is in $subnet, false if not */
962
function ip_in_subnet($addr,$subnet) {
963
	list($ip, $mask) = explode('/', $subnet);
964
	$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
965
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
966
}
967

    
968
/* verify (and remove) the digital signature on a file - returns 0 if OK */
969
function verify_digital_signature($fname) {
970
	global $g;
971

    
972
	if(!file_exists("/usr/local/sbin/gzsig"))
973
		return 4;
974

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

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

    
984
	if ($arpoutput[0]) {
985
		$arpi = explode(" ", $arpoutput[0]);
986
		$macaddr = $arpi[3];
987
		if (is_macaddr($macaddr))
988
			return $macaddr;
989
		else
990
			return false;
991
	}
992

    
993
	return false;
994
}
995

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

    
1005
function mac_format($clientmac) {
1006
    global $config;
1007

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

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

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

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

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

    
1024
        default:
1025
		return $clientmac;
1026
    }
1027
}
1028

    
1029
function resolve_retry($hostname, $retries = 5) {
1030

    
1031
	if (is_ipaddr($hostname))
1032
		return $hostname;
1033

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

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

    
1042
		sleep(1);
1043
	}
1044

    
1045
	return false;
1046
}
1047

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

    
1060
function update_filter_reload_status($text) {
1061
	global $g;
1062

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

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

    
1091
function run_plugins($directory) {
1092
	global $config, $g;
1093

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

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

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

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

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

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

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

    
1161
	return $values;
1162
}
1163

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

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

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

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

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

    
1194
	return $ret;
1195
}
1196

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

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

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

    
1239
function start_devd() {
1240
	global $g;
1241

    
1242
	exec("/sbin/devd");
1243
	sleep(1);
1244
}
1245

    
1246
function is_interface_vlan_mismatch() {
1247
	global $config, $g;
1248

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

    
1256
	return false;
1257
}
1258

    
1259
function is_interface_mismatch() {
1260
	global $config, $g;
1261

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

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

    
1283
	return $do_assign;
1284
}
1285

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

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

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

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

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

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

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

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

    
1463
	$arrays = func_get_args();
1464
	$remains = $arrays;
1465

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

    
1470
	// loop available array
1471
	foreach($arrays as $array) {
1472

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

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

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

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

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

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

    
1545
function get_current_theme() {
1546
	global $config, $g;
1547
	/*
1548
	 *   if user has selected a custom template, use it.
1549
	 *   otherwise default to pfsense tempalte
1550
	 */
1551
	if (($g["disablethemeselection"] === true) && !empty($g["default_theme"]) && (is_dir($g["www_path"].'/themes/'.$g["default_theme"])))
1552
		$theme = $g["default_theme"];
1553
	elseif($config['theme'] <> "" && (is_dir($g["www_path"].'/themes/'.$config['theme'])))
1554
		$theme = $config['theme'];
1555
	else
1556
		$theme = "pfsense";
1557
	/*
1558
	 *  If this device is an apple ipod/iphone
1559
	 *  switch the theme to one that works with it.
1560
	 */
1561
	$lowres_ua = array("iPhone", "iPod", "iPad", "Android", "BlackBerry", "Opera Mini", "Opera Mobi", "PlayBook");
1562
	foreach($lowres_ua as $useragent)
1563
		if(strstr($_SERVER['HTTP_USER_AGENT'], $useragent))
1564
			$theme = (empty($g['theme_lowres']) && (is_dir($g["www_path"].'/themes/'.$g['theme_lowres']))) ? "pfsense" : $g['theme_lowres'];
1565
	return $theme;
1566
}
1567
?>
(50-50/62)