Project

General

Profile

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

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

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

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

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

    
34
/*
35
	pfSense_BUILDER_BINARIES:	/sbin/ifconfig	/sbin/pfctl	/usr/local/bin/php /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_servres - get system dns servers
131
 * INPUTS
132
 *   $dns_servers - an array of the dns servers
133
 * RESULT
134
 *   null
135
 ******/
136
function get_dns_servers() {
137
	$dns_servers = array();
138
	$dns_s = file("/etc/resolv.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
139
	foreach ($dns_s as $dns) {
140
		$matches = "";
141
		if (preg_match("/nameserver (.*)/", $dns, $matches)) {
142
			$dns_servers[] = $matches[1];
143
		}
144
	}
145
	return array_unique($dns_servers);
146
}
147

    
148
function hardware_offloading_applyflags($iface) {
149
	global $config;
150

    
151
	$flags_on = 0;
152
	$flags_off = 0;
153
	$options = pfSense_get_interface_addresses($iface);
154

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

    
171
	if (isset($config['system']['disablesegmentationoffloading'])) {
172
		$flags_off |= IFCAP_TSO;
173
	} else if (isset($options['caps']['tso']) || isset($options['caps']['tso4']) || isset($options['caps']['tso6'])) {
174
		$flags_on |= IFCAP_TSO;
175
	}
176

    
177
	if (isset($config['system']['disablelargereceiveoffloading'])) {
178
		$flags_off |= IFCAP_LRO;
179
	} else if (isset($options['caps']['lro'])) {
180
		$flags_on |= IFCAP_LRO;
181
	}
182

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

    
190
	pfSense_interface_capabilities($iface, -$flags_off);
191
	pfSense_interface_capabilities($iface, $flags_on);
192
}
193

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

    
207
	$int = get_real_interface($interface);
208
	if (empty($int)) {
209
		return;
210
	}
211

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

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

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

    
249
	return false;
250
}
251

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

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

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

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

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

    
340
	if (isset($config['system']['polling'])) {
341
		set_single_sysctl("kern.polling.idle_poll", "1");
342
	} else {
343
		set_single_sysctl("kern.polling.idle_poll", "0");
344
	}
345

    
346
	if ($config['system']['polling_each_burst']) {
347
		set_single_sysctl("kern.polling.each_burst", $config['system']['polling_each_burst']);
348
	}
349
	if ($config['system']['polling_burst_max']) {
350
		set_single_sysctl("kern.polling.burst_max", $config['system']['polling_burst_max']);
351
	}
352
	if ($config['system']['polling_user_frac']) {
353
		set_single_sysctl("kern.polling.user_frac", $config['system']['polling_user_frac']);
354
	}
355
}
356

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

    
370
	/* if list */
371
	$iflist = get_configured_interface_list(false, true);
372
	foreach ($iflist as $if => $ifdescr) {
373
		enable_hardware_offloading($if);
374
	}
375
	unset($iflist);
376
}
377

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

    
390
/*
391
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
392

    
393
 */
394
function convert_ip_to_network_format($ip, $subnet) {
395
	$ipsplit = explode('.', $ip);
396
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
397
	return $string;
398
}
399

    
400
/*
401
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
402
 */
403
function get_carp_interface_status($carpinterface) {
404

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

    
422
/*
423
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
424
 */
425
function get_pfsync_interface_status($pfsyncinterface) {
426
	if (!does_interface_exist($pfsyncinterface)) {
427
		return;
428
	}
429

    
430
	return exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/awk '/pfsync:/ {print \$5}'");
431
}
432

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

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

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

    
471
/*
472
 * get_filename_from_url($url): converts a url to its filename.
473
 */
474
function get_filename_from_url($url) {
475
	return basename($url);
476
}
477

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

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

    
501
	for ($a=0; $a < 6; $a++) {
502
		$hw_addr .= chr(hexdec($addr_byte[$a]));
503
	}
504

    
505
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
506

    
507
	for ($a = 1; $a <= 16; $a++) {
508
		$msg .= $hw_addr;
509
	}
510

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

    
528
	return false;
529
}
530

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

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

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

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

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

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

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

    
639
";
640

    
641
	$errno = "";
642
	$errstr = "";
643
	$fp = fsockopen($server, $port, $errno, $errstr);
644
	if (!$fp) {
645
		return false;
646
	}
647

    
648
	fputs($fp, $headers);
649
	fputs($fp, $urlencoded);
650

    
651
	$ret = "";
652
	while (!feof($fp)) {
653
		$ret .= fgets($fp, 1024);
654
	}
655
	fclose($fp);
656

    
657
	return $ret;
658
}
659

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

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

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

    
738
/*
739
 * call_pfsense_method(): Call a method exposed by the pfsense.org XMLRPC server.
740
 */
741
function call_pfsense_method($method, $params, $timeout = 0) {
742
	global $g, $config;
743

    
744
	$xmlrpc_base_url = get_active_xml_rpc_base_url();
745
	$xmlrpc_path = $g['xmlrpcpath'];
746

    
747
	$xmlrpcfqdn = preg_replace("(https?://)", "", $xmlrpc_base_url);
748
	$ip = gethostbyname($xmlrpcfqdn);
749
	if ($ip == $xmlrpcfqdn) {
750
		return false;
751
	}
752

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

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

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

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

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

    
832
	return $versions;
833
}
834

    
835
/*
836
 * host_firmware_version(): Return the versions used in this install
837
 */
