Project

General

Profile

Download (52.9 KB) Statistics
| Branch: | Tag: | Revision:
1 86a5e1a8 Renato Botelho
<?php
2 417fc5c4 Scott Ullrich
/*
3 5b237745 Scott Ullrich
	util.inc
4 417fc5c4 Scott Ullrich
	part of the pfSense project (http://www.pfsense.com)
5 98bbf05a Scott Ullrich
6 417fc5c4 Scott Ullrich
	originally part of m0n0wall (http://m0n0.ch/wall)
7 5b237745 Scott Ullrich
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9 98bbf05a Scott Ullrich
10 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12 98bbf05a Scott Ullrich
13 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15 98bbf05a Scott Ullrich
16 5b237745 Scott Ullrich
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19 98bbf05a Scott Ullrich
20 5b237745 Scott Ullrich
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31
32 523855b0 Scott Ullrich
/*
33
	pfSense_BUILDER_BINARIES:	/bin/ps	/bin/kill	/usr/bin/killall	/sbin/ifconfig	/usr/bin/netstat
34
	pfSense_BUILDER_BINARIES:	/usr/bin/awk	/sbin/dmesg		/sbin/ping /usr/local/sbin/gzsig	/usr/sbin/arp
35
	pfSense_BUILDER_BINARIES:	/sbin/conscontrol	/sbin/devd	/bin/ps
36
	pfSense_MODULE:	utils
37
*/
38
39 5b237745 Scott Ullrich
/* kill a process by pid file */
40
function killbypid($pidfile) {
41 435a418f Ermal
	return sigkillbypid($pidfile, "TERM");
42 5b237745 Scott Ullrich
}
43
44 c4594e36 Phil Davis
function isvalidpid($pidfile) {
45 0e604b3a Ermal
	$output = "";
46 c4594e36 Phil Davis
	if (file_exists($pidfile)) {
47
		exec("/bin/pgrep -nF {$pidfile}", $output, $retval);
48
		return (intval($retval) == 0);
49
	}
50
	return false;
51 53aca1fd Scott Ullrich
}
52
53 6dc3a5c2 Ermal Lu?i
function is_process_running($process) {
54 01d4b621 Ermal
	$output = "";
55 1dd8c3b6 Ermal
	exec("/bin/pgrep -anx {$process}", $output, $retval);
56 6dc3a5c2 Ermal Lu?i
57 5bbd08e1 Warren Baker
	return (intval($retval) == 0);
58 6dc3a5c2 Ermal Lu?i
}
59
60 53aca1fd Scott Ullrich
function isvalidproc($proc) {
61 ba8495f0 Ermal
	return is_process_running($proc);
62 53aca1fd Scott Ullrich
}
63
64 5b237745 Scott Ullrich
/* sigkill a process by pid file */
65 53aca1fd Scott Ullrich
/* return 1 for success and 0 for a failure */
66 5b237745 Scott Ullrich
function sigkillbypid($pidfile, $sig) {
67 ac94ebd8 Ermal
	if (file_exists($pidfile))
68 ba8495f0 Ermal
		return mwexec("/bin/pkill -{$sig} -F {$pidfile}", true);
69
70 53aca1fd Scott Ullrich
	return 0;
71
}
72
73
/* kill a process by name */
74
function sigkillbyname($procname, $sig) {
75
	if(isvalidproc($procname))
76 73239086 Seth Mos
		return mwexec("/usr/bin/killall -{$sig} " . escapeshellarg($procname), true);
77 5b237745 Scott Ullrich
}
78
79
/* kill a process by name */
80
function killbyname($procname) {
81 86a5e1a8 Renato Botelho
	if(isvalidproc($procname))
82 53aca1fd Scott Ullrich
		mwexec("/usr/bin/killall " . escapeshellarg($procname));
83 5b237745 Scott Ullrich
}
84
85 a368a026 Ermal Lu?i
function is_subsystem_dirty($subsystem = "") {
86
	global $g;
87
88
	if ($subsystem == "")
89
		return false;
90
91
	if (file_exists("{$g['varrun_path']}/{$subsystem}.dirty"))
92
		return true;
93
94
	return false;
95
}
96
97
function mark_subsystem_dirty($subsystem = "") {
98
	global $g;
99
100
	if (!file_put_contents("{$g['varrun_path']}/{$subsystem}.dirty", "DIRTY"))
101 fd7b47b6 Renato Botelho
		log_error(sprintf(gettext("WARNING: Could not mark subsystem: %s dirty"), $subsystem));
102 a368a026 Ermal Lu?i
}
103
104
function clear_subsystem_dirty($subsystem = "") {
105
	global $g;
106
107
	@unlink("{$g['varrun_path']}/{$subsystem}.dirty");
108
}
109
110 0027de0a Ermal Lu?i
function config_lock() {
111
	return;
112
}
113
function config_unlock() {
114
	return;
115
}
116
117
/* lock configuration file */
118 b6c34bfc Ermal
function lock($lock, $op = LOCK_SH) {
119 9e7ef1a5 Scott Ullrich
	global $g, $cfglckkeyconsumers;
120
	if (!$lock)
121 fd7b47b6 Renato Botelho
		die(gettext("WARNING: You must give a name as parameter to lock() function."));
122 6bee76d5 Ermal
	if (!file_exists("{$g['tmp_path']}/{$lock}.lock")) {
123 9e7ef1a5 Scott Ullrich
		@touch("{$g['tmp_path']}/{$lock}.lock");
124 6bee76d5 Ermal
		@chmod("{$g['tmp_path']}/{$lock}.lock", 0666);
125
	}
126 9e7ef1a5 Scott Ullrich
	$cfglckkeyconsumers++;
127 b6c34bfc Ermal
	if ($fp = fopen("{$g['tmp_path']}/{$lock}.lock", "w")) {
128
		if (flock($fp, $op))
129 9e7ef1a5 Scott Ullrich
			return $fp;
130 b6c34bfc Ermal
		else
131
			fclose($fp);
132 9e7ef1a5 Scott Ullrich
	}
133 0027de0a Ermal Lu?i
}
134
135 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 da6cb29e Renato Botelho
/* returns true if $test is in the range between $start and $end */
798
function is_inrange($test, $start, $end) {
799
	return is_ipaddrv6($test) ? is_inrange_v6($test, $start, $end) : is_inrange_v4($test, $start, $end);
800
}
801
802 7238e0cf Ermal
/* XXX: return the configured carp interface list */
803 abcb2bed Ermal Lu?i
function get_configured_carp_interface_list() {
804
	global $config;
805
806
	$iflist = array();
807
808
	if(is_array($config['virtualip']['vip'])) {
809 5bbd08e1 Warren Baker
		$viparr = &$config['virtualip']['vip'];
810
		foreach ($viparr as $vip) {
811
			switch ($vip['mode']) {
812 7b47bd4c Ermal
			case "carp":
813 049ed50d Ermal
				$vipif = get_real_interface($vip['interface']) . "@{$vip['vhid']}";
814 7b47bd4c Ermal
				$iflist[$vipif] = $vip['subnet'];
815
				break;
816 5bbd08e1 Warren Baker
			}
817
		}
818
	}
819 abcb2bed Ermal Lu?i
820
	return $iflist;
821
}
822
823 67b0902f pierrepomes
/* return the configured IP aliases list */
824 a119ecf8 Erik Fonnesbeck
function get_configured_ip_aliases_list($returnfullentry = false) {
825 5bbd08e1 Warren Baker
	global $config;
826 67b0902f pierrepomes
827 5bbd08e1 Warren Baker
	$alias_list=array();
828 67b0902f pierrepomes
829 5bbd08e1 Warren Baker
	if(is_array($config['virtualip']['vip'])) {
830
		$viparr = &$config['virtualip']['vip'];
831
		foreach ($viparr as $vip) {
832
			if ($vip['mode']=="ipalias") {
833 a119ecf8 Erik Fonnesbeck
				if ($returnfullentry)
834
					$alias_list[$vip['subnet']] = $vip;
835
				else
836
					$alias_list[$vip['subnet']] = $vip['interface'];
837 5bbd08e1 Warren Baker
			}
838
		}
839
	}
840 67b0902f pierrepomes
841 5bbd08e1 Warren Baker
	return $alias_list;
842 67b0902f pierrepomes
}
843
844 e6c60013 Renato Botelho
/* return all configured aliases list (IP, carp, proxyarp and other) */
845
function get_configured_vips_list() {
846
	global $config;
847
848
	$alias_list=array();
849
850
	if(is_array($config['virtualip']['vip'])) {
851
		$viparr = &$config['virtualip']['vip'];
852
		foreach ($viparr as $vip)
853
			$alias_list[] = array("ipaddr" => $vip['subnet'], "if" => $vip['interface']);
854
	}
855
856
	return $alias_list;
857
}
858 67b0902f pierrepomes
859 88bc2760 Erik Fonnesbeck
/* comparison function for sorting by the order in which interfaces are normally created */
860
function compare_interface_friendly_names($a, $b) {
861
	if ($a == $b)
862
		return 0;
863
	else if ($a == 'wan')
864
		return -1;
865
	else if ($b == 'wan')
866
		return 1;
867
	else if ($a == 'lan')
868
		return -1;
869
	else if ($b == 'lan')
870
		return 1;
871
872
	return strnatcmp($a, $b);
873
}
874
875 c8abe1d4 Ermal Luçi
/* return the configured interfaces list. */
876 3ad5e089 Ermal Luçi
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
877 c8abe1d4 Ermal Luçi
	global $config;
