Project

General

Profile

Download (13.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
/* 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}");
42
	} else {
43
		mwexec("/bin/kill -s $sig {$pidfile}");
44
	}
45
}
46

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

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

    
57
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
58
}
59

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

    
65
	return long2ip(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
66
}
67

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

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

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

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

    
92
	$ip_long = ip2long($ipaddr);
93
	$ip_reverse = long2ip($ip_long);
94

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

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

    
104
	global $aliastable, $config;
105

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

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

    
118
}
119

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

    
123
	global $aliastable;
124

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

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

    
136
	list($hp,$np) = explode('/', $subnet);
137

    
138
	if (!is_ipaddr($hp))
139
		return false;
140

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

    
144
	return true;
145
}
146

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

    
150
	global $aliastable;
151

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

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

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

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

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

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

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

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

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

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

    
207
	return true;
208
}
209

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

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

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

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

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

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

    
245
/* returns true if $val is a valid shaper bandwidth value */
246
function is_valid_shaperbw($val) {
247
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
248
}
249

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

    
341
/* wrapper for exec() */
342
function mwexec($command) {
343

    
344
	global $g;
345
	$oarr = "";
346
	$retval = "";
347
	if ($g['debug']) {
348
		if (!$_SERVER['REMOTE_ADDR'])
349
			echo "mwexec(): $command\n";
350
		exec("$command > /dev/null 2>&1", $oarr, $retval);
351
	} else {
352
		exec("$command > /dev/null 2>&1", $oarr, $retval);
353
	}
354

    
355
	return $retval;
356
}
357

    
358
/* wrapper for exec() in background */
359
function mwexec_bg($command) {
360

    
361
	global $g;
362

    
363
	if ($g['debug']) {
364
		if (!$_SERVER['REMOTE_ADDR'])
365
			echo "mwexec(): $command\n";
366
	}
367

    
368
	exec("nohup $command > /dev/null 2>&1 &");
369
}
370

    
371
/* unlink a file, if it exists */
372
function unlink_if_exists($fn) {
373
	$to_do = glob($fn);
374
	if(is_array($to_do)) {
375
		foreach($to_do as $filename)
376
			@unlink($filename);
377
	} else {
378
		@unlink($fn);
379
	}
380
}
381
/* make a global alias table (for faster lookups) */
382
function alias_make_table($config) {
383

    
384
	global $aliastable;
385

    
386
	$aliastable = array();
387

    
388
	if (is_array($config['aliases']['alias'])) {
389
		foreach ($config['aliases']['alias'] as $alias) {
390
			if ($alias['name'])
391
				$aliastable[$alias['name']] = $alias['address'];
392
		}
393
	}
394
}
395
/* check if an alias exists */
396
function is_alias($name) {
397

    
398
	global $aliastable;
399

    
400
	return isset($aliastable[$name]);
401
}
402

    
403
function alias_expand_value($name) {
404

    
405
	global $aliastable, $config;
406
	if($config['aliases']['alias'])
407
		foreach($config['aliases']['alias'] as $alias) {
408
			if($alias['name'] == $name)
409
				return $alias['address'];
410
		}
411

    
412
}
413

    
414
/* expand a host or network alias, if necessary */
415
function alias_expand($name) {
416

    
417
	global $aliastable;
418

    
419
	if (isset($aliastable[$name]))
420
		return "\${$name}";
421
	else if (is_ipaddr($name) || is_subnet($name))
422
		return "{$name}";
423
	else
424
		return null;
425
}
426

    
427
/* expand a host alias, if necessary */
428
function alias_expand_host($name) {
429
	global $aliastable;
430

    
431
	if (isset($aliastable[$name])) {
432
		$ip_arr = explode(" ", $aliastable[$name]);
433
		foreach($ip_arr as $ip) {
434
			if (!is_ipaddr($ip))
435
				return null;
436
		}
437
		return $aliastable[$name];
438
	} else if (is_ipaddr($name))
439
		return $name;
440
	else
441
		return null;
442
}
443

    
444
/* expand a network alias, if necessary */
445
function alias_expand_net($name) {
446

    
447
	global $aliastable;
448

    
449
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
450
		return $aliastable[$name];
451
	else if (is_subnet($name))
452
		return $name;
453
	else
454
		return null;
455
}
456

    
457
/* find out whether two subnets overlap */
458
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
459

    
460
	if (!is_numeric($bits1))
461
		$bits1 = 32;
462
	if (!is_numeric($bits2))
463
		$bits2 = 32;
464

    
465
	if ($bits1 < $bits2)
466
		$relbits = $bits1;
467
	else
468
		$relbits = $bits2;
469

    
470
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
471
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
472

    
473
	if ($sn1 == $sn2)
474
		return true;
475
	else
476
		return false;
477
}
478

    
479
/* compare two IP addresses */
480
function ipcmp($a, $b) {
481
	if (ip2long($a) < ip2long($b))
482
		return -1;
483
	else if (ip2long($a) > ip2long($b))
484
		return 1;
485
	else
486
		return 0;
487
}
488

    
489
/* return true if $addr is in $subnet, false if not */
490
function ip_in_subnet($addr,$subnet) {
491
	list($ip, $mask) = explode('/', $subnet);
492
	$mask = 0xffffffff << (32 - $mask);
493
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
494
}
495

    
496
/* verify (and remove) the digital signature on a file - returns 0 if OK */
497
function verify_digital_signature($fname) {
498

    
499
	global $g;
500

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

    
503
}
504

    
505
/* obtain MAC address given an IP address by looking at the ARP table */
506
function arp_get_mac_by_ip($ip) {
507
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
508
	$arpoutput = "";
509
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
510

    
511
	if ($arpoutput[0]) {
512
		$arpi = explode(" ", $arpoutput[0]);
513
		$macaddr = $arpi[3];
514
		if (is_macaddr($macaddr))
515
			return $macaddr;
516
		else
517
			return false;
518
	}
519

    
520
	return false;
521
}
522

    
523
/* return a fieldname that is safe for xml usage */
524
function xml_safe_fieldname($fieldname) {
525
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
526
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
527
			 ':', ',', '.', '\'', '\\'
528
		);
529
	return strtolower(str_replace($replace, "", $fieldname));
530
}
531

    
532
function mac_format($clientmac) {
533
    $mac =explode(":", $clientmac);
534

    
535
    global $config;
536

    
537
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
538

    
539
    switch($mac_format) {
540

    
541
        case 'singledash':
542
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
543

    
544
        case 'ietf':
545
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
546

    
547
        case 'cisco':
548
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
549

    
550
        case 'unformatted':
551
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
552

    
553
        default:
554
        return $clientmac;
555
    }
556
}
557

    
558
function resolve_retry($hostname, $retries = 5) {
559

    
560
       if (is_ipaddr($hostname))
561
               return $hostname;
562

    
563
       for ($i = 0; $i < $retries; $i++) {
564
               $ip = gethostbyname($hostname);
565

    
566
               if ($ip && $ip != $hostname) {
567
                       /* success */
568
                       return $ip;
569
               }
570

    
571
               sleep(1);
572
       }
573

    
574
       return false;
575
}
576

    
577
?>
(23-23/29)