Project

General

Profile

Download (94.1 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * pfsense-utils.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2016 Electric Sheep Fencing, LLC
7
 * All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright notice,
13
 *    this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this software
21
 *    must display the following acknowledgment:
22
 *    "This product includes software developed by the pfSense Project
23
 *    for use in the pfSense® software distribution. (http://www.pfsense.org/).
24
 *
25
 * 4. The names "pfSense" and "pfSense Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    coreteam@pfsense.org.
29
 *
30
 * 5. Products derived from this software may not be called "pfSense"
31
 *    nor may "pfSense" appear in their names without prior written
32
 *    permission of the Electric Sheep Fencing, LLC.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *
37
 * "This product includes software developed by the pfSense Project
38
 * for use in the pfSense software distribution (http://www.pfsense.org/).
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
41
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
44
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
52
 */
53

    
54
/****f* pfsense-utils/have_natpfruleint_access
55
 * NAME
56
 *   have_natpfruleint_access
57
 * INPUTS
58
 *	none
59
 * RESULT
60
 *   returns true if user has access to edit a specific firewall nat port forward interface
61
 ******/
62
function have_natpfruleint_access($if) {
63
	$security_url = "firewall_nat_edit.php?if=". strtolower($if);
64
	if (isAllowedPage($security_url, $allowed)) {
65
		return true;
66
	}
67
	return false;
68
}
69

    
70
/****f* pfsense-utils/have_ruleint_access
71
 * NAME
72
 *   have_ruleint_access
73
 * INPUTS
74
 *	none
75
 * RESULT
76
 *   returns true if user has access to edit a specific firewall interface
77
 ******/
78
function have_ruleint_access($if) {
79
	$security_url = "firewall_rules.php?if=". strtolower($if);
80
	if (isAllowedPage($security_url)) {
81
		return true;
82
	}
83
	return false;
84
}
85

    
86
/****f* pfsense-utils/does_url_exist
87
 * NAME
88
 *   does_url_exist
89
 * INPUTS
90
 *	none
91
 * RESULT
92
 *   returns true if a url is available
93
 ******/
94
function does_url_exist($url) {
95
	$fd = fopen("$url", "r");
96
	if ($fd) {
97
		fclose($fd);
98
		return true;
99
	} else {
100
		return false;
101
	}
102
}
103

    
104
/****f* pfsense-utils/is_private_ip
105
 * NAME
106
 *   is_private_ip
107
 * INPUTS
108
 *	none
109
 * RESULT
110
 *   returns true if an ip address is in a private range
111
 ******/
112
function is_private_ip($iptocheck) {
113
	$isprivate = false;
114
	$ip_private_list = array(
115
		"10.0.0.0/8",
116
		"100.64.0.0/10",
117
		"172.16.0.0/12",
118
		"192.168.0.0/16",
119
	);
120
	foreach ($ip_private_list as $private) {
121
		if (ip_in_subnet($iptocheck, $private) == true) {
122
			$isprivate = true;
123
		}
124
	}
125
	return $isprivate;
126
}
127

    
128
/****f* pfsense-utils/get_tmp_file
129
 * NAME
130
 *   get_tmp_file
131
 * INPUTS
132
 *	none
133
 * RESULT
134
 *   returns a temporary filename
135
 ******/
136
function get_tmp_file() {
137
	global $g;
138
	return "{$g['tmp_path']}/tmp-" . time();
139
}
140

    
141
/****f* pfsense-utils/get_dns_servers
142
 * NAME
143
 *   get_dns_servers - get system dns servers
144
 * INPUTS
145
 *   none
146
 * RESULT
147
 *   $dns_servers - an array of the dns servers
148
 ******/
149
function get_dns_servers() {
150
	$dns_servers = array();
151
	if (file_exists("/etc/resolv.conf")) {
152
		$dns_s = file("/etc/resolv.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
153
	}
154
	if (is_array($dns_s)) {
155
		foreach ($dns_s as $dns) {
156
			$matches = "";
157
			if (preg_match("/nameserver (.*)/", $dns, $matches)) {
158
				$dns_servers[] = $matches[1];
159
			}
160
		}
161
	}
162
	return array_unique($dns_servers);
163
}
164

    
165
/****f* pfsense-utils/get_css_files
166
 * NAME
167
 *   get_css_files - get a list of the available CSS files (themes)
168
 * INPUTS
169
 *   none
170
 * RESULT
171
 *   $csslist - an array of the CSS files
172
 ******/
173
function get_css_files() {
174
	$csslist = array();
175

    
176
	// List pfSense files, then any BETA files followed by any user-contributed files
177
	$cssfiles = glob("/usr/local/www/css/*.css");
178

    
179
	if (is_array($cssfiles)) {
180
		arsort($cssfiles);
181
		$usrcss = $pfscss = $betacss = array();
182

    
183
		foreach ($cssfiles as $css) {
184
			if (strpos($css, "BETA") != 0) {
185
				array_push($betacss, $css);
186
			} else if (strpos($css, "pfSense") != 0) {
187
				array_push($pfscss, $css);
188
			} else {
189
				array_push($usrcss, $css);
190
			}
191
		}
192

    
193
		$css = array_merge($pfscss, $betacss, $usrcss);
194

    
195
		foreach ($css as $file) {
196
			$file = basename($file);
197
			$csslist[$file] = pathinfo($file, PATHINFO_FILENAME);
198
		}
199
	}
200
	return $csslist;
201
}
202

    
203
/****f* pfsense-utils/gen_webguicss_field
204
 * NAME
205
 *   gen_webguicss_field
206
 * INPUTS
207
 *   Pointer to section object
208
 *   Initial value for the field
209
 * RESULT
210
 *   no return value, section object is updated
211
 ******/
212
function gen_webguicss_field(&$section, $value) {
213

    
214
	$csslist = get_css_files();
215

    
216
	if (!isset($csslist[$value])) {
217
		$value = "pfSense.css";
218
	}
219

    
220
	$section->addInput(new Form_Select(
221
		'webguicss',
222
		'Theme',
223
		$value,
224
		$csslist
225
	))->setHelp(sprintf(gettext('Choose an alternative css file (if installed) to change the appearance of the webConfigurator. css files are located in /usr/local/www/css/%s'), '<span id="csstxt"></span>'));
226
}
227

    
228
/****f* pfsense-utils/gen_webguifixedmenu_field
229
 * NAME
230
 *   gen_webguifixedmenu_field
231
 * INPUTS
232
 *   Pointer to section object
233
 *   Initial value for the field
234
 * RESULT
235
 *   no return value, section object is updated
236
 ******/
237
function gen_webguifixedmenu_field(&$section, $value) {
238

    
239
	$section->addInput(new Form_Select(
240
		'webguifixedmenu',
241
		'Top Navigation',
242
		$value,
243
		["" => gettext("Scrolls with page"), "fixed" => gettext("Fixed (Remains visible at top of page)")]
244
	))->setHelp("The fixed option is intended for large screens only.");
245
}
246

    
247
/****f* pfsense-utils/gen_webguihostnamemenu_field
248
 * NAME
249
 *   gen_webguihostnamemenu_field
250
 * INPUTS
251
 *   Pointer to section object
252
 *   Initial value for the field
253
 * RESULT
254
 *   no return value, section object is updated
255
 ******/
256
function gen_webguihostnamemenu_field(&$section, $value) {
257

    
258
	$section->addInput(new Form_Select(
259
		'webguihostnamemenu',
260
		'Hostname in Menu',
261
		$value,
262
		["" => gettext("Default (No hostname)"), "hostonly" => gettext("Hostname only"), "fqdn" => gettext("Fully Qualified Domain Name")]
263
	))->setHelp("Replaces the Help menu title in the Navbar with the system hostname or FQDN.");
264
}
265

    
266
/****f* pfsense-utils/gen_dashboardcolumns_field
267
 * NAME
268
 *   gen_dashboardcolumns_field
269
 * INPUTS
270
 *   Pointer to section object
271
 *   Initial value for the field
272
 * RESULT
273
 *   no return value, section object is updated
274
 ******/
275
function gen_dashboardcolumns_field(&$section, $value) {
276

    
277
	if (($value < 1) || ($value > 4)) {
278
		$value = 2;
279
	}
280

    
281
	$section->addInput(new Form_Input(
282
		'dashboardcolumns',
283
		'Dashboard Columns',
284
		'number',
285
		$value,
286
		[min => 1, max => 4]
287
	));
288
}
289

    
290
/****f* pfsense-utils/gen_associatedpanels_fields
291
 * NAME
292
 *   gen_associatedpanels_fields
293
 * INPUTS
294
 *   Pointer to section object
295
 *   Initial value for each of the fields
296
 * RESULT
297
 *   no return value, section object is updated
298
 ******/
299
function gen_associatedpanels_fields(&$section, $value1, $value2, $value3, $value4) {
300

    
301
	$group = new Form_Group('Associated Panels Show/Hide');
302

    
303
	$group->add(new Form_Checkbox(
304
		'dashboardavailablewidgetspanel',
305
		null,
306
		'Available Widgets',
307
		$value1
308
		))->setHelp('Show the Available Widgets panel on the Dashboard.');
309

    
310
	$group->add(new Form_Checkbox(
311
		'systemlogsfilterpanel',
312
		null,
313
		'Log Filter',
314
		$value2
315
	))->setHelp('Show the Log Filter panel in System Logs.');
316

    
317
	$group->add(new Form_Checkbox(
318
		'systemlogsmanagelogpanel',
319
		null,
320
		'Manage Log',
321
		$value3
322
	))->setHelp('Show the Manage Log panel in System Logs.');
323

    
324
	$group->add(new Form_Checkbox(
325
		'statusmonitoringsettingspanel',
326
		null,
327
		'Monitoring Settings',
328
		$value4
329
	))->setHelp('Show the Settings panel in Status Monitoring.');
330

    
331
	$group->setHelp('These options allow certain panels to be automatically hidden on page load. A control is provided in the title bar to un-hide the panel.');
332

    
333
	$section->add($group);
334
}
335

    
336
/****f* pfsense-utils/gen_webguileftcolumnhyper_field
337
 * NAME
338
 *   gen_webguileftcolumnhyper_field
339
 * INPUTS
340
 *   Pointer to section object
341
 *   Initial value for the field
342
 * RESULT
343
 *   no return value, section object is updated
344
 ******/
345
function gen_webguileftcolumnhyper_field(&$section, $value) {
346

    
347
	$section->addInput(new Form_Checkbox(
348
		'webguileftcolumnhyper',
349
		'Left Column Labels',
350
		'Active',
351
		$value
352
	))->setHelp('If selected, clicking a label in the left column will select/toggle the first item of the group.');
353
}
354

    
355
/****f* pfsense-utils/gen_pagenamefirst_field
356
 * NAME
357
 *   gen_pagenamefirst_field
358
 * INPUTS
359
 *   Pointer to section object
360
 *   Initial value for the field
361
 * RESULT
362
 *   no return value, section object is updated
363
 ******/
364
function gen_pagenamefirst_field(&$section, $value) {
365

    
366
	$section->addInput(new Form_Checkbox(
367
		'pagenamefirst',
368
		'Browser tab text',
369
		'Display page name first in browser tab',
370
		$value
371
	))->setHelp('When this is unchecked, the browser tab shows the host name followed '.
372
		'by the current page. Check this box to display the current page followed by the '.
373
		'host name.');
374
}
375

    
376
/****f* pfsense-utils/gen_user_settings_fields
377
 * NAME
378
 *   gen_user_settings_fields
379
 * INPUTS
380
 *   Pointer to section object
381
 *   Array of initial values for the fields
382
 * RESULT
383
 *   no return value, section object is updated
384
 ******/
385
function gen_user_settings_fields(&$section, $pconfig) {
386

    
387
	gen_webguicss_field($section, $pconfig['webguicss']);
388
	gen_webguifixedmenu_field($section, $pconfig['webguifixedmenu']);
389
	gen_webguihostnamemenu_field($section, $pconfig['webguihostnamemenu']);
390
	gen_dashboardcolumns_field($section, $pconfig['dashboardcolumns']);
391
	gen_associatedpanels_fields(
392
		$section,
393
		$pconfig['dashboardavailablewidgetspanel'],
394
		$pconfig['systemlogsfilterpanel'],
395
		$pconfig['systemlogsmanagelogpanel'],
396
		$pconfig['statusmonitoringsettingspanel']);
397
	gen_webguileftcolumnhyper_field($section, $pconfig['webguileftcolumnhyper']);
398
	gen_pagenamefirst_field($section, $pconfig['pagenamefirst']);
399
}
400

    
401
function hardware_offloading_applyflags($iface) {
402
	global $config;
403

    
404
	$flags_on = 0;
405
	$flags_off = 0;
406
	$options = pfSense_get_interface_addresses($iface);
407

    
408
	if (isset($config['system']['disablechecksumoffloading'])) {
409
		if (isset($options['encaps']['txcsum'])) {
410
			$flags_off |= IFCAP_TXCSUM;
411
		}
412
		if (isset($options['encaps']['rxcsum'])) {
413
			$flags_off |= IFCAP_RXCSUM;
414
		}
415
	} else {
416
		if (isset($options['caps']['txcsum'])) {
417
			$flags_on |= IFCAP_TXCSUM;
418
		}
419
		if (isset($options['caps']['rxcsum'])) {
420
			$flags_on |= IFCAP_RXCSUM;
421
		}
422
	}
423

    
424
	if (isset($config['system']['disablesegmentationoffloading'])) {
425
		$flags_off |= IFCAP_TSO;
426
	} else if (isset($options['caps']['tso']) || isset($options['caps']['tso4']) || isset($options['caps']['tso6'])) {
427
		$flags_on |= IFCAP_TSO;
428
	}
429

    
430
	if (isset($config['system']['disablelargereceiveoffloading'])) {
431
		$flags_off |= IFCAP_LRO;
432
	} else if (isset($options['caps']['lro'])) {
433
		$flags_on |= IFCAP_LRO;
434
	}
435

    
436
	/* if the NIC supports polling *AND* it is enabled in the GUI */
437
	if (!isset($config['system']['polling'])) {
438
		$flags_off |= IFCAP_POLLING;
439
	} else if (isset($options['caps']['polling'])) {
440
		$flags_on |= IFCAP_POLLING;
441
	}
442

    
443
	pfSense_interface_capabilities($iface, -$flags_off);
444
	pfSense_interface_capabilities($iface, $flags_on);
445
}
446

    
447
/****f* pfsense-utils/enable_hardware_offloading
448
 * NAME
449
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
450
 * INPUTS
451
 *   $interface	- string containing the physical interface to work on.
452
 * RESULT
453
 *   null
454
 * NOTES
455
 *   This function only supports the fxp driver's loadable microcode.
456
 ******/
457
function enable_hardware_offloading($interface) {
458
	global $g, $config;
459

    
460
	$int = get_real_interface($interface);
461
	if (empty($int)) {
462
		return;
463
	}
464

    
465
	if (!isset($config['system']['do_not_use_nic_microcode'])) {
466
		/* translate wan, lan, opt -> real interface if needed */
467
		$int_family = preg_split("/[0-9]+/", $int);
468
		$supported_ints = array('fxp');
469
		if (in_array($int_family, $supported_ints)) {
470
			if (does_interface_exist($int)) {
471
				pfSense_interface_flags($int, IFF_LINK0);
472
			}
473
		}
474
	}
475

    
476
	/* This is mostly for vlans and ppp types */
477
	$realhwif = get_parent_interface($interface);
478
	if ($realhwif[0] == $int) {
479
		hardware_offloading_applyflags($int);
480
	} else {
481
		hardware_offloading_applyflags($realhwif[0]);
482
		hardware_offloading_applyflags($int);
483
	}
484
}
485

    
486
/****f* pfsense-utils/interface_supports_polling
487
 * NAME
488
 *   checks to see if an interface supports polling according to man polling
489
 * INPUTS
490
 *
491
 * RESULT
492
 *   true or false
493
 * NOTES
494
 *
495
 ******/
496
function interface_supports_polling($iface) {
497
	$opts = pfSense_get_interface_addresses($iface);
498
	if (is_array($opts) && isset($opts['caps']['polling'])) {
499
		return true;
500
	}
501

    
502
	return false;
503
}
504

    
505
/****f* pfsense-utils/is_alias_inuse
506
 * NAME
507
 *   checks to see if an alias is currently in use by a rule
508
 * INPUTS
509
 *
510
 * RESULT
511
 *   true or false
512
 * NOTES
513
 *
514
 ******/
515
function is_alias_inuse($alias) {
516
	global $g, $config;
517

    
518
	if ($alias == "") {
519
		return false;
520
	}
521
	/* loop through firewall rules looking for alias in use */
522
	if (is_array($config['filter']['rule'])) {
523
		foreach ($config['filter']['rule'] as $rule) {
524
			if ($rule['source']['address']) {
525
				if ($rule['source']['address'] == $alias) {
526
					return true;
527
				}
528
			}
529
			if ($rule['destination']['address']) {
530
				if ($rule['destination']['address'] == $alias) {
531
					return true;
532
				}
533
			}
534
		}
535
	}
536
	/* loop through nat rules looking for alias in use */
537
	if (is_array($config['nat']['rule'])) {
538
		foreach ($config['nat']['rule'] as $rule) {
539
			if ($rule['target'] && $rule['target'] == $alias) {
540
				return true;
541
			}
542
			if ($rule['source']['address'] && $rule['source']['address'] == $alias) {
543
				return true;
544
			}
545
			if ($rule['destination']['address'] && $rule['destination']['address'] == $alias) {
546
				return true;
547
			}
548
		}
549
	}
550
	return false;
551
}
552

    
553
/****f* pfsense-utils/is_schedule_inuse
554
 * NAME
555
 *   checks to see if a schedule is currently in use by a rule
556
 * INPUTS
557
 *
558
 * RESULT
559
 *   true or false
560
 * NOTES
561
 *
562
 ******/
563
function is_schedule_inuse($schedule) {
564
	global $g, $config;
565

    
566
	if ($schedule == "") {
567
		return false;
568
	}
569
	/* loop through firewall rules looking for schedule in use */
570
	if (is_array($config['filter']['rule'])) {
571
		foreach ($config['filter']['rule'] as $rule) {
572
			if ($rule['sched'] == $schedule) {
573
				return true;
574
			}
575
		}
576
	}
577
	return false;
578
}
579

    
580
/****f* pfsense-utils/setup_polling
581
 * NAME
582
 *   sets up polling
583
 * INPUTS
584
 *
585
 * RESULT
586
 *   null
587
 * NOTES
588
 *
589
 ******/
590
function setup_polling() {
591
	global $g, $config;
592

    
593
	if (isset($config['system']['polling'])) {
594
		set_single_sysctl("kern.polling.idle_poll", "1");
595
	} else {
596
		set_single_sysctl("kern.polling.idle_poll", "0");
597
	}
598

    
599
	if ($config['system']['polling_each_burst']) {
600
		set_single_sysctl("kern.polling.each_burst", $config['system']['polling_each_burst']);
601
	}
602
	if ($config['system']['polling_burst_max']) {
603
		set_single_sysctl("kern.polling.burst_max", $config['system']['polling_burst_max']);
604
	}
605
	if ($config['system']['polling_user_frac']) {
606
		set_single_sysctl("kern.polling.user_frac", $config['system']['polling_user_frac']);
607
	}
608
}
609

    
610
/****f* pfsense-utils/setup_microcode
611
 * NAME
612
 *   enumerates all interfaces and calls enable_hardware_offloading which
613
 *   enables a NIC's supported hardware features.
614
 * INPUTS
615
 *
616
 * RESULT
617
 *   null
618
 * NOTES
619
 *   This function only supports the fxp driver's loadable microcode.
620
 ******/
621
function setup_microcode() {
622

    
623
	/* if list */
624
	$iflist = get_configured_interface_list(false, true);
625
	foreach ($iflist as $if => $ifdescr) {
626
		enable_hardware_offloading($if);
627
	}
628
	unset($iflist);
629
}
630

    
631
/****f* pfsense-utils/get_carp_status
632
 * NAME
633
 *   get_carp_status - Return whether CARP is enabled or disabled.
634
 * RESULT
635
 *   boolean	- true if CARP is enabled, false if otherwise.
636
 ******/
637
function get_carp_status() {
638
	/* grab the current status of carp */
639
	$status = get_single_sysctl('net.inet.carp.allow');
640
	return (intval($status) > 0);
641
}
642

    
643
/*
644
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
645

    
646
 */
647
function convert_ip_to_network_format($ip, $subnet) {
648
	$ipsplit = explode('.', $ip);
649
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
650
	return $string;
651
}
652

    
653
/*
654
 * get_carp_interface_status($carpid): returns the status of a carp uniqid
655
 */
656
function get_carp_interface_status($carpid) {
657

    
658
	$carpiface = get_configured_vip_interface($carpid);
659
	if ($carpiface == NULL)
660
		return "";
661
	$interface = get_real_interface($carpiface);
662
	if ($interface == NULL)
663
		return "";
664

    
665
	$vhid = $carp['vhid'];
666
	$carp_query = '';
667
	$_gb = exec("/sbin/ifconfig $interface | /usr/bin/grep carp: | /usr/bin/grep \"vhid $vhid\"", $carp_query);
668
	foreach ($carp_query as $int) {
669
		if (stripos($int, "MASTER"))
670
			return "MASTER";
671
		elseif (stripos($int, "BACKUP"))
672
			return "BACKUP";
673
		elseif (stripos($int, "INIT"))
674
			return "INIT";
675
	}
676

    
677
	return "";
678
}
679

    
680
/*
681
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
682
 */
683
function get_pfsync_interface_status($pfsyncinterface) {
684
	if (!does_interface_exist($pfsyncinterface)) {
685
		return;
686
	}
687

    
688
	return exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/awk '/pfsync:/ {print \$5}'");
689
}
690

    
691
/*
692
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
693
 */
694
function add_rule_to_anchor($anchor, $rule, $label) {
695
	mwexec("echo " . escapeshellarg($rule) . " | /sbin/pfctl -a " . escapeshellarg($anchor) . ":" . escapeshellarg($label) . " -f -");
696
}
697

    
698
/*
699
 * remove_text_from_file
700
 * remove $text from file $file
701
 */
702
function remove_text_from_file($file, $text) {
703
	if (!file_exists($file) && !is_writable($file)) {
704
		return;
705
	}
706
	$filecontents = file_get_contents($file);
707
	$text = str_replace($text, "", $filecontents);
708
	@file_put_contents($file, $text);
709
}
710

    
711
/*
712
 *   after_sync_bump_adv_skew(): create skew values by 1S
713
 */
714
function after_sync_bump_adv_skew() {
715
	global $config, $g;
716
	$processed_skew = 1;
717
	$a_vip = &$config['virtualip']['vip'];
718
	foreach ($a_vip as $vipent) {
719
		if ($vipent['advskew'] <> "") {
720
			$processed_skew = 1;
721
			$vipent['advskew'] = $vipent['advskew']+1;
722
		}
723
	}
724
	if ($processed_skew == 1) {
725
		write_config(gettext("After synch increase advertising skew"));
726
	}
727
}
728

    
729
/*
730
 * get_filename_from_url($url): converts a url to its filename.
731
 */
732
function get_filename_from_url($url) {
733
	return basename($url);
734
}
735

    
736
/*
737
 *   get_dir: return an array of $dir
738
 */
739
function get_dir($dir) {
740
	$dir_array = array();
741
	$d = dir($dir);
742
	if (!is_object($d)) {
743
		return array();
744
	}
745
	while (false !== ($entry = $d->read())) {
746
		array_push($dir_array, $entry);
747
	}
748
	$d->close();
749
	return $dir_array;
750
}
751

    
752
/****f* pfsense-utils/WakeOnLan
753
 * NAME
754
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
755
 * RESULT
756
 *   true/false - true if the operation was successful
757
 ******/
758
function WakeOnLan($addr, $mac) {
759
	$addr_byte = explode(':', $mac);
760
	$hw_addr = '';
761

    
762
	for ($a = 0; $a < 6; $a++) {
763
		$hw_addr .= chr(hexdec($addr_byte[$a]));
764
	}
765

    
766
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
767

    
768
	for ($a = 1; $a <= 16; $a++) {
769
		$msg .= $hw_addr;
770
	}
771

    
772
	// send it to the broadcast address using UDP
773
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
774
	if ($s == false) {
775
		log_error(gettext("Error creating socket!"));
776
		log_error(sprintf(gettext("Error code is '%1\$s' - %2\$s"), socket_last_error($s), socket_strerror(socket_last_error($s))));
777
	} else {
778
		// setting a broadcast option to socket:
779
		$opt_ret = socket_set_option($s, 1, 6, TRUE);
780
		if ($opt_ret < 0) {
781
			log_error(sprintf(gettext("setsockopt() failed, error: %s"), strerror($opt_ret)));
782
		}
783
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
784
		socket_close($s);
785
		log_error(sprintf(gettext('Magic Packet sent (%1$s) to (%2$s) MAC=%3$s'), $e, $addr, $mac));
786
		return true;
787
	}
788

    
789
	return false;
790
}
791

    
792
/*
793
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
794
 *					 Useful for finding paths and stripping file extensions.
795
 */
796
function reverse_strrchr($haystack, $needle) {
797
	if (!is_string($haystack)) {
798
		return;
799
	}
800
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1) : false;
801
}
802

    
803
/*
804
 *  backup_config_section($section): returns as an xml file string of
805
 *                                   the configuration section
806
 */
807
function backup_config_section($section_name) {
808
	global $config;
809
	$new_section = &$config[$section_name];
810
	/* generate configuration XML */
811
	$xmlconfig = dump_xml_config($new_section, $section_name);
812
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
813
	return $xmlconfig;
814
}
815

    
816
/*
817
 *  restore_config_section($section_name, new_contents): restore a configuration section,
818
 *                                                  and write the configuration out
819
 *                                                  to disk/cf.
820
 */
821
function restore_config_section($section_name, $new_contents) {
822
	global $config, $g;
823
	conf_mount_rw();
824
	$fout = fopen("{$g['tmp_path']}/tmpxml", "w");
825
	fwrite($fout, $new_contents);
826
	fclose($fout);
827

    
828
	$xml = parse_xml_config($g['tmp_path'] . "/tmpxml", null);
829
	if ($xml['pfsense']) {
830
		$xml = $xml['pfsense'];
831
	}
832
	else if ($xml['m0n0wall']) {
833
		$xml = $xml['m0n0wall'];
834
	}
835
	if ($xml[$section_name]) {
836
		$section_xml = $xml[$section_name];
837
	} else {
838
		$section_xml = -1;
839
	}
840

    
841
	@unlink($g['tmp_path'] . "/tmpxml");
842
	if ($section_xml === -1) {
843
		return false;
844
	}
845
	$config[$section_name] = &$section_xml;
846
	if (file_exists("{$g['tmp_path']}/config.cache")) {
847
		unlink("{$g['tmp_path']}/config.cache");
848
	}
849
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
850
	disable_security_checks();
851
	conf_mount_ro();
852
	return true;
853
}
854

    
855
/*
856
 *  merge_config_section($section_name, new_contents):   restore a configuration section,
857
 *                                                  and write the configuration out
858
 *                                                  to disk/cf.  But preserve the prior
859
 * 													structure if needed
860
 */
861
function merge_config_section($section_name, $new_contents) {
862
	global $config;
863
	conf_mount_rw();
864
	$fname = get_tmp_filename();
865
	$fout = fopen($fname, "w");
866
	fwrite($fout, $new_contents);
867
	fclose($fout);
868
	$section_xml = parse_xml_config($fname, $section_name);
869
	$config[$section_name] = $section_xml;
870
	unlink($fname);
871
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
872
	disable_security_checks();
873
	conf_mount_ro();
874
	return;
875
}
876

    
877
/*
878
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
879
 */
880
if (!function_exists('php_check_syntax')) {
881
	global $g;
882
	function php_check_syntax($code_to_check, &$errormessage) {
883
		return false;
884
		$fout = fopen("{$g['tmp_path']}/codetocheck.php", "w");
885
		$code = $_POST['content'];
886
		$code = str_replace("<?php", "", $code);
887
		$code = str_replace("?>", "", $code);
888
		fwrite($fout, "<?php\n\n");
889
		fwrite($fout, $code_to_check);
890
		fwrite($fout, "\n\n?>\n");
891
		fclose($fout);
892
		$command = "/usr/local/bin/php-cgi -l {$g['tmp_path']}/codetocheck.php";
893
		$output = exec_command($command);
894
		if (stristr($output, "Errors parsing") == false) {
895
			echo "false\n";
896
			$errormessage = '';
897
			return(false);
898
		} else {
899
			$errormessage = $output;
900
			return(true);
901
		}
902
	}
903
}
904

    
905
/*
906
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
907
 */
908
if (!function_exists('php_check_syntax')) {
909
	function php_check_syntax($code_to_check, &$errormessage) {
910
		return false;
911
		$command = "/usr/local/bin/php-cgi -l " . escapeshellarg($code_to_check);
912
		$output = exec_command($command);
913
		if (stristr($output, "Errors parsing") == false) {
914
			echo "false\n";
915
			$errormessage = '';
916
			return(false);
917
		} else {
918
			$errormessage = $output;
919
			return(true);
920
		}
921
	}
922
}
923

    
924
/*
925
 * rmdir_recursive($path, $follow_links=false)
926
 * Recursively remove a directory tree (rm -rf path)
927
 * This is for directories _only_
928
 */
929
function rmdir_recursive($path, $follow_links=false) {
930
	$to_do = glob($path);
931
	if (!is_array($to_do)) {
932
		$to_do = array($to_do);
933
	}
934
	foreach ($to_do as $workingdir) { // Handle wildcards by foreaching.
935
		if (file_exists($workingdir)) {
936
			if (is_dir($workingdir)) {
937
				$dir = opendir($workingdir);
938
				while ($entry = readdir($dir)) {
939
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry"))) {
940
						unlink("$workingdir/$entry");
941
					} elseif (is_dir("$workingdir/$entry") && $entry != '.' && $entry != '..') {
942
						rmdir_recursive("$workingdir/$entry");
943
					}
944
				}
945
				closedir($dir);
946
				rmdir($workingdir);
947
			} elseif (is_file($workingdir)) {
948
				unlink($workingdir);
949
			}
950
		}
951
	}
952
	return;
953
}
954

    
955
/*
956
 * host_firmware_version(): Return the versions used in this install
957
 */
958
function host_firmware_version($tocheck = "") {
959
	global $g, $config;
960

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

    
963
	return array(
964
		"firmware" => array("version" => $g['product_version']),
965
		"kernel"   => array("version" => $os_version),
966
		"base"     => array("version" => $os_version),
967
		"platform" => trim(file_get_contents('/etc/platform', " \n")),
968
		"config_version" => $config['version']
969
	);
970
}
971

    
972
function get_disk_info() {
973
	$diskout = "";
974
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
975
	return explode(' ', $diskout[0]);
976
}
977

    
978
/****f* pfsense-utils/strncpy
979
 * NAME
980
 *   strncpy - copy strings
981
 * INPUTS
982
 *   &$dst, $src, $length
983
 * RESULT
984
 *   none
985
 ******/
986
function strncpy(&$dst, $src, $length) {
987
	if (strlen($src) > $length) {
988
		$dst = substr($src, 0, $length);
989
	} else {
990
		$dst = $src;
991
	}
992
}
993

    
994
/****f* pfsense-utils/reload_interfaces_sync
995
 * NAME
996
 *   reload_interfaces - reload all interfaces
997
 * INPUTS
998
 *   none
999
 * RESULT
1000
 *   none
1001
 ******/
1002
function reload_interfaces_sync() {
1003
	global $config, $g;
1004

    
1005
	if ($g['debug']) {
1006
		log_error(gettext("reload_interfaces_sync() is starting."));
1007
	}
1008

    
1009
	/* parse config.xml again */
1010
	$config = parse_config(true);
1011

    
1012
	/* enable routing */
1013
	system_routing_enable();
1014
	if ($g['debug']) {
1015
		log_error(gettext("Enabling system routing"));
1016
	}
1017

    
1018
	if ($g['debug']) {
1019
		log_error(gettext("Cleaning up Interfaces"));
1020
	}
1021

    
1022
	/* set up interfaces */
1023
	interfaces_configure();
1024
}
1025

    
1026
/****f* pfsense-utils/reload_all
1027
 * NAME
1028
 *   reload_all - triggers a reload of all settings
1029
 *   * INPUTS
1030
 *   none
1031
 * RESULT
1032
 *   none
1033
 ******/
1034
function reload_all() {
1035
	send_event("service reload all");
1036
}
1037

    
1038
/****f* pfsense-utils/reload_interfaces
1039
 * NAME
1040
 *   reload_interfaces - triggers a reload of all interfaces
1041
 * INPUTS
1042
 *   none
1043
 * RESULT
1044
 *   none
1045
 ******/
1046
function reload_interfaces() {
1047
	send_event("interface all reload");
1048
}
1049

    
1050
/****f* pfsense-utils/reload_all_sync
1051
 * NAME
1052
 *   reload_all - reload all settings
1053
 *   * INPUTS
1054
 *   none
1055
 * RESULT
1056
 *   none
1057
 ******/
1058
function reload_all_sync() {
1059
	global $config, $g;
1060

    
1061
	/* parse config.xml again */
1062
	$config = parse_config(true);
1063

    
1064
	/* set up our timezone */
1065
	system_timezone_configure();
1066

    
1067
	/* set up our hostname */
1068
	system_hostname_configure();
1069

    
1070
	/* make hosts file */
1071
	system_hosts_generate();
1072

    
1073
	/* generate resolv.conf */
1074
	system_resolvconf_generate();
1075

    
1076
	/* enable routing */
1077
	system_routing_enable();
1078

    
1079
	/* set up interfaces */
1080
	interfaces_configure();
1081

    
1082
	/* start dyndns service */
1083
	services_dyndns_configure();
1084

    
1085
	/* configure cron service */
1086
	configure_cron();
1087

    
1088
	/* start the NTP client */
1089
	system_ntp_configure();
1090

    
1091
	/* sync pw database */
1092
	conf_mount_rw();
1093
	unlink_if_exists("/etc/spwd.db.tmp");
1094
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1095
	conf_mount_ro();
1096

    
1097
	/* restart sshd */
1098
	send_event("service restart sshd");
1099

    
1100
	/* restart webConfigurator if needed */
1101
	send_event("service restart webgui");
1102
}
1103

    
1104
function setup_serial_port($when = "save", $path = "") {
1105
	global $g, $config;
1106
	conf_mount_rw();
1107
	$ttys_file = "{$path}/etc/ttys";
1108
	$boot_config_file = "{$path}/boot.config";
1109
	$loader_conf_file = "{$path}/boot/loader.conf";
1110
	/* serial console - write out /boot.config */
1111
	if (file_exists($boot_config_file)) {
1112
		$boot_config = file_get_contents($boot_config_file);
1113
	} else {
1114
		$boot_config = "";
1115
	}
1116

    
1117
	$serialspeed = (is_numeric($config['system']['serialspeed'])) ? $config['system']['serialspeed'] : "115200";
1118
	if ($g['platform'] != "cdrom") {
1119
		$serial_only = false;
1120

    
1121
		if (($g['platform'] == "nanobsd") && isset($g['enableserial_force'])) {
1122
			$serial_only = true;
1123
		} else {
1124
			$specific_platform = system_identify_specific_platform();
1125
			if ($specific_platform['name'] == 'RCC-VE' ||
1126
			    $specific_platform['name'] == 'RCC' ||
1127
			    $specific_platform['name'] == 'RCC-DFF') {
1128
				$serial_only = true;
1129
			}
1130
		}
1131

    
1132
		$boot_config_split = explode("\n", $boot_config);
1133
		$fd = fopen($boot_config_file, "w");
1134
		if ($fd) {
1135
			foreach ($boot_config_split as $bcs) {
1136
				if (stristr($bcs, "-D") || stristr($bcs, "-h")) {
1137
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1138
				} else {
1139
					if ($bcs <> "") {
1140
						fwrite($fd, "{$bcs}\n");
1141
					}
1142
				}
1143
			}
1144
			if ($serial_only === true) {
1145
				fwrite($fd, "-S{$serialspeed} -h");
1146
			} else if (is_serial_enabled()) {
1147
				fwrite($fd, "-S{$serialspeed} -D");
1148
			}
1149
			fclose($fd);
1150
		}
1151

    
1152
		/* serial console - write out /boot/loader.conf */
1153
		if ($when == "upgrade") {
1154
			system("echo \"Reading {$loader_conf_file}...\" >> /conf/upgrade_log.txt");
1155
		}
1156
		$boot_config = file_get_contents($loader_conf_file);
1157
		$boot_config_split = explode("\n", $boot_config);
1158
		if (count($boot_config_split) > 0) {
1159
			$new_boot_config = array();
1160
			// Loop through and only add lines that are not empty, and which
1161
			//  do not contain a console directive.
1162
			foreach ($boot_config_split as $bcs) {
1163
				if (!empty($bcs) &&
1164
				    (stripos($bcs, "console") === false) &&
1165
				    (stripos($bcs, "boot_multicons") === false) &&
1166
				    (stripos($bcs, "boot_serial") === false) &&
1167
				    (stripos($bcs, "hw.usb.no_pf") === false) &&
1168
				    (stripos($bcs, "hint.uart.0.flags") === false) &&
1169
				    (stripos($bcs, "hint.uart.1.flags") === false)) {
1170
					$new_boot_config[] = $bcs;
1171
				}
1172
			}
1173

    
1174
			if ($serial_only === true) {
1175
				$new_boot_config[] = 'boot_serial="YES"';
1176
				$new_boot_config[] = 'console="comconsole"';
1177
			} else if (is_serial_enabled()) {
1178
				$new_boot_config[] = 'boot_multicons="YES"';
1179
				$new_boot_config[] = 'boot_serial="YES"';
1180
				$primaryconsole = isset($g['primaryconsole_force']) ? $g['primaryconsole_force'] : $config['system']['primaryconsole'];
1181
				switch ($primaryconsole) {
1182
					case "video":
1183
						$new_boot_config[] = 'console="vidconsole,comconsole"';
1184
						break;
1185
					case "serial":
1186
					default:
1187
						$new_boot_config[] = 'console="comconsole,vidconsole"';
1188
				}
1189
			}
1190
			$new_boot_config[] = 'comconsole_speed="' . $serialspeed . '"';
1191

    
1192
			$specplatform = system_identify_specific_platform();
1193
			if ($specplatform['name'] == 'RCC-VE' ||
1194
			    $specplatform['name'] == 'RCC' ||
1195
			    $specplatform['name'] == 'RCC-DFF') {
1196
				$new_boot_config[] = 'comconsole_port="0x2F8"';
1197
				$new_boot_config[] = 'hint.uart.0.flags="0x00"';
1198
				$new_boot_config[] = 'hint.uart.1.flags="0x10"';
1199
			}
1200
			$new_boot_config[] = 'hw.usb.no_pf="1"';
1201

    
1202
			file_put_contents($loader_conf_file, implode("\n", $new_boot_config) . "\n");
1203
		}
1204
	}
1205
	$ttys = file_get_contents($ttys_file);
1206
	$ttys_split = explode("\n", $ttys);
1207
	$fd = fopen($ttys_file, "w");
1208

    
1209
	$on_off = (is_serial_enabled() ? 'onifconsole' : 'off');
1210

    
1211
	if (isset($config['system']['disableconsolemenu'])) {
1212
		$console_type = 'Pc';
1213
		$serial_type = 'std.' . $serialspeed;
1214
	} else {
1215
		$console_type = 'al.Pc';
1216
		$serial_type = 'al.' . $serialspeed;
1217
	}
1218
	foreach ($ttys_split as $tty) {
1219
		if (stristr($tty, "ttyv0")) {
1220
			fwrite($fd, "ttyv0	\"/usr/libexec/getty {$console_type}\"	cons25	on	secure\n");
1221
		} else if (stristr($tty, "ttyu")) {
1222
			$ttyn = substr($tty, 0, 5);
1223
			fwrite($fd, "{$ttyn}	\"/usr/libexec/getty {$serial_type}\"	cons25	{$on_off}	secure\n");
1224
		} else {
1225
			fwrite($fd, $tty . "\n");
1226
		}
1227
	}
1228
	unset($on_off, $console_type, $serial_type);
1229
	fclose($fd);
1230
	if ($when != "upgrade") {
1231
		reload_ttys();
1232
	}
1233

    
1234
	conf_mount_ro();
1235
	return;
1236
}
1237

    
1238
function is_serial_enabled() {
1239
	global $g, $config;
1240

    
1241
	if (!isset($g['enableserial_force']) &&
1242
	    !isset($config['system']['enableserial']) &&
1243
	    ($g['platform'] == $g['product_name'] || $g['platform'] == "cdrom")) {
1244
		return false;
1245
	}
1246

    
1247
	return true;
1248
}
1249

    
1250
function reload_ttys() {
1251
	// Send a HUP signal to init will make it reload /etc/ttys
1252
	posix_kill(1, SIGHUP);
1253
}
1254

    
1255
function print_value_list($list, $count = 10, $separator = ",") {
1256
	$list = implode($separator, array_slice($list, 0, $count));
1257
	if (count($list) < $count) {
1258
		$list .= ".";
1259
	} else {
1260
		$list .= "...";
1261
	}
1262
	return $list;
1263
}
1264

    
1265
/* DHCP enabled on any interfaces? */
1266
function is_dhcp_server_enabled() {
1267
	global $config;
1268

    
1269
	if (!is_array($config['dhcpd'])) {
1270
		return false;
1271
	}
1272

    
1273
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1274
		if (isset($dhcpifconf['enable']) && !empty($config['interfaces'][$dhcpif])) {
1275
			return true;
1276
		}
1277
	}
1278

    
1279
	return false;
1280
}
1281

    
1282
/* DHCP enabled on any interfaces? */
1283
function is_dhcpv6_server_enabled() {
1284
	global $config;
1285

    
1286
	if (is_array($config['interfaces'])) {
1287
		foreach ($config['interfaces'] as $ifcfg) {
1288
			if (isset($ifcfg['enable']) && !empty($ifcfg['track6-interface'])) {
1289
				return true;
1290
			}
1291
		}
1292
	}
1293

    
1294
	if (!is_array($config['dhcpdv6'])) {
1295
		return false;
1296
	}
1297

    
1298
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
1299
		if (isset($dhcpv6ifconf['enable']) && !empty($config['interfaces'][$dhcpv6if])) {
1300
			return true;
1301
		}
1302
	}
1303

    
1304
	return false;
1305
}
1306

    
1307
/* radvd enabled on any interfaces? */
1308
function is_radvd_enabled() {
1309
	global $config;
1310

    
1311
	if (!is_array($config['dhcpdv6'])) {
1312
		$config['dhcpdv6'] = array();
1313
	}
1314

    
1315
	$dhcpdv6cfg = $config['dhcpdv6'];
1316
	$Iflist = get_configured_interface_list();
1317

    
1318
	/* handle manually configured DHCP6 server settings first */
1319
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1320
		if (!isset($config['interfaces'][$dhcpv6if]['enable'])) {
1321
			continue;
1322
		}
1323

    
1324
		if (!isset($dhcpv6ifconf['ramode'])) {
1325
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
1326
		}
1327

    
1328
		if ($dhcpv6ifconf['ramode'] == "disabled") {
1329
			continue;
1330
		}
1331

    
1332
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1333
		if (!is_ipaddrv6($ifcfgipv6)) {
1334
			continue;
1335
		}
1336

    
1337
		return true;
1338
	}
