Project

General

Profile

Download (17.2 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php /* $Id$ */ /*
2
	util.inc
3
	part of m0n0wall (http://m0n0.ch/wall)
4

    
5
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
6
	All rights reserved.
7

    
8
	Redistribution and use in source and binary forms, with or without
9
	modification, are permitted provided that the following conditions are met:
10

    
11
	1. Redistributions of source code must retain the above copyright notice,
12
	   this list of conditions and the following disclaimer.
13

    
14
	2. Redistributions in binary form must reproduce the above copyright
15
	   notice, this list of conditions and the following disclaimer in the
16
	   documentation and/or other materials provided with the distribution.
17

    
18
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
	POSSIBILITY OF SUCH DAMAGE.
28
*/
29

    
30
/* kill a process by pid file */
31
function killbypid($pidfile) {
32
	sigkillbypid($pidfile, "TERM");
33
}
34

    
35
function isvalidpid($pid) {
36
	$running = `ps -p $pid | wc -l`;
37
	if(intval($running) > 1)
38
		return true;
39
	else 
40
		return false;
41
}
42

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

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

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

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

    
74
function is_module_loaded($module_name) {
75
	$running = `/sbin/kldstat | grep {$module_name} | /usr/bin/grep -v grep | /usr/bin/wc -l`;
76
	if (intval($running) >= 1)
77
		return true;
78
	else
79
		return false;
80
}
81

    
82
/* return the subnet address given a host address and a subnet bit count */
83
function gen_subnet($ipaddr, $bits) {
84
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
85
		return "";
86

    
87
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
88
}
89

    
90
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
91
function gen_subnet_max($ipaddr, $bits) {
92
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
93
		return "";
94

    
95
	return long2ip(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
96
}
97

    
98
/* returns a subnet mask (long given a bit count) */
99
function gen_subnet_mask_long($bits) {
100
	$sm = 0;
101
	for ($i = 0; $i < $bits; $i++) {
102
		$sm >>= 1;
103
		$sm |= 0x80000000;
104
	}
105
	return $sm;
106
}
107

    
108
/* same as above but returns a string */
109
function gen_subnet_mask($bits) {
110
	return long2ip(gen_subnet_mask_long($bits));
111
}
112

    
113
function is_numericint($arg) {
114
	return (preg_match("/[^0-9]/", $arg) ? false : true);
115
}
116

    
117
/* returns true if $ipaddr is a valid dotted IPv4 address */
118
function is_ipaddr($ipaddr) {
119
	if (!is_string($ipaddr))
120
		return false;
121

    
122
	$ip_long = ip2long($ipaddr);
123
	$ip_reverse = long2ip($ip_long);
124

    
125
	if ($ipaddr == $ip_reverse)
126
		return true;
127
	else
128
		return false;
129
}
130

    
131
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
132
function is_ipaddroralias($ipaddr) {
133

    
134
	global $aliastable, $config;
135

    
136
	if(is_array($config['aliases']['alias'])) {
137
		foreach($config['aliases']['alias'] as $alias) {
138
			if($alias['name'] == $ipaddr)
139
				return true;
140
		}
141
	}
142

    
143
	if (isset($aliastable[$ipaddr]) && is_ipaddr($aliastable[$ipaddr]))
144
		return true;
145
	else
146
		return is_ipaddr($ipaddr);
147

    
148
}
149

    
150
/* returns true if $ipaddr is a valid dotted IPv4 address or any alias */
151
function is_ipaddroranyalias($ipaddr) {
152

    
153
	global $aliastable;
154

    
155
	if (isset($aliastable[$ipaddr]))
156
		return true;
157
	else
158
		return is_ipaddr($ipaddr);
159
}
160

    
161
/* returns true if $subnet is a valid subnet in CIDR format */
162
function is_subnet($subnet) {
163
	if (!is_string($subnet))
164
		return false;
165

    
166
	list($hp,$np) = explode('/', $subnet);
167

    
168
	if (!is_ipaddr($hp))
169
		return false;
170

    
171
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
172
		return false;
173

    
174
	return true;
175
}
176

    
177
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
178
function is_subnetoralias($subnet) {
179

    
180
	global $aliastable;
181

    
182
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
183
		return true;
184
	else
185
		return is_subnet($subnet);
186
}
187

    
188
/* returns true if $hostname is a valid hostname */
189
function is_hostname($hostname) {
190
	if (!is_string($hostname))
191
		return false;
192

    
193
	if (preg_match("/^([_a-z0-9\-]+\.?)+$/i", $hostname))
194
		return true;
195
	else
196
		return false;
197
}
198

    
199
/* returns true if $domain is a valid domain name */
200
function is_domain($domain) {
201
	if (!is_string($domain))
202
		return false;
203

    
204
	if (preg_match("/^([a-z0-9\-]+\.?)+$/i", $domain))
205
		return true;
206
	else
207
		return false;
208
}
209

    
210
/* returns true if $uname is a valid DynDNS username */
211
function is_dyndns_username($uname) {
212
	if (!is_string($uname))
213
		return false;
214

    
215
	if (preg_match("/[^a-z0-9\-.@_]/i", $uname))
216
		return false;
217
	else
218
		return true;
219
}
220

    
221
/* returns true if $macaddr is a valid MAC address */
222
function is_macaddr($macaddr) {
223
	if (!is_string($macaddr))
224
		return false;
225

    
226
	$maca = explode(":", $macaddr);
227
	if (count($maca) != 6)
228
		return false;
229

    
230
	foreach ($maca as $macel) {
231
		if (($macel === "") || (strlen($macel) > 2))
232
			return false;
233
		if (preg_match("/[^0-9a-f]/i", $macel))
234
			return false;
235
	}
236

    
237
	return true;
238
}
239

    
240
/* returns true if $name is a valid name for an alias */
241
/* returns NULL if a reserved word is used */
242
function is_validaliasname($name) {
243
	/* Array of reserved words */
244
	$reserved = array("port", "pass");
245
	if (in_array($name, $reserved, true))
246
		return; /* return NULL */
247

    
248
	if (!preg_match("/[^a-zA-Z0-9_]/", $name))
249
		return true;
250
	else
251
		return false;
252
}
253

    
254
/* returns true if $port is a valid TCP/UDP port */
255
function is_port($port) {
256
	if (!is_numericint($port))
257
		return false;
258

    
259
	if (($port < 1) || ($port > 65535))
260
		return false;
261
	else
262
		return true;
263
}
264

    
265
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
266
function is_portrange($portrange) {
267
        $ports = explode(":", $portrange);
268

    
269
        if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
270
                return true;
271
        else
272
                return false;
273
}
274

    
275
/* returns true if $val is a valid shaper bandwidth value */
276
function is_valid_shaperbw($val) {
277
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
278
}
279

    
280
/* return the configured interfaces list. */
281
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
282
	global $config;
283

    
284
	$iflist = array();
285

    
286
	if (!$only_opt) {
287
		if (isset($config['interfaces']['wan']))
288
			$iflist['wan'] = "wan";
289
		if (isset($config['interfaces']['lan']))
290
			$iflist['lan'] = "lan";
291
	}
292

    
293
	/* if list */
294
        foreach($config['interfaces'] as $if => $ifdetail) {
295
		if ($if == "wan" || $if == "lan")
296
			continue;
297
		if (isset($ifdetail['enable']) || $withdisabled == true)
298
			$iflist[$if] = $if;
299
	}
300

    
301
	return $iflist;
302
}
303

    
304
/* return the configured interfaces list with their description. */
305
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
306
        global $config;
307

    
308
        $iflist = array();
309

    
310
	if (!$only_opt) {
311
                if (isset($config['interfaces']['wan'])) {
312
			if (empty($config['interfaces']['wan']['descr']))
313
				$iflist['wan'] = "WAN";
314
			else
315
				$iflist['wan'] = $config['interfaces']['wan']['descr'];
316
		}
317
                if (isset($config['interfaces']['lan'])) {
318
			if (empty($config['interfaces']['lan']['descr']))
319
                                $iflist['lan'] = "LAN";
320
                        else
321
                                $iflist['lan'] = $config['interfaces']['lan']['descr'];
322
		}
323
        }
324

    
325
        /* if list */
326
        foreach($config['interfaces'] as $if => $ifdetail) {
327
		if (isset($ifdetail['enable']) || $withdisabled == true) {
328
			if($ifdetail['descr'] == "")
329
				$iflist[$if] = strtoupper($if);
330
                        else
331
				$iflist[$if] = strtoupper($ifdetail['descr']);
332
		}
333
	}
334

    
335
        return $iflist;
336
}
337

    
338

    
339
/*
340
 *   get_interface_list() - Return a list of all physical interfaces
341
 *   along with MAC and status.
342
 *
343
 *   $mode = "active" - use ifconfig -lu
344
 *           "media"  - use ifconfig to check physical connection
345
 *			status (much slower)
346
 */
