Project

General

Profile

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
253
	return false;
254
}
255

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

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

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

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

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

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

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

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

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

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

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

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

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

    
409
	$interface = get_real_interface($interface);
410
	$carp_query = '';
411
	$_gb = exec("/sbin/ifconfig $interface | /usr/bin/grep -v grep | /usr/bin/grep carp: | /usr/bin/head -n 1", $carp_query);
412
	foreach ($carp_query as $int) {
413
		if (stripos($int, "MASTER")) {
414
			return "MASTER";
415
		}
416
		if (stripos($int, "BACKUP")) {
417
			return "BACKUP";
418
		}
419
		if (stripos($int, "INIT")) {
420
			return "INIT";
421
		}
422
	}
423
	return;
424
}
425

    
426
/*
427
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
428
 */
429
function get_pfsync_interface_status($pfsyncinterface) {
430
	if (!does_interface_exist($pfsyncinterface)) {
431
		return;
432
	}
433

    
434
	return exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/awk '/pfsync:/ {print \$5}'");
435
}
436

    
437
/*
438
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
439
 */
440
function add_rule_to_anchor($anchor, $rule, $label) {
441
	mwexec("echo " . escapeshellarg($rule) . " | /sbin/pfctl -a " . escapeshellarg($anchor) . ":" . escapeshellarg($label) . " -f -");
442
}
443

    
444
/*
445
 * remove_text_from_file
446
 * remove $text from file $file
447
 */
448
function remove_text_from_file($file, $text) {
449
	if (!file_exists($file) && !is_writable($file)) {
450
		return;
451
	}
452
	$filecontents = file_get_contents($file);
453
	$text = str_replace($text, "", $filecontents);
454
	@file_put_contents($file, $text);
455
}
456

    
457
/*
458
 *   after_sync_bump_adv_skew(): create skew values by 1S
459
 */
460
function after_sync_bump_adv_skew() {
461
	global $config, $g;
462
	$processed_skew = 1;
463
	$a_vip = &$config['virtualip']['vip'];
464
	foreach ($a_vip as $vipent) {
465
		if ($vipent['advskew'] <> "") {
466
			$processed_skew = 1;
467
			$vipent['advskew'] = $vipent['advskew']+1;
468
		}
469
	}
470
	if ($processed_skew == 1) {
471
		write_config(gettext("After synch increase advertising skew"));
472
	}
473
}
474

    
475
/*
476
 * get_filename_from_url($url): converts a url to its filename.
477
 */
478
function get_filename_from_url($url) {
479
	return basename($url);
480
}
481

    
482
/*
483
 *   get_dir: return an array of $dir
484
 */
485
function get_dir($dir) {
486
	$dir_array = array();
487
	$d = dir($dir);
488
	while (false !== ($entry = $d->read())) {
489
		array_push($dir_array, $entry);
490
	}
491
	$d->close();
492
	return $dir_array;
493
}
494

    
495
/****f* pfsense-utils/WakeOnLan
496
 * NAME
497
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
498
 * RESULT
499
 *   true/false - true if the operation was successful
500
 ******/
501
function WakeOnLan($addr, $mac) {
502
	$addr_byte = explode(':', $mac);
503
	$hw_addr = '';
504

    
505
	for ($a = 0; $a < 6; $a++) {
506
		$hw_addr .= chr(hexdec($addr_byte[$a]));
507
	}
508

    
509
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
510

    
511
	for ($a = 1; $a <= 16; $a++) {
512
		$msg .= $hw_addr;
513
	}
514

    
515
	// send it to the broadcast address using UDP
516
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
517
	if ($s == false) {
518
		log_error(gettext("Error creating socket!"));
519
		log_error(sprintf(gettext("Error code is '%1\$s' - %2\$s"), socket_last_error($s), socket_strerror(socket_last_error($s))));
520
	} else {
521
		// setting a broadcast option to socket:
522
		$opt_ret = socket_set_option($s, 1, 6, TRUE);
523
		if ($opt_ret < 0) {
524
			log_error(sprintf(gettext("setsockopt() failed, error: %s"), strerror($opt_ret)));
525
		}
526
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
527
		socket_close($s);
528
		log_error(sprintf(gettext('Magic Packet sent (%1$s) to {%2$s} MAC=%3$s'), $e, $addr, $mac));
529
		return true;
530
	}
531

    
532
	return false;
533
}
534

    
535
/*
536
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
537
 *					 Useful for finding paths and stripping file extensions.
538
 */
539
function reverse_strrchr($haystack, $needle) {
540
	if (!is_string($haystack)) {
541
		return;
542
	}
543
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1) : false;
544
}
545

    
546
/*
547
 *  backup_config_section($section): returns as an xml file string of
548
 *                                   the configuration section
549
 */
550
function backup_config_section($section_name) {
551
	global $config;
552
	$new_section = &$config[$section_name];
553
	/* generate configuration XML */
554
	$xmlconfig = dump_xml_config($new_section, $section_name);
555
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
556
	return $xmlconfig;
557
}
558

    
559
/*
560
 *  restore_config_section($section_name, new_contents): restore a configuration section,
561
 *                                                  and write the configuration out
562
 *                                                  to disk/cf.
563
 */
564
function restore_config_section($section_name, $new_contents) {
565
	global $config, $g;
566
	conf_mount_rw();
567
	$fout = fopen("{$g['tmp_path']}/tmpxml", "w");
568
	fwrite($fout, $new_contents);
569
	fclose($fout);
570

    
571
	$xml = parse_xml_config($g['tmp_path'] . "/tmpxml", null);
572
	if ($xml['pfsense']) {
573
		$xml = $xml['pfsense'];
574
	}
575
	else if ($xml['m0n0wall']) {
576
		$xml = $xml['m0n0wall'];
577
	}
578
	if ($xml[$section_name]) {
579
		$section_xml = $xml[$section_name];
580
	} else {
581
		$section_xml = -1;
582
	}
583

    
584
	@unlink($g['tmp_path'] . "/tmpxml");
585
	if ($section_xml === -1) {
586
		return false;
587
	}
588
	$config[$section_name] = &$section_xml;
589
	if (file_exists("{$g['tmp_path']}/config.cache")) {
590
		unlink("{$g['tmp_path']}/config.cache");
591
	}
592
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
593
	disable_security_checks();
594
	conf_mount_ro();
595
	return true;
596
}
597

    
598
/*
599
 *  merge_config_section($section_name, new_contents):   restore a configuration section,
600
 *                                                  and write the configuration out
601
 *                                                  to disk/cf.  But preserve the prior
602
 * 													structure if needed
603
 */
604
function merge_config_section($section_name, $new_contents) {
605
	global $config;
606
	conf_mount_rw();
607
	$fname = get_tmp_filename();
608
	$fout = fopen($fname, "w");
609
	fwrite($fout, $new_contents);
610
	fclose($fout);
611
	$section_xml = parse_xml_config($fname, $section_name);
612
	$config[$section_name] = $section_xml;
613
	unlink($fname);
614
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
615
	disable_security_checks();
616
	conf_mount_ro();
617
	return;
618
}
619

    
620
/*
621
 * http_post($server, $port, $url, $vars): does an http post to a web server
622
 *                                         posting the vars array.
623
 * written by nf@bigpond.net.au
624
 */
625
function http_post($server, $port, $url, $vars) {
626
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
627
	$urlencoded = "";
628
	while (list($key, $value) = each($vars)) {
629
		$urlencoded .= urlencode($key) . "=" . urlencode($value) . "&";
630
	}
631
	$urlencoded = substr($urlencoded, 0, -1);
632
	$content_length = strlen($urlencoded);
633
	$headers = "POST $url HTTP/1.1
634
Accept: */*
635
Accept-Language: en-au
636
Content-Type: application/x-www-form-urlencoded
637
User-Agent: $user_agent
638
Host: $server
639
Connection: Keep-Alive
640
Cache-Control: no-cache
641
Content-Length: $content_length
642

    
643
";
644

    
645
	$errno = "";
646
	$errstr = "";
647
	$fp = fsockopen($server, $port, $errno, $errstr);
648
	if (!$fp) {
649
		return false;
650
	}
651

    
652
	fputs($fp, $headers);
653
	fputs($fp, $urlencoded);
654

    
655
	$ret = "";
656
	while (!feof($fp)) {
657
		$ret .= fgets($fp, 1024);
658
	}
659
	fclose($fp);
660

    
661
	return $ret;
662
}
663

    
664
/*
665
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
666
 */
667
if (!function_exists('php_check_syntax')) {
668
	global $g;
669
	function php_check_syntax($code_to_check, &$errormessage) {
670
		return false;
671
		$fout = fopen("{$g['tmp_path']}/codetocheck.php", "w");
672
		$code = $_POST['content'];
673
		$code = str_replace("<?php", "", $code);
674
		$code = str_replace("?>", "", $code);
675
		fwrite($fout, "<?php\n\n");
676
		fwrite($fout, $code_to_check);
677
		fwrite($fout, "\n\n?>\n");
678
		fclose($fout);
679
		$command = "/usr/local/bin/php-cgi -l {$g['tmp_path']}/codetocheck.php";
680
		$output = exec_command($command);
681
		if (stristr($output, "Errors parsing") == false) {
682
			echo "false\n";
683
			$errormessage = '';
684
			return(false);
685
		} else {
686
			$errormessage = $output;
687
			return(true);
688
		}
689
	}
690
}
691

    
692
/*
693
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
694
 */
695
if (!function_exists('php_check_syntax')) {
696
	function php_check_syntax($code_to_check, &$errormessage) {
697
		return false;
698
		$command = "/usr/local/bin/php-cgi -l " . escapeshellarg($code_to_check);
699
		$output = exec_command($command);
700
		if (stristr($output, "Errors parsing") == false) {
701
			echo "false\n";
702
			$errormessage = '';
703
			return(false);
704
		} else {
705
			$errormessage = $output;
706
			return(true);
707
		}
708
	}
709
}
710

    
711
/*
712
 * rmdir_recursive($path, $follow_links=false)
713
 * Recursively remove a directory tree (rm -rf path)
714
 * This is for directories _only_
715
 */
716
function rmdir_recursive($path, $follow_links=false) {
717
	$to_do = glob($path);
718
	if (!is_array($to_do)) {
719
		$to_do = array($to_do);
720
	}
721
	foreach ($to_do as $workingdir) { // Handle wildcards by foreaching.
722
		if (file_exists($workingdir)) {
723
			if (is_dir($workingdir)) {
724
				$dir = opendir($workingdir);
725
				while ($entry = readdir($dir)) {
726
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry"))) {
727
						unlink("$workingdir/$entry");
728
					} elseif (is_dir("$workingdir/$entry") && $entry != '.' && $entry != '..') {
729
						rmdir_recursive("$workingdir/$entry");
730
					}
731
				}
732
				closedir($dir);
733
				rmdir($workingdir);
734
			} elseif (is_file($workingdir)) {
735
				unlink($workingdir);
736
			}
737
		}
738
	}
739
	return;
740
}
741

    
742
/*
743
 * call_pfsense_method(): Call a method exposed by the pfsense.org XMLRPC server.
744
 */
745
function call_pfsense_method($method, $params, $timeout = 0) {
746
	global $g, $config;
747

    
748
	$xmlrpc_base_url = get_active_xml_rpc_base_url();
749
	$xmlrpc_path = $g['xmlrpcpath'];
750

    
751
	$xmlrpcfqdn = preg_replace("(https?://)", "", $xmlrpc_base_url);
752
	$ip = gethostbyname($xmlrpcfqdn);
753
	if ($ip == $xmlrpcfqdn) {
754
		return false;
755
	}
756

    
757
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
758
	$port = 0;
759
	$proxyurl = "";
760
	$proxyport = 0;
761
	$proxyuser = "";
762
	$proxypass = "";
763
	if (!empty($config['system']['proxyurl'])) {
764
		$proxyurl = $config['system']['proxyurl'];
765
	}
766
	if (!empty($config['system']['proxyport']) && is_numeric($config['system']['proxyport'])) {
767
		$proxyport = $config['system']['proxyport'];
768
	}
769
	if (!empty($config['system']['proxyuser'])) {
770
		$proxyuser = $config['system']['proxyuser'];
771
	}
772
	if (!empty($config['system']['proxypass'])) {
773
		$proxypass = $config['system']['proxypass'];
774
	}
775
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url, $port, $proxyurl, $proxyport, $proxyuser, $proxypass);
776
	// If the ALT PKG Repo has a username/password set, use it.
777
	if ($config['system']['altpkgrepo']['username'] &&
778
	    $config['system']['altpkgrepo']['password']) {
779
		$username = $config['system']['altpkgrepo']['username'];
780
		$password = $config['system']['altpkgrepo']['password'];
781
		$cli->setCredentials($username, $password);
782
	}
783
	$resp = $cli->send($msg, $timeout);
