Project

General

Profile

Download (34.2 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 = (shell_exec("/bin/pgrep -x {$process}") != '');
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 refcount_init($reference) {
146
	$shmid = shmop_open(1000, "c", 0644, 10);
147
	shmop_write($shmid, 0, 0);
148
	shmop_close($shmid);
149
}
150

    
151
function refcount_reference($reference) {
152
	$shmid = shmop_open(1000, "w", 0644, 10);
153
	$shm_data = shmop_read($shmid, 0, 10);
154
	$shm_data = intval($shm_data) + 1;
155
	shmop_write($shmid, $shm_data, 0);
156
	shmop_close($shmid);
157
	
158
	return $shm_data;
159
}
160

    
161
function refcount_unreference($reference) {
162
	/* We assume that the shared memory exists. */
163
	$shmid = shmop_open(1000, "w", 0644, 10);
164
	$shm_data = shmop_read($shmid, 0, 10);
165
	$shm_data = intval($shm_data) - 1;
166
	if ($shm_data < 0) {
167
		//debug_backtrace();
168
		log_error("Reference {$reference} is going negative, not doing unreference.");
169
	} else
170
		shmop_write($shmid, $shm_data, 0);
171
	shmop_close($shmid);
172
	
173
	return $shm_data;
174
}
175

    
176
function is_module_loaded($module_name) {
177
	$running = `/sbin/kldstat | grep {$module_name} | /usr/bin/grep -v grep | /usr/bin/wc -l`;
178
	if (intval($running) >= 1)
179
		return true;
180
	else
181
		return false;
182
}
183

    
184
/* return the subnet address given a host address and a subnet bit count */
185
function gen_subnet($ipaddr, $bits) {
186
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
187
		return "";
188

    
189
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
190
}
191

    
192
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
193
function gen_subnet_max($ipaddr, $bits) {
194
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
195
		return "";
196

    
197
	return long2ip(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
198
}
199

    
200
/* returns a subnet mask (long given a bit count) */
201
function gen_subnet_mask_long($bits) {
202
	$sm = 0;
203
	for ($i = 0; $i < $bits; $i++) {
204
		$sm >>= 1;
205
		$sm |= 0x80000000;
206
	}
207
	return $sm;
208
}
209

    
210
/* same as above but returns a string */
211
function gen_subnet_mask($bits) {
212
	return long2ip(gen_subnet_mask_long($bits));
213
}
214

    
215
/* Convert IP address to unsigned long int. */
216
function ip2ulong($ip) {
217
	return sprintf("%u", ip2long($ip));
218
}
219

    
220
/* Find out how many IPs are contained within a given IP range
221
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
222
 */
223
function ip_range_size($startip, $endip) {
224
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
225
		// Operate as unsigned long because otherwise it wouldn't work
226
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
227
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
228
	}
229
	return -1;
230
}
231

    
232
/* Find the smallest possible subnet mask which can contain a given number of IPs
233
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
234
 */
235
function find_smallest_cidr($number) {
236
	$smallest = 1;
237
	for ($b=32; $b > 0; $b--) {
238
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
239
	}
240
	return (32-$smallest);
241
}
242

    
243
/* Return the previous IP address before the given address */
244
function ip_before($ip) {
245
	return long2ip(ip2long($ip)-1);
246
}
247

    
248
/* Return the next IP address after the given address */
249
function ip_after($ip) {
250
	return long2ip(ip2long($ip)+1);
251
}
252

    
253
/* Return true if the first IP is 'before' the second */
254
function ip_less_than($ip1, $ip2) {
255
	// Compare as unsigned long because otherwise it wouldn't work when
256
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
257
	return ip2ulong($ip1) < ip2ulong($ip2);
258
}
259

    
260
/* Return true if the first IP is 'after' the second */
261
function ip_greater_than($ip1, $ip2) {
262
	// Compare as unsigned long because otherwise it wouldn't work
263
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
264
	return ip2ulong($ip1) > ip2ulong($ip2);
265
}
266

    
267
/* Convert a range of IPs to an array of subnets which can contain the range. */
268
function ip_range_to_subnet_array($startip, $endip) {
269
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
270
		return array();
271
	}
272

    
273
	// Container for subnets within this range.
274
	$rangesubnets = array();
275

    
276
	// Figure out what the smallest subnet is that holds the number of IPs in the given range.
277
	$cidr = find_smallest_cidr(ip_range_size($startip, $endip));
278

    
279
	// Loop here to reduce subnet size and retest as needed. We need to make sure
280
	//   that the target subnet is wholly contained between $startip and $endip.
281
	for ($cidr; $cidr <= 32; $cidr++) {
282
		// Find the network and broadcast addresses for the subnet being tested.
283
		$targetsub_min = gen_subnet($startip, $cidr);
284
		$targetsub_max = gen_subnet_max($startip, $cidr);
285

    
286
		// Check best case where the range is exactly one subnet.
287
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
288
			// Hooray, the range is exactly this subnet!
289
			return array("{$startip}/{$cidr}");
290
		}
291

    
292
		// These remaining scenarios will find a subnet that uses the largest
293
		//  chunk possible of the range being tested, and leave the rest to be
294
		//  tested recursively after the loop.
295

    
296
		// Check if the subnet begins with $startip and ends before $endip
297
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
298
			break;
299
		}
