Project

General

Profile

Download (86.9 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
 * add_text_to_file($file, $text): adds $text to $file.
455
 * replaces the text if it already exists.
456
 */
457
function add_text_to_file($file, $text, $replace = false) {
458
	if (file_exists($file) and is_writable($file)) {
459
		$filecontents = file($file);
460
		$filecontents = array_map('rtrim', $filecontents);
461
		array_push($filecontents, $text);
462
		if ($replace) {
463
			$filecontents = array_unique($filecontents);
464
		}
465

    
466
		$file_text = implode("\n", $filecontents);
467

    
468
		@file_put_contents($file, $file_text);
469
		return true;
470
	}
471
	return false;
472
}
473

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

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

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

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

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

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

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

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

    
550
	return false;
551
}
552

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

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

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

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

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

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

    
638
/*
639
 * http_post($server, $port, $url, $vars): does an http post to a web server
640
 *                                         posting the vars array.
641
 * written by nf@bigpond.net.au
642
 */
643
function http_post($server, $port, $url, $vars) {
644
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
645
	$urlencoded = "";
646
	while (list($key,$value) = each($vars)) {
647
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
648
	}
649
	$urlencoded = substr($urlencoded,0,-1);
650
	$content_length = strlen($urlencoded);
651
	$headers = "POST $url HTTP/1.1
652
Accept: */*
653
Accept-Language: en-au
654
Content-Type: application/x-www-form-urlencoded
655
User-Agent: $user_agent
656
Host: $server
657
Connection: Keep-Alive
658
Cache-Control: no-cache
659
Content-Length: $content_length
660

    
661
";
662

    
663
	$errno = "";
664
	$errstr = "";
665
	$fp = fsockopen($server, $port, $errno, $errstr);
666
	if (!$fp) {
667
		return false;
668
	}
669

    
670
	fputs($fp, $headers);
671
	fputs($fp, $urlencoded);
672

    
673
	$ret = "";
674
	while (!feof($fp)) {
675
		$ret.= fgets($fp, 1024);
676
	}
677
	fclose($fp);
678

    
679
	return $ret;
680
}
681

    
682
/*
683
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
684
 */
685
if (!function_exists('php_check_syntax')) {
686
	global $g;
687
	function php_check_syntax($code_to_check, &$errormessage) {
688
		return false;
689
		$fout = fopen("{$g['tmp_path']}/codetocheck.php","w");
690
		$code = $_POST['content'];
691
		$code = str_replace("<?php", "", $code);
692
		$code = str_replace("?>", "", $code);
693
		fwrite($fout, "<?php\n\n");
694
		fwrite($fout, $code_to_check);
695
		fwrite($fout, "\n\n?>\n");
696
		fclose($fout);
697
		$command = "/usr/local/bin/php -l {$g['tmp_path']}/codetocheck.php";
698
		$output = exec_command($command);
699
		if (stristr($output, "Errors parsing") == false) {
700
			echo "false\n";
701
			$errormessage = '';
702
			return(false);
703
		} else {
704
			$errormessage = $output;
705
			return(true);
706
		}
707
	}
708
}
709

    
710
/*
711
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
712
 */
713
if (!function_exists('php_check_syntax')) {
714
	function php_check_syntax($code_to_check, &$errormessage) {
715
		return false;
716
		$command = "/usr/local/bin/php -l " . escapeshellarg($code_to_check);
717
		$output = exec_command($command);
718
		if (stristr($output, "Errors parsing") == false) {
719
			echo "false\n";
720
			$errormessage = '';
721
			return(false);
722
		} else {
723
			$errormessage = $output;
724
			return(true);
725
		}
726
	}
727
}
728

    
729
/*
730
 * rmdir_recursive($path,$follow_links=false)
731
 * Recursively remove a directory tree (rm -rf path)
732
 * This is for directories _only_
733
 */
734
function rmdir_recursive($path,$follow_links=false) {
735
	$to_do = glob($path);
736
	if (!is_array($to_do)) {
737
		$to_do = array($to_do);
738
	}
739
	foreach ($to_do as $workingdir) { // Handle wildcards by foreaching.
740
		if (file_exists($workingdir)) {
741
			if (is_dir($workingdir)) {
742
				$dir = opendir($workingdir);
743
				while ($entry = readdir($dir)) {
744
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry"))) {
745
						unlink("$workingdir/$entry");
746
					} elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..') {
747
						rmdir_recursive("$workingdir/$entry");
748
					}
749
				}
750
				closedir($dir);
751
				rmdir($workingdir);
752
			} elseif (is_file($workingdir)) {
753
				unlink($workingdir);
754
			}
755
		}
756
	}
757
	return;
758
}
759

    
760
/*
761
 * call_pfsense_method(): Call a method exposed by the pfsense.org XMLRPC server.
762
 */
