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}\"	cons25	on	secure\n");
982
		} else if (stristr($tty, "ttyu")) {
983
			$ttyn = substr($tty, 0, 5);
984
			fwrite($fd, "{$ttyn}	\"/usr/libexec/getty {$serial_type}\"	cons25	{$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
/* Optional arg forces hh:mm:ss without days */
1148
function convert_seconds_to_dhms($sec, $showhoursonly = false) {
1149
	if (!is_numericint($sec)) {
1150
		return '-';
1151
	}
1152
	// FIXME: When we move to PHP 7 we can use "intdiv($sec % X, Y)" etc
1153
	list($d, $h, $m, $s) = array(	(int)($showhoursonly ? 0 : $sec/86400),
1154
					(int)($showhoursonly ? $sec : $sec % 86400)/3600),
1155
					(int)(($sec % 3600)/60),
1156
					$sec % 60
1157
				);
1158
	return ($d > 0 ? $d . 'd ' : '') . sprintf('%02d:%02d:%02d', $h, $m, $s);
1159
}
1160

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1431
	return $ifinfo;
1432
}
1433

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1624
	return false;
1625
}
1626

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

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

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

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

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

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

    
1666
	@curl_exec($ch);
1667
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1668
	fclose($fp);
1669
	curl_close($ch);
1670
	if ($http_code == 200) {
1671
		return true;
1672
	} else {
1673
		log_error(sprintf(gettext('Download file failed with status code %1$s. URL: %2$s'), $http_code, $url));
1674
		unlink_if_exists($destination);
1675
		return false;
1676
	}
1677
}
1678

    
1679
function download_file_with_progress_bar($url, $destination, $verify_ssl = true, $readbody = 'read_body', $connect_timeout = 5, $timeout = 0) {
1680
	global $config, $g;
1681
	global $ch, $fout, $file_size, $downloaded, $config, $first_progress_update;
1682
	$file_size = 1;
1683
	$downloaded = 1;
1684
	$first_progress_update = TRUE;
1685
	/* open destination file */
1686
	$fout = fopen($destination, "wb");
1687

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

    
1710
	if (!empty($config['system']['proxyurl'])) {
1711
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1712
		if (!empty($config['system']['proxyport'])) {
1713
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1714
		}
1715
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1716
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1717
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1718
		}
1719
	}
1720

    
1721
	@curl_exec($ch);
1722
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1723
	fclose($fout);
1724
	curl_close($ch);
1725
	if ($http_code == 200) {
1726
		return true;
1727
	} else {
1728
		log_error(sprintf(gettext('Download file failed with status code %1$s. URL: %2$s'), $http_code, $url));
1729
		unlink_if_exists($destination);
1730
		return false;
1731
	}
1732
}
1733

    
1734
function read_header($ch, $string) {
1735
	global $file_size, $fout;
1736
	$length = strlen($string);
1737
	$regs = "";
1738
	preg_match("/(Content-Length:) (.*)/", $string, $regs);
1739
	if ($regs[2] <> "") {
1740
		$file_size = intval($regs[2]);
1741
	}
1742
	ob_flush();
1743
	return $length;
1744
}
1745

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

    
1798
/*
1799
 *   update_output_window: update bottom textarea dynamically.
1800
 */
1801
function update_output_window($text) {
1802
	global $pkg_interface;
1803
	$log = preg_replace("/\n/", "\\n", $text);
1804
	if ($pkg_interface != "console") {
1805
?>
1806
<script type="text/javascript">
1807
//<![CDATA[
1808
	document.getElementById("output").textContent="<?=htmlspecialchars($log)?>";
1809
	document.getElementById("output").scrollTop = document.getElementById("output").scrollHeight;
1810
//]]>
1811
</script>
1812
<?php
1813
	}
1814
	/* ensure that contents are written out */
1815
	ob_flush();
1816
}
1817

    
1818
/*
1819
 *   update_status: update top textarea dynamically.
1820
 */
