Project

General

Profile

Download (28.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php 
2
/*
3
	util.inc
4
	part of the pfSense project (http://www.pfsense.com)
5

    
6
	originally part of m0n0wall (http://m0n0.ch/wall)
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
/*
33
	pfSense_BUILDER_BINARIES:	/bin/ps	/bin/kill	/usr/bin/killall	/sbin/ifconfig	/usr/bin/netstat
34
	pfSense_BUILDER_BINARIES:	/usr/bin/awk	/sbin/dmesg		/sbin/ping /usr/local/sbin/gzsig	/usr/sbin/arp
35
	pfSense_BUILDER_BINARIES:	/sbin/conscontrol	/sbin/devd	/bin/ps
36
	pfSense_MODULE:	utils
37
*/
38

    
39
/* kill a process by pid file */
40
function killbypid($pidfile) {
41
	sigkillbypid($pidfile, "TERM");
42
}
43

    
44
function isvalidpid($pid) {
45
	$running = `ps -p $pid | wc -l`;
46
	if(intval($running) > 1)
47
		return true;
48
	else 
49
		return false;
50
}
51

    
52
function is_process_running($process) {
53
        $running = (trim(shell_exec("ps axwu | grep '\b{$process}\b' | grep -v 'grep'")) != '');
54

    
55
        return $running;
56
}
57

    
58
function isvalidproc($proc) {
59
	$running = is_process_running($proc);
60
	if (intval($running) >= 1)
61
		return true;
62
	else 
63
		return false;
64
}
65

    
66
/* sigkill a process by pid file */
67
/* return 1 for success and 0 for a failure */
68
function sigkillbypid($pidfile, $sig) {
69
	if (is_file($pidfile)) {
70
		$pid = trim(file_get_contents($pidfile));
71
		if(isvalidpid($pid))
72
			return mwexec("/bin/kill -s $sig {$pid}", true);
73
	}
74
	return 0;
75
}
76

    
77
/* kill a process by name */
78
function sigkillbyname($procname, $sig) {
79
	if(isvalidproc($procname))
80
		return mwexec("/usr/bin/killall -{$sig} " . escapeshellarg($procname), true);
81
}
82

    
83
/* kill a process by name */
84
function killbyname($procname) {
85
	if(isvalidproc($procname)) 
86
		mwexec("/usr/bin/killall " . escapeshellarg($procname));
87
}
88

    
89
function is_subsystem_dirty($subsystem = "") {
90
	global $g;
91

    
92
	if ($subsystem == "")
93
		return false;
94

    
95
	if (file_exists("{$g['varrun_path']}/{$subsystem}.dirty"))
96
		return true;
97

    
98
	return false;
99
}
100

    
101
function mark_subsystem_dirty($subsystem = "") {
102
	global $g;
103

    
104
	if (!file_put_contents("{$g['varrun_path']}/{$subsystem}.dirty", "DIRTY"))
105
		log_error("WARNING: Could not mark subsystem: {$subsytem} dirty");
106
}
107

    
108
function clear_subsystem_dirty($subsystem = "") {
109
	global $g;
110

    
111
	@unlink("{$g['varrun_path']}/{$subsystem}.dirty");
112
}
113

    
114
function config_lock() {
115
	return;
116
}
117
function config_unlock() {
118
	return;
119
}
120

    
121
/* lock configuration file */
122
function lock($lock) {
123
	global $g, $cfglckkeyconsumers;
124
	if (!$lock)
125
		die("WARNING: You must give a name as parameter to lock() function.");
126
	if (!file_exists("{$g['tmp_path']}/{$lock}.lock"))
127
		@touch("{$g['tmp_path']}/{$lock}.lock");
128
	$cfglckkeyconsumers++;
129
	if ($fp = fopen("{$g['tmp_path']}/{$lock}.lock", "w+")) {
130
		if (flock($fp, LOCK_EX))
131
			return $fp;
132
		else
133
			fclose($fp);
134
	}
135
}
136

    
137
/* unlock configuration file */
138
function unlock($cfglckkey = 0) {
139
	global $g, $cfglckkeyconsumers;
140
	flock($cfglckkey, LOCK_UN);
141
	fclose($cfglckkey);
142
	return;
143
}
144

    
145
function is_module_loaded($module_name) {
146
	$running = `/sbin/kldstat | grep {$module_name} | /usr/bin/grep -v grep | /usr/bin/wc -l`;
147
	if (intval($running) >= 1)
148
		return true;
149
	else
150
		return false;
151
}
152

    
153
/* return the subnet address given a host address and a subnet bit count */
154
function gen_subnet($ipaddr, $bits) {
155
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
156
		return "";
157

    
158
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
159
}
160

    
161
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
162
function gen_subnet_max($ipaddr, $bits) {
163
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
164
		return "";
165

    
166
	return long2ip(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
167
}
168

    
169
/* returns a subnet mask (long given a bit count) */
170
function gen_subnet_mask_long($bits) {
171
	$sm = 0;
172
	for ($i = 0; $i < $bits; $i++) {
173
		$sm >>= 1;
174
		$sm |= 0x80000000;
175
	}
176
	return $sm;
177
}
178

    
179
/* same as above but returns a string */
180
function gen_subnet_mask($bits) {
181
	return long2ip(gen_subnet_mask_long($bits));
182
}
183

    
184
function is_numericint($arg) {
185
	return (preg_match("/[^0-9]/", $arg) ? false : true);
186
}
187

    
188
/* returns true if $ipaddr is a valid dotted IPv4 address */
189
function is_ipaddr($ipaddr) {
190
	if (!is_string($ipaddr))
191
		return false;
192

    
193
	$ip_long = ip2long($ipaddr);
194
	$ip_reverse = long2ip($ip_long);
195

    
196
	if ($ipaddr == $ip_reverse)
197
		return true;
198
	else
199
		return false;
200
}
201

    
202
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
203
function is_ipaddroralias($ipaddr) {
204
	global $config;
205

    
206
	if (is_alias($ipaddr)) {
207
		if (is_array($config['aliases']['alias'])) {
208
			foreach ($config['aliases']['alias'] as $alias) {
209
                        	if ($alias['name'] == $ipaddr && $alias['type'] != "port")
210
					return true;
211
			}
212
                }
213
		return false;
214
	} else
215
		return is_ipaddr($ipaddr);
216

    
217
}
218

    
219
/* returns true if $subnet is a valid subnet in CIDR format */
220
function is_subnet($subnet) {
221
	if (!is_string($subnet))
222
		return false;
223

    
224
	list($hp,$np) = explode('/', $subnet);
225

    
226
	if (!is_ipaddr($hp))
227
		return false;
228

    
229
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
230
		return false;
231

    
232
	return true;
233
}
234

    
235
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
236
function is_subnetoralias($subnet) {
237

    
238
	global $aliastable;
239

    
240
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
241
		return true;
242
	else
243
		return is_subnet($subnet);
244
}
245

    
246
/* returns true if $hostname is a valid hostname */
247
function is_hostname($hostname) {
248
	if (!is_string($hostname))
249
		return false;
250

    
251
	if (preg_match("/^([_a-z0-9\-]+\.?)+$/i", $hostname))
252
		return true;
253
	else
254
		return false;
255
}
256

    
257
/* returns true if $domain is a valid domain name */
258
function is_domain($domain) {
259
	if (!is_string($domain))
260
		return false;
261

    
262
	if (preg_match("/^([a-z0-9\-]+\.?)+$/i", $domain))
263
		return true;
264
	else
265
		return false;
266
}
267

    
268
/* returns true if $macaddr is a valid MAC address */
269
function is_macaddr($macaddr) {
270
	if (!is_string($macaddr))
271
		return false;
272

    
273
	$maca = explode(":", $macaddr);
274
	if (count($maca) != 6)
275
		return false;
276

    
277
	foreach ($maca as $macel) {
278
		if (($macel === "") || (strlen($macel) > 2))
279
			return false;
280
		if (preg_match("/[^0-9a-f]/i", $macel))
281
			return false;
282
	}
283

    
284
	return true;
285
}
286

    
287
/* returns true if $name is a valid name for an alias */
288
/* returns NULL if a reserved word is used */
289
function is_validaliasname($name) {
290
	/* Array of reserved words */
291
	$reserved = array("port", "pass");
292
	if (in_array($name, $reserved, true))
293
		return; /* return NULL */
294

    
295
	if (!preg_match("/[^a-zA-Z0-9_]/", $name))
296
		return true;
297
	else
298
		return false;
299
}
300

    
301
/* returns true if $port is a valid TCP/UDP port */
302
function is_port($port) {
303
	if ((intval($port) < 1) || (intval($port) > 65535))
304
		return false;
305
	else
306
		return true;
307
}
308

    
309
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
310
function is_portrange($portrange) {
311
        $ports = explode(":", $portrange);
312

    
313
        if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
314
                return true;
315
        else
316
                return false;
317
}
318

    
319
/* returns true if $port is a valid port number or an alias thereof */
320
function is_portoralias($port) {
321
	global $config;
322

    
323
        if (is_alias($port)) {
324
                if (is_array($config['aliases']['alias'])) {
325
                        foreach ($config['aliases']['alias'] as $alias) {
326
                                if ($alias['name'] == $port && $alias['type'] == "port")
327
                                        return true;
328
                        }
329
                }
330
                return false;
331
        } else
332
                return is_port($port);
333
}
334

    
335
/* returns true if $val is a valid shaper bandwidth value */
336
function is_valid_shaperbw($val) {
337
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
338
}
339

    
340
/* return the configured carp interface list */
341
function get_configured_carp_interface_list() {
342
	global $config;
343

    
344
	$iflist = array();
345

    
346
	if(is_array($config['virtualip']['vip'])) {
347
                $viparr = &$config['virtualip']['vip'];
348
                foreach ($viparr as $vip) {
349
                        switch ($vip['mode']) {
350
                        case "carp":
351
                        case "carpdev-dhcp":
352
				$vipif = "vip" . $vip['vhid'];
353
                        	$iflist[$vipif] = $vip['subnet'];
354
                                break;
355
                        }
356
                }
357
        }
358

    
359
	return $iflist;
360
}
361

    
362
/* return the configured interfaces list. */
363
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
364
	global $config;
365

    
366
	$iflist = array();
367

    
368
	if (!$only_opt) {
369
		if (isset($config['interfaces']['wan']))
370
			$iflist['wan'] = "wan";
371
		if (isset($config['interfaces']['lan']))
372
			$iflist['lan'] = "lan";
373
	}
374

    
375
	/* if list */
376
        foreach($config['interfaces'] as $if => $ifdetail) {
377
		if ($if == "wan" || $if == "lan")
378
			continue;
379
		if (isset($ifdetail['enable']) || $withdisabled == true)
380
			$iflist[$if] = $if;
381
	}
382

    
383
	return $iflist;
384
}
385

    
386
/* return the configured interfaces list. */
387
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
388
        global $config;
389

    
390
        $iflist = array();
391

    
392
        if (!$only_opt) {
393
                if (isset($config['interfaces']['wan'])) {
394
			$tmpif = get_real_interface("wan");
395
			if (!empty($tmpif))
396
				$iflist[$tmpif] = "wan";
397
		}
398
                if (isset($config['interfaces']['lan'])) {
399
			$tmpif = get_real_interface("lan");
400
			if (!empty($tmpif))
401
				$iflist[$tmpif] = "lan";
402
		}
403
        }
404

    
405
        /* if list */
406
        foreach($config['interfaces'] as $if => $ifdetail) {
407
                if ($if == "wan" || $if == "lan")
408
                        continue;
409
                if (isset($ifdetail['enable']) || $withdisabled == true) {
410
			$tmpif = get_real_interface($if);
411
			if (!empty($tmpif))
412
				$iflist[$tmpif] = $if;
413
		}
414
        }
415

    
416
        return $iflist;
417
}
418

    
419
/* return the configured interfaces list with their description. */
420
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
421
	global $config;
