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
 *
11
 * Copyright (C) 2004-2007 Scott Ullrich (sullrich@gmail.com)
12
 * All rights reserved.
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *
16
 * 1. Redistributions of source code must retain the above copyright notice,
17
 * this list of conditions and the following disclaimer.
18
 *
19
 * 2. Redistributions in binary form must reproduce the above copyright
20
 * notice, this list of conditions and the following disclaimer in the
21
 * documentation and/or other materials provided with the distribution.
22
 *
23
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
27
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
 * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 * POSSIBILITY OF SUCH DAMAGE.
33
 *
34
 */
35

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

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

    
58
/****f* pfsense-utils/have_ruleint_access
59
 * NAME
60
 *   have_ruleint_access
61
 * INPUTS
62
 *	none
63
 * RESULT
64
 *   returns true if user has access to edit a specific firewall interface
65
 ******/
66
function have_ruleint_access($if) {
67
	$security_url = "firewall_rules.php?if=". strtolower($if);
68
	if(isAllowedPage($security_url))
69
		return true;
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
	return $isprivate;
112
}
113

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

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

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

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

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

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

    
175
	if(isset($config['system']['disablelargereceiveoffloading']))
176
		$flags_off |= IFCAP_LRO;
177
	else if (isset($options['caps']['lro']))
178
		$flags_on |= IFCAP_LRO;
179

    
180
	/* if the NIC supports polling *AND* it is enabled in the GUI */
181
	if (!isset($config['system']['polling']))
182
		$flags_off |= IFCAP_POLLING;
183
	else if (isset($options['caps']['polling']))
184
		$flags_on |= IFCAP_POLLING;
185

    
186
	pfSense_interface_capabilities($iface, -$flags_off);
187
	pfSense_interface_capabilities($iface, $flags_on);
188
}
189

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

    
203
	$int = get_real_interface($interface);
204
	if(empty($int))
205
		return;
206

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

    
217
	/* This is mostly for vlans and ppp types */
218
	$realhwif = get_parent_interface($interface);
219
	if ($realhwif[0] == $int)
220
		hardware_offloading_applyflags($int);
221
	else {
222
		hardware_offloading_applyflags($realhwif[0]);
223
		hardware_offloading_applyflags($int);
224
	}
225
}
226

    
227
/****f* pfsense-utils/interface_supports_polling
228
 * NAME
229
 *   checks to see if an interface supports polling according to man polling
230
 * INPUTS
231
 *
232
 * RESULT
233
 *   true or false
234
 * NOTES
235
 *
236
 ******/
237
function interface_supports_polling($iface) {
238
	$opts = pfSense_get_interface_addresses($iface);
239
	if (is_array($opts) && isset($opts['caps']['polling']))
240
		return true;
241

    
242
	return false;
243
}
244

    
245
/****f* pfsense-utils/is_alias_inuse
246
 * NAME
247
 *   checks to see if an alias is currently in use by a rule
248
 * INPUTS
249
 *
250
 * RESULT
251
 *   true or false
252
 * NOTES
253
 *
254
 ******/
255
function is_alias_inuse($alias) {
256
	global $g, $config;
257

    
258
	if($alias == "") return false;
259
	/* loop through firewall rules looking for alias in use */
260
	if(is_array($config['filter']['rule']))
261
		foreach($config['filter']['rule'] as $rule) {
262
			if($rule['source']['address'])
263
				if($rule['source']['address'] == $alias)
264
					return true;
265
			if($rule['destination']['address'])
266
				if($rule['destination']['address'] == $alias)
267
					return true;
268
		}
269
	/* loop through nat rules looking for alias in use */
270
	if(is_array($config['nat']['rule']))
271
		foreach($config['nat']['rule'] as $rule) {
272
			if($rule['target'] && $rule['target'] == $alias)
273
				return true;
274
			if($rule['source']['address'] && $rule['source']['address'] == $alias)
275
				return true;
276
			if($rule['destination']['address'] && $rule['destination']['address'] == $alias)
277
				return true;
278
		}
279
	return false;
280
}
281

    
282
/****f* pfsense-utils/is_schedule_inuse
283
 * NAME
284
 *   checks to see if a schedule is currently in use by a rule
285
 * INPUTS
286
 *
287
 * RESULT
288
 *   true or false
289
 * NOTES
290
 *
291
 ******/
292
function is_schedule_inuse($schedule) {
293
	global $g, $config;
294

    
295
	if($schedule == "") return false;
296
	/* loop through firewall rules looking for schedule in use */
297
	if(is_array($config['filter']['rule']))
298
		foreach($config['filter']['rule'] as $rule) {
299
			if($rule['sched'] == $schedule)
300
				return true;
301
		}
302
	return false;
303
}
304

    
305
/****f* pfsense-utils/setup_polling
306
 * NAME
307
 *   sets up polling
308
 * INPUTS
309
 *
310
 * RESULT
311
 *   null
312
 * NOTES
313
 *
314
 ******/
315
function setup_polling() {
316
	global $g, $config;
317

    
318
	if (isset($config['system']['polling']))
319
		set_single_sysctl("kern.polling.idle_poll", "1");
320
	else
321
		set_single_sysctl("kern.polling.idle_poll", "0");
322

    
323
	if($config['system']['polling_each_burst'])
324
		set_single_sysctl("kern.polling.each_burst", $config['system']['polling_each_burst']);
325
	if($config['system']['polling_burst_max'])
326
		set_single_sysctl("kern.polling.burst_max", $config['system']['polling_burst_max']);
327
	if($config['system']['polling_user_frac'])
328
		set_single_sysctl("kern.polling.user_frac", $config['system']['polling_user_frac']);
329
}
330

    
331
/****f* pfsense-utils/setup_microcode
332
 * NAME
333
 *   enumerates all interfaces and calls enable_hardware_offloading which
334
 *   enables a NIC's supported hardware features.
335
 * INPUTS
336
 *
337
 * RESULT
338
 *   null
339
 * NOTES
340
 *   This function only supports the fxp driver's loadable microcode.
341
 ******/
342
function setup_microcode() {
343

    
344
	/* if list */
345
	$iflist = get_configured_interface_list(false, true);
346
	foreach($iflist as $if => $ifdescr)
347
		enable_hardware_offloading($if);
348
	unset($iflist);
349
}
350

    
351
/****f* pfsense-utils/get_carp_status
352
 * NAME
353
 *   get_carp_status - Return whether CARP is enabled or disabled.
354
 * RESULT
355
 *   boolean	- true if CARP is enabled, false if otherwise.
356
 ******/
357
function get_carp_status() {
358
	/* grab the current status of carp */
359
	$status = get_single_sysctl('net.inet.carp.allow');
360
	return (intval($status) > 0);
361
}
362

    
363
/*
364
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
365

    
366
 */
367
function convert_ip_to_network_format($ip, $subnet) {
368
	$ipsplit = explode('.', $ip);
369
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
370
	return $string;
371
}
372

    
373
/*
374
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
375
 */
376
function get_carp_interface_status($carpinterface) {
377
	$carp_query = "";
378

    
379
	/* XXX: Need to find a better way for this! */
380
	list ($interface, $vhid) = explode("_vip", $carpinterface);
381
	$interface = get_real_interface($interface);
382
	exec("/sbin/ifconfig $interface | /usr/bin/grep -v grep | /usr/bin/grep carp: | /usr/bin/grep 'vhid {$vhid}'", $carp_query);
383
	foreach($carp_query as $int) {
384
		if(stristr($int, "MASTER"))
385
			return "MASTER";
386
		if(stristr($int, "BACKUP"))
387
			return "BACKUP";
388
		if(stristr($int, "INIT"))
389
			return "INIT";
390
	}
391
	return;
392
}
393

    
394
/*
395
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
396
 */
397
function get_pfsync_interface_status($pfsyncinterface) {
398
	if (!does_interface_exist($pfsyncinterface))
399
		return;
400

    
401
	return exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/awk '/pfsync:/ {print \$5}'");
402
}
403

    
404
/*
405
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
406
 */
407
function add_rule_to_anchor($anchor, $rule, $label) {
408
	mwexec("echo " . escapeshellarg($rule) . " | /sbin/pfctl -a " . escapeshellarg($anchor) . ":" . escapeshellarg($label) . " -f -");
409
}
410

    
411
/*
412
 * remove_text_from_file
413
 * remove $text from file $file
414
 */
415
function remove_text_from_file($file, $text) {
416
	if(!file_exists($file) && !is_writable($file))
417
		return;
418
	$filecontents = file_get_contents($file);
419
	$text = str_replace($text, "", $filecontents);
420
	@file_put_contents($file, $text);
421
}
422

    
423
/*
424
 * add_text_to_file($file, $text): adds $text to $file.
425
 * replaces the text if it already exists.
426
 */
427
function add_text_to_file($file, $text, $replace = false) {
428
	if(file_exists($file) and is_writable($file)) {
429
		$filecontents = file($file);
430
		$filecontents = array_map('rtrim', $filecontents);
431
		array_push($filecontents, $text);
432
		if ($replace)
433
			$filecontents = array_unique($filecontents);
434

    
435
		$file_text = implode("\n", $filecontents);
436

    
437
		@file_put_contents($file, $file_text);
438
		return true;
439
	}
440
	return false;
441
}
442

    
443
/*
444
 *   after_sync_bump_adv_skew(): create skew values by 1S
445
 */
446
function after_sync_bump_adv_skew() {
447
	global $config, $g;
448
	$processed_skew = 1;
449
	$a_vip = &$config['virtualip']['vip'];
450
	foreach ($a_vip as $vipent) {
451
		if($vipent['advskew'] <> "") {
452
			$processed_skew = 1;
453
			$vipent['advskew'] = $vipent['advskew']+1;
454
		}
455
	}
456
	if($processed_skew == 1)
457
		write_config(gettext("After synch increase advertising skew"));
458
}
459

    
460
/*
461
 * get_filename_from_url($url): converts a url to its filename.
462
 */
463
function get_filename_from_url($url) {
464
	return basename($url);
465
}
466

    
467
/*
468
 *   get_dir: return an array of $dir
469
 */
470
function get_dir($dir) {
471
	$dir_array = array();
472
	$d = dir($dir);
473
	while (false !== ($entry = $d->read())) {
474
		array_push($dir_array, $entry);
475
	}
476
	$d->close();
477
	return $dir_array;
478
}
479

    
480
/****f* pfsense-utils/WakeOnLan
481
 * NAME
482
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
483
 * RESULT
484
 *   true/false - true if the operation was successful
485
 ******/
486
function WakeOnLan($addr, $mac)
487
{
488
	$addr_byte = explode(':', $mac);
489
	$hw_addr = '';
490

    
491
	for ($a=0; $a < 6; $a++)
492
		$hw_addr .= chr(hexdec($addr_byte[$a]));
493

    
494
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
495

    
496
	for ($a = 1; $a <= 16; $a++)
497
		$msg .= $hw_addr;
498

    
499
	// send it to the broadcast address using UDP
500
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
501
	if ($s == false) {
502
		log_error(gettext("Error creating socket!"));
503
		log_error(sprintf(gettext("Error code is '%1\$s' - %2\$s"), socket_last_error($s), socket_strerror(socket_last_error($s))));
504
	} else {
505
		// setting a broadcast option to socket:
506
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
507
		if($opt_ret < 0)
508
			log_error(sprintf(gettext("setsockopt() failed, error: %s"), strerror($opt_ret)));
509
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
510
		socket_close($s);
511
		log_error(sprintf(gettext('Magic Packet sent (%1$s) to {%2$s} MAC=%3$s'), $e, $addr, $mac));
512
		return true;
513
	}
514

    
515
	return false;
516
}
517

    
518
/*
519
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
520
 *					 Useful for finding paths and stripping file extensions.
521
 */
522
function reverse_strrchr($haystack, $needle) {
523
	if (!is_string($haystack))
524
		return;
525
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
526
}
527

    
528
/*
529
 *  backup_config_section($section): returns as an xml file string of
530
 *                                   the configuration section
531
 */
532
function backup_config_section($section_name) {
533
	global $config;
534
	$new_section = &$config[$section_name];
535
	/* generate configuration XML */
536
	$xmlconfig = dump_xml_config($new_section, $section_name);
537
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
538
	return $xmlconfig;
539
}
540

    
541
/*
542
 *  restore_config_section($section_name, new_contents): restore a configuration section,
543
 *                                                  and write the configuration out
544
 *                                                  to disk/cf.
545
 */
546
function restore_config_section($section_name, $new_contents) {
547
	global $config, $g;
548
	conf_mount_rw();
549
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
550
	fwrite($fout, $new_contents);
551
	fclose($fout);
552

    
553
	$xml = parse_xml_config($g['tmp_path'] . "/tmpxml", null);
554
	if ($xml['pfsense']) {
555
		$xml = $xml['pfsense'];
556
	}
557
	else if ($xml['m0n0wall']) {
558
		$xml = $xml['m0n0wall'];
559
	}
560
	if ($xml[$section_name]) {
561
		$section_xml = $xml[$section_name];
562
	} else {
563
		$section_xml = -1;
564
	}
565

    
566
	@unlink($g['tmp_path'] . "/tmpxml");
567
	if ($section_xml === -1) {
568
		return false;
569
	}
570
	$config[$section_name] = &$section_xml;
571
	if(file_exists("{$g['tmp_path']}/config.cache"))
572
		unlink("{$g['tmp_path']}/config.cache");
573
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
574
	disable_security_checks();
575
	conf_mount_ro();
576
	return true;
577
}
578

    
579
/*
580
 *  merge_config_section($section_name, new_contents):   restore a configuration section,
581
 *                                                  and write the configuration out
582
 *                                                  to disk/cf.  But preserve the prior
583
 * 													structure if needed
584
 */