1821
function update_status($status) {
1822
	global $pkg_interface;
1823

    
1824
	if ($pkg_interface == "console") {
1825
		print ("{$status}");
1826
	}
1827

    
1828
	/* ensure that contents are written out */
1829
	ob_flush();
1830
}
1831

    
1832
/*
1833
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
1834
 */
1835
function update_progress_bar($percent, $first_time) {
1836
	global $pkg_interface;
1837
	if ($percent > 100) {
1838
		$percent = 1;
1839
	}
1840
	if ($pkg_interface <> "console") {
1841
		echo '<script type="text/javascript">';
1842
		echo "\n//<![CDATA[\n";
1843
		echo 'document.getElementById("progressbar").style.width="'. $percent.'%"';
1844
		echo "\n//]]>\n";
1845
		echo '</script>';
1846
	} else {
1847
		if (!($first_time)) {
1848
			echo "\x08\x08\x08\x08\x08";
1849
		}
1850
		echo sprintf("%4d%%", $percent);
1851
	}
1852
}
1853

    
1854
/* 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. */
1855
if (!function_exists("split")) {
1856
	function split($separator, $haystack, $limit = null) {
1857
		log_error("deprecated split() call with separator '{$separator}'");
1858
		return preg_split($separator, $haystack, $limit);
1859
	}
1860
}
1861

    
1862
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
1863
	global $g, $config, $pconfig, $debug;
1864
	if (!$origname) {
1865
		return;
1866
	}
1867

    
1868
	$sectionref = &$config;
1869
	foreach ($section as $sectionname) {
1870
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
1871
			$sectionref = &$sectionref[$sectionname];
1872
		} else {
1873
			return;
1874
		}
1875
	}
1876

    
1877
	if ($debug) {
1878
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
1879
		fwrite($fd, print_r($pconfig, true));
1880
	}
1881

    
1882
	if (is_array($sectionref)) {
1883
		foreach ($sectionref as $itemkey => $item) {
1884
			if ($debug) {
1885
				fwrite($fd, "$itemkey\n");
1886
			}
1887

    
1888
			$fieldfound = true;
1889
			$fieldref = &$sectionref[$itemkey];
1890
			foreach ($field as $fieldname) {
1891
				if (is_array($fieldref) && isset($fieldref[$fieldname])) {
1892
					$fieldref = &$fieldref[$fieldname];
1893
				} else {
1894
					$fieldfound = false;
1895
					break;
1896
				}
1897
			}
1898
			if ($fieldfound && $fieldref == $origname) {
1899
				if ($debug) {
1900
					fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1901
				}
1902
				$fieldref = $new_alias_name;
1903
			}
1904
		}
1905
	}
1906

    
1907
	if ($debug) {
1908
		fclose($fd);
1909
	}
