Project

General

Profile

Download (43.3 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(sprintf(gettext("WARNING: Could not mark subsystem: %s dirty"), $subsystem));
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(gettext("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", 0644, 10);
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
		$shm_data = intval($shm_data) + 1;
189
		@shmop_write($shmid, $shm_data, 0);
190
		@shmop_close($shmid);
191
	} catch (Exception $e) {
192
		log_error($e->getMessage());
193
	}
194

    
195
	return $shm_data;
196
}
197

    
198
function refcount_unreference($reference) {
199
	try {
200
		/* We assume that the shared memory exists. */
201
		$shmid = @shmop_open($reference, "w", 0, 0);
202
		$shm_data = @shmop_read($shmid, 0, 10);
203
		$shm_data = intval($shm_data) - 1;
204
		if ($shm_data < 0) {
205
			//debug_backtrace();
206
			log_error(sprintf(gettext("Reference %s is going negative, not doing unreference."), $reference));
207
		} else
208
			@shmop_write($shmid, $shm_data, 0);
209
		@shmop_close($shmid);
210
	} catch (Exception $e) {
211
		log_error($e->getMessage());
212
	}
213

    
214
	return $shm_data;
215
}
216

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

    
225
/* return the subnet address given a host address and a subnet bit count */
226
function gen_subnet($ipaddr, $bits) {
227
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
228
		return "";
229
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
230
}
231

    
232
/* return the subnet address given a host address and a subnet bit count */
233
function gen_subnetv6($ipaddr, $bits) {
234
	if (!is_ipaddrv6($ipaddr) || !is_numeric($bits))
235
		return "";
236

    
237
	$address = Net_IPv6::getNetmask($ipaddr, $bits);
238
	return $address;
239
}
240

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

    
246
	return long2ip32(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
247
}
248

    
249
/* Generate end number for a given ipv6 subnet mask */
250
function gen_subnetv6_max($ipaddr, $bits) {
251
	if(!is_ipaddrv6($ipaddr))
252
		return false;
253
	
254
	$mask = Net_IPv6::getNetmask('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',$bits);
255
	
256
	$inet_ip = (binary)inet_pton($ipaddr);
257
	$inet_mask = (binary)inet_pton($mask);
258

    
259
	$inet_end = $inet_ip | ~$inet_mask;
260

    
261
	return(Net_IPv6::uncompress(inet_ntop($inet_end)));
262
}
263

    
264
/* returns a subnet mask (long given a bit count) */
265
function gen_subnet_mask_long($bits) {
266
	$sm = 0;
267
	for ($i = 0; $i < $bits; $i++) {
268
		$sm >>= 1;
269
		$sm |= 0x80000000;
270
	}
271
	return $sm;
272
}
273

    
274
/* same as above but returns a string */
275
function gen_subnet_mask($bits) {
276
	return long2ip(gen_subnet_mask_long($bits));
277
}
278

    
279
/* Convert long int to IP address, truncating to 32-bits. */
280
function long2ip32($ip) {
281
	return long2ip($ip & 0xFFFFFFFF);
282
}
283

    
284
/* Convert IP address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. */
285
function ip2long32($ip) {
286
	return ( ip2long($ip) & 0xFFFFFFFF );
287
}
288

    
289
/* Convert IP address to unsigned long int. */
290
function ip2ulong($ip) {
291
	return sprintf("%u", ip2long32($ip));
292
}
293

    
294
/* Find out how many IPs are contained within a given IP range
295
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
296
 */
297
function ip_range_size($startip, $endip) {
298
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
299
		// Operate as unsigned long because otherwise it wouldn't work
300
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
301
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
302
	}
303
	return -1;
304
}
305

    
306
/* Find the smallest possible subnet mask which can contain a given number of IPs
307
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
308
 */
309
function find_smallest_cidr($number) {
310
	$smallest = 1;
311
	for ($b=32; $b > 0; $b--) {
312
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
313
	}
314
	return (32-$smallest);
315
}
316

    
317
/* Return the previous IP address before the given address */
318
function ip_before($ip) {
319
	return long2ip32(ip2long($ip)-1);
320
}
321

    
322
/* Return the next IP address after the given address */
323
function ip_after($ip) {
324
	return long2ip32(ip2long($ip)+1);
325
}
326

    
327
/* Return true if the first IP is 'before' the second */
328
function ip_less_than($ip1, $ip2) {
329
	// Compare as unsigned long because otherwise it wouldn't work when
330
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
331
	return ip2ulong($ip1) < ip2ulong($ip2);
332
}
333

    
334
/* Return true if the first IP is 'after' the second */
335
function ip_greater_than($ip1, $ip2) {
336
	// Compare as unsigned long because otherwise it wouldn't work
337
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
338
	return ip2ulong($ip1) > ip2ulong($ip2);
339
}
340

    
341
/* Convert a range of IPs to an array of subnets which can contain the range. */
342
function ip_range_to_subnet_array($startip, $endip) {
343
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
344
		return array();
345
	}
346

    
347
	// Container for subnets within this range.
348
	$rangesubnets = array();
349

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

    
353
	// Loop here to reduce subnet size and retest as needed. We need to make sure
354
	//   that the target subnet is wholly contained between $startip and $endip.
355
	for ($cidr; $cidr <= 32; $cidr++) {
356
		// Find the network and broadcast addresses for the subnet being tested.
357
		$targetsub_min = gen_subnet($startip, $cidr);
358
		$targetsub_max = gen_subnet_max($startip, $cidr);
359

    
360
		// Check best case where the range is exactly one subnet.
361
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
362
			// Hooray, the range is exactly this subnet!
363
			return array("{$startip}/{$cidr}");
364
		}
365

    
366
		// These remaining scenarios will find a subnet that uses the largest
367
		//  chunk possible of the range being tested, and leave the rest to be
368
		//  tested recursively after the loop.
369

    
370
		// Check if the subnet begins with $startip and ends before $endip
371
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
372
			break;
373
		}
374

    
375
		// Check if the subnet ends at $endip and starts after $startip