585
function merge_config_section($section_name, $new_contents) {
586
	global $config;
587
	conf_mount_rw();
588
	$fname = get_tmp_filename();
589
	$fout = fopen($fname, "w");
590
	fwrite($fout, $new_contents);
591
	fclose($fout);
592
	$section_xml = parse_xml_config($fname, $section_name);
593
	$config[$section_name] = $section_xml;
594
	unlink($fname);
595
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
596
	disable_security_checks();
597
	conf_mount_ro();
598
	return;
599
}
600

    
601
/*
602
 * http_post($server, $port, $url, $vars): does an http post to a web server
603
 *                                         posting the vars array.
604
 * written by nf@bigpond.net.au
605
 */
606
function http_post($server, $port, $url, $vars) {
607
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
608
	$urlencoded = "";
609
	while (list($key,$value) = each($vars))
610
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
611
	$urlencoded = substr($urlencoded,0,-1);
612
	$content_length = strlen($urlencoded);
613
	$headers = "POST $url HTTP/1.1
614
Accept: */*
615
Accept-Language: en-au
616
Content-Type: application/x-www-form-urlencoded
617
User-Agent: $user_agent
618
Host: $server
619
Connection: Keep-Alive
620
Cache-Control: no-cache
621
Content-Length: $content_length
622

    
623
";
624

    
625
	$errno = "";
626
	$errstr = "";
627
	$fp = fsockopen($server, $port, $errno, $errstr);
628
	if (!$fp) {
629
		return false;
630
	}
631

    
632
	fputs($fp, $headers);
633
	fputs($fp, $urlencoded);
634

    
635
	$ret = "";
636
	while (!feof($fp))
637
		$ret.= fgets($fp, 1024);
638
	fclose($fp);
639

    
640
	return $ret;
641
}
642

    
643
/*
644
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
645
 */
646
if (!function_exists('php_check_syntax')){
647
	global $g;
648
	function php_check_syntax($code_to_check, &$errormessage){
649
		return false;
650
		$fout = fopen("{$g['tmp_path']}/codetocheck.php","w");
651
		$code = $_POST['content'];
652
		$code = str_replace("<?php", "", $code);
653
		$code = str_replace("?>", "", $code);
654
		fwrite($fout, "<?php\n\n");
655
		fwrite($fout, $code_to_check);
656
		fwrite($fout, "\n\n?>\n");
657
		fclose($fout);
658
		$command = "/usr/local/bin/php -l {$g['tmp_path']}/codetocheck.php";
659
		$output = exec_command($command);
660
		if (stristr($output, "Errors parsing") == false) {
661
			echo "false\n";
662
			$errormessage = '';
663
			return(false);
664
		} else {
665
			$errormessage = $output;
666
			return(true);
667
		}
668
	}
669
}
670

    
671
/*
672
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
673
 */
674
if (!function_exists('php_check_syntax')){
675
	function php_check_syntax($code_to_check, &$errormessage){
676
		return false;
677
		$command = "/usr/local/bin/php -l " . escapeshellarg($code_to_check);
678
		$output = exec_command($command);
679
		if (stristr($output, "Errors parsing") == false) {
680
			echo "false\n";
681
			$errormessage = '';
682
			return(false);
683
		} else {
684
			$errormessage = $output;
685
			return(true);
686
		}
687
	}
688
}
689

    
690
/*
691
 * rmdir_recursive($path,$follow_links=false)
692
 * Recursively remove a directory tree (rm -rf path)
693
 * This is for directories _only_
694
 */
695
function rmdir_recursive($path,$follow_links=false) {
696
	$to_do = glob($path);
697
	if(!is_array($to_do)) $to_do = array($to_do);
698
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
699
		if(file_exists($workingdir)) {
700
			if(is_dir($workingdir)) {
701
				$dir = opendir($workingdir);
702
				while ($entry = readdir($dir)) {
703
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
704
						unlink("$workingdir/$entry");
705
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
706
						rmdir_recursive("$workingdir/$entry");
707
				}
708
				closedir($dir);
709
				rmdir($workingdir);
710
			} elseif (is_file($workingdir)) {
711
				unlink($workingdir);
712
			}
713
		}
714
	}
715
	return;
716
}
717

    
718
/*
719
 * call_pfsense_method(): Call a method exposed by the pfsense.org XMLRPC server.
720
 */
721
function call_pfsense_method($method, $params, $timeout = 0) {
722
	global $g, $config;
723

    
724
	$xmlrpc_base_url = get_active_xml_rpc_base_url();
725
	$xmlrpc_path = $g['xmlrpcpath'];
726
	
727
	$xmlrpcfqdn = preg_replace("(https?://)", "", $xmlrpc_base_url);
728
	$ip = gethostbyname($xmlrpcfqdn);
729
	if($ip == $xmlrpcfqdn)
730
		return false;
731

    
732
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
733
	$port = 0;
734
	$proxyurl = "";
735
	$proxyport = 0;
736
	$proxyuser = "";
737
	$proxypass = "";
738
	if (!empty($config['system']['proxyurl']))
739
		$proxyurl = $config['system']['proxyurl'];
740
	if (!empty($config['system']['proxyport']) && is_numeric($config['system']['proxyport']))
741
		$proxyport = $config['system']['proxyport'];
742
	if (!empty($config['system']['proxyuser']))
743
		$proxyuser = $config['system']['proxyuser'];
744
	if (!empty($config['system']['proxypass']))
745
		$proxypass = $config['system']['proxypass'];
746
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url, $port, $proxyurl, $proxyport, $proxyuser, $proxypass);
747
	// If the ALT PKG Repo has a username/password set, use it.
748
	if($config['system']['altpkgrepo']['username'] &&
749
	   $config['system']['altpkgrepo']['password']) {
750
		$username = $config['system']['altpkgrepo']['username'];
751
		$password = $config['system']['altpkgrepo']['password'];
752
		$cli->setCredentials($username, $password);
753
	}
754
	$resp = $cli->send($msg, $timeout);
755
	if(!is_object($resp)) {
756
		log_error(sprintf(gettext("XMLRPC communication error: %s"), $cli->errstr));
757
		return false;
758
	} elseif($resp->faultCode()) {
759
		log_error(sprintf(gettext('XMLRPC request failed with error %1$s: %2$s'), $resp->faultCode(), $resp->faultString()));
760
		return false;
761
	} else {
762
		return XML_RPC_Decode($resp->value());
763
	}
764
}
765

    
766
/*
767
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
768
 */
769
function check_firmware_version($tocheck = "all", $return_php = true) {
770
	global $g, $config;
771
	
772
	$xmlrpc_base_url = get_active_xml_rpc_base_url();
773
	$xmlrpcfqdn = preg_replace("(https?://)", "", $xmlrpc_base_url);
774
	$ip = gethostbyname($xmlrpcfqdn);
775
	if($ip == $xmlrpcfqdn)
776
		return false;
777
	$version = php_uname('r');
778
	$version = explode('-', $version);
779
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
780
		"kernel"   => array("version" => $version[0]),
781
		"base"     => array("version" => $version[0]),
782
		"platform" => trim(file_get_contents('/etc/platform')),
783
		"config_version" => $config['version']
784
		);
785
	unset($version);
786

    
787
	if($tocheck == "all") {
788
		$params = $rawparams;
789
	} else {
790
		foreach($tocheck as $check) {
791
			$params['check'] = $rawparams['check'];
792
			$params['platform'] = $rawparams['platform'];
793
		}
794
	}
795
	if($config['system']['firmware']['branch'])
796
		$params['branch'] = $config['system']['firmware']['branch'];
797

    
798
	/* XXX: What is this method? */
799
	if(!($versions = call_pfsense_method('pfsense.get_firmware_version', $params))) {
800
		return false;
801
	} else {
802
		$versions["current"] = $params;
803
	}
804

    
805
	return $versions;
806
}
807

    
808
/*
809
 * host_firmware_version(): Return the versions used in this install
810
 */
811
function host_firmware_version($tocheck = "") {
812
	global $g, $config;
813

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

    
816
	return array(
817
		"firmware" => array("version" => trim(file_get_contents('/etc/version', " \n"))),
818
		"kernel"   => array("version" => $os_version),
819
		"base"     => array("version" => $os_version),
820
		"platform" => trim(file_get_contents('/etc/platform', " \n")),
821
		"config_version" => $config['version']
822
	);
823
}
824

    
825
function get_disk_info() {
826
	$diskout = "";
827
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
828
	return explode(' ', $diskout[0]);
829
}
830

    
831
/****f* pfsense-utils/strncpy
832
 * NAME
833
 *   strncpy - copy strings
834
 * INPUTS
835
 *   &$dst, $src, $length
836
 * RESULT
837
 *   none
838
 ******/
839
function strncpy(&$dst, $src, $length) {
840
	if (strlen($src) > $length) {
841
		$dst = substr($src, 0, $length);
842
	} else {
843
		$dst = $src;
844
	}
845
}
846

    
847
/****f* pfsense-utils/reload_interfaces_sync
848
 * NAME
849
 *   reload_interfaces - reload all interfaces
850
 * INPUTS
851
 *   none
852
 * RESULT
853
 *   none
854
 ******/
855
function reload_interfaces_sync() {
856
	global $config, $g;
857

    
858
	if($g['debug'])
859
		log_error(gettext("reload_interfaces_sync() is starting."));
860

    
861
	/* parse config.xml again */
862
	$config = parse_config(true);
863

    
864
	/* enable routing */
865
	system_routing_enable();
866
	if($g['debug'])
867
		log_error(gettext("Enabling system routing"));
868

    
869
	if($g['debug'])
870
		log_error(gettext("Cleaning up Interfaces"));
871

    
872
	/* set up interfaces */
873
	interfaces_configure();
874
}
875

    
876
/****f* pfsense-utils/reload_all
877
 * NAME
878
 *   reload_all - triggers a reload of all settings
879
 *   * INPUTS
880
 *   none
881
 * RESULT
882
 *   none
883
 ******/
884
function reload_all() {
885
	send_event("service reload all");
886
}
887

    
888
/****f* pfsense-utils/reload_interfaces
889
 * NAME
890
 *   reload_interfaces - triggers a reload of all interfaces
891
 * INPUTS
892
 *   none
893
 * RESULT
894
 *   none
895
 ******/
896
function reload_interfaces() {
897
	send_event("interface all reload");
898
}
899

    
900
/****f* pfsense-utils/reload_all_sync
901
 * NAME
902
 *   reload_all - reload all settings
903
 *   * INPUTS
904
 *   none
905
 * RESULT
906
 *   none
907
 ******/