347
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
348
        global $config;
349
	$upints = array();
350
        /* get a list of virtual interface types */
351
        if(!$vfaces) {
352
		$vfaces = array (
353
				'bridge',
354
				'ppp',
355
				'sl',
356
				'gif',
357
				'gre',
358
				'faith',
359
				'lo',
360
				'ng',
361
				'vlan',
362
				'pflog',
363
				'pfsync',
364
				'enc',
365
				'tun',
366
				'carp',
367
				'lagg',
368
				'plip'
369
		);
370
	}
371
	switch($mode) {
372
	case "active":
373
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
374
        	break;
375
	case "media":
376
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
377
                $ifconfig = "";
378
                exec("/sbin/ifconfig -a", $ifconfig);
379
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
380
                $ifstatus = preg_grep('/status:/', $ifconfig);
381
		foreach($ifstatus as $status) {
382
			$int = array_shift($intlist);
383
                	if(stristr($status, "active")) $upints[] = $int;
384
		}
385
		break;
386
	}
387
        /* build interface list with netstat */
388
        $linkinfo = "";
389
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
390
        array_shift($linkinfo);
391
	/* build ip address list with netstat */
392
	$ipinfo = "";
393
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
394
	array_shift($ipinfo);
395
	foreach($linkinfo as $link) {
396
		$friendly = "";
397
                $alink = explode(" ", $link);
398
                $ifname = rtrim(trim($alink[0]), '*');
399
                /* trim out all numbers before checking for vfaces */
400
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces)) {
401
			$toput = array(
402
					"mac" => trim($alink[1]),
403
					"up" => in_array($ifname, $upints)
404
				);
405
			foreach($ipinfo as $ip) {
406
				$aip = explode(" ", $ip);
407
				if($aip[0] == $ifname) {
408
					$toput['ipaddr'] = $aip[1];
409
				}
410
			}
411
			foreach($config['interfaces'] as $name => $int) {
412
				if($int['if'] == $ifname) $friendly = $name;
413
			}
414
			switch($keyby) {
415
			case "physical":
416
				if($friendly != "") {
417
					$toput['friendly'] = $friendly;
418
				}
419
				$dmesg_arr = array();
420
				exec("/sbin/dmesg |grep $ifname | head -n1", $dmesg_arr);
421
				preg_match_all("/<(.*?)>/i", $dmesg_arr[0], $dmesg);
422
				$toput['dmesg'] = $dmesg[1][0];
423
				$iflist[$ifname] = $toput;
424
				break;
425
			case "friendly":
426
				if($friendly != "") {
427
					$toput['if'] = $ifname;
428
					$iflist[$friendly] = $toput;
429
				}
430
				break;
431
			}
432
                }
