Project

General

Profile

Download (13.4 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2 307cd525 Bill Marquette
/* $Id$ */
3 5b237745 Scott Ullrich
/*
4
	util.inc
5
	part of m0n0wall (http://m0n0.ch/wall)
6 98bbf05a Scott Ullrich
7 5b237745 Scott Ullrich
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9 98bbf05a Scott Ullrich
10 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12 98bbf05a Scott Ullrich
13 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15 98bbf05a Scott Ullrich
16 5b237745 Scott Ullrich
	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 98bbf05a Scott Ullrich
20 5b237745 Scott Ullrich
	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 9d59c08f Scott Ullrich
		$pid = trim(file_get_contents($pidfile));
41 d7a6517a Scott Ullrich
		mwexec("/bin/kill -s $sig {$pid}");
42
	} else {
43
		mwexec("/bin/kill -s $sig {$pidfile}");
44 5b237745 Scott Ullrich
	}
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 98bbf05a Scott Ullrich
57 5b237745 Scott Ullrich
	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 98bbf05a Scott Ullrich
65 5b237745 Scott Ullrich
	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 98bbf05a Scott Ullrich
92 5b237745 Scott Ullrich
	$ip_long = ip2long($ipaddr);
93
	$ip_reverse = long2ip($ip_long);
94 98bbf05a Scott Ullrich
95 5b237745 Scott Ullrich
	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 3154d7ed Colin Smith
104 5b64aa38 Scott Ullrich
	global $aliastable, $config;
105
106 07168cc3 Bill Marquette
	if(is_array($config['aliases']['alias'])) {
107 55e0e4e5 Scott Ullrich
		foreach($config['aliases']['alias'] as $alias) {
108
			if($alias['name'] == $ipaddr)
109
				return true;
110
		}
111 8dbd4c3a Scott Ullrich
	}
112 98bbf05a Scott Ullrich
113 5b237745 Scott Ullrich
	if (isset($aliastable[$ipaddr]) && is_ipaddr($aliastable[$ipaddr]))
114
		return true;
115
	else
116
		return is_ipaddr($ipaddr);
117 b8014f9d Scott Ullrich
118 5b237745 Scott Ullrich
}
119
120
/* returns true if $ipaddr is a valid dotted IPv4 address or any alias */
121
function is_ipaddroranyalias($ipaddr) {
122 98bbf05a Scott Ullrich
123 5b237745 Scott Ullrich
	global $aliastable;
124 98bbf05a Scott Ullrich
125 5b237745 Scott Ullrich
	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 98bbf05a Scott Ullrich
136 5b237745 Scott Ullrich
	list($hp,$np) = explode('/', $subnet);
137 98bbf05a Scott Ullrich
138 5b237745 Scott Ullrich
	if (!is_ipaddr($hp))
139
		return false;
140 98bbf05a Scott Ullrich
141 5b237745 Scott Ullrich
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
142
		return false;
143 98bbf05a Scott Ullrich
144 5b237745 Scott Ullrich
	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 98bbf05a Scott Ullrich
150 5b237745 Scott Ullrich
	global $aliastable;
151 98bbf05a Scott Ullrich
152 5b237745 Scott Ullrich
	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 98bbf05a Scott Ullrich
163 161a01bd Scott Ullrich
	if (preg_match("/^([_a-z0-9\-]+\.?)+$/i", $hostname))
164 5b237745 Scott Ullrich
		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 98bbf05a Scott Ullrich
174 856887a3 Scott Ullrich
	if (preg_match("/^([a-z0-9\-]+\.?)+$/i", $domain))
175 5b237745 Scott Ullrich
		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 98bbf05a Scott Ullrich
185 5b237745 Scott Ullrich
	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 98bbf05a Scott Ullrich
196 5b237745 Scott Ullrich
	$maca = explode(":", $macaddr);
197
	if (count($maca) != 6)
198
		return false;
199 98bbf05a Scott Ullrich
200 5b237745 Scott Ullrich
	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 98bbf05a Scott Ullrich
207 5b237745 Scott Ullrich
	return true;
208
}
209
210 3caa8aa1 Bill Marquette
/* returns true if $name is a valid name for an alias */
211 9499c2d2 Bill Marquette
/* returns NULL if a reserved word is used */
212 5b237745 Scott Ullrich
function is_validaliasname($name) {
213 beeef1f0 Bill Marquette
	/* Array of reserved words */
214 0c2badde Colin Smith
	$reserved = array("port", "pass");
215
	if (in_array($name, $reserved, true))
216 9499c2d2 Bill Marquette
		return; /* return NULL */
217 beeef1f0 Bill Marquette
218 b7cb6042 Scott Ullrich
	if (!preg_match("/[^a-zA-Z0-9\-_]/", $name))
219 5b237745 Scott Ullrich
		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 98bbf05a Scott Ullrich
229 5b237745 Scott Ullrich
	if (($port < 1) || ($port > 65535))
230
		return false;
231
	else
232
		return true;
233
}
234
235 5a1eebc7 Scott Ullrich
/* 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 b8014f9d Scott Ullrich
/* returns true if $val is a valid shaper bandwidth value */
246
function is_valid_shaperbw($val) {
247
	return (preg_match("/^[0-9]+(Kb|Mb|Gb|%)$/", $val));
248
}
249
250 3154d7ed Colin Smith
/*
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 20203646 Colin Smith
 *			status (much slower)
257 3154d7ed Colin Smith
 */
258 36f546e9 Scott Ullrich
/*
259
 *   get_interface_list() - Return a list of all physical interfaces
260
 *   along with MAC and status.
261
 *
262
 *   $mode = "active" - use ifconfig -lu
263
 *           "media"  - use ifconfig to check physical connection
264
 *			status (much slower)
265
 */
266
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
267 37327d23 Scott Ullrich
	global $config;
268 65bed2d2 Scott Ullrich
	$upints = array();
269 37327d23 Scott Ullrich
	/* get a list of virtual interface types */
270
	if(!$vfaces) {
271 8b1f5806 Scott Ullrich
		$vfaces = array (
272
				'bridge',
273
				'ppp',
274
				'sl',
275
				'gif',
276
				'faith',
277
				'lo',
278
				'ng',
279
				'vlan',
280
				'pflog',
281
				'pfsync',
282
				'enc',
283
				'tun',
284
				'carp'
285
		);
286 36f546e9 Scott Ullrich
	}
287 20203646 Colin Smith
	switch($mode) {
288
	case "active":
289
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
290
        	break;
291
	case "media":
292
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
293 767a716e Scott Ullrich
                $ifconfig = "";
294 20203646 Colin Smith
                exec("/sbin/ifconfig -a", $ifconfig);
295
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
296
                $ifstatus = preg_grep('/status:/', $ifconfig);
297 49149b86 Colin Smith
		foreach($ifstatus as $status) {
298 bb3b9159 Colin Smith
			$int = array_shift($intlist);
299
                	if(stristr($status, "active")) $upints[] = $int;
300 49149b86 Colin Smith
		}
301 20203646 Colin Smith
		break;
302
	}
303
        /* build interface list with netstat */
304 767a716e Scott Ullrich
        $linkinfo = "";
305 89d1f0f2 Scott Ullrich
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
306 20203646 Colin Smith
        array_shift($linkinfo);
307 89d1f0f2 Scott Ullrich
	/* build ip address list with netstat */
308 767a716e Scott Ullrich
	$ipinfo = "";
309 89d1f0f2 Scott Ullrich
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
310
	array_shift($ipinfo);
311
	foreach($linkinfo as $link) {
312
		$friendly = "";
313 20203646 Colin Smith
                $alink = explode(" ", $link);
314
                $ifname = rtrim(trim($alink[0]), '*');
315 36f546e9 Scott Ullrich
                /* trim out all numbers before checking for vfaces */
316
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces)) {
317 20203646 Colin Smith
			$toput = array(
318
					"mac" => trim($alink[1]),
319
					"up" => in_array($ifname, $upints)
320
				);
321 89d1f0f2 Scott Ullrich
			foreach($ipinfo as $ip) {
322
				$aip = explode(" ", $ip);
323
				if($aip[0] == $ifname) {
324
					$toput['ipaddr'] = $aip[1];
325
				}
326
			}
327 20203646 Colin Smith
			foreach($config['interfaces'] as $name => $int) {
328
				if($int['if'] == $ifname) $friendly = $name;
329
			}
330
			switch($keyby) {
331
			case "physical":
332 89d1f0f2 Scott Ullrich
				if($friendly != "") {
333
					$toput['friendly'] = $friendly;
334
				}
335 20203646 Colin Smith
				$iflist[$ifname] = $toput;
336 3154d7ed Colin Smith
				break;
337 20203646 Colin Smith
			case "friendly":
338 89d1f0f2 Scott Ullrich
				if($friendly != "") {
339
					$toput['if'] = $ifname;
340
					$iflist[$friendly] = $toput;
341
				}
342 3154d7ed Colin Smith
				break;
343
			}
344 20203646 Colin Smith
                }