908
function reload_all_sync() {
909
	global $config, $g;
910

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

    
914
	/* set up our timezone */
915
	system_timezone_configure();
916

    
917
	/* set up our hostname */
918
	system_hostname_configure();
919

    
920
	/* make hosts file */
921
	system_hosts_generate();
922

    
923
	/* generate resolv.conf */
924
	system_resolvconf_generate();
925

    
926
	/* enable routing */
927
	system_routing_enable();
928

    
929
	/* set up interfaces */
930
	interfaces_configure();
931

    
932
	/* start dyndns service */
933
	services_dyndns_configure();
934

    
935
	/* configure cron service */
936
	configure_cron();
937

    
938
	/* start the NTP client */
939
	system_ntp_configure();
940

    
941
	/* sync pw database */
942
	conf_mount_rw();
943
	unlink_if_exists("/etc/spwd.db.tmp");
944
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
945
	conf_mount_ro();
946

    
947
	/* restart sshd */
948
	send_event("service restart sshd");
949

    
950
	/* restart webConfigurator if needed */
951
	send_event("service restart webgui");
952
}
953

    
954
function setup_serial_port($when="save", $path="") {
955
	global $g, $config;
956
	conf_mount_rw();
957
	$ttys_file = "{$path}/etc/ttys";
958
	$boot_config_file = "{$path}/boot.config";
959
	$loader_conf_file = "{$path}/boot/loader.conf";
960
	/* serial console - write out /boot.config */
961
	if(file_exists($boot_config_file))
962
		$boot_config = file_get_contents($boot_config_file);
963
	else
964
		$boot_config = "";
965

    
966
	$serialspeed = (is_numeric($config['system']['serialspeed'])) ? $config['system']['serialspeed'] : "115200";
967
	if ($g['platform'] != "cdrom") {
968
		$serial_only = false;
969

    
970
		if (($g['platform'] == "nanobsd") && !file_exists("/etc/nano_use_vga.txt")) {
971
			$serial_only = true;
972
		} else {
973
			$specific_platform = system_identify_specific_platform();
974
			if ($specific_platform['name'] == 'RCC-VE' ||
975
			    $specific_platform['name'] == 'RCC-DFF') {
976
				$serial_only = true;
977
			}
978
		}
979

    
980
		$boot_config_split = explode("\n", $boot_config);
981
		$fd = fopen($boot_config_file,"w");
982
		if($fd) {
983
			foreach($boot_config_split as $bcs) {
984
				if(stristr($bcs, "-D") || stristr($bcs, "-h")) {
985
					/* DONT WRITE OUT, WE'LL DO IT LATER */
986
				} else {
987
					if($bcs <> "")
988
						fwrite($fd, "{$bcs}\n");
989
				}
990
			}
991
			if ($serial_only === true)
992
				fwrite($fd, "-S{$serialspeed} -h");
993
			else if (is_serial_enabled())
994
				fwrite($fd, "-S{$serialspeed} -D");
995
			fclose($fd);
996
		}
997

    
998
		/* serial console - write out /boot/loader.conf */
999
		if ($when == "upgrade")
1000
			system("echo \"Reading {$loader_conf_file}...\" >> /conf/upgrade_log.txt");
1001
		$boot_config = file_get_contents($loader_conf_file);
1002
		$boot_config_split = explode("\n", $boot_config);
1003
		if(count($boot_config_split) > 0) {
1004
			$new_boot_config = array();
1005
			// Loop through and only add lines that are not empty, and which
1006
			//  do not contain a console directive.
1007
			foreach($boot_config_split as $bcs)
1008
				if(!empty($bcs)
1009
					&& (stripos($bcs, "console") === false)
1010
					&& (stripos($bcs, "boot_multicons") === false)
1011
					&& (stripos($bcs, "boot_serial") === false)
1012
					&& (stripos($bcs, "hw.usb.no_pf") === false)
1013
					&& (stripos($bcs, "hint.uart.0.flags") === false)
1014
					&& (stripos($bcs, "hint.uart.1.flags") === false))
1015
					$new_boot_config[] = $bcs;
1016

    
1017
			if ($serial_only === true) {
1018
				$new_boot_config[] = 'boot_serial="YES"';
1019
				$new_boot_config[] = 'console="comconsole"';
1020
			} else if (is_serial_enabled()) {
1021
				$new_boot_config[] = 'boot_multicons="YES"';
1022
				$new_boot_config[] = 'boot_serial="YES"';
1023
				$primaryconsole = isset($g['primaryconsole_force']) ? $g['primaryconsole_force'] : $config['system']['primaryconsole'];
1024
				switch ($primaryconsole) {
1025
					case "video":
1026
						$new_boot_config[] = 'console="vidconsole,comconsole"';
1027
						break;
1028
					case "serial":
1029
					default:
1030
						$new_boot_config[] = 'console="comconsole,vidconsole"';
1031
				}
1032
			}
1033
			$new_boot_config[] = 'comconsole_speed="' . $serialspeed . '"';
1034
			
1035
			$specplatform = system_identify_specific_platform();
1036
			if ($specplatform['name'] == 'RCC-VE' ||
1037
			    $specplatform['name'] == 'RCC-DFF') {
1038
				$new_boot_config[] = 'comconsole_port="0x2F8"';
1039
				$new_boot_config[] = 'hint.uart.0.flags="0x00"';
1040
				$new_boot_config[] = 'hint.uart.1.flags="0x10"';
1041
			}
1042
			$new_boot_config[] = 'hw.usb.no_pf="1"';
1043

    
1044
			file_put_contents($loader_conf_file, implode("\n", $new_boot_config) . "\n");
1045
		}
1046
	}
1047
	$ttys = file_get_contents($ttys_file);
1048
	$ttys_split = explode("\n", $ttys);
1049
	$fd = fopen($ttys_file, "w");
1050

    
1051
	$on_off = (is_serial_enabled() ? 'onifconsole' : 'off');
1052

    
1053
	if (isset($config['system']['disableconsolemenu'])) {
1054
		$console_type = 'Pc';
1055
		$serial_type = 'std.' . $serialspeed;
1056
	} else {
1057
		$console_type = 'al.Pc';
1058
		$serial_type = 'al.' . $serialspeed;
1059
	}
1060
	foreach($ttys_split as $tty) {
1061
		if (stristr($tty, "ttyv0"))
1062
			fwrite($fd, "ttyv0	\"/usr/libexec/getty {$console_type}\"	cons25	on	secure\n");
1063
		else if (stristr($tty, "ttyu")) {
1064
			$ttyn = substr($tty, 0, 5);
1065
			fwrite($fd, "{$ttyn}	\"/usr/libexec/getty {$serial_type}\"	cons25	{$on_off}	secure\n");
1066
		} else
1067
			fwrite($fd, $tty . "\n");
1068
	}
1069
	unset($on_off, $console_type, $serial_type);
1070
	fclose($fd);
1071
	if ($when != "upgrade")
1072
		reload_ttys();
1073

    
1074
	conf_mount_ro();
1075
	return;
1076
}
1077

    
1078
function is_serial_enabled() {
1079
	global $g, $config;
1080

    
1081
	if (!isset($g['enableserial_force']) &&
1082
	    !isset($config['system']['enableserial']) &&
1083
	    ($g['platform'] == "pfSense" || $g['platform'] == "cdrom" || file_exists("/etc/nano_use_vga.txt")))
1084
		return false;
1085

    
1086
	return true;
1087
}
1088

    
1089
function reload_ttys() {
1090
	// Send a HUP signal to init will make it reload /etc/ttys
1091
	posix_kill(1, SIGHUP);
1092
}
1093

    
1094
function print_value_list($list, $count = 10, $separator = ",") {
1095
	$list = implode($separator, array_slice($list, 0, $count));
1096
	if(count($list) < $count) {
1097
		$list .= ".";
1098
	} else {
1099
		$list .= "...";
1100
	}
1101
	return $list;
1102
}
1103

    
1104
/* DHCP enabled on any interfaces? */
1105
function is_dhcp_server_enabled() {
1106
	global $config;
1107

    
1108
	if (!is_array($config['dhcpd']))
1109
		return false;
1110

    
1111
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1112
		if (isset($dhcpifconf['enable']) && !empty($config['interfaces'][$dhcpif]))
1113
			return true;
1114
	}
1115

    
1116
	return false;
1117
}
1118

    
1119
/* DHCP enabled on any interfaces? */
1120
function is_dhcpv6_server_enabled() {
1121
	global $config;
1122

    
1123
	if (is_array($config['interfaces'])) {
1124
		foreach ($config['interfaces'] as $ifcfg) {
1125
			if (isset($ifcfg['enable']) && !empty($ifcfg['track6-interface']))
1126
				return true;
1127
		}
1128
	}
1129

    
1130
	if (!is_array($config['dhcpdv6']))
1131
		return false;
1132

    
1133
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
1134
		if (isset($dhcpv6ifconf['enable']) && !empty($config['interfaces'][$dhcpv6if]))
1135
			return true;
1136
	}
1137

    
1138
	return false;
1139
}
1140

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

    
1145
	if (!is_array($config['dhcpdv6']))
1146
		$config['dhcpdv6'] = array();
1147

    
1148
	$dhcpdv6cfg = $config['dhcpdv6'];
1149
	$Iflist = get_configured_interface_list();
1150

    
1151
	/* handle manually configured DHCP6 server settings first */
1152
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1153
		if(!isset($config['interfaces'][$dhcpv6if]['enable']))
1154
			continue;
1155

    
1156
		if(!isset($dhcpv6ifconf['ramode']))
1157
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
1158

    
1159
		if($dhcpv6ifconf['ramode'] == "disabled")
1160
			continue;
1161

    
1162
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1163
		if(!is_ipaddrv6($ifcfgipv6))
1164
			continue;
1165

    
1166
		return true;
1167
	}
1168

    
1169
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
1170
	foreach ($Iflist as $if => $ifdescr) {
1171
		if(!isset($config['interfaces'][$if]['track6-interface']))
1172
			continue;
1173
		if(!isset($config['interfaces'][$if]['enable']))
1174
			continue;
1175

    
1176
		$ifcfgipv6 = get_interface_ipv6($if);
1177
		if(!is_ipaddrv6($ifcfgipv6))
1178
			continue;
1179

    
1180
		$ifcfgsnv6 = get_interface_subnetv6($if);
1181
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1182

    
1183
		if(!is_ipaddrv6($subnetv6))
1184
			continue;
1185

    
1186
		return true;
1187
	}
1188

    
1189
	return false;
1190
}
1191

    
1192
/* Any PPPoE servers enabled? */
1193
function is_pppoe_server_enabled() {
1194
	global $config;
1195

    
1196
	$pppoeenable = false;
1197

    
1198
	if (!is_array($config['pppoes']) || !is_array($config['pppoes']['pppoe']))
1199
		return false;
1200

    
1201
	foreach ($config['pppoes']['pppoe'] as $pppoes)
1202
		if ($pppoes['mode'] == 'server')
1203
			$pppoeenable = true;
1204

    
1205
	return $pppoeenable;
1206
}
1207

    
1208
function convert_seconds_to_hms($sec){
1209
	$min=$hrs=0;
1210
	if ($sec != 0){
1211
		$min = floor($sec/60);
1212
		$sec %= 60;
1213
	}
1214
	if ($min != 0){
1215
		$hrs = floor($min/60);
1216
		$min %= 60;
1217
	}
1218
	if ($sec < 10)
1219
		$sec = "0".$sec;
1220
	if ($min < 10)
1221
		$min = "0".$min;
1222
	if ($hrs < 10)
1223
		$hrs = "0".$hrs;
1224
	$result = $hrs.":".$min.":".$sec;
1225
	return $result;
1226
}
1227

    
1228
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1229

    
1230
function get_ppp_uptime($port){
1231
	if (file_exists("/conf/{$port}.log")){
1232
		$saved_time = file_get_contents("/conf/{$port}.log");
1233
		$uptime_data = explode("\n",$saved_time);
1234
		$sec=0;
1235
		foreach($uptime_data as $upt) {
1236
			$sec += substr($upt, 1 + strpos($upt, " "));
1237
		}
1238
		return convert_seconds_to_hms($sec);
1239
	} else {
1240
		$total_time = gettext("No history data found!");
1241
		return $total_time;
1242
	}
1243
}
1244

    
1245
//returns interface information
1246
function get_interface_info($ifdescr) {
1247
	global $config, $g;
1248

    
1249
	$ifinfo = array();
1250
	if (empty($config['interfaces'][$ifdescr]))
1251
		return;
1252
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
1253
	$ifinfo['if'] = get_real_interface($ifdescr);
1254

    
1255
	$chkif = $ifinfo['if'];
1256
	$ifinfotmp = pfSense_get_interface_addresses($chkif);
1257
	$ifinfo['status'] = $ifinfotmp['status'];
1258
	if (empty($ifinfo['status']))
1259
		$ifinfo['status'] = "down";
1260
	$ifinfo['macaddr'] = $ifinfotmp['macaddr'];
1261
	$ifinfo['mtu'] = $ifinfotmp['mtu'];
1262
	$ifinfo['ipaddr'] = $ifinfotmp['ipaddr'];
1263
	$ifinfo['subnet'] = $ifinfotmp['subnet'];
1264
	$ifinfo['linklocal'] = get_interface_linklocal($ifdescr);
1265
	$ifinfo['ipaddrv6'] = get_interface_ipv6($ifdescr);
1266
	$ifinfo['subnetv6'] = get_interface_subnetv6($ifdescr);
1267
	if (isset($ifinfotmp['link0']))
1268
		$link0 = "down";
1269
	$ifinfotmp = pfSense_get_interface_stats($chkif);
1270
	// $ifinfo['inpkts'] = $ifinfotmp['inpkts'];
1271
	// $ifinfo['outpkts'] = $ifinfotmp['outpkts'];
1272
	$ifinfo['inerrs'] = $ifinfotmp['inerrs'];
1273
	$ifinfo['outerrs'] = $ifinfotmp['outerrs'];
1274
	$ifinfo['collisions'] = $ifinfotmp['collisions'];
1275

    
1276
	/* Use pfctl for non wrapping 64 bit counters */
1277
	/* Pass */
1278
	exec("/sbin/pfctl -vvsI -i {$chkif}", $pfctlstats);
1279
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1280
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1281
	$pf_in6_pass = preg_split("/ +/ ", $pfctlstats[7]);
1282
	$pf_out6_pass = preg_split("/ +/", $pfctlstats[9]);
1283
	$in4_pass = $pf_in4_pass[5];
1284
	$out4_pass = $pf_out4_pass[5];
1285
	$in4_pass_packets = $pf_in4_pass[3];
1286
	$out4_pass_packets = $pf_out4_pass[3];
1287
	$in6_pass = $pf_in6_pass[5];
1288
	$out6_pass = $pf_out6_pass[5];
1289
	$in6_pass_packets = $pf_in6_pass[3];
1290
	$out6_pass_packets = $pf_out6_pass[3];
1291
	$ifinfo['inbytespass'] = $in4_pass + $in6_pass;
1292
	$ifinfo['outbytespass'] = $out4_pass + $out6_pass;
1293
	$ifinfo['inpktspass'] = $in4_pass_packets + $in6_pass_packets;
1294
	$ifinfo['outpktspass'] = $out4_pass_packets + $out6_pass_packets;
1295

    
1296
	/* Block */
1297
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1298
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1299
	$pf_in6_block = preg_split("/ +/", $pfctlstats[8]);
1300
	$pf_out6_block = preg_split("/ +/", $pfctlstats[10]);
1301
	$in4_block = $pf_in4_block[5];
1302
	$out4_block = $pf_out4_block[5];
1303
	$in4_block_packets = $pf_in4_block[3];
1304
	$out4_block_packets = $pf_out4_block[3];
1305
	$in6_block = $pf_in6_block[5];
1306
	$out6_block = $pf_out6_block[5];
1307
	$in6_block_packets = $pf_in6_block[3];
1308
	$out6_block_packets = $pf_out6_block[3];
1309
	$ifinfo['inbytesblock'] = $in4_block + $in6_block;
1310
	$ifinfo['outbytesblock'] = $out4_block + $out6_block;
1311
	$ifinfo['inpktsblock'] = $in4_block_packets + $in6_block_packets;
1312
	$ifinfo['outpktsblock'] = $out4_block_packets + $out6_block_packets;
1313

    
1314
	$ifinfo['inbytes'] = $in4_pass + $in6_pass;
1315
	$ifinfo['outbytes'] = $out4_pass + $out6_pass;
1316
	$ifinfo['inpkts'] = $in4_pass_packets + $in6_pass_packets;
1317
	$ifinfo['outpkts'] = $out4_pass_packets + $out6_pass_packets;
1318

    
1319
	$ifconfiginfo = "";
1320
	$link_type = $config['interfaces'][$ifdescr]['ipaddr'];
1321
	switch ($link_type) {
1322
	/* DHCP? -> see if dhclient is up */
1323
	case "dhcp":
1324
		/* see if dhclient is up */
1325
		if (find_dhclient_process($ifinfo['if']) != 0)
1326
			$ifinfo['dhcplink'] = "up";
1327
		else
1328
			$ifinfo['dhcplink'] = "down";
1329

    
1330
		break;
1331
	/* PPPoE/PPTP/L2TP interface? -> get status from virtual interface */
1332
	case "pppoe":
1333
	case "pptp":
1334
	case "l2tp":
1335
		if ($ifinfo['status'] == "up" && !isset($link0))
1336
			/* get PPPoE link status for dial on demand */
1337
			$ifinfo["{$link_type}link"] = "up";
1338
		else
1339
			$ifinfo["{$link_type}link"] = "down";
1340

    
1341
		break;
1342
	/* PPP interface? -> get uptime for this session and cumulative uptime from the persistant log file in conf */
1343
	case "ppp":
1344
		if ($ifinfo['status'] == "up")
1345
			$ifinfo['ppplink'] = "up";
1346
		else
1347
			$ifinfo['ppplink'] = "down" ;
1348

    
1349
		if (empty($ifinfo['status']))
1350
			$ifinfo['status'] = "down";
1351

    
1352
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1353
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1354
				if ($config['interfaces'][$ifdescr]['if'] == $ppp['if'])
1355
					break;
1356
			}
1357
		}