838
function host_firmware_version($tocheck = "") {
839
	global $g, $config;
840

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

    
843
	return array(
844
		"firmware" => array("version" => trim(file_get_contents('/etc/version', " \n"))),
845
		"kernel"   => array("version" => $os_version),
846
		"base"     => array("version" => $os_version),
847
		"platform" => trim(file_get_contents('/etc/platform', " \n")),
848
		"config_version" => $config['version']
849
	);
850
}
851

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

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

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

    
885
	if ($g['debug']) {
886
		log_error(gettext("reload_interfaces_sync() is starting."));
887
	}
888

    
889
	/* parse config.xml again */
890
	$config = parse_config(true);
891

    
892
	/* enable routing */
893
	system_routing_enable();
894
	if ($g['debug']) {
895
		log_error(gettext("Enabling system routing"));
896
	}
897

    
898
	if ($g['debug']) {
899
		log_error(gettext("Cleaning up Interfaces"));
900
	}
901

    
902
	/* set up interfaces */
903
	interfaces_configure();
904
}
905

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

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

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

    
941
	/* parse config.xml again */
942
	$config = parse_config(true);
943

    
944
	/* set up our timezone */
945
	system_timezone_configure();
946

    
947
	/* set up our hostname */
948
	system_hostname_configure();
949

    
950
	/* make hosts file */
951
	system_hosts_generate();
952

    
953
	/* generate resolv.conf */
954
	system_resolvconf_generate();
955

    
956
	/* enable routing */
957
	system_routing_enable();
958

    
959
	/* set up interfaces */
960
	interfaces_configure();
961

    
962
	/* start dyndns service */
963
	services_dyndns_configure();
964

    
965
	/* configure cron service */
966
	configure_cron();
967

    
968
	/* start the NTP client */
969
	system_ntp_configure();
970

    
971
	/* sync pw database */
972
	conf_mount_rw();
973
	unlink_if_exists("/etc/spwd.db.tmp");
974
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
975
	conf_mount_ro();
976

    
977
	/* restart sshd */
978
	send_event("service restart sshd");
979

    
980
	/* restart webConfigurator if needed */
981
	send_event("service restart webgui");
982
}
983

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

    
997
	$serialspeed = (is_numeric($config['system']['serialspeed'])) ? $config['system']['serialspeed'] : "115200";
998
	if ($g['platform'] != "cdrom") {
999
		$serial_only = false;
1000

    
1001
		if (($g['platform'] == "nanobsd") && !file_exists("/etc/nano_use_vga.txt")) {
1002
			$serial_only = true;
1003
		} else {
1004
			$specific_platform = system_identify_specific_platform();
1005
			if ($specific_platform['name'] == 'RCC-VE') {
1006
				$serial_only = true;
1007
			}
1008
		}
1009

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

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

    
1052
			if ($serial_only === true) {
1053
				$new_boot_config[] = 'boot_serial="YES"';
1054
				$new_boot_config[] = 'console="comconsole"';
1055
			} else if (is_serial_enabled()) {
1056
				$new_boot_config[] = 'boot_multicons="YES"';
1057
				$new_boot_config[] = 'boot_serial="YES"';
1058
				$primaryconsole = isset($g['primaryconsole_force']) ? $g['primaryconsole_force'] : $config['system']['primaryconsole'];
1059
				switch ($primaryconsole) {
1060
					case "video":
1061
						$new_boot_config[] = 'console="vidconsole,comconsole"';
1062
						break;
1063
					case "serial":
1064
					default:
1065
						$new_boot_config[] = 'console="comconsole,vidconsole"';
1066
				}
1067
			}
1068
			$new_boot_config[] = 'comconsole_speed="' . $serialspeed . '"';
1069
			
1070
			$specplatform = system_identify_specific_platform();
1071
			if ($specplatform['name'] == "RCC-VE") {
1072
				$new_boot_config[] = 'comconsole_port="0x2F8"';
1073
				$new_boot_config[] = 'hint.uart.0.flags="0x00"';
1074
				$new_boot_config[] = 'hint.uart.1.flags="0x10"';
1075
			}
1076
			$new_boot_config[] = 'hw.usb.no_pf="1"';
1077

    
1078
			file_put_contents($loader_conf_file, implode("\n", $new_boot_config) . "\n");
1079
		}
1080
	}
1081
	$ttys = file_get_contents($ttys_file);
1082
	$ttys_split = explode("\n", $ttys);
1083
	$fd = fopen($ttys_file, "w");
1084

    
1085
	$on_off = (is_serial_enabled() ? 'onifconsole' : 'off');
1086

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

    
1110
	conf_mount_ro();
1111
	return;
1112
}
1113

    
1114
function is_serial_enabled() {
1115
	global $g, $config;
1116

    
1117
	if (!isset($g['enableserial_force']) &&
1118
	    !isset($config['system']['enableserial']) &&
1119
	    ($g['platform'] == "pfSense" || $g['platform'] == "cdrom" || file_exists("/etc/nano_use_vga.txt"))) {
1120
		return false;
1121
	}
1122

    
1123
	return true;
1124
}
1125

    
1126
function reload_ttys() {
1127
	// Send a HUP signal to init will make it reload /etc/ttys
1128
	posix_kill(1, SIGHUP);
1129
}
1130

    
1131
function print_value_list($list, $count = 10, $separator = ",") {
1132
	$list = implode($separator, array_slice($list, 0, $count));
1133
	if (count($list) < $count) {
1134
		$list .= ".";
1135
	} else {
1136
		$list .= "...";
1137
	}
1138
	return $list;
1139
}
1140

    
1141
/* DHCP enabled on any interfaces? */
1142
function is_dhcp_server_enabled() {
1143
	global $config;
1144

    
1145
	if (!is_array($config['dhcpd'])) {
1146
		return false;
1147
	}
1148

    
1149
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1150
		if (isset($dhcpifconf['enable']) && !empty($config['interfaces'][$dhcpif])) {
1151
			return true;
1152
		}
1153
	}