878
879
	$iflist = array();
880 14f49fd0 Erik Fonnesbeck
881 c8abe1d4 Ermal Luçi
	/* if list */
882 8735afe8 Erik Fonnesbeck
	foreach($config['interfaces'] as $if => $ifdetail) {
883
		if ($only_opt && ($if == "wan" || $if == "lan"))
884 42c9d20e Ermal Luçi
			continue;
885 47c8b036 Ermal Lu?i
		if (isset($ifdetail['enable']) || $withdisabled == true)
886 c8abe1d4 Ermal Luçi
			$iflist[$if] = $if;
887 42c9d20e Ermal Luçi
	}
888 c8abe1d4 Ermal Luçi
889
	return $iflist;
890
}
891
892 bb34737f Ermal Lu?i
/* return the configured interfaces list. */
893
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
894 8735afe8 Erik Fonnesbeck
	global $config;
895 bb34737f Ermal Lu?i
896 8735afe8 Erik Fonnesbeck
	$iflist = array();
897 bb34737f Ermal Lu?i
898 8735afe8 Erik Fonnesbeck
	/* if list */
899
	foreach($config['interfaces'] as $if => $ifdetail) {
900
		if ($only_opt && ($if == "wan" || $if == "lan"))
901
			continue;
902
		if (isset($ifdetail['enable']) || $withdisabled == true) {
903 bb34737f Ermal Lu?i
			$tmpif = get_real_interface($if);
904
			if (!empty($tmpif))
905
				$iflist[$tmpif] = $if;
906
		}
907 8735afe8 Erik Fonnesbeck
	}
908 bb34737f Ermal Lu?i
909 8735afe8 Erik Fonnesbeck
	return $iflist;
910 bb34737f Ermal Lu?i
}
911
912 c8abe1d4 Ermal Luçi
/* return the configured interfaces list with their description. */
913 3ad5e089 Ermal Luçi
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
914 a42d1da2 Scott Ullrich
	global $config;
915 c8abe1d4 Ermal Luçi
916 a42d1da2 Scott Ullrich
	$iflist = array();
917 c8abe1d4 Ermal Luçi
918 a42d1da2 Scott Ullrich
	/* if list */
919
	foreach($config['interfaces'] as $if => $ifdetail) {
920 8735afe8 Erik Fonnesbeck
		if ($only_opt && ($if == "wan" || $if == "lan"))
921
			continue;
922 47c8b036 Ermal Lu?i
		if (isset($ifdetail['enable']) || $withdisabled == true) {
923 8735afe8 Erik Fonnesbeck
			if(empty($ifdetail['descr']))
924 8e74cb8d Ermal Luçi
				$iflist[$if] = strtoupper($if);
925 a42d1da2 Scott Ullrich
			else
926 44b0ec83 Scott Ullrich
				$iflist[$if] = strtoupper($ifdetail['descr']);
927 0e218dc1 Ermal Luçi
		}
928 42c9d20e Ermal Luçi
	}
929 c8abe1d4 Ermal Luçi
930 a42d1da2 Scott Ullrich
	return $iflist;
931 c8abe1d4 Ermal Luçi
}
932
933 4fe9c2dc Scott Ullrich
/*
934
 *   get_configured_ip_addresses() - Return a list of all configured
935
 *   interfaces IP Addresses
936
 *
937
 */
938
function get_configured_ip_addresses() {
939 5dbd619f smos
	global $config;
940 a1e4e2a7 Ermal
941 d97741c2 Ermal
	if (!function_exists('get_interface_ip'))
942 a1e4e2a7 Ermal
		require_once("interfaces.inc");
943 4fe9c2dc Scott Ullrich
	$ip_array = array();
944
	$interfaces = get_configured_interface_list();
945 a1e4e2a7 Ermal
	if (is_array($interfaces)) {
946 d9114ce0 Scott Ullrich
		foreach($interfaces as $int) {
947
			$ipaddr = get_interface_ip($int);
948
			$ip_array[$int] = $ipaddr;
949
		}
950 4fe9c2dc Scott Ullrich
	}
951 19f101d7 Scott Ullrich
	$interfaces = get_configured_carp_interface_list();
952 86a5e1a8 Renato Botelho
	if (is_array($interfaces))
953
		foreach($interfaces as $int => $ipaddr)
954 d9114ce0 Scott Ullrich
			$ip_array[$int] = $ipaddr;
955 5dbd619f smos
956
	/* pppoe server */
957 a1e4e2a7 Ermal
	if (is_array($config['pppoes']) && is_array($config['pppoes']['pppoe'])) {
958 5dbd619f smos
		foreach($config['pppoes']['pppoe'] as $pppoe) {
959
			if ($pppoe['mode'] == "server") {
960
				if(is_ipaddr($pppoe['localip'])) {
961
					$int = "pppoes". $pppoe['pppoeid'];
962
					$ip_array[$int] = $pppoe['localip'];
963
				}
964
			}
965
		}
966
	}
967 a1e4e2a7 Ermal
968 4fe9c2dc Scott Ullrich
	return $ip_array;
969
}
970 c8abe1d4 Ermal Luçi
971 e6f7e0be smos
/*
972
 *   get_configured_ipv6_addresses() - Return a list of all configured
973
 *   interfaces IPv6 Addresses
974
 *
975
 */
976
function get_configured_ipv6_addresses() {
977
	require_once("interfaces.inc");
978
	$ipv6_array = array();
979
	$interfaces = get_configured_interface_list();
980
	if(is_array($interfaces)) {
981
		foreach($interfaces as $int) {
982
			$ipaddrv6 = get_interface_ipv6($int);
983
			$ipv6_array[$int] = $ipaddrv6;
984
		}
985
	}
986
	$interfaces = get_configured_carp_interface_list();
987 86a5e1a8 Renato Botelho
	if(is_array($interfaces))
988
		foreach($interfaces as $int => $ipaddrv6)
989 e6f7e0be smos
			$ipv6_array[$int] = $ipaddrv6;
990
	return $ipv6_array;
991
}
992
993 36f546e9 Scott Ullrich
/*
994
 *   get_interface_list() - Return a list of all physical interfaces
995
 *   along with MAC and status.
996
 *
997
 *   $mode = "active" - use ifconfig -lu
998
 *           "media"  - use ifconfig to check physical connection
999
 *			status (much slower)
1000
 */
1001
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
1002 86a5e1a8 Renato Botelho
	global $config;
1003 65bed2d2 Scott Ullrich
	$upints = array();
1004 86a5e1a8 Renato Botelho
	/* get a list of virtual interface types */
