Project

General

Profile

Download (15.7 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
function isvalidpid($pid) {
38
	$running = `ps -p $pid | wc -l`;
39
	if(intval($running) > 1)
40
		return true;
41
	else 
42
		return false;
43
}
44

    
45
function isvalidproc($proc) {
46
	$running = `ps awux | grep $proc | grep -v grep | wc -l`;
47
	if(intval($running) > 1)
48
		return true;
49
	else 
50
		return false;
51
}
52

    
53
/* sigkill a process by pid file */
54
/* return 1 for success and 0 for a failure */
55
function sigkillbypid($pidfile, $sig) {
56
	if (is_file($pidfile)) {
57
		$pid = trim(file_get_contents($pidfile));
58
		if(isvalidpid($pid))
59
			return mwexec("/bin/kill -s $sig {$pid}");
60
	}
61

    
62
	return 0;
63
}
64

    
65
/* kill a process by name */
66
function sigkillbyname($procname, $sig) {
67
	if(isvalidproc($procname))
68
		return mwexec("/usr/bin/killall -{$sig} " . escapeshellarg($procname));
69
}
70

    
71
/* kill a process by name */
72
function killbyname($procname) {
73
	if(isvalidproc($procname))
74
		mwexec("/usr/bin/killall " . escapeshellarg($procname));
75
}
76

    
77
/* return the subnet address given a host address and a subnet bit count */
78
function gen_subnet($ipaddr, $bits) {
79
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
80
		return "";
81

    
82
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
83
}
84

    
85
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
86
function gen_subnet_max($ipaddr, $bits) {
87
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
88
		return "";
89

    
90
	return long2ip(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
91
}
92

    
93
/* returns a subnet mask (long given a bit count) */
94
function gen_subnet_mask_long($bits) {
95
	$sm = 0;
96
	for ($i = 0; $i < $bits; $i++) {
97
		$sm >>= 1;
98
		$sm |= 0x80000000;
99
	}
100
	return $sm;
101
}
102

    
103
/* same as above but returns a string */
104
function gen_subnet_mask($bits) {
105
	return long2ip(gen_subnet_mask_long($bits));
106
}
107

    
108
function is_numericint($arg) {
109
	return (preg_match("/[^0-9]/", $arg) ? false : true);
110
}
111

    
112
/* returns true if $ipaddr is a valid dotted IPv4 address */
113
function is_ipaddr($ipaddr) {
114
	if (!is_string($ipaddr))
115
		return false;
116

    
117
	$ip_long = ip2long($ipaddr);
118
	$ip_reverse = long2ip($ip_long);
119

    
120
	if ($ipaddr == $ip_reverse)
121
		return true;
122
	else
123
		return false;
124
}
125

    
126
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
127
function is_ipaddroralias($ipaddr) {
128

    
129
	global $aliastable, $config;
130

    
131
	if(is_array($config['aliases']['alias'])) {
132
		foreach($config['aliases']['alias'] as $alias) {
133
			if($alias['name'] == $ipaddr)
134
				return true;
135
		}
136
	}
137

    
138
	if (isset($aliastable[$ipaddr]) && is_ipaddr($aliastable[$ipaddr]))
139
		return true;
140
	else
141
		return is_ipaddr($ipaddr);
142

    
143
}
144

    
145
/* returns true if $ipaddr is a valid dotted IPv4 address or any alias */
146
function is_ipaddroranyalias($ipaddr) {
147

    
148
	global $aliastable;
149

    
150
	if (isset($aliastable[$ipaddr]))
151
		return true;
152
	else
153
		return is_ipaddr($ipaddr);
154
}
155

    
156
/* returns true if $subnet is a valid subnet in CIDR format */
157
function is_subnet($subnet) {
158
	if (!is_string($subnet))
159
		return false;
160

    
161
	list($hp,$np) = explode('/', $subnet);
162

    
163
	if (!is_ipaddr($hp))
164
		return false;
165

    
166
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
167
		return false;
168

    
169
	return true;
170
}
171

    
172
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
173
function is_subnetoralias($subnet) {
174

    
175
	global $aliastable;
176

    
177
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
178
		return true;
179
	else
180
		return is_subnet($subnet);
181
}
182

    
183
/* returns true if $hostname is a valid hostname */
184
function is_hostname($hostname) {
185
	if (!is_string($hostname))
186
		return false;
187

    
188
	if (preg_match("/^([_a-z0-9\-]+\.?)+$/i", $hostname))
189
		return true;
190
	else
191
		return false;
192
}
193

    
194
/* returns true if $domain is a valid domain name */
195
function is_domain($domain) {
196
	if (!is_string($domain))
197
		return false;
198

    
199
	if (preg_match("/^([a-z0-9\-]+\.?)+$/i", $domain))
200
		return true;
201
	else
202
		return false;
203
}
204

    
205
/* returns true if $uname is a valid DynDNS username */
206
function is_dyndns_username($uname) {
207
	if (!is_string($uname))
208
		return false;
209

    
210
	if (preg_match("/[^a-z0-9\-.@_]/i", $uname))
211
		return false;
212
	else
213
		return true;
214
}
215

    
216
/* returns true if $macaddr is a valid MAC address */
217
function is_macaddr($macaddr) {
218
	if (!is_string($macaddr))
219
		return false;
220

    
221
	$maca = explode(":", $macaddr);
222
	if (count($maca) != 6)
223
		return false;
224

    
225
	foreach ($maca as $macel) {
226
		if (($macel === "") || (strlen($macel) > 2))
227
			return false;
228
		if (preg_match("/[^0-9a-f]/i", $macel))
229
			return false;
230
	}
231

    
232
	return true;
233
}
234

    
235
/* returns true if $name is a valid name for an alias */
236
/* returns NULL if a reserved word is used */
237
function is_validaliasname($name) {
238
	/* Array of reserved words */
239
	$reserved = array("port", "pass");
240
	if (in_array($name, $reserved, true))
241
		return; /* return NULL */
242

    
243
	if (!preg_match("/[^a-zA-Z0-9_]/", $name))
244
		return true;
245
	else
246
		return false;
247
}
248

    
249
/* returns true if $port is a valid TCP/UDP port */
250
function is_port($port) {
251
	if (!is_numericint($port))
252
		return false;
253

    
254
	if (($port < 1) || ($port > 65535))
255
		return false;
256
	else
257
		return true;
258
}
259

    
260
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
261
function is_portrange($portrange) {
262
        $ports = explode(":", $portrange);
263

    
264
        if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
265
                return true;
266
        else
267
                return false;
268
}
269

    
270
/* returns true if $val is a valid shaper bandwidth value */
271
function is_valid_shaperbw($val) {
272
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
273
}
274

    
275
/* return the configured interfaces list. */
276
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
277
	global $config;
278

    
279
	$iflist = array();
280

    
281
	/* if list */
282
        foreach($config['interfaces'] as $if => $ifdetail) {
283
		if ($only_opt == true && ($if == "wan" || $if == "lan"))
284
			continue;
285
		if ($if == "wan" || $if == "lan" || isset($ifdetail['enable']) || 
286
			$withdisabled == true) 
287
			$iflist[$if] = $if;
288
	}
289

    
290
	return $iflist;
291
			
292
}
293

    
294
/* return the configured interfaces list with their description. */
295
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
296
        global $config;
297

    
298
        $iflist = array();
299

    
300
        /* if list */
301
        foreach($config['interfaces'] as $if => $ifdetail) {
302
               	if ($only_opt == true && ($if == "wan" || $if == "lan"))
303
                        continue;
304
                if ($if == "wan" || $if == "lan" || isset($ifdetail['enable']) ||
305
			$withdisabled == true) {
306
			if($ifdetail['descr'] == "")
307
				$iflist[$if] = strtoupper($if);
308
                        else
309
				$iflist[$if] = $ifdetail['descr'];
310
		}
311
	}
312

    
313
        return $iflist;
314

    
315
}
316

    
317

    
318
/*
319
 *   get_interface_list() - Return a list of all physical interfaces
320
 *   along with MAC and status.
321
 *
322
 *   $mode = "active" - use ifconfig -lu
323
 *           "media"  - use ifconfig to check physical connection
324
 *			status (much slower)
325
 */
