Project

General

Profile

Download (45.4 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
		@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
	while ($try < 3) {
173
		$fd = @fsockopen($g['event_address']);
174
		if ($fd) {
175
			foreach ($cmds as $cmd) {
176
				fwrite($fd, $cmd);
177
				$resp = fread($fd, 4096);
178
				if ($resp != "OK\n")
179
					log_error("send_event: sent {$cmd} got {$resp}");
180
			}
181
			fclose($fd);
182
			$try = 3;
183
		} else if (!is_process_running("check_reload_status"))
184
			mwexec_bg("/usr/bin/nice -n20 /usr/local/sbin/check_reload_status");
185
		$try++;
186
	}
187
}
188

    
189
function refcount_init($reference) {
190
	$shmid = @shmop_open($reference, "c", 0644, 10);
191
	@shmop_write($shmid, 0, 0);
192
	@shmop_close($shmid);
193
}
194

    
195
function refcount_reference($reference) {
196
	try {
197
		$shmid = @shmop_open($reference, "w", 0644, 10);
198
		if (!$shmid) {
199
			refcount_init($reference);
200
			$shmid = @shmop_open($reference, "w", 0, 0);
201
		}
202
		$shm_data = @shmop_read($shmid, 0, 10);
203
		$shm_data = intval($shm_data) + 1;
204
		@shmop_write($shmid, $shm_data, 0);
205
		@shmop_close($shmid);
206
	} catch (Exception $e) {
207
		log_error($e->getMessage());
208
	}
209

    
210
	return $shm_data;
211
}
212

    
213
function refcount_unreference($reference) {
214
	try {
215
		/* We assume that the shared memory exists. */
216
		$shmid = @shmop_open($reference, "w", 0, 0);
217
		$shm_data = @shmop_read($shmid, 0, 10);
218
		$shm_data = intval($shm_data) - 1;
219
		if ($shm_data < 0) {
220
			//debug_backtrace();
221
			log_error(sprintf(gettext("Reference %s is going negative, not doing unreference."), $reference));
222
		} else
223
			@shmop_write($shmid, $shm_data, 0);
224
		@shmop_close($shmid);
225
	} catch (Exception $e) {
226
		log_error($e->getMessage());
227
	}
228

    
229
	return $shm_data;
230
}
231

    
232
function is_module_loaded($module_name) {
233
	$running = `/sbin/kldstat | grep {$module_name} | /usr/bin/grep -v grep | /usr/bin/wc -l`;
234
	if (intval($running) >= 1)
235
		return true;
236
	else
237
		return false;
238
}
239

    
240
/* return the subnet address given a host address and a subnet bit count */
241
function gen_subnet($ipaddr, $bits) {
242
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
243
		return "";
244
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
245
}
246

    
247
/* return the subnet address given a host address and a subnet bit count */
248
function gen_subnetv6($ipaddr, $bits) {
249
	if (!is_ipaddrv6($ipaddr) || !is_numeric($bits))
250
		return "";
251

    
252
	$address = Net_IPv6::getNetmask($ipaddr, $bits);
253
	return $address;
254
}
255

    
256
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
257
function gen_subnet_max($ipaddr, $bits) {
258
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
259
		return "";
260

    
261
	return long2ip32(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
262
}
263

    
264
/* Generate end number for a given ipv6 subnet mask */
265
function gen_subnetv6_max($ipaddr, $bits) {
266
	if(!is_ipaddrv6($ipaddr))
267
		return false;
268
	
269
	$mask = Net_IPv6::getNetmask('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',$bits);
270
	
271
	$inet_ip = (binary)inet_pton($ipaddr);
272
	$inet_mask = (binary)inet_pton($mask);
273

    
274
	$inet_end = $inet_ip | ~$inet_mask;
275

    
276
	return(Net_IPv6::uncompress(inet_ntop($inet_end)));
277
}
278

    
279
/* returns a subnet mask (long given a bit count) */
280
function gen_subnet_mask_long($bits) {
281
	$sm = 0;
282
	for ($i = 0; $i < $bits; $i++) {
283
		$sm >>= 1;
284
		$sm |= 0x80000000;
285
	}
286
	return $sm;
287
}
288

    
289
/* same as above but returns a string */
290
function gen_subnet_mask($bits) {
291
	return long2ip(gen_subnet_mask_long($bits));
292
}
293

    
294
/* Convert long int to IP address, truncating to 32-bits. */
295
function long2ip32($ip) {
296
	return long2ip($ip & 0xFFFFFFFF);
297
}
298

    
299
/* Convert IP address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. */
300
function ip2long32($ip) {
301
	return ( ip2long($ip) & 0xFFFFFFFF );
302
}
303

    
304
/* Convert IP address to unsigned long int. */
305
function ip2ulong($ip) {
306
	return sprintf("%u", ip2long32($ip));
307
}
308

    
309
/* Find out how many IPs are contained within a given IP range
310
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
311
 */
312
function ip_range_size($startip, $endip) {
313
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
314
		// Operate as unsigned long because otherwise it wouldn't work
315
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
316
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
317
	}
318
	return -1;
319
}
320

    
321
/* Find the smallest possible subnet mask which can contain a given number of IPs
322
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
323
 */
324
function find_smallest_cidr($number) {
325
	$smallest = 1;
326
	for ($b=32; $b > 0; $b--) {
327
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
328
	}
329
	return (32-$smallest);
330
}
331

    
332
/* Return the previous IP address before the given address */
333
function ip_before($ip) {
334
	return long2ip32(ip2long($ip)-1);
335
}
336

    
337
/* Return the next IP address after the given address */
338
function ip_after($ip) {
339
	return long2ip32(ip2long($ip)+1);
340
}
341

    
342
/* Return true if the first IP is 'before' the second */
343
function ip_less_than($ip1, $ip2) {
344
	// Compare as unsigned long because otherwise it wouldn't work when
345
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
346
	return ip2ulong($ip1) < ip2ulong($ip2);
347
}
348

    
349
/* Return true if the first IP is 'after' the second */
350
function ip_greater_than($ip1, $ip2) {
351
	// Compare as unsigned long because otherwise it wouldn't work
352
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
353
	return ip2ulong($ip1) > ip2ulong($ip2);
354
}
355

    
356
/* Convert a range of IPs to an array of subnets which can contain the range. */
357
function ip_range_to_subnet_array($startip, $endip) {
358
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
359
		return array();
360
	}