1358
		$dev = $ppp['ports'];
1359
		if ($config['interfaces'][$ifdescr]['if'] != $ppp['if'] || empty($dev))
1360
			break;
1361
		if (!file_exists($dev)) {
1362
			$ifinfo['nodevice'] = 1;
1363
			$ifinfo['pppinfo'] = $dev . " " . gettext("device not present! Is the modem attached to the system?");
1364
		}
1365

    
1366
		$usbmodemoutput = array();
1367
		exec("usbconfig", $usbmodemoutput);
1368
		$mondev = "{$g['tmp_path']}/3gstats.{$ifdescr}";
1369
		if(file_exists($mondev)) {
1370
			$cellstats = file($mondev);
1371
			/* skip header */
1372
			$a_cellstats = explode(",", $cellstats[1]);
1373
			if(preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1374
				$ifinfo['cell_rssi'] = huawei_rssi_to_string($a_cellstats[1]);
1375
				$ifinfo['cell_mode'] = huawei_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1376
				$ifinfo['cell_simstate'] = huawei_simstate_to_string($a_cellstats[10]);
1377
				$ifinfo['cell_service'] = huawei_service_to_string(trim($a_cellstats[11]));
1378
			}
1379
			if(preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1380
				$ifinfo['cell_rssi'] = zte_rssi_to_string($a_cellstats[1]);
1381
				$ifinfo['cell_mode'] = zte_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1382
				$ifinfo['cell_simstate'] = zte_simstate_to_string($a_cellstats[10]);
1383
				$ifinfo['cell_service'] = zte_service_to_string(trim($a_cellstats[11]));
1384
			}
1385
			$ifinfo['cell_upstream'] = $a_cellstats[4];
1386
			$ifinfo['cell_downstream'] = trim($a_cellstats[5]);
1387
			$ifinfo['cell_sent'] = $a_cellstats[6];
1388
			$ifinfo['cell_received'] = trim($a_cellstats[7]);
1389
			$ifinfo['cell_bwupstream'] = $a_cellstats[8];
1390
			$ifinfo['cell_bwdownstream'] = trim($a_cellstats[9]);
1391
		}
1392
		// Calculate cumulative uptime for PPP link. Useful for connections that have per minute/hour contracts so you don't go over!
1393
		if (isset($ppp['uptime']))
1394
			$ifinfo['ppp_uptime_accumulated'] = "(".get_ppp_uptime($ifinfo['if']).")";
1395
		break;
1396
	default:
1397
		break;
1398
	}
1399

    
1400
	if (file_exists("{$g['varrun_path']}/{$link_type}_{$ifdescr}.pid")) {
1401
		$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1402
		$ifinfo['ppp_uptime'] = convert_seconds_to_hms($sec);
1403
	}
1404

    
1405
	if ($ifinfo['status'] == "up") {
1406
		/* try to determine media with ifconfig */
1407
		unset($ifconfiginfo);
1408
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1409
		$wifconfiginfo = array();
1410
		if(is_interface_wireless($ifdescr)) {
1411
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1412
			array_shift($wifconfiginfo);
1413
		}
1414
		$matches = "";
1415
		foreach ($ifconfiginfo as $ici) {
1416

    
1417
			/* don't list media/speed for wireless cards, as it always
1418
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1419
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1420
				$ifinfo['media'] = $matches[1];
1421
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1422
				$ifinfo['media'] = $matches[1];
1423
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1424
				$ifinfo['media'] = $matches[1];
1425
			}
1426

    
1427
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
1428
				if ($matches[1] != "active")
1429
					$ifinfo['status'] = $matches[1];
1430
				if($ifinfo['status'] == gettext("running"))
1431
					$ifinfo['status'] = gettext("up");
1432
			}
1433
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
1434
				$ifinfo['channel'] = $matches[1];
1435
			}
1436
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
1437
				if ($matches[1][0] == '"')
1438
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
1439
				else
1440
					$ifinfo['ssid'] = $matches[1];
1441
			}
1442
			if (preg_match("/laggproto (.*)$/", $ici, $matches)) {
1443
				$ifinfo['laggproto'] = $matches[1];
1444
			}
1445
			if (preg_match("/laggport: (.*)$/", $ici, $matches)) {
1446
				$ifinfo['laggport'][] = $matches[1];
1447
			}
1448
		}
1449
		foreach($wifconfiginfo as $ici) {
1450
			$elements = preg_split("/[ ]+/i", $ici);
1451
			if ($elements[0] != "") {
1452
				$ifinfo['bssid'] = $elements[0];
1453
			}
1454
			if ($elements[3] != "") {
1455
				$ifinfo['rate'] = $elements[3];
1456
			}
1457
			if ($elements[4] != "") {
1458
				$ifinfo['rssi'] = $elements[4];
1459
			}
1460

    
1461
		}
1462
		/* lookup the gateway */
1463
		if (interface_has_gateway($ifdescr)) {
1464
			$ifinfo['gateway'] = get_interface_gateway($ifdescr);
1465
			$ifinfo['gatewayv6'] = get_interface_gateway_v6($ifdescr);
1466
		}
1467
	}
1468

    
1469
	$bridge = "";
1470
	$bridge = link_interface_to_bridge($ifdescr);
1471
	if($bridge) {
1472
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1473
		if(stristr($bridge_text, "blocking") <> false) {
1474
			$ifinfo['bridge'] = "<b><font color='red'>" . gettext("blocking") . "</font></b> - " . gettext("check for ethernet loops");
1475
			$ifinfo['bridgeint'] = $bridge;
1476
		} else if(stristr($bridge_text, "learning") <> false) {
1477
			$ifinfo['bridge'] = gettext("learning");
1478
			$ifinfo['bridgeint'] = $bridge;
1479
		} else if(stristr($bridge_text, "forwarding") <> false) {
1480
			$ifinfo['bridge'] = gettext("forwarding");
1481
			$ifinfo['bridgeint'] = $bridge;
1482
		}
1483
	}
1484

    
1485
	return $ifinfo;
1486
}
1487

    
1488
//returns cpu speed of processor. Good for determining capabilities of machine
1489
function get_cpu_speed() {
1490
	return get_single_sysctl("hw.clockrate");
1491
}
1492

    
1493
function get_uptime_sec() {
1494
	$boottime = "";
1495
	$matches = "";
1496
	$boottime = get_single_sysctl("kern.boottime");
1497
	preg_match("/sec = (\d+)/", $boottime, $matches);
1498
	$boottime = $matches[1];
1499
	if(intval($boottime) == 0)
1500
		return 0;
1501

    
1502
	$uptime = time() - $boottime;
1503
	return $uptime;
1504
}
1505

    
1506
function add_hostname_to_watch($hostname) {
1507
	if(!is_dir("/var/db/dnscache")) {
1508
		mkdir("/var/db/dnscache");
1509
	}
1510
	$result = array();
1511
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1512
		$domrecords = array();
1513
		$domips = array();
1514
		exec("host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1515
		if($rethost == 0) {
1516
			foreach($domrecords as $domr) {
1517
				$doml = explode(" ", $domr);
1518
				$domip = $doml[3];
1519
				/* fill array with domain ip addresses */
1520
				if(is_ipaddr($domip)) {
1521
					$domips[] = $domip;
1522
				}
1523
			}
1524
		}
1525
		sort($domips);
1526
		$contents = "";
1527
		if(! empty($domips)) {
1528
			foreach($domips as $ip) {
1529
				$contents .= "$ip\n";
1530
			}
1531
		}
1532
		file_put_contents("/var/db/dnscache/$hostname", $contents);
1533
		/* Remove empty elements */
1534
		$result = array_filter(explode("\n", $contents), 'strlen');
1535
	}
1536
	return $result;
1537
}
1538

    
1539
function is_fqdn($fqdn) {
1540
	$hostname = false;
1541
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1542
		$hostname = true;
1543
	}
1544
	if(preg_match("/\.\./", $fqdn)) {
1545
		$hostname = false;
1546
	}
1547
	if(preg_match("/^\./i", $fqdn)) {
1548
		$hostname = false;
1549
	}
1550
	if(preg_match("/\//i", $fqdn)) {
1551
		$hostname = false;
1552
	}
1553
	return($hostname);
1554
}
1555

    
1556
function pfsense_default_state_size() {
1557
	/* get system memory amount */
1558
	$memory = get_memory();
1559
	$physmem = $memory[0];
1560
	/* Be cautious and only allocate 10% of system memory to the state table */
1561
	$max_states = (int) ($physmem/10)*1000;
1562
	return $max_states;
1563
}
1564

    
1565
function pfsense_default_tables_size() {
1566
	$current = `pfctl -sm | grep ^tables | awk '{print $4};'`;
1567
	return $current;
1568
}
1569

    
1570
function pfsense_default_table_entries_size() {
1571
	$current = `pfctl -sm | grep table-entries | awk '{print $4};'`;
1572
	return $current;
1573
}
1574

    
1575
/* Compare the current hostname DNS to the DNS cache we made
1576
 * if it has changed we return the old records
1577
 * if no change we return false */
1578
function compare_hostname_to_dnscache($hostname) {
1579
	if(!is_dir("/var/db/dnscache")) {
1580
		mkdir("/var/db/dnscache");
1581
	}
1582
	$hostname = trim($hostname);
1583
	if(is_readable("/var/db/dnscache/{$hostname}")) {
1584
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
1585
	} else {
1586
		$oldcontents = "";
1587
	}
1588
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1589
		$domrecords = array();
1590
		$domips = array();
1591
		exec("host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1592
		if($rethost == 0) {
1593
			foreach($domrecords as $domr) {
1594
				$doml = explode(" ", $domr);
1595
				$domip = $doml[3];
1596
				/* fill array with domain ip addresses */
1597
				if(is_ipaddr($domip)) {
1598
					$domips[] = $domip;
1599
				}
1600
			}
1601
		}
1602
		sort($domips);
1603
		$contents = "";
1604
		if(! empty($domips)) {
1605
			foreach($domips as $ip) {
1606
				$contents .= "$ip\n";
1607
			}
1608
		}
1609
	}
1610

    
1611
	if(trim($oldcontents) != trim($contents)) {
1612
		if($g['debug']) {
1613
			log_error(sprintf(gettext('DNSCACHE: Found old IP %1$s and new IP %2$s'), $oldcontents, $contents));
1614
		}
1615
		return ($oldcontents);
1616
	} else {
1617
		return false;
1618
	}
1619
}
1620

    
1621
/*
1622
 * load_crypto() - Load crypto modules if enabled in config.
1623
 */
1624
function load_crypto() {
1625
	global $config, $g;
1626
	$crypto_modules = array('glxsb', 'aesni');
1627

    
1628
	if (!in_array($config['system']['crypto_hardware'], $crypto_modules))
1629
		return false;
1630

    
1631
	if (!empty($config['system']['crypto_hardware']) && !is_module_loaded($config['system']['crypto_hardware'])) {
1632
		log_error("Loading {$config['system']['crypto_hardware']} cryptographic accelerator module.");
1633
		mwexec("/sbin/kldload {$config['system']['crypto_hardware']}");
1634
	}
1635
}
1636

    
1637
/*
1638
 * load_thermal_hardware() - Load temperature monitor kernel module
1639
 */