422

    
423
	$iflist = array();
424

    
425
	if (!$only_opt) {
426
		if (isset($config['interfaces']['wan'])) {
427
			if (empty($config['interfaces']['wan']['descr']))
428
				$iflist['wan'] = "WAN";
429
			else
430
				$iflist['wan'] = strtoupper($config['interfaces']['wan']['descr']);
431
		}
432
		if (isset($config['interfaces']['lan'])) {
433
			if (empty($config['interfaces']['lan']['descr']))
434
				$iflist['lan'] = "LAN";
435
			else
436
				$iflist['lan'] = strtoupper($config['interfaces']['lan']['descr']);
437
		}
438
	}
439

    
440
	/* if list */
441
	foreach($config['interfaces'] as $if => $ifdetail) {
442
		if (isset($ifdetail['enable']) || $withdisabled == true) {
443
			if($ifdetail['descr'] == "")
444
				$iflist[$if] = strtoupper($if);
445
			else
446
				$iflist[$if] = strtoupper($ifdetail['descr']);
447
		}
448
	}
449

    
450
	return $iflist;
451
}
452

    
453

    
454
/*
455
 *   get_interface_list() - Return a list of all physical interfaces
456
 *   along with MAC and status.
457
 *
458
 *   $mode = "active" - use ifconfig -lu
459
 *           "media"  - use ifconfig to check physical connection
460
 *			status (much slower)
461
 */
