Project

General

Profile

Download (34.4 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($reference, "c", 0644, 10);
147
	shmop_write($shmid, 0, 0);
148
	shmop_close($shmid);
149
}
150

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

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

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

    
188
/* return the subnet address given a host address and a subnet bit count */
189
function gen_subnet($ipaddr, $bits) {
190
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
191
		return "";
192

    
193
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
194
}
195

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

    
201
	return long2ip(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
202
}
203

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

    
214
/* same as above but returns a string */
215
function gen_subnet_mask($bits) {
216
	return long2ip(gen_subnet_mask_long($bits));
217
}
218

    
219
/* Convert IP address to unsigned long int. */
220
function ip2ulong($ip) {
221
	return sprintf("%u", ip2long($ip));
222
}
223

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

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

    
247
/* Return the previous IP address before the given address */
248
function ip_before($ip) {
249
	return long2ip(ip2long($ip)-1);
250
}
251

    
252
/* Return the next IP address after the given address */
253
function ip_after($ip) {
254
	return long2ip(ip2long($ip)+1);
255
}
256

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

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

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

    
277
	// Container for subnets within this range.
278
	$rangesubnets = array();
279

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

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

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

    
296
		// These remaining scenarios will find a subnet that uses the largest
297
		//  chunk possible of the range being tested, and leave the rest to be
298
		//  tested recursively after the loop.
299

    
300
		// Check if the subnet begins with $startip and ends before $endip
301
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
302
			break;
303
		}
304

    
305
		// Check if the subnet ends at $endip and starts after $startip
306
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
307
			break;
308
		}
309

    
310
		// Check if the subnet is between $startip and $endip
311
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
312
			break;
313
		}
314
	}
315

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

    
322
	// Add in the subnet we found before, to preserve ordering
323
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
324

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

    
332
function is_iprange($range) {
333
	if (substr_count($range, '-') != 1) {
334
		return false;
335
	}
336
	list($ip1, $ip2) = explode ('-', $range);
337
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
338
}
339

    
340
function is_numericint($arg) {
341
	return (preg_match("/[^0-9]/", $arg) ? false : true);
342
}
343

    
344
/* returns true if $ipaddr is a valid dotted IPv4 address */
345
function is_ipaddr($ipaddr) {
346
	if (!is_string($ipaddr))
347
		return false;
348

    
349
	$ip_long = ip2long($ipaddr);
350
	$ip_reverse = long2ip($ip_long);
351

    
352
	if ($ipaddr == $ip_reverse)
353
		return true;
354
	else
355
		return false;
356
}
357

    
358
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
359
function is_ipaddroralias($ipaddr) {
360
	global $config;
361

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

    
373
}
374

    
375
/* returns true if $subnet is a valid subnet in CIDR format */
376
function is_subnet($subnet) {
377
	if (!is_string($subnet))
378
		return false;
379

    
380
	list($hp,$np) = explode('/', $subnet);
381

    
382
	if (!is_ipaddr($hp))
383
		return false;
384

    
385
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
386
		return false;
387

    
388
	return true;
389
}
390

    
391
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
392
function is_subnetoralias($subnet) {
393

    
394
	global $aliastable;
395

    
396
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
397
		return true;
398
	else
399
		return is_subnet($subnet);
400
}
401

    
402
/* returns true if $hostname is a valid hostname */
403
function is_hostname($hostname) {
404
	if (!is_string($hostname))
405
		return false;
406

    
407
	if (preg_match("/^([_a-z0-9\-]+\.?)+$/i", $hostname))
408
		return true;
409
	else
410
		return false;
411
}
412

    
413
/* returns true if $domain is a valid domain name */
414
function is_domain($domain) {
415
	if (!is_string($domain))
416
		return false;
417

    
418
	if (preg_match("/^([a-z0-9\-]+\.?)+$/i", $domain))
419
		return true;
420
	else
421
		return false;
422
}
423

    
424
/* returns true if $macaddr is a valid MAC address */
425
function is_macaddr($macaddr) {
426
	if (!is_string($macaddr))
427
		return false;
428

    
429
	$maca = explode(":", $macaddr);
430
	if (count($maca) != 6)
431
		return false;
432

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

    
440
	return true;
441
}
442

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

    
451
	if (!preg_match("/[^a-zA-Z0-9_]/", $name))
452
		return true;
453
	else
454
		return false;