376
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
377
			break;
378
		}
379

    
380
		// Check if the subnet is between $startip and $endip
381
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
382
			break;
383
		}
384
	}
385

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

    
392
	// Add in the subnet we found before, to preserve ordering
393
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
394

    
395
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
396
	if ($endip != $targetsub_max) {
397
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
398
	}
399
	return $rangesubnets;
400
}
401

    
402
function is_iprange($range) {
403
	if (substr_count($range, '-') != 1) {
404
		return false;
405
	}
406
	list($ip1, $ip2) = explode ('-', $range);
407
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
408
}
409

    
410
function is_numericint($arg) {
411
	return (preg_match("/[^0-9]/", $arg) ? false : true);
412
}
413

    
414

    
415
/* returns true if $ipaddr is a valid dotted IPv4 address or a IPv6 */
416
function is_ipaddr($ipaddr) {
417
	if(is_ipaddrv4($ipaddr)) {
418
		return true;
419
	}
420
	if(is_ipaddrv6($ipaddr)) {
421
		return true;
422
	}
423
	return false;
424
}
425

    
426
/* returns true if $ipaddr is a valid IPv6 address */
427
function is_ipaddrv6($ipaddr) {
428
	$result = Net_IPv6::checkIPv6($ipaddr);
429
	return $result;
430
}
431

    
432
/* returns true if $ipaddr is a valid dotted IPv4 address */
433
function is_ipaddrv4($ipaddr) {
434
	if (!is_string($ipaddr))
435
		return false;
436

    
437
	$ip_long = ip2long($ipaddr);
438
	$ip_reverse = long2ip32($ip_long);
439

    
440
	if ($ipaddr == $ip_reverse)
441
		return true;
442
	else
443
		return false;
444
}
445

    
446

    
447
/* returns true if $ipaddr is a valid literal IPv6 address */
448
function is_literalipaddrv6($ipaddr) {
449
	if(preg_match("/\[([0-9a-f:]+)\]/i", $ipaddr, $match))
450
		$ipaddr = $match[1];
451
	else
452
		return false;
453

    
454
	return is_ipaddrv6($ipaddr);
455
}
456

    
457
function is_ipaddrwithport($ipport) {
458
	$parts = explode(":", $ipport);
459
	$port = array_pop($parts);
460
	if (count($parts) == 1) {
461
		return is_ipaddrv4($parts[0]) && is_port($port);
462
	} elseif (count($parts) > 1) {
463
		return is_literalipaddrv6(implode(":", $parts)) && is_port($port);
464
	} else {
465
		return false;
466
	}
467
}
468

    
469
function is_hostnamewithport($hostport) {
470
	$parts = explode(":", $hostport);
471
	$port = array_pop($parts);
472
	if (count($parts) == 1) {
473
		return is_hostname($parts[0]) && is_port($port);
474
	} else {
475
		return false;
476
	}
477
}
478

    
479
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
480
function is_ipaddroralias($ipaddr) {
481
	global $config;
482

    
483
	if (is_alias($ipaddr)) {
484
		if (is_array($config['aliases']['alias'])) {
485
			foreach ($config['aliases']['alias'] as $alias) {
486
				if ($alias['name'] == $ipaddr && $alias['type'] != "port")
487
					return true;
488
			}
489
		}
490
		return false;
491
	} else
492
		return is_ipaddr($ipaddr);
493

    
494
}
495

    
496
/* returns true if $subnet is a valid IPv4 or IPv6 subnet in CIDR format */
497
function is_subnet($subnet) {
498
	if(is_subnetv4($subnet)) {
499
		return true;
500
	}
501
	if(is_subnetv6($subnet)) {
502
		return true;
503
	}
504
	return false;
505
}
506

    
507
/* returns true if $subnet is a valid IPv4 subnet in CIDR format */
508
function is_subnetv4($subnet) {
509
	if (!is_string($subnet))
510
		return false;
511

    
512
	list($hp,$np) = explode('/', $subnet);
513

    
514
	if (!is_ipaddrv4($hp))
515
		return false;
516

    
517
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
518
		return false;
519

    
520
	return true;
521
}
522

    
523
/* returns true if $subnet is a valid IPv6 subnet in CIDR format */
524
function is_subnetv6($subnet) {
525
	if (!is_string($subnet))
526
		return false;
527

    
528
	list($hp,$np) = explode('/', $subnet);
529

    
530
	if (!is_ipaddrv6($hp))
531
		return false;
532

    
533
	if (!is_numeric($np) || ($np < 1) || ($np > 128))
534
		return false;
535

    
536
	return true;
537
}
538

    
539

    
540
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
541
function is_subnetoralias($subnet) {
542
	global $aliastable;
543

    
544
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
545
		return true;
546
	else
547
		return is_subnet($subnet);
548
}
549

    
550
/* returns true if $hostname is a valid hostname */
551
function is_hostname($hostname) {
552
	if (!is_string($hostname))
553
		return false;
554

    
555
	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))
556
		return true;
557
	else
558
		return false;
559
}
560

    
561
/* returns true if $domain is a valid domain name */
562
function is_domain($domain) {
563
	if (!is_string($domain))
564
		return false;
565

    
566
	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))
567
		return true;
568
	else
569
		return false;