784
	if (!is_object($resp)) {
785
		log_error(sprintf(gettext("XMLRPC communication error: %s"), $cli->errstr));
786
		return false;
787
	} elseif ($resp->faultCode()) {
788
		log_error(sprintf(gettext('XMLRPC request failed with error %1$s: %2$s'), $resp->faultCode(), $resp->faultString()));
789
		return false;
790
	} else {
791
		return XML_RPC_Decode($resp->value());
792
	}
793
}
794

    
795
/*
796
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
797
 */
798
function check_firmware_version($tocheck = "all", $return_php = true) {
799
	global $g, $config;
800

    
801
	$xmlrpc_base_url = get_active_xml_rpc_base_url();
802
	$xmlrpcfqdn = preg_replace("(https?://)", "", $xmlrpc_base_url);
803
	$ip = gethostbyname($xmlrpcfqdn);
804
	if ($ip == $xmlrpcfqdn) {
805
		return false;
806
	}
807
	$version = php_uname('r');
808
	$version = explode('-', $version);
809
	$rawparams = array("firmware" => array("version" => $g['product_version']),
810
		"kernel"   => array("version" => $version[0]),
811
		"base"     => array("version" => $version[0]),
812
		"platform" => trim(file_get_contents('/etc/platform')),
813
		"config_version" => $config['version']
814
		);
815
	unset($version);
816

    
817
	if ($tocheck == "all") {
818
		$params = $rawparams;
819
	} else {
820
		foreach ($tocheck as $check) {
821
			$params['check'] = $rawparams['check'];
822
			$params['platform'] = $rawparams['platform'];
823
		}
824
	}
825
	if ($config['system']['firmware']['branch']) {
826
		$params['branch'] = $config['system']['firmware']['branch'];
827
	}
828

    
829
	/* XXX: What is this method? */
830
	if (!($versions = call_pfsense_method('pfsense.get_firmware_version', $params))) {
831
		return false;
832
	} else {
833
		$versions["current"] = $params;
834
	}
835

    
836
	return $versions;
837
}
838

    
839
/*
840
 * host_firmware_version(): Return the versions used in this install
841
 */
842
function host_firmware_version($tocheck = "") {
843
	global $g, $config;
844

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

    
847
	return array(
848
		"firmware" => array("version" => $g['product_version']),
849
		"kernel"   => array("version" => $os_version),
850
		"base"     => array("version" => $os_version),
851
		"platform" => trim(file_get_contents('/etc/platform', " \n")),
852
		"config_version" => $config['version']
853
	);
854
}
855

    
856
function get_disk_info() {
857
	$diskout = "";
858
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
859
	return explode(' ', $diskout[0]);
860
}
861

    
862
/****f* pfsense-utils/strncpy
863
 * NAME
864
 *   strncpy - copy strings
865
 * INPUTS
866
 *   &$dst, $src, $length
867
 * RESULT
868
 *   none
869
 ******/
870
function strncpy(&$dst, $src, $length) {
871
	if (strlen($src) > $length) {
872
		$dst = substr($src, 0, $length);
873
	} else {
874
		$dst = $src;
875
	}
876
}
877

    
878
/****f* pfsense-utils/reload_interfaces_sync
879
 * NAME
880
 *   reload_interfaces - reload all interfaces
881
 * INPUTS
882
 *   none
883
 * RESULT
884
 *   none
885
 ******/
886
function reload_interfaces_sync() {
887
	global $config, $g;
888

    
889
	if ($g['debug']) {
890
		log_error(gettext("reload_interfaces_sync() is starting."));
891
	}
892

    
893
	/* parse config.xml again */
894
	$config = parse_config(true);
895

    
896
	/* enable routing */
897
	system_routing_enable();
898
	if ($g['debug']) {
899
		log_error(gettext("Enabling system routing"));
900
	}
901

    
902
	if ($g['debug']) {
903
		log_error(gettext("Cleaning up Interfaces"));
904
	}
905

    
906
	/* set up interfaces */
907
	interfaces_configure();
908
}
909

    
910
/****f* pfsense-utils/reload_all
911
 * NAME
912
 *   reload_all - triggers a reload of all settings
913
 *   * INPUTS
914
 *   none
915
 * RESULT
916
 *   none
917
 ******/
918
function reload_all() {
919
	send_event("service reload all");
920
}
921

    
922
/****f* pfsense-utils/reload_interfaces
923
 * NAME
924
 *   reload_interfaces - triggers a reload of all interfaces
925
 * INPUTS
926
 *   none
927
 * RESULT
928
 *   none
929
 ******/
930
function reload_interfaces() {
931
	send_event("interface all reload");
932
}
933

    
934
/****f* pfsense-utils/reload_all_sync
935
 * NAME
936
 *   reload_all - reload all settings
937
 *   * INPUTS
938
 *   none
939
 * RESULT
940
 *   none
941
 ******/
942
function reload_all_sync() {
943
	global $config, $g;
944

    
945
	/* parse config.xml again */
946
	$config = parse_config(true);
947

    
948
	/* set up our timezone */
949
	system_timezone_configure();
950

    
951
	/* set up our hostname */
952
	system_hostname_configure();
953

    
954
	/* make hosts file */
955
	system_hosts_generate();
956

    
957
	/* generate resolv.conf */
958
	system_resolvconf_generate();
959

    
960
	/* enable routing */
961
	system_routing_enable();
962

    
963
	/* set up interfaces */
964
	interfaces_configure();
965

    
966
	/* start dyndns service */
967
	services_dyndns_configure();
968

    
969
	/* configure cron service */
970
	configure_cron();
971

    
972
	/* start the NTP client */
973
	system_ntp_configure();
974

    
975
	/* sync pw database */
976
	conf_mount_rw();
977
	unlink_if_exists("/etc/spwd.db.tmp");
978
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
979
	conf_mount_ro();
980

    
981
	/* restart sshd */
982
	send_event("service restart sshd");
983

    
984
	/* restart webConfigurator if needed */
985
	send_event("service restart webgui");
986
}
987

    
988
function setup_serial_port($when = "save", $path = "") {
989
	global $g, $config;
990
	conf_mount_rw();
991
	$ttys_file = "{$path}/etc/ttys";
992
	$boot_config_file = "{$path}/boot.config";
993
	$loader_conf_file = "{$path}/boot/loader.conf";
994
	/* serial console - write out /boot.config */
995
	if (file_exists($boot_config_file)) {
996
		$boot_config = file_get_contents($boot_config_file);
997
	} else {
998
		$boot_config = "";
999
	}
1000

    
1001
	$serialspeed = (is_numeric($config['system']['serialspeed'])) ? $config['system']['serialspeed'] : "115200";
1002
	if ($g['platform'] != "cdrom") {
1003
		$serial_only = false;
1004

    
1005
		if (($g['platform'] == "nanobsd") && isset($g['enableserial_force'])) {
1006
			$serial_only = true;
1007
		} else {
1008
			$specific_platform = system_identify_specific_platform();
1009
			if ($specific_platform['name'] == 'RCC-VE' ||
1010
			    $specific_platform['name'] == 'RCC-DFF') {
1011
				$serial_only = true;
1012
			}
1013
		}
1014

    
1015
		$boot_config_split = explode("\n", $boot_config);
1016
		$fd = fopen($boot_config_file, "w");
1017
		if ($fd) {
1018
			foreach ($boot_config_split as $bcs) {
1019
				if (stristr($bcs, "-D") || stristr($bcs, "-h")) {
1020
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1021
				} else {
1022
					if ($bcs <> "") {
1023
						fwrite($fd, "{$bcs}\n");
1024
					}
1025
				}
1026
			}
1027
			if ($serial_only === true) {
1028
				fwrite($fd, "-S{$serialspeed} -h");
1029
			} else if (is_serial_enabled()) {
1030
				fwrite($fd, "-S{$serialspeed} -D");
1031
			}
1032
			fclose($fd);
1033
		}
1034

    
1035
		/* serial console - write out /boot/loader.conf */
1036
		if ($when == "upgrade") {
1037
			system("echo \"Reading {$loader_conf_file}...\" >> /conf/upgrade_log.txt");
1038
		}
1039
		$boot_config = file_get_contents($loader_conf_file);
1040
		$boot_config_split = explode("\n", $boot_config);
1041
		if (count($boot_config_split) > 0) {
1042
			$new_boot_config = array();
1043
			// Loop through and only add lines that are not empty, and which
1044
			//  do not contain a console directive.
1045
			foreach ($boot_config_split as $bcs) {
1046
				if (!empty($bcs) &&
1047
				    (stripos($bcs, "console") === false) &&
1048
				    (stripos($bcs, "boot_multicons") === false) &&
1049
				    (stripos($bcs, "boot_serial") === false) &&
1050
				    (stripos($bcs, "hw.usb.no_pf") === false) &&
1051
				    (stripos($bcs, "hint.uart.0.flags") === false) &&
1052
				    (stripos($bcs, "hint.uart.1.flags") === false)) {
1053
					$new_boot_config[] = $bcs;
1054
				}
1055
			}
1056

    
1057
			if ($serial_only === true) {
1058
				$new_boot_config[] = 'boot_serial="YES"';
1059
				$new_boot_config[] = 'console="comconsole"';
1060
			} else if (is_serial_enabled()) {
1061
				$new_boot_config[] = 'boot_multicons="YES"';
1062
				$new_boot_config[] = 'boot_serial="YES"';
1063
				$primaryconsole = isset($g['primaryconsole_force']) ? $g['primaryconsole_force'] : $config['system']['primaryconsole'];
1064
				switch ($primaryconsole) {
1065
					case "video":
1066
						$new_boot_config[] = 'console="vidconsole,comconsole"';
1067
						break;
1068
					case "serial":
1069
					default:
1070
						$new_boot_config[] = 'console="comconsole,vidconsole"';
1071
				}
1072
			}
1073
			$new_boot_config[] = 'comconsole_speed="' . $serialspeed . '"';
1074

    
1075
			$specplatform = system_identify_specific_platform();
1076
			if ($specplatform['name'] == 'RCC-VE' ||
1077
			    $specplatform['name'] == 'RCC-DFF') {
1078
				$new_boot_config[] = 'comconsole_port="0x2F8"';
1079
				$new_boot_config[] = 'hint.uart.0.flags="0x00"';
1080
				$new_boot_config[] = 'hint.uart.1.flags="0x10"';
1081
			}
1082
			$new_boot_config[] = 'hw.usb.no_pf="1"';
1083

    
1084
			file_put_contents($loader_conf_file, implode("\n", $new_boot_config) . "\n");
1085
		}
1086
	}
1087
	$ttys = file_get_contents($ttys_file);
1088
	$ttys_split = explode("\n", $ttys);
1089
	$fd = fopen($ttys_file, "w");
1090

    
1091
	$on_off = (is_serial_enabled() ? 'onifconsole' : 'off');
1092

    
1093
	if (isset($config['system']['disableconsolemenu'])) {
1094
		$console_type = 'Pc';
1095
		$serial_type = 'std.' . $serialspeed;
1096
	} else {
1097
		$console_type = 'al.Pc';
1098
		$serial_type = 'al.' . $serialspeed;
1099
	}
1100
	foreach ($ttys_split as $tty) {
1101
		if (stristr($tty, "ttyv0")) {
1102
			fwrite($fd, "ttyv0	\"/usr/libexec/getty {$console_type}\"	cons25	on	secure\n");
1103
		} else if (stristr($tty, "ttyu")) {
1104
			$ttyn = substr($tty, 0, 5);
1105
			fwrite($fd, "{$ttyn}	\"/usr/libexec/getty {$serial_type}\"	cons25	{$on_off}	secure\n");
1106
		} else {
1107
			fwrite($fd, $tty . "\n");
1108
		}
1109
	}
1110
	unset($on_off, $console_type, $serial_type);
1111
	fclose($fd);
1112
	if ($when != "upgrade") {
1113
		reload_ttys();
1114
	}
1115

    
1116
	conf_mount_ro();
1117
	return;
1118
}
1119

    
1120
function is_serial_enabled() {
1121
	global $g, $config;
1122

    
1123
	if (!isset($g['enableserial_force']) &&
1124
	    !isset($config['system']['enableserial']) &&
1125
	    ($g['platform'] == "pfSense" || $g['platform'] == "cdrom")) {
1126
		return false;
1127
	}
1128

    
1129
	return true;
1130
}
1131

    
1132
function reload_ttys() {
1133
	// Send a HUP signal to init will make it reload /etc/ttys
1134
	posix_kill(1, SIGHUP);
1135
}
1136

    
1137
function print_value_list($list, $count = 10, $separator = ",") {
1138
	$list = implode($separator, array_slice($list, 0, $count));
1139
	if (count($list) < $count) {
1140
		$list .= ".";
1141
	} else {
1142
		$list .= "...";
1143
	}
1144
	return $list;
1145
}
1146

    
1147
/* DHCP enabled on any interfaces? */
1148
function is_dhcp_server_enabled() {
1149
	global $config;
1150

    
1151
	if (!is_array($config['dhcpd'])) {
1152
		return false;
1153
	}
1154

    
1155
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1156
		if (isset($dhcpifconf['enable']) && !empty($config['interfaces'][$dhcpif])) {
1157
			return true;
1158
		}
1159
	}