326
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
327
        global $config;
328
	$upints = array();
329
        /* get a list of virtual interface types */
330
        if(!$vfaces) {
331
		$vfaces = array (
332
				'bridge',
333
				'ppp',
334
				'sl',
335
				'gif',
336
				'faith',
337
				'lo',
338
				'ng',
339
				'vlan',
340
				'pflog',
341
				'pfsync',
342
				'enc',
343
				'tun',
344
				'carp'
345
		);
346
	}
347
	switch($mode) {
348
	case "active":
349
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
350
        	break;
351
	case "media":
352
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
353
                $ifconfig = "";
354
                exec("/sbin/ifconfig -a", $ifconfig);
355
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
356
                $ifstatus = preg_grep('/status:/', $ifconfig);
357
		foreach($ifstatus as $status) {
358
			$int = array_shift($intlist);
359
                	if(stristr($status, "active")) $upints[] = $int;
360
		}
361
		break;
362
	}
363
        /* build interface list with netstat */
364
        $linkinfo = "";
365
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
366
        array_shift($linkinfo);
367
	/* build ip address list with netstat */
368
	$ipinfo = "";
369
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
370
	array_shift($ipinfo);
371
	foreach($linkinfo as $link) {
372
		$friendly = "";
373
                $alink = explode(" ", $link);
374
                $ifname = rtrim(trim($alink[0]), '*');
375
                /* trim out all numbers before checking for vfaces */
376
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces)) {
377
			$toput = array(
378
					"mac" => trim($alink[1]),
379
					"up" => in_array($ifname, $upints)
380
				);
381
			foreach($ipinfo as $ip) {
382
				$aip = explode(" ", $ip);
383
				if($aip[0] == $ifname) {
384
					$toput['ipaddr'] = $aip[1];
385
				}
386
			}
387
			foreach($config['interfaces'] as $name => $int) {
388
				if($int['if'] == $ifname) $friendly = $name;
389
			}
390
			switch($keyby) {
391
			case "physical":
392
				if($friendly != "") {
393
					$toput['friendly'] = $friendly;
394
				}
395
				$iflist[$ifname] = $toput;
396
				break;
397
			case "friendly":
398
				if($friendly != "") {
399
					$toput['if'] = $ifname;
400
					$iflist[$friendly] = $toput;
401
				}
402
				break;
403
			}
404
                }
