Project

General

Profile

Download (11.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
		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
/* expand a host or network alias, if necessary */
353
function alias_expand($name) {
354

    
355
	global $aliastable;
356

    
357
	if (isset($aliastable[$name]))
358
		return "\${$name}";
359
	else if (is_ipaddr($name) || is_subnet($name))
360
		return "{$name}";
361
	else
362
		return null;
363
}
364

    
365
/* expand a host alias, if necessary */
366
function alias_expand_host($name) {
367

    
368
	global $aliastable;
369

    
370
	if (isset($aliastable[$name]) && is_ipaddr($aliastable[$name]))
371
		return $aliastable[$name];
372
	else if (is_ipaddr($name))
373
		return $name;
374
	else
375
		return null;
376
}
377

    
378
/* expand a network alias, if necessary */
379
function alias_expand_net($name) {
380

    
381
	global $aliastable;
382

    
383
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
384
		return $aliastable[$name];
385
	else if (is_subnet($name))
386
		return $name;
387
	else
388
		return null;
389
}
390

    
391
/* find out whether two subnets overlap */
392
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
393

    
394
	if (!is_numeric($bits1))
395
		$bits1 = 32;
396
	if (!is_numeric($bits2))
397
		$bits2 = 32;
398

    
399
	if ($bits1 < $bits2)
400
		$relbits = $bits1;
401
	else
402
		$relbits = $bits2;
403

    
404
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
405
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
406

    
407
	if ($sn1 == $sn2)
408
		return true;
409
	else
410
		return false;
411
}
412

    
413
/* compare two IP addresses */
414
function ipcmp($a, $b) {
415
	if (ip2long($a) < ip2long($b))
416
		return -1;
417
	else if (ip2long($a) > ip2long($b))
418
		return 1;
419
	else
420
		return 0;
421
}
422

    
423
/* return true if $addr is in $subnet, false if not */
424
function ip_in_subnet($addr,$subnet) {
425
	list($ip, $mask) = explode('/', $subnet);
426
	$mask = 0xffffffff << (32 - $mask);
427
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
428
}
429

    
430
/* verify (and remove) the digital signature on a file - returns 0 if OK */
431
function verify_digital_signature($fname) {
432

    
433
	global $g;
434

    
435
	return mwexec("/usr/local/bin/verifysig " .
436
		escapeshellarg("{$g['etc_path']}/pubkey.pem") . " " .
437
		escapeshellarg($fname));
438
}
439

    
440
/* obtain MAC address given an IP address by looking at the ARP table */
441
function arp_get_mac_by_ip($ip) {
442
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
443
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
444

    
445
	if ($arpoutput[0]) {
446
		$arpi = explode(" ", $arpoutput[0]);
447
		$macaddr = $arpi[3];
448
		if (is_macaddr($macaddr))
449
			return $macaddr;
450
		else
451
			return false;
452
	}
453

    
454
	return false;
455
}
456

    
457
/* return a fieldname that is safe for xml usage */
458
function xml_safe_fieldname($fieldname) {
459
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
460
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
461
			 ':', ',', '.', '\'', '\\'
462
		);
463
	return strtolower(str_replace($replace, "", $fieldname));
464
}
465

    
466
?>
(18-18/24)