Project

General

Profile

Download (41.5 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
	$fd = fsockopen($g['event_address']);
170
	if ($fd) {
171
		foreach ($cmds as $cmd) {
172
			fwrite($fd, $cmd);
173
			$resp = fread($fd, 4096);
174
			if ($resp != "OK\n")
175
				log_error("send_event: sent {$cmd} got {$resp}");
176
		}
177
		fclose($fd);
178
	}
179
}
180

    
181
function refcount_init($reference) {
182
	$shmid = @shmop_open($reference, "c", 0644, 10);
183
	@shmop_write($shmid, 0, 0);
184
	@shmop_close($shmid);
185
}
186

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

    
202
	return $shm_data;
203
}
204

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

    
221
	return $shm_data;
222
}
223

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

    
232
/* return the subnet address given a host address and a subnet bit count */
233
function gen_subnet($ipaddr, $bits) {
234
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
235
		return "";
236
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
237
}
238

    
239
/* return the subnet address given a host address and a subnet bit count */
240
function gen_subnetv6($ipaddr, $bits) {
241
	if (!is_ipaddrv6($ipaddr) || !is_numeric($bits))
242
		return "";
243

    
244
	$address = Net_IPv6::getNetmask($ipaddr, $bits);
245
	return $address;
246
}
247

    
248
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
249
function gen_subnet_max($ipaddr, $bits) {
250
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
251
		return "";
252

    
253
	return long2ip32(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
254
}
255

    
256
/* Generate end number for a given ipv6 subnet mask
257
 * no, it does not perform math */
258
function gen_subnetv6_max($ipaddr, $bits) {
259
	if(!is_ipaddrv6($ipaddr))
260
		return false;
261
	
262
	$subnetstart = gen_subnetv6($ipaddr, $bits);
263
	/* we should have a expanded full ipv6 subnet starting at 0.
264
	 * Now split those by the semicolon so we can do 16 bit math */
265
	$parts = explode(":", $subnetstart);
266
	if(count($parts) <> 8)
267
		return false;
268
	
269
	$result = array();
270
	/* set the itteration count properly */
271
	$bitsleft = $bits;
272
	$i = 0;
273
	foreach($parts as $part) {
274
		/* if we have more then 16 bits we just append the part to the result */
275
		if($bitsleft >= 16) {
276
			$result[$i] = $parts[$i];
277
			$bitsleft = $bitsleft - 16;
278
			$i++;
279
			continue;
280
		}
281
		/* if we have less then 16 bits we need to calculate the other bits */
282
		if(($bitsleft < 16) && ($bitsleft > 0)) {
283
			$result[$i] = dechex(pow(2, (16 - $bitsleft)) -1) ;
284
			$integer = pow(2, (16 - $bitsleft));
285
			$strlen = strlen($result[$i]);
286
			while($strlen < 4) {
287
				$result[$i] = 0 . $result[$i];
288
				$strlen++;
289
			}
290
			$bitsleft = 0;
291
			$i++;
292
			continue;
293
		}
294
		/* counter is zero, append quad F */
295
		if($bitsleft == 0) {
296
			$result[$i] = "ffff";
297
			$i++;
298
			continue;
299
		}
300
		$i++;
301
	}
302
	$subnet_end = implode(":", $result);
303
	return $subnet_end;
304
}
305

    
306
/* returns a subnet mask (long given a bit count) */
307
function gen_subnet_mask_long($bits) {
308
	$sm = 0;
309
	for ($i = 0; $i < $bits; $i++) {
310
		$sm >>= 1;
311
		$sm |= 0x80000000;
312
	}
313
	return $sm;
314
}
315

    
316
/* same as above but returns a string */
317
function gen_subnet_mask($bits) {
318
	return long2ip(gen_subnet_mask_long($bits));
319
}
320

    
321
/* Convert long int to IP address, truncating to 32-bits. */
322
function long2ip32($ip) {
323
	return long2ip($ip & 0xFFFFFFFF);
324
}
325

    
326
/* Convert IP address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. */
327
function ip2long32($ip) {
328
	return ( ip2long($ip) & 0xFFFFFFFF );
329
}
330

    
331
/* Convert IP address to unsigned long int. */
332
function ip2ulong($ip) {
333
	return sprintf("%u", ip2long32($ip));
334
}
335

    
336
/* Find out how many IPs are contained within a given IP range
337
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
338
 */
339
function ip_range_size($startip, $endip) {
340
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
341
		// Operate as unsigned long because otherwise it wouldn't work
342
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
343
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
344
	}
345
	return -1;
346
}
347

    
348
/* Find the smallest possible subnet mask which can contain a given number of IPs
349
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
350
 */
