Project

General

Profile

Download (12.2 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 5b64aa38 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 5b237745 Scott Ullrich
	if (preg_match("/^[a-z0-9\-]+$/i", $hostname))
164
		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 98e9e3d5 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 3154d7ed Colin Smith
/*
236
 *   get_interface_list() - Return a list of all physical interfaces
237
 *   along with MAC and status.
238
 *
239
 *   $mode = "active" - use ifconfig -lu
240
 *           "media"  - use ifconfig to check physical connection
241 20203646 Colin Smith
 *			status (much slower)
242 3154d7ed Colin Smith
 */
243 36f546e9 Scott Ullrich
/*
244
 *   get_interface_list() - Return a list of all physical interfaces
245
 *   along with MAC and status.
246
 *
247
 *   $mode = "active" - use ifconfig -lu
248
 *           "media"  - use ifconfig to check physical connection
249
 *			status (much slower)
250
 */
251
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
252 20203646 Colin Smith
        global $config;
253 65bed2d2 Scott Ullrich
	$upints = array();
254 20203646 Colin Smith
        /* get a list of virtual interface types */
255 36f546e9 Scott Ullrich
        if(!$vfaces) {
256
		$vfaces = array(
257 8c328253 Scott Ullrich
				'bridge',
258 36f546e9 Scott Ullrich
				'ppp',
259
				'sl',
260
				'gif',
261
				'faith',
262
				'lo',
263
				'ng',
264
				'vlan',
265
				'pflog',
266
				'pfsync',
267
				'carp'
268
			);
269
	}
270 20203646 Colin Smith
	switch($mode) {
271
	case "active":
272
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
273
        	break;
274
	case "media":
275
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
276 767a716e Scott Ullrich
                $ifconfig = "";
277 20203646 Colin Smith
                exec("/sbin/ifconfig -a", $ifconfig);
278
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
279
                $ifstatus = preg_grep('/status:/', $ifconfig);
280 49149b86 Colin Smith
		foreach($ifstatus as $status) {
281 bb3b9159 Colin Smith
			$int = array_shift($intlist);
282
                	if(stristr($status, "active")) $upints[] = $int;
283 49149b86 Colin Smith
		}
284 20203646 Colin Smith
		break;
285
	}
286
        /* build interface list with netstat */
287 767a716e Scott Ullrich
        $linkinfo = "";
288 89d1f0f2 Scott Ullrich
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
289 20203646 Colin Smith
        array_shift($linkinfo);
290 89d1f0f2 Scott Ullrich
	/* build ip address list with netstat */
291 767a716e Scott Ullrich
	$ipinfo = "";
292 89d1f0f2 Scott Ullrich
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
293
	array_shift($ipinfo);
294
	foreach($linkinfo as $link) {
295
		$friendly = "";
296 20203646 Colin Smith
                $alink = explode(" ", $link);
297
                $ifname = rtrim(trim($alink[0]), '*');
298 36f546e9 Scott Ullrich
                /* trim out all numbers before checking for vfaces */
299
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces)) {
300 20203646 Colin Smith
			$toput = array(
301
					"mac" => trim($alink[1]),
302
					"up" => in_array($ifname, $upints)
303
				);
304 89d1f0f2 Scott Ullrich
			foreach($ipinfo as $ip) {
305
				$aip = explode(" ", $ip);
306
				if($aip[0] == $ifname) {
307
					$toput['ipaddr'] = $aip[1];
308
				}
309
			}
310 20203646 Colin Smith
			foreach($config['interfaces'] as $name => $int) {
311
				if($int['if'] == $ifname) $friendly = $name;
312
			}
313
			switch($keyby) {
314
			case "physical":
315 89d1f0f2 Scott Ullrich
				if($friendly != "") {
316
					$toput['friendly'] = $friendly;
317
				}
318 20203646 Colin Smith
				$iflist[$ifname] = $toput;
319 3154d7ed Colin Smith
				break;
320 20203646 Colin Smith
			case "friendly":
321 89d1f0f2 Scott Ullrich
				if($friendly != "") {
322
					$toput['if'] = $ifname;
323
					$iflist[$friendly] = $toput;
324
				}
325 3154d7ed Colin Smith
				break;
326
			}
327 20203646 Colin Smith
                }
