Project

General

Profile

Download (89.2 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
{
499
	$addr_byte = explode(':', $mac);
500
	$hw_addr = '';
501

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

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

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

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

    
529
	return false;
530
}
531

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

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

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

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

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

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

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

    
640
";
641

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

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

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

    
658
	return $ret;
659
}
660

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

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

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

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

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

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

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

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

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

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

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

    
833
	return $versions;
834
}
835

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1050
			if ($serial_only === true) {
1051
				$new_boot_config[] = 'boot_serial="YES"';
1052
				$new_boot_config[] = 'console="comconsole"';
1053
			} else if (is_serial_enabled()) {
1054
				$new_boot_config[] = 'boot_multicons="YES"';
1055
				$new_boot_config[] = 'boot_serial="YES"';
1056
				$primaryconsole = isset($g['primaryconsole_force']) ? $g['primaryconsole_force'] : $config['system']['primaryconsole'];
1057
				switch ($primaryconsole) {
1058
					case "video":
1059
						$new_boot_config[] = 'console="vidconsole,comconsole"';
1060
						break;
1061
					case "serial":
1062
					default:
1063
						$new_boot_config[] = 'console="comconsole,vidconsole"';
1064
				}
1065
			}
1066
			$new_boot_config[] = 'comconsole_speed="' . $serialspeed . '"';
1067

    
1068
			file_put_contents($loader_conf_file, implode("\n", $new_boot_config) . "\n");
1069
		}
1070
	}
1071
	$ttys = file_get_contents($ttys_file);
1072
	$ttys_split = explode("\n", $ttys);
1073
	$fd = fopen($ttys_file, "w");
1074

    
1075
	$on_off = (is_serial_enabled() ? 'onifconsole' : 'off');
1076

    
1077
	if (isset($config['system']['disableconsolemenu'])) {
1078
		$console_type = 'Pc';
1079
		$serial_type = 'std.' . $serialspeed;
1080
	} else {
1081
		$console_type = 'al.Pc';
1082
		$serial_type = 'al.' . $serialspeed;
1083
	}
1084
	foreach ($ttys_split as $tty) {
1085
		if (stristr($tty, "ttyv0")) {
1086
			fwrite($fd, "ttyv0	\"/usr/libexec/getty {$console_type}\"	cons25	on	secure\n");
1087
		} else if (stristr($tty, "ttyu")) {
1088
			$ttyn = substr($tty, 0, 5);
1089
			fwrite($fd, "{$ttyn}	\"/usr/libexec/getty {$serial_type}\"	cons25	{$on_off}	secure\n");
1090
		} else {
1091
			fwrite($fd, $tty . "\n");
1092
		}
1093
	}
1094
	unset($on_off, $console_type, $serial_type);
1095
	fclose($fd);
1096
	if ($when != "upgrade") {
1097
		reload_ttys();
1098
	}
1099

    
1100
	conf_mount_ro();
1101
	return;
1102
}
1103

    
1104
function is_serial_enabled() {
1105
	global $g, $config;
1106

    
1107
	if (!isset($g['enableserial_force']) &&
1108
	    !isset($config['system']['enableserial']) &&
1109
	    ($g['platform'] == "pfSense" || $g['platform'] == "cdrom" || file_exists("/etc/nano_use_vga.txt"))) {
1110
		return false;
1111
	}
1112

    
1113
	return true;
1114
}
1115

    
1116
function reload_ttys() {
1117
	// Send a HUP signal to init will make it reload /etc/ttys
1118
	posix_kill(1, SIGHUP);
1119
}
1120

    
1121
function print_value_list($list, $count = 10, $separator = ",") {
1122
	$list = implode($separator, array_slice($list, 0, $count));
1123
	if (count($list) < $count) {
1124
		$list .= ".";
1125
	} else {
1126
		$list .= "...";
1127
	}
1128
	return $list;
1129
}
1130

    
1131
/* DHCP enabled on any interfaces? */
1132
function is_dhcp_server_enabled() {
1133
	global $config;
1134

    
1135
	if (!is_array($config['dhcpd'])) {
1136
		return false;
1137
	}
1138

    
1139
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1140
		if (isset($dhcpifconf['enable']) && !empty($config['interfaces'][$dhcpif])) {
1141
			return true;
1142
		}
1143
	}
1144

    
1145
	return false;
1146
}
1147

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

    
1152
	if (is_array($config['interfaces'])) {
1153
		foreach ($config['interfaces'] as $ifcfg) {
1154
			if (isset($ifcfg['enable']) && !empty($ifcfg['track6-interface'])) {
1155
				return true;
1156
			}
1157
		}
1158
	}
1159

    
1160
	if (!is_array($config['dhcpdv6'])) {
1161
		return false;
1162
	}
1163

    
1164
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
1165
		if (isset($dhcpv6ifconf['enable']) && !empty($config['interfaces'][$dhcpv6if])) {
1166
			return true;
1167
		}
1168
	}
1169

    
1170
	return false;
1171
}
1172

    
1173
/* radvd enabled on any interfaces? */
1174
function is_radvd_enabled() {
1175
	global $config;
1176

    
1177
	if (!is_array($config['dhcpdv6'])) {
1178
		$config['dhcpdv6'] = array();
1179
	}
1180

    
1181
	$dhcpdv6cfg = $config['dhcpdv6'];
1182
	$Iflist = get_configured_interface_list();
1183

    
1184
	/* handle manually configured DHCP6 server settings first */
1185
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1186
		if (!isset($config['interfaces'][$dhcpv6if]['enable'])) {
1187
			continue;
1188
		}
1189

    
1190
		if (!isset($dhcpv6ifconf['ramode'])) {
1191
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
1192
		}
1193

    
1194
		if ($dhcpv6ifconf['ramode'] == "disabled") {
1195
			continue;
1196
		}
1197

    
1198
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1199
		if (!is_ipaddrv6($ifcfgipv6)) {
1200
			continue;
1201
		}
1202

    
1203
		return true;
1204
	}
1205

    
1206
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
1207
	foreach ($Iflist as $if => $ifdescr) {
1208
		if (!isset($config['interfaces'][$if]['track6-interface'])) {
1209
			continue;
1210
		}
1211
		if (!isset($config['interfaces'][$if]['enable'])) {
1212
			continue;
1213
		}
1214

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

    
1220
		$ifcfgsnv6 = get_interface_subnetv6($if);
1221
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1222

    
1223
		if (!is_ipaddrv6($subnetv6)) {
1224
			continue;
1225
		}
1226

    
1227
		return true;
1228
	}
1229

    
1230
	return false;
