Project

General

Profile

Download (92.4 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
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 * http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21

    
22
/****f* pfsense-utils/have_natpfruleint_access
23
 * NAME
24
 *   have_natpfruleint_access
25
 * INPUTS
26
 *	none
27
 * RESULT
28
 *   returns true if user has access to edit a specific firewall nat port forward interface
29
 ******/
30
function have_natpfruleint_access($if) {
31
	$security_url = "firewall_nat_edit.php?if=". strtolower($if);
32
	if (isAllowedPage($security_url, $allowed)) {
33
		return true;
34
	}
35
	return false;
36
}
37

    
38
/****f* pfsense-utils/have_ruleint_access
39
 * NAME
40
 *   have_ruleint_access
41
 * INPUTS
42
 *	none
43
 * RESULT
44
 *   returns true if user has access to edit a specific firewall interface
45
 ******/
46
function have_ruleint_access($if) {
47
	$security_url = "firewall_rules.php?if=". strtolower($if);
48
	if (isAllowedPage($security_url)) {
49
		return true;
50
	}
51
	return false;
52
}
53

    
54
/****f* pfsense-utils/does_url_exist
55
 * NAME
56
 *   does_url_exist
57
 * INPUTS
58
 *	none
59
 * RESULT
60
 *   returns true if a url is available
61
 ******/
62
function does_url_exist($url) {
63
	$fd = fopen("$url", "r");
64
	if ($fd) {
65
		fclose($fd);
66
		return true;
67
	} else {
68
		return false;
69
	}
70
}
71

    
72
/****f* pfsense-utils/is_private_ip
73
 * NAME
74
 *   is_private_ip
75
 * INPUTS
76
 *	none
77
 * RESULT
78
 *   returns true if an ip address is in a private range
79
 ******/
80
function is_private_ip($iptocheck) {
81
	$isprivate = false;
82
	$ip_private_list = array(
83
		"10.0.0.0/8",
84
		"100.64.0.0/10",
85
		"172.16.0.0/12",
86
		"192.168.0.0/16",
87
	);
88
	foreach ($ip_private_list as $private) {
89
		if (ip_in_subnet($iptocheck, $private) == true) {
90
			$isprivate = true;
91
		}
92
	}
93
	return $isprivate;
94
}
95

    
96
/****f* pfsense-utils/get_tmp_file
97
 * NAME
98
 *   get_tmp_file
99
 * INPUTS
100
 *	none
101
 * RESULT
102
 *   returns a temporary filename
103
 ******/
104
function get_tmp_file() {
105
	global $g;
106
	return "{$g['tmp_path']}/tmp-" . time();
107
}
108

    
109
/****f* pfsense-utils/get_dns_servers
110
 * NAME
111
 *   get_dns_servers - get system dns servers
112
 * INPUTS
113
 *   none
114
 * RESULT
115
 *   $dns_servers - an array of the dns servers
116
 ******/
117
function get_dns_servers() {
118
	$dns_servers = array();
119
	if (file_exists("/etc/resolv.conf")) {
120
		$dns_s = file("/etc/resolv.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
121
	}
122
	if (is_array($dns_s)) {
123
		foreach ($dns_s as $dns) {
124
			$matches = "";
125
			if (preg_match("/nameserver (.*)/", $dns, $matches)) {
126
				$dns_servers[] = $matches[1];
127
			}
128
		}
129
	}
130
	return array_unique($dns_servers);
131
}
132

    
133
/****f* pfsense-utils/get_css_files
134
 * NAME
135
 *   get_css_files - get a list of the available CSS files (themes)
136
 * INPUTS
137
 *   none
138
 * RESULT
139
 *   $csslist - an array of the CSS files
140
 ******/
141
function get_css_files() {
142
	$csslist = array();
143

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

    
147
	if (is_array($cssfiles)) {
148
		arsort($cssfiles);
149
		$usrcss = $pfscss = $betacss = array();
150

    
151
		foreach ($cssfiles as $css) {
152
			if (strpos($css, "BETA") != 0) {
153
				array_push($betacss, $css);
154
			} else if (strpos($css, "pfSense") != 0) {
155
				array_push($pfscss, $css);
156
			} else {
157
				array_push($usrcss, $css);
158
			}
159
		}
160

    
161
		$css = array_merge($pfscss, $betacss, $usrcss);
162

    
163
		foreach ($css as $file) {
164
			$file = basename($file);
165
			$csslist[$file] = pathinfo($file, PATHINFO_FILENAME);
166
		}
167
	}
168
	return $csslist;
169
}
170

    
171
/****f* pfsense-utils/gen_webguicss_field
172
 * NAME
173
 *   gen_webguicss_field
174
 * INPUTS
175
 *   Pointer to section object
176
 *   Initial value for the field
177
 * RESULT
178
 *   no return value, section object is updated
179
 ******/
180
function gen_webguicss_field(&$section, $value) {
181

    
182
	$csslist = get_css_files();
183

    
184
	if (!isset($csslist[$value])) {
185
		$value = "pfSense.css";
186
	}
187

    
188
	$section->addInput(new Form_Select(
189
		'webguicss',
190
		'Theme',
191
		$value,
192
		$csslist
193
	))->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>'));
194
}
195

    
196
/****f* pfsense-utils/gen_webguifixedmenu_field
197
 * NAME
198
 *   gen_webguifixedmenu_field
199
 * INPUTS
200
 *   Pointer to section object
201
 *   Initial value for the field
202
 * RESULT
203
 *   no return value, section object is updated
204
 ******/
205
function gen_webguifixedmenu_field(&$section, $value) {
206

    
207
	$section->addInput(new Form_Select(
208
		'webguifixedmenu',
209
		'Top Navigation',
210
		$value,
211
		["" => gettext("Scrolls with page"), "fixed" => gettext("Fixed (Remains visible at top of page)")]
212
	))->setHelp("The fixed option is intended for large screens only.");
213
}
214

    
215
/****f* pfsense-utils/gen_webguihostnamemenu_field
216
 * NAME
217
 *   gen_webguihostnamemenu_field
218
 * INPUTS
219
 *   Pointer to section object
220
 *   Initial value for the field
221
 * RESULT
222
 *   no return value, section object is updated
223
 ******/
224
function gen_webguihostnamemenu_field(&$section, $value) {
225

    
226
	$section->addInput(new Form_Select(
227
		'webguihostnamemenu',
228
		'Hostname in Menu',
229
		$value,
230
		["" => gettext("Default (No hostname)"), "hostonly" => gettext("Hostname only"), "fqdn" => gettext("Fully Qualified Domain Name")]
231
	))->setHelp("Replaces the Help menu title in the Navbar with the system hostname or FQDN.");
232
}
233

    
234
/****f* pfsense-utils/gen_dashboardcolumns_field
235
 * NAME
236
 *   gen_dashboardcolumns_field
237
 * INPUTS
238
 *   Pointer to section object
239
 *   Initial value for the field
240
 * RESULT
241
 *   no return value, section object is updated
242
 ******/
243
function gen_dashboardcolumns_field(&$section, $value) {
244

    
245
	if (($value < 1) || ($value > 4)) {
246
		$value = 2;
247
	}
248

    
249
	$section->addInput(new Form_Input(
250
		'dashboardcolumns',
251
		'Dashboard Columns',
252
		'number',
253
		$value,
254
		[min => 1, max => 4]
255
	));
256
}
257

    
258
/****f* pfsense-utils/gen_associatedpanels_fields
259
 * NAME
260
 *   gen_associatedpanels_fields
261
 * INPUTS
262
 *   Pointer to section object
263
 *   Initial value for each of the fields
264
 * RESULT
265
 *   no return value, section object is updated
266
 ******/
267
function gen_associatedpanels_fields(&$section, $value1, $value2, $value3, $value4) {
268

    
269
	$group = new Form_Group('Associated Panels Show/Hide');
270

    
271
	$group->add(new Form_Checkbox(
272
		'dashboardavailablewidgetspanel',
273
		null,
274
		'Available Widgets',
275
		$value1
276
		))->setHelp('Show the Available Widgets panel on the Dashboard.');
277

    
278
	$group->add(new Form_Checkbox(
279
		'systemlogsfilterpanel',
280
		null,
281
		'Log Filter',
282
		$value2
283
	))->setHelp('Show the Log Filter panel in System Logs.');
284

    
285
	$group->add(new Form_Checkbox(
286
		'systemlogsmanagelogpanel',
287
		null,
288
		'Manage Log',
289
		$value3
290
	))->setHelp('Show the Manage Log panel in System Logs.');
291

    
292
	$group->add(new Form_Checkbox(
293
		'statusmonitoringsettingspanel',
294
		null,
295
		'Monitoring Settings',
296
		$value4
297
	))->setHelp('Show the Settings panel in Status Monitoring.');
298

    
299
	$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.');
300

    
301
	$section->add($group);
302
}
303

    
304
/****f* pfsense-utils/gen_webguileftcolumnhyper_field
305
 * NAME
306
 *   gen_webguileftcolumnhyper_field
307
 * INPUTS
308
 *   Pointer to section object
309
 *   Initial value for the field
310
 * RESULT
311
 *   no return value, section object is updated
312
 ******/
313
function gen_webguileftcolumnhyper_field(&$section, $value) {
314

    
315
	$section->addInput(new Form_Checkbox(
316
		'webguileftcolumnhyper',
317
		'Left Column Labels',
318
		'Active',
319
		$value
320
	))->setHelp('If selected, clicking a label in the left column will select/toggle the first item of the group.');
321
}
322

    
323
/****f* pfsense-utils/gen_pagenamefirst_field
324
 * NAME
325
 *   gen_pagenamefirst_field
326
 * INPUTS
327
 *   Pointer to section object
328
 *   Initial value for the field
329
 * RESULT
330
 *   no return value, section object is updated
331
 ******/
332
function gen_pagenamefirst_field(&$section, $value) {
333

    
334
	$section->addInput(new Form_Checkbox(
335
		'pagenamefirst',
336
		'Browser tab text',
337
		'Display page name first in browser tab',
338
		$value
339
	))->setHelp('When this is unchecked, the browser tab shows the host name followed '.
340
		'by the current page. Check this box to display the current page followed by the '.
341
		'host name.');
342
}
343

    
344
/****f* pfsense-utils/gen_user_settings_fields
345
 * NAME
346
 *   gen_user_settings_fields
347
 * INPUTS
348
 *   Pointer to section object
349
 *   Array of initial values for the fields
350
 * RESULT
351
 *   no return value, section object is updated
352
 ******/
353
function gen_user_settings_fields(&$section, $pconfig) {
354

    
355
	gen_webguicss_field($section, $pconfig['webguicss']);
356
	gen_webguifixedmenu_field($section, $pconfig['webguifixedmenu']);
357
	gen_webguihostnamemenu_field($section, $pconfig['webguihostnamemenu']);
358
	gen_dashboardcolumns_field($section, $pconfig['dashboardcolumns']);
359
	gen_associatedpanels_fields(
360
		$section,
361
		$pconfig['dashboardavailablewidgetspanel'],
362
		$pconfig['systemlogsfilterpanel'],
363
		$pconfig['systemlogsmanagelogpanel'],
364
		$pconfig['statusmonitoringsettingspanel']);
365
	gen_webguileftcolumnhyper_field($section, $pconfig['webguileftcolumnhyper']);
366
	gen_pagenamefirst_field($section, $pconfig['pagenamefirst']);
367
}
368

    
369
function hardware_offloading_applyflags($iface) {
370
	global $config;
371

    
372
	$flags_on = 0;
373
	$flags_off = 0;
374
	$options = pfSense_get_interface_addresses($iface);
375

    
376
	if (isset($config['system']['disablechecksumoffloading'])) {
377
		if (isset($options['encaps']['txcsum'])) {
378
			$flags_off |= IFCAP_TXCSUM;
379
		}
380
		if (isset($options['encaps']['rxcsum'])) {
381
			$flags_off |= IFCAP_RXCSUM;
382
		}
383
	} else {
384
		if (isset($options['caps']['txcsum'])) {
385
			$flags_on |= IFCAP_TXCSUM;
386
		}
387
		if (isset($options['caps']['rxcsum'])) {
388
			$flags_on |= IFCAP_RXCSUM;
389
		}
390
	}
391

    
392
	if (isset($config['system']['disablesegmentationoffloading'])) {
393
		$flags_off |= IFCAP_TSO;
394
	} else if (isset($options['caps']['tso']) || isset($options['caps']['tso4']) || isset($options['caps']['tso6'])) {
395
		$flags_on |= IFCAP_TSO;
396
	}
397

    
398
	if (isset($config['system']['disablelargereceiveoffloading'])) {
399
		$flags_off |= IFCAP_LRO;
400
	} else if (isset($options['caps']['lro'])) {
401
		$flags_on |= IFCAP_LRO;
402
	}
403

    
404
	/* if the NIC supports polling *AND* it is enabled in the GUI */
405
	if (!isset($config['system']['polling'])) {
406
		$flags_off |= IFCAP_POLLING;
407
	} else if (isset($options['caps']['polling'])) {
408
		$flags_on |= IFCAP_POLLING;
409
	}
410

    
411
	pfSense_interface_capabilities($iface, -$flags_off);
412
	pfSense_interface_capabilities($iface, $flags_on);
413
}
414

    
415
/****f* pfsense-utils/enable_hardware_offloading
416
 * NAME
417
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
418
 * INPUTS
419
 *   $interface	- string containing the physical interface to work on.
420
 * RESULT
421
 *   null
422
 * NOTES
423
 *   This function only supports the fxp driver's loadable microcode.
424
 ******/
425
function enable_hardware_offloading($interface) {
426
	global $g, $config;
427

    
428
	$int = get_real_interface($interface);
429
	if (empty($int)) {
430
		return;
431
	}
432

    
433
	if (!isset($config['system']['do_not_use_nic_microcode'])) {
434
		/* translate wan, lan, opt -> real interface if needed */
435
		$int_family = preg_split("/[0-9]+/", $int);
436
		$supported_ints = array('fxp');
437
		if (in_array($int_family, $supported_ints)) {
438
			if (does_interface_exist($int)) {
439
				pfSense_interface_flags($int, IFF_LINK0);
440
			}
441
		}
442
	}
443

    
444
	/* This is mostly for vlans and ppp types */
445
	$realhwif = get_parent_interface($interface);
446
	if ($realhwif[0] == $int) {
447
		hardware_offloading_applyflags($int);
448
	} else {
449
		hardware_offloading_applyflags($realhwif[0]);
450
		hardware_offloading_applyflags($int);
451
	}
452
}
453

    
454
/****f* pfsense-utils/interface_supports_polling
455
 * NAME
456
 *   checks to see if an interface supports polling according to man polling
457
 * INPUTS
458
 *
459
 * RESULT
460
 *   true or false
461
 * NOTES
462
 *
463
 ******/
464
function interface_supports_polling($iface) {
465
	$opts = pfSense_get_interface_addresses($iface);
466
	if (is_array($opts) && isset($opts['caps']['polling'])) {
467
		return true;
468
	}
469

    
470
	return false;
471
}
472

    
473
/****f* pfsense-utils/is_alias_inuse
474
 * NAME
475
 *   checks to see if an alias is currently in use by a rule
476
 * INPUTS
477
 *
478
 * RESULT
479
 *   true or false
480
 * NOTES
481
 *
482
 ******/
483
function is_alias_inuse($alias) {
484
	global $g, $config;
485

    
486
	if ($alias == "") {
487
		return false;
488
	}
489
	/* loop through firewall rules looking for alias in use */
490
	if (is_array($config['filter']['rule'])) {
491
		foreach ($config['filter']['rule'] as $rule) {
492
			if ($rule['source']['address']) {
493
				if ($rule['source']['address'] == $alias) {
494
					return true;
495
				}
496
			}
497
			if ($rule['destination']['address']) {
498
				if ($rule['destination']['address'] == $alias) {
499
					return true;
500
				}
501
			}
502
		}
503
	}
504
	/* loop through nat rules looking for alias in use */
505
	if (is_array($config['nat']['rule'])) {
506
		foreach ($config['nat']['rule'] as $rule) {
507
			if ($rule['target'] && $rule['target'] == $alias) {
508
				return true;
509
			}
510
			if ($rule['source']['address'] && $rule['source']['address'] == $alias) {
511
				return true;
512
			}
513
			if ($rule['destination']['address'] && $rule['destination']['address'] == $alias) {
514
				return true;
515
			}
516
		}
517
	}
518
	return false;
519
}
520

    
521
/****f* pfsense-utils/is_schedule_inuse
522
 * NAME
523
 *   checks to see if a schedule is currently in use by a rule
524
 * INPUTS
525
 *
526
 * RESULT
527
 *   true or false
528
 * NOTES
529
 *
530
 ******/
531
function is_schedule_inuse($schedule) {
532
	global $g, $config;
533

    
534
	if ($schedule == "") {
535
		return false;
536
	}
537
	/* loop through firewall rules looking for schedule in use */
538
	if (is_array($config['filter']['rule'])) {
539
		foreach ($config['filter']['rule'] as $rule) {
540
			if ($rule['sched'] == $schedule) {
541
				return true;
542
			}
543
		}
544
	}
545
	return false;
546
}
547

    
548
/****f* pfsense-utils/setup_polling
549
 * NAME
550
 *   sets up polling
551
 * INPUTS
552
 *
553
 * RESULT
554
 *   null
555
 * NOTES
556
 *
557
 ******/
558
function setup_polling() {
559
	global $g, $config;
560

    
561
	if (isset($config['system']['polling'])) {
562
		set_single_sysctl("kern.polling.idle_poll", "1");
563
	} else {
564
		set_single_sysctl("kern.polling.idle_poll", "0");
565
	}
566

    
567
	if ($config['system']['polling_each_burst']) {
568
		set_single_sysctl("kern.polling.each_burst", $config['system']['polling_each_burst']);
569
	}
570
	if ($config['system']['polling_burst_max']) {
571
		set_single_sysctl("kern.polling.burst_max", $config['system']['polling_burst_max']);
572
	}
573
	if ($config['system']['polling_user_frac']) {
574
		set_single_sysctl("kern.polling.user_frac", $config['system']['polling_user_frac']);
575
	}
576
}
577

    
578
/****f* pfsense-utils/setup_microcode
579
 * NAME
580
 *   enumerates all interfaces and calls enable_hardware_offloading which
581
 *   enables a NIC's supported hardware features.
582
 * INPUTS
583
 *
584
 * RESULT
585
 *   null
586
 * NOTES
587
 *   This function only supports the fxp driver's loadable microcode.
588
 ******/
589
function setup_microcode() {
590

    
591
	/* if list */
592
	$iflist = get_configured_interface_list(false, true);
593
	foreach ($iflist as $if => $ifdescr) {
594
		enable_hardware_offloading($if);
595
	}
596
	unset($iflist);
597
}
598

    
599
/****f* pfsense-utils/get_carp_status
600
 * NAME
601
 *   get_carp_status - Return whether CARP is enabled or disabled.
602
 * RESULT
603
 *   boolean	- true if CARP is enabled, false if otherwise.
604
 ******/
605
function get_carp_status() {
606
	/* grab the current status of carp */
607
	$status = get_single_sysctl('net.inet.carp.allow');
608
	return (intval($status) > 0);
609
}
610

    
611
/*
612
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
613

    
614
 */
615
function convert_ip_to_network_format($ip, $subnet) {
616
	$ipsplit = explode('.', $ip);
617
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
618
	return $string;
619
}
620

    
621
/*
622
 * get_carp_interface_status($carpid): returns the status of a carp uniqid
623
 */
624
function get_carp_interface_status($carpid) {
625

    
626
	$carpiface = get_configured_vip_interface($carpid);
627
	if ($carpiface == NULL)
628
		return "";
629
	$interface = get_real_interface($carpiface);
630
	if ($interface == NULL)
631
		return "";
632

    
633
	$vhid = $carp['vhid'];
634
	$carp_query = '';
635
	$_gb = exec("/sbin/ifconfig $interface | /usr/bin/grep carp: | /usr/bin/grep \"vhid $vhid\"", $carp_query);
636
	foreach ($carp_query as $int) {
637
		if (stripos($int, "MASTER"))
638
			return "MASTER";
639
		elseif (stripos($int, "BACKUP"))
640
			return "BACKUP";
641
		elseif (stripos($int, "INIT"))
642
			return "INIT";
643
	}
644

    
645
	return "";
646
}
647

    
648
/*
649
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
650
 */
651
function get_pfsync_interface_status($pfsyncinterface) {
652
	if (!does_interface_exist($pfsyncinterface)) {
653
		return;
654
	}
655

    
656
	return exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/awk '/pfsync:/ {print \$5}'");
657
}
658

    
659
/*
660
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
661
 */
662
function add_rule_to_anchor($anchor, $rule, $label) {
663
	mwexec("echo " . escapeshellarg($rule) . " | /sbin/pfctl -a " . escapeshellarg($anchor) . ":" . escapeshellarg($label) . " -f -");
664
}
665

    
666
/*
667
 * remove_text_from_file
668
 * remove $text from file $file
669
 */
670
function remove_text_from_file($file, $text) {
671
	if (!file_exists($file) && !is_writable($file)) {
672
		return;
673
	}
674
	$filecontents = file_get_contents($file);
675
	$text = str_replace($text, "", $filecontents);
676
	@file_put_contents($file, $text);
677
}
678

    
679
/*
680
 *   after_sync_bump_adv_skew(): create skew values by 1S
681
 */
682
function after_sync_bump_adv_skew() {
683
	global $config, $g;
684
	$processed_skew = 1;
685
	$a_vip = &$config['virtualip']['vip'];
686
	foreach ($a_vip as $vipent) {
687
		if ($vipent['advskew'] <> "") {
688
			$processed_skew = 1;
689
			$vipent['advskew'] = $vipent['advskew']+1;
690
		}
691
	}
692
	if ($processed_skew == 1) {
693
		write_config(gettext("After synch increase advertising skew"));
694
	}
695
}
696

    
697
/*
698
 * get_filename_from_url($url): converts a url to its filename.
699
 */
700
function get_filename_from_url($url) {
701
	return basename($url);
702
}
703

    
704
/*
705
 *   get_dir: return an array of $dir
706
 */
707
function get_dir($dir) {
708
	$dir_array = array();
709
	$d = dir($dir);
710
	if (!is_object($d)) {
711
		return array();
712
	}
713
	while (false !== ($entry = $d->read())) {
714
		array_push($dir_array, $entry);
715
	}
716
	$d->close();
717
	return $dir_array;
718
}
719

    
720
/****f* pfsense-utils/WakeOnLan
721
 * NAME
722
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
723
 * RESULT
724
 *   true/false - true if the operation was successful
725
 ******/
726
function WakeOnLan($addr, $mac) {
727
	$addr_byte = explode(':', $mac);
728
	$hw_addr = '';
729

    
730
	for ($a = 0; $a < 6; $a++) {
731
		$hw_addr .= chr(hexdec($addr_byte[$a]));
732
	}
733

    
734
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
735

    
736
	for ($a = 1; $a <= 16; $a++) {
737
		$msg .= $hw_addr;
738
	}
739

    
740
	// send it to the broadcast address using UDP
741
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
742
	if ($s == false) {
743
		log_error(gettext("Error creating socket!"));
744
		log_error(sprintf(gettext("Error code is '%1\$s' - %2\$s"), socket_last_error($s), socket_strerror(socket_last_error($s))));
745
	} else {
746
		// setting a broadcast option to socket:
747
		$opt_ret = socket_set_option($s, 1, 6, TRUE);
748
		if ($opt_ret < 0) {
749
			log_error(sprintf(gettext("setsockopt() failed, error: %s"), strerror($opt_ret)));
750
		}
751
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
752
		socket_close($s);
753
		log_error(sprintf(gettext('Magic Packet sent (%1$s) to (%2$s) MAC=%3$s'), $e, $addr, $mac));
754
		return true;
755
	}
756

    
757
	return false;
758
}
759

    
760
/*
761
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
762
 *					 Useful for finding paths and stripping file extensions.
763
 */
764
function reverse_strrchr($haystack, $needle) {
765
	if (!is_string($haystack)) {
766
		return;
767
	}
768
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1) : false;
769
}
770

    
771
/*
772
 *  backup_config_section($section): returns as an xml file string of
773
 *                                   the configuration section
774
 */
775
function backup_config_section($section_name) {
776
	global $config;
777
	$new_section = &$config[$section_name];
778
	/* generate configuration XML */
779
	$xmlconfig = dump_xml_config($new_section, $section_name);
780
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
781
	return $xmlconfig;
782
}
783

    
784
/*
785
 *  restore_config_section($section_name, new_contents): restore a configuration section,
786
 *                                                  and write the configuration out
787
 *                                                  to disk/cf.
788
 */
789
function restore_config_section($section_name, $new_contents) {
790
	global $config, $g;
791
	conf_mount_rw();
792
	$fout = fopen("{$g['tmp_path']}/tmpxml", "w");
793
	fwrite($fout, $new_contents);
794
	fclose($fout);
795

    
796
	$xml = parse_xml_config($g['tmp_path'] . "/tmpxml", null);
797
	if ($xml['pfsense']) {
798
		$xml = $xml['pfsense'];
799
	}
800
	else if ($xml['m0n0wall']) {
801
		$xml = $xml['m0n0wall'];
802
	}
803
	if ($xml[$section_name]) {
804
		$section_xml = $xml[$section_name];
805
	} else {
806
		$section_xml = -1;
807
	}
808

    
809
	@unlink($g['tmp_path'] . "/tmpxml");
810
	if ($section_xml === -1) {
811
		return false;
812
	}
813
	$config[$section_name] = &$section_xml;
814
	if (file_exists("{$g['tmp_path']}/config.cache")) {
815
		unlink("{$g['tmp_path']}/config.cache");
816
	}
817
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
818
	disable_security_checks();
819
	conf_mount_ro();
820
	return true;
821
}
822

    
823
/*
824
 *  merge_config_section($section_name, new_contents):   restore a configuration section,
825
 *                                                  and write the configuration out
826
 *                                                  to disk/cf.  But preserve the prior
827
 * 													structure if needed
828
 */
829
function merge_config_section($section_name, $new_contents) {
830
	global $config;
831
	conf_mount_rw();
832
	$fname = get_tmp_filename();
833
	$fout = fopen($fname, "w");
834
	fwrite($fout, $new_contents);
835
	fclose($fout);
836
	$section_xml = parse_xml_config($fname, $section_name);
837
	$config[$section_name] = $section_xml;
838
	unlink($fname);
839
	write_config(sprintf(gettext("Restored %s of config file (maybe from CARP partner)"), $section_name));
840
	disable_security_checks();
841
	conf_mount_ro();
842
	return;
843
}
844

    
845
/*
846
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
847
 */
848
if (!function_exists('php_check_syntax')) {
849
	global $g;
850
	function php_check_syntax($code_to_check, &$errormessage) {
851
		return false;
852
		$fout = fopen("{$g['tmp_path']}/codetocheck.php", "w");
853
		$code = $_POST['content'];
854
		$code = str_replace("<?php", "", $code);
855
		$code = str_replace("?>", "", $code);
856
		fwrite($fout, "<?php\n\n");
857
		fwrite($fout, $code_to_check);
858
		fwrite($fout, "\n\n?>\n");
859
		fclose($fout);
860
		$command = "/usr/local/bin/php-cgi -l {$g['tmp_path']}/codetocheck.php";
861
		$output = exec_command($command);
862
		if (stristr($output, "Errors parsing") == false) {
863
			echo "false\n";
864
			$errormessage = '';
865
			return(false);
866
		} else {
867
			$errormessage = $output;
868
			return(true);
869
		}
870
	}
871
}
872

    
873
/*
874
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
875
 */
876
if (!function_exists('php_check_syntax')) {
877
	function php_check_syntax($code_to_check, &$errormessage) {
878
		return false;
879
		$command = "/usr/local/bin/php-cgi -l " . escapeshellarg($code_to_check);
880
		$output = exec_command($command);
881
		if (stristr($output, "Errors parsing") == false) {
882
			echo "false\n";
883
			$errormessage = '';
884
			return(false);
885
		} else {
886
			$errormessage = $output;
887
			return(true);
888
		}
889
	}
890
}
891

    
892
/*
893
 * rmdir_recursive($path, $follow_links=false)
894
 * Recursively remove a directory tree (rm -rf path)
895
 * This is for directories _only_
896
 */
897
function rmdir_recursive($path, $follow_links=false) {
898
	$to_do = glob($path);
899
	if (!is_array($to_do)) {
900
		$to_do = array($to_do);
901
	}
902
	foreach ($to_do as $workingdir) { // Handle wildcards by foreaching.
903
		if (file_exists($workingdir)) {
904
			if (is_dir($workingdir)) {
905
				$dir = opendir($workingdir);
906
				while ($entry = readdir($dir)) {
907
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry"))) {
908
						unlink("$workingdir/$entry");
909
					} elseif (is_dir("$workingdir/$entry") && $entry != '.' && $entry != '..') {
910
						rmdir_recursive("$workingdir/$entry");
911
					}
912
				}
913
				closedir($dir);
914
				rmdir($workingdir);
915
			} elseif (is_file($workingdir)) {
916
				unlink($workingdir);
917
			}
918
		}
919
	}
920
	return;
921
}
922

    
923
/*
924
 * host_firmware_version(): Return the versions used in this install
925
 */