351
function find_smallest_cidr($number) {
352
	$smallest = 1;
353
	for ($b=32; $b > 0; $b--) {
354
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
355
	}
356
	return (32-$smallest);
357
}
358

    
359
/* Return the previous IP address before the given address */
360
function ip_before($ip) {
361
	return long2ip32(ip2long($ip)-1);
362
}
363

    
364
/* Return the next IP address after the given address */
365
function ip_after($ip) {
366
	return long2ip32(ip2long($ip)+1);
367
}
368

    
369
/* Return true if the first IP is 'before' the second */
370
function ip_less_than($ip1, $ip2) {
371
	// Compare as unsigned long because otherwise it wouldn't work when
372
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
373
	return ip2ulong($ip1) < ip2ulong($ip2);
374
}
375

    
376
/* Return true if the first IP is 'after' the second */
377
function ip_greater_than($ip1, $ip2) {
378
	// Compare as unsigned long because otherwise it wouldn't work
379
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
380
	return ip2ulong($ip1) > ip2ulong($ip2);
381
}
382

    
383
/* Convert a range of IPs to an array of subnets which can contain the range. */
384
function ip_range_to_subnet_array($startip, $endip) {
385
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
386
		return array();
387
	}
388

    
389
	// Container for subnets within this range.
390
	$rangesubnets = array();
391

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

    
395
	// Loop here to reduce subnet size and retest as needed. We need to make sure
396
	//   that the target subnet is wholly contained between $startip and $endip.
397
	for ($cidr; $cidr <= 32; $cidr++) {
398
		// Find the network and broadcast addresses for the subnet being tested.
399
		$targetsub_min = gen_subnet($startip, $cidr);
400
		$targetsub_max = gen_subnet_max($startip, $cidr);
401

    
402
		// Check best case where the range is exactly one subnet.
403
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
404
			// Hooray, the range is exactly this subnet!
405
			return array("{$startip}/{$cidr}");
406
		}
407

    
408
		// These remaining scenarios will find a subnet that uses the largest
409
		//  chunk possible of the range being tested, and leave the rest to be
410
		//  tested recursively after the loop.
411

    
412
		// Check if the subnet begins with $startip and ends before $endip
413
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
414
			break;
415
		}
416

    
417
		// Check if the subnet ends at $endip and starts after $startip
418
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
419
			break;
420
		}
421

    
422
		// Check if the subnet is between $startip and $endip
423
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
424
			break;
425
		}
426
	}
427

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

    
434
	// Add in the subnet we found before, to preserve ordering
435
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
436

    
437
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
438
	if ($endip != $targetsub_max) {
439
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
440
	}
441
	return $rangesubnets;
