Project

General

Profile

Download (49.9 KB) Statistics
| Branch: | Tag: | Revision:
1 86a5e1a8 Renato Botelho
<?php
2 417fc5c4 Scott Ullrich
/*
3 5b237745 Scott Ullrich
	util.inc
4 417fc5c4 Scott Ullrich
	part of the pfSense project (http://www.pfsense.com)
5 98bbf05a Scott Ullrich
6 417fc5c4 Scott Ullrich
	originally part of m0n0wall (http://m0n0.ch/wall)
7 5b237745 Scott Ullrich
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9 98bbf05a Scott Ullrich
10 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12 98bbf05a Scott Ullrich
13 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15 98bbf05a Scott Ullrich
16 5b237745 Scott Ullrich
	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 98bbf05a Scott Ullrich
20 5b237745 Scott Ullrich
	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 523855b0 Scott Ullrich
/*
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 5b237745 Scott Ullrich
/* kill a process by pid file */
40
function killbypid($pidfile) {
41 435a418f Ermal
	return sigkillbypid($pidfile, "TERM");
42 5b237745 Scott Ullrich
}
43
44 c4594e36 Phil Davis
function isvalidpid($pidfile) {
45 0e604b3a Ermal
	$output = "";
46 c4594e36 Phil Davis
	if (file_exists($pidfile)) {
47
		exec("/bin/pgrep -nF {$pidfile}", $output, $retval);
48
		return (intval($retval) == 0);
49
	}
50
	return false;
51 53aca1fd Scott Ullrich
}
52
53 6dc3a5c2 Ermal Lu?i
function is_process_running($process) {
54 01d4b621 Ermal
	$output = "";
55 1dd8c3b6 Ermal
	exec("/bin/pgrep -anx {$process}", $output, $retval);
56 6dc3a5c2 Ermal Lu?i
57 5bbd08e1 Warren Baker
	return (intval($retval) == 0);
58 6dc3a5c2 Ermal Lu?i
}
59
60 53aca1fd Scott Ullrich
function isvalidproc($proc) {
61 ba8495f0 Ermal
	return is_process_running($proc);
62 53aca1fd Scott Ullrich
}
63
64 5b237745 Scott Ullrich
/* sigkill a process by pid file */
65 53aca1fd Scott Ullrich
/* return 1 for success and 0 for a failure */
66 5b237745 Scott Ullrich
function sigkillbypid($pidfile, $sig) {
67 ac94ebd8 Ermal
	if (file_exists($pidfile))
68 ba8495f0 Ermal
		return mwexec("/bin/pkill -{$sig} -F {$pidfile}", true);
69
70 53aca1fd Scott Ullrich
	return 0;
71
}
72
73
/* kill a process by name */
74
function sigkillbyname($procname, $sig) {
75
	if(isvalidproc($procname))
76 73239086 Seth Mos
		return mwexec("/usr/bin/killall -{$sig} " . escapeshellarg($procname), true);
77 5b237745 Scott Ullrich
}
78
79
/* kill a process by name */
80
function killbyname($procname) {
81 86a5e1a8 Renato Botelho
	if(isvalidproc($procname))
82 53aca1fd Scott Ullrich
		mwexec("/usr/bin/killall " . escapeshellarg($procname));
83 5b237745 Scott Ullrich
}
84
85 a368a026 Ermal Lu?i
function is_subsystem_dirty($subsystem = "") {
86
	global $g;
87
88
	if ($subsystem == "")
89
		return false;
90
91
	if (file_exists("{$g['varrun_path']}/{$subsystem}.dirty"))
92
		return true;
93
94
	return false;
95
}
96
97
function mark_subsystem_dirty($subsystem = "") {
98
	global $g;
99
100
	if (!file_put_contents("{$g['varrun_path']}/{$subsystem}.dirty", "DIRTY"))
101 fd7b47b6 Renato Botelho
		log_error(sprintf(gettext("WARNING: Could not mark subsystem: %s dirty"), $subsystem));
102 a368a026 Ermal Lu?i
}
103
104
function clear_subsystem_dirty($subsystem = "") {
105
	global $g;
106
107
	@unlink("{$g['varrun_path']}/{$subsystem}.dirty");
108
}
109
110 0027de0a Ermal Lu?i
function config_lock() {
111
	return;
112
}
113
function config_unlock() {
114
	return;
115
}
116
117
/* lock configuration file */
118 b6c34bfc Ermal
function lock($lock, $op = LOCK_SH) {
119 9e7ef1a5 Scott Ullrich
	global $g, $cfglckkeyconsumers;
120
	if (!$lock)
121 fd7b47b6 Renato Botelho
		die(gettext("WARNING: You must give a name as parameter to lock() function."));
122 6bee76d5 Ermal
	if (!file_exists("{$g['tmp_path']}/{$lock}.lock")) {
123 9e7ef1a5 Scott Ullrich
		@touch("{$g['tmp_path']}/{$lock}.lock");
124 6bee76d5 Ermal
		@chmod("{$g['tmp_path']}/{$lock}.lock", 0666);
125
	}
126 9e7ef1a5 Scott Ullrich
	$cfglckkeyconsumers++;
127 b6c34bfc Ermal
	if ($fp = fopen("{$g['tmp_path']}/{$lock}.lock", "w")) {
128
		if (flock($fp, $op))
129 9e7ef1a5 Scott Ullrich
			return $fp;
130 b6c34bfc Ermal
		else
131
			fclose($fp);
132 9e7ef1a5 Scott Ullrich
	}
133 0027de0a Ermal Lu?i
}
134
135
/* unlock configuration file */
136
function unlock($cfglckkey = 0) {
137 9e7ef1a5 Scott Ullrich
	global $g, $cfglckkeyconsumers;
138
	flock($cfglckkey, LOCK_UN);
139 cb6fd90b Ermal Lu?i
	fclose($cfglckkey);
140 9e7ef1a5 Scott Ullrich
	return;
141 0027de0a Ermal Lu?i
}
142
143 0ae6daf8 Ermal
function send_event($cmd) {
144
	global $g;
145
146 1015b3a9 Warren Baker
	if(!isset($g['event_address']))
147
		$g['event_address'] = "unix:///var/run/check_reload_status";
148 86a5e1a8 Renato Botelho
149 838feb14 Ermal
	$try = 0;
150
	while ($try < 3) {
151
		$fd = @fsockopen($g['event_address']);
152
		if ($fd) {
153
			fwrite($fd, $cmd);
154
			$resp = fread($fd, 4096);
155
			if ($resp != "OK\n")
156
				log_error("send_event: sent {$cmd} got {$resp}");
157
			fclose($fd);
158
			$try = 3;
159 915089b7 Ermal
		} else if (!is_process_running("check_reload_status"))
160 838feb14 Ermal
			mwexec_bg("/usr/bin/nice -n20 /usr/local/sbin/check_reload_status");
161
		$try++;
162 0ae6daf8 Ermal
	}
163
}
164
165
function send_multiple_events($cmds) {
166 1015b3a9 Warren Baker
	global $g;
167 0ae6daf8 Ermal
168 1015b3a9 Warren Baker
	if(!isset($g['event_address']))
169
		$g['event_address'] = "unix:///var/run/check_reload_status";
170 86a5e1a8 Renato Botelho
171 0ae6daf8 Ermal
	if (!is_array($cmds))
172
		return;
173 6e1f456f Ermal
174 915089b7 Ermal
	while ($try < 3) {
175
		$fd = @fsockopen($g['event_address']);
176
		if ($fd) {
177
			foreach ($cmds as $cmd) {
178
				fwrite($fd, $cmd);
179
				$resp = fread($fd, 4096);
180
				if ($resp != "OK\n")
181
					log_error("send_event: sent {$cmd} got {$resp}");
182
			}
183
			fclose($fd);
184
			$try = 3;
185
		} else if (!is_process_running("check_reload_status"))
186
			mwexec_bg("/usr/bin/nice -n20 /usr/local/sbin/check_reload_status");
187
		$try++;
188
	}
189 0ae6daf8 Ermal
}
190
191 ef3af02e Ermal Lu?i
function refcount_init($reference) {
192 eb295a1b Ermal
	$shmid = @shmop_open($reference, "c", 0644, 10);
193
	@shmop_write($shmid, str_pad("0", 10, "\x0", STR_PAD_RIGHT), 0);
194
	@shmop_close($shmid);
195 ef3af02e Ermal Lu?i
}
196
197
function refcount_reference($reference) {
198 eb295a1b Ermal
	/* Take out a lock across the shared memory read, increment, write sequence to make it atomic. */
199
	$shm_lck = lock("shm{$reference}", LOCK_EX);
200 e15e9c6b Ermal
	try {
201 eb295a1b Ermal
		/* NOTE: A warning is generated when shared memory does not exist */
202 7074a89a Phil Davis
		$shmid = @shmop_open($reference, "w", 0, 0);
203 e15e9c6b Ermal
		if (!$shmid) {
204
			refcount_init($reference);
205 eb295a1b Ermal
			$shmid = @shmop_open($reference, "w", 0, 0);
206
			if (!$shmid) {
207
				log_error(gettext("Could not open shared memory {$reference}"));
208 712eb769 Ermal
				unlock($shm_lck);
209 eb295a1b Ermal
				return;
210
			}
211 e15e9c6b Ermal
		}
212 eb295a1b Ermal
		$shm_data = @shmop_read($shmid, 0, 10);
213 7074a89a Phil Davis
		$shm_data = intval($shm_data) + 1;
214 eb295a1b Ermal
		@shmop_write($shmid, str_pad($shm_data, 10, "\x0", STR_PAD_RIGHT), 0);
215
		@shmop_close($shmid);
216 7074a89a Phil Davis
		unlock($shm_lck);
217 e15e9c6b Ermal
	} catch (Exception $e) {
218
		log_error($e->getMessage());
219 eb295a1b Ermal
		unlock($shm_lck);
220 a45e27ba Ermal
	}
221 e15e9c6b Ermal
222 ef3af02e Ermal Lu?i
	return $shm_data;
223
}
224
225
function refcount_unreference($reference) {
226 eb295a1b Ermal
	/* Take out a lock across the shared memory read, decrement, write sequence to make it atomic. */
227
	$shm_lck = lock("shm{$reference}", LOCK_EX);
228 e15e9c6b Ermal
	try {
229
		$shmid = @shmop_open($reference, "w", 0, 0);
230 eb295a1b Ermal
		if (!$shmid) {
231
			refcount_init($reference);
232
			log_error(gettext("Could not open shared memory {$reference}"));
233 712eb769 Ermal
			unlock($shm_lck);
234 eb295a1b Ermal
			return;
235
		}
236
		$shm_data = @shmop_read($shmid, 0, 10);
237 780705e9 jim-p
		$shm_data = intval($shm_data) - 1;
238 e15e9c6b Ermal
		if ($shm_data < 0) {
239
			//debug_backtrace();
240
			log_error(sprintf(gettext("Reference %s is going negative, not doing unreference."), $reference));
241
		} else
242 eb295a1b Ermal
			@shmop_write($shmid, str_pad($shm_data, 10, "\x0", STR_PAD_RIGHT), 0);
243
		@shmop_close($shmid);
244 7074a89a Phil Davis
		unlock($shm_lck);
245 e15e9c6b Ermal
	} catch (Exception $e) {
246
		log_error($e->getMessage());
247 eb295a1b Ermal
		unlock($shm_lck);
248 e15e9c6b Ermal
	}
249
250 f2f0a748 Ermal Lu?i
	return $shm_data;
251 96cecadb Phil Davis
}
252
253
function refcount_read($reference) {
254
	/* This function just reads the current value of the refcount for information. */
255
	/* There is no need for locking. */
256
	$shmid = @shmop_open($reference, "a", 0, 0);
257
	if (!$shmid) {
258
		log_error(gettext("Could not open shared memory for read {$reference}"));
259
		return -1;
260
	}
261
	$shm_data = @shmop_read($shmid, 0, 10);
262
	@shmop_close($shmid);
263
	return $shm_data;
264 ef3af02e Ermal Lu?i
}
265
266 1ab56363 Ermal Lu?i
function is_module_loaded($module_name) {
267 de5de07c Ermal Lu?i
	$running = `/sbin/kldstat | grep {$module_name} | /usr/bin/grep -v grep | /usr/bin/wc -l`;
268 1ab56363 Ermal Lu?i
	if (intval($running) >= 1)
269
		return true;
270
	else
271
		return false;
272
}
273
274 5b237745 Scott Ullrich
/* return the subnet address given a host address and a subnet bit count */
275
function gen_subnet($ipaddr, $bits) {
276 22b5abac Seth Mos
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
277
		return "";
278
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
279
}
280
281
/* return the subnet address given a host address and a subnet bit count */
282
function gen_subnetv6($ipaddr, $bits) {
283
	if (!is_ipaddrv6($ipaddr) || !is_numeric($bits))
284
		return "";
285 cf6bc278 Seth Mos
286
	$address = Net_IPv6::getNetmask($ipaddr, $bits);
287 88cc00db Ermal
	$address = Net_IPv6::compress($address);
288 cf6bc278 Seth Mos
	return $address;
289 5b237745 Scott Ullrich
}
290
291
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
292
function gen_subnet_max($ipaddr, $bits) {
293
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
294
		return "";
295 98bbf05a Scott Ullrich
296 96033063 Erik Fonnesbeck
	return long2ip32(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
297 5b237745 Scott Ullrich
}
298
299 47335ae3 Pierre POMES
/* Generate end number for a given ipv6 subnet mask */
300 c75a8185 Seth Mos
function gen_subnetv6_max($ipaddr, $bits) {
301
	if(!is_ipaddrv6($ipaddr))
302
		return false;
303 86a5e1a8 Renato Botelho
304 47335ae3 Pierre POMES
	$mask = Net_IPv6::getNetmask('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',$bits);
305 86a5e1a8 Renato Botelho
306 47335ae3 Pierre POMES
	$inet_ip = (binary)inet_pton($ipaddr);
307
	$inet_mask = (binary)inet_pton($mask);
308
309
	$inet_end = $inet_ip | ~$inet_mask;
310
311 88cc00db Ermal
	return (inet_ntop($inet_end));
312 c75a8185 Seth Mos
}
313
314 5b237745 Scott Ullrich
/* returns a subnet mask (long given a bit count) */
315
function gen_subnet_mask_long($bits) {
316
	$sm = 0;
317
	for ($i = 0; $i < $bits; $i++) {
318
		$sm >>= 1;
319
		$sm |= 0x80000000;
320
	}
321
	return $sm;
322
}
323
324
/* same as above but returns a string */
325
function gen_subnet_mask($bits) {
326
	return long2ip(gen_subnet_mask_long($bits));
327
}
328
329 96033063 Erik Fonnesbeck
/* Convert long int to IP address, truncating to 32-bits. */
330
function long2ip32($ip) {
331
	return long2ip($ip & 0xFFFFFFFF);
332
}
333
334
/* Convert IP address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. */
335
function ip2long32($ip) {
336
	return ( ip2long($ip) & 0xFFFFFFFF );
337
}
338
339 ecd1f2d9 jim-p
/* Convert IP address to unsigned long int. */
340
function ip2ulong($ip) {
341 96033063 Erik Fonnesbeck
	return sprintf("%u", ip2long32($ip));
342 ecd1f2d9 jim-p
}
343
344
/* Find out how many IPs are contained within a given IP range
345
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
346
 */
347
function ip_range_size($startip, $endip) {
348
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
349
		// Operate as unsigned long because otherwise it wouldn't work
350
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
351
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
352
	}
353
	return -1;
354
}
355
356
/* Find the smallest possible subnet mask which can contain a given number of IPs
357
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
358
 */