1339

    
1340
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
1341
	foreach ($Iflist as $if => $ifdescr) {
1342
		if (!isset($config['interfaces'][$if]['track6-interface'])) {
1343
			continue;
1344
		}
1345
		if (!isset($config['interfaces'][$if]['enable'])) {
1346
			continue;
1347
		}
1348

    
1349
		$ifcfgipv6 = get_interface_ipv6($if);
1350
		if (!is_ipaddrv6($ifcfgipv6)) {
1351
			continue;
1352
		}
1353

    
1354
		$ifcfgsnv6 = get_interface_subnetv6($if);
1355
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1356

    
1357
		if (!is_ipaddrv6($subnetv6)) {
1358
			continue;
1359
		}
1360

    
1361
		return true;
1362
	}
1363

    
1364
	return false;
1365
}
1366

    
1367
/* Any PPPoE servers enabled? */
1368
function is_pppoe_server_enabled() {
1369
	global $config;
1370

    
1371
	$pppoeenable = false;
1372

    
1373
	if (!is_array($config['pppoes']) || !is_array($config['pppoes']['pppoe'])) {
1374
		return false;
1375
	}
1376

    
1377
	foreach ($config['pppoes']['pppoe'] as $pppoes) {
1378
		if ($pppoes['mode'] == 'server') {
1379
			$pppoeenable = true;
1380
		}
1381
	}
1382

    
1383
	return $pppoeenable;
1384
}
1385

    
1386
/* Optional arg forces hh:mm:ss without days */
1387
function convert_seconds_to_dhms($sec, $showhoursonly = false) {
1388
	if (!is_numericint($sec)) {
1389
		return '-';
1390
	}
1391
	// FIXME: When we move to PHP 7 we can use "intdiv($sec % X, Y)" etc
1392
	list($d, $h, $m, $s) = array(	(int)($showhoursonly ? 0 : $sec/86400),
1393
					(int)(($showhoursonly ? $sec : $sec % 86400)/3600),
1394
					(int)(($sec % 3600)/60),
1395
					$sec % 60
1396
				);
1397
	return ($d > 0 ? $d . 'd ' : '') . sprintf('%02d:%02d:%02d', $h, $m, $s);
1398
}
1399

    
1400
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1401

    
1402
function get_ppp_uptime($port) {
1403
	if (file_exists("/conf/{$port}.log")) {
1404
		$saved_time = file_get_contents("/conf/{$port}.log");
1405
		$uptime_data = explode("\n", $saved_time);
1406
		$sec = 0;
1407
		foreach ($uptime_data as $upt) {
1408
			$sec += substr($upt, 1 + strpos($upt, " "));
1409
		}
1410
		return convert_seconds_to_dhms($sec);
1411
	} else {
1412
		$total_time = gettext("No history data found!");
1413
		return $total_time;
1414
	}
1415
}
1416

    
1417
//returns interface information
1418
function get_interface_info($ifdescr) {
1419
	global $config, $g;
1420

    
1421
	$ifinfo = array();
1422
	if (empty($config['interfaces'][$ifdescr])) {
1423
		return;
1424
	}
1425
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
1426
	$ifinfo['if'] = get_real_interface($ifdescr);
1427

    
1428
	$chkif = $ifinfo['if'];
1429
	$ifinfotmp = pfSense_get_interface_addresses($chkif);
1430
	$ifinfo['status'] = $ifinfotmp['status'];
1431
	if (empty($ifinfo['status'])) {
1432
		$ifinfo['status'] = "down";
1433
	}
1434
	$ifinfo['macaddr'] = $ifinfotmp['macaddr'];
1435
	$ifinfo['mtu'] = $ifinfotmp['mtu'];
1436
	$ifinfo['ipaddr'] = $ifinfotmp['ipaddr'];
1437
	$ifinfo['subnet'] = $ifinfotmp['subnet'];
1438
	$ifinfo['linklocal'] = get_interface_linklocal($ifdescr);
1439
	$ifinfo['ipaddrv6'] = get_interface_ipv6($ifdescr);
1440
	$ifinfo['subnetv6'] = get_interface_subnetv6($ifdescr);
1441
	if (isset($ifinfotmp['link0'])) {
1442
		$link0 = "down";
1443
	}
1444
	$ifinfotmp = pfSense_get_interface_stats($chkif);
1445
	// $ifinfo['inpkts'] = $ifinfotmp['inpkts'];
1446
	// $ifinfo['outpkts'] = $ifinfotmp['outpkts'];
1447
	$ifinfo['inerrs'] = $ifinfotmp['inerrs'];
1448
	$ifinfo['outerrs'] = $ifinfotmp['outerrs'];
1449
	$ifinfo['collisions'] = $ifinfotmp['collisions'];
1450

    
1451
	/* Use pfctl for non wrapping 64 bit counters */
1452
	/* Pass */
1453
	exec("/sbin/pfctl -vvsI -i {$chkif}", $pfctlstats);
1454
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1455
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1456
	$pf_in6_pass = preg_split("/ +/ ", $pfctlstats[7]);
1457
	$pf_out6_pass = preg_split("/ +/", $pfctlstats[9]);
1458
	$in4_pass = $pf_in4_pass[5];
1459
	$out4_pass = $pf_out4_pass[5];
1460
	$in4_pass_packets = $pf_in4_pass[3];
1461
	$out4_pass_packets = $pf_out4_pass[3];
1462
	$in6_pass = $pf_in6_pass[5];
1463
	$out6_pass = $pf_out6_pass[5];
1464
	$in6_pass_packets = $pf_in6_pass[3];
1465
	$out6_pass_packets = $pf_out6_pass[3];
1466
	$ifinfo['inbytespass'] = $in4_pass + $in6_pass;
1467
	$ifinfo['outbytespass'] = $out4_pass + $out6_pass;
1468
	$ifinfo['inpktspass'] = $in4_pass_packets + $in6_pass_packets;
1469
	$ifinfo['outpktspass'] = $out4_pass_packets + $out6_pass_packets;
1470

    
1471
	/* Block */
1472
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1473
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1474
	$pf_in6_block = preg_split("/ +/", $pfctlstats[8]);
1475
	$pf_out6_block = preg_split("/ +/", $pfctlstats[10]);
1476
	$in4_block = $pf_in4_block[5];
1477
	$out4_block = $pf_out4_block[5];
1478
	$in4_block_packets = $pf_in4_block[3];
1479
	$out4_block_packets = $pf_out4_block[3];
1480
	$in6_block = $pf_in6_block[5];
1481
	$out6_block = $pf_out6_block[5];
1482
	$in6_block_packets = $pf_in6_block[3];
1483
	$out6_block_packets = $pf_out6_block[3];
1484
	$ifinfo['inbytesblock'] = $in4_block + $in6_block;
1485
	$ifinfo['outbytesblock'] = $out4_block + $out6_block;
1486
	$ifinfo['inpktsblock'] = $in4_block_packets + $in6_block_packets;
1487
	$ifinfo['outpktsblock'] = $out4_block_packets + $out6_block_packets;
1488

    
1489
	$ifinfo['inbytes'] = $in4_pass + $in6_pass;
1490
	$ifinfo['outbytes'] = $out4_pass + $out6_pass;
1491
	$ifinfo['inpkts'] = $in4_pass_packets + $in6_pass_packets;
1492
	$ifinfo['outpkts'] = $out4_pass_packets + $out6_pass_packets;
1493

    
1494
	$ifconfiginfo = "";
1495
	$link_type = $config['interfaces'][$ifdescr]['ipaddr'];
1496
	switch ($link_type) {
1497
		/* DHCP? -> see if dhclient is up */
1498
		case "dhcp":
1499
			/* see if dhclient is up */
1500
			if (find_dhclient_process($ifinfo['if']) != 0) {
1501
				$ifinfo['dhcplink'] = "up";
1502
			} else {
1503
				$ifinfo['dhcplink'] = "down";
1504
			}
1505

    
1506
			break;
1507
		/* PPPoE/PPTP/L2TP interface? -> get status from virtual interface */
1508
		case "pppoe":
1509
		case "pptp":
1510
		case "l2tp":
1511
			if ($ifinfo['status'] == "up" && !isset($link0)) {
1512
				/* get PPPoE link status for dial on demand */
1513
				$ifinfo["{$link_type}link"] = "up";
1514
			} else {
1515
				$ifinfo["{$link_type}link"] = "down";
1516
			}
1517

    
1518
			break;
1519
		/* PPP interface? -> get uptime for this session and cumulative uptime from the persistent log file in conf */
1520
		case "ppp":
1521
			if ($ifinfo['status'] == "up") {
1522
				$ifinfo['ppplink'] = "up";
1523
			} else {
1524
				$ifinfo['ppplink'] = "down" ;
1525
			}
1526

    
1527
			if (empty($ifinfo['status'])) {
1528
				$ifinfo['status'] = "down";
1529
			}
1530

    
1531
			if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1532
				foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1533
					if ($config['interfaces'][$ifdescr]['if'] == $ppp['if']) {
1534
						break;
1535
					}
1536
				}
1537
			}