1231
}
1232

    
1233
/* Any PPPoE servers enabled? */
1234
function is_pppoe_server_enabled() {
1235
	global $config;
1236

    
1237
	$pppoeenable = false;
1238

    
1239
	if (!is_array($config['pppoes']) || !is_array($config['pppoes']['pppoe'])) {
1240
		return false;
1241
	}
1242

    
1243
	foreach ($config['pppoes']['pppoe'] as $pppoes) {
1244
		if ($pppoes['mode'] == 'server') {
1245
			$pppoeenable = true;
1246
		}
1247
	}
1248

    
1249
	return $pppoeenable;
1250
}
1251

    
1252
function convert_seconds_to_hms($sec) {
1253
	$min=$hrs=0;
1254
	if ($sec != 0) {
1255
		$min = floor($sec/60);
1256
		$sec %= 60;
1257
	}
1258
	if ($min != 0) {
1259
		$hrs = floor($min/60);
1260
		$min %= 60;
1261
	}
1262
	if ($sec < 10) {
1263
		$sec = "0".$sec;
1264
	}
1265
	if ($min < 10) {
1266
		$min = "0".$min;
1267
	}
1268
	if ($hrs < 10) {
1269
		$hrs = "0".$hrs;
1270
	}
1271
	$result = $hrs.":".$min.":".$sec;
1272
	return $result;
1273
}
1274

    
1275
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1276

    
1277
function get_ppp_uptime($port) {
1278
	if (file_exists("/conf/{$port}.log")) {
1279
		$saved_time = file_get_contents("/conf/{$port}.log");
1280
		$uptime_data = explode("\n",$saved_time);
1281
		$sec=0;
1282
		foreach ($uptime_data as $upt) {
1283
			$sec += substr($upt, 1 + strpos($upt, " "));
1284
		}
1285
		return convert_seconds_to_hms($sec);
1286
	} else {
1287
		$total_time = gettext("No history data found!");
1288
		return $total_time;
1289
	}
1290
}
1291

    
1292
//returns interface information
1293
function get_interface_info($ifdescr) {
1294
	global $config, $g;
1295

    
1296
	$ifinfo = array();
1297
	if (empty($config['interfaces'][$ifdescr])) {
1298
		return;
1299
	}
1300
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
1301
	$ifinfo['if'] = get_real_interface($ifdescr);
1302

    
1303
	$chkif = $ifinfo['if'];
1304
	$ifinfotmp = pfSense_get_interface_addresses($chkif);
1305
	$ifinfo['status'] = $ifinfotmp['status'];
1306
	if (empty($ifinfo['status'])) {
1307
		$ifinfo['status'] = "down";
1308
	}
1309
	$ifinfo['macaddr'] = $ifinfotmp['macaddr'];
1310
	$ifinfo['mtu'] = $ifinfotmp['mtu'];
1311
	$ifinfo['ipaddr'] = $ifinfotmp['ipaddr'];
1312
	$ifinfo['subnet'] = $ifinfotmp['subnet'];
1313
	$ifinfo['linklocal'] = get_interface_linklocal($ifdescr);
1314
	$ifinfo['ipaddrv6'] = get_interface_ipv6($ifdescr);
1315
	$ifinfo['subnetv6'] = get_interface_subnetv6($ifdescr);
1316
	if (isset($ifinfotmp['link0'])) {
1317
		$link0 = "down";
1318
	}
1319
	$ifinfotmp = pfSense_get_interface_stats($chkif);
1320
	// $ifinfo['inpkts'] = $ifinfotmp['inpkts'];
1321
	// $ifinfo['outpkts'] = $ifinfotmp['outpkts'];
1322
	$ifinfo['inerrs'] = $ifinfotmp['inerrs'];
1323
	$ifinfo['outerrs'] = $ifinfotmp['outerrs'];
1324
	$ifinfo['collisions'] = $ifinfotmp['collisions'];
1325

    
1326
	/* Use pfctl for non wrapping 64 bit counters */
1327
	/* Pass */
1328
	exec("/sbin/pfctl -vvsI -i {$chkif}", $pfctlstats);
1329
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1330
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1331
	$pf_in6_pass = preg_split("/ +/ ", $pfctlstats[7]);
1332
	$pf_out6_pass = preg_split("/ +/", $pfctlstats[9]);
1333
	$in4_pass = $pf_in4_pass[5];
1334
	$out4_pass = $pf_out4_pass[5];
1335
	$in4_pass_packets = $pf_in4_pass[3];
1336
	$out4_pass_packets = $pf_out4_pass[3];
1337
	$in6_pass = $pf_in6_pass[5];
1338
	$out6_pass = $pf_out6_pass[5];
1339
	$in6_pass_packets = $pf_in6_pass[3];
1340
	$out6_pass_packets = $pf_out6_pass[3];
1341
	$ifinfo['inbytespass'] = $in4_pass + $in6_pass;
1342
	$ifinfo['outbytespass'] = $out4_pass + $out6_pass;
1343
	$ifinfo['inpktspass'] = $in4_pass_packets + $in6_pass_packets;
1344
	$ifinfo['outpktspass'] = $out4_pass_packets + $out6_pass_packets;
1345

    
1346
	/* Block */
1347
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1348
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1349
	$pf_in6_block = preg_split("/ +/", $pfctlstats[8]);
1350
	$pf_out6_block = preg_split("/ +/", $pfctlstats[10]);
1351
	$in4_block = $pf_in4_block[5];
1352
	$out4_block = $pf_out4_block[5];
1353
	$in4_block_packets = $pf_in4_block[3];
1354
	$out4_block_packets = $pf_out4_block[3];
1355
	$in6_block = $pf_in6_block[5];
1356
	$out6_block = $pf_out6_block[5];
1357
	$in6_block_packets = $pf_in6_block[3];
1358
	$out6_block_packets = $pf_out6_block[3];
1359
	$ifinfo['inbytesblock'] = $in4_block + $in6_block;
1360
	$ifinfo['outbytesblock'] = $out4_block + $out6_block;
1361
	$ifinfo['inpktsblock'] = $in4_block_packets + $in6_block_packets;
1362
	$ifinfo['outpktsblock'] = $out4_block_packets + $out6_block_packets;
1363

    
1364
	$ifinfo['inbytes'] = $in4_pass + $in6_pass;
1365
	$ifinfo['outbytes'] = $out4_pass + $out6_pass;
1366
	$ifinfo['inpkts'] = $in4_pass_packets + $in6_pass_packets;
1367
	$ifinfo['outpkts'] = $out4_pass_packets + $out6_pass_packets;
1368

    
1369
	$ifconfiginfo = "";
1370
	$link_type = $config['interfaces'][$ifdescr]['ipaddr'];
1371
	switch ($link_type) {
1372
		/* DHCP? -> see if dhclient is up */
1373
		case "dhcp":
1374
			/* see if dhclient is up */
1375
			if (find_dhclient_process($ifinfo['if']) != 0) {
1376
				$ifinfo['dhcplink'] = "up";
1377
			} else {
1378
				$ifinfo['dhcplink'] = "down";
1379
			}
1380

    
1381
			break;
1382
		/* PPPoE/PPTP/L2TP interface? -> get status from virtual interface */
1383
		case "pppoe":
1384
		case "pptp":
1385
		case "l2tp":
1386
			if ($ifinfo['status'] == "up" && !isset($link0)) {
1387
				/* get PPPoE link status for dial on demand */
1388
				$ifinfo["{$link_type}link"] = "up";
1389
			} else {
1390
				$ifinfo["{$link_type}link"] = "down";
1391
			}
1392

    
1393
			break;
1394
		/* PPP interface? -> get uptime for this session and cumulative uptime from the persistent log file in conf */
1395
		case "ppp":
1396
			if ($ifinfo['status'] == "up") {
1397
				$ifinfo['ppplink'] = "up";
1398
			} else {
1399
				$ifinfo['ppplink'] = "down" ;
1400
			}
1401

    
1402
			if (empty($ifinfo['status'])) {
1403
				$ifinfo['status'] = "down";
1404
			}
1405

    
1406
			if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1407
				foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1408
					if ($config['interfaces'][$ifdescr]['if'] == $ppp['if']) {
1409
						break;
1410
					}
1411
				}
1412
			}