763
function call_pfsense_method($method, $params, $timeout = 0) {
764
	global $g, $config;
765

    
766
	$xmlrpc_base_url = get_active_xml_rpc_base_url();
767
	$xmlrpc_path = $g['xmlrpcpath'];
768

    
769
	$xmlrpcfqdn = preg_replace("(https?://)", "", $xmlrpc_base_url);
770
	$ip = gethostbyname($xmlrpcfqdn);
771
	if ($ip == $xmlrpcfqdn) {
772
		return false;
773
	}
774

    
775
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
776
	$port = 0;
777
	$proxyurl = "";
778
	$proxyport = 0;
779
	$proxyuser = "";
780
	$proxypass = "";
781
	if (!empty($config['system']['proxyurl'])) {
782
		$proxyurl = $config['system']['proxyurl'];
783
	}
784
	if (!empty($config['system']['proxyport']) && is_numeric($config['system']['proxyport'])) {
785
		$proxyport = $config['system']['proxyport'];
786
	}
787
	if (!empty($config['system']['proxyuser'])) {
788
		$proxyuser = $config['system']['proxyuser'];
789
	}
790
	if (!empty($config['system']['proxypass'])) {
791
		$proxypass = $config['system']['proxypass'];
792
	}
793
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url, $port, $proxyurl, $proxyport, $proxyuser, $proxypass);
794
	// If the ALT PKG Repo has a username/password set, use it.
795
	if ($config['system']['altpkgrepo']['username'] &&
796
	    $config['system']['altpkgrepo']['password']) {
797
		$username = $config['system']['altpkgrepo']['username'];
798
		$password = $config['system']['altpkgrepo']['password'];
799
		$cli->setCredentials($username, $password);
800
	}
801
	$resp = $cli->send($msg, $timeout);
802
	if (!is_object($resp)) {
803
		log_error(sprintf(gettext("XMLRPC communication error: %s"), $cli->errstr));
804
		return false;
805
	} elseif ($resp->faultCode()) {
806
		log_error(sprintf(gettext('XMLRPC request failed with error %1$s: %2$s'), $resp->faultCode(), $resp->faultString()));
807
		return false;
808
	} else {
809
		return XML_RPC_Decode($resp->value());
810
	}
811
}
812

    
813
/*
814
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
815
 */
816
function check_firmware_version($tocheck = "all", $return_php = true) {
817
	global $g, $config;
818

    
819
	$xmlrpc_base_url = get_active_xml_rpc_base_url();
820
	$xmlrpcfqdn = preg_replace("(https?://)", "", $xmlrpc_base_url);
821
	$ip = gethostbyname($xmlrpcfqdn);
822
	if ($ip == $xmlrpcfqdn) {
823
		return false;
824
	}
825
	$version = php_uname('r');
826
	$version = explode('-', $version);
827
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
828
		"kernel"   => array("version" => $version[0]),
829
		"base"     => array("version" => $version[0]),
830
		"platform" => trim(file_get_contents('/etc/platform')),
831
		"config_version" => $config['version']
832
		);
833
	unset($version);
834

    
835
	if ($tocheck == "all") {
836
		$params = $rawparams;
837
	} else {
838
		foreach ($tocheck as $check) {
839
			$params['check'] = $rawparams['check'];
840
			$params['platform'] = $rawparams['platform'];
841
		}
842
	}
843
	if ($config['system']['firmware']['branch']) {
844
		$params['branch'] = $config['system']['firmware']['branch'];
845
	}
846

    
847
	/* XXX: What is this method? */
848
	if (!($versions = call_pfsense_method('pfsense.get_firmware_version', $params))) {
849
		return false;
850
	} else {
851
		$versions["current"] = $params;
852
	}
853

    
854
	return $versions;
855
}
856

    
857
/*
858
 * host_firmware_version(): Return the versions used in this install
859
 */
860
function host_firmware_version($tocheck = "") {
861
	global $g, $config;
862

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

    
865
	return array(
866
		"firmware" => array("version" => trim(file_get_contents('/etc/version', " \n"))),
867
		"kernel"   => array("version" => $os_version),
868
		"base"     => array("version" => $os_version),
869
		"platform" => trim(file_get_contents('/etc/platform', " \n")),
870
		"config_version" => $config['version']
871
	);
872
}
873

    
874
function get_disk_info() {
875
	$diskout = "";
876
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
877
	return explode(' ', $diskout[0]);
878
}
879

    
880
/****f* pfsense-utils/strncpy
881
 * NAME
882
 *   strncpy - copy strings
883
 * INPUTS
884
 *   &$dst, $src, $length
885
 * RESULT
886
 *   none
887
 ******/