1538
			$dev = $ppp['ports'];
1539
			if ($config['interfaces'][$ifdescr]['if'] != $ppp['if'] || empty($dev)) {
1540
				break;
1541
			}
1542
			if (!file_exists($dev)) {
1543
				$ifinfo['nodevice'] = 1;
1544
				$ifinfo['pppinfo'] = $dev . " " . gettext("device not present! Is the modem attached to the system?");
1545
			}
1546

    
1547
			$usbmodemoutput = array();
1548
			exec("/usr/sbin/usbconfig", $usbmodemoutput);
1549
			$mondev = "{$g['tmp_path']}/3gstats.{$ifdescr}";
1550
			if (file_exists($mondev)) {
1551
				$cellstats = file($mondev);
1552
				/* skip header */
1553
				$a_cellstats = explode(",", $cellstats[1]);
1554
				if (preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1555
					$ifinfo['cell_rssi'] = huawei_rssi_to_string($a_cellstats[1]);
1556
					$ifinfo['cell_mode'] = huawei_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1557
					$ifinfo['cell_simstate'] = huawei_simstate_to_string($a_cellstats[10]);
1558
					$ifinfo['cell_service'] = huawei_service_to_string(trim($a_cellstats[11]));
1559
				}
1560
				if (preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1561
					$ifinfo['cell_rssi'] = zte_rssi_to_string($a_cellstats[1]);
1562
					$ifinfo['cell_mode'] = zte_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1563
					$ifinfo['cell_simstate'] = zte_simstate_to_string($a_cellstats[10]);
1564
					$ifinfo['cell_service'] = zte_service_to_string(trim($a_cellstats[11]));
1565
				}
1566
				$ifinfo['cell_upstream'] = $a_cellstats[4];
1567
				$ifinfo['cell_downstream'] = trim($a_cellstats[5]);
1568
				$ifinfo['cell_sent'] = $a_cellstats[6];
1569
				$ifinfo['cell_received'] = trim($a_cellstats[7]);
1570
				$ifinfo['cell_bwupstream'] = $a_cellstats[8];
1571
				$ifinfo['cell_bwdownstream'] = trim($a_cellstats[9]);
1572
			}