442
}
443

    
444
function is_iprange($range) {
445
	if (substr_count($range, '-') != 1) {
446
		return false;
447
	}
448
	list($ip1, $ip2) = explode ('-', $range);
449
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
450
}
451

    
452
function is_numericint($arg) {
453
	return (preg_match("/[^0-9]/", $arg) ? false : true);
454
}
455

    
456

    
457
/* returns true if $ipaddr is a valid dotted IPv4 address or a IPv6 */
458
function is_ipaddr($ipaddr) {
459
	if(is_ipaddrv4($ipaddr)) {
460
		return true;
461
	}
462
	if(is_ipaddrv6($ipaddr)) {
463
		return true;
464
	}
465
	return false;
466
}
467

    
468
/* returns true if $ipaddr is a valid IPv6 address */
469
function is_ipaddrv6($ipaddr) {
470
	$result = Net_IPv6::checkIPv6($ipaddr);
471
	return $result;
472
}
473

    
474
/* returns true if $ipaddr is a valid dotted IPv4 address */
475
function is_ipaddrv4($ipaddr) {
476
	if (!is_string($ipaddr))
477
		return false;
478

    
479
	$ip_long = ip2long($ipaddr);
480
	$ip_reverse = long2ip32($ip_long);
481

    
482
	if ($ipaddr == $ip_reverse)
483
		return true;
484
	else
485
		return false;
486
}
487

    
488
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
489
function is_ipaddroralias($ipaddr) {
490
	global $config;
491

    
492
	if (is_alias($ipaddr)) {
493
		if (is_array($config['aliases']['alias'])) {
494
			foreach ($config['aliases']['alias'] as $alias) {
495
				if ($alias['name'] == $ipaddr && $alias['type'] != "port")
496
					return true;
497
			}
498
		}
499
		return false;
500
	} else
501
		return is_ipaddr($ipaddr);
502

    
503
}
504

    
505
/* returns true if $subnet is a valid IPv4 or IPv6 subnet in CIDR format */
506
function is_subnet($subnet) {
507
	if(is_subnetv4($subnet)) {
508
		return true;
509
	}
510
	if(is_subnetv6($subnet)) {
511
		return true;
512
	}
513
	return false;
514
}
515

    
516
/* returns true if $subnet is a valid IPv4 subnet in CIDR format */
517
function is_subnetv4($subnet) {
518
	if (!is_string($subnet))
519
		return false;
520

    
521
	list($hp,$np) = explode('/', $subnet);
522

    
523
	if (!is_ipaddrv4($hp))
524
		return false;
525

    
526
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
527
		return false;
528

    
529
	return true;
530
}
531

    
532
/* returns true if $subnet is a valid IPv6 subnet in CIDR format */
533
function is_subnetv6($subnet) {
534
	if (!is_string($subnet))
535
		return false;
536

    
537
	list($hp,$np) = explode('/', $subnet);
538

    
539
	if (!is_ipaddrv6($hp))
540
		return false;
541

    
542
	if (!is_numeric($np) || ($np < 1) || ($np > 128))
543
		return false;
544

    
545
	return true;
546
}
547

    
548

    
549
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
550
function is_subnetoralias($subnet) {
551
	global $aliastable;
552

    
553
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
554
		return true;
555
	else
556
		return is_subnet($subnet);
557
}
558

    
559
/* returns true if $hostname is a valid hostname */
560
function is_hostname($hostname) {
561
	if (!is_string($hostname))
562
		return false;
563

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

    
570
/* returns true if $domain is a valid domain name */
571
function is_domain($domain) {
572
	if (!is_string($domain))
573
		return false;
574

    
575
	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))
576
		return true;
577
	else
578
		return false;
579
}
580

    
581
/* returns true if $macaddr is a valid MAC address */
582
function is_macaddr($macaddr) {
583
	return preg_match('/^[0-9A-F]{2}(?:[:][0-9A-F]{2}){5}$/i', $macaddr) == 1 ? true : false;
584
}
585

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

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

    
613
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
614
function is_portrange($portrange) {
615
	$ports = explode(":", $portrange);
616

    
617
	if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
618
		return true;
619
	else
620
		return false;
621
}
622

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

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

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

    
644
/* return the configured carp interface list */
645
function get_configured_carp_interface_list() {
646
	global $config;
647

    
648
	$iflist = array();
649

    
650
	if(is_array($config['virtualip']['vip'])) {
651
		$viparr = &$config['virtualip']['vip'];
652
		foreach ($viparr as $vip) {
653
			switch ($vip['mode']) {
654
				case "carp":
655
				case "carpdev-dhcp":
656
					$vipif = "vip" . $vip['vhid'];
657
					$iflist[$vipif] = $vip['subnet'];
658
					break;
659
			}
660
		}
661
	}
662

    
663
	return $iflist;
664
}
665

    
666
/* return the configured IP aliases list */
667
function get_configured_ip_aliases_list() {
668
	global $config;
669

    
670
	$alias_list=array();
671

    
672
	if(is_array($config['virtualip']['vip'])) {
673
		$viparr = &$config['virtualip']['vip'];
674
		foreach ($viparr as $vip) {
675
			if ($vip['mode']=="ipalias") {
676
				$alias_list[$vip['subnet']] = $vip['interface'];
677
			}
678
		}
679
	}
680

    
681
	return $alias_list;
682
}
683

    
684

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

    
698
	return strnatcmp($a, $b);
699
}
700

    
701
/* return the configured interfaces list. */
702
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
703
	global $config;
704

    
705
	$iflist = array();
706

    
707
	/* if list */
708
	foreach($config['interfaces'] as $if => $ifdetail) {
709
		if ($only_opt && ($if == "wan" || $if == "lan"))
710
			continue;
711
		if (isset($ifdetail['enable']) || $withdisabled == true)
712
			$iflist[$if] = $if;
713
	}