359
function find_smallest_cidr($number) {
360
	$smallest = 1;
361
	for ($b=32; $b > 0; $b--) {
362
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
363
	}
364
	return (32-$smallest);
365
}
366
367
/* Return the previous IP address before the given address */
368
function ip_before($ip) {
369 96033063 Erik Fonnesbeck
	return long2ip32(ip2long($ip)-1);
370 ecd1f2d9 jim-p
}
371
372
/* Return the next IP address after the given address */
373
function ip_after($ip) {
374 96033063 Erik Fonnesbeck
	return long2ip32(ip2long($ip)+1);
375 ecd1f2d9 jim-p
}
376
377
/* Return true if the first IP is 'before' the second */
378
function ip_less_than($ip1, $ip2) {
379
	// Compare as unsigned long because otherwise it wouldn't work when
380
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
381
	return ip2ulong($ip1) < ip2ulong($ip2);
382
}
383
384
/* Return true if the first IP is 'after' the second */
385
function ip_greater_than($ip1, $ip2) {
386
	// Compare as unsigned long because otherwise it wouldn't work
387
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
388
	return ip2ulong($ip1) > ip2ulong($ip2);
389
}
390
391
/* Convert a range of IPs to an array of subnets which can contain the range. */
392
function ip_range_to_subnet_array($startip, $endip) {
393
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
394
		return array();
395
	}
396
397
	// Container for subnets within this range.
398
	$rangesubnets = array();
399
400
	// Figure out what the smallest subnet is that holds the number of IPs in the given range.
401
	$cidr = find_smallest_cidr(ip_range_size($startip, $endip));
402
403
	// Loop here to reduce subnet size and retest as needed. We need to make sure
404
	//   that the target subnet is wholly contained between $startip and $endip.
405
	for ($cidr; $cidr <= 32; $cidr++) {
406
		// Find the network and broadcast addresses for the subnet being tested.
407
		$targetsub_min = gen_subnet($startip, $cidr);
408
		$targetsub_max = gen_subnet_max($startip, $cidr);
409
410
		// Check best case where the range is exactly one subnet.
411
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
412
			// Hooray, the range is exactly this subnet!
413
			return array("{$startip}/{$cidr}");
414
		}
415
416
		// These remaining scenarios will find a subnet that uses the largest
417
		//  chunk possible of the range being tested, and leave the rest to be
418
		//  tested recursively after the loop.
419
420
		// Check if the subnet begins with $startip and ends before $endip
421
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
422
			break;
423
		}
424
425
		// Check if the subnet ends at $endip and starts after $startip
426
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
427
			break;
428
		}
429
430
		// Check if the subnet is between $startip and $endip
431
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
432
			break;
433
		}
434
	}
435
436
	// Some logic that will recursivly search from $startip to the first IP before the start of the subnet we just found.
437
	// NOTE: This may never be hit, the way the above algo turned out, but is left for completeness.
438
	if ($startip != $targetsub_min) {
439
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array($startip, ip_before($targetsub_min)));
440
	}
441
442
	// Add in the subnet we found before, to preserve ordering
443
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
444
445
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
446
	if ($endip != $targetsub_max) {
447
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
448
	}
449
	return $rangesubnets;
