Project

General

Profile

Download (90.3 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 /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 -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 -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") && !file_exists("/etc/nano_use_vga.txt")) {
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" || file_exists("/etc/nano_use_vga.txt"))) {
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
		echo "\n<script type=\"text/javascript\">";
1923
		echo "\n//<![CDATA[";
1924
		echo "\nthis.document.forms[0].output.value = \"" . $log . "\";";
1925
		echo "\nthis.document.forms[0].output.scrollTop = this.document.forms[0].output.scrollHeight;";
1926
		echo "\n//]]>";
1927
		echo "\n</script>";
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 "\n<script type=\"text/javascript\">";
1942
		echo "\n//<![CDATA[";
1943
		echo "\nthis.document.forms[0].status.value=\"" . $status . "\";";
1944
		echo "\n//]]>";
1945
		echo "\n</script>";
1946
	}
1947
	/* ensure that contents are written out */
1948
	ob_flush();
1949
}
1950

    
1951
/*
1952
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
1953
 */
1954
function update_progress_bar($percent, $first_time) {
1955
	global $pkg_interface;
1956
	if ($percent > 100) {
1957
		$percent = 1;
1958
	}
1959
	if ($pkg_interface <> "console") {
1960
		echo "\n<script type=\"text/javascript\">";
1961
		echo "\n//<![CDATA[";
1962
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1963
		echo "\n//]]>";
1964
		echo "\n</script>";
1965
	} else {
1966
		if (!($first_time)) {
1967
			echo "\x08\x08\x08\x08\x08";
1968
		}
1969
		echo sprintf("%4d%%", $percent);
1970
	}
1971
}
1972

    
1973
/* 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. */
1974
if (!function_exists("split")) {
1975
	function split($separator, $haystack, $limit = null) {
1976
		log_error("deprecated split() call with separator '{$separator}'");
1977
		return preg_split($separator, $haystack, $limit);
1978
	}
1979
}
1980

    
1981
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
1982
	global $g, $config, $pconfig, $debug;
1983
	if (!$origname) {
1984
		return;
1985
	}
1986

    
1987
	$sectionref = &$config;
1988
	foreach ($section as $sectionname) {
1989
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
1990
			$sectionref = &$sectionref[$sectionname];
1991
		} else {
1992
			return;
1993
		}
1994
	}
1995

    
1996
	if ($debug) {
1997
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
1998
		fwrite($fd, print_r($pconfig, true));
1999
	}
2000

    
2001
	if (is_array($sectionref)) {
2002
		foreach ($sectionref as $itemkey => $item) {
2003
			if ($debug) {
2004
				fwrite($fd, "$itemkey\n");
2005
			}
2006

    
2007
			$fieldfound = true;
2008
			$fieldref = &$sectionref[$itemkey];
2009
			foreach ($field as $fieldname) {
2010
				if (is_array($fieldref) && isset($fieldref[$fieldname])) {
2011
					$fieldref = &$fieldref[$fieldname];
2012
				} else {
2013
					$fieldfound = false;
2014
					break;
2015
				}
2016
			}
2017
			if ($fieldfound && $fieldref == $origname) {
2018
				if ($debug) {
2019
					fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
2020
				}
2021
				$fieldref = $new_alias_name;
2022
			}
2023
		}
2024
	}
2025

    
2026
	if ($debug) {
2027
		fclose($fd);
2028
	}