570
}
571

    
572
/* returns true if $macaddr is a valid MAC address */
573
function is_macaddr($macaddr) {
574
	return preg_match('/^[0-9A-F]{2}(?:[:][0-9A-F]{2}){5}$/i', $macaddr) == 1 ? true : false;
575
}
576

    
577
/* returns true if $name is a valid name for an alias */
578
/* returns NULL if a reserved word is used */
579
function is_validaliasname($name) {
580
	/* Array of reserved words */
581
	$reserved = array("port", "pass");
582
	if (in_array($name, $reserved, true))
583
		return; /* return NULL */
584
	if (!preg_match("/[^a-zA-Z0-9_]/", $name) && (strlen($name) < 32))
585
		return true;
586
	else
587
		return false;
588
}
589

    
590
/* returns true if $port is a valid TCP/UDP port */
591
function is_port($port) {
592
	$tmpports = explode(":", $port);
593
	foreach($tmpports as $tmpport) {
594
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
595
			continue;
596
		if (!ctype_digit($tmpport))
597
			return false;
598
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
599
			return false;
600
	}
601
	return true;
602
}
603

    
604
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
605
function is_portrange($portrange) {
606
	$ports = explode(":", $portrange);
607

    
608
	if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
609
		return true;
610
	else
611
		return false;
612
}
613

    
614
/* returns true if $port is a valid port number or an alias thereof */
615
function is_portoralias($port) {
616
	global $config;
617

    
618
	if (is_alias($port)) {
619
		if (is_array($config['aliases']['alias'])) {
620
			foreach ($config['aliases']['alias'] as $alias) {
621
				if ($alias['name'] == $port && $alias['type'] == "port")
622
					return true;
623
				}
624
			}
625
			return false;
626
	} else
627
		return is_port($port);
628
}
629

    
630
/* returns true if $val is a valid shaper bandwidth value */
631
function is_valid_shaperbw($val) {
632
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
633
}
634

    
635
/* return the configured carp interface list */
636
function get_configured_carp_interface_list() {
637
	global $config;
638

    
639
	$iflist = array();
640

    
641
	if(is_array($config['virtualip']['vip'])) {
642
		$viparr = &$config['virtualip']['vip'];
643
		foreach ($viparr as $vip) {
644
			switch ($vip['mode']) {
645
			case "carp":
646
			case "carpdev-dhcp":
647
				$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
648
				$iflist[$vipif] = $vip['subnet'];
649
				break;
650
			}
651
		}
652
	}
653

    
654
	return $iflist;
655
}
656

    
657
/* return the configured IP aliases list */
658
function get_configured_ip_aliases_list($returnfullentry = false) {
659
	global $config;
660

    
661
	$alias_list=array();
662

    
663
	if(is_array($config['virtualip']['vip'])) {
664
		$viparr = &$config['virtualip']['vip'];
665
		foreach ($viparr as $vip) {
666
			if ($vip['mode']=="ipalias") {
667
				if ($returnfullentry)
668
					$alias_list[$vip['subnet']] = $vip;
669
				else
670
					$alias_list[$vip['subnet']] = $vip['interface'];
671
			}
672
		}
673
	}
674

    
675
	return $alias_list;
676
}
677

    
678

    
679
/* comparison function for sorting by the order in which interfaces are normally created */
680
function compare_interface_friendly_names($a, $b) {
681
	if ($a == $b)
682
		return 0;
683
	else if ($a == 'wan')
684
		return -1;
685
	else if ($b == 'wan')
686
		return 1;
687
	else if ($a == 'lan')
688
		return -1;
689
	else if ($b == 'lan')
690
		return 1;
691

    
692
	return strnatcmp($a, $b);
693
}
694

    
695
/* return the configured interfaces list. */
696
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
697
	global $config;
698

    
699
	$iflist = array();
700

    
701
	/* if list */
702
	foreach($config['interfaces'] as $if => $ifdetail) {
703
		if ($only_opt && ($if == "wan" || $if == "lan"))
704
			continue;
705
		if (isset($ifdetail['enable']) || $withdisabled == true)
706
			$iflist[$if] = $if;
707
	}
708

    
709
	return $iflist;
710
}
711

    
712
/* return the configured interfaces list. */
713
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
714
	global $config;
715

    
716
	$iflist = array();
717

    
718
	/* if list */
719
	foreach($config['interfaces'] as $if => $ifdetail) {
720
		if ($only_opt && ($if == "wan" || $if == "lan"))
721
			continue;
722
		if (isset($ifdetail['enable']) || $withdisabled == true) {
723
			$tmpif = get_real_interface($if);
724
			if (!empty($tmpif))
725
				$iflist[$tmpif] = $if;
726
		}
727
	}
728

    
729
	return $iflist;
730
}
731

    
732
/* return the configured interfaces list with their description. */
733
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
734
	global $config;
735

    
736
	$iflist = array();
737

    
738
	/* if list */
739
	foreach($config['interfaces'] as $if => $ifdetail) {
740
		if ($only_opt && ($if == "wan" || $if == "lan"))
741
			continue;
742
		if (isset($ifdetail['enable']) || $withdisabled == true) {
743
			if(empty($ifdetail['descr']))
744
				$iflist[$if] = strtoupper($if);
745
			else
746
				$iflist[$if] = strtoupper($ifdetail['descr']);
747
		}
748
	}
749

    
750
	return $iflist;
751
}
752

    
753
/*
754
 *   get_configured_ip_addresses() - Return a list of all configured
755
 *   interfaces IP Addresses
756
 *
757
 */
758
function get_configured_ip_addresses() {
759
	require_once("interfaces.inc");
760
	$ip_array = array();
761
	$interfaces = get_configured_interface_list();
762
	if(is_array($interfaces)) {
763
		foreach($interfaces as $int) {
764
			$ipaddr = get_interface_ip($int);
765
			$ip_array[$int] = $ipaddr;
766
		}
767
	}
768
	$interfaces = get_configured_carp_interface_list();
769
	if(is_array($interfaces)) 
770
		foreach($interfaces as $int => $ipaddr) 
771
			$ip_array[$int] = $ipaddr;
772
	return $ip_array;
773
}
774

    
775
/*
776
 *   get_configured_ipv6_addresses() - Return a list of all configured
777
 *   interfaces IPv6 Addresses
778
 *
779
 */
780
function get_configured_ipv6_addresses() {
781
	require_once("interfaces.inc");
782
	$ipv6_array = array();
783
	$interfaces = get_configured_interface_list();
784
	if(is_array($interfaces)) {
785
		foreach($interfaces as $int) {
786
			$ipaddrv6 = get_interface_ipv6($int);
787
			$ipv6_array[$int] = $ipaddrv6;
788
		}
789
	}
790
	$interfaces = get_configured_carp_interface_list();
791
	if(is_array($interfaces)) 
792
		foreach($interfaces as $int => $ipaddrv6) 
793
			$ipv6_array[$int] = $ipaddrv6;
794
	return $ipv6_array;
795
}
796

    
797
/*
798
 *   get_interface_list() - Return a list of all physical interfaces
799
 *   along with MAC and status.
800
 *
801
 *   $mode = "active" - use ifconfig -lu
802
 *           "media"  - use ifconfig to check physical connection
803
 *			status (much slower)
804
 */