450
}
451
452
function is_iprange($range) {
453
	if (substr_count($range, '-') != 1) {
454
		return false;
455
	}
456
	list($ip1, $ip2) = explode ('-', $range);
457
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
458
}
459
460 5b237745 Scott Ullrich
function is_numericint($arg) {
461
	return (preg_match("/[^0-9]/", $arg) ? false : true);
462
}
463
464 47593ac6 Seth Mos
465
/* returns true if $ipaddr is a valid dotted IPv4 address or a IPv6 */
466 5b237745 Scott Ullrich
function is_ipaddr($ipaddr) {
467 47593ac6 Seth Mos
	if(is_ipaddrv4($ipaddr)) {
468
		return true;
469
	}
470
	if(is_ipaddrv6($ipaddr)) {
471
		return true;
472
	}
473
	return false;
474
}
475
476 22b5abac Seth Mos
/* returns true if $ipaddr is a valid IPv6 address */
477 47593ac6 Seth Mos
function is_ipaddrv6($ipaddr) {
478 b5b5bcc0 Ermal
	if (!is_string($ipaddr) || empty($ipaddr))
479
		return false;
480 1e5da31d Ermal
	return Net_IPv6::checkIPv6($ipaddr);
481 47593ac6 Seth Mos
}
482
483
/* returns true if $ipaddr is a valid dotted IPv4 address */
484
function is_ipaddrv4($ipaddr) {
485 b5b5bcc0 Ermal
	if (!is_string($ipaddr) || empty($ipaddr))
486 5b237745 Scott Ullrich
		return false;
487 98bbf05a Scott Ullrich
488 5b237745 Scott Ullrich
	$ip_long = ip2long($ipaddr);
489 96033063 Erik Fonnesbeck
	$ip_reverse = long2ip32($ip_long);
490 98bbf05a Scott Ullrich
491 5b237745 Scott Ullrich
	if ($ipaddr == $ip_reverse)
492
		return true;
493
	else
494
		return false;
495
}
496
497 19341491 Renato Botelho
/* returns true if $ipaddr is a valid linklocal address */
498
function is_linklocal($ipaddr) {
499
	return preg_match('/^fe80:/i', $ipaddr);
500
}
501 3f5f7ad3 smos
502
/* returns true if $ipaddr is a valid literal IPv6 address */
503
function is_literalipaddrv6($ipaddr) {
504
	if(preg_match("/\[([0-9a-f:]+)\]/i", $ipaddr, $match))
505
		$ipaddr = $match[1];
506
	else
507
		return false;
508
509
	return is_ipaddrv6($ipaddr);
510
}
511
512 4a8a90ff jim-p
function is_ipaddrwithport($ipport) {
513
	$parts = explode(":", $ipport);
514
	$port = array_pop($parts);
515
	if (count($parts) == 1) {
516
		return is_ipaddrv4($parts[0]) && is_port($port);
517
	} elseif (count($parts) > 1) {
518 3f5f7ad3 smos
		return is_literalipaddrv6(implode(":", $parts)) && is_port($port);
519 4a8a90ff jim-p
	} else {
520
		return false;
521
	}
522
}
523
524 d3a2337a jim-p
function is_hostnamewithport($hostport) {
525
	$parts = explode(":", $hostport);
526
	$port = array_pop($parts);
527
	if (count($parts) == 1) {
528
		return is_hostname($parts[0]) && is_port($port);
529
	} else {
530
		return false;
531
	}
532
}
533
534 87f0be87 Chris Buechler
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
535 5b237745 Scott Ullrich
function is_ipaddroralias($ipaddr) {
536 1e578a7f Ermal Lu?i
	global $config;
537 87f0be87 Chris Buechler
538 1e578a7f Ermal Lu?i
	if (is_alias($ipaddr)) {
539
		if (is_array($config['aliases']['alias'])) {
540
			foreach ($config['aliases']['alias'] as $alias) {
541 5bbd08e1 Warren Baker
				if ($alias['name'] == $ipaddr && $alias['type'] != "port")
542 1e578a7f Ermal Lu?i
					return true;
543
			}
544 5bbd08e1 Warren Baker
		}
545 1e578a7f Ermal Lu?i
		return false;
546
	} else
547 87f0be87 Chris Buechler
		return is_ipaddr($ipaddr);
548
549 5b237745 Scott Ullrich
}
550
551 b1b42a06 Warren Baker
/* returns true if $subnet is a valid IPv4 or IPv6 subnet in CIDR format */
552 5b237745 Scott Ullrich
function is_subnet($subnet) {
553 b1b42a06 Warren Baker
	if(is_subnetv4($subnet)) {
554
		return true;
555
	}
556
	if(is_subnetv6($subnet)) {
557
		return true;
558
	}
559
	return false;
560
}
561
562
/* returns true if $subnet is a valid IPv4 subnet in CIDR format */
563
function is_subnetv4($subnet) {
564 5b237745 Scott Ullrich
	if (!is_string($subnet))
565
		return false;
566 98bbf05a Scott Ullrich
567 5b237745 Scott Ullrich
	list($hp,$np) = explode('/', $subnet);
568 98bbf05a Scott Ullrich
569 fdb9c1db Warren Baker
	if (!is_ipaddrv4($hp))
570 5b237745 Scott Ullrich
		return false;
571 98bbf05a Scott Ullrich
572 5b237745 Scott Ullrich
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
573
		return false;
574 98bbf05a Scott Ullrich
575 5b237745 Scott Ullrich
	return true;
576
}
577
578 fdb9c1db Warren Baker
/* returns true if $subnet is a valid IPv6 subnet in CIDR format */
579
function is_subnetv6($subnet) {
580
	if (!is_string($subnet))
581
		return false;
582
583
	list($hp,$np) = explode('/', $subnet);
584
585
	if (!is_ipaddrv6($hp))
586
		return false;
587
588
	if (!is_numeric($np) || ($np < 1) || ($np > 128))
589
		return false;
590
591
	return true;
592
}
593
594
595 5b237745 Scott Ullrich
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
596
function is_subnetoralias($subnet) {
597
	global $aliastable;
598 98bbf05a Scott Ullrich
599 5b237745 Scott Ullrich
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
600
		return true;
601
	else
602
		return is_subnet($subnet);
603
}
604
605
/* returns true if $hostname is a valid hostname */
606
function is_hostname($hostname) {
607
	if (!is_string($hostname))
608
		return false;
609 98bbf05a Scott Ullrich
610 88efcf04 Erik Fonnesbeck
	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))
611 5b237745 Scott Ullrich
		return true;
612
	else
613
		return false;
614
}
615
616
/* returns true if $domain is a valid domain name */
617
function is_domain($domain) {
618
	if (!is_string($domain))
619
		return false;
620 98bbf05a Scott Ullrich
621 88efcf04 Erik Fonnesbeck
	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))
622 5b237745 Scott Ullrich
		return true;
623
	else
624
		return false;
625
}
626
627
/* returns true if $macaddr is a valid MAC address */
628 1f1a08c8 jim-p
function is_macaddr($macaddr, $partial=false) {
629
	$repeat = ($partial) ? '1,5' : '5';
630
	return preg_match('/^[0-9A-F]{2}(?:[:][0-9A-F]{2}){'.$repeat.'}$/i', $macaddr) == 1 ? true : false;
631 5b237745 Scott Ullrich
}
632
633 3caa8aa1 Bill Marquette
/* returns true if $name is a valid name for an alias */
634 9499c2d2 Bill Marquette
/* returns NULL if a reserved word is used */
635 5b237745 Scott Ullrich
function is_validaliasname($name) {
636 beeef1f0 Bill Marquette
	/* Array of reserved words */
637 0c2badde Colin Smith
	$reserved = array("port", "pass");
638
	if (in_array($name, $reserved, true))
639 9499c2d2 Bill Marquette
		return; /* return NULL */
640 bac9941b jim-p
	if (!preg_match("/[^a-zA-Z0-9_]/", $name) && (strlen($name) < 32))
641 5b237745 Scott Ullrich
		return true;
642
	else
643
		return false;
644
}
645
646
/* returns true if $port is a valid TCP/UDP port */
647
function is_port($port) {
648 231e0606 Ermal Lu?i
	$tmpports = explode(":", $port);
649
	foreach($tmpports as $tmpport) {
650
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
651 5bbd08e1 Warren Baker
			continue;
652 231e0606 Ermal Lu?i
		if (!ctype_digit($tmpport))
653
			return false;
654 b52f883a Ermal Lu?i
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
655 231e0606 Ermal Lu?i
			return false;
656
	}
657
	return true;
658 5b237745 Scott Ullrich
}
659
660 5a1eebc7 Scott Ullrich
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
661
function is_portrange($portrange) {
662 5bbd08e1 Warren Baker
	$ports = explode(":", $portrange);
663 5a1eebc7 Scott Ullrich
664 e371f8b9 whjvenyl
	return (count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]));
665 5a1eebc7 Scott Ullrich
}
666
667 1e578a7f Ermal Lu?i
/* returns true if $port is a valid port number or an alias thereof */
668
function is_portoralias($port) {
669
	global $config;
670
671 5bbd08e1 Warren Baker
	if (is_alias($port)) {
672
		if (is_array($config['aliases']['alias'])) {
673
			foreach ($config['aliases']['alias'] as $alias) {
674
				if ($alias['name'] == $port && $alias['type'] == "port")
675
					return true;
676
				}
677
			}
678
			return false;
679
	} else
680
		return is_port($port);
681 1e578a7f Ermal Lu?i
}
682
683 b8014f9d Scott Ullrich
/* returns true if $val is a valid shaper bandwidth value */
684
function is_valid_shaperbw($val) {
685 eaa37259 Ermal Luçi
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
686 b8014f9d Scott Ullrich
}
687
688 54404519 Renato Botelho
/* returns true if $test is in the range between $start and $end */
689
function is_inrange_v4($test, $start, $end) {
690
	if ( (ip2ulong($test) <= ip2ulong($end)) && (ip2ulong($test) >= ip2ulong($start)) )
691
		return true;
692
	else
693
		return false;
694
}
695
696 41b4867e Renato Botelho
/* returns true if $test is in the range between $start and $end */
697
function is_inrange_v6($test, $start, $end) {
698
	if ( (inet_pton($test) <= inet_pton($end)) && (inet_pton($test) >= inet_pton($start)) )
699
		return true;
700
	else
701
		return false;
702
}
703
704 abcb2bed Ermal Lu?i
/* return the configured carp interface list */
705
function get_configured_carp_interface_list() {
706
	global $config;
707
708
	$iflist = array();
709
710
	if(is_array($config['virtualip']['vip'])) {
711 5bbd08e1 Warren Baker
		$viparr = &$config['virtualip']['vip'];
712
		foreach ($viparr as $vip) {
713
			switch ($vip['mode']) {
714 7b47bd4c Ermal
			case "carp":
715
				$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
716
				$iflist[$vipif] = $vip['subnet'];
717
				break;
718 5bbd08e1 Warren Baker
			}
719
		}
720
	}
721 abcb2bed Ermal Lu?i
722
	return $iflist;
723
}
724
725 67b0902f pierrepomes
/* return the configured IP aliases list */
726 a119ecf8 Erik Fonnesbeck
function get_configured_ip_aliases_list($returnfullentry = false) {
727 5bbd08e1 Warren Baker
	global $config;
728 67b0902f pierrepomes
729 5bbd08e1 Warren Baker
	$alias_list=array();
730 67b0902f pierrepomes
731 5bbd08e1 Warren Baker
	if(is_array($config['virtualip']['vip'])) {
732
		$viparr = &$config['virtualip']['vip'];
733
		foreach ($viparr as $vip) {
734
			if ($vip['mode']=="ipalias") {
735 a119ecf8 Erik Fonnesbeck
				if ($returnfullentry)
736
					$alias_list[$vip['subnet']] = $vip;
737
				else
738
					$alias_list[$vip['subnet']] = $vip['interface'];
739 5bbd08e1 Warren Baker
			}
740
		}
741
	}
742 67b0902f pierrepomes
743 5bbd08e1 Warren Baker
	return $alias_list;
744 67b0902f pierrepomes
}
745
746 e6c60013 Renato Botelho
/* return all configured aliases list (IP, carp, proxyarp and other) */
747
function get_configured_vips_list() {
748
	global $config;
749
750
	$alias_list=array();
751
752
	if(is_array($config['virtualip']['vip'])) {
753
		$viparr = &$config['virtualip']['vip'];
754
		foreach ($viparr as $vip)
755
			$alias_list[] = array("ipaddr" => $vip['subnet'], "if" => $vip['interface']);
756
	}
757
758
	return $alias_list;
759
}
760 67b0902f pierrepomes
761 88bc2760 Erik Fonnesbeck
/* comparison function for sorting by the order in which interfaces are normally created */
762
function compare_interface_friendly_names($a, $b) {
763
	if ($a == $b)
764
		return 0;
765
	else if ($a == 'wan')
766
		return -1;
767
	else if ($b == 'wan')
768
		return 1;
769
	else if ($a == 'lan')
770
		return -1;
771
	else if ($b == 'lan')
772
		return 1;
773
774
	return strnatcmp($a, $b);
775
}
776
777 c8abe1d4 Ermal Luçi
/* return the configured interfaces list. */
778 3ad5e089 Ermal Luçi
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
779 c8abe1d4 Ermal Luçi
	global $config;