1573
			// Calculate cumulative uptime for PPP link. Useful for connections that have per minute/hour contracts so you don't go over!
1574
			if (isset($ppp['uptime'])) {
1575
				$ifinfo['ppp_uptime_accumulated'] = "(".get_ppp_uptime($ifinfo['if']).")";
1576
			}
1577
			break;
1578
		default:
1579
			break;
1580
	}
1581

    
1582
	if (file_exists("{$g['varrun_path']}/{$link_type}_{$ifdescr}.pid")) {
1583
		$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1584
		$ifinfo['ppp_uptime'] = convert_seconds_to_dhms($sec);
1585
	}
1586

    
1587
	if ($ifinfo['status'] == "up") {
1588
		/* try to determine media with ifconfig */
1589
		unset($ifconfiginfo);
1590
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1591
		$wifconfiginfo = array();
1592
		if (is_interface_wireless($ifdescr)) {
1593
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1594
			array_shift($wifconfiginfo);
1595
		}
1596
		$matches = "";
1597
		foreach ($ifconfiginfo as $ici) {
1598

    
1599
			/* don't list media/speed for wireless cards, as it always
1600
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1601
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1602
				$ifinfo['media'] = $matches[1];
1603
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1604
				$ifinfo['media'] = $matches[1];
1605
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1606
				$ifinfo['media'] = $matches[1];
1607
			}
1608

    
1609
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
1610
				if ($matches[1] != "active") {
1611
					$ifinfo['status'] = $matches[1];
1612
				}
1613
				if ($ifinfo['status'] == gettext("running")) {
1614
					$ifinfo['status'] = gettext("up");
1615
				}
1616
			}
1617
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
1618
				$ifinfo['channel'] = $matches[1];
1619
			}
1620
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
1621
				if ($matches[1][0] == '"') {
1622
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
1623
				}
1624
				else {
1625
					$ifinfo['ssid'] = $matches[1];
1626
				}
1627
			}
1628
			if (preg_match("/laggproto (.*)$/", $ici, $matches)) {
1629
				$ifinfo['laggproto'] = $matches[1];
1630
			}
1631
			if (preg_match("/laggport: (.*)$/", $ici, $matches)) {
1632
				$ifinfo['laggport'][] = $matches[1];
1633
			}
1634
		}
1635
		foreach ($wifconfiginfo as $ici) {
1636
			$elements = preg_split("/[ ]+/i", $ici);
1637
			if ($elements[0] != "") {
1638
				$ifinfo['bssid'] = $elements[0];
1639
			}
1640
			if ($elements[3] != "") {
1641
				$ifinfo['rate'] = $elements[3];
1642
			}
1643
			if ($elements[4] != "") {
1644
				$ifinfo['rssi'] = $elements[4];
1645
			}
1646
		}
1647
		/* lookup the gateway */
1648
		if (interface_has_gateway($ifdescr)) {
1649
			$ifinfo['gateway'] = get_interface_gateway($ifdescr);
1650
			$ifinfo['gatewayv6'] = get_interface_gateway_v6($ifdescr);
1651
		}
1652
	}
1653

    
1654
	$bridge = "";
1655
	$bridge = link_interface_to_bridge($ifdescr);
1656
	if ($bridge) {
1657
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1658
		if (stristr($bridge_text, "blocking") <> false) {
1659
			$ifinfo['bridge'] = "<b><font color='red'>" . gettext("blocking") . "</font></b> - " . gettext("check for ethernet loops");
1660
			$ifinfo['bridgeint'] = $bridge;
1661
		} else if (stristr($bridge_text, "learning") <> false) {
1662
			$ifinfo['bridge'] = gettext("learning");
1663
			$ifinfo['bridgeint'] = $bridge;
1664
		} else if (stristr($bridge_text, "forwarding") <> false) {
1665
			$ifinfo['bridge'] = gettext("forwarding");
1666
			$ifinfo['bridgeint'] = $bridge;
1667
		}
1668
	}
1669

    
1670
	return $ifinfo;
1671
}
1672

    
1673
//returns cpu speed of processor. Good for determining capabilities of machine
1674
function get_cpu_speed() {
1675
	return get_single_sysctl("hw.clockrate");
1676
}
1677

    
1678
function get_uptime_sec() {
1679
	$boottime = "";
1680
	$matches = "";
1681
	$boottime = get_single_sysctl("kern.boottime");
1682
	preg_match("/sec = (\d+)/", $boottime, $matches);
1683
	$boottime = $matches[1];
1684
	if (intval($boottime) == 0) {
1685
		return 0;
1686
	}
1687

    
1688
	$uptime = time() - $boottime;
1689
	return $uptime;
1690
}
1691

    
1692
function add_hostname_to_watch($hostname) {
1693
	if (!is_dir("/var/db/dnscache")) {
1694
		mkdir("/var/db/dnscache");
1695
	}
1696
	$result = array();
1697
	if ((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1698
		$domrecords = array();
1699
		$domips = array();
1700
		exec("/usr/bin/host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1701
		if ($rethost == 0) {
1702
			foreach ($domrecords as $domr) {
1703
				$doml = explode(" ", $domr);
1704
				$domip = $doml[3];
1705
				/* fill array with domain ip addresses */
1706
				if (is_ipaddr($domip)) {
1707
					$domips[] = $domip;
1708
				}
1709
			}
1710
		}
1711
		sort($domips);
1712
		$contents = "";
1713
		if (!empty($domips)) {
1714
			foreach ($domips as $ip) {
1715
				$contents .= "$ip\n";
1716
			}
1717
		}
1718
		file_put_contents("/var/db/dnscache/$hostname", $contents);
1719
		/* Remove empty elements */
1720
		$result = array_filter(explode("\n", $contents), 'strlen');
1721
	}
1722
	return $result;
1723
}
1724

    
1725
function is_fqdn($fqdn) {
1726
	$hostname = false;
1727
	if (preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1728
		$hostname = true;
1729
	}
1730
	if (preg_match("/\.\./", $fqdn)) {
1731
		$hostname = false;
1732
	}
1733
	if (preg_match("/^\./i", $fqdn)) {
1734
		$hostname = false;
1735
	}
1736
	if (preg_match("/\//i", $fqdn)) {
1737
		$hostname = false;
1738
	}
1739
	return($hostname);
1740
}
1741

    
1742
function pfsense_default_state_size() {
1743
	/* get system memory amount */
1744
	$memory = get_memory();
1745
	$physmem = $memory[0];
1746
	/* Be cautious and only allocate 10% of system memory to the state table */
1747
	$max_states = (int) ($physmem/10)*1000;
1748
	return $max_states;
1749
}
1750

    
1751
function pfsense_default_tables_size() {
1752
	$current = `pfctl -sm | grep ^tables | awk '{print $4};'`;
1753
	return $current;
1754
}
1755

    
1756
function pfsense_default_table_entries_size() {
1757
	$current = `pfctl -sm | grep table-entries | awk '{print $4};'`;
1758
	return (trim($current));
1759
}
1760

    
1761
/* Compare the current hostname DNS to the DNS cache we made
1762
 * if it has changed we return the old records
1763
 * if no change we return false */
1764
function compare_hostname_to_dnscache($hostname) {
1765
	if (!is_dir("/var/db/dnscache")) {
1766
		mkdir("/var/db/dnscache");
1767
	}
1768
	$hostname = trim($hostname);
1769
	if (is_readable("/var/db/dnscache/{$hostname}")) {
1770
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
1771
	} else {
1772
		$oldcontents = "";
1773
	}
1774
	if ((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1775
		$domrecords = array();
1776
		$domips = array();
1777
		exec("/usr/bin/host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1778
		if ($rethost == 0) {
1779
			foreach ($domrecords as $domr) {
1780
				$doml = explode(" ", $domr);
1781
				$domip = $doml[3];
1782
				/* fill array with domain ip addresses */
1783
				if (is_ipaddr($domip)) {
1784
					$domips[] = $domip;
1785
				}
1786
			}
1787
		}
1788
		sort($domips);
1789
		$contents = "";
1790
		if (!empty($domips)) {
1791
			foreach ($domips as $ip) {
1792
				$contents .= "$ip\n";
1793
			}
1794
		}
1795
	}
1796

    
1797
	if (trim($oldcontents) != trim($contents)) {
1798
		if ($g['debug']) {
1799
			log_error(sprintf(gettext('DNSCACHE: Found old IP %1$s and new IP %2$s'), $oldcontents, $contents));
1800
		}
1801
		return ($oldcontents);
1802
	} else {
1803
		return false;
1804
	}
1805
}
1806

    
1807
/*
1808
 * load_crypto() - Load crypto modules if enabled in config.
1809
 */
1810
function load_crypto() {
1811
	global $config, $g;
1812
	$crypto_modules = array('glxsb', 'aesni');
1813

    
1814
	if (!in_array($config['system']['crypto_hardware'], $crypto_modules)) {
1815
		return false;
1816
	}
1817

    
1818
	if (!empty($config['system']['crypto_hardware']) && !is_module_loaded($config['system']['crypto_hardware'])) {
1819
		log_error(sprintf(gettext("Loading %s cryptographic accelerator module."), $config['system']['crypto_hardware']));
1820
		mwexec("/sbin/kldload {$config['system']['crypto_hardware']}");
1821
	}
1822
}
1823

    
1824
/*
1825
 * load_thermal_hardware() - Load temperature monitor kernel module
1826
 */
1827
function load_thermal_hardware() {
1828
	global $config, $g;
1829
	$thermal_hardware_modules = array('coretemp', 'amdtemp');
1830

    
1831
	if (!in_array($config['system']['thermal_hardware'], $thermal_hardware_modules)) {
1832
		return false;
1833
	}
1834

    
1835
	if (!empty($config['system']['thermal_hardware']) && !is_module_loaded($config['system']['thermal_hardware'])) {
1836
		log_error(sprintf(gettext("Loading %s thermal monitor module."), $config['system']['thermal_hardware']));
1837
		mwexec("/sbin/kldload {$config['system']['thermal_hardware']}");
1838
	}
1839
}
1840

    
1841
/****f* pfsense-utils/isvm
1842
 * NAME
1843
 *   isvm
1844
 * INPUTS
1845
 *	none
1846
 * RESULT
1847
 *   returns true if machine is running under a virtual environment
1848
 ******/
1849
function isvm() {
1850
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86", "VirtualBox");
1851
	$_gb = exec('/bin/kenv smbios.system.product 2>/dev/null', $output, $rc);
1852

    
1853
	if ($rc != 0 || !isset($output[0])) {
1854
		return false;
1855
	}
1856

    
1857
	foreach ($virtualenvs as $virtualenv) {
1858
		if (stripos($output[0], $virtualenv) !== false) {
1859
			return true;
1860
		}
1861
	}
1862

    
1863
	return false;
1864
}
1865

    
1866
function get_freebsd_version() {
1867
	$version = explode(".", php_uname("r"));
1868
	return $version[0];
1869
}
1870

    
1871
function download_file($url, $destination, $verify_ssl = true, $connect_timeout = 5, $timeout = 0) {
1872
	global $config, $g;
1873

    
1874
	$fp = fopen($destination, "wb");
1875

    
1876
	if (!$fp) {
1877
		return false;
1878
	}
1879

    
1880
	$ch = curl_init();
1881
	curl_setopt($ch, CURLOPT_URL, $url);
1882
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1883
	curl_setopt($ch, CURLOPT_FILE, $fp);
1884
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1885
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1886
	curl_setopt($ch, CURLOPT_HEADER, false);
1887
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1888
	if (!isset($config['system']['do_not_send_host_uuid'])) {
1889
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1890
	} else {
1891
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1892
	}
1893

    
1894
	if (!empty($config['system']['proxyurl'])) {
1895
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1896
		if (!empty($config['system']['proxyport'])) {
1897
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1898
		}
1899
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1900
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1901
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1902
		}
1903
	}
1904

    
1905
	@curl_exec($ch);
1906
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1907
	fclose($fp);
1908
	curl_close($ch);
1909
	if ($http_code == 200) {
1910
		return true;
1911
	} else {
1912
		log_error(sprintf(gettext('Download file failed with status code %1$s. URL: %2$s'), $http_code, $url));
1913
		unlink_if_exists($destination);
1914
		return false;
1915
	}
1916
}
1917

    
1918
function download_file_with_progress_bar($url, $destination, $verify_ssl = true, $readbody = 'read_body', $connect_timeout = 5, $timeout = 0) {
1919
	global $config, $g;
1920
	global $ch, $fout, $file_size, $downloaded, $config, $first_progress_update;
1921
	$file_size = 1;
1922
	$downloaded = 1;
1923
	$first_progress_update = TRUE;
1924
	/* open destination file */
1925
	$fout = fopen($destination, "wb");
1926

    
1927
	if (!$fout) {
1928
		return false;
1929
	}
1930
	/*
1931
	 *      Originally by Author: Keyvan Minoukadeh
1932
	 *      Modified by Scott Ullrich to return Content-Length size
1933
	 */
1934
	$ch = curl_init();
1935
	curl_setopt($ch, CURLOPT_URL, $url);
1936
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1937
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1938
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1939
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1940
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1941
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1942
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1943
	if (!isset($config['system']['do_not_send_host_uuid'])) {
1944
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1945
	} else {
1946
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1947
	}
1948

    
1949
	if (!empty($config['system']['proxyurl'])) {
1950
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1951
		if (!empty($config['system']['proxyport'])) {
1952
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1953
		}
1954
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1955
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1956
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1957
		}
1958
	}
1959

    
1960
	@curl_exec($ch);
1961
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1962
	fclose($fout);
1963
	curl_close($ch);
1964
	if ($http_code == 200) {
1965
		return true;
1966
	} else {
1967
		log_error(sprintf(gettext('Download file failed with status code %1$s. URL: %2$s'), $http_code, $url));
1968
		unlink_if_exists($destination);
1969
		return false;
1970
	}
1971
}
1972

    
1973
function read_header($ch, $string) {
1974
	global $file_size, $fout;
1975
	$length = strlen($string);
1976
	$regs = "";
1977
	preg_match("/(Content-Length:) (.*)/", $string, $regs);
1978
	if ($regs[2] <> "") {
1979
		$file_size = intval($regs[2]);
1980
	}
1981
	ob_flush();
1982
	return $length;
1983
}
1984

    
1985
function read_body($ch, $string) {
1986
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen, $first_progress_update;
1987
	global $pkg_interface;
1988
	$length = strlen($string);
1989
	$downloaded += intval($length);
1990
	if ($file_size > 0) {
1991
		$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1992
		$downloadProgress = 100 - $downloadProgress;
1993
	} else {
1994
		$downloadProgress = 0;
1995
	}
1996
	if ($lastseen <> $downloadProgress and $downloadProgress < 101) {
1997
		if ($sendto == "status") {
1998
			if ($pkg_interface == "console") {
1999
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
2000
					$tostatus = $static_status . $downloadProgress . "%";
2001
					if ($downloadProgress == 100) {
2002
						$tostatus = $tostatus . "\r";
2003
					}
2004
					update_status($tostatus);
2005
				}
2006
			} else {
2007
				$tostatus = $static_status . $downloadProgress . "%";
2008
				update_status($tostatus);
2009
			}
2010
		} else {
2011
			if ($pkg_interface == "console") {
2012
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
2013
					$tooutput = $static_output . $downloadProgress . "%";
2014
					if ($downloadProgress == 100) {
2015
						$tooutput = $tooutput . "\r";
2016
					}
2017
					update_output_window($tooutput);
2018
				}
2019
			} else {
2020
				$tooutput = $static_output . $downloadProgress . "%";
2021
				update_output_window($tooutput);
2022
			}
2023
		}
2024
		if (($pkg_interface != "console") || (($downloadProgress % 10) == 0) || ($downloadProgress < 10)) {
2025
			update_progress_bar($downloadProgress, $first_progress_update);
2026
			$first_progress_update = FALSE;
2027
		}
2028
		$lastseen = $downloadProgress;
2029
	}
2030
	if ($fout) {
2031
		fwrite($fout, $string);
2032
	}
2033
	ob_flush();
2034
	return $length;
2035
}
2036

    
2037
/*
2038
 *   update_output_window: update bottom textarea dynamically.
2039
 */