361

    
362
	// Container for subnets within this range.
363
	$rangesubnets = array();
364

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

    
368
	// Loop here to reduce subnet size and retest as needed. We need to make sure
369
	//   that the target subnet is wholly contained between $startip and $endip.
370
	for ($cidr; $cidr <= 32; $cidr++) {
371
		// Find the network and broadcast addresses for the subnet being tested.
372
		$targetsub_min = gen_subnet($startip, $cidr);
373
		$targetsub_max = gen_subnet_max($startip, $cidr);
374

    
375
		// Check best case where the range is exactly one subnet.
376
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
377
			// Hooray, the range is exactly this subnet!
378
			return array("{$startip}/{$cidr}");
379
		}
380

    
381
		// These remaining scenarios will find a subnet that uses the largest
382
		//  chunk possible of the range being tested, and leave the rest to be
383
		//  tested recursively after the loop.
384

    
385
		// Check if the subnet begins with $startip and ends before $endip
386
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
387
			break;
388
		}
389

    
390
		// Check if the subnet ends at $endip and starts after $startip
391
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
392
			break;
393
		}
394

    
395
		// Check if the subnet is between $startip and $endip
396
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
397
			break;
398
		}
399
	}
400

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

    
407
	// Add in the subnet we found before, to preserve ordering
408
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
409

    
410
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
411
	if ($endip != $targetsub_max) {
412
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
413
	}
414
	return $rangesubnets;
415
}
416

    
417
function is_iprange($range) {
418
	if (substr_count($range, '-') != 1) {
419
		return false;
420
	}
421
	list($ip1, $ip2) = explode ('-', $range);
422
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
423
}
424

    
425
function is_numericint($arg) {
426
	return (preg_match("/[^0-9]/", $arg) ? false : true);
427
}
428

    
429

    
430
/* returns true if $ipaddr is a valid dotted IPv4 address or a IPv6 */
431
function is_ipaddr($ipaddr) {
432
	if(is_ipaddrv4($ipaddr)) {
433
		return true;
434
	}
435
	if(is_ipaddrv6($ipaddr)) {
436
		return true;
437
	}
438
	return false;
439
}
440

    
441
/* returns true if $ipaddr is a valid IPv6 address */
442
function is_ipaddrv6($ipaddr) {
443
	$result = Net_IPv6::checkIPv6($ipaddr);
444
	return $result;
445
}
446

    
447
/* returns true if $ipaddr is a valid dotted IPv4 address */
448
function is_ipaddrv4($ipaddr) {
449
	if (!is_string($ipaddr))
450
		return false;
451

    
452
	$ip_long = ip2long($ipaddr);
453
	$ip_reverse = long2ip32($ip_long);
454

    
455
	if ($ipaddr == $ip_reverse)
456
		return true;
457
	else
458
		return false;
459
}
460

    
461

    
462
/* returns true if $ipaddr is a valid literal IPv6 address */
463
function is_literalipaddrv6($ipaddr) {
464
	if(preg_match("/\[([0-9a-f:]+)\]/i", $ipaddr, $match))
465
		$ipaddr = $match[1];
466
	else
467
		return false;
468

    
469
	return is_ipaddrv6($ipaddr);
470
}
471

    
472
function is_ipaddrwithport($ipport) {
473
	$parts = explode(":", $ipport);
474
	$port = array_pop($parts);
475
	if (count($parts) == 1) {
476
		return is_ipaddrv4($parts[0]) && is_port($port);
477
	} elseif (count($parts) > 1) {
478
		return is_literalipaddrv6(implode(":", $parts)) && is_port($port);
479
	} else {
480
		return false;
481
	}
482
}
483

    
484
function is_hostnamewithport($hostport) {
485
	$parts = explode(":", $hostport);
486
	$port = array_pop($parts);
487
	if (count($parts) == 1) {
488
		return is_hostname($parts[0]) && is_port($port);
489
	} else {
490
		return false;
491
	}
492
}
493

    
494
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
495
function is_ipaddroralias($ipaddr) {
496
	global $config;
497

    
498
	if (is_alias($ipaddr)) {
499
		if (is_array($config['aliases']['alias'])) {
500
			foreach ($config['aliases']['alias'] as $alias) {
501
				if ($alias['name'] == $ipaddr && $alias['type'] != "port")
502
					return true;
503
			}
504
		}
505
		return false;
506
	} else
507
		return is_ipaddr($ipaddr);
508

    
509
}
510

    
511
/* returns true if $subnet is a valid IPv4 or IPv6 subnet in CIDR format */
512
function is_subnet($subnet) {
513
	if(is_subnetv4($subnet)) {
514
		return true;
515
	}
516
	if(is_subnetv6($subnet)) {
517
		return true;
518
	}
519
	return false;
520
}
521

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

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

    
529
	if (!is_ipaddrv4($hp))
530
		return false;
531

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

    
535
	return true;
536
}
537

    
538
/* returns true if $subnet is a valid IPv6 subnet in CIDR format */
539
function is_subnetv6($subnet) {
540
	if (!is_string($subnet))
541
		return false;
542

    
543
	list($hp,$np) = explode('/', $subnet);
544

    
545
	if (!is_ipaddrv6($hp))
546
		return false;
547

    
548
	if (!is_numeric($np) || ($np < 1) || ($np > 128))
549
		return false;
550

    
551
	return true;
552
}
553

    
554

    
555
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
556
function is_subnetoralias($subnet) {
557
	global $aliastable;
558

    
559
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
560
		return true;
561
	else
562
		return is_subnet($subnet);
563
}
564

    
565
/* returns true if $hostname is a valid hostname */
566
function is_hostname($hostname) {
567
	if (!is_string($hostname))
568
		return false;
569

    
570
	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))