345
        }
346
        return $iflist;
347 5b237745 Scott Ullrich
}
348
349
/* wrapper for exec() */
350
function mwexec($command) {
351
352
	global $g;
353 767a716e Scott Ullrich
	$oarr = "";
354
	$retval = "";
355 5b237745 Scott Ullrich
	if ($g['debug']) {
356
		if (!$_SERVER['REMOTE_ADDR'])
357
			echo "mwexec(): $command\n";
358 c9847bc4 Scott Ullrich
		exec("$command > /dev/null 2>&1", $oarr, $retval);
359 5b237745 Scott Ullrich
	} else {
360
		exec("$command > /dev/null 2>&1", $oarr, $retval);
361
	}
362 98bbf05a Scott Ullrich
363
	return $retval;
364 5b237745 Scott Ullrich
}
365
366
/* wrapper for exec() in background */
367
function mwexec_bg($command) {
368
369
	global $g;
370 98bbf05a Scott Ullrich
371 5b237745 Scott Ullrich
	if ($g['debug']) {
372
		if (!$_SERVER['REMOTE_ADDR'])
373
			echo "mwexec(): $command\n";
374
	}
375 98bbf05a Scott Ullrich
376 5b237745 Scott Ullrich
	exec("nohup $command > /dev/null 2>&1 &");
377
}
378
379
/* unlink a file, if it exists */
380
function unlink_if_exists($fn) {
381 336cb718 Scott Ullrich
	$to_do = glob($fn);
382 3b378be5 Scott Ullrich
	if(is_array($to_do)) {
383 336cb718 Scott Ullrich
		foreach($to_do as $filename)
384 9ff926a2 Colin Smith
			@unlink($filename);
385 336cb718 Scott Ullrich
	} else {
386 9ff926a2 Colin Smith
		@unlink($fn);
387 336cb718 Scott Ullrich
	}
388 5b237745 Scott Ullrich
}
389
/* make a global alias table (for faster lookups) */
390 918a884d Bill Marquette
function alias_make_table($config) {
391 98bbf05a Scott Ullrich
392 918a884d Bill Marquette
	global $aliastable;
393 98bbf05a Scott Ullrich
394 5b237745 Scott Ullrich
	$aliastable = array();
395 98bbf05a Scott Ullrich
396 5b237745 Scott Ullrich
	if (is_array($config['aliases']['alias'])) {
397
		foreach ($config['aliases']['alias'] as $alias) {
398
			if ($alias['name'])
399
				$aliastable[$alias['name']] = $alias['address'];
400
		}
401
	}
402
}
403
/* check if an alias exists */
404
function is_alias($name) {
405 98bbf05a Scott Ullrich
406 5b237745 Scott Ullrich
	global $aliastable;
407 98bbf05a Scott Ullrich
408 5b237745 Scott Ullrich
	return isset($aliastable[$name]);
409 b8014f9d Scott Ullrich
}
410 27ff8a3c Scott Ullrich
411
function alias_expand_value($name) {
412
413
	global $aliastable, $config;
414 800e9138 Scott Ullrich
	if($config['aliases']['alias'])
415
		foreach($config['aliases']['alias'] as $alias) {
416
			if($alias['name'] == $name)
417
				return $alias['address'];
418
		}
419 27ff8a3c Scott Ullrich
420 5b237745 Scott Ullrich
}
421
422
/* expand a host or network alias, if necessary */
423
function alias_expand($name) {
424 98bbf05a Scott Ullrich
425 5b237745 Scott Ullrich
	global $aliastable;
426 98bbf05a Scott Ullrich
427 5b237745 Scott Ullrich
	if (isset($aliastable[$name]))
428 4335dc87 Bill Marquette
		return "\${$name}";
429 5b237745 Scott Ullrich
	else if (is_ipaddr($name) || is_subnet($name))
430 57989da5 Scott Ullrich
		return "{$name}";
431 5b237745 Scott Ullrich
	else
432
		return null;
433
}
434
435
/* expand a host alias, if necessary */
436
function alias_expand_host($name) {
437
	global $aliastable;
438 98bbf05a Scott Ullrich
439 9b00dc26 Bill Marquette
	if (isset($aliastable[$name])) {
440
		$ip_arr = explode(" ", $aliastable[$name]);
441
		foreach($ip_arr as $ip) {
442
			if (!is_ipaddr($ip))
443
				return null;
444
		}
445 5b237745 Scott Ullrich
		return $aliastable[$name];
446 9b00dc26 Bill Marquette
	} else if (is_ipaddr($name))
447 5b237745 Scott Ullrich
		return $name;
448
	else
449
		return null;
450
}
451
452
/* expand a network alias, if necessary */
453
function alias_expand_net($name) {
454 98bbf05a Scott Ullrich
455 5b237745 Scott Ullrich
	global $aliastable;
456 98bbf05a Scott Ullrich
457 5b237745 Scott Ullrich
	if (isset($aliastable[$name]) && is_subnet($aliastable[$name]))
458
		return $aliastable[$name];
459
	else if (is_subnet($name))
460
		return $name;
461
	else
462
		return null;
463
}
464
465
/* find out whether two subnets overlap */
466
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
467
468
	if (!is_numeric($bits1))