328
        }
329
        return $iflist;
330 5b237745 Scott Ullrich
}
331
332
/* wrapper for exec() */
333
function mwexec($command) {
334
335
	global $g;
336 767a716e Scott Ullrich
	$oarr = "";
337
	$retval = "";
338 5b237745 Scott Ullrich
	if ($g['debug']) {
339
		if (!$_SERVER['REMOTE_ADDR'])
340
			echo "mwexec(): $command\n";
341 c9847bc4 Scott Ullrich
		exec("$command > /dev/null 2>&1", $oarr, $retval);
342 5b237745 Scott Ullrich
	} else {
343
		exec("$command > /dev/null 2>&1", $oarr, $retval);
344
	}
345 98bbf05a Scott Ullrich
346
	return $retval;
347 5b237745 Scott Ullrich
}
348
349
/* wrapper for exec() in background */
350
function mwexec_bg($command) {
351
352
	global $g;
353 98bbf05a Scott Ullrich
354 5b237745 Scott Ullrich
	if ($g['debug']) {
355
		if (!$_SERVER['REMOTE_ADDR'])
356
			echo "mwexec(): $command\n";
357
	}
358 98bbf05a Scott Ullrich
359 5b237745 Scott Ullrich
	exec("nohup $command > /dev/null 2>&1 &");
360
}
361
362
/* unlink a file, if it exists */
363
function unlink_if_exists($fn) {
364 336cb718 Scott Ullrich
	$to_do = glob($fn);
365 3b378be5 Scott Ullrich
	if(is_array($to_do)) {
366 336cb718 Scott Ullrich
		foreach($to_do as $filename)
367 9ff926a2 Colin Smith
			@unlink($filename);
368 336cb718 Scott Ullrich
	} else {
369 9ff926a2 Colin Smith
		@unlink($fn);
370 336cb718 Scott Ullrich
	}
371 5b237745 Scott Ullrich
}
372
373
/* make a global alias table (for faster lookups) */
374 918a884d Bill Marquette
function alias_make_table($config) {
375 98bbf05a Scott Ullrich
376 918a884d Bill Marquette
	global $aliastable;
377 98bbf05a Scott Ullrich
378 5b237745 Scott Ullrich
	$aliastable = array();
379 98bbf05a Scott Ullrich
380 5b237745 Scott Ullrich
	if (is_array($config['aliases']['alias'])) {
381
		foreach ($config['aliases']['alias'] as $alias) {
382
			if ($alias['name'])
383
				$aliastable[$alias['name']] = $alias['address'];
384
		}
385
	}
386
}
387
388
/* check if an alias exists */
389
function is_alias($name) {
390 98bbf05a Scott Ullrich
391 5b237745 Scott Ullrich
	global $aliastable;
392 98bbf05a Scott Ullrich
393 5b237745 Scott Ullrich
	return isset($aliastable[$name]);
394 27ff8a3c Scott Ullrich
}	
395
396
function alias_expand_value($name) {
397
398
	global $aliastable, $config;
399
400
	foreach($config['aliases']['alias'] as $alias) {
401
		if($alias['name'] == $name)
402
			return $alias['address'];
403
	}
404
405 5b237745 Scott Ullrich
}
406
407
/* expand a host or network alias, if necessary */
408
function alias_expand($name) {
409 98bbf05a Scott Ullrich
410 5b237745 Scott Ullrich
	global $aliastable;
411 98bbf05a Scott Ullrich
412 5b237745 Scott Ullrich
	if (isset($aliastable[$name]))
413 4335dc87 Bill Marquette
		return "\${$name}";
414 5b237745 Scott Ullrich
	else if (is_ipaddr($name) || is_subnet($name))
415 57989da5 Scott Ullrich
		return "{$name}";
416 5b237745 Scott Ullrich
	else
417
		return null;
418
}
419
420
/* expand a host alias, if necessary */
421
function alias_expand_host($name) {
422 98bbf05a Scott Ullrich
423 5b237745 Scott Ullrich
	global $aliastable;
424 98bbf05a Scott Ullrich
425 5b237745 Scott Ullrich
	if (isset($aliastable[$name]) && is_ipaddr($aliastable[$name]))
426
		return $aliastable[$name];
427
	else if (is_ipaddr($name))
428
		return $name;
429
	else
430
		return null;
431
}
432
433
/* expand a network alias, if necessary */
434
function alias_expand_net($name) {
435 98bbf05a Scott Ullrich
436 5b237745 Scott Ullrich
	global $aliastable;
437 98bbf05a Scott Ullrich
438 5b237745 Scott Ullrich
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
439
		return $aliastable[$name];
440
	else if (is_subnet($name))
441
		return $name;
442
	else
443
		return null;
444
}
445
446
/* find out whether two subnets overlap */
447
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
448
449
	if (!is_numeric($bits1))