571
		return true;
572
	else
573
		return false;
574
}
575

    
576
/* returns true if $domain is a valid domain name */
577
function is_domain($domain) {
578
	if (!is_string($domain))
579
		return false;
580

    
581
	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))
582
		return true;
583
	else
584
		return false;
585
}
586

    
587
/* returns true if $macaddr is a valid MAC address */
588
function is_macaddr($macaddr) {
589
	return preg_match('/^[0-9A-F]{2}(?:[:][0-9A-F]{2}){5}$/i', $macaddr) == 1 ? true : false;
590
}
591

    
592
/* returns true if $name is a valid name for an alias */
593
/* returns NULL if a reserved word is used */
594
function is_validaliasname($name) {
595
	/* Array of reserved words */
596
	$reserved = array("port", "pass");
597
	if (in_array($name, $reserved, true))
598
		return; /* return NULL */
599
	if (!preg_match("/[^a-zA-Z0-9_]/", $name) && (strlen($name) < 32))
600
		return true;
601
	else
602
		return false;
603
}
604

    
605
/* returns true if $port is a valid TCP/UDP port */
606
function is_port($port) {
607
	$tmpports = explode(":", $port);
608
	foreach($tmpports as $tmpport) {
609
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
610
			continue;
611
		if (!ctype_digit($tmpport))
612
			return false;
613
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
614
			return false;
615
	}
616
	return true;
617
}
618

    
619
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
620
function is_portrange($portrange) {
621
	$ports = explode(":", $portrange);
622

    
623
	return (count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]));
624
}
625

    
626
/* returns true if $port is a valid port number or an alias thereof */
627
function is_portoralias($port) {
628
	global $config;
629

    
630
	if (is_alias($port)) {
631
		if (is_array($config['aliases']['alias'])) {
632
			foreach ($config['aliases']['alias'] as $alias) {
633
				if ($alias['name'] == $port && $alias['type'] == "port")
634
					return true;
635
				}
636
			}
637
			return false;
638
	} else
639
		return is_port($port);
640
}
641

    
642
/* returns true if $val is a valid shaper bandwidth value */
643
function is_valid_shaperbw($val) {
644
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
645
}
646

    
647
/* return the configured carp interface list */
648
function get_configured_carp_interface_list() {
649
	global $config;
650

    
651
	$iflist = array();
652

    
653
	if(is_array($config['virtualip']['vip'])) {
654
		$viparr = &$config['virtualip']['vip'];
655
		foreach ($viparr as $vip) {
656
			switch ($vip['mode']) {
657
			case "carp":
658
				$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
659
				$iflist[$vipif] = $vip['subnet'];
660
				break;
661
			}
662
		}
663
	}
664

    
665
	return $iflist;
666
}
667

    
668
/* return the configured IP aliases list */
669
function get_configured_ip_aliases_list($returnfullentry = false) {
670
	global $config;
671

    
672
	$alias_list=array();
673

    
674
	if(is_array($config['virtualip']['vip'])) {
675
		$viparr = &$config['virtualip']['vip'];
676
		foreach ($viparr as $vip) {
677
			if ($vip['mode']=="ipalias") {
678
				if ($returnfullentry)
679
					$alias_list[$vip['subnet']] = $vip;
680
				else
681
					$alias_list[$vip['subnet']] = $vip['interface'];
682
			}
683
		}
684
	}
685

    
686
	return $alias_list;
687
}
688

    
689

    
690
/* comparison function for sorting by the order in which interfaces are normally created */
691
function compare_interface_friendly_names($a, $b) {
692
	if ($a == $b)
693
		return 0;
694
	else if ($a == 'wan')
695
		return -1;
696
	else if ($b == 'wan')
697
		return 1;
698
	else if ($a == 'lan')
699
		return -1;
700
	else if ($b == 'lan')
701
		return 1;
702

    
703
	return strnatcmp($a, $b);
704
}
705

    
706
/* return the configured interfaces list. */
707
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
708
	global $config;
709

    
710
	$iflist = array();
711

    
712
	/* if list */
713
	foreach($config['interfaces'] as $if => $ifdetail) {
714
		if ($only_opt && ($if == "wan" || $if == "lan"))
715
			continue;
716
		if (isset($ifdetail['enable']) || $withdisabled == true)
717
			$iflist[$if] = $if;
718
	}
719

    
720
	return $iflist;
721
}
722

    
723
/* return the configured interfaces list. */
724
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
725
	global $config;
726

    
727
	$iflist = array();
728

    
729
	/* if list */
730
	foreach($config['interfaces'] as $if => $ifdetail) {
731
		if ($only_opt && ($if == "wan" || $if == "lan"))
732
			continue;
733
		if (isset($ifdetail['enable']) || $withdisabled == true) {
734
			$tmpif = get_real_interface($if);
735
			if (!empty($tmpif))
736
				$iflist[$tmpif] = $if;
737
		}
738
	}
739

    
740
	return $iflist;
741
}
742

    
743
/* return the configured interfaces list with their description. */
744
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
745
	global $config;
746

    
747
	$iflist = array();
748

    
749
	/* if list */
750
	foreach($config['interfaces'] as $if => $ifdetail) {
751
		if ($only_opt && ($if == "wan" || $if == "lan"))
752
			continue;
753
		if (isset($ifdetail['enable']) || $withdisabled == true) {
754
			if(empty($ifdetail['descr']))
755
				$iflist[$if] = strtoupper($if);
756
			else
757
				$iflist[$if] = strtoupper($ifdetail['descr']);
758
		}
759
	}
760

    
761
	return $iflist;
762
}
763

    
764
/*
765
 *   get_configured_ip_addresses() - Return a list of all configured
766
 *   interfaces IP Addresses
767
 *
768
 */
