Project

General

Profile

Download (12.1 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
		$pid = trim(file_get_contents($pidfile));
41
		mwexec("/bin/kill -s $sig {$pid}");
42
	} else {
43
		mwexec("/bin/kill -s $sig {$pidfile}");
44
	}
45
}
46

    
47
/* kill a process by name */
48
function killbyname($procname) {
49
	mwexec("/usr/bin/killall " . escapeshellarg($procname));
50
}
51

    
52
/* return the subnet address given a host address and a subnet bit count */
53
function gen_subnet($ipaddr, $bits) {
54
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
55
		return "";
56

    
57
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
58
}
59

    
60
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
61
function gen_subnet_max($ipaddr, $bits) {
62
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
63
		return "";
64

    
65
	return long2ip(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
66
}
67

    
68
/* returns a subnet mask (long given a bit count) */
69
function gen_subnet_mask_long($bits) {
70
	$sm = 0;
71
	for ($i = 0; $i < $bits; $i++) {
72
		$sm >>= 1;
73
		$sm |= 0x80000000;
74
	}
75
	return $sm;
76
}
77

    
78
/* same as above but returns a string */
79
function gen_subnet_mask($bits) {
80
	return long2ip(gen_subnet_mask_long($bits));
81
}
82

    
83
function is_numericint($arg) {
84
	return (preg_match("/[^0-9]/", $arg) ? false : true);
85
}
86

    
87
/* returns true if $ipaddr is a valid dotted IPv4 address */
88
function is_ipaddr($ipaddr) {
89
	if (!is_string($ipaddr))
90
		return false;
91

    
92
	$ip_long = ip2long($ipaddr);
93
	$ip_reverse = long2ip($ip_long);
94

    
95
	if ($ipaddr == $ip_reverse)
96
		return true;
97
	else
98
		return false;
99
}
100

    
101
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
102
function is_ipaddroralias($ipaddr) {
103

    
104
	global $aliastable, $config;
105

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

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

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

    
123
	global $aliastable;
124

    
125
	if (isset($aliastable[$ipaddr]))
126
		return true;
127
	else
128
		return is_ipaddr($ipaddr);
129
}
130

    
131
/* returns true if $subnet is a valid subnet in CIDR format */
132
function is_subnet($subnet) {
133
	if (!is_string($subnet))
134
		return false;
135

    
136
	list($hp,$np) = explode('/', $subnet);
137

    
138
	if (!is_ipaddr($hp))
139
		return false;
140

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

    
144
	return true;
145
}
146

    
147
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
148
function is_subnetoralias($subnet) {
149

    
150
	global $aliastable;
151

    
152
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
153
		return true;
154
	else
155
		return is_subnet($subnet);
156
}
157

    
158
/* returns true if $hostname is a valid hostname */
159
function is_hostname($hostname) {
160
	if (!is_string($hostname))
161
		return false;
162

    
163
	if (preg_match("/^[a-z0-9\-]+$/i", $hostname))
164
		return true;
165
	else
166
		return false;
167
}
168

    
169
/* returns true if $domain is a valid domain name */
170
function is_domain($domain) {
171
	if (!is_string($domain))
172
		return false;
173

    
174
	if (preg_match("/^([a-z0-9\-]+\.?)*$/i", $domain))
175
		return true;
176
	else
177
		return false;
178
}
179

    
180
/* returns true if $uname is a valid DynDNS username */
181
function is_dyndns_username($uname) {
182
	if (!is_string($uname))
183
		return false;
184

    
185
	if (preg_match("/[^a-z0-9\-.@_]/i", $uname))
186
		return false;
187
	else
188
		return true;
189
}
190

    
191
/* returns true if $macaddr is a valid MAC address */
192
function is_macaddr($macaddr) {
193
	if (!is_string($macaddr))
194
		return false;
195

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

    
200
	foreach ($maca as $macel) {
201
		if (($macel === "") || (strlen($macel) > 2))
202
			return false;
203
		if (preg_match("/[^0-9a-f]/i", $macel))
204
			return false;
205
	}
206

    
207
	return true;
208
}
209

    
210
/* returns true if $name is a valid name for an alias */
211
/* returns NULL if a reserved word is used */
212
function is_validaliasname($name) {
213
	/* Array of reserved words */
214
	$reserved = array("port", "pass");
215
	if (in_array($name, $reserved, true))
216
		return; /* return NULL */
217

    
218
	if (!preg_match("/[^a-zA-Z0-9]/", $name))
219
		return true;
220
	else
221
		return false;
222
}
223

    
224
/* returns true if $port is a valid TCP/UDP port */
225
function is_port($port) {
226
	if (!is_numericint($port))
227
		return false;
228

    
229
	if (($port < 1) || ($port > 65535))
230
		return false;
231
	else
232
		return true;
233
}
234

    
235
/*
236
 *   get_interface_list() - Return a list of all physical interfaces
237
 *   along with MAC and status.
238
 *
239
 *   $mode = "active" - use ifconfig -lu
240
 *           "media"  - use ifconfig to check physical connection
241
 *			status (much slower)
242
 */
243
/*
244
 *   get_interface_list() - Return a list of all physical interfaces
245
 *   along with MAC and status.
246
 *
247
 *   $mode = "active" - use ifconfig -lu
248
 *           "media"  - use ifconfig to check physical connection
249
 *			status (much slower)
250
 */
251
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
252
        global $config;
253
	$upints = array();
254
        /* get a list of virtual interface types */
255
        if(!$vfaces) {
256
		$vfaces = array(
257
				'ppp',
258
				'sl',
259
				'gif',
260
				'faith',
261
				'lo',
262
				'ng',
263
				'vlan',
264
				'tun',
265
				'pflog',
266
				'pfsync',
267
				'carp'
268
			);
269
	}
270
	switch($mode) {
271
	case "active":
272
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
273
        	break;
274
	case "media":
275
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
276
                exec("/sbin/ifconfig -a", $ifconfig);
277
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
278
                $ifstatus = preg_grep('/status:/', $ifconfig);
279
		foreach($ifstatus as $status) {
280
			$int = array_shift($intlist);
281
                	if(stristr($status, "active")) $upints[] = $int;
282
		}
283
		break;
284
	}
285
        /* build interface list with netstat */
286
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
287
        array_shift($linkinfo);
288
	/* build ip address list with netstat */
289
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
290
	array_shift($ipinfo);
291
	foreach($linkinfo as $link) {
292
		$friendly = "";
293
                $alink = explode(" ", $link);
294
                $ifname = rtrim(trim($alink[0]), '*');
295
                /* trim out all numbers before checking for vfaces */
296
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces)) {
297
			$toput = array(
298
					"mac" => trim($alink[1]),
299
					"up" => in_array($ifname, $upints)
300
				);
301
			foreach($ipinfo as $ip) {
302
				$aip = explode(" ", $ip);
303
				if($aip[0] == $ifname) {
304
					$toput['ipaddr'] = $aip[1];
305
				}
306
			}
307
			foreach($config['interfaces'] as $name => $int) {
308
				if($int['if'] == $ifname) $friendly = $name;
309
			}
310
			switch($keyby) {
311
			case "physical":
312
				if($friendly != "") {
313
					$toput['friendly'] = $friendly;
314
				}
315
				$iflist[$ifname] = $toput;
316
				break;
317
			case "friendly":
318
				if($friendly != "") {
319
					$toput['if'] = $ifname;
320
					$iflist[$friendly] = $toput;
321
				}
322
				break;
323
			}
324
                }
