Project

General

Profile

Download (12.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
		$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
				'bridge',
258
				'ppp',
259
				'sl',
260
				'gif',
261
				'faith',
262
				'lo',
263
				'ng',
264
				'vlan',
265
				'tun',
266
				'pflog',
267
				'pfsync',
268
				'carp'
269
			);
270
	}
271
	switch($mode) {
272
	case "active":
273
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
274
        	break;
275
	case "media":
276
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
277
                $ifconfig = "";
278
                exec("/sbin/ifconfig -a", $ifconfig);
279
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
280
                $ifstatus = preg_grep('/status:/', $ifconfig);
281
		foreach($ifstatus as $status) {
282
			$int = array_shift($intlist);
283
                	if(stristr($status, "active")) $upints[] = $int;
284
		}
285
		break;
286
	}
287
        /* build interface list with netstat */
288
        $linkinfo = "";
289
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
290
        array_shift($linkinfo);
291
	/* build ip address list with netstat */
292
	$ipinfo = "";
293
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
294
	array_shift($ipinfo);
295
	foreach($linkinfo as $link) {
296
		$friendly = "";
297
                $alink = explode(" ", $link);
298
                $ifname = rtrim(trim($alink[0]), '*');
299
                /* trim out all numbers before checking for vfaces */
300
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces)) {
301
			$toput = array(
302
					"mac" => trim($alink[1]),
303
					"up" => in_array($ifname, $upints)
304
				);
305
			foreach($ipinfo as $ip) {
306
				$aip = explode(" ", $ip);
307
				if($aip[0] == $ifname) {
308
					$toput['ipaddr'] = $aip[1];
309
				}
310
			}
311
			foreach($config['interfaces'] as $name => $int) {
312
				if($int['if'] == $ifname) $friendly = $name;
313
			}
314
			switch($keyby) {
315
			case "physical":
316
				if($friendly != "") {
317
					$toput['friendly'] = $friendly;
318
				}
319
				$iflist[$ifname] = $toput;
320
				break;
321
			case "friendly":
322
				if($friendly != "") {
323
					$toput['if'] = $ifname;
324
					$iflist[$friendly] = $toput;
325
				}
326
				break;
327
			}
328
                }
329
        }
330
        return $iflist;
331
}
332

    
333
/* wrapper for exec() */
334
function mwexec($command) {
335

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

    
347
	return $retval;
348
}
349

    
350
/* wrapper for exec() in background */
351
function mwexec_bg($command) {
352

    
353
	global $g;
354

    
355
	if ($g['debug']) {
356
		if (!$_SERVER['REMOTE_ADDR'])
357
			echo "mwexec(): $command\n";
358
	}
359

    
360
	exec("nohup $command > /dev/null 2>&1 &");
361
}
362

    
363
/* unlink a file, if it exists */
364
function unlink_if_exists($fn) {
365
	$to_do = glob($fn);
366
	if(is_array($to_do)) {
367
		foreach($to_do as $filename)
368
			@unlink($filename);
369
	} else {
370
		@unlink($fn);
371
	}
372
}
373

    
374
/* make a global alias table (for faster lookups) */
375
function alias_make_table($config) {
376

    
377
	global $aliastable;
378

    
379
	$aliastable = array();
380

    
381
	if (is_array($config['aliases']['alias'])) {
382
		foreach ($config['aliases']['alias'] as $alias) {
383
			if ($alias['name'])
384
				$aliastable[$alias['name']] = $alias['address'];
385
		}
386
	}
387
}
388

    
389
/* check if an alias exists */
390
function is_alias($name) {
391

    
392
	global $aliastable;
393

    
394
	return isset($aliastable[$name]);
395
}	
396

    
397
function alias_expand_value($name) {
398

    
399
	global $aliastable, $config;
400

    
401
	foreach($config['aliases']['alias'] as $alias) {
402
		if($alias['name'] == $name)
403
			return $alias['address'];
404
	}
405

    
406
}
407

    
408
/* expand a host or network alias, if necessary */
409
function alias_expand($name) {
410

    
411
	global $aliastable;
412

    
413
	if (isset($aliastable[$name]))
414
		return "\${$name}";
415
	else if (is_ipaddr($name) || is_subnet($name))
416
		return "{$name}";
417
	else
418
		return null;
419
}
420

    
421
/* expand a host alias, if necessary */
422
function alias_expand_host($name) {
423

    
424
	global $aliastable;
425

    
426
	if (isset($aliastable[$name]) && is_ipaddr($aliastable[$name]))
427
		return $aliastable[$name];
428
	else if (is_ipaddr($name))
429
		return $name;
430
	else
431
		return null;
432
}
433

    
434
/* expand a network alias, if necessary */
435
function alias_expand_net($name) {
436

    
437
	global $aliastable;
438

    
439
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
440
		return $aliastable[$name];
441
	else if (is_subnet($name))
442
		return $name;
443
	else
444
		return null;
445
}
446

    
447
/* find out whether two subnets overlap */
448
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
449

    
450
	if (!is_numeric($bits1))
451
		$bits1 = 32;
452
	if (!is_numeric($bits2))
453
		$bits2 = 32;
454

    
455
	if ($bits1 < $bits2)
456
		$relbits = $bits1;
457
	else
458
		$relbits = $bits2;
459

    
460
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
461
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
462

    
463
	if ($sn1 == $sn2)
464
		return true;
465
	else
466
		return false;
467
}
468

    
469
/* compare two IP addresses */
470
function ipcmp($a, $b) {
471
	if (ip2long($a) < ip2long($b))
472
		return -1;
473
	else if (ip2long($a) > ip2long($b))
474
		return 1;
475
	else
476
		return 0;
477
}
478

    
479
/* return true if $addr is in $subnet, false if not */
480
function ip_in_subnet($addr,$subnet) {
481
	list($ip, $mask) = explode('/', $subnet);
482
	$mask = 0xffffffff << (32 - $mask);
483
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
484
}
485

    
486
/* verify (and remove) the digital signature on a file - returns 0 if OK */
487
function verify_digital_signature($fname) {
488

    
489
	global $g;
490

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

    
493
}
494

    
495
/* obtain MAC address given an IP address by looking at the ARP table */
496
function arp_get_mac_by_ip($ip) {
497
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
498
	$arpoutput = "";
499
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
500

    
501
	if ($arpoutput[0]) {
502
		$arpi = explode(" ", $arpoutput[0]);
503
		$macaddr = $arpi[3];
504
		if (is_macaddr($macaddr))
505
			return $macaddr;
506
		else
507
			return false;
508
	}
509

    
510
	return false;
511
}
512

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

    
522
?>
(21-21/27)