Project

General

Profile

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