Project

General

Profile

Download (85.6 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/pfsense-utils
3
	NAME
4
		pfsense-utils.inc - Utilities specific to pfSense
5
	DESCRIPTION
6
		This include contains various pfSense specific functions.
7
	HISTORY
8
		$Id$
9

    
10
	Copyright (C) 2004-2007 Scott Ullrich (sullrich@gmail.com)
11
	All rights reserved.
12
	Redistribution and use in source and binary forms, with or without
13
	modification, are permitted provided that the following conditions are met:
14

    
15
	1. Redistributions of source code must retain the above copyright notice,
16
	   this list of conditions and the following disclaimer.
17

    
18
	2. Redistributions in binary form must reproduce the above copyright
19
	   notice, this list of conditions and the following disclaimer in the
20
	   documentation and/or other materials provided with the distribution.
21

    
22
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
26
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
	POSSIBILITY OF SUCH DAMAGE.
32
*/
33

    
34
/*
35
	pfSense_BUILDER_BINARIES:	/sbin/ifconfig	/sbin/pfctl	/usr/local/bin/php-cgi
36
	pfSense_BUILDER_BINARIES:	/bin/df	/usr/bin/grep	/usr/bin/awk	/bin/rm	/usr/sbin/pwd_mkdb	/usr/bin/host
37
	pfSense_BUILDER_BINARIES:	/sbin/kldload
38
	pfSense_MODULE:	utils
39
*/
40

    
41
/****f* pfsense-utils/have_natpfruleint_access
42
 * NAME
43
 *   have_natpfruleint_access
44
 * INPUTS
45
 *	none
46
 * RESULT
47
 *   returns true if user has access to edit a specific firewall nat port forward interface
48
 ******/
49
function have_natpfruleint_access($if) {
50
	$security_url = "firewall_nat_edit.php?if=". strtolower($if);
51
	if (isAllowedPage($security_url, $allowed)) {
52
		return true;
53
	}
54
	return false;
55
}
56

    
57
/****f* pfsense-utils/have_ruleint_access
58
 * NAME
59
 *   have_ruleint_access
60
 * INPUTS
61
 *	none
62
 * RESULT
63
 *   returns true if user has access to edit a specific firewall interface
64
 ******/
65
function have_ruleint_access($if) {
66
	$security_url = "firewall_rules.php?if=". strtolower($if);
67
	if (isAllowedPage($security_url)) {
68
		return true;
69
	}
70
	return false;
71
}
72

    
73
/****f* pfsense-utils/does_url_exist
74
 * NAME
75
 *   does_url_exist
76
 * INPUTS
77
 *	none
78
 * RESULT
79
 *   returns true if a url is available
80
 ******/
81
function does_url_exist($url) {
82
	$fd = fopen("$url", "r");
83
	if ($fd) {
84
		fclose($fd);
85
		return true;
86
	} else {
87
		return false;
88
	}
89
}
90

    
91
/****f* pfsense-utils/is_private_ip
92
 * NAME
93
 *   is_private_ip
94
 * INPUTS
95
 *	none
96
 * RESULT
97
 *   returns true if an ip address is in a private range
98
 ******/
99
function is_private_ip($iptocheck) {
100
	$isprivate = false;
101
	$ip_private_list = array(
102
		"10.0.0.0/8",
103
		"100.64.0.0/10",
104
		"172.16.0.0/12",
105
		"192.168.0.0/16",
106
	);
107
	foreach ($ip_private_list as $private) {
108
		if (ip_in_subnet($iptocheck, $private) == true) {
109
			$isprivate = true;
110
		}
111
	}
112
	return $isprivate;
113
}
114

    
115
/****f* pfsense-utils/get_tmp_file
116
 * NAME
117
 *   get_tmp_file
118
 * INPUTS
119
 *	none
120
 * RESULT
121
 *   returns a temporary filename
122
 ******/
123
function get_tmp_file() {
124
	global $g;
125
	return "{$g['tmp_path']}/tmp-" . time();
126
}
127

    
128
/****f* pfsense-utils/get_dns_servers
129
 * NAME
130
 *   get_dns_servers - get system dns servers
131
 * INPUTS
132
 *   none
133
 * RESULT
134
 *   $dns_servers - an array of the dns servers
135
 ******/
136
function get_dns_servers() {
137
	$dns_servers = array();
138
	if (file_exists("/etc/resolv.conf")) {
139
		$dns_s = file("/etc/resolv.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
140
	}
141
	if (is_array($dns_s)) {
142
		foreach ($dns_s as $dns) {
143
			$matches = "";
144
			if (preg_match("/nameserver (.*)/", $dns, $matches)) {
145
				$dns_servers[] = $matches[1];
146
			}
147
		}
148
	}
149
	return array_unique($dns_servers);
150
}
151

    
152
function hardware_offloading_applyflags($iface) {
153
	global $config;
154

    
155
	$flags_on = 0;
156
	$flags_off = 0;
157
	$options = pfSense_get_interface_addresses($iface);
158

    
159
	if (isset($config['system']['disablechecksumoffloading'])) {
160
		if (isset($options['encaps']['txcsum'])) {
161
			$flags_off |= IFCAP_TXCSUM;
162
		}
163
		if (isset($options['encaps']['rxcsum'])) {
164
			$flags_off |= IFCAP_RXCSUM;
165
		}
166
	} else {
167
		if (isset($options['caps']['txcsum'])) {
168
			$flags_on |= IFCAP_TXCSUM;
169
		}
170
		if (isset($options['caps']['rxcsum'])) {
171
			$flags_on |= IFCAP_RXCSUM;
172
		}
173
	}
174

    
175
	if (isset($config['system']['disablesegmentationoffloading'])) {
176
		$flags_off |= IFCAP_TSO;
177
	} else if (isset($options['caps']['tso']) || isset($options['caps']['tso4']) || isset($options['caps']['tso6'])) {
178
		$flags_on |= IFCAP_TSO;
179
	}
180

    
181
	if (isset($config['system']['disablelargereceiveoffloading'])) {
182
		$flags_off |= IFCAP_LRO;
183
	} else if (isset($options['caps']['lro'])) {
184
		$flags_on |= IFCAP_LRO;
185
	}
186

    
187
	/* if the NIC supports polling *AND* it is enabled in the GUI */
188
	if (!isset($config['system']['polling'])) {
189
		$flags_off |= IFCAP_POLLING;
190
	} else if (isset($options['caps']['polling'])) {
191
		$flags_on |= IFCAP_POLLING;
192
	}
193

    
194
	pfSense_interface_capabilities($iface, -$flags_off);
195
	pfSense_interface_capabilities($iface, $flags_on);
196
}
197

    
198
/****f* pfsense-utils/enable_hardware_offloading
199
 * NAME
200
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
201
 * INPUTS
202
 *   $interface	- string containing the physical interface to work on.
203
 * RESULT
204
 *   null
205
 * NOTES
206
 *   This function only supports the fxp driver's loadable microcode.
207
 ******/
208
function enable_hardware_offloading($interface) {
209
	global $g, $config;
210

    
211
	$int = get_real_interface($interface);
212
	if (empty($int)) {
213
		return;
214
	}
215

    
216
	if (!isset($config['system']['do_not_use_nic_microcode'])) {
217
		/* translate wan, lan, opt -> real interface if needed */
218
		$int_family = preg_split("/[0-9]+/", $int);
219
		$supported_ints = array('fxp');
220
		if (in_array($int_family, $supported_ints)) {
221
			if (does_interface_exist($int)) {
222
				pfSense_interface_flags($int, IFF_LINK0);
223
			}
224
		}
225
	}
226

    
227
	/* This is mostly for vlans and ppp types */
228
	$realhwif = get_parent_interface($interface);
229
	if ($realhwif[0] == $int) {
230
		hardware_offloading_applyflags($int);
231
	} else {
232
		hardware_offloading_applyflags($realhwif[0]);
233
		hardware_offloading_applyflags($int);
234
	}
235
}
236

    
237
/****f* pfsense-utils/interface_supports_polling
238
 * NAME
239
 *   checks to see if an interface supports polling according to man polling
240
 * INPUTS
241
 *
242
 * RESULT
243
 *   true or false
244
 * NOTES
245
 *
246
 ******/
247
function interface_supports_polling($iface) {
248
	$opts = pfSense_get_interface_addresses($iface);
249
	if (is_array($opts) && isset($opts['caps']['polling'])) {
250
		return true;
251
	}
252

    
253
	return false;
254
}
255

    
256
/****f* pfsense-utils/is_alias_inuse
257
 * NAME
258
 *   checks to see if an alias is currently in use by a rule
259
 * INPUTS
260
 *
261
 * RESULT
262
 *   true or false
263
 * NOTES
264
 *
265
 ******/
266
function is_alias_inuse($alias) {
267
	global $g, $config;
268

    
269
	if ($alias == "") {
270
		return false;
271
	}
272
	/* loop through firewall rules looking for alias in use */
273
	if (is_array($config['filter']['rule'])) {
274
		foreach ($config['filter']['rule'] as $rule) {
275
			if ($rule['source']['address']) {
276
				if ($rule['source']['address'] == $alias) {
277
					return true;
278
				}
279
			}
280
			if ($rule['destination']['address']) {
281
				if ($rule['destination']['address'] == $alias) {
282
					return true;
283
				}
284
			}
285
		}
286
	}
287
	/* loop through nat rules looking for alias in use */
288
	if (is_array($config['nat']['rule'])) {
289
		foreach ($config['nat']['rule'] as $rule) {
290
			if ($rule['target'] && $rule['target'] == $alias) {
291
				return true;
292
			}
293
			if ($rule['source']['address'] && $rule['source']['address'] == $alias) {
294
				return true;
295
			}
296
			if ($rule['destination']['address'] && $rule['destination']['address'] == $alias) {
297
				return true;
298
			}
299
		}
300
	}
301
	return false;
302
}
303

    
304
/****f* pfsense-utils/is_schedule_inuse
305
 * NAME
306
 *   checks to see if a schedule is currently in use by a rule
307
 * INPUTS
308
 *
309
 * RESULT
310
 *   true or false
311
 * NOTES
312
 *
313
 ******/
314
function is_schedule_inuse($schedule) {
315
	global $g, $config;
316

    
317
	if ($schedule == "") {
318
		return false;
319
	}
320
	/* loop through firewall rules looking for schedule in use */
321
	if (is_array($config['filter']['rule'])) {
322
		foreach ($config['filter']['rule'] as $rule) {
323
			if ($rule['sched'] == $schedule) {
324
				return true;
325
			}
326
		}
327
	}
328
	return false;
329
}
330

    
331
/****f* pfsense-utils/setup_polling
332
 * NAME
333
 *   sets up polling
334
 * INPUTS
335
 *
336
 * RESULT
337
 *   null
338
 * NOTES
339
 *
340
 ******/
341
function setup_polling() {
342
	global $g, $config;
343

    
344
	if (isset($config['system']['polling'])) {
345
		set_single_sysctl("kern.polling.idle_poll", "1");
346
	} else {
347
		set_single_sysctl("kern.polling.idle_poll", "0");
348
	}
349

    
350
	if ($config['system']['polling_each_burst']) {
351
		set_single_sysctl("kern.polling.each_burst", $config['system']['polling_each_burst']);
352
	}
353
	if ($config['system']['polling_burst_max']) {
354
		set_single_sysctl("kern.polling.burst_max", $config['system']['polling_burst_max']);
355
	}
356
	if ($config['system']['polling_user_frac']) {
357
		set_single_sysctl("kern.polling.user_frac", $config['system']['polling_user_frac']);
358
	}
359
}
360

    
361
/****f* pfsense-utils/setup_microcode
362
 * NAME
363
 *   enumerates all interfaces and calls enable_hardware_offloading which
364
 *   enables a NIC's supported hardware features.
365
 * INPUTS
366
 *
367
 * RESULT
368
 *   null
369
 * NOTES
370
 *   This function only supports the fxp driver's loadable microcode.
371
 ******/
372
function setup_microcode() {
373

    
374
	/* if list */
375
	$iflist = get_configured_interface_list(false, true);
376
	foreach ($iflist as $if => $ifdescr) {
377
		enable_hardware_offloading($if);
378
	}
379
	unset($iflist);
380
}
381

    
382
/****f* pfsense-utils/get_carp_status
383
 * NAME
384
 *   get_carp_status - Return whether CARP is enabled or disabled.
385
 * RESULT
386
 *   boolean	- true if CARP is enabled, false if otherwise.
387
 ******/
388
function get_carp_status() {
389
	/* grab the current status of carp */
390
	$status = get_single_sysctl('net.inet.carp.allow');
391
	return (intval($status) > 0);
392
}
393

    
394
/*
395
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
396

    
397
 */
398
function convert_ip_to_network_format($ip, $subnet) {
399
	$ipsplit = explode('.', $ip);
400
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
401
	return $string;
402
}
403

    
404
/*
405
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
406
 */
407
function get_carp_interface_status($carpinterface) {
408
	global $config;
409

    
410
	foreach ($config['virtualip']['vip'] as $carp) {
411
		if ($carp['mode'] != "carp")
412
			continue;
413
		$carpif = "_vip{$carp['uniqid']}";
414
		if ($carpinterface !== $carpif)
415
			continue;
416

    
417
		$interface = get_real_interface($carp['interface']);
418
		$vhid = $carp['vhid'];
419
		$carp_query = '';
420
		$_gb = exec("/sbin/ifconfig $interface | /usr/bin/grep carp: | /usr/bin/grep \"vhid $vhid\"", $carp_query);
421
		foreach ($carp_query as $int) {
422
			if (stripos($int, "MASTER")) {
423
				return "MASTER";
424
			}
425
			if (stripos($int, "BACKUP")) {
426
				return "BACKUP";
427
			}
428
			if (stripos($int, "INIT")) {
429
				return "INIT";
430
			}
431
		}
432
		break;
433
	}
434

    
435
	return;
436
}
437

    
438
/*
439
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
440
 */
441
function get_pfsync_interface_status($pfsyncinterface) {
442
	if (!does_interface_exist($pfsyncinterface)) {
443
		return;
444
	}
445

    
446
	return exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/awk '/pfsync:/ {print \$5}'");
447
}
448

    
449
/*
450
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
451
 */
452
function add_rule_to_anchor($anchor, $rule, $label) {
453
	mwexec("echo " . escapeshellarg($rule) . " | /sbin/pfctl -a " . escapeshellarg($anchor) . ":" . escapeshellarg($label) . " -f -");
454
}
455

    
456
/*
457
 * remove_text_from_file
458
 * remove $text from file $file
459
 */
460
function remove_text_from_file($file, $text) {
461
	if (!file_exists($file) && !is_writable($file)) {
462
		return;
463
	}
464
	$filecontents = file_get_contents($file);
465
	$text = str_replace($text, "", $filecontents);
466
	@file_put_contents($file, $text);
467
}
468

    
469
/*
470
 *   after_sync_bump_adv_skew(): create skew values by 1S
471
 */
472
function after_sync_bump_adv_skew() {
473
	global $config, $g;
474
	$processed_skew = 1;
475
	$a_vip = &$config['virtualip']['vip'];
476
	foreach ($a_vip as $vipent) {
477
		if ($vipent['advskew'] <> "") {
478
			$processed_skew = 1;
479
			$vipent['advskew'] = $vipent['advskew']+1;
480
		}
481
	}
482
	if ($processed_skew == 1) {
483
		write_config(gettext("After synch increase advertising skew"));
484
	}
485
}
486

    
487
/*
488
 * get_filename_from_url($url): converts a url to its filename.
489
 */
490
function get_filename_from_url($url) {
491
	return basename($url);
492
}
493

    
494
/*
495
 *   get_dir: return an array of $dir
496
 */
497
function get_dir($dir) {
498
	$dir_array = array();
499
	$d = dir($dir);
500
	while (false !== ($entry = $d->read())) {
501
		array_push($dir_array, $entry);
502
	}
503
	$d->close();
504
	return $dir_array;
505
}
506

    
507
/****f* pfsense-utils/WakeOnLan
508
 * NAME
509
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
510
 * RESULT
511
 *   true/false - true if the operation was successful
512
 ******/
513
function WakeOnLan($addr, $mac) {
514
	$addr_byte = explode(':', $mac);
515
	$hw_addr = '';
516

    
517
	for ($a = 0; $a < 6; $a++) {
518
		$hw_addr .= chr(hexdec($addr_byte[$a]));
519
	}
520

    
521
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
522

    
523
	for ($a = 1; $a <= 16; $a++) {
524
		$msg .= $hw_addr;
525
	}
526

    
527
	// send it to the broadcast address using UDP
528
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
529
	if ($s == false) {
530
		log_error(gettext("Error creating socket!"));
531
		log_error(sprintf(gettext("Error code is '%1\$s' - %2\$s"), socket_last_error($s), socket_strerror(socket_last_error($s))));
532
	} else {
533
		// setting a broadcast option to socket:
534
		$opt_ret = socket_set_option($s, 1, 6, TRUE);
535
		if ($opt_ret < 0) {
536
			log_error(sprintf(gettext("setsockopt() failed, error: %s"), strerror($opt_ret)));
537
		}
538
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
539
		socket_close($s);
540
		log_error(sprintf(gettext('Magic Packet sent (%1$s) to {%2$s} MAC=%3$s'), $e, $addr, $mac));
541
		return true;
542
	}
543

    
544
	return false;
545
}
546

    
547
/*
548
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
549
 *					 Useful for finding paths and stripping file extensions.
550
 */
551
function reverse_strrchr($haystack, $needle) {
552
	if (!is_string($haystack)) {
553
		return;
554
	}
555
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1) : false;
556
}
557

    
558
/*
559
 *  backup_config_section($section): returns as an xml file string of
560
 *                                   the configuration section
561
 */
562
function backup_config_section($section_name) {
563
	global $config;
564
	$new_section = &$config[$section_name];
565
	/* generate configuration XML */
566
	$xmlconfig = dump_xml_config($new_section, $section_name);
567
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
568
	return $xmlconfig;
569
}
570

    
571
/*
572
 *  restore_config_section($section_name, new_contents): restore a configuration section,
573
 *                                                  and write the configuration out
574
 *                                                  to disk/cf.
575
 */
576
function restore_config_section($section_name, $new_contents) {
577
	global $config, $g;
578
	conf_mount_rw();
579
	$fout = fopen("{$g['tmp_path']}/tmpxml", "w");
580
	fwrite($fout, $new_contents);
581
	fclose($fout);
582

    
583
	$xml = parse_xml_config($g['tmp_path'] . "/tmpxml", null);
584
	if ($xml['pfsense']) {
585
		$xml = $xml['pfsense'];
586
	}
587
	else if ($xml['m0n0wall']) {
588
		$xml = $xml['m0n0wall'];
589
	}
590
	if ($xml[$section_name]) {
591
		$section_xml = $xml[$section_name];
592
	} else {
593
		$section_xml = -1;
594
	}
595

    
596
	@unlink($g['tmp_path'] . "/tmpxml");
597
	if ($section_xml === -1) {
598
		return false;
599
	}
600
	$config[$section_name] = &$section_xml;
601
	if (file_exists("{$g['tmp_path']}/config.cache")) {
602
		unlink("{$g['tmp_path']}/config.cache");
603
	}
604
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
605
	disable_security_checks();
606
	conf_mount_ro();
607
	return true;
608
}
609

    
610
/*
611
 *  merge_config_section($section_name, new_contents):   restore a configuration section,
612
 *                                                  and write the configuration out
613
 *                                                  to disk/cf.  But preserve the prior
614
 * 													structure if needed
615
 */
616
function merge_config_section($section_name, $new_contents) {
617
	global $config;
618
	conf_mount_rw();
619
	$fname = get_tmp_filename();
620
	$fout = fopen($fname, "w");
621
	fwrite($fout, $new_contents);
622
	fclose($fout);
623
	$section_xml = parse_xml_config($fname, $section_name);
624
	$config[$section_name] = $section_xml;
625
	unlink($fname);
626
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
627
	disable_security_checks();
628
	conf_mount_ro();
629
	return;
630
}
631

    
632
/*
633
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
634
 */
635
if (!function_exists('php_check_syntax')) {
636
	global $g;
637
	function php_check_syntax($code_to_check, &$errormessage) {
638
		return false;
639
		$fout = fopen("{$g['tmp_path']}/codetocheck.php", "w");
640
		$code = $_POST['content'];
641
		$code = str_replace("<?php", "", $code);
642
		$code = str_replace("?>", "", $code);
643
		fwrite($fout, "<?php\n\n");
644
		fwrite($fout, $code_to_check);
645
		fwrite($fout, "\n\n?>\n");
646
		fclose($fout);
647
		$command = "/usr/local/bin/php-cgi -l {$g['tmp_path']}/codetocheck.php";
648
		$output = exec_command($command);
649
		if (stristr($output, "Errors parsing") == false) {
650
			echo "false\n";
651
			$errormessage = '';
652
			return(false);
653
		} else {
654
			$errormessage = $output;
655
			return(true);
656
		}
657
	}
658
}
659

    
660
/*
661
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
662
 */
663
if (!function_exists('php_check_syntax')) {
664
	function php_check_syntax($code_to_check, &$errormessage) {
665
		return false;
666
		$command = "/usr/local/bin/php-cgi -l " . escapeshellarg($code_to_check);
667
		$output = exec_command($command);
668
		if (stristr($output, "Errors parsing") == false) {
669
			echo "false\n";
670
			$errormessage = '';
671
			return(false);
672
		} else {
673
			$errormessage = $output;
674
			return(true);
675
		}
676
	}
677
}
678

    
679
/*
680
 * rmdir_recursive($path, $follow_links=false)
681
 * Recursively remove a directory tree (rm -rf path)
682
 * This is for directories _only_
683
 */
684
function rmdir_recursive($path, $follow_links=false) {
685
	$to_do = glob($path);
686
	if (!is_array($to_do)) {
687
		$to_do = array($to_do);
688
	}
689
	foreach ($to_do as $workingdir) { // Handle wildcards by foreaching.
690
		if (file_exists($workingdir)) {
691
			if (is_dir($workingdir)) {
692
				$dir = opendir($workingdir);
693
				while ($entry = readdir($dir)) {
694
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry"))) {
695
						unlink("$workingdir/$entry");
696
					} elseif (is_dir("$workingdir/$entry") && $entry != '.' && $entry != '..') {
697
						rmdir_recursive("$workingdir/$entry");
698
					}
699
				}
700
				closedir($dir);
701
				rmdir($workingdir);
702
			} elseif (is_file($workingdir)) {
703
				unlink($workingdir);
704
			}
705
		}
706
	}
707
	return;
708
}
709

    
710
/*
711
 * host_firmware_version(): Return the versions used in this install
712
 */