1910

    
1911
}
1912

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

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

    
1965
function update_alias_url_data() {
1966
	global $config, $g;
1967

    
1968
	$updated = false;
1969

    
1970
	/* item is a url type */
1971
	$lockkey = lock('aliasurl');
1972
	if (is_array($config['aliases']['alias'])) {
1973
		foreach ($config['aliases']['alias'] as $x => $alias) {
1974
			if (empty($alias['aliasurl'])) {
1975
				continue;
1976
			}
1977

    
1978
			$address = null;
1979
			foreach ($alias['aliasurl'] as $alias_url) {
1980
				/* fetch down and add in */
1981
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
1982
				unlink($temp_filename);
1983
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
1984
				mkdir($temp_filename);
1985
				if (!download_file($alias_url, $temp_filename . "/aliases", $verify_ssl)) {
1986
					log_error(sprintf(gettext("Failed to download alias %s"), $alias_url));
1987
					continue;
1988
				}
1989

    
1990
				/* if the item is tar gzipped then extract */
1991
				if (stripos($alias_url, '.tgz')) {
1992
					if (!process_alias_tgz($temp_filename)) {
1993
						continue;
1994
					}
1995
				}
1996
				if (file_exists("{$temp_filename}/aliases")) {
1997
					$address = parse_aliases_file("{$temp_filename}/aliases", $alias['type'], 5000);
1998
					mwexec("/bin/rm -rf {$temp_filename}");
1999
				}
2000
			}
2001
			if ($address != null) {
2002
				$config['aliases']['alias'][$x]['address'] = implode(" ", $address);
2003
				$updated = true;
2004
			}
2005
		}
2006
	}
2007
	unlock($lockkey);
2008

    
2009
	/* Report status to callers as well */
2010
	return $updated;
2011
}
2012

    
2013
function process_alias_tgz($temp_filename) {
2014
	if (!file_exists('/usr/bin/tar')) {
2015
		log_error(gettext("Alias archive is a .tar/tgz file which cannot be decompressed because utility is missing!"));
2016
		return false;
2017
	}
2018
	rename("{$temp_filename}/aliases", "{$temp_filename}/aliases.tgz");
2019
	mwexec("/usr/bin/tar xzf {$temp_filename}/aliases.tgz -C {$temp_filename}/aliases/");
2020
	unlink("{$temp_filename}/aliases.tgz");
2021
	$files_to_process = return_dir_as_array("{$temp_filename}/");
2022
	/* foreach through all extracted files and build up aliases file */
2023
	$fd = @fopen("{$temp_filename}/aliases", "w");
2024
	if (!$fd) {
2025
		log_error(sprintf(gettext("Could not open %s/aliases for writing!"), $temp_filename));
2026
		return false;
2027
	}
2028
	foreach ($files_to_process as $f2p) {
2029
		$tmpfd = @fopen($f2p, 'r');
2030
		if (!$tmpfd) {
2031
			log_error(sprintf(gettext('The following file could not be read %1$s from %2$s'), $f2p, $temp_filename));
2032
			continue;
2033
		}
2034
		while (($tmpbuf = fread($tmpfd, 65536)) !== FALSE) {
2035
			fwrite($fd, $tmpbuf);
2036
		}
2037
		fclose($tmpfd);
2038
		unlink($f2p);
2039
	}
2040
	fclose($fd);
2041
	unset($tmpbuf);
2042

    
2043
	return true;
2044
}
2045

    
2046
function version_compare_dates($a, $b) {
2047
	$a_time = strtotime($a);
2048
	$b_time = strtotime($b);
2049

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

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

    
2134
		// First try to compare the numeric parts of the version string.
2135
		$v = version_compare_numeric($cur_num, $rem_num);
2136

    
2137
		// If the numeric parts are the same, compare the string parts.
2138
		if ($v == 0) {
2139
			return version_compare_string($cur_str, $rem_str);
2140
		}
2141
	}
2142
	return $v;
