Project

General

Profile

Download (13.1 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2 307cd525 Bill Marquette
/* $Id$ */
3 5b237745 Scott Ullrich
/*
4
	util.inc
5
	part of m0n0wall (http://m0n0.ch/wall)
6 98bbf05a Scott Ullrich
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
/* kill a process by pid file */
33
function killbypid($pidfile) {
34
	sigkillbypid($pidfile, "TERM");
35
}
36
37
/* sigkill a process by pid file */
38
function sigkillbypid($pidfile, $sig) {
39
	if (file_exists($pidfile)) {
40 9d59c08f Scott Ullrich
		$pid = trim(file_get_contents($pidfile));
41 d7a6517a Scott Ullrich
		mwexec("/bin/kill -s $sig {$pid}");
42
	} else {
43
		mwexec("/bin/kill -s $sig {$pidfile}");
44 5b237745 Scott Ullrich
	}
45
}
46
47
/* kill a process by name */
48
function killbyname($procname) {
49
	mwexec("/usr/bin/killall " . escapeshellarg($procname));
50
}
51
52
/* return the subnet address given a host address and a subnet bit count */
53
function gen_subnet($ipaddr, $bits) {
54
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
55
		return "";
56 98bbf05a Scott Ullrich
57 5b237745 Scott Ullrich
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
58
}
59
60
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
61
function gen_subnet_max($ipaddr, $bits) {
62
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
63
		return "";
64 98bbf05a Scott Ullrich
65 5b237745 Scott Ullrich
	return long2ip(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
66
}
67
68
/* returns a subnet mask (long given a bit count) */
69
function gen_subnet_mask_long($bits) {
70
	$sm = 0;
71
	for ($i = 0; $i < $bits; $i++) {
72
		$sm >>= 1;
73
		$sm |= 0x80000000;
74
	}
75
	return $sm;
76
}
77
78
/* same as above but returns a string */
79
function gen_subnet_mask($bits) {
80
	return long2ip(gen_subnet_mask_long($bits));
81
}
82
83
function is_numericint($arg) {
84
	return (preg_match("/[^0-9]/", $arg) ? false : true);
85
}
86
87
/* returns true if $ipaddr is a valid dotted IPv4 address */
88
function is_ipaddr($ipaddr) {
89
	if (!is_string($ipaddr))
90
		return false;
91 98bbf05a Scott Ullrich
92 5b237745 Scott Ullrich
	$ip_long = ip2long($ipaddr);
93
	$ip_reverse = long2ip($ip_long);
94 98bbf05a Scott Ullrich
95 5b237745 Scott Ullrich
	if ($ipaddr == $ip_reverse)
96
		return true;
97
	else
98
		return false;
99
}
100
101
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
102
function is_ipaddroralias($ipaddr) {
103 3154d7ed Colin Smith
104 5b64aa38 Scott Ullrich
	global $aliastable, $config;
105
106 07168cc3 Bill Marquette
	if(is_array($config['aliases']['alias'])) {
107 55e0e4e5 Scott Ullrich
		foreach($config['aliases']['alias'] as $alias) {
108
			if($alias['name'] == $ipaddr)
109
				return true;
110
		}
111 8dbd4c3a Scott Ullrich
	}
112 98bbf05a Scott Ullrich
113 5b237745 Scott Ullrich
	if (isset($aliastable[$ipaddr]) && is_ipaddr($aliastable[$ipaddr]))
114
		return true;
115
	else
116
		return is_ipaddr($ipaddr);
117 b8014f9d Scott Ullrich
118 5b237745 Scott Ullrich
}
119
120
/* returns true if $ipaddr is a valid dotted IPv4 address or any alias */
121
function is_ipaddroranyalias($ipaddr) {
122 98bbf05a Scott Ullrich
123 5b237745 Scott Ullrich
	global $aliastable;
124 98bbf05a Scott Ullrich
125 5b237745 Scott Ullrich
	if (isset($aliastable[$ipaddr]))
126
		return true;
127
	else
128
		return is_ipaddr($ipaddr);
129
}
130
131
/* returns true if $subnet is a valid subnet in CIDR format */
132
function is_subnet($subnet) {
133
	if (!is_string($subnet))
134
		return false;
135 98bbf05a Scott Ullrich
136 5b237745 Scott Ullrich
	list($hp,$np) = explode('/', $subnet);
137 98bbf05a Scott Ullrich
138 5b237745 Scott Ullrich
	if (!is_ipaddr($hp))
139
		return false;
140 98bbf05a Scott Ullrich
141 5b237745 Scott Ullrich
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
142
		return false;
143 98bbf05a Scott Ullrich
144 5b237745 Scott Ullrich
	return true;
145
}
146
147
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
148
function is_subnetoralias($subnet) {
149 98bbf05a Scott Ullrich
150 5b237745 Scott Ullrich
	global $aliastable;
151 98bbf05a Scott Ullrich
152 5b237745 Scott Ullrich
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
153
		return true;
154
	else
155
		return is_subnet($subnet);
156
}
157
158
/* returns true if $hostname is a valid hostname */
159
function is_hostname($hostname) {
160
	if (!is_string($hostname))
161
		return false;
162 98bbf05a Scott Ullrich
163 161a01bd Scott Ullrich
	if (preg_match("/^([_a-z0-9\-]+\.?)+$/i", $hostname))
164 5b237745 Scott Ullrich
		return true;
165
	else
166
		return false;
167
}
168
169
/* returns true if $domain is a valid domain name */
170
function is_domain($domain) {
171
	if (!is_string($domain))
172
		return false;
173 98bbf05a Scott Ullrich
174 856887a3 Scott Ullrich
	if (preg_match("/^([a-z0-9\-]+\.?)+$/i", $domain))
175 5b237745 Scott Ullrich
		return true;
176
	else
177
		return false;
178
}
179
180
/* returns true if $uname is a valid DynDNS username */
181
function is_dyndns_username($uname) {
182
	if (!is_string($uname))
183
		return false;
184 98bbf05a Scott Ullrich
185 5b237745 Scott Ullrich
	if (preg_match("/[^a-z0-9\-.@_]/i", $uname))
186
		return false;
187
	else
188
		return true;
189
}
190
191
/* returns true if $macaddr is a valid MAC address */
192
function is_macaddr($macaddr) {
193
	if (!is_string($macaddr))
194
		return false;
195 98bbf05a Scott Ullrich
196 5b237745 Scott Ullrich
	$maca = explode(":", $macaddr);
197
	if (count($maca) != 6)
198
		return false;
199 98bbf05a Scott Ullrich
200 5b237745 Scott Ullrich
	foreach ($maca as $macel) {
201
		if (($macel === "") || (strlen($macel) > 2))
202
			return false;
203
		if (preg_match("/[^0-9a-f]/i", $macel))
204
			return false;
205
	}
206 98bbf05a Scott Ullrich
207 5b237745 Scott Ullrich
	return true;
208
}
209
210 3caa8aa1 Bill Marquette
/* returns true if $name is a valid name for an alias */
211 9499c2d2 Bill Marquette
/* returns NULL if a reserved word is used */
212 5b237745 Scott Ullrich
function is_validaliasname($name) {
213 beeef1f0 Bill Marquette
	/* Array of reserved words */
214 0c2badde Colin Smith
	$reserved = array("port", "pass");
215
	if (in_array($name, $reserved, true))
216 9499c2d2 Bill Marquette
		return; /* return NULL */
217 beeef1f0 Bill Marquette
218 5b237745 Scott Ullrich
	if (!preg_match("/[^a-zA-Z0-9]/", $name))
219
		return true;
220
	else
221
		return false;
222
}
223
224
/* returns true if $port is a valid TCP/UDP port */
225
function is_port($port) {
226
	if (!is_numericint($port))
227
		return false;
228 98bbf05a Scott Ullrich
229 5b237745 Scott Ullrich
	if (($port < 1) || ($port > 65535))
230
		return false;
231
	else
232
		return true;
233
}
234
235 b8014f9d Scott Ullrich
/* returns true if $val is a valid shaper bandwidth value */
236
function is_valid_shaperbw($val) {
237
	return (preg_match("/^[0-9]+(Kb|Mb|Gb|%)$/", $val));
238
}
239
240 3154d7ed Colin Smith
/*
241
 *   get_interface_list() - Return a list of all physical interfaces
242
 *   along with MAC and status.
243
 *
244
 *   $mode = "active" - use ifconfig -lu
245
 *           "media"  - use ifconfig to check physical connection
246 20203646 Colin Smith
 *			status (much slower)
247 3154d7ed Colin Smith
 */
248 36f546e9 Scott Ullrich
/*
249
 *   get_interface_list() - Return a list of all physical interfaces
250
 *   along with MAC and status.
251
 *
252
 *   $mode = "active" - use ifconfig -lu
253
 *           "media"  - use ifconfig to check physical connection
254
 *			status (much slower)
255
 */
256
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
257 20203646 Colin Smith
        global $config;
258 65bed2d2 Scott Ullrich
	$upints = array();
259 20203646 Colin Smith
        /* get a list of virtual interface types */
260 36f546e9 Scott Ullrich
        if(!$vfaces) {
261
		$vfaces = array(
262 8c328253 Scott Ullrich
				'bridge',
263 36f546e9 Scott Ullrich
				'ppp',
264
				'sl',
265
				'gif',
266
				'faith',
267
				'lo',
268
				'ng',
269
				'vlan',
270
				'pflog',
271
				'pfsync',
272 4ef5ea89 Scott Ullrich
				'enc',
273 38d42ff4 Scott Ullrich
				'tun',
274 36f546e9 Scott Ullrich
				'carp'
275
			);
276
	}
277 20203646 Colin Smith
	switch($mode) {
278
	case "active":
279
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
280
        	break;
281
	case "media":
282
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
283 767a716e Scott Ullrich
                $ifconfig = "";
284 20203646 Colin Smith
                exec("/sbin/ifconfig -a", $ifconfig);
285
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
286
                $ifstatus = preg_grep('/status:/', $ifconfig);
287 49149b86 Colin Smith
		foreach($ifstatus as $status) {
288 bb3b9159 Colin Smith
			$int = array_shift($intlist);
289
                	if(stristr($status, "active")) $upints[] = $int;
290 49149b86 Colin Smith
		}
291 20203646 Colin Smith
		break;
292
	}
293
        /* build interface list with netstat */
294 767a716e Scott Ullrich
        $linkinfo = "";
295 89d1f0f2 Scott Ullrich
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
296 20203646 Colin Smith
        array_shift($linkinfo);
297 89d1f0f2 Scott Ullrich
	/* build ip address list with netstat */
298 767a716e Scott Ullrich
	$ipinfo = "";
299 89d1f0f2 Scott Ullrich
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
300
	array_shift($ipinfo);
301
	foreach($linkinfo as $link) {
302
		$friendly = "";
303 20203646 Colin Smith
                $alink = explode(" ", $link);
304
                $ifname = rtrim(trim($alink[0]), '*');
305 36f546e9 Scott Ullrich
                /* trim out all numbers before checking for vfaces */
306
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces)) {
307 20203646 Colin Smith
			$toput = array(
308
					"mac" => trim($alink[1]),
309
					"up" => in_array($ifname, $upints)
310
				);
311 89d1f0f2 Scott Ullrich
			foreach($ipinfo as $ip) {
312
				$aip = explode(" ", $ip);
313
				if($aip[0] == $ifname) {
314
					$toput['ipaddr'] = $aip[1];
315
				}
316
			}
317 20203646 Colin Smith
			foreach($config['interfaces'] as $name => $int) {
318
				if($int['if'] == $ifname) $friendly = $name;
319
			}
320
			switch($keyby) {
321
			case "physical":
322 89d1f0f2 Scott Ullrich
				if($friendly != "") {
323
					$toput['friendly'] = $friendly;
324
				}
325 20203646 Colin Smith
				$iflist[$ifname] = $toput;
326 3154d7ed Colin Smith
				break;
327 20203646 Colin Smith
			case "friendly":
328 89d1f0f2 Scott Ullrich
				if($friendly != "") {
329
					$toput['if'] = $ifname;
330
					$iflist[$friendly] = $toput;
331
				}
332 3154d7ed Colin Smith
				break;
333
			}
334 20203646 Colin Smith
                }
335
        }