1154

    
1155
	return false;
1156
}
1157

    
1158
/* DHCP enabled on any interfaces? */
1159
function is_dhcpv6_server_enabled() {
1160
	global $config;
1161

    
1162
	if (is_array($config['interfaces'])) {
1163
		foreach ($config['interfaces'] as $ifcfg) {
1164
			if (isset($ifcfg['enable']) && !empty($ifcfg['track6-interface'])) {
1165
				return true;
1166
			}
1167
		}
1168
	}
1169

    
1170
	if (!is_array($config['dhcpdv6'])) {
1171
		return false;
1172
	}
1173

    
1174
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
1175
		if (isset($dhcpv6ifconf['enable']) && !empty($config['interfaces'][$dhcpv6if])) {
1176
			return true;
1177
		}
1178
	}
1179

    
1180
	return false;
1181
}
1182

    
1183
/* radvd enabled on any interfaces? */
1184
function is_radvd_enabled() {
1185
	global $config;
1186

    
1187
	if (!is_array($config['dhcpdv6'])) {
1188
		$config['dhcpdv6'] = array();
1189
	}
1190

    
1191
	$dhcpdv6cfg = $config['dhcpdv6'];
1192
	$Iflist = get_configured_interface_list();
1193

    
1194
	/* handle manually configured DHCP6 server settings first */
1195
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1196
		if (!isset($config['interfaces'][$dhcpv6if]['enable'])) {
1197
			continue;
1198
		}
1199

    
1200
		if (!isset($dhcpv6ifconf['ramode'])) {
1201
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
1202
		}
1203

    
1204
		if ($dhcpv6ifconf['ramode'] == "disabled") {
1205
			continue;
1206
		}
1207

    
1208
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1209
		if (!is_ipaddrv6($ifcfgipv6)) {
1210
			continue;
1211
		}
1212

    
1213
		return true;
1214
	}
1215

    
1216
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
1217
	foreach ($Iflist as $if => $ifdescr) {
1218
		if (!isset($config['interfaces'][$if]['track6-interface'])) {
1219
			continue;
1220
		}
1221
		if (!isset($config['interfaces'][$if]['enable'])) {
1222
			continue;
1223
		}
1224

    
1225
		$ifcfgipv6 = get_interface_ipv6($if);
1226
		if (!is_ipaddrv6($ifcfgipv6)) {
1227
			continue;
1228
		}
1229

    
1230
		$ifcfgsnv6 = get_interface_subnetv6($if);
1231
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1232

    
1233
		if (!is_ipaddrv6($subnetv6)) {
1234
			continue;
1235
		}
1236

    
1237
		return true;
1238
	}
1239

    
1240
	return false;