462
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
463
        global $config;
464
	$upints = array();
465
        /* get a list of virtual interface types */
466
        if(!$vfaces) {
467
		$vfaces = array (
468
				'bridge',
469
				'ppp',
470
				'sl',
471
				'gif',
472
				'gre',
473
				'faith',
474
				'lo',
475
				'ng',
476
				'vlan',
477
				'pflog',
478
				'plip',
479
				'pfsync',
480
				'enc',
481
				'tun',
482
				'carp',
483
				'lagg',
484
				'vip'
485
		);
486
	}
487
	switch($mode) {
488
	case "active":
489
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
490
        	break;
491
	case "media":
492
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
493
                $ifconfig = "";
494
                exec("/sbin/ifconfig -a", $ifconfig);
495
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
496
                $ifstatus = preg_grep('/status:/', $ifconfig);
497
		foreach($ifstatus as $status) {
498
			$int = array_shift($intlist);
499
                	if(stristr($status, "active")) $upints[] = $int;
500
		}
501
		break;
502
	}
503
        /* build interface list with netstat */
504
        $linkinfo = "";
505
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
506
        array_shift($linkinfo);
507
	/* build ip address list with netstat */
508
	$ipinfo = "";
509
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
510
	array_shift($ipinfo);
511
	foreach($linkinfo as $link) {
512
		$friendly = "";
513
                $alink = explode(" ", $link);
514
                $ifname = rtrim(trim($alink[0]), '*');
515
                /* trim out all numbers before checking for vfaces */
516
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces) &&
517
			!stristr($ifname, "_vl")) {
518
			$toput = array(
519
					"mac" => trim($alink[1]),
520
					"up" => in_array($ifname, $upints)
521
				);
522
			foreach($ipinfo as $ip) {
523
				$aip = explode(" ", $ip);
524
				if($aip[0] == $ifname) {
525
					$toput['ipaddr'] = $aip[1];
526
				}
527
			}
528
			foreach($config['interfaces'] as $name => $int) {
529
				if($int['if'] == $ifname) $friendly = $name;
530
			}
531
			switch($keyby) {
532
			case "physical":
533
				if($friendly != "") {
534
					$toput['friendly'] = $friendly;
535
				}
536
				$dmesg_arr = array();
537
				exec("/sbin/dmesg |grep $ifname | head -n1", $dmesg_arr);
538
				preg_match_all("/<(.*?)>/i", $dmesg_arr[0], $dmesg);
539
				$toput['dmesg'] = $dmesg[1][0];
540
				$iflist[$ifname] = $toput;
541
				break;
542
			case "ppp":
543
				
544
			case "friendly":
545
				if($friendly != "") {
546
					$toput['if'] = $ifname;
547
					$iflist[$friendly] = $toput;
548
				}
549
				break;
550
			}
551
                }