713
function host_firmware_version($tocheck = "") {
714
	global $g, $config;
715

    
716
	$os_version = trim(substr(php_uname("r"), 0, strpos(php_uname("r"), '-')));
717

    
718
	return array(
719
		"firmware" => array("version" => $g['product_version']),
720
		"kernel"   => array("version" => $os_version),
721
		"base"     => array("version" => $os_version),
722
		"platform" => trim(file_get_contents('/etc/platform', " \n")),
723
		"config_version" => $config['version']
724
	);
725
}
726

    
727
function get_disk_info() {
728
	$diskout = "";
729
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
730
	return explode(' ', $diskout[0]);
731
}
732

    
733
/****f* pfsense-utils/strncpy
734
 * NAME
735
 *   strncpy - copy strings
736
 * INPUTS
737
 *   &$dst, $src, $length
738
 * RESULT
739
 *   none
740
 ******/
741
function strncpy(&$dst, $src, $length) {
742
	if (strlen($src) > $length) {
743
		$dst = substr($src, 0, $length);
744
	} else {
745
		$dst = $src;
746
	}
747
}
748

    
749
/****f* pfsense-utils/reload_interfaces_sync
750
 * NAME
751
 *   reload_interfaces - reload all interfaces
752
 * INPUTS
753
 *   none
754
 * RESULT
755
 *   none
756
 ******/
757
function reload_interfaces_sync() {
758
	global $config, $g;
759

    
760
	if ($g['debug']) {
761
		log_error(gettext("reload_interfaces_sync() is starting."));
762
	}
763

    
764
	/* parse config.xml again */
765
	$config = parse_config(true);
766

    
767
	/* enable routing */
768
	system_routing_enable();
769
	if ($g['debug']) {
770
		log_error(gettext("Enabling system routing"));
771
	}
772

    
773
	if ($g['debug']) {
774
		log_error(gettext("Cleaning up Interfaces"));
775
	}
776

    
777
	/* set up interfaces */
778
	interfaces_configure();
779
}
780

    
781
/****f* pfsense-utils/reload_all
782
 * NAME
783
 *   reload_all - triggers a reload of all settings
784
 *   * INPUTS
785
 *   none
786
 * RESULT
787
 *   none
788
 ******/
789
function reload_all() {
790
	send_event("service reload all");
791
}
792

    
793
/****f* pfsense-utils/reload_interfaces
794
 * NAME
795
 *   reload_interfaces - triggers a reload of all interfaces
796
 * INPUTS
797
 *   none
798
 * RESULT
799
 *   none
800
 ******/
801
function reload_interfaces() {
802
	send_event("interface all reload");
803
}
804

    
805
/****f* pfsense-utils/reload_all_sync
806
 * NAME
807
 *   reload_all - reload all settings
808
 *   * INPUTS
809
 *   none
810
 * RESULT
811
 *   none
812
 ******/