926
function host_firmware_version($tocheck = "") {
927
	global $g, $config;
928

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

    
931
	return array(
932
		"firmware" => array("version" => $g['product_version']),
933
		"kernel"   => array("version" => $os_version),
934
		"base"     => array("version" => $os_version),
935
		"platform" => trim(file_get_contents('/etc/platform', " \n")),
936
		"config_version" => $config['version']
937
	);
938
}
939

    
940
function get_disk_info() {
941
	$diskout = "";
942
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
943
	return explode(' ', $diskout[0]);
944
}
945

    
946
/****f* pfsense-utils/strncpy
947
 * NAME
948
 *   strncpy - copy strings
949
 * INPUTS
950
 *   &$dst, $src, $length
951
 * RESULT
952
 *   none
953
 ******/
954
function strncpy(&$dst, $src, $length) {
955
	if (strlen($src) > $length) {
956
		$dst = substr($src, 0, $length);
957
	} else {
958
		$dst = $src;
959
	}
960
}
961

    
962
/****f* pfsense-utils/reload_interfaces_sync
963
 * NAME
964
 *   reload_interfaces - reload all interfaces
965
 * INPUTS
966
 *   none
967
 * RESULT
968
 *   none
969
 ******/
970
function reload_interfaces_sync() {
971
	global $config, $g;
972

    
973
	if ($g['debug']) {
974
		log_error(gettext("reload_interfaces_sync() is starting."));
975
	}
976

    
977
	/* parse config.xml again */
978
	$config = parse_config(true);
979

    
980
	/* enable routing */
981
	system_routing_enable();
982
	if ($g['debug']) {
983
		log_error(gettext("Enabling system routing"));
984
	}
985

    
986
	if ($g['debug']) {
987
		log_error(gettext("Cleaning up Interfaces"));
988
	}
989

    
990
	/* set up interfaces */
991
	interfaces_configure();
992
}
993

    
994
/****f* pfsense-utils/reload_all
995
 * NAME
996
 *   reload_all - triggers a reload of all settings
997
 *   * INPUTS
998
 *   none
999
 * RESULT
1000
 *   none
1001
 ******/
