Project

General

Profile

Download (35.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, $op = LOCK_SH) {
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, $op))
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 long2ip32(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 long int to IP address, truncating to 32-bits. */
220
function long2ip32($ip) {
221
	return long2ip($ip & 0xFFFFFFFF);
222
}
223

    
224
/* Convert IP address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. */
225
function ip2long32($ip) {
226
	return ( ip2long($ip) & 0xFFFFFFFF );
227
}
228

    
229
/* Convert IP address to unsigned long int. */
230
function ip2ulong($ip) {
231
	return sprintf("%u", ip2long32($ip));
232
}
233

    
234
/* Find out how many IPs are contained within a given IP range
235
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
236
 */
237
function ip_range_size($startip, $endip) {
238
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
239
		// Operate as unsigned long because otherwise it wouldn't work
240
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
241
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
242
	}
243
	return -1;
244
}
245

    
246
/* Find the smallest possible subnet mask which can contain a given number of IPs
247
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
248
 */
249
function find_smallest_cidr($number) {
250
	$smallest = 1;
251
	for ($b=32; $b > 0; $b--) {
252
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
253
	}
254
	return (32-$smallest);
255
}
256

    
257
/* Return the previous IP address before the given address */
258
function ip_before($ip) {
259
	return long2ip32(ip2long($ip)-1);
260
}
261

    
262
/* Return the next IP address after the given address */
263
function ip_after($ip) {
264
	return long2ip32(ip2long($ip)+1);
265
}
266

    
267
/* Return true if the first IP is 'before' the second */
268
function ip_less_than($ip1, $ip2) {
269
	// Compare as unsigned long because otherwise it wouldn't work when
270
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
271
	return ip2ulong($ip1) < ip2ulong($ip2);
272
}
273

    
274
/* Return true if the first IP is 'after' the second */
275
function ip_greater_than($ip1, $ip2) {
276
	// Compare as unsigned long because otherwise it wouldn't work
277
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
278
	return ip2ulong($ip1) > ip2ulong($ip2);
279
}
280

    
281
/* Convert a range of IPs to an array of subnets which can contain the range. */
282
function ip_range_to_subnet_array($startip, $endip) {
283
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
284
		return array();
285
	}
286

    
287
	// Container for subnets within this range.
288
	$rangesubnets = array();
289

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

    
293
	// Loop here to reduce subnet size and retest as needed. We need to make sure
294
	//   that the target subnet is wholly contained between $startip and $endip.
295
	for ($cidr; $cidr <= 32; $cidr++) {
296
		// Find the network and broadcast addresses for the subnet being tested.
297
		$targetsub_min = gen_subnet($startip, $cidr);
298
		$targetsub_max = gen_subnet_max($startip, $cidr);
299

    
300
		// Check best case where the range is exactly one subnet.
301
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
302
			// Hooray, the range is exactly this subnet!
303
			return array("{$startip}/{$cidr}");
304
		}
305

    
306
		// These remaining scenarios will find a subnet that uses the largest
307
		//  chunk possible of the range being tested, and leave the rest to be
308
		//  tested recursively after the loop.
309

    
310
		// Check if the subnet begins with $startip and ends before $endip
311
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
312
			break;
313
		}
314

    
315
		// Check if the subnet ends at $endip and starts after $startip
316
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
317
			break;
318
		}
319

    
320
		// Check if the subnet is between $startip and $endip
321
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
322
			break;
323
		}
324
	}
325

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

    
332
	// Add in the subnet we found before, to preserve ordering
333
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
334

    
335
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
336
	if ($endip != $targetsub_max) {
337
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
338
	}
339
	return $rangesubnets;