769
function get_configured_ip_addresses() {
770
	require_once("interfaces.inc");
771
	$ip_array = array();
772
	$interfaces = get_configured_interface_list();
773
	if(is_array($interfaces)) {
774
		foreach($interfaces as $int) {
775
			$ipaddr = get_interface_ip($int);
776
			$ip_array[$int] = $ipaddr;
777
		}
778
	}
779
	$interfaces = get_configured_carp_interface_list();
780
	if(is_array($interfaces)) 
781
		foreach($interfaces as $int => $ipaddr) 
782
			$ip_array[$int] = $ipaddr;
783
	return $ip_array;
784
}
785

    
786
/*
787
 *   get_configured_ipv6_addresses() - Return a list of all configured
788
 *   interfaces IPv6 Addresses
789
 *
790
 */
791
function get_configured_ipv6_addresses() {
792
	require_once("interfaces.inc");
793
	$ipv6_array = array();
794
	$interfaces = get_configured_interface_list();
795
	if(is_array($interfaces)) {
796
		foreach($interfaces as $int) {
797
			$ipaddrv6 = get_interface_ipv6($int);
798
			$ipv6_array[$int] = $ipaddrv6;
799
		}
800
	}
801
	$interfaces = get_configured_carp_interface_list();
802
	if(is_array($interfaces)) 
803
		foreach($interfaces as $int => $ipaddrv6) 
804
			$ipv6_array[$int] = $ipaddrv6;
805
	return $ipv6_array;
806
}
807

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

    
919
/****f* util/log_error
920
* NAME
921
*   log_error  - Sends a string to syslog.
922
* INPUTS
923
*   $error     - string containing the syslog message.
924
* RESULT
925
*   null
926
******/
927
function log_error($error) {
928
	global $g;
929
	$page = $_SERVER['SCRIPT_NAME'];
930
	syslog(LOG_ERR, "$page: $error");
931
	if ($g['debug'])
932
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
933
	return;
934
}
935

    
936
/****f* util/log_auth
937
* NAME
938
*   log_error  - Sends a string to syslog as LOG_AUTH facility
939
* INPUTS
940
*   $error     - string containing the syslog message.
941
* RESULT
942
*   null
943
******/
944
function log_auth($error) {
945
	global $g;
946
	$page = $_SERVER['SCRIPT_NAME'];
947
	syslog(LOG_AUTH, "$page: $error");
948
	if ($g['debug'])
949
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
950
	return;
951
}
952

    
953
/****f* util/exec_command
954
 * NAME
955
 *   exec_command - Execute a command and return a string of the result.
956
 * INPUTS
957
 *   $command   - String of the command to be executed.
958
 * RESULT
959
 *   String containing the command's result.
960
 * NOTES
961
 *   This function returns the command's stdout and stderr.
962
 ******/
963
function exec_command($command) {
964
	$output = array();
965
	exec($command . ' 2>&1 ', $output);
966
	return(implode("\n", $output));
967
}
968

    
969
/* wrapper for exec() */
970
function mwexec($command, $mute = false, $clearsigmask = false) {
971
	global $g;
972

    
973
	if ($g['debug']) {
974
		if (!$_SERVER['REMOTE_ADDR'])
975
			echo "mwexec(): $command\n";
976
	}
977
	$oarr = array();
978
	$retval = 0;
979

    
980
	if ($clearsigmask) {
981
		$oldset = array();
982
		pcntl_sigprocmask(SIG_SETMASK, array(), $oldset);
983
	}
984
	$garbage = exec("$command 2>&1", $oarr, $retval);
985
	if ($clearsigmask) {
986
		pcntl_sigprocmask(SIG_SETMASK, $oldset);
987
	}
988

    
989
	if(isset($config['system']['developerspew']))
990
		$mute = false;
991
	if(($retval <> 0) && ($mute === false)) {
992
		$output = implode(" ", $oarr);
993
		log_error(sprintf(gettext("The command '%1\$s' returned exit code '%2\$d', the output was '%3\$s' "), $command, $retval, $output));
994
	}
995
	return $retval;
996
}
997

    
998
/* wrapper for exec() in background */
999
function mwexec_bg($command, $clearsigmask = false) {
1000
	global $g;
1001

    
1002
	if ($g['debug']) {
1003
		if (!$_SERVER['REMOTE_ADDR'])
1004
			echo "mwexec(): $command\n";
1005
	}
1006

    
1007
	if ($clearsigmask) {
1008
		$oldset = array();
1009
		pcntl_sigprocmask(SIG_SETMASK, array(), $oldset);
1010
	}
1011
	exec("nohup $command > /dev/null 2>&1 &");
1012
	if ($clearsigmask) {
1013
		pcntl_sigprocmask(SIG_SETMASK, $oldset);
1014
	}
1015
}
1016

    
1017
/* unlink a file, if it exists */
1018
function unlink_if_exists($fn) {
1019
	$to_do = glob($fn);
1020
	if(is_array($to_do)) {
1021
		foreach($to_do as $filename)
1022
			@unlink($filename);
1023
	} else {
1024
		@unlink($fn);
1025
	}
1026
}
1027
/* make a global alias table (for faster lookups) */
1028
function alias_make_table($config) {
1029
	global $aliastable;
1030

    
1031
	$aliastable = array();
1032

    
1033
	if (is_array($config['aliases']['alias'])) {
1034
		foreach ($config['aliases']['alias'] as $alias) {
1035
			if ($alias['name'])
1036
				$aliastable[$alias['name']] = $alias['address'];
1037
		}
1038
	}
1039
}
1040

    
1041
/* check if an alias exists */
1042
function is_alias($name) {
1043
	global $aliastable;
1044

    
1045
	return isset($aliastable[$name]);
1046
}
1047

    
1048
function alias_get_type($name) {
1049
        global $config;
1050
        
1051
	if (is_array($config['aliases']['alias'])) {
1052
		foreach ($config['aliases']['alias'] as $alias) {
1053
			if ($name == $alias['name'])
1054
				return $alias['type'];
1055
		}
1056
	}
1057

    
1058
        return "";
1059
}
1060

    
1061
/* expand a host or network alias, if necessary */
1062
function alias_expand($name) {
1063
	global $aliastable;
1064

    
1065
	if (isset($aliastable[$name]))
1066
		return "\${$name}";
1067
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
1068
		return "{$name}";
1069
	else
1070
		return null;
1071
}
1072

    
1073
function alias_expand_urltable($name) {
1074
	global $config;
1075
	$urltable_prefix = "/var/db/aliastables/";
1076
	$urltable_filename = $urltable_prefix . $name . ".txt";
1077

    
1078
	if (is_array($config['aliases']['alias'])) {
1079
		foreach ($config['aliases']['alias'] as $alias) {
1080
			if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
1081
				if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
1082
					return $urltable_filename;
1083
				else if (process_alias_urltable($name, $alias["url"], 0, true))
1084
					return $urltable_filename;
1085
			}
1086
		}
1087
	}