1002
function reload_all() {
1003
	send_event("service reload all");
1004
}
1005

    
1006
/****f* pfsense-utils/reload_interfaces
1007
 * NAME
1008
 *   reload_interfaces - triggers a reload of all interfaces
1009
 * INPUTS
1010
 *   none
1011
 * RESULT
1012
 *   none
1013
 ******/
1014
function reload_interfaces() {
1015
	send_event("interface all reload");
1016
}
1017

    
1018
/****f* pfsense-utils/reload_all_sync
1019
 * NAME
1020
 *   reload_all - reload all settings
1021
 *   * INPUTS
1022
 *   none
1023
 * RESULT
1024
 *   none
1025
 ******/
1026
function reload_all_sync() {
1027
	global $config, $g;
1028

    
1029
	/* parse config.xml again */
1030
	$config = parse_config(true);
1031

    
1032
	/* set up our timezone */
1033
	system_timezone_configure();
1034

    
1035
	/* set up our hostname */
1036
	system_hostname_configure();
1037

    
1038
	/* make hosts file */
1039
	system_hosts_generate();
1040

    
1041
	/* generate resolv.conf */
1042
	system_resolvconf_generate();
1043

    
1044
	/* enable routing */
1045
	system_routing_enable();
1046

    
1047
	/* set up interfaces */
1048
	interfaces_configure();
1049

    
1050
	/* start dyndns service */
1051
	services_dyndns_configure();
1052

    
1053
	/* configure cron service */
1054
	configure_cron();
1055

    
1056
	/* start the NTP client */
1057
	system_ntp_configure();
1058

    
1059
	/* sync pw database */
1060
	conf_mount_rw();
1061
	unlink_if_exists("/etc/spwd.db.tmp");
1062
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1063
	conf_mount_ro();
1064

    
1065
	/* restart sshd */
1066
	send_event("service restart sshd");
1067

    
1068
	/* restart webConfigurator if needed */
1069
	send_event("service restart webgui");
1070
}
1071

    
1072
function setup_serial_port($when = "save", $path = "") {
1073
	global $g, $config;
1074
	conf_mount_rw();
1075
	$ttys_file = "{$path}/etc/ttys";
1076
	$boot_config_file = "{$path}/boot.config";
1077
	$loader_conf_file = "{$path}/boot/loader.conf";
1078
	/* serial console - write out /boot.config */
1079
	if (file_exists($boot_config_file)) {
1080
		$boot_config = file_get_contents($boot_config_file);
1081
	} else {
1082
		$boot_config = "";
1083
	}
1084

    
1085
	$serialspeed = (is_numeric($config['system']['serialspeed'])) ? $config['system']['serialspeed'] : "115200";
1086
	if ($g['platform'] != "cdrom") {
1087
		$serial_only = false;
1088

    
1089
		if (($g['platform'] == "nanobsd") && isset($g['enableserial_force'])) {
1090
			$serial_only = true;
1091
		} else {
1092
			$specific_platform = system_identify_specific_platform();
1093
			if ($specific_platform['name'] == 'RCC-VE' ||
1094
			    $specific_platform['name'] == 'RCC' ||
1095
			    $specific_platform['name'] == 'RCC-DFF') {
1096
				$serial_only = true;
1097
			}
1098
		}
1099

    
1100
		$boot_config_split = explode("\n", $boot_config);
1101
		$fd = fopen($boot_config_file, "w");
1102
		if ($fd) {
1103
			foreach ($boot_config_split as $bcs) {
1104
				if (stristr($bcs, "-D") || stristr($bcs, "-h")) {
1105
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1106
				} else {
1107
					if ($bcs <> "") {
1108
						fwrite($fd, "{$bcs}\n");
1109
					}
1110
				}
1111
			}
1112
			if ($serial_only === true) {
1113
				fwrite($fd, "-S{$serialspeed} -h");
1114
			} else if (is_serial_enabled()) {
1115
				fwrite($fd, "-S{$serialspeed} -D");
1116
			}
1117
			fclose($fd);
1118
		}
1119

    
1120
		/* serial console - write out /boot/loader.conf */
1121
		if ($when == "upgrade") {
1122
			system("echo \"Reading {$loader_conf_file}...\" >> /conf/upgrade_log.txt");
1123
		}
1124
		$boot_config = file_get_contents($loader_conf_file);
1125
		$boot_config_split = explode("\n", $boot_config);
1126
		if (count($boot_config_split) > 0) {
1127
			$new_boot_config = array();
1128
			// Loop through and only add lines that are not empty, and which
1129
			//  do not contain a console directive.
1130
			foreach ($boot_config_split as $bcs) {
1131
				if (!empty($bcs) &&
1132
				    (stripos($bcs, "console") === false) &&
1133
				    (stripos($bcs, "boot_multicons") === false) &&
1134
				    (stripos($bcs, "boot_serial") === false) &&
1135
				    (stripos($bcs, "hw.usb.no_pf") === false) &&
1136
				    (stripos($bcs, "hint.uart.0.flags") === false) &&
1137
				    (stripos($bcs, "hint.uart.1.flags") === false)) {
1138
					$new_boot_config[] = $bcs;
1139
				}
1140
			}
1141

    
1142
			if ($serial_only === true) {
1143
				$new_boot_config[] = 'boot_serial="YES"';
1144
				$new_boot_config[] = 'console="comconsole"';
1145
			} else if (is_serial_enabled()) {
1146
				$new_boot_config[] = 'boot_multicons="YES"';
1147
				$new_boot_config[] = 'boot_serial="YES"';
1148
				$primaryconsole = isset($g['primaryconsole_force']) ? $g['primaryconsole_force'] : $config['system']['primaryconsole'];
1149
				switch ($primaryconsole) {
1150
					case "video":
1151
						$new_boot_config[] = 'console="vidconsole,comconsole"';
1152
						break;
1153
					case "serial":
1154
					default:
1155
						$new_boot_config[] = 'console="comconsole,vidconsole"';
1156
				}
1157
			}
1158
			$new_boot_config[] = 'comconsole_speed="' . $serialspeed . '"';
1159

    
1160
			$specplatform = system_identify_specific_platform();
1161
			if ($specplatform['name'] == 'RCC-VE' ||
1162
			    $specplatform['name'] == 'RCC' ||
1163
			    $specplatform['name'] == 'RCC-DFF') {
1164
				$new_boot_config[] = 'comconsole_port="0x2F8"';
1165
				$new_boot_config[] = 'hint.uart.0.flags="0x00"';
1166
				$new_boot_config[] = 'hint.uart.1.flags="0x10"';
1167
			}
1168
			$new_boot_config[] = 'hw.usb.no_pf="1"';
1169

    
1170
			file_put_contents($loader_conf_file, implode("\n", $new_boot_config) . "\n");
1171
		}
1172
	}
1173
	$ttys = file_get_contents($ttys_file);
1174
	$ttys_split = explode("\n", $ttys);
1175
	$fd = fopen($ttys_file, "w");
1176

    
1177
	$on_off = (is_serial_enabled() ? 'onifconsole' : 'off');
1178

    
1179
	if (isset($config['system']['disableconsolemenu'])) {
1180
		$console_type = 'Pc';
1181
		$serial_type = '3wire';
1182
	} else {
1183
		$console_type = 'al.Pc';
1184
		$serial_type = 'al.3wire';
1185
	}
1186
	foreach ($ttys_split as $tty) {
1187
		if (stristr($tty, "ttyv0")) {
1188
			fwrite($fd, "ttyv0	\"/usr/libexec/getty {$console_type}\"	xterm	on	secure\n");
1189
		} else if (stristr($tty, "ttyu")) {
1190
			$ttyn = substr($tty, 0, 5);
1191
			fwrite($fd, "{$ttyn}	\"/usr/libexec/getty {$serial_type}\"	vt100	{$on_off}	secure\n");
1192
		} else {
1193
			fwrite($fd, $tty . "\n");
1194
		}
1195
	}
1196
	unset($on_off, $console_type, $serial_type);
1197
	fclose($fd);
1198
	if ($when != "upgrade") {
1199
		reload_ttys();
1200
	}
1201

    
1202
	conf_mount_ro();
1203
	return;
1204
}
1205

    
1206
function is_serial_enabled() {
1207
	global $g, $config;
1208

    
1209
	if (!isset($g['enableserial_force']) &&
1210
	    !isset($config['system']['enableserial']) &&
1211
	    ($g['platform'] == $g['product_name'] || $g['platform'] == "cdrom")) {
1212
		return false;
1213
	}
1214

    
1215
	return true;
1216
}
1217

    
1218
function reload_ttys() {
1219
	// Send a HUP signal to init will make it reload /etc/ttys
1220
	posix_kill(1, SIGHUP);
1221
}
1222

    
1223
function print_value_list($list, $count = 10, $separator = ",") {
1224
	$list = implode($separator, array_slice($list, 0, $count));
1225
	if (count($list) < $count) {
1226
		$list .= ".";
1227
	} else {
1228
		$list .= "...";
1229
	}
1230
	return $list;
1231
}
1232

    
1233
/* DHCP enabled on any interfaces? */
1234
function is_dhcp_server_enabled() {
1235
	global $config;
1236

    
1237
	if (!is_array($config['dhcpd'])) {
1238
		return false;
1239
	}
1240

    
1241
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1242
		if (isset($dhcpifconf['enable']) && !empty($config['interfaces'][$dhcpif])) {
1243
			return true;
1244
		}
1245
	}
1246

    
1247
	return false;
1248
}
1249

    
1250
/* DHCP enabled on any interfaces? */
1251
function is_dhcpv6_server_enabled() {
1252
	global $config;
1253

    
1254
	if (is_array($config['interfaces'])) {
1255
		foreach ($config['interfaces'] as $ifcfg) {
1256
			if (isset($ifcfg['enable']) && !empty($ifcfg['track6-interface'])) {
1257
				return true;
1258
			}
1259
		}
1260
	}
1261

    
1262
	if (!is_array($config['dhcpdv6'])) {
1263
		return false;
1264
	}
1265

    
1266
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
1267
		if (isset($dhcpv6ifconf['enable']) && !empty($config['interfaces'][$dhcpv6if])) {
1268
			return true;
1269
		}
1270
	}
1271

    
1272
	return false;
1273
}
1274

    
1275
/* radvd enabled on any interfaces? */
1276
function is_radvd_enabled() {
1277
	global $config;
1278

    
1279
	if (!is_array($config['dhcpdv6'])) {
1280
		$config['dhcpdv6'] = array();
1281
	}
1282

    
1283
	$dhcpdv6cfg = $config['dhcpdv6'];
1284
	$Iflist = get_configured_interface_list();
1285

    
1286
	/* handle manually configured DHCP6 server settings first */
1287
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1288
		if (!isset($config['interfaces'][$dhcpv6if]['enable'])) {
1289
			continue;
1290
		}
1291

    
1292
		if (!isset($dhcpv6ifconf['ramode'])) {
1293
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
1294
		}
1295

    
1296
		if ($dhcpv6ifconf['ramode'] == "disabled") {
1297
			continue;
1298
		}
1299

    
1300
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1301
		if (!is_ipaddrv6($ifcfgipv6)) {
1302
			continue;
1303
		}
1304

    
1305
		return true;
1306
	}
1307

    
1308
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
1309
	foreach ($Iflist as $if => $ifdescr) {
1310
		if (!isset($config['interfaces'][$if]['track6-interface'])) {
1311
			continue;
1312
		}
1313
		if (!isset($config['interfaces'][$if]['enable'])) {
1314
			continue;
1315
		}
1316

    
1317
		$ifcfgipv6 = get_interface_ipv6($if);
1318
		if (!is_ipaddrv6($ifcfgipv6)) {
1319
			continue;
1320
		}
1321

    
1322
		$ifcfgsnv6 = get_interface_subnetv6($if);
1323
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1324

    
1325
		if (!is_ipaddrv6($subnetv6)) {
1326
			continue;
1327
		}
1328

    
1329
		return true;
1330
	}
1331

    
1332
	return false;