340
}
341

    
342
function is_iprange($range) {
343
	if (substr_count($range, '-') != 1) {
344
		return false;
345
	}
346
	list($ip1, $ip2) = explode ('-', $range);
347
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
348
}
349

    
350
function is_numericint($arg) {
351
	return (preg_match("/[^0-9]/", $arg) ? false : true);
352
}
353

    
354
/* returns true if $ipaddr is a valid dotted IPv4 address */
355
function is_ipaddr($ipaddr) {
356
	if (!is_string($ipaddr))
357
		return false;
358

    
359
	$ip_long = ip2long($ipaddr);
360
	$ip_reverse = long2ip32($ip_long);
361

    
362
	if ($ipaddr == $ip_reverse)
363
		return true;
364
	else
365
		return false;
366
}
367

    
368
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
369
function is_ipaddroralias($ipaddr) {
370
	global $config;
371

    
372
	if (is_alias($ipaddr)) {
373
		if (is_array($config['aliases']['alias'])) {
374
			foreach ($config['aliases']['alias'] as $alias) {
375
                        	if ($alias['name'] == $ipaddr && $alias['type'] != "port")
376
					return true;
377
			}
378
                }
379
		return false;
380
	} else
381
		return is_ipaddr($ipaddr);
382

    
383
}
384

    
385
/* returns true if $subnet is a valid subnet in CIDR format */
386
function is_subnet($subnet) {
387
	if (!is_string($subnet))
388
		return false;
389

    
390
	list($hp,$np) = explode('/', $subnet);
391

    
392
	if (!is_ipaddr($hp))
393
		return false;
394

    
395
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
396
		return false;
397

    
398
	return true;
399
}
400

    
401
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
402
function is_subnetoralias($subnet) {
403

    
404
	global $aliastable;
405

    
406
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
407
		return true;
408
	else
409
		return is_subnet($subnet);
410
}
411

    
412
/* returns true if $hostname is a valid hostname */
413
function is_hostname($hostname) {
414
	if (!is_string($hostname))
415
		return false;
416

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

    
423
/* returns true if $domain is a valid domain name */
424
function is_domain($domain) {
425
	if (!is_string($domain))
426
		return false;
427

    
428
	if (preg_match("/^([a-z0-9\-]+\.?)+$/i", $domain))
429
		return true;
430
	else
431
		return false;
432
}
433

    
434
/* returns true if $macaddr is a valid MAC address */
435
function is_macaddr($macaddr) {
436
	if (!is_string($macaddr))
437
		return false;
438

    
439
	$maca = explode(":", $macaddr);
440
	if (count($maca) != 6)
441
		return false;
442

    
443
	foreach ($maca as $macel) {
444
		if (($macel === "") || (strlen($macel) > 2))
445
			return false;
446
		if (preg_match("/[^0-9a-f]/i", $macel))
447
			return false;
448
	}
449

    
450
	return true;
451
}
452

    
453
/* returns true if $name is a valid name for an alias */
454
/* returns NULL if a reserved word is used */
455
function is_validaliasname($name) {
456
	/* Array of reserved words */
457
	$reserved = array("port", "pass");
458
	if (in_array($name, $reserved, true))
459
		return; /* return NULL */
460

    
461
	if (!preg_match("/[^a-zA-Z0-9_]/", $name))
462
		return true;
463
	else
464
		return false;
465
}
466

    
467
/* returns true if $port is a valid TCP/UDP port */
468
function is_port($port) {
469
	$tmpports = explode(":", $port);
470
	foreach($tmpports as $tmpport) {
471
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
472
                	continue;
473
		if (!ctype_digit($tmpport))
474
			return false;
475
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
476
			return false;
477
	}
478
	return true;
479
}
480

    
481
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
482
function is_portrange($portrange) {
483
        $ports = explode(":", $portrange);
484

    
485
        if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
486
                return true;
487
        else
488
                return false;
489
}
490

    
491
/* returns true if $port is a valid port number or an alias thereof */
492
function is_portoralias($port) {
493
	global $config;
494

    
495
        if (is_alias($port)) {
496
                if (is_array($config['aliases']['alias'])) {
497
                        foreach ($config['aliases']['alias'] as $alias) {
498
                                if ($alias['name'] == $port && $alias['type'] == "port")
499
                                        return true;
500
                        }
501
                }
502
                return false;
503
        } else
504
                return is_port($port);
505
}
506

    
507
/* returns true if $val is a valid shaper bandwidth value */
508
function is_valid_shaperbw($val) {
509
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
510
}
511

    
512
/* return the configured carp interface list */
513
function get_configured_carp_interface_list() {
514
	global $config;
515

    
516
	$iflist = array();
517

    
518
	if(is_array($config['virtualip']['vip'])) {
519
                $viparr = &$config['virtualip']['vip'];
520
                foreach ($viparr as $vip) {
521
                        switch ($vip['mode']) {
522
                        case "carp":
523
                        case "carpdev-dhcp":
524
				$vipif = "vip" . $vip['vhid'];
525
                        	$iflist[$vipif] = $vip['subnet'];
526
                                break;
527
                        }
528
                }
529
        }
530

    
531
	return $iflist;
532
}
533

    
534
/* return the configured IP aliases list */
535
function get_configured_ip_aliases_list() {
536
        global $config;
537

    
538
        $alias_list=array();
539

    
540
        if(is_array($config['virtualip']['vip'])) {
541
                $viparr = &$config['virtualip']['vip'];
542
                foreach ($viparr as $vip) {
543
                        if ($vip['mode']=="ipalias") {
544
                                $alias_list[$vip['subnet']] = $vip['interface'];
545
                        }
546
                }
547
        }
548

    
549
        return $alias_list;
550
}
551

    
552

    
553
/* return the configured interfaces list. */
554
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
555
	global $config;
556

    
557
	$iflist = array();
558

    
559
	if (!$only_opt) {
560
		if (isset($config['interfaces']['wan']))
561
			$iflist['wan'] = "wan";
562
		if (isset($config['interfaces']['lan']))
563
			$iflist['lan'] = "lan";
564
	}
565

    
566
	/* if list */
567
        foreach($config['interfaces'] as $if => $ifdetail) {
568
		if ($if == "wan" || $if == "lan")
569
			continue;
570
		if (isset($ifdetail['enable']) || $withdisabled == true)
571
			$iflist[$if] = $if;
572
	}
573

    
574
	return $iflist;
575
}
576

    
577
/* return the configured interfaces list. */
578
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
579
        global $config;
