Project

General

Profile

Download (87.6 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 = 'std.' . $serialspeed;
975
	} else {
976
		$console_type = 'al.Pc';
977
		$serial_type = 'al.' . $serialspeed;
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 (!file_exists($filename)) {
1924
		log_error(sprintf(gettext("Could not process non-existent file from alias: %s"), $filename));
1925
		return null;
1926
	}
1927

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

    
1970
function update_alias_url_data() {
1971
	global $config, $g;
1972

    
1973
	$updated = false;
1974

    
1975
	/* item is a url type */
1976
	$lockkey = lock('aliasurl');
1977
	if (is_array($config['aliases']['alias'])) {
1978
		foreach ($config['aliases']['alias'] as $x => $alias) {
1979
			if (empty($alias['aliasurl'])) {
1980
				continue;
1981
			}
1982

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

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

    
2014
	/* Report status to callers as well */
2015
	return $updated;
2016
}
2017

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

    
2048
	return true;
2049
}
2050

    
2051
function version_compare_dates($a, $b) {
2052
	$a_time = strtotime($a);
2053
	$b_time = strtotime($b);
2054

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

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

    
2139
		// First try to compare the numeric parts of the version string.
2140
		$v = version_compare_numeric($cur_num, $rem_num);
2141

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

    
2152
	$urltable_prefix = "/var/db/aliastables/";
2153
	$urltable_filename = $urltable_prefix . $name . ".txt";
2154
	$tmp_urltable_filename = $urltable_filename . ".tmp";
2155

    
2156
	// Make the aliases directory if it doesn't exist
2157
	if (!file_exists($urltable_prefix)) {
2158
		mkdir($urltable_prefix);
2159
	} elseif (!is_dir($urltable_prefix)) {
2160
		unlink($urltable_prefix);
2161
		mkdir($urltable_prefix);
2162
	}
2163

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

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

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

    
2179
			$parsed_contents = parse_aliases_file($tmp_urltable_filename, $type, "-1", true);
2180
			if ($type == "urltable_ports") {
2181
				$parsed_contents = group_ports($parsed_contents, true);
2182
			}
2183
			if (is_array($parsed_contents)) {
2184
				file_put_contents($urltable_filename, implode("\n", $parsed_contents));
2185
			}
2186

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

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

    
2234
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2235
		$slice = $TOFLASH;
2236
	} else {
2237
		$slice = $BOOTFLASH;
2238
	}
2239

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

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

    
2298
	mkdir($tmppath);
2299
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2300
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2301
	copy("/etc/fstab", $fstabpath);
2302

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

    
2319
	return $status;
2320
}
2321
function nanobsd_detect_slice_info() {
2322
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2323
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2324
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2325

    
2326
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2327
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2328
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2329
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2330

    
2331
	// Detect which slice is active and set information.
2332
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2333
		$SLICE = "2";
2334
		$OLDSLICE = "1";
2335
		$GLABEL_SLICE = "pfsense1";
2336
		$UFS_ID = "1";
2337
		$OLD_UFS_ID = "0";
2338

    
2339
	} else {
2340
		$SLICE = "1";
2341
		$OLDSLICE = "2";
2342
		$GLABEL_SLICE = "pfsense0";
2343
		$UFS_ID = "0";
2344
		$OLD_UFS_ID = "1";
2345
	}
2346
	$TOFLASH = "{$BOOT_DRIVE}s{$SLICE}";
2347
	$COMPLETE_PATH = "{$BOOT_DRIVE}s{$SLICE}a";
2348
	$COMPLETE_BOOT_PATH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2349
	$BOOTFLASH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2350
}
2351

    
2352
function nanobsd_friendly_slice_name($slicename) {
2353
	global $g;
2354
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2355
}
2356

    
2357
function get_include_contents($filename) {
2358
	if (is_file($filename)) {
2359
		ob_start();
2360
		include $filename;
2361
		$contents = ob_get_contents();
2362
		ob_end_clean();
2363
		return $contents;
2364
	}
2365
	return false;
2366
}
2367

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

    
2480
function get_country_name($country_code) {
2481
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2482
		return "";
2483
	}
2484

    
2485
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2486
	$country_names_contents = file_get_contents($country_names_xml);
2487
	$country_names = xml2array($country_names_contents);
2488

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

    
2499
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2500
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2501
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2502
		}
2503
	}
2504
	return "";
2505
}
2506

    
2507
/* sort by interface only, retain the original order of rules that apply to
2508
   the same interface */
