Project

General

Profile

Download (87.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	pfsense-utils.inc
4

    
5
	part of pfSense (https://www.pfsense.org)
6
	Copyright (c) 2004-2016 Electric Sheep Fencing, LLC.
7
	All rights reserved.
8

    
9
	Redistribution and use in source and binary forms, with or without
10
	modification, are permitted provided that the following conditions are met:
11

    
12
	1. Redistributions of source code must retain the above copyright notice,
13
	   this list of conditions and the following disclaimer.
14

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

    
20
	3. All advertising materials mentioning features or use of this software
21
	   must display the following acknowledgment:
22
	   "This product includes software developed by the pfSense Project
23
	   for use in the pfSense® software distribution. (http://www.pfsense.org/).
24

    
25
	4. The names "pfSense" and "pfSense Project" must not be used to
26
	   endorse or promote products derived from this software without
27
	   prior written permission. For written permission, please contact
28
	   coreteam@pfsense.org.
29

    
30
	5. Products derived from this software may not be called "pfSense"
31
	   nor may "pfSense" appear in their names without prior written
32
	   permission of the Electric Sheep Fencing, LLC.
33

    
34
	6. Redistributions of any form whatsoever must retain the following
35
	   acknowledgment:
36

    
37
	"This product includes software developed by the pfSense Project
38
	for use in the pfSense software distribution (http://www.pfsense.org/).
39

    
40
	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
41
	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
44
	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
	OF THE POSSIBILITY OF SUCH DAMAGE.
52
*/
53

    
54
/****f* pfsense-utils/have_natpfruleint_access
55
 * NAME
56
 *   have_natpfruleint_access
57
 * INPUTS
58
 *	none
59
 * RESULT
60
 *   returns true if user has access to edit a specific firewall nat port forward interface
61
 ******/
62
function have_natpfruleint_access($if) {
63
	$security_url = "firewall_nat_edit.php?if=". strtolower($if);
64
	if (isAllowedPage($security_url, $allowed)) {
65
		return true;
66
	}
67
	return false;
68
}
69

    
70
/****f* pfsense-utils/have_ruleint_access
71
 * NAME
72
 *   have_ruleint_access
73
 * INPUTS
74
 *	none
75
 * RESULT
76
 *   returns true if user has access to edit a specific firewall interface
77
 ******/
78
function have_ruleint_access($if) {
79
	$security_url = "firewall_rules.php?if=". strtolower($if);
80
	if (isAllowedPage($security_url)) {
81
		return true;
82
	}
83
	return false;
84
}
85

    
86
/****f* pfsense-utils/does_url_exist
87
 * NAME
88
 *   does_url_exist
89
 * INPUTS
90
 *	none
91
 * RESULT
92
 *   returns true if a url is available
93
 ******/
94
function does_url_exist($url) {
95
	$fd = fopen("$url", "r");
96
	if ($fd) {
97
		fclose($fd);
98
		return true;
99
	} else {
100
		return false;
101
	}
102
}
103

    
104
/****f* pfsense-utils/is_private_ip
105
 * NAME
106
 *   is_private_ip
107
 * INPUTS
108
 *	none
109
 * RESULT
110
 *   returns true if an ip address is in a private range
111
 ******/
112
function is_private_ip($iptocheck) {
113
	$isprivate = false;
114
	$ip_private_list = array(
115
		"10.0.0.0/8",
116
		"100.64.0.0/10",
117
		"172.16.0.0/12",
118
		"192.168.0.0/16",
119
	);
120
	foreach ($ip_private_list as $private) {
121
		if (ip_in_subnet($iptocheck, $private) == true) {
122
			$isprivate = true;
123
		}
124
	}
125
	return $isprivate;
126
}
127

    
128
/****f* pfsense-utils/get_tmp_file
129
 * NAME
130
 *   get_tmp_file
131
 * INPUTS
132
 *	none
133
 * RESULT
134
 *   returns a temporary filename
135
 ******/
136
function get_tmp_file() {
137
	global $g;
138
	return "{$g['tmp_path']}/tmp-" . time();
139
}
140

    
141
/****f* pfsense-utils/get_dns_servers
142
 * NAME
143
 *   get_dns_servers - get system dns servers
144
 * INPUTS
145
 *   none
146
 * RESULT
147
 *   $dns_servers - an array of the dns servers
148
 ******/
149
function get_dns_servers() {
150
	$dns_servers = array();
151
	if (file_exists("/etc/resolv.conf")) {
152
		$dns_s = file("/etc/resolv.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
153
	}
154
	if (is_array($dns_s)) {
155
		foreach ($dns_s as $dns) {
156
			$matches = "";
157
			if (preg_match("/nameserver (.*)/", $dns, $matches)) {
158
				$dns_servers[] = $matches[1];
159
			}
160
		}
161
	}
162
	return array_unique($dns_servers);
163
}
164

    
165
function hardware_offloading_applyflags($iface) {
166
	global $config;
167

    
168
	$flags_on = 0;
169
	$flags_off = 0;
170
	$options = pfSense_get_interface_addresses($iface);
171

    
172
	if (isset($config['system']['disablechecksumoffloading'])) {
173
		if (isset($options['encaps']['txcsum'])) {
174
			$flags_off |= IFCAP_TXCSUM;
175
		}
176
		if (isset($options['encaps']['rxcsum'])) {
177
			$flags_off |= IFCAP_RXCSUM;
178
		}
179
	} else {
180
		if (isset($options['caps']['txcsum'])) {
181
			$flags_on |= IFCAP_TXCSUM;
182
		}
183
		if (isset($options['caps']['rxcsum'])) {
184
			$flags_on |= IFCAP_RXCSUM;
185
		}
186
	}
187

    
188
	if (isset($config['system']['disablesegmentationoffloading'])) {
189
		$flags_off |= IFCAP_TSO;
190
	} else if (isset($options['caps']['tso']) || isset($options['caps']['tso4']) || isset($options['caps']['tso6'])) {
191
		$flags_on |= IFCAP_TSO;
192
	}
193

    
194
	if (isset($config['system']['disablelargereceiveoffloading'])) {
195
		$flags_off |= IFCAP_LRO;
196
	} else if (isset($options['caps']['lro'])) {
197
		$flags_on |= IFCAP_LRO;
198
	}
199

    
200
	/* if the NIC supports polling *AND* it is enabled in the GUI */
201
	if (!isset($config['system']['polling'])) {
202
		$flags_off |= IFCAP_POLLING;
203
	} else if (isset($options['caps']['polling'])) {
204
		$flags_on |= IFCAP_POLLING;
205
	}
206

    
207
	pfSense_interface_capabilities($iface, -$flags_off);
208
	pfSense_interface_capabilities($iface, $flags_on);
209
}
210

    
211
/****f* pfsense-utils/enable_hardware_offloading
212
 * NAME
213
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
214
 * INPUTS
215
 *   $interface	- string containing the physical interface to work on.
216
 * RESULT
217
 *   null
218
 * NOTES
219
 *   This function only supports the fxp driver's loadable microcode.
220
 ******/
221
function enable_hardware_offloading($interface) {
222
	global $g, $config;
223

    
224
	$int = get_real_interface($interface);
225
	if (empty($int)) {
226
		return;
227
	}
228

    
229
	if (!isset($config['system']['do_not_use_nic_microcode'])) {
230
		/* translate wan, lan, opt -> real interface if needed */
231
		$int_family = preg_split("/[0-9]+/", $int);
232
		$supported_ints = array('fxp');
233
		if (in_array($int_family, $supported_ints)) {
234
			if (does_interface_exist($int)) {
235
				pfSense_interface_flags($int, IFF_LINK0);
236
			}
237
		}
238
	}
239

    
240
	/* This is mostly for vlans and ppp types */
241
	$realhwif = get_parent_interface($interface);
242
	if ($realhwif[0] == $int) {
243
		hardware_offloading_applyflags($int);
244
	} else {
245
		hardware_offloading_applyflags($realhwif[0]);
246
		hardware_offloading_applyflags($int);
247
	}
248
}
249

    
250
/****f* pfsense-utils/interface_supports_polling
251
 * NAME
252
 *   checks to see if an interface supports polling according to man polling
253
 * INPUTS
254
 *
255
 * RESULT
256
 *   true or false
257
 * NOTES
258
 *
259
 ******/
260
function interface_supports_polling($iface) {
261
	$opts = pfSense_get_interface_addresses($iface);
262
	if (is_array($opts) && isset($opts['caps']['polling'])) {
263
		return true;
264
	}
265

    
266
	return false;
267
}
268

    
269
/****f* pfsense-utils/is_alias_inuse
270
 * NAME
271
 *   checks to see if an alias is currently in use by a rule
272
 * INPUTS
273
 *
274
 * RESULT
275
 *   true or false
276
 * NOTES
277
 *
278
 ******/
279
function is_alias_inuse($alias) {
280
	global $g, $config;
281

    
282
	if ($alias == "") {
283
		return false;
284
	}
285
	/* loop through firewall rules looking for alias in use */
286
	if (is_array($config['filter']['rule'])) {
287
		foreach ($config['filter']['rule'] as $rule) {
288
			if ($rule['source']['address']) {
289
				if ($rule['source']['address'] == $alias) {
290
					return true;
291
				}
292
			}
293
			if ($rule['destination']['address']) {
294
				if ($rule['destination']['address'] == $alias) {
295
					return true;
296
				}
297
			}
298
		}
299
	}
300
	/* loop through nat rules looking for alias in use */
301
	if (is_array($config['nat']['rule'])) {
302
		foreach ($config['nat']['rule'] as $rule) {
303
			if ($rule['target'] && $rule['target'] == $alias) {
304
				return true;
305
			}
306
			if ($rule['source']['address'] && $rule['source']['address'] == $alias) {
307
				return true;
308
			}
309
			if ($rule['destination']['address'] && $rule['destination']['address'] == $alias) {
310
				return true;
311
			}
312
		}
313
	}
314
	return false;
315
}
316

    
317
/****f* pfsense-utils/is_schedule_inuse
318
 * NAME
319
 *   checks to see if a schedule is currently in use by a rule
320
 * INPUTS
321
 *
322
 * RESULT
323
 *   true or false
324
 * NOTES
325
 *
326
 ******/
327
function is_schedule_inuse($schedule) {
328
	global $g, $config;
329

    
330
	if ($schedule == "") {
331
		return false;
332
	}
333
	/* loop through firewall rules looking for schedule in use */
334
	if (is_array($config['filter']['rule'])) {
335
		foreach ($config['filter']['rule'] as $rule) {
336
			if ($rule['sched'] == $schedule) {
337
				return true;
338
			}
339
		}
340
	}
341
	return false;
342
}
343

    
344
/****f* pfsense-utils/setup_polling
345
 * NAME
346
 *   sets up polling
347
 * INPUTS
348
 *
349
 * RESULT
350
 *   null
351
 * NOTES
352
 *
353
 ******/
354
function setup_polling() {
355
	global $g, $config;
356

    
357
	if (isset($config['system']['polling'])) {
358
		set_single_sysctl("kern.polling.idle_poll", "1");
359
	} else {
360
		set_single_sysctl("kern.polling.idle_poll", "0");
361
	}
362

    
363
	if ($config['system']['polling_each_burst']) {
364
		set_single_sysctl("kern.polling.each_burst", $config['system']['polling_each_burst']);
365
	}
366
	if ($config['system']['polling_burst_max']) {
367
		set_single_sysctl("kern.polling.burst_max", $config['system']['polling_burst_max']);
368
	}
369
	if ($config['system']['polling_user_frac']) {
370
		set_single_sysctl("kern.polling.user_frac", $config['system']['polling_user_frac']);
371
	}
372
}
373

    
374
/****f* pfsense-utils/setup_microcode
375
 * NAME
376
 *   enumerates all interfaces and calls enable_hardware_offloading which
377
 *   enables a NIC's supported hardware features.
378
 * INPUTS
379
 *
380
 * RESULT
381
 *   null
382
 * NOTES
383
 *   This function only supports the fxp driver's loadable microcode.
384
 ******/
385
function setup_microcode() {
386

    
387
	/* if list */
388
	$iflist = get_configured_interface_list(false, true);
389
	foreach ($iflist as $if => $ifdescr) {
390
		enable_hardware_offloading($if);
391
	}
392
	unset($iflist);
393
}
394

    
395
/****f* pfsense-utils/get_carp_status
396
 * NAME
397
 *   get_carp_status - Return whether CARP is enabled or disabled.
398
 * RESULT
399
 *   boolean	- true if CARP is enabled, false if otherwise.
400
 ******/
401
function get_carp_status() {
402
	/* grab the current status of carp */
403
	$status = get_single_sysctl('net.inet.carp.allow');
404
	return (intval($status) > 0);
405
}
406

    
407
/*
408
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
409

    
410
 */
411
function convert_ip_to_network_format($ip, $subnet) {
412
	$ipsplit = explode('.', $ip);
413
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
414
	return $string;
415
}
416

    
417
/*
418
 * get_carp_interface_status($carpid): returns the status of a carp uniqid
419
 */
420
function get_carp_interface_status($carpid) {
421

    
422
	$carpiface = get_configured_vip_interface($carpid);
423
	if ($carpiface == NULL)
424
		return "";
425
	$interface = get_real_interface($carpiface);
426
	if ($interface == NULL)
427
		return "";
428

    
429
	$vhid = $carp['vhid'];
430
	$carp_query = '';
431
	$_gb = exec("/sbin/ifconfig $interface | /usr/bin/grep carp: | /usr/bin/grep \"vhid $vhid\"", $carp_query);
432
	foreach ($carp_query as $int) {
433
		if (stripos($int, "MASTER"))
434
			return "MASTER";
435
		elseif (stripos($int, "BACKUP"))
436
			return "BACKUP";
437
		elseif (stripos($int, "INIT"))
438
			return "INIT";
439
	}
440

    
441
	return "";
442
}
443

    
444
/*
445
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
446
 */
447
function get_pfsync_interface_status($pfsyncinterface) {
448
	if (!does_interface_exist($pfsyncinterface)) {
449
		return;
450
	}
451

    
452
	return exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/awk '/pfsync:/ {print \$5}'");
453
}
454

    
455
/*
456
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
457
 */
458
function add_rule_to_anchor($anchor, $rule, $label) {
459
	mwexec("echo " . escapeshellarg($rule) . " | /sbin/pfctl -a " . escapeshellarg($anchor) . ":" . escapeshellarg($label) . " -f -");
460
}
461

    
462
/*
463
 * remove_text_from_file
464
 * remove $text from file $file
465
 */
466
function remove_text_from_file($file, $text) {
467
	if (!file_exists($file) && !is_writable($file)) {
468
		return;
469
	}
470
	$filecontents = file_get_contents($file);
471
	$text = str_replace($text, "", $filecontents);
472
	@file_put_contents($file, $text);
473
}
474

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

    
493
/*
494
 * get_filename_from_url($url): converts a url to its filename.
495
 */
496
function get_filename_from_url($url) {
497
	return basename($url);
498
}
499

    
500
/*
501
 *   get_dir: return an array of $dir
502
 */
503
function get_dir($dir) {
504
	$dir_array = array();
505
	$d = dir($dir);
506
	while (false !== ($entry = $d->read())) {
507
		array_push($dir_array, $entry);
508
	}
509
	$d->close();
510
	return $dir_array;
511
}
512

    
513
/****f* pfsense-utils/WakeOnLan
514
 * NAME
515
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
516
 * RESULT
517
 *   true/false - true if the operation was successful
518
 ******/
519
function WakeOnLan($addr, $mac) {
520
	$addr_byte = explode(':', $mac);
521
	$hw_addr = '';
522

    
523
	for ($a = 0; $a < 6; $a++) {
524
		$hw_addr .= chr(hexdec($addr_byte[$a]));
525
	}
526

    
527
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
528

    
529
	for ($a = 1; $a <= 16; $a++) {
530
		$msg .= $hw_addr;
531
	}
532

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

    
550
	return false;
551
}
552

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

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

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

    
589
	$xml = parse_xml_config($g['tmp_path'] . "/tmpxml", null);
590
	if ($xml['pfsense']) {
591
		$xml = $xml['pfsense'];
592
	}
593
	else if ($xml['m0n0wall']) {
594
		$xml = $xml['m0n0wall'];
595
	}
596
	if ($xml[$section_name]) {
597
		$section_xml = $xml[$section_name];
598
	} else {
599
		$section_xml = -1;
600
	}
601

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

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

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

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

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

    
716
/*
717
 * host_firmware_version(): Return the versions used in this install
718
 */
719
function host_firmware_version($tocheck = "") {
720
	global $g, $config;
721

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

    
724
	return array(
725
		"firmware" => array("version" => $g['product_version']),
726
		"kernel"   => array("version" => $os_version),
727
		"base"     => array("version" => $os_version),
728
		"platform" => trim(file_get_contents('/etc/platform', " \n")),
729
		"config_version" => $config['version']
730
	);
731
}
732

    
733
function get_disk_info() {
734
	$diskout = "";
735
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
736
	return explode(' ', $diskout[0]);
737
}
738

    
739
/****f* pfsense-utils/strncpy
740
 * NAME
741
 *   strncpy - copy strings
742
 * INPUTS
743
 *   &$dst, $src, $length
744
 * RESULT
745
 *   none
746
 ******/
747
function strncpy(&$dst, $src, $length) {
748
	if (strlen($src) > $length) {
749
		$dst = substr($src, 0, $length);
750
	} else {
751
		$dst = $src;
752
	}
753
}
754

    
755
/****f* pfsense-utils/reload_interfaces_sync
756
 * NAME
757
 *   reload_interfaces - reload all interfaces
758
 * INPUTS
759
 *   none
760
 * RESULT
761
 *   none
762
 ******/
763
function reload_interfaces_sync() {
764
	global $config, $g;
765

    
766
	if ($g['debug']) {
767
		log_error(gettext("reload_interfaces_sync() is starting."));
768
	}
769

    
770
	/* parse config.xml again */
771
	$config = parse_config(true);
772

    
773
	/* enable routing */
774
	system_routing_enable();
775
	if ($g['debug']) {
776
		log_error(gettext("Enabling system routing"));
777
	}
778

    
779
	if ($g['debug']) {
780
		log_error(gettext("Cleaning up Interfaces"));
781
	}
782

    
783
	/* set up interfaces */
784
	interfaces_configure();
785
}
786

    
787
/****f* pfsense-utils/reload_all
788
 * NAME
789
 *   reload_all - triggers a reload of all settings
790
 *   * INPUTS
791
 *   none
792
 * RESULT
793
 *   none
794
 ******/
795
function reload_all() {
796
	send_event("service reload all");
797
}
798

    
799
/****f* pfsense-utils/reload_interfaces
800
 * NAME
801
 *   reload_interfaces - triggers a reload of all interfaces
802
 * INPUTS
803
 *   none
804
 * RESULT
805
 *   none
806
 ******/
807
function reload_interfaces() {
808
	send_event("interface all reload");
809
}
810

    
811
/****f* pfsense-utils/reload_all_sync
812
 * NAME
813
 *   reload_all - reload all settings
814
 *   * INPUTS
815
 *   none
816
 * RESULT
817
 *   none
818
 ******/
819
function reload_all_sync() {
820
	global $config, $g;
821

    
822
	/* parse config.xml again */
823
	$config = parse_config(true);
824

    
825
	/* set up our timezone */
826
	system_timezone_configure();
827

    
828
	/* set up our hostname */
829
	system_hostname_configure();
830

    
831
	/* make hosts file */
832
	system_hosts_generate();
833

    
834
	/* generate resolv.conf */
835
	system_resolvconf_generate();
836

    
837
	/* enable routing */
838
	system_routing_enable();
839

    
840
	/* set up interfaces */
841
	interfaces_configure();
842

    
843
	/* start dyndns service */
844
	services_dyndns_configure();
845

    
846
	/* configure cron service */
847
	configure_cron();
848

    
849
	/* start the NTP client */
850
	system_ntp_configure();
851

    
852
	/* sync pw database */
853
	conf_mount_rw();
854
	unlink_if_exists("/etc/spwd.db.tmp");
855
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
856
	conf_mount_ro();
857

    
858
	/* restart sshd */
859
	send_event("service restart sshd");
860

    
861
	/* restart webConfigurator if needed */
862
	send_event("service restart webgui");
863
}
864

    
865
function setup_serial_port($when = "save", $path = "") {
866
	global $g, $config;
867
	conf_mount_rw();
868
	$ttys_file = "{$path}/etc/ttys";
869
	$boot_config_file = "{$path}/boot.config";
870
	$loader_conf_file = "{$path}/boot/loader.conf";
871
	/* serial console - write out /boot.config */
872
	if (file_exists($boot_config_file)) {
873
		$boot_config = file_get_contents($boot_config_file);
874
	} else {
875
		$boot_config = "";
876
	}
877

    
878
	$serialspeed = (is_numeric($config['system']['serialspeed'])) ? $config['system']['serialspeed'] : "115200";
879
	if ($g['platform'] != "cdrom") {
880
		$serial_only = false;
881

    
882
		if (($g['platform'] == "nanobsd") && isset($g['enableserial_force'])) {
883
			$serial_only = true;
884
		} else {
885
			$specific_platform = system_identify_specific_platform();
886
			if ($specific_platform['name'] == 'RCC-VE' ||
887
			    $specific_platform['name'] == 'RCC' ||
888
			    $specific_platform['name'] == 'RCC-DFF') {
889
				$serial_only = true;
890
			}
891
		}
892

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

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

    
935
			if ($serial_only === true) {
936
				$new_boot_config[] = 'boot_serial="YES"';
937
				$new_boot_config[] = 'console="comconsole"';
938
			} else if (is_serial_enabled()) {
939
				$new_boot_config[] = 'boot_multicons="YES"';
940
				$new_boot_config[] = 'boot_serial="YES"';
941
				$primaryconsole = isset($g['primaryconsole_force']) ? $g['primaryconsole_force'] : $config['system']['primaryconsole'];
942
				switch ($primaryconsole) {
943
					case "video":
944
						$new_boot_config[] = 'console="vidconsole,comconsole"';
945
						break;
946
					case "serial":
947
					default:
948
						$new_boot_config[] = 'console="comconsole,vidconsole"';
949
				}
950
			}
951
			$new_boot_config[] = 'comconsole_speed="' . $serialspeed . '"';
952

    
953
			$specplatform = system_identify_specific_platform();
954
			if ($specplatform['name'] == 'RCC-VE' ||
955
			    $specplatform['name'] == 'RCC' ||
956
			    $specplatform['name'] == 'RCC-DFF') {
957
				$new_boot_config[] = 'comconsole_port="0x2F8"';
958
				$new_boot_config[] = 'hint.uart.0.flags="0x00"';
959
				$new_boot_config[] = 'hint.uart.1.flags="0x10"';
960
			}
961
			$new_boot_config[] = 'hw.usb.no_pf="1"';
962

    
963
			file_put_contents($loader_conf_file, implode("\n", $new_boot_config) . "\n");
964
		}
965
	}
966
	$ttys = file_get_contents($ttys_file);
967
	$ttys_split = explode("\n", $ttys);
968
	$fd = fopen($ttys_file, "w");
969

    
970
	$on_off = (is_serial_enabled() ? 'onifconsole' : 'off');
971

    
972
	if (isset($config['system']['disableconsolemenu'])) {
973
		$console_type = 'Pc';
974
		$serial_type = '3wire';
975
	} else {
976
		$console_type = 'al.Pc';
977
		$serial_type = 'al.3wire';
978
	}
979
	foreach ($ttys_split as $tty) {
980
		if (stristr($tty, "ttyv0")) {
981
			fwrite($fd, "ttyv0	\"/usr/libexec/getty {$console_type}\"	xterm	on	secure\n");
982
		} else if (stristr($tty, "ttyu")) {
983
			$ttyn = substr($tty, 0, 5);
984
			fwrite($fd, "{$ttyn}	\"/usr/libexec/getty {$serial_type}\"	vt100	{$on_off}	secure\n");
985
		} else {
986
			fwrite($fd, $tty . "\n");
987
		}
988
	}
989
	unset($on_off, $console_type, $serial_type);
990
	fclose($fd);
991
	if ($when != "upgrade") {
992
		reload_ttys();
993
	}
994

    
995
	conf_mount_ro();
996
	return;
997
}
998

    
999
function is_serial_enabled() {
1000
	global $g, $config;
1001

    
1002
	if (!isset($g['enableserial_force']) &&
1003
	    !isset($config['system']['enableserial']) &&
1004
	    ($g['platform'] == $g['product_name'] || $g['platform'] == "cdrom")) {
1005
		return false;
1006
	}
1007

    
1008
	return true;
1009
}
1010

    
1011
function reload_ttys() {
1012
	// Send a HUP signal to init will make it reload /etc/ttys
1013
	posix_kill(1, SIGHUP);
1014
}
1015

    
1016
function print_value_list($list, $count = 10, $separator = ",") {
1017
	$list = implode($separator, array_slice($list, 0, $count));
1018
	if (count($list) < $count) {
1019
		$list .= ".";
1020
	} else {
1021
		$list .= "...";
1022
	}
1023
	return $list;
1024
}
1025

    
1026
/* DHCP enabled on any interfaces? */
1027
function is_dhcp_server_enabled() {
1028
	global $config;
1029

    
1030
	if (!is_array($config['dhcpd'])) {
1031
		return false;
1032
	}
1033

    
1034
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1035
		if (isset($dhcpifconf['enable']) && !empty($config['interfaces'][$dhcpif])) {
1036
			return true;
1037
		}
1038
	}
1039

    
1040
	return false;
1041
}
1042

    
1043
/* DHCP enabled on any interfaces? */
1044
function is_dhcpv6_server_enabled() {
1045
	global $config;
1046

    
1047
	if (is_array($config['interfaces'])) {
1048
		foreach ($config['interfaces'] as $ifcfg) {
1049
			if (isset($ifcfg['enable']) && !empty($ifcfg['track6-interface'])) {
1050
				return true;
1051
			}
1052
		}
1053
	}
1054

    
1055
	if (!is_array($config['dhcpdv6'])) {
1056
		return false;
1057
	}
1058

    
1059
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
1060
		if (isset($dhcpv6ifconf['enable']) && !empty($config['interfaces'][$dhcpv6if])) {
1061
			return true;
1062
		}
1063
	}
1064

    
1065
	return false;
1066
}
1067

    
1068
/* radvd enabled on any interfaces? */
1069
function is_radvd_enabled() {
1070
	global $config;
1071

    
1072
	if (!is_array($config['dhcpdv6'])) {
1073
		$config['dhcpdv6'] = array();
1074
	}
1075

    
1076
	$dhcpdv6cfg = $config['dhcpdv6'];
1077
	$Iflist = get_configured_interface_list();
1078

    
1079
	/* handle manually configured DHCP6 server settings first */
1080
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1081
		if (!isset($config['interfaces'][$dhcpv6if]['enable'])) {
1082
			continue;
1083
		}
1084

    
1085
		if (!isset($dhcpv6ifconf['ramode'])) {
1086
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
1087
		}
1088

    
1089
		if ($dhcpv6ifconf['ramode'] == "disabled") {
1090
			continue;
1091
		}
1092

    
1093
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1094
		if (!is_ipaddrv6($ifcfgipv6)) {
1095
			continue;
1096
		}
1097

    
1098
		return true;
1099
	}
1100

    
1101
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
1102
	foreach ($Iflist as $if => $ifdescr) {
1103
		if (!isset($config['interfaces'][$if]['track6-interface'])) {
1104
			continue;
1105
		}
1106
		if (!isset($config['interfaces'][$if]['enable'])) {
1107
			continue;
1108
		}
1109

    
1110
		$ifcfgipv6 = get_interface_ipv6($if);
1111
		if (!is_ipaddrv6($ifcfgipv6)) {
1112
			continue;
1113
		}
1114

    
1115
		$ifcfgsnv6 = get_interface_subnetv6($if);
1116
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1117

    
1118
		if (!is_ipaddrv6($subnetv6)) {
1119
			continue;
1120
		}
1121

    
1122
		return true;
1123
	}
1124

    
1125
	return false;
1126
}
1127

    
1128
/* Any PPPoE servers enabled? */
1129
function is_pppoe_server_enabled() {
1130
	global $config;
1131

    
1132
	$pppoeenable = false;
1133

    
1134
	if (!is_array($config['pppoes']) || !is_array($config['pppoes']['pppoe'])) {
1135
		return false;
1136
	}
1137

    
1138
	foreach ($config['pppoes']['pppoe'] as $pppoes) {
1139
		if ($pppoes['mode'] == 'server') {
1140
			$pppoeenable = true;
1141
		}
1142
	}
1143

    
1144
	return $pppoeenable;
1145
}
1146

    
1147
function convert_seconds_to_hms($sec) {
1148
	$min = $hrs = 0;
1149
	if ($sec != 0) {
1150
		$min = floor($sec/60);
1151
		$sec %= 60;
1152
	}
1153
	if ($min != 0) {
1154
		$hrs = floor($min/60);
1155
		$min %= 60;
1156
	}
1157
	if ($sec < 10) {
1158
		$sec = "0".$sec;
1159
	}
1160
	if ($min < 10) {
1161
		$min = "0".$min;
1162
	}
1163
	if ($hrs < 10) {
1164
		$hrs = "0".$hrs;
1165
	}
1166
	$result = $hrs.":".$min.":".$sec;
1167
	return $result;
1168
}
1169

    
1170
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1171

    
1172
function get_ppp_uptime($port) {
1173
	if (file_exists("/conf/{$port}.log")) {
1174
		$saved_time = file_get_contents("/conf/{$port}.log");
1175
		$uptime_data = explode("\n", $saved_time);
1176
		$sec = 0;
1177
		foreach ($uptime_data as $upt) {
1178
			$sec += substr($upt, 1 + strpos($upt, " "));
1179
		}
1180
		return convert_seconds_to_hms($sec);
1181
	} else {
1182
		$total_time = gettext("No history data found!");
1183
		return $total_time;
1184
	}
1185
}
1186

    
1187
//returns interface information
1188
function get_interface_info($ifdescr) {
1189
	global $config, $g;
1190

    
1191
	$ifinfo = array();
1192
	if (empty($config['interfaces'][$ifdescr])) {
1193
		return;
1194
	}
1195
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
1196
	$ifinfo['if'] = get_real_interface($ifdescr);
1197

    
1198
	$chkif = $ifinfo['if'];
1199
	$ifinfotmp = pfSense_get_interface_addresses($chkif);
1200
	$ifinfo['status'] = $ifinfotmp['status'];
1201
	if (empty($ifinfo['status'])) {
1202
		$ifinfo['status'] = "down";
1203
	}
1204
	$ifinfo['macaddr'] = $ifinfotmp['macaddr'];
1205
	$ifinfo['mtu'] = $ifinfotmp['mtu'];
1206
	$ifinfo['ipaddr'] = $ifinfotmp['ipaddr'];
1207
	$ifinfo['subnet'] = $ifinfotmp['subnet'];
1208
	$ifinfo['linklocal'] = get_interface_linklocal($ifdescr);
1209
	$ifinfo['ipaddrv6'] = get_interface_ipv6($ifdescr);
1210
	$ifinfo['subnetv6'] = get_interface_subnetv6($ifdescr);
1211
	if (isset($ifinfotmp['link0'])) {
1212
		$link0 = "down";
1213
	}
1214
	$ifinfotmp = pfSense_get_interface_stats($chkif);
1215
	// $ifinfo['inpkts'] = $ifinfotmp['inpkts'];
1216
	// $ifinfo['outpkts'] = $ifinfotmp['outpkts'];
1217
	$ifinfo['inerrs'] = $ifinfotmp['inerrs'];
1218
	$ifinfo['outerrs'] = $ifinfotmp['outerrs'];
1219
	$ifinfo['collisions'] = $ifinfotmp['collisions'];
1220

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

    
1241
	/* Block */
1242
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1243
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1244
	$pf_in6_block = preg_split("/ +/", $pfctlstats[8]);
1245
	$pf_out6_block = preg_split("/ +/", $pfctlstats[10]);
1246
	$in4_block = $pf_in4_block[5];
1247
	$out4_block = $pf_out4_block[5];
1248
	$in4_block_packets = $pf_in4_block[3];
1249
	$out4_block_packets = $pf_out4_block[3];
1250
	$in6_block = $pf_in6_block[5];
1251
	$out6_block = $pf_out6_block[5];
1252
	$in6_block_packets = $pf_in6_block[3];
1253
	$out6_block_packets = $pf_out6_block[3];
1254
	$ifinfo['inbytesblock'] = $in4_block + $in6_block;
1255
	$ifinfo['outbytesblock'] = $out4_block + $out6_block;
1256
	$ifinfo['inpktsblock'] = $in4_block_packets + $in6_block_packets;
1257
	$ifinfo['outpktsblock'] = $out4_block_packets + $out6_block_packets;
1258

    
1259
	$ifinfo['inbytes'] = $in4_pass + $in6_pass;
1260
	$ifinfo['outbytes'] = $out4_pass + $out6_pass;
1261
	$ifinfo['inpkts'] = $in4_pass_packets + $in6_pass_packets;
1262
	$ifinfo['outpkts'] = $out4_pass_packets + $out6_pass_packets;
1263

    
1264
	$ifconfiginfo = "";
1265
	$link_type = $config['interfaces'][$ifdescr]['ipaddr'];
1266
	switch ($link_type) {
1267
		/* DHCP? -> see if dhclient is up */
1268
		case "dhcp":
1269
			/* see if dhclient is up */
1270
			if (find_dhclient_process($ifinfo['if']) != 0) {
1271
				$ifinfo['dhcplink'] = "up";
1272
			} else {
1273
				$ifinfo['dhcplink'] = "down";
1274
			}
1275

    
1276
			break;
1277
		/* PPPoE/PPTP/L2TP interface? -> get status from virtual interface */
1278
		case "pppoe":
1279
		case "pptp":
1280
		case "l2tp":
1281
			if ($ifinfo['status'] == "up" && !isset($link0)) {
1282
				/* get PPPoE link status for dial on demand */
1283
				$ifinfo["{$link_type}link"] = "up";
1284
			} else {
1285
				$ifinfo["{$link_type}link"] = "down";
1286
			}
1287

    
1288
			break;
1289
		/* PPP interface? -> get uptime for this session and cumulative uptime from the persistent log file in conf */
1290
		case "ppp":
1291
			if ($ifinfo['status'] == "up") {
1292
				$ifinfo['ppplink'] = "up";
1293
			} else {
1294
				$ifinfo['ppplink'] = "down" ;
1295
			}
1296

    
1297
			if (empty($ifinfo['status'])) {
1298
				$ifinfo['status'] = "down";
1299
			}
1300

    
1301
			if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1302
				foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1303
					if ($config['interfaces'][$ifdescr]['if'] == $ppp['if']) {
1304
						break;
1305
					}
1306
				}
1307
			}
1308
			$dev = $ppp['ports'];
1309
			if ($config['interfaces'][$ifdescr]['if'] != $ppp['if'] || empty($dev)) {
1310
				break;
1311
			}
1312
			if (!file_exists($dev)) {
1313
				$ifinfo['nodevice'] = 1;
1314
				$ifinfo['pppinfo'] = $dev . " " . gettext("device not present! Is the modem attached to the system?");
1315
			}
1316

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

    
1352
	if (file_exists("{$g['varrun_path']}/{$link_type}_{$ifdescr}.pid")) {
1353
		$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1354
		$ifinfo['ppp_uptime'] = convert_seconds_to_hms($sec);
1355
	}
1356

    
1357
	if ($ifinfo['status'] == "up") {
1358
		/* try to determine media with ifconfig */
1359
		unset($ifconfiginfo);
1360
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1361
		$wifconfiginfo = array();
1362
		if (is_interface_wireless($ifdescr)) {
1363
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1364
			array_shift($wifconfiginfo);
1365
		}
1366
		$matches = "";
1367
		foreach ($ifconfiginfo as $ici) {
1368

    
1369
			/* don't list media/speed for wireless cards, as it always
1370
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1371
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1372
				$ifinfo['media'] = $matches[1];
1373
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1374
				$ifinfo['media'] = $matches[1];
1375
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1376
				$ifinfo['media'] = $matches[1];
1377
			}
1378

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

    
1424
	$bridge = "";
1425
	$bridge = link_interface_to_bridge($ifdescr);
1426
	if ($bridge) {
1427
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1428
		if (stristr($bridge_text, "blocking") <> false) {
1429
			$ifinfo['bridge'] = "<b><font color='red'>" . gettext("blocking") . "</font></b> - " . gettext("check for ethernet loops");
1430
			$ifinfo['bridgeint'] = $bridge;
1431
		} else if (stristr($bridge_text, "learning") <> false) {
1432
			$ifinfo['bridge'] = gettext("learning");
1433
			$ifinfo['bridgeint'] = $bridge;
1434
		} else if (stristr($bridge_text, "forwarding") <> false) {
1435
			$ifinfo['bridge'] = gettext("forwarding");
1436
			$ifinfo['bridgeint'] = $bridge;
1437
		}
1438
	}
1439

    
1440
	return $ifinfo;
1441
}
1442

    
1443
//returns cpu speed of processor. Good for determining capabilities of machine
1444
function get_cpu_speed() {
1445
	return get_single_sysctl("hw.clockrate");
1446
}
1447

    
1448
function get_uptime_sec() {
1449
	$boottime = "";
1450
	$matches = "";
1451
	$boottime = get_single_sysctl("kern.boottime");
1452
	preg_match("/sec = (\d+)/", $boottime, $matches);
1453
	$boottime = $matches[1];
1454
	if (intval($boottime) == 0) {
1455
		return 0;
1456
	}
1457

    
1458
	$uptime = time() - $boottime;
1459
	return $uptime;
1460
}
1461

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

    
1495
function is_fqdn($fqdn) {
1496
	$hostname = false;
1497
	if (preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1498
		$hostname = true;
1499
	}
1500
	if (preg_match("/\.\./", $fqdn)) {
1501
		$hostname = false;
1502
	}
1503
	if (preg_match("/^\./i", $fqdn)) {
1504
		$hostname = false;
1505
	}
1506
	if (preg_match("/\//i", $fqdn)) {
1507
		$hostname = false;
1508
	}
1509
	return($hostname);
1510
}
1511

    
1512
function pfsense_default_state_size() {
1513
	/* get system memory amount */
1514
	$memory = get_memory();
1515
	$physmem = $memory[0];
1516
	/* Be cautious and only allocate 10% of system memory to the state table */
1517
	$max_states = (int) ($physmem/10)*1000;
1518
	return $max_states;
1519
}
1520

    
1521
function pfsense_default_tables_size() {
1522
	$current = `pfctl -sm | grep ^tables | awk '{print $4};'`;
1523
	return $current;
1524
}
1525

    
1526
function pfsense_default_table_entries_size() {
1527
	$current = `pfctl -sm | grep table-entries | awk '{print $4};'`;
1528
	return (trim($current));
1529
}
1530

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

    
1567
	if (trim($oldcontents) != trim($contents)) {
1568
		if ($g['debug']) {
1569
			log_error(sprintf(gettext('DNSCACHE: Found old IP %1$s and new IP %2$s'), $oldcontents, $contents));
1570
		}
1571
		return ($oldcontents);
1572
	} else {
1573
		return false;
1574
	}
1575
}
1576

    
1577
/*
1578
 * load_crypto() - Load crypto modules if enabled in config.
1579
 */
1580
function load_crypto() {
1581
	global $config, $g;
1582
	$crypto_modules = array('glxsb', 'aesni');
1583

    
1584
	if (!in_array($config['system']['crypto_hardware'], $crypto_modules)) {
1585
		return false;
1586
	}
1587

    
1588
	if (!empty($config['system']['crypto_hardware']) && !is_module_loaded($config['system']['crypto_hardware'])) {
1589
		log_error(sprintf(gettext("Loading %s cryptographic accelerator module."), $config['system']['crypto_hardware']));
1590
		mwexec("/sbin/kldload {$config['system']['crypto_hardware']}");
1591
	}
1592
}
1593

    
1594
/*
1595
 * load_thermal_hardware() - Load temperature monitor kernel module
1596
 */
1597
function load_thermal_hardware() {
1598
	global $config, $g;
1599
	$thermal_hardware_modules = array('coretemp', 'amdtemp');
1600

    
1601
	if (!in_array($config['system']['thermal_hardware'], $thermal_hardware_modules)) {
1602
		return false;
1603
	}
1604

    
1605
	if (!empty($config['system']['thermal_hardware']) && !is_module_loaded($config['system']['thermal_hardware'])) {
1606
		log_error(sprintf(gettext("Loading %s thermal monitor module."), $config['system']['thermal_hardware']));
1607
		mwexec("/sbin/kldload {$config['system']['thermal_hardware']}");
1608
	}
1609
}
1610

    
1611
/****f* pfsense-utils/isvm
1612
 * NAME
1613
 *   isvm
1614
 * INPUTS
1615
 *	none
1616
 * RESULT
1617
 *   returns true if machine is running under a virtual environment
1618
 ******/
1619
function isvm() {
1620
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86", "VirtualBox");
1621
	$_gb = exec('/bin/kenv smbios.system.product 2>/dev/null', $output, $rc);
1622

    
1623
	if ($rc != 0 || !isset($output[0])) {
1624
		return false;
1625
	}
1626

    
1627
	foreach ($virtualenvs as $virtualenv) {
1628
		if (stripos($output[0], $virtualenv) !== false) {
1629
			return true;
1630
		}
1631
	}
1632

    
1633
	return false;
1634
}
1635

    
1636
function get_freebsd_version() {
1637
	$version = explode(".", php_uname("r"));
1638
	return $version[0];
1639
}
1640

    
1641
function download_file($url, $destination, $verify_ssl = true, $connect_timeout = 5, $timeout = 0) {
1642
	global $config, $g;
1643

    
1644
	$fp = fopen($destination, "wb");
1645

    
1646
	if (!$fp) {
1647
		return false;
1648
	}
1649

    
1650
	$ch = curl_init();
1651
	curl_setopt($ch, CURLOPT_URL, $url);
1652
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1653
	curl_setopt($ch, CURLOPT_FILE, $fp);
1654
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1655
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1656
	curl_setopt($ch, CURLOPT_HEADER, false);
1657
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1658
	if (!isset($config['system']['do_not_send_host_uuid'])) {
1659
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1660
	} else {
1661
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1662
	}
1663

    
1664
	if (!empty($config['system']['proxyurl'])) {
1665
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1666
		if (!empty($config['system']['proxyport'])) {
1667
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1668
		}
1669
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1670
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1671
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1672
		}
1673
	}
1674

    
1675
	@curl_exec($ch);
1676
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1677
	fclose($fp);
1678
	curl_close($ch);
1679
	if ($http_code == 200) {
1680
		return true;
1681
	} else {
1682
		log_error(sprintf(gettext('Download file failed with status code %1$s. URL: %2$s'), $http_code, $url));
1683
		unlink_if_exists($destination);
1684
		return false;
1685
	}
1686
}
1687

    
1688
function download_file_with_progress_bar($url, $destination, $verify_ssl = true, $readbody = 'read_body', $connect_timeout = 5, $timeout = 0) {
1689
	global $config, $g;
1690
	global $ch, $fout, $file_size, $downloaded, $config, $first_progress_update;
1691
	$file_size = 1;
1692
	$downloaded = 1;
1693
	$first_progress_update = TRUE;
1694
	/* open destination file */
1695
	$fout = fopen($destination, "wb");
1696

    
1697
	if (!$fout) {
1698
		return false;
1699
	}
1700
	/*
1701
	 *      Originally by Author: Keyvan Minoukadeh
1702
	 *      Modified by Scott Ullrich to return Content-Length size
1703
	 */
1704
	$ch = curl_init();
1705
	curl_setopt($ch, CURLOPT_URL, $url);
1706
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1707
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1708
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1709
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1710
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1711
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1712
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1713
	if (!isset($config['system']['do_not_send_host_uuid'])) {
1714
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1715
	} else {
1716
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1717
	}
1718

    
1719
	if (!empty($config['system']['proxyurl'])) {
1720
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1721
		if (!empty($config['system']['proxyport'])) {
1722
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1723
		}
1724
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1725
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1726
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1727
		}
1728
	}