2143
}
2144
function process_alias_urltable($name, $type, $url, $freq, $forceupdate=false, $validateonly=false) {
2145
	global $g, $config;
2146

    
2147
	$urltable_prefix = "/var/db/aliastables/";
2148
	$urltable_filename = $urltable_prefix . $name . ".txt";
2149
	$tmp_urltable_filename = $urltable_filename . ".tmp";
2150

    
2151
	// Make the aliases directory if it doesn't exist
2152
	if (!file_exists($urltable_prefix)) {
2153
		mkdir($urltable_prefix);
2154
	} elseif (!is_dir($urltable_prefix)) {
2155
		unlink($urltable_prefix);
2156
		mkdir($urltable_prefix);
2157
	}
2158

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

    
2164
		// Try to fetch the URL supplied
2165
		conf_mount_rw();
2166
		unlink_if_exists($tmp_urltable_filename);
2167
		$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2168
		if (download_file($url, $tmp_urltable_filename, $verify_ssl)) {
2169
			// Convert lines that begin with '$' or ';' to comments '#' instead of deleting them.
2170
			mwexec("/usr/bin/sed -i \"\" -E 's/^[[:space:]]*($|#|;)/#/g; /^#/!s/\;.*//g;' ". escapeshellarg($tmp_urltable_filename));
2171

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

    
2174
			$parsed_contents = parse_aliases_file($tmp_urltable_filename, $type, "-1", true);
2175
			if ($type == "urltable_ports") {
2176
				$parsed_contents = group_ports($parsed_contents, true);
2177
			}
2178
			if (is_array($parsed_contents)) {
2179
				file_put_contents($urltable_filename, implode("\n", $parsed_contents));
2180
			}
2181

    
2182
			/* 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. */
2183
			if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
2184
				unlink_if_exists("{$g['cf_conf_path']}/RAM_Disk_Store{$urltable_filename}.tgz");
2185
			} else {
2186
				/* Update the RAM disk store with the new/updated table file. */
2187
				mwexec("cd / && /usr/bin/tar -czf \"{$g['cf_conf_path']}/RAM_Disk_Store{$urltable_filename}.tgz\" -C / \"{$urltable_filename}\"");
2188
			}
2189
			unlink_if_exists($tmp_urltable_filename);
2190
		} else {
2191
			if (!$validateonly) {
2192
				touch($urltable_filename);
2193
			}
2194
			conf_mount_ro();
2195
			return false;
2196
		}
2197
		conf_mount_ro();
2198
		return true;
2199
	} else {
2200
		// File exists, and it doesn't need to be updated.
2201
		return -1;
2202
	}
2203
}
2204
function get_real_slice_from_glabel($label) {
2205
	$label = escapeshellarg($label);
2206
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/{$label} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`);
2207
}
2208
function nanobsd_get_boot_slice() {
2209
	return trim(`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`);
2210
}
2211
function nanobsd_get_boot_drive() {
2212
	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`);
2213
}
2214
function nanobsd_get_active_slice() {
2215
	$boot_drive = nanobsd_get_boot_drive();
2216
	$active = trim(`gpart show $boot_drive | grep '\[active\]' | awk '{print $3;}'`);
2217

    
2218
	return "{$boot_drive}s{$active}";
2219
}
2220
function nanobsd_get_size() {
2221
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2222
}
2223
function nanobsd_switch_boot_slice() {
2224
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2225
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2226
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2227
	nanobsd_detect_slice_info();
2228

    
2229
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2230
		$slice = $TOFLASH;
2231
	} else {
2232
		$slice = $BOOTFLASH;
2233
	}
2234

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

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

    
2293
	mkdir($tmppath);
2294
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2295
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2296
	copy("/etc/fstab", $fstabpath);
2297

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

    
2314
	return $status;
2315
}
2316
function nanobsd_detect_slice_info() {
2317
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2318
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2319
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2320

    
2321
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2322
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2323
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2324
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2325

    
2326
	// Detect which slice is active and set information.
2327
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2328
		$SLICE = "2";
2329
		$OLDSLICE = "1";
2330
		$GLABEL_SLICE = "pfsense1";
2331
		$UFS_ID = "1";
2332
		$OLD_UFS_ID = "0";
2333

    
2334
	} else {
2335
		$SLICE = "1";
2336
		$OLDSLICE = "2";
2337
		$GLABEL_SLICE = "pfsense0";
2338
		$UFS_ID = "0";
2339
		$OLD_UFS_ID = "1";
2340
	}
2341
	$TOFLASH = "{$BOOT_DRIVE}s{$SLICE}";
2342
	$COMPLETE_PATH = "{$BOOT_DRIVE}s{$SLICE}a";
2343
	$COMPLETE_BOOT_PATH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2344
	$BOOTFLASH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2345
}
2346

    
2347
function nanobsd_friendly_slice_name($slicename) {
2348
	global $g;
2349
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2350
}
2351

    
2352
function get_include_contents($filename) {
2353
	if (is_file($filename)) {
2354
		ob_start();
2355
		include $filename;
2356
		$contents = ob_get_contents();
2357
		ob_end_clean();
2358
		return $contents;
2359
	}
2360
	return false;
2361
}
2362

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

    
2475
function get_country_name($country_code) {
2476
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2477
		return "";
2478
	}