780
781
	$iflist = array();
782 14f49fd0 Erik Fonnesbeck
783 c8abe1d4 Ermal Luçi
	/* if list */
784 8735afe8 Erik Fonnesbeck
	foreach($config['interfaces'] as $if => $ifdetail) {
785
		if ($only_opt && ($if == "wan" || $if == "lan"))
786 42c9d20e Ermal Luçi
			continue;
787 47c8b036 Ermal Lu?i
		if (isset($ifdetail['enable']) || $withdisabled == true)
788 c8abe1d4 Ermal Luçi
			$iflist[$if] = $if;
789 42c9d20e Ermal Luçi
	}
790 c8abe1d4 Ermal Luçi
791
	return $iflist;
792
}
793
794 bb34737f Ermal Lu?i
/* return the configured interfaces list. */
795
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
796 8735afe8 Erik Fonnesbeck
	global $config;
797 bb34737f Ermal Lu?i
798 8735afe8 Erik Fonnesbeck
	$iflist = array();
799 bb34737f Ermal Lu?i
800 8735afe8 Erik Fonnesbeck
	/* if list */
801
	foreach($config['interfaces'] as $if => $ifdetail) {
802
		if ($only_opt && ($if == "wan" || $if == "lan"))
803
			continue;
804
		if (isset($ifdetail['enable']) || $withdisabled == true) {
805 bb34737f Ermal Lu?i
			$tmpif = get_real_interface($if);
806
			if (!empty($tmpif))
807
				$iflist[$tmpif] = $if;
808
		}
809 8735afe8 Erik Fonnesbeck
	}
810 bb34737f Ermal Lu?i
811 8735afe8 Erik Fonnesbeck
	return $iflist;
812 bb34737f Ermal Lu?i
}
813
814 c8abe1d4 Ermal Luçi
/* return the configured interfaces list with their description. */
815 3ad5e089 Ermal Luçi
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
816 a42d1da2 Scott Ullrich
	global $config;
817 c8abe1d4 Ermal Luçi
818 a42d1da2 Scott Ullrich
	$iflist = array();
819 c8abe1d4 Ermal Luçi
820 a42d1da2 Scott Ullrich
	/* if list */
821
	foreach($config['interfaces'] as $if => $ifdetail) {
822 8735afe8 Erik Fonnesbeck
		if ($only_opt && ($if == "wan" || $if == "lan"))
823
			continue;
824 47c8b036 Ermal Lu?i
		if (isset($ifdetail['enable']) || $withdisabled == true) {
825 8735afe8 Erik Fonnesbeck
			if(empty($ifdetail['descr']))
826 8e74cb8d Ermal Luçi
				$iflist[$if] = strtoupper($if);
827 a42d1da2 Scott Ullrich
			else
828 44b0ec83 Scott Ullrich
				$iflist[$if] = strtoupper($ifdetail['descr']);
829 0e218dc1 Ermal Luçi
		}
830 42c9d20e Ermal Luçi
	}
831 c8abe1d4 Ermal Luçi
832 a42d1da2 Scott Ullrich
	return $iflist;
833 c8abe1d4 Ermal Luçi
}
834
835 4fe9c2dc Scott Ullrich
/*
836
 *   get_configured_ip_addresses() - Return a list of all configured
837
 *   interfaces IP Addresses
838
 *
839
 */
840
function get_configured_ip_addresses() {
841 5dbd619f smos
	global $config;
842 a1e4e2a7 Ermal
843 d97741c2 Ermal
	if (!function_exists('get_interface_ip'))
844 a1e4e2a7 Ermal
		require_once("interfaces.inc");
845 4fe9c2dc Scott Ullrich
	$ip_array = array();
846
	$interfaces = get_configured_interface_list();
847 a1e4e2a7 Ermal
	if (is_array($interfaces)) {
848 d9114ce0 Scott Ullrich
		foreach($interfaces as $int) {
849
			$ipaddr = get_interface_ip($int);
850
			$ip_array[$int] = $ipaddr;
851
		}
852 4fe9c2dc Scott Ullrich
	}
853 19f101d7 Scott Ullrich
	$interfaces = get_configured_carp_interface_list();
854 86a5e1a8 Renato Botelho
	if (is_array($interfaces))
855
		foreach($interfaces as $int => $ipaddr)
856 d9114ce0 Scott Ullrich
			$ip_array[$int] = $ipaddr;
857 5dbd619f smos
858
	/* pppoe server */
859 a1e4e2a7 Ermal
	if (is_array($config['pppoes']) && is_array($config['pppoes']['pppoe'])) {
860 5dbd619f smos
		foreach($config['pppoes']['pppoe'] as $pppoe) {
861
			if ($pppoe['mode'] == "server") {
862
				if(is_ipaddr($pppoe['localip'])) {
863
					$int = "pppoes". $pppoe['pppoeid'];
864
					$ip_array[$int] = $pppoe['localip'];
865
				}
866
			}
867
		}
868
	}
869 a1e4e2a7 Ermal
870 4fe9c2dc Scott Ullrich
	return $ip_array;
871
}
872 c8abe1d4 Ermal Luçi
873 e6f7e0be smos
/*
874
 *   get_configured_ipv6_addresses() - Return a list of all configured
875
 *   interfaces IPv6 Addresses
876
 *
877
 */
878
function get_configured_ipv6_addresses() {
879
	require_once("interfaces.inc");
880
	$ipv6_array = array();
881
	$interfaces = get_configured_interface_list();
882
	if(is_array($interfaces)) {
883
		foreach($interfaces as $int) {
884
			$ipaddrv6 = get_interface_ipv6($int);
885
			$ipv6_array[$int] = $ipaddrv6;
886
		}
887
	}
888
	$interfaces = get_configured_carp_interface_list();
889 86a5e1a8 Renato Botelho
	if(is_array($interfaces))
890
		foreach($interfaces as $int => $ipaddrv6)
891 e6f7e0be smos
			$ipv6_array[$int] = $ipaddrv6;
892
	return $ipv6_array;
893
}
894
895 36f546e9 Scott Ullrich
/*
896
 *   get_interface_list() - Return a list of all physical interfaces
897
 *   along with MAC and status.
898
 *
899
 *   $mode = "active" - use ifconfig -lu
900
 *           "media"  - use ifconfig to check physical connection
901
 *			status (much slower)
902
 */
903
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
904 86a5e1a8 Renato Botelho
	global $config;
905 65bed2d2 Scott Ullrich
	$upints = array();
906 86a5e1a8 Renato Botelho
	/* get a list of virtual interface types */
907
	if(!$vfaces) {
908 9ce38409 Scott Ullrich
		$vfaces = array (
909
				'bridge',
910
				'ppp',
911 27c0c7c6 Ermal Lu?i
				'pppoe',
912
				'pptp',
913
				'l2tp',
914 9ce38409 Scott Ullrich
				'sl',
915
				'gif',
916 613571ea Ermal Luçi
				'gre',
917 9ce38409 Scott Ullrich
				'faith',
918
				'lo',
919
				'ng',
920 27616d6e Seth Mos
				'_vlan',
921 7c53bc7b Erik Fonnesbeck
				'_wlan',
922 9ce38409 Scott Ullrich
				'pflog',
923 a42d1da2 Scott Ullrich
				'plip',
924 9ce38409 Scott Ullrich
				'pfsync',
925
				'enc',
926
				'tun',
927 0a140d2e Ermal Luçi
				'carp',
928 1fb2bf25 Ermal Lu?i
				'lagg',
929 1fd35e95 Ermal
				'vip',
930
				'ipfw'
931 9ce38409 Scott Ullrich
		);
932 36f546e9 Scott Ullrich
	}
933 20203646 Colin Smith
	switch($mode) {
934
	case "active":
935 86a5e1a8 Renato Botelho
		$upints = pfSense_interface_listget(IFF_UP);
936
		break;
937 20203646 Colin Smith
	case "media":
938 d9adca3b Ermal
		$intlist = pfSense_interface_listget();
939 86a5e1a8 Renato Botelho
		$ifconfig = "";
940
		exec("/sbin/ifconfig -a", $ifconfig);
941
		$regexp = '/(' . implode('|', $intlist) . '):\s/';
942
		$ifstatus = preg_grep('/status:/', $ifconfig);
943 49149b86 Colin Smith
		foreach($ifstatus as $status) {
944 bb3b9159 Colin Smith
			$int = array_shift($intlist);
945 5bbd08e1 Warren Baker
			if(stristr($status, "active")) $upints[] = $int;
946 49149b86 Colin Smith
		}
947 20203646 Colin Smith
		break;
948 72993196 Ermal
	default:
949 d9adca3b Ermal
		$upints = pfSense_interface_listget();
950 72993196 Ermal
		break;
951 20203646 Colin Smith
	}
952 86a5e1a8 Renato Botelho
	/* build interface list with netstat */
953
	$linkinfo = "";
954
	exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
955
	array_shift($linkinfo);
956 89d1f0f2 Scott Ullrich
	/* build ip address list with netstat */
957 767a716e Scott Ullrich
	$ipinfo = "";
958 89d1f0f2 Scott Ullrich
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
959
	array_shift($ipinfo);
960
	foreach($linkinfo as $link) {
961
		$friendly = "";
962 5bbd08e1 Warren Baker
		$alink = explode(" ", $link);
963
		$ifname = rtrim(trim($alink[0]), '*');
964
		/* trim out all numbers before checking for vfaces */
965 494be6e8 Ermal Lu?i
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces) &&
966 7c53bc7b Erik Fonnesbeck
			!stristr($ifname, "_vlan") && !stristr($ifname, "_wlan")) {
967 20203646 Colin Smith
			$toput = array(
968
					"mac" => trim($alink[1]),
969
					"up" => in_array($ifname, $upints)
970
				);
971 89d1f0f2 Scott Ullrich
			foreach($ipinfo as $ip) {
972
				$aip = explode(" ", $ip);
973
				if($aip[0] == $ifname) {
974
					$toput['ipaddr'] = $aip[1];
975
				}
976
			}
977 72993196 Ermal
			if (is_array($config['interfaces'])) {
978
				foreach($config['interfaces'] as $name => $int)
979
					if($int['if'] == $ifname) $friendly = $name;
980 20203646 Colin Smith
			}
981
			switch($keyby) {
982
			case "physical":
983 89d1f0f2 Scott Ullrich
				if($friendly != "") {
984
					$toput['friendly'] = $friendly;
985
				}
986 a296c95d Seth Mos
				$dmesg_arr = array();
987
				exec("/sbin/dmesg |grep $ifname | head -n1", $dmesg_arr);
988
				preg_match_all("/<(.*?)>/i", $dmesg_arr[0], $dmesg);
989
				$toput['dmesg'] = $dmesg[1][0];
990 20203646 Colin Smith
				$iflist[$ifname] = $toput;
991 3154d7ed Colin Smith
				break;
992 4aca19b3 Scott Ullrich
			case "ppp":
993 86a5e1a8 Renato Botelho
994 20203646 Colin Smith
			case "friendly":
995 89d1f0f2 Scott Ullrich
				if($friendly != "") {
996
					$toput['if'] = $ifname;
997
					$iflist[$friendly] = $toput;
998
				}
999 3154d7ed Colin Smith
				break;
1000
			}
1001 5bbd08e1 Warren Baker
		}