1088
	return null;
1089
}
1090

    
1091
function subnet_size ($subnet) {
1092
	if (is_subnetv4($subnet)) {
1093
		list ($ip, $bits) = explode("/", $subnet);
1094
		return round(exp(log(2) * (32 - $bits)));
1095
	}
1096
	else if (is_subnetv6($subnet)) {
1097
		list ($ip, $bits) = explode("/", $subnet);
1098
		return round(exp(log(2) * (128 - $bits)));
1099
	}
1100
	else {
1101
		return 0;
1102
	}
1103
}
1104

    
1105
function subnet_expand ($subnet) {
1106
	if (is_subnetv4($subnet)) {
1107
		return subnetv4_expand($subnet);
1108
	} else if (is_subnetv6($subnet)) {
1109
		return subnetv6_expand($subnet);
1110
	} else {
1111
		return $subnet;
1112
	}
1113
}
1114

    
1115
function subnetv4_expand ($subnet) {
1116
	$result = array();
1117
	list ($ip, $bits) = explode("/", $subnet);
1118
	$net  = ip2long($ip);
1119
	$mask = (0xffffffff << (32 - $bits));
1120
	$net &= $mask;
1121
	$size = round(exp(log(2) * (32 - $bits)));
1122
	for ($i = 0; $i < $size; $i += 1) {
1123
		$result[] = long2ip($net | $i);
1124
	}
1125
	return $result;
1126
}
1127

    
1128
/* find out whether two subnets overlap */
1129
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
1130

    
1131
	if (!is_numeric($bits1))
1132
		$bits1 = 32;
1133
	if (!is_numeric($bits2))
1134
		$bits2 = 32;
1135

    
1136
	if ($bits1 < $bits2)
1137
		$relbits = $bits1;
1138
	else
1139
		$relbits = $bits2;
1140

    
1141
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
1142
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
1143

    
1144
	return ($sn1 == $sn2);
1145
}
1146

    
1147
/* compare two IP addresses */
1148
function ipcmp($a, $b) {
1149
	if (ip_less_than($a, $b))
1150
		return -1;
1151
	else if (ip_greater_than($a, $b))
1152
		return 1;
1153
	else
1154
		return 0;
1155
}
1156

    
1157
/* return true if $addr is in $subnet, false if not */
1158
function ip_in_subnet($addr,$subnet) {
1159
	if(is_ipaddrv6($addr)) {
1160
		$result = Net_IPv6::IsInNetmask($addr, $subnet);
1161
		if($result)
1162
			return true;
1163
		else
1164
			return false;
1165
	}
1166
	list($ip, $mask) = explode('/', $subnet);
1167
	$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
1168
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
1169
}
1170

    
1171
/* verify (and remove) the digital signature on a file - returns 0 if OK */
1172
function verify_digital_signature($fname) {
1173
	global $g;
1174

    
1175
	if(!file_exists("/usr/local/sbin/gzsig"))
1176
		return 4;
1177

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

    
1181
/* obtain MAC address given an IP address by looking at the ARP table */
1182
function arp_get_mac_by_ip($ip) {
1183
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
1184
	$arpoutput = "";
1185
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
1186

    
1187
	if ($arpoutput[0]) {
1188
		$arpi = explode(" ", $arpoutput[0]);
1189
		$macaddr = $arpi[3];
1190
		if (is_macaddr($macaddr))
1191
			return $macaddr;
1192
		else
1193
			return false;
1194
	}
1195

    
1196
	return false;
1197
}
1198

    
1199
/* return a fieldname that is safe for xml usage */
1200
function xml_safe_fieldname($fieldname) {
1201
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
1202
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
1203
			 ':', ',', '.', '\'', '\\'
1204
		);
1205
	return strtolower(str_replace($replace, "", $fieldname));
1206
}
1207

    
1208
function mac_format($clientmac, $zone = false) {
1209
    global $config;
1210

    
1211
    $mac = explode(":", $clientmac);
1212
    if ($zone)
1213
      $mac_format = $zone ? $config['captiveportal'][$zone]['radmac_format'] : false;
1214

    
1215
    switch($mac_format) {
1216
        case 'singledash':
1217
		return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
1218

    
1219
        case 'ietf':
1220
		return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
1221

    
1222
        case 'cisco':
1223
		return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
1224

    
1225
        case 'unformatted':
1226
		return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
1227

    
1228
        default:
1229
		return $clientmac;
1230
    }
1231
}
1232

    
1233
function resolve_retry($hostname, $retries = 5) {
1234

    
1235
	if (is_ipaddr($hostname))
1236
		return $hostname;
1237

    
1238
       for ($i = 0; $i < $retries; $i++) {
1239
		// FIXME: gethostbyname does not work for AAAA hostnames, boo, hiss
1240
               $ip = gethostbyname($hostname);
1241

    
1242
		if ($ip && $ip != $hostname) {
1243
			/* success */
1244
			return $ip;
1245
		}
1246

    
1247
		sleep(1);
1248
	}
1249

    
1250
	return false;
1251
}
1252

    
1253
function format_bytes($bytes) {
1254
	if ($bytes >= 1073741824) {
1255
		return sprintf("%.2f GB", $bytes/1073741824);
1256
	} else if ($bytes >= 1048576) {
1257
		return sprintf("%.2f MB", $bytes/1048576);
1258
	} else if ($bytes >= 1024) {
1259
		return sprintf("%.0f KB", $bytes/1024);
1260
	} else {
1261
		return sprintf("%d bytes", $bytes);
1262
	}
1263
}
1264

    
1265
function update_filter_reload_status($text) {
1266
	global $g;
1267

    
1268
	file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1269
}
1270

    
1271
/****f* util/return_dir_as_array
1272
 * NAME
1273
 *   return_dir_as_array - Return a directory's contents as an array.
1274
 * INPUTS
1275
 *   $dir       - string containing the path to the desired directory.
1276
 * RESULT
1277
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1278
 ******/