2479

    
2480
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2481
	$country_names_contents = file_get_contents($country_names_xml);
2482
	$country_names = xml2array($country_names_contents);
2483

    
2484
	if ($country_code == "ALL") {
2485
		$country_list = array();
2486
		foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2487
			$country_list[] = array(
2488
				"code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2489
				"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])));
2490
		}
2491
		return $country_list;
2492
	}
2493

    
2494
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2495
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2496
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2497
		}
2498
	}
2499
	return "";
2500
}
2501

    
2502
/* sort by interface only, retain the original order of rules that apply to
2503
   the same interface */
2504
function filter_rules_sort() {
2505
	global $config;
2506

    
2507
	/* mark each rule with the sequence number (to retain the order while sorting) */
2508
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2509
		$config['filter']['rule'][$i]['seq'] = $i;
2510
	}
2511

    
2512
	usort($config['filter']['rule'], "filter_rules_compare");
2513

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

    
2533
function generate_ipv6_from_mac($mac) {
2534
	$elements = explode(":", $mac);
2535
	if (count($elements) <> 6) {
2536
		return false;
2537
	}
2538

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

    
2560
		$i++;
2561
	}
2562
	return $ipv6;
2563
}
2564

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

    
2591
}
2592

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

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

    
2632
	$where_configured = array();
2633

    
2634
	$pos = strpos($ignore_if, '_virtualip');
2635
	if ($pos !== false) {
2636
		$ignore_vip_id = substr($ignore_if, $pos+10);
2637
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2638
	} else {
2639
		$ignore_vip_id = -1;
2640
		$ignore_vip_if = $ignore_if;
2641
	}
2642

    
2643
	$isipv6 = is_ipaddrv6($ipaddr);
2644

    
2645
	if ($check_subnets) {
2646
		$cidrprefix = intval($cidrprefix);
2647
		if ($isipv6) {
2648
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2649
				$cidrprefix = 128;
2650
			}
2651
		} else {
2652
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2653
				$cidrprefix = 32;
2654
			}
2655
		}
2656
		$iflist = get_configured_interface_list();
2657
		foreach ($iflist as $if => $ifname) {
2658
			if ($ignore_if == $if) {
2659
				continue;
2660
			}
2661

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

    
2689
		foreach ($interface_list_ips as $if => $ilips) {
2690
			if ($ignore_if == $if) {
2691
				continue;
2692
			}
2693
			if (strcasecmp($ipaddr, $ilips) == 0) {
2694
				$where_entry = array();
2695
				$where_entry['if'] = $if;
2696
				$where_entry['ip_or_subnet'] = $ilips;
2697
				$where_configured[] = $where_entry;
2698
			}
2699
		}
2700
	}
2701

    
2702
	if ($check_localip) {
2703
		if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0)) {
2704
			$where_entry = array();
2705
			$where_entry['if'] = 'l2tp';
2706
			$where_entry['ip_or_subnet'] = $config['l2tp']['localip'];
2707
			$where_configured[] = $where_entry;
2708
		}
2709
	}
2710

    
2711
	return $where_configured;
