Project

General

Profile

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