1729

    
1730
	@curl_exec($ch);
1731
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1732
	fclose($fout);
1733
	curl_close($ch);
1734
	if ($http_code == 200) {
1735
		return true;
1736
	} else {
1737
		log_error(sprintf(gettext('Download file failed with status code %1$s. URL: %2$s'), $http_code, $url));
1738
		unlink_if_exists($destination);
1739
		return false;
1740
	}
1741
}
1742

    
1743
function read_header($ch, $string) {
1744
	global $file_size, $fout;
1745
	$length = strlen($string);
1746
	$regs = "";
1747
	preg_match("/(Content-Length:) (.*)/", $string, $regs);
1748
	if ($regs[2] <> "") {
1749
		$file_size = intval($regs[2]);
1750
	}
1751
	ob_flush();
1752
	return $length;
1753
}
1754

    
1755
function read_body($ch, $string) {
1756
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen, $first_progress_update;
1757
	global $pkg_interface;
1758
	$length = strlen($string);
1759
	$downloaded += intval($length);
1760
	if ($file_size > 0) {
1761
		$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1762
		$downloadProgress = 100 - $downloadProgress;
1763
	} else {
1764
		$downloadProgress = 0;
1765
	}
1766
	if ($lastseen <> $downloadProgress and $downloadProgress < 101) {
1767
		if ($sendto == "status") {
1768
			if ($pkg_interface == "console") {
1769
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1770
					$tostatus = $static_status . $downloadProgress . "%";
1771
					if ($downloadProgress == 100) {
1772
						$tostatus = $tostatus . "\r";
1773
					}
1774
					update_status($tostatus);
1775
				}
1776
			} else {
1777
				$tostatus = $static_status . $downloadProgress . "%";
1778
				update_status($tostatus);
1779
			}
1780
		} else {
1781
			if ($pkg_interface == "console") {
1782
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1783
					$tooutput = $static_output . $downloadProgress . "%";
1784
					if ($downloadProgress == 100) {
1785
						$tooutput = $tooutput . "\r";
1786
					}
1787
					update_output_window($tooutput);
1788
				}
1789
			} else {
1790
				$tooutput = $static_output . $downloadProgress . "%";
1791
				update_output_window($tooutput);
1792
			}
1793
		}