1160

    
1161
	return false;
1162
}
1163

    
1164
/* DHCP enabled on any interfaces? */
1165
function is_dhcpv6_server_enabled() {
1166
	global $config;
1167

    
1168
	if (is_array($config['interfaces'])) {
1169
		foreach ($config['interfaces'] as $ifcfg) {
1170
			if (isset($ifcfg['enable']) && !empty($ifcfg['track6-interface'])) {
1171
				return true;
1172
			}
1173
		}
1174
	}
1175

    
1176
	if (!is_array($config['dhcpdv6'])) {
1177
		return false;
1178
	}
1179

    
1180
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
1181
		if (isset($dhcpv6ifconf['enable']) && !empty($config['interfaces'][$dhcpv6if])) {
1182
			return true;
1183
		}
1184
	}
1185

    
1186
	return false;
1187
}
1188

    
1189
/* radvd enabled on any interfaces? */
1190
function is_radvd_enabled() {
1191
	global $config;
1192

    
1193
	if (!is_array($config['dhcpdv6'])) {
1194
		$config['dhcpdv6'] = array();
1195
	}
1196

    
1197
	$dhcpdv6cfg = $config['dhcpdv6'];
1198
	$Iflist = get_configured_interface_list();
1199

    
1200
	/* handle manually configured DHCP6 server settings first */
1201
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1202
		if (!isset($config['interfaces'][$dhcpv6if]['enable'])) {
1203
			continue;
1204
		}
1205

    
1206
		if (!isset($dhcpv6ifconf['ramode'])) {
1207
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
1208
		}
1209

    
1210
		if ($dhcpv6ifconf['ramode'] == "disabled") {
1211
			continue;
1212
		}
1213

    
1214
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1215
		if (!is_ipaddrv6($ifcfgipv6)) {
1216
			continue;
1217
		}
1218

    
1219
		return true;
1220
	}
1221

    
1222
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
1223
	foreach ($Iflist as $if => $ifdescr) {
1224
		if (!isset($config['interfaces'][$if]['track6-interface'])) {
1225
			continue;
1226
		}
1227
		if (!isset($config['interfaces'][$if]['enable'])) {
1228
			continue;
1229
		}
1230

    
1231
		$ifcfgipv6 = get_interface_ipv6($if);
1232
		if (!is_ipaddrv6($ifcfgipv6)) {
1233
			continue;
1234
		}
1235

    
1236
		$ifcfgsnv6 = get_interface_subnetv6($if);
1237
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1238

    
1239
		if (!is_ipaddrv6($subnetv6)) {
1240
			continue;
1241
		}
1242

    
1243
		return true;
1244
	}
1245

    
1246
	return false;
1247
}
1248

    
1249
/* Any PPPoE servers enabled? */
1250
function is_pppoe_server_enabled() {
1251
	global $config;
1252

    
1253
	$pppoeenable = false;
1254

    
1255
	if (!is_array($config['pppoes']) || !is_array($config['pppoes']['pppoe'])) {
1256
		return false;
1257
	}
1258

    
1259
	foreach ($config['pppoes']['pppoe'] as $pppoes) {
1260
		if ($pppoes['mode'] == 'server') {
1261
			$pppoeenable = true;
1262
		}
1263
	}
1264

    
1265
	return $pppoeenable;
1266
}
1267

    
1268
function convert_seconds_to_hms($sec) {
1269
	$min = $hrs = 0;
1270
	if ($sec != 0) {
1271
		$min = floor($sec/60);
1272
		$sec %= 60;
1273
	}
1274
	if ($min != 0) {
1275
		$hrs = floor($min/60);
1276
		$min %= 60;
1277
	}
1278
	if ($sec < 10) {
1279
		$sec = "0".$sec;
1280
	}
1281
	if ($min < 10) {
1282
		$min = "0".$min;
1283
	}
1284
	if ($hrs < 10) {
1285
		$hrs = "0".$hrs;
1286
	}
1287
	$result = $hrs.":".$min.":".$sec;
1288
	return $result;
1289
}
1290

    
1291
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1292

    
1293
function get_ppp_uptime($port) {
1294
	if (file_exists("/conf/{$port}.log")) {
1295
		$saved_time = file_get_contents("/conf/{$port}.log");
1296
		$uptime_data = explode("\n", $saved_time);
1297
		$sec = 0;
1298
		foreach ($uptime_data as $upt) {
1299
			$sec += substr($upt, 1 + strpos($upt, " "));
1300
		}
1301
		return convert_seconds_to_hms($sec);
1302
	} else {
1303
		$total_time = gettext("No history data found!");
1304
		return $total_time;
1305
	}
1306
}
1307

    
1308
//returns interface information
1309
function get_interface_info($ifdescr) {
1310
	global $config, $g;
1311

    
1312
	$ifinfo = array();
1313
	if (empty($config['interfaces'][$ifdescr])) {
1314
		return;
1315
	}
1316
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
1317
	$ifinfo['if'] = get_real_interface($ifdescr);
1318

    
1319
	$chkif = $ifinfo['if'];
1320
	$ifinfotmp = pfSense_get_interface_addresses($chkif);
1321
	$ifinfo['status'] = $ifinfotmp['status'];
1322
	if (empty($ifinfo['status'])) {
1323
		$ifinfo['status'] = "down";
1324
	}
1325
	$ifinfo['macaddr'] = $ifinfotmp['macaddr'];
1326
	$ifinfo['mtu'] = $ifinfotmp['mtu'];
1327
	$ifinfo['ipaddr'] = $ifinfotmp['ipaddr'];
1328
	$ifinfo['subnet'] = $ifinfotmp['subnet'];
1329
	$ifinfo['linklocal'] = get_interface_linklocal($ifdescr);
1330
	$ifinfo['ipaddrv6'] = get_interface_ipv6($ifdescr);
1331
	$ifinfo['subnetv6'] = get_interface_subnetv6($ifdescr);
1332
	if (isset($ifinfotmp['link0'])) {
1333
		$link0 = "down";
1334
	}
1335
	$ifinfotmp = pfSense_get_interface_stats($chkif);
1336
	// $ifinfo['inpkts'] = $ifinfotmp['inpkts'];
1337
	// $ifinfo['outpkts'] = $ifinfotmp['outpkts'];
1338
	$ifinfo['inerrs'] = $ifinfotmp['inerrs'];
1339
	$ifinfo['outerrs'] = $ifinfotmp['outerrs'];
1340
	$ifinfo['collisions'] = $ifinfotmp['collisions'];
1341

    
1342
	/* Use pfctl for non wrapping 64 bit counters */
1343
	/* Pass */
1344
	exec("/sbin/pfctl -vvsI -i {$chkif}", $pfctlstats);
1345
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1346
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1347
	$pf_in6_pass = preg_split("/ +/ ", $pfctlstats[7]);
1348
	$pf_out6_pass = preg_split("/ +/", $pfctlstats[9]);
1349
	$in4_pass = $pf_in4_pass[5];
1350
	$out4_pass = $pf_out4_pass[5];
1351
	$in4_pass_packets = $pf_in4_pass[3];
1352
	$out4_pass_packets = $pf_out4_pass[3];
1353
	$in6_pass = $pf_in6_pass[5];
1354
	$out6_pass = $pf_out6_pass[5];
1355
	$in6_pass_packets = $pf_in6_pass[3];
1356
	$out6_pass_packets = $pf_out6_pass[3];
1357
	$ifinfo['inbytespass'] = $in4_pass + $in6_pass;
1358
	$ifinfo['outbytespass'] = $out4_pass + $out6_pass;
1359
	$ifinfo['inpktspass'] = $in4_pass_packets + $in6_pass_packets;
1360
	$ifinfo['outpktspass'] = $out4_pass_packets + $out6_pass_packets;
1361

    
1362
	/* Block */
1363
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1364
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1365
	$pf_in6_block = preg_split("/ +/", $pfctlstats[8]);
1366
	$pf_out6_block = preg_split("/ +/", $pfctlstats[10]);
1367
	$in4_block = $pf_in4_block[5];
1368
	$out4_block = $pf_out4_block[5];
1369
	$in4_block_packets = $pf_in4_block[3];
1370
	$out4_block_packets = $pf_out4_block[3];
1371
	$in6_block = $pf_in6_block[5];
1372
	$out6_block = $pf_out6_block[5];
1373
	$in6_block_packets = $pf_in6_block[3];
1374
	$out6_block_packets = $pf_out6_block[3];
1375
	$ifinfo['inbytesblock'] = $in4_block + $in6_block;
1376
	$ifinfo['outbytesblock'] = $out4_block + $out6_block;
1377
	$ifinfo['inpktsblock'] = $in4_block_packets + $in6_block_packets;
1378
	$ifinfo['outpktsblock'] = $out4_block_packets + $out6_block_packets;
1379

    
1380
	$ifinfo['inbytes'] = $in4_pass + $in6_pass;
1381
	$ifinfo['outbytes'] = $out4_pass + $out6_pass;
1382
	$ifinfo['inpkts'] = $in4_pass_packets + $in6_pass_packets;
1383
	$ifinfo['outpkts'] = $out4_pass_packets + $out6_pass_packets;
1384

    
1385
	$ifconfiginfo = "";
1386
	$link_type = $config['interfaces'][$ifdescr]['ipaddr'];
1387
	switch ($link_type) {
1388
		/* DHCP? -> see if dhclient is up */
1389
		case "dhcp":
1390
			/* see if dhclient is up */
1391
			if (find_dhclient_process($ifinfo['if']) != 0) {
1392
				$ifinfo['dhcplink'] = "up";
1393
			} else {
1394
				$ifinfo['dhcplink'] = "down";
1395
			}
1396

    
1397
			break;
1398
		/* PPPoE/PPTP/L2TP interface? -> get status from virtual interface */
1399
		case "pppoe":
1400
		case "pptp":
1401
		case "l2tp":
1402
			if ($ifinfo['status'] == "up" && !isset($link0)) {
1403
				/* get PPPoE link status for dial on demand */
1404
				$ifinfo["{$link_type}link"] = "up";
1405
			} else {
1406
				$ifinfo["{$link_type}link"] = "down";
1407
			}
1408

    
1409
			break;
1410
		/* PPP interface? -> get uptime for this session and cumulative uptime from the persistent log file in conf */
1411
		case "ppp":
1412
			if ($ifinfo['status'] == "up") {
1413
				$ifinfo['ppplink'] = "up";
1414
			} else {
1415
				$ifinfo['ppplink'] = "down" ;
1416
			}
1417

    
1418
			if (empty($ifinfo['status'])) {
1419
				$ifinfo['status'] = "down";
1420
			}
1421

    
1422
			if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1423
				foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1424
					if ($config['interfaces'][$ifdescr]['if'] == $ppp['if']) {
1425
						break;
1426
					}
1427
				}
1428
			}
1429
			$dev = $ppp['ports'];
1430
			if ($config['interfaces'][$ifdescr]['if'] != $ppp['if'] || empty($dev)) {
1431
				break;
1432
			}
1433
			if (!file_exists($dev)) {
1434
				$ifinfo['nodevice'] = 1;
1435
				$ifinfo['pppinfo'] = $dev . " " . gettext("device not present! Is the modem attached to the system?");
1436
			}
1437

    
1438
			$usbmodemoutput = array();
1439
			exec("usbconfig", $usbmodemoutput);
1440
			$mondev = "{$g['tmp_path']}/3gstats.{$ifdescr}";
1441
			if (file_exists($mondev)) {
1442
				$cellstats = file($mondev);
1443
				/* skip header */
1444
				$a_cellstats = explode(",", $cellstats[1]);
1445
				if (preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1446
					$ifinfo['cell_rssi'] = huawei_rssi_to_string($a_cellstats[1]);
1447
					$ifinfo['cell_mode'] = huawei_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1448
					$ifinfo['cell_simstate'] = huawei_simstate_to_string($a_cellstats[10]);
1449
					$ifinfo['cell_service'] = huawei_service_to_string(trim($a_cellstats[11]));
1450
				}
1451
				if (preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1452
					$ifinfo['cell_rssi'] = zte_rssi_to_string($a_cellstats[1]);
1453
					$ifinfo['cell_mode'] = zte_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1454
					$ifinfo['cell_simstate'] = zte_simstate_to_string($a_cellstats[10]);
1455
					$ifinfo['cell_service'] = zte_service_to_string(trim($a_cellstats[11]));
1456
				}
1457
				$ifinfo['cell_upstream'] = $a_cellstats[4];
1458
				$ifinfo['cell_downstream'] = trim($a_cellstats[5]);
1459
				$ifinfo['cell_sent'] = $a_cellstats[6];
1460
				$ifinfo['cell_received'] = trim($a_cellstats[7]);
1461
				$ifinfo['cell_bwupstream'] = $a_cellstats[8];
1462
				$ifinfo['cell_bwdownstream'] = trim($a_cellstats[9]);
1463
			}