552
        }
553
        return $iflist;
554
}
555

    
556
/****f* util/log_error
557
* NAME
558
*   log_error  - Sends a string to syslog.
559
* INPUTS
560
*   $error     - string containing the syslog message.
561
* RESULT
562
*   null
563
******/
564
function log_error($error) {
565
        global $g;
566
        $page = $_SERVER['SCRIPT_NAME'];
567
        syslog(LOG_WARNING, "$page: $error");
568
        if ($g['debug'])
569
                syslog(LOG_WARNING, var_dump(debug_backtrace()));
570
        return;
571
}
572

    
573
/****f* util/exec_command
574
 * NAME
575
 *   exec_command - Execute a command and return a string of the result.
576
 * INPUTS
577
 *   $command   - String of the command to be executed.
578
 * RESULT
579
 *   String containing the command's result.
580
 * NOTES
581
 *   This function returns the command's stdout and stderr.
582
 ******/
583
function exec_command($command) {
584
        $output = array();
585
        exec($command . ' 2>&1 ', $output);
586
        return(implode("\n", $output));
587
}
588

    
589
/* wrapper for exec() */
590
function mwexec($command, $mute = false) {
591

    
592
	global $g;
593
	$oarr = array();
594
	$retval = 0;
595
	if ($g['debug']) {
596
		if (!$_SERVER['REMOTE_ADDR'])
597
			echo "mwexec(): $command\n";
598
		exec("$command 2>&1", $oarr, $retval);
599
	} else {
600
		exec("$command 2>&1", $oarr, $retval);
601
	}
602
	if(isset($config['system']['developerspew']))
603
                $mute = false;
604
	if(($retval <> 0) && ($mute === false)) {
605
		$output = implode(" ", $oarr);
606
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
607
	}
608
	return $retval;
609
}
610

    
611
/* wrapper for exec() in background */
612
function mwexec_bg($command) {
613

    
614
	global $g;
615

    
616
	if ($g['debug']) {
617
		if (!$_SERVER['REMOTE_ADDR'])
618
			echo "mwexec(): $command\n";
619
	}
620

    
621
	exec("nohup $command > /dev/null 2>&1 &");
622
}
623

    
624
/* unlink a file, if it exists */
625
function unlink_if_exists($fn) {
626
	$to_do = glob($fn);
627
	if(is_array($to_do)) {
628
		foreach($to_do as $filename)
629
			@unlink($filename);
630
	} else {
631
		@unlink($fn);
632
	}
633
}
634
/* make a global alias table (for faster lookups) */
635
function alias_make_table($config) {
636

    
637
	global $aliastable;
638

    
639
	$aliastable = array();
640

    
641
	if (is_array($config['aliases']['alias'])) {
642
		foreach ($config['aliases']['alias'] as $alias) {
643
			if ($alias['name'])
644
				$aliastable[$alias['name']] = $alias['address'];
645
		}
646
	}
647
}
648
/* check if an alias exists */
649
function is_alias($name) {
650

    
651
	global $aliastable;
652

    
653
	return isset($aliastable[$name]);
654
}
655

    
656
/* expand a host or network alias, if necessary */
657
function alias_expand($name) {
658

    
659
	global $aliastable;
660

    
661
	if (isset($aliastable[$name]))
662
		return "\${$name}";
663
	else if (is_ipaddr($name) || is_subnet($name))
664
		return "{$name}";
665
	else
666
		return null;
667
}
668

    
669
/* find out whether two subnets overlap */
670
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
671

    
672
	if (!is_numeric($bits1))