1005
	if(!$vfaces) {
1006 9ce38409 Scott Ullrich
		$vfaces = array (
1007
				'bridge',
1008
				'ppp',
1009 27c0c7c6 Ermal Lu?i
				'pppoe',
1010
				'pptp',
1011
				'l2tp',
1012 9ce38409 Scott Ullrich
				'sl',
1013
				'gif',
1014 613571ea Ermal Luçi
				'gre',
1015 9ce38409 Scott Ullrich
				'faith',
1016
				'lo',
1017
				'ng',
1018 27616d6e Seth Mos
				'_vlan',
1019 7c53bc7b Erik Fonnesbeck
				'_wlan',
1020 9ce38409 Scott Ullrich
				'pflog',
1021 a42d1da2 Scott Ullrich
				'plip',
1022 9ce38409 Scott Ullrich
				'pfsync',
1023
				'enc',
1024
				'tun',
1025 0a140d2e Ermal Luçi
				'carp',
1026 1fb2bf25 Ermal Lu?i
				'lagg',
1027 1fd35e95 Ermal
				'vip',
1028
				'ipfw'
1029 9ce38409 Scott Ullrich
		);
1030 36f546e9 Scott Ullrich
	}
1031 20203646 Colin Smith
	switch($mode) {
1032
	case "active":
1033 86a5e1a8 Renato Botelho
		$upints = pfSense_interface_listget(IFF_UP);
1034
		break;
1035 20203646 Colin Smith
	case "media":
1036 d9adca3b Ermal
		$intlist = pfSense_interface_listget();
1037 86a5e1a8 Renato Botelho
		$ifconfig = "";
1038
		exec("/sbin/ifconfig -a", $ifconfig);
1039
		$regexp = '/(' . implode('|', $intlist) . '):\s/';
1040
		$ifstatus = preg_grep('/status:/', $ifconfig);
1041 49149b86 Colin Smith
		foreach($ifstatus as $status) {
1042 bb3b9159 Colin Smith
			$int = array_shift($intlist);
1043 5bbd08e1 Warren Baker
			if(stristr($status, "active")) $upints[] = $int;
1044 49149b86 Colin Smith
		}
1045 20203646 Colin Smith
		break;
1046 72993196 Ermal
	default:
1047 d9adca3b Ermal
		$upints = pfSense_interface_listget();
1048 72993196 Ermal
		break;
1049 20203646 Colin Smith
	}
1050 86a5e1a8 Renato Botelho
	/* build interface list with netstat */
1051
	$linkinfo = "";
1052
	exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
1053
	array_shift($linkinfo);
1054 89d1f0f2 Scott Ullrich
	/* build ip address list with netstat */
1055 767a716e Scott Ullrich
	$ipinfo = "";
1056 89d1f0f2 Scott Ullrich
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
1057
	array_shift($ipinfo);
1058
	foreach($linkinfo as $link) {
1059
		$friendly = "";
1060 5bbd08e1 Warren Baker
		$alink = explode(" ", $link);
1061
		$ifname = rtrim(trim($alink[0]), '*');
1062
		/* trim out all numbers before checking for vfaces */
1063 494be6e8 Ermal Lu?i
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces) &&
1064 7c53bc7b Erik Fonnesbeck
			!stristr($ifname, "_vlan") && !stristr($ifname, "_wlan")) {
1065 20203646 Colin Smith
			$toput = array(
1066
					"mac" => trim($alink[1]),
1067
					"up" => in_array($ifname, $upints)
1068
				);
1069 89d1f0f2 Scott Ullrich
			foreach($ipinfo as $ip) {
1070
				$aip = explode(" ", $ip);
1071
				if($aip[0] == $ifname) {
1072
					$toput['ipaddr'] = $aip[1];
1073
				}
1074
			}
1075 72993196 Ermal
			if (is_array($config['interfaces'])) {
1076
				foreach($config['interfaces'] as $name => $int)
1077
					if($int['if'] == $ifname) $friendly = $name;
1078 20203646 Colin Smith
			}
1079
			switch($keyby) {
1080
			case "physical":
1081 89d1f0f2 Scott Ullrich
				if($friendly != "") {
1082
					$toput['friendly'] = $friendly;
1083
				}
1084 a296c95d Seth Mos
				$dmesg_arr = array();
1085
				exec("/sbin/dmesg |grep $ifname | head -n1", $dmesg_arr);
1086
				preg_match_all("/<(.*?)>/i", $dmesg_arr[0], $dmesg);
1087
				$toput['dmesg'] = $dmesg[1][0];
1088 20203646 Colin Smith
				$iflist[$ifname] = $toput;
1089 3154d7ed Colin Smith
				break;
1090 4aca19b3 Scott Ullrich
			case "ppp":
1091 86a5e1a8 Renato Botelho
1092 20203646 Colin Smith
			case "friendly":
1093 89d1f0f2 Scott Ullrich
				if($friendly != "") {
1094
					$toput['if'] = $ifname;
1095
					$iflist[$friendly] = $toput;
1096
				}
1097 3154d7ed Colin Smith
				break;
1098
			}
1099 5bbd08e1 Warren Baker
		}
1100
	}
1101
	return $iflist;
1102 5b237745 Scott Ullrich
}
1103
1104 2b4d37de Ermal Lu?i
/****f* util/log_error
1105
* NAME
1106
*   log_error  - Sends a string to syslog.
1107
* INPUTS
1108
*   $error     - string containing the syslog message.
1109
* RESULT
1110
*   null
1111
******/
1112
function log_error($error) {
1113 5bbd08e1 Warren Baker
	global $g;
1114
	$page = $_SERVER['SCRIPT_NAME'];
1115 866b1d61 jim-p
	if (empty($page)) {
1116
		$files = get_included_files();
1117
		$page = basename($files[0]);
1118
	}
1119 0d0cb047 jim-p
	syslog(LOG_ERR, "$page: $error");
1120 5bbd08e1 Warren Baker
	if ($g['debug'])
1121
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
1122
	return;
1123 2b4d37de Ermal Lu?i
}
1124
1125 3aba1835 Scott Ullrich
/****f* util/log_auth
1126
* NAME
1127 1198abf9 PiBa-NL
*   log_auth   - Sends a string to syslog as LOG_AUTH facility
1128 3aba1835 Scott Ullrich
* INPUTS
1129
*   $error     - string containing the syslog message.
1130
* RESULT
1131
*   null
1132
******/
1133
function log_auth($error) {
1134 5bbd08e1 Warren Baker
	global $g;
1135
	$page = $_SERVER['SCRIPT_NAME'];
1136
	syslog(LOG_AUTH, "$page: $error");
1137
	if ($g['debug'])
1138
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
1139
	return;
1140 3aba1835 Scott Ullrich
}
1141
1142 83bc3749 Ermal Lu?i
/****f* util/exec_command
1143
 * NAME
1144
 *   exec_command - Execute a command and return a string of the result.
1145
 * INPUTS
1146
 *   $command   - String of the command to be executed.
1147
 * RESULT
1148
 *   String containing the command's result.
1149
 * NOTES
1150
 *   This function returns the command's stdout and stderr.
1151
 ******/
