Project

General

Profile

Download (34.8 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
function alias_expand_urltable($name) {
855
	global $config;
856
	$urltable_prefix = "/var/db/aliastables/";
857
	$urltable_filename = $urltable_prefix . $name . ".txt";
858

    
859
	foreach ($config['aliases']['alias'] as $alias) {
860
		if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
861
			if (is_URL($alias["url"]) && file_exists($urltable_filename))
862
				return $urltable_filename;
863
			else if (process_alias_urltable($name, $alias["url"], 0, true))
864
				return $urltable_filename;
865
		}
866
	}
867
	return null;
868
}
869

    
870
/* find out whether two subnets overlap */
871
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
872

    
873
	if (!is_numeric($bits1))
874
		$bits1 = 32;
875
	if (!is_numeric($bits2))
876
		$bits2 = 32;
877

    
878
	if ($bits1 < $bits2)
879
		$relbits = $bits1;
880
	else
881
		$relbits = $bits2;
882

    
883
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
884
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
885

    
886
	if ($sn1 == $sn2)
887
		return true;
888
	else
889
		return false;
890
}
891

    
892
/* compare two IP addresses */
893
function ipcmp($a, $b) {
894
	if (ip2long($a) < ip2long($b))
895
		return -1;
896
	else if (ip2long($a) > ip2long($b))
897
		return 1;
898
	else
899
		return 0;
900
}
901

    
902
/* return true if $addr is in $subnet, false if not */
903
function ip_in_subnet($addr,$subnet) {
904
	list($ip, $mask) = explode('/', $subnet);
905
	$mask = 0xffffffff << (32 - $mask);
906
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
907
}
908

    
909
/* verify (and remove) the digital signature on a file - returns 0 if OK */
910
function verify_digital_signature($fname) {
911
	global $g;
912

    
913
	if(!file_exists("/usr/local/sbin/gzsig"))
914
		return 4;
915

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

    
919
/* obtain MAC address given an IP address by looking at the ARP table */
920
function arp_get_mac_by_ip($ip) {
921
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
922
	$arpoutput = "";
923
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
924

    
925
	if ($arpoutput[0]) {
926
		$arpi = explode(" ", $arpoutput[0]);
927
		$macaddr = $arpi[3];
928
		if (is_macaddr($macaddr))
929
			return $macaddr;
930
		else
931
			return false;
932
	}
933

    
934
	return false;
935
}
936

    
937
/* return a fieldname that is safe for xml usage */
938
function xml_safe_fieldname($fieldname) {
939
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
940
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
941
			 ':', ',', '.', '\'', '\\'
942
		);
943
	return strtolower(str_replace($replace, "", $fieldname));
944
}
945

    
946
function mac_format($clientmac) {
947
    $mac =explode(":", $clientmac);
948

    
949
    global $config;
950

    
951
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
952

    
953
    switch($mac_format) {
954

    
955
        case 'singledash':
956
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
957

    
958
        case 'ietf':
959
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
960

    
961
        case 'cisco':
962
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
963

    
964
        case 'unformatted':
965
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
966

    
967
        default:
968
        return $clientmac;
969
    }
970
}
971

    
972
function resolve_retry($hostname, $retries = 5) {
973

    
974
       if (is_ipaddr($hostname))
975
               return $hostname;
976

    
977
       for ($i = 0; $i < $retries; $i++) {
978
               $ip = gethostbyname($hostname);
979

    
980
               if ($ip && $ip != $hostname) {
981
                       /* success */
982
                       return $ip;
983
               }
984

    
985
               sleep(1);
986
       }
987

    
988
       return false;
989
}
990

    
991
function format_bytes($bytes) {
992
	if ($bytes >= 1073741824) {
993
		return sprintf("%.2f GB", $bytes/1073741824);
994
	} else if ($bytes >= 1048576) {
995
		return sprintf("%.2f MB", $bytes/1048576);
996
	} else if ($bytes >= 1024) {
997
		return sprintf("%.0f KB", $bytes/1024);
998
	} else {
999
		return sprintf("%d bytes", $bytes);
1000
	}
1001
}
1002

    
1003
function update_filter_reload_status($text) {
1004
        global $g;
1005

    
1006
        file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1007
}
1008

    
1009
/****f* util/return_dir_as_array
1010
 * NAME
1011
 *   return_dir_as_array - Return a directory's contents as an array.
1012
 * INPUTS
1013
 *   $dir       - string containing the path to the desired directory.
1014
 * RESULT
1015
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1016
 ******/