1640
function load_thermal_hardware() {
1641
	global $config, $g;
1642
	$thermal_hardware_modules = array('coretemp', 'amdtemp');
1643

    
1644
	if (!in_array($config['system']['thermal_hardware'], $thermal_hardware_modules))
1645
		return false;
1646

    
1647
	if (!empty($config['system']['thermal_hardware']) && !is_module_loaded($config['system']['thermal_hardware'])) {
1648
		log_error("Loading {$config['system']['thermal_hardware']} thermal monitor module.");
1649
		mwexec("/sbin/kldload {$config['system']['thermal_hardware']}");
1650
	}
1651
}
1652

    
1653
/****f* pfsense-utils/isvm
1654
 * NAME
1655
 *   isvm
1656
 * INPUTS
1657
 *	none
1658
 * RESULT
1659
 *   returns true if machine is running under a virtual environment
1660
 ******/
1661
function isvm() {
1662
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86", "VirtualBox");
1663
	$_gb = exec('/bin/kenv smbios.system.product 2>/dev/null', $output, $rc);
1664

    
1665
	if ($rc != 0 || !isset($output[0]))
1666
		return false;
1667

    
1668
	foreach ($virtualenvs as $virtualenv)
1669
		if (stripos($output[0], $virtualenv) !== false)
1670
			return true;
1671

    
1672
	return false;
1673
}
1674

    
1675
function get_freebsd_version() {
1676
	$version = explode(".", php_uname("r"));
1677
	return $version[0];
1678
}
1679

    
1680
function download_file($url, $destination, $verify_ssl = false, $connect_timeout = 5, $timeout = 0) {
1681
	global $config, $g;
1682

    
1683
	$fp = fopen($destination, "wb");
1684

    
1685
	if (!$fp)
1686
		return false;
1687

    
1688
	$ch = curl_init();
1689
	curl_setopt($ch, CURLOPT_URL, $url);
1690
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1691
	curl_setopt($ch, CURLOPT_FILE, $fp);
1692
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1693
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1694
	curl_setopt($ch, CURLOPT_HEADER, false);
1695
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1696
	if (!isset($config['system']['host_uuid']))
1697
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version") . ' : ' . get_single_sysctl('kern.hostuuid')));
1698
	else
1699
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version")));
1700

    
1701
	if (!empty($config['system']['proxyurl'])) {
1702
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1703
		if (!empty($config['system']['proxyport']))
1704
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1705
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1706
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1707
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1708
		}
1709
	}
1710

    
1711
	@curl_exec($ch);
1712
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1713
	fclose($fp);
1714
	curl_close($ch);
1715
	return ($http_code == 200) ? true : $http_code;
1716
}
1717

    
1718
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body', $connect_timeout = 5, $timeout=0) {
1719
	global $config, $g;
1720
	global $ch, $fout, $file_size, $downloaded, $config, $first_progress_update;
1721
	$file_size  = 1;
1722
	$downloaded = 1;
1723
	$first_progress_update = TRUE;
1724
	/* open destination file */
1725
	$fout = fopen($destination_file, "wb");
1726

    
1727
	/*
1728
	 *      Originally by Author: Keyvan Minoukadeh
1729
	 *      Modified by Scott Ullrich to return Content-Length size
1730
	 */
1731

    
1732
	$ch = curl_init();
1733
	curl_setopt($ch, CURLOPT_URL, $url_file);
1734
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1735
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1736
	/* Don't verify SSL peers since we don't have the certificates to do so. */
1737
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
1738
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1739
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1740
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1741
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1742
	if (!isset($config['system']['host_uuid']))
1743
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version") . ' : ' . get_single_sysctl('kern.hostuuid')));
1744
	else
1745
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version")));
1746

    
1747
	if (!empty($config['system']['proxyurl'])) {
1748
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1749
		if (!empty($config['system']['proxyport']))
1750
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1751
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1752
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1753
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1754
		}
1755
	}
1756

    
1757
	@curl_exec($ch);
1758
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1759
	if($fout)
1760
		fclose($fout);
1761
	curl_close($ch);
1762
	return ($http_code == 200) ? true : $http_code;
