Project

General

Profile

Download (11.3 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
        foreach ($linkinfo as $link) {
264
                $alink = explode(" ", $link);
265
                $ifname = rtrim(trim($alink[0]), '*');
266
                if (!in_array(substr($ifname, 0, -1), $vfaces)) {
267
			$toput = array(
268
					"mac" => trim($alink[1]),
269
					"up" => in_array($ifname, $upints)
270
				);
271
			foreach($config['interfaces'] as $name => $int) {
272
				if($int['if'] == $ifname) $friendly = $name;
273
			}
274
			switch($keyby) {
275
			case "physical":
276
				$toput['friendly'] = $friendly;
277
				$iflist[$ifname] = $toput;
278
				break;
279
			case "friendly":
280
				$toput['if'] = $ifname;
281
				$iflist[$friendly] = $toput;
282
				break;
283
			}
284
                }
285
        }
286
        return $iflist;
287
}
288

    
289
/* wrapper for exec() */
290
function mwexec($command) {
291

    
292
	global $g;
293

    
294
	if ($g['debug']) {
295
		if (!$_SERVER['REMOTE_ADDR'])
296
			echo "mwexec(): $command\n";
297
		passthru($command, $retval);
298
	} else {
299
		exec("$command > /dev/null 2>&1", $oarr, $retval);
300
	}
301

    
302
	return $retval;
303
}
304

    
305
/* wrapper for exec() in background */
306
function mwexec_bg($command) {
307

    
308
	global $g;
309

    
310
	if ($g['debug']) {
311
		if (!$_SERVER['REMOTE_ADDR'])
312
			echo "mwexec(): $command\n";
313
	}
314

    
315
	exec("nohup $command > /dev/null 2>&1 &");
316
}
317

    
318
/* unlink a file, if it exists */
319
function unlink_if_exists($fn) {
320
	$to_do = glob($fn);
321
	if(is_array($to_do)) {
322
		foreach($to_do as $filename)
323
			@unlink($filename);
324
	} else {
325
		@unlink($fn);
326
	}
327
}
328

    
329
/* make a global alias table (for faster lookups) */
330
function alias_make_table($config) {
331

    
332
	global $aliastable;
333

    
334
	$aliastable = array();
335

    
336
	if (is_array($config['aliases']['alias'])) {
337
		foreach ($config['aliases']['alias'] as $alias) {
338
			if ($alias['name'])
339
				$aliastable[$alias['name']] = $alias['address'];
340
		}
341
	}
342
}
343

    
344
/* check if an alias exists */
345
function is_alias($name) {
346

    
347
	global $aliastable;
348

    
349
	return isset($aliastable[$name]);
350
}	
351

    
352
function alias_expand_value($name) {
353

    
354
	global $aliastable, $config;
355

    
356
	foreach($config['aliases']['alias'] as $alias) {
357
		if($alias['name'] == $name)
358
			return $alias['address'];
359
	}
360

    
361
}
362

    
363
/* expand a host or network alias, if necessary */
364
function alias_expand($name) {
365

    
366
	global $aliastable;
367

    
368
	if (isset($aliastable[$name]))
369
		return "\${$name}";
370
	else if (is_ipaddr($name) || is_subnet($name))
371
		return "{$name}";
372
	else
373
		return null;
374
}
375

    
376
/* expand a host alias, if necessary */
377
function alias_expand_host($name) {
378

    
379
	global $aliastable;
380

    
381
	if (isset($aliastable[$name]) && is_ipaddr($aliastable[$name]))
382
		return $aliastable[$name];
383
	else if (is_ipaddr($name))
384
		return $name;
385
	else
386
		return null;
387
}
388

    
389
/* expand a network alias, if necessary */
390
function alias_expand_net($name) {
391

    
392
	global $aliastable;
393

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

    
402
/* find out whether two subnets overlap */
403
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
404

    
405
	if (!is_numeric($bits1))
406
		$bits1 = 32;
407
	if (!is_numeric($bits2))
408
		$bits2 = 32;
409

    
410
	if ($bits1 < $bits2)
411
		$relbits = $bits1;
412
	else
413
		$relbits = $bits2;
414

    
415
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
416
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
417

    
418
	if ($sn1 == $sn2)
419
		return true;
420
	else
421
		return false;
422
}
423

    
424
/* compare two IP addresses */
425
function ipcmp($a, $b) {
426
	if (ip2long($a) < ip2long($b))
427
		return -1;
428
	else if (ip2long($a) > ip2long($b))
429
		return 1;
430
	else
431
		return 0;
432
}
433

    
434
/* return true if $addr is in $subnet, false if not */
435
function ip_in_subnet($addr,$subnet) {
436
	list($ip, $mask) = explode('/', $subnet);
437
	$mask = 0xffffffff << (32 - $mask);
438
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
439
}
440

    
441
/* verify (and remove) the digital signature on a file - returns 0 if OK */
442
function verify_digital_signature($fname) {
443

    
444
	global $g;
445

    
446
	return mwexec("/usr/local/bin/verifysig " .
447
		escapeshellarg("{$g['etc_path']}/pubkey.pem") . " " .
448
		escapeshellarg($fname));
449
}
450

    
451
/* obtain MAC address given an IP address by looking at the ARP table */
452
function arp_get_mac_by_ip($ip) {
453
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
454
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
455

    
456
	if ($arpoutput[0]) {
457
		$arpi = explode(" ", $arpoutput[0]);
458
		$macaddr = $arpi[3];
459
		if (is_macaddr($macaddr))
460
			return $macaddr;
461
		else
462
			return false;
463
	}
464

    
465
	return false;
466
}
467

    
468
/* return a fieldname that is safe for xml usage */
469
function xml_safe_fieldname($fieldname) {
470
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
471
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
472
			 ':', ',', '.', '\'', '\\'
473
		);
474
	return strtolower(str_replace($replace, "", $fieldname));
475
}
476

    
477
?>
(18-18/24)