405
        }
406
        return $iflist;
407
}
408

    
409
/* wrapper for exec() */
410
function mwexec($command) {
411

    
412
	global $g;
413
	$oarr = "";
414
	$retval = "";
415
	if ($g['debug']) {
416
		if (!$_SERVER['REMOTE_ADDR'])
417
			echo "mwexec(): $command\n";
418
		exec("$command > /dev/null 2>&1", $oarr, $retval);
419
	} else {
420
		exec("$command > /dev/null 2>&1", $oarr, $retval);
421
	}
422

    
423
	return $retval;
424
}
425

    
426
/* wrapper for exec() in background */
427
function mwexec_bg($command) {
428

    
429
	global $g;
430

    
431
	if ($g['debug']) {
432
		if (!$_SERVER['REMOTE_ADDR'])
433
			echo "mwexec(): $command\n";
434
	}
435

    
436
	exec("nohup $command > /dev/null 2>&1 &");
437
}
438

    
439
/* unlink a file, if it exists */
440
function unlink_if_exists($fn) {
441
	$to_do = glob($fn);
442
	if(is_array($to_do)) {
443
		foreach($to_do as $filename)
444
			@unlink($filename);
445
	} else {
446
		@unlink($fn);
447
	}
448
}
449
/* make a global alias table (for faster lookups) */
450
function alias_make_table($config) {
451

    
452
	global $aliastable;
453

    
454
	$aliastable = array();
455

    
456
	if (is_array($config['aliases']['alias'])) {
457
		foreach ($config['aliases']['alias'] as $alias) {
458
			if ($alias['name'])
459
				$aliastable[$alias['name']] = $alias['address'];
460
		}
461
	}
462
}
463
/* check if an alias exists */
464
function is_alias($name) {
465

    
466
	global $aliastable;
467

    
468
	return isset($aliastable[$name]);
469
}
470

    
471
function alias_expand_value($name) {
472

    
473
	global $aliastable, $config;
474
	$newaddress = "";
475
	$firstentry = true;
476
	if($config['aliases']['alias'])
477
		foreach($config['aliases']['alias'] as $alias) {
478
			if($alias['name'] == $name) {
479
				if($alias['type'] == "openvpn") {
480
					$vpn_address_split = split(" ", $alias['address']);
481
					foreach($vpn_address_split as $vpnsplit) {
482
						foreach($config['openvpn']['user'] as $openvpn) {
483
							if($openvpn['name'] == $vpnsplit) {
484
								if($firstentry == false) 
485
									$newaddress .= " ";
486
								$newaddress .= $openvpn['ip'];
487
								$firstentry = false;
488
							}
489
						}
490
					}
491
				} else {
492
					$newaddress = $alias['address'];
493
				}
494
			}
495
		}
496
		return $newaddress;
497
}
498

    
499
/* expand a host or network alias, if necessary */
500
function alias_expand($name) {
501

    
502
	global $aliastable;
503

    
504
	if (isset($aliastable[$name]))
505
		return "\${$name}";
506
	else if (is_ipaddr($name) || is_subnet($name))
507
		return "{$name}";
508
	else
509
		return null;
510
}
511

    
512
/* expand a host alias, if necessary */
513
function alias_expand_host($name) {
514
	global $aliastable;
515

    
516
	if (isset($aliastable[$name])) {
517
		$ip_arr = explode(" ", $aliastable[$name]);
518
		foreach($ip_arr as $ip) {
519
			if (!is_ipaddr($ip))
520
				return null;
521
		}
522
		return $aliastable[$name];
523
	} else if (is_ipaddr($name))
524
		return $name;
525
	else
526
		return null;
527
}
528

    
529
/* expand a network alias, if necessary */
530
function alias_expand_net($name) {
531

    
532
	global $aliastable;
533

    
534
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
535
		return $aliastable[$name];
536
	else if (is_subnet($name))
537
		return $name;
538
	else
539
		return null;
540
}
541

    
542
/* find out whether two subnets overlap */
543
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
544

    
545
	if (!is_numeric($bits1))