1333
}
1334

    
1335
/* Any PPPoE servers enabled? */
1336
function is_pppoe_server_enabled() {
1337
	global $config;
1338

    
1339
	$pppoeenable = false;
1340

    
1341
	if (!is_array($config['pppoes']) || !is_array($config['pppoes']['pppoe'])) {
1342
		return false;
1343
	}
1344

    
1345
	foreach ($config['pppoes']['pppoe'] as $pppoes) {
1346
		if ($pppoes['mode'] == 'server') {
1347
			$pppoeenable = true;
1348
		}
1349
	}
1350

    
1351
	return $pppoeenable;
1352
}
1353

    
1354
/* Optional arg forces hh:mm:ss without days */
1355
function convert_seconds_to_dhms($sec, $showhoursonly = false) {
1356
	if (!is_numericint($sec)) {
1357
		return '-';
1358
	}
1359
	// FIXME: When we move to PHP 7 we can use "intdiv($sec % X, Y)" etc
1360
	list($d, $h, $m, $s) = array(	(int)($showhoursonly ? 0 : $sec/86400),
1361
					(int)(($showhoursonly ? $sec : $sec % 86400)/3600),
1362
					(int)(($sec % 3600)/60),
1363
					$sec % 60
1364
				);
1365
	return ($d > 0 ? $d . 'd ' : '') . sprintf('%02d:%02d:%02d', $h, $m, $s);
1366
}
1367

    
1368
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1369

    
1370
function get_ppp_uptime($port) {
1371
	if (file_exists("/conf/{$port}.log")) {
1372
		$saved_time = file_get_contents("/conf/{$port}.log");
1373
		$uptime_data = explode("\n", $saved_time);
1374
		$sec = 0;
1375
		foreach ($uptime_data as $upt) {
1376
			$sec += substr($upt, 1 + strpos($upt, " "));
1377
		}
1378
		return convert_seconds_to_dhms($sec);
1379
	} else {
1380
		$total_time = gettext("No history data found!");
1381
		return $total_time;
1382
	}
1383
}
1384

    
1385
//returns interface information
1386
function get_interface_info($ifdescr) {
1387
	global $config, $g;
1388

    
1389
	$ifinfo = array();
1390
	if (empty($config['interfaces'][$ifdescr])) {
1391
		return;
1392
	}
1393
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
1394
	$ifinfo['if'] = get_real_interface($ifdescr);
1395

    
1396
	$chkif = $ifinfo['if'];
1397
	$ifinfotmp = pfSense_get_interface_addresses($chkif);
1398
	$ifinfo['status'] = $ifinfotmp['status'];
1399
	if (empty($ifinfo['status'])) {
1400
		$ifinfo['status'] = "down";
1401
	}
1402
	$ifinfo['macaddr'] = $ifinfotmp['macaddr'];
1403
	$ifinfo['mtu'] = $ifinfotmp['mtu'];
1404
	$ifinfo['ipaddr'] = $ifinfotmp['ipaddr'];
1405
	$ifinfo['subnet'] = $ifinfotmp['subnet'];
1406
	$ifinfo['linklocal'] = get_interface_linklocal($ifdescr);
1407
	$ifinfo['ipaddrv6'] = get_interface_ipv6($ifdescr);
1408
	$ifinfo['subnetv6'] = get_interface_subnetv6($ifdescr);
1409
	if (isset($ifinfotmp['link0'])) {
1410
		$link0 = "down";
1411
	}
1412
	$ifinfotmp = pfSense_get_interface_stats($chkif);
1413
	// $ifinfo['inpkts'] = $ifinfotmp['inpkts'];
1414
	// $ifinfo['outpkts'] = $ifinfotmp['outpkts'];
1415
	$ifinfo['inerrs'] = $ifinfotmp['inerrs'];
1416
	$ifinfo['outerrs'] = $ifinfotmp['outerrs'];
1417
	$ifinfo['collisions'] = $ifinfotmp['collisions'];
1418

    
1419
	/* Use pfctl for non wrapping 64 bit counters */
1420
	/* Pass */
1421
	exec("/sbin/pfctl -vvsI -i {$chkif}", $pfctlstats);
1422
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1423
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1424
	$pf_in6_pass = preg_split("/ +/ ", $pfctlstats[7]);
1425
	$pf_out6_pass = preg_split("/ +/", $pfctlstats[9]);
1426
	$in4_pass = $pf_in4_pass[5];
1427
	$out4_pass = $pf_out4_pass[5];
1428
	$in4_pass_packets = $pf_in4_pass[3];
1429
	$out4_pass_packets = $pf_out4_pass[3];
1430
	$in6_pass = $pf_in6_pass[5];
1431
	$out6_pass = $pf_out6_pass[5];
1432
	$in6_pass_packets = $pf_in6_pass[3];
1433
	$out6_pass_packets = $pf_out6_pass[3];
1434
	$ifinfo['inbytespass'] = $in4_pass + $in6_pass;
1435
	$ifinfo['outbytespass'] = $out4_pass + $out6_pass;
1436
	$ifinfo['inpktspass'] = $in4_pass_packets + $in6_pass_packets;
1437
	$ifinfo['outpktspass'] = $out4_pass_packets + $out6_pass_packets;
1438

    
1439
	/* Block */
1440
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1441
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1442
	$pf_in6_block = preg_split("/ +/", $pfctlstats[8]);
1443
	$pf_out6_block = preg_split("/ +/", $pfctlstats[10]);
1444
	$in4_block = $pf_in4_block[5];
1445
	$out4_block = $pf_out4_block[5];
1446
	$in4_block_packets = $pf_in4_block[3];
1447
	$out4_block_packets = $pf_out4_block[3];
1448
	$in6_block = $pf_in6_block[5];
1449
	$out6_block = $pf_out6_block[5];
1450
	$in6_block_packets = $pf_in6_block[3];
1451
	$out6_block_packets = $pf_out6_block[3];
1452
	$ifinfo['inbytesblock'] = $in4_block + $in6_block;
1453
	$ifinfo['outbytesblock'] = $out4_block + $out6_block;
1454
	$ifinfo['inpktsblock'] = $in4_block_packets + $in6_block_packets;
1455
	$ifinfo['outpktsblock'] = $out4_block_packets + $out6_block_packets;
1456

    
1457
	$ifinfo['inbytes'] = $in4_pass + $in6_pass;
1458
	$ifinfo['outbytes'] = $out4_pass + $out6_pass;
1459
	$ifinfo['inpkts'] = $in4_pass_packets + $in6_pass_packets;
1460
	$ifinfo['outpkts'] = $out4_pass_packets + $out6_pass_packets;
1461

    
1462
	$ifconfiginfo = "";
1463
	$link_type = $config['interfaces'][$ifdescr]['ipaddr'];
1464
	switch ($link_type) {
1465
		/* DHCP? -> see if dhclient is up */
1466
		case "dhcp":
1467
			/* see if dhclient is up */
1468
			if (find_dhclient_process($ifinfo['if']) != 0) {
1469
				$ifinfo['dhcplink'] = "up";
1470
			} else {
1471
				$ifinfo['dhcplink'] = "down";
1472
			}
1473

    
1474
			break;
1475
		/* PPPoE/PPTP/L2TP interface? -> get status from virtual interface */
1476
		case "pppoe":
1477
		case "pptp":
1478
		case "l2tp":
1479
			if ($ifinfo['status'] == "up" && !isset($link0)) {
1480
				/* get PPPoE link status for dial on demand */
1481
				$ifinfo["{$link_type}link"] = "up";
1482
			} else {
1483
				$ifinfo["{$link_type}link"] = "down";
1484
			}
1485

    
1486
			break;
1487
		/* PPP interface? -> get uptime for this session and cumulative uptime from the persistent log file in conf */
1488
		case "ppp":
1489
			if ($ifinfo['status'] == "up") {
1490
				$ifinfo['ppplink'] = "up";
1491
			} else {
1492
				$ifinfo['ppplink'] = "down" ;
1493
			}
1494

    
1495
			if (empty($ifinfo['status'])) {
1496
				$ifinfo['status'] = "down";
1497
			}
1498

    
1499
			if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1500
				foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1501
					if ($config['interfaces'][$ifdescr]['if'] == $ppp['if']) {
1502
						break;
1503
					}
1504
				}
1505
			}
1506
			$dev = $ppp['ports'];
1507
			if ($config['interfaces'][$ifdescr]['if'] != $ppp['if'] || empty($dev)) {
1508
				break;
1509
			}
1510
			if (!file_exists($dev)) {
1511
				$ifinfo['nodevice'] = 1;
1512
				$ifinfo['pppinfo'] = $dev . " " . gettext("device not present! Is the modem attached to the system?");
1513
			}
1514

    
1515
			$usbmodemoutput = array();
1516
			exec("/usr/sbin/usbconfig", $usbmodemoutput);
1517
			$mondev = "{$g['tmp_path']}/3gstats.{$ifdescr}";
1518
			if (file_exists($mondev)) {
1519
				$cellstats = file($mondev);
1520
				/* skip header */
1521
				$a_cellstats = explode(",", $cellstats[1]);
1522
				if (preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1523
					$ifinfo['cell_rssi'] = huawei_rssi_to_string($a_cellstats[1]);
1524
					$ifinfo['cell_mode'] = huawei_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1525
					$ifinfo['cell_simstate'] = huawei_simstate_to_string($a_cellstats[10]);
1526
					$ifinfo['cell_service'] = huawei_service_to_string(trim($a_cellstats[11]));
1527
				}
1528
				if (preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1529
					$ifinfo['cell_rssi'] = zte_rssi_to_string($a_cellstats[1]);
1530
					$ifinfo['cell_mode'] = zte_mode_to_string($a_cellstats[2], $a_cellstats[3]);
1531
					$ifinfo['cell_simstate'] = zte_simstate_to_string($a_cellstats[10]);
1532
					$ifinfo['cell_service'] = zte_service_to_string(trim($a_cellstats[11]));
1533
				}
1534
				$ifinfo['cell_upstream'] = $a_cellstats[4];
1535
				$ifinfo['cell_downstream'] = trim($a_cellstats[5]);
1536
				$ifinfo['cell_sent'] = $a_cellstats[6];
1537
				$ifinfo['cell_received'] = trim($a_cellstats[7]);
1538
				$ifinfo['cell_bwupstream'] = $a_cellstats[8];
1539
				$ifinfo['cell_bwdownstream'] = trim($a_cellstats[9]);
1540
			}
1541
			// Calculate cumulative uptime for PPP link. Useful for connections that have per minute/hour contracts so you don't go over!
1542
			if (isset($ppp['uptime'])) {
1543
				$ifinfo['ppp_uptime_accumulated'] = "(".get_ppp_uptime($ifinfo['if']).")";
1544
			}
1545
			break;
1546
		default:
1547
			break;
1548
	}
1549

    
1550
	if (file_exists("{$g['varrun_path']}/{$link_type}_{$ifdescr}.pid")) {
1551
		$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1552
		$ifinfo['ppp_uptime'] = convert_seconds_to_dhms($sec);
1553
	}
1554

    
1555
	if ($ifinfo['status'] == "up") {
1556
		/* try to determine media with ifconfig */
1557
		unset($ifconfiginfo);
1558
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1559
		$wifconfiginfo = array();
1560
		if (is_interface_wireless($ifdescr)) {
1561
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1562
			array_shift($wifconfiginfo);
1563
		}
1564
		$matches = "";
1565
		foreach ($ifconfiginfo as $ici) {
1566

    
1567
			/* don't list media/speed for wireless cards, as it always
1568
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1569
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1570
				$ifinfo['media'] = $matches[1];
1571
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1572
				$ifinfo['media'] = $matches[1];
1573
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1574
				$ifinfo['media'] = $matches[1];
1575
			}
1576

    
1577
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
1578
				if ($matches[1] != "active") {
1579
					$ifinfo['status'] = $matches[1];
1580
				}
1581
				if ($ifinfo['status'] == gettext("running")) {
1582
					$ifinfo['status'] = gettext("up");
1583
				}
1584
			}
1585
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
1586
				$ifinfo['channel'] = $matches[1];
1587
			}
1588
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
1589
				if ($matches[1][0] == '"') {
1590
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
1591
				}
1592
				else {
1593
					$ifinfo['ssid'] = $matches[1];
1594
				}
1595
			}
1596
			if (preg_match("/laggproto (.*)$/", $ici, $matches)) {
1597
				$ifinfo['laggproto'] = $matches[1];
1598
			}
1599
			if (preg_match("/laggport: (.*)$/", $ici, $matches)) {
1600
				$ifinfo['laggport'][] = $matches[1];
1601
			}
1602
		}
1603
		foreach ($wifconfiginfo as $ici) {
1604
			$elements = preg_split("/[ ]+/i", $ici);
1605
			if ($elements[0] != "") {
1606
				$ifinfo['bssid'] = $elements[0];
1607
			}
1608
			if ($elements[3] != "") {
1609
				$ifinfo['rate'] = $elements[3];
1610
			}
1611
			if ($elements[4] != "") {
1612
				$ifinfo['rssi'] = $elements[4];
1613
			}
1614
		}
1615
		/* lookup the gateway */
1616
		if (interface_has_gateway($ifdescr)) {
1617
			$ifinfo['gateway'] = get_interface_gateway($ifdescr);
1618
			$ifinfo['gatewayv6'] = get_interface_gateway_v6($ifdescr);
1619
		}
1620
	}
1621

    
1622
	$bridge = "";
1623
	$bridge = link_interface_to_bridge($ifdescr);
1624
	if ($bridge) {
1625
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1626
		if (stristr($bridge_text, "blocking") <> false) {
1627
			$ifinfo['bridge'] = "<b><font color='red'>" . gettext("blocking") . "</font></b> - " . gettext("check for ethernet loops");
1628
			$ifinfo['bridgeint'] = $bridge;
1629
		} else if (stristr($bridge_text, "learning") <> false) {
1630
			$ifinfo['bridge'] = gettext("learning");
1631
			$ifinfo['bridgeint'] = $bridge;
1632
		} else if (stristr($bridge_text, "forwarding") <> false) {
1633
			$ifinfo['bridge'] = gettext("forwarding");
1634
			$ifinfo['bridgeint'] = $bridge;
1635
		}
1636
	}
1637

    
1638
	return $ifinfo;
1639
}
1640

    
1641
//returns cpu speed of processor. Good for determining capabilities of machine
1642
function get_cpu_speed() {
1643
	return get_single_sysctl("hw.clockrate");
1644
}
1645

    
1646
function get_uptime_sec() {
1647
	$boottime = "";
1648
	$matches = "";
1649
	$boottime = get_single_sysctl("kern.boottime");
1650
	preg_match("/sec = (\d+)/", $boottime, $matches);
1651
	$boottime = $matches[1];
1652
	if (intval($boottime) == 0) {
1653
		return 0;
1654
	}
1655

    
1656
	$uptime = time() - $boottime;
1657
	return $uptime;
1658
}
1659

    
1660
function add_hostname_to_watch($hostname) {
1661
	if (!is_dir("/var/db/dnscache")) {
1662
		mkdir("/var/db/dnscache");
1663
	}
1664
	$result = array();
1665
	if ((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1666
		$domrecords = array();
1667
		$domips = array();
1668
		exec("/usr/bin/host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1669
		if ($rethost == 0) {
1670
			foreach ($domrecords as $domr) {
1671
				$doml = explode(" ", $domr);
1672
				$domip = $doml[3];
1673
				/* fill array with domain ip addresses */
1674
				if (is_ipaddr($domip)) {
1675
					$domips[] = $domip;
1676
				}
1677
			}
1678
		}
1679
		sort($domips);
1680
		$contents = "";
1681
		if (!empty($domips)) {
1682
			foreach ($domips as $ip) {
1683
				$contents .= "$ip\n";
1684
			}
1685
		}
1686
		file_put_contents("/var/db/dnscache/$hostname", $contents);
1687
		/* Remove empty elements */
1688
		$result = array_filter(explode("\n", $contents), 'strlen');
1689
	}
1690
	return $result;
1691
}
1692

    
1693
function is_fqdn($fqdn) {
1694
	$hostname = false;
1695
	if (preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1696
		$hostname = true;
1697
	}
1698
	if (preg_match("/\.\./", $fqdn)) {
1699
		$hostname = false;
1700
	}
1701
	if (preg_match("/^\./i", $fqdn)) {
1702
		$hostname = false;
1703
	}
1704
	if (preg_match("/\//i", $fqdn)) {
1705
		$hostname = false;
1706
	}
1707
	return($hostname);
1708
}
1709

    
1710
function pfsense_default_state_size() {
1711
	/* get system memory amount */
1712
	$memory = get_memory();
1713
	$physmem = $memory[0];
1714
	/* Be cautious and only allocate 10% of system memory to the state table */
1715
	$max_states = (int) ($physmem/10)*1000;
1716
	return $max_states;
1717
}
1718

    
1719
function pfsense_default_tables_size() {
1720
	$current = `pfctl -sm | grep ^tables | awk '{print $4};'`;
1721
	return $current;
1722
}
1723

    
1724
function pfsense_default_table_entries_size() {
1725
	$current = `pfctl -sm | grep table-entries | awk '{print $4};'`;
1726
	return (trim($current));
1727
}
1728

    
1729
/* Compare the current hostname DNS to the DNS cache we made
1730
 * if it has changed we return the old records
1731
 * if no change we return false */
1732
function compare_hostname_to_dnscache($hostname) {
1733
	if (!is_dir("/var/db/dnscache")) {
1734
		mkdir("/var/db/dnscache");
1735
	}
1736
	$hostname = trim($hostname);
1737
	if (is_readable("/var/db/dnscache/{$hostname}")) {
1738
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
1739
	} else {
1740
		$oldcontents = "";
1741
	}
1742
	if ((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1743
		$domrecords = array();
1744
		$domips = array();
1745
		exec("/usr/bin/host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
1746
		if ($rethost == 0) {
1747
			foreach ($domrecords as $domr) {
1748
				$doml = explode(" ", $domr);
1749
				$domip = $doml[3];
1750
				/* fill array with domain ip addresses */
1751
				if (is_ipaddr($domip)) {
1752
					$domips[] = $domip;
1753
				}
1754
			}
1755
		}
1756
		sort($domips);
1757
		$contents = "";
1758
		if (!empty($domips)) {
1759
			foreach ($domips as $ip) {
1760
				$contents .= "$ip\n";
1761
			}
1762
		}
1763
	}
1764

    
1765
	if (trim($oldcontents) != trim($contents)) {
1766
		if ($g['debug']) {
1767
			log_error(sprintf(gettext('DNSCACHE: Found old IP %1$s and new IP %2$s'), $oldcontents, $contents));
1768
		}
1769
		return ($oldcontents);
1770
	} else {
1771
		return false;
1772
	}
1773
}
1774

    
1775
/*
1776
 * load_crypto() - Load crypto modules if enabled in config.
1777
 */
1778
function load_crypto() {
1779
	global $config, $g;
1780
	$crypto_modules = array('glxsb', 'aesni');
1781

    
1782
	if (!in_array($config['system']['crypto_hardware'], $crypto_modules)) {
1783
		return false;
1784
	}
1785

    
1786
	if (!empty($config['system']['crypto_hardware']) && !is_module_loaded($config['system']['crypto_hardware'])) {
1787
		log_error(sprintf(gettext("Loading %s cryptographic accelerator module."), $config['system']['crypto_hardware']));
1788
		mwexec("/sbin/kldload {$config['system']['crypto_hardware']}");
1789
	}
1790
}
1791

    
1792
/*
1793
 * load_thermal_hardware() - Load temperature monitor kernel module
1794
 */
1795
function load_thermal_hardware() {
1796
	global $config, $g;
1797
	$thermal_hardware_modules = array('coretemp', 'amdtemp');
1798

    
1799
	if (!in_array($config['system']['thermal_hardware'], $thermal_hardware_modules)) {
1800
		return false;
1801
	}
1802

    
1803
	if (!empty($config['system']['thermal_hardware']) && !is_module_loaded($config['system']['thermal_hardware'])) {
1804
		log_error(sprintf(gettext("Loading %s thermal monitor module."), $config['system']['thermal_hardware']));
1805
		mwexec("/sbin/kldload {$config['system']['thermal_hardware']}");
1806
	}
1807
}
1808

    
1809
/****f* pfsense-utils/isvm
1810
 * NAME
1811
 *   isvm
1812
 * INPUTS
1813
 *	none
1814
 * RESULT
1815
 *   returns true if machine is running under a virtual environment
1816
 ******/
1817
function isvm() {
1818
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86", "VirtualBox");
1819
	$_gb = exec('/bin/kenv smbios.system.product 2>/dev/null', $output, $rc);
1820

    
1821
	if ($rc != 0 || !isset($output[0])) {
1822
		return false;
1823
	}
1824

    
1825
	foreach ($virtualenvs as $virtualenv) {
1826
		if (stripos($output[0], $virtualenv) !== false) {
1827
			return true;
1828
		}
1829
	}
1830

    
1831
	return false;
1832
}
1833

    
1834
function get_freebsd_version() {
1835
	$version = explode(".", php_uname("r"));
1836
	return $version[0];
1837
}
1838

    
1839
function download_file($url, $destination, $verify_ssl = true, $connect_timeout = 5, $timeout = 0) {
1840
	global $config, $g;
1841

    
1842
	$fp = fopen($destination, "wb");
1843

    
1844
	if (!$fp) {
1845
		return false;
1846
	}
1847

    
1848
	$ch = curl_init();
1849
	curl_setopt($ch, CURLOPT_URL, $url);
1850
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1851
	curl_setopt($ch, CURLOPT_FILE, $fp);
1852
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1853
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1854
	curl_setopt($ch, CURLOPT_HEADER, false);
1855
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1856
	if (!isset($config['system']['do_not_send_host_uuid'])) {
1857
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1858
	} else {
1859
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1860
	}
1861

    
1862
	if (!empty($config['system']['proxyurl'])) {
1863
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1864
		if (!empty($config['system']['proxyport'])) {
1865
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1866
		}
1867
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1868
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1869
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1870
		}
1871
	}
1872

    
1873
	@curl_exec($ch);
1874
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1875
	fclose($fp);
1876
	curl_close($ch);
1877
	if ($http_code == 200) {
1878
		return true;
1879
	} else {
1880
		log_error(sprintf(gettext('Download file failed with status code %1$s. URL: %2$s'), $http_code, $url));
1881
		unlink_if_exists($destination);
1882
		return false;
1883
	}
1884
}
1885

    
1886
function download_file_with_progress_bar($url, $destination, $verify_ssl = true, $readbody = 'read_body', $connect_timeout = 5, $timeout = 0) {
1887
	global $config, $g;
1888
	global $ch, $fout, $file_size, $downloaded, $config, $first_progress_update;
1889
	$file_size = 1;
1890
	$downloaded = 1;
1891
	$first_progress_update = TRUE;
1892
	/* open destination file */
1893
	$fout = fopen($destination, "wb");
1894

    
1895
	if (!$fout) {
1896
		return false;
1897
	}
1898
	/*
1899
	 *      Originally by Author: Keyvan Minoukadeh
1900
	 *      Modified by Scott Ullrich to return Content-Length size
1901
	 */
1902
	$ch = curl_init();
1903
	curl_setopt($ch, CURLOPT_URL, $url);
1904
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl);
1905
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1906
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
1907
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1908
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1909
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
1910
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1911
	if (!isset($config['system']['do_not_send_host_uuid'])) {
1912
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version'] . ' : ' . get_single_sysctl('kern.hostuuid'));
1913
	} else {
1914
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . $g['product_version']);
1915
	}
1916

    
1917
	if (!empty($config['system']['proxyurl'])) {
1918
		curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']);
1919
		if (!empty($config['system']['proxyport'])) {
1920
			curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']);
1921
		}
1922
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
1923
			@curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE);
1924
			curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}");
1925
		}