714

    
715
	return $iflist;
716
}
717

    
718
/* return the configured interfaces list. */
719
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
720
	global $config;
721

    
722
	$iflist = array();
723

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

    
735
	return $iflist;
736
}
737

    
738
/* return the configured interfaces list with their description. */
739
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
740
	global $config;
741

    
742
	$iflist = array();
743

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

    
756
	return $iflist;
757
}
758

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

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

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

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

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

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

    
964
/* wrapper for exec() */
965
function mwexec($command, $mute = false) {
966
	global $g;
967

    
968
	if ($g['debug']) {
969
		if (!$_SERVER['REMOTE_ADDR'])
970
			echo "mwexec(): $command\n";
971
	}
972
	$oarr = array();
973
	$retval = 0;
974
	$garbage = exec("$command 2>&1", $oarr, $retval);
975

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

    
985
/* wrapper for exec() in background */
986
function mwexec_bg($command) {
987
	global $g;
988

    
989
	if ($g['debug']) {
990
		if (!$_SERVER['REMOTE_ADDR'])
991
			echo "mwexec(): $command\n";
992
	}
993

    
994
	exec("nohup $command > /dev/null 2>&1 &");
995
}
996

    
997
/* unlink a file, if it exists */
998
function unlink_if_exists($fn) {
999
	$to_do = glob($fn);
1000
	if(is_array($to_do)) {
1001
		foreach($to_do as $filename)
1002
			@unlink($filename);
1003
	} else {
1004
		@unlink($fn);
1005
	}
1006
}
1007
/* make a global alias table (for faster lookups) */
1008
function alias_make_table($config) {
1009
	global $aliastable;
1010

    
1011
	$aliastable = array();
1012

    
1013
	if (is_array($config['aliases']['alias'])) {
1014
		foreach ($config['aliases']['alias'] as $alias) {
1015
			if ($alias['name'])
1016
				$aliastable[$alias['name']] = $alias['address'];
1017
		}
1018
	}
1019
}
1020

    
1021
/* check if an alias exists */
1022
function is_alias($name) {
1023
	global $aliastable;
1024

    
1025
	return isset($aliastable[$name]);
1026
}
1027

    
1028
function alias_get_type($name) {
1029
        global $config;
1030
        
1031
	if (is_array($config['aliases']['alias'])) {
1032
		foreach ($config['aliases']['alias'] as $alias) {
1033
			if ($name == $alias['name'])
1034
				return $alias['type'];
1035
		}
1036
	}
1037

    
1038
        return "";
1039
}
1040

    
1041
/* expand a host or network alias, if necessary */
1042
function alias_expand($name) {
1043
	global $aliastable;
1044

    
1045
	if (isset($aliastable[$name]))
1046
		return "\${$name}";
1047
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
1048
		return "{$name}";
1049
	else
1050
		return null;
1051
}
1052

    
1053
function alias_expand_urltable($name) {
1054
	global $config;
1055
	$urltable_prefix = "/var/db/aliastables/";
1056
	$urltable_filename = $urltable_prefix . $name . ".txt";
1057

    
1058
	if (is_array($config['aliases']['alias'])) {
1059
		foreach ($config['aliases']['alias'] as $alias) {
1060
			if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
1061
				if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
1062
					return $urltable_filename;
1063
				else if (process_alias_urltable($name, $alias["url"], 0, true))
1064
					return $urltable_filename;
1065
			}
1066
		}
1067
	}
1068
	return null;
1069
}
1070

    
1071
/* find out whether two subnets overlap */
1072
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
1073

    
1074
	if (!is_numeric($bits1))
1075
		$bits1 = 32;
1076
	if (!is_numeric($bits2))
1077
		$bits2 = 32;
1078

    
1079
	if ($bits1 < $bits2)
1080
		$relbits = $bits1;
1081
	else
1082
		$relbits = $bits2;
1083

    
1084
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
1085
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
1086

    
1087
	if ($sn1 == $sn2)
1088
		return true;
1089
	else
1090
		return false;