1464
			// Calculate cumulative uptime for PPP link. Useful for connections that have per minute/hour contracts so you don't go over!
1465
			if (isset($ppp['uptime'])) {
1466
				$ifinfo['ppp_uptime_accumulated'] = "(".get_ppp_uptime($ifinfo['if']).")";
1467
			}
1468
			break;
1469
		default:
1470
			break;
1471
	}
1472

    
1473
	if (file_exists("{$g['varrun_path']}/{$link_type}_{$ifdescr}.pid")) {
1474
		$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1475
		$ifinfo['ppp_uptime'] = convert_seconds_to_hms($sec);
1476
	}
1477

    
1478
	if ($ifinfo['status'] == "up") {
1479
		/* try to determine media with ifconfig */
1480
		unset($ifconfiginfo);
1481
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1482
		$wifconfiginfo = array();
1483
		if (is_interface_wireless($ifdescr)) {
1484
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1485
			array_shift($wifconfiginfo);
1486
		}
1487
		$matches = "";
1488
		foreach ($ifconfiginfo as $ici) {
1489

    
1490
			/* don't list media/speed for wireless cards, as it always
1491
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1492
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1493
				$ifinfo['media'] = $matches[1];
1494
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1495
				$ifinfo['media'] = $matches[1];
1496
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1497
				$ifinfo['media'] = $matches[1];
1498
			}
1499

    
1500
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
1501
				if ($matches[1] != "active") {
1502
					$ifinfo['status'] = $matches[1];
1503
				}
1504
				if ($ifinfo['status'] == gettext("running")) {
1505
					$ifinfo['status'] = gettext("up");
1506
				}
1507
			}
1508
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
1509
				$ifinfo['channel'] = $matches[1];
1510
			}
1511
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
1512
				if ($matches[1][0] == '"') {
1513
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
1514
				}
1515
				else {
1516
					$ifinfo['ssid'] = $matches[1];
1517
				}
1518
			}
1519
			if (preg_match("/laggproto (.*)$/", $ici, $matches)) {
1520
				$ifinfo['laggproto'] = $matches[1];
1521
			}
1522
			if (preg_match("/laggport: (.*)$/", $ici, $matches)) {
1523
				$ifinfo['laggport'][] = $matches[1];
1524
			}
1525
		}
1526
		foreach ($wifconfiginfo as $ici) {
1527
			$elements = preg_split("/[ ]+/i", $ici);
1528
			if ($elements[0] != "") {
1529
				$ifinfo['bssid'] = $elements[0];
1530
			}
1531
			if ($elements[3] != "") {
1532
				$ifinfo['rate'] = $elements[3];
1533
			}
1534
			if ($elements[4] != "") {
1535
				$ifinfo['rssi'] = $elements[4];
1536
			}
1537
		}
1538
		/* lookup the gateway */
1539
		if (interface_has_gateway($ifdescr)) {
1540
			$ifinfo['gateway'] = get_interface_gateway($ifdescr);
1541
			$ifinfo['gatewayv6'] = get_interface_gateway_v6($ifdescr);
1542
		}
1543
	}
1544

    
1545
	$bridge = "";
1546
	$bridge = link_interface_to_bridge($ifdescr);
1547
	if ($bridge) {
1548
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1549
		if (stristr($bridge_text, "blocking") <> false) {
1550
			$ifinfo['bridge'] = "<b><font color='red'>" . gettext("blocking") . "</font></b> - " . gettext("check for ethernet loops");
1551
			$ifinfo['bridgeint'] = $bridge;
1552
		} else if (stristr($bridge_text, "learning") <> false) {
1553
			$ifinfo['bridge'] = gettext("learning");
1554
			$ifinfo['bridgeint'] = $bridge;
1555
		} else if (stristr($bridge_text, "forwarding") <> false) {
1556
			$ifinfo['bridge'] = gettext("forwarding");
1557
			$ifinfo['bridgeint'] = $bridge;
1558
		}
1559
	}
1560

    
1561
	return $ifinfo;
1562
}
1563

    
1564
//returns cpu speed of processor. Good for determining capabilities of machine
1565
function get_cpu_speed() {
1566
	return get_single_sysctl("hw.clockrate");
1567
}
1568

    
1569
function get_uptime_sec() {
1570
	$boottime = "";
1571
	$matches = "";
1572
	$boottime = get_single_sysctl("kern.boottime");
1573
	preg_match("/sec = (\d+)/", $boottime, $matches);
1574
	$boottime = $matches[1];
1575
	if (intval($boottime) == 0) {
1576
		return 0;
1577
	}
1578

    
1579
	$uptime = time() - $boottime;
1580
	return $uptime;
1581
}
1582

    
1583
function add_hostname_to_watch($hostname) {
1584
	if (!is_dir("/var/db/dnscache")) {
1585
		mkdir("/var/db/dnscache");
1586
	}
1587
	$result = array();
1588
	if ((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1589
		$domrecords = array();
1590
		$domips = array();
1591
		exec("host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1592
		if ($rethost == 0) {
1593
			foreach ($domrecords as $domr) {
1594
				$doml = explode(" ", $domr);
1595
				$domip = $doml[3];
1596
				/* fill array with domain ip addresses */
1597
				if (is_ipaddr($domip)) {
1598
					$domips[] = $domip;
1599
				}
1600
			}
1601
		}
1602
		sort($domips);
1603
		$contents = "";
1604
		if (!empty($domips)) {
1605
			foreach ($domips as $ip) {
1606
				$contents .= "$ip\n";
1607
			}
1608
		}
1609
		file_put_contents("/var/db/dnscache/$hostname", $contents);
1610
		/* Remove empty elements */
1611
		$result = array_filter(explode("\n", $contents), 'strlen');
1612
	}
1613
	return $result;
1614
}
1615

    
1616
function is_fqdn($fqdn) {
1617
	$hostname = false;
1618
	if (preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1619
		$hostname = true;
1620
	}
1621
	if (preg_match("/\.\./", $fqdn)) {
1622
		$hostname = false;
1623
	}
1624
	if (preg_match("/^\./i", $fqdn)) {
1625
		$hostname = false;
1626
	}
1627
	if (preg_match("/\//i", $fqdn)) {
1628
		$hostname = false;
1629
	}
1630
	return($hostname);
1631
}
1632

    
1633
function pfsense_default_state_size() {
1634
	/* get system memory amount */
1635
	$memory = get_memory();
1636
	$physmem = $memory[0];
1637
	/* Be cautious and only allocate 10% of system memory to the state table */
1638
	$max_states = (int) ($physmem/10)*1000;
1639
	return $max_states;
1640
}
1641

    
1642
function pfsense_default_tables_size() {
1643
	$current = `pfctl -sm | grep ^tables | awk '{print $4};'`;
1644
	return $current;
1645
}
1646

    
1647
function pfsense_default_table_entries_size() {
1648
	$current = `pfctl -sm | grep table-entries | awk '{print $4};'`;
1649
	return $current;
1650
}
1651

    
1652
/* Compare the current hostname DNS to the DNS cache we made
1653
 * if it has changed we return the old records
1654
 * if no change we return false */
1655
function compare_hostname_to_dnscache($hostname) {
1656
	if (!is_dir("/var/db/dnscache")) {
1657
		mkdir("/var/db/dnscache");
1658
	}
1659
	$hostname = trim($hostname);
1660
	if (is_readable("/var/db/dnscache/{$hostname}")) {
1661
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
1662
	} else {
1663
		$oldcontents = "";
1664
	}
1665
	if ((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1666
		$domrecords = array();
1667
		$domips = array();
1668
		exec("host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1669
		if ($rethost == 0) {
1670
			foreach ($domrecords as $domr) {
1671
				$doml = explode(" ", $domr);
1672
				$domip = $doml[3];
1673
				/* fill array with domain ip addresses */
1674
				if (is_ipaddr($domip)) {
1675
					$domips[] = $domip;
1676
				}
1677
			}
1678
		}
1679
		sort($domips);
1680
		$contents = "";
1681
		if (!empty($domips)) {
1682
			foreach ($domips as $ip) {
1683
				$contents .= "$ip\n";
1684
			}
1685
		}
1686
	}
1687

    
1688
	if (trim($oldcontents) != trim($contents)) {
1689
		if ($g['debug']) {
1690
			log_error(sprintf(gettext('DNSCACHE: Found old IP %1$s and new IP %2$s'), $oldcontents, $contents));
1691
		}
1692
		return ($oldcontents);
1693
	} else {
1694
		return false;
1695
	}
1696
}
1697

    
1698
/*
1699
 * load_crypto() - Load crypto modules if enabled in config.
1700
 */
1701
function load_crypto() {
1702
	global $config, $g;
1703
	$crypto_modules = array('glxsb', 'aesni');
1704

    
1705
	if (!in_array($config['system']['crypto_hardware'], $crypto_modules)) {
1706
		return false;
1707
	}
1708

    
1709
	if (!empty($config['system']['crypto_hardware']) && !is_module_loaded($config['system']['crypto_hardware'])) {
1710
		log_error("Loading {$config['system']['crypto_hardware']} cryptographic accelerator module.");
1711
		mwexec("/sbin/kldload {$config['system']['crypto_hardware']}");
1712
	}
1713
}
1714

    
1715
/*
1716
 * load_thermal_hardware() - Load temperature monitor kernel module
1717
 */
1718
function load_thermal_hardware() {
1719
	global $config, $g;
1720
	$thermal_hardware_modules = array('coretemp', 'amdtemp');
1721

    
1722
	if (!in_array($config['system']['thermal_hardware'], $thermal_hardware_modules)) {
1723
		return false;
1724
	}
1725

    
1726
	if (!empty($config['system']['thermal_hardware']) && !is_module_loaded($config['system']['thermal_hardware'])) {
1727
		log_error("Loading {$config['system']['thermal_hardware']} thermal monitor module.");
1728
		mwexec("/sbin/kldload {$config['system']['thermal_hardware']}");
1729
	}
1730
}
1731

    
1732
/****f* pfsense-utils/isvm
1733
 * NAME
1734
 *   isvm
1735
 * INPUTS
1736
 *	none
1737
 * RESULT
1738
 *   returns true if machine is running under a virtual environment
1739
 ******/
1740
function isvm() {
1741
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86", "VirtualBox");
1742
	$_gb = exec('/bin/kenv smbios.system.product 2>/dev/null', $output, $rc);
1743

    
1744
	if ($rc != 0 || !isset($output[0])) {
1745
		return false;
1746
	}
1747

    
1748
	foreach ($virtualenvs as $virtualenv) {
1749
		if (stripos($output[0], $virtualenv) !== false) {
1750
			return true;
1751
		}
1752
	}
1753

    
1754
	return false;
1755
}
1756

    
1757
function get_freebsd_version() {
1758
	$version = explode(".", php_uname("r"));
1759
	return $version[0];
1760
}
1761

    
1762
function download_file($url, $destination, $verify_ssl = true, $connect_timeout = 5, $timeout = 0) {
1763
	global $config, $g;
1764

    
1765
	$fp = fopen($destination, "wb");
1766

    
1767
	if (!$fp) {
1768
		return false;
1769
	}
1770

    
1771
	$ch = curl_init();
1772
	curl_setopt($ch, CURLOPT_URL, $url);
1773
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1774
	curl_setopt($ch, CURLOPT_FILE, $fp);
1775
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1776
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1777
	curl_setopt($ch, CURLOPT_HEADER, false);
1778
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1779
	if (!isset($config['system']['host_uuid'])) {
1780
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1781
	} else {
1782
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1783
	}
1784

    
1785
	if (!empty($config['system']['proxyurl'])) {
1786
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1787
		if (!empty($config['system']['proxyport'])) {
1788
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1789
		}
1790
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1791
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1792
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1793
		}
1794
	}
1795

    
1796
	@curl_exec($ch);
1797
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1798
	fclose($fp);
1799
	curl_close($ch);
1800
	return ($http_code == 200) ? true : $http_code;
1801
}
1802

    
1803
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body', $connect_timeout = 5, $timeout = 0) {
1804
	global $config, $g;
1805
	global $ch, $fout, $file_size, $downloaded, $config, $first_progress_update;
1806
	$file_size = 1;
1807
	$downloaded = 1;
1808
	$first_progress_update = TRUE;
1809
	/* open destination file */
1810
	$fout = fopen($destination_file, "wb");
1811

    
1812
	/*
1813
	 *      Originally by Author: Keyvan Minoukadeh
1814
	 *      Modified by Scott Ullrich to return Content-Length size
1815
	 */
1816

    
1817
	$ch = curl_init();
1818
	curl_setopt($ch, CURLOPT_URL, $url_file);
1819
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1820
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1821
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1822
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1823
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1824
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1825
	if (!isset($config['system']['host_uuid'])) {
1826
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1827
	} else {
1828
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1829
	}
1830

    
1831
	if (!empty($config['system']['proxyurl'])) {
1832
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1833
		if (!empty($config['system']['proxyport'])) {
1834
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1835
		}
1836
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1837
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1838
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1839
		}
1840
	}
1841

    
1842
	@curl_exec($ch);
1843
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1844
	if ($fout) {
1845
		fclose($fout);
1846
	}
1847
	curl_close($ch);
1848
	return ($http_code == 200) ? true : $http_code;
1849
}
1850

    
1851
function read_header($ch, $string) {
1852
	global $file_size, $fout;
1853
	$length = strlen($string);
1854
	$regs = "";
1855
	preg_match("/(Content-Length:) (.*)/", $string, $regs);
1856
	if ($regs[2] <> "") {
1857
		$file_size = intval($regs[2]);
1858
	}
1859
	ob_flush();
1860
	return $length;
1861
}
1862

    
1863
function read_body($ch, $string) {
1864
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen, $first_progress_update;
1865
	global $pkg_interface;
1866
	$length = strlen($string);
1867
	$downloaded += intval($length);
1868
	if ($file_size > 0) {
1869
		$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1870
		$downloadProgress = 100 - $downloadProgress;
1871
	} else {
1872
		$downloadProgress = 0;
1873
	}
1874
	if ($lastseen <> $downloadProgress and $downloadProgress < 101) {
1875
		if ($sendto == "status") {
1876
			if ($pkg_interface == "console") {
1877
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1878
					$tostatus = $static_status . $downloadProgress . "%";
1879
					if ($downloadProgress == 100) {
1880
						$tostatus = $tostatus . "\r";
1881
					}
1882
					update_status($tostatus);
1883
				}
1884
			} else {
1885
				$tostatus = $static_status . $downloadProgress . "%";
1886
				update_status($tostatus);
1887
			}
1888
		} else {
1889
			if ($pkg_interface == "console") {
1890
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1891
					$tooutput = $static_output . $downloadProgress . "%";
1892
					if ($downloadProgress == 100) {
1893
						$tooutput = $tooutput . "\r";
1894
					}
1895
					update_output_window($tooutput);
1896
				}
1897
			} else {
1898
				$tooutput = $static_output . $downloadProgress . "%";
1899
				update_output_window($tooutput);
1900
			}
1901
		}
1902
		if (($pkg_interface != "console") || (($downloadProgress % 10) == 0) || ($downloadProgress < 10)) {
1903
			update_progress_bar($downloadProgress, $first_progress_update);
1904
			$first_progress_update = FALSE;
1905
		}
1906
		$lastseen = $downloadProgress;
1907
	}