300

    
301
		// Check if the subnet ends at $endip and starts after $startip
302
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
303
			break;
304
		}
305

    
306
		// Check if the subnet is between $startip and $endip
307
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
308
			break;
309
		}
310
	}
311

    
312
	// Some logic that will recursivly search from $startip to the first IP before the start of the subnet we just found.
313
	// NOTE: This may never be hit, the way the above algo turned out, but is left for completeness.
314
	if ($startip != $targetsub_min) {
315
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array($startip, ip_before($targetsub_min)));
316
	}
317

    
318
	// Add in the subnet we found before, to preserve ordering
319
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
320

    
321
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
322
	if ($endip != $targetsub_max) {
323
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
324
	}
325
	return $rangesubnets;
326
}
327

    
328
function is_iprange($range) {
329
	if (substr_count($range, '-') != 1) {
330
		return false;
331
	}
332
	list($ip1, $ip2) = explode ('-', $range);
333
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
334
}
335

    
336
function is_numericint($arg) {
337
	return (preg_match("/[^0-9]/", $arg) ? false : true);
338
}
339

    
340
/* returns true if $ipaddr is a valid dotted IPv4 address */
341
function is_ipaddr($ipaddr) {
342
	if (!is_string($ipaddr))
343
		return false;
344

    
345
	$ip_long = ip2long($ipaddr);
346
	$ip_reverse = long2ip($ip_long);
347

    
348
	if ($ipaddr == $ip_reverse)
349
		return true;
350
	else
351
		return false;
352
}
353

    
354
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
355
function is_ipaddroralias($ipaddr) {
356
	global $config;
357

    
358
	if (is_alias($ipaddr)) {
359
		if (is_array($config['aliases']['alias'])) {
360
			foreach ($config['aliases']['alias'] as $alias) {
361
                        	if ($alias['name'] == $ipaddr && $alias['type'] != "port")
362
					return true;
363
			}
364
                }
365
		return false;
366
	} else
367
		return is_ipaddr($ipaddr);
368

    
369
}
370

    
371
/* returns true if $subnet is a valid subnet in CIDR format */
372
function is_subnet($subnet) {
373
	if (!is_string($subnet))
374
		return false;
375

    
376
	list($hp,$np) = explode('/', $subnet);
377

    
378
	if (!is_ipaddr($hp))
379
		return false;
380

    
381
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
382
		return false;
383

    
384
	return true;
385
}
386

    
387
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
388
function is_subnetoralias($subnet) {
389

    
390
	global $aliastable;
391

    
392
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
393
		return true;
394
	else
395
		return is_subnet($subnet);
396
}
397

    
398
/* returns true if $hostname is a valid hostname */
399
function is_hostname($hostname) {
400
	if (!is_string($hostname))
401
		return false;
402

    
403
	if (preg_match("/^([_a-z0-9\-]+\.?)+$/i", $hostname))
404
		return true;
405
	else
406
		return false;
407
}
408

    
409
/* returns true if $domain is a valid domain name */
410
function is_domain($domain) {
411
	if (!is_string($domain))
412
		return false;
413

    
414
	if (preg_match("/^([a-z0-9\-]+\.?)+$/i", $domain))
415
		return true;
416
	else
417
		return false;
418
}
419

    
420
/* returns true if $macaddr is a valid MAC address */
421
function is_macaddr($macaddr) {
422
	if (!is_string($macaddr))
423
		return false;
424

    
425
	$maca = explode(":", $macaddr);
426
	if (count($maca) != 6)
427
		return false;
428

    
429
	foreach ($maca as $macel) {
430
		if (($macel === "") || (strlen($macel) > 2))
431
			return false;
432
		if (preg_match("/[^0-9a-f]/i", $macel))
433
			return false;
434
	}
435

    
436
	return true;
437
}
438

    
439
/* returns true if $name is a valid name for an alias */
440
/* returns NULL if a reserved word is used */
441
function is_validaliasname($name) {
442
	/* Array of reserved words */
443
	$reserved = array("port", "pass");
444
	if (in_array($name, $reserved, true))
445
		return; /* return NULL */
446

    
447
	if (!preg_match("/[^a-zA-Z0-9_]/", $name))
448
		return true;
449
	else
450
		return false;
451
}
452

    
453
/* returns true if $port is a valid TCP/UDP port */
454
function is_port($port) {
455
	$tmpports = explode(":", $port);
456
	foreach($tmpports as $tmpport) {
457
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
458
                	continue;
459
		if (!ctype_digit($tmpport))
460
			return false;
461
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
462
			return false;
463
	}
464
	return true;
465
}
466

    
467
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
468
function is_portrange($portrange) {
469
        $ports = explode(":", $portrange);
470

    
471
        if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
472
                return true;
473
        else
474
                return false;
475
}
476

    
477
/* returns true if $port is a valid port number or an alias thereof */
478
function is_portoralias($port) {
479
	global $config;
480

    
481
        if (is_alias($port)) {
482
                if (is_array($config['aliases']['alias'])) {
483
                        foreach ($config['aliases']['alias'] as $alias) {
484
                                if ($alias['name'] == $port && $alias['type'] == "port")
485
                                        return true;
486
                        }
487
                }
488
                return false;
489
        } else
490
                return is_port($port);
491
}
492

    
493
/* returns true if $val is a valid shaper bandwidth value */
494
function is_valid_shaperbw($val) {
495
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
496
}
497

    
498
/* return the configured carp interface list */
499
function get_configured_carp_interface_list() {
500
	global $config;
501

    
502
	$iflist = array();
503

    
504
	if(is_array($config['virtualip']['vip'])) {
505
                $viparr = &$config['virtualip']['vip'];
506
                foreach ($viparr as $vip) {
507
                        switch ($vip['mode']) {
508
                        case "carp":
509
                        case "carpdev-dhcp":
510
				$vipif = "vip" . $vip['vhid'];
511
                        	$iflist[$vipif] = $vip['subnet'];
512
                                break;
513
                        }
514
                }
515
        }
516

    
517
	return $iflist;
518
}
519

    
520
/* return the configured IP aliases list */
521
function get_configured_ip_aliases_list() {
522
        global $config;
523

    
524
        $alias_list=array();
525

    
526
        if(is_array($config['virtualip']['vip'])) {
527
                $viparr = &$config['virtualip']['vip'];
528
                foreach ($viparr as $vip) {
529
                        if ($vip['mode']=="ipalias") {
530
                                $alias_list[$vip['subnet']] = $vip['interface'];
531
                        }
532
                }
533
        }
534

    
535
        return $alias_list;
536
}
537

    
538

    
539
/* return the configured interfaces list. */
540
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
541
	global $config;