813
function reload_all_sync() {
814
	global $config, $g;
815

    
816
	/* parse config.xml again */
817
	$config = parse_config(true);
818

    
819
	/* set up our timezone */
820
	system_timezone_configure();
821

    
822
	/* set up our hostname */
823
	system_hostname_configure();
824

    
825
	/* make hosts file */
826
	system_hosts_generate();
827

    
828
	/* generate resolv.conf */
829
	system_resolvconf_generate();
830

    
831
	/* enable routing */
832
	system_routing_enable();
833

    
834
	/* set up interfaces */
835
	interfaces_configure();
836

    
837
	/* start dyndns service */
838
	services_dyndns_configure();
839

    
840
	/* configure cron service */
841
	configure_cron();
842

    
843
	/* start the NTP client */
844
	system_ntp_configure();
845

    
846
	/* sync pw database */
847
	conf_mount_rw();
848
	unlink_if_exists("/etc/spwd.db.tmp");
849
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
850
	conf_mount_ro();
851

    
852
	/* restart sshd */
853
	send_event("service restart sshd");
854

    
855
	/* restart webConfigurator if needed */
856
	send_event("service restart webgui");
857
}
858

    
859
function setup_serial_port($when = "save", $path = "") {
860
	global $g, $config;
861
	conf_mount_rw();
862
	$ttys_file = "{$path}/etc/ttys";
863
	$boot_config_file = "{$path}/boot.config";
864
	$loader_conf_file = "{$path}/boot/loader.conf";
865
	/* serial console - write out /boot.config */
866
	if (file_exists($boot_config_file)) {
867
		$boot_config = file_get_contents($boot_config_file);
868
	} else {
869
		$boot_config = "";
870
	}
871

    
872
	$serialspeed = (is_numeric($config['system']['serialspeed'])) ? $config['system']['serialspeed'] : "115200";
873
	if ($g['platform'] != "cdrom") {
874
		$serial_only = false;
875

    
876
		if (($g['platform'] == "nanobsd") && isset($g['enableserial_force'])) {
877
			$serial_only = true;
878
		} else {
879
			$specific_platform = system_identify_specific_platform();
880
			if ($specific_platform['name'] == 'RCC-VE' ||
881
			    $specific_platform['name'] == 'RCC-DFF') {
882
				$serial_only = true;
883
			}
884
		}
885

    
886
		$boot_config_split = explode("\n", $boot_config);
887
		$fd = fopen($boot_config_file, "w");
888
		if ($fd) {
889
			foreach ($boot_config_split as $bcs) {
890
				if (stristr($bcs, "-D") || stristr($bcs, "-h")) {
891
					/* DONT WRITE OUT, WE'LL DO IT LATER */
892
				} else {
893
					if ($bcs <> "") {
894
						fwrite($fd, "{$bcs}\n");
895
					}
896
				}
897
			}
898
			if ($serial_only === true) {
899
				fwrite($fd, "-S{$serialspeed} -h");
900
			} else if (is_serial_enabled()) {
901
				fwrite($fd, "-S{$serialspeed} -D");
902
			}
903
			fclose($fd);
904
		}
905

    
906
		/* serial console - write out /boot/loader.conf */
907
		if ($when == "upgrade") {
908
			system("echo \"Reading {$loader_conf_file}...\" >> /conf/upgrade_log.txt");
909
		}
910
		$boot_config = file_get_contents($loader_conf_file);
911
		$boot_config_split = explode("\n", $boot_config);
912
		if (count($boot_config_split) > 0) {
913
			$new_boot_config = array();
914
			// Loop through and only add lines that are not empty, and which
915
			//  do not contain a console directive.
916
			foreach ($boot_config_split as $bcs) {
917
				if (!empty($bcs) &&
918
				    (stripos($bcs, "console") === false) &&
919
				    (stripos($bcs, "boot_multicons") === false) &&
920
				    (stripos($bcs, "boot_serial") === false) &&
921
				    (stripos($bcs, "hw.usb.no_pf") === false) &&
922
				    (stripos($bcs, "hint.uart.0.flags") === false) &&
923
				    (stripos($bcs, "hint.uart.1.flags") === false)) {
924
					$new_boot_config[] = $bcs;
925
				}
926
			}
927

    
928
			if ($serial_only === true) {
929
				$new_boot_config[] = 'boot_serial="YES"';
930
				$new_boot_config[] = 'console="comconsole"';
931
			} else if (is_serial_enabled()) {
932
				$new_boot_config[] = 'boot_multicons="YES"';
933
				$new_boot_config[] = 'boot_serial="YES"';
934
				$primaryconsole = isset($g['primaryconsole_force']) ? $g['primaryconsole_force'] : $config['system']['primaryconsole'];
935
				switch ($primaryconsole) {
936
					case "video":
937
						$new_boot_config[] = 'console="vidconsole,comconsole"';
938
						break;
939
					case "serial":
940
					default:
941
						$new_boot_config[] = 'console="comconsole,vidconsole"';
942
				}
943
			}
944
			$new_boot_config[] = 'comconsole_speed="' . $serialspeed . '"';
945

    
946
			$specplatform = system_identify_specific_platform();
947
			if ($specplatform['name'] == 'RCC-VE' ||
948
			    $specplatform['name'] == 'RCC-DFF') {
949
				$new_boot_config[] = 'comconsole_port="0x2F8"';
950
				$new_boot_config[] = 'hint.uart.0.flags="0x00"';
951
				$new_boot_config[] = 'hint.uart.1.flags="0x10"';
952
			}
953
			$new_boot_config[] = 'hw.usb.no_pf="1"';
954

    
955
			file_put_contents($loader_conf_file, implode("\n", $new_boot_config) . "\n");
956
		}
957
	}
958
	$ttys = file_get_contents($ttys_file);
959
	$ttys_split = explode("\n", $ttys);
960
	$fd = fopen($ttys_file, "w");
961

    
962
	$on_off = (is_serial_enabled() ? 'onifconsole' : 'off');
963

    
964
	if (isset($config['system']['disableconsolemenu'])) {
965
		$console_type = 'Pc';
966
		$serial_type = 'std.' . $serialspeed;
967
	} else {
968
		$console_type = 'al.Pc';
969
		$serial_type = 'al.' . $serialspeed;
970
	}
971
	foreach ($ttys_split as $tty) {
972
		if (stristr($tty, "ttyv0")) {
973
			fwrite($fd, "ttyv0	\"/usr/libexec/getty {$console_type}\"	cons25	on	secure\n");
974
		} else if (stristr($tty, "ttyu")) {
975
			$ttyn = substr($tty, 0, 5);
976
			fwrite($fd, "{$ttyn}	\"/usr/libexec/getty {$serial_type}\"	cons25	{$on_off}	secure\n");
977
		} else {
978
			fwrite($fd, $tty . "\n");
979
		}
980
	}
981
	unset($on_off, $console_type, $serial_type);
982
	fclose($fd);
983
	if ($when != "upgrade") {
984
		reload_ttys();
985
	}
986

    
987
	conf_mount_ro();
988
	return;
989
}
990

    
991
function is_serial_enabled() {
992
	global $g, $config;
993

    
994
	if (!isset($g['enableserial_force']) &&
995
	    !isset($config['system']['enableserial']) &&
996
	    ($g['platform'] == $g['product_name'] || $g['platform'] == "cdrom")) {
997
		return false;
998
	}
999

    
1000
	return true;
1001
}
1002

    
1003
function reload_ttys() {
1004
	// Send a HUP signal to init will make it reload /etc/ttys
1005
	posix_kill(1, SIGHUP);
1006
}
1007

    
1008
function print_value_list($list, $count = 10, $separator = ",") {
1009
	$list = implode($separator, array_slice($list, 0, $count));
1010
	if (count($list) < $count) {
1011
		$list .= ".";
1012
	} else {
1013
		$list .= "...";
1014
	}
1015
	return $list;
1016
}
1017

    
1018
/* DHCP enabled on any interfaces? */
1019
function is_dhcp_server_enabled() {
1020
	global $config;
1021

    
1022
	if (!is_array($config['dhcpd'])) {
1023
		return false;
1024
	}
1025

    
1026
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1027
		if (isset($dhcpifconf['enable']) && !empty($config['interfaces'][$dhcpif])) {
1028
			return true;
1029
		}
1030
	}
1031

    
1032
	return false;
1033
}
1034

    
1035
/* DHCP enabled on any interfaces? */
1036
function is_dhcpv6_server_enabled() {
1037
	global $config;
1038

    
1039
	if (is_array($config['interfaces'])) {
1040
		foreach ($config['interfaces'] as $ifcfg) {
1041
			if (isset($ifcfg['enable']) && !empty($ifcfg['track6-interface'])) {
1042
				return true;
1043
			}
1044
		}
1045
	}
1046

    
1047
	if (!is_array($config['dhcpdv6'])) {
1048
		return false;
1049
	}
1050

    
1051
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
1052
		if (isset($dhcpv6ifconf['enable']) && !empty($config['interfaces'][$dhcpv6if])) {
1053
			return true;
1054
		}
1055
	}
1056

    
1057
	return false;
1058
}
1059

    
1060
/* radvd enabled on any interfaces? */
1061
function is_radvd_enabled() {
1062
	global $config;
1063

    
1064
	if (!is_array($config['dhcpdv6'])) {
1065
		$config['dhcpdv6'] = array();
1066
	}
1067

    
1068
	$dhcpdv6cfg = $config['dhcpdv6'];
1069
	$Iflist = get_configured_interface_list();
1070

    
1071
	/* handle manually configured DHCP6 server settings first */
1072
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1073
		if (!isset($config['interfaces'][$dhcpv6if]['enable'])) {
1074
			continue;
1075
		}
1076

    
1077
		if (!isset($dhcpv6ifconf['ramode'])) {
1078
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
1079
		}
1080

    
1081
		if ($dhcpv6ifconf['ramode'] == "disabled") {
1082
			continue;
1083
		}
1084

    
1085
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1086
		if (!is_ipaddrv6($ifcfgipv6)) {
1087
			continue;
1088
		}
1089

    
1090
		return true;
1091
	}
1092

    
1093
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
1094
	foreach ($Iflist as $if => $ifdescr) {
1095
		if (!isset($config['interfaces'][$if]['track6-interface'])) {
1096
			continue;
1097
		}
1098
		if (!isset($config['interfaces'][$if]['enable'])) {
1099
			continue;
1100
		}
1101

    
1102
		$ifcfgipv6 = get_interface_ipv6($if);
1103
		if (!is_ipaddrv6($ifcfgipv6)) {
1104
			continue;
1105
		}
1106

    
1107
		$ifcfgsnv6 = get_interface_subnetv6($if);
1108
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1109

    
1110
		if (!is_ipaddrv6($subnetv6)) {
1111
			continue;
1112
		}
1113

    
1114
		return true;
1115
	}
1116

    
1117
	return false;
1118
}
1119

    
1120
/* Any PPPoE servers enabled? */
1121
function is_pppoe_server_enabled() {
1122
	global $config;
1123

    
1124
	$pppoeenable = false;
1125

    
1126
	if (!is_array($config['pppoes']) || !is_array($config['pppoes']['pppoe'])) {
1127
		return false;
1128
	}
1129

    
1130
	foreach ($config['pppoes']['pppoe'] as $pppoes) {
1131
		if ($pppoes['mode'] == 'server') {
1132
			$pppoeenable = true;
1133
		}
1134
	}
1135

    
1136
	return $pppoeenable;
1137
}
1138

    
1139
function convert_seconds_to_hms($sec) {
1140
	$min = $hrs = 0;
1141
	if ($sec != 0) {
1142
		$min = floor($sec/60);
1143
		$sec %= 60;
1144
	}
1145
	if ($min != 0) {
1146
		$hrs = floor($min/60);
1147
		$min %= 60;
1148
	}
1149
	if ($sec < 10) {
1150
		$sec = "0".$sec;
1151
	}
1152
	if ($min < 10) {
1153
		$min = "0".$min;
1154
	}
1155
	if ($hrs < 10) {
1156
		$hrs = "0".$hrs;
1157
	}
1158
	$result = $hrs.":".$min.":".$sec;
1159
	return $result;
1160
}
1161

    
1162
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1163

    
1164
function get_ppp_uptime($port) {
1165
	if (file_exists("/conf/{$port}.log")) {
1166
		$saved_time = file_get_contents("/conf/{$port}.log");
1167
		$uptime_data = explode("\n", $saved_time);
1168
		$sec = 0;
1169
		foreach ($uptime_data as $upt) {
1170
			$sec += substr($upt, 1 + strpos($upt, " "));
1171
		}
1172
		return convert_seconds_to_hms($sec);
1173
	} else {
1174
		$total_time = gettext("No history data found!");
1175
		return $total_time;
1176
	}
1177
}
1178

    
1179
//returns interface information
1180
function get_interface_info($ifdescr) {
1181
	global $config, $g;
1182

    
1183
	$ifinfo = array();
1184
	if (empty($config['interfaces'][$ifdescr])) {
1185
		return;
1186
	}
1187
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
1188
	$ifinfo['if'] = get_real_interface($ifdescr);
1189

    
1190
	$chkif = $ifinfo['if'];
1191
	$ifinfotmp = pfSense_get_interface_addresses($chkif);
1192
	$ifinfo['status'] = $ifinfotmp['status'];
1193
	if (empty($ifinfo['status'])) {
1194
		$ifinfo['status'] = "down";
1195
	}
1196
	$ifinfo['macaddr'] = $ifinfotmp['macaddr'];
1197
	$ifinfo['mtu'] = $ifinfotmp['mtu'];
1198
	$ifinfo['ipaddr'] = $ifinfotmp['ipaddr'];
1199
	$ifinfo['subnet'] = $ifinfotmp['subnet'];
1200
	$ifinfo['linklocal'] = get_interface_linklocal($ifdescr);
1201
	$ifinfo['ipaddrv6'] = get_interface_ipv6($ifdescr);
1202
	$ifinfo['subnetv6'] = get_interface_subnetv6($ifdescr);
1203
	if (isset($ifinfotmp['link0'])) {
1204
		$link0 = "down";
1205
	}
1206
	$ifinfotmp = pfSense_get_interface_stats($chkif);
1207
	// $ifinfo['inpkts'] = $ifinfotmp['inpkts'];
1208
	// $ifinfo['outpkts'] = $ifinfotmp['outpkts'];
1209
	$ifinfo['inerrs'] = $ifinfotmp['inerrs'];
1210
	$ifinfo['outerrs'] = $ifinfotmp['outerrs'];
1211
	$ifinfo['collisions'] = $ifinfotmp['collisions'];
1212

    
1213
	/* Use pfctl for non wrapping 64 bit counters */
1214
	/* Pass */
1215
	exec("/sbin/pfctl -vvsI -i {$chkif}", $pfctlstats);
1216
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1217
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1218
	$pf_in6_pass = preg_split("/ +/ ", $pfctlstats[7]);
1219
	$pf_out6_pass = preg_split("/ +/", $pfctlstats[9]);
1220
	$in4_pass = $pf_in4_pass[5];
1221
	$out4_pass = $pf_out4_pass[5];
1222
	$in4_pass_packets = $pf_in4_pass[3];
1223
	$out4_pass_packets = $pf_out4_pass[3];
1224
	$in6_pass = $pf_in6_pass[5];
1225
	$out6_pass = $pf_out6_pass[5];
1226
	$in6_pass_packets = $pf_in6_pass[3];
1227
	$out6_pass_packets = $pf_out6_pass[3];
1228
	$ifinfo['inbytespass'] = $in4_pass + $in6_pass;
1229
	$ifinfo['outbytespass'] = $out4_pass + $out6_pass;
1230
	$ifinfo['inpktspass'] = $in4_pass_packets + $in6_pass_packets;
1231
	$ifinfo['outpktspass'] = $out4_pass_packets + $out6_pass_packets;
1232

    
1233
	/* Block */
1234
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1235
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1236
	$pf_in6_block = preg_split("/ +/", $pfctlstats[8]);
1237
	$pf_out6_block = preg_split("/ +/", $pfctlstats[10]);
1238
	$in4_block = $pf_in4_block[5];
1239
	$out4_block = $pf_out4_block[5];
1240
	$in4_block_packets = $pf_in4_block[3];
1241
	$out4_block_packets = $pf_out4_block[3];
1242
	$in6_block = $pf_in6_block[5];
1243
	$out6_block = $pf_out6_block[5];
1244
	$in6_block_packets = $pf_in6_block[3];
1245
	$out6_block_packets = $pf_out6_block[3];
1246
	$ifinfo['inbytesblock'] = $in4_block + $in6_block;
1247
	$ifinfo['outbytesblock'] = $out4_block + $out6_block;
1248
	$ifinfo['inpktsblock'] = $in4_block_packets + $in6_block_packets;
1249
	$ifinfo['outpktsblock'] = $out4_block_packets + $out6_block_packets;
1250

    
1251
	$ifinfo['inbytes'] = $in4_pass + $in6_pass;
1252
	$ifinfo['outbytes'] = $out4_pass + $out6_pass;
1253
	$ifinfo['inpkts'] = $in4_pass_packets + $in6_pass_packets;
1254
	$ifinfo['outpkts'] = $out4_pass_packets + $out6_pass_packets;
1255

    
1256
	$ifconfiginfo = "";
1257
	$link_type = $config['interfaces'][$ifdescr]['ipaddr'];
1258
	switch ($link_type) {
1259
		/* DHCP? -> see if dhclient is up */
1260
		case "dhcp":
1261
			/* see if dhclient is up */
1262
			if (find_dhclient_process($ifinfo['if']) != 0) {
1263
				$ifinfo['dhcplink'] = "up";
1264
			} else {
1265
				$ifinfo['dhcplink'] = "down";
1266
			}
1267

    
1268
			break;
1269
		/* PPPoE/PPTP/L2TP interface? -> get status from virtual interface */
1270
		case "pppoe":
1271
		case "pptp":
1272
		case "l2tp":
1273
			if ($ifinfo['status'] == "up" && !isset($link0)) {
1274
				/* get PPPoE link status for dial on demand */
1275
				$ifinfo["{$link_type}link"] = "up";
1276
			} else {
1277
				$ifinfo["{$link_type}link"] = "down";
1278
			}
1279

    
1280
			break;
1281
		/* PPP interface? -> get uptime for this session and cumulative uptime from the persistent log file in conf */
1282
		case "ppp":
1283
			if ($ifinfo['status'] == "up") {
1284
				$ifinfo['ppplink'] = "up";
1285
			} else {
1286
				$ifinfo['ppplink'] = "down" ;
1287
			}
1288

    
1289
			if (empty($ifinfo['status'])) {
1290
				$ifinfo['status'] = "down";
1291
			}
1292

    
1293
			if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1294
				foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1295
					if ($config['interfaces'][$ifdescr]['if'] == $ppp['if']) {
1296
						break;
1297
					}
1298
				}
1299
			}