805
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
806
        global $config;
807
	$upints = array();
808
        /* get a list of virtual interface types */
809
        if(!$vfaces) {
810
		$vfaces = array (
811
				'bridge',
812
				'ppp',
813
				'pppoe',
814
				'pptp',
815
				'l2tp',
816
				'sl',
817
				'gif',
818
				'gre',
819
				'faith',
820
				'lo',
821
				'ng',
822
				'_vlan',
823
				'_wlan',
824
				'pflog',
825
				'plip',
826
				'pfsync',
827
				'enc',
828
				'tun',
829
				'carp',
830
				'lagg',
831
				'vip',
832
				'ipfw'
833
		);
834
	}
835
	switch($mode) {
836
	case "active":
837
                $upints = pfSense_interface_listget(IFF_UP);
838
        	break;
839
	case "media":
840
		$intlist = pfSense_interface_listget();
841
                $ifconfig = "";
842
                exec("/sbin/ifconfig -a", $ifconfig);
843
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
844
                $ifstatus = preg_grep('/status:/', $ifconfig);
845
		foreach($ifstatus as $status) {
846
			$int = array_shift($intlist);
847
			if(stristr($status, "active")) $upints[] = $int;
848
		}
849
		break;
850
	default:
851
		$upints = pfSense_interface_listget();
852
		break;
853
	}
854
        /* build interface list with netstat */
855
        $linkinfo = "";
856
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
857
        array_shift($linkinfo);
858
	/* build ip address list with netstat */
859
	$ipinfo = "";
860
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
861
	array_shift($ipinfo);
862
	foreach($linkinfo as $link) {
863
		$friendly = "";
864
		$alink = explode(" ", $link);
865
		$ifname = rtrim(trim($alink[0]), '*');
866
		/* trim out all numbers before checking for vfaces */
867
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces) &&
868
			!stristr($ifname, "_vlan") && !stristr($ifname, "_wlan")) {
869
			$toput = array(
870
					"mac" => trim($alink[1]),
871
					"up" => in_array($ifname, $upints)
872
				);
873
			foreach($ipinfo as $ip) {
874
				$aip = explode(" ", $ip);
875
				if($aip[0] == $ifname) {
876
					$toput['ipaddr'] = $aip[1];
877
				}
878
			}
879
			if (is_array($config['interfaces'])) {
880
				foreach($config['interfaces'] as $name => $int)
881
					if($int['if'] == $ifname) $friendly = $name;
882
			}
883
			switch($keyby) {
884
			case "physical":
885
				if($friendly != "") {
886
					$toput['friendly'] = $friendly;
887
				}
888
				$dmesg_arr = array();
889
				exec("/sbin/dmesg |grep $ifname | head -n1", $dmesg_arr);
890
				preg_match_all("/<(.*?)>/i", $dmesg_arr[0], $dmesg);
891
				$toput['dmesg'] = $dmesg[1][0];
892
				$iflist[$ifname] = $toput;
893
				break;
894
			case "ppp":
895
				
896
			case "friendly":
897
				if($friendly != "") {
898
					$toput['if'] = $ifname;
899
					$iflist[$friendly] = $toput;
900
				}
901
				break;
902
			}
903
		}
904
	}
905
	return $iflist;
906
}
907

    
908
/****f* util/log_error
909
* NAME
910
*   log_error  - Sends a string to syslog.
911
* INPUTS
912
*   $error     - string containing the syslog message.
913
* RESULT
914
*   null
915
******/
916
function log_error($error) {
917
	global $g;
918
	$page = $_SERVER['SCRIPT_NAME'];
919
	syslog(LOG_WARNING, "$page: $error");
920
	if ($g['debug'])
921
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
922
	return;
923
}
924

    
925
/****f* util/log_auth
926
* NAME
927
*   log_error  - Sends a string to syslog as LOG_AUTH facility
928
* INPUTS
929
*   $error     - string containing the syslog message.
930
* RESULT
931
*   null
932
******/
933
function log_auth($error) {
934
	global $g;
935
	$page = $_SERVER['SCRIPT_NAME'];
936
	syslog(LOG_AUTH, "$page: $error");
937
	if ($g['debug'])
938
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
939
	return;
940
}
941

    
942
/****f* util/exec_command
943
 * NAME
944
 *   exec_command - Execute a command and return a string of the result.
945
 * INPUTS
946
 *   $command   - String of the command to be executed.
947
 * RESULT
948
 *   String containing the command's result.
949
 * NOTES
950
 *   This function returns the command's stdout and stderr.
951
 ******/