450
		$bits1 = 32;
451
	if (!is_numeric($bits2))
452
		$bits2 = 32;
453
454
	if ($bits1 < $bits2)
455
		$relbits = $bits1;
456
	else
457
		$relbits = $bits2;
458 98bbf05a Scott Ullrich
459 5b237745 Scott Ullrich
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
460
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
461 98bbf05a Scott Ullrich
462 5b237745 Scott Ullrich
	if ($sn1 == $sn2)
463
		return true;
464
	else
465
		return false;
466
}
467
468
/* compare two IP addresses */
469
function ipcmp($a, $b) {
470
	if (ip2long($a) < ip2long($b))
471
		return -1;
472
	else if (ip2long($a) > ip2long($b))
473
		return 1;
474
	else
475
		return 0;
476
}
477
478
/* return true if $addr is in $subnet, false if not */
479
function ip_in_subnet($addr,$subnet) {
480
	list($ip, $mask) = explode('/', $subnet);
481
	$mask = 0xffffffff << (32 - $mask);
482
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
483
}
484
485
/* verify (and remove) the digital signature on a file - returns 0 if OK */
486
function verify_digital_signature($fname) {
487
488
	global $g;
489
490 f024f52d Scott Ullrich
	return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname));
491
492 5b237745 Scott Ullrich
}
493
494
/* obtain MAC address given an IP address by looking at the ARP table */
495
function arp_get_mac_by_ip($ip) {
496 08443c7a Chris Dionissopoulos
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
497 767a716e Scott Ullrich
	$arpoutput = "";
498 5b237745 Scott Ullrich
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
499 98bbf05a Scott Ullrich
500 5b237745 Scott Ullrich
	if ($arpoutput[0]) {
501
		$arpi = explode(" ", $arpoutput[0]);
502
		$macaddr = $arpi[3];
503
		if (is_macaddr($macaddr))
504
			return $macaddr;
505
		else
506
			return false;
507
	}
508 98bbf05a Scott Ullrich
509 5b237745 Scott Ullrich
	return false;
510
}
511
512 98bbf05a Scott Ullrich
/* return a fieldname that is safe for xml usage */
513
function xml_safe_fieldname($fieldname) {
514 ddce8ef2 Colin Smith
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
515 9ef924eb Colin Smith
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
516 ddce8ef2 Colin Smith
			 ':', ',', '.', '\'', '\\'
517
		);
518
	return strtolower(str_replace($replace, "", $fieldname));
519 98bbf05a Scott Ullrich
}
520
521 4f8e387d Scott Ullrich
?>