336
        return $iflist;
337 5b237745 Scott Ullrich
}
338
339
/* wrapper for exec() */
340
function mwexec($command) {
341
342
	global $g;
343 767a716e Scott Ullrich
	$oarr = "";
344
	$retval = "";
345 5b237745 Scott Ullrich
	if ($g['debug']) {
346
		if (!$_SERVER['REMOTE_ADDR'])
347
			echo "mwexec(): $command\n";
348 c9847bc4 Scott Ullrich
		exec("$command > /dev/null 2>&1", $oarr, $retval);
349 5b237745 Scott Ullrich
	} else {
350
		exec("$command > /dev/null 2>&1", $oarr, $retval);
351
	}
352 98bbf05a Scott Ullrich
353
	return $retval;
354 5b237745 Scott Ullrich
}
355
356
/* wrapper for exec() in background */
357
function mwexec_bg($command) {
358
359
	global $g;
360 98bbf05a Scott Ullrich
361 5b237745 Scott Ullrich
	if ($g['debug']) {
362
		if (!$_SERVER['REMOTE_ADDR'])
363
			echo "mwexec(): $command\n";
364
	}
365 98bbf05a Scott Ullrich
366 5b237745 Scott Ullrich
	exec("nohup $command > /dev/null 2>&1 &");
367
}
368
369
/* unlink a file, if it exists */
370
function unlink_if_exists($fn) {
371 336cb718 Scott Ullrich
	$to_do = glob($fn);
372 3b378be5 Scott Ullrich
	if(is_array($to_do)) {
373 336cb718 Scott Ullrich
		foreach($to_do as $filename)
374 9ff926a2 Colin Smith
			@unlink($filename);
375 336cb718 Scott Ullrich
	} else {
376 9ff926a2 Colin Smith
		@unlink($fn);
377 336cb718 Scott Ullrich
	}
378 5b237745 Scott Ullrich
}
379
/* make a global alias table (for faster lookups) */
380 918a884d Bill Marquette
function alias_make_table($config) {
381 98bbf05a Scott Ullrich
382 918a884d Bill Marquette
	global $aliastable;
383 98bbf05a Scott Ullrich
384 5b237745 Scott Ullrich
	$aliastable = array();
385 98bbf05a Scott Ullrich
386 5b237745 Scott Ullrich
	if (is_array($config['aliases']['alias'])) {
387
		foreach ($config['aliases']['alias'] as $alias) {
388
			if ($alias['name'])
389
				$aliastable[$alias['name']] = $alias['address'];
390
		}
391
	}
392
}
393
/* check if an alias exists */
394
function is_alias($name) {
395 98bbf05a Scott Ullrich
396 5b237745 Scott Ullrich
	global $aliastable;
397 98bbf05a Scott Ullrich
398 5b237745 Scott Ullrich
	return isset($aliastable[$name]);
399 b8014f9d Scott Ullrich
}
400 27ff8a3c Scott Ullrich
401
function alias_expand_value($name) {
402
403
	global $aliastable, $config;
404
405
	foreach($config['aliases']['alias'] as $alias) {
406
		if($alias['name'] == $name)
407
			return $alias['address'];
408
	}
409
410 5b237745 Scott Ullrich
}
411
412
/* expand a host or network alias, if necessary */
413
function alias_expand($name) {
414 98bbf05a Scott Ullrich
415 5b237745 Scott Ullrich
	global $aliastable;
416 98bbf05a Scott Ullrich
417 5b237745 Scott Ullrich
	if (isset($aliastable[$name]))
418 4335dc87 Bill Marquette
		return "\${$name}";
419 5b237745 Scott Ullrich
	else if (is_ipaddr($name) || is_subnet($name))
420 57989da5 Scott Ullrich
		return "{$name}";
421 5b237745 Scott Ullrich
	else
422
		return null;
423
}
424
425
/* expand a host alias, if necessary */
426
function alias_expand_host($name) {
427
	global $aliastable;
428 98bbf05a Scott Ullrich
429 9b00dc26 Bill Marquette
	if (isset($aliastable[$name])) {
430
		$ip_arr = explode(" ", $aliastable[$name]);
431
		foreach($ip_arr as $ip) {
432
			if (!is_ipaddr($ip))
433
				return null;
434
		}
435 5b237745 Scott Ullrich
		return $aliastable[$name];
436 9b00dc26 Bill Marquette
	} else if (is_ipaddr($name))
437 5b237745 Scott Ullrich
		return $name;
438
	else
439
		return null;
440
}
441
442
/* expand a network alias, if necessary */
443
function alias_expand_net($name) {
444 98bbf05a Scott Ullrich
445 5b237745 Scott Ullrich
	global $aliastable;
446 98bbf05a Scott Ullrich
447 5b237745 Scott Ullrich
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
448
		return $aliastable[$name];
449
	else if (is_subnet($name))
450
		return $name;
451
	else
452
		return null;
453
}
454
455
/* find out whether two subnets overlap */
456
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
457
458
	if (!is_numeric($bits1))