1279
function return_dir_as_array($dir) {
1280
	$dir_array = array();
1281
	if (is_dir($dir)) {
1282
		if ($dh = opendir($dir)) {
1283
			while (($file = readdir($dh)) !== false) {
1284
				$canadd = 0;
1285
				if($file == ".") $canadd = 1;
1286
				if($file == "..") $canadd = 1;
1287
				if($canadd == 0)
1288
					array_push($dir_array, $file);
1289
			}
1290
			closedir($dh);
1291
		}
1292
	}
1293
	return $dir_array;
1294
}
1295

    
1296
function run_plugins($directory) {
1297
	global $config, $g;
1298

    
1299
	/* process packager manager custom rules */
1300
	$files = return_dir_as_array($directory);
1301
	if (is_array($files)) {
1302
		foreach ($files as $file) {
1303
			if (stristr($file, ".sh") == true)
1304
				mwexec($directory . $file . " start");
1305
			else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1306
				require_once($directory . "/" . $file);
1307
		}
1308
	}
1309
}
1310

    
1311
/*
1312
 *    safe_mkdir($path, $mode = 0755)
1313
 *    create directory if it doesn't already exist and isn't a file!
1314
 */
1315
function safe_mkdir($path, $mode=0755) {
1316
	global $g;
1317

    
1318
	if (!is_file($path) && !is_dir($path)) {
1319
		return @mkdir($path, $mode, true);
1320
	} else {
1321
		return false;
1322
	}
1323
}
1324

    
1325
/*
1326
 * make_dirs($path, $mode = 0755)
1327
 * create directory tree recursively (mkdir -p)
1328
 */
1329
function make_dirs($path, $mode = 0755) {
1330
	$base = '';
1331
	foreach (explode('/', $path) as $dir) {
1332
		$base .= "/$dir";
1333
		if (!is_dir($base)) {
1334
			if (!@mkdir($base, $mode))
1335
				return false;
1336
		}
1337
	}
1338
	return true;
1339
}
1340

    
1341
/*
1342
 * get_sysctl($names)
1343
 * Get values of sysctl OID's listed in $names (accepts an array or a single
1344
 * name) and return an array of key/value pairs set for those that exist
1345
 */
1346
function get_sysctl($names) {
1347
	if (empty($names))
1348
		return array();
1349

    
1350
	if (is_array($names)) {
1351
		$name_list = array();
1352
		foreach ($names as $name) {
1353
			$name_list[] = escapeshellarg($name);
1354
		}
1355
	} else
1356
		$name_list = array(escapeshellarg($names));
1357

    
1358
	exec("/sbin/sysctl -i " . implode(" ", $name_list), $output);
1359
	$values = array();
1360
	foreach ($output as $line) {
1361
		$line = explode(": ", $line, 2);
1362
		if (count($line) == 2)
1363
			$values[$line[0]] = $line[1];
1364
	}
1365

    
1366
	return $values;
1367
}
1368

    
1369
/*
1370
 * set_sysctl($value_list)
1371
 * Set sysctl OID's listed as key/value pairs and return
1372
 * an array with keys set for those that succeeded
1373
 */
1374
function set_sysctl($values) {
1375
	if (empty($values))
1376
		return array();
1377

    
1378
	$value_list = array();
1379
	foreach ($values as $key => $value) {
1380
		$value_list[] = escapeshellarg($key) . "=" . escapeshellarg($value);
1381
	}
1382

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

    
1385
	/* Retry individually if failed (one or more read-only) */
1386
	if ($success <> 0 && count($value_list) > 1) {
1387
		foreach ($value_list as $value) {
1388
			exec("/sbin/sysctl -i " . $value, $output);
1389
		}
1390
	}
1391

    
1392
	$ret = array();
1393
	foreach ($output as $line) {
1394
		$line = explode(": ", $line, 2);
1395
		if (count($line) == 2)
1396
			$ret[$line[0]] = true;
1397
	}
1398

    
1399
	return $ret;
1400
}
1401

    
1402
/*
1403
 *     get_memory()
1404
 *     returns an array listing the amount of
1405
 *     memory installed in the hardware
1406
 *     [0]real and [1]available
1407
 */