1241
}
1242

    
1243
/* Any PPPoE servers enabled? */
1244
function is_pppoe_server_enabled() {
1245
	global $config;
1246

    
1247
	$pppoeenable = false;
1248

    
1249
	if (!is_array($config['pppoes']) || !is_array($config['pppoes']['pppoe'])) {
1250
		return false;
1251
	}
1252

    
1253
	foreach ($config['pppoes']['pppoe'] as $pppoes) {
1254
		if ($pppoes['mode'] == 'server') {
1255
			$pppoeenable = true;
1256
		}
1257
	}
1258

    
1259
	return $pppoeenable;
1260
}
1261

    
1262
function convert_seconds_to_hms($sec) {
1263
	$min=$hrs=0;
1264
	if ($sec != 0) {
1265
		$min = floor($sec/60);
1266
		$sec %= 60;
1267
	}
1268
	if ($min != 0) {
1269
		$hrs = floor($min/60);
1270
		$min %= 60;
1271
	}
1272
	if ($sec < 10) {
1273
		$sec = "0".$sec;
1274
	}
1275
	if ($min < 10) {
1276
		$min = "0".$min;
1277
	}
1278
	if ($hrs < 10) {
1279
		$hrs = "0".$hrs;
1280
	}
1281
	$result = $hrs.":".$min.":".$sec;
1282
	return $result;
1283
}
1284

    
1285
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1286

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

    
1302
//returns interface information
1303
function get_interface_info($ifdescr) {
1304
	global $config, $g;
1305

    
1306
	$ifinfo = array();
1307
	if (empty($config['interfaces'][$ifdescr])) {
1308
		return;
1309
	}
1310
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
1311
	$ifinfo['if'] = get_real_interface($ifdescr);
1312

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

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

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

    
1374
	$ifinfo['inbytes'] = $in4_pass + $in6_pass;
1375
	$ifinfo['outbytes'] = $out4_pass + $out6_pass;
1376
	$ifinfo['inpkts'] = $in4_pass_packets + $in6_pass_packets;
1377
	$ifinfo['outpkts'] = $out4_pass_packets + $out6_pass_packets;
1378

    
1379
	$ifconfiginfo = "";
1380
	$link_type = $config['interfaces'][$ifdescr]['ipaddr'];
1381
	switch ($link_type) {
1382
		/* DHCP? -> see if dhclient is up */
1383
		case "dhcp":
1384
			/* see if dhclient is up */
1385
			if (find_dhclient_process($ifinfo['if']) != 0) {
1386
				$ifinfo['dhcplink'] = "up";
1387
			} else {
1388
				$ifinfo['dhcplink'] = "down";
1389
			}
1390

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

    
1403
			break;
1404
		/* PPP interface? -> get uptime for this session and cumulative uptime from the persistent log file in conf */
1405
		case "ppp":
1406
			if ($ifinfo['status'] == "up") {
1407
				$ifinfo['ppplink'] = "up";
1408
			} else {
1409
				$ifinfo['ppplink'] = "down" ;
1410
			}
1411

    
1412
			if (empty($ifinfo['status'])) {
1413
				$ifinfo['status'] = "down";
1414
			}
1415

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

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

    
1467
	if (file_exists("{$g['varrun_path']}/{$link_type}_{$ifdescr}.pid")) {
1468
		$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1469
		$ifinfo['ppp_uptime'] = convert_seconds_to_hms($sec);
1470
	}
1471

    
1472
	if ($ifinfo['status'] == "up") {
1473
		/* try to determine media with ifconfig */
1474
		unset($ifconfiginfo);
1475
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1476
		$wifconfiginfo = array();
1477
		if (is_interface_wireless($ifdescr)) {
1478
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1479
			array_shift($wifconfiginfo);
1480
		}
1481
		$matches = "";
1482
		foreach ($ifconfiginfo as $ici) {
1483

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

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

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

    
1555
	return $ifinfo;
1556
}
1557

    
1558
//returns cpu speed of processor. Good for determining capabilities of machine
1559
function get_cpu_speed() {
1560
	return get_single_sysctl("hw.clockrate");
1561
}
1562

    
1563
function get_uptime_sec() {
1564
	$boottime = "";
1565
	$matches = "";
1566
	$boottime = get_single_sysctl("kern.boottime");
1567
	preg_match("/sec = (\d+)/", $boottime, $matches);
1568
	$boottime = $matches[1];
1569
	if (intval($boottime) == 0) {
1570
		return 0;
1571
	}
1572

    
1573
	$uptime = time() - $boottime;
1574
	return $uptime;
1575
}
1576

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

    
1610
function is_fqdn($fqdn) {
1611
	$hostname = false;
1612
	if (preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1613
		$hostname = true;
1614
	}
1615
	if (preg_match("/\.\./", $fqdn)) {
1616
		$hostname = false;
1617
	}
1618
	if (preg_match("/^\./i", $fqdn)) {
1619
		$hostname = false;
1620
	}
1621
	if (preg_match("/\//i", $fqdn)) {
1622
		$hostname = false;
1623
	}
1624
	return($hostname);
1625
}
1626

    
1627
function pfsense_default_state_size() {
1628
	/* get system memory amount */
1629
	$memory = get_memory();
1630
	$physmem = $memory[0];
1631
	/* Be cautious and only allocate 10% of system memory to the state table */
1632
	$max_states = (int) ($physmem/10)*1000;
1633
	return $max_states;
1634
}
1635

    
1636
function pfsense_default_tables_size() {
1637
	$current = `pfctl -sm | grep ^tables | awk '{print $4};'`;
1638
	return $current;
1639
}
1640

    
1641
function pfsense_default_table_entries_size() {
1642
	$current = `pfctl -sm | grep table-entries | awk '{print $4};'`;
1643
	return $current;
1644
}
1645

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

    
1682
	if (trim($oldcontents) != trim($contents)) {
1683
		if ($g['debug']) {
1684
			log_error(sprintf(gettext('DNSCACHE: Found old IP %1$s and new IP %2$s'), $oldcontents, $contents));
1685
		}
1686
		return ($oldcontents);
1687
	} else {
1688
		return false;
1689
	}
1690
}
1691

    
1692
/*
1693
 * load_crypto() - Load crypto modules if enabled in config.
1694
 */
1695
function load_crypto() {
1696
	global $config, $g;
1697
	$crypto_modules = array('glxsb', 'aesni');
1698

    
1699
	if (!in_array($config['system']['crypto_hardware'], $crypto_modules)) {
1700
		return false;
1701
	}
1702

    
1703
	if (!empty($config['system']['crypto_hardware']) && !is_module_loaded($config['system']['crypto_hardware'])) {
1704
		log_error("Loading {$config['system']['crypto_hardware']} cryptographic accelerator module.");
1705
		mwexec("/sbin/kldload {$config['system']['crypto_hardware']}");
1706
	}
1707
}
1708

    
1709
/*
1710
 * load_thermal_hardware() - Load temperature monitor kernel module
1711
 */
1712
function load_thermal_hardware() {
1713
	global $config, $g;
1714
	$thermal_hardware_modules = array('coretemp', 'amdtemp');
1715

    
1716
	if (!in_array($config['system']['thermal_hardware'], $thermal_hardware_modules)) {
1717
		return false;
1718
	}
1719

    
1720
	if (!empty($config['system']['thermal_hardware']) && !is_module_loaded($config['system']['thermal_hardware'])) {
1721
		log_error("Loading {$config['system']['thermal_hardware']} thermal monitor module.");
1722
		mwexec("/sbin/kldload {$config['system']['thermal_hardware']}");
1723
	}
1724
}
1725

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

    
1738
	if ($rc != 0 || !isset($output[0])) {
1739
		return false;
1740
	}
1741

    
1742
	foreach ($virtualenvs as $virtualenv) {
1743
		if (stripos($output[0], $virtualenv) !== false) {
1744
			return true;
1745
		}
1746
	}
1747

    
1748
	return false;
1749
}
1750

    
1751
function get_freebsd_version() {
1752
	$version = explode(".", php_uname("r"));
1753
	return $version[0];
1754
}
1755

    
1756
function download_file($url, $destination, $verify_ssl = true, $connect_timeout = 5, $timeout = 0) {
1757
	global $config, $g;
1758

    
1759
	$fp = fopen($destination, "wb");
1760

    
1761
	if (!$fp) {
1762
		return false;
1763
	}
1764

    
1765
	$ch = curl_init();
1766
	curl_setopt($ch, CURLOPT_URL, $url);
1767
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1768
	curl_setopt($ch, CURLOPT_FILE, $fp);
1769
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1770
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1771
	curl_setopt($ch, CURLOPT_HEADER, false);
1772
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1773
	curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version") . ' : ' . get_single_sysctl('kern.hostuuid')));
1774

    
1775
	if (!empty($config['system']['proxyurl'])) {
1776
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1777
		if (!empty($config['system']['proxyport'])) {
1778
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1779
		}
1780
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1781
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1782
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1783
		}
1784
	}
1785

    
1786
	@curl_exec($ch);
1787
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1788
	fclose($fp);
1789
	curl_close($ch);
1790
	return ($http_code == 200) ? true : $http_code;
1791
}
1792

    
1793
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body', $connect_timeout = 5, $timeout=0) {
1794
	global $ch, $fout, $file_size, $downloaded, $config, $first_progress_update, $g;
