Project

General

Profile

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
266
	return false;
267
}
268

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
441
	return "";
442
}
443

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

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

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

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

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

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

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

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

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

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

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

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

    
550
	return false;
551
}
552

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
995
	conf_mount_ro();
996
	return;
997
}
998

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

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

    
1008
	return true;
1009
}
1010

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

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

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

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

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

    
1040
	return false;
1041
}
1042

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

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

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

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

    
1065
	return false;
1066
}
1067

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

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

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

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

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

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

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

    
1098
		return true;
1099
	}
1100

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

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

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

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

    
1122
		return true;
1123
	}
1124

    
1125
	return false;
1126
}
1127

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

    
1132
	$pppoeenable = false;
1133

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

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

    
1144
	return $pppoeenable;
1145
}
1146

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1440
	return $ifinfo;
1441
}
1442

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1633
	return false;
1634
}
1635

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1863
/* Split() is being DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 6.0.0. Relying on this feature is highly discouraged. */
1864
if (!function_exists("split")) {
1865
	function split($separator, $haystack, $limit = null) {
1866
		log_error("deprecated split() call with separator '{$separator}'");
1867
		return preg_split($separator, $haystack, $limit);
1868
	}
1869
}
1870

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

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

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

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

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

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

    
1920
}
1921

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

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

    
1974
function update_alias_url_data() {
1975
	global $config, $g;
1976

    
1977
	$updated = false;
1978

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

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

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

    
2018
	/* Report status to callers as well */
2019
	return $updated;
2020
}
2021

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

    
2052
	return true;
2053
}
2054

    
2055
function version_compare_dates($a, $b) {
2056
	$a_time = strtotime($a);
2057
	$b_time = strtotime($b);
2058

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

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

    
2143
		// First try to compare the numeric parts of the version string.
2144
		$v = version_compare_numeric($cur_num, $rem_num);
2145

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

    
2156
	$urltable_prefix = "/var/db/aliastables/";
2157
	$urltable_filename = $urltable_prefix . $name . ".txt";
2158
	$tmp_urltable_filename = $urltable_filename . ".tmp";
2159

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

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

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

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

    
2183
			$parsed_contents = parse_aliases_file($tmp_urltable_filename, $type, "-1", true);
2184
			if ($type == "urltable_ports") {
2185
				$parsed_contents = group_ports($parsed_contents, true);
2186
			}
2187
			if (is_array($parsed_contents)) {
2188
				file_put_contents($urltable_filename, implode("\n", $parsed_contents));
2189
			}
2190

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

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

    
2238
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2239
		$slice = $TOFLASH;
2240
	} else {
2241
		$slice = $BOOTFLASH;
2242
	}
2243

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

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

    
2302
	mkdir($tmppath);
2303
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2304
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2305
	copy("/etc/fstab", $fstabpath);
2306

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

    
2323
	return $status;
2324
}
2325
function nanobsd_detect_slice_info() {
2326
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2327
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2328
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2329

    
2330
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2331
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2332
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2333
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2334

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

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

    
2356
function nanobsd_friendly_slice_name($slicename) {
2357
	global $g;
2358
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2359
}
2360

    
2361
function get_include_contents($filename) {
2362
	if (is_file($filename)) {
2363
		ob_start();
2364
		include $filename;
2365
		$contents = ob_get_contents();
2366
		ob_end_clean();
2367
		return $contents;
2368
	}
2369
	return false;
2370
}
2371

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

    
2484
function get_country_name($country_code) {
2485
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2486
		return "";
2487
	}
2488

    
2489
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2490
	$country_names_contents = file_get_contents($country_names_xml);
2491
	$country_names = xml2array($country_names_contents);
2492

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

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

    
2511
/* sort by interface only, retain the original order of rules that apply to
2512
   the same interface */
2513
function filter_rules_sort() {
2514
	global $config;
2515

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

    
2521
	usort($config['filter']['rule'], "filter_rules_compare");
2522

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

    
2542
function generate_ipv6_from_mac($mac) {
2543
	$elements = explode(":", $mac);
2544
	if (count($elements) <> 6) {
2545
		return false;
2546
	}
2547

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

    
2569
		$i++;
2570
	}
2571
	return $ipv6;
2572
}
2573

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

    
2600
}
2601

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

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

    
2641
	$where_configured = array();