673
		$bits1 = 32;
674
	if (!is_numeric($bits2))
675
		$bits2 = 32;
676

    
677
	if ($bits1 < $bits2)
678
		$relbits = $bits1;
679
	else
680
		$relbits = $bits2;
681

    
682
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
683
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
684

    
685
	if ($sn1 == $sn2)
686
		return true;
687
	else
688
		return false;
689
}
690

    
691
/* compare two IP addresses */
692
function ipcmp($a, $b) {
693
	if (ip2long($a) < ip2long($b))
694
		return -1;
695
	else if (ip2long($a) > ip2long($b))
696
		return 1;
697
	else
698
		return 0;
699
}
700

    
701
/* return true if $addr is in $subnet, false if not */
702
function ip_in_subnet($addr,$subnet) {
703
	list($ip, $mask) = explode('/', $subnet);
704
	$mask = 0xffffffff << (32 - $mask);
705
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
706
}
707

    
708
/* verify (and remove) the digital signature on a file - returns 0 if OK */
709
function verify_digital_signature($fname) {
710

    
711
	global $g;
712

    
713
	if(!file_exists("/usr/local/sbin/gzsig"))
714
		return 1;
715

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

    
719
/* obtain MAC address given an IP address by looking at the ARP table */
720
function arp_get_mac_by_ip($ip) {
721
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
722
	$arpoutput = "";
723
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
724

    
725
	if ($arpoutput[0]) {
726
		$arpi = explode(" ", $arpoutput[0]);
727
		$macaddr = $arpi[3];
728
		if (is_macaddr($macaddr))
729
			return $macaddr;
730
		else
731
			return false;
732
	}
733

    
734
	return false;
735
}
736

    
737
/* return a fieldname that is safe for xml usage */
738
function xml_safe_fieldname($fieldname) {
739
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
740
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
741
			 ':', ',', '.', '\'', '\\'
742
		);
743
	return strtolower(str_replace($replace, "", $fieldname));
744
}
745

    
746
function mac_format($clientmac) {
747
    $mac =explode(":", $clientmac);
748

    
749
    global $config;
750

    
751
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
752

    
753
    switch($mac_format) {
754

    
755
        case 'singledash':
756
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
757

    
758
        case 'ietf':
759
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
760

    
761
        case 'cisco':
762
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
763

    
764
        case 'unformatted':
765
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
766

    
767
        default:
768
        return $clientmac;
769
    }
770
}
771

    
772
function resolve_retry($hostname, $retries = 5) {
773

    
774
       if (is_ipaddr($hostname))
775
               return $hostname;
776

    
777
       for ($i = 0; $i < $retries; $i++) {
778
               $ip = gethostbyname($hostname);
779

    
780
               if ($ip && $ip != $hostname) {
781
                       /* success */
782
                       return $ip;
783
               }
784

    
785
               sleep(1);
786
       }
787

    
788
       return false;
789
}
790

    
791
function format_bytes($bytes) {
792
	if ($bytes >= 1073741824) {
793
		return sprintf("%.2f GB", $bytes/1073741824);
794
	} else if ($bytes >= 1048576) {
795
		return sprintf("%.2f MB", $bytes/1048576);
796
	} else if ($bytes >= 1024) {
797
		return sprintf("%.0f KB", $bytes/1024);
798
	} else {
799
		return sprintf("%d bytes", $bytes);
800
	}
801
}
802

    
803
function update_filter_reload_status($text) {
804
        global $g;
805

    
806
        file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
807
}
808

    
809
/****f* util/return_dir_as_array
810
 * NAME
811
 *   return_dir_as_array - Return a directory's contents as an array.
812
 * INPUTS
813
 *   $dir       - string containing the path to the desired directory.
814
 * RESULT
815
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
816
 ******/