1300
			$dev = $ppp['ports'];
1301
			if ($config['interfaces'][$ifdescr]['if'] != $ppp['if'] || empty($dev)) {
1302
				break;
1303
			}
1304
			if (!file_exists($dev)) {
1305
				$ifinfo['nodevice'] = 1;
1306
				$ifinfo['pppinfo'] = $dev . " " . gettext("device not present! Is the modem attached to the system?");
1307
			}
1308

    
1309
			$usbmodemoutput = array();
1310
			exec("/usr/sbin/usbconfig", $usbmodemoutput);
1311
			$mondev = "{$g['tmp_path']}/3gstats.{$ifdescr}";
1312
			if (file_exists($mondev)) {
1313
				$cellstats = file($mondev);
1314
				/* skip header */
1315
				$a_cellstats = explode(",", $cellstats[1]);
1316
				if (preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1317
					$ifinfo['cell_rssi'] = huawei_rssi_to_string($a_cellstats[1]);
1318
					$ifinfo['cell_mode'] = huawei_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1319
					$ifinfo['cell_simstate'] = huawei_simstate_to_string($a_cellstats[10]);
1320
					$ifinfo['cell_service'] = huawei_service_to_string(trim($a_cellstats[11]));
1321
				}
1322
				if (preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1323
					$ifinfo['cell_rssi'] = zte_rssi_to_string($a_cellstats[1]);
1324
					$ifinfo['cell_mode'] = zte_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1325
					$ifinfo['cell_simstate'] = zte_simstate_to_string($a_cellstats[10]);
1326
					$ifinfo['cell_service'] = zte_service_to_string(trim($a_cellstats[11]));
1327
				}
1328
				$ifinfo['cell_upstream'] = $a_cellstats[4];
1329
				$ifinfo['cell_downstream'] = trim($a_cellstats[5]);
1330
				$ifinfo['cell_sent'] = $a_cellstats[6];
1331
				$ifinfo['cell_received'] = trim($a_cellstats[7]);
1332
				$ifinfo['cell_bwupstream'] = $a_cellstats[8];
1333
				$ifinfo['cell_bwdownstream'] = trim($a_cellstats[9]);
1334
			}
1335
			// Calculate cumulative uptime for PPP link. Useful for connections that have per minute/hour contracts so you don't go over!
1336
			if (isset($ppp['uptime'])) {
1337
				$ifinfo['ppp_uptime_accumulated'] = "(".get_ppp_uptime($ifinfo['if']).")";
1338
			}
1339
			break;
1340
		default:
1341
			break;
1342
	}
1343

    
1344
	if (file_exists("{$g['varrun_path']}/{$link_type}_{$ifdescr}.pid")) {
1345
		$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1346
		$ifinfo['ppp_uptime'] = convert_seconds_to_hms($sec);
1347
	}
1348

    
1349
	if ($ifinfo['status'] == "up") {
1350
		/* try to determine media with ifconfig */
1351
		unset($ifconfiginfo);
1352
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1353
		$wifconfiginfo = array();
1354
		if (is_interface_wireless($ifdescr)) {
1355
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1356
			array_shift($wifconfiginfo);
1357
		}
1358
		$matches = "";
1359
		foreach ($ifconfiginfo as $ici) {
1360

    
1361
			/* don't list media/speed for wireless cards, as it always
1362
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1363
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1364
				$ifinfo['media'] = $matches[1];
1365
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1366
				$ifinfo['media'] = $matches[1];
1367
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1368
				$ifinfo['media'] = $matches[1];
1369
			}
1370

    
1371
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
1372
				if ($matches[1] != "active") {
1373
					$ifinfo['status'] = $matches[1];
1374
				}
1375
				if ($ifinfo['status'] == gettext("running")) {
1376
					$ifinfo['status'] = gettext("up");
1377
				}
1378
			}
1379
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
1380
				$ifinfo['channel'] = $matches[1];
1381
			}
1382
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
1383
				if ($matches[1][0] == '"') {
1384
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
1385
				}
1386
				else {
1387
					$ifinfo['ssid'] = $matches[1];
1388
				}
1389
			}
1390
			if (preg_match("/laggproto (.*)$/", $ici, $matches)) {
1391
				$ifinfo['laggproto'] = $matches[1];
1392
			}
1393
			if (preg_match("/laggport: (.*)$/", $ici, $matches)) {
1394
				$ifinfo['laggport'][] = $matches[1];
1395
			}
1396
		}
1397
		foreach ($wifconfiginfo as $ici) {
1398
			$elements = preg_split("/[ ]+/i", $ici);
1399
			if ($elements[0] != "") {
1400
				$ifinfo['bssid'] = $elements[0];
1401
			}
1402
			if ($elements[3] != "") {
1403
				$ifinfo['rate'] = $elements[3];
1404
			}
1405
			if ($elements[4] != "") {
1406
				$ifinfo['rssi'] = $elements[4];
1407
			}
1408
		}
1409
		/* lookup the gateway */
1410
		if (interface_has_gateway($ifdescr)) {
1411
			$ifinfo['gateway'] = get_interface_gateway($ifdescr);
1412
			$ifinfo['gatewayv6'] = get_interface_gateway_v6($ifdescr);
1413
		}
1414
	}
1415

    
1416
	$bridge = "";
1417
	$bridge = link_interface_to_bridge($ifdescr);
1418
	if ($bridge) {
1419
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1420
		if (stristr($bridge_text, "blocking") <> false) {
1421
			$ifinfo['bridge'] = "<b><font color='red'>" . gettext("blocking") . "</font></b> - " . gettext("check for ethernet loops");
1422
			$ifinfo['bridgeint'] = $bridge;
1423
		} else if (stristr($bridge_text, "learning") <> false) {
1424
			$ifinfo['bridge'] = gettext("learning");
1425
			$ifinfo['bridgeint'] = $bridge;
1426
		} else if (stristr($bridge_text, "forwarding") <> false) {
1427
			$ifinfo['bridge'] = gettext("forwarding");
1428
			$ifinfo['bridgeint'] = $bridge;
1429
		}
1430
	}
1431

    
1432
	return $ifinfo;
1433
}
1434

    
1435
//returns cpu speed of processor. Good for determining capabilities of machine
1436
function get_cpu_speed() {
1437
	return get_single_sysctl("hw.clockrate");
1438
}
1439

    
1440
function get_uptime_sec() {
1441
	$boottime = "";
1442
	$matches = "";
1443
	$boottime = get_single_sysctl("kern.boottime");
1444
	preg_match("/sec = (\d+)/", $boottime, $matches);
1445
	$boottime = $matches[1];
1446
	if (intval($boottime) == 0) {
1447
		return 0;
1448
	}
1449

    
1450
	$uptime = time() - $boottime;
1451
	return $uptime;
1452
}
1453

    
1454
function add_hostname_to_watch($hostname) {
1455
	if (!is_dir("/var/db/dnscache")) {
1456
		mkdir("/var/db/dnscache");
1457
	}
1458
	$result = array();
1459
	if ((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1460
		$domrecords = array();
1461
		$domips = array();
1462
		exec("/usr/bin/host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1463
		if ($rethost == 0) {
1464
			foreach ($domrecords as $domr) {
1465
				$doml = explode(" ", $domr);
1466
				$domip = $doml[3];
1467
				/* fill array with domain ip addresses */
1468
				if (is_ipaddr($domip)) {
1469
					$domips[] = $domip;
1470
				}
1471
			}
1472
		}
1473
		sort($domips);
1474
		$contents = "";
1475
		if (!empty($domips)) {
1476
			foreach ($domips as $ip) {
1477
				$contents .= "$ip\n";
1478
			}
1479
		}
1480
		file_put_contents("/var/db/dnscache/$hostname", $contents);
1481
		/* Remove empty elements */
1482
		$result = array_filter(explode("\n", $contents), 'strlen');
1483
	}
1484
	return $result;
1485
}
1486

    
1487
function is_fqdn($fqdn) {
1488
	$hostname = false;
1489
	if (preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1490
		$hostname = true;
1491
	}
1492
	if (preg_match("/\.\./", $fqdn)) {
1493
		$hostname = false;
1494
	}
1495
	if (preg_match("/^\./i", $fqdn)) {
1496
		$hostname = false;
1497
	}
1498
	if (preg_match("/\//i", $fqdn)) {
1499
		$hostname = false;
1500
	}
1501
	return($hostname);
1502
}
1503

    
1504
function pfsense_default_state_size() {
1505
	/* get system memory amount */
1506
	$memory = get_memory();
1507
	$physmem = $memory[0];
1508
	/* Be cautious and only allocate 10% of system memory to the state table */
1509
	$max_states = (int) ($physmem/10)*1000;
1510
	return $max_states;
1511
}
1512

    
1513
function pfsense_default_tables_size() {
1514
	$current = `pfctl -sm | grep ^tables | awk '{print $4};'`;
1515
	return $current;
1516
}
1517

    
1518
function pfsense_default_table_entries_size() {
1519
	$current = `pfctl -sm | grep table-entries | awk '{print $4};'`;
1520
	return $current;
1521
}
1522

    
1523
/* Compare the current hostname DNS to the DNS cache we made
1524
 * if it has changed we return the old records
1525
 * if no change we return false */
1526
function compare_hostname_to_dnscache($hostname) {
1527
	if (!is_dir("/var/db/dnscache")) {
1528
		mkdir("/var/db/dnscache");
1529
	}
1530
	$hostname = trim($hostname);
1531
	if (is_readable("/var/db/dnscache/{$hostname}")) {
1532
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
1533
	} else {
1534
		$oldcontents = "";
1535
	}
1536
	if ((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1537
		$domrecords = array();
1538
		$domips = array();
1539
		exec("/usr/bin/host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1540
		if ($rethost == 0) {
1541
			foreach ($domrecords as $domr) {
1542
				$doml = explode(" ", $domr);
1543
				$domip = $doml[3];
1544
				/* fill array with domain ip addresses */
1545
				if (is_ipaddr($domip)) {
1546
					$domips[] = $domip;
1547
				}
1548
			}
1549
		}
1550
		sort($domips);
1551
		$contents = "";
1552
		if (!empty($domips)) {
1553
			foreach ($domips as $ip) {
1554
				$contents .= "$ip\n";
1555
			}
1556
		}
1557
	}
1558

    
1559
	if (trim($oldcontents) != trim($contents)) {
1560
		if ($g['debug']) {
1561
			log_error(sprintf(gettext('DNSCACHE: Found old IP %1$s and new IP %2$s'), $oldcontents, $contents));
1562
		}
1563
		return ($oldcontents);
1564
	} else {
1565
		return false;
1566
	}
1567
}
1568

    
1569
/*
1570
 * load_crypto() - Load crypto modules if enabled in config.
1571
 */
1572
function load_crypto() {
1573
	global $config, $g;
1574
	$crypto_modules = array('glxsb', 'aesni');
1575

    
1576
	if (!in_array($config['system']['crypto_hardware'], $crypto_modules)) {
1577
		return false;
1578
	}
1579

    
1580
	if (!empty($config['system']['crypto_hardware']) && !is_module_loaded($config['system']['crypto_hardware'])) {
1581
		log_error("Loading {$config['system']['crypto_hardware']} cryptographic accelerator module.");
1582
		mwexec("/sbin/kldload {$config['system']['crypto_hardware']}");
1583
	}
1584
}
1585

    
1586
/*
1587
 * load_thermal_hardware() - Load temperature monitor kernel module
1588
 */
1589
function load_thermal_hardware() {
1590
	global $config, $g;
1591
	$thermal_hardware_modules = array('coretemp', 'amdtemp');
1592

    
1593
	if (!in_array($config['system']['thermal_hardware'], $thermal_hardware_modules)) {
1594
		return false;
1595
	}
1596

    
1597
	if (!empty($config['system']['thermal_hardware']) && !is_module_loaded($config['system']['thermal_hardware'])) {
1598
		log_error("Loading {$config['system']['thermal_hardware']} thermal monitor module.");
1599
		mwexec("/sbin/kldload {$config['system']['thermal_hardware']}");
1600
	}
1601
}
1602

    
1603
/****f* pfsense-utils/isvm
1604
 * NAME
1605
 *   isvm
1606
 * INPUTS
1607
 *	none
1608
 * RESULT
1609
 *   returns true if machine is running under a virtual environment
1610
 ******/
1611
function isvm() {
1612
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86", "VirtualBox");
1613
	$_gb = exec('/bin/kenv smbios.system.product 2>/dev/null', $output, $rc);
1614

    
1615
	if ($rc != 0 || !isset($output[0])) {
1616
		return false;
1617
	}
1618

    
1619
	foreach ($virtualenvs as $virtualenv) {
1620
		if (stripos($output[0], $virtualenv) !== false) {
1621
			return true;
1622
		}
1623
	}
1624

    
1625
	return false;
1626
}
1627

    
1628
function get_freebsd_version() {
1629
	$version = explode(".", php_uname("r"));
1630
	return $version[0];
1631
}
1632

    
1633
function download_file($url, $destination, $verify_ssl = true, $connect_timeout = 5, $timeout = 0) {
1634
	global $config, $g;
1635

    
1636
	$fp = fopen($destination, "wb");
1637

    
1638
	if (!$fp) {
1639
		return false;
1640
	}
1641

    
1642
	$ch = curl_init();
1643
	curl_setopt($ch, CURLOPT_URL, $url);
1644
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1645
	curl_setopt($ch, CURLOPT_FILE, $fp);
1646
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1647
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1648
	curl_setopt($ch, CURLOPT_HEADER, false);
1649
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1650
	if (!isset($config['system']['do_not_send_host_uuid'])) {
1651
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1652
	} else {
1653
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1654
	}
1655

    
1656
	if (!empty($config['system']['proxyurl'])) {
1657
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1658
		if (!empty($config['system']['proxyport'])) {
1659
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1660
		}
1661
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1662
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1663
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1664
		}
1665
	}
1666

    
1667
	@curl_exec($ch);
1668
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1669
	fclose($fp);
1670
	curl_close($ch);
1671
	return ($http_code == 200) ? true : $http_code;
1672
}
1673

    
1674
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body', $connect_timeout = 5, $timeout = 0) {
1675
	global $config, $g;
1676
	global $ch, $fout, $file_size, $downloaded, $config, $first_progress_update;
1677
	$file_size = 1;
1678
	$downloaded = 1;
1679
	$first_progress_update = TRUE;
1680
	/* open destination file */
1681
	$fout = fopen($destination_file, "wb");
1682

    
1683
	/*
1684
	 *      Originally by Author: Keyvan Minoukadeh
1685
	 *      Modified by Scott Ullrich to return Content-Length size
1686
	 */
1687

    
1688
	$ch = curl_init();
1689
	curl_setopt($ch, CURLOPT_URL, $url_file);
1690
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1691
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1692
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1693
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1694
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1695
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1696
	if (!isset($config['system']['do_not_send_host_uuid'])) {
1697
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1698
	} else {
1699
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1700
	}
1701

    
1702
	if (!empty($config['system']['proxyurl'])) {
1703
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1704
		if (!empty($config['system']['proxyport'])) {
1705
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1706
		}
1707
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1708
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1709
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1710
		}
1711
	}
1712

    
1713
	@curl_exec($ch);
1714
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1715
	if ($fout) {
1716
		fclose($fout);
1717
	}
1718
	curl_close($ch);
1719
	return ($http_code == 200) ? true : $http_code;
1720
}
1721

    
1722
function read_header($ch, $string) {
1723
	global $file_size, $fout;
1724
	$length = strlen($string);
1725
	$regs = "";
1726
	preg_match("/(Content-Length:) (.*)/", $string, $regs);
1727
	if ($regs[2] <> "") {
1728
		$file_size = intval($regs[2]);
1729
	}
1730
	ob_flush();
1731
	return $length;
1732
}
1733

    
1734
function read_body($ch, $string) {
1735
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen, $first_progress_update;
1736
	global $pkg_interface;
1737
	$length = strlen($string);
1738
	$downloaded += intval($length);
1739
	if ($file_size > 0) {
1740
		$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1741
		$downloadProgress = 100 - $downloadProgress;
1742
	} else {
1743
		$downloadProgress = 0;
1744
	}
1745
	if ($lastseen <> $downloadProgress and $downloadProgress < 101) {
1746
		if ($sendto == "status") {
1747
			if ($pkg_interface == "console") {
1748
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1749
					$tostatus = $static_status . $downloadProgress . "%";
1750
					if ($downloadProgress == 100) {
1751
						$tostatus = $tostatus . "\r";
1752
					}
1753
					update_status($tostatus);
1754
				}
1755
			} else {
1756
				$tostatus = $static_status . $downloadProgress . "%";
1757
				update_status($tostatus);
1758
			}
1759
		} else {
1760
			if ($pkg_interface == "console") {
1761
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1762
					$tooutput = $static_output . $downloadProgress . "%";
1763
					if ($downloadProgress == 100) {
1764
						$tooutput = $tooutput . "\r";
1765
					}
1766
					update_output_window($tooutput);
1767
				}
1768
			} else {
1769
				$tooutput = $static_output . $downloadProgress . "%";
1770
				update_output_window($tooutput);
1771
			}
1772
		}
1773
		if (($pkg_interface != "console") || (($downloadProgress % 10) == 0) || ($downloadProgress < 10)) {
1774
			update_progress_bar($downloadProgress, $first_progress_update);
1775
			$first_progress_update = FALSE;
1776
		}
1777
		$lastseen = $downloadProgress;
1778
	}
