Project

General

Profile

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