1926
	}
1927

    
1928
	@curl_exec($ch);
1929
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1930
	fclose($fout);
1931
	curl_close($ch);
1932
	if ($http_code == 200) {
1933
		return true;
1934
	} else {
1935
		log_error(sprintf(gettext('Download file failed with status code %1$s. URL: %2$s'), $http_code, $url));
1936
		unlink_if_exists($destination);
1937
		return false;
1938
	}
1939
}
1940

    
1941
function read_header($ch, $string) {
1942
	global $file_size, $fout;
1943
	$length = strlen($string);
1944
	$regs = "";
1945
	preg_match("/(Content-Length:) (.*)/", $string, $regs);
1946
	if ($regs[2] <> "") {
1947
		$file_size = intval($regs[2]);
1948
	}
1949
	ob_flush();
1950
	return $length;
1951
}
1952

    
1953
function read_body($ch, $string) {
1954
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen, $first_progress_update;
1955
	global $pkg_interface;
1956
	$length = strlen($string);
1957
	$downloaded += intval($length);
1958
	if ($file_size > 0) {
1959
		$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1960
		$downloadProgress = 100 - $downloadProgress;
1961
	} else {
1962
		$downloadProgress = 0;
1963
	}
1964
	if ($lastseen <> $downloadProgress and $downloadProgress < 101) {
1965
		if ($sendto == "status") {
1966
			if ($pkg_interface == "console") {
1967
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1968
					$tostatus = $static_status . $downloadProgress . "%";
1969
					if ($downloadProgress == 100) {
1970
						$tostatus = $tostatus . "\r";
1971
					}
1972
					update_status($tostatus);
1973
				}
1974
			} else {
1975
				$tostatus = $static_status . $downloadProgress . "%";
1976
				update_status($tostatus);
1977
			}
1978
		} else {
1979
			if ($pkg_interface == "console") {
1980
				if (($downloadProgress % 10) == 0 || $downloadProgress < 10) {
1981
					$tooutput = $static_output . $downloadProgress . "%";
1982
					if ($downloadProgress == 100) {
1983
						$tooutput = $tooutput . "\r";
1984
					}
1985
					update_output_window($tooutput);
1986
				}
1987
			} else {
1988
				$tooutput = $static_output . $downloadProgress . "%";
1989
				update_output_window($tooutput);
1990
			}
1991
		}
1992
		if (($pkg_interface != "console") || (($downloadProgress % 10) == 0) || ($downloadProgress < 10)) {
1993
			update_progress_bar($downloadProgress, $first_progress_update);
1994
			$first_progress_update = FALSE;
1995
		}
1996
		$lastseen = $downloadProgress;
1997
	}
1998
	if ($fout) {
1999
		fwrite($fout, $string);
2000
	}
2001
	ob_flush();
2002
	return $length;
2003
}
2004

    
2005
/*
2006
 *   update_output_window: update bottom textarea dynamically.
2007
 */
2008
function update_output_window($text) {
2009
	global $pkg_interface;
2010
	$log = preg_replace("/\n/", "\\n", $text);
2011
	if ($pkg_interface != "console") {
2012
?>
2013
<script type="text/javascript">
2014
//<![CDATA[
2015
	document.getElementById("output").textContent="<?=htmlspecialchars($log)?>";
2016
	document.getElementById("output").scrollTop = document.getElementById("output").scrollHeight;
2017
//]]>
2018
</script>
2019
<?php
2020
	}
2021
	/* ensure that contents are written out */
2022
	ob_flush();
2023
}
2024

    
2025
/*
2026
 *   update_status: update top textarea dynamically.
2027
 */
2028
function update_status($status) {
2029
	global $pkg_interface;
2030

    
2031
	if ($pkg_interface == "console") {
2032
		print ("{$status}");
2033
	}
2034

    
2035
	/* ensure that contents are written out */
2036
	ob_flush();
2037
}
2038

    
2039
/*
2040
 * update_progress_bar($percent, $first_time): updates the javascript driven progress bar.
2041
 */