2029

    
2030
}
2031

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

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

    
2075
function update_alias_url_data() {
2076
	global $config, $g;
2077

    
2078
	$updated = false;
2079

    
2080
	/* item is a url type */
2081
	$lockkey = lock('aliasurl');
2082
	if (is_array($config['aliases']['alias'])) {
2083
		foreach ($config['aliases']['alias'] as $x => $alias) {
2084
			if (empty($alias['aliasurl'])) {
2085
				continue;
2086
			}
2087

    
2088
			$address = null;
2089
			foreach ($alias['aliasurl'] as $alias_url) {
2090
				/* fetch down and add in */
2091
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
2092
				unlink($temp_filename);
2093
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2094
				mkdir($temp_filename);
2095
				download_file($alias_url, $temp_filename . "/aliases", $verify_ssl);
2096

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

    
2120
	/* Report status to callers as well */
2121
	return $updated;
2122
}
2123

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

    
2154
	return true;
2155
}
2156

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

    
2187
	return true;
2188
}
2189

    
2190
function version_compare_dates($a, $b) {
2191
	$a_time = strtotime($a);
2192
	$b_time = strtotime($b);
2193

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

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

    
2278
		// First try to compare the numeric parts of the version string.
2279
		$v = version_compare_numeric($cur_num, $rem_num);
2280

    
2281
		// If the numeric parts are the same, compare the string parts.
2282
		if ($v == 0) {
2283
			return version_compare_string($cur_str, $rem_str);
2284
		}
2285
	}
2286
	return $v;
2287
}
2288
function process_alias_urltable($name, $url, $freq, $forceupdate=false) {
2289
	global $config;
2290

    
2291
	$urltable_prefix = "/var/db/aliastables/";
2292
	$urltable_filename = $urltable_prefix . $name . ".txt";
2293

    
2294
	// Make the aliases directory if it doesn't exist
2295
	if (!file_exists($urltable_prefix)) {
2296
		mkdir($urltable_prefix);
2297
	} elseif (!is_dir($urltable_prefix)) {
2298
		unlink($urltable_prefix);
2299
		mkdir($urltable_prefix);
2300
	}
2301

    
2302
	// If the file doesn't exist or is older than update_freq days, fetch a new copy.
2303
	if (!file_exists($urltable_filename) ||
2304
	    ((time() - filemtime($urltable_filename)) > ($freq * 86400 - 90)) ||
2305
	    $forceupdate) {
2306

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

    
2343
	return "{$boot_drive}s{$active}";
2344
}
2345
function nanobsd_get_size() {
2346
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2347
}
2348
function nanobsd_switch_boot_slice() {
2349
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2350
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2351
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2352
	nanobsd_detect_slice_info();
2353

    
2354
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2355
		$slice = $TOFLASH;
2356
	} else {
2357
		$slice = $BOOTFLASH;
2358
	}
2359

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

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

    
2418
	mkdir($tmppath);
2419
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2420
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2421
	copy("/etc/fstab", $fstabpath);
2422

    
2423
	if (!file_exists($fstabpath)) {
2424
		$fstab = <<<EOF
2425
/dev/ufs/{$gslice} / ufs ro,noatime 1 1
2426
/dev/ufs/cf /cf ufs ro,noatime 1 1
2427
EOF;
2428
		if (file_put_contents($fstabpath, $fstab)) {
2429
			$status = true;
2430
		} else {
2431
			$status = false;
2432
		}
2433
	} else {
2434
		$status = exec("sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2435
	}
2436
	exec("/sbin/umount {$tmppath}");
2437
	rmdir($tmppath);
2438

    
2439
	return $status;
2440
}
2441
function nanobsd_detect_slice_info() {
2442
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2443
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2444
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2445

    
2446
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2447
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2448
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2449
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2450

    
2451
	// Detect which slice is active and set information.
2452
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2453
		$SLICE = "2";
2454
		$OLDSLICE = "1";
2455
		$GLABEL_SLICE = "pfsense1";
2456
		$UFS_ID = "1";
2457
		$OLD_UFS_ID = "0";
2458

    
2459
	} else {
2460
		$SLICE = "1";
2461
		$OLDSLICE = "2";
2462
		$GLABEL_SLICE = "pfsense0";
2463
		$UFS_ID = "0";
2464
		$OLD_UFS_ID = "1";
2465
	}
2466
	$TOFLASH = "{$BOOT_DRIVE}s{$SLICE}";
2467
	$COMPLETE_PATH = "{$BOOT_DRIVE}s{$SLICE}a";
2468
	$COMPLETE_BOOT_PATH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2469
	$BOOTFLASH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2470
}
2471

    
2472
function nanobsd_friendly_slice_name($slicename) {
2473
	global $g;
2474
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2475
}
2476

    
2477
function get_include_contents($filename) {
2478
	if (is_file($filename)) {
2479
		ob_start();
2480
		include $filename;
2481
		$contents = ob_get_contents();
2482
		ob_end_clean();
2483
		return $contents;
2484
	}
2485
	return false;
2486
}
2487

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

    
2600
function get_country_name($country_code) {
2601
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2602
		return "";
2603
	}
2604

    
2605
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2606
	$country_names_contents = file_get_contents($country_names_xml);
2607
	$country_names = xml2array($country_names_contents);
2608

    
2609
	if ($country_code == "ALL") {
2610
		$country_list = array();
2611
		foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2612
			$country_list[] = array(
2613
				"code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2614
				"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])));
2615
		}
2616
		return $country_list;
2617
	}