542

    
543
	$iflist = array();
544

    
545
	if (!$only_opt) {
546
		if (isset($config['interfaces']['wan']))
547
			$iflist['wan'] = "wan";
548
		if (isset($config['interfaces']['lan']))
549
			$iflist['lan'] = "lan";
550
	}
551

    
552
	/* if list */
553
        foreach($config['interfaces'] as $if => $ifdetail) {
554
		if ($if == "wan" || $if == "lan")
555
			continue;
556
		if (isset($ifdetail['enable']) || $withdisabled == true)
557
			$iflist[$if] = $if;
558
	}
559

    
560
	return $iflist;
561
}
562

    
563
/* return the configured interfaces list. */
564
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
565
        global $config;
566

    
567
        $iflist = array();
568

    
569
        if (!$only_opt) {
570
                if (isset($config['interfaces']['wan'])) {
571
			$tmpif = get_real_interface("wan");
572
			if (!empty($tmpif))
573
				$iflist[$tmpif] = "wan";
574
		}
575
                if (isset($config['interfaces']['lan'])) {
576
			$tmpif = get_real_interface("lan");
577
			if (!empty($tmpif))
578
				$iflist[$tmpif] = "lan";
579
		}
580
        }
581

    
582
        /* if list */
583
        foreach($config['interfaces'] as $if => $ifdetail) {
584
                if ($if == "wan" || $if == "lan")
585
                        continue;
586
                if (isset($ifdetail['enable']) || $withdisabled == true) {
587
			$tmpif = get_real_interface($if);
588
			if (!empty($tmpif))
589
				$iflist[$tmpif] = $if;
590
		}
591
        }
