Project

General

Profile

Download (10 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(!$config['aliases']['alias']) 
104
		return;
105

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

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

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

    
121
	global $aliastable;
122

    
123
	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

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

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

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

    
142
	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

    
148
	global $aliastable;
149

    
150
	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

    
161
	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

    
172
	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

    
183
	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

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

    
198
	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

    
205
	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

    
221
	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

    
234
	$iflist = array();
235

    
236
	foreach ($linkinfo as $link) {
237
		$alink = preg_split("/\s+/", $link);
238
		$ifname = chop($alink[0]);
239

    
240
		if (substr($ifname, -1) == "*")
241
			$ifname = substr($ifname, 0, strlen($ifname) - 1);
242

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

    
246
			$iflist[$ifname]['mac'] = chop($alink[3]);
247
			$iflist[$ifname]['up'] = false;
248

    
249
			/* find out if the link on this interface is up */
250
			unset($ifinfo);
251
			exec("/sbin/ifconfig {$ifname}", $ifinfo);
252

    
253
			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

    
263
	return $iflist;
264
}
265

    
266
/* wrapper for exec() */
267
function mwexec($command) {
268

    
269
	global $g;
270

    
271
	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

    
279
	return $retval;
280
}
281

    
282
/* wrapper for exec() in background */
283
function mwexec_bg($command) {
284

    
285
	global $g;
286

    
287
	if ($g['debug']) {
288
		if (!$_SERVER['REMOTE_ADDR'])
289
			echo "mwexec(): $command\n";
290
	}
291

    
292
	exec("nohup $command > /dev/null 2>&1 &");
293
}
294

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

    
306
/* make a global alias table (for faster lookups) */
307
function alias_make_table($config) {
308

    
309
	global $aliastable;
310

    
311
	$aliastable = array();
312

    
313
	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

    
324
	global $aliastable;
325

    
326
	return isset($aliastable[$name]);
327
}
328

    
329
/* expand a host or network alias, if necessary */
330
function alias_expand($name) {
331

    
332
	global $aliastable;
333

    
334
	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

    
345
	global $aliastable;
346

    
347
	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

    
358
	global $aliastable;
359

    
360
	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

    
381
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
382
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
383

    
384
	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
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
420
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
421

    
422
	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

    
431
	return false;
432
}
433

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

    
443
?>
(17-17/22)