1091
}
1092

    
1093
/* compare two IP addresses */
1094
function ipcmp($a, $b) {
1095
	if (ip_less_than($a, $b))
1096
		return -1;
1097
	else if (ip_greater_than($a, $b))
1098
		return 1;
1099
	else
1100
		return 0;
1101
}
1102

    
1103
/* return true if $addr is in $subnet, false if not */
1104
function ip_in_subnet($addr,$subnet) {
1105
	if(is_ipaddrv6($addr)) {
1106
		$result = Net_IPv6::IsInNetmask($addr, $subnet);
1107
		if($result)
1108
			return true;
1109
		else
1110
			return false;
1111
	}
1112
	list($ip, $mask) = explode('/', $subnet);
1113
	$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
1114
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
1115
}
1116

    
1117
/* verify (and remove) the digital signature on a file - returns 0 if OK */
1118
function verify_digital_signature($fname) {
1119
	global $g;
1120

    
1121
	if(!file_exists("/usr/local/sbin/gzsig"))
1122
		return 4;
1123

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

    
1127
/* obtain MAC address given an IP address by looking at the ARP table */
1128
function arp_get_mac_by_ip($ip) {
1129
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
1130
	$arpoutput = "";
1131
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
1132

    
1133
	if ($arpoutput[0]) {
1134
		$arpi = explode(" ", $arpoutput[0]);
1135
		$macaddr = $arpi[3];
1136
		if (is_macaddr($macaddr))
1137
			return $macaddr;
1138
		else
1139
			return false;
1140
	}
1141

    
1142
	return false;
1143
}
1144

    
1145
/* return a fieldname that is safe for xml usage */
1146
function xml_safe_fieldname($fieldname) {
1147
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
1148
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
1149
			 ':', ',', '.', '\'', '\\'
1150
		);
1151
	return strtolower(str_replace($replace, "", $fieldname));
1152
}
1153

    
1154
function mac_format($clientmac) {
1155
    $mac =explode(":", $clientmac);
1156

    
1157
    global $config;
1158

    
1159
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
1160

    
1161
    switch($mac_format) {
1162

    
1163
        case 'singledash':
1164
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
1165

    
1166
        case 'ietf':
1167
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
1168

    
1169
        case 'cisco':
1170
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
1171

    
1172
        case 'unformatted':
1173
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
1174

    
1175
        default:
1176
        return $clientmac;
1177
    }
1178
}
1179

    
1180
function resolve_retry($hostname, $retries = 5) {
1181

    
1182
	if (is_ipaddr($hostname))
1183
		return $hostname;
1184

    
1185
       for ($i = 0; $i < $retries; $i++) {
1186
		// FIXME: gethostbyname does not work for AAAA hostnames, boo, hiss
1187
               $ip = gethostbyname($hostname);
1188

    
1189
		if ($ip && $ip != $hostname) {
1190
			/* success */
1191
			return $ip;
1192
		}
1193

    
1194
		sleep(1);
1195
	}
1196

    
1197
	return false;
1198
}
1199

    
1200
function format_bytes($bytes) {
1201
	if ($bytes >= 1073741824) {
1202
		return sprintf("%.2f GB", $bytes/1073741824);
1203
	} else if ($bytes >= 1048576) {
1204
		return sprintf("%.2f MB", $bytes/1048576);
1205
	} else if ($bytes >= 1024) {
1206
		return sprintf("%.0f KB", $bytes/1024);
1207
	} else {
1208
		return sprintf("%d bytes", $bytes);
1209
	}
1210
}
1211

    
1212
function update_filter_reload_status($text) {
1213
	global $g;
1214

    
1215
	file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1216
}
1217

    
1218
/****f* util/return_dir_as_array
1219
 * NAME
1220
 *   return_dir_as_array - Return a directory's contents as an array.
1221
 * INPUTS
1222
 *   $dir       - string containing the path to the desired directory.
1223
 * RESULT
1224
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1225
 ******/
1226
function return_dir_as_array($dir) {
1227
	$dir_array = array();
1228
	if (is_dir($dir)) {
1229
		if ($dh = opendir($dir)) {
1230
			while (($file = readdir($dh)) !== false) {
1231
				$canadd = 0;
1232
				if($file == ".") $canadd = 1;
1233
				if($file == "..") $canadd = 1;
1234
				if($canadd == 0)
1235
					array_push($dir_array, $file);
1236
			}
1237
			closedir($dh);
1238
		}
1239
	}
1240
	return $dir_array;
1241
}
1242

    
1243
function run_plugins($directory) {
1244
	global $config, $g;
1245

    
1246
	/* process packager manager custom rules */
1247
	$files = return_dir_as_array($directory);
1248
	if (is_array($files)) {
1249
		foreach ($files as $file) {
1250
			if (stristr($file, ".sh") == true)
1251
				mwexec($directory . $file . " start");
1252
			else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1253
				require_once($directory . "/" . $file);
1254
		}
1255
	}
1256
}
1257

    
1258
/*
1259
 *    safe_mkdir($path, $mode = 0755)
1260
 *    create directory if it doesn't already exist and isn't a file!
1261
 */