1779
	if ($fout) {
1780
		fwrite($fout, $string);
1781
	}
1782
	ob_flush();
1783
	return $length;
1784
}
1785

    
1786
/*
1787
 *   update_output_window: update bottom textarea dynamically.
1788
 */
1789
function update_output_window($text) {
1790
	global $pkg_interface;
1791
	$log = preg_replace("/\n/", "\\n", $text);
1792
	if ($pkg_interface != "console") {
1793
?>
1794
<script type="text/javascript">
1795
//<![CDATA[
1796
	document.getElementById("output").textContent="<?=htmlspecialchars($log)?>";
1797
	document.getElementById("output").scrollTop = document.getElementById("output").scrollHeight;
1798
//]]>
1799
</script>
1800
<?php
1801
	}
1802
	/* ensure that contents are written out */
1803
	ob_flush();
1804
}
1805

    
1806
/*
1807
 *   update_status: update top textarea dynamically.
1808
 */
1809
function update_status($status) {
1810
	global $pkg_interface;
1811

    
1812
	if ($pkg_interface == "console") {
1813
		echo "\r{$status}";
1814
	}
1815

    
1816
	/* ensure that contents are written out */
1817
	ob_flush();
1818
}
1819

    
1820
/*
1821
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
1822
 */
1823
function update_progress_bar($percent, $first_time) {
1824
	global $pkg_interface;
1825
	if ($percent > 100) {
1826
		$percent = 1;
1827
	}
1828
	if ($pkg_interface <> "console") {
1829
		echo '<script type="text/javascript">';
1830
		echo "\n//<![CDATA[\n";
1831
		echo 'document.getElementById("progressbar").style.width="'. $percent.'%";';
1832
		echo "\n//]]>\n";
1833
		echo '</script>';
1834
	} else {
1835
		if (!($first_time)) {
1836
			echo "\x08\x08\x08\x08\x08";
1837
		}
1838
		echo sprintf("%4d%%", $percent);
1839
	}
1840
}
1841

    
1842
/* Split() is being DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 6.0.0. Relying on this feature is highly discouraged. */
1843
if (!function_exists("split")) {
1844
	function split($separator, $haystack, $limit = null) {
1845
		log_error("deprecated split() call with separator '{$separator}'");
1846
		return preg_split($separator, $haystack, $limit);
1847
	}
1848
}
1849

    
1850
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
1851
	global $g, $config, $pconfig, $debug;
1852
	if (!$origname) {
1853
		return;
1854
	}
1855

    
1856
	$sectionref = &$config;
1857
	foreach ($section as $sectionname) {
1858
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
1859
			$sectionref = &$sectionref[$sectionname];
1860
		} else {
1861
			return;
1862
		}
1863
	}
1864

    
1865
	if ($debug) {
1866
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
1867
		fwrite($fd, print_r($pconfig, true));
1868
	}
1869

    
1870
	if (is_array($sectionref)) {
1871
		foreach ($sectionref as $itemkey => $item) {
1872
			if ($debug) {
1873
				fwrite($fd, "$itemkey\n");
1874
			}
1875

    
1876
			$fieldfound = true;
1877
			$fieldref = &$sectionref[$itemkey];
1878
			foreach ($field as $fieldname) {
1879
				if (is_array($fieldref) && isset($fieldref[$fieldname])) {
1880
					$fieldref = &$fieldref[$fieldname];
1881
				} else {
1882
					$fieldfound = false;
1883
					break;
1884
				}
1885
			}
1886
			if ($fieldfound && $fieldref == $origname) {
1887
				if ($debug) {
1888
					fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1889
				}
1890
				$fieldref = $new_alias_name;
1891
			}
1892
		}
1893
	}
1894

    
1895
	if ($debug) {
1896
		fclose($fd);
1897
	}
