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
				'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
                $ifconfig = "";
277
                exec("/sbin/ifconfig -a", $ifconfig);
278
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
279
                $ifstatus = preg_grep('/status:/', $ifconfig);
280
		foreach($ifstatus as $status) {
281
			$int = array_shift($intlist);
282
                	if(stristr($status, "active")) $upints[] = $int;
283
		}
284
		break;
285
	}
286
        /* build interface list with netstat */
287
        $linkinfo = "";
288
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
289
        array_shift($linkinfo);
290
	/* build ip address list with netstat */
291
	$ipinfo = "";
292
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
293
	array_shift($ipinfo);
294
	foreach($linkinfo as $link) {
295
		$friendly = "";
296
                $alink = explode(" ", $link);
297
                $ifname = rtrim(trim($alink[0]), '*');
298
                /* trim out all numbers before checking for vfaces */
299
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces)) {
300
			$toput = array(
301
					"mac" => trim($alink[1]),
302
					"up" => in_array($ifname, $upints)
303
				);
304
			foreach($ipinfo as $ip) {
305
				$aip = explode(" ", $ip);
306
				if($aip[0] == $ifname) {
307
					$toput['ipaddr'] = $aip[1];
308
				}
309
			}
310
			foreach($config['interfaces'] as $name => $int) {
311
				if($int['if'] == $ifname) $friendly = $name;
312
			}
313
			switch($keyby) {
314
			case "physical":
315
				if($friendly != "") {
316
					$toput['friendly'] = $friendly;
317
				}
318
				$iflist[$ifname] = $toput;
319
				break;
320
			case "friendly":
321
				if($friendly != "") {
322
					$toput['if'] = $ifname;
323
					$iflist[$friendly] = $toput;
324
				}
325
				break;
326
			}
327
                }
328
        }
329
        return $iflist;
330
}
331

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

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

    
346
	return $retval;
347
}
348

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

    
352
	global $g;
353

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

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

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

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

    
376
	global $aliastable;
377

    
378
	$aliastable = array();
379

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

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

    
391
	global $aliastable;
392

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

    
396
function alias_expand_value($name) {
397

    
398
	global $aliastable, $config;
399

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

    
405
}
406

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

    
410
	global $aliastable;
411

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

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

    
423
	global $aliastable;
424

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

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

    
436
	global $aliastable;
437

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

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

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

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

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

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

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

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

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

    
488
	global $g;
489

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

    
492
}
493

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

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

    
509
	return false;
510
}
511

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

    
521
?>
(21-21/27)