325
        }
326
        return $iflist;
327
}
328

    
329
/* wrapper for exec() */
330
function mwexec($command) {
331

    
332
	global $g;
333

    
334
	if ($g['debug']) {
335
		if (!$_SERVER['REMOTE_ADDR'])
336
			echo "mwexec(): $command\n";
337
		exec("$command > /dev/null 2>&1", $oarr, $retval);
338
	} else {
339
		exec("$command > /dev/null 2>&1", $oarr, $retval);
340
	}
341

    
342
	return $retval;
343
}
344

    
345
/* wrapper for exec() in background */
346
function mwexec_bg($command) {
347

    
348
	global $g;
349

    
350
	if ($g['debug']) {
351
		if (!$_SERVER['REMOTE_ADDR'])
352
			echo "mwexec(): $command\n";
353
	}
354

    
355
	exec("nohup $command > /dev/null 2>&1 &");
356
}
357

    
358
/* unlink a file, if it exists */
359
function unlink_if_exists($fn) {
360
	$to_do = glob($fn);
361
	if(is_array($to_do)) {
362
		foreach($to_do as $filename)
363
			@unlink($filename);
364
	} else {
365
		@unlink($fn);
366
	}
367
}
368

    
369
/* make a global alias table (for faster lookups) */
370
function alias_make_table($config) {
371

    
372
	global $aliastable;
373

    
374
	$aliastable = array();
375

    
376
	if (is_array($config['aliases']['alias'])) {
377
		foreach ($config['aliases']['alias'] as $alias) {
378
			if ($alias['name'])
379
				$aliastable[$alias['name']] = $alias['address'];
380
		}
381
	}
382
}
383

    
384
/* check if an alias exists */
385
function is_alias($name) {
386

    
387
	global $aliastable;
388

    
389
	return isset($aliastable[$name]);
390
}	
391

    
392
function alias_expand_value($name) {
393

    
394
	global $aliastable, $config;
395

    
396
	foreach($config['aliases']['alias'] as $alias) {
397
		if($alias['name'] == $name)
398
			return $alias['address'];
399
	}
400

    
401
}
402

    
403
/* expand a host or network alias, if necessary */
404
function alias_expand($name) {
405

    
406
	global $aliastable;
407

    
408
	if (isset($aliastable[$name]))
409
		return "\${$name}";
410
	else if (is_ipaddr($name) || is_subnet($name))
411
		return "{$name}";
412
	else
413
		return null;
414
}
415

    
416
/* expand a host alias, if necessary */
417
function alias_expand_host($name) {
418

    
419
	global $aliastable;
420

    
421
	if (isset($aliastable[$name]) && is_ipaddr($aliastable[$name]))
422
		return $aliastable[$name];
423
	else if (is_ipaddr($name))
424
		return $name;
425
	else
426
		return null;
427
}
428

    
429
/* expand a network alias, if necessary */
430
function alias_expand_net($name) {
431

    
432
	global $aliastable;
433

    
434
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
435
		return $aliastable[$name];
436
	else if (is_subnet($name))
437
		return $name;
438
	else
439
		return null;
440
}
441

    
442
/* find out whether two subnets overlap */
443
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
444

    
445
	if (!is_numeric($bits1))