1413
			$dev = $ppp['ports'];
1414
			if ($config['interfaces'][$ifdescr]['if'] != $ppp['if'] || empty($dev)) {
1415
				break;
1416
			}
1417
			if (!file_exists($dev)) {
1418
				$ifinfo['nodevice'] = 1;
1419
				$ifinfo['pppinfo'] = $dev . " " . gettext("device not present! Is the modem attached to the system?");
1420
			}
1421

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

    
1457
	if (file_exists("{$g['varrun_path']}/{$link_type}_{$ifdescr}.pid")) {
1458
		$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1459
		$ifinfo['ppp_uptime'] = convert_seconds_to_hms($sec);
1460
	}
1461

    
1462
	if ($ifinfo['status'] == "up") {
1463
		/* try to determine media with ifconfig */
1464
		unset($ifconfiginfo);
1465
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1466
		$wifconfiginfo = array();
1467
		if (is_interface_wireless($ifdescr)) {
1468
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1469
			array_shift($wifconfiginfo);
1470
		}
1471
		$matches = "";
1472
		foreach ($ifconfiginfo as $ici) {
1473

    
1474
			/* don't list media/speed for wireless cards, as it always
1475
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1476
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1477
				$ifinfo['media'] = $matches[1];
1478
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1479
				$ifinfo['media'] = $matches[1];
1480
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1481
				$ifinfo['media'] = $matches[1];
1482
			}
1483

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

    
1529
	$bridge = "";
1530
	$bridge = link_interface_to_bridge($ifdescr);
1531
	if ($bridge) {
1532
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1533
		if (stristr($bridge_text, "blocking") <> false) {
1534
			$ifinfo['bridge'] = "<b><font color='red'>" . gettext("blocking") . "</font></b> - " . gettext("check for ethernet loops");
1535
			$ifinfo['bridgeint'] = $bridge;
1536
		} else if (stristr($bridge_text, "learning") <> false) {
1537
			$ifinfo['bridge'] = gettext("learning");
1538
			$ifinfo['bridgeint'] = $bridge;
1539
		} else if (stristr($bridge_text, "forwarding") <> false) {
1540
			$ifinfo['bridge'] = gettext("forwarding");
1541
			$ifinfo['bridgeint'] = $bridge;
1542
		}
1543
	}
1544

    
1545
	return $ifinfo;
1546
}
1547

    
1548
//returns cpu speed of processor. Good for determining capabilities of machine
1549
function get_cpu_speed() {
1550
	return get_single_sysctl("hw.clockrate");
1551
}
1552

    
1553
function get_uptime_sec() {
1554
	$boottime = "";
1555
	$matches = "";
1556
	$boottime = get_single_sysctl("kern.boottime");
1557
	preg_match("/sec = (\d+)/", $boottime, $matches);
1558
	$boottime = $matches[1];
1559
	if (intval($boottime) == 0) {
1560
		return 0;
1561
	}
1562

    
1563
	$uptime = time() - $boottime;
1564
	return $uptime;
1565
}
1566

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

    
1600
function is_fqdn($fqdn) {
1601
	$hostname = false;
1602
	if (preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1603
		$hostname = true;
1604
	}
1605
	if (preg_match("/\.\./", $fqdn)) {
1606
		$hostname = false;
1607
	}
1608
	if (preg_match("/^\./i", $fqdn)) {
1609
		$hostname = false;
1610
	}
1611
	if (preg_match("/\//i", $fqdn)) {
1612
		$hostname = false;
1613
	}
1614
	return($hostname);
1615
}
1616

    
1617
function pfsense_default_state_size() {
1618
	/* get system memory amount */
1619
	$memory = get_memory();
1620
	$physmem = $memory[0];
1621
	/* Be cautious and only allocate 10% of system memory to the state table */
1622
	$max_states = (int) ($physmem/10)*1000;
1623
	return $max_states;
1624
}
1625

    
1626
function pfsense_default_tables_size() {
1627
	$current = `pfctl -sm | grep ^tables | awk '{print $4};'`;
1628
	return $current;
1629
}
1630

    
1631
function pfsense_default_table_entries_size() {
1632
	$current = `pfctl -sm | grep table-entries | awk '{print $4};'`;
1633
	return $current;
1634
}
1635

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

    
1672
	if (trim($oldcontents) != trim($contents)) {
1673
		if ($g['debug']) {
1674
			log_error(sprintf(gettext('DNSCACHE: Found old IP %1$s and new IP %2$s'), $oldcontents, $contents));
1675
		}
1676
		return ($oldcontents);
1677
	} else {
1678
		return false;
1679
	}
1680
}
1681

    
1682
/*
1683
 * load_crypto() - Load crypto modules if enabled in config.
1684
 */
1685
function load_crypto() {
1686
	global $config, $g;
1687
	$crypto_modules = array('glxsb', 'aesni');
1688

    
1689
	if (!in_array($config['system']['crypto_hardware'], $crypto_modules)) {
1690
		return false;
1691
	}
1692

    
1693
	if (!empty($config['system']['crypto_hardware']) && !is_module_loaded($config['system']['crypto_hardware'])) {
1694
		log_error("Loading {$config['system']['crypto_hardware']} cryptographic accelerator module.");
1695
		mwexec("/sbin/kldload {$config['system']['crypto_hardware']}");
1696
	}
1697
}
1698

    
1699
/*
1700
 * load_thermal_hardware() - Load temperature monitor kernel module
1701
 */