1795
	$file_size  = 1;
1796
	$downloaded = 1;
1797
	$first_progress_update = TRUE;
1798
	/* open destination file */
1799
	$fout = fopen($destination_file, "wb");
1800

    
1801
	/*
1802
	 *      Originally by Author: Keyvan Minoukadeh
1803
	 *      Modified by Scott Ullrich to return Content-Length size
1804
	 */
1805

    
1806
	$ch = curl_init();
1807
	curl_setopt($ch, CURLOPT_URL, $url_file);
1808
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1809
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1810
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1811
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1812
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1813
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1814
	curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version") . ' : ' . get_single_sysctl('kern.hostuuid')));
1815

    
1816
	if (!empty($config['system']['proxyurl'])) {
1817
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1818
		if (!empty($config['system']['proxyport'])) {
1819
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1820
		}
1821
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1822
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1823
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1824
		}
1825
	}
1826

    
1827
	@curl_exec($ch);
1828
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1829
	if ($fout) {
1830
		fclose($fout);
1831
	}
1832
	curl_close($ch);
1833
	return ($http_code == 200) ? true : $http_code;
1834
}
1835

    
1836
function read_header($ch, $string) {
1837
	global $file_size, $fout;
1838
	$length = strlen($string);
1839
	$regs = "";
1840
	preg_match("/(Content-Length:) (.*)/", $string, $regs);
1841
	if ($regs[2] <> "") {
1842
		$file_size = intval($regs[2]);
1843
	}
1844
	ob_flush();
1845
	return $length;
1846
}
1847

    
1848
function read_body($ch, $string) {
1849
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen, $first_progress_update;
1850
	global $pkg_interface;
1851
	$length = strlen($string);
1852
	$downloaded += intval($length);
1853
	if ($file_size > 0) {
1854
		$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1855
		$downloadProgress = 100 - $downloadProgress;
1856
	} else {
1857
		$downloadProgress = 0;
1858
	}
1859
	if ($lastseen <> $downloadProgress and $downloadProgress < 101) {
1860
		if ($sendto == "status") {
1861
			if ($pkg_interface == "console") {
1862
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1863
					$tostatus = $static_status . $downloadProgress . "%";
1864
					if ($downloadProgress == 100) {
1865
						$tostatus = $tostatus . "\r";
1866
					}
1867
					update_status($tostatus);
1868
				}
1869
			} else {
1870
				$tostatus = $static_status . $downloadProgress . "%";
1871
				update_status($tostatus);
1872
			}
1873
		} else {
1874
			if ($pkg_interface == "console") {
1875
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1876
					$tooutput = $static_output . $downloadProgress . "%";
1877
					if ($downloadProgress == 100) {
1878
						$tooutput = $tooutput . "\r";
1879
					}
1880
					update_output_window($tooutput);
1881
				}
1882
			} else {
1883
				$tooutput = $static_output . $downloadProgress . "%";
1884
				update_output_window($tooutput);
1885
			}
1886
		}
1887
		if (($pkg_interface != "console") || (($downloadProgress % 10) == 0) || ($downloadProgress < 10)) {
1888
			update_progress_bar($downloadProgress, $first_progress_update);
1889
			$first_progress_update = FALSE;
1890
		}
1891
		$lastseen = $downloadProgress;
1892
	}
1893
	if ($fout) {
1894
		fwrite($fout, $string);
1895
	}
1896
	ob_flush();
1897
	return $length;
1898
}
1899

    
1900
/*
1901
 *   update_output_window: update bottom textarea dynamically.
1902
 */