592

    
593
        return $iflist;
594
}
595

    
596
/* return the configured interfaces list with their description. */
597
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
598
	global $config;
599

    
600
	$iflist = array();
601

    
602
	if (!$only_opt) {
603
		if (isset($config['interfaces']['wan'])) {
604
			if (empty($config['interfaces']['wan']['descr']))
605
				$iflist['wan'] = "WAN";
606
			else
607
				$iflist['wan'] = strtoupper($config['interfaces']['wan']['descr']);
608
		}
609
		if (isset($config['interfaces']['lan'])) {
610
			if (empty($config['interfaces']['lan']['descr']))
611
				$iflist['lan'] = "LAN";
612
			else
613
				$iflist['lan'] = strtoupper($config['interfaces']['lan']['descr']);
614
		}
615
	}
616

    
617
	/* if list */
618
	foreach($config['interfaces'] as $if => $ifdetail) {
619
		if (isset($ifdetail['enable']) || $withdisabled == true) {
620
			if($ifdetail['descr'] == "")
621
				$iflist[$if] = strtoupper($if);
622
			else
623
				$iflist[$if] = strtoupper($ifdetail['descr']);
624
		}
625
	}
626

    
627
	return $iflist;
628
}
629

    
630

    
631
/*
632
 *   get_interface_list() - Return a list of all physical interfaces
633
 *   along with MAC and status.
634
 *
635
 *   $mode = "active" - use ifconfig -lu
636
 *           "media"  - use ifconfig to check physical connection
637
 *			status (much slower)
638
 */
639
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
640
        global $config;
641
	$upints = array();
642
        /* get a list of virtual interface types */
643
        if(!$vfaces) {
644
		$vfaces = array (
645
				'bridge',
646
				'ppp',
647
				'pppoe',
648
				'pptp',
649
				'l2tp',
650
				'sl',
651
				'gif',
652
				'gre',
653
				'faith',
654
				'lo',
655
				'ng',
656
				'_vlan',
657
				'_wlan',
658
				'pflog',
659
				'plip',
660
				'pfsync',
661
				'enc',
662
				'tun',
663
				'carp',
664
				'lagg',
665
				'vip'
666
		);
667
	}
668
	switch($mode) {
669
	case "active":
670
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
671
        	break;
672
	case "media":
673
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
674
                $ifconfig = "";
675
                exec("/sbin/ifconfig -a", $ifconfig);
676
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
677
                $ifstatus = preg_grep('/status:/', $ifconfig);
678
		foreach($ifstatus as $status) {
679
			$int = array_shift($intlist);
680
                	if(stristr($status, "active")) $upints[] = $int;
681
		}
682
		break;
683
	}
684
        /* build interface list with netstat */
685
        $linkinfo = "";
686
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
687
        array_shift($linkinfo);
688
	/* build ip address list with netstat */
689
	$ipinfo = "";
690
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
691
	array_shift($ipinfo);
692
	foreach($linkinfo as $link) {
693
		$friendly = "";
694
                $alink = explode(" ", $link);
695
                $ifname = rtrim(trim($alink[0]), '*');
696
                /* trim out all numbers before checking for vfaces */
697
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces) &&
698
			!stristr($ifname, "_vlan") && !stristr($ifname, "_wlan")) {
699
			$toput = array(
700
					"mac" => trim($alink[1]),
701
					"up" => in_array($ifname, $upints)
702
				);
703
			foreach($ipinfo as $ip) {
704
				$aip = explode(" ", $ip);
705
				if($aip[0] == $ifname) {
706
					$toput['ipaddr'] = $aip[1];
707
				}
708
			}
709
			foreach($config['interfaces'] as $name => $int) {
710
				if($int['if'] == $ifname) $friendly = $name;
711
			}
712
			switch($keyby) {
713
			case "physical":
714
				if($friendly != "") {
715
					$toput['friendly'] = $friendly;
716
				}
717
				$dmesg_arr = array();
718
				exec("/sbin/dmesg |grep $ifname | head -n1", $dmesg_arr);
719
				preg_match_all("/<(.*?)>/i", $dmesg_arr[0], $dmesg);
720
				$toput['dmesg'] = $dmesg[1][0];
721
				$iflist[$ifname] = $toput;
722
				break;
723
			case "ppp":
724
				
725
			case "friendly":
726
				if($friendly != "") {
727
					$toput['if'] = $ifname;
728
					$iflist[$friendly] = $toput;
729
				}
730
				break;
731
			}
732
                }