2040
function update_output_window($text) {
2041
	global $pkg_interface;
2042
	$log = preg_replace("/\n/", "\\n", $text);
2043
	if ($pkg_interface != "console") {
2044
?>
2045
<script type="text/javascript">
2046
//<![CDATA[
2047
	document.getElementById("output").textContent="<?=htmlspecialchars($log)?>";
2048
	document.getElementById("output").scrollTop = document.getElementById("output").scrollHeight;
2049
//]]>
2050
</script>
2051
<?php
2052
	}
2053
	/* ensure that contents are written out */
2054
	ob_flush();
2055
}
2056

    
2057
/*
2058
 *   update_status: update top textarea dynamically.
2059
 */
2060
function update_status($status) {
2061
	global $pkg_interface;
2062

    
2063
	if ($pkg_interface == "console") {
2064
		print ("{$status}");
2065
	}
2066

    
2067
	/* ensure that contents are written out */
2068
	ob_flush();
2069
}
2070

    
2071
/*
2072
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
2073
 */
2074
function update_progress_bar($percent, $first_time) {
2075
	global $pkg_interface;
2076
	if ($percent > 100) {
2077
		$percent = 1;
2078
	}
2079
	if ($pkg_interface <> "console") {
2080
		echo '<script type="text/javascript">';
2081
		echo "\n//<![CDATA[\n";
2082
		echo 'document.getElementById("progressbar").style.width="'. $percent.'%"';
2083
		echo "\n//]]>\n";
2084
		echo '</script>';
2085
	} else {
2086
		if (!($first_time)) {
2087
			echo "\x08\x08\x08\x08\x08";
2088
		}
2089
		echo sprintf("%4d%%", $percent);
2090
	}
2091
}
2092

    
2093
/* 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. */
2094
if (!function_exists("split")) {
2095
	function split($separator, $haystack, $limit = null) {
2096
		log_error("deprecated split() call with separator '{$separator}'");
2097
		return preg_split($separator, $haystack, $limit);
2098
	}
2099
}
2100

    
2101
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
2102
	global $g, $config, $pconfig, $debug;
2103
	if (!$origname) {
2104
		return;
2105
	}
2106

    
2107
	$sectionref = &$config;
2108
	foreach ($section as $sectionname) {
2109
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
2110
			$sectionref = &$sectionref[$sectionname];
2111
		} else {
2112
			return;
2113
		}
2114
	}
2115

    
2116
	if ($debug) {
2117
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
2118
		fwrite($fd, print_r($pconfig, true));
2119
	}
2120

    
2121
	if (is_array($sectionref)) {
2122
		foreach ($sectionref as $itemkey => $item) {
2123
			if ($debug) {
2124
				fwrite($fd, "$itemkey\n");
2125
			}
2126

    
2127
			$fieldfound = true;
2128
			$fieldref = &$sectionref[$itemkey];
2129
			foreach ($field as $fieldname) {
2130
				if (is_array($fieldref) && isset($fieldref[$fieldname])) {
2131
					$fieldref = &$fieldref[$fieldname];
2132
				} else {
2133
					$fieldfound = false;
2134
					break;
2135
				}
2136
			}
2137
			if ($fieldfound && $fieldref == $origname) {
2138
				if ($debug) {
2139
					fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
2140
				}
2141
				$fieldref = $new_alias_name;
2142
			}
2143
		}
2144
	}
2145

    
2146
	if ($debug) {
2147
		fclose($fd);
2148
	}