1702
function load_thermal_hardware() {
1703
	global $config, $g;
1704
	$thermal_hardware_modules = array('coretemp', 'amdtemp');
1705

    
1706
	if (!in_array($config['system']['thermal_hardware'], $thermal_hardware_modules)) {
1707
		return false;
1708
	}
1709

    
1710
	if (!empty($config['system']['thermal_hardware']) && !is_module_loaded($config['system']['thermal_hardware'])) {
1711
		log_error("Loading {$config['system']['thermal_hardware']} thermal monitor module.");
1712
		mwexec("/sbin/kldload {$config['system']['thermal_hardware']}");
1713
	}
1714
}
1715

    
1716
/****f* pfsense-utils/isvm
1717
 * NAME
1718
 *   isvm
1719
 * INPUTS
1720
 *	none
1721
 * RESULT
1722
 *   returns true if machine is running under a virtual environment
1723
 ******/
1724
function isvm() {
1725
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86", "VirtualBox");
1726
	$_gb = exec('/bin/kenv smbios.system.product 2>/dev/null', $output, $rc);
1727

    
1728
	if ($rc != 0 || !isset($output[0])) {
1729
		return false;
1730
	}
1731

    
1732
	foreach ($virtualenvs as $virtualenv) {
1733
		if (stripos($output[0], $virtualenv) !== false) {
1734
			return true;
1735
		}
1736
	}
1737

    
1738
	return false;
1739
}
1740

    
1741
function get_freebsd_version() {
1742
	$version = explode(".", php_uname("r"));
1743
	return $version[0];
1744
}
1745

    
1746
function download_file($url, $destination, $verify_ssl = true, $connect_timeout = 60, $timeout = 0) {
1747
	global $config, $g;
1748

    
1749
	$fp = fopen($destination, "wb");
1750

    
1751
	if (!$fp) {
1752
		return false;
1753
	}
1754

    
1755
	$ch = curl_init();
1756
	curl_setopt($ch, CURLOPT_URL, $url);
1757
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1758
	curl_setopt($ch, CURLOPT_FILE, $fp);
1759
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1760
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1761
	curl_setopt($ch, CURLOPT_HEADER, false);
1762
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1763
	curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version")));
1764

    
1765
	if (!empty($config['system']['proxyurl'])) {
1766
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1767
		if (!empty($config['system']['proxyport'])) {
1768
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1769
		}
1770
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1771
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1772
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1773
		}
1774
	}
1775

    
1776
	@curl_exec($ch);
1777
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1778
	fclose($fp);
1779
	curl_close($ch);
1780
	return ($http_code == 200) ? true : $http_code;
1781
}
1782

    
1783
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body', $connect_timeout=60, $timeout=0) {
1784
	global $ch, $fout, $file_size, $downloaded, $config, $first_progress_update, $g;
1785
	$file_size  = 1;
1786
	$downloaded = 1;
1787
	$first_progress_update = TRUE;
1788
	/* open destination file */
1789
	$fout = fopen($destination_file, "wb");
1790

    
1791
	/*
1792
	 *      Originally by Author: Keyvan Minoukadeh
1793
	 *      Modified by Scott Ullrich to return Content-Length size
1794
	 */
1795

    
1796
	$ch = curl_init();
1797
	curl_setopt($ch, CURLOPT_URL, $url_file);
1798
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1799
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1800
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1801
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1802
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1803
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1804
	curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version")));
1805

    
1806
	if (!empty($config['system']['proxyurl'])) {
1807
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1808
		if (!empty($config['system']['proxyport'])) {
1809
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1810
		}
1811
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1812
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1813
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1814
		}
1815
	}
1816

    
1817
	@curl_exec($ch);
1818
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1819
	if ($fout) {
1820
		fclose($fout);
1821
	}
1822
	curl_close($ch);
1823
	return ($http_code == 200) ? true : $http_code;
1824
}
1825

    
1826
function read_header($ch, $string) {
1827
	global $file_size, $fout;
1828
	$length = strlen($string);
1829
	$regs = "";
1830
	preg_match("/(Content-Length:) (.*)/", $string, $regs);
1831
	if ($regs[2] <> "") {
1832
		$file_size = intval($regs[2]);
1833
	}
1834
	ob_flush();
1835
	return $length;
1836
}
1837

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

    
1890
/*
1891
 *   update_output_window: update bottom textarea dynamically.
1892
 */
1893
function update_output_window($text) {
1894
	global $pkg_interface;
1895
	$log = preg_replace("/\n/", "\\n", $text);
1896
	if ($pkg_interface != "console") {
1897
		echo "\n<script type=\"text/javascript\">";
1898
		echo "\n//<![CDATA[";
1899
		echo "\nthis.document.forms[0].output.value = \"" . $log . "\";";
1900
		echo "\nthis.document.forms[0].output.scrollTop = this.document.forms[0].output.scrollHeight;";
1901
		echo "\n//]]>";
1902
		echo "\n</script>";
1903
	}
1904
	/* ensure that contents are written out */
1905
	ob_flush();
1906
}
1907

    
1908
/*
1909
 *   update_status: update top textarea dynamically.
1910
 */
1911
function update_status($status) {
1912
	global $pkg_interface;
1913
	if ($pkg_interface == "console") {
1914
		echo "\r{$status}";
1915
	} else {
1916
		echo "\n<script type=\"text/javascript\">";
1917
		echo "\n//<![CDATA[";
1918
		echo "\nthis.document.forms[0].status.value=\"" . $status . "\";";
1919
		echo "\n//]]>";
1920
		echo "\n</script>";
1921
	}
1922
	/* ensure that contents are written out */
1923
	ob_flush();
1924
}
1925

    
1926
/*
1927
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
1928
 */
1929
function update_progress_bar($percent, $first_time) {
1930
	global $pkg_interface;
1931
	if ($percent > 100) {
1932
		$percent = 1;
1933
	}
1934
	if ($pkg_interface <> "console") {
1935
		echo "\n<script type=\"text/javascript\">";
1936
		echo "\n//<![CDATA[";
1937
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1938
		echo "\n//]]>";
1939
		echo "\n</script>";
1940
	} else {
1941
		if (!($first_time)) {
1942
			echo "\x08\x08\x08\x08\x08";
1943
		}
1944
		echo sprintf("%4d%%", $percent);
1945
	}
1946
}
1947

    
1948
/* 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. */
1949
if (!function_exists("split")) {
1950
	function split($separator, $haystack, $limit = null) {
1951
		log_error("deprecated split() call with separator '{$separator}'");
1952
		return preg_split($separator, $haystack, $limit);
1953
	}
1954
}
1955

    
1956
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
1957
	global $g, $config, $pconfig, $debug;