1903
function update_output_window($text) {
1904
	global $pkg_interface;
1905
	$log = preg_replace("/\n/", "\\n", $text);
1906
	if ($pkg_interface != "console") {
1907
		echo "\n<script type=\"text/javascript\">";
1908
		echo "\n//<![CDATA[";
1909
		echo "\nthis.document.forms[0].output.value = \"" . $log . "\";";
1910
		echo "\nthis.document.forms[0].output.scrollTop = this.document.forms[0].output.scrollHeight;";
1911
		echo "\n//]]>";
1912
		echo "\n</script>";
1913
	}
1914
	/* ensure that contents are written out */
1915
	ob_flush();
1916
}
1917

    
1918
/*
1919
 *   update_status: update top textarea dynamically.
1920
 */
1921
function update_status($status) {
1922
	global $pkg_interface;
1923
	if ($pkg_interface == "console") {
1924
		echo "\r{$status}";
1925
	} else {
1926
		echo "\n<script type=\"text/javascript\">";
1927
		echo "\n//<![CDATA[";
1928
		echo "\nthis.document.forms[0].status.value=\"" . $status . "\";";
1929
		echo "\n//]]>";
1930
		echo "\n</script>";
1931
	}
1932
	/* ensure that contents are written out */
1933
	ob_flush();
1934
}
1935

    
1936
/*
1937
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
1938
 */
1939
function update_progress_bar($percent, $first_time) {
1940
	global $pkg_interface;
1941
	if ($percent > 100) {
1942
		$percent = 1;
1943
	}
1944
	if ($pkg_interface <> "console") {
1945
		echo "\n<script type=\"text/javascript\">";
1946
		echo "\n//<![CDATA[";
1947
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1948
		echo "\n//]]>";
1949
		echo "\n</script>";
1950
	} else {
1951
		if (!($first_time)) {
1952
			echo "\x08\x08\x08\x08\x08";
1953
		}
1954
		echo sprintf("%4d%%", $percent);
1955
	}
1956
}
1957

    
1958
/* 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. */
1959
if (!function_exists("split")) {
1960
	function split($separator, $haystack, $limit = null) {
1961
		log_error("deprecated split() call with separator '{$separator}'");
1962
		return preg_split($separator, $haystack, $limit);
1963
	}
1964
}
1965

    
1966
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
1967
	global $g, $config, $pconfig, $debug;
1968
	if (!$origname) {
1969
		return;
1970
	}
1971

    
1972
	$sectionref = &$config;
1973
	foreach ($section as $sectionname) {
1974
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
1975
			$sectionref = &$sectionref[$sectionname];
1976
		} else {
1977
			return;
1978
		}
1979
	}
1980

    
1981
	if ($debug) {
1982
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
1983
		fwrite($fd, print_r($pconfig, true));
1984
	}
1985

    
1986
	if (is_array($sectionref)) {
1987
		foreach ($sectionref as $itemkey => $item) {
1988
			if ($debug) {
1989
				fwrite($fd, "$itemkey\n");
1990
			}
1991

    
1992
			$fieldfound = true;
1993
			$fieldref = &$sectionref[$itemkey];
1994
			foreach ($field as $fieldname) {
1995
				if (is_array($fieldref) && isset($fieldref[$fieldname])) {
1996
					$fieldref = &$fieldref[$fieldname];
1997
				} else {
1998
					$fieldfound = false;
1999
					break;
2000
				}
2001
			}
2002
			if ($fieldfound && $fieldref == $origname) {
2003
				if ($debug) {
2004
					fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
2005
				}
2006
				$fieldref = $new_alias_name;
2007
			}
2008
		}
2009
	}
2010

    
2011
	if ($debug) {
2012
		fclose($fd);
2013
	}