2149

    
2150
}
2151

    
2152
function parse_aliases_file($filename, $type = "url", $max_items = -1, $kflc = false) {
2153
	/*
2154
	 * $filename = file to process for example blocklist like DROP:  http://www.spamhaus.org/drop/drop.txt
2155
	 * $type = if set to 'url' then subnets and ips will be returned,
2156
	 *         if set to 'url_ports' port-ranges and ports will be returned
2157
	 * $max_items = sets the maximum amount of valid items to load, -1 the default defines there is no limit.
2158
	 *
2159
	 * RETURNS an array of ip subnets and ip's or ports and port-ranges, returns NULL upon a error conditions (file not found)
2160
	 */
2161

    
2162
	if (!file_exists($filename)) {
2163
		log_error(sprintf(gettext("Could not process non-existent file from alias: %s"), $filename));
2164
		return null;
2165
	}
2166

    
2167
	if (filesize($filename) == 0) {
2168
		log_error(sprintf(gettext("Could not process empty file from alias: %s"), $filename));
2169
		return null;
2170
	}
2171
	$fd = @fopen($filename, 'r');
2172
	if (!$fd) {
2173
		log_error(sprintf(gettext("Could not process aliases from alias: %s"), $filename));
2174
		return null;
2175
	}
2176
	$items = array();
2177
	$comments = array();
2178
	/* NOTE: fgetss() is not a typo RTFM before being smart */
2179
	while (($fc = fgetss($fd)) !== FALSE) {
2180
		$tmp = trim($fc, " \t\n\r");
2181
		if (empty($tmp)) {
2182
			continue;
2183
		}
2184
		if (($kflc) && (strpos($tmp, '#') === 0)) {	// Keep Full Line Comments (lines beginning with #).
2185
			$comments[] = $tmp;
2186
		} else {
2187
			$tmp_str = strstr($tmp, '#', true);
2188
			if (!empty($tmp_str)) {
2189
				$tmp = $tmp_str;
2190
			}
2191
			$tmp_str = strstr($tmp, ' ', true);
2192
			if (!empty($tmp_str)) {
2193
				$tmp = $tmp_str;
2194
			}
2195
			$valid = (($type == "url" || $type == "urltable") && (is_ipaddr($tmp) || is_subnet($tmp))) ||
2196
				(($type == "url_ports" || $type == "urltable_ports") && (is_port($tmp) || is_portrange($tmp)));
2197
			if ($valid) {
2198
				$items[] = $tmp;
2199
				if (count($items) == $max_items) {
2200
					break;
2201
				}
2202
			}
2203
		}
2204
	}
2205
	fclose($fd);
2206
	return array_merge($comments, $items);
2207
}
2208

    
2209
function update_alias_url_data() {
2210
	global $config, $g;
2211

    
2212
	$updated = false;
2213

    
2214
	/* item is a url type */
2215
	$lockkey = lock('aliasurl');
2216
	if (is_array($config['aliases']['alias'])) {
2217
		foreach ($config['aliases']['alias'] as $x => $alias) {
2218
			if (empty($alias['aliasurl'])) {
2219
				continue;
2220
			}
2221

    
2222
			$address = null;
2223
			foreach ($alias['aliasurl'] as $alias_url) {
2224
				/* fetch down and add in */
2225
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
2226
				unlink($temp_filename);
2227
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2228
				mkdir($temp_filename);
2229
				if (!download_file($alias_url, $temp_filename . "/aliases", $verify_ssl)) {
2230
					log_error(sprintf(gettext("Failed to download alias %s"), $alias_url));
2231
					continue;
2232
				}
2233

    
2234
				/* if the item is tar gzipped then extract */
2235
				if (stripos($alias_url, '.tgz')) {
2236
					if (!process_alias_tgz($temp_filename)) {
2237
						continue;
2238
					}
2239
				}
2240
				if (file_exists("{$temp_filename}/aliases")) {
2241
					$address = parse_aliases_file("{$temp_filename}/aliases", $alias['type'], 5000);
2242
					mwexec("/bin/rm -rf {$temp_filename}");
2243
				}
2244
			}
2245
			if ($address != null) {
2246
				$config['aliases']['alias'][$x]['address'] = implode(" ", $address);
2247
				$updated = true;
2248
			}
2249
		}
2250
	}
2251
	unlock($lockkey);
2252

    
2253
	/* Report status to callers as well */
2254
	return $updated;
2255
}
2256

    
2257
function process_alias_tgz($temp_filename) {
2258
	if (!file_exists('/usr/bin/tar')) {
2259
		log_error(gettext("Alias archive is a .tar/tgz file which cannot be decompressed because utility is missing!"));
2260
		return false;
2261
	}
2262
	rename("{$temp_filename}/aliases", "{$temp_filename}/aliases.tgz");
2263
	mwexec("/usr/bin/tar xzf {$temp_filename}/aliases.tgz -C {$temp_filename}/aliases/");
2264
	unlink("{$temp_filename}/aliases.tgz");
2265
	$files_to_process = return_dir_as_array("{$temp_filename}/");
2266
	/* foreach through all extracted files and build up aliases file */
2267
	$fd = @fopen("{$temp_filename}/aliases", "w");
2268
	if (!$fd) {
2269
		log_error(sprintf(gettext("Could not open %s/aliases for writing!"), $temp_filename));
2270
		return false;
2271
	}
2272
	foreach ($files_to_process as $f2p) {
2273
		$tmpfd = @fopen($f2p, 'r');
2274
		if (!$tmpfd) {
2275
			log_error(sprintf(gettext('The following file could not be read %1$s from %2$s'), $f2p, $temp_filename));
2276
			continue;
2277
		}
2278
		while (($tmpbuf = fread($tmpfd, 65536)) !== FALSE) {
2279
			fwrite($fd, $tmpbuf);
2280
		}
2281
		fclose($tmpfd);
2282
		unlink($f2p);
2283
	}
2284
	fclose($fd);
2285
	unset($tmpbuf);
2286

    
2287
	return true;
2288
}
2289

    
2290
function version_compare_dates($a, $b) {
2291
	$a_time = strtotime($a);
2292
	$b_time = strtotime($b);
2293

    
2294
	if ((!$a_time) || (!$b_time)) {
2295
		return FALSE;
2296
	} else {
2297
		if ($a_time < $b_time) {
2298
			return -1;
2299
		} elseif ($a_time == $b_time) {
2300
			return 0;
2301
		} else {
2302
			return 1;
2303
		}
2304
	}
2305
}
2306
function version_get_string_value($a) {
2307
	$strs = array(
2308
		0 => "ALPHA-ALPHA",
2309
		2 => "ALPHA",
2310
		3 => "BETA",
2311
		4 => "B",
2312
		5 => "C",
2313
		6 => "D",
2314
		7 => "RC",
2315
		8 => "RELEASE",
2316
		9 => "*"			// Matches all release levels
2317
	);
2318
	$major = 0;
2319
	$minor = 0;
2320
	foreach ($strs as $num => $str) {
2321
		if (substr($a, 0, strlen($str)) == $str) {
2322
			$major = $num;
2323
			$n = substr($a, strlen($str));
2324
			if (is_numeric($n)) {
2325
				$minor = $n;
2326
			}
2327
			break;
2328
		}
2329
	}
2330
	return "{$major}.{$minor}";
2331
}
2332
function version_compare_string($a, $b) {
2333
	// Only compare string parts if both versions give a specific release
2334
	// (If either version lacks a string part, assume intended to match all release levels)
2335
	if (isset($a) && isset($b)) {
2336
		return version_compare_numeric(version_get_string_value($a), version_get_string_value($b));
2337
	} else {
2338
		return 0;
2339
	}
2340
}
2341
function version_compare_numeric($a, $b) {
2342
	$a_arr = explode('.', rtrim($a, '.'));
2343
	$b_arr = explode('.', rtrim($b, '.'));
2344

    
2345
	foreach ($a_arr as $n => $val) {
2346
		if (array_key_exists($n, $b_arr)) {
2347
			// So far so good, both have values at this minor version level. Compare.
2348
			if ($val > $b_arr[$n]) {
2349
				return 1;
2350
			} elseif ($val < $b_arr[$n]) {
2351
				return -1;
2352
			}
2353
		} else {
2354
			// a is greater, since b doesn't have any minor version here.
2355
			return 1;
2356
		}
2357
	}
2358
	if (count($b_arr) > count($a_arr)) {
2359
		// b is longer than a, so it must be greater.
2360
		return -1;
2361
	} else {
2362
		// Both a and b are of equal length and value.
2363
		return 0;
2364
	}
2365
}
2366
function pfs_version_compare($cur_time, $cur_text, $remote) {
2367
	// First try date compare
2368
	$v = version_compare_dates($cur_time, $remote);
2369
	if ($v === FALSE) {
2370
		// If that fails, try to compare by string
2371
		// Before anything else, simply test if the strings are equal
2372
		if (($cur_text == $remote) || ($cur_time == $remote)) {
2373
			return 0;
2374
		}
2375
		list($cur_num, $cur_str) = explode('-', $cur_text);
2376
		list($rem_num, $rem_str) = explode('-', $remote);
2377

    
2378
		// First try to compare the numeric parts of the version string.
2379
		$v = version_compare_numeric($cur_num, $rem_num);
2380

    
2381
		// If the numeric parts are the same, compare the string parts.
2382
		if ($v == 0) {
2383
			return version_compare_string($cur_str, $rem_str);
2384
		}
2385
	}
2386
	return $v;
2387
}
2388
function process_alias_urltable($name, $type, $url, $freq, $forceupdate=false, $validateonly=false) {
2389
	global $g, $config;
2390

    
2391
	$urltable_prefix = "/var/db/aliastables/";
2392
	$urltable_filename = $urltable_prefix . $name . ".txt";
2393
	$tmp_urltable_filename = $urltable_filename . ".tmp";
2394

    
2395
	// Make the aliases directory if it doesn't exist
2396
	if (!file_exists($urltable_prefix)) {
2397
		mkdir($urltable_prefix);
2398
	} elseif (!is_dir($urltable_prefix)) {
2399
		unlink($urltable_prefix);
2400
		mkdir($urltable_prefix);
2401
	}
2402

    
2403
	// If the file doesn't exist or is older than update_freq days, fetch a new copy.
2404
	if (!file_exists($urltable_filename) || (filesize($urltable_filename) == "0") ||
2405
	    ((time() - filemtime($urltable_filename)) > ($freq * 86400 - 90)) ||
2406
	    $forceupdate) {
2407

    
2408
		// Try to fetch the URL supplied
2409
		conf_mount_rw();
2410
		unlink_if_exists($tmp_urltable_filename);
2411
		$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2412
		if (download_file($url, $tmp_urltable_filename, $verify_ssl)) {
2413
			// Convert lines that begin with '$' or ';' to comments '#' instead of deleting them.
2414
			mwexec("/usr/bin/sed -i \"\" -E 's/^[[:space:]]*($|#|;)/#/g; /^#/!s/\;.*//g;' ". escapeshellarg($tmp_urltable_filename));
2415

    
2416
			$type = ($type) ? $type : alias_get_type($name);	// If empty type passed, try to get it from config.
2417

    
2418
			$parsed_contents = parse_aliases_file($tmp_urltable_filename, $type, "-1", true);
2419
			if ($type == "urltable_ports") {
2420
				$parsed_contents = group_ports($parsed_contents, true);
2421
			}
2422
			if (is_array($parsed_contents)) {
2423
				file_put_contents($urltable_filename, implode("\n", $parsed_contents));
2424
			} else {
2425
				touch($urltable_filename);
2426
			}
2427

    
2428
			/* If this backup is still there on a full install, but we aren't going to use ram disks, remove the archive since this is a transition. */
2429
			if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
2430
				unlink_if_exists("{$g['cf_conf_path']}/RAM_Disk_Store{$urltable_filename}.tgz");
2431
			} else {
2432
				/* Update the RAM disk store with the new/updated table file. */
2433
				mwexec("cd / && /usr/bin/tar -czf \"{$g['cf_conf_path']}/RAM_Disk_Store{$urltable_filename}.tgz\" -C / \"{$urltable_filename}\"");
2434
			}
2435
			unlink_if_exists($tmp_urltable_filename);
2436
		} else {
2437
			if (!$validateonly) {
2438
				touch($urltable_filename);
2439
			}
2440
			conf_mount_ro();
2441
			return false;
2442
		}
2443
		conf_mount_ro();
2444
		return true;
2445
	} else {
2446
		// File exists, and it doesn't need to be updated.
2447
		return -1;
2448
	}
2449
}
2450
function get_real_slice_from_glabel($label) {
2451
	$label = escapeshellarg($label);
2452
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/{$label} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`);
2453
}
2454
function nanobsd_get_boot_slice() {
2455
	return trim(`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`);
2456
}
2457
function nanobsd_get_boot_drive() {
2458
	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`);
2459
}
2460
function nanobsd_get_active_slice() {
2461
	$boot_drive = nanobsd_get_boot_drive();
2462
	$active = trim(`gpart show $boot_drive | grep '\[active\]' | awk '{print $3;}'`);
2463

    
2464
	return "{$boot_drive}s{$active}";
2465
}
2466
function nanobsd_get_size() {
2467
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2468
}
2469
function nanobsd_switch_boot_slice() {
2470
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2471
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2472
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2473
	nanobsd_detect_slice_info();
2474

    
2475
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2476
		$slice = $TOFLASH;
2477
	} else {
2478
		$slice = $BOOTFLASH;
2479
	}
2480

    
2481
	for ($i = 0; $i < ob_get_level(); $i++) {
2482
		ob_end_flush();
2483
	}
2484
	ob_implicit_flush(1);
2485
	if (strstr($slice, "s2")) {
2486
		$ASLICE = "2";
2487
		$AOLDSLICE = "1";
2488
		$AGLABEL_SLICE = "pfsense1";
2489
		$AUFS_ID = "1";
2490
		$AOLD_UFS_ID = "0";
2491
	} else {
2492
		$ASLICE = "1";
2493
		$AOLDSLICE = "2";
2494
		$AGLABEL_SLICE = "pfsense0";
2495
		$AUFS_ID = "0";
2496
		$AOLD_UFS_ID = "1";
2497
	}
2498
	$ATOFLASH = "{$BOOT_DRIVE}s{$ASLICE}";
2499
	$ACOMPLETE_PATH = "{$BOOT_DRIVE}s{$ASLICE}a";
2500
	$ABOOTFLASH = "{$BOOT_DRIVE}s{$AOLDSLICE}";
2501
	conf_mount_rw();
2502
	set_single_sysctl("kern.geom.debugflags", "16");
2503
	exec("/sbin/gpart set -a active -i {$ASLICE} {$BOOT_DRIVE}");
2504
	exec("/usr/sbin/boot0cfg -s {$ASLICE} -v /dev/{$BOOT_DRIVE}");
2505
	// We can't update these if they are mounted now.
2506
	if ($BOOTFLASH != $slice) {
2507
		exec("/sbin/tunefs -L ${AGLABEL_SLICE} /dev/$ACOMPLETE_PATH");
2508
		nanobsd_update_fstab($AGLABEL_SLICE, $ACOMPLETE_PATH, $AOLD_UFS_ID, $AUFS_ID);
2509
	}
2510
	set_single_sysctl("kern.geom.debugflags", "0");
2511
	conf_mount_ro();