888
function strncpy(&$dst, $src, $length) {
889
	if (strlen($src) > $length) {
890
		$dst = substr($src, 0, $length);
891
	} else {
892
		$dst = $src;
893
	}
894
}
895

    
896
/****f* pfsense-utils/reload_interfaces_sync
897
 * NAME
898
 *   reload_interfaces - reload all interfaces
899
 * INPUTS
900
 *   none
901
 * RESULT
902
 *   none
903
 ******/
904
function reload_interfaces_sync() {
905
	global $config, $g;
906

    
907
	if ($g['debug']) {
908
		log_error(gettext("reload_interfaces_sync() is starting."));
909
	}
910

    
911
	/* parse config.xml again */
912
	$config = parse_config(true);
913

    
914
	/* enable routing */
915
	system_routing_enable();
916
	if ($g['debug']) {
917
		log_error(gettext("Enabling system routing"));
918
	}
919

    
920
	if ($g['debug']) {
921
		log_error(gettext("Cleaning up Interfaces"));
922
	}
923

    
924
	/* set up interfaces */
925
	interfaces_configure();
926
}
927

    
928
/****f* pfsense-utils/reload_all
929
 * NAME
930
 *   reload_all - triggers a reload of all settings
931
 *   * INPUTS
932
 *   none
933
 * RESULT
934
 *   none
935
 ******/
936
function reload_all() {
937
	send_event("service reload all");
938
}
939

    
940
/****f* pfsense-utils/reload_interfaces
941
 * NAME
942
 *   reload_interfaces - triggers a reload of all interfaces
943
 * INPUTS
944
 *   none
945
 * RESULT
946
 *   none
947
 ******/
948
function reload_interfaces() {
949
	send_event("interface all reload");
950
}
951

    
952
/****f* pfsense-utils/reload_all_sync
953
 * NAME
954
 *   reload_all - reload all settings
955
 *   * INPUTS
956
 *   none
957
 * RESULT
958
 *   none
959
 ******/
960
function reload_all_sync() {
961
	global $config, $g;
962

    
963
	/* parse config.xml again */
964
	$config = parse_config(true);
965

    
966
	/* set up our timezone */
967
	system_timezone_configure();
968

    
969
	/* set up our hostname */
970
	system_hostname_configure();
971

    
972
	/* make hosts file */
973
	system_hosts_generate();
974

    
975
	/* generate resolv.conf */
976
	system_resolvconf_generate();
977

    
978
	/* enable routing */
979
	system_routing_enable();
980

    
981
	/* set up interfaces */
982
	interfaces_configure();
983

    
984
	/* start dyndns service */
985
	services_dyndns_configure();
986

    
987
	/* configure cron service */
988
	configure_cron();
989

    
990
	/* start the NTP client */
991
	system_ntp_configure();
992

    
993
	/* sync pw database */
994
	conf_mount_rw();
995
	unlink_if_exists("/etc/spwd.db.tmp");
996
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
997
	conf_mount_ro();
998

    
999
	/* restart sshd */
1000
	send_event("service restart sshd");
1001

    
1002
	/* restart webConfigurator if needed */
1003
	send_event("service restart webgui");
1004
}
1005

    
1006
function setup_serial_port($when="save", $path="") {
1007
	global $g, $config;
1008
	conf_mount_rw();
1009
	$ttys_file = "{$path}/etc/ttys";
1010
	$boot_config_file = "{$path}/boot.config";
1011
	$loader_conf_file = "{$path}/boot/loader.conf";
1012
	/* serial console - write out /boot.config */
1013
	if (file_exists($boot_config_file)) {
1014
		$boot_config = file_get_contents($boot_config_file);
1015
	} else {
1016
		$boot_config = "";
1017
	}
1018

    
1019
	$serialspeed = (is_numeric($config['system']['serialspeed'])) ? $config['system']['serialspeed'] : "115200";
1020
	if ($g['platform'] != "cdrom") {
1021
		$boot_config_split = explode("\n", $boot_config);
1022
		$fd = fopen($boot_config_file,"w");
1023
		if ($fd) {
1024
			foreach ($boot_config_split as $bcs) {
1025
				if (stristr($bcs, "-D") || stristr($bcs, "-h")) {
1026
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1027
				} else {
1028
					if ($bcs <> "") {
1029
						fwrite($fd, "{$bcs}\n");
1030
					}
1031
				}
1032
			}
1033
			if (($g['platform'] == "nanobsd") && !file_exists("/etc/nano_use_vga.txt")) {
1034
				fwrite($fd, "-S{$serialspeed} -h");
1035
			} else if (is_serial_enabled()) {
1036
				fwrite($fd, "-S{$serialspeed} -D");
1037
			}
1038
			fclose($fd);
1039
		}
1040

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

    
1061
			if (($g['platform'] == "nanobsd") && !file_exists("/etc/nano_use_vga.txt")) {
1062
				$new_boot_config[] = 'boot_serial="YES"';
1063
				$new_boot_config[] = 'console="comconsole"';
1064
			} else if (is_serial_enabled()) {
1065
				$new_boot_config[] = 'boot_multicons="YES"';
1066
				$new_boot_config[] = 'boot_serial="YES"';
1067
				$primaryconsole = isset($g['primaryconsole_force']) ? $g['primaryconsole_force'] : $config['system']['primaryconsole'];
1068
				switch ($primaryconsole) {
1069
					case "video":
1070
						$new_boot_config[] = 'console="vidconsole,comconsole"';
1071
						break;
1072
					case "serial":
1073
					default:
1074
						$new_boot_config[] = 'console="comconsole,vidconsole"';
1075
				}
1076
			}
1077
			$new_boot_config[] = 'comconsole_speed="' . $serialspeed . '"';
1078
			$new_boot_config[] = 'hw.usb.no_pf="1"';
1079

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

    
1087
	$on_off = (is_serial_enabled() ? 'onifconsole' : 'off');
1088

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

    
1112
	conf_mount_ro();
1113
	return;
1114
}
1115

    
1116
function is_serial_enabled() {
1117
	global $g, $config;
1118

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

    
1125
	return true;
1126
}
1127

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

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

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

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

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

    
1157
	return false;
1158
}
1159

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

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

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

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

    
1182
	return false;