1908
	if ($fout) {
1909
		fwrite($fout, $string);
1910
	}
1911
	ob_flush();
1912
	return $length;
1913
}
1914

    
1915
/*
1916
 *   update_output_window: update bottom textarea dynamically.
1917
 */
1918
function update_output_window($text) {
1919
	global $pkg_interface;
1920
	$log = preg_replace("/\n/", "\\n", $text);
1921
	if ($pkg_interface != "console") {
1922
?>
1923
<script>
1924
	document.getElementById("output").textContent="<?=htmlspecialchars($log)?>";
1925
	document.getElementById("output").scrollTop = document.getElementById("output").scrollHeight;
1926
</script>
1927
<?php
1928
	}
1929
	/* ensure that contents are written out */
1930
	ob_flush();
1931
}
1932

    
1933
/*
1934
 *   update_status: update top textarea dynamically.
1935
 */
1936
function update_status($status) {
1937
	global $pkg_interface;
1938
	if ($pkg_interface == "console") {
1939
		echo "\r{$status}";
1940
	} else {
1941
		echo '<script>document.getElementById("status").innerText="'. htmlspecialchars($status).'";</script>';
1942
	}
1943

    
1944
	/* ensure that contents are written out */
1945
	ob_flush();
1946
}
1947

    
1948
/*
1949
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
1950
 */
1951
function update_progress_bar($percent, $first_time) {
1952
	global $pkg_interface;
1953
	if ($percent > 100) {
1954
		$percent = 1;
1955
	}
1956
	if ($pkg_interface <> "console") {
1957
		echo '<script>document.getElementById("progressbar").style.width="'. $percent.'%";</script>';
1958
	} else {
1959
		if (!($first_time)) {
1960
			echo "\x08\x08\x08\x08\x08";
1961
		}
1962
		echo sprintf("%4d%%", $percent);
1963
	}
1964
}
1965

    
1966
/* 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. */
1967
if (!function_exists("split")) {
1968
	function split($separator, $haystack, $limit = null) {
1969
		log_error("deprecated split() call with separator '{$separator}'");
1970
		return preg_split($separator, $haystack, $limit);
1971
	}
1972
}
1973

    
1974
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
1975
	global $g, $config, $pconfig, $debug;
1976
	if (!$origname) {
1977
		return;
1978
	}
1979

    
1980
	$sectionref = &$config;
1981
	foreach ($section as $sectionname) {
1982
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
1983
			$sectionref = &$sectionref[$sectionname];
1984
		} else {
1985
			return;
1986
		}
1987
	}
1988

    
1989
	if ($debug) {
1990
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
1991
		fwrite($fd, print_r($pconfig, true));
1992
	}
1993

    
1994
	if (is_array($sectionref)) {
1995
		foreach ($sectionref as $itemkey => $item) {
1996
			if ($debug) {
1997
				fwrite($fd, "$itemkey\n");
1998
			}
1999

    
2000
			$fieldfound = true;
2001
			$fieldref = &$sectionref[$itemkey];
2002
			foreach ($field as $fieldname) {
2003
				if (is_array($fieldref) && isset($fieldref[$fieldname])) {
2004
					$fieldref = &$fieldref[$fieldname];
2005
				} else {
2006
					$fieldfound = false;
2007
					break;
2008
				}
2009
			}
2010
			if ($fieldfound && $fieldref == $origname) {
2011
				if ($debug) {
2012
					fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
2013
				}
2014
				$fieldref = $new_alias_name;
2015
			}
2016
		}
2017
	}
2018

    
2019
	if ($debug) {
2020
		fclose($fd);
2021
	}
2022

    
2023
}
2024

    
2025
function parse_aliases_file($filename, $type = "url", $max_items = -1) {
2026
	/*
2027
	 * $filename = file to process for example blocklist like DROP:  http://www.spamhaus.org/drop/drop.txt
2028
	 * $type = if set to 'url' then subnets and ips will be returned,
2029
	 *         if set to 'url_ports' port-ranges and ports will be returned
2030
	 * $max_items = sets the maximum amount of valid items to load, -1 the default defines there is no limit.
2031
	 *
2032
	 * RETURNS an array of ip subnets and ip's or ports and port-ranges, returns NULL upon a error conditions (file not found)
2033
	 */
2034

    
2035
	$fd = @fopen($filename, 'r');
2036
	if (!$fd) {
2037
		log_error(gettext("Could not process aliases from alias: {$alias_url}"));
2038
		return null;
2039
	}
2040
	$items = array();
2041
	/* NOTE: fgetss() is not a typo RTFM before being smart */
2042
	while (($fc = fgetss($fd)) !== FALSE) {
2043
		$tmp = trim($fc, " \t\n\r");
2044
		if (empty($tmp)) {
2045
			continue;
2046
		}
2047
		$tmp_str = strstr($tmp, '#', true);
2048
		if (!empty($tmp_str)) {
2049
			$tmp = $tmp_str;
2050
		}
2051
		$tmp_str = strstr($tmp, ' ', true);
2052
		if (!empty($tmp_str)) {
2053
			$tmp = $tmp_str;
2054
		}
2055
		$valid = ($type == "url" && (is_ipaddr($tmp) || is_subnet($tmp))) ||
2056
			 ($type == "url_ports" && (is_port($tmp) || is_portrange($tmp)));
2057
		if ($valid) {
2058
			$items[] = $tmp;
2059
			if (count($items) == $max_items) {
2060
				break;
2061
			}
2062
		}
2063
	}
2064
	fclose($fd);
2065
	return $items;
2066
}
2067

    
2068
function update_alias_url_data() {
2069
	global $config, $g;
2070

    
2071
	$updated = false;
2072

    
2073
	/* item is a url type */
2074
	$lockkey = lock('aliasurl');
2075
	if (is_array($config['aliases']['alias'])) {
2076
		foreach ($config['aliases']['alias'] as $x => $alias) {
2077
			if (empty($alias['aliasurl'])) {
2078
				continue;
2079
			}
2080

    
2081
			$address = null;
2082
			foreach ($alias['aliasurl'] as $alias_url) {
2083
				/* fetch down and add in */
2084
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
2085
				unlink($temp_filename);
2086
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2087
				mkdir($temp_filename);
2088
				download_file($alias_url, $temp_filename . "/aliases", $verify_ssl);
2089

    
2090
				/* if the item is tar gzipped then extract */
2091
				if (stripos($alias_url, '.tgz')) {
2092
					if (!process_alias_tgz($temp_filename)) {
2093
						continue;
2094
					}
2095
				} else if (stripos($alias_url, '.zip')) {
2096
					if (!process_alias_unzip($temp_filename)) {
2097
						continue;
2098
					}
2099
				}
2100
				if (file_exists("{$temp_filename}/aliases")) {
2101
					$address = parse_aliases_file("{$temp_filename}/aliases", $alias['type'], 3000);
2102
					mwexec("/bin/rm -rf {$temp_filename}");
2103
				}
2104
			}
2105
			if ($address != null) {
2106
				$config['aliases']['alias'][$x]['address'] = implode(" ", $address);
2107
				$updated = true;
2108
			}
2109
		}
2110
	}
2111
	unlock($lockkey);
2112

    
2113
	/* Report status to callers as well */
2114
	return $updated;
2115
}
2116

    
2117
function process_alias_unzip($temp_filename) {
2118
	if (!file_exists("/usr/local/bin/unzip")) {
2119
		log_error(gettext("Alias archive is a .zip file which cannot be decompressed because utility is missing!"));
2120
		return false;
2121
	}
2122
	rename("{$temp_filename}/aliases", "{$temp_filename}/aliases.zip");
2123
	mwexec("/usr/local/bin/unzip {$temp_filename}/aliases.tgz -d {$temp_filename}/aliases/");
2124
	unlink("{$temp_filename}/aliases.zip");
2125
	$files_to_process = return_dir_as_array("{$temp_filename}/");
2126
	/* foreach through all extracted files and build up aliases file */
2127
	$fd = @fopen("{$temp_filename}/aliases", "w");
2128
	if (!$fd) {
2129
		log_error(gettext("Could not open {$temp_filename}/aliases for writing!"));
2130
		return false;
2131
	}
2132
	foreach ($files_to_process as $f2p) {
2133
		$tmpfd = @fopen($f2p, 'r');
2134
		if (!$tmpfd) {
2135
			log_error(gettext("The following file could not be read {$f2p} from {$temp_filename}"));
2136
			continue;
2137
		}
2138
		while (($tmpbuf = fread($tmpfd, 65536)) !== FALSE) {
2139
			fwrite($fd, $tmpbuf);
2140
		}
2141
		fclose($tmpfd);
2142
		unlink($f2p);
2143
	}
2144
	fclose($fd);
2145
	unset($tmpbuf);
2146

    
2147
	return true;
2148
}
2149

    
2150
function process_alias_tgz($temp_filename) {
2151
	if (!file_exists('/usr/bin/tar')) {
2152
		log_error(gettext("Alias archive is a .tar/tgz file which cannot be decompressed because utility is missing!"));
2153
		return false;
2154
	}
2155
	rename("{$temp_filename}/aliases", "{$temp_filename}/aliases.tgz");
2156
	mwexec("/usr/bin/tar xzf {$temp_filename}/aliases.tgz -C {$temp_filename}/aliases/");
2157
	unlink("{$temp_filename}/aliases.tgz");
2158
	$files_to_process = return_dir_as_array("{$temp_filename}/");
2159
	/* foreach through all extracted files and build up aliases file */
2160
	$fd = @fopen("{$temp_filename}/aliases", "w");
2161
	if (!$fd) {
2162
		log_error(gettext("Could not open {$temp_filename}/aliases for writing!"));
2163
		return false;
2164
	}
2165
	foreach ($files_to_process as $f2p) {
2166
		$tmpfd = @fopen($f2p, 'r');
2167
		if (!$tmpfd) {
2168
			log_error(gettext("The following file could not be read {$f2p} from {$temp_filename}"));
2169
			continue;
2170
		}
2171
		while (($tmpbuf = fread($tmpfd, 65536)) !== FALSE) {
2172
			fwrite($fd, $tmpbuf);
2173
		}
2174
		fclose($tmpfd);
2175
		unlink($f2p);
2176
	}
2177
	fclose($fd);
2178
	unset($tmpbuf);
2179

    
2180
	return true;
2181
}
2182

    
2183
function version_compare_dates($a, $b) {
2184
	$a_time = strtotime($a);
2185
	$b_time = strtotime($b);
2186

    
2187
	if ((!$a_time) || (!$b_time)) {
2188
		return FALSE;
2189
	} else {
2190
		if ($a_time < $b_time) {
2191
			return -1;
2192
		} elseif ($a_time == $b_time) {
2193
			return 0;
2194
		} else {
2195
			return 1;
2196
		}
2197
	}
2198
}
2199
function version_get_string_value($a) {
2200
	$strs = array(
2201
		0 => "ALPHA-ALPHA",
2202
		2 => "ALPHA",
2203
		3 => "BETA",
2204
		4 => "B",
2205
		5 => "C",
2206
		6 => "D",
2207
		7 => "RC",
2208
		8 => "RELEASE",
2209
		9 => "*"			// Matches all release levels
2210
	);
2211
	$major = 0;
2212
	$minor = 0;
2213
	foreach ($strs as $num => $str) {
2214
		if (substr($a, 0, strlen($str)) == $str) {
2215
			$major = $num;
2216
			$n = substr($a, strlen($str));
2217
			if (is_numeric($n)) {
2218
				$minor = $n;
2219
			}
2220
			break;
2221
		}
2222
	}
2223
	return "{$major}.{$minor}";
2224
}
2225
function version_compare_string($a, $b) {
2226
	// Only compare string parts if both versions give a specific release
2227
	// (If either version lacks a string part, assume intended to match all release levels)
2228
	if (isset($a) && isset($b)) {
2229
		return version_compare_numeric(version_get_string_value($a), version_get_string_value($b));
2230
	} else {
2231
		return 0;
2232
	}
2233
}
2234
function version_compare_numeric($a, $b) {
2235
	$a_arr = explode('.', rtrim($a, '.'));
2236
	$b_arr = explode('.', rtrim($b, '.'));
2237

    
2238
	foreach ($a_arr as $n => $val) {
2239
		if (array_key_exists($n, $b_arr)) {
2240
			// So far so good, both have values at this minor version level. Compare.
2241
			if ($val > $b_arr[$n]) {
2242
				return 1;
2243
			} elseif ($val < $b_arr[$n]) {
2244
				return -1;
2245
			}
2246
		} else {
2247
			// a is greater, since b doesn't have any minor version here.
2248
			return 1;
2249
		}
2250
	}
2251
	if (count($b_arr) > count($a_arr)) {
2252
		// b is longer than a, so it must be greater.
2253
		return -1;
2254
	} else {
2255
		// Both a and b are of equal length and value.
2256
		return 0;
2257
	}
2258
}
2259
function pfs_version_compare($cur_time, $cur_text, $remote) {
2260
	// First try date compare
2261
	$v = version_compare_dates($cur_time, $remote);
2262
	if ($v === FALSE) {
2263
		// If that fails, try to compare by string
2264
		// Before anything else, simply test if the strings are equal
2265
		if (($cur_text == $remote) || ($cur_time == $remote)) {
2266
			return 0;
2267
		}
2268
		list($cur_num, $cur_str) = explode('-', $cur_text);
2269
		list($rem_num, $rem_str) = explode('-', $remote);
2270

    
2271
		// First try to compare the numeric parts of the version string.
2272
		$v = version_compare_numeric($cur_num, $rem_num);
2273

    
2274
		// If the numeric parts are the same, compare the string parts.
2275
		if ($v == 0) {
2276
			return version_compare_string($cur_str, $rem_str);
2277
		}
2278
	}
2279
	return $v;
2280
}
2281
function process_alias_urltable($name, $url, $freq, $forceupdate=false) {
2282
	global $config;
2283

    
2284
	$urltable_prefix = "/var/db/aliastables/";
2285
	$urltable_filename = $urltable_prefix . $name . ".txt";
2286

    
2287
	// Make the aliases directory if it doesn't exist
2288
	if (!file_exists($urltable_prefix)) {
2289
		mkdir($urltable_prefix);
2290
	} elseif (!is_dir($urltable_prefix)) {
2291
		unlink($urltable_prefix);
2292
		mkdir($urltable_prefix);
2293
	}
2294

    
2295
	// If the file doesn't exist or is older than update_freq days, fetch a new copy.
2296
	if (!file_exists($urltable_filename) ||
2297
	    ((time() - filemtime($urltable_filename)) > ($freq * 86400 - 90)) ||
2298
	    $forceupdate) {
2299

    
2300
		// Try to fetch the URL supplied
2301
		conf_mount_rw();
2302
		unlink_if_exists($urltable_filename . ".tmp");
2303
		$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2304
		if (download_file($url, $urltable_filename . ".tmp", $verify_ssl)) {
2305
			mwexec("/usr/bin/sed -E 's/\;.*//g; /^[[:space:]]*($|#)/d' ". escapeshellarg($urltable_filename . ".tmp") . " > " . escapeshellarg($urltable_filename));
2306
			if (alias_get_type($name) == "urltable_ports") {
2307
				$ports = explode("\n", str_replace("\r", "", file_get_contents($urltable_filename)));
2308
				$ports = group_ports($ports);
2309
				file_put_contents($urltable_filename, implode("\n", $ports));
2310
			}
2311
			unlink_if_exists($urltable_filename . ".tmp");
2312
		} else {
2313
			touch($urltable_filename);
2314
		}
2315
		conf_mount_ro();
2316
		return true;
2317
	} else {
2318
		// File exists, and it doesn't need to be updated.
2319
		return -1;
2320
	}
2321
}
2322
function get_real_slice_from_glabel($label) {
2323
	$label = escapeshellarg($label);
2324
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/{$label} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`);
2325
}
2326
function nanobsd_get_boot_slice() {
2327
	return trim(`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`);
2328
}
2329
function nanobsd_get_boot_drive() {
2330
	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`);