469
		$bits1 = 32;
470
	if (!is_numeric($bits2))
471
		$bits2 = 32;
472
473
	if ($bits1 < $bits2)
474
		$relbits = $bits1;
475
	else
476
		$relbits = $bits2;
477 98bbf05a Scott Ullrich
478 5b237745 Scott Ullrich
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
479
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
480 98bbf05a Scott Ullrich
481 5b237745 Scott Ullrich
	if ($sn1 == $sn2)
482
		return true;
483
	else
484
		return false;
485
}
486
487
/* compare two IP addresses */
488
function ipcmp($a, $b) {
489
	if (ip2long($a) < ip2long($b))
490
		return -1;
491
	else if (ip2long($a) > ip2long($b))
492
		return 1;
493
	else
494
		return 0;
495
}
496
497
/* return true if $addr is in $subnet, false if not */
498
function ip_in_subnet($addr,$subnet) {
499
	list($ip, $mask) = explode('/', $subnet);
500
	$mask = 0xffffffff << (32 - $mask);
501
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
502
}
503
504
/* verify (and remove) the digital signature on a file - returns 0 if OK */
505
function verify_digital_signature($fname) {
506
507
	global $g;
508
509 f024f52d Scott Ullrich
	return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname));
510
511 5b237745 Scott Ullrich
}
512
513
/* obtain MAC address given an IP address by looking at the ARP table */
514
function arp_get_mac_by_ip($ip) {
515 08443c7a Chris Dionissopoulos
	mwexec("/sbin/ping -c 1 -t 1 {$ip}");
516 767a716e Scott Ullrich
	$arpoutput = "";
517 5b237745 Scott Ullrich
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
518 98bbf05a Scott Ullrich
519 5b237745 Scott Ullrich
	if ($arpoutput[0]) {
520
		$arpi = explode(" ", $arpoutput[0]);
521
		$macaddr = $arpi[3];
522
		if (is_macaddr($macaddr))
523
			return $macaddr;
524
		else
525
			return false;
526
	}
527 98bbf05a Scott Ullrich
528 5b237745 Scott Ullrich
	return false;
529
}
530
531 98bbf05a Scott Ullrich
/* return a fieldname that is safe for xml usage */
532
function xml_safe_fieldname($fieldname) {
533 ddce8ef2 Colin Smith
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
534 9ef924eb Colin Smith
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
535 ddce8ef2 Colin Smith
			 ':', ',', '.', '\'', '\\'
536
		);
537
	return strtolower(str_replace($replace, "", $fieldname));
538 98bbf05a Scott Ullrich
}
539
540 4129df39 Scott Ullrich
function mac_format($clientmac) {
541
    $mac =explode(":", $clientmac);
542
543
    global $config;
544
545
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
546
547
    switch($mac_format) {
548
549
        case 'singledash':
550
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
551
552
        case 'ietf':
553
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
554
555
        case 'cisco':
556
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
557
558
        case 'unformatted':
559
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
560
561
        default:
562
        return $clientmac;
563
    }
564
}
565
566 b7cb6042 Scott Ullrich
?>