Project

General

Profile

Download (10 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 98bbf05a Scott Ullrich
101 5b64aa38 Scott Ullrich
	global $aliastable, $config;
102
103 abe524dc Scott Ullrich
	if(!$config['aliases']['alias']) 
104
		return;
105
106 5b64aa38 Scott Ullrich
	foreach($config['aliases']['alias'] as $alias) {
107
		if($alias['name'] == $ipaddr)
108
			return true;
109
	}
110 98bbf05a Scott Ullrich
111 5b237745 Scott Ullrich
	if (isset($aliastable[$ipaddr]) && is_ipaddr($aliastable[$ipaddr]))
112
		return true;
113
	else
114
		return is_ipaddr($ipaddr);
115 5b64aa38 Scott Ullrich
	
116 5b237745 Scott Ullrich
}
117
118
/* returns true if $ipaddr is a valid dotted IPv4 address or any alias */
119
function is_ipaddroranyalias($ipaddr) {
120 98bbf05a Scott Ullrich
121 5b237745 Scott Ullrich
	global $aliastable;
122 98bbf05a Scott Ullrich
123 5b237745 Scott Ullrich
	if (isset($aliastable[$ipaddr]))
124
		return true;
125
	else
126
		return is_ipaddr($ipaddr);
127
}
128
129
/* returns true if $subnet is a valid subnet in CIDR format */
130
function is_subnet($subnet) {
131
	if (!is_string($subnet))
132
		return false;
133 98bbf05a Scott Ullrich
134 5b237745 Scott Ullrich
	list($hp,$np) = explode('/', $subnet);
135 98bbf05a Scott Ullrich
136 5b237745 Scott Ullrich
	if (!is_ipaddr($hp))
137
		return false;
138 98bbf05a Scott Ullrich
139 5b237745 Scott Ullrich
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
140
		return false;
141 98bbf05a Scott Ullrich
142 5b237745 Scott Ullrich
	return true;
143
}
144
145
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
146
function is_subnetoralias($subnet) {
147 98bbf05a Scott Ullrich
148 5b237745 Scott Ullrich
	global $aliastable;
149 98bbf05a Scott Ullrich
150 5b237745 Scott Ullrich
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
151
		return true;
152
	else
153
		return is_subnet($subnet);
154
}
155
156
/* returns true if $hostname is a valid hostname */
157
function is_hostname($hostname) {
158
	if (!is_string($hostname))
159
		return false;
160 98bbf05a Scott Ullrich
161 5b237745 Scott Ullrich
	if (preg_match("/^[a-z0-9\-]+$/i", $hostname))
162
		return true;
163
	else
164
		return false;
165
}
166
167
/* returns true if $domain is a valid domain name */
168
function is_domain($domain) {
169
	if (!is_string($domain))
170
		return false;
171 98bbf05a Scott Ullrich
172 5b237745 Scott Ullrich
	if (preg_match("/^([a-z0-9\-]+\.?)*$/i", $domain))
173
		return true;
174
	else
175
		return false;
176
}
177
178
/* returns true if $uname is a valid DynDNS username */
179
function is_dyndns_username($uname) {
180
	if (!is_string($uname))
181
		return false;
182 98bbf05a Scott Ullrich
183 5b237745 Scott Ullrich
	if (preg_match("/[^a-z0-9\-.@_]/i", $uname))
184
		return false;
185
	else
186
		return true;
187
}
188
189
/* returns true if $macaddr is a valid MAC address */
190
function is_macaddr($macaddr) {
191
	if (!is_string($macaddr))
192
		return false;
193 98bbf05a Scott Ullrich
194 5b237745 Scott Ullrich
	$maca = explode(":", $macaddr);
195
	if (count($maca) != 6)
196
		return false;
197 98bbf05a Scott Ullrich
198 5b237745 Scott Ullrich
	foreach ($maca as $macel) {
199
		if (($macel === "") || (strlen($macel) > 2))
200
			return false;
201
		if (preg_match("/[^0-9a-f]/i", $macel))
202
			return false;
203
	}
204 98bbf05a Scott Ullrich
205 5b237745 Scott Ullrich
	return true;
206
}
207
208
/* returns true if $name is a valid name for an alias */
209
function is_validaliasname($name) {
210
	if (!preg_match("/[^a-zA-Z0-9]/", $name))
211
		return true;
212
	else
213
		return false;
214
}
215
216
/* returns true if $port is a valid TCP/UDP port */
217
function is_port($port) {
218
	if (!is_numericint($port))
219
		return false;
220 98bbf05a Scott Ullrich
221 5b237745 Scott Ullrich
	if (($port < 1) || ($port > 65535))
222
		return false;
223
	else
224
		return true;
225
}
226
227
/* returns a list of interfaces with MAC addresses
228
   (skips VLAN and other virtual interfaces) */