1763
}
1764

    
1765
function read_header($ch, $string) {
1766
	global $file_size, $fout;
1767
	$length = strlen($string);
1768
	$regs = "";
1769
	preg_match("/(Content-Length:) (.*)/", $string, $regs);
1770
	if($regs[2] <> "") {
1771
		$file_size = intval($regs[2]);
1772
	}
1773
	ob_flush();
1774
	return $length;
1775
}
1776

    
1777
function read_body($ch, $string) {
1778
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen, $first_progress_update;
1779
	global $pkg_interface;
1780
	$length = strlen($string);
1781
	$downloaded += intval($length);
1782
	if($file_size > 0) {
1783
		$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1784
		$downloadProgress = 100 - $downloadProgress;
1785
	} else
1786
		$downloadProgress = 0;
1787
	if($lastseen <> $downloadProgress and $downloadProgress < 101) {
1788
		if($sendto == "status") {
1789
			if($pkg_interface == "console") {
1790
				if(($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1791
					$tostatus = $static_status . $downloadProgress . "%";
1792
					if ($downloadProgress == 100) {
1793
						$tostatus = $tostatus . "\r";
1794
					}
1795
					update_status($tostatus);
1796
				}
1797
			} else {
1798
				$tostatus = $static_status . $downloadProgress . "%";
1799
				update_status($tostatus);
1800
			}
1801
		} else {
1802
			if($pkg_interface == "console") {
1803
				if(($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1804
					$tooutput = $static_output . $downloadProgress . "%";
1805
					if ($downloadProgress == 100) {
1806
						$tooutput = $tooutput . "\r";
1807
					}
1808
					update_output_window($tooutput);
1809
				}
1810
			} else {
1811
				$tooutput = $static_output . $downloadProgress . "%";
1812
				update_output_window($tooutput);
1813
			}
1814
		}
1815
				if(($pkg_interface != "console") || (($downloadProgress % 10) == 0) || ($downloadProgress < 10)) {
1816
					update_progress_bar($downloadProgress, $first_progress_update);
1817
					$first_progress_update = FALSE;
1818
				}
1819
		$lastseen = $downloadProgress;
1820
	}
1821
	if($fout)
1822
		fwrite($fout, $string);
1823
	ob_flush();
1824
	return $length;
1825
}
1826

    
1827
/*
1828
 *   update_output_window: update bottom textarea dynamically.
1829
 */
1830
function update_output_window($text) {
1831
	global $pkg_interface;
1832
	$log = preg_replace("/\n/", "\\n", $text);
1833
	if($pkg_interface != "console") {
1834
		echo "\n<script type=\"text/javascript\">";
1835
		echo "\n//<![CDATA[";
1836
		echo "\nthis.document.forms[0].output.value = \"" . $log . "\";";
1837
		echo "\nthis.document.forms[0].output.scrollTop = this.document.forms[0].output.scrollHeight;";
1838
		echo "\n//]]>";
1839
		echo "\n</script>";
1840
	}
1841
	/* ensure that contents are written out */
1842
	ob_flush();
1843
}
1844

    
1845
/*
1846
 *   update_status: update top textarea dynamically.
1847
 */
1848
function update_status($status) {
1849
	global $pkg_interface;
1850
	if($pkg_interface == "console") {
1851
		echo "\r{$status}";
1852
	} else {
1853
		echo "\n<script type=\"text/javascript\">";
1854
		echo "\n//<![CDATA[";
1855
		echo "\nthis.document.forms[0].status.value=\"" . $status . "\";";
1856
		echo "\n//]]>";
1857
		echo "\n</script>";
1858
	}
1859
	/* ensure that contents are written out */
1860
	ob_flush();
1861
}
1862

    
1863
/*
1864
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
1865
 */
1866
function update_progress_bar($percent, $first_time) {
1867
	global $pkg_interface;
1868
	if($percent > 100) $percent = 1;
1869
	if($pkg_interface <> "console") {
1870
		echo "\n<script type=\"text/javascript\">";
1871
		echo "\n//<![CDATA[";
1872
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1873
		echo "\n//]]>";
1874
		echo "\n</script>";
1875
	} else {
1876
		if(!($first_time))
1877
			echo "\x08\x08\x08\x08\x08";
1878
		echo sprintf("%4d%%", $percent);
1879
	}
1880
}
1881

    
1882
/* 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. */
1883
if(!function_exists("split")) {
1884
	function split($separator, $haystack, $limit = null) {
1885
		log_error("deprecated split() call with separator '{$separator}'");
1886
		return preg_split($separator, $haystack, $limit);
1887
	}
1888
}
1889

    
1890
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
1891
	global $g, $config, $pconfig, $debug;
1892
	if(!$origname)
1893
		return;
1894

    
1895
	$sectionref = &$config;
1896
	foreach($section as $sectionname) {
1897
		if(is_array($sectionref) && isset($sectionref[$sectionname]))
1898
			$sectionref = &$sectionref[$sectionname];
1899
		else
1900
			return;
1901
	}
1902

    
1903
	if($debug) $fd = fopen("{$g['tmp_path']}/print_r", "a");
1904
	if($debug) fwrite($fd, print_r($pconfig, true));
1905

    
1906
	if(is_array($sectionref)) {
1907
		foreach($sectionref as $itemkey => $item) {
1908
			if($debug) fwrite($fd, "$itemkey\n");
1909

    
1910
			$fieldfound = true;
1911
			$fieldref = &$sectionref[$itemkey];
1912
			foreach($field as $fieldname) {
1913
				if(is_array($fieldref) && isset($fieldref[$fieldname]))
1914
					$fieldref = &$fieldref[$fieldname];
1915
				else {
1916
					$fieldfound = false;
1917
					break;
1918
				}
1919
			}
1920
			if($fieldfound && $fieldref == $origname) {
1921
				if($debug) fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1922
				$fieldref = $new_alias_name;
1923
			}
1924
		}
1925
	}
1926

    
1927
	if($debug) fclose($fd);
1928

    
1929
}
1930

    
1931
function parse_aliases_file($filename, $type = "url", $max_items = -1) {
1932
	/*
1933
	 * $filename = file to process for example blocklist like DROP:  http://www.spamhaus.org/drop/drop.txt
1934
	 * $type = if set to 'url' then subnets and ips will be returned,
1935
	 *         if set to 'url_ports' port-ranges and ports will be returned
1936
	 * $max_items = sets the maximum amount of valid items to load, -1 the default defines there is no limit.
1937
	 *
1938
	 * RETURNS an array of ip subnets and ip's or ports and port-ranges, returns NULL upon a error conditions (file not found)
1939
	 */
1940

    
1941
	$fd = @fopen($filename, 'r');
1942
	if (!$fd) {
1943
		log_error(gettext("Could not process aliases from alias: {$alias_url}"));
1944
		return null;
1945
	}
1946
	$items = array();
1947
	/* NOTE: fgetss() is not a typo RTFM before being smart */
1948
	while (($fc = fgetss($fd)) !== FALSE) {
1949
		$tmp = trim($fc, " \t\n\r");
1950
		if (empty($tmp))
1951
			continue;
1952
		$tmp_str = strstr($tmp, '#', true);
1953
		if (!empty($tmp_str))
1954
			$tmp = $tmp_str;
1955
		$tmp_str = strstr($tmp, ' ', true);
1956
		if (!empty($tmp_str))
1957
			$tmp = $tmp_str;
1958
		$valid = ($type == "url" && (is_ipaddr($tmp) || is_subnet($tmp))) ||
1959
		         ($type == "url_ports" && (is_port($tmp) || is_portrange($tmp)));
1960
		if ($valid) {
1961
			$items[] = $tmp;
1962
			if (count($items) == $max_items)
1963
				break;
1964
		}
1965
	}
1966
	fclose($fd);
1967
	return $items;
1968
}
1969

    
1970
function update_alias_url_data() {
1971
	global $config, $g;
1972

    
1973
	$updated = false;
1974

    
1975
	/* item is a url type */
1976
	$lockkey = lock('aliasurl');
1977
	if (is_array($config['aliases']['alias'])) {
1978
		foreach ($config['aliases']['alias'] as $x => $alias) {
1979
			if (empty($alias['aliasurl']))
1980
				continue;
1981

    
1982
			$address = null;
1983
			foreach ($alias['aliasurl'] as $alias_url) {
1984
				/* fetch down and add in */
1985
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
1986
				unlink($temp_filename);
1987
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
1988
				mkdir($temp_filename);
1989
				download_file($alias_url, $temp_filename . "/aliases", $verify_ssl);
1990

    
1991
				/* if the item is tar gzipped then extract */
1992
				if (stripos($alias_url, '.tgz')) {
1993
					if (!process_alias_tgz($temp_filename))
1994
						continue;
1995
				} else if (stripos($alias_url, '.zip')) {
1996
					if (!process_alias_unzip($temp_filename))
1997
						continue;
1998
				}
1999
				if (file_exists("{$temp_filename}/aliases")) {
2000
					$address = parse_aliases_file("{$temp_filename}/aliases", $alias['type'], 3000);
2001
					mwexec("/bin/rm -rf {$temp_filename}");
2002
				}
2003
			}
2004
			if ($address != null) {
2005
				$config['aliases']['alias'][$x]['address'] = implode(" ", $address);
2006
				$updated = true;
2007
			}
2008
		}
2009
	}
2010
	unlock($lockkey);
2011

    
2012
	/* Report status to callers as well */
2013
	return $updated;
2014
}
2015

    
2016
function process_alias_unzip($temp_filename) {
2017
	if(!file_exists("/usr/local/bin/unzip")) {
2018
		log_error(gettext("Alias archive is a .zip file which cannot be decompressed because utility is missing!"));
2019
		return false;
2020
	}
2021
	rename("{$temp_filename}/aliases", "{$temp_filename}/aliases.zip");
2022
	mwexec("/usr/local/bin/unzip {$temp_filename}/aliases.tgz -d {$temp_filename}/aliases/");
2023
	unlink("{$temp_filename}/aliases.zip");
2024
	$files_to_process = return_dir_as_array("{$temp_filename}/");
2025
	/* foreach through all extracted files and build up aliases file */
2026
	$fd = @fopen("{$temp_filename}/aliases", "w");
2027
	if (!$fd) {
2028
		log_error(gettext("Could not open {$temp_filename}/aliases for writing!"));
2029
		return false;
2030
	}
2031
	foreach($files_to_process as $f2p) {
2032
		$tmpfd = @fopen($f2p, 'r');
2033
		if (!$tmpfd) {
2034
			log_error(gettext("The following file could not be read {$f2p} from {$temp_filename}"));
2035
			continue;
2036
		}
2037
		while (($tmpbuf = fread($tmpfd, 65536)) !== FALSE)
2038
			fwrite($fd, $tmpbuf);
2039
		fclose($tmpfd);
2040
		unlink($f2p);
2041
	}
2042
	fclose($fd);
2043
	unset($tmpbuf);
2044

    
2045
	return true;
2046
}
2047

    
2048
function process_alias_tgz($temp_filename) {
2049
	if(!file_exists('/usr/bin/tar')) {
2050
		log_error(gettext("Alias archive is a .tar/tgz file which cannot be decompressed because utility is missing!"));
2051
		return false;
2052
	}
2053
	rename("{$temp_filename}/aliases", "{$temp_filename}/aliases.tgz");
2054
	mwexec("/usr/bin/tar xzf {$temp_filename}/aliases.tgz -C {$temp_filename}/aliases/");
2055
	unlink("{$temp_filename}/aliases.tgz");
2056
	$files_to_process = return_dir_as_array("{$temp_filename}/");
2057
	/* foreach through all extracted files and build up aliases file */
2058
	$fd = @fopen("{$temp_filename}/aliases", "w");
2059
	if (!$fd) {
2060
		log_error(gettext("Could not open {$temp_filename}/aliases for writing!"));
2061
		return false;
2062
	}
2063
	foreach($files_to_process as $f2p) {
2064
		$tmpfd = @fopen($f2p, 'r');
2065
		if (!$tmpfd) {
2066
			log_error(gettext("The following file could not be read {$f2p} from {$temp_filename}"));
2067
			continue;
2068
		}
2069
		while (($tmpbuf = fread($tmpfd, 65536)) !== FALSE)
2070
			fwrite($fd, $tmpbuf);
2071
		fclose($tmpfd);
2072
		unlink($f2p);
2073
	}
2074
	fclose($fd);
2075
	unset($tmpbuf);
2076

    
2077
	return true;
2078
}
2079

    
2080
function version_compare_dates($a, $b) {
2081
	$a_time = strtotime($a);
2082
	$b_time = strtotime($b);
2083

    
2084
	if ((!$a_time) || (!$b_time)) {
2085
		return FALSE;
2086
	} else {
2087
		if ($a_time < $b_time)
2088
			return -1;
2089
		elseif ($a_time == $b_time)
2090
			return 0;
2091
		else
2092
			return 1;
2093
	}
2094
}
2095
function version_get_string_value($a) {
2096
	$strs = array(
2097
		0 => "ALPHA-ALPHA",
2098
		2 => "ALPHA",
2099
		3 => "BETA",
2100
		4 => "B",
2101
		5 => "C",
2102
		6 => "D",
2103
		7 => "RC",
2104
		8 => "RELEASE",
2105
		9 => "*"			// Matches all release levels
2106
	);
2107
	$major = 0;
2108
	$minor = 0;
2109
	foreach ($strs as $num => $str) {
2110
		if (substr($a, 0, strlen($str)) == $str) {
2111
			$major = $num;
2112
			$n = substr($a, strlen($str));
2113
			if (is_numeric($n))
2114
				$minor = $n;
2115
			break;
2116
		}
2117
	}
2118
	return "{$major}.{$minor}";
2119
}
2120
function version_compare_string($a, $b) {
2121
	// Only compare string parts if both versions give a specific release
2122
	// (If either version lacks a string part, assume intended to match all release levels)
2123
	if (isset($a) && isset($b))
2124
		return version_compare_numeric(version_get_string_value($a), version_get_string_value($b));
2125
	else
2126
		return 0;
2127
}
2128
function version_compare_numeric($a, $b) {
2129
	$a_arr = explode('.', rtrim($a, '.'));
2130
	$b_arr = explode('.', rtrim($b, '.'));
2131

    
2132
	foreach ($a_arr as $n => $val) {
2133
		if (array_key_exists($n, $b_arr)) {
2134
			// So far so good, both have values at this minor version level. Compare.
2135
			if ($val > $b_arr[$n])
2136
				return 1;
2137
			elseif ($val < $b_arr[$n])
2138
				return -1;
2139
		} else {
2140
			// a is greater, since b doesn't have any minor version here.
2141
			return 1;
2142
		}
2143
	}
2144
	if (count($b_arr) > count($a_arr)) {
2145
		// b is longer than a, so it must be greater.
2146
		return -1;
2147
	} else {
2148
		// Both a and b are of equal length and value.
2149
		return 0;
2150
	}
2151
}
2152
function pfs_version_compare($cur_time, $cur_text, $remote) {
2153
	// First try date compare
2154
	$v = version_compare_dates($cur_time, $remote);
2155
	if ($v === FALSE) {
2156
		// If that fails, try to compare by string
2157
		// Before anything else, simply test if the strings are equal
2158
		if (($cur_text == $remote) || ($cur_time == $remote))
2159
			return 0;
2160
		list($cur_num, $cur_str) = explode('-', $cur_text);
2161
		list($rem_num, $rem_str) = explode('-', $remote);
2162

    
2163
		// First try to compare the numeric parts of the version string.
2164
		$v = version_compare_numeric($cur_num, $rem_num);
2165

    
2166
		// If the numeric parts are the same, compare the string parts.
2167
		if ($v == 0)
2168
			return version_compare_string($cur_str, $rem_str);
2169
	}
2170
	return $v;
2171
}
2172
function process_alias_urltable($name, $url, $freq, $forceupdate=false) {
2173
	global $config;
2174

    
2175
	$urltable_prefix = "/var/db/aliastables/";
2176
	$urltable_filename = $urltable_prefix . $name . ".txt";
2177

    
2178
	// Make the aliases directory if it doesn't exist
2179
	if (!file_exists($urltable_prefix)) {
2180
		mkdir($urltable_prefix);
2181
	} elseif (!is_dir($urltable_prefix)) {
2182
		unlink($urltable_prefix);
2183
		mkdir($urltable_prefix);
2184
	}
2185

    
2186
	// If the file doesn't exist or is older than update_freq days, fetch a new copy.
2187
	if (!file_exists($urltable_filename)
2188
		|| ((time() - filemtime($urltable_filename)) > ($freq * 86400 - 90))
2189
		|| $forceupdate) {
2190

    
2191
		// Try to fetch the URL supplied
2192
		conf_mount_rw();
2193
		unlink_if_exists($urltable_filename . ".tmp");
2194
		$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2195
		if (download_file($url, $urltable_filename . ".tmp", $verify_ssl)) {
2196
			mwexec("/usr/bin/sed -E 's/\;.*//g; /^[[:space:]]*($|#)/d' ". escapeshellarg($urltable_filename . ".tmp") . " > " . escapeshellarg($urltable_filename));
2197
			if (alias_get_type($name) == "urltable_ports") {
2198
				$ports = explode("\n", str_replace("\r", "", file_get_contents($urltable_filename)));
2199
				$ports = group_ports($ports);
2200
				file_put_contents($urltable_filename, implode("\n", $ports));
2201
			}
2202
			unlink_if_exists($urltable_filename . ".tmp");
2203
		} else
2204
			touch($urltable_filename);
2205
		conf_mount_ro();
2206
		return true;
2207
	} else {
2208
		// File exists, and it doesn't need updated.
2209
		return -1;
2210
	}
2211
}
2212
function get_real_slice_from_glabel($label) {
2213
	$label = escapeshellarg($label);
2214
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/{$label} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`);
2215
}
2216
function nanobsd_get_boot_slice() {
2217
	return trim(`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`);
2218
}
2219
function nanobsd_get_boot_drive() {
2220
	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`);
2221
}
2222
function nanobsd_get_active_slice() {
2223
	$boot_drive = nanobsd_get_boot_drive();
2224
	$active = trim(`gpart show $boot_drive | grep '\[active\]' | awk '{print $3;}'`);
2225

    
2226
	return "{$boot_drive}s{$active}";
2227
}
2228
function nanobsd_get_size() {
2229
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2230
}
2231
function nanobsd_switch_boot_slice() {
2232
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2233
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2234
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2235
	nanobsd_detect_slice_info();
2236

    
2237
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2238
		$slice = $TOFLASH;
2239
	} else {
2240
		$slice = $BOOTFLASH;
2241
	}
2242

    
2243
	for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
2244
	ob_implicit_flush(1);
2245
	if(strstr($slice, "s2")) {
2246
		$ASLICE="2";
2247
		$AOLDSLICE="1";
2248
		$AGLABEL_SLICE="pfsense1";
2249
		$AUFS_ID="1";
2250
		$AOLD_UFS_ID="0";
2251
	} else {
2252
		$ASLICE="1";
2253
		$AOLDSLICE="2";
2254
		$AGLABEL_SLICE="pfsense0";
2255
		$AUFS_ID="0";
2256
		$AOLD_UFS_ID="1";
2257
	}
2258
	$ATOFLASH="{$BOOT_DRIVE}s{$ASLICE}";
2259
	$ACOMPLETE_PATH="{$BOOT_DRIVE}s{$ASLICE}a";
2260
	$ABOOTFLASH="{$BOOT_DRIVE}s{$AOLDSLICE}";
2261
	conf_mount_rw();
2262
	set_single_sysctl("kern.geom.debugflags", "16");
2263
	exec("gpart set -a active -i {$ASLICE} {$BOOT_DRIVE}");
2264
	exec("/usr/sbin/boot0cfg -s {$ASLICE} -v /dev/{$BOOT_DRIVE}");
2265
	// We can't update these if they are mounted now.
2266
	if ($BOOTFLASH != $slice) {
2267
		exec("/sbin/tunefs -L ${AGLABEL_SLICE} /dev/$ACOMPLETE_PATH");
2268
		nanobsd_update_fstab($AGLABEL_SLICE, $ACOMPLETE_PATH, $AOLD_UFS_ID, $AUFS_ID);
2269
	}
2270
	set_single_sysctl("kern.geom.debugflags", "0");
2271
	conf_mount_ro();