1017
function return_dir_as_array($dir) {
1018
        $dir_array = array();
1019
        if (is_dir($dir)) {
1020
                if ($dh = opendir($dir)) {
1021
                        while (($file = readdir($dh)) !== false) {
1022
                                $canadd = 0;
1023
                                if($file == ".") $canadd = 1;
1024
                                if($file == "..") $canadd = 1;
1025
                                if($canadd == 0)
1026
                                        array_push($dir_array, $file);
1027
                        }
1028
                        closedir($dh);
1029
                }
1030
        }
1031
        return $dir_array;
1032
}
1033

    
1034
function run_plugins($directory) {
1035
        global $config, $g;
1036

    
1037
		/* process packager manager custom rules */
1038
		$files = return_dir_as_array($directory);
1039
		if (is_array($files)) {
1040
			foreach ($files as $file) {
1041
				if (stristr($file, ".sh") == true)
1042
					mwexec($directory . $file . " start");
1043
				else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1044
					require_once($directory . "/" . $file);
1045
			}
1046
		}
1047
}
1048

    
1049
/*
1050
 *    safe_mkdir($path, $mode = 0755)
1051
 *    create directory if it doesn't already exist and isn't a file!
1052
 */
1053
function safe_mkdir($path, $mode=0755) {
1054
        global $g;
1055

    
1056
        if (!is_file($path) && !is_dir($path)) {
1057
                return @mkdir($path, $mode);
1058
        } else {
1059
                return false;
1060
        }
1061
}
1062

    
1063
/*
1064
 * make_dirs($path, $mode = 0755)
1065
 * create directory tree recursively (mkdir -p)
1066
 */
1067
function make_dirs($path, $mode = 0755) {
1068
        $base = '';
1069
        foreach (explode('/', $path) as $dir) {
1070
                $base .= "/$dir";
1071
                if (!is_dir($base)) {
1072
                        if (!@mkdir($base, $mode))
1073
                                return false;
1074
                }
1075
        }
1076
        return true;
1077
}
1078

    
1079
/*
1080
 *     get_memory()
1081
 *     returns an array listing the amount of
1082
 *     memory installed in the hardware
1083
 *     [0]real and [1]available
1084
 */
