Project

General

Profile

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