Project

General

Profile

Download (16.3 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
/* return the subnet address given a host address and a subnet bit count */
75
function gen_subnet($ipaddr, $bits) {
76
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
77
		return "";
78

    
79
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
80
}
81

    
82
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
83
function gen_subnet_max($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
/* returns a subnet mask (long given a bit count) */
91
function gen_subnet_mask_long($bits) {
92
	$sm = 0;
93
	for ($i = 0; $i < $bits; $i++) {
94
		$sm >>= 1;
95
		$sm |= 0x80000000;
96
	}
97
	return $sm;
98
}
99

    
100
/* same as above but returns a string */
101
function gen_subnet_mask($bits) {
102
	return long2ip(gen_subnet_mask_long($bits));
103
}
104

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

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

    
114
	$ip_long = ip2long($ipaddr);
115
	$ip_reverse = long2ip($ip_long);
116

    
117
	if ($ipaddr == $ip_reverse)
118
		return true;
119
	else
120
		return false;
121
}
122

    
123
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
124
function is_ipaddroralias($ipaddr) {
125

    
126
	global $aliastable, $config;
127

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

    
135
	if (isset($aliastable[$ipaddr]) && is_ipaddr($aliastable[$ipaddr]))
136
		return true;
137
	else
138
		return is_ipaddr($ipaddr);
139

    
140
}
141

    
142
/* returns true if $ipaddr is a valid dotted IPv4 address or any alias */
143
function is_ipaddroranyalias($ipaddr) {
144

    
145
	global $aliastable;
146

    
147
	if (isset($aliastable[$ipaddr]))
148
		return true;
149
	else
150
		return is_ipaddr($ipaddr);
151
}
152

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

    
158
	list($hp,$np) = explode('/', $subnet);
159

    
160
	if (!is_ipaddr($hp))
161
		return false;
162

    
163
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
164
		return false;
165

    
166
	return true;
167
}
168

    
169
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
170
function is_subnetoralias($subnet) {
171

    
172
	global $aliastable;
173

    
174
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
175
		return true;
176
	else
177
		return is_subnet($subnet);
178
}
179

    
180
/* returns true if $hostname is a valid hostname */
181
function is_hostname($hostname) {
182
	if (!is_string($hostname))
183
		return false;
184

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

    
191
/* returns true if $domain is a valid domain name */
192
function is_domain($domain) {
193
	if (!is_string($domain))
194
		return false;
195

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

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

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

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

    
218
	$maca = explode(":", $macaddr);
219
	if (count($maca) != 6)
220
		return false;
221

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

    
229
	return true;
230
}
231

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

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

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

    
251
	if (($port < 1) || ($port > 65535))
252
		return false;
253
	else
254
		return true;
255
}
256

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

    
261
        if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
262
                return true;
263
        else
264
                return false;
265
}
266

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

    
272
/* return the configured interfaces list. */
273
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
274
	global $config;
275

    
276
	$iflist = array();
277

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

    
287
	return $iflist;
288
			
289
}
290

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

    
295
        $iflist = array();
296

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

    
310
        return $iflist;
311

    
312
}
313

    
314

    
315
/*
316
 *   get_interface_list() - Return a list of all physical interfaces
317
 *   along with MAC and status.
318
 *
319
 *   $mode = "active" - use ifconfig -lu
320
 *           "media"  - use ifconfig to check physical connection
321
 *			status (much slower)
322
 */
323
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
324
        global $config;
325
	$upints = array();
326
        /* get a list of virtual interface types */
