Project

General

Profile

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

    
366
/* wrapper for exec() */
367
function mwexec($command) {
368

    
369
	global $g;
370
	$oarr = "";
371
	$retval = "";
372
	if ($g['debug']) {
373
		if (!$_SERVER['REMOTE_ADDR'])
374
			echo "mwexec(): $command\n";
375
		exec("$command > /dev/null 2>&1", $oarr, $retval);
376
	} else {
377
		exec("$command > /dev/null 2>&1", $oarr, $retval);
378
	}
379

    
380
	return $retval;
381
}
382

    
383
/* wrapper for exec() in background */
384
function mwexec_bg($command) {
385

    
386
	global $g;
387

    
388
	if ($g['debug']) {
389
		if (!$_SERVER['REMOTE_ADDR'])
390
			echo "mwexec(): $command\n";
391
	}
392

    
393
	exec("nohup $command > /dev/null 2>&1 &");
394
}
395

    
396
/* unlink a file, if it exists */
397
function unlink_if_exists($fn) {
398
	$to_do = glob($fn);
399
	if(is_array($to_do)) {
400
		foreach($to_do as $filename)
401
			@unlink($filename);
402
	} else {
403
		@unlink($fn);
404
	}
405
}
406
/* make a global alias table (for faster lookups) */
407
function alias_make_table($config) {
408

    
409
	global $aliastable;
410

    
411
	$aliastable = array();
412

    
413
	if (is_array($config['aliases']['alias'])) {
414
		foreach ($config['aliases']['alias'] as $alias) {
415
			if ($alias['name'])
416
				$aliastable[$alias['name']] = $alias['address'];
417
		}
418
	}
419
}
420
/* check if an alias exists */
421
function is_alias($name) {
422

    
423
	global $aliastable;
424

    
425
	return isset($aliastable[$name]);
426
}
427

    
428
function alias_expand_value($name) {
429

    
430
	global $aliastable, $config;
431
	$newaddress = "";
432
	$firstentry = true;
433
	if($config['aliases']['alias'])
434
		foreach($config['aliases']['alias'] as $alias) {
435
			if($alias['name'] == $name) {
436
				if($alias['type'] == "openvpn") {
437
					$vpn_address_split = split(" ", $alias['address']);
438
					foreach($vpn_address_split as $vpnsplit) {
439
						foreach($config['openvpn']['user'] as $openvpn) {
440
							if($openvpn['name'] == $vpnsplit) {
441
								if($firstentry == false) 
442
									$newaddress .= " ";
443
								$newaddress .= $openvpn['ip'];
444
								$firstentry = false;
445
							}
446
						}
447
					}
448
				} else {
449
					$newaddress = $alias['address'];
450
				}
451
			}
452
		}
453
		return $newaddress;
454
}
455

    
456
/* expand a host or network alias, if necessary */
457
function alias_expand($name) {
458

    
459
	global $aliastable;
460

    
461
	if (isset($aliastable[$name]))
462
		return "\${$name}";
463
	else if (is_ipaddr($name) || is_subnet($name))
464
		return "{$name}";
465
	else
466
		return null;
467
}
468

    
469
/* expand a host alias, if necessary */
470
function alias_expand_host($name) {
471
	global $aliastable;
472

    
473
	if (isset($aliastable[$name])) {
474
		$ip_arr = explode(" ", $aliastable[$name]);
475
		foreach($ip_arr as $ip) {
476
			if (!is_ipaddr($ip))
477
				return null;
478
		}
479
		return $aliastable[$name];
480
	} else if (is_ipaddr($name))
481
		return $name;
482
	else
483
		return null;
484
}
485

    
486
/* expand a network alias, if necessary */
487
function alias_expand_net($name) {
488

    
489
	global $aliastable;
490

    
491
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
492
		return $aliastable[$name];
493
	else if (is_subnet($name))
494
		return $name;
495
	else
496
		return null;
497
}
498

    
499
/* find out whether two subnets overlap */
500
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
501

    
502
	if (!is_numeric($bits1))
503
		$bits1 = 32;
504
	if (!is_numeric($bits2))
505
		$bits2 = 32;
506

    
507
	if ($bits1 < $bits2)
508
		$relbits = $bits1;
509
	else
510
		$relbits = $bits2;
511

    
512
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
513
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
514

    
515
	if ($sn1 == $sn2)
516
		return true;
517
	else
518
		return false;
519
}
520

    
521
/* compare two IP addresses */
522
function ipcmp($a, $b) {
523
	if (ip2long($a) < ip2long($b))
524
		return -1;
525
	else if (ip2long($a) > ip2long($b))
526
		return 1;
527
	else
528
		return 0;
529
}
530

    
531
/* return true if $addr is in $subnet, false if not */
532
function ip_in_subnet($addr,$subnet) {
533
	list($ip, $mask) = explode('/', $subnet);
534
	$mask = 0xffffffff << (32 - $mask);
535
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
536
}
537

    
538
/* verify (and remove) the digital signature on a file - returns 0 if OK */
539
function verify_digital_signature($fname) {
540

    
541
	global $g;
542

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

    
545
}
546

    
547
/* obtain MAC address given an IP address by looking at the ARP table */
548
function arp_get_mac_by_ip($ip) {
549
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
550
	$arpoutput = "";
551
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
552

    
553
	if ($arpoutput[0]) {
554
		$arpi = explode(" ", $arpoutput[0]);
555
		$macaddr = $arpi[3];
556
		if (is_macaddr($macaddr))
557
			return $macaddr;
558
		else
559
			return false;
560
	}
561

    
562
	return false;
563
}
564

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

    
574
function mac_format($clientmac) {
575
    $mac =explode(":", $clientmac);
576

    
577
    global $config;
578

    
579
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
580

    
581
    switch($mac_format) {
582

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

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

    
589
        case 'cisco':
590
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
591

    
592
        case 'unformatted':
593
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
594

    
595
        default:
596
        return $clientmac;
597
    }
598
}
599

    
600
function resolve_retry($hostname, $retries = 5) {
601

    
602
       if (is_ipaddr($hostname))
603
               return $hostname;
604

    
605
       for ($i = 0; $i < $retries; $i++) {
606
               $ip = gethostbyname($hostname);
607

    
608
               if ($ip && $ip != $hostname) {
609
                       /* success */
610
                       return $ip;
611
               }
612

    
613
               sleep(1);
614
       }
615

    
616
       return false;
617
}
618

    
619
?>
(23-23/29)