1794
		if (($pkg_interface != "console") || (($downloadProgress % 10) == 0) || ($downloadProgress < 10)) {
1795
			update_progress_bar($downloadProgress, $first_progress_update);
1796
			$first_progress_update = FALSE;
1797
		}
1798
		$lastseen = $downloadProgress;
1799
	}
1800
	if ($fout) {
1801
		fwrite($fout, $string);
1802
	}
1803
	ob_flush();
1804
	return $length;
1805
}
1806

    
1807
/*
1808
 *   update_output_window: update bottom textarea dynamically.
1809
 */
1810
function update_output_window($text) {
1811
	global $pkg_interface;
1812
	$log = preg_replace("/\n/", "\\n", $text);
1813
	if ($pkg_interface != "console") {
1814
?>
1815
<script type="text/javascript">
1816
//<![CDATA[
1817
	document.getElementById("output").textContent="<?=htmlspecialchars($log)?>";
1818
	document.getElementById("output").scrollTop = document.getElementById("output").scrollHeight;
1819
//]]>
1820
</script>
1821
<?php
1822
	}
1823
	/* ensure that contents are written out */
1824
	ob_flush();
1825
}
1826

    
1827
/*
1828
 *   update_status: update top textarea dynamically.
1829
 */
1830
function update_status($status) {
1831
	global $pkg_interface;
1832

    
1833
	if ($pkg_interface == "console") {
1834
		print ("{$status}");
1835
	}
1836

    
1837
	/* ensure that contents are written out */
1838
	ob_flush();
1839
}
1840

    
1841
/*
1842
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
1843
 */