1183
}
1184

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

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

    
1193
	$dhcpdv6cfg = $config['dhcpdv6'];
1194
	$Iflist = get_configured_interface_list();
1195

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

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

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

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

    
1215
		return true;
1216
	}
1217

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

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

    
1232
		$ifcfgsnv6 = get_interface_subnetv6($if);
1233
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1234

    
1235
		if (!is_ipaddrv6($subnetv6)) {
1236
			continue;
1237
		}
1238

    
1239
		return true;
1240
	}
1241

    
1242
	return false;
1243
}
1244

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

    
1249
	$pppoeenable = false;
1250

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

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

    
1261
	return $pppoeenable;
1262
}
1263

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

    
1287
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1288

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1557
	return $ifinfo;
1558
}
1559

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

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

    
1575
	$uptime = time() - $boottime;
1576
	return $uptime;
1577
}
1578

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1750
	return false;
1751
}
1752

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

    
1758
function download_file($url, $destination, $verify_ssl = false, $connect_timeout = 60, $timeout = 0) {
1759
	global $config, $g;
1760

    
1761
	$fp = fopen($destination, "wb");
1762

    
1763
	if (!$fp) {
1764
		return false;
1765
	}
1766

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

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

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

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

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

    
1808
	$ch = curl_init();
1809
	curl_setopt($ch, CURLOPT_URL, $url_file);
1810
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1811
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1812
	/* Don't verify SSL peers since we don't have the certificates to do so. */
1813
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
1814
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1815
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1816
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1817
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1818
	curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version")));
1819

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

    
1831
	@curl_exec($ch);
1832
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1833
	if ($fout) {
1834
		fclose($fout);
1835
	}
1836
	curl_close($ch);
1837
	return ($http_code == 200) ? true : $http_code;
1838
}
1839

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

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

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

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

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

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

    
1970
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
1971
	global $g, $config, $pconfig, $debug;
1972
	if (!$origname) {
1973
		return;
1974
	}
1975

    
1976
	$sectionref = &$config;
1977
	foreach ($section as $sectionname) {
1978
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
1979
			$sectionref = &$sectionref[$sectionname];
1980
		} else {
1981
			return;
1982
		}
1983
	}
1984

    
1985
	if ($debug) {
1986
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
1987
		fwrite($fd, print_r($pconfig, true));
1988
	}
1989

    
1990
	if (is_array($sectionref)) {
1991
		foreach ($sectionref as $itemkey => $item) {
1992
			if ($debug) {
1993
				fwrite($fd, "$itemkey\n");
1994
			}
1995

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

    
2015
	if ($debug) {
2016
		fclose($fd);
2017
	}
2018

    
2019
}
2020

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

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

    
2064
function update_alias_url_data() {
2065
	global $config, $g;
2066

    
2067
	$updated = false;
2068

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

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

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

    
2109
	/* Report status to callers as well */
2110
	return $updated;
2111
}
2112

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

    
2143
	return true;
2144
}
2145

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

    
2176
	return true;
2177
}
2178

    
2179
function version_compare_dates($a, $b) {
2180
	$a_time = strtotime($a);
2181
	$b_time = strtotime($b);
2182

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

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

    
2267
		// First try to compare the numeric parts of the version string.
2268
		$v = version_compare_numeric($cur_num, $rem_num);
2269

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

    
2280
	$urltable_prefix = "/var/db/aliastables/";
2281
	$urltable_filename = $urltable_prefix . $name . ".txt";
2282

    
2283
	// Make the aliases directory if it doesn't exist
2284
	if (!file_exists($urltable_prefix)) {
2285
		mkdir($urltable_prefix);
2286
	} elseif (!is_dir($urltable_prefix)) {
2287
		unlink($urltable_prefix);
2288
		mkdir($urltable_prefix);
2289
	}
2290

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

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

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

    
2343
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2344
		$slice = $TOFLASH;
2345
	} else {
2346
		$slice = $BOOTFLASH;
2347
	}