2042
function update_progress_bar($percent, $first_time) {
2043
	global $pkg_interface;
2044
	if ($percent > 100) {
2045
		$percent = 1;
2046
	}
2047
	if ($pkg_interface <> "console") {
2048
		echo '<script type="text/javascript">';
2049
		echo "\n//<![CDATA[\n";
2050
		echo 'document.getElementById("progressbar").style.width="'. $percent.'%"';
2051
		echo "\n//]]>\n";
2052
		echo '</script>';
2053
	} else {
2054
		if (!($first_time)) {
2055
			echo "\x08\x08\x08\x08\x08";
2056
		}
2057
		echo sprintf("%4d%%", $percent);
2058
	}
2059
}
2060

    
2061
/* 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. */
2062
if (!function_exists("split")) {
2063
	function split($separator, $haystack, $limit = null) {
2064
		log_error("deprecated split() call with separator '{$separator}'");
2065
		return preg_split($separator, $haystack, $limit);
2066
	}
2067
}
2068

    
2069
function update_alias_names_upon_change($section, $field, $new_alias_name, $origname) {
2070
	global $g, $config, $pconfig, $debug;
2071
	if (!$origname) {
2072
		return;
2073
	}
2074

    
2075
	$sectionref = &$config;
2076
	foreach ($section as $sectionname) {
2077
		if (is_array($sectionref) && isset($sectionref[$sectionname])) {
2078
			$sectionref = &$sectionref[$sectionname];
2079
		} else {
2080
			return;
2081
		}
2082
	}
2083

    
2084
	if ($debug) {
2085
		$fd = fopen("{$g['tmp_path']}/print_r", "a");
2086
		fwrite($fd, print_r($pconfig, true));
2087
	}
2088

    
2089
	if (is_array($sectionref)) {
2090
		foreach ($sectionref as $itemkey => $item) {
2091
			if ($debug) {
2092
				fwrite($fd, "$itemkey\n");
2093
			}
2094

    
2095
			$fieldfound = true;
2096
			$fieldref = &$sectionref[$itemkey];
2097
			foreach ($field as $fieldname) {
2098
				if (is_array($fieldref) && isset($fieldref[$fieldname])) {
2099
					$fieldref = &$fieldref[$fieldname];
2100
				} else {
2101
					$fieldfound = false;
2102
					break;
2103
				}
2104
			}
2105
			if ($fieldfound && $fieldref == $origname) {
2106
				if ($debug) {
2107
					fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
2108
				}
2109
				$fieldref = $new_alias_name;
2110
			}
2111
		}
2112
	}
2113

    
2114
	if ($debug) {
2115
		fclose($fd);
2116
	}
2117

    
2118
}
2119

    
2120
function parse_aliases_file($filename, $type = "url", $max_items = -1, $kflc = false) {
2121
	/*
2122
	 * $filename = file to process for example blocklist like DROP:  http://www.spamhaus.org/drop/drop.txt
2123
	 * $type = if set to 'url' then subnets and ips will be returned,
2124
	 *         if set to 'url_ports' port-ranges and ports will be returned
2125
	 * $max_items = sets the maximum amount of valid items to load, -1 the default defines there is no limit.
2126
	 *
2127
	 * RETURNS an array of ip subnets and ip's or ports and port-ranges, returns NULL upon a error conditions (file not found)
2128
	 */
2129

    
2130
	if (!file_exists($filename)) {
2131
		log_error(sprintf(gettext("Could not process non-existent file from alias: %s"), $filename));
2132
		return null;
2133
	}
2134

    
2135
	if (filesize($filename) == 0) {
2136
		log_error(sprintf(gettext("Could not process empty file from alias: %s"), $filename));
2137
		return null;
2138
	}
2139
	$fd = @fopen($filename, 'r');
2140
	if (!$fd) {
2141
		log_error(sprintf(gettext("Could not process aliases from alias: %s"), $filename));
2142
		return null;
2143
	}
2144
	$items = array();
2145
	$comments = array();
2146
	/* NOTE: fgetss() is not a typo RTFM before being smart */
2147
	while (($fc = fgetss($fd)) !== FALSE) {
2148
		$tmp = trim($fc, " \t\n\r");
2149
		if (empty($tmp)) {
2150
			continue;
2151
		}
2152
		if (($kflc) && (strpos($tmp, '#') === 0)) {	// Keep Full Line Comments (lines beginning with #).
2153
			$comments[] = $tmp;
2154
		} else {
2155
			$tmp_str = strstr($tmp, '#', true);
2156
			if (!empty($tmp_str)) {
2157
				$tmp = $tmp_str;
2158
			}
2159
			$tmp_str = strstr($tmp, ' ', true);
2160
			if (!empty($tmp_str)) {
2161
				$tmp = $tmp_str;
2162
			}
2163
			$valid = (($type == "url" || $type == "urltable") && (is_ipaddr($tmp) || is_subnet($tmp))) ||
2164
				(($type == "url_ports" || $type == "urltable_ports") && (is_port($tmp) || is_portrange($tmp)));
2165
			if ($valid) {
2166
				$items[] = $tmp;
2167
				if (count($items) == $max_items) {
2168
					break;
2169
				}
2170
			}
2171
		}
2172
	}
2173
	fclose($fd);
2174
	return array_merge($comments, $items);
2175
}
2176

    
2177
function update_alias_url_data() {
2178
	global $config, $g;
2179

    
2180
	$updated = false;
2181

    
2182
	/* item is a url type */
2183
	$lockkey = lock('aliasurl');
2184
	if (is_array($config['aliases']['alias'])) {
2185
		foreach ($config['aliases']['alias'] as $x => $alias) {
2186
			if (empty($alias['aliasurl'])) {
2187
				continue;
2188
			}
2189

    
2190
			$address = null;
2191
			foreach ($alias['aliasurl'] as $alias_url) {
2192
				/* fetch down and add in */
2193
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
2194
				unlink($temp_filename);
2195
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2196
				mkdir($temp_filename);
2197
				if (!download_file($alias_url, $temp_filename . "/aliases", $verify_ssl)) {
2198
					log_error(sprintf(gettext("Failed to download alias %s"), $alias_url));
2199
					continue;
2200
				}
2201

    
2202
				/* if the item is tar gzipped then extract */
2203
				if (stripos($alias_url, '.tgz')) {
2204
					if (!process_alias_tgz($temp_filename)) {
2205
						continue;
2206
					}
2207
				}
2208
				if (file_exists("{$temp_filename}/aliases")) {
2209
					$address = parse_aliases_file("{$temp_filename}/aliases", $alias['type'], 5000);
2210
					mwexec("/bin/rm -rf {$temp_filename}");
2211
				}
2212
			}
2213
			if ($address != null) {
2214
				$config['aliases']['alias'][$x]['address'] = implode(" ", $address);
2215
				$updated = true;
2216
			}
2217
		}
2218
	}
2219
	unlock($lockkey);
2220

    
2221
	/* Report status to callers as well */
2222
	return $updated;
2223
}
2224

    
2225
function process_alias_tgz($temp_filename) {
2226
	if (!file_exists('/usr/bin/tar')) {
2227
		log_error(gettext("Alias archive is a .tar/tgz file which cannot be decompressed because utility is missing!"));
2228
		return false;
2229
	}
2230
	rename("{$temp_filename}/aliases", "{$temp_filename}/aliases.tgz");
2231
	mwexec("/usr/bin/tar xzf {$temp_filename}/aliases.tgz -C {$temp_filename}/aliases/");
2232
	unlink("{$temp_filename}/aliases.tgz");
2233
	$files_to_process = return_dir_as_array("{$temp_filename}/");
2234
	/* foreach through all extracted files and build up aliases file */
2235
	$fd = @fopen("{$temp_filename}/aliases", "w");
2236
	if (!$fd) {
2237
		log_error(sprintf(gettext("Could not open %s/aliases for writing!"), $temp_filename));
2238
		return false;
2239
	}
2240
	foreach ($files_to_process as $f2p) {
2241
		$tmpfd = @fopen($f2p, 'r');
2242
		if (!$tmpfd) {
2243
			log_error(sprintf(gettext('The following file could not be read %1$s from %2$s'), $f2p, $temp_filename));
2244
			continue;
2245
		}
2246
		while (($tmpbuf = fread($tmpfd, 65536)) !== FALSE) {
2247
			fwrite($fd, $tmpbuf);
2248
		}
2249
		fclose($tmpfd);
2250
		unlink($f2p);
2251
	}
2252
	fclose($fd);
2253
	unset($tmpbuf);
2254

    
2255
	return true;
2256
}
2257

    
2258
function version_compare_dates($a, $b) {
2259
	$a_time = strtotime($a);
2260
	$b_time = strtotime($b);
2261

    
2262
	if ((!$a_time) || (!$b_time)) {
2263
		return FALSE;
2264
	} else {
2265
		if ($a_time < $b_time) {
2266
			return -1;
2267
		} elseif ($a_time == $b_time) {
2268
			return 0;
2269
		} else {
2270
			return 1;
2271
		}
2272
	}
2273
}
2274
function version_get_string_value($a) {
2275
	$strs = array(
2276
		0 => "ALPHA-ALPHA",
2277
		2 => "ALPHA",
2278
		3 => "BETA",
2279
		4 => "B",
2280
		5 => "C",
2281
		6 => "D",
2282
		7 => "RC",
2283
		8 => "RELEASE",
2284
		9 => "*"			// Matches all release levels
2285
	);
2286
	$major = 0;
2287
	$minor = 0;
2288
	foreach ($strs as $num => $str) {
2289
		if (substr($a, 0, strlen($str)) == $str) {
2290
			$major = $num;
2291
			$n = substr($a, strlen($str));
2292
			if (is_numeric($n)) {
2293
				$minor = $n;
2294
			}
2295
			break;
2296
		}
2297
	}
2298
	return "{$major}.{$minor}";
2299
}
2300
function version_compare_string($a, $b) {
2301
	// Only compare string parts if both versions give a specific release
2302
	// (If either version lacks a string part, assume intended to match all release levels)
2303
	if (isset($a) && isset($b)) {
2304
		return version_compare_numeric(version_get_string_value($a), version_get_string_value($b));
2305
	} else {
2306
		return 0;
2307
	}
2308
}
2309
function version_compare_numeric($a, $b) {
2310
	$a_arr = explode('.', rtrim($a, '.'));
2311
	$b_arr = explode('.', rtrim($b, '.'));
2312

    
2313
	foreach ($a_arr as $n => $val) {
2314
		if (array_key_exists($n, $b_arr)) {
2315
			// So far so good, both have values at this minor version level. Compare.
2316
			if ($val > $b_arr[$n]) {
2317
				return 1;
2318
			} elseif ($val < $b_arr[$n]) {
2319
				return -1;
2320
			}
2321
		} else {
2322
			// a is greater, since b doesn't have any minor version here.
2323
			return 1;
2324
		}
2325
	}
2326
	if (count($b_arr) > count($a_arr)) {
2327
		// b is longer than a, so it must be greater.
2328
		return -1;
2329
	} else {
2330
		// Both a and b are of equal length and value.
2331
		return 0;
2332
	}
2333
}
2334
function pfs_version_compare($cur_time, $cur_text, $remote) {
2335
	// First try date compare
2336
	$v = version_compare_dates($cur_time, $remote);
2337
	if ($v === FALSE) {
2338
		// If that fails, try to compare by string
2339
		// Before anything else, simply test if the strings are equal
2340
		if (($cur_text == $remote) || ($cur_time == $remote)) {
2341
			return 0;
2342
		}
2343
		list($cur_num, $cur_str) = explode('-', $cur_text);
2344
		list($rem_num, $rem_str) = explode('-', $remote);
2345

    
2346
		// First try to compare the numeric parts of the version string.
2347
		$v = version_compare_numeric($cur_num, $rem_num);
2348

    
2349
		// If the numeric parts are the same, compare the string parts.
2350
		if ($v == 0) {
2351
			return version_compare_string($cur_str, $rem_str);
2352
		}
2353
	}
2354
	return $v;
2355
}
2356
function process_alias_urltable($name, $type, $url, $freq, $forceupdate=false, $validateonly=false) {
2357
	global $g, $config;
2358

    
2359
	$urltable_prefix = "/var/db/aliastables/";
2360
	$urltable_filename = $urltable_prefix . $name . ".txt";
2361
	$tmp_urltable_filename = $urltable_filename . ".tmp";
2362

    
2363
	// Make the aliases directory if it doesn't exist
2364
	if (!file_exists($urltable_prefix)) {
2365
		mkdir($urltable_prefix);
2366
	} elseif (!is_dir($urltable_prefix)) {
2367
		unlink($urltable_prefix);
2368
		mkdir($urltable_prefix);
2369
	}
2370

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

    
2376
		// Try to fetch the URL supplied
2377
		conf_mount_rw();
2378
		unlink_if_exists($tmp_urltable_filename);
2379
		$verify_ssl = isset($config['system']['checkaliasesurlcert']);
2380
		if (download_file($url, $tmp_urltable_filename, $verify_ssl)) {
2381
			// Convert lines that begin with '$' or ';' to comments '#' instead of deleting them.
2382
			mwexec("/usr/bin/sed -i \"\" -E 's/^[[:space:]]*($|#|;)/#/g; /^#/!s/\;.*//g;' ". escapeshellarg($tmp_urltable_filename));
2383

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

    
2386
			$parsed_contents = parse_aliases_file($tmp_urltable_filename, $type, "-1", true);
2387
			if ($type == "urltable_ports") {
2388
				$parsed_contents = group_ports($parsed_contents, true);
2389
			}
2390
			if (is_array($parsed_contents)) {
2391
				file_put_contents($urltable_filename, implode("\n", $parsed_contents));
2392
			} else {
2393
				touch($urltable_filename);
2394
			}
2395

    
2396
			/* 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. */
2397
			if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
2398
				unlink_if_exists("{$g['cf_conf_path']}/RAM_Disk_Store{$urltable_filename}.tgz");
2399
			} else {
2400
				/* Update the RAM disk store with the new/updated table file. */
2401
				mwexec("cd / && /usr/bin/tar -czf \"{$g['cf_conf_path']}/RAM_Disk_Store{$urltable_filename}.tgz\" -C / \"{$urltable_filename}\"");
2402
			}
2403
			unlink_if_exists($tmp_urltable_filename);
2404
		} else {
2405
			if (!$validateonly) {
2406
				touch($urltable_filename);
2407
			}
2408
			conf_mount_ro();
2409
			return false;
2410
		}
2411
		conf_mount_ro();
2412
		return true;
2413
	} else {
2414
		// File exists, and it doesn't need to be updated.
2415
		return -1;
2416
	}
2417
}
2418
function get_real_slice_from_glabel($label) {
2419
	$label = escapeshellarg($label);
2420
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/{$label} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`);
2421
}
2422
function nanobsd_get_boot_slice() {
2423
	return trim(`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`);
2424
}
2425
function nanobsd_get_boot_drive() {
2426
	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`);