2509
function filter_rules_sort() {
2510
	global $config;
2511

    
2512
	/* mark each rule with the sequence number (to retain the order while sorting) */
2513
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2514
		$config['filter']['rule'][$i]['seq'] = $i;
2515
	}
2516

    
2517
	usort($config['filter']['rule'], "filter_rules_compare");
2518

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

    
2538
function generate_ipv6_from_mac($mac) {
2539
	$elements = explode(":", $mac);
2540
	if (count($elements) <> 6) {
2541
		return false;
2542
	}
2543

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

    
2565
		$i++;
2566
	}
2567
	return $ipv6;
2568
}
2569

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

    
2596
}
2597

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

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

    
2637
	$where_configured = array();
2638

    
2639
	$pos = strpos($ignore_if, '_virtualip');
2640
	if ($pos !== false) {
2641
		$ignore_vip_id = substr($ignore_if, $pos+10);
2642
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2643
	} else {
2644
		$ignore_vip_id = -1;
2645
		$ignore_vip_if = $ignore_if;
2646
	}
2647

    
2648
	$isipv6 = is_ipaddrv6($ipaddr);
2649

    
2650
	if ($check_subnets) {
2651
		$cidrprefix = intval($cidrprefix);
2652
		if ($isipv6) {
2653
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2654
				$cidrprefix = 128;
2655
			}
2656
		} else {
2657
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2658
				$cidrprefix = 32;
2659
			}
2660
		}
2661
		$iflist = get_configured_interface_list();
2662
		foreach ($iflist as $if => $ifname) {
2663
			if ($ignore_if == $if) {
2664
				continue;
2665
			}
2666

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

    
2694
		foreach ($interface_list_ips as $if => $ilips) {
2695
			if ($ignore_if == $if) {
2696
				continue;
2697
			}
2698
			if (strcasecmp($ipaddr, $ilips) == 0) {
2699
				$where_entry = array();
2700
				$where_entry['if'] = $if;
2701
				$where_entry['ip_or_subnet'] = $ilips;
2702
				$where_configured[] = $where_entry;
2703
			}
2704
		}
2705
	}
2706

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

    
2716
	return $where_configured;