1262
function safe_mkdir($path, $mode=0755) {
1263
	global $g;
1264

    
1265
	if (!is_file($path) && !is_dir($path)) {
1266
		return @mkdir($path, $mode, true);
1267
	} else {
1268
		return false;
1269
	}
1270
}
1271

    
1272
/*
1273
 * make_dirs($path, $mode = 0755)
1274
 * create directory tree recursively (mkdir -p)
1275
 */
1276
function make_dirs($path, $mode = 0755) {
1277
	$base = '';
1278
	foreach (explode('/', $path) as $dir) {
1279
		$base .= "/$dir";
1280
		if (!is_dir($base)) {
1281
			if (!@mkdir($base, $mode))
1282
				return false;
1283
		}
1284
	}
1285
	return true;
1286
}
1287

    
1288
/*
1289
 * get_sysctl($names)
1290
 * Get values of sysctl OID's listed in $names (accepts an array or a single
1291
 * name) and return an array of key/value pairs set for those that exist
1292
 */
1293
function get_sysctl($names) {
1294
	if (empty($names))
1295
		return array();
1296

    
1297
	if (is_array($names)) {
1298
		$name_list = array();
1299
		foreach ($names as $name) {
1300
			$name_list[] = escapeshellarg($name);
1301
		}
1302
	} else
1303
		$name_list = array(escapeshellarg($names));
1304

    
1305
	exec("/sbin/sysctl -i " . implode(" ", $name_list), $output);
1306
	$values = array();
1307
	foreach ($output as $line) {
1308
		$line = explode(": ", $line, 2);
1309
		if (count($line) == 2)
1310
			$values[$line[0]] = $line[1];
1311
	}
1312

    
1313
	return $values;
1314
}
1315

    
1316
/*
1317
 * set_sysctl($value_list)
1318
 * Set sysctl OID's listed as key/value pairs and return
1319
 * an array with keys set for those that succeeded
1320
 */
1321
function set_sysctl($values) {
1322
	if (empty($values))
1323
		return array();
1324

    
1325
	$value_list = array();
1326
	foreach ($values as $key => $value) {
1327
		$value_list[] = escapeshellarg($key) . "=" . escapeshellarg($value);
1328
	}
1329

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

    
1332
	/* Retry individually if failed (one or more read-only) */
1333
	if ($success <> 0 && count($value_list) > 1) {
1334
		foreach ($value_list as $value) {
1335
			exec("/sbin/sysctl -i " . $value, $output);
1336
		}
1337
	}
1338

    
1339
	$ret = array();
1340
	foreach ($output as $line) {
1341
		$line = explode(": ", $line, 2);
1342
		if (count($line) == 2)
1343
			$ret[$line[0]] = true;
1344
	}
1345

    
1346
	return $ret;
1347
}
1348

    
1349
/*
1350
 *     get_memory()
1351
 *     returns an array listing the amount of
1352
 *     memory installed in the hardware
1353
 *     [0]real and [1]available
1354
 */