952
function exec_command($command) {
953
	$output = array();
954
	exec($command . ' 2>&1 ', $output);
955
	return(implode("\n", $output));
956
}
957

    
958
/* wrapper for exec() */
959
function mwexec($command, $mute = false) {
960
	global $g;
961

    
962
	if ($g['debug']) {
963
		if (!$_SERVER['REMOTE_ADDR'])
964
			echo "mwexec(): $command\n";
965
	}
966
	$oarr = array();
967
	$retval = 0;
968
	$garbage = exec("$command 2>&1", $oarr, $retval);
969

    
970
	if(isset($config['system']['developerspew']))
971
		$mute = false;
972
	if(($retval <> 0) && ($mute === false)) {
973
		$output = implode(" ", $oarr);
974
		log_error(sprintf(gettext("The command '%1\$s' returned exit code '%2\$d', the output was '%3\$s' "), $command, $retval, $output));
975
	}
976
	return $retval;
977
}
978

    
979
/* wrapper for exec() in background */
980
function mwexec_bg($command) {
981
	global $g;
982

    
983
	if ($g['debug']) {
984
		if (!$_SERVER['REMOTE_ADDR'])
985
			echo "mwexec(): $command\n";
986
	}
987

    
988
	exec("nohup $command > /dev/null 2>&1 &");
989
}
990

    
991
/* unlink a file, if it exists */
992
function unlink_if_exists($fn) {
993
	$to_do = glob($fn);
994
	if(is_array($to_do)) {
995
		foreach($to_do as $filename)
996
			@unlink($filename);
997
	} else {
998
		@unlink($fn);
999
	}
1000
}
1001
/* make a global alias table (for faster lookups) */
1002
function alias_make_table($config) {
1003
	global $aliastable;
1004

    
1005
	$aliastable = array();
1006

    
1007
	if (is_array($config['aliases']['alias'])) {
1008
		foreach ($config['aliases']['alias'] as $alias) {
1009
			if ($alias['name'])
1010
				$aliastable[$alias['name']] = $alias['address'];
1011
		}
1012
	}
1013
}
1014

    
1015
/* check if an alias exists */
1016
function is_alias($name) {
1017
	global $aliastable;
1018

    
1019
	return isset($aliastable[$name]);
1020
}
1021

    
1022
function alias_get_type($name) {
1023
        global $config;
1024
        
1025
	if (is_array($config['aliases']['alias'])) {
1026
		foreach ($config['aliases']['alias'] as $alias) {
1027
			if ($name == $alias['name'])
1028
				return $alias['type'];
1029
		}
1030
	}
1031

    
1032
        return "";
1033
}
1034

    
1035
/* expand a host or network alias, if necessary */
1036
function alias_expand($name) {
1037
	global $aliastable;
1038

    
1039
	if (isset($aliastable[$name]))
1040
		return "\${$name}";
1041
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
1042
		return "{$name}";
1043
	else
1044
		return null;
1045
}
1046

    
1047
function alias_expand_urltable($name) {
1048
	global $config;
1049
	$urltable_prefix = "/var/db/aliastables/";
1050
	$urltable_filename = $urltable_prefix . $name . ".txt";
1051

    
1052
	if (is_array($config['aliases']['alias'])) {
1053
		foreach ($config['aliases']['alias'] as $alias) {
1054
			if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
1055
				if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
1056
					return $urltable_filename;
1057
				else if (process_alias_urltable($name, $alias["url"], 0, true))
1058
					return $urltable_filename;
1059
			}
1060
		}
1061
	}
1062
	return null;
1063
}
1064

    
1065
function subnet_size ($subnet) {
1066
	if (is_subnetv4($subnet)) {
1067
		list ($ip, $bits) = explode("/", $subnet);
1068
		return round(exp(log(2) * (32 - $bits)));
1069
	}
1070
	else if (is_subnetv6($subnet)) {
1071
		list ($ip, $bits) = explode("/", $subnet);
1072
		return round(exp(log(2) * (128 - $bits)));
1073
	}
1074
	else {
1075
		return 0;
1076
	}
1077
}
1078

    
1079
function subnet_expand ($subnet) {
1080
	if (is_subnetv4($subnet)) {
1081
		return subnetv4_expand($subnet);
1082
	} else if (is_subnetv6($subnet)) {
1083
		return subnetv6_expand($subnet);
1084
	} else {
1085
		return $subnet;
1086
	}
1087
}
1088

    
1089
function subnetv4_expand ($subnet) {
1090
	$result = array();
1091
	list ($ip, $bits) = explode("/", $subnet);
1092
	$net  = ip2long($ip);
1093
	$mask = (0xffffffff << (32 - $bits));
1094
	$net &= $mask;
1095
	$size = round(exp(log(2) * (32 - $bits)));
1096
	for ($i = 0; $i < $size; $i += 1) {
1097
		$result[] = long2ip($net | $i);
1098
	}
1099
	return $result;
1100
}
1101

    
1102
/* find out whether two subnets overlap */
1103
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
1104

    
1105
	if (!is_numeric($bits1))
1106
		$bits1 = 32;
1107
	if (!is_numeric($bits2))
1108
		$bits2 = 32;
1109

    
1110
	if ($bits1 < $bits2)
1111
		$relbits = $bits1;
1112
	else
1113
		$relbits = $bits2;
1114

    
1115
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
1116
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
1117

    
1118
	if ($sn1 == $sn2)
1119
		return true;
1120
	else
1121
		return false;