2512
}
2513
function nanobsd_clone_slice() {
2514
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2515
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2516
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2517
	nanobsd_detect_slice_info();
2518

    
2519
	for ($i = 0; $i < ob_get_level(); $i++) {
2520
		ob_end_flush();
2521
	}
2522
	ob_implicit_flush(1);
2523
	set_single_sysctl("kern.geom.debugflags", "16");
2524
	exec("/bin/dd if=/dev/zero of=/dev/{$TOFLASH} bs=1m count=1");
2525
	exec("/bin/dd if=/dev/{$BOOTFLASH} of=/dev/{$TOFLASH} bs=64k");
2526
	exec("/sbin/tunefs -L {$GLABEL_SLICE} /dev/{$COMPLETE_PATH}");
2527
	$status = nanobsd_update_fstab($GLABEL_SLICE, $COMPLETE_PATH, $OLD_UFS_ID, $UFS_ID);
2528
	set_single_sysctl("kern.geom.debugflags", "0");
2529
	if ($status) {
2530
		return false;
2531
	} else {
2532
		return true;
2533
	}
2534
}
2535
function nanobsd_update_fstab($gslice, $complete_path, $oldufs, $newufs) {
2536
	$tmppath = "/tmp/{$gslice}";
2537
	$fstabpath = "/tmp/{$gslice}/etc/fstab";
2538

    
2539
	mkdir($tmppath);
2540
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2541
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2542
	copy("/etc/fstab", $fstabpath);
2543

    
2544
	if (!file_exists($fstabpath)) {
2545
		$fstab = <<<EOF
2546
/dev/ufs/{$gslice} / ufs ro,noatime 1 1
2547
/dev/ufs/cf /cf ufs ro,noatime 1 1
2548
EOF;
2549
		if (file_put_contents($fstabpath, $fstab)) {
2550
			$status = true;
2551
		} else {
2552
			$status = false;
2553
		}
2554
	} else {
2555
		$status = exec("/usr/bin/sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2556
	}
2557
	exec("/sbin/umount {$tmppath}");
2558
	rmdir($tmppath);
2559

    
2560
	return $status;
2561
}
2562
function nanobsd_detect_slice_info() {
2563
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2564
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2565
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2566

    
2567
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2568
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2569
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2570
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2571

    
2572
	// Detect which slice is active and set information.
2573
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2574
		$SLICE = "2";
2575
		$OLDSLICE = "1";
2576
		$GLABEL_SLICE = "pfsense1";
2577
		$UFS_ID = "1";
2578
		$OLD_UFS_ID = "0";
2579

    
2580
	} else {
2581
		$SLICE = "1";
2582
		$OLDSLICE = "2";
2583
		$GLABEL_SLICE = "pfsense0";
2584
		$UFS_ID = "0";
2585
		$OLD_UFS_ID = "1";
2586
	}
2587
	$TOFLASH = "{$BOOT_DRIVE}s{$SLICE}";
2588
	$COMPLETE_PATH = "{$BOOT_DRIVE}s{$SLICE}a";
2589
	$COMPLETE_BOOT_PATH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2590
	$BOOTFLASH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2591
}
2592

    
2593
function nanobsd_friendly_slice_name($slicename) {
2594
	global $g;
2595
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2596
}
2597

    
2598
function get_include_contents($filename) {
2599
	if (is_file($filename)) {
2600
		ob_start();
2601
		include $filename;
2602
		$contents = ob_get_contents();
2603
		ob_end_clean();
2604
		return $contents;
2605
	}
2606
	return false;
2607
}
2608

    
2609
/* This xml 2 array function is courtesy of the php.net comment section on xml_parse.
2610
 * it is roughly 4 times faster then our existing pfSense parser but due to the large
2611
 * size of the RRD xml dumps this is required.
2612
 * The reason we do not use it for pfSense is that it does not know about array fields
2613
 * which causes it to fail on array fields with single items. Possible Todo?
2614
 */
2615
function xml2array($contents, $get_attributes = 1, $priority = 'tag') {
2616
	if (!function_exists('xml_parser_create')) {
2617
		return array ();
2618
	}
2619
	$parser = xml_parser_create('');
2620
	xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
2621
	xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
2622
	xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
2623
	xml_parse_into_struct($parser, trim($contents), $xml_values);
2624
	xml_parser_free($parser);
2625
	if (!$xml_values) {
2626
		return; //Hmm...
2627
	}
2628
	$xml_array = array ();
2629
	$parents = array ();
2630
	$opened_tags = array ();
2631
	$arr = array ();
2632
	$current = & $xml_array;
2633
	$repeated_tag_index = array ();
2634
	foreach ($xml_values as $data) {
2635
		unset ($attributes, $value);
2636
		extract($data);
2637
		$result = array ();
2638
		$attributes_data = array ();
2639
		if (isset ($value)) {
2640
			if ($priority == 'tag') {
2641
				$result = $value;
2642
			} else {
2643
				$result['value'] = $value;
2644
			}
2645
		}
2646
		if (isset ($attributes) and $get_attributes) {
2647
			foreach ($attributes as $attr => $val) {
2648
				if ($priority == 'tag') {
2649
					$attributes_data[$attr] = $val;
2650
				} else {
2651
					$result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
2652
				}
2653
			}
2654
		}
2655
		if ($type == "open") {
2656
			$parent[$level -1] = & $current;
2657
			if (!is_array($current) or (!in_array($tag, array_keys($current)))) {
2658
				$current[$tag] = $result;
2659
				if ($attributes_data) {
2660
					$current[$tag . '_attr'] = $attributes_data;
2661
				}
2662
				$repeated_tag_index[$tag . '_' . $level] = 1;
2663
				$current = & $current[$tag];
2664
			} else {
2665
				if (isset ($current[$tag][0])) {
2666
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2667
					$repeated_tag_index[$tag . '_' . $level]++;
2668
				} else {
2669
					$current[$tag] = array (
2670
						$current[$tag],
2671
						$result
2672
						);
2673
					$repeated_tag_index[$tag . '_' . $level] = 2;
2674
					if (isset ($current[$tag . '_attr'])) {
2675
						$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2676
						unset ($current[$tag . '_attr']);
2677
					}
2678
				}
2679
				$last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
2680
				$current = & $current[$tag][$last_item_index];
2681
			}
2682
		} elseif ($type == "complete") {
2683
			if (!isset ($current[$tag])) {
2684
				$current[$tag] = $result;
2685
				$repeated_tag_index[$tag . '_' . $level] = 1;
2686
				if ($priority == 'tag' and $attributes_data) {
2687
					$current[$tag . '_attr'] = $attributes_data;
2688
				}
2689
			} else {
2690
				if (isset ($current[$tag][0]) and is_array($current[$tag])) {
2691
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2692
					if ($priority == 'tag' and $get_attributes and $attributes_data) {
2693
						$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2694
					}
2695
					$repeated_tag_index[$tag . '_' . $level]++;
2696
				} else {
2697
					$current[$tag] = array (
2698
						$current[$tag],
2699
						$result
2700
						);
2701
					$repeated_tag_index[$tag . '_' . $level] = 1;
2702
					if ($priority == 'tag' and $get_attributes) {
2703
						if (isset ($current[$tag . '_attr'])) {
2704
							$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2705
							unset ($current[$tag . '_attr']);
2706
						}
2707
						if ($attributes_data) {
2708
							$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2709
						}
2710
					}
2711
					$repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
2712
				}
2713
			}
2714
		} elseif ($type == 'close') {
2715
			$current = & $parent[$level -1];
2716
		}
2717
	}
2718
	return ($xml_array);
2719
}
2720

    
2721
function get_country_name($country_code) {
2722
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2723
		return "";
2724
	}
2725

    
2726
	$country_names_xml = "/usr/local/share/mobile-broadband-provider-info/iso_3166-1_list_en.xml";
2727
	$country_names_contents = file_get_contents($country_names_xml);
2728
	$country_names = xml2array($country_names_contents);
2729

    
2730
	if ($country_code == "ALL") {
2731
		$country_list = array();
2732
		foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2733
			$country_list[] = array(
2734
				"code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2735
				"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])));
2736
		}
2737
		return $country_list;
2738
	}
2739

    
2740
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2741
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2742
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2743
		}
2744
	}
2745
	return "";
2746
}
2747

    
2748
/* sort by interface only, retain the original order of rules that apply to
2749
   the same interface */
2750
function filter_rules_sort() {
2751
	global $config;
2752

    
2753
	/* mark each rule with the sequence number (to retain the order while sorting) */
2754
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2755
		$config['filter']['rule'][$i]['seq'] = $i;
2756
	}
2757

    
2758
	usort($config['filter']['rule'], "filter_rules_compare");
2759

    
2760
	/* strip the sequence numbers again */
2761
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2762
		unset($config['filter']['rule'][$i]['seq']);
2763
	}
2764
}
2765
function filter_rules_compare($a, $b) {
2766
	if (isset($a['floating']) && isset($b['floating'])) {
2767
		return $a['seq'] - $b['seq'];
2768
	} else if (isset($a['floating'])) {
2769
		return -1;
2770
	} else if (isset($b['floating'])) {
2771
		return 1;
2772
	} else if ($a['interface'] == $b['interface']) {
2773
		return $a['seq'] - $b['seq'];
2774
	} else {
2775
		return compare_interface_friendly_names($a['interface'], $b['interface']);
2776
	}
2777
}
2778

    
2779
function generate_ipv6_from_mac($mac) {
2780
	$elements = explode(":", $mac);
2781
	if (count($elements) <> 6) {
2782
		return false;
2783
	}
2784

    
2785
	$i = 0;
2786
	$ipv6 = "fe80::";
2787
	foreach ($elements as $byte) {
2788
		if ($i == 0) {
2789
			$hexadecimal = substr($byte, 1, 2);
2790
			$bitmap = base_convert($hexadecimal, 16, 2);
2791
			$bitmap = str_pad($bitmap, 4, "0", STR_PAD_LEFT);
2792
			$bitmap = substr($bitmap, 0, 2) ."1". substr($bitmap, 3, 4);
2793
			$byte = substr($byte, 0, 1) . base_convert($bitmap, 2, 16);
2794
		}
2795
		$ipv6 .= $byte;
2796
		if ($i == 1) {
2797
			$ipv6 .= ":";
2798
		}
2799
		if ($i == 3) {
2800
			$ipv6 .= ":";
2801
		}
2802
		if ($i == 2) {
2803
			$ipv6 .= "ff:fe";
2804
		}
2805

    
2806
		$i++;
2807
	}
2808
	return $ipv6;
2809
}
2810

    
2811
/****f* pfsense-utils/load_mac_manufacturer_table
2812
 * NAME
2813
 *   load_mac_manufacturer_table
2814
 * INPUTS
2815
 *   none
2816
 * RESULT
2817
 *   returns associative array with MAC-Manufacturer pairs
2818
 ******/
2819
function load_mac_manufacturer_table() {
2820
	/* load MAC-Manufacture data from the file */
2821
	$macs = false;
2822
	if (file_exists("/usr/local/share/nmap/nmap-mac-prefixes")) {
2823
		$macs=file("/usr/local/share/nmap/nmap-mac-prefixes");
2824
	}
2825
	if ($macs) {
2826
		foreach ($macs as $line) {
2827
			if (preg_match('/([0-9A-Fa-f]{6}) (.*)$/', $line, $matches)) {
2828
				/* store values like this $mac_man['000C29']='VMware' */
2829
				$mac_man["$matches[1]"] = $matches[2];
2830
			}
2831
		}
2832
		return $mac_man;
2833
	} else {
2834
		return -1;
2835
	}
2836

    
2837
}
2838

    
2839
/****f* pfsense-utils/is_ipaddr_configured
2840
 * NAME
2841
 *   is_ipaddr_configured
2842
 * INPUTS
2843
 *   IP Address to check.
2844
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2845
 *   check_localip - if true then also check for matches with PPTP and L2TP addresses
2846
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2847
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2848
 *     If check_subnets is true and cidrprefix is specified,
2849
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2850
 * RESULT
2851
 *   returns true if the IP Address is configured and present on this device or overlaps a configured subnet.
2852
*/
2853
function is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2854
	if (count(where_is_ipaddr_configured($ipaddr, $ignore_if, $check_localip, $check_subnets, $cidrprefix))) {
2855
		return true;
2856
	}
2857
	return false;
2858
}
2859

    
2860
/****f* pfsense-utils/where_is_ipaddr_configured
2861
 * NAME
2862
 *   where_is_ipaddr_configured
2863
 * INPUTS
2864
 *   IP Address to check.
2865
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2866
 *   check_localip - if true then also check for matches with PPTP and L2TP addresses
2867
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2868
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2869
 *     If check_subnets is true and cidrprefix is specified,
2870
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2871
 * RESULT
2872
 *   Returns an array of the interfaces 'if' plus IP address or subnet 'ip_or_subnet' that match or overlap the IP address to check.
2873
 *   If there are no matches then an empty array is returned.
2874
*/
2875
function where_is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2876
	global $config;
2877

    
2878
	$where_configured = array();
2879

    
2880
	$pos = strpos($ignore_if, '_virtualip');
2881
	if ($pos !== false) {
2882
		$ignore_vip_id = substr($ignore_if, $pos+10);
2883
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2884
	} else {
2885
		$ignore_vip_id = -1;
2886
		$ignore_vip_if = $ignore_if;
2887
	}
2888

    
2889
	$isipv6 = is_ipaddrv6($ipaddr);
2890

    
2891
	if ($check_subnets) {
2892
		$cidrprefix = intval($cidrprefix);
2893
		if ($isipv6) {
2894
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2895
				$cidrprefix = 128;
2896
			}
2897
		} else {
2898
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2899
				$cidrprefix = 32;
2900
			}
2901
		}
2902
		$iflist = get_configured_interface_list();
2903
		foreach ($iflist as $if => $ifname) {
2904
			if ($ignore_if == $if) {
2905
				continue;
2906
			}
2907

    
2908
			if ($isipv6) {
2909
				$if_ipv6 = get_interface_ipv6($if);
2910
				$if_snbitsv6 = get_interface_subnetv6($if);
2911
				if ($if_ipv6 && $if_snbitsv6 && check_subnetsv6_overlap($ipaddr, $cidrprefix, $if_ipv6, $if_snbitsv6)) {
2912
					$where_entry = array();
2913
					$where_entry['if'] = $if;
2914
					$where_entry['ip_or_subnet'] = get_interface_ipv6($if) . "/" . get_interface_subnetv6($if);
2915
					$where_configured[] = $where_entry;
2916
				}
2917
			} else {
2918
				$if_ipv4 = get_interface_ip($if);
2919
				$if_snbitsv4 = get_interface_subnet($if);
2920
				if ($if_ipv4 && $if_snbitsv4 && check_subnets_overlap($ipaddr, $cidrprefix, $if_ipv4, $if_snbitsv4)) {
2921
					$where_entry = array();
2922
					$where_entry['if'] = $if;
2923
					$where_entry['ip_or_subnet'] = get_interface_ip($if) . "/" . get_interface_subnet($if);
2924
					$where_configured[] = $where_entry;
2925
				}
2926
			}
2927
		}
2928
	} else {
2929
		if ($isipv6) {
2930
			$interface_list_ips = get_configured_ipv6_addresses();
2931
		} else {
2932
			$interface_list_ips = get_configured_ip_addresses();
2933
		}
2934

    
2935
		foreach ($interface_list_ips as $if => $ilips) {
2936
			if ($ignore_if == $if) {
2937
				continue;
2938
			}
2939
			if (strcasecmp($ipaddr, $ilips) == 0) {
2940
				$where_entry = array();
2941
				$where_entry['if'] = $if;
2942
				$where_entry['ip_or_subnet'] = $ilips;
2943
				$where_configured[] = $where_entry;
2944
			}
2945
		}
2946
	}
2947

    
2948
	if ($check_localip) {
2949
		if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0)) {
2950
			$where_entry = array();
2951
			$where_entry['if'] = 'l2tp';
2952
			$where_entry['ip_or_subnet'] = $config['l2tp']['localip'];
2953
			$where_configured[] = $where_entry;
2954
		}
2955
	}