1844
function update_progress_bar($percent, $first_time) {
1845
	global $pkg_interface;
1846
	if ($percent > 100) {
1847
		$percent = 1;
1848
	}
1849
	if ($pkg_interface <> "console") {
1850
		echo '<script type="text/javascript">';
1851
		echo "\n//<![CDATA[\n";
1852
		echo 'document.getElementById("progressbar").style.width="'. $percent.'%"';
1853
		echo "\n//]]>\n";
1854
		echo '</script>';
1855
	} else {
1856
		if (!($first_time)) {
1857
			echo "\x08\x08\x08\x08\x08";
1858
		}
1859
		echo sprintf("%4d%%", $percent);
1860
	}
1861
}
1862

    
1863
/* 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. */
1864
if (!function_exists("split")) {
1865
	function split($separator, $haystack, $limit = null) {
1866
		log_error("deprecated split() call with separator '{$separator}'");
1867
		return preg_split($separator, $haystack, $limit);
1868
	}
1869
}
1870

    
1871
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
1872
	global $g, $config, $pconfig, $debug;
1873
	if (!$origname) {
1874
		return;
1875
	}
1876

    
1877
	$sectionref = &$config;
1878
	foreach ($section as $sectionname) {
1879
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
1880
			$sectionref = &$sectionref[$sectionname];
1881
		} else {
1882
			return;
1883
		}