1408
function get_memory() {
1409
	$matches = "";
1410
	if(file_exists("/var/log/dmesg.boot"))
1411
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1412
	else
1413
		$mem = `dmesg -a | grep memory`;			
1414
	if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1415
		return array($matches[1][0], $matches[1][0]);
1416
	if(!$real && !$avail) {
1417
		$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1418
		$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1419
		/* convert from bytes to megabytes */
1420
		return array(($real/1048576),($avail/1048576));
1421
	}
1422
}
1423

    
1424
function mute_kernel_msgs() {
1425
	global $config;
1426
	// Do not mute serial console.  The kernel gets very very cranky
1427
	// and will start dishing you cannot control tty errors.
1428
	switch (trim(file_get_contents("/etc/platform"))) {
1429
		case "nanobsd":
1430
		case "jail":
1431
			return;
1432
	}
1433
	if($config['system']['enableserial']) 
1434
		return;			
1435
	exec("/sbin/conscontrol mute on");
1436
}
1437

    
1438
function unmute_kernel_msgs() {
1439
	global $config;
1440
	// Do not mute serial console.  The kernel gets very very cranky
1441
	// and will start dishing you cannot control tty errors.
1442
	switch (trim(file_get_contents("/etc/platform"))) {
1443
		case "nanobsd":
1444
		case "jail":
1445
			return;
1446
	}
1447
	exec("/sbin/conscontrol mute off");
1448
}
1449

    
1450
function start_devd() {
1451
	global $g;
1452

    
1453
	if ($g['platform'] == 'jail')
1454
		return;
1455
	exec("/sbin/devd");
1456
	sleep(1);
1457
}
1458

    
1459
function is_interface_vlan_mismatch() {
1460
	global $config, $g;
1461

    
1462
	if (is_array($config['vlans']['vlan'])) {
1463
		foreach ($config['vlans']['vlan'] as $vlan) {
1464
			if (does_interface_exist($vlan['if']) == false)
1465
				return true;
1466
		}
1467
	}
1468

    
1469
	return false;
1470
}
1471

    
1472
function is_interface_mismatch() {
1473
	global $config, $g;
1474

    
1475
	$do_assign = false;
1476
	$i = 0;
1477
	if (is_array($config['interfaces'])) {
1478
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
1479
			if (preg_match("/^enc|^cua|^tun|^tap|^l2tp|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1480
				// Do not check these interfaces.
1481
				$i++;
1482
				continue;
1483
			}
1484
			else if (does_interface_exist($ifcfg['if']) == false) {
1485
				echo "Warning: Interface '{$ifcfg['if']}' does not exist.\n";
1486
				$do_assign = true;
1487
			} else
1488
				$i++;
1489
		}
1490
	}
1491

    
1492
	if ($g['minimum_nic_count'] > $i) {
1493
		$do_assign = true;
1494
	} else if (file_exists("{$g['tmp_path']}/assign_complete"))
1495
	$do_assign = false;
1496

    
1497
	return $do_assign;
1498
}
1499

    
1500
/* sync carp entries to other firewalls */
1501
function carp_sync_client() {
1502
	global $g;
1503
	send_event("filter sync");
1504
}
1505

    
1506
/****f* util/isAjax
1507
 * NAME
1508
 *   isAjax - reports if the request is driven from prototype
1509
 * INPUTS
1510
 *   none
1511
 * RESULT
1512
 *   true/false
1513
 ******/
1514
function isAjax() {
1515
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1516
}
1517

    
1518
/****f* util/timeout
1519
 * NAME
1520
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1521
 * INPUTS
1522
 *   optional, seconds to wait before timeout. Default 9 seconds.
1523
 * RESULT
1524
 *   returns 1 char of user input or null if no input.
1525
 ******/
1526
function timeout($timer = 9) {
1527
	while(!isset($key)) {
1528
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1529
		else { echo chr(8). "{$timer}"; }
1530
		`/bin/stty -icanon min 0 time 25`;
1531
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1532
		`/bin/stty icanon`;
1533
		if ($key == '')
1534
			unset($key);
1535
		$timer--;
1536
		if ($timer == 0)
1537
			break;
1538
	}
1539
	return $key;	
1540
}
1541

    
1542
/****f* util/msort
1543
 * NAME
1544
 *   msort - sort array
1545
 * INPUTS
1546
 *   $array to be sorted, field to sort by, direction of sort
1547
 * RESULT
1548
 *   returns newly sorted array
1549
 ******/
1550
function msort($array, $id="id", $sort_ascending=true) {
1551
	$temp_array = array();
1552
	while(count($array)>0) {
1553
		$lowest_id = 0;
1554
		$index=0;
1555
		foreach ($array as $item) {
1556
			if (isset($item[$id])) {
1557
				if ($array[$lowest_id][$id]) {
1558
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1559
						$lowest_id = $index;
1560
					}
1561
				}
1562
			}
1563
			$index++;
1564
		}
1565
		$temp_array[] = $array[$lowest_id];
1566
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1567
	}
1568
	if ($sort_ascending) {
1569
		return $temp_array;
1570
	} else {
1571
    		return array_reverse($temp_array);
1572
	}
1573
}
1574

    
1575
/****f* util/color
1576
 * NAME
1577
 *   color - outputs a color code to the ansi terminal if supported
1578
 * INPUTS
1579
 *   color code or color name
1580
 * RESULT
1581
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1582
 ******/
1583
function color($color = "0m") {
1584
	/*
1585
		Color codes available:
1586
		 0m reset; clears all colors and styles (to white on black)
1587
		 1m bold on (see below)
1588
		 3m italics on
1589
		 4m underline on
1590
		 7m inverse on; reverses foreground & background colors
1591
		 9m strikethrough on
1592
		 22m bold off (see below)
1593
		 23m italics off
1594
		 24m underline off
1595
		 27m inverse off
1596
		 29m strikethrough off
1597
		 30m set foreground color to black
1598
		 31m set foreground color to red
1599
		 32m set foreground color to green
1600
		 33m set foreground color to yellow
1601
		 34m set foreground color to blue
1602
		 35m set foreground color to magenta (purple)
1603
		 36m set foreground color to cyan
1604
		 37m set foreground color to white
1605
		 40m  set background color to black
1606
		 41m set background color to red
1607
		 42m set background color to green
1608
		 43m set background color to yellow
1609
		 44m set background color to blue
1610
		 45m set background color to magenta (purple)
1611
		 46m set background color to cyan
1612
		 47m set background color to white
1613
		 49m set background color to default (black)
1614
	*/	
1615
	// Allow caching of TERM to 
1616
	// speedup subequence requests.
1617
	global $TERM;
1618
	if(!$TERM) 
1619
		$TERM=`/usr/bin/env | grep color`;
1620
	if(!$TERM)
1621
		$TERM=`/usr/bin/env | grep cons25`;
1622
	if($TERM) {
1623
		$ESCAPE=chr(27);
1624
		switch ($color) {
1625
			case "black":
1626
				return "{$ESCAPE}[30m"; 
1627
			case "red":
1628
				return "{$ESCAPE}[31m"; 
1629
			case "green":
1630
				return "{$ESCAPE}[32m"; 
1631
			case "yellow":
1632
				return "{$ESCAPE}[33m"; 
1633
			case "blue":
1634
				return "{$ESCAPE}[34m"; 
1635
			case "magenta":
1636
				return "{$ESCAPE}[35m"; 
1637
			case "cyan":
1638
				return "{$ESCAPE}[36m"; 
1639
			case "white":
1640
				return "{$ESCAPE}[37m"; 
1641
			case "default":
1642
				return "{$ESCAPE}[39m"; 
1643
		}
1644
		return "{$ESCAPE}[{$color}";
1645
	}
1646
}
1647

    
1648
/****f* util/is_URL
1649
 * NAME
1650
 *   is_URL
1651
 * INPUTS
1652
 *   string to check
1653
 * RESULT
1654
 *   Returns true if item is a URL
1655
 ******/