2427
}
2428
function nanobsd_get_active_slice() {
2429
	$boot_drive = nanobsd_get_boot_drive();
2430
	$active = trim(`gpart show $boot_drive | grep '\[active\]' | awk '{print $3;}'`);
2431

    
2432
	return "{$boot_drive}s{$active}";
2433
}
2434
function nanobsd_get_size() {
2435
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
2436
}
2437
function nanobsd_switch_boot_slice() {
2438
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2439
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2440
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2441
	nanobsd_detect_slice_info();
2442

    
2443
	if ($BOOTFLASH == $ACTIVE_SLICE) {
2444
		$slice = $TOFLASH;
2445
	} else {
2446
		$slice = $BOOTFLASH;
2447
	}
2448

    
2449
	for ($i = 0; $i < ob_get_level(); $i++) {
2450
		ob_end_flush();
2451
	}
2452
	ob_implicit_flush(1);
2453
	if (strstr($slice, "s2")) {
2454
		$ASLICE = "2";
2455
		$AOLDSLICE = "1";
2456
		$AGLABEL_SLICE = "pfsense1";
2457
		$AUFS_ID = "1";
2458
		$AOLD_UFS_ID = "0";
2459
	} else {
2460
		$ASLICE = "1";
2461
		$AOLDSLICE = "2";
2462
		$AGLABEL_SLICE = "pfsense0";
2463
		$AUFS_ID = "0";
2464
		$AOLD_UFS_ID = "1";
2465
	}
2466
	$ATOFLASH = "{$BOOT_DRIVE}s{$ASLICE}";
2467
	$ACOMPLETE_PATH = "{$BOOT_DRIVE}s{$ASLICE}a";
2468
	$ABOOTFLASH = "{$BOOT_DRIVE}s{$AOLDSLICE}";
2469
	conf_mount_rw();
2470
	set_single_sysctl("kern.geom.debugflags", "16");
2471
	exec("/sbin/gpart set -a active -i {$ASLICE} {$BOOT_DRIVE}");
2472
	exec("/usr/sbin/boot0cfg -s {$ASLICE} -v /dev/{$BOOT_DRIVE}");
2473
	// We can't update these if they are mounted now.
2474
	if ($BOOTFLASH != $slice) {
2475
		exec("/sbin/tunefs -L ${AGLABEL_SLICE} /dev/$ACOMPLETE_PATH");
2476
		nanobsd_update_fstab($AGLABEL_SLICE, $ACOMPLETE_PATH, $AOLD_UFS_ID, $AUFS_ID);
2477
	}
2478
	set_single_sysctl("kern.geom.debugflags", "0");
2479
	conf_mount_ro();
2480
}
2481
function nanobsd_clone_slice() {
2482
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2483
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2484
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2485
	nanobsd_detect_slice_info();
2486

    
2487
	for ($i = 0; $i < ob_get_level(); $i++) {
2488
		ob_end_flush();
2489
	}
2490
	ob_implicit_flush(1);
2491
	set_single_sysctl("kern.geom.debugflags", "16");
2492
	exec("/bin/dd if=/dev/zero of=/dev/{$TOFLASH} bs=1m count=1");
2493
	exec("/bin/dd if=/dev/{$BOOTFLASH} of=/dev/{$TOFLASH} bs=64k");
2494
	exec("/sbin/tunefs -L {$GLABEL_SLICE} /dev/{$COMPLETE_PATH}");
2495
	$status = nanobsd_update_fstab($GLABEL_SLICE, $COMPLETE_PATH, $OLD_UFS_ID, $UFS_ID);
2496
	set_single_sysctl("kern.geom.debugflags", "0");
2497
	if ($status) {
2498
		return false;
2499
	} else {
2500
		return true;
2501
	}
2502
}
2503
function nanobsd_update_fstab($gslice, $complete_path, $oldufs, $newufs) {
2504
	$tmppath = "/tmp/{$gslice}";
2505
	$fstabpath = "/tmp/{$gslice}/etc/fstab";
2506

    
2507
	mkdir($tmppath);
2508
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
2509
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
2510
	copy("/etc/fstab", $fstabpath);
2511

    
2512
	if (!file_exists($fstabpath)) {
2513
		$fstab = <<<EOF
2514
/dev/ufs/{$gslice} / ufs ro,noatime 1 1
2515
/dev/ufs/cf /cf ufs ro,noatime 1 1
2516
EOF;
2517
		if (file_put_contents($fstabpath, $fstab)) {
2518
			$status = true;
2519
		} else {
2520
			$status = false;
2521
		}
2522
	} else {
2523
		$status = exec("/usr/bin/sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2524
	}
2525
	exec("/sbin/umount {$tmppath}");
2526
	rmdir($tmppath);
2527

    
2528
	return $status;
2529
}
2530
function nanobsd_detect_slice_info() {
2531
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2532
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2533
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2534

    
2535
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2536
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2537
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2538
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2539

    
2540
	// Detect which slice is active and set information.
2541
	if (strstr($REAL_BOOT_DEVICE, "s1")) {
2542
		$SLICE = "2";
2543
		$OLDSLICE = "1";
2544
		$GLABEL_SLICE = "pfsense1";
2545
		$UFS_ID = "1";
2546
		$OLD_UFS_ID = "0";
2547

    
2548
	} else {
2549
		$SLICE = "1";
2550
		$OLDSLICE = "2";
2551
		$GLABEL_SLICE = "pfsense0";
2552
		$UFS_ID = "0";
2553
		$OLD_UFS_ID = "1";
2554
	}
2555
	$TOFLASH = "{$BOOT_DRIVE}s{$SLICE}";
2556
	$COMPLETE_PATH = "{$BOOT_DRIVE}s{$SLICE}a";
2557
	$COMPLETE_BOOT_PATH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2558
	$BOOTFLASH = "{$BOOT_DRIVE}s{$OLDSLICE}";
2559
}
2560

    
2561
function nanobsd_friendly_slice_name($slicename) {
2562
	global $g;
2563
	return strtolower(str_ireplace('pfsense', $g['product_name'], $slicename));
2564
}
2565

    
2566
function get_include_contents($filename) {
2567
	if (is_file($filename)) {
2568
		ob_start();
2569
		include $filename;
2570
		$contents = ob_get_contents();
2571
		ob_end_clean();
2572
		return $contents;
2573
	}
2574
	return false;
2575
}
2576

    
2577
/* This xml 2 array function is courtesy of the php.net comment section on xml_parse.
2578
 * it is roughly 4 times faster then our existing pfSense parser but due to the large
2579
 * size of the RRD xml dumps this is required.
2580
 * The reason we do not use it for pfSense is that it does not know about array fields
2581
 * which causes it to fail on array fields with single items. Possible Todo?
2582
 */
2583
function xml2array($contents, $get_attributes = 1, $priority = 'tag') {
2584
	if (!function_exists('xml_parser_create')) {
2585
		return array ();
2586
	}
2587
	$parser = xml_parser_create('');
2588
	xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
2589
	xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
2590
	xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
2591
	xml_parse_into_struct($parser, trim($contents), $xml_values);
2592
	xml_parser_free($parser);
2593
	if (!$xml_values) {
2594
		return; //Hmm...
2595
	}
2596
	$xml_array = array ();
2597
	$parents = array ();
2598
	$opened_tags = array ();
2599
	$arr = array ();
2600
	$current = & $xml_array;
2601
	$repeated_tag_index = array ();
2602
	foreach ($xml_values as $data) {
2603
		unset ($attributes, $value);
2604
		extract($data);
2605
		$result = array ();
2606
		$attributes_data = array ();
2607
		if (isset ($value)) {
2608
			if ($priority == 'tag') {
2609
				$result = $value;
2610
			} else {
2611
				$result['value'] = $value;
2612
			}
2613
		}
2614
		if (isset ($attributes) and $get_attributes) {
2615
			foreach ($attributes as $attr => $val) {
2616
				if ($priority == 'tag') {
2617
					$attributes_data[$attr] = $val;
2618
				} else {
2619
					$result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
2620
				}
2621
			}
2622
		}
2623
		if ($type == "open") {
2624
			$parent[$level -1] = & $current;
2625
			if (!is_array($current) or (!in_array($tag, array_keys($current)))) {
2626
				$current[$tag] = $result;
2627
				if ($attributes_data) {
2628
					$current[$tag . '_attr'] = $attributes_data;
2629
				}
2630
				$repeated_tag_index[$tag . '_' . $level] = 1;
2631
				$current = & $current[$tag];
2632
			} else {
2633
				if (isset ($current[$tag][0])) {
2634
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2635
					$repeated_tag_index[$tag . '_' . $level]++;
2636
				} else {
2637
					$current[$tag] = array (
2638
						$current[$tag],
2639
						$result
2640
						);
2641
					$repeated_tag_index[$tag . '_' . $level] = 2;
2642
					if (isset ($current[$tag . '_attr'])) {
2643
						$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2644
						unset ($current[$tag . '_attr']);
2645
					}
2646
				}
2647
				$last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
2648
				$current = & $current[$tag][$last_item_index];
2649
			}
2650
		} elseif ($type == "complete") {
2651
			if (!isset ($current[$tag])) {
2652
				$current[$tag] = $result;
2653
				$repeated_tag_index[$tag . '_' . $level] = 1;
2654
				if ($priority == 'tag' and $attributes_data) {
2655
					$current[$tag . '_attr'] = $attributes_data;
2656
				}
2657
			} else {
2658
				if (isset ($current[$tag][0]) and is_array($current[$tag])) {
2659
					$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
2660
					if ($priority == 'tag' and $get_attributes and $attributes_data) {
2661
						$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2662
					}
2663
					$repeated_tag_index[$tag . '_' . $level]++;
2664
				} else {
2665
					$current[$tag] = array (
2666
						$current[$tag],
2667
						$result
2668
						);
2669
					$repeated_tag_index[$tag . '_' . $level] = 1;
2670
					if ($priority == 'tag' and $get_attributes) {
2671
						if (isset ($current[$tag . '_attr'])) {
2672
							$current[$tag]['0_attr'] = $current[$tag . '_attr'];
2673
							unset ($current[$tag . '_attr']);
2674
						}
2675
						if ($attributes_data) {
2676
							$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
2677
						}
2678
					}
2679
					$repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
2680
				}
2681
			}
2682
		} elseif ($type == 'close') {
2683
			$current = & $parent[$level -1];
2684
		}
2685
	}
2686
	return ($xml_array);
2687
}
2688

    
2689
function get_country_name($country_code) {
2690
	if ($country_code != "ALL" && strlen($country_code) != 2) {
2691
		return "";
2692
	}
2693

    
2694
	$country_names_xml = "/usr/local/share/pfSense/iso_3166-1_list_en.xml";
2695
	$country_names_contents = file_get_contents($country_names_xml);
2696
	$country_names = xml2array($country_names_contents);
2697

    
2698
	if ($country_code == "ALL") {
2699
		$country_list = array();
2700
		foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2701
			$country_list[] = array(
2702
				"code" => $country['ISO_3166-1_Alpha-2_Code_element'],
2703
				"name" => ucwords(strtolower($country['ISO_3166-1_Country_name'])));
2704
		}
2705
		return $country_list;
2706
	}
2707

    
2708
	foreach ($country_names['ISO_3166-1_List_en']['ISO_3166-1_Entry'] as $country) {
2709
		if ($country['ISO_3166-1_Alpha-2_Code_element'] == strtoupper($country_code)) {
2710
			return ucwords(strtolower($country['ISO_3166-1_Country_name']));
2711
		}
2712
	}
2713
	return "";
2714
}
2715

    
2716
/* sort by interface only, retain the original order of rules that apply to
2717
   the same interface */
2718
function filter_rules_sort() {
2719
	global $config;
2720

    
2721
	/* mark each rule with the sequence number (to retain the order while sorting) */
2722
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2723
		$config['filter']['rule'][$i]['seq'] = $i;
2724
	}
2725

    
2726
	usort($config['filter']['rule'], "filter_rules_compare");
2727

    
2728
	/* strip the sequence numbers again */
2729
	for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
2730
		unset($config['filter']['rule'][$i]['seq']);
2731
	}
2732
}
2733
function filter_rules_compare($a, $b) {
2734
	if (isset($a['floating']) && isset($b['floating'])) {
2735
		return $a['seq'] - $b['seq'];
2736
	} else if (isset($a['floating'])) {
2737
		return -1;
2738
	} else if (isset($b['floating'])) {
2739
		return 1;
2740
	} else if ($a['interface'] == $b['interface']) {
2741
		return $a['seq'] - $b['seq'];
2742
	} else {
2743
		return compare_interface_friendly_names($a['interface'], $b['interface']);
2744
	}
2745
}
2746

    
2747
function generate_ipv6_from_mac($mac) {
2748
	$elements = explode(":", $mac);
2749
	if (count($elements) <> 6) {
2750
		return false;
2751
	}
2752

    
2753
	$i = 0;
2754
	$ipv6 = "fe80::";
2755
	foreach ($elements as $byte) {
2756
		if ($i == 0) {
2757
			$hexadecimal = substr($byte, 1, 2);
2758
			$bitmap = base_convert($hexadecimal, 16, 2);
2759
			$bitmap = str_pad($bitmap, 4, "0", STR_PAD_LEFT);
2760
			$bitmap = substr($bitmap, 0, 2) ."1". substr($bitmap, 3, 4);
2761
			$byte = substr($byte, 0, 1) . base_convert($bitmap, 2, 16);
2762
		}
2763
		$ipv6 .= $byte;
2764
		if ($i == 1) {
2765
			$ipv6 .= ":";
2766
		}
2767
		if ($i == 3) {
2768
			$ipv6 .= ":";
2769
		}
2770
		if ($i == 2) {
2771
			$ipv6 .= "ff:fe";
2772
		}
2773

    
2774
		$i++;
2775
	}
2776
	return $ipv6;
2777
}
2778

    
2779
/****f* pfsense-utils/load_mac_manufacturer_table
2780
 * NAME
2781
 *   load_mac_manufacturer_table
2782
 * INPUTS
2783
 *   none
2784
 * RESULT
2785
 *   returns associative array with MAC-Manufacturer pairs
2786
 ******/
2787
function load_mac_manufacturer_table() {
2788
	/* load MAC-Manufacture data from the file */
2789
	$macs = false;
2790
	if (file_exists("/usr/local/share/nmap/nmap-mac-prefixes")) {
2791
		$macs=file("/usr/local/share/nmap/nmap-mac-prefixes");
2792
	}
2793
	if ($macs) {
2794
		foreach ($macs as $line) {
2795
			if (preg_match('/([0-9A-Fa-f]{6}) (.*)$/', $line, $matches)) {
2796
				/* store values like this $mac_man['000C29']='VMware' */
2797
				$mac_man["$matches[1]"] = $matches[2];
2798
			}
2799
		}
2800
		return $mac_man;
2801
	} else {
2802
		return -1;
2803
	}
2804

    
2805
}
2806

    
2807
/****f* pfsense-utils/is_ipaddr_configured
2808
 * NAME
2809
 *   is_ipaddr_configured
2810
 * INPUTS
2811
 *   IP Address to check.
2812
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2813
 *   check_localip - if true then also check for matches with PPTP and L2TP addresses
2814
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2815
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2816
 *     If check_subnets is true and cidrprefix is specified,
2817
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2818
 * RESULT
2819
 *   returns true if the IP Address is configured and present on this device or overlaps a configured subnet.
2820
*/
2821
function is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2822
	if (count(where_is_ipaddr_configured($ipaddr, $ignore_if, $check_localip, $check_subnets, $cidrprefix))) {
2823
		return true;
2824
	}
2825
	return false;
2826
}
2827

    
2828
/****f* pfsense-utils/where_is_ipaddr_configured
2829
 * NAME
2830
 *   where_is_ipaddr_configured
2831
 * INPUTS
2832
 *   IP Address to check.
2833
 *   If ignore_if is a VIP (not carp), vip array index is passed after string _virtualip
2834
 *   check_localip - if true then also check for matches with PPTP and L2TP addresses
2835
 *   check_subnets - if true then check if the given ipaddr is contained anywhere in the subnet of any other configured IP address
2836
 *   cidrprefix - the CIDR prefix (16, 20, 24, 64...) of ipaddr.
2837
 *     If check_subnets is true and cidrprefix is specified,
2838
 *     then check if the ipaddr/cidrprefix subnet overlaps the subnet of any other configured IP address
2839
 * RESULT
2840
 *   Returns an array of the interfaces 'if' plus IP address or subnet 'ip_or_subnet' that match or overlap the IP address to check.
2841
 *   If there are no matches then an empty array is returned.
2842
*/
2843
function where_is_ipaddr_configured($ipaddr, $ignore_if = "", $check_localip = false, $check_subnets = false, $cidrprefix = "") {
2844
	global $config;
2845

    
2846
	$where_configured = array();
2847

    
2848
	$pos = strpos($ignore_if, '_virtualip');
2849
	if ($pos !== false) {
2850
		$ignore_vip_id = substr($ignore_if, $pos+10);
2851
		$ignore_vip_if = substr($ignore_if, 0, $pos);
2852
	} else {
2853
		$ignore_vip_id = -1;
2854
		$ignore_vip_if = $ignore_if;
2855
	}
2856

    
2857
	$isipv6 = is_ipaddrv6($ipaddr);
2858

    
2859
	if ($check_subnets) {
2860
		$cidrprefix = intval($cidrprefix);
2861
		if ($isipv6) {
2862
			if (($cidrprefix < 1) || ($cidrprefix > 128)) {
2863
				$cidrprefix = 128;
2864
			}
2865
		} else {
2866
			if (($cidrprefix < 1) || ($cidrprefix > 32)) {
2867
				$cidrprefix = 32;
2868
			}
2869
		}
2870
		$iflist = get_configured_interface_list();
2871
		foreach ($iflist as $if => $ifname) {
2872
			if ($ignore_if == $if) {
2873
				continue;
2874
			}
2875

    
2876
			if ($isipv6) {
2877
				$if_ipv6 = get_interface_ipv6($if);
2878
				$if_snbitsv6 = get_interface_subnetv6($if);
2879
				if ($if_ipv6 && $if_snbitsv6 && check_subnetsv6_overlap($ipaddr, $cidrprefix, $if_ipv6, $if_snbitsv6)) {
2880
					$where_entry = array();
2881
					$where_entry['if'] = $if;
2882
					$where_entry['ip_or_subnet'] = get_interface_ipv6($if) . "/" . get_interface_subnetv6($if);
2883
					$where_configured[] = $where_entry;
2884
				}
2885
			} else {
2886
				$if_ipv4 = get_interface_ip($if);
2887
				$if_snbitsv4 = get_interface_subnet($if);
2888
				if ($if_ipv4 && $if_snbitsv4 && check_subnets_overlap($ipaddr, $cidrprefix, $if_ipv4, $if_snbitsv4)) {
2889
					$where_entry = array();
2890
					$where_entry['if'] = $if;
2891
					$where_entry['ip_or_subnet'] = get_interface_ip($if) . "/" . get_interface_subnet($if);
2892
					$where_configured[] = $where_entry;
2893
				}
2894
			}
2895
		}
2896
	} else {
2897
		if ($isipv6) {
2898
			$interface_list_ips = get_configured_ipv6_addresses();
2899
		} else {
2900
			$interface_list_ips = get_configured_ip_addresses();
2901
		}
2902

    
2903
		foreach ($interface_list_ips as $if => $ilips) {
2904
			if ($ignore_if == $if) {
2905
				continue;
2906
			}
2907
			if (strcasecmp($ipaddr, $ilips) == 0) {
2908
				$where_entry = array();
2909
				$where_entry['if'] = $if;
2910
				$where_entry['ip_or_subnet'] = $ilips;
2911
				$where_configured[] = $where_entry;
2912
			}
2913
		}
2914
	}
2915

    
2916
	if ($check_localip) {
2917
		if (!is_array($config['l2tp']) && !empty($config['l2tp']['localip']) && (strcasecmp($ipaddr, $config['l2tp']['localip']) == 0)) {
2918
			$where_entry = array();
2919
			$where_entry['if'] = 'l2tp';
2920
			$where_entry['ip_or_subnet'] = $config['l2tp']['localip'];
2921
			$where_configured[] = $where_entry;
2922
		}
2923
	}
2924

    
2925
	return $where_configured;
2926
}
2927

    
2928
/****f* pfsense-utils/pfSense_handle_custom_code
2929
 * NAME
2930
 *   pfSense_handle_custom_code
2931
 * INPUTS
2932
 *   directory name to process
2933
 * RESULT
2934
 *   globs the directory and includes the files
2935
 */