2331
}
2332
function nanobsd_get_active_slice() {
2333
	$boot_drive = nanobsd_get_boot_drive();
2334
	$active = trim(`gpart show $boot_drive | grep '\[active\]' | awk '{print $3;}'`);
2335

    
2336
	return "{$boot_drive}s{$active}";
2337
}
2338
function nanobsd_get_size() {
2339
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2340
}
2341
function nanobsd_switch_boot_slice() {
2342
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2343
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2344
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2345
	nanobsd_detect_slice_info();
2346

    
2347
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2348
		$slice = $TOFLASH;
2349
	} else {
2350
		$slice = $BOOTFLASH;
2351
	}
2352

    
2353
	for ($i = 0; $i < ob_get_level(); $i++) {
2354
		ob_end_flush();
2355
	}
2356
	ob_implicit_flush(1);
2357
	if (strstr($slice, "s2")) {
2358
		$ASLICE = "2";
2359
		$AOLDSLICE = "1";
2360
		$AGLABEL_SLICE = "pfsense1";
2361
		$AUFS_ID = "1";
2362
		$AOLD_UFS_ID = "0";
2363
	} else {
2364
		$ASLICE = "1";
2365
		$AOLDSLICE = "2";
2366
		$AGLABEL_SLICE = "pfsense0";
2367
		$AUFS_ID = "0";
2368
		$AOLD_UFS_ID = "1";
2369
	}
2370
	$ATOFLASH = "{$BOOT_DRIVE}s{$ASLICE}";
2371
	$ACOMPLETE_PATH = "{$BOOT_DRIVE}s{$ASLICE}a";
2372
	$ABOOTFLASH = "{$BOOT_DRIVE}s{$AOLDSLICE}";
2373
	conf_mount_rw();
2374
	set_single_sysctl("kern.geom.debugflags", "16");
2375
	exec("gpart set -a active -i {$ASLICE} {$BOOT_DRIVE}");
2376
	exec("/usr/sbin/boot0cfg -s {$ASLICE} -v /dev/{$BOOT_DRIVE}");
2377
	// We can't update these if they are mounted now.
2378
	if ($BOOTFLASH != $slice) {
2379
		exec("/sbin/tunefs -L ${AGLABEL_SLICE} /dev/$ACOMPLETE_PATH");
2380
		nanobsd_update_fstab($AGLABEL_SLICE, $ACOMPLETE_PATH, $AOLD_UFS_ID, $AUFS_ID);
2381
	}
2382
	set_single_sysctl("kern.geom.debugflags", "0");
2383
	conf_mount_ro();
2384
}
2385
function nanobsd_clone_slice() {
2386
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2387
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2388
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2389
	nanobsd_detect_slice_info();
2390

    
2391
	for ($i = 0; $i < ob_get_level(); $i++) {
2392
		ob_end_flush();
2393
	}
2394
	ob_implicit_flush(1);
2395
	set_single_sysctl("kern.geom.debugflags", "16");
2396
	exec("/bin/dd if=/dev/zero of=/dev/{$TOFLASH} bs=1m count=1");
2397
	exec("/bin/dd if=/dev/{$BOOTFLASH} of=/dev/{$TOFLASH} bs=64k");
2398
	exec("/sbin/tunefs -L {$GLABEL_SLICE} /dev/{$COMPLETE_PATH}");
2399
	$status = nanobsd_update_fstab($GLABEL_SLICE, $COMPLETE_PATH, $OLD_UFS_ID, $UFS_ID);
2400
	set_single_sysctl("kern.geom.debugflags", "0");
2401
	if ($status) {
2402
		return false;
2403
	} else {
2404
		return true;
2405
	}
2406
}
2407
function nanobsd_update_fstab($gslice, $complete_path, $oldufs, $newufs) {
2408
	$tmppath = "/tmp/{$gslice}";
2409
	$fstabpath = "/tmp/{$gslice}/etc/fstab";
2410

    
2411
	mkdir($tmppath);
2412
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2413
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2414
	copy("/etc/fstab", $fstabpath);
2415

    
2416
	if (!file_exists($fstabpath)) {
2417
		$fstab = <<<EOF
2418
/dev/ufs/{$gslice} / ufs ro,noatime 1 1
2419
/dev/ufs/cf /cf ufs ro,noatime 1 1
2420
EOF;
2421
		if (file_put_contents($fstabpath, $fstab)) {
2422
			$status = true;
2423
		} else {
2424
			$status = false;
2425
		}
2426
	} else {
2427
		$status = exec("sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2428
	}
2429
	exec("/sbin/umount {$tmppath}");
2430
	rmdir($tmppath);
2431

    
2432
	return $status;
2433
}
2434
function nanobsd_detect_slice_info() {
2435
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2436
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2437
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2438

    
2439
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2440
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2441
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2442
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2443

    
2444
	// Detect which slice is active and set information.
2445
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2446
		$SLICE = "2";
2447
		$OLDSLICE = "1";
2448
		$GLABEL_SLICE = "pfsense1";
2449
		$UFS_ID = "1";
2450
		$OLD_UFS_ID = "0";
2451

    
2452
	} else {
2453
		$SLICE = "1";
2454
		$OLDSLICE = "2";
2455
		$GLABEL_SLICE = "pfsense0";
2456
		$UFS_ID = "0";
2457
		$OLD_UFS_ID = "1";
2458
	}
2459
	$TOFLASH = "{$BOOT_DRIVE}s{$SLICE}";
2460
	$COMPLETE_PATH = "{$BOOT_DRIVE}s{$SLICE}a";
2461
	$COMPLETE_BOOT_PATH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2462
	$BOOTFLASH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2463
}
2464

    
2465
function nanobsd_friendly_slice_name($slicename) {
2466
	global $g;
2467
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2468
}
2469

    
2470
function get_include_contents($filename) {
2471
	if (is_file($filename)) {
2472
		ob_start();
2473
		include $filename;
2474
		$contents = ob_get_contents();
2475
		ob_end_clean();
2476
		return $contents;
2477
	}
2478
	return false;
2479
}
2480

    
2481
/* This xml 2 array function is courtesy of the php.net comment section on xml_parse.
2482
 * it is roughly 4 times faster then our existing pfSense parser but due to the large
2483
 * size of the RRD xml dumps this is required.
2484
 * The reason we do not use it for pfSense is that it does not know about array fields
2485
 * which causes it to fail on array fields with single items. Possible Todo?
2486
 */