1152
function exec_command($command) {
1153 5bbd08e1 Warren Baker
	$output = array();
1154
	exec($command . ' 2>&1 ', $output);
1155
	return(implode("\n", $output));
1156 83bc3749 Ermal Lu?i
}
1157
1158 5b237745 Scott Ullrich
/* wrapper for exec() */
1159 b61e8960 jim-p
function mwexec($command, $mute = false, $clearsigmask = false) {
1160 5b237745 Scott Ullrich
	global $g;
1161 435a418f Ermal
1162 5b237745 Scott Ullrich
	if ($g['debug']) {
1163
		if (!$_SERVER['REMOTE_ADDR'])
1164
			echo "mwexec(): $command\n";
1165 f9db3cda Seth Mos
	}
1166 435a418f Ermal
	$oarr = array();
1167
	$retval = 0;
1168 b61e8960 jim-p
1169
	if ($clearsigmask) {
1170
		$oldset = array();
1171
		pcntl_sigprocmask(SIG_SETMASK, array(), $oldset);
1172
	}
1173 435a418f Ermal
	$garbage = exec("$command 2>&1", $oarr, $retval);
1174 b61e8960 jim-p
	if ($clearsigmask) {
1175
		pcntl_sigprocmask(SIG_SETMASK, $oldset);
1176
	}
1177 435a418f Ermal
1178 61c6b6c1 Chris Buechler
	if(isset($config['system']['developerspew']))
1179 5bbd08e1 Warren Baker
		$mute = false;
1180 12169c92 Seth Mos
	if(($retval <> 0) && ($mute === false)) {
1181 f9db3cda Seth Mos
		$output = implode(" ", $oarr);
1182 addc0439 Renato Botelho
		log_error(sprintf(gettext("The command '%1\$s' returned exit code '%2\$d', the output was '%3\$s' "), $command, $retval, $output));
1183 5b237745 Scott Ullrich
	}
1184 98bbf05a Scott Ullrich
	return $retval;
1185 5b237745 Scott Ullrich
}
1186
1187
/* wrapper for exec() in background */
1188 b61e8960 jim-p
function mwexec_bg($command, $clearsigmask = false) {
1189 5b237745 Scott Ullrich
	global $g;
1190 98bbf05a Scott Ullrich
1191 5b237745 Scott Ullrich
	if ($g['debug']) {
1192
		if (!$_SERVER['REMOTE_ADDR'])
1193
			echo "mwexec(): $command\n";
1194
	}
1195 98bbf05a Scott Ullrich
1196 b61e8960 jim-p
	if ($clearsigmask) {
1197
		$oldset = array();
1198
		pcntl_sigprocmask(SIG_SETMASK, array(), $oldset);
1199
	}
1200 77daff18 Ermal
	$_gb = exec("/usr/bin/nohup $command > /dev/null 2>&1 &");
1201 b61e8960 jim-p
	if ($clearsigmask) {
1202
		pcntl_sigprocmask(SIG_SETMASK, $oldset);
1203
	}
1204 fba1804f Ermal
	unset($_gb);
1205 5b237745 Scott Ullrich
}
1206
1207
/* unlink a file, if it exists */
1208
function unlink_if_exists($fn) {
1209 336cb718 Scott Ullrich
	$to_do = glob($fn);
1210 3b378be5 Scott Ullrich
	if(is_array($to_do)) {
1211 336cb718 Scott Ullrich
		foreach($to_do as $filename)
1212 9ff926a2 Colin Smith
			@unlink($filename);
1213 336cb718 Scott Ullrich
	} else {
1214 9ff926a2 Colin Smith
		@unlink($fn);
1215 336cb718 Scott Ullrich
	}
1216 5b237745 Scott Ullrich
}
1217
/* make a global alias table (for faster lookups) */
1218 918a884d Bill Marquette
function alias_make_table($config) {
1219
	global $aliastable;
1220 98bbf05a Scott Ullrich
1221 5b237745 Scott Ullrich
	$aliastable = array();
1222 98bbf05a Scott Ullrich
1223 5b237745 Scott Ullrich
	if (is_array($config['aliases']['alias'])) {
1224
		foreach ($config['aliases']['alias'] as $alias) {
1225
			if ($alias['name'])
1226
				$aliastable[$alias['name']] = $alias['address'];
1227
		}
1228
	}
1229
}
1230 5ffa3389 Ermal
1231 5b237745 Scott Ullrich
/* check if an alias exists */
1232
function is_alias($name) {
1233
	global $aliastable;
1234 98bbf05a Scott Ullrich
1235 5b237745 Scott Ullrich
	return isset($aliastable[$name]);
1236 b8014f9d Scott Ullrich
}
1237 27ff8a3c Scott Ullrich
1238 5ffa3389 Ermal
function alias_get_type($name) {
1239 86a5e1a8 Renato Botelho
	global $config;
1240
1241 5ffa3389 Ermal
	if (is_array($config['aliases']['alias'])) {
1242
		foreach ($config['aliases']['alias'] as $alias) {
1243
			if ($name == $alias['name'])
1244
				return $alias['type'];
1245
		}
1246
	}
1247
1248 86a5e1a8 Renato Botelho
	return "";
1249 5ffa3389 Ermal
}
1250
1251 5b237745 Scott Ullrich
/* expand a host or network alias, if necessary */
1252
function alias_expand($name) {
1253
	global $aliastable;
1254 98bbf05a Scott Ullrich
1255 87f0be87 Chris Buechler
	if (isset($aliastable[$name]))
1256 4335dc87 Bill Marquette
		return "\${$name}";
1257 a584475a Ermal Lu?i
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
1258 57989da5 Scott Ullrich
		return "{$name}";
1259 87f0be87 Chris Buechler
	else
1260 5b237745 Scott Ullrich
		return null;
1261
}
1262
1263 c7de8be4 jim-p
function alias_expand_urltable($name) {
1264
	global $config;
1265
	$urltable_prefix = "/var/db/aliastables/";
1266
	$urltable_filename = $urltable_prefix . $name . ".txt";
1267
1268 5ffa3389 Ermal
	if (is_array($config['aliases']['alias'])) {
1269
		foreach ($config['aliases']['alias'] as $alias) {
1270 dd042c51 Renato Botelho
			if (preg_match("/urltable/i", $alias['type']) && ($alias['name'] == $name)) {
1271 5ffa3389 Ermal
				if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
1272
					return $urltable_filename;
1273
				else if (process_alias_urltable($name, $alias["url"], 0, true))
1274
					return $urltable_filename;
1275
			}
1276 c7de8be4 jim-p
		}
1277
	}
1278
	return null;
1279
}
1280
1281 dbea91b3 bcyrill
function subnet_size($subnet) {
1282 0917cb21 Darren Embry
	if (is_subnetv4($subnet)) {
1283
		list ($ip, $bits) = explode("/", $subnet);
1284
		return round(exp(log(2) * (32 - $bits)));
1285
	}
1286
	else if (is_subnetv6($subnet)) {
1287
		list ($ip, $bits) = explode("/", $subnet);
1288
		return round(exp(log(2) * (128 - $bits)));
1289
	}
1290
	else {
1291
		return 0;
1292
	}
1293
}
1294
1295 dbea91b3 bcyrill
function subnet_expand($subnet) {
1296 0917cb21 Darren Embry
	if (is_subnetv4($subnet)) {
1297
		return subnetv4_expand($subnet);
1298
	} else if (is_subnetv6($subnet)) {
1299
		return subnetv6_expand($subnet);
1300
	} else {
1301
		return $subnet;
1302
	}
1303
}
1304
1305 dbea91b3 bcyrill
function subnetv4_expand($subnet) {
1306 0917cb21 Darren Embry
	$result = array();
1307
	list ($ip, $bits) = explode("/", $subnet);
1308
	$net  = ip2long($ip);
1309
	$mask = (0xffffffff << (32 - $bits));
1310
	$net &= $mask;
1311
	$size = round(exp(log(2) * (32 - $bits)));
1312
	for ($i = 0; $i < $size; $i += 1) {
1313
		$result[] = long2ip($net | $i);
1314
	}
1315
	return $result;
1316
}
1317
1318 5b237745 Scott Ullrich
/* find out whether two subnets overlap */
1319
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
1320
1321
	if (!is_numeric($bits1))
1322
		$bits1 = 32;
1323
	if (!is_numeric($bits2))
1324
		$bits2 = 32;
1325
1326
	if ($bits1 < $bits2)
1327
		$relbits = $bits1;
1328
	else
1329
		$relbits = $bits2;
1330 98bbf05a Scott Ullrich
1331 5b237745 Scott Ullrich
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
1332
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
1333 98bbf05a Scott Ullrich
1334 e371f8b9 whjvenyl
	return ($sn1 == $sn2);