2014

    
2015
}
2016

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

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

    
2060
function update_alias_url_data() {
2061
	global $config, $g;
2062

    
2063
	$updated = false;
2064

    
2065
	/* item is a url type */
2066
	$lockkey = lock('aliasurl');
2067
	if (is_array($config['aliases']['alias'])) {
2068
		foreach ($config['aliases']['alias'] as $x => $alias) {
2069
			if (empty($alias['aliasurl'])) {
2070
				continue;
2071
			}
2072

    
2073
			$address = null;
2074
			foreach ($alias['aliasurl'] as $alias_url) {
2075
				/* fetch down and add in */
2076
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
2077
				unlink($temp_filename);
2078
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2079
				mkdir($temp_filename);
2080
				download_file($alias_url, $temp_filename . "/aliases", $verify_ssl);
2081

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

    
2105
	/* Report status to callers as well */
2106
	return $updated;
2107
}
2108

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

    
2139
	return true;
2140
}
2141

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

    
2172
	return true;
2173
}
2174

    
2175
function version_compare_dates($a, $b) {
2176
	$a_time = strtotime($a);
2177
	$b_time = strtotime($b);
2178

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

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

    
2263
		// First try to compare the numeric parts of the version string.
2264
		$v = version_compare_numeric($cur_num, $rem_num);
2265

    
2266
		// If the numeric parts are the same, compare the string parts.
2267
		if ($v == 0) {
2268
			return version_compare_string($cur_str, $rem_str);
2269
		}
2270
	}
2271
	return $v;
2272
}
2273
function process_alias_urltable($name, $url, $freq, $forceupdate=false) {
2274
	global $config;
2275

    
2276
	$urltable_prefix = "/var/db/aliastables/";
2277
	$urltable_filename = $urltable_prefix . $name . ".txt";
2278

    
2279
	// Make the aliases directory if it doesn't exist
2280
	if (!file_exists($urltable_prefix)) {
2281
		mkdir($urltable_prefix);
2282
	} elseif (!is_dir($urltable_prefix)) {
2283
		unlink($urltable_prefix);
2284
		mkdir($urltable_prefix);
2285
	}
2286

    
2287
	// If the file doesn't exist or is older than update_freq days, fetch a new copy.
2288
	if (!file_exists($urltable_filename) ||
2289
	    ((time() - filemtime($urltable_filename)) > ($freq * 86400 - 90)) ||
2290
	    $forceupdate) {
2291

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

    
2328
	return "{$boot_drive}s{$active}";
2329
}
2330
function nanobsd_get_size() {
2331
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2332
}
2333
function nanobsd_switch_boot_slice() {
2334
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2335
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2336
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2337
	nanobsd_detect_slice_info();
2338

    
2339
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2340
		$slice = $TOFLASH;
2341
	} else {
2342
		$slice = $BOOTFLASH;
2343
	}
2344

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

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

    
2403
	mkdir($tmppath);
2404
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2405
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2406
	copy("/etc/fstab", $fstabpath);
2407

    
2408
	if (!file_exists($fstabpath)) {
2409
		$fstab = <<<EOF
2410
/dev/ufs/{$gslice} / ufs ro,noatime 1 1
2411
/dev/ufs/cf /cf ufs ro,noatime 1 1
2412
EOF;
2413
		if (file_put_contents($fstabpath, $fstab)) {
2414
			$status = true;
2415
		} else {
2416
			$status = false;
2417
		}
2418
	} else {
2419
		$status = exec("sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2420
	}
2421
	exec("/sbin/umount {$tmppath}");
2422
	rmdir($tmppath);
2423

    
2424
	return $status;
2425
}
2426
function nanobsd_detect_slice_info() {
2427
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2428
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2429
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2430

    
2431
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2432
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2433
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2434
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2435

    
2436
	// Detect which slice is active and set information.
2437
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2438
		$SLICE="2";
2439
		$OLDSLICE="1";
2440
		$GLABEL_SLICE="pfsense1";
2441
		$UFS_ID="1";
2442
		$OLD_UFS_ID="0";
2443

    
2444
	} else {
2445
		$SLICE="1";
2446
		$OLDSLICE="2";
2447
		$GLABEL_SLICE="pfsense0";
2448
		$UFS_ID="0";
2449
		$OLD_UFS_ID="1";
2450
	}
2451
	$TOFLASH="{$BOOT_DRIVE}s{$SLICE}";
2452
	$COMPLETE_PATH="{$BOOT_DRIVE}s{$SLICE}a";
2453
	$COMPLETE_BOOT_PATH="{$BOOT_DRIVE}s{$OLDSLICE}";
2454
	$BOOTFLASH="{$BOOT_DRIVE}s{$OLDSLICE}";
2455
}
2456

    
2457
function nanobsd_friendly_slice_name($slicename) {
2458
	global $g;
2459
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2460
}
2461

    
2462
function get_include_contents($filename) {
2463
	if (is_file($filename)) {
2464
		ob_start();
2465
		include $filename;
2466
		$contents = ob_get_contents();
2467
		ob_end_clean();
2468
		return $contents;
2469
	}
2470
	return false;
2471
}
2472

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

    
2585
function get_country_name($country_code) {
2586
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2587
		return "";
2588
	}
2589

    
2590
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2591
	$country_names_contents = file_get_contents($country_names_xml);
2592
	$country_names = xml2array($country_names_contents);
2593

    
2594
	if ($country_code == "ALL") {
2595
		$country_list = array();
2596
		foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2597
			$country_list[] = array(
2598
				"code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2599
				"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])));
2600
		}
2601
		return $country_list;
2602
	}
2603

    
2604
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2605
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2606
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2607
		}
2608
	}
2609
	return "";
2610
}
2611

    
2612
/* sort by interface only, retain the original order of rules that apply to
2613
   the same interface */
2614
function filter_rules_sort() {
2615
	global $config;
2616

    
2617
	/* mark each rule with the sequence number (to retain the order while sorting) */
2618
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2619
		$config['filter']['rule'][$i]['seq'] = $i;
2620
	}
2621

    
2622
	usort($config['filter']['rule'], "filter_rules_compare");
2623

    
2624
	/* strip the sequence numbers again */
2625
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2626
		unset($config['filter']['rule'][$i]['seq']);
2627
	}