1884
	}
1885

    
1886
	if ($debug) {
1887
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
1888
		fwrite($fd, print_r($pconfig, true));
1889
	}
1890

    
1891
	if (is_array($sectionref)) {
1892
		foreach ($sectionref as $itemkey => $item) {
1893
			if ($debug) {
1894
				fwrite($fd, "$itemkey\n");
1895
			}
1896

    
1897
			$fieldfound = true;
1898
			$fieldref = &$sectionref[$itemkey];
1899
			foreach ($field as $fieldname) {
1900
				if (is_array($fieldref) && isset($fieldref[$fieldname])) {
1901
					$fieldref = &$fieldref[$fieldname];
1902
				} else {
1903
					$fieldfound = false;
1904
					break;
1905
				}
1906
			}
1907
			if ($fieldfound && $fieldref == $origname) {
1908
				if ($debug) {
1909
					fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1910
				}
1911
				$fieldref = $new_alias_name;
1912
			}
1913
		}
1914
	}
1915

    
1916
	if ($debug) {
1917
		fclose($fd);
1918
	}
1919

    
1920
}
1921

    
1922
function parse_aliases_file($filename, $type = "url", $max_items = -1, $kflc = false) {
1923
	/*
1924
	 * $filename = file to process for example blocklist like DROP:  http://www.spamhaus.org/drop/drop.txt
1925
	 * $type = if set to 'url' then subnets and ips will be returned,
1926
	 *         if set to 'url_ports' port-ranges and ports will be returned
1927
	 * $max_items = sets the maximum amount of valid items to load, -1 the default defines there is no limit.
1928
	 *
1929
	 * RETURNS an array of ip subnets and ip's or ports and port-ranges, returns NULL upon a error conditions (file not found)
1930
	 */
1931

    
1932
	if (!file_exists($filename)) {
1933
		log_error(sprintf(gettext("Could not process non-existent file from alias: %s"), $filename));
1934
		return null;
1935
	}
1936

    
1937
	if (filesize($filename) == 0) {
1938
		log_error(sprintf(gettext("Could not process empty file from alias: %s"), $filename));
1939
		return null;
1940
	}
1941
	$fd = @fopen($filename, 'r');
1942
	if (!$fd) {
1943
		log_error(sprintf(gettext("Could not process aliases from alias: %s"), $filename));
1944
		return null;
1945
	}
1946
	$items = array();
1947
	$comments = array();
1948
	/* NOTE: fgetss() is not a typo RTFM before being smart */
1949
	while (($fc = fgetss($fd)) !== FALSE) {
1950
		$tmp = trim($fc, " \t\n\r");
1951
		if (empty($tmp)) {
1952
			continue;
1953
		}
1954
		if (($kflc) && (strpos($tmp, '#') === 0)) {	// Keep Full Line Comments (lines beginning with #).
1955
			$comments[] = $tmp;
1956
		} else {
1957
			$tmp_str = strstr($tmp, '#', true);
1958
			if (!empty($tmp_str)) {
1959
				$tmp = $tmp_str;
1960
			}
1961
			$tmp_str = strstr($tmp, ' ', true);
1962
			if (!empty($tmp_str)) {
1963
				$tmp = $tmp_str;
1964
			}
1965
			$valid = (($type == "url" || $type == "urltable") && (is_ipaddr($tmp) || is_subnet($tmp))) ||
1966
				(($type == "url_ports" || $type == "urltable_ports") && (is_port($tmp) || is_portrange($tmp)));
1967
			if ($valid) {
1968
				$items[] = $tmp;
1969
				if (count($items) == $max_items) {
1970
					break;
1971
				}
1972
			}
1973
		}
1974
	}
1975
	fclose($fd);
1976
	return array_merge($comments, $items);
1977
}
1978

    
1979
function update_alias_url_data() {
1980
	global $config, $g;
1981

    
1982
	$updated = false;
1983

    
1984
	/* item is a url type */
1985
	$lockkey = lock('aliasurl');
1986
	if (is_array($config['aliases']['alias'])) {
1987
		foreach ($config['aliases']['alias'] as $x => $alias) {
1988
			if (empty($alias['aliasurl'])) {
1989
				continue;
1990
			}
1991

    
1992
			$address = null;
1993
			foreach ($alias['aliasurl'] as $alias_url) {
1994
				/* fetch down and add in */
1995
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
1996
				unlink($temp_filename);
1997
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
1998
				mkdir($temp_filename);
1999
				if (!download_file($alias_url, $temp_filename . "/aliases", $verify_ssl)) {
2000
					log_error(sprintf(gettext("Failed to download alias %s"), $alias_url));
2001
					continue;
2002
				}
2003

    
2004
				/* if the item is tar gzipped then extract */
2005
				if (stripos($alias_url, '.tgz')) {
2006
					if (!process_alias_tgz($temp_filename)) {
2007
						continue;
2008
					}
2009
				}
2010
				if (file_exists("{$temp_filename}/aliases")) {
2011
					$address = parse_aliases_file("{$temp_filename}/aliases", $alias['type'], 5000);
2012
					mwexec("/bin/rm -rf {$temp_filename}");
2013
				}
2014
			}
2015
			if ($address != null) {
2016
				$config['aliases']['alias'][$x]['address'] = implode(" ", $address);
2017
				$updated = true;
2018
			}
2019
		}
2020
	}
2021
	unlock($lockkey);
2022

    
2023
	/* Report status to callers as well */
2024
	return $updated;
2025
}
2026

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

    
2057
	return true;