817
function return_dir_as_array($dir) {
818
        $dir_array = array();
819
        if (is_dir($dir)) {
820
                if ($dh = opendir($dir)) {
821
                        while (($file = readdir($dh)) !== false) {
822
                                $canadd = 0;
823
                                if($file == ".") $canadd = 1;
824
                                if($file == "..") $canadd = 1;
825
                                if($canadd == 0)
826
                                        array_push($dir_array, $file);
827
                        }
828
                        closedir($dh);
829
                }
830
        }
831
        return $dir_array;
832
}
833

    
834
function run_plugins($directory) {
835
        global $config, $g;
836

    
837
		/* process packager manager custom rules */
838
		$files = return_dir_as_array($directory);
839
		if (is_array($files)) {
840
			foreach ($files as $file) {
841
				if (stristr($file, ".sh") == true)
842
					mwexec($directory . $file . " start");
843
				else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
844
					require_once($directory . "/" . $file);
845
			}
846
		}
847
}
848

    
849
/*
850
 *    safe_mkdir($path, $mode = 0755)
851
 *    create directory if it doesn't already exist and isn't a file!
852
 */
853
function safe_mkdir($path, $mode=0755) {
854
        global $g;
855

    
856
        if (!is_file($path) && !is_dir($path)) {
857
                return @mkdir($path, $mode);
858
        } else {
859
                return false;
860
        }
861
}
862

    
863
/*
864
 * make_dirs($path, $mode = 0755)
865
 * create directory tree recursively (mkdir -p)
866
 */