580

    
581
        $iflist = array();
582

    
583
        if (!$only_opt) {
584
                if (isset($config['interfaces']['wan'])) {
585
			$tmpif = get_real_interface("wan");
586
			if (!empty($tmpif))
587
				$iflist[$tmpif] = "wan";
588
		}
589
                if (isset($config['interfaces']['lan'])) {
590
			$tmpif = get_real_interface("lan");
591
			if (!empty($tmpif))
592
				$iflist[$tmpif] = "lan";
593
		}
594
        }
595

    
596
        /* if list */
597
        foreach($config['interfaces'] as $if => $ifdetail) {
598
                if ($if == "wan" || $if == "lan")
599
                        continue;
600
                if (isset($ifdetail['enable']) || $withdisabled == true) {
601
			$tmpif = get_real_interface($if);
602
			if (!empty($tmpif))
603
				$iflist[$tmpif] = $if;
604
		}
605
        }
606

    
607
        return $iflist;
608
}
609

    
610
/* return the configured interfaces list with their description. */
611
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
612
	global $config;
613

    
614
	$iflist = array();
615

    
616
	if (!$only_opt) {
617
		if (isset($config['interfaces']['wan'])) {
618
			if (empty($config['interfaces']['wan']['descr']))
619
				$iflist['wan'] = "WAN";
620
			else
621
				$iflist['wan'] = strtoupper($config['interfaces']['wan']['descr']);
622
		}
623
		if (isset($config['interfaces']['lan'])) {
624
			if (empty($config['interfaces']['lan']['descr']))
625
				$iflist['lan'] = "LAN";
626
			else
627
				$iflist['lan'] = strtoupper($config['interfaces']['lan']['descr']);
628
		}
629
	}
630

    
631
	/* if list */
632
	foreach($config['interfaces'] as $if => $ifdetail) {
633
		if (isset($ifdetail['enable']) || $withdisabled == true) {
634
			if($ifdetail['descr'] == "")
635
				$iflist[$if] = strtoupper($if);
636
			else
637
				$iflist[$if] = strtoupper($ifdetail['descr']);
638
		}
639
	}
640

    
641
	return $iflist;
642
}
643

    
644

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

    
752
/****f* util/log_error
753
* NAME
754
*   log_error  - Sends a string to syslog.
755
* INPUTS
756
*   $error     - string containing the syslog message.
757
* RESULT
758
*   null
759
******/
760
function log_error($error) {
761
        global $g;
762
        $page = $_SERVER['SCRIPT_NAME'];
763
        syslog(LOG_WARNING, "$page: $error");
764
        if ($g['debug'])
765
                syslog(LOG_WARNING, var_dump(debug_backtrace()));
766
        return;
767
}
768

    
769
/****f* util/exec_command
770
 * NAME
771
 *   exec_command - Execute a command and return a string of the result.
772
 * INPUTS
773
 *   $command   - String of the command to be executed.
774
 * RESULT
775
 *   String containing the command's result.
776
 * NOTES
777
 *   This function returns the command's stdout and stderr.
778
 ******/