2058
}
2059

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

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

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

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

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

    
2161
	$urltable_prefix = "/var/db/aliastables/";
2162
	$urltable_filename = $urltable_prefix . $name . ".txt";
2163
	$tmp_urltable_filename = $urltable_filename . ".tmp";
2164

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

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

    
2178
		// Try to fetch the URL supplied
2179
		conf_mount_rw();
2180
		unlink_if_exists($tmp_urltable_filename);
2181
		$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2182
		if (download_file($url, $tmp_urltable_filename, $verify_ssl)) {
2183
			// Convert lines that begin with '$' or ';' to comments '#' instead of deleting them.
2184
			mwexec("/usr/bin/sed -i \"\" -E 's/^[[:space:]]*($|#|;)/#/g; /^#/!s/\;.*//g;' ". escapeshellarg($tmp_urltable_filename));
2185

    
2186
			$type = ($type) ? $type : alias_get_type($name);	// If empty type passed, try to get it from config.
2187

    
2188
			$parsed_contents = parse_aliases_file($tmp_urltable_filename, $type, "-1", true);
2189
			if ($type == "urltable_ports") {
2190
				$parsed_contents = group_ports($parsed_contents, true);
2191
			}
2192
			if (is_array($parsed_contents)) {
2193
				file_put_contents($urltable_filename, implode("\n", $parsed_contents));
2194
			}
2195

    
2196
			/* If this backup is still there on a full install, but we aren't going to use ram disks, remove the archive since this is a transition. */
2197
			if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
2198
				unlink_if_exists("{$g['cf_conf_path']}/RAM_Disk_Store{$urltable_filename}.tgz");
2199
			} else {
2200
				/* Update the RAM disk store with the new/updated table file. */
2201
				mwexec("cd / && /usr/bin/tar -czf \"{$g['cf_conf_path']}/RAM_Disk_Store{$urltable_filename}.tgz\" -C / \"{$urltable_filename}\"");
2202
			}
2203
			unlink_if_exists($tmp_urltable_filename);
2204
		} else {
2205
			if (!$validateonly) {
2206
				touch($urltable_filename);
2207
			}
2208
			conf_mount_ro();
2209
			return false;
2210
		}
2211
		conf_mount_ro();
2212
		return true;
2213
	} else {
2214
		// File exists, and it doesn't need to be updated.
2215
		return -1;
2216
	}
2217
}
2218
function get_real_slice_from_glabel($label) {
2219
	$label = escapeshellarg($label);
2220
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/{$label} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`);
2221
}
2222
function nanobsd_get_boot_slice() {
2223
	return trim(`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`);
2224
}
2225
function nanobsd_get_boot_drive() {
2226
	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`);
2227
}
2228
function nanobsd_get_active_slice() {
2229
	$boot_drive = nanobsd_get_boot_drive();
2230
	$active = trim(`gpart show $boot_drive | grep '\[active\]' | awk '{print $3;}'`);
2231

    
2232
	return "{$boot_drive}s{$active}";
2233
}
2234
function nanobsd_get_size() {
2235
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2236
}
2237
function nanobsd_switch_boot_slice() {
2238
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2239
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2240
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2241
	nanobsd_detect_slice_info();
2242

    
2243
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2244
		$slice = $TOFLASH;
2245
	} else {
2246
		$slice = $BOOTFLASH;
2247
	}
2248

    
2249
	for ($i = 0; $i < ob_get_level(); $i++) {
2250
		ob_end_flush();
2251
	}
2252
	ob_implicit_flush(1);
2253
	if (strstr($slice, "s2")) {
2254
		$ASLICE = "2";
2255
		$AOLDSLICE = "1";
2256
		$AGLABEL_SLICE = "pfsense1";
2257
		$AUFS_ID = "1";
2258
		$AOLD_UFS_ID = "0";
2259
	} else {
2260
		$ASLICE = "1";
2261
		$AOLDSLICE = "2";
2262
		$AGLABEL_SLICE = "pfsense0";
2263
		$AUFS_ID = "0";
2264
		$AOLD_UFS_ID = "1";
2265
	}
2266
	$ATOFLASH = "{$BOOT_DRIVE}s{$ASLICE}";
2267
	$ACOMPLETE_PATH = "{$BOOT_DRIVE}s{$ASLICE}a";
2268
	$ABOOTFLASH = "{$BOOT_DRIVE}s{$AOLDSLICE}";
2269
	conf_mount_rw();
2270
	set_single_sysctl("kern.geom.debugflags", "16");
2271
	exec("/sbin/gpart set -a active -i {$ASLICE} {$BOOT_DRIVE}");
2272
	exec("/usr/sbin/boot0cfg -s {$ASLICE} -v /dev/{$BOOT_DRIVE}");
2273
	// We can't update these if they are mounted now.
2274
	if ($BOOTFLASH != $slice) {
2275
		exec("/sbin/tunefs -L ${AGLABEL_SLICE} /dev/$ACOMPLETE_PATH");
2276
		nanobsd_update_fstab($AGLABEL_SLICE, $ACOMPLETE_PATH, $AOLD_UFS_ID, $AUFS_ID);
2277
	}
2278
	set_single_sysctl("kern.geom.debugflags", "0");
2279
	conf_mount_ro();
2280
}
2281
function nanobsd_clone_slice() {
2282
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2283
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2284
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2285
	nanobsd_detect_slice_info();
2286

    
2287
	for ($i = 0; $i < ob_get_level(); $i++) {
2288
		ob_end_flush();
2289
	}
2290
	ob_implicit_flush(1);
2291
	set_single_sysctl("kern.geom.debugflags", "16");
2292
	exec("/bin/dd if=/dev/zero of=/dev/{$TOFLASH} bs=1m count=1");
2293
	exec("/bin/dd if=/dev/{$BOOTFLASH} of=/dev/{$TOFLASH} bs=64k");
2294
	exec("/sbin/tunefs -L {$GLABEL_SLICE} /dev/{$COMPLETE_PATH}");
2295
	$status = nanobsd_update_fstab($GLABEL_SLICE, $COMPLETE_PATH, $OLD_UFS_ID, $UFS_ID);
2296
	set_single_sysctl("kern.geom.debugflags", "0");
2297
	if ($status) {
2298
		return false;
2299
	} else {
2300
		return true;
2301
	}
2302
}
2303
function nanobsd_update_fstab($gslice, $complete_path, $oldufs, $newufs) {
2304
	$tmppath = "/tmp/{$gslice}";
2305
	$fstabpath = "/tmp/{$gslice}/etc/fstab";
2306

    
2307
	mkdir($tmppath);
2308
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2309
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2310
	copy("/etc/fstab", $fstabpath);
2311

    
2312
	if (!file_exists($fstabpath)) {
2313
		$fstab = <<<EOF
2314
/dev/ufs/{$gslice} / ufs ro,noatime 1 1
2315
/dev/ufs/cf /cf ufs ro,noatime 1 1
2316
EOF;
2317
		if (file_put_contents($fstabpath, $fstab)) {
2318
			$status = true;
2319
		} else {
2320
			$status = false;
2321
		}
2322
	} else {
2323
		$status = exec("/usr/bin/sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2324
	}
2325
	exec("/sbin/umount {$tmppath}");
2326
	rmdir($tmppath);
2327

    
2328
	return $status;
2329
}
2330
function nanobsd_detect_slice_info() {
2331
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2332
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2333
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2334

    
2335
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2336
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2337
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2338
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2339

    
2340
	// Detect which slice is active and set information.
2341
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2342
		$SLICE = "2";
2343
		$OLDSLICE = "1";
2344
		$GLABEL_SLICE = "pfsense1";
2345
		$UFS_ID = "1";
2346
		$OLD_UFS_ID = "0";
2347

    
2348
	} else {
2349
		$SLICE = "1";
2350
		$OLDSLICE = "2";
2351
		$GLABEL_SLICE = "pfsense0";
2352
		$UFS_ID = "0";
2353
		$OLD_UFS_ID = "1";
2354
	}
2355
	$TOFLASH = "{$BOOT_DRIVE}s{$SLICE}";
2356
	$COMPLETE_PATH = "{$BOOT_DRIVE}s{$SLICE}a";
2357
	$COMPLETE_BOOT_PATH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2358
	$BOOTFLASH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2359
}
2360

    
2361
function nanobsd_friendly_slice_name($slicename) {
2362
	global $g;
2363
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2364
}
2365

    
2366
function get_include_contents($filename) {
2367
	if (is_file($filename)) {
2368
		ob_start();
2369
		include $filename;
2370
		$contents = ob_get_contents();
2371
		ob_end_clean();
2372
		return $contents;
2373
	}
2374
	return false;
2375
}
2376

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

    
2489
function get_country_name($country_code) {
2490
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2491
		return "";
2492
	}
2493

    
2494
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2495
	$country_names_contents = file_get_contents($country_names_xml);
2496
	$country_names = xml2array($country_names_contents);
2497

    
2498
	if ($country_code == "ALL") {
2499
		$country_list = array();
2500
		foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2501
			$country_list[] = array(
2502
				"code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2503
				"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])));
2504
		}
2505
		return $country_list;
2506
	}
2507

    
2508
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2509
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2510
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2511
		}
2512
	}
2513
	return "";
2514
}
2515

    
2516
/* sort by interface only, retain the original order of rules that apply to
2517
   the same interface */
2518
function filter_rules_sort() {
2519
	global $config;
2520

    
2521
	/* mark each rule with the sequence number (to retain the order while sorting) */
2522
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2523
		$config['filter']['rule'][$i]['seq'] = $i;
2524
	}
2525

    
2526
	usort($config['filter']['rule'], "filter_rules_compare");
2527

    
2528
	/* strip the sequence numbers again */
2529
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2530
		unset($config['filter']['rule'][$i]['seq']);
2531
	}
