Project

General

Profile

Download (13.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
		$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
/* returns true if $val is a valid shaper bandwidth value */
236
function is_valid_shaperbw($val) {
237
	return (preg_match("/^[0-9]+(Kb|Mb|Gb|%)$/", $val));
238
}
239

    
240
/*
241
 *   get_interface_list() - Return a list of all physical interfaces
242
 *   along with MAC and status.
243
 *
244
 *   $mode = "active" - use ifconfig -lu
245
 *           "media"  - use ifconfig to check physical connection
246
 *			status (much slower)
247
 */
248
/*
249
 *   get_interface_list() - Return a list of all physical interfaces
250
 *   along with MAC and status.
251
 *
252
 *   $mode = "active" - use ifconfig -lu
253
 *           "media"  - use ifconfig to check physical connection
254
 *			status (much slower)
255
 */
256
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
257
        global $config;
258
	$upints = array();
259
        /* get a list of virtual interface types */
260
        if(!$vfaces) {
261
		$vfaces = array(
262
				'bridge',
263
				'ppp',
264
				'sl',
265
				'gif',
266
				'faith',
267
				'lo',
268
				'ng',
269
				'vlan',
270
				'pflog',
271
				'pfsync',
272
				'enc',
273
				'tun',
274
				'carp'
275
			);
276
	}
277
	switch($mode) {
278
	case "active":
279
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
280
        	break;
281
	case "media":
282
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
283
                $ifconfig = "";
284
                exec("/sbin/ifconfig -a", $ifconfig);
285
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
286
                $ifstatus = preg_grep('/status:/', $ifconfig);
287
		foreach($ifstatus as $status) {
288
			$int = array_shift($intlist);
289
                	if(stristr($status, "active")) $upints[] = $int;
290
		}
291
		break;
292
	}
293
        /* build interface list with netstat */
294
        $linkinfo = "";
295
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
296
        array_shift($linkinfo);
297
	/* build ip address list with netstat */
298
	$ipinfo = "";
299
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
300
	array_shift($ipinfo);
301
	foreach($linkinfo as $link) {
302
		$friendly = "";
303
                $alink = explode(" ", $link);
304
                $ifname = rtrim(trim($alink[0]), '*');
305
                /* trim out all numbers before checking for vfaces */
306
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces)) {
307
			$toput = array(
308
					"mac" => trim($alink[1]),
309
					"up" => in_array($ifname, $upints)
310
				);
311
			foreach($ipinfo as $ip) {
312
				$aip = explode(" ", $ip);
313
				if($aip[0] == $ifname) {
314
					$toput['ipaddr'] = $aip[1];
315
				}
316
			}
317
			foreach($config['interfaces'] as $name => $int) {
318
				if($int['if'] == $ifname) $friendly = $name;
319
			}
320
			switch($keyby) {
321
			case "physical":
322
				if($friendly != "") {
323
					$toput['friendly'] = $friendly;
324
				}
325
				$iflist[$ifname] = $toput;
326
				break;
327
			case "friendly":
328
				if($friendly != "") {
329
					$toput['if'] = $ifname;
330
					$iflist[$friendly] = $toput;
331
				}
332
				break;
333
			}
334
                }
335
        }
336
        return $iflist;