2618

    
2619
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2620
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2621
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2622
		}
2623
	}
2624
	return "";
2625
}
2626

    
2627
/* sort by interface only, retain the original order of rules that apply to
2628
   the same interface */
2629
function filter_rules_sort() {
2630
	global $config;
2631

    
2632
	/* mark each rule with the sequence number (to retain the order while sorting) */
2633
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2634
		$config['filter']['rule'][$i]['seq'] = $i;
2635
	}
2636

    
2637
	usort($config['filter']['rule'], "filter_rules_compare");
2638

    
2639
	/* strip the sequence numbers again */
2640
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2641
		unset($config['filter']['rule'][$i]['seq']);
2642
	}
2643
}
2644
function filter_rules_compare($a, $b) {
2645
	if (isset($a['floating']) && isset($b['floating'])) {
2646
		return $a['seq'] - $b['seq'];
2647
	} else if (isset($a['floating'])) {
2648
		return -1;
2649
	} else if (isset($b['floating'])) {
2650
		return 1;
2651
	} else if ($a['interface'] == $b['interface']) {
2652
		return $a['seq'] - $b['seq'];
2653
	} else {
2654
		return compare_interface_friendly_names($a['interface'], $b['interface']);
2655
	}
2656
}
2657

    
2658
function generate_ipv6_from_mac($mac) {
2659
	$elements = explode(":", $mac);
2660
	if (count($elements) <> 6) {
2661
		return false;
2662
	}
2663

    
2664
	$i = 0;
2665
	$ipv6 = "fe80::";
2666
	foreach ($elements as $byte) {
2667
		if ($i == 0) {
2668
			$hexadecimal = substr($byte, 1, 2);
2669
			$bitmap = base_convert($hexadecimal, 16, 2);
2670
			$bitmap = str_pad($bitmap, 4, "0", STR_PAD_LEFT);
2671
			$bitmap = substr($bitmap, 0, 2) ."1". substr($bitmap, 3, 4);
2672
			$byte = substr($byte, 0, 1) . base_convert($bitmap, 2, 16);
2673
		}
2674
		$ipv6 .= $byte;
2675
		if ($i == 1) {
2676
			$ipv6 .= ":";
2677
		}
2678
		if ($i == 3) {
2679
			$ipv6 .= ":";
2680
		}
2681
		if ($i == 2) {
2682
			$ipv6 .= "ff:fe";
2683
		}
2684

    
2685
		$i++;
2686
	}
2687
	return $ipv6;
2688
}
2689

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

    
2716
}
2717

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

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

    
2757
	$where_configured = array();
2758

    
2759
	$pos = strpos($ignore_if, '_virtualip');
2760
	if ($pos !== false) {
2761
		$ignore_vip_id = substr($ignore_if, $pos+10);
2762
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2763
	} else {
2764
		$ignore_vip_id = -1;
2765
		$ignore_vip_if = $ignore_if;
2766
	}
2767

    
2768
	$isipv6 = is_ipaddrv6($ipaddr);
2769

    
2770
	if ($check_subnets) {
2771
		$cidrprefix = intval($cidrprefix);
2772
		if ($isipv6) {
2773
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2774
				$cidrprefix = 128;
2775
			}
2776
		} else {
2777
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2778
				$cidrprefix = 32;
2779
			}
2780
		}
2781
		$iflist = get_configured_interface_list();
2782
		foreach ($iflist as $if => $ifname) {
2783
			if ($ignore_if == $if) {
2784
				continue;
2785
			}
2786

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

    
2814
		foreach ($interface_list_ips as $if => $ilips) {
2815
			if ($ignore_if == $if) {
2816
				continue;
2817
			}
2818
			if (strcasecmp($ipaddr, $ilips) == 0) {
2819
				$where_entry = array();
2820
				$where_entry['if'] = $if;
2821
				$where_entry['ip_or_subnet'] = $ilips;
2822
				$where_configured[] = $where_entry;
2823
			}
2824
		}
2825
	}
2826

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

    
2841
	if ($check_localip) {
2842
		if (is_array($config['pptpd']) && !empty($config['pptpd']['localip']) && (strcasecmp($ipaddr, $config['pptpd']['localip']) == 0)) {
2843
			$where_entry = array();
2844
			$where_entry['if'] = 'pptp';
2845
			$where_entry['ip_or_subnet'] = $config['pptpd']['localip'];
2846
			$where_configured[] = $where_entry;
2847
		}
2848

    
2849
		if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0)) {
2850
			$where_entry = array();
2851
			$where_entry['if'] = 'l2tp';
2852
			$where_entry['ip_or_subnet'] = $config['l2tp']['localip'];
2853
			$where_configured[] = $where_entry;
2854
		}