1335 5b237745 Scott Ullrich
}
1336
1337 dbea91b3 bcyrill
/* find out whether two IPv6 subnets overlap */
1338
function check_subnetsv6_overlap($subnet1, $bits1, $subnet2, $bits2) {
1339
	$sub1_min = gen_subnetv6($subnet1, $bits1);
1340
	$sub1_max = gen_subnetv6_max($subnet1, $bits1);
1341
	$sub2_min = gen_subnetv6($subnet2, $bits2);
1342
	$sub2_max = gen_subnetv6_max($subnet2, $bits2);
1343 86a5e1a8 Renato Botelho
1344 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));
1345 dbea91b3 bcyrill
}
1346
1347 5b237745 Scott Ullrich
/* compare two IP addresses */
1348
function ipcmp($a, $b) {
1349 96033063 Erik Fonnesbeck
	if (ip_less_than($a, $b))
1350 5b237745 Scott Ullrich
		return -1;
1351 96033063 Erik Fonnesbeck
	else if (ip_greater_than($a, $b))
1352 5b237745 Scott Ullrich
		return 1;
1353
	else
1354
		return 0;
1355
}
1356
1357
/* return true if $addr is in $subnet, false if not */
1358
function ip_in_subnet($addr,$subnet) {
1359 c75a8185 Seth Mos
	if(is_ipaddrv6($addr)) {
1360 83a12422 Ermal
		return (Net_IPv6::isInNetmask($addr, $subnet));
1361
	} else { /* XXX: Maybe check for IPv4 */
1362
		list($ip, $mask) = explode('/', $subnet);
1363
		$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
1364
		return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
1365 c75a8185 Seth Mos
	}
1366 5b237745 Scott Ullrich
}
1367
1368
/* verify (and remove) the digital signature on a file - returns 0 if OK */
1369
function verify_digital_signature($fname) {
1370
	global $g;
1371
1372 c50da179 Scott Ullrich
	if(!file_exists("/usr/local/sbin/gzsig"))
1373 9f007e8c Chris Buechler
		return 4;
1374 c50da179 Scott Ullrich
1375 f024f52d Scott Ullrich
	return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname));
1376 5b237745 Scott Ullrich
}
1377
1378
/* obtain MAC address given an IP address by looking at the ARP table */
1379
function arp_get_mac_by_ip($ip) {
1380 f3ebffee Ermal Lu?i
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
1381 767a716e Scott Ullrich
	$arpoutput = "";
1382 5b237745 Scott Ullrich
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
1383 98bbf05a Scott Ullrich
1384 5b237745 Scott Ullrich
	if ($arpoutput[0]) {
1385
		$arpi = explode(" ", $arpoutput[0]);
1386
		$macaddr = $arpi[3];
1387
		if (is_macaddr($macaddr))
1388
			return $macaddr;
1389
		else
1390
			return false;
1391
	}
1392 98bbf05a Scott Ullrich
1393 5b237745 Scott Ullrich
	return false;
1394
}
1395
1396 98bbf05a Scott Ullrich
/* return a fieldname that is safe for xml usage */
1397
function xml_safe_fieldname($fieldname) {
1398 87f0be87 Chris Buechler
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
1399
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
1400 ddce8ef2 Colin Smith
			 ':', ',', '.', '\'', '\\'
1401
		);
1402
	return strtolower(str_replace($replace, "", $fieldname));
1403 98bbf05a Scott Ullrich
}
1404
1405 805b9ab6 Ermal
function mac_format($clientmac) {
1406 86a5e1a8 Renato Botelho
	global $config, $cpzone;
1407 4129df39 Scott Ullrich
1408 86a5e1a8 Renato Botelho
	$mac = explode(":", $clientmac);
1409
	$mac_format = $cpzone ? $config['captiveportal'][$cpzone]['radmac_format'] : false;
1410 4129df39 Scott Ullrich
1411 86a5e1a8 Renato Botelho
	switch($mac_format) {
1412
	case 'singledash':
1413 7b89ea6a Ermal
		return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
1414 4129df39 Scott Ullrich
1415 86a5e1a8 Renato Botelho
	case 'ietf':
1416 7b89ea6a Ermal
		return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
1417 4129df39 Scott Ullrich
1418 86a5e1a8 Renato Botelho
	case 'cisco':
1419 7b89ea6a Ermal
		return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
1420 4129df39 Scott Ullrich
1421 86a5e1a8 Renato Botelho
	case 'unformatted':
1422 7b89ea6a Ermal
		return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
1423 4129df39 Scott Ullrich
1424 86a5e1a8 Renato Botelho
	default:
1425 7b89ea6a Ermal
		return $clientmac;
1426 86a5e1a8 Renato Botelho
	}
1427 4129df39 Scott Ullrich
}
1428
1429 979cd6db Scott Ullrich
function resolve_retry($hostname, $retries = 5) {
1430
1431 5bbd08e1 Warren Baker
	if (is_ipaddr($hostname))
1432
		return $hostname;
1433 979cd6db Scott Ullrich
1434 86a5e1a8 Renato Botelho
	for ($i = 0; $i < $retries; $i++) {
1435 6c4f3b54 Seth Mos
		// FIXME: gethostbyname does not work for AAAA hostnames, boo, hiss
1436 86a5e1a8 Renato Botelho
		$ip = gethostbyname($hostname);
1437 979cd6db Scott Ullrich
1438 5bbd08e1 Warren Baker
		if ($ip && $ip != $hostname) {
1439
			/* success */
1440
			return $ip;
1441
		}
1442 979cd6db Scott Ullrich
1443 5bbd08e1 Warren Baker
		sleep(1);
1444
	}
1445 979cd6db Scott Ullrich
1446 5bbd08e1 Warren Baker
	return false;
1447 979cd6db Scott Ullrich
}
1448
1449 44bfd1fa Scott Ullrich
function format_bytes($bytes) {
1450
	if ($bytes >= 1073741824) {
1451
		return sprintf("%.2f GB", $bytes/1073741824);
1452
	} else if ($bytes >= 1048576) {
1453
		return sprintf("%.2f MB", $bytes/1048576);
1454
	} else if ($bytes >= 1024) {
1455
		return sprintf("%.0f KB", $bytes/1024);
1456
	} else {
1457
		return sprintf("%d bytes", $bytes);
1458
	}
1459
}
1460
1461 2b4d37de Ermal Lu?i
function update_filter_reload_status($text) {
1462 5bbd08e1 Warren Baker
	global $g;
1463 2b4d37de Ermal Lu?i
1464 5bbd08e1 Warren Baker
	file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1465 2b4d37de Ermal Lu?i
}
1466
1467 a2219caf Renato Botelho
/****** util/return_dir_as_array
1468 2b4d37de Ermal Lu?i
 * NAME
1469
 *   return_dir_as_array - Return a directory's contents as an array.
1470
 * INPUTS
1471 a2219caf Renato Botelho
 *   $dir          - string containing the path to the desired directory.
1472
 *   $filter_regex - string containing a regular expression to filter file names. Default empty.
1473 2b4d37de Ermal Lu?i
 * RESULT
1474
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1475
 ******/
1476 a2219caf Renato Botelho
function return_dir_as_array($dir, $filter_regex = '') {
1477 5bbd08e1 Warren Baker
	$dir_array = array();
1478
	if (is_dir($dir)) {
1479
		if ($dh = opendir($dir)) {
1480
			while (($file = readdir($dh)) !== false) {
1481 a2219caf Renato Botelho
				if (($file == ".") || ($file == ".."))
1482
					continue;
1483
1484
				if (empty($filter_regex) || preg_match($filter_regex, $file))
1485 5bbd08e1 Warren Baker
					array_push($dir_array, $file);
1486
			}
1487
			closedir($dh);
1488
		}
1489
	}
1490
	return $dir_array;
1491 2b4d37de Ermal Lu?i
}
1492
1493
function run_plugins($directory) {
1494 5bbd08e1 Warren Baker
	global $config, $g;
1495
1496
	/* process packager manager custom rules */
1497
	$files = return_dir_as_array($directory);
1498
	if (is_array($files)) {
1499
		foreach ($files as $file) {
1500
			if (stristr($file, ".sh") == true)
1501
				mwexec($directory . $file . " start");
1502 86a5e1a8 Renato Botelho
			else if (!is_dir($directory . "/" . $file) && stristr($file,".inc"))
1503 5bbd08e1 Warren Baker
				require_once($directory . "/" . $file);
1504 2990acf8 Scott Ullrich
		}
1505 5bbd08e1 Warren Baker
	}
1506 2b4d37de Ermal Lu?i
}
1507
1508
/*
1509
 *    safe_mkdir($path, $mode = 0755)
1510
 *    create directory if it doesn't already exist and isn't a file!
1511
 */