1898

    
1899
}
1900

    
1901
function parse_aliases_file($filename, $type = "url", $max_items = -1) {
1902
	/*
1903
	 * $filename = file to process for example blocklist like DROP:  http://www.spamhaus.org/drop/drop.txt
1904
	 * $type = if set to 'url' then subnets and ips will be returned,
1905
	 *         if set to 'url_ports' port-ranges and ports will be returned
1906
	 * $max_items = sets the maximum amount of valid items to load, -1 the default defines there is no limit.
1907
	 *
1908
	 * RETURNS an array of ip subnets and ip's or ports and port-ranges, returns NULL upon a error conditions (file not found)
1909
	 */
1910

    
1911
	$fd = @fopen($filename, 'r');
1912
	if (!$fd) {
1913
		log_error(gettext("Could not process aliases from alias: {$alias_url}"));
1914
		return null;
1915
	}
1916
	$items = array();
1917
	/* NOTE: fgetss() is not a typo RTFM before being smart */
1918
	while (($fc = fgetss($fd)) !== FALSE) {
1919
		$tmp = trim($fc, " \t\n\r");
1920
		if (empty($tmp)) {
1921
			continue;
1922
		}
1923
		$tmp_str = strstr($tmp, '#', true);
1924
		if (!empty($tmp_str)) {
1925
			$tmp = $tmp_str;
1926
		}
1927
		$tmp_str = strstr($tmp, ' ', true);
1928
		if (!empty($tmp_str)) {
1929
			$tmp = $tmp_str;
1930
		}
1931
		$valid = ($type == "url" && (is_ipaddr($tmp) || is_subnet($tmp))) ||
1932
			 ($type == "url_ports" && (is_port($tmp) || is_portrange($tmp)));
1933
		if ($valid) {
1934
			$items[] = $tmp;
1935
			if (count($items) == $max_items) {
1936
				break;
1937
			}
1938
		}
1939
	}
1940
	fclose($fd);
1941
	return $items;
1942
}
1943

    
1944
function update_alias_url_data() {
1945
	global $config, $g;
1946

    
1947
	$updated = false;
1948

    
1949
	/* item is a url type */
1950
	$lockkey = lock('aliasurl');
1951
	if (is_array($config['aliases']['alias'])) {
1952
		foreach ($config['aliases']['alias'] as $x => $alias) {
1953
			if (empty($alias['aliasurl'])) {
1954
				continue;
1955
			}
1956

    
1957
			$address = null;
1958
			foreach ($alias['aliasurl'] as $alias_url) {
1959
				/* fetch down and add in */
1960
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
1961
				unlink($temp_filename);
1962
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
1963
				mkdir($temp_filename);
1964
				download_file($alias_url, $temp_filename . "/aliases", $verify_ssl);
1965

    
1966
				/* if the item is tar gzipped then extract */
1967
				if (stripos($alias_url, '.tgz')) {
1968
					if (!process_alias_tgz($temp_filename)) {
1969
						continue;
1970
					}
1971
				} else if (stripos($alias_url, '.zip')) {
1972
					if (!process_alias_unzip($temp_filename)) {
1973
						continue;
1974
					}
1975
				}
1976
				if (file_exists("{$temp_filename}/aliases")) {
1977
					$address = parse_aliases_file("{$temp_filename}/aliases", $alias['type'], 3000);
1978
					mwexec("/bin/rm -rf {$temp_filename}");
1979
				}
1980
			}
1981
			if ($address != null) {
1982
				$config['aliases']['alias'][$x]['address'] = implode(" ", $address);
1983
				$updated = true;
1984
			}
1985
		}
1986
	}
1987
	unlock($lockkey);
1988

    
1989
	/* Report status to callers as well */
1990
	return $updated;
1991
}
1992

    
1993
function process_alias_unzip($temp_filename) {
1994
	if (!file_exists("/usr/local/bin/unzip")) {
1995
		log_error(gettext("Alias archive is a .zip file which cannot be decompressed because utility is missing!"));
1996
		return false;
1997
	}
1998
	rename("{$temp_filename}/aliases", "{$temp_filename}/aliases.zip");
1999
	mwexec("/usr/local/bin/unzip {$temp_filename}/aliases.tgz -d {$temp_filename}/aliases/");
2000
	unlink("{$temp_filename}/aliases.zip");
2001
	$files_to_process = return_dir_as_array("{$temp_filename}/");
2002
	/* foreach through all extracted files and build up aliases file */
2003
	$fd = @fopen("{$temp_filename}/aliases", "w");
2004
	if (!$fd) {
2005
		log_error(gettext("Could not open {$temp_filename}/aliases for writing!"));
2006
		return false;
2007
	}
2008
	foreach ($files_to_process as $f2p) {
2009
		$tmpfd = @fopen($f2p, 'r');
2010
		if (!$tmpfd) {
2011
			log_error(gettext("The following file could not be read {$f2p} from {$temp_filename}"));
2012
			continue;
2013
		}
2014
		while (($tmpbuf = fread($tmpfd, 65536)) !== FALSE) {
2015
			fwrite($fd, $tmpbuf);
2016
		}
2017
		fclose($tmpfd);
2018
		unlink($f2p);
2019
	}
2020
	fclose($fd);
2021
	unset($tmpbuf);
2022

    
2023
	return true;
2024
}
2025

    
2026
function process_alias_tgz($temp_filename) {
2027
	if (!file_exists('/usr/bin/tar')) {
2028
		log_error(gettext("Alias archive is a .tar/tgz file which cannot be decompressed because utility is missing!"));
2029
		return false;
2030
	}
2031
	rename("{$temp_filename}/aliases", "{$temp_filename}/aliases.tgz");
2032
	mwexec("/usr/bin/tar xzf {$temp_filename}/aliases.tgz -C {$temp_filename}/aliases/");
2033
	unlink("{$temp_filename}/aliases.tgz");
2034
	$files_to_process = return_dir_as_array("{$temp_filename}/");
2035
	/* foreach through all extracted files and build up aliases file */
2036
	$fd = @fopen("{$temp_filename}/aliases", "w");
2037
	if (!$fd) {
2038
		log_error(gettext("Could not open {$temp_filename}/aliases for writing!"));
2039
		return false;
2040
	}
2041
	foreach ($files_to_process as $f2p) {
2042
		$tmpfd = @fopen($f2p, 'r');
2043
		if (!$tmpfd) {
2044
			log_error(gettext("The following file could not be read {$f2p} from {$temp_filename}"));
2045
			continue;
2046
		}
2047
		while (($tmpbuf = fread($tmpfd, 65536)) !== FALSE) {
2048
			fwrite($fd, $tmpbuf);
2049
		}
2050
		fclose($tmpfd);
2051
		unlink($f2p);
2052
	}
2053
	fclose($fd);
2054
	unset($tmpbuf);
2055

    
2056
	return true;
2057
}
2058

    
2059
function version_compare_dates($a, $b) {
2060
	$a_time = strtotime($a);
2061
	$b_time = strtotime($b);
2062

    
2063
	if ((!$a_time) || (!$b_time)) {
2064
		return FALSE;
2065
	} else {
2066
		if ($a_time < $b_time) {
2067
			return -1;
2068
		} elseif ($a_time == $b_time) {
2069
			return 0;
2070
		} else {
2071
			return 1;
2072
		}
2073
	}
2074
}
2075
function version_get_string_value($a) {
2076
	$strs = array(
2077
		0 => "ALPHA-ALPHA",
2078
		2 => "ALPHA",
2079
		3 => "BETA",
2080
		4 => "B",
2081
		5 => "C",
2082
		6 => "D",
2083
		7 => "RC",
2084
		8 => "RELEASE",
2085
		9 => "*"			// Matches all release levels
2086
	);
2087
	$major = 0;
2088
	$minor = 0;
2089
	foreach ($strs as $num => $str) {
2090
		if (substr($a, 0, strlen($str)) == $str) {
2091
			$major = $num;
2092
			$n = substr($a, strlen($str));
2093
			if (is_numeric($n)) {
2094
				$minor = $n;
2095
			}
2096
			break;
2097
		}
2098
	}
2099
	return "{$major}.{$minor}";
2100
}
2101
function version_compare_string($a, $b) {
2102
	// Only compare string parts if both versions give a specific release
2103
	// (If either version lacks a string part, assume intended to match all release levels)
2104
	if (isset($a) && isset($b)) {
2105
		return version_compare_numeric(version_get_string_value($a), version_get_string_value($b));
2106
	} else {
2107
		return 0;
2108
	}
2109
}
2110
function version_compare_numeric($a, $b) {
2111
	$a_arr = explode('.', rtrim($a, '.'));
2112
	$b_arr = explode('.', rtrim($b, '.'));
2113

    
2114
	foreach ($a_arr as $n => $val) {
2115
		if (array_key_exists($n, $b_arr)) {
2116
			// So far so good, both have values at this minor version level. Compare.
2117
			if ($val > $b_arr[$n]) {
2118
				return 1;
2119
			} elseif ($val < $b_arr[$n]) {
2120
				return -1;
2121
			}
2122
		} else {
2123
			// a is greater, since b doesn't have any minor version here.
2124
			return 1;
2125
		}
2126
	}
2127
	if (count($b_arr) > count($a_arr)) {
2128
		// b is longer than a, so it must be greater.
2129
		return -1;
2130
	} else {
2131
		// Both a and b are of equal length and value.
2132
		return 0;
2133
	}
2134
}
2135
function pfs_version_compare($cur_time, $cur_text, $remote) {
2136
	// First try date compare
2137
	$v = version_compare_dates($cur_time, $remote);
2138
	if ($v === FALSE) {
2139
		// If that fails, try to compare by string
2140
		// Before anything else, simply test if the strings are equal
2141
		if (($cur_text == $remote) || ($cur_time == $remote)) {
2142
			return 0;
2143
		}
2144
		list($cur_num, $cur_str) = explode('-', $cur_text);
2145
		list($rem_num, $rem_str) = explode('-', $remote);
2146

    
2147
		// First try to compare the numeric parts of the version string.
2148
		$v = version_compare_numeric($cur_num, $rem_num);
2149

    
2150
		// If the numeric parts are the same, compare the string parts.
2151
		if ($v == 0) {
2152
			return version_compare_string($cur_str, $rem_str);
2153
		}
2154
	}
2155
	return $v;
2156
}
2157
function process_alias_urltable($name, $url, $freq, $forceupdate=false) {
2158
	global $config;
2159

    
2160
	$urltable_prefix = "/var/db/aliastables/";
2161
	$urltable_filename = $urltable_prefix . $name . ".txt";
2162

    
2163
	// Make the aliases directory if it doesn't exist
2164
	if (!file_exists($urltable_prefix)) {
2165
		mkdir($urltable_prefix);
2166
	} elseif (!is_dir($urltable_prefix)) {
2167
		unlink($urltable_prefix);
2168
		mkdir($urltable_prefix);
2169
	}
2170

    
2171
	// If the file doesn't exist or is older than update_freq days, fetch a new copy.
2172
	if (!file_exists($urltable_filename) ||
2173
	    ((time() - filemtime($urltable_filename)) > ($freq * 86400 - 90)) ||
2174
	    $forceupdate) {
2175

    
2176
		// Try to fetch the URL supplied
2177
		conf_mount_rw();
2178
		unlink_if_exists($urltable_filename . ".tmp");
2179
		$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2180
		if (download_file($url, $urltable_filename . ".tmp", $verify_ssl)) {
2181
			mwexec("/usr/bin/sed -E 's/\;.*//g; /^[[:space:]]*($|#)/d' ". escapeshellarg($urltable_filename . ".tmp") . " > " . escapeshellarg($urltable_filename));
2182
			if (alias_get_type($name) == "urltable_ports") {
2183
				$ports = explode("\n", str_replace("\r", "", file_get_contents($urltable_filename)));
2184
				$ports = group_ports($ports);
2185
				file_put_contents($urltable_filename, implode("\n", $ports));
2186
			}
2187
			unlink_if_exists($urltable_filename . ".tmp");
2188
		} else {
2189
			touch($urltable_filename);
2190
		}
2191
		conf_mount_ro();
2192
		return true;
2193
	} else {
2194
		// File exists, and it doesn't need to be updated.
2195
		return -1;
2196
	}
2197
}
2198
function get_real_slice_from_glabel($label) {
2199
	$label = escapeshellarg($label);
2200
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/{$label} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`);
2201
}
2202
function nanobsd_get_boot_slice() {
2203
	return trim(`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`);
2204
}
2205
function nanobsd_get_boot_drive() {
2206
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/pfsense | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' ' | /usr/bin/cut -d's' -f1`);
2207
}
2208
function nanobsd_get_active_slice() {
2209
	$boot_drive = nanobsd_get_boot_drive();
2210
	$active = trim(`gpart show $boot_drive | grep '\[active\]' | awk '{print $3;}'`);
2211

    
2212
	return "{$boot_drive}s{$active}";
2213
}
2214
function nanobsd_get_size() {
2215
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2216
}
2217
function nanobsd_switch_boot_slice() {
2218
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2219
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2220
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2221
	nanobsd_detect_slice_info();
2222

    
2223
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2224
		$slice = $TOFLASH;
2225
	} else {
2226
		$slice = $BOOTFLASH;
2227
	}
2228

    
2229
	for ($i = 0; $i < ob_get_level(); $i++) {
2230
		ob_end_flush();
2231
	}
2232
	ob_implicit_flush(1);
2233
	if (strstr($slice, "s2")) {
2234
		$ASLICE = "2";
2235
		$AOLDSLICE = "1";
2236
		$AGLABEL_SLICE = "pfsense1";
2237
		$AUFS_ID = "1";
2238
		$AOLD_UFS_ID = "0";
2239
	} else {
2240
		$ASLICE = "1";
2241
		$AOLDSLICE = "2";
2242
		$AGLABEL_SLICE = "pfsense0";
2243
		$AUFS_ID = "0";
2244
		$AOLD_UFS_ID = "1";
2245
	}
2246
	$ATOFLASH = "{$BOOT_DRIVE}s{$ASLICE}";
2247
	$ACOMPLETE_PATH = "{$BOOT_DRIVE}s{$ASLICE}a";
2248
	$ABOOTFLASH = "{$BOOT_DRIVE}s{$AOLDSLICE}";
2249
	conf_mount_rw();
2250
	set_single_sysctl("kern.geom.debugflags", "16");
2251
	exec("/sbin/gpart set -a active -i {$ASLICE} {$BOOT_DRIVE}");
2252
	exec("/usr/sbin/boot0cfg -s {$ASLICE} -v /dev/{$BOOT_DRIVE}");
2253
	// We can't update these if they are mounted now.
2254
	if ($BOOTFLASH != $slice) {
2255
		exec("/sbin/tunefs -L ${AGLABEL_SLICE} /dev/$ACOMPLETE_PATH");
2256
		nanobsd_update_fstab($AGLABEL_SLICE, $ACOMPLETE_PATH, $AOLD_UFS_ID, $AUFS_ID);
2257
	}
2258
	set_single_sysctl("kern.geom.debugflags", "0");
2259
	conf_mount_ro();
2260
}
2261
function nanobsd_clone_slice() {
2262
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2263
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2264
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2265
	nanobsd_detect_slice_info();
2266

    
2267
	for ($i = 0; $i < ob_get_level(); $i++) {
2268
		ob_end_flush();
2269
	}
2270
	ob_implicit_flush(1);
2271
	set_single_sysctl("kern.geom.debugflags", "16");
2272
	exec("/bin/dd if=/dev/zero of=/dev/{$TOFLASH} bs=1m count=1");
2273
	exec("/bin/dd if=/dev/{$BOOTFLASH} of=/dev/{$TOFLASH} bs=64k");
2274
	exec("/sbin/tunefs -L {$GLABEL_SLICE} /dev/{$COMPLETE_PATH}");
2275
	$status = nanobsd_update_fstab($GLABEL_SLICE, $COMPLETE_PATH, $OLD_UFS_ID, $UFS_ID);
2276
	set_single_sysctl("kern.geom.debugflags", "0");
2277
	if ($status) {
2278
		return false;
2279
	} else {
2280
		return true;
2281
	}
2282
}
2283
function nanobsd_update_fstab($gslice, $complete_path, $oldufs, $newufs) {
2284
	$tmppath = "/tmp/{$gslice}";
2285
	$fstabpath = "/tmp/{$gslice}/etc/fstab";
2286

    
2287
	mkdir($tmppath);
2288
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2289
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2290
	copy("/etc/fstab", $fstabpath);
2291

    
2292
	if (!file_exists($fstabpath)) {
2293
		$fstab = <<<EOF
2294
/dev/ufs/{$gslice} / ufs ro,noatime 1 1
2295
/dev/ufs/cf /cf ufs ro,noatime 1 1
2296
EOF;
2297
		if (file_put_contents($fstabpath, $fstab)) {
2298
			$status = true;
2299
		} else {
2300
			$status = false;
2301
		}
2302
	} else {
2303
		$status = exec("/usr/bin/sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2304
	}
2305
	exec("/sbin/umount {$tmppath}");
2306
	rmdir($tmppath);
2307

    
2308
	return $status;
2309
}
2310
function nanobsd_detect_slice_info() {
2311
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2312
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2313
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2314

    
2315
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2316
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2317
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2318
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2319

    
2320
	// Detect which slice is active and set information.
2321
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2322
		$SLICE = "2";
2323
		$OLDSLICE = "1";
2324
		$GLABEL_SLICE = "pfsense1";
2325
		$UFS_ID = "1";
2326
		$OLD_UFS_ID = "0";
2327

    
2328
	} else {
2329
		$SLICE = "1";
2330
		$OLDSLICE = "2";
2331
		$GLABEL_SLICE = "pfsense0";
2332
		$UFS_ID = "0";
2333
		$OLD_UFS_ID = "1";
2334
	}
2335
	$TOFLASH = "{$BOOT_DRIVE}s{$SLICE}";
2336
	$COMPLETE_PATH = "{$BOOT_DRIVE}s{$SLICE}a";
2337
	$COMPLETE_BOOT_PATH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2338
	$BOOTFLASH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2339
}
2340

    
2341
function nanobsd_friendly_slice_name($slicename) {
2342
	global $g;
2343
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2344
}
2345

    
2346
function get_include_contents($filename) {
2347
	if (is_file($filename)) {
2348
		ob_start();
2349
		include $filename;
2350
		$contents = ob_get_contents();
2351
		ob_end_clean();
2352
		return $contents;
2353
	}
2354
	return false;
2355
}
2356

    
2357
/* This xml 2 array function is courtesy of the php.net comment section on xml_parse.
2358
 * it is roughly 4 times faster then our existing pfSense parser but due to the large
2359
 * size of the RRD xml dumps this is required.
2360
 * The reason we do not use it for pfSense is that it does not know about array fields
2361
 * which causes it to fail on array fields with single items. Possible Todo?
2362
 */