867
function make_dirs($path, $mode = 0755) {
868
        $base = '';
869
        foreach (explode('/', $path) as $dir) {
870
                $base .= "/$dir";
871
                if (!is_dir($base)) {
872
                        if (!@mkdir($base, $mode))
873
                                return false;
874
                }
875
        }
876
        return true;
877
}
878

    
879
/*
880
 *     get_memory()
881
 *     returns an array listing the amount of
882
 *     memory installed in the hardware
883
 *     [0]real and [1]available
884
 */
885
function get_memory() {
886
		$matches = "";
887
        if(file_exists("/var/log/dmesg.boot"))
888
			$mem = `cat /var/log/dmesg.boot | grep memory`;
889
		else
890
			$mem = `dmesg -a | grep memory`;			
891
		if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
892
			return array($matches[1][0], $matches[1][0]);
893
		if(!$real && !$avail) {
894
			$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
895
			$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
896
			return array(($real/1024),($avail/1024));
897
		}
898
}
899

    
900
function mute_kernel_msgs() {
901
		global $config;
902
		// Do not mute serial console.  The kernel gets very very cranky
903
		// and will start dishing you cannot control tty errors.
904
		if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
905
			return;
906
		if($config['system']['enableserial']) 
907
			return;			
908
		exec("/sbin/conscontrol mute on");
909
}
910

    
911
function unmute_kernel_msgs() {
912
		global $config;
913
		// Do not mute serial console.  The kernel gets very very cranky
914
		// and will start dishing you cannot control tty errors.
915
		if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
916
			return;
917
		exec("/sbin/conscontrol mute off");
918
}
919

    
920
function start_devd() {
921
        exec("/sbin/devd");
922
        sleep(1);
923
        if(file_exists("/tmp/rc.linkup"))
924
                unlink("/tmp/rc.linkup");
925
}
926

    
927
function is_interface_mismatch() {
928
        global $config, $g;
929

    
930
        /* XXX: Should we process only enabled interfaces?! */
931
        $do_assign = false;
932
        $i = 0;
933
        foreach ($config['interfaces'] as $ifname => $ifcfg) {
934
                if (preg_match("/^enc|^tun|^ppp|^pptp|^pppoe|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $ifcfg['if'])) {
935
                        $i++;
936
                }
937
                else if (does_interface_exist($ifcfg['if']) == false) {
938
                        $do_assign = true;
939
                } else
940
                        $i++;
941
        }
942

    
943
        if ($g['minimum_nic_count'] > $i) {
944
                file_notice("interfaces", "Minimum allowed interfaces is set to {$g['minimum_nic_count']} but system has only {$i} interfaces!", "", "System", 2);
945
                $do_assign = true;
946
        } else if (file_exists("{$g['tmp_path']}/assign_complete"))
947
                $do_assign = false;
948

    
949
        return $do_assign;
950
}
951

    
952
/* sync carp entries to other firewalls */
953
function carp_sync_client() {
954
	global $g;
955
	touch($g['tmp_path'] . "/filter_sync"); 
956
}
957

    
958
/****f* util/isAjax
959
 * NAME
960
 *   isAjax - reports if the request is driven from prototype
961
 * INPUTS
962
 *   none
963
 * RESULT
964
 *   true/false
965
 ******/
966
function isAjax() {
967
        return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
968
}
969

    
970
/****f* util/timeout
971
 * NAME
972
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
973
 * INPUTS
974
 *   optional, seconds to wait before timeout. Default 9 seconds.
975
 * RESULT
976
 *   returns 1 char of user input or null if no input.
977
 ******/
978
function timeout($timer = 9) {
979
	while(!isset($key)) {
980
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
981
		else { echo chr(8). "{$timer}"; }
982
		`/bin/stty -icanon min 0 time 25`;
983
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
984
		`/bin/stty icanon`;
985
		if ($key == '')
986
			unset($key);
987
		$timer--;
988
		if ($timer == 0)
989
			break;
990
	}
991
	return $key;	
992
}
993

    
994
/****f* util/msort
995
 * NAME
996
 *   msort - sort array
997
 * INPUTS
998
 *   $array to be sorted, field to sort by, direction of sort
999
 * RESULT
1000
 *   returns newly sorted array
1001
 ******/
1002
function msort($array, $id="id", $sort_ascending=true) {
1003
	$temp_array = array();
1004
	while(count($array)>0) {
1005
		$lowest_id = 0;
1006
		$index=0;
1007
		foreach ($array as $item) {
1008
			if (isset($item[$id])) {
1009
				if ($array[$lowest_id][$id]) {
1010
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1011
						$lowest_id = $index;
1012
					}
1013
				}
1014
			}
1015
			$index++;
1016
		}
1017
		$temp_array[] = $array[$lowest_id];
1018
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1019
	}
1020
	if ($sort_ascending) {
1021
		return $temp_array;
1022
	} else {
1023
    	return array_reverse($temp_array);
1024
	}
1025
}
1026

    
1027
/****f* util/color
1028
 * NAME
1029
 *   color - outputs a color code to the ansi terminal if supported
1030
 * INPUTS
1031
 *   color code or color name
1032
 * RESULT
1033
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1034
 ******/
