Project

General

Profile

Download (11.6 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
/* returns NULL if a reserved word is used */
209
function is_validaliasname($name) {
210
	/* Array of reserved words */
211
	$reserved = array("port", "pass");
212
	if (in_array($name, $reserved, true))
213
		return; /* return NULL */
214

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

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

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

    
232
/*
233
 *   get_interface_list() - Return a list of all physical interfaces
234
 *   along with MAC and status.
235
 *
236
 *   $mode = "active" - use ifconfig -lu
237
 *           "media"  - use ifconfig to check physical connection
238
 *			status (much slower)
239
 */
240
function get_interface_list($mode = "active", $keyby = "physical") {
241
        global $config;
242
	$upints = array();
243
        /* get a list of virtual interface types */
244
        $vfaces = explode(" ", trim(shell_exec("/sbin/ifconfig -C")));
245
	switch($mode) {
246
	case "active":
247
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
248
        	break;
249
	case "media":
250
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
251
                exec("/sbin/ifconfig -a", $ifconfig);
252
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
253
                $ifstatus = preg_grep('/status:/', $ifconfig);
254
		foreach($ifstatus as $status) {
255
			$int = array_shift($intlist);
256
                	if(stristr($status, "active")) $upints[] = $int;
257
		}
258
		break;
259
	}
260
        /* build interface list with netstat */
261
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
262
        array_shift($linkinfo);
263
	/* build ip address list with netstat */
264
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
265
	array_shift($ipinfo);
266
	foreach($linkinfo as $link) {
267
		$friendly = "";
268
                $alink = explode(" ", $link);
269
                $ifname = rtrim(trim($alink[0]), '*');
270
                if (!in_array(substr($ifname, 0, -1), $vfaces)) {
271
			$toput = array(
272
					"mac" => trim($alink[1]),
273
					"up" => in_array($ifname, $upints)
274
				);
275
			foreach($ipinfo as $ip) {
276
				$aip = explode(" ", $ip);
277
				if($aip[0] == $ifname) {
278
					$toput['ipaddr'] = $aip[1];
279
				}
280
			}
281
			foreach($config['interfaces'] as $name => $int) {
282
				if($int['if'] == $ifname) $friendly = $name;
283
			}
284
			switch($keyby) {
285
			case "physical":
286
				if($friendly != "") {
287
					$toput['friendly'] = $friendly;
288
				}
289
				$iflist[$ifname] = $toput;
290
				break;
291
			case "friendly":
292
				if($friendly != "") {
293
					$toput['if'] = $ifname;
294
					$iflist[$friendly] = $toput;
295
				}
296
				break;
297
			}
298
                }
299
        }
300
        return $iflist;
301
}
302

    
303
/* wrapper for exec() */
304
function mwexec($command) {
305

    
306
	global $g;
307

    
308
	if ($g['debug']) {
309
		if (!$_SERVER['REMOTE_ADDR'])
310
			echo "mwexec(): $command\n";
311
		exec("$command > /dev/null 2>&1", $oarr, $retval);
312
	} else {
313
		exec("$command > /dev/null 2>&1", $oarr, $retval);
314
	}
315

    
316
	return $retval;
317
}
318

    
319
/* wrapper for exec() in background */
320
function mwexec_bg($command) {
321

    
322
	global $g;
323

    
324
	if ($g['debug']) {
325
		if (!$_SERVER['REMOTE_ADDR'])
326
			echo "mwexec(): $command\n";
327
	}
328

    
329
	exec("nohup $command > /dev/null 2>&1 &");
330
}
331

    
332
/* unlink a file, if it exists */
333
function unlink_if_exists($fn) {
334
	$to_do = glob($fn);
335
	if(is_array($to_do)) {
336
		foreach($to_do as $filename)
337
			@unlink($filename);
338
	} else {
339
		@unlink($fn);
340
	}
341
}
342

    
343
/* make a global alias table (for faster lookups) */
344
function alias_make_table($config) {
345

    
346
	global $aliastable;
347

    
348
	$aliastable = array();
349

    
350
	if (is_array($config['aliases']['alias'])) {
351
		foreach ($config['aliases']['alias'] as $alias) {
352
			if ($alias['name'])
353
				$aliastable[$alias['name']] = $alias['address'];
354
		}
355
	}
356
}
357

    
358
/* check if an alias exists */
359
function is_alias($name) {
360

    
361
	global $aliastable;
362

    
363
	return isset($aliastable[$name]);
364
}	
365

    
366
function alias_expand_value($name) {
367

    
368
	global $aliastable, $config;
369

    
370
	foreach($config['aliases']['alias'] as $alias) {
371
		if($alias['name'] == $name)
372
			return $alias['address'];
373
	}
374

    
375
}
376

    
377
/* expand a host or network alias, if necessary */
378
function alias_expand($name) {
379

    
380
	global $aliastable;
381

    
382
	if (isset($aliastable[$name]))
383
		return "\${$name}";
384
	else if (is_ipaddr($name) || is_subnet($name))
385
		return "{$name}";
386
	else
387
		return null;
388
}
389

    
390
/* expand a host alias, if necessary */
391
function alias_expand_host($name) {
392

    
393
	global $aliastable;
394

    
395
	if (isset($aliastable[$name]) && is_ipaddr($aliastable[$name]))
396
		return $aliastable[$name];
397
	else if (is_ipaddr($name))
398
		return $name;
399
	else
400
		return null;
401
}
402

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

    
406
	global $aliastable;
407

    
408
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
409
		return $aliastable[$name];
410
	else if (is_subnet($name))
411
		return $name;
412
	else
413
		return null;
414
}
415

    
416
/* find out whether two subnets overlap */
417
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
418

    
419
	if (!is_numeric($bits1))
420
		$bits1 = 32;
421
	if (!is_numeric($bits2))
422
		$bits2 = 32;
423

    
424
	if ($bits1 < $bits2)
425
		$relbits = $bits1;
426
	else
427
		$relbits = $bits2;
428

    
429
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
430
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
431

    
432
	if ($sn1 == $sn2)
433
		return true;
434
	else
435
		return false;
436
}
437

    
438
/* compare two IP addresses */
439
function ipcmp($a, $b) {
440
	if (ip2long($a) < ip2long($b))
441
		return -1;
442
	else if (ip2long($a) > ip2long($b))
443
		return 1;
444
	else
445
		return 0;
446
}
447

    
448
/* return true if $addr is in $subnet, false if not */
449
function ip_in_subnet($addr,$subnet) {
450
	list($ip, $mask) = explode('/', $subnet);
451
	$mask = 0xffffffff << (32 - $mask);
452
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
453
}
454

    
455
/* verify (and remove) the digital signature on a file - returns 0 if OK */
456
function verify_digital_signature($fname) {
457

    
458
	global $g;
459

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

    
462
}
463

    
464
/* obtain MAC address given an IP address by looking at the ARP table */
465
function arp_get_mac_by_ip($ip) {
466
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
467
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
468

    
469
	if ($arpoutput[0]) {
470
		$arpi = explode(" ", $arpoutput[0]);
471
		$macaddr = $arpi[3];
472
		if (is_macaddr($macaddr))
473
			return $macaddr;
474
		else
475
			return false;
476
	}
477

    
478
	return false;
479
}
480

    
481
/* return a fieldname that is safe for xml usage */
482
function xml_safe_fieldname($fieldname) {
483
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
484
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
485
			 ':', ',', '.', '\'', '\\'
486
		);
487
	return strtolower(str_replace($replace, "", $fieldname));
488
}
489

    
490
?>
(19-19/25)