1002
	}
1003
	return $iflist;
1004 5b237745 Scott Ullrich
}
1005
1006 2b4d37de Ermal Lu?i
/****f* util/log_error
1007
* NAME
1008
*   log_error  - Sends a string to syslog.
1009
* INPUTS
1010
*   $error     - string containing the syslog message.
1011
* RESULT
1012
*   null
1013
******/
1014
function log_error($error) {
1015 5bbd08e1 Warren Baker
	global $g;
1016
	$page = $_SERVER['SCRIPT_NAME'];
1017 866b1d61 jim-p
	if (empty($page)) {
1018
		$files = get_included_files();
1019
		$page = basename($files[0]);
1020
	}
1021 0d0cb047 jim-p
	syslog(LOG_ERR, "$page: $error");
1022 5bbd08e1 Warren Baker
	if ($g['debug'])
1023
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
1024
	return;
1025 2b4d37de Ermal Lu?i
}
1026
1027 3aba1835 Scott Ullrich
/****f* util/log_auth
1028
* NAME
1029 1198abf9 PiBa-NL
*   log_auth   - Sends a string to syslog as LOG_AUTH facility
1030 3aba1835 Scott Ullrich
* INPUTS
1031
*   $error     - string containing the syslog message.
1032
* RESULT
1033
*   null
1034
******/
1035
function log_auth($error) {
1036 5bbd08e1 Warren Baker
	global $g;
1037
	$page = $_SERVER['SCRIPT_NAME'];
1038
	syslog(LOG_AUTH, "$page: $error");
1039
	if ($g['debug'])
1040
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
1041
	return;
1042 3aba1835 Scott Ullrich
}
1043
1044 83bc3749 Ermal Lu?i
/****f* util/exec_command
1045
 * NAME
1046
 *   exec_command - Execute a command and return a string of the result.
1047
 * INPUTS
1048
 *   $command   - String of the command to be executed.
1049
 * RESULT
1050
 *   String containing the command's result.
1051
 * NOTES
1052
 *   This function returns the command's stdout and stderr.
1053
 ******/
1054
function exec_command($command) {
1055 5bbd08e1 Warren Baker
	$output = array();
1056
	exec($command . ' 2>&1 ', $output);
1057
	return(implode("\n", $output));
1058 83bc3749 Ermal Lu?i
}
1059
1060 5b237745 Scott Ullrich
/* wrapper for exec() */
1061 b61e8960 jim-p
function mwexec($command, $mute = false, $clearsigmask = false) {
1062 5b237745 Scott Ullrich
	global $g;
1063 435a418f Ermal
1064 5b237745 Scott Ullrich
	if ($g['debug']) {
1065
		if (!$_SERVER['REMOTE_ADDR'])
1066
			echo "mwexec(): $command\n";
1067 f9db3cda Seth Mos
	}
1068 435a418f Ermal
	$oarr = array();
1069
	$retval = 0;
1070 b61e8960 jim-p
1071
	if ($clearsigmask) {
1072
		$oldset = array();
1073
		pcntl_sigprocmask(SIG_SETMASK, array(), $oldset);
1074
	}
1075 435a418f Ermal
	$garbage = exec("$command 2>&1", $oarr, $retval);
1076 b61e8960 jim-p
	if ($clearsigmask) {
1077
		pcntl_sigprocmask(SIG_SETMASK, $oldset);
1078
	}
1079 435a418f Ermal
1080 61c6b6c1 Chris Buechler
	if(isset($config['system']['developerspew']))
1081 5bbd08e1 Warren Baker
		$mute = false;
1082 12169c92 Seth Mos
	if(($retval <> 0) && ($mute === false)) {
1083 f9db3cda Seth Mos
		$output = implode(" ", $oarr);
1084 addc0439 Renato Botelho
		log_error(sprintf(gettext("The command '%1\$s' returned exit code '%2\$d', the output was '%3\$s' "), $command, $retval, $output));
1085 5b237745 Scott Ullrich
	}
1086 98bbf05a Scott Ullrich
	return $retval;
1087 5b237745 Scott Ullrich
}
1088
1089
/* wrapper for exec() in background */
1090 b61e8960 jim-p
function mwexec_bg($command, $clearsigmask = false) {
1091 5b237745 Scott Ullrich
	global $g;
1092 98bbf05a Scott Ullrich
1093 5b237745 Scott Ullrich
	if ($g['debug']) {
1094
		if (!$_SERVER['REMOTE_ADDR'])
1095
			echo "mwexec(): $command\n";
1096
	}
1097 98bbf05a Scott Ullrich
1098 b61e8960 jim-p
	if ($clearsigmask) {
1099
		$oldset = array();
1100
		pcntl_sigprocmask(SIG_SETMASK, array(), $oldset);
1101
	}
1102 77daff18 Ermal
	$_gb = exec("/usr/bin/nohup $command > /dev/null 2>&1 &");
1103 b61e8960 jim-p
	if ($clearsigmask) {
1104
		pcntl_sigprocmask(SIG_SETMASK, $oldset);
1105
	}
1106 fba1804f Ermal
	unset($_gb);
1107 5b237745 Scott Ullrich
}
1108
1109
/* unlink a file, if it exists */
1110
function unlink_if_exists($fn) {
1111 336cb718 Scott Ullrich
	$to_do = glob($fn);
1112 3b378be5 Scott Ullrich
	if(is_array($to_do)) {
1113 336cb718 Scott Ullrich
		foreach($to_do as $filename)
1114 9ff926a2 Colin Smith
			@unlink($filename);
1115 336cb718 Scott Ullrich
	} else {
1116 9ff926a2 Colin Smith
		@unlink($fn);
1117 336cb718 Scott Ullrich
	}
1118 5b237745 Scott Ullrich
}
1119
/* make a global alias table (for faster lookups) */
1120 918a884d Bill Marquette
function alias_make_table($config) {
1121
	global $aliastable;
1122 98bbf05a Scott Ullrich
1123 5b237745 Scott Ullrich
	$aliastable = array();
1124 98bbf05a Scott Ullrich
1125 5b237745 Scott Ullrich
	if (is_array($config['aliases']['alias'])) {
1126
		foreach ($config['aliases']['alias'] as $alias) {
1127
			if ($alias['name'])
1128
				$aliastable[$alias['name']] = $alias['address'];
1129
		}
1130
	}
1131
}
1132 5ffa3389 Ermal
1133 5b237745 Scott Ullrich
/* check if an alias exists */
1134
function is_alias($name) {
1135
	global $aliastable;
1136 98bbf05a Scott Ullrich
1137 5b237745 Scott Ullrich
	return isset($aliastable[$name]);
1138 b8014f9d Scott Ullrich
}
1139 27ff8a3c Scott Ullrich
1140 5ffa3389 Ermal
function alias_get_type($name) {
1141 86a5e1a8 Renato Botelho
	global $config;
1142
1143 5ffa3389 Ermal
	if (is_array($config['aliases']['alias'])) {
1144
		foreach ($config['aliases']['alias'] as $alias) {
1145
			if ($name == $alias['name'])
1146
				return $alias['type'];
1147
		}
1148
	}
1149
1150 86a5e1a8 Renato Botelho
	return "";
1151 5ffa3389 Ermal
}
1152
1153 5b237745 Scott Ullrich
/* expand a host or network alias, if necessary */
1154
function alias_expand($name) {
1155
	global $aliastable;
1156 98bbf05a Scott Ullrich
1157 87f0be87 Chris Buechler
	if (isset($aliastable[$name]))
1158 4335dc87 Bill Marquette
		return "\${$name}";
1159 a584475a Ermal Lu?i
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
1160 57989da5 Scott Ullrich
		return "{$name}";
1161 87f0be87 Chris Buechler
	else
1162 5b237745 Scott Ullrich
		return null;
1163
}
1164
1165 c7de8be4 jim-p
function alias_expand_urltable($name) {
1166
	global $config;
1167
	$urltable_prefix = "/var/db/aliastables/";
1168
	$urltable_filename = $urltable_prefix . $name . ".txt";
1169
1170 5ffa3389 Ermal
	if (is_array($config['aliases']['alias'])) {
1171
		foreach ($config['aliases']['alias'] as $alias) {
1172
			if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
1173
				if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
1174
					return $urltable_filename;
1175
				else if (process_alias_urltable($name, $alias["url"], 0, true))
1176
					return $urltable_filename;
1177
			}
1178 c7de8be4 jim-p
		}
1179
	}
1180
	return null;
1181
}
1182
1183 dbea91b3 bcyrill
function subnet_size($subnet) {
1184 0917cb21 Darren Embry
	if (is_subnetv4($subnet)) {
1185
		list ($ip, $bits) = explode("/", $subnet);
1186
		return round(exp(log(2) * (32 - $bits)));
1187
	}
1188
	else if (is_subnetv6($subnet)) {
1189
		list ($ip, $bits) = explode("/", $subnet);
1190
		return round(exp(log(2) * (128 - $bits)));
1191
	}
1192
	else {
1193
		return 0;
1194
	}
1195
}
1196
1197 dbea91b3 bcyrill
function subnet_expand($subnet) {
1198 0917cb21 Darren Embry
	if (is_subnetv4($subnet)) {
1199
		return subnetv4_expand($subnet);
1200
	} else if (is_subnetv6($subnet)) {
1201
		return subnetv6_expand($subnet);
1202
	} else {
1203
		return $subnet;
1204
	}
1205
}
1206
1207 dbea91b3 bcyrill
function subnetv4_expand($subnet) {
1208 0917cb21 Darren Embry
	$result = array();
1209
	list ($ip, $bits) = explode("/", $subnet);
1210
	$net  = ip2long($ip);
1211
	$mask = (0xffffffff << (32 - $bits));
1212
	$net &= $mask;
1213
	$size = round(exp(log(2) * (32 - $bits)));
1214
	for ($i = 0; $i < $size; $i += 1) {
1215
		$result[] = long2ip($net | $i);
1216
	}
1217
	return $result;
1218
}
1219
1220 5b237745 Scott Ullrich
/* find out whether two subnets overlap */
1221
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
1222
1223
	if (!is_numeric($bits1))