2642

    
2643
	$pos = strpos($ignore_if, '_virtualip');
2644
	if ($pos !== false) {
2645
		$ignore_vip_id = substr($ignore_if, $pos+10);
2646
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2647
	} else {
2648
		$ignore_vip_id = -1;
2649
		$ignore_vip_if = $ignore_if;
2650
	}
2651

    
2652
	$isipv6 = is_ipaddrv6($ipaddr);
2653

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

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

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

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

    
2720
	return $where_configured;
2721
}
2722

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

    
2745
function set_language() {
2746
	global $config, $g;
2747

    
2748
	if (!empty($config['system']['language'])) {
2749
		$lang = $config['system']['language'];
2750
	} elseif (!empty($g['language'])) {
2751
		$lang = $g['language'];
2752
	}
2753
	$lang .= ".UTF-8";
2754

    
2755
	putenv("LANG={$lang}");
2756
	setlocale(LC_ALL, $lang);
2757
	textdomain("pfSense");
2758
	bindtextdomain("pfSense", "/usr/local/share/locale");
2759
	bind_textdomain_codeset("pfSense", $lang);
2760
}
2761

    
2762
function get_locale_list() {
2763
	$locales = array(
2764
		"en_US" => gettext("English"),
2765
		"pt_BR" => gettext("Portuguese (Brazil)"),
2766
		"tr" => gettext("Turkish"),
2767
	);
2768
	asort($locales);
2769
	return $locales;
2770
}
2771

    
2772
function return_hex_ipv4($ipv4) {
2773
	if (!is_ipaddrv4($ipv4)) {
2774
		return(false);
2775
	}
2776

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

    
2782
function convert_ipv6_to_128bit($ipv6) {
2783
	if (!is_ipaddrv6($ipv6)) {
2784
		return(false);
2785
	}
2786

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

    
2798
function convert_128bit_to_ipv6($ip6bin) {
2799
	if (strlen($ip6bin) <> 128) {
2800
		return(false);
2801
	}
2802

    
2803
	$ip6arr = array();
2804
	$ip6binarr = array();
2805
	$ip6binarr = str_split($ip6bin, 16);
2806
	foreach ($ip6binarr as $binpart) {
2807
		$ip6arr[] = dechex(bindec($binpart));
2808
	}
2809
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2810

    
2811
	return($ip6addr);
2812
}
2813

    
2814

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

    
2822
	if (!is_array($config['interfaces'][$if])) {
2823
		return false;
2824
	}
2825

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

    
2846
function merge_ipv6_delegated_prefix($prefix, $suffix, $len = 64) {
2847
	$prefix = Net_IPv6::uncompress($prefix, true);
2848
	$suffix = Net_IPv6::uncompress($suffix, true);
2849

    
2850
	/*
2851
	 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
2852
	 *                ^^^^ ^
2853
	 *                |||| \-> 64
2854
	 *                |||\---> 63, 62, 61, 60
2855
	 *                ||\----> 56
2856
	 *                |\-----> 52
2857
	 *                \------> 48
2858
	 */
2859

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

    
2890
	return Net_IPv6::compress(substr($prefix, 0, $prefix_len) .
2891
	    substr($suffix, $prefix_len));
2892
}
2893

    
2894
function dhcpv6_pd_str_help($pdlen) {
2895
	$result = '';
2896

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

    
2927
	return $result;
2928
}
2929

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

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

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

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

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

    
2987
function zte_rssi_to_string($rssi) {
2988
	return huawei_rssi_to_string($rssi);
2989
}
2990

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

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

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

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

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

    
3040
function get_pppoes_child_interfaces($ifpattern) {
3041
	$if_arr = array();
3042
	if ($ifpattern == "") {
3043
		return;
3044
	}
3045

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

    
3054
}
3055

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

    
3096
function restore_aliastables() {
3097
	global $g, $config;
3098

    
3099
	$dbpath = "{$g['vardb_path']}/aliastables/";
3100

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

    
3128
?>
(39-39/65)