2348

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

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

    
2407
	mkdir($tmppath);
2408
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2409
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2410
	copy("/etc/fstab", $fstabpath);
2411

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

    
2428
	return $status;
2429
}
2430
function nanobsd_detect_slice_info() {
2431
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2432
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2433
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2434

    
2435
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2436
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2437
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2438
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2439

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

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

    
2461
function nanobsd_friendly_slice_name($slicename) {
2462
	global $g;
2463
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2464
}
2465

    
2466
function get_include_contents($filename) {
2467
	if (is_file($filename)) {
2468
		ob_start();
2469
		include $filename;
2470
		$contents = ob_get_contents();
2471
		ob_end_clean();
2472
		return $contents;
2473
	}
2474
	return false;
2475
}
2476

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

    
2590
function get_country_name($country_code) {
2591
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2592
		return "";
2593
	}
2594

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

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

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

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

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

    
2627
	usort($config['filter']['rule'], "filter_rules_compare");
2628

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

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

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

    
2675
		$i++;
2676
	}
2677
	return $ipv6;
2678
}
2679

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

    
2706
}
2707

    
2708
/****f* pfsense-utils/is_ipaddr_configured
2709
 * NAME
2710
 *   is_ipaddr_configured
2711
 * INPUTS
2712
 *   IP Address to check.
2713
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2714
 * RESULT
2715
 *   returns true if the IP Address is
2716
 *   configured and present on this device.
2717
*/
2718
function is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false) {
2719
	global $config;
2720

    
2721
	$pos = strpos($ignore_if, '_virtualip');
2722
	if ($pos !== false) {
2723
		$ignore_vip_id = substr($ignore_if, $pos+10);
2724
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2725
	} else {
2726
		$ignore_vip_id = -1;
2727
		$ignore_vip_if = $ignore_if;
2728
	}
2729

    
2730
	$isipv6 = is_ipaddrv6($ipaddr);
2731

    
2732
	if ($check_subnets) {
2733
		$iflist = get_configured_interface_list();
2734
		foreach ($iflist as $if => $ifname) {
2735
			if ($ignore_if == $if) {
2736
				continue;
2737
			}
2738

    
2739
			if ($isipv6 === true) {
2740
				$bitmask = get_interface_subnetv6($if);
2741
				$subnet = gen_subnetv6(get_interface_ipv6($if), $bitmask);
2742
			} else {
2743
				$bitmask = get_interface_subnet($if);
2744
				$subnet = gen_subnet(get_interface_ip($if), $bitmask);
2745
			}
2746

    
2747
			if (ip_in_subnet($ipaddr, $subnet . '/' . $bitmask)) {
2748
				return true;
2749
			}
2750
		}
2751
	} else {
2752
		if ($isipv6 === true) {
2753
			$interface_list_ips = get_configured_ipv6_addresses();
2754
		} else {
2755
			$interface_list_ips = get_configured_ip_addresses();
2756
		}
2757

    
2758
		foreach ($interface_list_ips as $if => $ilips) {
2759
			if ($ignore_if == $if) {
2760
				continue;
2761
			}
2762
			if (strcasecmp($ipaddr, $ilips) == 0) {
2763
				return true;
2764
			}
2765
		}
2766
	}
2767

    
2768
	$interface_list_vips = get_configured_vips_list(true);
2769
	foreach ($interface_list_vips as $id => $vip) {
2770
		/* Skip CARP interfaces here since they were already checked above */
2771
		if ($id == $ignore_vip_id || (substr($ignore_if, 0, 4) == '_vip') && substr($ignore_vip_if, 5)  == $vip['uniqdid']) {
2772
			continue;
2773
		}
2774
		if (strcasecmp($ipaddr, $vip['ipaddr']) == 0) {
2775
			return true;
2776
		}
2777
	}
2778

    
2779
	if ($check_localip) {
2780
		if (is_array($config['pptpd']) && !empty($config['pptpd']['localip']) && (strcasecmp($ipaddr, $config['pptpd']['localip']) == 0)) {
2781
			return true;
2782
		}
2783

    
2784
		if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0)) {
2785
			return true;
2786
		}
2787
	}
2788

    
2789
	return false;
2790
}
2791

    
2792
/****f* pfsense-utils/pfSense_handle_custom_code
2793
 * NAME
2794
 *   pfSense_handle_custom_code
2795
 * INPUTS
2796
 *   directory name to process
2797
 * RESULT
2798
 *   globs the directory and includes the files
2799
 */