1035
function color($color = "0m") {
1036
	/*
1037
		Color codes available:
1038
		 0m reset; clears all colors and styles (to white on black)
1039
		 1m bold on (see below)
1040
		 3m italics on
1041
		 4m underline on
1042
		 7m inverse on; reverses foreground & background colors
1043
		 9m strikethrough on
1044
		 22m bold off (see below)
1045
		 23m italics off
1046
		 24m underline off
1047
		 27m inverse off
1048
		 29m strikethrough off
1049
		 30m set foreground color to black
1050
		 31m set foreground color to red
1051
		 32m set foreground color to green
1052
		 33m set foreground color to yellow
1053
		 34m set foreground color to blue
1054
		 35m set foreground color to magenta (purple)
1055
		 36m set foreground color to cyan
1056
		 37m set foreground color to white
1057
		 40m  set background color to black
1058
		 41m set background color to red
1059
		 42m set background color to green
1060
		 43m set background color to yellow
1061
		 44m set background color to blue
1062
		 45m set background color to magenta (purple)
1063
		 46m set background color to cyan
1064
		 47m set background color to white
1065
		 49m set background color to default (black)
1066
	*/	
1067
	// Allow caching of TERM to 
1068
	// speedup subequence requests.
1069
	global $TERM;
1070
	if(!$TERM) 
1071
		$TERM=`/usr/bin/env | grep color`;
1072
	if(!$TERM)
1073
		$TERM=`/usr/bin/env | grep cons25`;
1074
	if($TERM) {
1075
		$ESCAPE=chr(27);
1076
		switch ($color) {
1077
			case "black":
1078
				return "{$ESCAPE}[30m"; 
1079
			case "red":
1080
				return "{$ESCAPE}[31m"; 
1081
			case "green":
1082
				return "{$ESCAPE}[32m"; 
1083
			case "yellow":
1084
				return "{$ESCAPE}[33m"; 
1085
			case "blue":
1086
				return "{$ESCAPE}[34m"; 
1087
			case "magenta":
1088
				return "{$ESCAPE}[35m"; 
1089
			case "cyan":
1090
				return "{$ESCAPE}[36m"; 
1091
			case "white":
1092
				return "{$ESCAPE}[37m"; 
1093
			case "default":
1094
				return "{$ESCAPE}[39m"; 
1095
		}
1096
		return "{$ESCAPE}[{$color}";
1097
	}
1098
}
1099

    
1100
/****f* util/is_URL
1101
 * NAME
1102
 *   is_URL
1103
 * INPUTS
1104
 *   string to check
1105
 * RESULT
1106
 *   Returns true if item is a URL
1107
 ******/
1108
function is_URL($url) {
1109
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1110
	if($match)
1111
		return true;	
1112
	return false;
1113
}
1114

    
1115
?>
(42-42/51)