779
function exec_command($command) {
780
        $output = array();
781
        exec($command . ' 2>&1 ', $output);
782
        return(implode("\n", $output));
783
}
784

    
785
/* wrapper for exec() */
786
function mwexec($command, $mute = false) {
787

    
788
	global $g;
789
	$oarr = array();
790
	$retval = 0;
791
	if ($g['debug']) {
792
		if (!$_SERVER['REMOTE_ADDR'])
793
			echo "mwexec(): $command\n";
794
		exec("$command 2>&1", $oarr, $retval);
795
	} else {
796
		exec("$command 2>&1", $oarr, $retval);
797
	}
798
	if(isset($config['system']['developerspew']))
799
                $mute = false;
800
	if(($retval <> 0) && ($mute === false)) {
801
		$output = implode(" ", $oarr);
802
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
803
	}
804
	return $retval;
805
}
806

    
807
/* wrapper for exec() in background */
808
function mwexec_bg($command) {
809

    
810
	global $g;
811

    
812
	if ($g['debug']) {
813
		if (!$_SERVER['REMOTE_ADDR'])
814
			echo "mwexec(): $command\n";
815
	}
816

    
817
	exec("nohup $command > /dev/null 2>&1 &");
818
}
819

    
820
/* unlink a file, if it exists */
821
function unlink_if_exists($fn) {
822
	$to_do = glob($fn);
823
	if(is_array($to_do)) {
824
		foreach($to_do as $filename)
825
			@unlink($filename);
826
	} else {
827
		@unlink($fn);
828
	}
829
}
830
/* make a global alias table (for faster lookups) */
831
function alias_make_table($config) {
832

    
833
	global $aliastable;
834

    
835
	$aliastable = array();
836

    
837
	if (is_array($config['aliases']['alias'])) {
838
		foreach ($config['aliases']['alias'] as $alias) {
839
			if ($alias['name'])
840
				$aliastable[$alias['name']] = $alias['address'];
841
		}
842
	}
843
}
844
/* check if an alias exists */
845
function is_alias($name) {
846

    
847
	global $aliastable;
848

    
849
	return isset($aliastable[$name]);
850
}
851

    
852
/* expand a host or network alias, if necessary */
853
function alias_expand($name) {
854

    
855
	global $aliastable;
856

    
857
	if (isset($aliastable[$name]))
858
		return "\${$name}";
859
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
860
		return "{$name}";
861
	else
862
		return null;
863
}
864

    
865
function alias_expand_urltable($name) {
866
	global $config;
867
	$urltable_prefix = "/var/db/aliastables/";
868
	$urltable_filename = $urltable_prefix . $name . ".txt";
869

    
870
	foreach ($config['aliases']['alias'] as $alias) {
871
		if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
872
			if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
873
				return $urltable_filename;
874
			else if (process_alias_urltable($name, $alias["url"], 0, true))
875
				return $urltable_filename;
876
		}
877
	}
878
	return null;
879
}
880

    
881
/* find out whether two subnets overlap */
882
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
883

    
884
	if (!is_numeric($bits1))
885
		$bits1 = 32;
886
	if (!is_numeric($bits2))
887
		$bits2 = 32;
888

    
889
	if ($bits1 < $bits2)
890
		$relbits = $bits1;
891
	else
892
		$relbits = $bits2;
893

    
894
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
895
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
896

    
897
	if ($sn1 == $sn2)
898
		return true;
899
	else
900
		return false;