1512
function safe_mkdir($path, $mode=0755) {
1513 5bbd08e1 Warren Baker
	global $g;
1514 2b4d37de Ermal Lu?i
1515 5bbd08e1 Warren Baker
	if (!is_file($path) && !is_dir($path)) {
1516
		return @mkdir($path, $mode, true);
1517
	} else {
1518
		return false;
1519
	}
1520 2b4d37de Ermal Lu?i
}
1521
1522
/*
1523
 * make_dirs($path, $mode = 0755)
1524
 * create directory tree recursively (mkdir -p)
1525
 */
1526
function make_dirs($path, $mode = 0755) {
1527 5bbd08e1 Warren Baker
	$base = '';
1528
	foreach (explode('/', $path) as $dir) {
1529
		$base .= "/$dir";
1530
		if (!is_dir($base)) {
1531
			if (!@mkdir($base, $mode))
1532
				return false;
1533
		}
1534
	}
1535
	return true;
1536 2b4d37de Ermal Lu?i
}
1537
1538 aa4f498d Erik Fonnesbeck
/*
1539
 * get_sysctl($names)
1540
 * Get values of sysctl OID's listed in $names (accepts an array or a single
1541
 * name) and return an array of key/value pairs set for those that exist
1542
 */
1543
function get_sysctl($names) {
1544
	if (empty($names))
1545
		return array();
1546
1547
	if (is_array($names)) {
1548
		$name_list = array();
1549
		foreach ($names as $name) {
1550
			$name_list[] = escapeshellarg($name);
1551
		}
1552
	} else
1553
		$name_list = array(escapeshellarg($names));
1554
1555
	exec("/sbin/sysctl -i " . implode(" ", $name_list), $output);
1556
	$values = array();
1557
	foreach ($output as $line) {
1558
		$line = explode(": ", $line, 2);
1559
		if (count($line) == 2)
1560
			$values[$line[0]] = $line[1];
1561
	}
1562
1563
	return $values;
1564
}
1565
1566
/*
1567
 * set_sysctl($value_list)
1568
 * Set sysctl OID's listed as key/value pairs and return
1569
 * an array with keys set for those that succeeded
1570
 */
1571
function set_sysctl($values) {
1572
	if (empty($values))
1573
		return array();
1574
1575
	$value_list = array();
1576
	foreach ($values as $key => $value) {
1577
		$value_list[] = escapeshellarg($key) . "=" . escapeshellarg($value);
1578
	}
1579
1580
	exec("/sbin/sysctl -i " . implode(" ", $value_list), $output, $success);
1581
1582
	/* Retry individually if failed (one or more read-only) */
1583
	if ($success <> 0 && count($value_list) > 1) {
1584
		foreach ($value_list as $value) {
1585
			exec("/sbin/sysctl -i " . $value, $output);
1586
		}
1587
	}
1588
1589
	$ret = array();
1590
	foreach ($output as $line) {
1591
		$line = explode(": ", $line, 2);
1592
		if (count($line) == 2)
1593
			$ret[$line[0]] = true;
1594
	}
1595
1596
	return $ret;
1597
}
1598
1599 2b4d37de Ermal Lu?i
/*
1600
 *     get_memory()
1601
 *     returns an array listing the amount of
1602
 *     memory installed in the hardware
1603 517fb89e Phil Davis
 *     [0] net memory available for the OS (FreeBSD) after some is taken by BIOS, video or whatever - e.g. 235 MBytes
1604
 *     [1] real (actual) memory of the system, should be the size of the RAM card/s - e.g. 256 MBytes
1605 2b4d37de Ermal Lu?i
 */
1606
function get_memory() {
1607 5cd73772 Ermal
1608 517fb89e Phil Davis
	$physmem = trim(`sysctl -n hw.physmem`, " \n");
1609
	$realmem = trim(`sysctl -n hw.realmem`, " \n");
1610 5cd73772 Ermal
	/* convert from bytes to megabytes */
1611 517fb89e Phil Davis
	return array(($physmem/1048576),($realmem/1048576));
1612 2b4d37de Ermal Lu?i
}
1613
1614
function mute_kernel_msgs() {
1615 5bbd08e1 Warren Baker
	global $config;
1616
	// Do not mute serial console.  The kernel gets very very cranky
1617
	// and will start dishing you cannot control tty errors.
1618 7734aea6 Andrew Thompson
	switch (trim(file_get_contents("/etc/platform"))) {
1619
		case "nanobsd":
1620
		case "jail":
1621
			return;
1622
	}
1623 86a5e1a8 Renato Botelho
	if($config['system']['enableserial'])
1624
		return;
1625 5bbd08e1 Warren Baker
	exec("/sbin/conscontrol mute on");
1626 2b4d37de Ermal Lu?i
}
1627
1628
function unmute_kernel_msgs() {
1629 5bbd08e1 Warren Baker
	global $config;
1630
	// Do not mute serial console.  The kernel gets very very cranky
1631
	// and will start dishing you cannot control tty errors.
1632 7734aea6 Andrew Thompson
	switch (trim(file_get_contents("/etc/platform"))) {
1633
		case "nanobsd":
1634
		case "jail":
1635
			return;
1636
	}
1637 5bbd08e1 Warren Baker
	exec("/sbin/conscontrol mute off");
1638 2b4d37de Ermal Lu?i
}
1639
1640
function start_devd() {
1641 6955830f Ermal Lu?i
	global $g;
1642
1643 7734aea6 Andrew Thompson
	if ($g['platform'] == 'jail')
1644
		return;
1645 5bbd08e1 Warren Baker
	exec("/sbin/devd");
1646
	sleep(1);
1647 2b4d37de Ermal Lu?i
}
1648
1649 66bcba1b Ermal
function is_interface_vlan_mismatch() {
1650 5bbd08e1 Warren Baker
	global $config, $g;
1651 66bcba1b Ermal
1652 5bbd08e1 Warren Baker
	if (is_array($config['vlans']['vlan'])) {
1653
		foreach ($config['vlans']['vlan'] as $vlan) {
1654
			if (does_interface_exist($vlan['if']) == false)
1655 66bcba1b Ermal
				return true;
1656 5bbd08e1 Warren Baker
		}
1657
	}
1658 66bcba1b Ermal
1659
	return false;
1660
}
1661
1662 2b4d37de Ermal Lu?i
function is_interface_mismatch() {
1663 857da904 Scott Ullrich
	global $config, $g;
1664 2b4d37de Ermal Lu?i
1665 857da904 Scott Ullrich
	$do_assign = false;
1666
	$i = 0;
1667 e0a45ce0 Erik Fonnesbeck
	$missing_interfaces = array();
1668 72993196 Ermal
	if (is_array($config['interfaces'])) {
1669 857da904 Scott Ullrich
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
1670 fd863e5c Erik Fonnesbeck
			if (preg_match("/^enc|^cua|^tun|^tap|^l2tp|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1671 857da904 Scott Ullrich
				// Do not check these interfaces.
1672
				$i++;
1673
				continue;
1674
			}
1675
			else if (does_interface_exist($ifcfg['if']) == false) {
1676 e0a45ce0 Erik Fonnesbeck
				$missing_interfaces[] = $ifcfg['if'];
1677 72993196 Ermal
				$do_assign = true;
1678 857da904 Scott Ullrich
			} else
1679
				$i++;
1680
		}
1681 72993196 Ermal
	}
1682 2b4d37de Ermal Lu?i
1683 857da904 Scott Ullrich
	if ($g['minimum_nic_count'] > $i) {
1684
		$do_assign = true;
1685
	} else if (file_exists("{$g['tmp_path']}/assign_complete"))
1686 e0a45ce0 Erik Fonnesbeck
		$do_assign = false;
1687
1688
	if (!empty($missing_interfaces) && $do_assign)
1689
		file_put_contents("{$g['tmp_path']}/missing_interfaces", implode(' ', $missing_interfaces));
1690
	else
1691
		@unlink("{$g['tmp_path']}/missing_interfaces");
1692 2b4d37de Ermal Lu?i
1693 857da904 Scott Ullrich
	return $do_assign;
1694 2b4d37de Ermal Lu?i
}
1695
1696 6e8f7b53 Ermal Lu?i
/* sync carp entries to other firewalls */
1697
function carp_sync_client() {
1698 e14d1c01 Ermal Lu?i
	global $g;
1699 0ae6daf8 Ermal
	send_event("filter sync");
1700 6e8f7b53 Ermal Lu?i
}
1701
1702 6dc88d53 Ermal Luci
/****f* util/isAjax
1703
 * NAME
1704
 *   isAjax - reports if the request is driven from prototype
1705
 * INPUTS
1706
 *   none
1707
 * RESULT
1708
 *   true/false
1709
 ******/
