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
		);
681
	}
682
	switch($mode) {
683
	case "active":
684
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
685
        	break;
686
	case "media":
687
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
688
                $ifconfig = "";
689
                exec("/sbin/ifconfig -a", $ifconfig);
690
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
691
                $ifstatus = preg_grep('/status:/', $ifconfig);
692
		foreach($ifstatus as $status) {
693
			$int = array_shift($intlist);
694
                	if(stristr($status, "active")) $upints[] = $int;
695
		}
696
		break;
697
	}
698
        /* build interface list with netstat */
699
        $linkinfo = "";
700
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
701
        array_shift($linkinfo);
702
	/* build ip address list with netstat */
703
	$ipinfo = "";
704
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
705
	array_shift($ipinfo);
706
	foreach($linkinfo as $link) {
707
		$friendly = "";
708
                $alink = explode(" ", $link);
709
                $ifname = rtrim(trim($alink[0]), '*');
710
                /* trim out all numbers before checking for vfaces */
711
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces) &&
712
			!stristr($ifname, "_vlan") && !stristr($ifname, "_wlan")) {
713
			$toput = array(
714
					"mac" => trim($alink[1]),
715
					"up" => in_array($ifname, $upints)
716
				);
717
			foreach($ipinfo as $ip) {
718
				$aip = explode(" ", $ip);
719
				if($aip[0] == $ifname) {
720
					$toput['ipaddr'] = $aip[1];
721
				}
722
			}
723
			foreach($config['interfaces'] as $name => $int) {
724
				if($int['if'] == $ifname) $friendly = $name;
725
			}
726
			switch($keyby) {
727
			case "physical":
728
				if($friendly != "") {
729
					$toput['friendly'] = $friendly;
730
				}
731
				$dmesg_arr = array();
732
				exec("/sbin/dmesg |grep $ifname | head -n1", $dmesg_arr);
733
				preg_match_all("/<(.*?)>/i", $dmesg_arr[0], $dmesg);
734
				$toput['dmesg'] = $dmesg[1][0];
735
				$iflist[$ifname] = $toput;
736
				break;
737
			case "ppp":
738
				
739
			case "friendly":
740
				if($friendly != "") {
741
					$toput['if'] = $ifname;
742
					$iflist[$friendly] = $toput;
743
				}
744
				break;
745
			}
746
                }
747
        }
748
        return $iflist;
749
}
750

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

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

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

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

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

    
809
	global $g;
810

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

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

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

    
832
	global $aliastable;
833

    
834
	$aliastable = array();
835

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

    
846
	global $aliastable;
847

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

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

    
854
	global $aliastable;
855

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
944
	return false;
945
}
946

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

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

    
959
    global $config;
960

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

    
963
    switch($mac_format) {
964

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

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

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

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

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

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

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

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

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

    
995
               sleep(1);
996
       }
997

    
998
       return false;
999
}
1000

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1160
        return $do_assign;
1161
}
1162

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

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

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

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

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

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

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

    
1334
?>
(41-41/50)