901
}
902

    
903
/* compare two IP addresses */
904
function ipcmp($a, $b) {
905
	if (ip_less_than($a, $b))
906
		return -1;
907
	else if (ip_greater_than($a, $b))
908
		return 1;
909
	else
910
		return 0;
911
}
912

    
913
/* return true if $addr is in $subnet, false if not */
914
function ip_in_subnet($addr,$subnet) {
915
	list($ip, $mask) = explode('/', $subnet);
916
	$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
917
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
918
}
919

    
920
/* verify (and remove) the digital signature on a file - returns 0 if OK */
921
function verify_digital_signature($fname) {
922
	global $g;
923

    
924
	if(!file_exists("/usr/local/sbin/gzsig"))
925
		return 4;
926

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

    
930
/* obtain MAC address given an IP address by looking at the ARP table */
931
function arp_get_mac_by_ip($ip) {
932
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
933
	$arpoutput = "";
934
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
935

    
936
	if ($arpoutput[0]) {
937
		$arpi = explode(" ", $arpoutput[0]);
938
		$macaddr = $arpi[3];
939
		if (is_macaddr($macaddr))
940
			return $macaddr;
941
		else
942
			return false;
943
	}
944

    
945
	return false;
946
}
947

    
948
/* return a fieldname that is safe for xml usage */
949
function xml_safe_fieldname($fieldname) {
950
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
951
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
952
			 ':', ',', '.', '\'', '\\'
953
		);
954
	return strtolower(str_replace($replace, "", $fieldname));
955
}
956

    
957
function mac_format($clientmac) {
958
    $mac =explode(":", $clientmac);
959

    
960
    global $config;
961

    
962
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
963

    
964
    switch($mac_format) {
965

    
966
        case 'singledash':
967
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
968

    
969
        case 'ietf':
970
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
971

    
972
        case 'cisco':
973
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
974

    
975
        case 'unformatted':
976
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
977

    
978
        default:
979
        return $clientmac;
980
    }
981
}
982

    
983
function resolve_retry($hostname, $retries = 5) {
984

    
985
       if (is_ipaddr($hostname))
986
               return $hostname;
987

    
988
       for ($i = 0; $i < $retries; $i++) {
989
               $ip = gethostbyname($hostname);
990

    
991
               if ($ip && $ip != $hostname) {
992
                       /* success */
993
                       return $ip;
994
               }
995

    
996
               sleep(1);
997
       }
998

    
999
       return false;
1000
}
1001

    
1002
function format_bytes($bytes) {
1003
	if ($bytes >= 1073741824) {
1004
		return sprintf("%.2f GB", $bytes/1073741824);
1005
	} else if ($bytes >= 1048576) {
1006
		return sprintf("%.2f MB", $bytes/1048576);
1007
	} else if ($bytes >= 1024) {
1008
		return sprintf("%.0f KB", $bytes/1024);
1009
	} else {
1010
		return sprintf("%d bytes", $bytes);
1011
	}
1012
}
1013

    
1014
function update_filter_reload_status($text) {
1015
        global $g;
1016

    
1017
        file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1018
}
1019

    
1020
/****f* util/return_dir_as_array
1021
 * NAME
1022
 *   return_dir_as_array - Return a directory's contents as an array.
1023
 * INPUTS
1024
 *   $dir       - string containing the path to the desired directory.
1025
 * RESULT
1026
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1027
 ******/
1028
function return_dir_as_array($dir) {
1029
        $dir_array = array();
1030
        if (is_dir($dir)) {
1031
                if ($dh = opendir($dir)) {
1032
                        while (($file = readdir($dh)) !== false) {
1033
                                $canadd = 0;
1034
                                if($file == ".") $canadd = 1;
1035
                                if($file == "..") $canadd = 1;
1036
                                if($canadd == 0)
1037
                                        array_push($dir_array, $file);
1038
                        }
1039
                        closedir($dh);
1040
                }
1041
        }
1042
        return $dir_array;
1043
}
1044

    
1045
function run_plugins($directory) {
1046
        global $config, $g;
1047

    
1048
		/* process packager manager custom rules */
1049
		$files = return_dir_as_array($directory);
1050
		if (is_array($files)) {
1051
			foreach ($files as $file) {
1052
				if (stristr($file, ".sh") == true)
1053
					mwexec($directory . $file . " start");
1054
				else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1055
					require_once($directory . "/" . $file);
1056
			}
1057
		}
1058
}
1059

    
1060
/*
1061
 *    safe_mkdir($path, $mode = 0755)
1062
 *    create directory if it doesn't already exist and isn't a file!
1063
 */
1064
function safe_mkdir($path, $mode=0755) {
1065
        global $g;
1066

    
1067
        if (!is_file($path) && !is_dir($path)) {
1068
                return @mkdir($path, $mode);
1069
        } else {
1070
                return false;
1071
        }
1072
}
1073

    
1074
/*
1075
 * make_dirs($path, $mode = 0755)
1076
 * create directory tree recursively (mkdir -p)
1077
 */
1078
function make_dirs($path, $mode = 0755) {
1079
        $base = '';
1080
        foreach (explode('/', $path) as $dir) {
1081
                $base .= "/$dir";
1082
                if (!is_dir($base)) {
1083
                        if (!@mkdir($base, $mode))
1084
                                return false;
1085
                }
1086
        }
1087
        return true;
1088
}
1089

    
1090
/*
1091
 *     get_memory()
1092
 *     returns an array listing the amount of
1093
 *     memory installed in the hardware
1094
 *     [0]real and [1]available
1095
 */