2800
function pfSense_handle_custom_code($src_dir) {
2801
	// Allow extending of the nat edit page and include custom input validation
2802
	if (is_dir("$src_dir")) {
2803
		$cf = glob($src_dir . "/*.inc");
2804
		foreach ($cf as $nf) {
2805
			if ($nf == "." || $nf == "..") {
2806
				continue;
2807
			}
2808
			// Include the extra handler
2809
			include("$nf");
2810
		}
2811
	}
2812
}
2813

    
2814
function set_language($lang = 'en_US', $encoding = "UTF-8") {
2815
	putenv("LANG={$lang}.{$encoding}");
2816
	setlocale(LC_ALL, "{$lang}.{$encoding}");
2817
	textdomain("pfSense");
2818
	bindtextdomain("pfSense","/usr/local/share/locale");
2819
	bind_textdomain_codeset("pfSense","{$lang}.{$encoding}");
2820
}
2821

    
2822
function get_locale_list() {
2823
	$locales = array(
2824
		"en_US" => gettext("English"),
2825
		"pt_BR" => gettext("Portuguese (Brazil)"),
2826
		"tr" => gettext("Turkish"),
2827
	);
2828
	asort($locales);
2829
	return $locales;
2830
}
2831

    
2832
function system_get_language_code() {
2833
	global $config, $g_languages;
2834

    
2835
	// a language code, as per [RFC3066]
2836
	$language = $config['system']['language'];
2837
	//$code = $g_languages[$language]['code'];
2838
	$code = str_replace("_", "-", $language);
2839

    
2840
	if (empty($code)) {
2841
		$code = "en-US"; // Set default code.
2842
	}
2843

    
2844
	return $code;
2845
}
2846

    
2847
function system_get_language_codeset() {
2848
	global $config, $g_languages;
2849

    
2850
	$language = $config['system']['language'];
2851
	$codeset = $g_languages[$language]['codeset'];
2852

    
2853
	if (empty($codeset)) {
2854
		$codeset = "UTF-8"; // Set default codeset.
2855
	}
2856

    
2857
	return $codeset;
2858
}
2859

    
2860
/* Available languages/locales */
2861
$g_languages = array (
2862
	"sq"    => array("codeset" => "UTF-8", "desc" => gettext("Albanian")),
2863
	"bg"    => array("codeset" => "UTF-8", "desc" => gettext("Bulgarian")),
2864
	"zh_CN" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Simplified)")),
2865
	"zh_TW" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Traditional)")),
2866
	"nl"    => array("codeset" => "UTF-8", "desc" => gettext("Dutch")),
2867
	"da"    => array("codeset" => "UTF-8", "desc" => gettext("Danish")),
2868
	"en_US" => array("codeset" => "UTF-8", "desc" => gettext("English")),
2869
	"fi"    => array("codeset" => "UTF-8", "desc" => gettext("Finnish")),
2870
	"fr"    => array("codeset" => "UTF-8", "desc" => gettext("French")),
2871
	"de"    => array("codeset" => "UTF-8", "desc" => gettext("German")),
2872
	"el"    => array("codeset" => "UTF-8", "desc" => gettext("Greek")),
2873
	"hu"    => array("codeset" => "UTF-8", "desc" => gettext("Hungarian")),
2874
	"it"    => array("codeset" => "UTF-8", "desc" => gettext("Italian")),
2875
	"ja"    => array("codeset" => "UTF-8", "desc" => gettext("Japanese")),
2876
	"ko"    => array("codeset" => "UTF-8", "desc" => gettext("Korean")),
2877
	"lv"    => array("codeset" => "UTF-8", "desc" => gettext("Latvian")),
2878
	"nb"    => array("codeset" => "UTF-8", "desc" => gettext("Norwegian (Bokmal)")),
2879
	"pl"    => array("codeset" => "UTF-8", "desc" => gettext("Polish")),
2880
	"pt_BR" => array("codeset" => "ISO-8859-1", "desc" => gettext("Portuguese (Brazil)")),
2881
	"pt"    => array("codeset" => "UTF-8", "desc" => gettext("Portuguese (Portugal)")),
2882
	"ro"    => array("codeset" => "UTF-8", "desc" => gettext("Romanian")),
2883
	"ru"    => array("codeset" => "UTF-8", "desc" => gettext("Russian")),
2884
	"sl"    => array("codeset" => "UTF-8", "desc" => gettext("Slovenian")),
2885
	"tr"    => array("codeset" => "UTF-8", "desc" => gettext("Turkish")),
2886
	"es"    => array("codeset" => "UTF-8", "desc" => gettext("Spanish")),