2487
function xml2array($contents, $get_attributes = 1, $priority = 'tag') {
2488
	if (!function_exists('xml_parser_create')) {
2489
		return array ();
2490
	}
2491
	$parser = xml_parser_create('');
2492
	xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
2493
	xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
2494
	xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
2495
	xml_parse_into_struct($parser, trim($contents), $xml_values);
2496
	xml_parser_free($parser);
2497
	if (!$xml_values) {
2498
		return; //Hmm...
2499
	}
2500
	$xml_array = array ();
2501
	$parents = array ();
2502
	$opened_tags = array ();
2503
	$arr = array ();
2504
	$current = & $xml_array;
2505
	$repeated_tag_index = array ();
2506
	foreach ($xml_values as $data) {
2507
		unset ($attributes, $value);
2508
		extract($data);
2509
		$result = array ();
2510
		$attributes_data = array ();
2511
		if (isset ($value)) {
2512
			if ($priority == 'tag') {
2513
				$result = $value;
2514
			} else {
2515
				$result['value'] = $value;
2516
			}
2517
		}
2518
		if (isset ($attributes) and $get_attributes) {
2519
			foreach ($attributes as $attr => $val) {
2520
				if ($priority == 'tag') {
2521
					$attributes_data[$attr] = $val;
2522
				} else {
2523
					$result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
2524
				}
2525
			}
2526
		}
2527
		if ($type == "open") {
2528
			$parent[$level -1] = & $current;
2529
			if (!is_array($current) or (!in_array($tag, array_keys($current)))) {
2530
				$current[$tag] = $result;
2531
				if ($attributes_data) {
2532
					$current[$tag . '_attr'] = $attributes_data;
2533
				}
2534
				$repeated_tag_index[$tag . '_' . $level] = 1;
2535
				$current = & $current[$tag];
2536
			} else {
2537
				if (isset ($current[$tag][0])) {
2538
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2539
					$repeated_tag_index[$tag . '_' . $level]++;
2540
				} else {
2541
					$current[$tag] = array (
2542
						$current[$tag],
2543
						$result
2544
						);
2545
					$repeated_tag_index[$tag . '_' . $level] = 2;
2546
					if (isset ($current[$tag . '_attr'])) {
2547
						$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2548
						unset ($current[$tag . '_attr']);
2549
					}
2550
				}
2551
				$last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
2552
				$current = & $current[$tag][$last_item_index];
2553
			}
2554
		} elseif ($type == "complete") {
2555
			if (!isset ($current[$tag])) {
2556
				$current[$tag] = $result;
2557
				$repeated_tag_index[$tag . '_' . $level] = 1;
2558
				if ($priority == 'tag' and $attributes_data) {
2559
					$current[$tag . '_attr'] = $attributes_data;
2560
				}
2561
			} else {
2562
				if (isset ($current[$tag][0]) and is_array($current[$tag])) {
2563
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2564
					if ($priority == 'tag' and $get_attributes and $attributes_data) {
2565
						$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2566
					}
2567
					$repeated_tag_index[$tag . '_' . $level]++;
2568
				} else {
2569
					$current[$tag] = array (
2570
						$current[$tag],
2571
						$result
2572
						);
2573
					$repeated_tag_index[$tag . '_' . $level] = 1;
2574
					if ($priority == 'tag' and $get_attributes) {
2575
						if (isset ($current[$tag . '_attr'])) {
2576
							$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2577
							unset ($current[$tag . '_attr']);
2578
						}
2579
						if ($attributes_data) {
2580
							$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2581
						}
2582
					}
2583
					$repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
2584
				}
2585
			}
2586
		} elseif ($type == 'close') {
2587
			$current = & $parent[$level -1];
2588
		}
2589
	}
2590
	return ($xml_array);
2591
}
2592

    
2593
function get_country_name($country_code) {
2594
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2595
		return "";
2596
	}
2597

    
2598
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2599
	$country_names_contents = file_get_contents($country_names_xml);
2600
	$country_names = xml2array($country_names_contents);
2601

    
2602
	if ($country_code == "ALL") {
2603
		$country_list = array();
2604
		foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2605
			$country_list[] = array(
2606
				"code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2607
				"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])));
2608
		}
2609
		return $country_list;
2610
	}
2611

    
2612
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2613
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2614
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2615
		}
2616
	}
2617
	return "";
2618
}
2619

    
2620
/* sort by interface only, retain the original order of rules that apply to
2621
   the same interface */
2622
function filter_rules_sort() {
2623
	global $config;
2624

    
2625
	/* mark each rule with the sequence number (to retain the order while sorting) */
2626
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2627
		$config['filter']['rule'][$i]['seq'] = $i;
2628
	}
2629

    
2630
	usort($config['filter']['rule'], "filter_rules_compare");
2631

    
2632
	/* strip the sequence numbers again */
2633
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2634
		unset($config['filter']['rule'][$i]['seq']);
2635
	}
2636
}
2637
function filter_rules_compare($a, $b) {
2638
	if (isset($a['floating']) && isset($b['floating'])) {
2639
		return $a['seq'] - $b['seq'];
2640
	} else if (isset($a['floating'])) {
2641
		return -1;
2642
	} else if (isset($b['floating'])) {
2643
		return 1;
2644
	} else if ($a['interface'] == $b['interface']) {
2645
		return $a['seq'] - $b['seq'];
2646
	} else {
2647
		return compare_interface_friendly_names($a['interface'], $b['interface']);
2648
	}
2649
}
2650

    
2651
function generate_ipv6_from_mac($mac) {
2652
	$elements = explode(":", $mac);
2653
	if (count($elements) <> 6) {
2654
		return false;
2655
	}
2656

    
2657
	$i = 0;
2658
	$ipv6 = "fe80::";
2659
	foreach ($elements as $byte) {
2660
		if ($i == 0) {
2661
			$hexadecimal = substr($byte, 1, 2);
2662
			$bitmap = base_convert($hexadecimal, 16, 2);
2663
			$bitmap = str_pad($bitmap, 4, "0", STR_PAD_LEFT);
2664
			$bitmap = substr($bitmap, 0, 2) ."1". substr($bitmap, 3, 4);
2665
			$byte = substr($byte, 0, 1) . base_convert($bitmap, 2, 16);
2666
		}
2667
		$ipv6 .= $byte;
2668
		if ($i == 1) {
2669
			$ipv6 .= ":";
2670
		}
2671
		if ($i == 3) {
2672
			$ipv6 .= ":";
2673
		}
2674
		if ($i == 2) {
2675
			$ipv6 .= "ff:fe";
2676
		}
2677

    
2678
		$i++;
2679
	}
2680
	return $ipv6;
2681
}
2682

    
2683
/****f* pfsense-utils/load_mac_manufacturer_table
2684
 * NAME
2685
 *   load_mac_manufacturer_table
2686
 * INPUTS
2687
 *   none
2688
 * RESULT
2689
 *   returns associative array with MAC-Manufacturer pairs
2690
 ******/
2691
function load_mac_manufacturer_table() {
2692
	/* load MAC-Manufacture data from the file */
2693
	$macs = false;
2694
	if (file_exists("/usr/local/share/nmap/nmap-mac-prefixes")) {
2695
		$macs=file("/usr/local/share/nmap/nmap-mac-prefixes");
2696
	}
2697
	if ($macs) {
2698
		foreach ($macs as $line) {
2699
			if (preg_match('/([0-9A-Fa-f]{6}) (.*)$/', $line, $matches)) {
2700
				/* store values like this $mac_man['000C29']='VMware' */
2701
				$mac_man["$matches[1]"] = $matches[2];
2702
			}
2703
		}
2704
		return $mac_man;
2705
	} else {
2706
		return -1;
2707
	}
2708

    
2709
}
2710

    
2711
/****f* pfsense-utils/is_ipaddr_configured
2712
 * NAME
2713
 *   is_ipaddr_configured
2714
 * INPUTS
2715
 *   IP Address to check.
2716
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2717
 *   check_localip - if true then also check for matches with PPTP and LT2P addresses
2718
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2719
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2720
 *     If check_subnets is true and cidrprefix is specified,
2721
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2722
 * RESULT
2723
 *   returns true if the IP Address is configured and present on this device or overlaps a configured subnet.
2724
*/
2725
function is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2726
	if (count(where_is_ipaddr_configured($ipaddr, $ignore_if, $check_localip, $check_subnets, $cidrprefix))) {
2727
		return true;
2728
	}
2729
	return false;
2730
}
2731

    
2732
/****f* pfsense-utils/where_is_ipaddr_configured
2733
 * NAME
2734
 *   where_is_ipaddr_configured
2735
 * INPUTS
2736
 *   IP Address to check.
2737
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2738
 *   check_localip - if true then also check for matches with PPTP and LT2P addresses
2739
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2740
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2741
 *     If check_subnets is true and cidrprefix is specified,
2742
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2743
 * RESULT
2744
 *   Returns an array of the interfaces 'if' plus IP address or subnet 'ip_or_subnet' that match or overlap the IP address to check.
2745
 *   If there are no matches then an empty array is returned.
2746
*/
2747
function where_is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2748
	global $config;
2749

    
2750
	$where_configured = array();
2751

    
2752
	$pos = strpos($ignore_if, '_virtualip');
2753
	if ($pos !== false) {
2754
		$ignore_vip_id = substr($ignore_if, $pos+10);
2755
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2756
	} else {
2757
		$ignore_vip_id = -1;
2758
		$ignore_vip_if = $ignore_if;
2759
	}
2760

    
2761
	$isipv6 = is_ipaddrv6($ipaddr);
2762

    
2763
	if ($check_subnets) {
2764
		$cidrprefix = intval($cidrprefix);
2765
		if ($isipv6) {
2766
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2767
				$cidrprefix = 128;
2768
			}
2769
		} else {
2770
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2771
				$cidrprefix = 32;
2772
			}
2773
		}
2774
		$iflist = get_configured_interface_list();
2775
		foreach ($iflist as $if => $ifname) {
2776
			if ($ignore_if == $if) {
2777
				continue;
2778
			}
2779

    
2780
			if ($isipv6) {
2781
				$if_ipv6 = get_interface_ipv6($if);
2782
				$if_snbitsv6 = get_interface_subnetv6($if);
2783
				if ($if_ipv6 && $if_snbitsv6 && check_subnetsv6_overlap($ipaddr, $cidrprefix, $if_ipv6, $if_snbitsv6)) {
2784
					$where_entry = array();
2785
					$where_entry['if'] = $if;
2786
					$where_entry['ip_or_subnet'] = get_interface_ipv6($if) . "/" . get_interface_subnetv6($if);
2787
					$where_configured[] = $where_entry;
2788
				}
2789
			} else {
2790
				$if_ipv4 = get_interface_ip($if);
2791
				$if_snbitsv4 = get_interface_subnet($if);
2792
				if ($if_ipv4 && $if_snbitsv4 && check_subnets_overlap($ipaddr, $cidrprefix, $if_ipv4, $if_snbitsv4)) {
2793
					$where_entry = array();
2794
					$where_entry['if'] = $if;
2795
					$where_entry['ip_or_subnet'] = get_interface_ip($if) . "/" . get_interface_subnet($if);
2796
					$where_configured[] = $where_entry;
2797
				}
2798
			}
2799
		}
2800
	} else {
2801
		if ($isipv6) {
2802
			$interface_list_ips = get_configured_ipv6_addresses();
2803
		} else {
2804
			$interface_list_ips = get_configured_ip_addresses();
2805
		}
2806

    
2807
		foreach ($interface_list_ips as $if => $ilips) {
2808
			if ($ignore_if == $if) {
2809
				continue;
2810
			}
2811
			if (strcasecmp($ipaddr, $ilips) == 0) {
2812
				$where_entry = array();
2813
				$where_entry['if'] = $if;
2814
				$where_entry['ip_or_subnet'] = $ilips;
2815
				$where_configured[] = $where_entry;
2816
			}
2817
		}
2818
	}
2819

    
2820
	$interface_list_vips = get_configured_vips_list(true);
2821
	foreach ($interface_list_vips as $id => $vip) {
2822
		/* Skip CARP interfaces here since they were already checked above */
2823
		if ($id == $ignore_vip_id || (substr($ignore_if, 0, 4) == '_vip') && substr($ignore_vip_if, 5) == $vip['uniqdid']) {
2824
			continue;
2825
		}
2826
		if (strcasecmp($ipaddr, $vip['ipaddr']) == 0) {
2827
			$where_entry = array();
2828
			$where_entry['if'] = $vip['if'];
2829
			$where_entry['ip_or_subnet'] = $vip['ipaddr'];
2830
			$where_configured[] = $where_entry;
2831
		}
2832
	}
2833

    
2834
	if ($check_localip) {
2835
		if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0)) {
2836
			$where_entry = array();
2837
			$where_entry['if'] = 'l2tp';
2838
			$where_entry['ip_or_subnet'] = $config['l2tp']['localip'];
2839
			$where_configured[] = $where_entry;
2840
		}
2841
	}
2842

    
2843
	return $where_configured;
2844
}
2845

    
2846
/****f* pfsense-utils/pfSense_handle_custom_code
2847
 * NAME
2848
 *   pfSense_handle_custom_code
2849
 * INPUTS
2850
 *   directory name to process
2851
 * RESULT
2852
 *   globs the directory and includes the files
2853
 */