1710
function isAjax() {
1711 5bbd08e1 Warren Baker
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1712 6dc88d53 Ermal Luci
}
1713
1714 dad2b40e Tim Allender
/****f* util/timeout
1715
 * NAME
1716
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1717
 * INPUTS
1718
 *   optional, seconds to wait before timeout. Default 9 seconds.
1719
 * RESULT
1720
 *   returns 1 char of user input or null if no input.
1721
 ******/
1722
function timeout($timer = 9) {
1723
	while(!isset($key)) {
1724
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1725
		else { echo chr(8). "{$timer}"; }
1726
		`/bin/stty -icanon min 0 time 25`;
1727
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1728
		`/bin/stty icanon`;
1729
		if ($key == '')
1730
			unset($key);
1731
		$timer--;
1732
		if ($timer == 0)
1733
			break;
1734
	}
1735 86a5e1a8 Renato Botelho
	return $key;
1736 dad2b40e Tim Allender
}
1737 6dc88d53 Ermal Luci
1738 fdf3af3f Scott Ullrich
/****f* util/msort
1739
 * NAME
1740
 *   msort - sort array
1741
 * INPUTS
1742
 *   $array to be sorted, field to sort by, direction of sort
1743
 * RESULT
1744
 *   returns newly sorted array
1745
 ******/
1746 4a8bc5a2 Scott Ullrich
function msort($array, $id="id", $sort_ascending=true) {
1747
	$temp_array = array();
1748
	while(count($array)>0) {
1749
		$lowest_id = 0;
1750
		$index=0;
1751
		foreach ($array as $item) {
1752
			if (isset($item[$id])) {
1753
				if ($array[$lowest_id][$id]) {
1754
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1755
						$lowest_id = $index;
1756
					}
1757
				}
1758
			}
1759
			$index++;
1760
		}
1761
		$temp_array[] = $array[$lowest_id];
1762
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1763
	}
1764
	if ($sort_ascending) {
1765
		return $temp_array;
1766
	} else {
1767 86a5e1a8 Renato Botelho
		return array_reverse($temp_array);
1768 4a8bc5a2 Scott Ullrich
	}
1769
}
1770
1771 fdf3af3f Scott Ullrich
/****f* util/color
1772
 * NAME
1773
 *   color - outputs a color code to the ansi terminal if supported
1774
 * INPUTS
1775 6028a72d Scott Ullrich
 *   color code or color name
1776 fdf3af3f Scott Ullrich
 * RESULT
1777
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1778
 ******/