337
}
338

    
339
/* wrapper for exec() */
340
function mwexec($command) {
341

    
342
	global $g;
343
	$oarr = "";
344
	$retval = "";
345
	if ($g['debug']) {
346
		if (!$_SERVER['REMOTE_ADDR'])
347
			echo "mwexec(): $command\n";
348
		exec("$command > /dev/null 2>&1", $oarr, $retval);
349
	} else {
350
		exec("$command > /dev/null 2>&1", $oarr, $retval);
351
	}
352

    
353
	return $retval;
354
}
355

    
356
/* wrapper for exec() in background */
357
function mwexec_bg($command) {
358

    
359
	global $g;
360

    
361
	if ($g['debug']) {
362
		if (!$_SERVER['REMOTE_ADDR'])
363
			echo "mwexec(): $command\n";
364
	}
365

    
366
	exec("nohup $command > /dev/null 2>&1 &");
367
}
368

    
369
/* unlink a file, if it exists */
370
function unlink_if_exists($fn) {
371
	$to_do = glob($fn);
372
	if(is_array($to_do)) {
373
		foreach($to_do as $filename)
374
			@unlink($filename);
375
	} else {
376
		@unlink($fn);
377
	}
378
}
379

    
380
/* make a global alias table (for faster lookups) */
381
function alias_make_table($config) {
382

    
383
	global $aliastable;
384

    
385
	$aliastable = array();
386

    
387
	if (is_array($config['aliases']['alias'])) {
388
		foreach ($config['aliases']['alias'] as $alias) {
389
			if ($alias['name'])
390
				$aliastable[$alias['name']] = $alias['address'];
391
		}
392
	}
393
}
394

    
395
/* check if an alias exists */
396
function is_alias($name) {
397

    
398
	global $aliastable;
399

    
400
	return isset($aliastable[$name]);
401
}
402

    
403
function alias_expand_value($name) {
404

    
405
	global $aliastable, $config;
406

    
407
	foreach($config['aliases']['alias'] as $alias) {
408
		if($alias['name'] == $name)
409
			return $alias['address'];
410
	}
411

    
412
}
413

    
414
/* expand a host or network alias, if necessary */
415
function alias_expand($name) {
416

    
417
	global $aliastable;
418

    
419
	if (isset($aliastable[$name]))
420
		return "\${$name}";
421
	else if (is_ipaddr($name) || is_subnet($name))
422
		return "{$name}";
423
	else
424
		return null;
425
}
426

    
427
/* expand a host alias, if necessary */
428
function alias_expand_host($name) {
429
	global $aliastable;
430

    
431
	if (isset($aliastable[$name])) {
432
		$ip_arr = explode(" ", $aliastable[$name]);
433
		foreach($ip_arr as $ip) {
434
			if (!is_ipaddr($ip))
435
				return null;
436
		}
437
		return $aliastable[$name];
438
	} else if (is_ipaddr($name))
439
		return $name;
440
	else
441
		return null;
442
}
443

    
444
/* expand a network alias, if necessary */
445
function alias_expand_net($name) {
446

    
447
	global $aliastable;
448

    
449
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
450
		return $aliastable[$name];
451
	else if (is_subnet($name))
452
		return $name;
453
	else
454
		return null;
455
}
456

    
457
/* find out whether two subnets overlap */
458
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
459

    
460
	if (!is_numeric($bits1))
461
		$bits1 = 32;
462
	if (!is_numeric($bits2))
463
		$bits2 = 32;
464

    
465
	if ($bits1 < $bits2)
466
		$relbits = $bits1;
467
	else
468
		$relbits = $bits2;
469

    
470
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
471
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
472

    
473
	if ($sn1 == $sn2)
474
		return true;
475
	else
476
		return false;
477
}
478

    
479
/* compare two IP addresses */
480
function ipcmp($a, $b) {
481
	if (ip2long($a) < ip2long($b))
482
		return -1;
483
	else if (ip2long($a) > ip2long($b))
484
		return 1;
485
	else
486
		return 0;
487
}
488

    
489
/* return true if $addr is in $subnet, false if not */
490
function ip_in_subnet($addr,$subnet) {
491
	list($ip, $mask) = explode('/', $subnet);
492
	$mask = 0xffffffff << (32 - $mask);
493
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
494
}
495

    
496
/* verify (and remove) the digital signature on a file - returns 0 if OK */
497
function verify_digital_signature($fname) {
498

    
499
	global $g;
500

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

    
503
}
504

    
505
/* obtain MAC address given an IP address by looking at the ARP table */
506
function arp_get_mac_by_ip($ip) {
507
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
508
	$arpoutput = "";
509
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
510

    
511
	if ($arpoutput[0]) {
512
		$arpi = explode(" ", $arpoutput[0]);
513
		$macaddr = $arpi[3];
514
		if (is_macaddr($macaddr))
515
			return $macaddr;
516
		else
517
			return false;
518
	}
519

    
520
	return false;
521
}
522

    
523
/* return a fieldname that is safe for xml usage */
524
function xml_safe_fieldname($fieldname) {
525
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
526
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
527
			 ':', ',', '.', '\'', '\\'
528
		);
529
	return strtolower(str_replace($replace, "", $fieldname));
530
}
531

    
532
function mac_format($clientmac) {
533
    $mac =explode(":", $clientmac);
534

    
535
    global $config;
536

    
537
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
538

    
539
    switch($mac_format) {
540

    
541
        case 'singledash':
542
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
543

    
544
        case 'ietf':
545
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
546

    
547
        case 'cisco':
548
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
549

    
550
        case 'unformatted':
551
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
552

    
553
        default:
554
        return $clientmac;
555
    }
556
}
557

    
558
?>
(21-21/27)