2855
	}
2856

    
2857
	return $where_configured;
2858
}
2859

    
2860
/****f* pfsense-utils/pfSense_handle_custom_code
2861
 * NAME
2862
 *   pfSense_handle_custom_code
2863
 * INPUTS
2864
 *   directory name to process
2865
 * RESULT
2866
 *   globs the directory and includes the files
2867
 */
2868
function pfSense_handle_custom_code($src_dir) {
2869
	// Allow extending of the nat edit page and include custom input validation
2870
	if (is_dir("$src_dir")) {
2871
		$cf = glob($src_dir . "/*.inc");
2872
		foreach ($cf as $nf) {
2873
			if ($nf == "." || $nf == "..") {
2874
				continue;
2875
			}
2876
			// Include the extra handler
2877
			include("$nf");
2878
		}
2879
	}
2880
}
2881

    
2882
function set_language($lang = 'en_US', $encoding = "UTF-8") {
2883
	putenv("LANG={$lang}.{$encoding}");
2884
	setlocale(LC_ALL, "{$lang}.{$encoding}");
2885
	textdomain("pfSense");
2886
	bindtextdomain("pfSense", "/usr/local/share/locale");
2887
	bind_textdomain_codeset("pfSense", "{$lang}.{$encoding}");
2888
}
2889

    
2890
function get_locale_list() {
2891
	$locales = array(
2892
		"en_US" => gettext("English"),
2893
		"pt_BR" => gettext("Portuguese (Brazil)"),
2894
		"tr" => gettext("Turkish"),
2895
	);
2896
	asort($locales);
2897
	return $locales;
2898
}
2899

    
2900
function system_get_language_code() {
2901
	global $config, $g_languages;
2902

    
2903
	// a language code, as per [RFC3066]
2904
	$language = $config['system']['language'];
2905
	//$code = $g_languages[$language]['code'];
2906
	$code = str_replace("_", "-", $language);
2907

    
2908
	if (empty($code)) {
2909
		$code = "en-US"; // Set default code.
2910
	}
2911

    
2912
	return $code;
2913
}
2914

    
2915
function system_get_language_codeset() {
2916
	global $config, $g_languages;
2917

    
2918
	$language = $config['system']['language'];
2919
	$codeset = $g_languages[$language]['codeset'];
2920

    
2921
	if (empty($codeset)) {
2922
		$codeset = "UTF-8"; // Set default codeset.
2923
	}
2924

    
2925
	return $codeset;
2926
}
2927

    
2928
/* Available languages/locales */
2929
$g_languages = array (
2930
	"sq"    => array("codeset" => "UTF-8", "desc" => gettext("Albanian")),
2931
	"bg"    => array("codeset" => "UTF-8", "desc" => gettext("Bulgarian")),
2932
	"zh_CN" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Simplified)")),
2933
	"zh_TW" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Traditional)")),
2934
	"nl"    => array("codeset" => "UTF-8", "desc" => gettext("Dutch")),
2935
	"da"    => array("codeset" => "UTF-8", "desc" => gettext("Danish")),
2936
	"en_US" => array("codeset" => "UTF-8", "desc" => gettext("English")),
2937
	"fi"    => array("codeset" => "UTF-8", "desc" => gettext("Finnish")),
2938
	"fr"    => array("codeset" => "UTF-8", "desc" => gettext("French")),
2939
	"de"    => array("codeset" => "UTF-8", "desc" => gettext("German")),
2940
	"el"    => array("codeset" => "UTF-8", "desc" => gettext("Greek")),
2941
	"hu"    => array("codeset" => "UTF-8", "desc" => gettext("Hungarian")),
2942
	"it"    => array("codeset" => "UTF-8", "desc" => gettext("Italian")),
2943
	"ja"    => array("codeset" => "UTF-8", "desc" => gettext("Japanese")),
2944
	"ko"    => array("codeset" => "UTF-8", "desc" => gettext("Korean")),
2945
	"lv"    => array("codeset" => "UTF-8", "desc" => gettext("Latvian")),
2946
	"nb"    => array("codeset" => "UTF-8", "desc" => gettext("Norwegian (Bokmal)")),