1779
function color($color = "0m") {
1780
	/*
1781
		Color codes available:
1782
		 0m reset; clears all colors and styles (to white on black)
1783
		 1m bold on (see below)
1784
		 3m italics on
1785
		 4m underline on
1786
		 7m inverse on; reverses foreground & background colors
1787
		 9m strikethrough on
1788
		 22m bold off (see below)
1789
		 23m italics off
1790
		 24m underline off
1791
		 27m inverse off
1792
		 29m strikethrough off
1793
		 30m set foreground color to black
1794
		 31m set foreground color to red
1795
		 32m set foreground color to green
1796
		 33m set foreground color to yellow
1797
		 34m set foreground color to blue
1798
		 35m set foreground color to magenta (purple)
1799
		 36m set foreground color to cyan
1800
		 37m set foreground color to white
1801
		 40m  set background color to black
1802
		 41m set background color to red
1803
		 42m set background color to green
1804
		 43m set background color to yellow
1805
		 44m set background color to blue
1806
		 45m set background color to magenta (purple)
1807
		 46m set background color to cyan
1808
		 47m set background color to white
1809
		 49m set background color to default (black)
1810 86a5e1a8 Renato Botelho
	*/
1811
	// Allow caching of TERM to
1812 fdf3af3f Scott Ullrich
	// speedup subequence requests.
1813
	global $TERM;
1814 86a5e1a8 Renato Botelho
	if(!$TERM)
1815 fdf3af3f Scott Ullrich
		$TERM=`/usr/bin/env | grep color`;
1816 78e0b65c Scott Ullrich
	if(!$TERM)
1817
		$TERM=`/usr/bin/env | grep cons25`;
1818 b927a013 Scott Ullrich
	if($TERM) {
1819 6028a72d Scott Ullrich
		$ESCAPE=chr(27);
1820 b927a013 Scott Ullrich
		switch ($color) {
1821 6028a72d Scott Ullrich
			case "black":
1822 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[30m";
1823 6028a72d Scott Ullrich
			case "red":
1824 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[31m";
1825 6028a72d Scott Ullrich
			case "green":
1826 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[32m";
1827 6028a72d Scott Ullrich
			case "yellow":
1828 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[33m";
1829 6028a72d Scott Ullrich
			case "blue":
1830 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[34m";
1831 6028a72d Scott Ullrich
			case "magenta":
1832 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[35m";
1833 6028a72d Scott Ullrich
			case "cyan":
1834 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[36m";
1835 6028a72d Scott Ullrich
			case "white":
1836 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[37m";
1837 6028a72d Scott Ullrich
			case "default":
1838 86a5e1a8 Renato Botelho
				return "{$ESCAPE}[39m";
1839 b927a013 Scott Ullrich
		}
1840 385a3a31 Scott Ullrich
		return "{$ESCAPE}[{$color}";
1841 b927a013 Scott Ullrich
	}
1842 fdf3af3f Scott Ullrich
}
1843
1844 5e9dd72a sullrich
/****f* util/is_URL
1845
 * NAME
1846
 *   is_URL
1847
 * INPUTS
1848
 *   string to check
1849
 * RESULT
1850
 *   Returns true if item is a URL
1851
 ******/
1852
function is_URL($url) {
1853
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1854
	if($match)
1855 86a5e1a8 Renato Botelho
		return true;
1856 5e9dd72a sullrich
	return false;
1857
}
1858
1859 ab94ba00 Ermal Lu?i
function is_file_included($file = "") {
1860
	$files = get_included_files();
1861
	if (in_array($file, $files))
1862
		return true;
1863 86a5e1a8 Renato Botelho
1864 ab94ba00 Ermal Lu?i
	return false;
1865
}
1866
1867 f2cc3344 Renato Botelho
/*
1868
 * Replace a value on a deep associative array using regex
1869
 */
1870
function array_replace_values_recursive($data, $match, $replace) {
1871
	if (empty($data))
1872
		return $data;
1873
1874
	if (is_string($data))
1875
		$data = preg_replace("/{$match}/", $replace, $data);
1876
	else if (is_array($data))
1877
		foreach ($data as $k => $v)
1878
			$data[$k] = array_replace_values_recursive($v, $match, $replace);
1879
1880
	return $data;
1881
}
1882
1883 0d90fcaf jim-p
/*
1884
	This function was borrowed from a comment on PHP.net at the following URL:
1885
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
1886
 */
1887 5bbd08e1 Warren Baker
function array_merge_recursive_unique($array0, $array1) {
1888
1889
	$arrays = func_get_args();
1890
	$remains = $arrays;
1891 0d90fcaf jim-p
1892 5bbd08e1 Warren Baker
	// We walk through each arrays and put value in the results (without
1893
	// considering previous value).
1894
	$result = array();
1895 0d90fcaf jim-p
1896 5bbd08e1 Warren Baker
	// loop available array
1897
	foreach($arrays as $array) {
1898 0d90fcaf jim-p
1899 5bbd08e1 Warren Baker
		// The first remaining array is $array. We are processing it. So
1900
		// we remove it from remaing arrays.
1901 86a5e1a8 Renato Botelho
		array_shift($remains);
1902 0d90fcaf jim-p
1903 5bbd08e1 Warren Baker
		// We don't care non array param, like array_merge since PHP 5.0.
1904
		if(is_array($array)) {
1905
			// Loop values
1906
			foreach($array as $key => $value) {
1907
				if(is_array($value)) {
1908
					// we gather all remaining arrays that have such key available
1909
					$args = array();
1910
					foreach($remains as $remain) {
1911
						if(array_key_exists($key, $remain)) {
1912
							array_push($args, $remain[$key]);
1913
						}
1914
					}
1915
1916
					if(count($args) > 2) {
1917
						// put the recursion
1918
						$result[$key] = call_user_func_array(__FUNCTION__, $args);
1919
					} else {
1920
						foreach($value as $vkey => $vval) {
1921
							$result[$key][$vkey] = $vval;
1922
						}
1923
					}
1924
				} else {
1925
					// simply put the value
1926
					$result[$key] = $value;
1927
				}
1928
			}
1929
		}
1930
	}
1931
	return $result;
1932 0d90fcaf jim-p
}
1933
1934 f898c1a9 jim-p
1935 9a456170 Darren Embry
/*
1936
 * converts a string like "a,b,c,d"
1937
 * into an array like array("a" => "b", "c" => "d")
1938
 */
1939
function explode_assoc($delimiter, $string) {
1940
	$array = explode($delimiter, $string);
1941
	$result = array();
1942
	$numkeys = floor(count($array) / 2);
1943
	for ($i = 0; $i < $numkeys; $i += 1) {
1944
		$result[$array[$i * 2]] = $array[$i * 2 + 1];
1945
	}
1946
	return $result;
1947
}
1948
1949 1901463c Renato Botelho
function get_staticroutes($returnsubnetsonly = false, $returnhostnames = false) {
1950
	global $config, $aliastable;
1951 f898c1a9 jim-p
1952
	/* Bail if there are no routes, but return an array always so callers don't have to check. */
1953
	if (!is_array($config['staticroutes']['route']))
1954
		return array();
1955
1956 bcab1b07 Ermal
	$allstaticroutes = array();
1957
	$allsubnets = array();
1958 f898c1a9 jim-p
	/* Loop through routes and expand aliases as we find them. */
1959
	foreach ($config['staticroutes']['route'] as $route) {
1960
		if (is_alias($route['network'])) {
1961 1901463c Renato Botelho
			if (!isset($aliastable[$route['network']]))
1962
				continue;
1963
1964
			$subnets = preg_split('/\s+/', $aliastable[$route['network']]);
1965 f898c1a9 jim-p
			foreach ($subnets as $net) {
1966 bcab1b07 Ermal
				if (!is_subnet($net)) {
1967
					if (is_ipaddrv4($net))
1968
						$net .= "/32";
1969
					else if (is_ipaddrv6($net))
1970
						$net .= "/128";
1971 1901463c Renato Botelho
					else if ($returnhostnames === false || !is_fqdn($net))
1972 bcab1b07 Ermal
						continue;
1973
				}
1974 f898c1a9 jim-p
				$temproute = $route;
1975
				$temproute['network'] = $net;
1976
				$allstaticroutes[] = $temproute;
1977
				$allsubnets[] = $net;
1978
			}
1979
		} elseif (is_subnet($route['network'])) {
1980
			$allstaticroutes[] = $route;
1981
			$allsubnets[] = $route['network'];
1982
		}
1983
	}
1984 bcab1b07 Ermal
	if ($returnsubnetsonly)
1985 f898c1a9 jim-p
		return $allsubnets;
1986 bcab1b07 Ermal
	else
1987 f898c1a9 jim-p
		return $allstaticroutes;
1988
}
1989 a0539faa Darren Embry
1990
/****f* util/get_alias_list
1991
 * NAME
1992
 *   get_alias_list - Provide a list of aliases.
1993
 * INPUTS
1994
 *   $type          - Optional, can be a string or array specifying what type(s) of aliases you need.
1995
 * RESULT
1996
 *   Array containing list of aliases.
1997
 *   If $type is unspecified, all aliases are returned.
1998
 *   If $type is a string, all aliases of the type specified in $type are returned.
1999
 *   If $type is an array, all aliases of any type specified in any element of $type are returned.
2000
 */
2001
function get_alias_list($type = null) {
2002
	global $config;
2003
	$result = array();
2004
	if ($config['aliases']['alias'] <> "" && is_array($config['aliases']['alias'])) {
2005
		foreach ($config['aliases']['alias'] as $alias) {
2006
			if ($type === null) {
2007
				$result[] = $alias['name'];
2008
			}
2009
			else if (is_array($type)) {
2010
				if (in_array($alias['type'], $type)) {
2011
					$result[] = $alias['name'];
2012
				}
2013
			}
2014
			else if ($type === $alias['type']) {
2015
				$result[] = $alias['name'];
2016
			}
2017
		}
2018 86a5e1a8 Renato Botelho
	}
2019 a0539faa Darren Embry
	return $result;
2020
}
2021
2022 4dfd930e Darren Embry
/* returns an array consisting of every element of $haystack that is not equal to $needle. */
2023
function array_exclude($needle, $haystack) {
2024
	$result = array();
2025
	if (is_array($haystack)) {
2026
		foreach ($haystack as $thing) {
2027
			if ($needle !== $thing) {
2028
				$result[] = $thing;
2029
			}
2030
		}
2031
	}
2032
	return $result;
2033
}
2034
2035 45930696 jim-p
function setup_library_paths() {
2036
	$current_library_paths = explode(":", exec("/sbin/ldconfig -r | /usr/bin/grep 'search directories' | /usr/bin/awk '{print $3;}'"));
2037 a2beee75 jim-p
	$pbi_library_paths = array_merge(glob("/usr/pbi/*/lib", GLOB_ONLYDIR), glob("/usr/pbi/*/lib/*", GLOB_ONLYDIR));
2038 45930696 jim-p
	foreach ($pbi_library_paths as $pbilib) {
2039
		if (!in_array($pbilib, $current_library_paths))
2040
			exec("/sbin/ldconfig -m {$pbilib}");
2041
	}
2042
}
2043
2044 1e1e1ec8 jim-p
function get_current_theme() {
2045
	global $config, $g;
2046
	/*
2047
	 *   if user has selected a custom template, use it.
2048
	 *   otherwise default to pfsense tempalte
2049
	 */
2050
	if (($g["disablethemeselection"] === true) && !empty($g["default_theme"]) && (is_dir($g["www_path"].'/themes/'.$g["default_theme"])))
2051
		$theme = $g["default_theme"];
2052
	elseif($config['theme'] <> "" && (is_dir($g["www_path"].'/themes/'.$config['theme'])))
2053
		$theme = $config['theme'];
2054
	else
2055
		$theme = "pfsense";
2056
	/*
2057
	 *  If this device is an apple ipod/iphone
2058
	 *  switch the theme to one that works with it.
2059
	 */
2060 2cf899d3 un0x
	$lowres_ua = array("iPhone", "iPod", "iPad", "Android", "BlackBerry", "Opera Mini", "Opera Mobi", "PlayBook", "IEMobile");
2061 1e1e1ec8 jim-p
	foreach($lowres_ua as $useragent)
2062
		if(strstr($_SERVER['HTTP_USER_AGENT'], $useragent))
2063
			$theme = (empty($g['theme_lowres']) && (is_dir($g["www_path"].'/themes/'.$g['theme_lowres']))) ? "pfsense" : $g['theme_lowres'];
2064
	return $theme;
2065
}
2066
2067 77a341a4 Renato Botelho
/* Define what is preferred, IPv4 or IPv6 */
2068
function prefer_ipv4_or_ipv6() {
2069
	global $config;
2070
2071
	if (isset($config['system']['prefer_ipv4']))
2072
		mwexec("/etc/rc.d/ip6addrctl prefer_ipv4");
2073
	else
2074
		mwexec("/etc/rc.d/ip6addrctl prefer_ipv6");
2075
}
2076
2077 eb295a1b Ermal
?>