2272
}
2273
function nanobsd_clone_slice() {
2274
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2275
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2276
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2277
	nanobsd_detect_slice_info();
2278

    
2279
	for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
2280
	ob_implicit_flush(1);
2281
	set_single_sysctl("kern.geom.debugflags", "16");
2282
	exec("/bin/dd if=/dev/zero of=/dev/{$TOFLASH} bs=1m count=1");
2283
	exec("/bin/dd if=/dev/{$BOOTFLASH} of=/dev/{$TOFLASH} bs=64k");
2284
	exec("/sbin/tunefs -L {$GLABEL_SLICE} /dev/{$COMPLETE_PATH}");
2285
	$status = nanobsd_update_fstab($GLABEL_SLICE, $COMPLETE_PATH, $OLD_UFS_ID, $UFS_ID);
2286
	set_single_sysctl("kern.geom.debugflags", "0");
2287
	if($status) {
2288
		return false;
2289
	} else {
2290
		return true;
2291
	}
2292
}
2293
function nanobsd_update_fstab($gslice, $complete_path, $oldufs, $newufs) {
2294
	$tmppath = "/tmp/{$gslice}";
2295
	$fstabpath = "/tmp/{$gslice}/etc/fstab";
2296

    
2297
	mkdir($tmppath);
2298
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2299
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2300
	copy("/etc/fstab", $fstabpath);
2301

    
2302
	if (!file_exists($fstabpath)) {
2303
		$fstab = <<<EOF
2304
/dev/ufs/{$gslice} / ufs ro,noatime 1 1
2305
/dev/ufs/cf /cf ufs ro,noatime 1 1
2306
EOF;
2307
		if (file_put_contents($fstabpath, $fstab))
2308
			$status = true;
2309
		else
2310
			$status = false;
2311
	} else {
2312
		$status = exec("sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2313
	}
2314
	exec("/sbin/umount {$tmppath}");
2315
	rmdir($tmppath);
2316

    
2317
	return $status;
2318
}
2319
function nanobsd_detect_slice_info() {
2320
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2321
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2322
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2323

    
2324
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2325
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2326
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2327
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2328

    
2329
	// Detect which slice is active and set information.
2330
	if(strstr($REAL_BOOT_DEVICE, "s1")) {
2331
		$SLICE="2";
2332
		$OLDSLICE="1";
2333
		$GLABEL_SLICE="pfsense1";
2334
		$UFS_ID="1";
2335
		$OLD_UFS_ID="0";
2336

    
2337
	} else {
2338
		$SLICE="1";
2339
		$OLDSLICE="2";
2340
		$GLABEL_SLICE="pfsense0";
2341
		$UFS_ID="0";
2342
		$OLD_UFS_ID="1";
2343
	}
2344
	$TOFLASH="{$BOOT_DRIVE}s{$SLICE}";
2345
	$COMPLETE_PATH="{$BOOT_DRIVE}s{$SLICE}a";
2346
	$COMPLETE_BOOT_PATH="{$BOOT_DRIVE}s{$OLDSLICE}";
2347
	$BOOTFLASH="{$BOOT_DRIVE}s{$OLDSLICE}";
2348
}
2349

    
2350
function nanobsd_friendly_slice_name($slicename) {
2351
	global $g;
2352
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2353
}
2354

    
2355
function get_include_contents($filename) {
2356
	if (is_file($filename)) {
2357
		ob_start();
2358
		include $filename;
2359
		$contents = ob_get_contents();
2360
		ob_end_clean();
2361
		return $contents;
2362
	}
2363
	return false;
2364
}
2365

    
2366
/* This xml 2 array function is courtesy of the php.net comment section on xml_parse.
2367
 * it is roughly 4 times faster then our existing pfSense parser but due to the large
2368
 * size of the RRD xml dumps this is required.
2369
 * The reason we do not use it for pfSense is that it does not know about array fields
2370
 * which causes it to fail on array fields with single items. Possible Todo?
2371
 */
2372
function xml2array($contents, $get_attributes = 1, $priority = 'tag')
2373
{
2374
	if (!function_exists('xml_parser_create'))
2375
	{
2376
		return array ();
2377
	}
2378
	$parser = xml_parser_create('');
2379
	xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
2380
	xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
2381
	xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
2382
	xml_parse_into_struct($parser, trim($contents), $xml_values);
2383
	xml_parser_free($parser);
2384
	if (!$xml_values)
2385
		return; //Hmm...
2386
	$xml_array = array ();
2387
	$parents = array ();
2388
	$opened_tags = array ();
2389
	$arr = array ();
2390
	$current = & $xml_array;
2391
	$repeated_tag_index = array ();
2392
	foreach ($xml_values as $data)
2393
	{
2394
		unset ($attributes, $value);
2395
		extract($data);
2396
		$result = array ();
2397
		$attributes_data = array ();
2398
		if (isset ($value))
2399
		{
2400
			if ($priority == 'tag')
2401
				$result = $value;
2402
			else
2403
				$result['value'] = $value;
2404
		}
2405
		if (isset ($attributes) and $get_attributes)
2406
		{
2407
			foreach ($attributes as $attr => $val)
2408
			{
2409
				if ($priority == 'tag')
2410
					$attributes_data[$attr] = $val;
2411
				else
2412
					$result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
2413
			}
2414
		}
2415
		if ($type == "open")
2416
		{
2417
			$parent[$level -1] = & $current;
2418
			if (!is_array($current) or (!in_array($tag, array_keys($current))))
2419
			{
2420
				$current[$tag] = $result;
2421
				if ($attributes_data)
2422
					$current[$tag . '_attr'] = $attributes_data;
2423
				$repeated_tag_index[$tag . '_' . $level] = 1;
2424
				$current = & $current[$tag];
2425
			}
2426
			else
2427
			{
2428
				if (isset ($current[$tag][0]))
2429
				{
2430
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2431
					$repeated_tag_index[$tag . '_' . $level]++;
2432
				}
2433
				else
2434
				{
2435
					$current[$tag] = array (
2436
						$current[$tag],
2437
						$result
2438
						);
2439
					$repeated_tag_index[$tag . '_' . $level] = 2;
2440
					if (isset ($current[$tag . '_attr']))
2441
					{
2442
						$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2443
						unset ($current[$tag . '_attr']);
2444
					}
2445
				}
2446
				$last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
2447
				$current = & $current[$tag][$last_item_index];
2448
			}
2449
		}
2450
		elseif ($type == "complete")
2451
		{
2452
			if (!isset ($current[$tag]))
2453
			{
2454
				$current[$tag] = $result;
2455
				$repeated_tag_index[$tag . '_' . $level] = 1;
2456
				if ($priority == 'tag' and $attributes_data)
2457
					$current[$tag . '_attr'] = $attributes_data;
2458
			}
2459
			else
2460
			{
2461
				if (isset ($current[$tag][0]) and is_array($current[$tag]))
2462
				{
2463
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2464
					if ($priority == 'tag' and $get_attributes and $attributes_data)
2465
					{
2466
						$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2467
					}
2468
					$repeated_tag_index[$tag . '_' . $level]++;
2469
				}
2470
				else
2471
				{
2472
					$current[$tag] = array (
2473
						$current[$tag],
2474
						$result
2475
						);
2476
					$repeated_tag_index[$tag . '_' . $level] = 1;
2477
					if ($priority == 'tag' and $get_attributes)
2478
					{
2479
						if (isset ($current[$tag . '_attr']))
2480
						{
2481
							$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2482
							unset ($current[$tag . '_attr']);
2483
						}
2484
						if ($attributes_data)
2485
						{
2486
							$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2487
						}
2488
					}
2489
					$repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
2490
				}
2491
			}
2492
		}
2493
		elseif ($type == 'close')
2494
		{
2495
			$current = & $parent[$level -1];
2496
		}
2497
	}
2498
	return ($xml_array);
2499
}
2500

    
2501
function get_country_name($country_code) {
2502
	if ($country_code != "ALL" && strlen($country_code) != 2)
2503
		return "";
2504

    
2505
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2506
	$country_names_contents = file_get_contents($country_names_xml);
2507
	$country_names = xml2array($country_names_contents);
2508

    
2509
	if($country_code == "ALL") {
2510
		$country_list = array();
2511
		foreach($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2512
			$country_list[] = array("code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2513
						"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])) );
2514
		}
2515
		return $country_list;
2516
	}
2517

    
2518
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2519
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2520
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2521
		}
2522
	}
2523
	return "";
2524
}
2525

    
2526
/* sort by interface only, retain the original order of rules that apply to
2527
   the same interface */
2528
function filter_rules_sort() {
2529
	global $config;
2530

    
2531
	/* mark each rule with the sequence number (to retain the order while sorting) */
2532
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++)
2533
		$config['filter']['rule'][$i]['seq'] = $i;
2534

    
2535
	usort($config['filter']['rule'], "filter_rules_compare");
2536

    
2537
	/* strip the sequence numbers again */
2538
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++)
2539
		unset($config['filter']['rule'][$i]['seq']);
2540
}
2541
function filter_rules_compare($a, $b) {
2542
	if (isset($a['floating']) && isset($b['floating']))
2543
		return $a['seq'] - $b['seq'];
2544
	else if (isset($a['floating']))
2545
		return -1;
2546
	else if (isset($b['floating']))
2547
		return 1;
2548
	else if ($a['interface'] == $b['interface'])
2549
		return $a['seq'] - $b['seq'];
2550
	else
2551
		return compare_interface_friendly_names($a['interface'], $b['interface']);
2552
}
2553

    
2554
function generate_ipv6_from_mac($mac) {
2555
	$elements = explode(":", $mac);
2556
	if(count($elements) <> 6)
2557
		return false;
2558

    
2559
	$i = 0;
2560
	$ipv6 = "fe80::";
2561
	foreach($elements as $byte) {
2562
		if($i == 0) {
2563
			$hexadecimal =  substr($byte, 1, 2);
2564
			$bitmap = base_convert($hexadecimal, 16, 2);
2565
			$bitmap = str_pad($bitmap, 4, "0", STR_PAD_LEFT);
2566
			$bitmap = substr($bitmap, 0, 2) ."1". substr($bitmap, 3,4);
2567
			$byte = substr($byte, 0, 1) . base_convert($bitmap, 2, 16);
2568
		}
2569
		$ipv6 .= $byte;
2570
		if($i == 1) {
2571
			$ipv6 .= ":";
2572
		}
2573
		if($i == 3) {
2574
			$ipv6 .= ":";
2575
		}
2576
		if($i == 2) {
2577
			$ipv6 .= "ff:fe";
2578
		}
2579

    
2580
		$i++;
2581
	}
2582
	return $ipv6;
2583
}
2584

    
2585
/****f* pfsense-utils/load_mac_manufacturer_table
2586
 * NAME
2587
 *   load_mac_manufacturer_table
2588
 * INPUTS
2589
 *   none
2590
 * RESULT
2591
 *   returns associative array with MAC-Manufacturer pairs
2592
 ******/
2593
function load_mac_manufacturer_table() {
2594
	/* load MAC-Manufacture data from the file */
2595
	$macs = false;
2596
	if (file_exists("/usr/local/share/nmap/nmap-mac-prefixes"))
2597
		$macs=file("/usr/local/share/nmap/nmap-mac-prefixes");
2598
	if ($macs){
2599
		foreach ($macs as $line){
2600
			if (preg_match('/([0-9A-Fa-f]{6}) (.*)$/', $line, $matches)){
2601
				/* store values like this $mac_man['000C29']='VMware' */
2602
				$mac_man["$matches[1]"]=$matches[2];
2603
			}
2604
		}
2605
		return $mac_man;
2606
	} else
2607
		return -1;
2608

    
2609
}
2610

    
2611
/****f* pfsense-utils/is_ipaddr_configured
2612
 * NAME
2613
 *   is_ipaddr_configured
2614
 * INPUTS
2615
 *   IP Address to check.
2616
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2617
 * RESULT
2618
 *   returns true if the IP Address is
2619
 *   configured and present on this device.
2620
*/
2621
function is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false) {
2622
	global $config;
2623

    
2624
	$pos = strpos($ignore_if, '_virtualip');
2625
	if ($pos !== false) {
2626
		$ignore_vip_id = substr($ignore_if, $pos+10);
2627
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2628
	} else {
2629
		$ignore_vip_id = -1;
2630
		$ignore_vip_if = $ignore_if;
2631
	}
2632

    
2633
	$isipv6 = is_ipaddrv6($ipaddr);
2634

    
2635
	if ($check_subnets) {
2636
		$iflist = get_configured_interface_list();
2637
		foreach ($iflist as $if => $ifname) {
2638
			if ($ignore_if == $if)
2639
				continue;
2640

    
2641
			if ($isipv6 === true) {
2642
				$bitmask = get_interface_subnetv6($if);
2643
				$subnet = gen_subnetv6(get_interface_ipv6($if), $bitmask);
2644
			} else {
2645
				$bitmask = get_interface_subnet($if);
2646
				$subnet = gen_subnet(get_interface_ip($if), $bitmask);
2647
			}
2648

    
2649
			if (ip_in_subnet($ipaddr, $subnet . '/' . $bitmask))
2650
				return true;
2651
		}
2652
	} else {
2653
		if ($isipv6 === true)
2654
			$interface_list_ips = get_configured_ipv6_addresses();
2655
		else
2656
			$interface_list_ips = get_configured_ip_addresses();
2657

    
2658
		foreach($interface_list_ips as $if => $ilips) {
2659
			if ($ignore_if == $if)
2660
				continue;
2661
			if (strcasecmp($ipaddr, $ilips) == 0)
2662
				return true;
2663
		}
2664
	}
2665

    
2666
	$interface_list_vips = get_configured_vips_list(true);
2667
	foreach ($interface_list_vips as $id => $vip) {
2668
		/* Skip CARP interfaces here since they were already checked above */
2669
		if ($id == $ignore_vip_id || (strstr($ignore_if, '_vip') && $ignore_vip_if == $vip['if']))
2670
			continue;
2671
		if (strcasecmp($ipaddr, $vip['ipaddr']) == 0)
2672
			return true;
2673
	}
2674

    
2675
	if ($check_localip) {
2676
		if (is_array($config['pptpd']) && !empty($config['pptpd']['localip']) && (strcasecmp($ipaddr, $config['pptpd']['localip']) == 0))
2677
			return true;
2678

    
2679
		if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0))
2680
			return true;
2681
	}
2682

    
2683
	return false;
2684
}
2685

    
2686
/****f* pfsense-utils/pfSense_handle_custom_code
2687
 * NAME
2688
 *   pfSense_handle_custom_code
2689
 * INPUTS
2690
 *   directory name to process
2691
 * RESULT
2692
 *   globs the directory and includes the files
2693
 */