1085
function get_memory() {
1086
		$matches = "";
1087
        if(file_exists("/var/log/dmesg.boot"))
1088
			$mem = `cat /var/log/dmesg.boot | grep memory`;
1089
		else
1090
			$mem = `dmesg -a | grep memory`;			
1091
		if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1092
			return array($matches[1][0], $matches[1][0]);
1093
		if(!$real && !$avail) {
1094
			$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1095
			$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1096
			return array(($real/1024),($avail/1024));
1097
		}
1098
}
1099

    
1100
function mute_kernel_msgs() {
1101
		global $config;
1102
		// Do not mute serial console.  The kernel gets very very cranky
1103
		// and will start dishing you cannot control tty errors.
1104
		if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1105
			return;
1106
		if($config['system']['enableserial']) 
1107
			return;			
1108
		exec("/sbin/conscontrol mute on");
1109
}
1110

    
1111
function unmute_kernel_msgs() {
1112
		global $config;
1113
		// Do not mute serial console.  The kernel gets very very cranky
1114
		// and will start dishing you cannot control tty errors.
1115
		if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1116
			return;
1117
		exec("/sbin/conscontrol mute off");
1118
}
1119

    
1120
function start_devd() {
1121
	global $g;
1122

    
1123
        exec("/sbin/devd");
1124
        sleep(1);
1125
        if(file_exists("{$g['tmp_path']}/rc.linkup"))
1126
                unlink("{$g['tmp_path']}/rc.linkup");
1127
}
1128

    
1129
function is_interface_mismatch() {
1130
        global $config, $g;
1131

    
1132
        /* XXX: Should we process only enabled interfaces?! */
1133
        $do_assign = false;
1134
        $i = 0;
1135
        foreach ($config['interfaces'] as $ifname => $ifcfg) {
1136
                if (preg_match("/^enc|^cua|^tun|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1137
                        $i++;
1138
                }
1139
                else if (does_interface_exist($ifcfg['if']) == false) {
1140
                        $do_assign = true;
1141
                } else
1142
                        $i++;
1143
        }
1144

    
1145
        if ($g['minimum_nic_count'] > $i) {
1146
                $do_assign = true;
1147
        } else if (file_exists("{$g['tmp_path']}/assign_complete"))
1148
                $do_assign = false;
1149

    
1150
        return $do_assign;
1151
}
1152

    
1153
/* sync carp entries to other firewalls */
1154
function carp_sync_client() {
1155
	global $g;
1156
	touch($g['tmp_path'] . "/filter_sync"); 
1157
}
1158

    
1159
/****f* util/isAjax
1160
 * NAME
1161
 *   isAjax - reports if the request is driven from prototype
1162
 * INPUTS
1163
 *   none
1164
 * RESULT
1165
 *   true/false
1166
 ******/
1167
function isAjax() {
1168
        return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1169
}
1170

    
1171
/****f* util/timeout
1172
 * NAME
1173
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1174
 * INPUTS
1175
 *   optional, seconds to wait before timeout. Default 9 seconds.
1176
 * RESULT
1177
 *   returns 1 char of user input or null if no input.
1178
 ******/
1179
function timeout($timer = 9) {
1180
	while(!isset($key)) {
1181
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1182
		else { echo chr(8). "{$timer}"; }
1183
		`/bin/stty -icanon min 0 time 25`;
1184
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1185
		`/bin/stty icanon`;
1186
		if ($key == '')
1187
			unset($key);
1188
		$timer--;
1189
		if ($timer == 0)
1190
			break;
1191
	}
1192
	return $key;	
1193
}
1194

    
1195
/****f* util/msort
1196
 * NAME
1197
 *   msort - sort array
1198
 * INPUTS
1199
 *   $array to be sorted, field to sort by, direction of sort
1200
 * RESULT
1201
 *   returns newly sorted array
1202
 ******/
1203
function msort($array, $id="id", $sort_ascending=true) {
1204
	$temp_array = array();
1205
	while(count($array)>0) {
1206
		$lowest_id = 0;
1207
		$index=0;
1208
		foreach ($array as $item) {
1209
			if (isset($item[$id])) {
1210
				if ($array[$lowest_id][$id]) {
1211
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1212
						$lowest_id = $index;
1213
					}
1214
				}
1215
			}
1216
			$index++;
1217
		}
1218
		$temp_array[] = $array[$lowest_id];
1219
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1220
	}
1221
	if ($sort_ascending) {
1222
		return $temp_array;
1223
	} else {
1224
    	return array_reverse($temp_array);
1225
	}
1226
}
1227

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

    
1301
/****f* util/is_URL
1302
 * NAME
1303
 *   is_URL
1304
 * INPUTS
1305
 *   string to check
1306
 * RESULT
1307
 *   Returns true if item is a URL
1308
 ******/
1309
function is_URL($url) {
1310
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1311
	if($match)
1312
		return true;	
1313
	return false;
1314
}
1315

    
1316
function is_file_included($file = "") {
1317
	$files = get_included_files();
1318
	if (in_array($file, $files))
1319
		return true;
1320
	
1321
	return false;
1322
}
1323

    
1324
?>
(41-41/50)