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
/* make a global alias table (for faster lookups) */
380
function alias_make_table($config) {
381

    
382
	global $aliastable;
383

    
384
	$aliastable = array();
385

    
386
	if (is_array($config['aliases']['alias'])) {
387
		foreach ($config['aliases']['alias'] as $alias) {
388
			if ($alias['name'])
389
				$aliastable[$alias['name']] = $alias['address'];
390
		}
391
	}
392
}
393
/* check if an alias exists */
394
function is_alias($name) {
395

    
396
	global $aliastable;
397

    
398
	return isset($aliastable[$name]);
399
}
400

    
401
function alias_expand_value($name) {
402

    
403
	global $aliastable, $config;
404

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

    
410
}
411

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

    
415
	global $aliastable;
416

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

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

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

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

    
445
	global $aliastable;
446

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

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

    
458
	if (!is_numeric($bits1))
459
		$bits1 = 32;
460
	if (!is_numeric($bits2))
461
		$bits2 = 32;
462

    
463
	if ($bits1 < $bits2)
464
		$relbits = $bits1;
465
	else
466
		$relbits = $bits2;
467

    
468
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
469
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
470

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

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

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

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

    
497
	global $g;
498

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

    
501
}
502

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

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

    
518
	return false;
519
}
520

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

    
530
function mac_format($clientmac) {
531
    $mac =explode(":", $clientmac);
532

    
533
    global $config;
534

    
535
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
536

    
537
    switch($mac_format) {
538

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

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

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

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

    
551
        default:
552
        return $clientmac;
553
    }
554
}
555

    
556
?>
(21-21/27)