Project

General

Profile

Download (13.4 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 $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
236
function is_portrange($portrange) {
237
        $ports = explode(":", $portrange);
238

    
239
        if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
240
                return true;
241
        else
242
                return false;
243
}
244

    
245
/* returns true if $val is a valid shaper bandwidth value */
246
function is_valid_shaperbw($val) {
247
	return (preg_match("/^[0-9]+(Kb|Mb|Gb|%)$/", $val));
248
}
249

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

    
349
/* wrapper for exec() */
350
function mwexec($command) {
351

    
352
	global $g;
353
	$oarr = "";
354
	$retval = "";
355
	if ($g['debug']) {
356
		if (!$_SERVER['REMOTE_ADDR'])
357
			echo "mwexec(): $command\n";
358
		exec("$command > /dev/null 2>&1", $oarr, $retval);
359
	} else {
360
		exec("$command > /dev/null 2>&1", $oarr, $retval);
361
	}
362

    
363
	return $retval;
364
}
365

    
366
/* wrapper for exec() in background */
367
function mwexec_bg($command) {
368

    
369
	global $g;
370

    
371
	if ($g['debug']) {
372
		if (!$_SERVER['REMOTE_ADDR'])
373
			echo "mwexec(): $command\n";
374
	}
375

    
376
	exec("nohup $command > /dev/null 2>&1 &");
377
}
378

    
379
/* unlink a file, if it exists */
380
function unlink_if_exists($fn) {
381
	$to_do = glob($fn);
382
	if(is_array($to_do)) {
383
		foreach($to_do as $filename)
384
			@unlink($filename);
385
	} else {
386
		@unlink($fn);
387
	}
388
}
389
/* make a global alias table (for faster lookups) */
390
function alias_make_table($config) {
391

    
392
	global $aliastable;
393

    
394
	$aliastable = array();
395

    
396
	if (is_array($config['aliases']['alias'])) {
397
		foreach ($config['aliases']['alias'] as $alias) {
398
			if ($alias['name'])
399
				$aliastable[$alias['name']] = $alias['address'];
400
		}
401
	}
402
}
403
/* check if an alias exists */
404
function is_alias($name) {
405

    
406
	global $aliastable;
407

    
408
	return isset($aliastable[$name]);
409
}
410

    
411
function alias_expand_value($name) {
412

    
413
	global $aliastable, $config;
414
	if($config['aliases']['alias'])
415
		foreach($config['aliases']['alias'] as $alias) {
416
			if($alias['name'] == $name)
417
				return $alias['address'];
418
		}
419

    
420
}
421

    
422
/* expand a host or network alias, if necessary */
423
function alias_expand($name) {
424

    
425
	global $aliastable;
426

    
427
	if (isset($aliastable[$name]))
428
		return "\${$name}";
429
	else if (is_ipaddr($name) || is_subnet($name))
430
		return "{$name}";
431
	else
432
		return null;
433
}
434

    
435
/* expand a host alias, if necessary */
436
function alias_expand_host($name) {
437
	global $aliastable;
438

    
439
	if (isset($aliastable[$name])) {
440
		$ip_arr = explode(" ", $aliastable[$name]);
441
		foreach($ip_arr as $ip) {
442
			if (!is_ipaddr($ip))
443
				return null;
444
		}
445
		return $aliastable[$name];
446
	} else if (is_ipaddr($name))
447
		return $name;
448
	else
449
		return null;
450
}
451

    
452
/* expand a network alias, if necessary */
453
function alias_expand_net($name) {
454

    
455
	global $aliastable;
456

    
457
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
458
		return $aliastable[$name];
459
	else if (is_subnet($name))
460
		return $name;
461
	else
462
		return null;
463
}
464

    
465
/* find out whether two subnets overlap */
466
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
467

    
468
	if (!is_numeric($bits1))
469
		$bits1 = 32;
470
	if (!is_numeric($bits2))
471
		$bits2 = 32;
472

    
473
	if ($bits1 < $bits2)
474
		$relbits = $bits1;
475
	else
476
		$relbits = $bits2;
477

    
478
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
479
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
480

    
481
	if ($sn1 == $sn2)
482
		return true;
483
	else
484
		return false;
485
}
486

    
487
/* compare two IP addresses */
488
function ipcmp($a, $b) {
489
	if (ip2long($a) < ip2long($b))
490
		return -1;
491
	else if (ip2long($a) > ip2long($b))
492
		return 1;
493
	else
494
		return 0;
495
}
496

    
497
/* return true if $addr is in $subnet, false if not */
498
function ip_in_subnet($addr,$subnet) {
499
	list($ip, $mask) = explode('/', $subnet);
500
	$mask = 0xffffffff << (32 - $mask);
501
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
502
}
503

    
504
/* verify (and remove) the digital signature on a file - returns 0 if OK */
505
function verify_digital_signature($fname) {
506

    
507
	global $g;
508

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

    
511
}
512

    
513
/* obtain MAC address given an IP address by looking at the ARP table */
514
function arp_get_mac_by_ip($ip) {
515
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
516
	$arpoutput = "";
517
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
518

    
519
	if ($arpoutput[0]) {
520
		$arpi = explode(" ", $arpoutput[0]);
521
		$macaddr = $arpi[3];
522
		if (is_macaddr($macaddr))
523
			return $macaddr;
524
		else
525
			return false;
526
	}
527

    
528
	return false;
529
}
530

    
531
/* return a fieldname that is safe for xml usage */
532
function xml_safe_fieldname($fieldname) {
533
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
534
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
535
			 ':', ',', '.', '\'', '\\'
536
		);
537
	return strtolower(str_replace($replace, "", $fieldname));
538
}
539

    
540
function mac_format($clientmac) {
541
    $mac =explode(":", $clientmac);
542

    
543
    global $config;
544

    
545
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
546

    
547
    switch($mac_format) {
548

    
549
        case 'singledash':
550
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
551

    
552
        case 'ietf':
553
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
554

    
555
        case 'cisco':
556
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
557

    
558
        case 'unformatted':
559
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
560

    
561
        default:
562
        return $clientmac;
563
    }
564
}
565

    
566
?>
(21-21/27)