2854
function pfSense_handle_custom_code($src_dir) {
2855
	// Allow extending of the nat edit page and include custom input validation
2856
	if (is_dir("$src_dir")) {
2857
		$cf = glob($src_dir . "/*.inc");
2858
		foreach ($cf as $nf) {
2859
			if ($nf == "." || $nf == "..") {
2860
				continue;
2861
			}
2862
			// Include the extra handler
2863
			include("$nf");
2864
		}
2865
	}
2866
}
2867

    
2868
function set_language($lang = 'en_US', $encoding = "UTF-8") {
2869
	putenv("LANG={$lang}.{$encoding}");
2870
	setlocale(LC_ALL, "{$lang}.{$encoding}");
2871
	textdomain("pfSense");
2872
	bindtextdomain("pfSense", "/usr/local/share/locale");
2873
	bind_textdomain_codeset("pfSense", "{$lang}.{$encoding}");
2874
}
2875

    
2876
function get_locale_list() {
2877
	$locales = array(
2878
		"en_US" => gettext("English"),
2879
		"pt_BR" => gettext("Portuguese (Brazil)"),
2880
		"tr" => gettext("Turkish"),
2881
	);
2882
	asort($locales);
2883
	return $locales;
2884
}
2885

    
2886
function system_get_language_code() {
2887
	global $config, $g_languages;
2888

    
2889
	// a language code, as per [RFC3066]
2890
	$language = $config['system']['language'];
2891
	//$code = $g_languages[$language]['code'];
2892
	$code = str_replace("_", "-", $language);
2893

    
2894
	if (empty($code)) {
2895
		$code = "en-US"; // Set default code.
2896
	}
2897

    
2898
	return $code;
2899
}
2900

    
2901
function system_get_language_codeset() {
2902
	global $config, $g_languages;
2903

    
2904
	$language = $config['system']['language'];
2905
	$codeset = $g_languages[$language]['codeset'];
2906

    
2907
	if (empty($codeset)) {
2908
		$codeset = "UTF-8"; // Set default codeset.
2909
	}
2910

    
2911
	return $codeset;
2912
}
2913

    
2914
/* Available languages/locales */
2915
$g_languages = array (
2916
	"sq"    => array("codeset" => "UTF-8", "desc" => gettext("Albanian")),
2917
	"bg"    => array("codeset" => "UTF-8", "desc" => gettext("Bulgarian")),
2918
	"zh_CN" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Simplified)")),
2919
	"zh_TW" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Traditional)")),
2920
	"nl"    => array("codeset" => "UTF-8", "desc" => gettext("Dutch")),
2921
	"da"    => array("codeset" => "UTF-8", "desc" => gettext("Danish")),
2922
	"en_US" => array("codeset" => "UTF-8", "desc" => gettext("English")),
2923
	"fi"    => array("codeset" => "UTF-8", "desc" => gettext("Finnish")),
2924
	"fr"    => array("codeset" => "UTF-8", "desc" => gettext("French")),
2925
	"de"    => array("codeset" => "UTF-8", "desc" => gettext("German")),
2926
	"el"    => array("codeset" => "UTF-8", "desc" => gettext("Greek")),
2927
	"hu"    => array("codeset" => "UTF-8", "desc" => gettext("Hungarian")),
2928
	"it"    => array("codeset" => "UTF-8", "desc" => gettext("Italian")),
2929
	"ja"    => array("codeset" => "UTF-8", "desc" => gettext("Japanese")),
2930
	"ko"    => array("codeset" => "UTF-8", "desc" => gettext("Korean")),
2931
	"lv"    => array("codeset" => "UTF-8", "desc" => gettext("Latvian")),
2932
	"nb"    => array("codeset" => "UTF-8", "desc" => gettext("Norwegian (Bokmal)")),
2933
	"pl"    => array("codeset" => "UTF-8", "desc" => gettext("Polish")),
2934
	"pt_BR" => array("codeset" => "UTF-8", "desc" => gettext("Portuguese (Brazil)")),
2935
	"pt"    => array("codeset" => "UTF-8", "desc" => gettext("Portuguese (Portugal)")),
2936
	"ro"    => array("codeset" => "UTF-8", "desc" => gettext("Romanian")),
2937
	"ru"    => array("codeset" => "UTF-8", "desc" => gettext("Russian")),
2938
	"sl"    => array("codeset" => "UTF-8", "desc" => gettext("Slovenian")),
2939
	"tr"    => array("codeset" => "UTF-8", "desc" => gettext("Turkish")),
2940
	"es"    => array("codeset" => "UTF-8", "desc" => gettext("Spanish")),
2941
	"sv"    => array("codeset" => "UTF-8", "desc" => gettext("Swedish")),
2942
	"sk"    => array("codeset" => "UTF-8", "desc" => gettext("Slovak")),
2943
	"cs"    => array("codeset" => "UTF-8", "desc" => gettext("Czech"))
2944
);
2945

    
2946
function return_hex_ipv4($ipv4) {
2947
	if (!is_ipaddrv4($ipv4)) {
2948
		return(false);
2949
	}
2950

    
2951
	/* we need the hex form of the interface IPv4 address */
2952
	$ip4arr = explode(".", $ipv4);
2953
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2954
}
2955

    
2956
function convert_ipv6_to_128bit($ipv6) {
2957
	if (!is_ipaddrv6($ipv6)) {
2958
		return(false);
2959
	}
2960

    
2961
	$ip6arr = array();
2962
	$ip6prefix = Net_IPv6::uncompress($ipv6);
2963
	$ip6arr = explode(":", $ip6prefix);
2964
	/* binary presentation of the prefix for all 128 bits. */
2965
	$ip6prefixbin = "";
2966
	foreach ($ip6arr as $element) {
2967
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
2968
	}
2969
	return($ip6prefixbin);
2970
}
2971

    
2972
function convert_128bit_to_ipv6($ip6bin) {
2973
	if (strlen($ip6bin) <> 128) {
2974
		return(false);
2975
	}
2976

    
2977
	$ip6arr = array();
2978
	$ip6binarr = array();
2979
	$ip6binarr = str_split($ip6bin, 16);
2980
	foreach ($ip6binarr as $binpart) {
2981
		$ip6arr[] = dechex(bindec($binpart));
2982
	}
2983
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2984

    
2985
	return($ip6addr);
2986
}
2987

    
2988

    
2989
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
2990
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
2991
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
2992
/* 6to4 is 16 bits, e.g. 65535 */
2993
function calculate_ipv6_delegation_length($if) {
2994
	global $config;
2995

    
2996
	if (!is_array($config['interfaces'][$if])) {
2997
		return false;
2998
	}
2999

    
3000
	switch ($config['interfaces'][$if]['ipaddrv6']) {
3001
		case "6to4":
3002
			$pdlen = 16;
3003
			break;
3004
		case "6rd":
3005
			$rd6cfg = $config['interfaces'][$if];
3006
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
3007
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
3008
			break;
3009
		case "dhcp6":
3010
			$dhcp6cfg = $config['interfaces'][$if];
3011
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
3012
			break;
3013
		default:
3014
			$pdlen = 0;
3015
			break;
3016
	}
3017
	return($pdlen);
3018
}
3019

    
3020
function huawei_rssi_to_string($rssi) {
3021
	$dbm = array();
3022
	$i = 0;
3023
	$dbstart = -113;
3024
	while ($i < 32) {
3025
		$dbm[$i] = $dbstart + ($i * 2);
3026
		$i++;
3027
	}
3028
	$percent = round(($rssi / 31) * 100);
3029
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
3030
	return $string;
3031
}
3032

    
3033
function huawei_mode_to_string($mode, $submode) {
3034
	$modes[0] = "None";
3035
	$modes[1] = "AMPS";
3036
	$modes[2] = "CDMA";
3037
	$modes[3] = "GSM/GPRS";
3038
	$modes[4] = "HDR";
3039
	$modes[5] = "WCDMA";
3040
	$modes[6] = "GPS";
3041

    
3042
	$submodes[0] = "No Service";
3043
	$submodes[1] = "GSM";
3044
	$submodes[2] = "GPRS";
3045
	$submodes[3] = "EDGE";
3046
	$submodes[4] = "WCDMA";
3047
	$submodes[5] = "HSDPA";
3048
	$submodes[6] = "HSUPA";
3049
	$submodes[7] = "HSDPA+HSUPA";
3050
	$submodes[8] = "TD-SCDMA";
3051
	$submodes[9] = "HSPA+";
3052
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
3053
	return $string;
3054
}
3055

    
3056
function huawei_service_to_string($state) {
3057
	$modes[0] = "No";
3058
	$modes[1] = "Restricted";
3059
	$modes[2] = "Valid";
3060
	$modes[3] = "Restricted Regional";
3061
	$modes[4] = "Powersaving";
3062
	$string = "{$modes[$state]} Service";
3063
	return $string;
3064
}
3065

    
3066
function huawei_simstate_to_string($state) {
3067
	$modes[0] = "Invalid SIM/locked";
3068
	$modes[1] = "Valid SIM";
3069
	$modes[2] = "Invalid SIM CS";
3070
	$modes[3] = "Invalid SIM PS";
3071
	$modes[4] = "Invalid SIM CS/PS";
3072
	$modes[255] = "Missing SIM";
3073
	$string = "{$modes[$state]} State";
3074
	return $string;
3075
}
3076

    
3077
function zte_rssi_to_string($rssi) {
3078
	return huawei_rssi_to_string($rssi);
3079
}
3080

    
3081
function zte_mode_to_string($mode, $submode) {
3082
	$modes[0] = "No Service";
3083
	$modes[1] = "Limited Service";
3084
	$modes[2] = "GPRS";
3085
	$modes[3] = "GSM";
3086
	$modes[4] = "UMTS";
3087
	$modes[5] = "EDGE";
3088
	$modes[6] = "HSDPA";
3089

    
3090
	$submodes[0] = "CS_ONLY";
3091
	$submodes[1] = "PS_ONLY";
3092
	$submodes[2] = "CS_PS";
3093
	$submodes[3] = "CAMPED";
3094
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
3095
	return $string;
3096
}
3097

    
3098
function zte_service_to_string($state) {
3099
	$modes[0] = "Initializing";
3100
	$modes[1] = "Network Lock error";
3101
	$modes[2] = "Network Locked";
3102
	$modes[3] = "Unlocked or correct MCC/MNC";
3103
	$string = "{$modes[$state]} Service";
3104
	return $string;
3105
}
3106

    
3107
function zte_simstate_to_string($state) {
3108
	$modes[0] = "No action";
3109
	$modes[1] = "Network lock";
3110
	$modes[2] = "(U)SIM card lock";
3111
	$modes[3] = "Network Lock and (U)SIM card Lock";
3112
	$string = "{$modes[$state]} State";
3113
	return $string;
3114
}
3115

    
3116
function get_configured_pppoe_server_interfaces() {
3117
	global $config;
3118
	$iflist = array();
3119
	if (is_array($config['pppoes']['pppoe'])) {
3120
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
3121
			if ($pppoe['mode'] == "server") {
3122
				$int = "poes". $pppoe['pppoeid'];
3123
				$iflist[$int] = strtoupper($int);
3124
			}
3125
		}
3126
	}
3127
	return $iflist;
3128
}
3129

    
3130
function get_pppoes_child_interfaces($ifpattern) {
3131
	$if_arr = array();
3132
	if ($ifpattern == "") {
3133
		return;
3134
	}
3135

    
3136
	exec("ifconfig", $out, $ret);
3137
	foreach ($out as $line) {
3138
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3139
			$if_arr[] = $match[1];
3140
		}
3141
	}
3142
	return $if_arr;
3143

    
3144
}
3145

    
3146
/****f* pfsense-utils/pkg_call_plugins
3147
 * NAME
3148
 *   pkg_call_plugins
3149
 * INPUTS
3150
 *   $plugin_type value used to search in package configuration if the plugin is used, also used to create the function name
3151
 *   $plugin_params parameters to pass to the plugin function for passing multiple parameters a array can be used.
3152
 * RESULT
3153
 *   returns associative array results from the plugin calls for each package
3154
 * NOTES
3155
 *   This generic function can be used to notify or retrieve results from functions that are defined in packages.
3156
 ******/
3157
function pkg_call_plugins($plugin_type, $plugin_params) {
3158
	global $g, $config;
3159
	$results = array();
3160
	if (!is_array($config['installedpackages']['package'])) {
3161
		return $results;
3162
	}
3163
	foreach ($config['installedpackages']['package'] as $package) {
3164
		if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
3165
			continue;
3166
		}
3167
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], 'packagegui');
3168
		$pkgname = substr(reverse_strrchr($package['configurationfile'], "."), 0, -1);
3169
		if (is_array($pkg_config['plugins']['item'])) {
3170
			foreach ($pkg_config['plugins']['item'] as $plugin) {
3171
				if ($plugin['type'] == $plugin_type) {
3172
					if (file_exists($pkg_config['include_file'])) {
3173
						require_once($pkg_config['include_file']);
3174
					} else {
3175
						continue;
3176
					}
3177
					$plugin_function = $pkgname . '_'. $plugin_type;
3178
					$results[$pkgname] = call_user_func($plugin_function, $plugin_params);
3179
				}
3180
			}
3181
		}
3182
	}
3183
	return $results;
3184
}
3185

    
3186
/* Function to find and return the active XML RPC base URL to avoid code duplication */
3187
function get_active_xml_rpc_base_url() {
3188
	global $config, $g;
3189
	/* If the user has activated the option to enable an alternate xmlrpcbaseurl, and it's not empty, then use it */
3190
	if (isset($config['system']['altpkgrepo']['enable']) && !empty($config['system']['altpkgrepo']['xmlrpcbaseurl'])) {
3191
		return $config['system']['altpkgrepo']['xmlrpcbaseurl'];
3192
	} else {
3193
		return $g['xmlrpcbaseurl'];
3194
	}
3195
}
3196

    
3197
?>
(40-40/68)