733
        }
734
        return $iflist;
735
}
736

    
737
/****f* util/log_error
738
* NAME
739
*   log_error  - Sends a string to syslog.
740
* INPUTS
741
*   $error     - string containing the syslog message.
742
* RESULT
743
*   null
744
******/
745
function log_error($error) {
746
        global $g;
747
        $page = $_SERVER['SCRIPT_NAME'];
748
        syslog(LOG_WARNING, "$page: $error");
749
        if ($g['debug'])
750
                syslog(LOG_WARNING, var_dump(debug_backtrace()));
751
        return;
752
}
753

    
754
/****f* util/exec_command
755
 * NAME
756
 *   exec_command - Execute a command and return a string of the result.
757
 * INPUTS
758
 *   $command   - String of the command to be executed.
759
 * RESULT
760
 *   String containing the command's result.
761
 * NOTES
762
 *   This function returns the command's stdout and stderr.
763
 ******/
764
function exec_command($command) {
765
        $output = array();
766
        exec($command . ' 2>&1 ', $output);
767
        return(implode("\n", $output));
768
}
769

    
770
/* wrapper for exec() */
771
function mwexec($command, $mute = false) {
772

    
773
	global $g;
774
	$oarr = array();
775
	$retval = 0;
776
	if ($g['debug']) {
777
		if (!$_SERVER['REMOTE_ADDR'])
778
			echo "mwexec(): $command\n";
779
		exec("$command 2>&1", $oarr, $retval);
780
	} else {
781
		exec("$command 2>&1", $oarr, $retval);
782
	}
783
	if(isset($config['system']['developerspew']))
784
                $mute = false;
785
	if(($retval <> 0) && ($mute === false)) {
786
		$output = implode(" ", $oarr);
787
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
788
	}
789
	return $retval;
790
}
791

    
792
/* wrapper for exec() in background */
793
function mwexec_bg($command) {
794

    
795
	global $g;
796

    
797
	if ($g['debug']) {
798
		if (!$_SERVER['REMOTE_ADDR'])
799
			echo "mwexec(): $command\n";
800
	}
801

    
802
	exec("nohup $command > /dev/null 2>&1 &");
803
}
804

    
805
/* unlink a file, if it exists */
806
function unlink_if_exists($fn) {
807
	$to_do = glob($fn);
808
	if(is_array($to_do)) {
809
		foreach($to_do as $filename)
810
			@unlink($filename);
811
	} else {
812
		@unlink($fn);
813
	}
814
}
815
/* make a global alias table (for faster lookups) */
816
function alias_make_table($config) {
817

    
818
	global $aliastable;
819

    
820
	$aliastable = array();
821

    
822
	if (is_array($config['aliases']['alias'])) {
823
		foreach ($config['aliases']['alias'] as $alias) {
824
			if ($alias['name'])
825
				$aliastable[$alias['name']] = $alias['address'];
826
		}
827
	}
828
}
829
/* check if an alias exists */
830
function is_alias($name) {
831

    
832
	global $aliastable;
833

    
834
	return isset($aliastable[$name]);
835
}
836

    
837
/* expand a host or network alias, if necessary */
838
function alias_expand($name) {
839

    
840
	global $aliastable;
841

    
842
	if (isset($aliastable[$name]))
843
		return "\${$name}";
844
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
845
		return "{$name}";
846
	else
847
		return null;
848
}
849

    
850
/* find out whether two subnets overlap */
851
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
852

    
853
	if (!is_numeric($bits1))
854
		$bits1 = 32;
855
	if (!is_numeric($bits2))
856
		$bits2 = 32;
857

    
858
	if ($bits1 < $bits2)
859
		$relbits = $bits1;
860
	else
861
		$relbits = $bits2;
862

    
863
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
864
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
865

    
866
	if ($sn1 == $sn2)
867
		return true;
868
	else
869
		return false;