455
}
456

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

    
471
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
472
function is_portrange($portrange) {
473
        $ports = explode(":", $portrange);
474

    
475
        if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
476
                return true;
477
        else
478
                return false;
479
}
480

    
481
/* returns true if $port is a valid port number or an alias thereof */
482
function is_portoralias($port) {
483
	global $config;
484

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

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

    
502
/* return the configured carp interface list */
503
function get_configured_carp_interface_list() {
504
	global $config;
505

    
506
	$iflist = array();
507

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

    
521
	return $iflist;
522
}
523

    
524
/* return the configured IP aliases list */
525
function get_configured_ip_aliases_list() {
526
        global $config;
527

    
528
        $alias_list=array();
529

    
530
        if(is_array($config['virtualip']['vip'])) {
531
                $viparr = &$config['virtualip']['vip'];
532
                foreach ($viparr as $vip) {
533
                        if ($vip['mode']=="ipalias") {
534
                                $alias_list[$vip['subnet']] = $vip['interface'];
535
                        }
536
                }
537
        }
538

    
539
        return $alias_list;
540
}
541

    
542

    
543
/* return the configured interfaces list. */
544
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
545
	global $config;
546

    
547
	$iflist = array();
548

    
549
	if (!$only_opt) {
550
		if (isset($config['interfaces']['wan']))
551
			$iflist['wan'] = "wan";
552
		if (isset($config['interfaces']['lan']))
553
			$iflist['lan'] = "lan";
554
	}
555

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

    
564
	return $iflist;
565
}
566

    
567
/* return the configured interfaces list. */
568
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
569
        global $config;
570

    
571
        $iflist = array();
572

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

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

    
597
        return $iflist;
598
}
599

    
600
/* return the configured interfaces list with their description. */
601
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
602
	global $config;
603

    
604
	$iflist = array();
605

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

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

    
631
	return $iflist;
632
}
633

    
634

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

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

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

    
774
/* wrapper for exec() */
775
function mwexec($command, $mute = false) {
776

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

    
796
/* wrapper for exec() in background */
797
function mwexec_bg($command) {
798

    
799
	global $g;
800

    
801
	if ($g['debug']) {
802
		if (!$_SERVER['REMOTE_ADDR'])
803
			echo "mwexec(): $command\n";
804
	}
805

    
806
	exec("nohup $command > /dev/null 2>&1 &");
807
}
808

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

    
822
	global $aliastable;
823

    
824
	$aliastable = array();
825

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

    
836
	global $aliastable;
837

    
838
	return isset($aliastable[$name]);
839
}
840

    
841
/* expand a host or network alias, if necessary */
842
function alias_expand($name) {
843

    
844
	global $aliastable;
845

    
846
	if (isset($aliastable[$name]))
847
		return "\${$name}";
848
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
849
		return "{$name}";
850
	else
851
		return null;
852
}
853

    
854
/* find out whether two subnets overlap */
855
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
856

    
857
	if (!is_numeric($bits1))
858
		$bits1 = 32;
859
	if (!is_numeric($bits2))
860
		$bits2 = 32;
861

    
862
	if ($bits1 < $bits2)
863
		$relbits = $bits1;
864
	else
865
		$relbits = $bits2;
866

    
867
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
868
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
869

    
870
	if ($sn1 == $sn2)
871
		return true;
872
	else
873
		return false;
874
}
875

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

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

    
893
/* verify (and remove) the digital signature on a file - returns 0 if OK */
894
function verify_digital_signature($fname) {
895
	global $g;
896

    
897
	if(!file_exists("/usr/local/sbin/gzsig"))
898
		return 4;
899

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

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

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

    
918
	return false;
919
}
920

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

    
930
function mac_format($clientmac) {
931
    $mac =explode(":", $clientmac);
932

    
933
    global $config;
934

    
935
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
936

    
937
    switch($mac_format) {
938

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

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

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

    
948
        case 'unformatted':
949
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
950

    
951
        default:
952
        return $clientmac;
953
    }
954
}
955

    
956
function resolve_retry($hostname, $retries = 5) {
957

    
958
       if (is_ipaddr($hostname))
959
               return $hostname;
960

    
961
       for ($i = 0; $i < $retries; $i++) {
962
               $ip = gethostbyname($hostname);
963

    
964
               if ($ip && $ip != $hostname) {
965
                       /* success */
966
                       return $ip;
967
               }
968

    
969
               sleep(1);
970
       }
971

    
972
       return false;
973
}
974

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

    
987
function update_filter_reload_status($text) {
988
        global $g;
989

    
990
        file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
991
}
992

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

    
1018
function run_plugins($directory) {
1019
        global $config, $g;
1020

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

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

    
1040
        if (!is_file($path) && !is_dir($path)) {
1041
                return @mkdir($path, $mode);
1042
        } else {
1043
                return false;
1044
        }
1045
}
1046

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

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

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

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

    
1104
function start_devd() {
1105
	global $g;
1106

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

    
1113
function is_interface_mismatch() {
1114
        global $config, $g;
1115

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

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

    
1134
        return $do_assign;
1135
}
1136

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

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

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

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

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

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

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

    
1308
?>
(41-41/50)