Project

General

Profile

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