870
}
871

    
872
/* compare two IP addresses */
873
function ipcmp($a, $b) {
874
	if (ip2long($a) < ip2long($b))
875
		return -1;
876
	else if (ip2long($a) > ip2long($b))
877
		return 1;
878
	else
879
		return 0;
880
}
881

    
882
/* return true if $addr is in $subnet, false if not */
883
function ip_in_subnet($addr,$subnet) {
884
	list($ip, $mask) = explode('/', $subnet);
885
	$mask = 0xffffffff << (32 - $mask);
886
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
887
}
888

    
889
/* verify (and remove) the digital signature on a file - returns 0 if OK */
890
function verify_digital_signature($fname) {
891

    
892
	global $g;
893

    
894
	if(!file_exists("/usr/local/sbin/gzsig"))
895
		return 4;
896

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

    
900
/* obtain MAC address given an IP address by looking at the ARP table */
901
function arp_get_mac_by_ip($ip) {
902
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
903
	$arpoutput = "";
904
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
905

    
906
	if ($arpoutput[0]) {
907
		$arpi = explode(" ", $arpoutput[0]);
908
		$macaddr = $arpi[3];
909
		if (is_macaddr($macaddr))
910
			return $macaddr;
911
		else
912
			return false;
913
	}
914

    
915
	return false;
916
}
917

    
918
/* return a fieldname that is safe for xml usage */
919
function xml_safe_fieldname($fieldname) {
920
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
921
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
922
			 ':', ',', '.', '\'', '\\'
923
		);
924
	return strtolower(str_replace($replace, "", $fieldname));
925
}
926

    
927
function mac_format($clientmac) {
928
    $mac =explode(":", $clientmac);
929

    
930
    global $config;
931

    
932
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
933

    
934
    switch($mac_format) {
935

    
936
        case 'singledash':
937
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
938

    
939
        case 'ietf':
940
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
941

    
942
        case 'cisco':
943
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
944

    
945
        case 'unformatted':
946
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
947

    
948
        default:
949
        return $clientmac;
950
    }
951
}
952

    
953
function resolve_retry($hostname, $retries = 5) {
954

    
955
       if (is_ipaddr($hostname))
956
               return $hostname;
957

    
958
       for ($i = 0; $i < $retries; $i++) {
959
               $ip = gethostbyname($hostname);
960

    
961
               if ($ip && $ip != $hostname) {
962
                       /* success */
963
                       return $ip;
964
               }
965

    
966
               sleep(1);
967
       }
968

    
969
       return false;
970
}
971

    
972
function format_bytes($bytes) {
973
	if ($bytes >= 1073741824) {
974
		return sprintf("%.2f GB", $bytes/1073741824);
975
	} else if ($bytes >= 1048576) {
976
		return sprintf("%.2f MB", $bytes/1048576);
977
	} else if ($bytes >= 1024) {
978
		return sprintf("%.0f KB", $bytes/1024);
979
	} else {
980
		return sprintf("%d bytes", $bytes);
981
	}
982
}
983

    
984
function update_filter_reload_status($text) {
985
        global $g;
986

    
987
        file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
988
}
989

    
990
/****f* util/return_dir_as_array
991
 * NAME
992
 *   return_dir_as_array - Return a directory's contents as an array.
993
 * INPUTS
994
 *   $dir       - string containing the path to the desired directory.
995
 * RESULT
996
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
997
 ******/
998
function return_dir_as_array($dir) {
999
        $dir_array = array();
1000
        if (is_dir($dir)) {
1001
                if ($dh = opendir($dir)) {
1002
                        while (($file = readdir($dh)) !== false) {
1003
                                $canadd = 0;
1004
                                if($file == ".") $canadd = 1;
1005
                                if($file == "..") $canadd = 1;
1006
                                if($canadd == 0)
1007
                                        array_push($dir_array, $file);
1008
                        }
1009
                        closedir($dh);
1010
                }
1011
        }
1012
        return $dir_array;
1013
}
1014

    
1015
function run_plugins($directory) {
1016
        global $config, $g;
1017

    
1018
		/* process packager manager custom rules */
1019
		$files = return_dir_as_array($directory);
1020
		if (is_array($files)) {
1021
			foreach ($files as $file) {
1022
				if (stristr($file, ".sh") == true)
1023
					mwexec($directory . $file . " start");
1024
				else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1025
					require_once($directory . "/" . $file);
1026
			}
1027
		}
1028
}
1029

    
1030
/*
1031
 *    safe_mkdir($path, $mode = 0755)
1032
 *    create directory if it doesn't already exist and isn't a file!
1033
 */