1958
	if (!$origname) {
1959
		return;
1960
	}
1961

    
1962
	$sectionref = &$config;
1963
	foreach ($section as $sectionname) {
1964
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
1965
			$sectionref = &$sectionref[$sectionname];
1966
		} else {
1967
			return;
1968
		}
1969
	}
1970

    
1971
	if ($debug) {
1972
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
1973
		fwrite($fd, print_r($pconfig, true));
1974
	}
1975

    
1976
	if (is_array($sectionref)) {
1977
		foreach ($sectionref as $itemkey => $item) {
1978
			if ($debug) {
1979
				fwrite($fd, "$itemkey\n");
1980
			}
1981

    
1982
			$fieldfound = true;
1983
			$fieldref = &$sectionref[$itemkey];
1984
			foreach ($field as $fieldname) {
1985
				if (is_array($fieldref) && isset($fieldref[$fieldname])) {
1986
					$fieldref = &$fieldref[$fieldname];
1987
				} else {
1988
					$fieldfound = false;
1989
					break;
1990
				}
1991
			}
1992
			if ($fieldfound && $fieldref == $origname) {
1993
				if ($debug) {
1994
					fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1995
				}
1996
				$fieldref = $new_alias_name;
1997
			}
1998
		}
1999
	}
2000

    
2001
	if ($debug) {
2002
		fclose($fd);
2003
	}
2004

    
2005
}
2006

    
2007
function parse_aliases_file($filename, $type = "url", $max_items = -1) {
2008
	/*
2009
	 * $filename = file to process for example blocklist like DROP:  http://www.spamhaus.org/drop/drop.txt
2010
	 * $type = if set to 'url' then subnets and ips will be returned,
2011
	 *         if set to 'url_ports' port-ranges and ports will be returned
2012
	 * $max_items = sets the maximum amount of valid items to load, -1 the default defines there is no limit.
2013
	 *
2014
	 * RETURNS an array of ip subnets and ip's or ports and port-ranges, returns NULL upon a error conditions (file not found)
2015
	 */
2016

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

    
2050
function update_alias_url_data() {
2051
	global $config, $g;
2052

    
2053
	$updated = false;
2054

    
2055
	/* item is a url type */
2056
	$lockkey = lock('aliasurl');
2057
	if (is_array($config['aliases']['alias'])) {
2058
		foreach ($config['aliases']['alias'] as $x => $alias) {
2059
			if (empty($alias['aliasurl'])) {
2060
				continue;
2061
			}
2062

    
2063
			$address = null;
2064
			foreach ($alias['aliasurl'] as $alias_url) {
2065
				/* fetch down and add in */
2066
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
2067
				unlink($temp_filename);
2068
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2069
				mkdir($temp_filename);
2070
				download_file($alias_url, $temp_filename . "/aliases", $verify_ssl);
2071

    
2072
				/* if the item is tar gzipped then extract */
2073
				if (stripos($alias_url, '.tgz')) {
2074
					if (!process_alias_tgz($temp_filename)) {
2075
						continue;
2076
					}
2077
				} else if (stripos($alias_url, '.zip')) {
2078
					if (!process_alias_unzip($temp_filename)) {
2079
						continue;
2080
					}
2081
				}
2082
				if (file_exists("{$temp_filename}/aliases")) {
2083
					$address = parse_aliases_file("{$temp_filename}/aliases", $alias['type'], 3000);
2084
					mwexec("/bin/rm -rf {$temp_filename}");
2085
				}
2086
			}
2087
			if ($address != null) {
2088
				$config['aliases']['alias'][$x]['address'] = implode(" ", $address);
2089
				$updated = true;
2090
			}
2091
		}
2092
	}
2093
	unlock($lockkey);
2094

    
2095
	/* Report status to callers as well */
2096
	return $updated;
2097
}
2098

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

    
2129
	return true;
2130
}
2131

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

    
2162
	return true;
2163
}
2164

    
2165
function version_compare_dates($a, $b) {
2166
	$a_time = strtotime($a);
2167
	$b_time = strtotime($b);
2168

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

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

    
2253
		// First try to compare the numeric parts of the version string.
2254
		$v = version_compare_numeric($cur_num, $rem_num);
2255

    
2256
		// If the numeric parts are the same, compare the string parts.
2257
		if ($v == 0) {
2258
			return version_compare_string($cur_str, $rem_str);
2259
		}
2260
	}
2261
	return $v;