1656
function is_URL($url) {
1657
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1658
	if($match)
1659
		return true;	
1660
	return false;
1661
}
1662

    
1663
function is_file_included($file = "") {
1664
	$files = get_included_files();
1665
	if (in_array($file, $files))
1666
		return true;
1667
	
1668
	return false;
1669
}
1670

    
1671
/*
1672
	This function was borrowed from a comment on PHP.net at the following URL:
1673
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
1674
 */
1675
function array_merge_recursive_unique($array0, $array1) {
1676

    
1677
	$arrays = func_get_args();
1678
	$remains = $arrays;
1679

    
1680
	// We walk through each arrays and put value in the results (without
1681
	// considering previous value).
1682
	$result = array();
1683

    
1684
	// loop available array
1685
	foreach($arrays as $array) {
1686

    
1687
		// The first remaining array is $array. We are processing it. So
1688
		// we remove it from remaing arrays.
1689
        array_shift($remains);
1690

    
1691
		// We don't care non array param, like array_merge since PHP 5.0.
1692
		if(is_array($array)) {
1693
			// Loop values
1694
			foreach($array as $key => $value) {
1695
				if(is_array($value)) {
1696
					// we gather all remaining arrays that have such key available
1697
					$args = array();
1698
					foreach($remains as $remain) {
1699
						if(array_key_exists($key, $remain)) {
1700
							array_push($args, $remain[$key]);
1701
						}
1702
					}
1703

    
1704
					if(count($args) > 2) {
1705
						// put the recursion
1706
						$result[$key] = call_user_func_array(__FUNCTION__, $args);
1707
					} else {
1708
						foreach($value as $vkey => $vval) {
1709
							$result[$key][$vkey] = $vval;
1710
						}
1711
					}
1712
				} else {
1713
					// simply put the value
1714
					$result[$key] = $value;
1715
				}
1716
			}
1717
		}
1718
	}
1719
	return $result;
1720
}
1721

    
1722

    
1723
/*
1724
 * converts a string like "a,b,c,d"
1725
 * into an array like array("a" => "b", "c" => "d")
1726
 */
1727
function explode_assoc($delimiter, $string) {
1728
	$array = explode($delimiter, $string);
1729
	$result = array();
1730
	$numkeys = floor(count($array) / 2);
1731
	for ($i = 0; $i < $numkeys; $i += 1) {
1732
		$result[$array[$i * 2]] = $array[$i * 2 + 1];
1733
	}
1734
	return $result;
1735
}
1736

    
1737
function get_staticroutes($returnsubnetsonly = false) {
1738
	global $config;
1739
	require_once('filter.inc');
1740
	$allstaticroutes = array();
1741
	$allsubnets = array();
1742

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

    
1747
	/* Loop through routes and expand aliases as we find them. */
1748
	foreach ($config['staticroutes']['route'] as $route) {
1749
		if (is_alias($route['network'])) {
1750
			$subnets = filter_expand_alias_array($route['network']);
1751
			foreach ($subnets as $net) {
1752
				if (is_ipaddr($net))
1753
					$net .= "/32";
1754
				/* This must be a hostname, we can't use it. */
1755
				if (!is_subnet($net))
1756
					continue;
1757
				$temproute = $route;
1758
				$temproute['network'] = $net;
1759
				$allstaticroutes[] = $temproute;
1760
				$allsubnets[] = $net;
1761
			}
1762
		} elseif (is_subnet($route['network'])) {
1763
			$allstaticroutes[] = $route;
1764
			$allsubnets[] = $route['network'];
1765
		}
1766
	}
1767
	if ($returnsubnetsonly) {
1768
		return $allsubnets;
1769
	} else {
1770
		return $allstaticroutes;
1771
	}
1772
}
1773

    
1774
/****f* util/get_alias_list
1775
 * NAME
1776
 *   get_alias_list - Provide a list of aliases.
1777
 * INPUTS
1778
 *   $type          - Optional, can be a string or array specifying what type(s) of aliases you need.
1779
 * RESULT
1780
 *   Array containing list of aliases.
1781
 *   If $type is unspecified, all aliases are returned.
1782
 *   If $type is a string, all aliases of the type specified in $type are returned.
1783
 *   If $type is an array, all aliases of any type specified in any element of $type are returned.
1784
 */
1785
function get_alias_list($type = null) {
1786
	global $config;
1787
	$result = array();
1788
	if ($config['aliases']['alias'] <> "" && is_array($config['aliases']['alias'])) {
1789
		foreach ($config['aliases']['alias'] as $alias) {
1790
			if ($type === null) {
1791
				$result[] = $alias['name'];
1792
			}
1793
			else if (is_array($type)) {
1794
				if (in_array($alias['type'], $type)) {
1795
					$result[] = $alias['name'];
1796
				}
1797
			}
1798
			else if ($type === $alias['type']) {
1799
				$result[] = $alias['name'];
1800
			}
1801
		}
1802
	}		
1803
	return $result;
1804
}
1805

    
1806
/* returns an array consisting of every element of $haystack that is not equal to $needle. */
1807
function array_exclude($needle, $haystack) {
1808
	$result = array();
1809
	if (is_array($haystack)) {
1810
		foreach ($haystack as $thing) {
1811
			if ($needle !== $thing) {
1812
				$result[] = $thing;
1813
			}
1814
		}
1815
	}
1816
	return $result;
1817
}
1818

    
1819
?>
(54-54/66)