1034
function safe_mkdir($path, $mode=0755) {
1035
        global $g;
1036

    
1037
        if (!is_file($path) && !is_dir($path)) {
1038
                return @mkdir($path, $mode);
1039
        } else {
1040
                return false;
1041
        }
1042
}
1043

    
1044
/*
1045
 * make_dirs($path, $mode = 0755)
1046
 * create directory tree recursively (mkdir -p)
1047
 */
1048
function make_dirs($path, $mode = 0755) {
1049
        $base = '';
1050
        foreach (explode('/', $path) as $dir) {
1051
                $base .= "/$dir";
1052
                if (!is_dir($base)) {
1053
                        if (!@mkdir($base, $mode))
1054
                                return false;
1055
                }
1056
        }
1057
        return true;
1058
}
1059

    
1060
/*
1061
 *     get_memory()
1062
 *     returns an array listing the amount of
1063
 *     memory installed in the hardware
1064
 *     [0]real and [1]available
1065
 */
1066
function get_memory() {
1067
		$matches = "";
1068
        if(file_exists("/var/log/dmesg.boot"))
1069
			$mem = `cat /var/log/dmesg.boot | grep memory`;
1070
		else
1071
			$mem = `dmesg -a | grep memory`;			
1072
		if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1073
			return array($matches[1][0], $matches[1][0]);
1074
		if(!$real && !$avail) {
1075
			$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1076
			$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1077
			return array(($real/1024),($avail/1024));
1078
		}
1079
}
1080

    
1081
function mute_kernel_msgs() {
1082
		global $config;
1083
		// Do not mute serial console.  The kernel gets very very cranky
1084
		// and will start dishing you cannot control tty errors.
1085
		if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1086
			return;
1087
		if($config['system']['enableserial']) 
1088
			return;			
1089
		exec("/sbin/conscontrol mute on");
1090
}
1091

    
1092
function unmute_kernel_msgs() {
1093
		global $config;
1094
		// Do not mute serial console.  The kernel gets very very cranky
1095
		// and will start dishing you cannot control tty errors.
1096
		if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1097
			return;
1098
		exec("/sbin/conscontrol mute off");
1099
}
1100

    
1101
function start_devd() {
1102
	global $g;
1103

    
1104
        exec("/sbin/devd");
1105
        sleep(1);
1106
        if(file_exists("{$g['tmp_path']}/rc.linkup"))
1107
                unlink("{$g['tmp_path']}/rc.linkup");
1108
}
1109

    
1110
function is_interface_mismatch() {
1111
        global $config, $g;
1112

    
1113
        /* XXX: Should we process only enabled interfaces?! */
1114
        $do_assign = false;
1115
        $i = 0;
1116
        foreach ($config['interfaces'] as $ifname => $ifcfg) {
1117
                if (preg_match("/^enc|^tun|^ppp|^pptp|^pppoe|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1118
                        $i++;
1119
                }
1120
                else if (does_interface_exist($ifcfg['if']) == false) {
1121
                        $do_assign = true;
1122
                } else
1123
                        $i++;
1124
        }
1125

    
1126
        if ($g['minimum_nic_count'] > $i) {
1127
                $do_assign = true;
1128
        } else if (file_exists("{$g['tmp_path']}/assign_complete"))
1129
                $do_assign = false;
1130

    
1131
        return $do_assign;
1132
}
1133

    
1134
/* sync carp entries to other firewalls */
1135
function carp_sync_client() {
1136
	global $g;
1137
	touch($g['tmp_path'] . "/filter_sync"); 
1138
}
1139

    
1140
/****f* util/isAjax
1141
 * NAME
1142
 *   isAjax - reports if the request is driven from prototype
1143
 * INPUTS
1144
 *   none
1145
 * RESULT
1146
 *   true/false
1147
 ******/
1148
function isAjax() {
1149
        return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1150
}
1151

    
1152
/****f* util/timeout
1153
 * NAME
1154
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1155
 * INPUTS
1156
 *   optional, seconds to wait before timeout. Default 9 seconds.
1157
 * RESULT
1158
 *   returns 1 char of user input or null if no input.
1159
 ******/
1160
function timeout($timer = 9) {
1161
	while(!isset($key)) {
1162
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1163
		else { echo chr(8). "{$timer}"; }
1164
		`/bin/stty -icanon min 0 time 25`;
1165
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1166
		`/bin/stty icanon`;
1167
		if ($key == '')
1168
			unset($key);
1169
		$timer--;
1170
		if ($timer == 0)
1171
			break;
1172
	}
1173
	return $key;	
1174
}
1175

    
1176
/****f* util/msort
1177
 * NAME
1178
 *   msort - sort array
1179
 * INPUTS
1180
 *   $array to be sorted, field to sort by, direction of sort
1181
 * RESULT
1182
 *   returns newly sorted array
1183
 ******/
1184
function msort($array, $id="id", $sort_ascending=true) {
1185
	$temp_array = array();
1186
	while(count($array)>0) {
1187
		$lowest_id = 0;
1188
		$index=0;
1189
		foreach ($array as $item) {
1190
			if (isset($item[$id])) {
1191
				if ($array[$lowest_id][$id]) {
1192
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1193
						$lowest_id = $index;
1194
					}
1195
				}
1196
			}
1197
			$index++;
1198
		}
1199
		$temp_array[] = $array[$lowest_id];
1200
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1201
	}
1202
	if ($sort_ascending) {
1203
		return $temp_array;
1204
	} else {
1205
    	return array_reverse($temp_array);
1206
	}
1207
}
1208

    
1209
/****f* util/color
1210
 * NAME
1211
 *   color - outputs a color code to the ansi terminal if supported
1212
 * INPUTS
1213
 *   color code or color name
1214
 * RESULT
1215
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1216
 ******/