546
		$bits1 = 32;
547
	if (!is_numeric($bits2))
548
		$bits2 = 32;
549

    
550
	if ($bits1 < $bits2)
551
		$relbits = $bits1;
552
	else
553
		$relbits = $bits2;
554

    
555
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
556
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
557

    
558
	if ($sn1 == $sn2)
559
		return true;
560
	else
561
		return false;
562
}
563

    
564
/* compare two IP addresses */
565
function ipcmp($a, $b) {
566
	if (ip2long($a) < ip2long($b))
567
		return -1;
568
	else if (ip2long($a) > ip2long($b))
569
		return 1;
570
	else
571
		return 0;
572
}
573

    
574
/* return true if $addr is in $subnet, false if not */
575
function ip_in_subnet($addr,$subnet) {
576
	list($ip, $mask) = explode('/', $subnet);
577
	$mask = 0xffffffff << (32 - $mask);
578
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
579
}
580

    
581
/* verify (and remove) the digital signature on a file - returns 0 if OK */
582
function verify_digital_signature($fname) {
583

    
584
	global $g;
585

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

    
588
}
589

    
590
/* obtain MAC address given an IP address by looking at the ARP table */
591
function arp_get_mac_by_ip($ip) {
592
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
593
	$arpoutput = "";
594
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
595

    
596
	if ($arpoutput[0]) {
597
		$arpi = explode(" ", $arpoutput[0]);
598
		$macaddr = $arpi[3];
599
		if (is_macaddr($macaddr))
600
			return $macaddr;
601
		else
602
			return false;
603
	}
604

    
605
	return false;
606
}
607

    
608
/* return a fieldname that is safe for xml usage */
609
function xml_safe_fieldname($fieldname) {
610
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
611
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
612
			 ':', ',', '.', '\'', '\\'
613
		);
614
	return strtolower(str_replace($replace, "", $fieldname));
615
}
616

    
617
function mac_format($clientmac) {
618
    $mac =explode(":", $clientmac);
619

    
620
    global $config;
621

    
622
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
623

    
624
    switch($mac_format) {
625

    
626
        case 'singledash':
627
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
628

    
629
        case 'ietf':
630
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
631

    
632
        case 'cisco':
633
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
634

    
635
        case 'unformatted':
636
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
637

    
638
        default:
639
        return $clientmac;
640
    }
641
}
642

    
643
function resolve_retry($hostname, $retries = 5) {
644

    
645
       if (is_ipaddr($hostname))
646
               return $hostname;
647

    
648
       for ($i = 0; $i < $retries; $i++) {
649
               $ip = gethostbyname($hostname);
650

    
651
               if ($ip && $ip != $hostname) {
652
                       /* success */
653
                       return $ip;
654
               }
655

    
656
               sleep(1);
657
       }
658

    
659
       return false;
660
}
661

    
662
?>
(25-25/31)