2694
function pfSense_handle_custom_code($src_dir) {
2695
	// Allow extending of the nat edit page and include custom input validation
2696
	if(is_dir("$src_dir")) {
2697
		$cf = glob($src_dir . "/*.inc");
2698
		foreach($cf as $nf) {
2699
			if($nf == "." || $nf == "..")
2700
				continue;
2701
			// Include the extra handler
2702
			include("$nf");
2703
		}
2704
	}
2705
}
2706

    
2707
function set_language($lang = 'en_US', $encoding = "UTF-8") {
2708
	putenv("LANG={$lang}.{$encoding}");
2709
	setlocale(LC_ALL, "{$lang}.{$encoding}");
2710
	textdomain("pfSense");
2711
	bindtextdomain("pfSense","/usr/local/share/locale");
2712
	bind_textdomain_codeset("pfSense","{$lang}.{$encoding}");
2713
}
2714

    
2715
function get_locale_list() {
2716
	$locales = array(
2717
		"en_US" => gettext("English"),
2718
		"pt_BR" => gettext("Portuguese (Brazil)"),
2719
		"tr" => gettext("Turkish"),
2720
	);
2721
	asort($locales);
2722
	return $locales;
2723
}
2724

    
2725
function system_get_language_code() {
2726
	global $config, $g_languages;
2727

    
2728
	// a language code, as per [RFC3066]
2729
	$language = $config['system']['language'];
2730
	//$code = $g_languages[$language]['code'];
2731
	$code = str_replace("_", "-", $language);
2732

    
2733
	if (empty($code))
2734
		$code = "en-US"; // Set default code.
2735

    
2736
	return $code;
2737
}
2738

    
2739
function system_get_language_codeset() {
2740
	global $config, $g_languages;
2741

    
2742
	$language = $config['system']['language'];
2743
	$codeset = $g_languages[$language]['codeset'];
2744

    
2745
	if (empty($codeset))
2746
		$codeset = "UTF-8"; // Set default codeset.
2747

    
2748
	return $codeset;
2749
}
2750

    
2751
/* Available languages/locales */
2752
$g_languages = array (
2753
	"sq"    => array("codeset" => "UTF-8", "desc" => gettext("Albanian")),
2754
	"bg"    => array("codeset" => "UTF-8", "desc" => gettext("Bulgarian")),
2755
	"zh_CN" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Simplified)")),
2756
	"zh_TW" => array("codeset" => "UTF-8", "desc" => gettext("Chinese (Traditional)")),
2757
	"nl"    => array("codeset" => "UTF-8", "desc" => gettext("Dutch")),
2758
	"da"    => array("codeset" => "UTF-8", "desc" => gettext("Danish")),
2759
	"en_US" => array("codeset" => "UTF-8", "desc" => gettext("English")),
2760
	"fi"    => array("codeset" => "UTF-8", "desc" => gettext("Finnish")),
2761
	"fr"    => array("codeset" => "UTF-8", "desc" => gettext("French")),
2762
	"de"    => array("codeset" => "UTF-8", "desc" => gettext("German")),
2763
	"el"    => array("codeset" => "UTF-8", "desc" => gettext("Greek")),
2764
	"hu"    => array("codeset" => "UTF-8", "desc" => gettext("Hungarian")),
2765
	"it"    => array("codeset" => "UTF-8", "desc" => gettext("Italian")),
2766
	"ja"    => array("codeset" => "UTF-8", "desc" => gettext("Japanese")),
2767
	"ko"    => array("codeset" => "UTF-8", "desc" => gettext("Korean")),
2768
	"lv"    => array("codeset" => "UTF-8", "desc" => gettext("Latvian")),
2769
	"nb"    => array("codeset" => "UTF-8", "desc" => gettext("Norwegian (Bokmal)")),
2770
	"pl"    => array("codeset" => "UTF-8", "desc" => gettext("Polish")),
2771
	"pt_BR" => array("codeset" => "UTF-8", "desc" => gettext("Portuguese (Brazil)")),
2772
	"pt"    => array("codeset" => "UTF-8", "desc" => gettext("Portuguese (Portugal)")),
2773
	"ro"    => array("codeset" => "UTF-8", "desc" => gettext("Romanian")),
2774
	"ru"    => array("codeset" => "UTF-8", "desc" => gettext("Russian")),
2775
	"sl"    => array("codeset" => "UTF-8", "desc" => gettext("Slovenian")),
2776
	"tr"    => array("codeset" => "UTF-8", "desc" => gettext("Turkish")),
2777
	"es"    => array("codeset" => "UTF-8", "desc" => gettext("Spanish")),
2778
	"sv"    => array("codeset" => "UTF-8", "desc" => gettext("Swedish")),
2779
	"sk"    => array("codeset" => "UTF-8", "desc" => gettext("Slovak")),
2780
	"cs"    => array("codeset" => "UTF-8", "desc" => gettext("Czech"))
2781
);
2782

    
2783
function return_hex_ipv4($ipv4) {
2784
	if(!is_ipaddrv4($ipv4))
2785
		return(false);
2786

    
2787
	/* we need the hex form of the interface IPv4 address */
2788
	$ip4arr = explode(".", $ipv4);
2789
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2790
}
2791

    
2792
function convert_ipv6_to_128bit($ipv6) {
2793
	if(!is_ipaddrv6($ipv6))
2794
		return(false);
2795

    
2796
	$ip6arr = array();
2797
	$ip6prefix = Net_IPv6::uncompress($ipv6);
2798
	$ip6arr = explode(":", $ip6prefix);
2799
	/* binary presentation of the prefix for all 128 bits. */
2800
	$ip6prefixbin = "";
2801
	foreach($ip6arr as $element) {
2802
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
2803
	}
2804
	return($ip6prefixbin);
2805
}
2806

    
2807
function convert_128bit_to_ipv6($ip6bin) {
2808
	if(strlen($ip6bin) <> 128)
2809
		return(false);
2810

    
2811
	$ip6arr = array();
2812
	$ip6binarr = array();
2813
	$ip6binarr = str_split($ip6bin, 16);
2814
	foreach($ip6binarr as $binpart)
2815
		$ip6arr[] = dechex(bindec($binpart));
2816
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
2817

    
2818
	return($ip6addr);
2819
}
2820

    
2821

    
2822
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
2823
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
2824
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
2825
/* 6to4 is 16 bits, e.g. 65535 */
2826
function calculate_ipv6_delegation_length($if) {
2827
	global $config;
2828

    
2829
	if(!is_array($config['interfaces'][$if]))
2830
		return false;
2831

    
2832
	switch($config['interfaces'][$if]['ipaddrv6']) {
2833
		case "6to4":
2834
			$pdlen = 16;
2835
			break;
2836
		case "6rd":
2837
			$rd6cfg = $config['interfaces'][$if];
2838
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
2839
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
2840
			break;
2841
		case "dhcp6":
2842
			$dhcp6cfg = $config['interfaces'][$if];
2843
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
2844
			break;
2845
		default:
2846
			$pdlen = 0;
2847
			break;
2848
	}
2849
	return($pdlen);
2850
}
2851

    
2852
function huawei_rssi_to_string($rssi) {
2853
	$dbm = array();
2854
	$i = 0;
2855
	$dbstart = -113;
2856
	while($i < 32) {
2857
		$dbm[$i] = $dbstart + ($i * 2);
2858
		$i++;
2859
	}
2860
	$percent = round(($rssi / 31) * 100);
2861
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
2862
	return $string;
2863
}
2864

    
2865
function huawei_mode_to_string($mode, $submode) {
2866
	$modes[0] = "None";
2867
	$modes[1] = "AMPS";
2868
	$modes[2] = "CDMA";
2869
	$modes[3] = "GSM/GPRS";
2870
	$modes[4] = "HDR";
2871
	$modes[5] = "WCDMA";
2872
	$modes[6] = "GPS";
2873

    
2874
	$submodes[0] = "No Service";
2875
	$submodes[1] = "GSM";
2876
	$submodes[2] = "GPRS";
2877
	$submodes[3] = "EDGE";
2878
	$submodes[4] = "WCDMA";
2879
	$submodes[5] = "HSDPA";
2880
	$submodes[6] = "HSUPA";
2881
	$submodes[7] = "HSDPA+HSUPA";
2882
	$submodes[8] = "TD-SCDMA";
2883
	$submodes[9] = "HSPA+";
2884
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
2885
	return $string;
2886
}
2887

    
2888
function huawei_service_to_string($state) {
2889
	$modes[0] = "No";
2890
	$modes[1] = "Restricted";
2891
	$modes[2] = "Valid";
2892
	$modes[3] = "Restricted Regional";
2893
	$modes[4] = "Powersaving";
2894
	$string = "{$modes[$state]} Service";
2895
	return $string;
2896
}
2897

    
2898
function huawei_simstate_to_string($state) {
2899
	$modes[0] = "Invalid SIM/locked";
2900
	$modes[1] = "Valid SIM";
2901
	$modes[2] = "Invalid SIM CS";
2902
	$modes[3] = "Invalid SIM PS";
2903
	$modes[4] = "Invalid SIM CS/PS";
2904
	$modes[255] = "Missing SIM";
2905
	$string = "{$modes[$state]} State";
2906
	return $string;
2907
}
2908

    
2909
function zte_rssi_to_string($rssi) {
2910
	return huawei_rssi_to_string($rssi);
2911
}
2912

    
2913
function zte_mode_to_string($mode, $submode) {
2914
	$modes[0] = "No Service";
2915
	$modes[1] = "Limited Service";
2916
	$modes[2] = "GPRS";
2917
	$modes[3] = "GSM";
2918
	$modes[4] = "UMTS";
2919
	$modes[5] = "EDGE";
2920
	$modes[6] = "HSDPA";
2921

    
2922
	$submodes[0] = "CS_ONLY";
2923
	$submodes[1] = "PS_ONLY";
2924
	$submodes[2] = "CS_PS";
2925
	$submodes[3] = "CAMPED";
2926
	$string = "{$modes[$mode]}, {$submodes[$submode]} Mode";
2927
	return $string;
2928
}
2929

    
2930
function zte_service_to_string($state) {
2931
	$modes[0] = "Initializing";
2932
	$modes[1] = "Network Lock error";
2933
	$modes[2] = "Network Locked";
2934
	$modes[3] = "Unlocked or correct MCC/MNC";
2935
	$string = "{$modes[$state]} Service";
2936
	return $string;
2937
}
2938

    
2939
function zte_simstate_to_string($state) {
2940
	$modes[0] = "No action";
2941
	$modes[1] = "Network lock";
2942
	$modes[2] = "(U)SIM card lock";
2943
	$modes[3] = "Network Lock and (U)SIM card Lock";
2944
	$string = "{$modes[$state]} State";
2945
	return $string;
2946
}
2947

    
2948
function get_configured_pppoe_server_interfaces() {
2949
	global $config;
2950
	$iflist = array();
2951
	if (is_array($config['pppoes']['pppoe'])) {
2952
		foreach($config['pppoes']['pppoe'] as $pppoe) {
2953
			if ($pppoe['mode'] == "server") {
2954
				$int = "poes". $pppoe['pppoeid'];
2955
				$iflist[$int] = strtoupper($int);
2956
			}
2957
		}
2958
	}
2959
	return $iflist;
2960
}
2961

    
2962
function get_pppoes_child_interfaces($ifpattern) {
2963
	$if_arr = array();
2964
	if($ifpattern == "")
2965
		return;
2966

    
2967
	exec("ifconfig", $out, $ret);
2968
	foreach($out as $line) {
2969
		if(preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
2970
			$if_arr[] = $match[1];
2971
		}
2972
	}
2973
	return $if_arr;
2974

    
2975
}
2976

    
2977
/****f* pfsense-utils/pkg_call_plugins
2978
 * NAME
2979
 *   pkg_call_plugins
2980
 * INPUTS
2981
 *   $plugin_type value used to search in package configuration if the plugin is used, also used to create the function name
2982
 *   $plugin_params parameters to pass to the plugin function for passing multiple parameters a array can be used.
2983
 * RESULT
2984
 *   returns associative array results from the plugin calls for each package
2985
 * NOTES
2986
 *   This generic function can be used to notify or retrieve results from functions that are defined in packages.
2987
 ******/
2988
function pkg_call_plugins($plugin_type, $plugin_params) {
2989
	global $g, $config;
2990
	$results = array();
2991
	if (!is_array($config['installedpackages']['package']))
2992
		return $results;
2993
	foreach ($config['installedpackages']['package'] as $package) {
2994
		if(!file_exists("/usr/local/pkg/" . $package['configurationfile']))
2995
			continue;
2996
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], 'packagegui');
2997
		$pkgname = substr(reverse_strrchr($package['configurationfile'], "."),0,-1);
2998
		if (is_array($pkg_config['plugins']['item']))
2999
			foreach ($pkg_config['plugins']['item'] as $plugin) {
3000
				if ($plugin['type'] == $plugin_type) {
3001
					if (file_exists($pkg_config['include_file']))
3002
						require_once($pkg_config['include_file']);
3003
					else
3004
						continue;
3005
					$plugin_function = $pkgname . '_'. $plugin_type;
3006
					$results[$pkgname] = @eval($plugin_function($plugin_params));
3007
				}
3008
			}
3009
	}
3010
	return $results;
3011
}
3012

    
3013
/* Function to find and return the active XML RPC base URL to avoid code duplication */
3014
function get_active_xml_rpc_base_url() {
3015
	global $config, $g;
3016
	/* If the user has activated the option to enable an alternate xmlrpcbaseurl, and it's not empty, then use it */
3017
	if (isset($config['system']['altpkgrepo']['enable']) && !empty($config['system']['altpkgrepo']['xmlrpcbaseurl'])) {
3018
		return $config['system']['altpkgrepo']['xmlrpcbaseurl'];
3019
	} else {
3020
		return $g['xmlrpcbaseurl'];
3021
	}
3022
}
3023

    
3024
?>
(40-40/68)