1355
function get_memory() {
1356
	$matches = "";
1357
	if(file_exists("/var/log/dmesg.boot"))
1358
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1359
	else
1360
		$mem = `dmesg -a | grep memory`;			
1361
	if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1362
		return array($matches[1][0], $matches[1][0]);
1363
	if(!$real && !$avail) {
1364
		$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1365
		$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1366
		/* convert from bytes to megabytes */
1367
		return array(($real/1048576),($avail/1048576));
1368
	}
1369
}
1370

    
1371
function mute_kernel_msgs() {
1372
	global $config;
1373
	// Do not mute serial console.  The kernel gets very very cranky
1374
	// and will start dishing you cannot control tty errors.
1375
	switch (trim(file_get_contents("/etc/platform"))) {
1376
		case "nanobsd":
1377
		case "jail":
1378
			return;
1379
	}
1380
	if($config['system']['enableserial']) 
1381
		return;			
1382
	exec("/sbin/conscontrol mute on");
1383
}
1384

    
1385
function unmute_kernel_msgs() {
1386
	global $config;
1387
	// Do not mute serial console.  The kernel gets very very cranky
1388
	// and will start dishing you cannot control tty errors.
1389
	switch (trim(file_get_contents("/etc/platform"))) {
1390
		case "nanobsd":
1391
		case "jail":
1392
			return;
1393
	}
1394
	exec("/sbin/conscontrol mute off");
1395
}
1396

    
1397
function start_devd() {
1398
	global $g;
1399

    
1400
	if ($g['platform'] == 'jail')
1401
		return;
1402
	exec("/sbin/devd");
1403
	sleep(1);
1404
}
1405

    
1406
function is_interface_vlan_mismatch() {
1407
	global $config, $g;
1408

    
1409
	if (is_array($config['vlans']['vlan'])) {
1410
		foreach ($config['vlans']['vlan'] as $vlan) {
1411
			if (does_interface_exist($vlan['if']) == false)
1412
				return true;
1413
		}
1414
	}
1415

    
1416
	return false;
1417
}
1418

    
1419
function is_interface_mismatch() {
1420
	global $config, $g;
1421

    
1422
	$do_assign = false;
1423
	$i = 0;
1424
	if (is_array($config['interfaces'])) {
1425
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
1426
			if (preg_match("/^enc|^cua|^tun|^l2tp|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1427
				// Do not check these interfaces.
1428
				$i++;
1429
				continue;
1430
			}
1431
			else if (does_interface_exist($ifcfg['if']) == false) {
1432
				$do_assign = true;
1433
			} else
1434
				$i++;
1435
		}
1436
	}
1437

    
1438
	if ($g['minimum_nic_count'] > $i) {
1439
		$do_assign = true;
1440
	} else if (file_exists("{$g['tmp_path']}/assign_complete"))
1441
	$do_assign = false;
1442

    
1443
	return $do_assign;
1444
}
1445

    
1446
/* sync carp entries to other firewalls */
1447
function carp_sync_client() {
1448
	global $g;
1449
	send_event("filter sync");
1450
}
1451

    
1452
/****f* util/isAjax
1453
 * NAME
1454
 *   isAjax - reports if the request is driven from prototype
1455
 * INPUTS
1456
 *   none
1457
 * RESULT
1458
 *   true/false
1459
 ******/
1460
function isAjax() {
1461
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1462
}
1463

    
1464
/****f* util/timeout
1465
 * NAME
1466
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1467
 * INPUTS
1468
 *   optional, seconds to wait before timeout. Default 9 seconds.
1469
 * RESULT
1470
 *   returns 1 char of user input or null if no input.
1471
 ******/
1472
function timeout($timer = 9) {
1473
	while(!isset($key)) {
1474
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1475
		else { echo chr(8). "{$timer}"; }
1476
		`/bin/stty -icanon min 0 time 25`;
1477
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1478
		`/bin/stty icanon`;
1479
		if ($key == '')
1480
			unset($key);
1481
		$timer--;
1482
		if ($timer == 0)
1483
			break;
1484
	}
1485
	return $key;	
1486
}
1487

    
1488
/****f* util/msort
1489
 * NAME
1490
 *   msort - sort array
1491
 * INPUTS
1492
 *   $array to be sorted, field to sort by, direction of sort
1493
 * RESULT
1494
 *   returns newly sorted array
1495
 ******/
1496
function msort($array, $id="id", $sort_ascending=true) {
1497
	$temp_array = array();
1498
	while(count($array)>0) {
1499
		$lowest_id = 0;
1500
		$index=0;
1501
		foreach ($array as $item) {
1502
			if (isset($item[$id])) {
1503
				if ($array[$lowest_id][$id]) {
1504
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1505
						$lowest_id = $index;
1506
					}
1507
				}
1508
			}
1509
			$index++;
1510
		}
1511
		$temp_array[] = $array[$lowest_id];
1512
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1513
	}
1514
	if ($sort_ascending) {
1515
		return $temp_array;
1516
	} else {
1517
    	return array_reverse($temp_array);
1518
	}
1519
}
1520

    
1521
/****f* util/color
1522
 * NAME
1523
 *   color - outputs a color code to the ansi terminal if supported
1524
 * INPUTS
1525
 *   color code or color name
1526
 * RESULT
1527
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1528
 ******/