1096
function get_memory() {
1097
		$matches = "";
1098
        if(file_exists("/var/log/dmesg.boot"))
1099
			$mem = `cat /var/log/dmesg.boot | grep memory`;
1100
		else
1101
			$mem = `dmesg -a | grep memory`;			
1102
		if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1103
			return array($matches[1][0], $matches[1][0]);
1104
		if(!$real && !$avail) {
1105
			$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1106
			$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1107
			return array(($real/1024),($avail/1024));
1108
		}
1109
}
1110

    
1111
function mute_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
		if($config['system']['enableserial']) 
1118
			return;			
1119
		exec("/sbin/conscontrol mute on");
1120
}
1121

    
1122
function unmute_kernel_msgs() {
1123
		global $config;
1124
		// Do not mute serial console.  The kernel gets very very cranky
1125
		// and will start dishing you cannot control tty errors.
1126
		if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1127
			return;
1128
		exec("/sbin/conscontrol mute off");
1129
}
1130

    
1131
function start_devd() {
1132
	global $g;
1133

    
1134
        exec("/sbin/devd");
1135
        sleep(1);
1136
        if(file_exists("{$g['tmp_path']}/rc.linkup"))
1137
                unlink("{$g['tmp_path']}/rc.linkup");
1138
}
1139

    
1140
function is_interface_mismatch() {
1141
        global $config, $g;
1142

    
1143
        /* XXX: Should we process only enabled interfaces?! */
1144
        $do_assign = false;
1145
        $i = 0;
1146
        foreach ($config['interfaces'] as $ifname => $ifcfg) {
1147
                if (preg_match("/^enc|^cua|^tun|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1148
                        $i++;
1149
                }
1150
                else if (does_interface_exist($ifcfg['if']) == false) {
1151
                        $do_assign = true;
1152
                } else
1153
                        $i++;
1154
        }
1155

    
1156
        if ($g['minimum_nic_count'] > $i) {
1157
                $do_assign = true;
1158
        } else if (file_exists("{$g['tmp_path']}/assign_complete"))
1159
                $do_assign = false;
1160

    
1161
        return $do_assign;
1162
}
1163

    
1164
/* sync carp entries to other firewalls */
1165
function carp_sync_client() {
1166
	global $g;
1167
	touch($g['tmp_path'] . "/filter_sync"); 
1168
}
1169

    
1170
/****f* util/isAjax
1171
 * NAME
1172
 *   isAjax - reports if the request is driven from prototype
1173
 * INPUTS
1174
 *   none
1175
 * RESULT
1176
 *   true/false
1177
 ******/
1178
function isAjax() {
1179
        return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1180
}
1181

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

    
1206
/****f* util/msort
1207
 * NAME
1208
 *   msort - sort array
1209
 * INPUTS
1210
 *   $array to be sorted, field to sort by, direction of sort
1211
 * RESULT
1212
 *   returns newly sorted array
1213
 ******/
1214
function msort($array, $id="id", $sort_ascending=true) {
1215
	$temp_array = array();
1216
	while(count($array)>0) {
1217
		$lowest_id = 0;
1218
		$index=0;
1219
		foreach ($array as $item) {
1220
			if (isset($item[$id])) {
1221
				if ($array[$lowest_id][$id]) {
1222
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1223
						$lowest_id = $index;
1224
					}
1225
				}
1226
			}
1227
			$index++;
1228
		}
1229
		$temp_array[] = $array[$lowest_id];
1230
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1231
	}
1232
	if ($sort_ascending) {
1233
		return $temp_array;
1234
	} else {
1235
    	return array_reverse($temp_array);
1236
	}
1237
}
1238

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

    
1312
/****f* util/is_URL
1313
 * NAME
1314
 *   is_URL
1315
 * INPUTS
1316
 *   string to check
1317
 * RESULT
1318
 *   Returns true if item is a URL
1319
 ******/
1320
function is_URL($url) {
1321
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1322
	if($match)
1323
		return true;	
1324
	return false;
1325
}
1326

    
1327
function is_file_included($file = "") {
1328
	$files = get_included_files();
1329
	if (in_array($file, $files))
1330
		return true;
1331
	
1332
	return false;
1333
}
1334

    
1335
?>
(41-41/50)