Project

General

Profile

Download (14.5 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}", true);
42
	}
43
}
44

    
45
/* kill a process by name */
46
function killbyname($procname) {
47
	mwexec("/usr/bin/killall " . escapeshellarg($procname), true);
48
}
49

    
50
/* return the subnet address given a host address and a subnet bit count */
51
function gen_subnet($ipaddr, $bits) {
52
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
53
		return "";
54

    
55
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
56
}
57

    
58
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
59
function gen_subnet_max($ipaddr, $bits) {
60
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
61
		return "";
62

    
63
	return long2ip(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
64
}
65

    
66
/* returns a subnet mask (long given a bit count) */
67
function gen_subnet_mask_long($bits) {
68
	$sm = 0;
69
	for ($i = 0; $i < $bits; $i++) {
70
		$sm >>= 1;
71
		$sm |= 0x80000000;
72
	}
73
	return $sm;
74
}
75

    
76
/* same as above but returns a string */
77
function gen_subnet_mask($bits) {
78
	return long2ip(gen_subnet_mask_long($bits));
79
}
80

    
81
function is_numericint($arg) {
82
	return (preg_match("/[^0-9]/", $arg) ? false : true);
83
}
84

    
85
/* returns true if $ipaddr is a valid dotted IPv4 address */
86
function is_ipaddr($ipaddr) {
87
	if (!is_string($ipaddr))
88
		return false;
89

    
90
	$ip_long = ip2long($ipaddr);
91
	$ip_reverse = long2ip($ip_long);
92

    
93
	if ($ipaddr == $ip_reverse)
94
		return true;
95
	else
96
		return false;
97
}
98

    
99
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
100
function is_ipaddroralias($ipaddr) {
101

    
102
	global $aliastable, $config;
103

    
104
	if(is_array($config['aliases']['alias'])) {
105
		foreach($config['aliases']['alias'] as $alias) {
106
			if($alias['name'] == $ipaddr)
107
				return true;
108
		}
109
	}
110

    
111
	if (isset($aliastable[$ipaddr]) && is_ipaddr($aliastable[$ipaddr]))
112
		return true;
113
	else
114
		return is_ipaddr($ipaddr);
115

    
116
}
117

    
118
/* returns true if $ipaddr is a valid dotted IPv4 address or any alias */
119
function is_ipaddroranyalias($ipaddr) {
120

    
121
	global $aliastable;
122

    
123
	if (isset($aliastable[$ipaddr]))
124
		return true;
125
	else
126
		return is_ipaddr($ipaddr);
127
}
128

    
129
/* returns true if $subnet is a valid subnet in CIDR format */
130
function is_subnet($subnet) {
131
	if (!is_string($subnet))
132
		return false;
133

    
134
	list($hp,$np) = explode('/', $subnet);
135

    
136
	if (!is_ipaddr($hp))
137
		return false;
138

    
139
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
140
		return false;
141

    
142
	return true;
143
}
144

    
145
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
146
function is_subnetoralias($subnet) {
147

    
148
	global $aliastable;
149

    
150
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
151
		return true;
152
	else
153
		return is_subnet($subnet);
154
}
155

    
156
/* returns true if $hostname is a valid hostname */
157
function is_hostname($hostname) {
158
	if (!is_string($hostname))
159
		return false;
160

    
161
	if (preg_match("/^([_a-z0-9\-]+\.?)+$/i", $hostname))
162
		return true;
163
	else
164
		return false;
165
}
166

    
167
/* returns true if $domain is a valid domain name */
168
function is_domain($domain) {
169
	if (!is_string($domain))
170
		return false;
171

    
172
	if (preg_match("/^([a-z0-9\-]+\.?)+$/i", $domain))
173
		return true;
174
	else
175
		return false;
176
}
177

    
178
/* returns true if $uname is a valid DynDNS username */
179
function is_dyndns_username($uname) {
180
	if (!is_string($uname))
181
		return false;
182

    
183
	if (preg_match("/[^a-z0-9\-.@_:]/i", $uname))
184
		return false;
185
	else
186
		return true;
187
}
188

    
189
/* returns true if $macaddr is a valid MAC address */
190
function is_macaddr($macaddr) {
191
	if (!is_string($macaddr))
192
		return false;
193

    
194
	$maca = explode(":", $macaddr);
195
	if (count($maca) != 6)
196
		return false;
197

    
198
	foreach ($maca as $macel) {
199
		if (($macel === "") || (strlen($macel) > 2))
200
			return false;
201
		if (preg_match("/[^0-9a-f]/i", $macel))
202
			return false;
203
	}
204

    
205
	return true;
206
}
207

    
208
/* returns true if $name is a valid name for an alias */
209
/* returns NULL if a reserved word is used */
210
function is_validaliasname($name) {
211
	/* Array of reserved words */
212
	$reserved = array("port", "pass");
213
	if (in_array($name, $reserved, true))
214
		return; /* return NULL */
215

    
216
	if (!preg_match("/[^a-zA-Z0-9_]/", $name))
217
		return true;
218
	else
219
		return false;
220
}
221

    
222
/* returns true if $port is a valid TCP/UDP port */
223
function is_port($port) {
224
	if (!is_numericint($port))
225
		return false;
226

    
227
	if (($port < 1) || ($port > 65535))
228
		return false;
229
	else
230
		return true;
231
}
232

    
233
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
234
function is_portrange($portrange) {
235
        $ports = explode(":", $portrange);
236

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

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

    
347
function lock($lock) {
348
	global $g, $cfglckkeyconsumers;
349
	if (!$lock)
350
		die("WARNING: You must give a name as parameter to lock() function.");
351
	if (!file_exists("{$g['tmp_path']}/{$lock}.lock"))
352
		@touch("{$g['tmp_path']}/{$lock}.lock");
353
	$cfglckkeyconsumers++;
354
	if ($fp = fopen("{$g['tmp_path']}/{$lock}.lock", "w+")) {
355
		if (flock($fp, LOCK_EX))
356
			return $fp;
357
		else
358
			fclose($fp);
359
	}
360
}
361

    
362
/* unlock configuration file */
363
function unlock($cfglckkey = 0) {
364
	global $g, $cfglckkeyconsumers;
365
	flock($cfglckkey, LOCK_UN);
366
	return;
367
}
368

    
369
/* wrapper for exec() */
370
function mwexec($command, $mute = true) {
371

    
372
	global $g;
373
	$oarr = array();
374
	$retval = 0;
375
	if ($g['debug']) {
376
		if (!$_SERVER['REMOTE_ADDR'])
377
			echo "mwexec(): $command\n";
378
		exec("$command 2>&1", $oarr, $retval);
379
	} else {
380
		exec("$command 2>&1", $oarr, $retval);
381
	}
382
        if(isset($config['system']['developerspew']))
383
                $mute = false;
384
	if(($retval <> 0) && ($mute === false)) {
385
		$output = implode(" ", $oarr);
386
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
387
	}
388
	return $retval;
389
}
390

    
391
/* wrapper for exec() in background */
392
function mwexec_bg($command) {
393

    
394
	global $g;
395

    
396
	if ($g['debug']) {
397
		if (!$_SERVER['REMOTE_ADDR'])
398
			echo "mwexec(): $command\n";
399
	}
400

    
401
	exec("nohup $command > /dev/null 2>&1 &");
402
}
403

    
404
/* unlink a file, if it exists */
405
function unlink_if_exists($fn) {
406
	$to_do = glob($fn);
407
	if(is_array($to_do)) {
408
		foreach($to_do as $filename)
409
			@unlink($filename);
410
	} else {
411
		@unlink($fn);
412
	}
413
}
414
/* make a global alias table (for faster lookups) */
415
function alias_make_table($config) {
416

    
417
	global $aliastable;
418

    
419
	$aliastable = array();
420

    
421
	if (is_array($config['aliases']['alias'])) {
422
		foreach ($config['aliases']['alias'] as $alias) {
423
			if ($alias['name'])
424
				$aliastable[$alias['name']] = $alias['address'];
425
		}
426
	}
427
}
428
/* check if an alias exists */
429
function is_alias($name) {
430

    
431
	global $aliastable;
432

    
433
	return isset($aliastable[$name]);
434
}
435

    
436
function alias_expand_value($name) {
437

    
438
	global $aliastable, $config;
439
	if($config['aliases']['alias'])
440
		foreach($config['aliases']['alias'] as $alias) {
441
			if($alias['name'] == $name)
442
				return $alias['address'];
443
		}
444

    
445
}
446

    
447
/* expand a host or network alias, if necessary */
448
function alias_expand($name) {
449

    
450
	global $aliastable;
451

    
452
	if (isset($aliastable[$name]))
453
		return "\${$name}";
454
	else if (is_ipaddr($name) || is_subnet($name))
455
		return "{$name}";
456
	else
457
		return null;
458
}
459

    
460
/* expand a host alias, if necessary */
461
function alias_expand_host($name) {
462
	global $aliastable;
463

    
464
	if (isset($aliastable[$name])) {
465
		$ip_arr = explode(" ", $aliastable[$name]);
466
		foreach($ip_arr as $ip) {
467
			if (!is_ipaddr($ip))
468
				return null;
469
		}
470
		return $aliastable[$name];
471
	} else if (is_ipaddr($name))
472
		return $name;
473
	else
474
		return null;
475
}
476

    
477
/* expand a network alias, if necessary */
478
function alias_expand_net($name) {
479

    
480
	global $aliastable;
481

    
482
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
483
		return $aliastable[$name];
484
	else if (is_subnet($name))
485
		return $name;
486
	else
487
		return null;
488
}
489

    
490
/* find out whether two subnets overlap */
491
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
492

    
493
	if (!is_numeric($bits1))
494
		$bits1 = 32;
495
	if (!is_numeric($bits2))
496
		$bits2 = 32;
497

    
498
	if ($bits1 < $bits2)
499
		$relbits = $bits1;
500
	else
501
		$relbits = $bits2;
502

    
503
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
504
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
505

    
506
	if ($sn1 == $sn2)
507
		return true;
508
	else
509
		return false;
510
}
511

    
512
/* compare two IP addresses */
513
function ipcmp($a, $b) {
514
	if (ip2long($a) < ip2long($b))
515
		return -1;
516
	else if (ip2long($a) > ip2long($b))
517
		return 1;
518
	else
519
		return 0;
520
}
521

    
522
/* return true if $addr is in $subnet, false if not */
523
function ip_in_subnet($addr,$subnet) {
524
	list($ip, $mask) = explode('/', $subnet);
525
	$mask = 0xffffffff << (32 - $mask);
526
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
527
}
528

    
529
/* verify (and remove) the digital signature on a file - returns 0 if OK */
530
function verify_digital_signature($fname) {
531

    
532
	global $g;
533

    
534
	if(!file_exists("/usr/local/sbin/gzsig"))
535
		return 1;
536

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

    
539
}
540

    
541
/* obtain MAC address given an IP address by looking at the ARP table */
542
function arp_get_mac_by_ip($ip) {
543
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
544
	$arpoutput = "";
545
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
546

    
547
	if ($arpoutput[0]) {
548
		$arpi = explode(" ", $arpoutput[0]);
549
		$macaddr = $arpi[3];
550
		if (is_macaddr($macaddr))
551
			return $macaddr;
552
		else
553
			return false;
554
	}
555

    
556
	return false;
557
}
558

    
559
/* return a fieldname that is safe for xml usage */
560
function xml_safe_fieldname($fieldname) {
561
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
562
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
563
			 ':', ',', '.', '\'', '\\'
564
		);
565
	return strtolower(str_replace($replace, "", $fieldname));
566
}
567

    
568
function mac_format($clientmac) {
569
    $mac =explode(":", $clientmac);
570

    
571
    global $config;
572

    
573
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
574

    
575
    switch($mac_format) {
576

    
577
        case 'singledash':
578
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
579

    
580
        case 'ietf':
581
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
582

    
583
        case 'cisco':
584
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
585

    
586
        case 'unformatted':
587
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
588

    
589
        default:
590
        return $clientmac;
591
    }
592
}
593

    
594
function resolve_retry($hostname, $retries = 5) {
595

    
596
	if (is_ipaddr($hostname))
597
		return $hostname;
598

    
599
	for ($i = 0; $i < $retries; $i++) {
600
		$ip = gethostbyname($hostname);
601
		
602
		if ($ip && $ip != $hostname) {
603
			/* success */
604
			return $ip;
605
		}
606
		
607
		sleep(1);
608
	}
609
	
610
	return false;
611
}
612

    
613

    
614
?>
(21-21/27)