Project

General

Profile

Download (10.2 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	util.inc
5
	part of m0n0wall (http://m0n0.ch/wall)
6

    
7
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9

    
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12

    
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15

    
16
	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

    
20
	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

    
54
	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

    
62
	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

    
89
	$ip_long = ip2long($ipaddr);
90
	$ip_reverse = long2ip($ip_long);
91

    
92
	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

    
101
	global $aliastable, $config;
102

    
103
	if(is_array($config['aliases']['alias'])) {
104
		foreach($config['aliases']['alias'] as $alias) {
105
			if($alias['name'] == $ipaddr)
106
				return true;
107
		}
108
	}
109

    
110
	if (isset($aliastable[$ipaddr]) && is_ipaddr($aliastable[$ipaddr]))
111
		return true;
112
	else
113
		return is_ipaddr($ipaddr);
114
	
115
}
116

    
117
/* returns true if $ipaddr is a valid dotted IPv4 address or any alias */
118
function is_ipaddroranyalias($ipaddr) {
119

    
120
	global $aliastable;
121

    
122
	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

    
133
	list($hp,$np) = explode('/', $subnet);
134

    
135
	if (!is_ipaddr($hp))
136
		return false;
137

    
138
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
139
		return false;
140

    
141
	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

    
147
	global $aliastable;
148

    
149
	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

    
160
	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

    
171
	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

    
182
	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

    
193
	$maca = explode(":", $macaddr);
194
	if (count($maca) != 6)
195
		return false;
196

    
197
	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

    
204
	return true;
205
}
206

    
207
/* returns true if $name is a valid name for an alias */
208
function is_validaliasname($name) {
209
	/* Array of reserved words */
210
	$reserved = array("port");
211
	if (in_array($name, $reserved))
212
		return -1;
213

    
214
	if (!preg_match("/[^a-zA-Z0-9]/", $name))
215
		return true;
216
	else
217
		return false;
218
}
219

    
220
/* returns true if $port is a valid TCP/UDP port */
221
function is_port($port) {
222
	if (!is_numericint($port))
223
		return false;
224

    
225
	if (($port < 1) || ($port > 65535))
226
		return false;
227
	else
228
		return true;
229
}
230

    
231
/* returns a list of interfaces with MAC addresses
232
   (skips VLAN and other virtual interfaces) */
233
function get_interface_list() {
234
	/* build interface list with netstat */
235
	exec("/usr/bin/netstat -inW -f link", $linkinfo);
236
	array_shift($linkinfo);
237

    
238
	$iflist = array();
239

    
240
	foreach ($linkinfo as $link) {
241
		$alink = preg_split("/\s+/", $link);
242
		$ifname = chop($alink[0]);
243

    
244
		if (substr($ifname, -1) == "*")
245
			$ifname = substr($ifname, 0, strlen($ifname) - 1);
246

    
247
		if (!preg_match("/^(plip|pflog|pfsync|ppp|sl|gif|faith|lo|ng|vlan)/", $ifname)) {
248
			$iflist[$ifname] = array();
249

    
250
			$iflist[$ifname]['mac'] = chop($alink[3]);
251
			$iflist[$ifname]['up'] = false;
252

    
253
			/* find out if the link on this interface is up */
254
			unset($ifinfo);
255
			exec("/sbin/ifconfig {$ifname}", $ifinfo);
256

    
257
			foreach ($ifinfo as $ifil) {
258
				if (preg_match("/status: (.*)$/", $ifil, $matches)) {
259
					if ($matches[1] == "active")
260
						$iflist[$ifname]['up'] = true;
261
					break;
262
				}
263
			}
264
		}
265
	}
266

    
267
	return $iflist;
268
}
269

    
270
/* wrapper for exec() */
271
function mwexec($command) {
272

    
273
	global $g;
274

    
275
	if ($g['debug']) {
276
		if (!$_SERVER['REMOTE_ADDR'])
277
			echo "mwexec(): $command\n";
278
		passthru($command, $retval);
279
	} else {
280
		exec("$command > /dev/null 2>&1", $oarr, $retval);
281
	}
282

    
283
	return $retval;
284
}
285

    
286
/* wrapper for exec() in background */
287
function mwexec_bg($command) {
288

    
289
	global $g;
290

    
291
	if ($g['debug']) {
292
		if (!$_SERVER['REMOTE_ADDR'])
293
			echo "mwexec(): $command\n";
294
	}
295

    
296
	exec("nohup $command > /dev/null 2>&1 &");
297
}
298

    
299
/* unlink a file, if it exists */
300
function unlink_if_exists($fn) {
301
	$to_do = glob($fn);
302
	if(is_array($to_do)) {
303
		foreach($to_do as $filename)
304
			@unlink($filename);
305
	} else {
306
		@unlink($fn);
307
	}
308
}
309

    
310
/* make a global alias table (for faster lookups) */
311
function alias_make_table($config) {
312

    
313
	global $aliastable;
314

    
315
	$aliastable = array();
316

    
317
	if (is_array($config['aliases']['alias'])) {
318
		foreach ($config['aliases']['alias'] as $alias) {
319
			if ($alias['name'])
320
				$aliastable[$alias['name']] = $alias['address'];
321
		}
322
	}
323
}
324

    
325
/* check if an alias exists */
326
function is_alias($name) {
327

    
328
	global $aliastable;
329

    
330
	return isset($aliastable[$name]);
331
}
332

    
333
/* expand a host or network alias, if necessary */
334
function alias_expand($name) {
335

    
336
	global $aliastable;
337

    
338
	if (isset($aliastable[$name]))
339
		return $aliastable[$name];
340
	else if (is_ipaddr($name) || is_subnet($name))
341
		return $name;
342
	else
343
		return null;
344
}
345

    
346
/* expand a host alias, if necessary */
347
function alias_expand_host($name) {
348

    
349
	global $aliastable;
350

    
351
	if (isset($aliastable[$name]) && is_ipaddr($aliastable[$name]))
352
		return $aliastable[$name];
353
	else if (is_ipaddr($name))
354
		return $name;
355
	else
356
		return null;
357
}
358

    
359
/* expand a network alias, if necessary */
360
function alias_expand_net($name) {
361

    
362
	global $aliastable;
363

    
364
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
365
		return $aliastable[$name];
366
	else if (is_subnet($name))
367
		return $name;
368
	else
369
		return null;
370
}
371

    
372
/* find out whether two subnets overlap */
373
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
374

    
375
	if (!is_numeric($bits1))
376
		$bits1 = 32;
377
	if (!is_numeric($bits2))
378
		$bits2 = 32;
379

    
380
	if ($bits1 < $bits2)
381
		$relbits = $bits1;
382
	else
383
		$relbits = $bits2;
384

    
385
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
386
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
387

    
388
	if ($sn1 == $sn2)
389
		return true;
390
	else
391
		return false;
392
}
393

    
394
/* compare two IP addresses */
395
function ipcmp($a, $b) {
396
	if (ip2long($a) < ip2long($b))
397
		return -1;
398
	else if (ip2long($a) > ip2long($b))
399
		return 1;
400
	else
401
		return 0;
402
}
403

    
404
/* return true if $addr is in $subnet, false if not */
405
function ip_in_subnet($addr,$subnet) {
406
	list($ip, $mask) = explode('/', $subnet);
407
	$mask = 0xffffffff << (32 - $mask);
408
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
409
}
410

    
411
/* verify (and remove) the digital signature on a file - returns 0 if OK */
412
function verify_digital_signature($fname) {
413

    
414
	global $g;
415

    
416
	return mwexec("/usr/local/bin/verifysig " .
417
		escapeshellarg("{$g['etc_path']}/pubkey.pem") . " " .
418
		escapeshellarg($fname));
419
}
420

    
421
/* obtain MAC address given an IP address by looking at the ARP table */
422
function arp_get_mac_by_ip($ip) {
423
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
424
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
425

    
426
	if ($arpoutput[0]) {
427
		$arpi = explode(" ", $arpoutput[0]);
428
		$macaddr = $arpi[3];
429
		if (is_macaddr($macaddr))
430
			return $macaddr;
431
		else
432
			return false;
433
	}
434

    
435
	return false;
436
}
437

    
438
/* return a fieldname that is safe for xml usage */
439
function xml_safe_fieldname($fieldname) {
440
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
441
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
442
			 ':', ',', '.', '\'', '\\'
443
		);
444
	return strtolower(str_replace($replace, "", $fieldname));
445
}
446

    
447
?>
(17-17/23)