2887
	"sv"    => array("codeset" => "UTF-8", "desc" => gettext("Swedish")),
2888
	"sk"    => array("codeset" => "UTF-8", "desc" => gettext("Slovak")),
2889
	"cs"    => array("codeset" => "UTF-8", "desc" => gettext("Czech"))
2890
);
2891

    
2892
function return_hex_ipv4($ipv4) {
2893
	if (!is_ipaddrv4($ipv4)) {
2894
		return(false);
2895
	}
2896

    
2897
	/* we need the hex form of the interface IPv4 address */
2898
	$ip4arr = explode(".", $ipv4);
2899
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2900
}
2901

    
2902
function convert_ipv6_to_128bit($ipv6) {
2903
	if (!is_ipaddrv6($ipv6)) {
2904
		return(false);
2905
	}
2906

    
2907
	$ip6arr = array();
2908
	$ip6prefix = Net_IPv6::uncompress($ipv6);
2909
	$ip6arr = explode(":", $ip6prefix);
2910
	/* binary presentation of the prefix for all 128 bits. */
2911
	$ip6prefixbin = "";
2912
	foreach ($ip6arr as $element) {
2913
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
2914
	}
2915
	return($ip6prefixbin);
2916
}
2917

    
2918
function convert_128bit_to_ipv6($ip6bin) {
2919
	if (strlen($ip6bin) <> 128) {
2920
		return(false);
2921
	}
2922

    
2923
	$ip6arr = array();
2924
	$ip6binarr = array();
2925
	$ip6binarr = str_split($ip6bin, 16);
2926
	foreach ($ip6binarr as $binpart) {
2927
		$ip6arr[] = dechex(bindec($binpart));
2928
	}
2929
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2930

    
2931
	return($ip6addr);
2932
}
2933

    
2934

    
2935
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
2936
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
2937
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
2938
/* 6to4 is 16 bits, e.g. 65535 */
2939
function calculate_ipv6_delegation_length($if) {
2940
	global $config;
2941

    
2942
	if (!is_array($config['interfaces'][$if])) {
2943
		return false;
2944
	}
2945

    
2946
	switch ($config['interfaces'][$if]['ipaddrv6']) {
2947
		case "6to4":
2948
			$pdlen = 16;
2949
			break;
2950
		case "6rd":
2951
			$rd6cfg = $config['interfaces'][$if];
2952
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
2953
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
2954
			break;
2955
		case "dhcp6":
2956
			$dhcp6cfg = $config['interfaces'][$if];
2957
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
2958
			break;
2959
		default:
2960
			$pdlen = 0;
2961
			break;
2962
	}
2963
	return($pdlen);
2964
}
2965

    
2966
function huawei_rssi_to_string($rssi) {
2967
	$dbm = array();
2968
	$i = 0;
2969
	$dbstart = -113;
2970
	while ($i < 32) {
2971
		$dbm[$i] = $dbstart + ($i * 2);
2972
		$i++;
2973
	}
2974
	$percent = round(($rssi / 31) * 100);
2975
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
2976
	return $string;
2977
}
2978

    
2979
function huawei_mode_to_string($mode, $submode) {
2980
	$modes[0] = "None";
2981
	$modes[1] = "AMPS";
2982
	$modes[2] = "CDMA";
2983
	$modes[3] = "GSM/GPRS";
2984
	$modes[4] = "HDR";
2985
	$modes[5] = "WCDMA";
2986
	$modes[6] = "GPS";
2987

    
2988
	$submodes[0] = "No Service";
2989
	$submodes[1] = "GSM";
2990
	$submodes[2] = "GPRS";
2991
	$submodes[3] = "EDGE";
2992
	$submodes[4] = "WCDMA";
2993
	$submodes[5] = "HSDPA";
2994
	$submodes[6] = "HSUPA";
2995
	$submodes[7] = "HSDPA+HSUPA";
2996
	$submodes[8] = "TD-SCDMA";
2997
	$submodes[9] = "HSPA+";
2998
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
2999
	return $string;
3000
}
3001

    
3002
function huawei_service_to_string($state) {
3003
	$modes[0] = "No";
3004
	$modes[1] = "Restricted";
3005
	$modes[2] = "Valid";
3006
	$modes[3] = "Restricted Regional";
3007
	$modes[4] = "Powersaving";
3008
	$string = "{$modes[$state]} Service";
3009
	return $string;
3010
}
3011

    
3012
function huawei_simstate_to_string($state) {
3013
	$modes[0] = "Invalid SIM/locked";
3014
	$modes[1] = "Valid SIM";
3015
	$modes[2] = "Invalid SIM CS";
3016
	$modes[3] = "Invalid SIM PS";
3017
	$modes[4] = "Invalid SIM CS/PS";
3018
	$modes[255] = "Missing SIM";
3019
	$string = "{$modes[$state]} State";
3020
	return $string;
3021
}
3022

    
3023
function zte_rssi_to_string($rssi) {
3024
	return huawei_rssi_to_string($rssi);
3025
}
3026

    
3027
function zte_mode_to_string($mode, $submode) {
3028
	$modes[0] = "No Service";
3029
	$modes[1] = "Limited Service";
3030
	$modes[2] = "GPRS";
3031
	$modes[3] = "GSM";
3032
	$modes[4] = "UMTS";
3033
	$modes[5] = "EDGE";
3034
	$modes[6] = "HSDPA";
3035

    
3036
	$submodes[0] = "CS_ONLY";
3037
	$submodes[1] = "PS_ONLY";
3038
	$submodes[2] = "CS_PS";
3039
	$submodes[3] = "CAMPED";
3040
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
3041
	return $string;
3042
}
3043

    
3044
function zte_service_to_string($state) {
3045
	$modes[0] = "Initializing";
3046
	$modes[1] = "Network Lock error";
3047
	$modes[2] = "Network Locked";
3048
	$modes[3] = "Unlocked or correct MCC/MNC";
3049
	$string = "{$modes[$state]} Service";
3050
	return $string;
3051
}
3052

    
3053
function zte_simstate_to_string($state) {
3054
	$modes[0] = "No action";
3055
	$modes[1] = "Network lock";
3056
	$modes[2] = "(U)SIM card lock";
3057
	$modes[3] = "Network Lock and (U)SIM card Lock";
3058
	$string = "{$modes[$state]} State";
3059
	return $string;
3060
}
3061

    
3062
function get_configured_pppoe_server_interfaces() {
3063
	global $config;
3064
	$iflist = array();
3065
	if (is_array($config['pppoes']['pppoe'])) {
3066
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
3067
			if ($pppoe['mode'] == "server") {
3068
				$int = "poes". $pppoe['pppoeid'];
3069
				$iflist[$int] = strtoupper($int);
3070
			}
3071
		}
3072
	}