1224
		$bits1 = 32;
1225
	if (!is_numeric($bits2))
1226
		$bits2 = 32;
1227
1228
	if ($bits1 < $bits2)
1229
		$relbits = $bits1;
1230
	else
1231
		$relbits = $bits2;
1232 98bbf05a Scott Ullrich
1233 5b237745 Scott Ullrich
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
1234
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
1235 98bbf05a Scott Ullrich
1236 e371f8b9 whjvenyl
	return ($sn1 == $sn2);
1237 5b237745 Scott Ullrich
}
1238
1239 dbea91b3 bcyrill
/* find out whether two IPv6 subnets overlap */
1240
function check_subnetsv6_overlap($subnet1, $bits1, $subnet2, $bits2) {
1241
	$sub1_min = gen_subnetv6($subnet1, $bits1);
1242
	$sub1_max = gen_subnetv6_max($subnet1, $bits1);
1243
	$sub2_min = gen_subnetv6($subnet2, $bits2);
1244
	$sub2_max = gen_subnetv6_max($subnet2, $bits2);
1245 86a5e1a8 Renato Botelho
1246 bd92ede8 bcyrill
	return (is_inrange_v6($sub1_min, $sub2_min, $sub2_max) || is_inrange_v6($sub1_max, $sub2_min, $sub2_max) || is_inrange_v6($sub2_min, $sub1_min, $sub1_max));
1247 dbea91b3 bcyrill
}
1248
1249 5b237745 Scott Ullrich
/* compare two IP addresses */
1250
function ipcmp($a, $b) {
1251 96033063 Erik Fonnesbeck
	if (ip_less_than($a, $b))
1252 5b237745 Scott Ullrich
		return -1;
1253 96033063 Erik Fonnesbeck
	else if (ip_greater_than($a, $b))
1254 5b237745 Scott Ullrich
		return 1;
1255
	else
1256
		return 0;
1257
}
1258
1259
/* return true if $addr is in $subnet, false if not */
1260
function ip_in_subnet($addr,$subnet) {
1261 c75a8185 Seth Mos
	if(is_ipaddrv6($addr)) {
1262 83a12422 Ermal
		return (Net_IPv6::isInNetmask($addr, $subnet));
1263
	} else { /* XXX: Maybe check for IPv4 */
1264
		list($ip, $mask) = explode('/', $subnet);
1265
		$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
1266
		return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
1267 c75a8185 Seth Mos
	}
1268 5b237745 Scott Ullrich
}
1269
1270
/* verify (and remove) the digital signature on a file - returns 0 if OK */
1271
function verify_digital_signature($fname) {
1272
	global $g;
1273
1274 c50da179 Scott Ullrich
	if(!file_exists("/usr/local/sbin/gzsig"))
1275 9f007e8c Chris Buechler
		return 4;
1276 c50da179 Scott Ullrich
1277 f024f52d Scott Ullrich
	return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname));
1278 5b237745 Scott Ullrich
}
1279
1280
/* obtain MAC address given an IP address by looking at the ARP table */
1281
function arp_get_mac_by_ip($ip) {
1282 f3ebffee Ermal Lu?i
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
1283 767a716e Scott Ullrich
	$arpoutput = "";
1284 5b237745 Scott Ullrich
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
1285 98bbf05a Scott Ullrich
1286 5b237745 Scott Ullrich
	if ($arpoutput[0]) {
1287
		$arpi = explode(" ", $arpoutput[0]);
1288
		$macaddr = $arpi[3];
1289
		if (is_macaddr($macaddr))
1290
			return $macaddr;
1291
		else
1292
			return false;
1293
	}
1294 98bbf05a Scott Ullrich
1295 5b237745 Scott Ullrich
	return false;
1296
}
1297
1298 98bbf05a Scott Ullrich
/* return a fieldname that is safe for xml usage */
1299
function xml_safe_fieldname($fieldname) {
1300 87f0be87 Chris Buechler
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
1301
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
1302 ddce8ef2 Colin Smith
			 ':', ',', '.', '\'', '\\'
1303
		);
1304
	return strtolower(str_replace($replace, "", $fieldname));
1305 98bbf05a Scott Ullrich
}
1306
1307 805b9ab6 Ermal
function mac_format($clientmac) {
1308 86a5e1a8 Renato Botelho
	global $config, $cpzone;
1309 4129df39 Scott Ullrich
1310 86a5e1a8 Renato Botelho
	$mac = explode(":", $clientmac);
1311
	$mac_format = $cpzone ? $config['captiveportal'][$cpzone]['radmac_format'] : false;
1312 4129df39 Scott Ullrich
1313 86a5e1a8 Renato Botelho
	switch($mac_format) {
1314
	case 'singledash':
1315 7b89ea6a Ermal
		return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
1316 4129df39 Scott Ullrich
1317 86a5e1a8 Renato Botelho
	case 'ietf':
1318 7b89ea6a Ermal
		return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
1319 4129df39 Scott Ullrich
1320 86a5e1a8 Renato Botelho
	case 'cisco':
1321 7b89ea6a Ermal
		return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
1322 4129df39 Scott Ullrich
1323 86a5e1a8 Renato Botelho
	case 'unformatted':
1324 7b89ea6a Ermal
		return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
1325 4129df39 Scott Ullrich
1326 86a5e1a8 Renato Botelho
	default:
1327 7b89ea6a Ermal
		return $clientmac;
1328 86a5e1a8 Renato Botelho
	}
1329 4129df39 Scott Ullrich
}
1330
1331 979cd6db Scott Ullrich
function resolve_retry($hostname, $retries = 5) {
1332
1333 5bbd08e1 Warren Baker
	if (is_ipaddr($hostname))
1334
		return $hostname;
1335 979cd6db Scott Ullrich
1336 86a5e1a8 Renato Botelho
	for ($i = 0; $i < $retries; $i++) {
1337 6c4f3b54 Seth Mos
		// FIXME: gethostbyname does not work for AAAA hostnames, boo, hiss
1338 86a5e1a8 Renato Botelho
		$ip = gethostbyname($hostname);
1339 979cd6db Scott Ullrich
1340 5bbd08e1 Warren Baker
		if ($ip && $ip != $hostname) {
1341
			/* success */
1342
			return $ip;
1343
		}
1344 979cd6db Scott Ullrich
1345 5bbd08e1 Warren Baker
		sleep(1);
1346
	}
1347 979cd6db Scott Ullrich
1348 5bbd08e1 Warren Baker
	return false;
1349 979cd6db Scott Ullrich
}
1350
1351 44bfd1fa Scott Ullrich
function format_bytes($bytes) {
1352
	if ($bytes >= 1073741824) {
1353
		return sprintf("%.2f GB", $bytes/1073741824);
1354
	} else if ($bytes >= 1048576) {
1355
		return sprintf("%.2f MB", $bytes/1048576);
1356
	} else if ($bytes >= 1024) {
1357
		return sprintf("%.0f KB", $bytes/1024);
1358
	} else {
1359
		return sprintf("%d bytes", $bytes);
1360
	}
1361
}
1362
1363 2b4d37de Ermal Lu?i
function update_filter_reload_status($text) {
1364 5bbd08e1 Warren Baker
	global $g;
1365 2b4d37de Ermal Lu?i
1366 5bbd08e1 Warren Baker
	file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1367 2b4d37de Ermal Lu?i
}
1368
1369 a2219caf Renato Botelho
/****** util/return_dir_as_array
1370 2b4d37de Ermal Lu?i
 * NAME
1371
 *   return_dir_as_array - Return a directory's contents as an array.
1372
 * INPUTS
1373 a2219caf Renato Botelho
 *   $dir          - string containing the path to the desired directory.
1374
 *   $filter_regex - string containing a regular expression to filter file names. Default empty.
1375 2b4d37de Ermal Lu?i
 * RESULT
1376
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1377
 ******/
1378 a2219caf Renato Botelho
function return_dir_as_array($dir, $filter_regex = '') {
1379 5bbd08e1 Warren Baker
	$dir_array = array();
1380
	if (is_dir($dir)) {
1381
		if ($dh = opendir($dir)) {
1382
			while (($file = readdir($dh)) !== false) {
1383 a2219caf Renato Botelho
				if (($file == ".") || ($file == ".."))
1384
					continue;
1385
1386
				if (empty($filter_regex) || preg_match($filter_regex, $file))
1387 5bbd08e1 Warren Baker
					array_push($dir_array, $file);
1388
			}
1389
			closedir($dh);
1390
		}
1391
	}
1392
	return $dir_array;
1393 2b4d37de Ermal Lu?i
}
1394
1395
function run_plugins($directory) {
1396 5bbd08e1 Warren Baker
	global $config, $g;
1397
1398
	/* process packager manager custom rules */
1399
	$files = return_dir_as_array($directory);
1400
	if (is_array($files)) {
1401
		foreach ($files as $file) {
1402
			if (stristr($file, ".sh") == true)
1403
				mwexec($directory . $file . " start");
1404 86a5e1a8 Renato Botelho
			else if (!is_dir($directory . "/" . $file) && stristr($file,".inc"))
1405 5bbd08e1 Warren Baker
				require_once($directory . "/" . $file);
1406 2990acf8 Scott Ullrich
		}
1407 5bbd08e1 Warren Baker
	}
1408 2b4d37de Ermal Lu?i
}
1409
1410
/*
1411
 *    safe_mkdir($path, $mode = 0755)
1412
 *    create directory if it doesn't already exist and isn't a file!
1413
 */
1414
function safe_mkdir($path, $mode=0755) {
1415 5bbd08e1 Warren Baker
	global $g;
1416 2b4d37de Ermal Lu?i
1417 5bbd08e1 Warren Baker
	if (!is_file($path) && !is_dir($path)) {
1418
		return @mkdir($path, $mode, true);
1419
	} else {
1420
		return false;
1421
	}
1422 2b4d37de Ermal Lu?i
}
1423
1424
/*
1425
 * make_dirs($path, $mode = 0755)
1426
 * create directory tree recursively (mkdir -p)
1427
 */
1428
function make_dirs($path, $mode = 0755) {
1429 5bbd08e1 Warren Baker
	$base = '';
1430
	foreach (explode('/', $path) as $dir) {
1431
		$base .= "/$dir";
1432
		if (!is_dir($base)) {
1433
			if (!@mkdir($base, $mode))
1434
				return false;
1435
		}
1436
	}
1437
	return true;
1438 2b4d37de Ermal Lu?i
}
1439
1440 aa4f498d Erik Fonnesbeck
/*
1441
 * get_sysctl($names)
1442
 * Get values of sysctl OID's listed in $names (accepts an array or a single
1443
 * name) and return an array of key/value pairs set for those that exist
1444
 */