2712
}
2713

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

    
2736
function set_language() {
2737
	global $config, $g;
2738

    
2739
	if (!empty($config['system']['language'])) {
2740
		$lang = $config['system']['language'];
2741
	} elseif (!empty($g['language'])) {
2742
		$lang = $g['language'];
2743
	}
2744
	$lang .= ".UTF-8";
2745

    
2746
	putenv("LANG={$lang}");
2747
	setlocale(LC_ALL, $lang);
2748
	textdomain("pfSense");
2749
	bindtextdomain("pfSense", "/usr/local/share/locale");
2750
	bind_textdomain_codeset("pfSense", $lang);
2751
}
2752

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

    
2763
function return_hex_ipv4($ipv4) {
2764
	if (!is_ipaddrv4($ipv4)) {
2765
		return(false);
2766
	}
2767

    
2768
	/* we need the hex form of the interface IPv4 address */
2769
	$ip4arr = explode(".", $ipv4);
2770
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2771
}
2772

    
2773
function convert_ipv6_to_128bit($ipv6) {
2774
	if (!is_ipaddrv6($ipv6)) {
2775
		return(false);
2776
	}
2777

    
2778
	$ip6arr = array();
2779
	$ip6prefix = Net_IPv6::uncompress($ipv6);
2780
	$ip6arr = explode(":", $ip6prefix);
2781
	/* binary presentation of the prefix for all 128 bits. */
2782
	$ip6prefixbin = "";
2783
	foreach ($ip6arr as $element) {
2784
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
2785
	}
2786
	return($ip6prefixbin);
2787
}
2788

    
2789
function convert_128bit_to_ipv6($ip6bin) {
2790
	if (strlen($ip6bin) <> 128) {
2791
		return(false);
2792
	}
2793

    
2794
	$ip6arr = array();
2795
	$ip6binarr = array();
2796
	$ip6binarr = str_split($ip6bin, 16);
2797
	foreach ($ip6binarr as $binpart) {
2798
		$ip6arr[] = dechex(bindec($binpart));
2799
	}
2800
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2801

    
2802
	return($ip6addr);
2803
}
2804

    
2805

    
2806
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
2807
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
2808
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
2809
/* 6to4 is 16 bits, e.g. 65535 */
2810
function calculate_ipv6_delegation_length($if) {
2811
	global $config;
2812

    
2813
	if (!is_array($config['interfaces'][$if])) {
2814
		return false;
2815
	}
2816

    
2817
	switch ($config['interfaces'][$if]['ipaddrv6']) {
2818
		case "6to4":
2819
			$pdlen = 16;
2820
			break;
2821
		case "6rd":
2822
			$rd6cfg = $config['interfaces'][$if];
2823
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
2824
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
2825
			break;
2826
		case "dhcp6":
2827
			$dhcp6cfg = $config['interfaces'][$if];
2828
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
2829
			break;
2830
		default:
2831
			$pdlen = 0;
2832
			break;
2833
	}
2834
	return($pdlen);
2835
}
2836

    
2837
function merge_ipv6_delegated_prefix($prefix, $suffix, $len = 64) {
2838
	$prefix = Net_IPv6::uncompress($prefix, true);
2839
	$suffix = Net_IPv6::uncompress($suffix, true);
2840

    
2841
	/*
2842
	 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
2843
	 *                ^^^^ ^
2844
	 *                |||| \-> 64
2845
	 *                |||\---> 63, 62, 61, 60
2846
	 *                ||\----> 56
2847
	 *                |\-----> 52
2848
	 *                \------> 48
2849
	 */
2850

    
2851
	switch ($len) {
2852
	case 48:
2853
		$prefix_len = 15;
2854
		break;
2855
	case 52:
2856
		$prefix_len = 16;
2857
		break;
2858
	case 56:
2859
		$prefix_len = 17;
2860
		break;
2861
	case 60:
2862
		$prefix_len = 18;
2863
		break;
2864
	/*
2865
	 * XXX 63, 62 and 61 should use 18 but PD can change and if
2866
	 * we let user chose this bit it can end up out of PD network
2867
	 *
2868
	 * Leave this with 20 for now until we find a way to let user
2869
	 * chose it. The side-effect is users with PD with one of these
2870
	 * lengths will not be able to setup DHCP server range for full
2871
	 * PD size, only for last /64 network
2872
	 */
2873
	case 63:
2874
	case 62:
2875
	case 61:
2876
	default:
2877
		$prefix_len = 20;
2878
		break;
2879
	}
2880

    
2881
	return Net_IPv6::compress(substr($prefix, 0, $prefix_len) .
2882
	    substr($suffix, $prefix_len));
2883
}
2884

    
2885
function dhcpv6_pd_str_help($pdlen) {
2886
	$result = '';
2887

    
2888
	switch ($pdlen) {
2889
	case 48:
2890
		$result = '::xxxx:xxxx:xxxx:xxxx:xxxx';
2891
		break;
2892
	case 52:
2893
		$result = '::xxx:xxxx:xxxx:xxxx:xxxx';
2894
		break;
2895
	case 56:
2896
		$result = '::xx:xxxx:xxxx:xxxx:xxxx';
2897
		break;
2898
	case 60:
2899
		$result = '::x:xxxx:xxxx:xxxx:xxxx';
2900
		break;
2901
	/*
2902
	 * XXX 63, 62 and 61 should use same mask of 60 but it would
2903
	 * we let user chose this bit it can end up out of PD network
2904
	 *
2905
	 * Leave this with the same of 64 for now until we find a way to
2906
	 * let user chose it. The side-effect is users with PD with one
2907
	 * of these lengths will not be able to setup DHCP server range
2908
	 * for full PD size, only for last /64 network
2909
	 */
2910
	case 61:
2911
	case 62:
2912
	case 63:
2913
	case 64:
2914
		$result = '::xxxx:xxxx:xxxx:xxxx';
2915
		break;
2916
	}
2917

    
2918
	return $result;
2919
}
2920

    
2921
function huawei_rssi_to_string($rssi) {
2922
	$dbm = array();
2923
	$i = 0;
2924
	$dbstart = -113;
2925
	while ($i < 32) {
2926
		$dbm[$i] = $dbstart + ($i * 2);
2927
		$i++;
2928
	}
2929
	$percent = round(($rssi / 31) * 100);
2930
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
2931
	return $string;
2932
}
2933

    
2934
function huawei_mode_to_string($mode, $submode) {
2935
	$modes[0] = gettext("None");
2936
	$modes[1] = "AMPS";
2937
	$modes[2] = "CDMA";
2938
	$modes[3] = "GSM/GPRS";
2939
	$modes[4] = "HDR";
2940
	$modes[5] = "WCDMA";
2941
	$modes[6] = "GPS";
2942

    
2943
	$submodes[0] = gettext("No Service");
2944
	$submodes[1] = "GSM";
2945
	$submodes[2] = "GPRS";
2946
	$submodes[3] = "EDGE";
2947
	$submodes[4] = "WCDMA";
2948
	$submodes[5] = "HSDPA";
2949
	$submodes[6] = "HSUPA";
2950
	$submodes[7] = "HSDPA+HSUPA";
2951
	$submodes[8] = "TD-SCDMA";
2952
	$submodes[9] = "HSPA+";
2953
	$string = "{$modes[$mode]}, {$submodes[$submode]} " . gettext("Mode");
2954
	return $string;
2955
}
2956

    
2957
function huawei_service_to_string($state) {
2958
	$modes[0] = gettext("No Service");
2959
	$modes[1] = gettext("Restricted Service");
2960
	$modes[2] = gettext("Valid Service");
2961
	$modes[3] = gettext("Restricted Regional Service");
2962
	$modes[4] = gettext("Powersaving Service");
2963
	$string = $modes[$state];
2964
	return $string;
2965
}
2966

    
2967
function huawei_simstate_to_string($state) {
2968
	$modes[0] = gettext("Invalid SIM/locked State");
2969
	$modes[1] = gettext("Valid SIM State");
2970
	$modes[2] = gettext("Invalid SIM CS State");
2971
	$modes[3] = gettext("Invalid SIM PS State");
2972
	$modes[4] = gettext("Invalid SIM CS/PS State");
2973
	$modes[255] = gettext("Missing SIM State");
2974
	$string = $modes[$state];
2975
	return $string;
2976
}
2977

    
2978
function zte_rssi_to_string($rssi) {
2979
	return huawei_rssi_to_string($rssi);
2980
}
2981

    
2982
function zte_mode_to_string($mode, $submode) {
2983
	$modes[0] = gettext("No Service");
2984
	$modes[1] = gettext("Limited Service");
2985
	$modes[2] = "GPRS";
2986
	$modes[3] = "GSM";
2987
	$modes[4] = "UMTS";
2988
	$modes[5] = "EDGE";
2989
	$modes[6] = "HSDPA";
2990

    
2991
	$submodes[0] = "CS_ONLY";
2992
	$submodes[1] = "PS_ONLY";
2993
	$submodes[2] = "CS_PS";
2994
	$submodes[3] = "CAMPED";
2995
	$string = "{$modes[$mode]}, {$submodes[$submode]} " . gettext("Mode");
2996
	return $string;
2997
}
2998

    
2999
function zte_service_to_string($service) {
3000
	$modes[0] = gettext("Initializing Service");
3001
	$modes[1] = gettext("Network Lock error Service");
3002
	$modes[2] = gettext("Network Locked Service");
3003
	$modes[3] = gettext("Unlocked or correct MCC/MNC Service");
3004
	$string = $modes[$service];
3005
	return $string;
3006
}
3007

    
3008
function zte_simstate_to_string($state) {
3009
	$modes[0] = gettext("No action State");
3010
	$modes[1] = gettext("Network lock State");
3011
	$modes[2] = gettext("(U)SIM card lock State");
3012
	$modes[3] = gettext("Network Lock and (U)SIM card Lock State");
3013
	$string = $modes[$state];
3014
	return $string;
3015
}
3016

    
3017
function get_configured_pppoe_server_interfaces() {
3018
	global $config;
3019
	$iflist = array();
3020
	if (is_array($config['pppoes']['pppoe'])) {
3021
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
3022
			if ($pppoe['mode'] == "server") {
3023
				$int = "poes". $pppoe['pppoeid'];
3024
				$iflist[$int] = strtoupper($int);
3025
			}
3026
		}
3027
	}