2717
}
2718

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

    
2741
function set_language() {
2742
	global $config, $g;
2743

    
2744
	if (!empty($config['system']['language'])) {
2745
		$lang = $config['system']['language'];
2746
	} elseif (!empty($g['language'])) {
2747
		$lang = $g['language'];
2748
	}
2749
	$lang .= ".UTF-8";
2750

    
2751
	putenv("LANG={$lang}");
2752
	setlocale(LC_ALL, $lang);
2753
	textdomain("pfSense");
2754
	bindtextdomain("pfSense", "/usr/local/share/locale");
2755
	bind_textdomain_codeset("pfSense", $lang);
2756
}
2757

    
2758
function get_locale_list() {
2759
	$locales = array(
2760
		"en_US" => gettext("English"),
2761
		"pt_BR" => gettext("Portuguese (Brazil)"),
2762
		"tr" => gettext("Turkish"),
2763
	);
2764
	asort($locales);
2765
	return $locales;
2766
}
2767

    
2768
function return_hex_ipv4($ipv4) {
2769
	if (!is_ipaddrv4($ipv4)) {
2770
		return(false);
2771
	}
2772

    
2773
	/* we need the hex form of the interface IPv4 address */
2774
	$ip4arr = explode(".", $ipv4);
2775
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2776
}
2777

    
2778
function convert_ipv6_to_128bit($ipv6) {
2779
	if (!is_ipaddrv6($ipv6)) {
2780
		return(false);
2781
	}
2782

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

    
2794
function convert_128bit_to_ipv6($ip6bin) {
2795
	if (strlen($ip6bin) <> 128) {
2796
		return(false);
2797
	}
2798

    
2799
	$ip6arr = array();
2800
	$ip6binarr = array();
2801
	$ip6binarr = str_split($ip6bin, 16);
2802
	foreach ($ip6binarr as $binpart) {
2803
		$ip6arr[] = dechex(bindec($binpart));
2804
	}
2805
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2806

    
2807
	return($ip6addr);
2808
}
2809

    
2810

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

    
2818
	if (!is_array($config['interfaces'][$if])) {
2819
		return false;
2820
	}
2821

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

    
2842
function merge_ipv6_delegated_prefix($prefix, $suffix, $len = 64) {
2843
	$prefix = Net_IPv6::uncompress($prefix, true);
2844
	$suffix = Net_IPv6::uncompress($suffix, true);
2845

    
2846
	/*
2847
	 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
2848
	 *                ^^^^ ^
2849
	 *                |||| \-> 64
2850
	 *                |||\---> 63, 62, 61, 60
2851
	 *                ||\----> 56
2852
	 *                |\-----> 52
2853
	 *                \------> 48
2854
	 */
2855

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

    
2886
	return Net_IPv6::compress(substr($prefix, 0, $prefix_len) .
2887
	    substr($suffix, $prefix_len));
2888
}
2889

    
2890
function dhcpv6_pd_str_help($pdlen) {
2891
	$result = '';
2892

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

    
2923
	return $result;
2924
}
2925

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

    
2939
function huawei_mode_to_string($mode, $submode) {
2940
	$modes[0] = gettext("None");
2941
	$modes[1] = "AMPS";
2942
	$modes[2] = "CDMA";
2943
	$modes[3] = "GSM/GPRS";
2944
	$modes[4] = "HDR";
2945
	$modes[5] = "WCDMA";
2946
	$modes[6] = "GPS";
2947

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

    
2962
function huawei_service_to_string($state) {
2963
	$modes[0] = gettext("No Service");
2964
	$modes[1] = gettext("Restricted Service");
2965
	$modes[2] = gettext("Valid Service");
2966
	$modes[3] = gettext("Restricted Regional Service");
2967
	$modes[4] = gettext("Powersaving Service");
2968
	$string = $modes[$state];
2969
	return $string;
2970
}
2971

    
2972
function huawei_simstate_to_string($state) {
2973
	$modes[0] = gettext("Invalid SIM/locked State");
2974
	$modes[1] = gettext("Valid SIM State");
2975
	$modes[2] = gettext("Invalid SIM CS State");
2976
	$modes[3] = gettext("Invalid SIM PS State");
2977
	$modes[4] = gettext("Invalid SIM CS/PS State");
2978
	$modes[255] = gettext("Missing SIM State");
2979
	$string = $modes[$state];
2980
	return $string;
2981
}
2982

    
2983
function zte_rssi_to_string($rssi) {
2984
	return huawei_rssi_to_string($rssi);
2985
}
2986

    
2987
function zte_mode_to_string($mode, $submode) {
2988
	$modes[0] = gettext("No Service");
2989
	$modes[1] = gettext("Limited Service");
2990
	$modes[2] = "GPRS";
2991
	$modes[3] = "GSM";
2992
	$modes[4] = "UMTS";
2993
	$modes[5] = "EDGE";
2994
	$modes[6] = "HSDPA";
2995

    
2996
	$submodes[0] = "CS_ONLY";
2997
	$submodes[1] = "PS_ONLY";
2998
	$submodes[2] = "CS_PS";
2999
	$submodes[3] = "CAMPED";
3000
	$string = "{$modes[$mode]}, {$submodes[$submode]} " . gettext("Mode");
3001
	return $string;
3002
}
3003

    
3004
function zte_service_to_string($service) {
3005
	$modes[0] = gettext("Initializing Service");
3006
	$modes[1] = gettext("Network Lock error Service");
3007
	$modes[2] = gettext("Network Locked Service");
3008
	$modes[3] = gettext("Unlocked or correct MCC/MNC Service");
3009
	$string = $modes[$service];
3010
	return $string;
3011
}
3012

    
3013
function zte_simstate_to_string($state) {
3014
	$modes[0] = gettext("No action State");
3015
	$modes[1] = gettext("Network lock State");
3016
	$modes[2] = gettext("(U)SIM card lock State");
3017
	$modes[3] = gettext("Network Lock and (U)SIM card Lock State");
3018
	$string = $modes[$state];
3019
	return $string;
3020
}
3021

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

    
3036
function get_pppoes_child_interfaces($ifpattern) {
3037
	$if_arr = array();
3038
	if ($ifpattern == "") {
3039
		return;
3040
	}
3041

    
3042
	exec("/sbin/ifconfig", $out, $ret);
3043
	foreach ($out as $line) {
3044
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3045
			$if_arr[] = $match[1];
3046
		}
3047
	}
3048
	return $if_arr;
3049

    
3050
}
3051

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

    
3092
function restore_aliastables() {
3093
	global $g, $config;
3094

    
3095
	$dbpath = "{$g['vardb_path']}/aliastables/";
3096

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

    
3124
?>
(39-39/65)