433
        }
434
        return $iflist;
435
}
436

    
437
/* wrapper for exec() */
438
function mwexec($command, $mute = false) {
439

    
440
	global $g;
441
	$oarr = array();
442
	$retval = 0;
443
	if ($g['debug']) {
444
		if (!$_SERVER['REMOTE_ADDR'])
445
			echo "mwexec(): $command\n";
446
		exec("$command 2>&1", $oarr, $retval);
447
	} else {
448
		exec("$command 2>&1", $oarr, $retval);
449
	}
450
	if(isset($config['system']['developerspew']))
451
                $mute = false;
452
	if(($retval <> 0) && ($mute === false)) {
453
		$output = implode(" ", $oarr);
454
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
455
	}
456
	return $retval;
457
}
458

    
459
/* wrapper for exec() in background */
460
function mwexec_bg($command) {
461

    
462
	global $g;
463

    
464
	if ($g['debug']) {
465
		if (!$_SERVER['REMOTE_ADDR'])
466
			echo "mwexec(): $command\n";
467
	}
468

    
469
	exec("nohup $command > /dev/null 2>&1 &");
470
}
471

    
472
/* unlink a file, if it exists */
473
function unlink_if_exists($fn) {
474
	$to_do = glob($fn);
475
	if(is_array($to_do)) {
476
		foreach($to_do as $filename)
477
			@unlink($filename);
478
	} else {
479
		@unlink($fn);
480
	}
481
}
482
/* make a global alias table (for faster lookups) */
483
function alias_make_table($config) {
484

    
485
	global $aliastable;
486

    
487
	$aliastable = array();
488

    
489
	if (is_array($config['aliases']['alias'])) {
490
		foreach ($config['aliases']['alias'] as $alias) {
491
			if ($alias['name'])
492
				$aliastable[$alias['name']] = $alias['address'];
493
		}
494
	}
495
}
496
/* check if an alias exists */
497
function is_alias($name) {
498

    
499
	global $aliastable;
500

    
501
	return isset($aliastable[$name]);
502
}
503

    
504
function alias_expand_value($name) {
505

    
506
	global $aliastable, $config;
507
	$newaddress = "";
508
	$firstentry = true;
509
	if($config['aliases']['alias'])
510
		foreach($config['aliases']['alias'] as $alias) {
511
			if($alias['name'] == $name) {
512
				if($alias['type'] == "openvpn") {
513
					$vpn_address_split = split(" ", $alias['address']);
514
					foreach($vpn_address_split as $vpnsplit) {
515
						foreach($config['openvpn']['user'] as $openvpn) {
516
							if($openvpn['name'] == $vpnsplit) {
517
								if($firstentry == false) 
518
									$newaddress .= " ";
519
								$newaddress .= $openvpn['ip'];
520
								$firstentry = false;
521
							}
522
						}
523
					}
524
				} else {
525
					$newaddress = $alias['address'];
526
				}
527
			}
528
		}
529
		return $newaddress;
530
}
531

    
532
/* expand a host or network alias, if necessary */
533
function alias_expand($name) {
534

    
535
	global $aliastable;
536

    
537
	if (isset($aliastable[$name]))
538
		return "\${$name}";
539
	else if (is_ipaddr($name) || is_subnet($name))
540
		return "{$name}";
541
	else
542
		return null;
543
}
544

    
545
/* expand a host alias, if necessary */
546
function alias_expand_host($name) {
547
	global $aliastable;
548

    
549
	if (isset($aliastable[$name])) {
550
		$ip_arr = explode(" ", $aliastable[$name]);
551
		foreach($ip_arr as $ip) {
552
			if (!is_ipaddr($ip))
553
				return null;
554
		}
555
		return $aliastable[$name];
556
	} else if (is_ipaddr($name))
557
		return $name;
558
	else
559
		return null;
560
}
561

    
562
/* expand a network alias, if necessary */
563
function alias_expand_net($name) {
564

    
565
	global $aliastable;
566

    
567
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
568
		return $aliastable[$name];
569
	else if (is_subnet($name))
570
		return $name;
571
	else
572
		return null;
573
}
574

    
575
/* find out whether two subnets overlap */
576
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
577

    
578
	if (!is_numeric($bits1))