1217
function color($color = "0m") {
1218
	/*
1219
		Color codes available:
1220
		 0m reset; clears all colors and styles (to white on black)
1221
		 1m bold on (see below)
1222
		 3m italics on
1223
		 4m underline on
1224
		 7m inverse on; reverses foreground & background colors
1225
		 9m strikethrough on
1226
		 22m bold off (see below)
1227
		 23m italics off
1228
		 24m underline off
1229
		 27m inverse off
1230
		 29m strikethrough off
1231
		 30m set foreground color to black
1232
		 31m set foreground color to red
1233
		 32m set foreground color to green
1234
		 33m set foreground color to yellow
1235
		 34m set foreground color to blue
1236
		 35m set foreground color to magenta (purple)
1237
		 36m set foreground color to cyan
1238
		 37m set foreground color to white
1239
		 40m  set background color to black
1240
		 41m set background color to red
1241
		 42m set background color to green
1242
		 43m set background color to yellow
1243
		 44m set background color to blue
1244
		 45m set background color to magenta (purple)
1245
		 46m set background color to cyan
1246
		 47m set background color to white
1247
		 49m set background color to default (black)
1248
	*/	
1249
	// Allow caching of TERM to 
1250
	// speedup subequence requests.
1251
	global $TERM;
1252
	if(!$TERM) 
1253
		$TERM=`/usr/bin/env | grep color`;
1254
	if(!$TERM)
1255
		$TERM=`/usr/bin/env | grep cons25`;
1256
	if($TERM) {
1257
		$ESCAPE=chr(27);
1258
		switch ($color) {
1259
			case "black":
1260
				return "{$ESCAPE}[30m"; 
1261
			case "red":
1262
				return "{$ESCAPE}[31m"; 
1263
			case "green":
1264
				return "{$ESCAPE}[32m"; 
1265
			case "yellow":
1266
				return "{$ESCAPE}[33m"; 
1267
			case "blue":
1268
				return "{$ESCAPE}[34m"; 
1269
			case "magenta":
1270
				return "{$ESCAPE}[35m"; 
1271
			case "cyan":
1272
				return "{$ESCAPE}[36m"; 
1273
			case "white":
1274
				return "{$ESCAPE}[37m"; 
1275
			case "default":
1276
				return "{$ESCAPE}[39m"; 
1277
		}
1278
		return "{$ESCAPE}[{$color}";
1279
	}
1280
}
1281

    
1282
/****f* util/is_URL
1283
 * NAME
1284
 *   is_URL
1285
 * INPUTS
1286
 *   string to check
1287
 * RESULT
1288
 *   Returns true if item is a URL
1289
 ******/
1290
function is_URL($url) {
1291
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1292
	if($match)
1293
		return true;	
1294
	return false;
1295
}
1296

    
1297
function is_file_included($file = "") {
1298
	$files = get_included_files();
1299
	if (in_array($file, $files))
1300
		return true;
1301
	
1302
	return false;
1303
}
1304

    
1305
?>
(41-41/50)