2936
function pfSense_handle_custom_code($src_dir) {
2937
	// Allow extending of the nat edit page and include custom input validation
2938
	if (is_dir("$src_dir")) {
2939
		$cf = glob($src_dir . "/*.inc");
2940
		foreach ($cf as $nf) {
2941
			if ($nf == "." || $nf == "..") {
2942
				continue;
2943
			}
2944
			// Include the extra handler
2945
			include_once("$nf");
2946
		}
2947
	}
2948
}
2949

    
2950
function set_language() {
2951
	global $config, $g;
2952

    
2953
	if (!empty($config['system']['language'])) {
2954
		$lang = $config['system']['language'];
2955
	} elseif (!empty($g['language'])) {
2956
		$lang = $g['language'];
2957
	}
2958
	$lang .= ".UTF-8";
2959

    
2960
	putenv("LANG={$lang}");
2961
	setlocale(LC_ALL, $lang);
2962
	textdomain("pfSense");
2963
	bindtextdomain("pfSense", "/usr/local/share/locale");
2964
	bind_textdomain_codeset("pfSense", $lang);
2965
}
2966

    
2967
function get_locale_list() {
2968
	$locales = array(
2969
		"en_US" => gettext("English"),
2970
		"pt_BR" => gettext("Portuguese (Brazil)"),
2971
		"tr" => gettext("Turkish"),
2972
	);
2973
	asort($locales);
2974
	return $locales;
2975
}
2976

    
2977
function return_hex_ipv4($ipv4) {
2978
	if (!is_ipaddrv4($ipv4)) {
2979
		return(false);
2980
	}
2981

    
2982
	/* we need the hex form of the interface IPv4 address */
2983
	$ip4arr = explode(".", $ipv4);
2984
	return (sprintf("%02x%02x%02x%02x", $ip4arr[0], $ip4arr[1], $ip4arr[2], $ip4arr[3]));
2985
}
2986

    
2987
function convert_ipv6_to_128bit($ipv6) {
2988
	if (!is_ipaddrv6($ipv6)) {
2989
		return(false);
2990
	}
2991

    
2992
	$ip6arr = array();
2993
	$ip6prefix = Net_IPv6::uncompress($ipv6);
2994
	$ip6arr = explode(":", $ip6prefix);
2995
	/* binary presentation of the prefix for all 128 bits. */
2996
	$ip6prefixbin = "";
2997
	foreach ($ip6arr as $element) {
2998
		$ip6prefixbin .= sprintf("%016b", hexdec($element));
2999
	}
3000
	return($ip6prefixbin);
3001
}
3002

    
3003
function convert_128bit_to_ipv6($ip6bin) {
3004
	if (strlen($ip6bin) <> 128) {
3005
		return(false);
3006
	}
3007

    
3008
	$ip6arr = array();
3009
	$ip6binarr = array();
3010
	$ip6binarr = str_split($ip6bin, 16);
3011
	foreach ($ip6binarr as $binpart) {
3012
		$ip6arr[] = dechex(bindec($binpart));
3013
	}
3014
	$ip6addr = Net_IPv6::compress(implode(":", $ip6arr));
3015

    
3016
	return($ip6addr);
3017
}
3018

    
3019

    
3020
/* Returns the calculated bit length of the prefix delegation from the WAN interface */
3021
/* DHCP-PD is variable, calculate from the prefix-len on the WAN interface */
3022
/* 6rd is variable, calculate from 64 - (v6 prefixlen - (32 - v4 prefixlen)) */
3023
/* 6to4 is 16 bits, e.g. 65535 */
3024
function calculate_ipv6_delegation_length($if) {
3025
	global $config;
3026

    
3027
	if (!is_array($config['interfaces'][$if])) {
3028
		return false;
3029
	}
3030

    
3031
	switch ($config['interfaces'][$if]['ipaddrv6']) {
3032
		case "6to4":
3033
			$pdlen = 16;
3034
			break;
3035
		case "6rd":
3036
			$rd6cfg = $config['interfaces'][$if];
3037
			$rd6plen = explode("/", $rd6cfg['prefix-6rd']);
3038
			$pdlen = (64 - ($rd6plen[1] + (32 - $rd6cfg['prefix-6rd-v4plen'])));
3039
			break;
3040
		case "dhcp6":
3041
			$dhcp6cfg = $config['interfaces'][$if];
3042
			$pdlen = $dhcp6cfg['dhcp6-ia-pd-len'];
3043
			break;
3044
		default:
3045
			$pdlen = 0;
3046
			break;
3047
	}
3048
	return($pdlen);
3049
}
3050

    
3051
function merge_ipv6_delegated_prefix($prefix, $suffix, $len = 64) {
3052
	$prefix = Net_IPv6::uncompress($prefix, true);
3053
	$suffix = Net_IPv6::uncompress($suffix, true);
3054

    
3055
	/*
3056
	 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
3057
	 *                ^^^^ ^
3058
	 *                |||| \-> 64
3059
	 *                |||\---> 63, 62, 61, 60
3060
	 *                ||\----> 56
3061
	 *                |\-----> 52
3062
	 *                \------> 48
3063
	 */
3064

    
3065
	switch ($len) {
3066
	case 48:
3067
		$prefix_len = 15;
3068
		break;
3069
	case 52:
3070
		$prefix_len = 16;
3071
		break;
3072
	case 56:
3073
		$prefix_len = 17;
3074
		break;
3075
	case 60:
3076
		$prefix_len = 18;
3077
		break;
3078
	/*
3079
	 * XXX 63, 62 and 61 should use 18 but PD can change and if
3080
	 * we let user chose this bit it can end up out of PD network
3081
	 *
3082
	 * Leave this with 20 for now until we find a way to let user
3083
	 * chose it. The side-effect is users with PD with one of these
3084
	 * lengths will not be able to setup DHCP server range for full
3085
	 * PD size, only for last /64 network
3086
	 */
3087
	case 63:
3088
	case 62:
3089
	case 61:
3090
	default:
3091
		$prefix_len = 20;
3092
		break;
3093
	}
3094

    
3095
	return Net_IPv6::compress(substr($prefix, 0, $prefix_len) .
3096
	    substr($suffix, $prefix_len));
3097
}
3098

    
3099
function dhcpv6_pd_str_help($pdlen) {
3100
	$result = '';
3101

    
3102
	switch ($pdlen) {
3103
	case 48:
3104
		$result = '::xxxx:xxxx:xxxx:xxxx:xxxx';
3105
		break;
3106
	case 52:
3107
		$result = '::xxx:xxxx:xxxx:xxxx:xxxx';
3108
		break;
3109
	case 56:
3110
		$result = '::xx:xxxx:xxxx:xxxx:xxxx';
3111
		break;
3112
	case 60:
3113
		$result = '::x:xxxx:xxxx:xxxx:xxxx';
3114
		break;
3115
	/*
3116
	 * XXX 63, 62 and 61 should use same mask of 60 but it would
3117
	 * we let user chose this bit it can end up out of PD network
3118
	 *
3119
	 * Leave this with the same of 64 for now until we find a way to
3120
	 * let user chose it. The side-effect is users with PD with one
3121
	 * of these lengths will not be able to setup DHCP server range
3122
	 * for full PD size, only for last /64 network
3123
	 */
3124
	case 61:
3125
	case 62:
3126
	case 63:
3127
	case 64:
3128
		$result = '::xxxx:xxxx:xxxx:xxxx';
3129
		break;
3130
	}
3131

    
3132
	return $result;
3133
}
3134

    
3135
function huawei_rssi_to_string($rssi) {
3136
	$dbm = array();
3137
	$i = 0;
3138
	$dbstart = -113;
3139
	while ($i < 32) {
3140
		$dbm[$i] = $dbstart + ($i * 2);
3141
		$i++;
3142
	}
3143
	$percent = round(($rssi / 31) * 100);
3144
	$string = "rssi:{$rssi} level:{$dbm[$rssi]}dBm percent:{$percent}%";
3145
	return $string;
3146
}
3147

    
3148
function huawei_mode_to_string($mode, $submode) {
3149
	$modes[0] = gettext("None");
3150
	$modes[1] = "AMPS";
3151
	$modes[2] = "CDMA";
3152
	$modes[3] = "GSM/GPRS";
3153
	$modes[4] = "HDR";
3154
	$modes[5] = "WCDMA";
3155
	$modes[6] = "GPS";
3156

    
3157
	$submodes[0] = gettext("No Service");
3158
	$submodes[1] = "GSM";
3159
	$submodes[2] = "GPRS";
3160
	$submodes[3] = "EDGE";
3161
	$submodes[4] = "WCDMA";
3162
	$submodes[5] = "HSDPA";
3163
	$submodes[6] = "HSUPA";
3164
	$submodes[7] = "HSDPA+HSUPA";
3165
	$submodes[8] = "TD-SCDMA";
3166
	$submodes[9] = "HSPA+";
3167
	$string = "{$modes[$mode]}, {$submodes[$submode]} " . gettext("Mode");
3168
	return $string;
3169
}
3170

    
3171
function huawei_service_to_string($state) {
3172
	$modes[0] = gettext("No Service");
3173
	$modes[1] = gettext("Restricted Service");
3174
	$modes[2] = gettext("Valid Service");
3175
	$modes[3] = gettext("Restricted Regional Service");
3176
	$modes[4] = gettext("Powersaving Service");
3177
	$string = $modes[$state];
3178
	return $string;
3179
}
3180

    
3181
function huawei_simstate_to_string($state) {
3182
	$modes[0] = gettext("Invalid SIM/locked State");
3183
	$modes[1] = gettext("Valid SIM State");
3184
	$modes[2] = gettext("Invalid SIM CS State");
3185
	$modes[3] = gettext("Invalid SIM PS State");
3186
	$modes[4] = gettext("Invalid SIM CS/PS State");
3187
	$modes[255] = gettext("Missing SIM State");
3188
	$string = $modes[$state];
3189
	return $string;
3190
}
3191

    
3192
function zte_rssi_to_string($rssi) {
3193
	return huawei_rssi_to_string($rssi);
3194
}
3195

    
3196
function zte_mode_to_string($mode, $submode) {
3197
	$modes[0] = gettext("No Service");
3198
	$modes[1] = gettext("Limited Service");
3199
	$modes[2] = "GPRS";
3200
	$modes[3] = "GSM";
3201
	$modes[4] = "UMTS";
3202
	$modes[5] = "EDGE";
3203
	$modes[6] = "HSDPA";
3204

    
3205
	$submodes[0] = "CS_ONLY";
3206
	$submodes[1] = "PS_ONLY";
3207
	$submodes[2] = "CS_PS";
3208
	$submodes[3] = "CAMPED";
3209
	$string = "{$modes[$mode]}, {$submodes[$submode]} " . gettext("Mode");
3210
	return $string;
3211
}
3212

    
3213
function zte_service_to_string($service) {
3214
	$modes[0] = gettext("Initializing Service");
3215
	$modes[1] = gettext("Network Lock error Service");
3216
	$modes[2] = gettext("Network Locked Service");
3217
	$modes[3] = gettext("Unlocked or correct MCC/MNC Service");
3218
	$string = $modes[$service];
3219
	return $string;
3220
}
3221

    
3222
function zte_simstate_to_string($state) {
3223
	$modes[0] = gettext("No action State");
3224
	$modes[1] = gettext("Network lock State");
3225
	$modes[2] = gettext("(U)SIM card lock State");
3226
	$modes[3] = gettext("Network Lock and (U)SIM card Lock State");
3227
	$string = $modes[$state];
3228
	return $string;
3229
}
3230

    
3231
function get_configured_pppoe_server_interfaces() {
3232
	global $config;
3233
	$iflist = array();
3234
	if (is_array($config['pppoes']['pppoe'])) {
3235
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
3236
			if ($pppoe['mode'] == "server") {
3237
				$int = "poes". $pppoe['pppoeid'];
3238
				$iflist[$int] = strtoupper($int);
3239
			}
3240
		}
3241
	}
3242
	return $iflist;
3243
}
3244

    
3245
function get_pppoes_child_interfaces($ifpattern) {
3246
	$if_arr = array();
3247
	if ($ifpattern == "") {
3248
		return;
3249
	}
3250

    
3251
	exec("/sbin/ifconfig", $out, $ret);
3252
	foreach ($out as $line) {
3253
		if (preg_match("/^({$ifpattern}[0-9]+):/i", $line, $match)) {
3254
			$if_arr[] = $match[1];
3255
		}
3256
	}
3257
	return $if_arr;
3258

    
3259
}
3260

    
3261
/****f* pfsense-utils/pkg_call_plugins
3262
 * NAME
3263
 *   pkg_call_plugins
3264
 * INPUTS
3265
 *   $plugin_type value used to search in package configuration if the plugin is used, also used to create the function name
3266
 *   $plugin_params parameters to pass to the plugin function for passing multiple parameters a array can be used.
3267
 * RESULT
3268
 *   returns associative array results from the plugin calls for each package
3269
 * NOTES
3270
 *   This generic function can be used to notify or retrieve results from functions that are defined in packages.
3271
 ******/
3272
function pkg_call_plugins($plugin_type, $plugin_params) {
3273
	global $g, $config;
3274
	$results = array();
3275
	if (!is_array($config['installedpackages']['package'])) {
3276
		return $results;
3277
	}
3278
	foreach ($config['installedpackages']['package'] as $package) {
3279
		if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
3280
			continue;
3281
		}
3282
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], 'packagegui');
3283
		$pkgname = substr(reverse_strrchr($package['configurationfile'], "."), 0, -1);
3284
		if (is_array($pkg_config['plugins']['item'])) {
3285
			foreach ($pkg_config['plugins']['item'] as $plugin) {
3286
				if ($plugin['type'] == $plugin_type) {
3287
					if (file_exists($pkg_config['include_file'])) {
3288
						require_once($pkg_config['include_file']);
3289
					} else {
3290
						continue;
3291
					}
3292
					$plugin_function = $pkgname . '_'. $plugin_type;
3293
					$results[$pkgname] = call_user_func($plugin_function, $plugin_params);
3294
				}
3295
			}
3296
		}
3297
	}
3298
	return $results;
3299
}
3300

    
3301
function restore_aliastables() {
3302
	global $g, $config;
3303

    
3304
	$dbpath = "{$g['vardb_path']}/aliastables/";
3305

    
3306
	/* restore the alias tables, if we have them */
3307
	$files = glob("{$g['cf_conf_path']}/RAM_Disk_Store{$dbpath}*.tgz");
3308
	if (count($files)) {
3309
		echo "Restoring alias tables...";
3310
		foreach ($files as $file) {
3311
			if (file_exists($file)) {
3312
				$aliastablesrestore = "";
3313
				$aliastablesreturn = "";
3314
				exec("cd /;LANG=C /usr/bin/tar -xzf {$file} 2>&1", $aliastablesrestore, $aliastablesreturn);
3315
				$aliastablesrestore = implode(" ", $aliastablesrestore);
3316
				if ($aliastablesreturn <> 0) {
3317
					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"));
3318
				} else {
3319
					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"));
3320
				}
3321
			}
3322
			/* 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. */
3323
			if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
3324
				unlink_if_exists("{$file}");
3325
			}
3326
		}
3327
		echo "done.\n";
3328
		return true;
3329
	}
3330
	return false;
3331
}
3332

    
3333
?>
(30-30/53)