1529
function color($color = "0m") {
1530
	/*
1531
		Color codes available:
1532
		 0m reset; clears all colors and styles (to white on black)
1533
		 1m bold on (see below)
1534
		 3m italics on
1535
		 4m underline on
1536
		 7m inverse on; reverses foreground & background colors
1537
		 9m strikethrough on
1538
		 22m bold off (see below)
1539
		 23m italics off
1540
		 24m underline off
1541
		 27m inverse off
1542
		 29m strikethrough off
1543
		 30m set foreground color to black
1544
		 31m set foreground color to red
1545
		 32m set foreground color to green
1546
		 33m set foreground color to yellow
1547
		 34m set foreground color to blue
1548
		 35m set foreground color to magenta (purple)
1549
		 36m set foreground color to cyan
1550
		 37m set foreground color to white
1551
		 40m  set background color to black
1552
		 41m set background color to red
1553
		 42m set background color to green
1554
		 43m set background color to yellow
1555
		 44m set background color to blue
1556
		 45m set background color to magenta (purple)
1557
		 46m set background color to cyan
1558
		 47m set background color to white
1559
		 49m set background color to default (black)
1560
	*/	
1561
	// Allow caching of TERM to 
1562
	// speedup subequence requests.
1563
	global $TERM;
1564
	if(!$TERM) 
1565
		$TERM=`/usr/bin/env | grep color`;
1566
	if(!$TERM)
1567
		$TERM=`/usr/bin/env | grep cons25`;
1568
	if($TERM) {
1569
		$ESCAPE=chr(27);
1570
		switch ($color) {
1571
			case "black":
1572
				return "{$ESCAPE}[30m"; 
1573
			case "red":
1574
				return "{$ESCAPE}[31m"; 
1575
			case "green":
1576
				return "{$ESCAPE}[32m"; 
1577
			case "yellow":
1578
				return "{$ESCAPE}[33m"; 
1579
			case "blue":
1580
				return "{$ESCAPE}[34m"; 
1581
			case "magenta":
1582
				return "{$ESCAPE}[35m"; 
1583
			case "cyan":
1584
				return "{$ESCAPE}[36m"; 
1585
			case "white":
1586
				return "{$ESCAPE}[37m"; 
1587
			case "default":
1588
				return "{$ESCAPE}[39m"; 
1589
		}
1590
		return "{$ESCAPE}[{$color}";
1591
	}
1592
}
1593

    
1594
/****f* util/is_URL
1595
 * NAME
1596
 *   is_URL
1597
 * INPUTS
1598
 *   string to check
1599
 * RESULT
1600
 *   Returns true if item is a URL
1601
 ******/
1602
function is_URL($url) {
1603
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1604
	if($match)
1605
		return true;	
1606
	return false;
1607
}
1608

    
1609
function is_file_included($file = "") {
1610
	$files = get_included_files();
1611
	if (in_array($file, $files))
1612
		return true;
1613
	
1614
	return false;
1615
}
1616

    
1617
/*
1618
	This function was borrowed from a comment on PHP.net at the following URL:
1619
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
1620
 */
1621
function array_merge_recursive_unique($array0, $array1) {
1622

    
1623
	$arrays = func_get_args();
1624
	$remains = $arrays;
1625

    
1626
	// We walk through each arrays and put value in the results (without
1627
	// considering previous value).
1628
	$result = array();
1629

    
1630
	// loop available array
1631
	foreach($arrays as $array) {
1632

    
1633
		// The first remaining array is $array. We are processing it. So
1634
		// we remove it from remaing arrays.
1635
        array_shift($remains);
1636

    
1637
		// We don't care non array param, like array_merge since PHP 5.0.
1638
		if(is_array($array)) {
1639
			// Loop values
1640
			foreach($array as $key => $value) {
1641
				if(is_array($value)) {
1642
					// we gather all remaining arrays that have such key available
1643
					$args = array();
1644
					foreach($remains as $remain) {
1645
						if(array_key_exists($key, $remain)) {
1646
							array_push($args, $remain[$key]);
1647
						}
1648
					}
1649

    
1650
					if(count($args) > 2) {
1651
						// put the recursion
1652
						$result[$key] = call_user_func_array(__FUNCTION__, $args);
1653
					} else {
1654
						foreach($value as $vkey => $vval) {
1655
							$result[$key][$vkey] = $vval;
1656
						}
1657
					}
1658
				} else {
1659
					// simply put the value
1660
					$result[$key] = $value;
1661
				}
1662
			}
1663
		}
1664
	}
1665
	return $result;
1666
}
1667

    
1668
?>
(52-52/64)