327
        if(!$vfaces) {
328
		$vfaces = array (
329
				'bridge',
330
				'ppp',
331
				'sl',
332
				'gif',
333
				'gre',
334
				'faith',
335
				'lo',
336
				'ng',
337
				'vlan',
338
				'pflog',
339
				'pfsync',
340
				'enc',
341
				'tun',
342
				'carp',
343
				'lagg',
344
				'plip'
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, $mute = false) {
411

    
412
	global $g;
413
	$oarr = array();
414
	$retval = 0;
415
	if ($g['debug']) {
416
		if (!$_SERVER['REMOTE_ADDR'])
417
			echo "mwexec(): $command\n";
418
		exec("$command 2>&1", $oarr, $retval);
419
	} else {
420
		exec("$command 2>&1", $oarr, $retval);
421
	}
422
	if(isset($config['system']['developerspew']))
423
                $mute = false;
424
	if(($retval <> 0) && ($mute === false)) {
425
		$output = implode(" ", $oarr);
426
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
427
	}
428
	return $retval;
429
}
430

    
431
/* wrapper for exec() in background */
432
function mwexec_bg($command) {
433

    
434
	global $g;
435

    
436
	if ($g['debug']) {
437
		if (!$_SERVER['REMOTE_ADDR'])
438
			echo "mwexec(): $command\n";
439
	}
440

    
441
	exec("nohup $command > /dev/null 2>&1 &");
442
}
443

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

    
457
	global $aliastable;
458

    
459
	$aliastable = array();
460

    
461
	if (is_array($config['aliases']['alias'])) {
462
		foreach ($config['aliases']['alias'] as $alias) {
463
			if ($alias['name'])
464
				$aliastable[$alias['name']] = $alias['address'];
465
		}
466
	}
467
}
468
/* check if an alias exists */
469
function is_alias($name) {
470

    
471
	global $aliastable;
472

    
473
	return isset($aliastable[$name]);
474
}
475

    
476
function alias_expand_value($name) {
477

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

    
504
/* expand a host or network alias, if necessary */
505
function alias_expand($name) {
506

    
507
	global $aliastable;
508

    
509
	if (isset($aliastable[$name]))
510
		return "\${$name}";
511
	else if (is_ipaddr($name) || is_subnet($name))
512
		return "{$name}";
513
	else
514
		return null;
515
}
516

    
517
/* expand a host alias, if necessary */
518
function alias_expand_host($name) {
519
	global $aliastable;
520

    
521
	if (isset($aliastable[$name])) {
522
		$ip_arr = explode(" ", $aliastable[$name]);
523
		foreach($ip_arr as $ip) {
524
			if (!is_ipaddr($ip))
525
				return null;
526
		}
527
		return $aliastable[$name];
528
	} else if (is_ipaddr($name))
529
		return $name;
530
	else
531
		return null;
532
}
533

    
534
/* expand a network alias, if necessary */
535
function alias_expand_net($name) {
536

    
537
	global $aliastable;
538

    
539
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
540
		return $aliastable[$name];
541
	else if (is_subnet($name))
542
		return $name;
543
	else
544
		return null;
545
}
546

    
547
/* find out whether two subnets overlap */
548
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
549

    
550
	if (!is_numeric($bits1))
551
		$bits1 = 32;
552
	if (!is_numeric($bits2))
553
		$bits2 = 32;
554

    
555
	if ($bits1 < $bits2)
556
		$relbits = $bits1;
557
	else
558
		$relbits = $bits2;
559

    
560
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
561
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
562

    
563
	if ($sn1 == $sn2)
564
		return true;
565
	else
566
		return false;
567
}
568

    
569
/* compare two IP addresses */
570
function ipcmp($a, $b) {
571
	if (ip2long($a) < ip2long($b))
572
		return -1;
573
	else if (ip2long($a) > ip2long($b))
574
		return 1;
575
	else
576
		return 0;
577
}
578

    
579
/* return true if $addr is in $subnet, false if not */
580
function ip_in_subnet($addr,$subnet) {
581
	list($ip, $mask) = explode('/', $subnet);
582
	$mask = 0xffffffff << (32 - $mask);
583
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
584
}
585

    
586
/* verify (and remove) the digital signature on a file - returns 0 if OK */
587
function verify_digital_signature($fname) {
588

    
589
	global $g;
590

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

    
593
}
594

    
595
/* obtain MAC address given an IP address by looking at the ARP table */
596
function arp_get_mac_by_ip($ip) {
597
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
598
	$arpoutput = "";
599
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
600

    
601
	if ($arpoutput[0]) {
602
		$arpi = explode(" ", $arpoutput[0]);
603
		$macaddr = $arpi[3];
604
		if (is_macaddr($macaddr))
605
			return $macaddr;
606
		else
607
			return false;
608
	}
609

    
610
	return false;
611
}
612

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

    
622
function mac_format($clientmac) {
623
    $mac =explode(":", $clientmac);
624

    
625
    global $config;
626

    
627
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
628

    
629
    switch($mac_format) {
630

    
631
        case 'singledash':
632
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
633

    
634
        case 'ietf':
635
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
636

    
637
        case 'cisco':
638
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
639

    
640
        case 'unformatted':
641
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
642

    
643
        default:
644
        return $clientmac;
645
    }
646
}
647

    
648
function resolve_retry($hostname, $retries = 5) {
649

    
650
       if (is_ipaddr($hostname))
651
               return $hostname;
652

    
653
       for ($i = 0; $i < $retries; $i++) {
654
               $ip = gethostbyname($hostname);
655

    
656
               if ($ip && $ip != $hostname) {
657
                       /* success */
658
                       return $ip;
659
               }
660

    
661
               sleep(1);
662
       }
663

    
664
       return false;
665
}
666

    
667
function format_bytes($bytes) {
668
	if ($bytes >= 1073741824) {
669
		return sprintf("%.2f GB", $bytes/1073741824);
670
	} else if ($bytes >= 1048576) {
671
		return sprintf("%.2f MB", $bytes/1048576);
672
	} else if ($bytes >= 1024) {
673
		return sprintf("%.0f KB", $bytes/1024);
674
	} else {
675
		return sprintf("%d bytes", $bytes);
676
	}
677
}
678

    
679
?>
(33-33/39)