1445
function get_sysctl($names) {
1446
	if (empty($names))
1447
		return array();
1448
1449
	if (is_array($names)) {
1450
		$name_list = array();
1451
		foreach ($names as $name) {
1452
			$name_list[] = escapeshellarg($name);
1453
		}
1454
	} else
1455
		$name_list = array(escapeshellarg($names));
1456
1457
	exec("/sbin/sysctl -i " . implode(" ", $name_list), $output);
1458
	$values = array();
1459
	foreach ($output as $line) {
1460
		$line = explode(": ", $line, 2);
1461
		if (count($line) == 2)
1462
			$values[$line[0]] = $line[1];
1463
	}
1464
1465
	return $values;
1466
}
1467
1468
/*
1469
 * set_sysctl($value_list)
1470
 * Set sysctl OID's listed as key/value pairs and return
1471
 * an array with keys set for those that succeeded
1472
 */
1473
function set_sysctl($values) {
1474
	if (empty($values))
1475
		return array();
1476
1477
	$value_list = array();
1478
	foreach ($values as $key => $value) {
1479
		$value_list[] = escapeshellarg($key) . "=" . escapeshellarg($value);
1480
	}
1481
1482
	exec("/sbin/sysctl -i " . implode(" ", $value_list), $output, $success);
1483
1484
	/* Retry individually if failed (one or more read-only) */
1485
	if ($success <> 0 && count($value_list) > 1) {
1486
		foreach ($value_list as $value) {
1487
			exec("/sbin/sysctl -i " . $value, $output);
1488
		}
1489
	}
1490
1491
	$ret = array();
1492
	foreach ($output as $line) {
1493
		$line = explode(": ", $line, 2);
1494
		if (count($line) == 2)
1495
			$ret[$line[0]] = true;
1496
	}
1497
1498
	return $ret;
1499
}
1500
1501 2b4d37de Ermal Lu?i
/*
1502
 *     get_memory()
1503
 *     returns an array listing the amount of
1504
 *     memory installed in the hardware
1505
 *     [0]real and [1]available
1506
 */
1507
function get_memory() {
1508 5cd73772 Ermal
1509
	$real = trim(`sysctl -n hw.physmem`, " \n");
1510 281cf46f Ermal
	$avail = trim(`sysctl -n hw.realmem`, " \n");
1511 5cd73772 Ermal
	/* convert from bytes to megabytes */
1512
	return array(($real/1048576),($avail/1048576));
1513 2b4d37de Ermal Lu?i
}
1514
1515
function mute_kernel_msgs() {
1516 5bbd08e1 Warren Baker
	global $config;
1517
	// Do not mute serial console.  The kernel gets very very cranky
1518
	// and will start dishing you cannot control tty errors.
1519 7734aea6 Andrew Thompson
	switch (trim(file_get_contents("/etc/platform"))) {
1520
		case "nanobsd":
1521
		case "jail":
1522
			return;
1523
	}
1524 86a5e1a8 Renato Botelho
	if($config['system']['enableserial'])
1525
		return;
1526 5bbd08e1 Warren Baker
	exec("/sbin/conscontrol mute on");
1527 2b4d37de Ermal Lu?i
}
1528
1529
function unmute_kernel_msgs() {
1530 5bbd08e1 Warren Baker
	global $config;
1531
	// Do not mute serial console.  The kernel gets very very cranky
1532
	// and will start dishing you cannot control tty errors.
1533 7734aea6 Andrew Thompson
	switch (trim(file_get_contents("/etc/platform"))) {
1534
		case "nanobsd":
1535
		case "jail":
1536
			return;
1537
	}
1538 5bbd08e1 Warren Baker
	exec("/sbin/conscontrol mute off");
1539 2b4d37de Ermal Lu?i
}
1540
1541
function start_devd() {
1542 6955830f Ermal Lu?i
	global $g;
1543
1544 7734aea6 Andrew Thompson
	if ($g['platform'] == 'jail')
1545
		return;
1546 5bbd08e1 Warren Baker
	exec("/sbin/devd");
1547
	sleep(1);
1548 2b4d37de Ermal Lu?i
}
1549
1550 66bcba1b Ermal
function is_interface_vlan_mismatch() {
1551 5bbd08e1 Warren Baker
	global $config, $g;
1552 66bcba1b Ermal
1553 5bbd08e1 Warren Baker
	if (is_array($config['vlans']['vlan'])) {
1554
		foreach ($config['vlans']['vlan'] as $vlan) {
1555
			if (does_interface_exist($vlan['if']) == false)
1556 66bcba1b Ermal
				return true;
1557 5bbd08e1 Warren Baker
		}
1558
	}
1559 66bcba1b Ermal
1560
	return false;
1561
}
1562
1563 2b4d37de Ermal Lu?i
function is_interface_mismatch() {
1564 857da904 Scott Ullrich
	global $config, $g;
1565 2b4d37de Ermal Lu?i
1566 857da904 Scott Ullrich
	$do_assign = false;
1567
	$i = 0;
1568 e0a45ce0 Erik Fonnesbeck
	$missing_interfaces = array();
1569 72993196 Ermal
	if (is_array($config['interfaces'])) {
1570 857da904 Scott Ullrich
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
1571 fd863e5c Erik Fonnesbeck
			if (preg_match("/^enc|^cua|^tun|^tap|^l2tp|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1572 857da904 Scott Ullrich
				// Do not check these interfaces.
1573
				$i++;
1574
				continue;
1575
			}
1576
			else if (does_interface_exist($ifcfg['if']) == false) {
1577 e0a45ce0 Erik Fonnesbeck
				$missing_interfaces[] = $ifcfg['if'];
1578 72993196 Ermal
				$do_assign = true;
1579 857da904 Scott Ullrich
			} else
1580
				$i++;
1581
		}
1582 72993196 Ermal
	}
1583 2b4d37de Ermal Lu?i
1584 857da904 Scott Ullrich
	if ($g['minimum_nic_count'] > $i) {
1585
		$do_assign = true;
1586
	} else if (file_exists("{$g['tmp_path']}/assign_complete"))
1587 e0a45ce0 Erik Fonnesbeck
		$do_assign = false;
1588
1589
	if (!empty($missing_interfaces) && $do_assign)
1590
		file_put_contents("{$g['tmp_path']}/missing_interfaces", implode(' ', $missing_interfaces));
1591
	else
1592
		@unlink("{$g['tmp_path']}/missing_interfaces");
1593 2b4d37de Ermal Lu?i
1594 857da904 Scott Ullrich
	return $do_assign;
1595 2b4d37de Ermal Lu?i
}
1596
1597 6e8f7b53 Ermal Lu?i
/* sync carp entries to other firewalls */
1598
function carp_sync_client() {
1599 e14d1c01 Ermal Lu?i
	global $g;
1600 0ae6daf8 Ermal
	send_event("filter sync");
1601 6e8f7b53 Ermal Lu?i
}
1602
1603 6dc88d53 Ermal Luci
/****f* util/isAjax
1604
 * NAME
1605
 *   isAjax - reports if the request is driven from prototype
1606
 * INPUTS
1607
 *   none
1608
 * RESULT
1609
 *   true/false
1610
 ******/
1611
function isAjax() {
1612 5bbd08e1 Warren Baker
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1613 6dc88d53 Ermal Luci
}
1614
1615 dad2b40e Tim Allender
/****f* util/timeout
1616
 * NAME
1617
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1618
 * INPUTS
1619
 *   optional, seconds to wait before timeout. Default 9 seconds.
1620
 * RESULT
1621
 *   returns 1 char of user input or null if no input.
1622
 ******/
1623
function timeout($timer = 9) {
1624
	while(!isset($key)) {
1625
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1626
		else { echo chr(8). "{$timer}"; }
1627
		`/bin/stty -icanon min 0 time 25`;
1628
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1629
		`/bin/stty icanon`;
1630
		if ($key == '')
1631
			unset($key);
1632
		$timer--;
1633
		if ($timer == 0)
1634
			break;
1635
	}
1636 86a5e1a8 Renato Botelho
	return $key;
1637 dad2b40e Tim Allender
}
1638 6dc88d53 Ermal Luci
1639 fdf3af3f Scott Ullrich
/****f* util/msort
1640
 * NAME
1641
 *   msort - sort array
1642
 * INPUTS
1643
 *   $array to be sorted, field to sort by, direction of sort
1644
 * RESULT
1645
 *   returns newly sorted array
1646
 ******/
1647 4a8bc5a2 Scott Ullrich
function msort($array, $id="id", $sort_ascending=true) {
1648
	$temp_array = array();
1649
	while(count($array)>0) {
1650
		$lowest_id = 0;
1651
		$index=0;
1652
		foreach ($array as $item) {
1653
			if (isset($item[$id])) {
1654
				if ($array[$lowest_id][$id]) {
1655
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1656
						$lowest_id = $index;
1657
					}
1658
				}
1659
			}
1660
			$index++;
1661
		}
1662
		$temp_array[] = $array[$lowest_id];
1663
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1664
	}
1665
	if ($sort_ascending) {
1666
		return $temp_array;
1667
	} else {
1668 86a5e1a8 Renato Botelho
		return array_reverse($temp_array);
1669 4a8bc5a2 Scott Ullrich
	}
1670
}
1671
1672 fdf3af3f Scott Ullrich
/****f* util/color
1673
 * NAME
1674
 *   color - outputs a color code to the ansi terminal if supported
1675
 * INPUTS
1676 6028a72d Scott Ullrich
 *   color code or color name
1677 fdf3af3f Scott Ullrich
 * RESULT
1678
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1679
 ******/