459
		$bits1 = 32;
460
	if (!is_numeric($bits2))
461
		$bits2 = 32;
462
463
	if ($bits1 < $bits2)
464
		$relbits = $bits1;
465
	else
466
		$relbits = $bits2;
467 98bbf05a Scott Ullrich
468 5b237745 Scott Ullrich
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
469
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
470 98bbf05a Scott Ullrich
471 5b237745 Scott Ullrich
	if ($sn1 == $sn2)
472
		return true;
473
	else
474
		return false;
475
}
476
477
/* compare two IP addresses */
478
function ipcmp($a, $b) {
479
	if (ip2long($a) < ip2long($b))
480
		return -1;
481
	else if (ip2long($a) > ip2long($b))
482
		return 1;
483
	else
484
		return 0;
485
}
486
487
/* return true if $addr is in $subnet, false if not */
488
function ip_in_subnet($addr,$subnet) {
489
	list($ip, $mask) = explode('/', $subnet);
490
	$mask = 0xffffffff << (32 - $mask);
491
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
492
}
493
494
/* verify (and remove) the digital signature on a file - returns 0 if OK */
495
function verify_digital_signature($fname) {
496
497
	global $g;
498
499 f024f52d Scott Ullrich
	return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname));
500
501 5b237745 Scott Ullrich
}
502
503
/* obtain MAC address given an IP address by looking at the ARP table */
504
function arp_get_mac_by_ip($ip) {
505 08443c7a Chris Dionissopoulos
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
506 767a716e Scott Ullrich
	$arpoutput = "";
507 5b237745 Scott Ullrich
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
508 98bbf05a Scott Ullrich
509 5b237745 Scott Ullrich
	if ($arpoutput[0]) {
510
		$arpi = explode(" ", $arpoutput[0]);
511
		$macaddr = $arpi[3];
512
		if (is_macaddr($macaddr))
513
			return $macaddr;
514
		else
515
			return false;
516
	}
517 98bbf05a Scott Ullrich
518 5b237745 Scott Ullrich
	return false;
519
}
520
521 98bbf05a Scott Ullrich
/* return a fieldname that is safe for xml usage */
522
function xml_safe_fieldname($fieldname) {
523 ddce8ef2 Colin Smith
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
524 9ef924eb Colin Smith
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
525 ddce8ef2 Colin Smith
			 ':', ',', '.', '\'', '\\'
526
		);
527
	return strtolower(str_replace($replace, "", $fieldname));
528 98bbf05a Scott Ullrich
}
529
530 4129df39 Scott Ullrich
function mac_format($clientmac) {
531
    $mac =explode(":", $clientmac);
532
533
    global $config;
534
535
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
536
537
    switch($mac_format) {
538
539
        case 'singledash':
540
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
541
542
        case 'ietf':
543
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
544
545
        case 'cisco':
546
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
547
548
        case 'unformatted':
549
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
550
551
        default:
552
        return $clientmac;
553
    }
554
}
555
556 856887a3 Scott Ullrich
?>