3073
	return $iflist;
3074
}
3075

    
3076
function get_pppoes_child_interfaces($ifpattern) {
3077
	$if_arr = array();
3078
	if ($ifpattern == "") {
3079
		return;
3080
	}
3081

    
3082
	exec("ifconfig", $out, $ret);
3083
	foreach ($out as $line) {
3084
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3085
			$if_arr[] = $match[1];
3086
		}
3087
	}
3088
	return $if_arr;
3089

    
3090
}
3091

    
3092
/****f* pfsense-utils/pkg_call_plugins
3093
 * NAME
3094
 *   pkg_call_plugins
3095
 * INPUTS
3096
 *   $plugin_type value used to search in package configuration if the plugin is used, also used to create the function name
3097
 *   $plugin_params parameters to pass to the plugin function for passing multiple parameters a array can be used.
3098
 * RESULT
3099
 *   returns associative array results from the plugin calls for each package
3100
 * NOTES
3101
 *   This generic function can be used to notify or retrieve results from functions that are defined in packages.
3102
 ******/
3103
function pkg_call_plugins($plugin_type, $plugin_params) {
3104
	global $g, $config;
3105
	$results = array();
3106
	if (!is_array($config['installedpackages']['package'])) {
3107
		return $results;
3108
	}
3109
	foreach ($config['installedpackages']['package'] as $package) {
3110
		if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
3111
			continue;
3112
		}
3113
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], 'packagegui');
3114
		$pkgname = substr(reverse_strrchr($package['configurationfile'], "."),0,-1);
3115
		if (is_array($pkg_config['plugins']['item'])) {
3116
			foreach ($pkg_config['plugins']['item'] as $plugin) {
3117
				if ($plugin['type'] == $plugin_type) {
3118
					if (file_exists($pkg_config['include_file'])) {
3119
						require_once($pkg_config['include_file']);
3120
					} else {
3121
						continue;
3122
					}
3123
					$plugin_function = $pkgname . '_'. $plugin_type;
3124
					$results[$pkgname] = @eval($plugin_function($plugin_params));
3125
				}
3126
			}
3127
		}
3128
	}
3129
	return $results;
3130
}
3131

    
3132
/* Function to find and return the active XML RPC base URL to avoid code duplication */
3133
function get_active_xml_rpc_base_url() {
3134
	global $config, $g;
3135
	/* If the user has activated the option to enable an alternate xmlrpcbaseurl, and it's not empty, then use it */
3136
	if (isset($config['system']['altpkgrepo']['enable']) && !empty($config['system']['altpkgrepo']['xmlrpcbaseurl'])) {
3137
		return $config['system']['altpkgrepo']['xmlrpcbaseurl'];
3138
	} else {
3139
		return $g['xmlrpcbaseurl'];
3140
	}
3141
}
3142

    
3143
?>
(40-40/68)