Project

General

Profile

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