2262
}
2263
function process_alias_urltable($name, $url, $freq, $forceupdate=false) {
2264
	global $config;
2265

    
2266
	$urltable_prefix = "/var/db/aliastables/";
2267
	$urltable_filename = $urltable_prefix . $name . ".txt";
2268

    
2269
	// Make the aliases directory if it doesn't exist
2270
	if (!file_exists($urltable_prefix)) {
2271
		mkdir($urltable_prefix);
2272
	} elseif (!is_dir($urltable_prefix)) {
2273
		unlink($urltable_prefix);
2274
		mkdir($urltable_prefix);
2275
	}
2276

    
2277
	// If the file doesn't exist or is older than update_freq days, fetch a new copy.
2278
	if (!file_exists($urltable_filename) ||
2279
	    ((time() - filemtime($urltable_filename)) > ($freq * 86400 - 90)) ||
2280
	    $forceupdate) {
2281

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

    
2318
	return "{$boot_drive}s{$active}";
2319
}
2320
function nanobsd_get_size() {
2321
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2322
}
2323
function nanobsd_switch_boot_slice() {
2324
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2325
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2326
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2327
	nanobsd_detect_slice_info();
2328

    
2329
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2330
		$slice = $TOFLASH;
2331
	} else {
2332
		$slice = $BOOTFLASH;
2333
	}
2334

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

    
2373
	for ($i = 0; $i < ob_get_level(); $i++) {
2374
		ob_end_flush();
2375
	}
2376
	ob_implicit_flush(1);
2377
	set_single_sysctl("kern.geom.debugflags", "16");
2378
	exec("/bin/dd if=/dev/zero of=/dev/{$TOFLASH} bs=1m count=1");
2379
	exec("/bin/dd if=/dev/{$BOOTFLASH} of=/dev/{$TOFLASH} bs=64k");
2380
	exec("/sbin/tunefs -L {$GLABEL_SLICE} /dev/{$COMPLETE_PATH}");
2381
	$status = nanobsd_update_fstab($GLABEL_SLICE, $COMPLETE_PATH, $OLD_UFS_ID, $UFS_ID);
2382
	set_single_sysctl("kern.geom.debugflags", "0");
2383
	if ($status) {
2384
		return false;
2385
	} else {
2386
		return true;
2387
	}
2388
}
2389
function nanobsd_update_fstab($gslice, $complete_path, $oldufs, $newufs) {
2390
	$tmppath = "/tmp/{$gslice}";
2391
	$fstabpath = "/tmp/{$gslice}/etc/fstab";
2392

    
2393
	mkdir($tmppath);
2394
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2395
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2396
	copy("/etc/fstab", $fstabpath);
2397

    
2398
	if (!file_exists($fstabpath)) {
2399
		$fstab = <<<EOF
2400
/dev/ufs/{$gslice} / ufs ro,noatime 1 1
2401
/dev/ufs/cf /cf ufs ro,noatime 1 1
2402
EOF;
2403
		if (file_put_contents($fstabpath, $fstab)) {
2404
			$status = true;
2405
		} else {
2406
			$status = false;
2407
		}
2408
	} else {
2409
		$status = exec("sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2410
	}
2411
	exec("/sbin/umount {$tmppath}");
2412
	rmdir($tmppath);
2413

    
2414
	return $status;
2415
}
2416
function nanobsd_detect_slice_info() {
2417
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2418
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2419
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2420

    
2421
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2422
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2423
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2424
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2425

    
2426
	// Detect which slice is active and set information.
2427
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2428
		$SLICE="2";
2429
		$OLDSLICE="1";
2430
		$GLABEL_SLICE="pfsense1";
2431
		$UFS_ID="1";
2432
		$OLD_UFS_ID="0";
2433

    
2434
	} else {
2435
		$SLICE="1";
2436
		$OLDSLICE="2";
2437
		$GLABEL_SLICE="pfsense0";
2438
		$UFS_ID="0";
2439
		$OLD_UFS_ID="1";
2440
	}
2441
	$TOFLASH="{$BOOT_DRIVE}s{$SLICE}";
2442
	$COMPLETE_PATH="{$BOOT_DRIVE}s{$SLICE}a";
2443
	$COMPLETE_BOOT_PATH="{$BOOT_DRIVE}s{$OLDSLICE}";
2444
	$BOOTFLASH="{$BOOT_DRIVE}s{$OLDSLICE}";
2445
}
2446

    
2447
function nanobsd_friendly_slice_name($slicename) {
2448
	global $g;
2449
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2450
}
2451

    
2452
function get_include_contents($filename) {
2453
	if (is_file($filename)) {
2454
		ob_start();
2455
		include $filename;
2456
		$contents = ob_get_contents();
2457
		ob_end_clean();
2458
		return $contents;
2459
	}
2460
	return false;
2461
}
2462

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

    
2576
function get_country_name($country_code) {
2577
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2578
		return "";
2579
	}
2580

    
2581
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2582
	$country_names_contents = file_get_contents($country_names_xml);
2583
	$country_names = xml2array($country_names_contents);
2584

    
2585
	if ($country_code == "ALL") {
2586
		$country_list = array();
2587
		foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2588
			$country_list[] = array(
2589
				"code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2590
				"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])));
2591
		}
2592
		return $country_list;
2593
	}
2594

    
2595
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2596
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2597
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2598
		}
2599
	}
2600
	return "";
2601
}
2602

    
2603
/* sort by interface only, retain the original order of rules that apply to
2604
   the same interface */
2605
function filter_rules_sort() {
2606
	global $config;
2607

    
2608
	/* mark each rule with the sequence number (to retain the order while sorting) */
2609
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2610
		$config['filter']['rule'][$i]['seq'] = $i;
2611
	}
2612

    
2613
	usort($config['filter']['rule'], "filter_rules_compare");
2614

    
2615
	/* strip the sequence numbers again */
2616
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2617
		unset($config['filter']['rule'][$i]['seq']);
2618
	}
2619
}
2620
function filter_rules_compare($a, $b) {
2621
	if (isset($a['floating']) && isset($b['floating'])) {
2622
		return $a['seq'] - $b['seq'];
2623
	} else if (isset($a['floating'])) {
2624
		return -1;
2625
	} else if (isset($b['floating'])) {
2626
		return 1;
2627
	} else if ($a['interface'] == $b['interface']) {
2628
		return $a['seq'] - $b['seq'];
2629
	} else {
2630
		return compare_interface_friendly_names($a['interface'], $b['interface']);
2631
	}
2632
}
2633

    
2634
function generate_ipv6_from_mac($mac) {
2635
	$elements = explode(":", $mac);
2636
	if (count($elements) <> 6) {
2637
		return false;
2638
	}
2639

    
2640
	$i = 0;
2641
	$ipv6 = "fe80::";
2642
	foreach ($elements as $byte) {
2643
		if ($i == 0) {
2644
			$hexadecimal =  substr($byte, 1, 2);
2645
			$bitmap = base_convert($hexadecimal, 16, 2);
2646
			$bitmap = str_pad($bitmap, 4, "0", STR_PAD_LEFT);
2647
			$bitmap = substr($bitmap, 0, 2) ."1". substr($bitmap, 3,4);
2648
			$byte = substr($byte, 0, 1) . base_convert($bitmap, 2, 16);
2649
		}
2650
		$ipv6 .= $byte;
2651
		if ($i == 1) {
2652
			$ipv6 .= ":";
2653
		}
2654
		if ($i == 3) {
2655
			$ipv6 .= ":";
2656
		}
2657
		if ($i == 2) {
2658
			$ipv6 .= "ff:fe";
2659
		}
2660

    
2661
		$i++;
2662
	}
2663
	return $ipv6;
2664
}
2665

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

    
2692
}
2693

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

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

    
2733
	$where_configured = array();
2734

    
2735
	$pos = strpos($ignore_if, '_virtualip');
2736
	if ($pos !== false) {
2737
		$ignore_vip_id = substr($ignore_if, $pos+10);
2738
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2739
	} else {
2740
		$ignore_vip_id = -1;
2741
		$ignore_vip_if = $ignore_if;
2742
	}
2743

    
2744
	$isipv6 = is_ipaddrv6($ipaddr);
2745

    
2746
	if ($check_subnets) {
2747
		$cidrprefix = intval($cidrprefix);
2748
		if ($isipv6) {
2749
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2750
				$cidrprefix = 128;
2751
			}
2752
		} else {
2753
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2754
				$cidrprefix = 32;
2755
			}
2756
		}
2757
		$iflist = get_configured_interface_list();