446
		$bits1 = 32;
447
	if (!is_numeric($bits2))
448
		$bits2 = 32;
449

    
450
	if ($bits1 < $bits2)
451
		$relbits = $bits1;
452
	else
453
		$relbits = $bits2;
454

    
455
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
456
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
457

    
458
	if ($sn1 == $sn2)
459
		return true;
460
	else
461
		return false;
462
}
463

    
464
/* compare two IP addresses */
465
function ipcmp($a, $b) {
466
	if (ip2long($a) < ip2long($b))
467
		return -1;
468
	else if (ip2long($a) > ip2long($b))
469
		return 1;
470
	else
471
		return 0;
472
}
473

    
474
/* return true if $addr is in $subnet, false if not */
475
function ip_in_subnet($addr,$subnet) {
476
	list($ip, $mask) = explode('/', $subnet);
477
	$mask = 0xffffffff << (32 - $mask);
478
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
479
}
480

    
481
/* verify (and remove) the digital signature on a file - returns 0 if OK */
482
function verify_digital_signature($fname) {
483

    
484
	global $g;
485

    
486
	return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname));
487

    
488
}
489

    
490
/* obtain MAC address given an IP address by looking at the ARP table */
491
function arp_get_mac_by_ip($ip) {
492
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
493
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
494

    
495
	if ($arpoutput[0]) {
496
		$arpi = explode(" ", $arpoutput[0]);
497
		$macaddr = $arpi[3];
498
		if (is_macaddr($macaddr))
499
			return $macaddr;
500
		else
501
			return false;
502
	}
503

    
504
	return false;
505
}
506

    
507
/* return a fieldname that is safe for xml usage */
508
function xml_safe_fieldname($fieldname) {
509
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
510
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
511
			 ':', ',', '.', '\'', '\\'
512
		);
513
	return strtolower(str_replace($replace, "", $fieldname));
514
}
515

    
516
?>
(20-20/26)