2363
function xml2array($contents, $get_attributes = 1, $priority = 'tag') {
2364
	if (!function_exists('xml_parser_create')) {
2365
		return array ();
2366
	}
2367
	$parser = xml_parser_create('');
2368
	xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
2369
	xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
2370
	xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
2371
	xml_parse_into_struct($parser, trim($contents), $xml_values);
2372
	xml_parser_free($parser);
2373
	if (!$xml_values) {
2374
		return; //Hmm...
2375
	}
2376
	$xml_array = array ();
2377
	$parents = array ();
2378
	$opened_tags = array ();
2379
	$arr = array ();
2380
	$current = & $xml_array;
2381
	$repeated_tag_index = array ();
2382
	foreach ($xml_values as $data) {
2383
		unset ($attributes, $value);
2384
		extract($data);
2385
		$result = array ();
2386
		$attributes_data = array ();
2387
		if (isset ($value)) {
2388
			if ($priority == 'tag') {
2389
				$result = $value;
2390
			} else {
2391
				$result['value'] = $value;
2392
			}
2393
		}
2394
		if (isset ($attributes) and $get_attributes) {
2395
			foreach ($attributes as $attr => $val) {
2396
				if ($priority == 'tag') {
2397
					$attributes_data[$attr] = $val;
2398
				} else {
2399
					$result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
2400
				}
2401
			}
2402
		}
2403
		if ($type == "open") {
2404
			$parent[$level -1] = & $current;
2405
			if (!is_array($current) or (!in_array($tag, array_keys($current)))) {
2406
				$current[$tag] = $result;
2407
				if ($attributes_data) {
2408
					$current[$tag . '_attr'] = $attributes_data;
2409
				}
2410
				$repeated_tag_index[$tag . '_' . $level] = 1;
2411
				$current = & $current[$tag];
2412
			} else {
2413
				if (isset ($current[$tag][0])) {
2414
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2415
					$repeated_tag_index[$tag . '_' . $level]++;
2416
				} else {
2417
					$current[$tag] = array (
2418
						$current[$tag],
2419
						$result
2420
						);
2421
					$repeated_tag_index[$tag . '_' . $level] = 2;
2422
					if (isset ($current[$tag . '_attr'])) {
2423
						$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2424
						unset ($current[$tag . '_attr']);
2425
					}
2426
				}
2427
				$last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
2428
				$current = & $current[$tag][$last_item_index];
2429
			}
2430
		} elseif ($type == "complete") {
2431
			if (!isset ($current[$tag])) {
2432
				$current[$tag] = $result;
2433
				$repeated_tag_index[$tag . '_' . $level] = 1;
2434
				if ($priority == 'tag' and $attributes_data) {
2435
					$current[$tag . '_attr'] = $attributes_data;
2436
				}
2437
			} else {
2438
				if (isset ($current[$tag][0]) and is_array($current[$tag])) {
2439
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2440
					if ($priority == 'tag' and $get_attributes and $attributes_data) {
2441
						$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2442
					}
2443
					$repeated_tag_index[$tag . '_' . $level]++;
2444
				} else {
2445
					$current[$tag] = array (
2446
						$current[$tag],
2447
						$result
2448
						);
2449
					$repeated_tag_index[$tag . '_' . $level] = 1;
2450
					if ($priority == 'tag' and $get_attributes) {
2451
						if (isset ($current[$tag . '_attr'])) {
2452
							$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2453
							unset ($current[$tag . '_attr']);
2454
						}
2455
						if ($attributes_data) {
2456
							$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2457
						}
2458
					}
2459
					$repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
2460
				}
2461
			}
2462
		} elseif ($type == 'close') {
2463
			$current = & $parent[$level -1];
2464
		}
2465
	}
2466
	return ($xml_array);
2467
}
2468

    
2469
function get_country_name($country_code) {
2470
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2471
		return "";
2472
	}
2473

    
2474
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2475
	$country_names_contents = file_get_contents($country_names_xml);
2476
	$country_names = xml2array($country_names_contents);
2477

    
2478
	if ($country_code == "ALL") {
2479
		$country_list = array();
2480
		foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2481
			$country_list[] = array(
2482
				"code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2483
				"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])));
2484
		}
2485
		return $country_list;
2486
	}
2487

    
2488
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2489
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2490
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2491
		}
2492
	}
2493
	return "";
2494
}
2495

    
2496
/* sort by interface only, retain the original order of rules that apply to
2497
   the same interface */
2498
function filter_rules_sort() {
2499
	global $config;
2500

    
2501
	/* mark each rule with the sequence number (to retain the order while sorting) */
2502
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2503
		$config['filter']['rule'][$i]['seq'] = $i;
2504
	}
2505

    
2506
	usort($config['filter']['rule'], "filter_rules_compare");
2507

    
2508
	/* strip the sequence numbers again */
2509
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2510
		unset($config['filter']['rule'][$i]['seq']);
2511
	}
2512
}
2513
function filter_rules_compare($a, $b) {
2514
	if (isset($a['floating']) && isset($b['floating'])) {
2515
		return $a['seq'] - $b['seq'];
2516
	} else if (isset($a['floating'])) {
2517
		return -1;
2518
	} else if (isset($b['floating'])) {
2519
		return 1;
2520
	} else if ($a['interface'] == $b['interface']) {
2521
		return $a['seq'] - $b['seq'];
2522
	} else {
2523
		return compare_interface_friendly_names($a['interface'], $b['interface']);
2524
	}
2525
}
2526

    
2527
function generate_ipv6_from_mac($mac) {
2528
	$elements = explode(":", $mac);
2529
	if (count($elements) <> 6) {
2530
		return false;
2531
	}
2532

    
2533
	$i = 0;
2534
	$ipv6 = "fe80::";
2535
	foreach ($elements as $byte) {
2536
		if ($i == 0) {
2537
			$hexadecimal = substr($byte, 1, 2);
2538
			$bitmap = base_convert($hexadecimal, 16, 2);
2539
			$bitmap = str_pad($bitmap, 4, "0", STR_PAD_LEFT);
2540
			$bitmap = substr($bitmap, 0, 2) ."1". substr($bitmap, 3, 4);
2541
			$byte = substr($byte, 0, 1) . base_convert($bitmap, 2, 16);
2542
		}
2543
		$ipv6 .= $byte;
2544
		if ($i == 1) {
2545
			$ipv6 .= ":";
2546
		}
2547
		if ($i == 3) {
2548
			$ipv6 .= ":";
2549
		}
2550
		if ($i == 2) {
2551
			$ipv6 .= "ff:fe";
2552
		}
2553

    
2554
		$i++;
2555
	}
2556
	return $ipv6;
2557
}
2558

    
2559
/****f* pfsense-utils/load_mac_manufacturer_table
2560
 * NAME
2561
 *   load_mac_manufacturer_table
2562
 * INPUTS
2563
 *   none
2564
 * RESULT
2565
 *   returns associative array with MAC-Manufacturer pairs
2566
 ******/
2567
function load_mac_manufacturer_table() {
2568
	/* load MAC-Manufacture data from the file */
2569
	$macs = false;
2570
	if (file_exists("/usr/local/share/nmap/nmap-mac-prefixes")) {
2571
		$macs=file("/usr/local/share/nmap/nmap-mac-prefixes");
2572
	}
2573
	if ($macs) {
2574
		foreach ($macs as $line) {
2575
			if (preg_match('/([0-9A-Fa-f]{6}) (.*)$/', $line, $matches)) {
2576
				/* store values like this $mac_man['000C29']='VMware' */
2577
				$mac_man["$matches[1]"] = $matches[2];
2578
			}
2579
		}
2580
		return $mac_man;
2581
	} else {
2582
		return -1;
2583
	}
2584

    
2585
}
2586

    
2587
/****f* pfsense-utils/is_ipaddr_configured
2588
 * NAME
2589
 *   is_ipaddr_configured
2590
 * INPUTS
2591
 *   IP Address to check.
2592
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2593
 *   check_localip - if true then also check for matches with PPTP and LT2P addresses
2594
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2595
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2596
 *     If check_subnets is true and cidrprefix is specified,
2597
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2598
 * RESULT
2599
 *   returns true if the IP Address is configured and present on this device or overlaps a configured subnet.
2600
*/
2601
function is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2602
	if (count(where_is_ipaddr_configured($ipaddr, $ignore_if, $check_localip, $check_subnets, $cidrprefix))) {
2603
		return true;
2604
	}
2605
	return false;
2606
}
2607

    
2608
/****f* pfsense-utils/where_is_ipaddr_configured
2609
 * NAME
2610
 *   where_is_ipaddr_configured
2611
 * INPUTS
2612
 *   IP Address to check.
2613
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2614
 *   check_localip - if true then also check for matches with PPTP and LT2P addresses
2615
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2616
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2617
 *     If check_subnets is true and cidrprefix is specified,
2618
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2619
 * RESULT
2620
 *   Returns an array of the interfaces 'if' plus IP address or subnet 'ip_or_subnet' that match or overlap the IP address to check.
2621
 *   If there are no matches then an empty array is returned.
2622
*/
2623
function where_is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2624
	global $config;
2625

    
2626
	$where_configured = array();
2627

    
2628
	$pos = strpos($ignore_if, '_virtualip');
2629
	if ($pos !== false) {
2630
		$ignore_vip_id = substr($ignore_if, $pos+10);
2631
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2632
	} else {
2633
		$ignore_vip_id = -1;
2634
		$ignore_vip_if = $ignore_if;
2635
	}
2636

    
2637
	$isipv6 = is_ipaddrv6($ipaddr);
2638

    
2639
	if ($check_subnets) {
2640
		$cidrprefix = intval($cidrprefix);
2641
		if ($isipv6) {
2642
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2643
				$cidrprefix = 128;
2644
			}
2645
		} else {
2646
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2647
				$cidrprefix = 32;
2648
			}
2649
		}
2650
		$iflist = get_configured_interface_list();
2651
		foreach ($iflist as $if => $ifname) {
2652
			if ($ignore_if == $if) {
2653
				continue;
2654
			}
2655

    
2656
			if ($isipv6) {
2657
				$if_ipv6 = get_interface_ipv6($if);
2658
				$if_snbitsv6 = get_interface_subnetv6($if);
2659
				if ($if_ipv6 && $if_snbitsv6 && check_subnetsv6_overlap($ipaddr, $cidrprefix, $if_ipv6, $if_snbitsv6)) {
2660
					$where_entry = array();
2661
					$where_entry['if'] = $if;
2662
					$where_entry['ip_or_subnet'] = get_interface_ipv6($if) . "/" . get_interface_subnetv6($if);
2663
					$where_configured[] = $where_entry;
2664
				}
2665
			} else {
2666
				$if_ipv4 = get_interface_ip($if);
2667
				$if_snbitsv4 = get_interface_subnet($if);
2668
				if ($if_ipv4 && $if_snbitsv4 && check_subnets_overlap($ipaddr, $cidrprefix, $if_ipv4, $if_snbitsv4)) {
2669
					$where_entry = array();
2670
					$where_entry['if'] = $if;
2671
					$where_entry['ip_or_subnet'] = get_interface_ip($if) . "/" . get_interface_subnet($if);
2672
					$where_configured[] = $where_entry;
2673
				}
2674
			}
2675
		}
2676
	} else {
2677
		if ($isipv6) {
2678
			$interface_list_ips = get_configured_ipv6_addresses();
2679
		} else {
2680
			$interface_list_ips = get_configured_ip_addresses();
2681
		}
2682

    
2683
		foreach ($interface_list_ips as $if => $ilips) {
2684
			if ($ignore_if == $if) {
2685
				continue;
2686
			}
2687
			if (strcasecmp($ipaddr, $ilips) == 0) {
2688
				$where_entry = array();
2689
				$where_entry['if'] = $if;
2690
				$where_entry['ip_or_subnet'] = $ilips;
2691
				$where_configured[] = $where_entry;
2692
			}
2693
		}
2694
	}
2695

    
2696
	$interface_list_vips = get_configured_vips_list(true);
2697
	foreach ($interface_list_vips as $id => $vip) {
2698
		/* Skip CARP interfaces here since they were already checked above */
2699
		if ($id == $ignore_vip_id || (substr($ignore_if, 0, 4) == '_vip') && $ignore_vip_if === $vip['if']) {
2700
			continue;
2701
		}
2702
		if (strcasecmp($ipaddr, $vip['ipaddr']) == 0) {
2703
			$where_entry = array();
2704
			$where_entry['if'] = $vip['if'];
2705
			$where_entry['ip_or_subnet'] = $vip['ipaddr'];
2706
			$where_configured[] = $where_entry;
2707
		}
2708
	}