1680
function color($color = "0m") {
1681
	/*
1682
		Color codes available:
1683
		 0m reset; clears all colors and styles (to white on black)
1684
		 1m bold on (see below)
1685
		 3m italics on
1686
		 4m underline on
1687
		 7m inverse on; reverses foreground & background colors
1688
		 9m strikethrough on
1689
		 22m bold off (see below)
1690
		 23m italics off
1691
		 24m underline off
1692
		 27m inverse off
1693
		 29m strikethrough off
1694
		 30m set foreground color to black
1695
		 31m set foreground color to red
1696
		 32m set foreground color to green
1697
		 33m set foreground color to yellow
1698
		 34m set foreground color to blue
1699
		 35m set foreground color to magenta (purple)
1700
		 36m set foreground color to cyan
1701
		 37m set foreground color to white
1702
		 40m  set background color to black
1703
		 41m set background color to red
1704
		 42m set background color to green
1705
		 43m set background color to yellow
1706
		 44m set background color to blue
1707
		 45m set background color to magenta (purple)
1708
		 46m set background color to cyan
1709
		 47m set background color to white
1710
		 49m set background color to default (black)
1711 86a5e1a8 Renato Botelho
	*/
1712
	// Allow caching of TERM to
1713 fdf3af3f Scott Ullrich
	// speedup subequence requests.
1714
	global $TERM;
1715 86a5e1a8 Renato Botelho
	if(!$TERM)
1716 fdf3af3f Scott Ullrich
		$TERM=`/usr/bin/env | grep color`;
1717 78e0b65c Scott Ullrich
	if(!$TERM)
1718
		$TERM=`/usr/bin/env | grep cons25`;
1719 b927a013 Scott Ullrich
	if($TERM) {
1720 6028a72d Scott Ullrich
		$ESCAPE=chr(27);
1721 b927a013 Scott Ullrich
		switch ($color) {
1722 6028a72d Scott Ullrich
			case "black":
1723 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[30m";
1724 6028a72d Scott Ullrich
			case "red":
1725 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[31m";
1726 6028a72d Scott Ullrich
			case "green":
1727 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[32m";
1728 6028a72d Scott Ullrich
			case "yellow":
1729 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[33m";
1730 6028a72d Scott Ullrich
			case "blue":
1731 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[34m";
1732 6028a72d Scott Ullrich
			case "magenta":
1733 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[35m";
1734 6028a72d Scott Ullrich
			case "cyan":
1735 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[36m";
1736 6028a72d Scott Ullrich
			case "white":
1737 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[37m";
1738 6028a72d Scott Ullrich
			case "default":
1739 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[39m";
1740 b927a013 Scott Ullrich
		}
1741 385a3a31 Scott Ullrich
		return "{$ESCAPE}[{$color}";
1742 b927a013 Scott Ullrich
	}
1743 fdf3af3f Scott Ullrich
}
1744
1745 5e9dd72a sullrich
/****f* util/is_URL
1746
 * NAME
1747
 *   is_URL
1748
 * INPUTS
1749
 *   string to check
1750
 * RESULT
1751
 *   Returns true if item is a URL
1752
 ******/
1753
function is_URL($url) {
1754
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1755
	if($match)
1756 86a5e1a8 Renato Botelho
		return true;
1757 5e9dd72a sullrich
	return false;
1758
}
1759
1760 ab94ba00 Ermal Lu?i
function is_file_included($file = "") {
1761
	$files = get_included_files();
1762
	if (in_array($file, $files))
1763
		return true;
1764 86a5e1a8 Renato Botelho
1765 ab94ba00 Ermal Lu?i
	return false;
1766
}
1767
1768 0d90fcaf jim-p
/*
1769
	This function was borrowed from a comment on PHP.net at the following URL:
1770
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
1771
 */
1772 5bbd08e1 Warren Baker
function array_merge_recursive_unique($array0, $array1) {
1773
1774
	$arrays = func_get_args();
1775
	$remains = $arrays;
1776 0d90fcaf jim-p
1777 5bbd08e1 Warren Baker
	// We walk through each arrays and put value in the results (without
1778
	// considering previous value).
1779
	$result = array();
1780 0d90fcaf jim-p
1781 5bbd08e1 Warren Baker
	// loop available array
1782
	foreach($arrays as $array) {
1783 0d90fcaf jim-p
1784 5bbd08e1 Warren Baker
		// The first remaining array is $array. We are processing it. So
1785
		// we remove it from remaing arrays.
1786 86a5e1a8 Renato Botelho
		array_shift($remains);
1787 0d90fcaf jim-p
1788 5bbd08e1 Warren Baker
		// We don't care non array param, like array_merge since PHP 5.0.
1789
		if(is_array($array)) {
1790
			// Loop values
1791
			foreach($array as $key => $value) {
1792
				if(is_array($value)) {
1793
					// we gather all remaining arrays that have such key available
1794
					$args = array();
1795
					foreach($remains as $remain) {
1796
						if(array_key_exists($key, $remain)) {
1797
							array_push($args, $remain[$key]);
1798
						}
1799
					}
1800
1801
					if(count($args) > 2) {
1802
						// put the recursion
1803
						$result[$key] = call_user_func_array(__FUNCTION__, $args);
1804
					} else {
1805
						foreach($value as $vkey => $vval) {
1806
							$result[$key][$vkey] = $vval;
1807
						}
1808
					}
1809
				} else {
1810
					// simply put the value
1811
					$result[$key] = $value;
1812
				}
1813
			}
1814
		}
1815
	}
1816
	return $result;
1817 0d90fcaf jim-p
}
1818
1819 f898c1a9 jim-p
1820 9a456170 Darren Embry
/*
1821
 * converts a string like "a,b,c,d"
1822
 * into an array like array("a" => "b", "c" => "d")
1823
 */
1824
function explode_assoc($delimiter, $string) {
1825
	$array = explode($delimiter, $string);
1826
	$result = array();
1827
	$numkeys = floor(count($array) / 2);
1828
	for ($i = 0; $i < $numkeys; $i += 1) {
1829
		$result[$array[$i * 2]] = $array[$i * 2 + 1];
1830
	}
1831
	return $result;
1832
}
1833
1834 1901463c Renato Botelho
function get_staticroutes($returnsubnetsonly = false, $returnhostnames = false) {
1835
	global $config, $aliastable;
1836 f898c1a9 jim-p
1837
	/* Bail if there are no routes, but return an array always so callers don't have to check. */
1838
	if (!is_array($config['staticroutes']['route']))
1839
		return array();
1840
1841 bcab1b07 Ermal
	$allstaticroutes = array();
1842
	$allsubnets = array();
1843 f898c1a9 jim-p
	/* Loop through routes and expand aliases as we find them. */
1844
	foreach ($config['staticroutes']['route'] as $route) {
1845
		if (is_alias($route['network'])) {
1846 1901463c Renato Botelho
			if (!isset($aliastable[$route['network']]))
1847
				continue;
1848
1849
			$subnets = preg_split('/\s+/', $aliastable[$route['network']]);
1850 f898c1a9 jim-p
			foreach ($subnets as $net) {
1851 bcab1b07 Ermal
				if (!is_subnet($net)) {
1852
					if (is_ipaddrv4($net))
1853
						$net .= "/32";
1854
					else if (is_ipaddrv6($net))
1855
						$net .= "/128";
1856 1901463c Renato Botelho
					else if ($returnhostnames === false || !is_fqdn($net))
1857 bcab1b07 Ermal
						continue;
1858
				}
1859 f898c1a9 jim-p
				$temproute = $route;
1860
				$temproute['network'] = $net;
1861
				$allstaticroutes[] = $temproute;
1862
				$allsubnets[] = $net;
1863
			}
1864
		} elseif (is_subnet($route['network'])) {
1865
			$allstaticroutes[] = $route;
1866
			$allsubnets[] = $route['network'];
1867
		}
1868
	}
1869 bcab1b07 Ermal
	if ($returnsubnetsonly)
1870 f898c1a9 jim-p
		return $allsubnets;
1871 bcab1b07 Ermal
	else
1872 f898c1a9 jim-p
		return $allstaticroutes;
1873
}
1874 a0539faa Darren Embry
1875
/****f* util/get_alias_list
1876
 * NAME
1877
 *   get_alias_list - Provide a list of aliases.
1878
 * INPUTS
1879
 *   $type          - Optional, can be a string or array specifying what type(s) of aliases you need.
1880
 * RESULT
1881
 *   Array containing list of aliases.
1882
 *   If $type is unspecified, all aliases are returned.
1883
 *   If $type is a string, all aliases of the type specified in $type are returned.
1884
 *   If $type is an array, all aliases of any type specified in any element of $type are returned.
1885
 */
1886
function get_alias_list($type = null) {
1887
	global $config;
1888
	$result = array();
1889
	if ($config['aliases']['alias'] <> "" && is_array($config['aliases']['alias'])) {
1890
		foreach ($config['aliases']['alias'] as $alias) {
1891
			if ($type === null) {
1892
				$result[] = $alias['name'];
1893
			}
1894
			else if (is_array($type)) {
1895
				if (in_array($alias['type'], $type)) {
1896
					$result[] = $alias['name'];
1897
				}
1898
			}
1899
			else if ($type === $alias['type']) {
1900
				$result[] = $alias['name'];
1901
			}
1902
		}
1903 86a5e1a8 Renato Botelho
	}
1904 a0539faa Darren Embry
	return $result;
1905
}
1906
1907 4dfd930e Darren Embry
/* returns an array consisting of every element of $haystack that is not equal to $needle. */
1908
function array_exclude($needle, $haystack) {
1909
	$result = array();
1910
	if (is_array($haystack)) {
1911
		foreach ($haystack as $thing) {
1912
			if ($needle !== $thing) {
1913
				$result[] = $thing;
1914
			}
1915
		}
1916
	}
1917
	return $result;
1918
}
1919
1920 45930696 jim-p
function setup_library_paths() {
1921
	$current_library_paths = explode(":", exec("/sbin/ldconfig -r | /usr/bin/grep 'search directories' | /usr/bin/awk '{print $3;}'"));
1922 a2beee75 jim-p
	$pbi_library_paths = array_merge(glob("/usr/pbi/*/lib", GLOB_ONLYDIR), glob("/usr/pbi/*/lib/*", GLOB_ONLYDIR));
1923 45930696 jim-p
	foreach ($pbi_library_paths as $pbilib) {
1924
		if (!in_array($pbilib, $current_library_paths))
1925
			exec("/sbin/ldconfig -m {$pbilib}");
1926
	}
1927
}
1928
1929 1e1e1ec8 jim-p
function get_current_theme() {
1930
	global $config, $g;
1931
	/*
1932
	 *   if user has selected a custom template, use it.
1933
	 *   otherwise default to pfsense tempalte
1934
	 */
1935
	if (($g["disablethemeselection"] === true) && !empty($g["default_theme"]) && (is_dir($g["www_path"].'/themes/'.$g["default_theme"])))
1936
		$theme = $g["default_theme"];
1937
	elseif($config['theme'] <> "" && (is_dir($g["www_path"].'/themes/'.$config['theme'])))
1938
		$theme = $config['theme'];
1939
	else
1940
		$theme = "pfsense";
1941
	/*
1942
	 *  If this device is an apple ipod/iphone
1943
	 *  switch the theme to one that works with it.
1944
	 */
1945 2cf899d3 un0x
	$lowres_ua = array("iPhone", "iPod", "iPad", "Android", "BlackBerry", "Opera Mini", "Opera Mobi", "PlayBook", "IEMobile");
1946 1e1e1ec8 jim-p
	foreach($lowres_ua as $useragent)
1947
		if(strstr($_SERVER['HTTP_USER_AGENT'], $useragent))
1948
			$theme = (empty($g['theme_lowres']) && (is_dir($g["www_path"].'/themes/'.$g['theme_lowres']))) ? "pfsense" : $g['theme_lowres'];
1949
	return $theme;
1950
}
1951
1952 eb295a1b Ermal
?>