2758
		foreach ($iflist as $if => $ifname) {
2759
			if ($ignore_if == $if) {
2760
				continue;
2761
			}
2762

    
2763
			if ($isipv6) {
2764
				$if_ipv6 = get_interface_ipv6($if);
2765
				$if_snbitsv6 = get_interface_subnetv6($if);
2766
				if ($if_ipv6 && $if_snbitsv6 && check_subnetsv6_overlap($ipaddr, $cidrprefix, $if_ipv6, $if_snbitsv6)) {
2767
					$where_entry = array();
2768
					$where_entry['if'] = $if;
2769
					$where_entry['ip_or_subnet'] = get_interface_ipv6($if) . "/" . get_interface_subnetv6($if);
2770
					$where_configured[] = $where_entry;
2771
				}
2772
			} else {
2773
				$if_ipv4 = get_interface_ip($if);
2774
				$if_snbitsv4 = get_interface_subnet($if);
2775
				if ($if_ipv4 && $if_snbitsv4 && check_subnets_overlap($ipaddr, $cidrprefix, $if_ipv4, $if_snbitsv4)) {
2776
					$where_entry = array();
2777
					$where_entry['if'] = $if;
2778
					$where_entry['ip_or_subnet'] = get_interface_ip($if) . "/" . get_interface_subnet($if);
2779
					$where_configured[] = $where_entry;
2780
				}
2781
			}
2782
		}
2783
	} else {
2784
		if ($isipv6) {
2785
			$interface_list_ips = get_configured_ipv6_addresses();
2786
		} else {
2787
			$interface_list_ips = get_configured_ip_addresses();
2788
		}
2789

    
2790
		foreach ($interface_list_ips as $if => $ilips) {
2791
			if ($ignore_if == $if) {
2792
				continue;
2793
			}
2794
			if (strcasecmp($ipaddr, $ilips) == 0) {
2795
				$where_entry = array();
2796
				$where_entry['if'] = $if;
2797
				$where_entry['ip_or_subnet'] = $ilips;
2798
				$where_configured[] = $where_entry;
2799
			}
2800
		}
2801
	}
2802

    
2803
	$interface_list_vips = get_configured_vips_list(true);
2804
	foreach ($interface_list_vips as $id => $vip) {
2805
		/* Skip CARP interfaces here since they were already checked above */
2806
		if ($id == $ignore_vip_id || (substr($ignore_if, 0, 4) == '_vip') && substr($ignore_vip_if, 5)  == $vip['uniqdid']) {
2807
			continue;
2808
		}
2809
		if (strcasecmp($ipaddr, $vip['ipaddr']) == 0) {
2810
			$where_entry = array();
2811
			$where_entry['if'] = $vip['if'];
2812
			$where_entry['ip_or_subnet'] = $vip['ipaddr'];
2813
			$where_configured[] = $where_entry;
2814
		}
2815
	}
2816

    
2817
	if ($check_localip) {
2818
		if (is_array($config['pptpd']) && !empty($config['pptpd']['localip']) && (strcasecmp($ipaddr, $config['pptpd']['localip']) == 0)) {
2819
			$where_entry = array();
2820
			$where_entry['if'] = 'pptp';
2821
			$where_entry['ip_or_subnet'] = $config['pptpd']['localip'];
2822
			$where_configured[] = $where_entry;
2823
		}
2824

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

    
2833
	return $where_configured;
2834
}
2835

    
2836
/****f* pfsense-utils/pfSense_handle_custom_code
2837
 * NAME
2838
 *   pfSense_handle_custom_code
2839
 * INPUTS
2840
 *   directory name to process
2841
 * RESULT
2842
 *   globs the directory and includes the files
2843
 */