2947
	"pl"    => array("codeset" => "UTF-8", "desc" => gettext("Polish")),
2948
	"pt_BR" => array("codeset" => "UTF-8", "desc" => gettext("Portuguese (Brazil)")),
2949
	"pt"    => array("codeset" => "UTF-8", "desc" => gettext("Portuguese (Portugal)")),
2950
	"ro"    => array("codeset" => "UTF-8", "desc" => gettext("Romanian")),
2951
	"ru"    => array("codeset" => "UTF-8", "desc" => gettext("Russian")),
2952
	"sl"    => array("codeset" => "UTF-8", "desc" => gettext("Slovenian")),
2953
	"tr"    => array("codeset" => "UTF-8", "desc" => gettext("Turkish")),
2954
	"es"    => array("codeset" => "UTF-8", "desc" => gettext("Spanish")),
2955
	"sv"    => array("codeset" => "UTF-8", "desc" => gettext("Swedish")),
2956
	"sk"    => array("codeset" => "UTF-8", "desc" => gettext("Slovak")),
2957
	"cs"    => array("codeset" => "UTF-8", "desc" => gettext("Czech"))
2958
);
2959

    
2960
function return_hex_ipv4($ipv4) {
2961
	if (!is_ipaddrv4($ipv4)) {
2962
		return(false);
2963
	}
2964

    
2965
	/* we need the hex form of the interface IPv4 address */
2966
	$ip4arr = explode(".", $ipv4);
2967
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2968
}
2969

    
2970
function convert_ipv6_to_128bit($ipv6) {
2971
	if (!is_ipaddrv6($ipv6)) {
2972
		return(false);
2973
	}
2974

    
2975
	$ip6arr = array();
2976
	$ip6prefix = Net_IPv6::uncompress($ipv6);
2977
	$ip6arr = explode(":", $ip6prefix);
2978
	/* binary presentation of the prefix for all 128 bits. */
2979
	$ip6prefixbin = "";
2980
	foreach ($ip6arr as $element) {
2981
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
2982
	}
2983
	return($ip6prefixbin);
2984
}
2985

    
2986
function convert_128bit_to_ipv6($ip6bin) {
2987
	if (strlen($ip6bin) <> 128) {
2988
		return(false);
2989
	}
2990

    
2991
	$ip6arr = array();
2992
	$ip6binarr = array();
2993
	$ip6binarr = str_split($ip6bin, 16);
2994
	foreach ($ip6binarr as $binpart) {
2995
		$ip6arr[] = dechex(bindec($binpart));
2996
	}
2997
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2998

    
2999
	return($ip6addr);
3000
}
3001

    
3002

    
3003
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
3004
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
3005
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
3006
/* 6to4 is 16 bits, e.g. 65535 */
3007
function calculate_ipv6_delegation_length($if) {
3008
	global $config;
3009

    
3010
	if (!is_array($config['interfaces'][$if])) {
3011
		return false;
3012
	}
3013

    
3014
	switch ($config['interfaces'][$if]['ipaddrv6']) {
3015
		case "6to4":
3016
			$pdlen = 16;
3017
			break;
3018
		case "6rd":
3019
			$rd6cfg = $config['interfaces'][$if];
3020
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
3021
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
3022
			break;
3023
		case "dhcp6":
3024
			$dhcp6cfg = $config['interfaces'][$if];
3025
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
3026
			break;
3027
		default:
3028
			$pdlen = 0;
3029
			break;
3030
	}
3031
	return($pdlen);
3032
}
3033

    
3034
function huawei_rssi_to_string($rssi) {
3035
	$dbm = array();
3036
	$i = 0;
3037
	$dbstart = -113;
3038
	while ($i < 32) {
3039
		$dbm[$i] = $dbstart + ($i * 2);
3040
		$i++;
3041
	}
3042
	$percent = round(($rssi / 31) * 100);
3043
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
3044
	return $string;
3045
}
3046

    
3047
function huawei_mode_to_string($mode, $submode) {
3048
	$modes[0] = "None";
3049
	$modes[1] = "AMPS";
3050
	$modes[2] = "CDMA";
3051
	$modes[3] = "GSM/GPRS";
3052
	$modes[4] = "HDR";
3053
	$modes[5] = "WCDMA";
3054
	$modes[6] = "GPS";
3055

    
3056
	$submodes[0] = "No Service";
3057
	$submodes[1] = "GSM";
3058
	$submodes[2] = "GPRS";
3059
	$submodes[3] = "EDGE";
3060
	$submodes[4] = "WCDMA";
3061
	$submodes[5] = "HSDPA";
3062
	$submodes[6] = "HSUPA";
3063
	$submodes[7] = "HSDPA+HSUPA";
3064
	$submodes[8] = "TD-SCDMA";
3065
	$submodes[9] = "HSPA+";
3066
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
3067
	return $string;
3068
}
3069

    
3070
function huawei_service_to_string($state) {
3071
	$modes[0] = "No";
3072
	$modes[1] = "Restricted";
3073
	$modes[2] = "Valid";
3074
	$modes[3] = "Restricted Regional";
3075
	$modes[4] = "Powersaving";
3076
	$string = "{$modes[$state]} Service";
3077
	return $string;
3078
}
3079

    
3080
function huawei_simstate_to_string($state) {
3081
	$modes[0] = "Invalid SIM/locked";
3082
	$modes[1] = "Valid SIM";
3083
	$modes[2] = "Invalid SIM CS";
3084
	$modes[3] = "Invalid SIM PS";
3085
	$modes[4] = "Invalid SIM CS/PS";
3086
	$modes[255] = "Missing SIM";
3087
	$string = "{$modes[$state]} State";
3088
	return $string;
3089
}
3090

    
3091
function zte_rssi_to_string($rssi) {
3092
	return huawei_rssi_to_string($rssi);
3093
}
3094

    
3095
function zte_mode_to_string($mode, $submode) {
3096
	$modes[0] = "No Service";
3097
	$modes[1] = "Limited Service";
3098
	$modes[2] = "GPRS";
3099
	$modes[3] = "GSM";
3100
	$modes[4] = "UMTS";
3101
	$modes[5] = "EDGE";
3102
	$modes[6] = "HSDPA";
3103

    
3104
	$submodes[0] = "CS_ONLY";
3105
	$submodes[1] = "PS_ONLY";
3106
	$submodes[2] = "CS_PS";
3107
	$submodes[3] = "CAMPED";
3108
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
3109
	return $string;
3110
}
3111

    
3112
function zte_service_to_string($state) {
3113
	$modes[0] = "Initializing";
3114
	$modes[1] = "Network Lock error";
3115
	$modes[2] = "Network Locked";
3116
	$modes[3] = "Unlocked or correct MCC/MNC";
3117
	$string = "{$modes[$state]} Service";
3118
	return $string;
3119
}
3120

    
3121
function zte_simstate_to_string($state) {
3122
	$modes[0] = "No action";
3123
	$modes[1] = "Network lock";
3124
	$modes[2] = "(U)SIM card lock";
3125
	$modes[3] = "Network Lock and (U)SIM card Lock";
3126
	$string = "{$modes[$state]} State";
3127
	return $string;
3128
}
3129

    
3130
function get_configured_pppoe_server_interfaces() {
3131
	global $config;
3132
	$iflist = array();
3133
	if (is_array($config['pppoes']['pppoe'])) {
3134
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
3135
			if ($pppoe['mode'] == "server") {
3136
				$int = "poes". $pppoe['pppoeid'];
3137
				$iflist[$int] = strtoupper($int);
3138
			}
3139
		}
3140
	}
3141
	return $iflist;
3142
}
3143

    
3144
function get_pppoes_child_interfaces($ifpattern) {
3145
	$if_arr = array();
3146
	if ($ifpattern == "") {
3147
		return;
3148
	}
3149

    
3150
	exec("ifconfig", $out, $ret);
3151
	foreach ($out as $line) {
3152
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3153
			$if_arr[] = $match[1];
3154
		}
3155
	}
3156
	return $if_arr;
3157

    
3158
}
3159

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

    
3200
/* Function to find and return the active XML RPC base URL to avoid code duplication */
3201
function get_active_xml_rpc_base_url() {
3202
	global $config, $g;
3203
	/* If the user has activated the option to enable an alternate xmlrpcbaseurl, and it's not empty, then use it */
3204
	if (isset($config['system']['altpkgrepo']['enable']) && !empty($config['system']['altpkgrepo']['xmlrpcbaseurl'])) {
3205
		return $config['system']['altpkgrepo']['xmlrpcbaseurl'];
3206
	} else {
3207
		return $g['xmlrpcbaseurl'];
3208
	}
3209
}
3210

    
3211
?>
(40-40/68)