2709

    
2710
	if ($check_localip) {
2711
		if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0)) {
2712
			$where_entry = array();
2713
			$where_entry['if'] = 'l2tp';
2714
			$where_entry['ip_or_subnet'] = $config['l2tp']['localip'];
2715
			$where_configured[] = $where_entry;
2716
		}
2717
	}
2718

    
2719
	return $where_configured;
2720
}
2721

    
2722
/****f* pfsense-utils/pfSense_handle_custom_code
2723
 * NAME
2724
 *   pfSense_handle_custom_code
2725
 * INPUTS
2726
 *   directory name to process
2727
 * RESULT
2728
 *   globs the directory and includes the files
2729
 */
2730
function pfSense_handle_custom_code($src_dir) {
2731
	// Allow extending of the nat edit page and include custom input validation
2732
	if (is_dir("$src_dir")) {
2733
		$cf = glob($src_dir . "/*.inc");
2734
		foreach ($cf as $nf) {
2735
			if ($nf == "." || $nf == "..") {
2736
				continue;
2737
			}
2738
			// Include the extra handler
2739
			include("$nf");
2740
		}
2741
	}
2742
}
2743

    
2744
function set_language($lang = 'en_US', $encoding = "UTF-8") {
2745
	putenv("LANG={$lang}.{$encoding}");
2746
	setlocale(LC_ALL, "{$lang}.{$encoding}");
2747
	textdomain("pfSense");
2748
	bindtextdomain("pfSense", "/usr/local/share/locale");
2749
	bind_textdomain_codeset("pfSense", "{$lang}.{$encoding}");
2750
}
2751

    
2752
function get_locale_list() {
2753
	$locales = array(
2754
		"en_US" => gettext("English"),
2755
		"pt_BR" => gettext("Portuguese (Brazil)"),
2756
		"tr" => gettext("Turkish"),
2757
	);
2758
	asort($locales);
2759
	return $locales;
2760
}
2761

    
2762
function system_get_language_code() {
2763
	global $config, $g_languages;
2764

    
2765
	// a language code, as per [RFC3066]
2766
	$language = $config['system']['language'];
2767
	//$code = $g_languages[$language]['code'];
2768
	$code = str_replace("_", "-", $language);
2769

    
2770
	if (empty($code)) {
2771
		$code = "en-US"; // Set default code.
2772
	}
2773

    
2774
	return $code;
2775
}
2776

    
2777
function system_get_language_codeset() {
2778
	global $config, $g_languages;
2779

    
2780
	$language = $config['system']['language'];
2781
	$codeset = $g_languages[$language]['codeset'];
2782

    
2783
	if (empty($codeset)) {
2784
		$codeset = "UTF-8"; // Set default codeset.
2785
	}
2786

    
2787
	return $codeset;
2788
}
2789

    
2790
/* Available languages/locales */
2791
$g_languages = array (
2792
	"sq"    => array("codeset" => "UTF-8", "desc" => gettext("Albanian")),
2793
	"bg"    => array("codeset" => "UTF-8", "desc" => gettext("Bulgarian")),
2794
	"zh_CN" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Simplified)")),
2795
	"zh_TW" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Traditional)")),
2796
	"nl"    => array("codeset" => "UTF-8", "desc" => gettext("Dutch")),
2797
	"da"    => array("codeset" => "UTF-8", "desc" => gettext("Danish")),
2798
	"en_US" => array("codeset" => "UTF-8", "desc" => gettext("English")),
2799
	"fi"    => array("codeset" => "UTF-8", "desc" => gettext("Finnish")),
2800
	"fr"    => array("codeset" => "UTF-8", "desc" => gettext("French")),
2801
	"de"    => array("codeset" => "UTF-8", "desc" => gettext("German")),
2802
	"el"    => array("codeset" => "UTF-8", "desc" => gettext("Greek")),
2803
	"hu"    => array("codeset" => "UTF-8", "desc" => gettext("Hungarian")),
2804
	"it"    => array("codeset" => "UTF-8", "desc" => gettext("Italian")),
2805
	"ja"    => array("codeset" => "UTF-8", "desc" => gettext("Japanese")),
2806
	"ko"    => array("codeset" => "UTF-8", "desc" => gettext("Korean")),
2807
	"lv"    => array("codeset" => "UTF-8", "desc" => gettext("Latvian")),
2808
	"nb"    => array("codeset" => "UTF-8", "desc" => gettext("Norwegian (Bokmal)")),
2809
	"pl"    => array("codeset" => "UTF-8", "desc" => gettext("Polish")),
2810
	"pt_BR" => array("codeset" => "UTF-8", "desc" => gettext("Portuguese (Brazil)")),
2811
	"pt"    => array("codeset" => "UTF-8", "desc" => gettext("Portuguese (Portugal)")),
2812
	"ro"    => array("codeset" => "UTF-8", "desc" => gettext("Romanian")),
2813
	"ru"    => array("codeset" => "UTF-8", "desc" => gettext("Russian")),
2814
	"sl"    => array("codeset" => "UTF-8", "desc" => gettext("Slovenian")),
2815
	"tr"    => array("codeset" => "UTF-8", "desc" => gettext("Turkish")),
2816
	"es"    => array("codeset" => "UTF-8", "desc" => gettext("Spanish")),
2817
	"sv"    => array("codeset" => "UTF-8", "desc" => gettext("Swedish")),
2818
	"sk"    => array("codeset" => "UTF-8", "desc" => gettext("Slovak")),
2819
	"cs"    => array("codeset" => "UTF-8", "desc" => gettext("Czech"))
2820
);
2821

    
2822
function return_hex_ipv4($ipv4) {
2823
	if (!is_ipaddrv4($ipv4)) {
2824
		return(false);
2825
	}
2826

    
2827
	/* we need the hex form of the interface IPv4 address */
2828
	$ip4arr = explode(".", $ipv4);
2829
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2830
}
2831

    
2832
function convert_ipv6_to_128bit($ipv6) {
2833
	if (!is_ipaddrv6($ipv6)) {
2834
		return(false);
2835
	}
2836

    
2837
	$ip6arr = array();
2838
	$ip6prefix = Net_IPv6::uncompress($ipv6);
2839
	$ip6arr = explode(":", $ip6prefix);
2840
	/* binary presentation of the prefix for all 128 bits. */
2841
	$ip6prefixbin = "";
2842
	foreach ($ip6arr as $element) {
2843
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
2844
	}
2845
	return($ip6prefixbin);
2846
}
2847

    
2848
function convert_128bit_to_ipv6($ip6bin) {
2849
	if (strlen($ip6bin) <> 128) {
2850
		return(false);
2851
	}
2852

    
2853
	$ip6arr = array();
2854
	$ip6binarr = array();
2855
	$ip6binarr = str_split($ip6bin, 16);
2856
	foreach ($ip6binarr as $binpart) {
2857
		$ip6arr[] = dechex(bindec($binpart));
2858
	}
2859
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2860

    
2861
	return($ip6addr);
2862
}
2863

    
2864

    
2865
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
2866
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
2867
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
2868
/* 6to4 is 16 bits, e.g. 65535 */
2869
function calculate_ipv6_delegation_length($if) {
2870
	global $config;
2871

    
2872
	if (!is_array($config['interfaces'][$if])) {
2873
		return false;
2874
	}
2875

    
2876
	switch ($config['interfaces'][$if]['ipaddrv6']) {
2877
		case "6to4":
2878
			$pdlen = 16;
2879
			break;
2880
		case "6rd":
2881
			$rd6cfg = $config['interfaces'][$if];
2882
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
2883
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
2884
			break;
2885
		case "dhcp6":
2886
			$dhcp6cfg = $config['interfaces'][$if];
2887
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
2888
			break;
2889
		default:
2890
			$pdlen = 0;
2891
			break;
2892
	}
2893
	return($pdlen);
2894
}
2895

    
2896
function huawei_rssi_to_string($rssi) {
2897
	$dbm = array();
2898
	$i = 0;
2899
	$dbstart = -113;
2900
	while ($i < 32) {
2901
		$dbm[$i] = $dbstart + ($i * 2);
2902
		$i++;
2903
	}
2904
	$percent = round(($rssi / 31) * 100);
2905
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
2906
	return $string;
2907
}
2908

    
2909
function huawei_mode_to_string($mode, $submode) {
2910
	$modes[0] = "None";
2911
	$modes[1] = "AMPS";
2912
	$modes[2] = "CDMA";
2913
	$modes[3] = "GSM/GPRS";
2914
	$modes[4] = "HDR";
2915
	$modes[5] = "WCDMA";
2916
	$modes[6] = "GPS";
2917

    
2918
	$submodes[0] = "No Service";
2919
	$submodes[1] = "GSM";
2920
	$submodes[2] = "GPRS";
2921
	$submodes[3] = "EDGE";
2922
	$submodes[4] = "WCDMA";
2923
	$submodes[5] = "HSDPA";
2924
	$submodes[6] = "HSUPA";
2925
	$submodes[7] = "HSDPA+HSUPA";
2926
	$submodes[8] = "TD-SCDMA";
2927
	$submodes[9] = "HSPA+";
2928
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
2929
	return $string;
2930
}
2931

    
2932
function huawei_service_to_string($state) {
2933
	$modes[0] = "No";
2934
	$modes[1] = "Restricted";
2935
	$modes[2] = "Valid";
2936
	$modes[3] = "Restricted Regional";
2937
	$modes[4] = "Powersaving";
2938
	$string = "{$modes[$state]} Service";
2939
	return $string;
2940
}
2941

    
2942
function huawei_simstate_to_string($state) {
2943
	$modes[0] = "Invalid SIM/locked";
2944
	$modes[1] = "Valid SIM";
2945
	$modes[2] = "Invalid SIM CS";
2946
	$modes[3] = "Invalid SIM PS";
2947
	$modes[4] = "Invalid SIM CS/PS";
2948
	$modes[255] = "Missing SIM";
2949
	$string = "{$modes[$state]} State";
2950
	return $string;
2951
}
2952

    
2953
function zte_rssi_to_string($rssi) {
2954
	return huawei_rssi_to_string($rssi);
2955
}
2956

    
2957
function zte_mode_to_string($mode, $submode) {
2958
	$modes[0] = "No Service";
2959
	$modes[1] = "Limited Service";
2960
	$modes[2] = "GPRS";
2961
	$modes[3] = "GSM";
2962
	$modes[4] = "UMTS";
2963
	$modes[5] = "EDGE";
2964
	$modes[6] = "HSDPA";
2965

    
2966
	$submodes[0] = "CS_ONLY";
2967
	$submodes[1] = "PS_ONLY";
2968
	$submodes[2] = "CS_PS";
2969
	$submodes[3] = "CAMPED";
2970
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
2971
	return $string;
2972
}
2973

    
2974
function zte_service_to_string($state) {
2975
	$modes[0] = "Initializing";
2976
	$modes[1] = "Network Lock error";
2977
	$modes[2] = "Network Locked";
2978
	$modes[3] = "Unlocked or correct MCC/MNC";
2979
	$string = "{$modes[$state]} Service";
2980
	return $string;
2981
}
2982

    
2983
function zte_simstate_to_string($state) {
2984
	$modes[0] = "No action";
2985
	$modes[1] = "Network lock";
2986
	$modes[2] = "(U)SIM card lock";
2987
	$modes[3] = "Network Lock and (U)SIM card Lock";
2988
	$string = "{$modes[$state]} State";
2989
	return $string;
2990
}
2991

    
2992
function get_configured_pppoe_server_interfaces() {
2993
	global $config;
2994
	$iflist = array();
2995
	if (is_array($config['pppoes']['pppoe'])) {
2996
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
2997
			if ($pppoe['mode'] == "server") {
2998
				$int = "poes". $pppoe['pppoeid'];
2999
				$iflist[$int] = strtoupper($int);
3000
			}
3001
		}
3002
	}
3003
	return $iflist;
3004
}
3005

    
3006
function get_pppoes_child_interfaces($ifpattern) {
3007
	$if_arr = array();
3008
	if ($ifpattern == "") {
3009
		return;
3010
	}
3011

    
3012
	exec("/sbin/ifconfig", $out, $ret);
3013
	foreach ($out as $line) {
3014
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3015
			$if_arr[] = $match[1];
3016
		}
3017
	}
3018
	return $if_arr;
3019

    
3020
}
3021

    
3022
/****f* pfsense-utils/pkg_call_plugins
3023
 * NAME
3024
 *   pkg_call_plugins
3025
 * INPUTS
3026
 *   $plugin_type value used to search in package configuration if the plugin is used, also used to create the function name
3027
 *   $plugin_params parameters to pass to the plugin function for passing multiple parameters a array can be used.
3028
 * RESULT
3029
 *   returns associative array results from the plugin calls for each package
3030
 * NOTES
3031
 *   This generic function can be used to notify or retrieve results from functions that are defined in packages.
3032
 ******/
3033
function pkg_call_plugins($plugin_type, $plugin_params) {
3034
	global $g, $config;
3035
	$results = array();
3036
	if (!is_array($config['installedpackages']['package'])) {
3037
		return $results;
3038
	}
3039
	foreach ($config['installedpackages']['package'] as $package) {
3040
		if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
3041
			continue;
3042
		}
3043
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], 'packagegui');
3044
		$pkgname = substr(reverse_strrchr($package['configurationfile'], "."), 0, -1);
3045
		if (is_array($pkg_config['plugins']['item'])) {
3046
			foreach ($pkg_config['plugins']['item'] as $plugin) {
3047
				if ($plugin['type'] == $plugin_type) {
3048
					if (file_exists($pkg_config['include_file'])) {
3049
						require_once($pkg_config['include_file']);
3050
					} else {
3051
						continue;
3052
					}
3053
					$plugin_function = $pkgname . '_'. $plugin_type;
3054
					$results[$pkgname] = call_user_func($plugin_function, $plugin_params);
3055
				}
3056
			}
3057
		}
3058
	}
3059
	return $results;
3060
}
3061

    
3062
?>
(39-39/65)