2844
function pfSense_handle_custom_code($src_dir) {
2845
	// Allow extending of the nat edit page and include custom input validation
2846
	if (is_dir("$src_dir")) {
2847
		$cf = glob($src_dir . "/*.inc");
2848
		foreach ($cf as $nf) {
2849
			if ($nf == "." || $nf == "..") {
2850
				continue;
2851
			}
2852
			// Include the extra handler
2853
			include("$nf");
2854
		}
2855
	}
2856
}
2857

    
2858
function set_language($lang = 'en_US', $encoding = "UTF-8") {
2859
	putenv("LANG={$lang}.{$encoding}");
2860
	setlocale(LC_ALL, "{$lang}.{$encoding}");
2861
	textdomain("pfSense");
2862
	bindtextdomain("pfSense","/usr/local/share/locale");
2863
	bind_textdomain_codeset("pfSense","{$lang}.{$encoding}");
2864
}
2865

    
2866
function get_locale_list() {
2867
	$locales = array(
2868
		"en_US" => gettext("English"),
2869
		"pt_BR" => gettext("Portuguese (Brazil)"),
2870
		"tr" => gettext("Turkish"),
2871
	);
2872
	asort($locales);
2873
	return $locales;
2874
}
2875

    
2876
function system_get_language_code() {
2877
	global $config, $g_languages;
2878

    
2879
	// a language code, as per [RFC3066]
2880
	$language = $config['system']['language'];
2881
	//$code = $g_languages[$language]['code'];
2882
	$code = str_replace("_", "-", $language);
2883

    
2884
	if (empty($code)) {
2885
		$code = "en-US"; // Set default code.
2886
	}
2887

    
2888
	return $code;
2889
}
2890

    
2891
function system_get_language_codeset() {
2892
	global $config, $g_languages;
2893

    
2894
	$language = $config['system']['language'];
2895
	$codeset = $g_languages[$language]['codeset'];
2896

    
2897
	if (empty($codeset)) {
2898
		$codeset = "UTF-8"; // Set default codeset.
2899
	}
2900

    
2901
	return $codeset;
2902
}
2903

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

    
2936
function return_hex_ipv4($ipv4) {
2937
	if (!is_ipaddrv4($ipv4)) {
2938
		return(false);
2939
	}
2940

    
2941
	/* we need the hex form of the interface IPv4 address */
2942
	$ip4arr = explode(".", $ipv4);
2943
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2944
}
2945

    
2946
function convert_ipv6_to_128bit($ipv6) {
2947
	if (!is_ipaddrv6($ipv6)) {
2948
		return(false);
2949
	}
2950

    
2951
	$ip6arr = array();
2952
	$ip6prefix = Net_IPv6::uncompress($ipv6);
2953
	$ip6arr = explode(":", $ip6prefix);
2954
	/* binary presentation of the prefix for all 128 bits. */
2955
	$ip6prefixbin = "";
2956
	foreach ($ip6arr as $element) {
2957
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
2958
	}
2959
	return($ip6prefixbin);
2960
}
2961

    
2962
function convert_128bit_to_ipv6($ip6bin) {
2963
	if (strlen($ip6bin) <> 128) {
2964
		return(false);
2965
	}
2966

    
2967
	$ip6arr = array();
2968
	$ip6binarr = array();
2969
	$ip6binarr = str_split($ip6bin, 16);
2970
	foreach ($ip6binarr as $binpart) {
2971
		$ip6arr[] = dechex(bindec($binpart));
2972
	}
2973
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2974

    
2975
	return($ip6addr);
2976
}
2977

    
2978

    
2979
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
2980
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
2981
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
2982
/* 6to4 is 16 bits, e.g. 65535 */
2983
function calculate_ipv6_delegation_length($if) {
2984
	global $config;
2985

    
2986
	if (!is_array($config['interfaces'][$if])) {
2987
		return false;
2988
	}
2989

    
2990
	switch ($config['interfaces'][$if]['ipaddrv6']) {
2991
		case "6to4":
2992
			$pdlen = 16;
2993
			break;
2994
		case "6rd":
2995
			$rd6cfg = $config['interfaces'][$if];
2996
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
2997
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
2998
			break;
2999
		case "dhcp6":
3000
			$dhcp6cfg = $config['interfaces'][$if];
3001
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
3002
			break;
3003
		default:
3004
			$pdlen = 0;
3005
			break;
3006
	}
3007
	return($pdlen);
3008
}
3009

    
3010
function huawei_rssi_to_string($rssi) {
3011
	$dbm = array();
3012
	$i = 0;
3013
	$dbstart = -113;
3014
	while ($i < 32) {
3015
		$dbm[$i] = $dbstart + ($i * 2);
3016
		$i++;
3017
	}
3018
	$percent = round(($rssi / 31) * 100);
3019
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
3020
	return $string;
3021
}
3022

    
3023
function huawei_mode_to_string($mode, $submode) {
3024
	$modes[0] = "None";
3025
	$modes[1] = "AMPS";
3026
	$modes[2] = "CDMA";
3027
	$modes[3] = "GSM/GPRS";
3028
	$modes[4] = "HDR";
3029
	$modes[5] = "WCDMA";
3030
	$modes[6] = "GPS";
3031

    
3032
	$submodes[0] = "No Service";
3033
	$submodes[1] = "GSM";
3034
	$submodes[2] = "GPRS";
3035
	$submodes[3] = "EDGE";
3036
	$submodes[4] = "WCDMA";
3037
	$submodes[5] = "HSDPA";
3038
	$submodes[6] = "HSUPA";
3039
	$submodes[7] = "HSDPA+HSUPA";
3040
	$submodes[8] = "TD-SCDMA";
3041
	$submodes[9] = "HSPA+";
3042
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
3043
	return $string;
3044
}
3045

    
3046
function huawei_service_to_string($state) {
3047
	$modes[0] = "No";
3048
	$modes[1] = "Restricted";
3049
	$modes[2] = "Valid";
3050
	$modes[3] = "Restricted Regional";
3051
	$modes[4] = "Powersaving";
3052
	$string = "{$modes[$state]} Service";
3053
	return $string;
3054
}
3055

    
3056
function huawei_simstate_to_string($state) {
3057
	$modes[0] = "Invalid SIM/locked";
3058
	$modes[1] = "Valid SIM";
3059
	$modes[2] = "Invalid SIM CS";
3060
	$modes[3] = "Invalid SIM PS";
3061
	$modes[4] = "Invalid SIM CS/PS";
3062
	$modes[255] = "Missing SIM";
3063
	$string = "{$modes[$state]} State";
3064
	return $string;
3065
}
3066

    
3067
function zte_rssi_to_string($rssi) {
3068
	return huawei_rssi_to_string($rssi);
3069
}
3070

    
3071
function zte_mode_to_string($mode, $submode) {
3072
	$modes[0] = "No Service";
3073
	$modes[1] = "Limited Service";
3074
	$modes[2] = "GPRS";
3075
	$modes[3] = "GSM";
3076
	$modes[4] = "UMTS";
3077
	$modes[5] = "EDGE";
3078
	$modes[6] = "HSDPA";
3079

    
3080
	$submodes[0] = "CS_ONLY";
3081
	$submodes[1] = "PS_ONLY";
3082
	$submodes[2] = "CS_PS";
3083
	$submodes[3] = "CAMPED";
3084
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
3085
	return $string;
3086
}
3087

    
3088
function zte_service_to_string($state) {
3089
	$modes[0] = "Initializing";
3090
	$modes[1] = "Network Lock error";
3091
	$modes[2] = "Network Locked";
3092
	$modes[3] = "Unlocked or correct MCC/MNC";
3093
	$string = "{$modes[$state]} Service";
3094
	return $string;
3095
}
3096

    
3097
function zte_simstate_to_string($state) {
3098
	$modes[0] = "No action";
3099
	$modes[1] = "Network lock";
3100
	$modes[2] = "(U)SIM card lock";
3101
	$modes[3] = "Network Lock and (U)SIM card Lock";
3102
	$string = "{$modes[$state]} State";
3103
	return $string;
3104
}
3105

    
3106
function get_configured_pppoe_server_interfaces() {
3107
	global $config;
3108
	$iflist = array();
3109
	if (is_array($config['pppoes']['pppoe'])) {
3110
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
3111
			if ($pppoe['mode'] == "server") {
3112
				$int = "poes". $pppoe['pppoeid'];
3113
				$iflist[$int] = strtoupper($int);
3114
			}
3115
		}
3116
	}
3117
	return $iflist;
3118
}
3119

    
3120
function get_pppoes_child_interfaces($ifpattern) {
3121
	$if_arr = array();
3122
	if ($ifpattern == "") {
3123
		return;
3124
	}
3125

    
3126
	exec("ifconfig", $out, $ret);
3127
	foreach ($out as $line) {
3128
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3129
			$if_arr[] = $match[1];
3130
		}
3131
	}
3132
	return $if_arr;
3133

    
3134
}
3135

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

    
3176
/* Function to find and return the active XML RPC base URL to avoid code duplication */
3177
function get_active_xml_rpc_base_url() {
3178
	global $config, $g;
3179
	/* If the user has activated the option to enable an alternate xmlrpcbaseurl, and it's not empty, then use it */
3180
	if (isset($config['system']['altpkgrepo']['enable']) && !empty($config['system']['altpkgrepo']['xmlrpcbaseurl'])) {
3181
		return $config['system']['altpkgrepo']['xmlrpcbaseurl'];
3182
	} else {
3183
		return $g['xmlrpcbaseurl'];
3184
	}
3185
}
3186

    
3187
?>
(39-39/67)