229
function get_interface_list() {
230
	/* build interface list with netstat */
231
	exec("/usr/bin/netstat -inW -f link", $linkinfo);
232
	array_shift($linkinfo);
233 98bbf05a Scott Ullrich
234 5b237745 Scott Ullrich
	$iflist = array();
235 98bbf05a Scott Ullrich
236 5b237745 Scott Ullrich
	foreach ($linkinfo as $link) {
237
		$alink = preg_split("/\s+/", $link);
238
		$ifname = chop($alink[0]);
239 98bbf05a Scott Ullrich
240 5b237745 Scott Ullrich
		if (substr($ifname, -1) == "*")
241
			$ifname = substr($ifname, 0, strlen($ifname) - 1);
242 98bbf05a Scott Ullrich
243 edb2ed90 Scott Ullrich
		if (!preg_match("/^(plip|pflog|ppp|sl|gif|faith|lo|ng|vlan)/", $ifname)) {
244 5b237745 Scott Ullrich
			$iflist[$ifname] = array();
245 98bbf05a Scott Ullrich
246 5b237745 Scott Ullrich
			$iflist[$ifname]['mac'] = chop($alink[3]);
247
			$iflist[$ifname]['up'] = false;
248 98bbf05a Scott Ullrich
249 5b237745 Scott Ullrich
			/* find out if the link on this interface is up */
250
			unset($ifinfo);
251
			exec("/sbin/ifconfig {$ifname}", $ifinfo);
252 98bbf05a Scott Ullrich
253 5b237745 Scott Ullrich
			foreach ($ifinfo as $ifil) {
254
				if (preg_match("/status: (.*)$/", $ifil, $matches)) {
255
					if ($matches[1] == "active")
256
						$iflist[$ifname]['up'] = true;
257
					break;
258
				}
259
			}
260
		}
261
	}
262 98bbf05a Scott Ullrich
263 5b237745 Scott Ullrich
	return $iflist;
264
}
265
266
/* wrapper for exec() */
267
function mwexec($command) {
268
269
	global $g;
270 98bbf05a Scott Ullrich
271 5b237745 Scott Ullrich
	if ($g['debug']) {
272
		if (!$_SERVER['REMOTE_ADDR'])
273
			echo "mwexec(): $command\n";
274
		passthru($command, $retval);
275
	} else {
276
		exec("$command > /dev/null 2>&1", $oarr, $retval);
277
	}
278 98bbf05a Scott Ullrich
279
	return $retval;
280 5b237745 Scott Ullrich
}
281
282
/* wrapper for exec() in background */
283
function mwexec_bg($command) {
284
285
	global $g;
286 98bbf05a Scott Ullrich
287 5b237745 Scott Ullrich
	if ($g['debug']) {
288
		if (!$_SERVER['REMOTE_ADDR'])
289
			echo "mwexec(): $command\n";
290
	}
291 98bbf05a Scott Ullrich
292 5b237745 Scott Ullrich
	exec("nohup $command > /dev/null 2>&1 &");
293
}
294
295
/* unlink a file, if it exists */
296
function unlink_if_exists($fn) {
297 336cb718 Scott Ullrich
	$to_do = glob($fn);
298 3b378be5 Scott Ullrich
	if(is_array($to_do)) {
299 336cb718 Scott Ullrich
		foreach($to_do as $filename)
300 9ff926a2 Colin Smith
			@unlink($filename);
301 336cb718 Scott Ullrich
	} else {
302 9ff926a2 Colin Smith
		@unlink($fn);
303 336cb718 Scott Ullrich
	}
304 5b237745 Scott Ullrich
}
305
306
/* make a global alias table (for faster lookups) */
307 918a884d Bill Marquette
function alias_make_table($config) {
308 98bbf05a Scott Ullrich
309 918a884d Bill Marquette
	global $aliastable;
310 98bbf05a Scott Ullrich
311 5b237745 Scott Ullrich
	$aliastable = array();
312 98bbf05a Scott Ullrich
313 5b237745 Scott Ullrich
	if (is_array($config['aliases']['alias'])) {
314
		foreach ($config['aliases']['alias'] as $alias) {
315
			if ($alias['name'])
316
				$aliastable[$alias['name']] = $alias['address'];
317
		}
318
	}
319
}
320
321
/* check if an alias exists */
322
function is_alias($name) {
323 98bbf05a Scott Ullrich
324 5b237745 Scott Ullrich
	global $aliastable;
325 98bbf05a Scott Ullrich
326 5b237745 Scott Ullrich
	return isset($aliastable[$name]);
327
}
328
329
/* expand a host or network alias, if necessary */
330
function alias_expand($name) {
331 98bbf05a Scott Ullrich
332 5b237745 Scott Ullrich
	global $aliastable;
333 98bbf05a Scott Ullrich
334 5b237745 Scott Ullrich
	if (isset($aliastable[$name]))
335
		return $aliastable[$name];
336
	else if (is_ipaddr($name) || is_subnet($name))
337
		return $name;
338
	else
339
		return null;
340
}
341
342
/* expand a host alias, if necessary */
343
function alias_expand_host($name) {
344 98bbf05a Scott Ullrich
345 5b237745 Scott Ullrich
	global $aliastable;
346 98bbf05a Scott Ullrich
347 5b237745 Scott Ullrich
	if (isset($aliastable[$name]) && is_ipaddr($aliastable[$name]))
348
		return $aliastable[$name];
349
	else if (is_ipaddr($name))
350
		return $name;
351
	else
352
		return null;
353
}
354
355
/* expand a network alias, if necessary */
356
function alias_expand_net($name) {
357 98bbf05a Scott Ullrich
358 5b237745 Scott Ullrich
	global $aliastable;
359 98bbf05a Scott Ullrich
360 5b237745 Scott Ullrich
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
361
		return $aliastable[$name];
362
	else if (is_subnet($name))
363
		return $name;
364
	else
365
		return null;
366
}
367
368
/* find out whether two subnets overlap */
369
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
370
371
	if (!is_numeric($bits1))