2956

    
2957
	return $where_configured;
2958
}
2959

    
2960
/****f* pfsense-utils/pfSense_handle_custom_code
2961
 * NAME
2962
 *   pfSense_handle_custom_code
2963
 * INPUTS
2964
 *   directory name to process
2965
 * RESULT
2966
 *   globs the directory and includes the files
2967
 */
2968
function pfSense_handle_custom_code($src_dir) {
2969
	// Allow extending of the nat edit page and include custom input validation
2970
	if (is_dir("$src_dir")) {
2971
		$cf = glob($src_dir . "/*.inc");
2972
		foreach ($cf as $nf) {
2973
			if ($nf == "." || $nf == "..") {
2974
				continue;
2975
			}
2976
			// Include the extra handler
2977
			include_once("$nf");
2978
		}
2979
	}
2980
}
2981

    
2982
function set_language() {
2983
	global $config, $g;
2984

    
2985
	if (!empty($config['system']['language'])) {
2986
		$lang = $config['system']['language'];
2987
	} elseif (!empty($g['language'])) {
2988
		$lang = $g['language'];
2989
	}
2990
	$lang .= ".UTF-8";
2991

    
2992
	putenv("LANG={$lang}");
2993
	setlocale(LC_ALL, $lang);
2994
	textdomain("pfSense");
2995
	bindtextdomain("pfSense", "/usr/local/share/locale");
2996
	bind_textdomain_codeset("pfSense", $lang);
2997
}
2998

    
2999
function get_locale_list() {
3000
	$locales = array(
3001
		"en_US" => gettext("English"),
3002
		"pt_BR" => gettext("Portuguese (Brazil)"),
3003
		"tr" => gettext("Turkish"),
3004
	);
3005
	asort($locales);
3006
	return $locales;
3007
}
3008

    
3009
function return_hex_ipv4($ipv4) {
3010
	if (!is_ipaddrv4($ipv4)) {
3011
		return(false);
3012
	}
3013

    
3014
	/* we need the hex form of the interface IPv4 address */
3015
	$ip4arr = explode(".", $ipv4);
3016
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
3017
}
3018

    
3019
function convert_ipv6_to_128bit($ipv6) {
3020
	if (!is_ipaddrv6($ipv6)) {
3021
		return(false);
3022
	}
3023

    
3024
	$ip6arr = array();
3025
	$ip6prefix = Net_IPv6::uncompress($ipv6);
3026
	$ip6arr = explode(":", $ip6prefix);
3027
	/* binary presentation of the prefix for all 128 bits. */
3028
	$ip6prefixbin = "";
3029
	foreach ($ip6arr as $element) {
3030
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
3031
	}
3032
	return($ip6prefixbin);
3033
}
3034

    
3035
function convert_128bit_to_ipv6($ip6bin) {
3036
	if (strlen($ip6bin) <> 128) {
3037
		return(false);
3038
	}
3039

    
3040
	$ip6arr = array();
3041
	$ip6binarr = array();
3042
	$ip6binarr = str_split($ip6bin, 16);
3043
	foreach ($ip6binarr as $binpart) {
3044
		$ip6arr[] = dechex(bindec($binpart));
3045
	}
3046
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
3047

    
3048
	return($ip6addr);
3049
}
3050

    
3051

    
3052
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
3053
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
3054
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
3055
/* 6to4 is 16 bits, e.g. 65535 */
3056
function calculate_ipv6_delegation_length($if) {
3057
	global $config;
3058

    
3059
	if (!is_array($config['interfaces'][$if])) {
3060
		return false;
3061
	}
3062

    
3063
	switch ($config['interfaces'][$if]['ipaddrv6']) {
3064
		case "6to4":
3065
			$pdlen = 16;
3066
			break;
3067
		case "6rd":
3068
			$rd6cfg = $config['interfaces'][$if];
3069
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
3070
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
3071
			break;
3072
		case "dhcp6":
3073
			$dhcp6cfg = $config['interfaces'][$if];
3074
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
3075
			break;
3076
		default:
3077
			$pdlen = 0;
3078
			break;
3079
	}
3080
	return($pdlen);
3081
}
3082

    
3083
function merge_ipv6_delegated_prefix($prefix, $suffix, $len = 64) {
3084
	$prefix = Net_IPv6::uncompress($prefix, true);
3085
	$suffix = Net_IPv6::uncompress($suffix, true);
3086

    
3087
	/*
3088
	 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
3089
	 *                ^^^^ ^
3090
	 *                |||| \-> 64
3091
	 *                |||\---> 63, 62, 61, 60
3092
	 *                ||\----> 56
3093
	 *                |\-----> 52
3094
	 *                \------> 48
3095
	 */
3096

    
3097
	switch ($len) {
3098
	case 48:
3099
		$prefix_len = 15;
3100
		break;
3101
	case 52:
3102
		$prefix_len = 16;
3103
		break;
3104
	case 56:
3105
		$prefix_len = 17;
3106
		break;
3107
	case 60:
3108
		$prefix_len = 18;
3109
		break;
3110
	/*
3111
	 * XXX 63, 62 and 61 should use 18 but PD can change and if
3112
	 * we let user chose this bit it can end up out of PD network
3113
	 *
3114
	 * Leave this with 20 for now until we find a way to let user
3115
	 * chose it. The side-effect is users with PD with one of these
3116
	 * lengths will not be able to setup DHCP server range for full
3117
	 * PD size, only for last /64 network
3118
	 */
3119
	case 63:
3120
	case 62:
3121
	case 61:
3122
	default:
3123
		$prefix_len = 20;
3124
		break;
3125
	}
3126

    
3127
	return Net_IPv6::compress(substr($prefix, 0, $prefix_len) .
3128
	    substr($suffix, $prefix_len));
3129
}
3130

    
3131
function dhcpv6_pd_str_help($pdlen) {
3132
	$result = '';
3133

    
3134
	switch ($pdlen) {
3135
	case 48:
3136
		$result = '::xxxx:xxxx:xxxx:xxxx:xxxx';
3137
		break;
3138
	case 52:
3139
		$result = '::xxx:xxxx:xxxx:xxxx:xxxx';
3140
		break;
3141
	case 56:
3142
		$result = '::xx:xxxx:xxxx:xxxx:xxxx';
3143
		break;
3144
	case 60:
3145
		$result = '::x:xxxx:xxxx:xxxx:xxxx';
3146
		break;
3147
	/*
3148
	 * XXX 63, 62 and 61 should use same mask of 60 but it would
3149
	 * we let user chose this bit it can end up out of PD network
3150
	 *
3151
	 * Leave this with the same of 64 for now until we find a way to
3152
	 * let user chose it. The side-effect is users with PD with one
3153
	 * of these lengths will not be able to setup DHCP server range
3154
	 * for full PD size, only for last /64 network
3155
	 */
3156
	case 61:
3157
	case 62:
3158
	case 63:
3159
	case 64:
3160
		$result = '::xxxx:xxxx:xxxx:xxxx';
3161
		break;
3162
	}
3163

    
3164
	return $result;
3165
}
3166

    
3167
function huawei_rssi_to_string($rssi) {
3168
	$dbm = array();
3169
	$i = 0;
3170
	$dbstart = -113;
3171
	while ($i < 32) {
3172
		$dbm[$i] = $dbstart + ($i * 2);
3173
		$i++;
3174
	}
3175
	$percent = round(($rssi / 31) * 100);
3176
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
3177
	return $string;
3178
}
3179

    
3180
function huawei_mode_to_string($mode, $submode) {
3181
	$modes[0] = gettext("None");
3182
	$modes[1] = "AMPS";
3183
	$modes[2] = "CDMA";
3184
	$modes[3] = "GSM/GPRS";
3185
	$modes[4] = "HDR";
3186
	$modes[5] = "WCDMA";
3187
	$modes[6] = "GPS";
3188

    
3189
	$submodes[0] = gettext("No Service");
3190
	$submodes[1] = "GSM";
3191
	$submodes[2] = "GPRS";
3192
	$submodes[3] = "EDGE";
3193
	$submodes[4] = "WCDMA";
3194
	$submodes[5] = "HSDPA";
3195
	$submodes[6] = "HSUPA";
3196
	$submodes[7] = "HSDPA+HSUPA";
3197
	$submodes[8] = "TD-SCDMA";
3198
	$submodes[9] = "HSPA+";
3199
	$string = "{$modes[$mode]}, {$submodes[$submode]} " . gettext("Mode");
3200
	return $string;
3201
}
3202

    
3203
function huawei_service_to_string($state) {
3204
	$modes[0] = gettext("No Service");
3205
	$modes[1] = gettext("Restricted Service");
3206
	$modes[2] = gettext("Valid Service");
3207
	$modes[3] = gettext("Restricted Regional Service");
3208
	$modes[4] = gettext("Powersaving Service");
3209
	$string = $modes[$state];
3210
	return $string;
3211
}
3212

    
3213
function huawei_simstate_to_string($state) {
3214
	$modes[0] = gettext("Invalid SIM/locked State");
3215
	$modes[1] = gettext("Valid SIM State");
3216
	$modes[2] = gettext("Invalid SIM CS State");
3217
	$modes[3] = gettext("Invalid SIM PS State");
3218
	$modes[4] = gettext("Invalid SIM CS/PS State");
3219
	$modes[255] = gettext("Missing SIM State");
3220
	$string = $modes[$state];
3221
	return $string;
3222
}
3223

    
3224
function zte_rssi_to_string($rssi) {
3225
	return huawei_rssi_to_string($rssi);
3226
}
3227

    
3228
function zte_mode_to_string($mode, $submode) {
3229
	$modes[0] = gettext("No Service");
3230
	$modes[1] = gettext("Limited Service");
3231
	$modes[2] = "GPRS";
3232
	$modes[3] = "GSM";
3233
	$modes[4] = "UMTS";
3234
	$modes[5] = "EDGE";
3235
	$modes[6] = "HSDPA";
3236

    
3237
	$submodes[0] = "CS_ONLY";
3238
	$submodes[1] = "PS_ONLY";
3239
	$submodes[2] = "CS_PS";
3240
	$submodes[3] = "CAMPED";
3241
	$string = "{$modes[$mode]}, {$submodes[$submode]} " . gettext("Mode");
3242
	return $string;
3243
}
3244

    
3245
function zte_service_to_string($service) {
3246
	$modes[0] = gettext("Initializing Service");
3247
	$modes[1] = gettext("Network Lock error Service");
3248
	$modes[2] = gettext("Network Locked Service");
3249
	$modes[3] = gettext("Unlocked or correct MCC/MNC Service");
3250
	$string = $modes[$service];
3251
	return $string;
3252
}
3253

    
3254
function zte_simstate_to_string($state) {
3255
	$modes[0] = gettext("No action State");
3256
	$modes[1] = gettext("Network lock State");
3257
	$modes[2] = gettext("(U)SIM card lock State");
3258
	$modes[3] = gettext("Network Lock and (U)SIM card Lock State");
3259
	$string = $modes[$state];
3260
	return $string;
3261
}
3262

    
3263
function get_configured_pppoe_server_interfaces() {
3264
	global $config;
3265
	$iflist = array();
3266
	if (is_array($config['pppoes']['pppoe'])) {
3267
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
3268
			if ($pppoe['mode'] == "server") {
3269
				$int = "poes". $pppoe['pppoeid'];
3270
				$iflist[$int] = strtoupper($int);
3271
			}
3272
		}
3273
	}
3274
	return $iflist;
3275
}
3276

    
3277
function get_pppoes_child_interfaces($ifpattern) {
3278
	$if_arr = array();
3279
	if ($ifpattern == "") {
3280
		return;
3281
	}
3282

    
3283
	exec("/sbin/ifconfig", $out, $ret);
3284
	foreach ($out as $line) {
3285
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3286
			$if_arr[] = $match[1];
3287
		}
3288
	}
3289
	return $if_arr;
3290

    
3291
}
3292

    
3293
/****f* pfsense-utils/pkg_call_plugins
3294
 * NAME
3295
 *   pkg_call_plugins
3296
 * INPUTS
3297
 *   $plugin_type value used to search in package configuration if the plugin is used, also used to create the function name
3298
 *   $plugin_params parameters to pass to the plugin function for passing multiple parameters a array can be used.
3299
 * RESULT
3300
 *   returns associative array results from the plugin calls for each package
3301
 * NOTES
3302
 *   This generic function can be used to notify or retrieve results from functions that are defined in packages.
3303
 ******/
3304
function pkg_call_plugins($plugin_type, $plugin_params) {
3305
	global $g, $config;
3306
	$results = array();
3307
	if (!is_array($config['installedpackages']['package'])) {
3308
		return $results;
3309
	}
3310
	foreach ($config['installedpackages']['package'] as $package) {
3311
		if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
3312
			continue;
3313
		}
3314
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], 'packagegui');
3315
		$pkgname = substr(reverse_strrchr($package['configurationfile'], "."), 0, -1);
3316
		if (is_array($pkg_config['plugins']['item'])) {
3317
			foreach ($pkg_config['plugins']['item'] as $plugin) {
3318
				if ($plugin['type'] == $plugin_type) {
3319
					if (file_exists($pkg_config['include_file'])) {
3320
						require_once($pkg_config['include_file']);
3321
					} else {
3322
						continue;
3323
					}
3324
					$plugin_function = $pkgname . '_'. $plugin_type;
3325
					$results[$pkgname] = call_user_func($plugin_function, $plugin_params);
3326
				}
3327
			}
3328
		}
3329
	}
3330
	return $results;
3331
}
3332

    
3333
function restore_aliastables() {
3334
	global $g, $config;
3335

    
3336
	$dbpath = "{$g['vardb_path']}/aliastables/";
3337

    
3338
	/* restore the alias tables, if we have them */
3339
	$files = glob("{$g['cf_conf_path']}/RAM_Disk_Store{$dbpath}*.tgz");
3340
	if (count($files)) {
3341
		echo "Restoring alias tables...";
3342
		foreach ($files as $file) {
3343
			if (file_exists($file)) {
3344
				$aliastablesrestore = "";
3345
				$aliastablesreturn = "";
3346
				exec("cd /;LANG=C /usr/bin/tar -xzf {$file} 2>&1", $aliastablesrestore, $aliastablesreturn);
3347
				$aliastablesrestore = implode(" ", $aliastablesrestore);
3348
				if ($aliastablesreturn <> 0) {
3349
					log_error(sprintf(gettext('Alias table restore failed exited with %1$s, the error is: %2$s %3$s%4$s'), $aliastablesreturn, $aliastablesrestore, $file, "\n"));
3350
				} else {
3351
					log_error(sprintf(gettext('Alias table restore succeeded exited with %1$s, the result is: %2$s %3$s%4$s'), $aliastablesreturn, $aliastablesrestore, $dbpath.basename($file, ".tgz"), "\n"));
3352
				}
3353
			}
3354
			/* If this backup is still there on a full install, but we aren't going to use ram disks, remove the archive since this is a transition. */
3355
			if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
3356
				unlink_if_exists("{$file}");
3357
			}
3358
		}
3359
		echo "done.\n";
3360
		return true;
3361
	}
3362
	return false;
3363
}
3364

    
3365
?>
(39-39/65)