2628
}
2629
function filter_rules_compare($a, $b) {
2630
	if (isset($a['floating']) && isset($b['floating'])) {
2631
		return $a['seq'] - $b['seq'];
2632
	} else if (isset($a['floating'])) {
2633
		return -1;
2634
	} else if (isset($b['floating'])) {
2635
		return 1;
2636
	} else if ($a['interface'] == $b['interface']) {
2637
		return $a['seq'] - $b['seq'];
2638
	} else {
2639
		return compare_interface_friendly_names($a['interface'], $b['interface']);
2640
	}
2641
}
2642

    
2643
function generate_ipv6_from_mac($mac) {
2644
	$elements = explode(":", $mac);
2645
	if (count($elements) <> 6) {
2646
		return false;
2647
	}
2648

    
2649
	$i = 0;
2650
	$ipv6 = "fe80::";
2651
	foreach ($elements as $byte) {
2652
		if ($i == 0) {
2653
			$hexadecimal =  substr($byte, 1, 2);
2654
			$bitmap = base_convert($hexadecimal, 16, 2);
2655
			$bitmap = str_pad($bitmap, 4, "0", STR_PAD_LEFT);
2656
			$bitmap = substr($bitmap, 0, 2) ."1". substr($bitmap, 3, 4);
2657
			$byte = substr($byte, 0, 1) . base_convert($bitmap, 2, 16);
2658
		}
2659
		$ipv6 .= $byte;
2660
		if ($i == 1) {
2661
			$ipv6 .= ":";
2662
		}
2663
		if ($i == 3) {
2664
			$ipv6 .= ":";
2665
		}
2666
		if ($i == 2) {
2667
			$ipv6 .= "ff:fe";
2668
		}
2669

    
2670
		$i++;
2671
	}
2672
	return $ipv6;
2673
}
2674

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

    
2701
}
2702

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

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

    
2742
	$where_configured = array();
2743

    
2744
	$pos = strpos($ignore_if, '_virtualip');
2745
	if ($pos !== false) {
2746
		$ignore_vip_id = substr($ignore_if, $pos+10);
2747
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2748
	} else {
2749
		$ignore_vip_id = -1;
2750
		$ignore_vip_if = $ignore_if;
2751
	}
2752

    
2753
	$isipv6 = is_ipaddrv6($ipaddr);
2754

    
2755
	if ($check_subnets) {
2756
		$cidrprefix = intval($cidrprefix);
2757
		if ($isipv6) {
2758
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2759
				$cidrprefix = 128;
2760
			}
2761
		} else {
2762
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2763
				$cidrprefix = 32;
2764
			}
2765
		}
2766
		$iflist = get_configured_interface_list();
2767
		foreach ($iflist as $if => $ifname) {
2768
			if ($ignore_if == $if) {
2769
				continue;
2770
			}
2771

    
2772
			if ($isipv6) {
2773
				$if_ipv6 = get_interface_ipv6($if);
2774
				$if_snbitsv6 = get_interface_subnetv6($if);
2775
				if ($if_ipv6 && $if_snbitsv6 && check_subnetsv6_overlap($ipaddr, $cidrprefix, $if_ipv6, $if_snbitsv6)) {
2776
					$where_entry = array();
2777
					$where_entry['if'] = $if;
2778
					$where_entry['ip_or_subnet'] = get_interface_ipv6($if) . "/" . get_interface_subnetv6($if);
2779
					$where_configured[] = $where_entry;
2780
				}
2781
			} else {
2782
				$if_ipv4 = get_interface_ip($if);
2783
				$if_snbitsv4 = get_interface_subnet($if);
2784
				if ($if_ipv4 && $if_snbitsv4 && check_subnets_overlap($ipaddr, $cidrprefix, $if_ipv4, $if_snbitsv4)) {
2785
					$where_entry = array();
2786
					$where_entry['if'] = $if;
2787
					$where_entry['ip_or_subnet'] = get_interface_ip($if) . "/" . get_interface_subnet($if);
2788
					$where_configured[] = $where_entry;
2789
				}
2790
			}
2791
		}
2792
	} else {
2793
		if ($isipv6) {
2794
			$interface_list_ips = get_configured_ipv6_addresses();
2795
		} else {
2796
			$interface_list_ips = get_configured_ip_addresses();
2797
		}
2798

    
2799
		foreach ($interface_list_ips as $if => $ilips) {
2800
			if ($ignore_if == $if) {
2801
				continue;
2802
			}
2803
			if (strcasecmp($ipaddr, $ilips) == 0) {
2804
				$where_entry = array();
2805
				$where_entry['if'] = $if;
2806
				$where_entry['ip_or_subnet'] = $ilips;
2807
				$where_configured[] = $where_entry;
2808
			}
2809
		}
2810
	}
2811

    
2812
	$interface_list_vips = get_configured_vips_list(true);
2813
	foreach ($interface_list_vips as $id => $vip) {
2814
		/* Skip CARP interfaces here since they were already checked above */
2815
		if ($id == $ignore_vip_id || (substr($ignore_if, 0, 4) == '_vip') && substr($ignore_vip_if, 5)  == $vip['uniqdid']) {
2816
			continue;
2817
		}
2818
		if (strcasecmp($ipaddr, $vip['ipaddr']) == 0) {
2819
			$where_entry = array();
2820
			$where_entry['if'] = $vip['if'];
2821
			$where_entry['ip_or_subnet'] = $vip['ipaddr'];
2822
			$where_configured[] = $where_entry;
2823
		}
2824
	}
2825

    
2826
	if ($check_localip) {
2827
		if (is_array($config['pptpd']) && !empty($config['pptpd']['localip']) && (strcasecmp($ipaddr, $config['pptpd']['localip']) == 0)) {
2828
			$where_entry = array();
2829
			$where_entry['if'] = 'pptp';
2830
			$where_entry['ip_or_subnet'] = $config['pptpd']['localip'];
2831
			$where_configured[] = $where_entry;
2832
		}
2833

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

    
2842
	return $where_configured;
2843
}
2844

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

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

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

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

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

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

    
2897
	return $code;
2898
}
2899

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

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

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

    
2910
	return $codeset;
2911
}
2912

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

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

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

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

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

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

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

    
2984
	return($ip6addr);
2985
}
2986

    
2987

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3143
}
3144

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

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

    
3196
?>
(40-40/68)