372
		$bits1 = 32;
373
	if (!is_numeric($bits2))
374
		$bits2 = 32;
375
376
	if ($bits1 < $bits2)
377
		$relbits = $bits1;
378
	else
379
		$relbits = $bits2;
380 98bbf05a Scott Ullrich
381 5b237745 Scott Ullrich
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
382
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
383 98bbf05a Scott Ullrich
384 5b237745 Scott Ullrich
	if ($sn1 == $sn2)
385
		return true;
386
	else
387
		return false;
388
}
389
390
/* compare two IP addresses */
391
function ipcmp($a, $b) {
392
	if (ip2long($a) < ip2long($b))
393
		return -1;
394
	else if (ip2long($a) > ip2long($b))
395
		return 1;
396
	else
397
		return 0;
398
}
399
400
/* return true if $addr is in $subnet, false if not */
401
function ip_in_subnet($addr,$subnet) {
402
	list($ip, $mask) = explode('/', $subnet);
403
	$mask = 0xffffffff << (32 - $mask);
404
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
405
}
406
407
/* verify (and remove) the digital signature on a file - returns 0 if OK */
408
function verify_digital_signature($fname) {
409
410
	global $g;
411
412
	return mwexec("/usr/local/bin/verifysig " .
413
		escapeshellarg("{$g['etc_path']}/pubkey.pem") . " " .
414
		escapeshellarg($fname));
415
}
416
417
/* obtain MAC address given an IP address by looking at the ARP table */
418
function arp_get_mac_by_ip($ip) {
419 08443c7a Chris Dionissopoulos
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
420 5b237745 Scott Ullrich
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
421 98bbf05a Scott Ullrich
422 5b237745 Scott Ullrich
	if ($arpoutput[0]) {
423
		$arpi = explode(" ", $arpoutput[0]);
424
		$macaddr = $arpi[3];
425
		if (is_macaddr($macaddr))
426
			return $macaddr;
427
		else
428
			return false;
429
	}
430 98bbf05a Scott Ullrich
431 5b237745 Scott Ullrich
	return false;
432
}
433
434 98bbf05a Scott Ullrich
/* return a fieldname that is safe for xml usage */
435
function xml_safe_fieldname($fieldname) {
436 ddce8ef2 Colin Smith
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
437 9ef924eb Colin Smith
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
438 ddce8ef2 Colin Smith
			 ':', ',', '.', '\'', '\\'
439
		);
440
	return strtolower(str_replace($replace, "", $fieldname));
441 98bbf05a Scott Ullrich
}
442
443 5b64aa38 Scott Ullrich
?>