3028
	return $iflist;
3029
}
3030

    
3031
function get_pppoes_child_interfaces($ifpattern) {
3032
	$if_arr = array();
3033
	if ($ifpattern == "") {
3034
		return;
3035
	}
3036

    
3037
	exec("/sbin/ifconfig", $out, $ret);
3038
	foreach ($out as $line) {
3039
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3040
			$if_arr[] = $match[1];
3041
		}
3042
	}
3043
	return $if_arr;
3044

    
3045
}
3046

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

    
3087
function restore_aliastables() {
3088
	global $g, $config;
3089

    
3090
	$dbpath = "{$g['vardb_path']}/aliastables/";
3091

    
3092
	/* restore the alias tables, if we have them */
3093
	$files = glob("{$g['cf_conf_path']}/RAM_Disk_Store{$dbpath}*.tgz");
3094
	if (count($files)) {
3095
		echo "Restoring alias tables...";
3096
		foreach ($files as $file) {
3097
			if (file_exists($file)) {
3098
				$aliastablesrestore = "";
3099
				$aliastablesreturn = "";
3100
				exec("cd /;LANG=C /usr/bin/tar -xzf {$file} 2>&1", $aliastablesrestore, $aliastablesreturn);
3101
				$aliastablesrestore = implode(" ", $aliastablesrestore);
3102
				if ($aliastablesreturn <> 0) {
3103
					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"));
3104
				} else {
3105
					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"));
3106
				}
3107
			}
3108
			/* 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. */
3109
			if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
3110
				unlink_if_exists("{$file}");
3111
			}
3112
		}
3113
		echo "done.\n";
3114
		return true;
3115
	}
3116
	return false;
3117
}
3118

    
3119
?>
(39-39/65)