1122
}
1123

    
1124
/* compare two IP addresses */
1125
function ipcmp($a, $b) {
1126
	if (ip_less_than($a, $b))
1127
		return -1;
1128
	else if (ip_greater_than($a, $b))
1129
		return 1;
1130
	else
1131
		return 0;
1132
}
1133

    
1134
/* return true if $addr is in $subnet, false if not */
1135
function ip_in_subnet($addr,$subnet) {
1136
	if(is_ipaddrv6($addr)) {
1137
		$result = Net_IPv6::IsInNetmask($addr, $subnet);
1138
		if($result)
1139
			return true;
1140
		else
1141
			return false;
1142
	}
1143
	list($ip, $mask) = explode('/', $subnet);
1144
	$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
1145
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
1146
}
1147

    
1148
/* verify (and remove) the digital signature on a file - returns 0 if OK */
1149
function verify_digital_signature($fname) {
1150
	global $g;
1151

    
1152
	if(!file_exists("/usr/local/sbin/gzsig"))
1153
		return 4;
1154

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

    
1158
/* obtain MAC address given an IP address by looking at the ARP table */
1159
function arp_get_mac_by_ip($ip) {
1160
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
1161
	$arpoutput = "";
1162
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
1163

    
1164
	if ($arpoutput[0]) {
1165
		$arpi = explode(" ", $arpoutput[0]);
1166
		$macaddr = $arpi[3];
1167
		if (is_macaddr($macaddr))
1168
			return $macaddr;
1169
		else
1170
			return false;
1171
	}
1172

    
1173
	return false;
1174
}
1175

    
1176
/* return a fieldname that is safe for xml usage */
1177
function xml_safe_fieldname($fieldname) {
1178
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
1179
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
1180
			 ':', ',', '.', '\'', '\\'
1181
		);
1182
	return strtolower(str_replace($replace, "", $fieldname));
1183
}
1184

    
1185
function mac_format($clientmac) {
1186
    global $config;
1187

    
1188
    $mac = explode(":", $clientmac);
1189
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
1190

    
1191
    switch($mac_format) {
1192
        case 'singledash':
1193
		return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
1194

    
1195
        case 'ietf':
1196
		return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
1197

    
1198
        case 'cisco':
1199
		return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
1200

    
1201
        case 'unformatted':
1202
		return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
1203

    
1204
        default:
1205
		return $clientmac;
1206
    }
1207
}
1208

    
1209
function resolve_retry($hostname, $retries = 5) {
1210

    
1211
	if (is_ipaddr($hostname))
1212
		return $hostname;
1213

    
1214
       for ($i = 0; $i < $retries; $i++) {
1215
		// FIXME: gethostbyname does not work for AAAA hostnames, boo, hiss
1216
               $ip = gethostbyname($hostname);
1217

    
1218
		if ($ip && $ip != $hostname) {
1219
			/* success */
1220
			return $ip;
1221
		}
1222

    
1223
		sleep(1);
1224
	}
1225

    
1226
	return false;
1227
}
1228

    
1229
function format_bytes($bytes) {
1230
	if ($bytes >= 1073741824) {
1231
		return sprintf("%.2f GB", $bytes/1073741824);
1232
	} else if ($bytes >= 1048576) {
1233
		return sprintf("%.2f MB", $bytes/1048576);
1234
	} else if ($bytes >= 1024) {
1235
		return sprintf("%.0f KB", $bytes/1024);
1236
	} else {
1237
		return sprintf("%d bytes", $bytes);
1238
	}
1239
}
1240

    
1241
function update_filter_reload_status($text) {
1242
	global $g;
1243

    
1244
	file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1245
}
1246

    
1247
/****f* util/return_dir_as_array
1248
 * NAME
1249
 *   return_dir_as_array - Return a directory's contents as an array.
1250
 * INPUTS
1251
 *   $dir       - string containing the path to the desired directory.
1252
 * RESULT
1253
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1254
 ******/
1255
function return_dir_as_array($dir) {
1256
	$dir_array = array();
1257
	if (is_dir($dir)) {
1258
		if ($dh = opendir($dir)) {
1259
			while (($file = readdir($dh)) !== false) {
1260
				$canadd = 0;
1261
				if($file == ".") $canadd = 1;
1262
				if($file == "..") $canadd = 1;
1263
				if($canadd == 0)
1264
					array_push($dir_array, $file);
1265
			}
1266
			closedir($dh);
1267
		}
1268
	}
1269
	return $dir_array;
1270
}
1271

    
1272
function run_plugins($directory) {
1273
	global $config, $g;
1274

    
1275
	/* process packager manager custom rules */
1276
	$files = return_dir_as_array($directory);
1277
	if (is_array($files)) {
1278
		foreach ($files as $file) {
1279
			if (stristr($file, ".sh") == true)
1280
				mwexec($directory . $file . " start");
1281
			else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1282
				require_once($directory . "/" . $file);
1283
		}
1284
	}
1285
}
1286

    
1287
/*
1288
 *    safe_mkdir($path, $mode = 0755)
1289
 *    create directory if it doesn't already exist and isn't a file!
1290
 */
1291
function safe_mkdir($path, $mode=0755) {
1292
	global $g;
1293

    
1294
	if (!is_file($path) && !is_dir($path)) {
1295
		return @mkdir($path, $mode, true);
1296
	} else {
1297
		return false;
1298
	}
1299
}
1300

    
1301
/*
1302
 * make_dirs($path, $mode = 0755)
1303
 * create directory tree recursively (mkdir -p)
1304
 */
1305
function make_dirs($path, $mode = 0755) {
1306
	$base = '';
1307
	foreach (explode('/', $path) as $dir) {
1308
		$base .= "/$dir";
1309
		if (!is_dir($base)) {
1310
			if (!@mkdir($base, $mode))
1311
				return false;
1312
		}
1313
	}
1314
	return true;
1315
}
1316

    
1317
/*
1318
 * get_sysctl($names)
1319
 * Get values of sysctl OID's listed in $names (accepts an array or a single
1320
 * name) and return an array of key/value pairs set for those that exist
1321
 */
1322
function get_sysctl($names) {
1323
	if (empty($names))
1324
		return array();
1325

    
1326
	if (is_array($names)) {
1327
		$name_list = array();
1328
		foreach ($names as $name) {
1329
			$name_list[] = escapeshellarg($name);
1330
		}
1331
	} else
1332
		$name_list = array(escapeshellarg($names));
1333

    
1334
	exec("/sbin/sysctl -i " . implode(" ", $name_list), $output);
1335
	$values = array();
1336
	foreach ($output as $line) {
1337
		$line = explode(": ", $line, 2);
1338
		if (count($line) == 2)
1339
			$values[$line[0]] = $line[1];
1340
	}
1341

    
1342
	return $values;
1343
}
1344

    
1345
/*
1346
 * set_sysctl($value_list)
1347
 * Set sysctl OID's listed as key/value pairs and return
1348
 * an array with keys set for those that succeeded
1349
 */
1350
function set_sysctl($values) {
1351
	if (empty($values))
1352
		return array();
1353

    
1354
	$value_list = array();
1355
	foreach ($values as $key => $value) {
1356
		$value_list[] = escapeshellarg($key) . "=" . escapeshellarg($value);
1357
	}
1358

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

    
1361
	/* Retry individually if failed (one or more read-only) */
1362
	if ($success <> 0 && count($value_list) > 1) {
1363
		foreach ($value_list as $value) {
1364
			exec("/sbin/sysctl -i " . $value, $output);
1365
		}
1366
	}
1367

    
1368
	$ret = array();
1369
	foreach ($output as $line) {
1370
		$line = explode(": ", $line, 2);
1371
		if (count($line) == 2)
1372
			$ret[$line[0]] = true;
1373
	}
1374

    
1375
	return $ret;
1376
}
1377

    
1378
/*
1379
 *     get_memory()
1380
 *     returns an array listing the amount of
1381
 *     memory installed in the hardware
1382
 *     [0]real and [1]available
1383
 */