579
		$bits1 = 32;
580
	if (!is_numeric($bits2))
581
		$bits2 = 32;
582

    
583
	if ($bits1 < $bits2)
584
		$relbits = $bits1;
585
	else
586
		$relbits = $bits2;
587

    
588
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
589
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
590

    
591
	if ($sn1 == $sn2)
592
		return true;
593
	else
594
		return false;
595
}
596

    
597
/* compare two IP addresses */
598
function ipcmp($a, $b) {
599
	if (ip2long($a) < ip2long($b))
600
		return -1;
601
	else if (ip2long($a) > ip2long($b))
602
		return 1;
603
	else
604
		return 0;
605
}
606

    
607
/* return true if $addr is in $subnet, false if not */
608
function ip_in_subnet($addr,$subnet) {
609
	list($ip, $mask) = explode('/', $subnet);
610
	$mask = 0xffffffff << (32 - $mask);
611
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
612
}
613

    
614
/* verify (and remove) the digital signature on a file - returns 0 if OK */
615
function verify_digital_signature($fname) {
616

    
617
	global $g;
618

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

    
621
}
622

    
623
/* obtain MAC address given an IP address by looking at the ARP table */
624
function arp_get_mac_by_ip($ip) {
625
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
626
	$arpoutput = "";
627
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
628

    
629
	if ($arpoutput[0]) {
630
		$arpi = explode(" ", $arpoutput[0]);
631
		$macaddr = $arpi[3];
632
		if (is_macaddr($macaddr))
633
			return $macaddr;
634
		else
635
			return false;
636
	}
637

    
638
	return false;
639
}
640

    
641
/* return a fieldname that is safe for xml usage */
642
function xml_safe_fieldname($fieldname) {
643
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
644
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
645
			 ':', ',', '.', '\'', '\\'
646
		);
647
	return strtolower(str_replace($replace, "", $fieldname));
648
}
649

    
650
function mac_format($clientmac) {
651
    $mac =explode(":", $clientmac);
652

    
653
    global $config;
654

    
655
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
656

    
657
    switch($mac_format) {
658

    
659
        case 'singledash':
660
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
661

    
662
        case 'ietf':
663
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
664

    
665
        case 'cisco':
666
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
667

    
668
        case 'unformatted':
669
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
670

    
671
        default:
672
        return $clientmac;
673
    }
674
}
675

    
676
function resolve_retry($hostname, $retries = 5) {
677

    
678
       if (is_ipaddr($hostname))
679
               return $hostname;
680

    
681
       for ($i = 0; $i < $retries; $i++) {
682
               $ip = gethostbyname($hostname);
683

    
684
               if ($ip && $ip != $hostname) {
685
                       /* success */
686
                       return $ip;
687
               }
688

    
689
               sleep(1);
690
       }
691

    
692
       return false;
693
}
694

    
695
function format_bytes($bytes) {
696
	if ($bytes >= 1073741824) {
697
		return sprintf("%.2f GB", $bytes/1073741824);
698
	} else if ($bytes >= 1048576) {
699
		return sprintf("%.2f MB", $bytes/1048576);
700
	} else if ($bytes >= 1024) {
701
		return sprintf("%.0f KB", $bytes/1024);
702
	} else {
703
		return sprintf("%d bytes", $bytes);
704
	}
705
}
706

    
707
?>
(34-34/40)