2532
}
2533
function filter_rules_compare($a, $b) {
2534
	if (isset($a['floating']) && isset($b['floating'])) {
2535
		return $a['seq'] - $b['seq'];
2536
	} else if (isset($a['floating'])) {
2537
		return -1;
2538
	} else if (isset($b['floating'])) {
2539
		return 1;
2540
	} else if ($a['interface'] == $b['interface']) {
2541
		return $a['seq'] - $b['seq'];
2542
	} else {
2543
		return compare_interface_friendly_names($a['interface'], $b['interface']);
2544
	}
2545
}
2546

    
2547
function generate_ipv6_from_mac($mac) {
2548
	$elements = explode(":", $mac);
2549
	if (count($elements) <> 6) {
2550
		return false;
2551
	}
2552

    
2553
	$i = 0;
2554
	$ipv6 = "fe80::";
2555
	foreach ($elements as $byte) {
2556
		if ($i == 0) {
2557
			$hexadecimal = substr($byte, 1, 2);
2558
			$bitmap = base_convert($hexadecimal, 16, 2);
2559
			$bitmap = str_pad($bitmap, 4, "0", STR_PAD_LEFT);
2560
			$bitmap = substr($bitmap, 0, 2) ."1". substr($bitmap, 3, 4);
2561
			$byte = substr($byte, 0, 1) . base_convert($bitmap, 2, 16);
2562
		}
2563
		$ipv6 .= $byte;
2564
		if ($i == 1) {
2565
			$ipv6 .= ":";
2566
		}
2567
		if ($i == 3) {
2568
			$ipv6 .= ":";
2569
		}
2570
		if ($i == 2) {
2571
			$ipv6 .= "ff:fe";
2572
		}
2573

    
2574
		$i++;
2575
	}
2576
	return $ipv6;
2577
}
2578

    
2579
/****f* pfsense-utils/load_mac_manufacturer_table
2580
 * NAME
2581
 *   load_mac_manufacturer_table
2582
 * INPUTS
2583
 *   none
2584
 * RESULT
2585
 *   returns associative array with MAC-Manufacturer pairs
2586
 ******/
2587
function load_mac_manufacturer_table() {
2588
	/* load MAC-Manufacture data from the file */
2589
	$macs = false;
2590
	if (file_exists("/usr/local/share/nmap/nmap-mac-prefixes")) {
2591
		$macs=file("/usr/local/share/nmap/nmap-mac-prefixes");
2592
	}
2593
	if ($macs) {
2594
		foreach ($macs as $line) {
2595
			if (preg_match('/([0-9A-Fa-f]{6}) (.*)$/', $line, $matches)) {
2596
				/* store values like this $mac_man['000C29']='VMware' */
2597
				$mac_man["$matches[1]"] = $matches[2];
2598
			}
2599
		}
2600
		return $mac_man;
2601
	} else {
2602
		return -1;
2603
	}
2604

    
2605
}
2606

    
2607
/****f* pfsense-utils/is_ipaddr_configured
2608
 * NAME
2609
 *   is_ipaddr_configured
2610
 * INPUTS
2611
 *   IP Address to check.
2612
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2613
 *   check_localip - if true then also check for matches with PPTP and LT2P addresses
2614
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2615
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2616
 *     If check_subnets is true and cidrprefix is specified,
2617
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2618
 * RESULT
2619
 *   returns true if the IP Address is configured and present on this device or overlaps a configured subnet.
2620
*/
2621
function is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2622
	if (count(where_is_ipaddr_configured($ipaddr, $ignore_if, $check_localip, $check_subnets, $cidrprefix))) {
2623
		return true;
2624
	}
2625
	return false;
2626
}
2627

    
2628
/****f* pfsense-utils/where_is_ipaddr_configured
2629
 * NAME
2630
 *   where_is_ipaddr_configured
2631
 * INPUTS
2632
 *   IP Address to check.
2633
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2634
 *   check_localip - if true then also check for matches with PPTP and LT2P addresses
2635
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2636
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2637
 *     If check_subnets is true and cidrprefix is specified,
2638
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2639
 * RESULT
2640
 *   Returns an array of the interfaces 'if' plus IP address or subnet 'ip_or_subnet' that match or overlap the IP address to check.
2641
 *   If there are no matches then an empty array is returned.
2642
*/
2643
function where_is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2644
	global $config;
2645

    
2646
	$where_configured = array();
2647

    
2648
	$pos = strpos($ignore_if, '_virtualip');
2649
	if ($pos !== false) {
2650
		$ignore_vip_id = substr($ignore_if, $pos+10);
2651
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2652
	} else {
2653
		$ignore_vip_id = -1;
2654
		$ignore_vip_if = $ignore_if;
2655
	}
2656

    
2657
	$isipv6 = is_ipaddrv6($ipaddr);
2658

    
2659
	if ($check_subnets) {
2660
		$cidrprefix = intval($cidrprefix);
2661
		if ($isipv6) {
2662
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2663
				$cidrprefix = 128;
2664
			}
2665
		} else {
2666
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2667
				$cidrprefix = 32;
2668
			}
2669
		}
2670
		$iflist = get_configured_interface_list();
2671
		foreach ($iflist as $if => $ifname) {
2672
			if ($ignore_if == $if) {
2673
				continue;
2674
			}
2675

    
2676
			if ($isipv6) {
2677
				$if_ipv6 = get_interface_ipv6($if);
2678
				$if_snbitsv6 = get_interface_subnetv6($if);
2679
				if ($if_ipv6 && $if_snbitsv6 && check_subnetsv6_overlap($ipaddr, $cidrprefix, $if_ipv6, $if_snbitsv6)) {
2680
					$where_entry = array();
2681
					$where_entry['if'] = $if;
2682
					$where_entry['ip_or_subnet'] = get_interface_ipv6($if) . "/" . get_interface_subnetv6($if);
2683
					$where_configured[] = $where_entry;
2684
				}
2685
			} else {
2686
				$if_ipv4 = get_interface_ip($if);
2687
				$if_snbitsv4 = get_interface_subnet($if);
2688
				if ($if_ipv4 && $if_snbitsv4 && check_subnets_overlap($ipaddr, $cidrprefix, $if_ipv4, $if_snbitsv4)) {
2689
					$where_entry = array();
2690
					$where_entry['if'] = $if;
2691
					$where_entry['ip_or_subnet'] = get_interface_ip($if) . "/" . get_interface_subnet($if);
2692
					$where_configured[] = $where_entry;
2693
				}
2694
			}
2695
		}
2696
	} else {
2697
		if ($isipv6) {
2698
			$interface_list_ips = get_configured_ipv6_addresses();
2699
		} else {
2700
			$interface_list_ips = get_configured_ip_addresses();
2701
		}
2702

    
2703
		foreach ($interface_list_ips as $if => $ilips) {
2704
			if ($ignore_if == $if) {
2705
				continue;
2706
			}
2707
			if (strcasecmp($ipaddr, $ilips) == 0) {
2708
				$where_entry = array();
2709
				$where_entry['if'] = $if;
2710
				$where_entry['ip_or_subnet'] = $ilips;
2711
				$where_configured[] = $where_entry;
2712
			}
2713
		}
2714
	}
2715

    
2716
	if ($check_localip) {
2717
		if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0)) {
2718
			$where_entry = array();
2719
			$where_entry['if'] = 'l2tp';
2720
			$where_entry['ip_or_subnet'] = $config['l2tp']['localip'];
2721
			$where_configured[] = $where_entry;
2722
		}
2723
	}
2724

    
2725
	return $where_configured;