1384
function get_memory() {
1385
	$matches = "";
1386
	if(file_exists("/var/log/dmesg.boot"))
1387
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1388
	else
1389
		$mem = `dmesg -a | grep memory`;			
1390
	if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1391
		return array($matches[1][0], $matches[1][0]);
1392
	if(!$real && !$avail) {
1393
		$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1394
		$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1395
		/* convert from bytes to megabytes */
1396
		return array(($real/1048576),($avail/1048576));
1397
	}
1398
}
1399

    
1400
function mute_kernel_msgs() {
1401
	global $config;
1402
	// Do not mute serial console.  The kernel gets very very cranky
1403
	// and will start dishing you cannot control tty errors.
1404
	switch (trim(file_get_contents("/etc/platform"))) {
1405
		case "nanobsd":
1406
		case "jail":
1407
			return;
1408
	}
1409
	if($config['system']['enableserial']) 
1410
		return;			
1411
	exec("/sbin/conscontrol mute on");
1412
}
1413

    
1414
function unmute_kernel_msgs() {
1415
	global $config;
1416
	// Do not mute serial console.  The kernel gets very very cranky
1417
	// and will start dishing you cannot control tty errors.
1418
	switch (trim(file_get_contents("/etc/platform"))) {
1419
		case "nanobsd":
1420
		case "jail":
1421
			return;
1422
	}
1423
	exec("/sbin/conscontrol mute off");
1424
}
1425

    
1426
function start_devd() {
1427
	global $g;
1428

    
1429
	if ($g['platform'] == 'jail')
1430
		return;
1431
	exec("/sbin/devd");
1432
	sleep(1);
1433
}
1434

    
1435
function is_interface_vlan_mismatch() {
1436
	global $config, $g;
1437

    
1438
	if (is_array($config['vlans']['vlan'])) {
1439
		foreach ($config['vlans']['vlan'] as $vlan) {
1440
			if (does_interface_exist($vlan['if']) == false)
1441
				return true;
1442
		}
1443
	}
1444

    
1445
	return false;
1446
}
1447

    
1448
function is_interface_mismatch() {
1449
	global $config, $g;
1450

    
1451
	$do_assign = false;
1452
	$i = 0;
1453
	if (is_array($config['interfaces'])) {
1454
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
1455
			if (preg_match("/^enc|^cua|^tun|^l2tp|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1456
				// Do not check these interfaces.
1457
				$i++;
1458
				continue;
1459
			}
1460
			else if (does_interface_exist($ifcfg['if']) == false) {
1461
				$do_assign = true;
1462
			} else
1463
				$i++;
1464
		}
1465
	}
1466

    
1467
	if ($g['minimum_nic_count'] > $i) {
1468
		$do_assign = true;
1469
	} else if (file_exists("{$g['tmp_path']}/assign_complete"))
1470
	$do_assign = false;
1471

    
1472
	return $do_assign;
1473
}
1474

    
1475
/* sync carp entries to other firewalls */
1476
function carp_sync_client() {
1477
	global $g;
1478
	send_event("filter sync");
1479
}
1480

    
1481
/****f* util/isAjax
1482
 * NAME
1483
 *   isAjax - reports if the request is driven from prototype
1484
 * INPUTS
1485
 *   none
1486
 * RESULT
1487
 *   true/false
1488
 ******/
1489
function isAjax() {
1490
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1491
}
1492

    
1493
/****f* util/timeout
1494
 * NAME
1495
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1496
 * INPUTS
1497
 *   optional, seconds to wait before timeout. Default 9 seconds.
1498
 * RESULT
1499
 *   returns 1 char of user input or null if no input.
1500
 ******/
1501
function timeout($timer = 9) {
1502
	while(!isset($key)) {
1503
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1504
		else { echo chr(8). "{$timer}"; }
1505
		`/bin/stty -icanon min 0 time 25`;
1506
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1507
		`/bin/stty icanon`;
1508
		if ($key == '')
1509
			unset($key);
1510
		$timer--;
1511
		if ($timer == 0)
1512
			break;
1513
	}
1514
	return $key;	
1515
}
1516

    
1517
/****f* util/msort
1518
 * NAME
1519
 *   msort - sort array
1520
 * INPUTS
1521
 *   $array to be sorted, field to sort by, direction of sort
1522
 * RESULT
1523
 *   returns newly sorted array
1524
 ******/
1525
function msort($array, $id="id", $sort_ascending=true) {
1526
	$temp_array = array();
1527
	while(count($array)>0) {
1528
		$lowest_id = 0;
1529
		$index=0;
1530
		foreach ($array as $item) {
1531
			if (isset($item[$id])) {
1532
				if ($array[$lowest_id][$id]) {
1533
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1534
						$lowest_id = $index;
1535
					}
1536
				}
1537
			}
1538
			$index++;
1539
		}
1540
		$temp_array[] = $array[$lowest_id];
1541
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1542
	}
1543
	if ($sort_ascending) {
1544
		return $temp_array;
1545
	} else {
1546
    	return array_reverse($temp_array);
1547
	}
1548
}
1549

    
1550
/****f* util/color
1551
 * NAME
1552
 *   color - outputs a color code to the ansi terminal if supported
1553
 * INPUTS
1554
 *   color code or color name
1555
 * RESULT
1556
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1557
 ******/
