Project

General

Profile

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