2726
}
2727

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

    
2750
function set_language() {
2751
	global $config, $g;
2752

    
2753
	if (!empty($config['system']['language'])) {
2754
		$lang = $config['system']['language'];
2755
	} elseif (!empty($g['language'])) {
2756
		$lang = $g['language'];
2757
	}
2758
	$lang .= ".UTF-8";
2759

    
2760
	putenv("LANG={$lang}");
2761
	setlocale(LC_ALL, $lang);
2762
	textdomain("pfSense");
2763
	bindtextdomain("pfSense", "/usr/local/share/locale");
2764
	bind_textdomain_codeset("pfSense", $lang);
2765
}
2766

    
2767
function get_locale_list() {
2768
	$locales = array(
2769
		"en_US" => gettext("English"),
2770
		"pt_BR" => gettext("Portuguese (Brazil)"),
2771
		"tr" => gettext("Turkish"),
2772
	);
2773
	asort($locales);
2774
	return $locales;
2775
}
2776

    
2777
function return_hex_ipv4($ipv4) {
2778
	if (!is_ipaddrv4($ipv4)) {
2779
		return(false);
2780
	}
2781

    
2782
	/* we need the hex form of the interface IPv4 address */
2783
	$ip4arr = explode(".", $ipv4);
2784
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2785
}
2786

    
2787
function convert_ipv6_to_128bit($ipv6) {
2788
	if (!is_ipaddrv6($ipv6)) {
2789
		return(false);
2790
	}
2791

    
2792
	$ip6arr = array();
2793
	$ip6prefix = Net_IPv6::uncompress($ipv6);
2794
	$ip6arr = explode(":", $ip6prefix);
2795
	/* binary presentation of the prefix for all 128 bits. */
2796
	$ip6prefixbin = "";
2797
	foreach ($ip6arr as $element) {
2798
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
2799
	}
2800
	return($ip6prefixbin);
2801
}
2802

    
2803
function convert_128bit_to_ipv6($ip6bin) {
2804
	if (strlen($ip6bin) <> 128) {
2805
		return(false);
2806
	}
2807

    
2808
	$ip6arr = array();
2809
	$ip6binarr = array();
2810
	$ip6binarr = str_split($ip6bin, 16);
2811
	foreach ($ip6binarr as $binpart) {
2812
		$ip6arr[] = dechex(bindec($binpart));
2813
	}
2814
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2815

    
2816
	return($ip6addr);
2817
}
2818

    
2819

    
2820
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
2821
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
2822
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
2823
/* 6to4 is 16 bits, e.g. 65535 */
2824
function calculate_ipv6_delegation_length($if) {
2825
	global $config;
2826

    
2827
	if (!is_array($config['interfaces'][$if])) {
2828
		return false;
2829
	}
2830

    
2831
	switch ($config['interfaces'][$if]['ipaddrv6']) {
2832
		case "6to4":
2833
			$pdlen = 16;
2834
			break;
2835
		case "6rd":
2836
			$rd6cfg = $config['interfaces'][$if];
2837
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
2838
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
2839
			break;
2840
		case "dhcp6":
2841
			$dhcp6cfg = $config['interfaces'][$if];
2842
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
2843
			break;
2844
		default:
2845
			$pdlen = 0;
2846
			break;
2847
	}
2848
	return($pdlen);
2849
}
2850

    
2851
function merge_ipv6_delegated_prefix($prefix, $suffix, $len = 64) {
2852
	$prefix = Net_IPv6::uncompress($prefix, true);
2853
	$suffix = Net_IPv6::uncompress($suffix, true);
2854

    
2855
	/*
2856
	 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
2857
	 *                ^^^^ ^
2858
	 *                |||| \-> 64
2859
	 *                |||\---> 63, 62, 61, 60
2860
	 *                ||\----> 56
2861
	 *                |\-----> 52
2862
	 *                \------> 48
2863
	 */
2864

    
2865
	switch ($len) {
2866
	case 48:
2867
		$prefix_len = 15;
2868
		break;
2869
	case 52:
2870
		$prefix_len = 16;
2871
		break;
2872
	case 56:
2873
		$prefix_len = 17;
2874
		break;
2875
	case 60:
2876
		$prefix_len = 18;
2877
		break;
2878
	/*
2879
	 * XXX 63, 62 and 61 should use 18 but PD can change and if
2880
	 * we let user chose this bit it can end up out of PD network
2881
	 *
2882
	 * Leave this with 20 for now until we find a way to let user
2883
	 * chose it. The side-effect is users with PD with one of these
2884
	 * lengths will not be able to setup DHCP server range for full
2885
	 * PD size, only for last /64 network
2886
	 */
2887
	case 63:
2888
	case 62:
2889
	case 61:
2890
	default:
2891
		$prefix_len = 20;
2892
		break;
2893
	}
2894

    
2895
	return Net_IPv6::compress(substr($prefix, 0, $prefix_len) .
2896
	    substr($suffix, $prefix_len));
2897
}
2898

    
2899
function dhcpv6_pd_str_help($pdlen) {
2900
	$result = '';
2901

    
2902
	switch ($pdlen) {
2903
	case 48:
2904
		$result = '::xxxx:xxxx:xxxx:xxxx:xxxx';
2905
		break;
2906
	case 52:
2907
		$result = '::xxx:xxxx:xxxx:xxxx:xxxx';
2908
		break;
2909
	case 56:
2910
		$result = '::xx:xxxx:xxxx:xxxx:xxxx';
2911
		break;
2912
	case 60:
2913
		$result = '::x:xxxx:xxxx:xxxx:xxxx';
2914
		break;
2915
	/*
2916
	 * XXX 63, 62 and 61 should use same mask of 60 but it would
2917
	 * we let user chose this bit it can end up out of PD network
2918
	 *
2919
	 * Leave this with the same of 64 for now until we find a way to
2920
	 * let user chose it. The side-effect is users with PD with one
2921
	 * of these lengths will not be able to setup DHCP server range
2922
	 * for full PD size, only for last /64 network
2923
	 */
2924
	case 61:
2925
	case 62:
2926
	case 63:
2927
	case 64:
2928
		$result = '::xxxx:xxxx:xxxx:xxxx';
2929
		break;
2930
	}
2931

    
2932
	return $result;
2933
}
2934

    
2935
function huawei_rssi_to_string($rssi) {
2936
	$dbm = array();
2937
	$i = 0;
2938
	$dbstart = -113;
2939
	while ($i < 32) {
2940
		$dbm[$i] = $dbstart + ($i * 2);
2941
		$i++;
2942
	}
2943
	$percent = round(($rssi / 31) * 100);
2944
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
2945
	return $string;
2946
}
2947

    
2948
function huawei_mode_to_string($mode, $submode) {
2949
	$modes[0] = gettext("None");
2950
	$modes[1] = "AMPS";
2951
	$modes[2] = "CDMA";
2952
	$modes[3] = "GSM/GPRS";
2953
	$modes[4] = "HDR";
2954
	$modes[5] = "WCDMA";
2955
	$modes[6] = "GPS";
2956

    
2957
	$submodes[0] = gettext("No Service");
2958
	$submodes[1] = "GSM";
2959
	$submodes[2] = "GPRS";
2960
	$submodes[3] = "EDGE";
2961
	$submodes[4] = "WCDMA";
2962
	$submodes[5] = "HSDPA";
2963
	$submodes[6] = "HSUPA";
2964
	$submodes[7] = "HSDPA+HSUPA";
2965
	$submodes[8] = "TD-SCDMA";
2966
	$submodes[9] = "HSPA+";
2967
	$string = "{$modes[$mode]}, {$submodes[$submode]} " . gettext("Mode");
2968
	return $string;
2969
}
2970

    
2971
function huawei_service_to_string($state) {
2972
	$modes[0] = gettext("No Service");
2973
	$modes[1] = gettext("Restricted Service");
2974
	$modes[2] = gettext("Valid Service");
2975
	$modes[3] = gettext("Restricted Regional Service");
2976
	$modes[4] = gettext("Powersaving Service");
2977
	$string = $modes[$state];
2978
	return $string;
2979
}
2980

    
2981
function huawei_simstate_to_string($state) {
2982
	$modes[0] = gettext("Invalid SIM/locked State");
2983
	$modes[1] = gettext("Valid SIM State");
2984
	$modes[2] = gettext("Invalid SIM CS State");
2985
	$modes[3] = gettext("Invalid SIM PS State");
2986
	$modes[4] = gettext("Invalid SIM CS/PS State");
2987
	$modes[255] = gettext("Missing SIM State");
2988
	$string = $modes[$state];
2989
	return $string;
2990
}
2991

    
2992
function zte_rssi_to_string($rssi) {
2993
	return huawei_rssi_to_string($rssi);
2994
}
2995

    
2996
function zte_mode_to_string($mode, $submode) {
2997
	$modes[0] = gettext("No Service");
2998
	$modes[1] = gettext("Limited Service");
2999
	$modes[2] = "GPRS";
3000
	$modes[3] = "GSM";
3001
	$modes[4] = "UMTS";
3002
	$modes[5] = "EDGE";
3003
	$modes[6] = "HSDPA";
3004

    
3005
	$submodes[0] = "CS_ONLY";
3006
	$submodes[1] = "PS_ONLY";
3007
	$submodes[2] = "CS_PS";
3008
	$submodes[3] = "CAMPED";
3009
	$string = "{$modes[$mode]}, {$submodes[$submode]} " . gettext("Mode");
3010
	return $string;
3011
}
3012

    
3013
function zte_service_to_string($service) {
3014
	$modes[0] = gettext("Initializing Service");
3015
	$modes[1] = gettext("Network Lock error Service");
3016
	$modes[2] = gettext("Network Locked Service");
3017
	$modes[3] = gettext("Unlocked or correct MCC/MNC Service");
3018
	$string = $modes[$service];
3019
	return $string;
3020
}
3021

    
3022
function zte_simstate_to_string($state) {
3023
	$modes[0] = gettext("No action State");
3024
	$modes[1] = gettext("Network lock State");
3025
	$modes[2] = gettext("(U)SIM card lock State");
3026
	$modes[3] = gettext("Network Lock and (U)SIM card Lock State");
3027
	$string = $modes[$state];
3028
	return $string;
3029
}
3030

    
3031
function get_configured_pppoe_server_interfaces() {
3032
	global $config;
3033
	$iflist = array();
3034
	if (is_array($config['pppoes']['pppoe'])) {
3035
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
3036
			if ($pppoe['mode'] == "server") {
3037
				$int = "poes". $pppoe['pppoeid'];
3038
				$iflist[$int] = strtoupper($int);
3039
			}
3040
		}
3041
	}
3042
	return $iflist;
3043
}
3044

    
3045
function get_pppoes_child_interfaces($ifpattern) {
3046
	$if_arr = array();
3047
	if ($ifpattern == "") {
3048
		return;
3049
	}
3050

    
3051
	exec("/sbin/ifconfig", $out, $ret);
3052
	foreach ($out as $line) {
3053
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3054
			$if_arr[] = $match[1];
3055
		}
3056
	}
3057
	return $if_arr;
3058

    
3059
}
3060

    
3061
/****f* pfsense-utils/pkg_call_plugins
3062
 * NAME
3063
 *   pkg_call_plugins
3064
 * INPUTS
3065
 *   $plugin_type value used to search in package configuration if the plugin is used, also used to create the function name
3066
 *   $plugin_params parameters to pass to the plugin function for passing multiple parameters a array can be used.
3067
 * RESULT
3068
 *   returns associative array results from the plugin calls for each package
3069
 * NOTES
3070
 *   This generic function can be used to notify or retrieve results from functions that are defined in packages.
3071
 ******/
3072
function pkg_call_plugins($plugin_type, $plugin_params) {
3073
	global $g, $config;
3074
	$results = array();
3075
	if (!is_array($config['installedpackages']['package'])) {
3076
		return $results;
3077
	}
3078
	foreach ($config['installedpackages']['package'] as $package) {
3079
		if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
3080
			continue;
3081
		}
3082
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], 'packagegui');
3083
		$pkgname = substr(reverse_strrchr($package['configurationfile'], "."), 0, -1);
3084
		if (is_array($pkg_config['plugins']['item'])) {
3085
			foreach ($pkg_config['plugins']['item'] as $plugin) {
3086
				if ($plugin['type'] == $plugin_type) {
3087
					if (file_exists($pkg_config['include_file'])) {
3088
						require_once($pkg_config['include_file']);
3089
					} else {
3090
						continue;
3091
					}
3092
					$plugin_function = $pkgname . '_'. $plugin_type;
3093
					$results[$pkgname] = call_user_func($plugin_function, $plugin_params);
3094
				}
3095
			}
3096
		}
3097
	}
3098
	return $results;
3099
}
3100

    
3101
function restore_aliastables() {
3102
	global $g, $config;
3103

    
3104
	$dbpath = "{$g['vardb_path']}/aliastables/";
3105

    
3106
	/* restore the alias tables, if we have them */
3107
	$files = glob("{$g['cf_conf_path']}/RAM_Disk_Store{$dbpath}*.tgz");
3108
	if (count($files)) {
3109
		echo "Restoring alias tables...";
3110
		foreach ($files as $file) {
3111
			if (file_exists($file)) {
3112
				$aliastablesrestore = "";
3113
				$aliastablesreturn = "";
3114
				exec("cd /;LANG=C /usr/bin/tar -xzf {$file} 2>&1", $aliastablesrestore, $aliastablesreturn);
3115
				$aliastablesrestore = implode(" ", $aliastablesrestore);
3116
				if ($aliastablesreturn <> 0) {
3117
					log_error(sprintf(gettext('Alias table restore failed exited with %1$s, the error is: %2$s %3$s%4$s'), $aliastablesreturn, $aliastablesrestore, $file, "\n"));
3118
				} else {
3119
					log_error(sprintf(gettext('Alias table restore succeeded exited with %1$s, the result is: %2$s %3$s%4$s'), $aliastablesreturn, $aliastablesrestore, $dbpath.basename($file, ".tgz"), "\n"));
3120
				}
3121
			}
3122
			/* If this backup is still there on a full install, but we aren't going to use ram disks, remove the archive since this is a transition. */
3123
			if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
3124
				unlink_if_exists("{$file}");
3125
			}
3126
		}
3127
		echo "done.\n";
3128
		return true;
3129
	}
3130
	return false;
3131
}
3132

    
3133
?>
(39-39/65)