1558
function color($color = "0m") {
1559
	/*
1560
		Color codes available:
1561
		 0m reset; clears all colors and styles (to white on black)
1562
		 1m bold on (see below)
1563
		 3m italics on
1564
		 4m underline on
1565
		 7m inverse on; reverses foreground & background colors
1566
		 9m strikethrough on
1567
		 22m bold off (see below)
1568
		 23m italics off
1569
		 24m underline off
1570
		 27m inverse off
1571
		 29m strikethrough off
1572
		 30m set foreground color to black
1573
		 31m set foreground color to red
1574
		 32m set foreground color to green
1575
		 33m set foreground color to yellow
1576
		 34m set foreground color to blue
1577
		 35m set foreground color to magenta (purple)
1578
		 36m set foreground color to cyan
1579
		 37m set foreground color to white
1580
		 40m  set background color to black
1581
		 41m set background color to red
1582
		 42m set background color to green
1583
		 43m set background color to yellow
1584
		 44m set background color to blue
1585
		 45m set background color to magenta (purple)
1586
		 46m set background color to cyan
1587
		 47m set background color to white
1588
		 49m set background color to default (black)
1589
	*/	
1590
	// Allow caching of TERM to 
1591
	// speedup subequence requests.
1592
	global $TERM;
1593
	if(!$TERM) 
1594
		$TERM=`/usr/bin/env | grep color`;
1595
	if(!$TERM)
1596
		$TERM=`/usr/bin/env | grep cons25`;
1597
	if($TERM) {
1598
		$ESCAPE=chr(27);
1599
		switch ($color) {
1600
			case "black":
1601
				return "{$ESCAPE}[30m"; 
1602
			case "red":
1603
				return "{$ESCAPE}[31m"; 
1604
			case "green":
1605
				return "{$ESCAPE}[32m"; 
1606
			case "yellow":
1607
				return "{$ESCAPE}[33m"; 
1608
			case "blue":
1609
				return "{$ESCAPE}[34m"; 
1610
			case "magenta":
1611
				return "{$ESCAPE}[35m"; 
1612
			case "cyan":
1613
				return "{$ESCAPE}[36m"; 
1614
			case "white":
1615
				return "{$ESCAPE}[37m"; 
1616
			case "default":
1617
				return "{$ESCAPE}[39m"; 
1618
		}
1619
		return "{$ESCAPE}[{$color}";
1620
	}
1621
}
1622

    
1623
/****f* util/is_URL
1624
 * NAME
1625
 *   is_URL
1626
 * INPUTS
1627
 *   string to check
1628
 * RESULT
1629
 *   Returns true if item is a URL
1630
 ******/
1631
function is_URL($url) {
1632
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1633
	if($match)
1634
		return true;	
1635
	return false;
1636
}
1637

    
1638
function is_file_included($file = "") {
1639
	$files = get_included_files();
1640
	if (in_array($file, $files))
1641
		return true;
1642
	
1643
	return false;
1644
}
1645

    
1646
/*
1647
	This function was borrowed from a comment on PHP.net at the following URL:
1648
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
1649
 */
1650
function array_merge_recursive_unique($array0, $array1) {
1651

    
1652
	$arrays = func_get_args();
1653
	$remains = $arrays;
1654

    
1655
	// We walk through each arrays and put value in the results (without
1656
	// considering previous value).
1657
	$result = array();
1658

    
1659
	// loop available array
1660
	foreach($arrays as $array) {
1661

    
1662
		// The first remaining array is $array. We are processing it. So
1663
		// we remove it from remaing arrays.
1664
        array_shift($remains);
1665

    
1666
		// We don't care non array param, like array_merge since PHP 5.0.
1667
		if(is_array($array)) {
1668
			// Loop values
1669
			foreach($array as $key => $value) {
1670
				if(is_array($value)) {
1671
					// we gather all remaining arrays that have such key available
1672
					$args = array();
1673
					foreach($remains as $remain) {
1674
						if(array_key_exists($key, $remain)) {
1675
							array_push($args, $remain[$key]);
1676
						}
1677
					}
1678

    
1679
					if(count($args) > 2) {
1680
						// put the recursion
1681
						$result[$key] = call_user_func_array(__FUNCTION__, $args);
1682
					} else {
1683
						foreach($value as $vkey => $vval) {
1684
							$result[$key][$vkey] = $vval;
1685
						}
1686
					}
1687
				} else {
1688
					// simply put the value
1689
					$result[$key] = $value;
1690
				}
1691
			}
1692
		}
1693
	}
1694
	return $result;
1695
}
1696

    
1697

    
1698
/*
1699
 * converts a string like "a,b,c,d"
1700
 * into an array like array("a" => "b", "c" => "d")
1701
 */
1702
function explode_assoc($delimiter, $string) {
1703
	$array = explode($delimiter, $string);
1704
	$result = array();
1705
	$numkeys = floor(count($array) / 2);
1706
	for ($i = 0; $i < $numkeys; $i += 1) {
1707
		$result[$array[$i * 2]] = $array[$i * 2 + 1];
1708
	}
1709
	return $result;
1710
}
1711

    
1712
function get_staticroutes($returnsubnetsonly = false) {
1713
	global $config;
1714
	require_once('filter.inc');
1715
	$allstaticroutes = array();
1716
	$allsubnets = array();
1717

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

    
1722
	/* Loop through routes and expand aliases as we find them. */
1723
	foreach ($config['staticroutes']['route'] as $route) {
1724
		if (is_alias($route['network'])) {
1725
			$subnets = filter_expand_alias_array($route['network']);
1726
			foreach ($subnets as $net) {
1727
				if (is_ipaddr($net))
1728
					$net .= "/32";
1729
				/* This must be a hostname, we can't use it. */
1730
				if (!is_subnet($net))
1731
					continue;
1732
				$temproute = $route;
1733
				$temproute['network'] = $net;
1734
				$allstaticroutes[] = $temproute;
1735
				$allsubnets[] = $net;
1736
			}
1737
		} elseif (is_subnet($route['network'])) {
1738
			$allstaticroutes[] = $route;
1739
			$allsubnets[] = $route['network'];
1740
		}
1741
	}
1742
	if ($returnsubnetsonly) {
1743
		return $allsubnets;
1744
	} else {
1745
		return $allstaticroutes;
1746
	}
1747
}
1748
?>
(53-53/65)