Project

General

Profile

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

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

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

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

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

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

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

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

    
142
/****f* pfsense-utils/get_dns_servers
143
 * NAME
144
 *   get_dns_servres - get system dns servers
145
 * INPUTS
146
 *   $dns_servers - an array of the dns servers
147
 * RESULT
148
 *   null
149
 ******/
150
function get_dns_servers() {
151
	$dns_servers = array();
152
	$dns = `cat /etc/resolv.conf`;
153
	$dns_s = split("\n", $dns);
154
	foreach($dns_s as $dns) {
155
		$matches = "";
156
		if (preg_match("/nameserver (.*)/", $dns, $matches))
157
			$dns_servers[] = $matches[1];
158
	}
159
	$dns_server_master = array();
160
	$lastseen = "";
161
	foreach($dns_servers as $t) {
162
		if($t <> $lastseen)
163
			if($t <> "")
164
				$dns_server_master[] = $t;
165
		$lastseen = $t;
166
	}
167
	return $dns_server_master;
168
}
169

    
170
/****f* pfsense-utils/enable_hardware_offloading
171
 * NAME
172
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
173
 * INPUTS
174
 *   $interface	- string containing the physical interface to work on.
175
 * RESULT
176
 *   null
177
 * NOTES
178
 *   This function only supports the fxp driver's loadable microcode.
179
 ******/
180
function enable_hardware_offloading($interface) {
181
	global $g, $config;
182

    
183
	if(stristr($interface,"lnc"))
184
		return;
185

    
186
	/* translate wan, lan, opt -> real interface if needed */
187
	$int = get_real_interface($interface);
188
	if($int <> "") 
189
		$interface = $int;
190
	$int_family = preg_split("/[0-9]+/", $interface);
191
	$options = strtolower(`/sbin/ifconfig -m {$interface} | grep capabilities`);
192
	$supported_ints = array('fxp');
193
	if (in_array($int_family, $supported_ints)) {
194
		if(isset($config['system']['do_not_use_nic_microcode']))
195
			continue;
196
		if(does_interface_exist($interface)) 
197
			mwexec("/sbin/ifconfig {$interface} link0");
198
	}
199

    
200
	/* skip vlans for checksumming and polling */
201
	if(stristr($interface, "vlan")) 
202
		return;
203

    
204
	if($config['system']['disablechecksumoffloading']) {
205
		if(stristr($options, "txcsum") == true)
206
			mwexec("/sbin/ifconfig {$interface} -txcsum 2>/dev/null");
207
		if(stristr($options, "rxcsum") == true)
208
			mwexec("/sbin/ifconfig {$interface} -rxcsum 2>/dev/null");
209
	} else {
210
		if(stristr($options, "txcsum") == true)
211
			mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
212
		if(stristr($options, "rxcsum") == true)
213
			mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
214
	}
215

    
216
	/* if the NIC supports polling *AND* it is enabled in the GUI */
217
	if(interface_supports_polling($interface)) {
218
		$polling = isset($config['system']['polling']);	
219
		if($polling) {
220
			mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
221
		} else {
222
			mwexec("/sbin/ifconfig {$interface} -polling 2>/dev/null");
223
		}
224
	}
225
	return;
226
}
227

    
228
/****f* pfsense-utils/interface_supports_polling
229
 * NAME
230
 *   checks to see if an interface supports polling according to man polling
231
 * INPUTS
232
 *
233
 * RESULT
234
 *   true or false
235
 * NOTES
236
 *
237
 ******/
238
function interface_supports_polling($iface) {
239
	$pattern = '/([a-z].*)[0-9]/';
240
	preg_match($pattern, $iface, $iface2);
241
	$interface=$iface2[1];
242
	$supported_ints = array("bge",
243
		"dc",
244
		"em",
245
		"fwe",
246
		"fwip",
247
		"fxp",
248
		"ixgb",
249
		"nfe",
250
		"vge",
251
		"re",
252
		"rl",
253
		"sf",
254
		"sis",
255
		"ste",
256
		"stge",    
257
		"vge",
258
		"vr",
259
		"xl");
260
	if(in_array($interface, $supported_ints))
261
		return true;
262
	return false;
263
}
264

    
265
/****f* pfsense-utils/is_alias_inuse
266
 * NAME
267
 *   checks to see if an alias is currently in use by a rule
268
 * INPUTS
269
 *
270
 * RESULT
271
 *   true or false
272
 * NOTES
273
 *
274
 ******/
275
function is_alias_inuse($alias) {
276
	global $g, $config;
277

    
278
	if($alias == "") return false;
279
	/* loop through firewall rules looking for alias in use */
280
	if(is_array($config['filter']['rule']))
281
		foreach($config['filter']['rule'] as $rule) {
282
			if($rule['source']['address'])
283
				if($rule['source']['address'] == $alias)
284
					return true;
285
			if($rule['destination']['address'])
286
				if($rule['destination']['address'] == $alias)
287
					return true;
288
		}
289
	/* loop through nat rules looking for alias in use */
290
	if(is_array($config['nat']['rule']))
291
		foreach($config['nat']['rule'] as $rule) {
292
			if($rule['target'] && $rule['target'] == $alias)
293
				return true;
294
			if($rule['source']['address'] && $rule['source']['address'] == $alias)
295
				return true;
296
			if($rule['destination']['address'] && $rule['destination']['address'] == $alias)
297
				return true;
298
		}
299
	return false;
300
}
301

    
302
/****f* pfsense-utils/is_schedule_inuse
303
 * NAME
304
 *   checks to see if a schedule is currently in use by a rule
305
 * INPUTS
306
 *
307
 * RESULT
308
 *   true or false
309
 * NOTES
310
 *
311
 ******/
312
function is_schedule_inuse($schedule) {
313
	global $g, $config;
314

    
315
	if($schedule == "") return false;
316
	/* loop through firewall rules looking for schedule in use */
317
	if(is_array($config['filter']['rule']))
318
		foreach($config['filter']['rule'] as $rule) {
319
			if($rule['sched'] == $schedule)
320
				return true;
321
		}
322
	return false;
323
}
324

    
325
/****f* pfsense-utils/setup_polling_defaults
326
 * NAME
327
 *   sets up sysctls for polling
328
 * INPUTS
329
 *
330
 * RESULT
331
 *   null
332
 * NOTES
333
 *
334
 ******/
335
function setup_polling_defaults() {
336
	global $g, $config;
337
	if($config['system']['polling_each_burst'])
338
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
339
	if($config['system']['polling_burst_max'])
340
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
341
	if($config['system']['polling_user_frac'])
342
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
343
}
344

    
345
/****f* pfsense-utils/setup_polling
346
 * NAME
347
 *   sets up polling
348
 * INPUTS
349
 *
350
 * RESULT
351
 *   null
352
 * NOTES
353
 *
354
 ******/
355
function setup_polling() {
356
	global $g, $config;
357

    
358
	setup_polling_defaults();
359

    
360
	$supported_ints = array('bge', 'dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
361

    
362
	/* if list */
363
	$iflist = get_configured_interface_list();
364

    
365
	foreach ($iflist as $ifent => $ifname) {
366
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
367
		$ifdevice = substr($real_interface, 0, -1);
368
		if(!in_array($ifdevice, $supported_ints)) {
369
			continue;
370
        }
371
		if(isset($config['system']['polling'])) {
372
			mwexec("/sbin/ifconfig {$real_interface} polling");
373
			mwexec("/sbin/sysctl kern.polling.idle_poll=1");
374
		} else {
375
			mwexec("/sbin/ifconfig {$real_interface} -polling");
376
		}
377
	}
378
}
379

    
380
/****f* pfsense-utils/setup_microcode
381
 * NAME
382
 *   enumerates all interfaces and calls enable_hardware_offloading which
383
 *   enables a NIC's supported hardware features.
384
 * INPUTS
385
 *
386
 * RESULT
387
 *   null
388
 * NOTES
389
 *   This function only supports the fxp driver's loadable microcode.
390
 ******/
391
function setup_microcode() {
392

    
393
	/* if list */
394
        $ifdescrs = get_configured_interface_list();
395

    
396
	foreach($ifdescrs as $if)
397
		enable_hardware_offloading($if);
398
}
399

    
400
/****f* pfsense-utils/get_carp_status
401
 * NAME
402
 *   get_carp_status - Return whether CARP is enabled or disabled.
403
 * RESULT
404
 *   boolean	- true if CARP is enabled, false if otherwise.
405
 ******/
406
function get_carp_status() {
407
    /* grab the current status of carp */
408
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
409
    if(intval($status) == "0") return false;
410
    return true;
411
}
412

    
413
/*
414
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
415

    
416
 */
417
function convert_ip_to_network_format($ip, $subnet) {
418
	$ipsplit = split('[.]', $ip);
419
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
420
	return $string;
421
}
422

    
423
/*
424
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
425
 */
426
function get_carp_interface_status($carpinterface) {
427
	/* basically cache the contents of ifconfig statement
428
	to speed up this routine */
429
	global $carp_query;
430
	if($carp_query == "")
431
		$carp_query = split("\n", `/sbin/ifconfig $carpinterface | grep carp`);
432
	foreach($carp_query as $int) {
433
		if(stristr($int, "MASTER")) 
434
			return "MASTER";
435
		if(stristr($int, "BACKUP")) 
436
			return "BACKUP";
437
		if(stristr($int, "INIT")) 
438
			return "INIT";
439
	}
440
	return;
441
}
442

    
443
/*
444
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
445
 */
446
function get_pfsync_interface_status($pfsyncinterface) {
447
    $result = does_interface_exist($pfsyncinterface);
448
    if($result <> true) return;
449
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/awk '/pfsync:/ {print \$5}'");
450
    return $status;
451
}
452

    
453
/*
454
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
455
 */
456
function add_rule_to_anchor($anchor, $rule, $label) {
457
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
458
}
459

    
460
/*
461
 * remove_text_from_file
462
 * remove $text from file $file
463
 */
464
function remove_text_from_file($file, $text) {
465
	global $fd_log;
466
	if($fd_log)
467
		fwrite($fd_log, "Adding needed text items:\n");
468
	$filecontents = file_get_contents($file);
469
	$textTMP = str_replace($text, "", $filecontents);
470
	$text = $textTMP;
471
	if($fd_log)
472
		fwrite($fd_log, $text);
473
	$fd = fopen($file, "w");
474
	fwrite($fd, $text);
475
	fclose($fd);
476
}
477

    
478
/*
479
 * add_text_to_file($file, $text): adds $text to $file.
480
 * replaces the text if it already exists.
481
 */
482
function add_text_to_file($file, $text, $replace = false) {
483
	if(file_exists($file) and is_writable($file)) {
484
		$filecontents = file($file);
485
		$fout = fopen($file, "w");
486

    
487
		$filecontents = array_map('rtrim', $filecontents);
488
		array_push($filecontents, $text);
489
		if ($replace)
490
			$filecontents = array_unique($filecontents);
491

    
492
		$file_text = implode("\n", $filecontents);
493

    
494
		fwrite($fout, $file_text);
495
		fclose($fout);
496
		return true;
497
	} else {
498
		return false;
499
	}
500
}
501

    
502
/*
503
 *   after_sync_bump_adv_skew(): create skew values by 1S
504
 */
505
function after_sync_bump_adv_skew() {
506
	global $config, $g;
507
	$processed_skew = 1;
508
	$a_vip = &$config['virtualip']['vip'];
509
	foreach ($a_vip as $vipent) {
510
		if($vipent['advskew'] <> "") {
511
			$processed_skew = 1;
512
			$vipent['advskew'] = $vipent['advskew']+1;
513
		}
514
	}
515
	if($processed_skew == 1)
516
		write_config("After synch increase advertising skew");
517
}
518

    
519
/*
520
 * get_filename_from_url($url): converts a url to its filename.
521
 */
522
function get_filename_from_url($url) {
523
	return basename($url);
524
}
525

    
526
/*
527
 *   get_dir: return an array of $dir
528
 */
529
function get_dir($dir) {
530
	$dir_array = array();
531
	$d = dir($dir);
532
	while (false !== ($entry = $d->read())) {
533
		array_push($dir_array, $entry);
534
	}
535
	$d->close();
536
	return $dir_array;
537
}
538

    
539
/****f* pfsense-utils/WakeOnLan
540
 * NAME
541
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
542
 * RESULT
543
 *   true/false - true if the operation was successful
544
 ******/
545
function WakeOnLan($addr, $mac)
546
{
547
	$addr_byte = explode(':', $mac);
548
	$hw_addr = '';
549

    
550
	for ($a=0; $a < 6; $a++)
551
		$hw_addr .= chr(hexdec($addr_byte[$a]));
552

    
553
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
554

    
555
	for ($a = 1; $a <= 16; $a++)
556
		$msg .= $hw_addr;
557

    
558
	// send it to the broadcast address using UDP
559
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
560
	if ($s == false) {
561
		log_error("Error creating socket!");
562
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
563
	} else {
564
		// setting a broadcast option to socket:
565
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
566
		if($opt_ret < 0)
567
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
568
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
569
		socket_close($s);
570
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
571
		return true;
572
	}
573

    
574
	return false;
575
}
576

    
577
/*
578
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
579
 *                             is queuename|qlength|measured_packets
580
 *                             NOTE: this command takes 5 seconds to run
581
 */
582
function gather_altq_queue_stats($dont_return_root_queues) {
583
	exec("/sbin/pfctl -vvsq", $stats_array);
584
	$queue_stats = array();
585
	foreach ($stats_array as $stats_line) {
586
		$match_array = "";
587
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
588
			$queue_name = $match_array[1][0];
589
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
590
			$speed = $match_array[1][0];
591
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
592
			$borrows = $match_array[1][0];
593
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
594
			$suspends = $match_array[1][0];
595
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
596
			$drops = $match_array[1][0];
597
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
598
			$measured = $match_array[1][0];
599
			if($dont_return_root_queues == true)
600
				if(stristr($queue_name,"root_") == false)
601
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
602
		}
603
	}
604
	return $queue_stats;
605
}
606

    
607
/*
608
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
609
 *					 Useful for finding paths and stripping file extensions.
610
 */
611
function reverse_strrchr($haystack, $needle) {
612
	if (!is_string($haystack))
613
		return;
614
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
615
}
616

    
617
/*
618
 *  backup_config_section($section): returns as an xml file string of
619
 *                                   the configuration section
620
 */
621
function backup_config_section($section) {
622
	global $config;
623
	$new_section = &$config[$section];
624
	/* generate configuration XML */
625
	$xmlconfig = dump_xml_config($new_section, $section);
626
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
627
	return $xmlconfig;
628
}
629

    
630
/*
631
 *  restore_config_section($section, new_contents): restore a configuration section,
632
 *                                                  and write the configuration out
633
 *                                                  to disk/cf.
634
 */
635
function restore_config_section($section, $new_contents) {
636
	global $config, $g;
637
	conf_mount_rw();
638
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
639
	fwrite($fout, $new_contents);
640
	fclose($fout);
641
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
642
	if ($section_xml != -1)
643
		$config[$section] = &$section_xml;
644
	@unlink($g['tmp_path'] . "/tmpxml");
645
	if(file_exists("{$g['tmp_path']}/config.cache"))
646
		unlink("{$g['tmp_path']}/config.cache");
647
	write_config("Restored {$section} of config file (maybe from CARP partner)");
648
	conf_mount_ro();
649
	return;
650
}
651

    
652
/*
653
 *  merge_config_section($section, new_contents):   restore a configuration section,
654
 *                                                  and write the configuration out
655
 *                                                  to disk/cf.  But preserve the prior
656
 * 													structure if needed
657
 */
658
function merge_config_section($section, $new_contents) {
659
	global $config;
660
	conf_mount_rw();
661
	$fname = get_tmp_filename();
662
	$fout = fopen($fname, "w");
663
	fwrite($fout, $new_contents);
664
	fclose($fout);
665
	$section_xml = parse_xml_config($fname, $section);
666
	$config[$section] = $section_xml;
667
	unlink($fname);
668
	write_config("Restored {$section} of config file (maybe from CARP partner)");
669
	conf_mount_ro();
670
	return;
671
}
672

    
673
/*
674
 * http_post($server, $port, $url, $vars): does an http post to a web server
675
 *                                         posting the vars array.
676
 * written by nf@bigpond.net.au
677
 */
678
function http_post($server, $port, $url, $vars) {
679
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
680
	$urlencoded = "";
681
	while (list($key,$value) = each($vars))
682
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
683
	$urlencoded = substr($urlencoded,0,-1);
684
	$content_length = strlen($urlencoded);
685
	$headers = "POST $url HTTP/1.1
686
Accept: */*
687
Accept-Language: en-au
688
Content-Type: application/x-www-form-urlencoded
689
User-Agent: $user_agent
690
Host: $server
691
Connection: Keep-Alive
692
Cache-Control: no-cache
693
Content-Length: $content_length
694

    
695
";
696

    
697
	$errno = "";
698
	$errstr = "";
699
	$fp = fsockopen($server, $port, $errno, $errstr);
700
	if (!$fp) {
701
		return false;
702
	}
703

    
704
	fputs($fp, $headers);
705
	fputs($fp, $urlencoded);
706

    
707
	$ret = "";
708
	while (!feof($fp))
709
		$ret.= fgets($fp, 1024);
710
	fclose($fp);
711

    
712
	return $ret;
713
}
714

    
715
/*
716
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
717
 */
718
if (!function_exists('php_check_syntax')){
719
	global $g;
720
	function php_check_syntax($code_to_check, &$errormessage){
721
		return false;
722
		$fout = fopen("{$g['tmp_path']}/codetocheck.php","w");
723
		$code = $_POST['content'];
724
		$code = str_replace("<?php", "", $code);
725
		$code = str_replace("?>", "", $code);
726
		fwrite($fout, "<?php\n\n");
727
		fwrite($fout, $code_to_check);
728
		fwrite($fout, "\n\n?>\n");
729
		fclose($fout);
730
		$command = "/usr/local/bin/php -l {$g['tmp_path']}/codetocheck.php";
731
		$output = exec_command($command);
732
		if (stristr($output, "Errors parsing") == false) {
733
			echo "false\n";
734
			$errormessage = '';
735
			return(false);
736
		} else {
737
			$errormessage = $output;
738
			return(true);
739
		}
740
	}
741
}
742

    
743
/*
744
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
745
 */
746
if (!function_exists('php_check_syntax')){
747
	function php_check_syntax($code_to_check, &$errormessage){
748
		return false;
749
		$command = "/usr/local/bin/php -l " . $code_to_check;
750
		$output = exec_command($command);
751
		if (stristr($output, "Errors parsing") == false) {
752
			echo "false\n";
753
			$errormessage = '';
754
			return(false);
755
		} else {
756
			$errormessage = $output;
757
			return(true);
758
		}
759
	}
760
}
761

    
762
/*
763
 * rmdir_recursive($path,$follow_links=false)
764
 * Recursively remove a directory tree (rm -rf path)
765
 * This is for directories _only_
766
 */
767
function rmdir_recursive($path,$follow_links=false) {
768
	$to_do = glob($path);
769
	if(!is_array($to_do)) $to_do = array($to_do);
770
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
771
		if(file_exists($workingdir)) {
772
			if(is_dir($workingdir)) {
773
				$dir = opendir($workingdir);
774
				while ($entry = readdir($dir)) {
775
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
776
						unlink("$workingdir/$entry");
777
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
778
						rmdir_recursive("$workingdir/$entry");
779
				}
780
				closedir($dir);
781
				rmdir($workingdir);
782
			} elseif (is_file($workingdir)) {
783
				unlink($workingdir);
784
			}
785
               	}
786
	}
787
	return;
788
}
789

    
790
/*
791
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
792
 */
793
function call_pfsense_method($method, $params, $timeout = 0) {
794
	global $g, $config;
795

    
796
	$ip = gethostbyname($g['product_website']);
797
	if($ip == $g['product_website'])
798
		return false;
799

    
800
	$xmlrpc_base_url = isset($config['system']['altpkgrepo']['enable']) ? $config['system']['altpkgrepo']['xmlrpcbaseurl'] : $g['xmlrpcbaseurl'];
801
	$xmlrpc_path = $g['xmlrpcpath'];
802
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
803
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
804
	// If the ALT PKG Repo has a username/password set, use it.
805
	if($config['system']['altpkgrepo']['username'] && 
806
	   $config['system']['altpkgrepo']['password']) {
807
		$username = $config['system']['altpkgrepo']['username'];
808
		$password = $config['system']['altpkgrepo']['password'];
809
		$cli->setCredentials($username, $password);
810
	}
811
	$resp = $cli->send($msg, $timeout);
812
	if(!$resp) {
813
		log_error("XMLRPC communication error: " . $cli->errstr);
814
		return false;
815
	} elseif($resp->faultCode()) {
816
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
817
		return false;
818
	} else {
819
		return XML_RPC_Decode($resp->value());
820
	}
821
}
822

    
823
/*
824
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
825
 */
826
function check_firmware_version($tocheck = "all", $return_php = true) {
827
	global $g, $config;
828
	$ip = gethostbyname($g['product_website']);
829
	if($ip == $g['product_website'])
830
		return false;
831
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
832
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
833
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
834
		"platform" => trim(file_get_contents('/etc/platform'))
835
		);
836
	if($tocheck == "all") {
837
		$params = $rawparams;
838
	} else {
839
		foreach($tocheck as $check) {
840
			$params['check'] = $rawparams['check'];
841
			$params['platform'] = $rawparams['platform'];
842
		}
843
	}
844
	if($config['system']['firmware']['branch']) {
845
		$params['branch'] = $config['system']['firmware']['branch'];
846
	}
847
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
848
		return false;
849
	} else {
850
		$versions["current"] = $params;
851
	}
852
	return $versions;
853
}
854

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

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

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

    
889
	/* XXX: Use locks?! */
890
	if (file_exists("{$g['tmp_path']}/reloading_all")) {
891
		log_error("WARNING: Recursive call to interfaces sync!");
892
		return;
893
	}
894
	touch("{$g['tmp_path']}/reloading_all");
895

    
896
	if($g['debug'])
897
		log_error("reload_interfaces_sync() is starting.");
898

    
899
	/* parse config.xml again */
900
	$config = parse_config(true);
901

    
902
	/* enable routing */
903
	system_routing_enable();
904
	if($g['debug'])
905
		log_error("Enabling system routing");
906

    
907
	if($g['debug'])
908
		log_error("Cleaning up Interfaces");
909

    
910
	/* set up interfaces */
911
	interfaces_configure();
912

    
913
	/* remove reloading_all trigger */
914
	if($g['debug'])
915
		log_error("Removing {$g['tmp_path']}/reloading_all");
916

    
917
	/* start devd back up */
918
	mwexec("/bin/rm {$g['tmp_path']}/reload*");
919
}
920

    
921
/****f* pfsense-utils/reload_all
922
 * NAME
923
 *   reload_all - triggers a reload of all settings
924
 *   * INPUTS
925
 *   none
926
 * RESULT
927
 *   none
928
 ******/
929
function reload_all() {
930
	global $g;
931
	touch("{$g['tmp_path']}/reload_all");
932
}
933

    
934
/****f* pfsense-utils/reload_interfaces
935
 * NAME
936
 *   reload_interfaces - triggers a reload of all interfaces
937
 * INPUTS
938
 *   none
939
 * RESULT
940
 *   none
941
 ******/
942
function reload_interfaces() {
943
	global $g;
944
	touch("{$g['tmp_path']}/reload_interfaces");
945
}
946

    
947
/****f* pfsense-utils/reload_all_sync
948
 * NAME
949
 *   reload_all - reload all settings
950
 *   * INPUTS
951
 *   none
952
 * RESULT
953
 *   none
954
 ******/
955
function reload_all_sync() {
956
	global $config, $g;
957

    
958
	$g['booting'] = false;
959

    
960
	/* XXX: Use locks?! */
961
        if (file_exists("{$g['tmp_path']}/reloading_all")) {
962
                log_error("WARNING: Recursive call to reload all sync!");
963
                return;
964
        }
965
	touch("{$g['tmp_path']}/reloading_all");
966

    
967
	/* parse config.xml again */
968
	$config = parse_config(true);
969

    
970
	/* set up our timezone */
971
	system_timezone_configure();
972

    
973
	/* set up our hostname */
974
	system_hostname_configure();
975

    
976
	/* make hosts file */
977
	system_hosts_generate();
978

    
979
	/* generate resolv.conf */
980
	system_resolvconf_generate();
981

    
982
	/* enable routing */
983
	system_routing_enable();
984

    
985
	/* set up interfaces */
986
	interfaces_configure();
987

    
988
	/* start dyndns service */
989
	services_dyndns_configure();
990

    
991
	/* configure cron service */
992
	configure_cron();
993

    
994
	/* start the NTP client */
995
	system_ntp_configure();
996

    
997
	/* sync pw database */
998
	conf_mount_rw();
999
	unlink_if_exists("/etc/spwd.db.tmp");
1000
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1001
	conf_mount_ro();
1002

    
1003
	/* restart sshd */
1004
	@touch("{$g['tmp_path']}/start_sshd");
1005

    
1006
	/* restart webConfigurator if needed */
1007
	touch("{$g['tmp_path']}/restart_webgui");
1008

    
1009
	mwexec("/bin/rm {$g['tmp_path']}/reload*");
1010
}
1011

    
1012
function auto_login() {
1013
	global $config;
1014

    
1015
	if(isset($config['system']['disableconsolemenu']))
1016
		$status = false;
1017
	else
1018
		$status = true;
1019

    
1020
	$gettytab = file_get_contents("/etc/gettytab");
1021
	$getty_split = split("\n", $gettytab);
1022
	conf_mount_rw();
1023
	$fd = false;
1024
	$tries = 0;
1025
	while (!$fd && $tries < 100) {
1026
		$fd = fopen("/etc/gettytab", "w");
1027
		$tries++;
1028
		
1029
	}
1030
	if (!$fd) {
1031
		conf_mount_ro();
1032
		log_error("Enabling auto login was not possible.");
1033
		return;
1034
	}
1035
	foreach($getty_split as $gs) {
1036
		if(stristr($gs, ":ht:np:sp#115200") ) {
1037
			if($status == true) {
1038
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
1039
			} else {
1040
				fwrite($fd, "	:ht:np:sp#115200:\n");
1041
			}
1042
		} else {
1043
			fwrite($fd, "{$gs}\n");
1044
		}
1045
	}
1046
	fclose($fd);
1047
	conf_mount_ro();
1048
}
1049

    
1050
function setup_serial_port() {
1051
	global $g, $config;
1052
	conf_mount_rw();
1053
	/* serial console - write out /boot.config */
1054
	if(file_exists("/boot.config"))
1055
		$boot_config = file_get_contents("/boot.config");
1056
	else
1057
		$boot_config = "";
1058

    
1059
	if($g['platform'] <> "cdrom") {
1060
		$boot_config_split = split("\n", $boot_config);
1061
		$fd = fopen("/boot.config","w");
1062
		if($fd) {
1063
			foreach($boot_config_split as $bcs) {
1064
				if(stristr($bcs, "-D")) {
1065
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1066
				} else {
1067
					if($bcs <> "")
1068
						fwrite($fd, "{$bcs}\n");
1069
				}
1070
			}
1071
			if(isset($config['system']['enableserial'])) {
1072
				fwrite($fd, "-D");
1073
			}
1074
			fclose($fd);
1075
		}
1076
		/* serial console - write out /boot/loader.conf */
1077
		$boot_config = file_get_contents("/boot/loader.conf");
1078
		$boot_config_split = split("\n", $boot_config);
1079
		$fd = fopen("/boot/loader.conf","w");
1080
		if($fd) {
1081
			foreach($boot_config_split as $bcs) {
1082
				if(stristr($bcs, "console")) {
1083
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1084
				} else {
1085
					if($bcs <> "")
1086
						fwrite($fd, "{$bcs}\n");
1087
				}
1088
			}
1089
			if(isset($config['system']['enableserial'])) {
1090
				fwrite($fd, "console=\"comconsole\"\n");
1091
			}
1092
			fclose($fd);
1093
		}
1094
	}
1095
	$ttys = file_get_contents("/etc/ttys");
1096
	$ttys_split = split("\n", $ttys);
1097
	$fd = fopen("/etc/ttys", "w");
1098
	foreach($ttys_split as $tty) {
1099
		if(stristr($tty, "ttyd0") or stristr($tty, "ttyu0")) {
1100
			if(isset($config['system']['enableserial'])) {
1101
				fwrite($fd, "ttyu0	\"/usr/libexec/getty bootupcli\"	cons25	on	secure\n");
1102
			} else {
1103
				fwrite($fd, "ttyu0	\"/usr/libexec/getty bootupcli\"	cons25	off	secure\n");
1104
			}
1105
		} else {
1106
			fwrite($fd, $tty . "\n");
1107
		}
1108
	}
1109
	fclose($fd);
1110
	auto_login();
1111

    
1112
	conf_mount_ro();
1113
	return;
1114
}
1115

    
1116
function print_value_list($list, $count = 10, $separator = ",") {
1117
	$list = implode($separator, array_slice($list, 0, $count));
1118
	if(count($list) < $count) {
1119
		$list .= ".";
1120
	} else {
1121
		$list .= "...";
1122
	}
1123
	return $list;
1124
}
1125

    
1126
/* DHCP enabled on any interfaces? */
1127
function is_dhcp_server_enabled() 
1128
{
1129
	global $config;
1130

    
1131
	$dhcpdenable = false;
1132
	
1133
	if (!is_array($config['dhcpd']))
1134
		return false;
1135

    
1136
	$Iflist = get_configured_interface_list();
1137

    
1138
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1139
		if (isset($dhcpifconf['enable']) && isset($Iflist[$dhcpif])) {
1140
			$dhcpdenable = true;
1141
			break;
1142
		}
1143
	}
1144

    
1145
	return $dhcpdenable;
1146
}
1147

    
1148
function convert_seconds_to_hms($sec){
1149
	$min=$hrs=0;
1150
	if ($sec != 0){
1151
		$min = floor($sec/60);
1152
		$sec %= 60;
1153
	}
1154
	if ($min != 0){
1155
		$hrs = floor($min/60);
1156
		$min %= 60;
1157
	}
1158
	if ($sec < 10)
1159
		$sec = "0".$sec;
1160
	if ($min < 10)
1161
		$min = "0".$min;
1162
	if ($hrs < 10)
1163
		$hrs = "0".$hrs;
1164
	$result = $hrs.":".$min.":".$sec;
1165
	return $result;
1166
}
1167

    
1168
/* Compute the total uptime from the ppp uptime log file in the conf directory */
1169
/* Written by: gnoahb@gmail.com */
1170

    
1171
function get_ppp_uptime($port){
1172
	if (file_exists("/conf/{$port}.log")){
1173
    	$saved_time = file_get_contents("/conf/{$port}.log");
1174
    	$uptime_data = explode("\n",$saved_time);
1175
		$sec=0;
1176
		foreach($uptime_data as $upt) {
1177
			$sec += substr($upt, 1 + strpos($upt, " "));
1178
 		}
1179
		return convert_seconds_to_hms($sec);
1180
	} else {
1181
		$total_time = "No session history data found!";
1182
		return $total_time;
1183
	}
1184
}
1185

    
1186
//returns interface information
1187
function get_interface_info($ifdescr) {
1188
	global $config, $g;
1189

    
1190
	$ifinfo = array();
1191
	if (empty($config['interfaces'][$ifdescr]))
1192
		return;
1193
	$ifinfo['hwif'] = $config['interfaces'][$if]['if'];
1194
	$ifinfo['if'] = get_real_interface($ifdescr);
1195

    
1196
	$chkif = $ifinfo['if'];
1197
	$ifinfotmp = pfSense_get_interface_addresses($chkif);
1198
	$ifinfo['status'] = $ifinfotmp['status'];
1199
	if (empty($ifinfo['status']))
1200
                $ifinfo['status'] = "down";
1201
	$ifinfo['macaddr'] = $ifinfotmp['macaddr'];
1202
	$ifinfo['ipaddr'] = $ifinfotmp['ipaddr'];
1203
	$ifinfo['subnet'] = $ifinfotmp['subnet'];
1204
	if (isset($ifinfotmp['link0']))
1205
		$link0 = "down";
1206
	$ifinfotmp = pfSense_get_interface_stats($chkif);
1207
        $ifinfo['inpkts'] = $ifinfotmp['inpkts'];
1208
        $ifinfo['outpkts'] = $ifinfotmp['outpkts'];
1209
        $ifinfo['inerrs'] = $ifinfotmp['inerrs'];
1210
        $ifinfo['outerrs'] = $ifinfotmp['outerrs'];
1211
        $ifinfo['collisions'] = $ifinfotmp['collisions'];
1212

    
1213
	/* Use pfctl for non wrapping 64 bit counters */
1214
	/* Pass */
1215
	exec("/sbin/pfctl -vvsI -i {$chkif}", $pfctlstats);
1216
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1217
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1218
	$in4_pass = $pf_in4_pass[5];
1219
	$out4_pass = $pf_out4_pass[5];
1220
	$in4_pass_packets = $pf_in4_pass[3];
1221
	$out4_pass_packets = $pf_out4_pass[3];
1222
	$ifinfo['inbytespass'] = $in4_pass;
1223
	$ifinfo['outbytespass'] = $out4_pass;
1224
	$ifinfo['inpktspass'] = $in4_pass_packets;
1225
	$ifinfo['outpktspass'] = $out4_pass_packets;
1226

    
1227
	/* Block */
1228
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1229
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1230
	$in4_block = $pf_in4_block[5];
1231
	$out4_block = $pf_out4_block[5];
1232
	$in4_block_packets = $pf_in4_block[3];
1233
	$out4_block_packets = $pf_out4_block[3];
1234
	$ifinfo['inbytesblock'] = $in4_block;
1235
	$ifinfo['outbytesblock'] = $out4_block;
1236
	$ifinfo['inpktsblock'] = $in4_block_packets;
1237
	$ifinfo['outpktsblock'] = $out4_block_packets;
1238

    
1239
	$ifinfo['inbytes'] = $in4_pass + $in4_block;
1240
	$ifinfo['outbytes'] = $out4_pass + $out4_block;
1241
	$ifinfo['inpkts'] = $in4_pass_packets + $in4_block_packets;
1242
	$ifinfo['outpkts'] = $in4_pass_packets + $out4_block_packets;
1243
		
1244
	$ifconfiginfo = "";
1245
	
1246
	switch ($config['interfaces'][$ifdescr]['ipaddr']) {
1247
	 /* DHCP? -> see if dhclient is up */
1248
	case "dhcp":
1249
	case "carpdev-dhcp":
1250
		/* see if dhclient is up */
1251
		if (find_dhclient_process($ifinfo['if']) <> "")
1252
			$ifinfo['dhcplink'] = "up";
1253
		else
1254
			$ifinfo['dhcplink'] = "down";
1255

    
1256
		break;
1257
	/* PPPoE interface? -> get status from virtual interface */
1258
	case "pppoe":
1259
		if ($ifinfo['status'] == "up" && !isset($link0))
1260
                        /* get PPPoE link status for dial on demand */
1261
                        $ifinfo['pppoelink'] = "up";
1262
		else
1263
			$ifinfo['pppoelink'] = "down";
1264

    
1265
		break;
1266
	/* PPTP interface? -> get status from virtual interface */
1267
	case "pptp":
1268
		if ($ifinfo['status'] == "up" && !isset($link0))
1269
                        /* get PPTP link status for dial on demand */
1270
                        $ifinfo['pptplink'] = "up";
1271
		else
1272
			$ifinfo['pptplink'] = "down";
1273
		break;
1274
	/* PPP interface? -> get uptime for this session and cumulative uptime from the persistant log file in conf */
1275
	case "ppp":
1276
		if ($ifinfo['status'] == "up")
1277
                        $ifinfo['ppplink'] = "up";
1278
		else
1279
			$ifinfo['ppplink'] = "down" ;
1280

    
1281
		$dev = $config['interfaces'][$if]['if'];
1282
		if (empty($dev))
1283
			break;
1284
		if (file_exists("/dev/{$dev}")) {
1285
			if (file_exists("{$g['varrun_path']}/ppp_{$if}.pid")) {
1286
				$ifinfo['pppinfo'] = "{$ifinfo['if']}";
1287
				$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1288
        		$ifinfo['ppp_uptime'] = convert_seconds_to_hms($sec);
1289
			}
1290
		} else {
1291
			$ifinfo['nodevice'] = 1;
1292
			$ifinfo['pppinfo'] = $dev . " device not present! Is the modem attached to the system?";	
1293
		}
1294
		// Calculate cumulative uptime for PPP link. Useful for connections that have per minute/hour contracts so you don't go over!
1295
		$ifinfo['ppp_uptime_accumulated'] = get_ppp_uptime($ifinfo['if']);
1296

    
1297
		break;
1298
	default:
1299
		break;
1300
	}
1301

    
1302
	if ($ifinfo['status'] == "up") {
1303
		/* try to determine media with ifconfig */
1304
		unset($ifconfiginfo);
1305
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1306
		$wifconfiginfo = array();
1307
		if(is_interface_wireless($ifdescr)) {
1308
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1309
			array_shift($wifconfiginfo);
1310
		}
1311
		$matches = "";
1312
		foreach ($ifconfiginfo as $ici) {
1313

    
1314
			/* don't list media/speed for wireless cards, as it always
1315
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1316
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1317
				$ifinfo['media'] = $matches[1];
1318
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1319
				$ifinfo['media'] = $matches[1];
1320
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1321
				$ifinfo['media'] = $matches[1];
1322
			}
1323

    
1324
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
1325
				if ($matches[1] != "active")
1326
					$ifinfo['status'] = $matches[1];
1327
				if($ifinfo['status'] == "running")
1328
					$ifinfo['status'] = "up";
1329
			}
1330
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
1331
				$ifinfo['channel'] = $matches[1];
1332
			}
1333
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
1334
				if ($matches[1][0] == '"')
1335
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
1336
				else
1337
					$ifinfo['ssid'] = $matches[1];
1338
			}
1339
		}
1340
		foreach($wifconfiginfo as $ici) {
1341
			$elements = preg_split("/[ ]+/i", $ici);
1342
			if ($elements[0] != "") {
1343
				$ifinfo['bssid'] = $elements[0];
1344
			}
1345
			if ($elements[3] != "") {
1346
				$ifinfo['rate'] = $elements[3];
1347
			}
1348
			if ($elements[4] != "") {
1349
				$ifinfo['rssi'] = $elements[4];
1350
			}
1351

    
1352
		}
1353
		/* lookup the gateway */
1354
		if (interface_has_gateway($if)) 
1355
			$ifinfo['gateway'] = get_interface_gateway($if);
1356
	}
1357

    
1358
	$bridge = "";
1359
	$bridge = link_interface_to_bridge($ifdescr);
1360
	if($bridge) {
1361
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1362
		if(stristr($bridge_text, "blocking") <> false) {
1363
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
1364
			$ifinfo['bridgeint'] = $bridge;
1365
		} else if(stristr($bridge_text, "learning") <> false) {
1366
			$ifinfo['bridge'] = "learning";
1367
			$ifinfo['bridgeint'] = $bridge;
1368
		} else if(stristr($bridge_text, "forwarding") <> false) {
1369
			$ifinfo['bridge'] = "forwarding";
1370
			$ifinfo['bridgeint'] = $bridge;
1371
		}
1372
	}
1373

    
1374
	return $ifinfo;
1375
}
1376

    
1377
//returns cpu speed of processor. Good for determining capabilities of machine
1378
function get_cpu_speed() {
1379
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
1380
}
1381

    
1382
function add_hostname_to_watch($hostname) {
1383
	if(!is_dir("/var/db/dnscache")) {
1384
		mkdir("/var/db/dnscache");
1385
	}
1386
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1387
		$domrecords = array();
1388
		$domips = array();
1389
		exec("host -t A $hostname", $domrecords, $rethost);
1390
		if($rethost == 0) {
1391
			foreach($domrecords as $domr) {
1392
				$doml = explode(" ", $domr);
1393
				$domip = $doml[3];
1394
				/* fill array with domain ip addresses */
1395
				if(is_ipaddr($domip)) {
1396
					$domips[] = $domip;
1397
				}
1398
			}
1399
		}
1400
		sort($domips);
1401
		$contents = "";
1402
		if(! empty($domips)) {
1403
			foreach($domips as $ip) {
1404
				$contents .= "$ip\n";
1405
			}
1406
		}
1407
		file_put_contents("/var/db/dnscache/$hostname", $contents);
1408
	}
1409
}
1410

    
1411
function is_fqdn($fqdn) {
1412
	$hostname = false;
1413
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1414
		$hostname = true;
1415
	}
1416
	if(preg_match("/\.\./", $fqdn)) {
1417
		$hostname = false;
1418
	}
1419
	if(preg_match("/^\./i", $fqdn)) { 
1420
		$hostname = false;
1421
	}
1422
	if(preg_match("/\//i", $fqdn)) {
1423
		$hostname = false;
1424
	}
1425
	return($hostname);
1426
}
1427

    
1428
function pfsense_default_state_size() {
1429
  /* get system memory amount */
1430
  $memory = get_memory();
1431
  $avail = $memory[0];
1432
  /* Be cautious and only allocate 10% of system memory to the state table */
1433
  $max_states = (int) ($avail/10)*1000;
1434
  return $max_states;
1435
}
1436

    
1437
function pfsense_default_table_entries_size() {
1438
	$current = `pfctl -sm | grep table-entries | awk '{print $4};'`;
1439
	return $current;
1440
}
1441

    
1442
/* Compare the current hostname DNS to the DNS cache we made
1443
 * if it has changed we return the old records
1444
 * if no change we return true */
1445
function compare_hostname_to_dnscache($hostname) {
1446
	if(!is_dir("/var/db/dnscache")) {
1447
		mkdir("/var/db/dnscache");
1448
	}
1449
	$hostname = trim($hostname);
1450
	if(is_readable("/var/db/dnscache/{$hostname}")) {
1451
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
1452
	} else {
1453
		$oldcontents = "";
1454
	}
1455
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1456
		$domrecords = array();
1457
		$domips = array();
1458
		exec("host -t A $hostname", $domrecords, $rethost);
1459
		if($rethost == 0) {
1460
			foreach($domrecords as $domr) {
1461
				$doml = explode(" ", $domr);
1462
				$domip = $doml[3];
1463
				/* fill array with domain ip addresses */
1464
				if(is_ipaddr($domip)) {
1465
					$domips[] = $domip;
1466
				}
1467
			}
1468
		}
1469
		sort($domips);
1470
		$contents = "";
1471
		if(! empty($domips)) {
1472
			foreach($domips as $ip) {
1473
				$contents .= "$ip\n";
1474
			}
1475
		}
1476
	}
1477

    
1478
	if(trim($oldcontents) != trim($contents)) {
1479
		if($g['debug']) {
1480
			log_error("DNSCACHE: Found old IP {$oldcontents} and new IP {$contents}");
1481
		}
1482
		return ($oldcontents);
1483
	} else {
1484
		return false;
1485
	}
1486
}
1487

    
1488
/*
1489
 * load_glxsb() - Load the glxsb crypto module if enabled in config.
1490
 */
1491
function load_glxsb() {
1492
	global $config, $g;
1493
	$is_loaded = `/sbin/kldstat | /usr/bin/grep -c glxsb`;
1494
	if (isset($config['system']['glxsb_enable']) && ($is_loaded == 0)) {
1495
		mwexec("/sbin/kldload glxsb");
1496
	}
1497
}
1498

    
1499
/****f* pfsense-utils/isvm
1500
 * NAME
1501
 *   isvm
1502
 * INPUTS
1503
 *	 none
1504
 * RESULT
1505
 *   returns true if machine is running under a virtual environment
1506
 ******/
1507
function isvm() {
1508
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86");
1509
	$bios_vendor = strtolower(`/bin/kenv | /usr/bin/awk -F= '/smbios.bios.vendor/ {print $2}'`);
1510
	if(in_array($bios_vendor, $virtualenvs)) 
1511
		return true;
1512
	else
1513
		return false;
1514
}
1515

    
1516
function get_freebsd_version() {
1517
	$version = trim(`/usr/bin/uname -r | /usr/bin/cut  -d'.' -f1`);
1518
	return $version;
1519
}
1520

    
1521
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body') {
1522
        global $ch, $fout, $file_size, $downloaded;
1523
        $file_size  = 1;
1524
        $downloaded = 1;
1525
        /* open destination file */
1526
        $fout = fopen($destination_file, "wb");
1527

    
1528
        /*
1529
         *      Originally by Author: Keyvan Minoukadeh
1530
         *      Modified by Scott Ullrich to return Content-Length size
1531
         */
1532

    
1533
        $ch = curl_init();
1534
        curl_setopt($ch, CURLOPT_URL, $url_file);
1535
        curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1536
        curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1537
        curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1538
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, '5');
1539
        curl_setopt($ch, CURLOPT_TIMEOUT, 0);
1540

    
1541
        curl_exec($ch);
1542
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1543
        if($fout)
1544
                fclose($fout);
1545
        curl_close($ch);
1546
        return ($http_code == 200) ? true : $http_code;
1547
}
1548

    
1549
function read_header($ch, $string) {
1550
        global $file_size, $fout;
1551
        $length = strlen($string);
1552
        $regs = "";
1553
        ereg("(Content-Length:) (.*)", $string, $regs);
1554
        if($regs[2] <> "") {
1555
                $file_size = intval($regs[2]);
1556
        }
1557
        ob_flush();
1558
        return $length;
1559
}
1560

    
1561
function read_body($ch, $string) {
1562
        global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen;
1563
        $length = strlen($string);
1564
        $downloaded += intval($length);
1565
        $downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1566
        $downloadProgress = 100 - $downloadProgress;
1567
        if($lastseen <> $downloadProgress and $downloadProgress < 101) {
1568
                if($sendto == "status") {
1569
                        $tostatus = $static_status . $downloadProgress . "%";
1570
                        update_status($tostatus);
1571
                } else {
1572
                        $tooutput = $static_output . $downloadProgress . "%";
1573
                        update_output_window($tooutput);
1574
                }
1575
                update_progress_bar($downloadProgress);
1576
                $lastseen = $downloadProgress;
1577
        }
1578
        if($fout)
1579
                fwrite($fout, $string);
1580
        ob_flush();
1581
        return $length;
1582
}
1583

    
1584
/*
1585
 *   update_output_window: update bottom textarea dynamically.
1586
 */
1587
function update_output_window($text) {
1588
        global $pkg_interface;
1589
        $log = ereg_replace("\n", "\\n", $text);
1590
        if($pkg_interface == "console") {
1591
                /* too chatty */
1592
        } else {
1593
                echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1594
        }
1595
        /* ensure that contents are written out */
1596
        ob_flush();
1597
}
1598

    
1599
/*
1600
 *   update_output_window: update top textarea dynamically.
1601
 */
1602
function update_status($status) {
1603
        global $pkg_interface;
1604
        if($pkg_interface == "console") {
1605
                echo $status . "\n";
1606
        } else {
1607
                echo "\n<script type=\"text/javascript\">this.document.forms[0].status.value=\"" . $status . "\";</script>";
1608
        }
1609
        /* ensure that contents are written out */
1610
        ob_flush();
1611
}
1612

    
1613
/*
1614
 * update_progress_bar($percent): updates the javascript driven progress bar.
1615
 */
1616
function update_progress_bar($percent) {
1617
        global $pkg_interface;
1618
        if($percent > 100) $percent = 1;
1619
        if($pkg_interface <> "console") {
1620
                echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1621
                echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1622
                echo "\n</script>";
1623
        } else {
1624
                echo " {$percent}%";
1625
        }
1626
}
1627

    
1628
/* 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. */
1629
if(!function_exists("split")) {
1630
	function split($seperator, $haystack, $limit = null) {
1631
		return preg_split($seperator, $haystack, $limit);
1632
	}
1633
}
1634

    
1635
function update_alias_names_upon_change($section, $subsection, $fielda, $fieldb, $new_alias_name, $origname) {
1636
	global $g, $config, $pconfig, $debug;
1637
	if(!$origname) 
1638
		return;
1639

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

    
1643
	if($fieldb) {
1644
		if($debug) fwrite($fd, "fieldb exists\n");
1645
		for ($i = 0; isset($config["$section"]["$subsection"][$i]["$fielda"]); $i++) {
1646
			if($debug) fwrite($fd, "$i\n");
1647
			if($config["$section"]["$subsection"][$i]["$fielda"]["$fieldb"] == $origname) {
1648
				if($debug) fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1649
				$config["$section"]["$subsection"][$i]["$fielda"]["$fieldb"] = $new_alias_name;
1650
			}
1651
		}	
1652
	} else {
1653
		if($debug) fwrite($fd, "fieldb does not exist\n");
1654
		for ($i = 0; isset($config["$section"]["$subsection"][$i]["$fielda"]); $i++) {
1655
			if($config["$section"]["$subsection"][$i]["$fielda"] == $origname) {
1656
				$config["$section"]["$subsection"][$i]["$fielda"] = $new_alias_name;
1657
				if($debug) fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1658
			}
1659
		}
1660
	}
1661

    
1662
	if($debug) fclose($fd);
1663

    
1664
}
1665

    
1666
function update_alias_url_data() {
1667
	global $config, $g;
1668
	/* item is a url type */
1669
	$lockkey = lock('config');
1670
	for($x=0; $x<count($config['aliases']['alias']); $x++) {
1671
		if($config['aliases']['alias'][$x]['aliasurl']) {
1672
			/* fetch down and add in */
1673
			$isfirst = 0;
1674
			$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
1675
			unlink($temp_filename);
1676
			$fda = fopen("{$g['tmp_path']}/tmpfetch","w");
1677
			fwrite($fda, "/usr/bin/fetch -q -o \"{$temp_filename}/aliases\" \"" . $config['aliases']['alias'][$x]['aliasurl'] . "\"");
1678
			fclose($fda);
1679
			mwexec("/bin/mkdir -p {$temp_filename}");
1680
			mwexec("/usr/bin/fetch -q -o \"{$temp_filename}/aliases\" \"" . $config['aliases']['alias'][$x]['aliasurl'] . "\"");
1681
			/* if the item is tar gzipped then extract */
1682
			if(stristr($config['aliases']['alias'][$x]['aliasurl'], ".tgz"))
1683
				process_alias_tgz($temp_filename);
1684
			if(stristr($config['aliases']['alias'][$x]['aliasurl'], ".zip"))
1685
				process_alias_unzip($temp_filename);
1686
			if(file_exists("{$temp_filename}/aliases")) {
1687
				$file_contents = file_get_contents("{$temp_filename}/aliases");
1688
				$file_contents = str_replace("#", "\n#", $file_contents);
1689
				$file_contents_split = split("\n", $file_contents);
1690
				foreach($file_contents_split as $fc) {
1691
					$tmp = trim($fc);
1692
					if(stristr($fc, "#")) {
1693
						$tmp_split = split("#", $tmp);
1694
						$tmp = trim($tmp_split[0]);
1695
					}
1696
					if(trim($tmp) <> "") {
1697
						if($isfirst == 1)
1698
							$address .= " ";
1699
						$address .= $tmp;
1700
						$isfirst = 1;
1701
					}
1702
				}
1703
				if($isfirst == 0) {
1704
					/* nothing was found */
1705
					$dont_update = true;
1706
					break;
1707
				}
1708
				if(!$dont_update) {
1709
					$config['aliases']['alias'][$x]['address'] = $address;
1710
					$updated = true;
1711
				}
1712
				mwexec("/bin/rm -rf {$temp_filename}");
1713
			}
1714
		}
1715
	}
1716
	if($updated)
1717
		write_config();
1718
	unlock($lockkey);
1719
}
1720

    
1721
function process_alias_unzip($temp_filename) {
1722
	if(!file_exists("/usr/local/bin/unzip"))
1723
		return;
1724
	mwexec("/bin/mv {$temp_filename}/aliases {$temp_filename}/aliases.zip");
1725
	mwexec("/usr/local/bin/unzip {$temp_filename}/aliases.tgz -d {$temp_filename}/aliases/");
1726
	unlink("{$temp_filename}/aliases.zip");
1727
	$files_to_process = return_dir_as_array("{$temp_filename}/");
1728
	/* foreach through all extracted files and build up aliases file */
1729
	$fd = fopen("{$temp_filename}/aliases", "w");
1730
	foreach($files_to_process as $f2p) {
1731
		$file_contents = file_get_contents($f2p);
1732
		fwrite($fd, $file_contents);
1733
		unlink($f2p);
1734
	}
1735
	fclose($fd);
1736
}
1737

    
1738
function process_alias_tgz($temp_filename) {
1739
	if(!file_exists("/usr/bin/tar"))
1740
		return;
1741
	mwexec("/bin/mv {$temp_filename}/aliases {$temp_filename}/aliases.tgz");
1742
	mwexec("/usr/bin/tar xzf {$temp_filename}/aliases.tgz -C {$temp_filename}/aliases/");
1743
	unlink("{$temp_filename}/aliases.tgz");
1744
	$files_to_process = return_dir_as_array("{$temp_filename}/");
1745
	/* foreach through all extracted files and build up aliases file */
1746
	$fd = fopen("{$temp_filename}/aliases", "w");
1747
	foreach($files_to_process as $f2p) {
1748
		$file_contents = file_get_contents($f2p);
1749
		fwrite($fd, $file_contents);
1750
		unlink($f2p);
1751
	}
1752
	fclose($fd);
1753
}
1754

    
1755
function version_compare_dates($a, $b) {
1756
	$a_time = strtotime($a);
1757
	$b_time = strtotime($b);
1758

    
1759
	if ((!$a_time) || (!$b_time)) {
1760
		return FALSE;
1761
	} else {
1762
		if ($a < $b)
1763
			return -1;
1764
		elseif ($a == $b)
1765
			return 0;
1766
		else
1767
			return 1;
1768
	}
1769
}
1770
function version_get_string_value($a) {
1771
	$strs = array(
1772
		0 => "ALPHA-ALPHA",
1773
		2 => "ALPHA",
1774
		3 => "BETA",
1775
		4 => "B",
1776
		5 => "RC",
1777
		6 => "RELEASE"
1778
	);
1779
	$major = 0;
1780
	$minor = 0;
1781
	foreach ($strs as $num => $str) {
1782
		if (substr($a, 0, strlen($str)) == $str) {
1783
			$major = $num;
1784
			$n = substr($a, strlen($str));
1785
			if (is_numeric($n))
1786
				$minor = $n;
1787
			break;
1788
		}
1789
	}
1790
	return "{$major}.{$minor}";
1791
}
1792
function version_compare_string($a, $b) {
1793
	return version_compare_numeric(version_get_string_value($a), version_get_string_value($b));
1794
}
1795
function version_compare_numeric($a, $b) {
1796
	$a_arr = explode('.', rtrim($a, '.0'));
1797
	$b_arr = explode('.', rtrim($b, '.0'));
1798

    
1799
	foreach ($a_arr as $n => $val) {
1800
		if (array_key_exists($n, $b_arr)) {
1801
			// So far so good, both have values at this minor version level. Compare.
1802
			if ($val > $b_arr[$n])
1803
				return 1;
1804
			elseif ($val < $b_arr[$n])
1805
				return -1;
1806
		} else {
1807
			// a is greater, since b doesn't have any minor version here.
1808
			return 1;
1809
		}
1810
	}
1811
	if (count($b_arr) > count($a_arr)) {
1812
		// b is longer than a, so it must be greater.
1813
		return -1;
1814
	} else {
1815
		// Both a and b are of equal length and value.
1816
		return 0;
1817
	}
1818
}
1819
function pfs_version_compare($cur_time, $cur_text, $remote) {
1820
	// First try date compare
1821
	$v = version_compare_dates($cur_time, $b);
1822
	if ($v === FALSE) {
1823
		// If that fails, try to compare by string
1824
		// Before anything else, simply test if the strings are equal
1825
		if ($cur_text == $remote)
1826
			return 0;
1827
		list($cur_num, $cur_str) = explode('-', $cur_text);
1828
		list($rem_num, $rem_str) = explode('-', $remote);
1829

    
1830
		// First try to compare the numeric parts of the version string.
1831
		$v = version_compare_numeric($cur_num, $rem_num);
1832

    
1833
		// If the numeric parts are the same, compare the string parts.
1834
		if ($v == 0)
1835
			return version_compare_string($cur_str, $rem_str);
1836
	}
1837
	return $v;
1838
}
1839
function process_alias_urltable($name, $url, $freq, $forceupdate=false) {
1840
	$urltable_prefix = "/var/db/aliastables/";
1841
	$urltable_filename = $urltable_prefix . $name . ".txt";
1842

    
1843
	// Make the aliases directory if it doesn't exist
1844
	if (!file_exists($urltable_prefix)) {
1845
		mkdir($urltable_prefix);
1846
	} elseif (!is_dir($urltable_prefix)) {
1847
		unlink($urltable_prefix);
1848
		mkdir($urltable_prefix);
1849
	}
1850

    
1851
	// If the file doesn't exist or is older than update_freq days, fetch a new copy.
1852
	if (!file_exists($urltable_filename)
1853
		|| ((time() - filemtime($urltable_filename)) > ($freq * 86400))
1854
		|| $forceupdate) {
1855

    
1856
		// Try to fetch the URL supplied
1857
		conf_mount_rw();
1858
		unlink_if_exists($urltable_filename . ".tmp");
1859
		// Use fetch to grab data since these may be large files, we don't want to process them through PHP if we can help it.
1860
		mwexec("/usr/bin/fetch -q -o " . escapeshellarg($urltable_filename . ".tmp") . " " . escapeshellarg($url));
1861
		// Remove comments. Might need some grep-fu to only allow lines that look like IPs/subnets
1862
		mwexec("/usr/bin/grep -v '^#' " . escapeshellarg($urltable_filename . ".tmp") . " > " . escapeshellarg($urltable_filename));
1863
		unlink_if_exists($urltable_filename . ".tmp");
1864
		conf_mount_ro();
1865
		if (filesize($urltable_filename)) {
1866
			return true;
1867
		} else {
1868
			// If it's unfetchable or an empty file, bail
1869
			return false;
1870
		}
1871
	} else {
1872
		// File exists, and it doesn't need updated.
1873
		return -1;
1874
	}
1875
}
1876
function get_real_slice_from_glabel($label) {
1877
	$label = escapeshellarg($label);
1878
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/{$label} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`);
1879
}
1880
function nanobsd_get_boot_slice() {
1881
	return trim(`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`);
1882
}
1883
function nanobsd_get_boot_drive() {
1884
	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`);
1885
}
1886
function nanobsd_get_active_slice() {
1887
	$boot_drive = nanobsd_get_boot_drive();
1888
	$active = trim(`gpart show $boot_drive | grep '\[active\]' | awk '{print $3;}'`);
1889

    
1890
	return "{$boot_drive}s{$active}";
1891
}
1892
function nanobsd_get_size() {
1893
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
1894
}
1895
function nanobsd_switch_boot_slice() {
1896
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
1897
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
1898
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
1899
	nanobsd_detect_slice_info();
1900

    
1901
	if ($BOOTFLASH == $ACTIVE_SLICE) {
1902
		$slice = $TOFLASH;
1903
	} else {
1904
		$slice = $BOOTFLASH;
1905
	}
1906

    
1907
	for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
1908
	ob_implicit_flush(1);
1909
	if(strstr($slice, "s2")) {
1910
		$ASLICE="2";
1911
		$AOLDSLICE="1";
1912
		$AGLABEL_SLICE="pfsense1";
1913
		$AUFS_ID="1";
1914
		$AOLD_UFS_ID="0";
1915
	} else {
1916
		$ASLICE="1";
1917
		$AOLDSLICE="2";
1918
		$AGLABEL_SLICE="pfsense0";
1919
		$AUFS_ID="0";
1920
		$AOLD_UFS_ID="1";
1921
	}
1922
	$ATOFLASH="{$BOOT_DRIVE}s{$ASLICE}";
1923
	$ACOMPLETE_PATH="{$BOOT_DRIVE}s{$ASLICE}a";
1924
	$ABOOTFLASH="{$BOOT_DRIVE}s{$AOLDSLICE}";
1925
	conf_mount_rw();
1926
	exec("sysctl kern.geom.debugflags=16");
1927
	exec("gpart set -a active -i {$ASLICE} {$BOOT_DRIVE}");
1928
	exec("/usr/sbin/boot0cfg -s {$ASLICE} -v /dev/{$BOOT_DRIVE}");
1929
	// We can't update these if they are mounted now.
1930
	if ($BOOTFLASH != $slice) {
1931
		exec("/sbin/tunefs -L ${AGLABEL_SLICE} /dev/$ACOMPLETE_PATH");
1932
		nanobsd_update_fstab($AGLABEL_SLICE, $ACOMPLETE_PATH, $AOLD_UFS_ID, $AUFS_ID);
1933
	}
1934
	exec("/sbin/sysctl kern.geom.debugflags=0");
1935
	conf_mount_ro();
1936
}
1937
function nanobsd_clone_slice() {
1938
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
1939
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
1940
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
1941
	nanobsd_detect_slice_info();
1942

    
1943
	for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
1944
	ob_implicit_flush(1);
1945
	exec("/sbin/sysctl kern.geom.debugflags=16");
1946
	exec("/bin/dd if=/dev/zero of=/dev/{$TOFLASH} bs=1m count=1");
1947
	exec("/bin/dd if=/dev/{$BOOTFLASH} of=/dev/{$TOFLASH} bs=64k");
1948
	exec("/sbin/tunefs -L {$GLABEL_SLICE} /dev/{$COMPLETE_PATH}");
1949
	$status = nanobsd_update_fstab($GLABEL_SLICE, $COMPLETE_PATH, $OLD_UFS_ID, $UFS_ID);
1950
	exec("/sbin/sysctl kern.geom.debugflags=0");
1951
	if($status) {
1952
		return false;
1953
	} else {
1954
		return true;
1955
	}
1956
}
1957
function nanobsd_update_fstab($gslice, $complete_path, $oldufs, $newufs) {
1958
	$tmppath = "/tmp/{$gslice}";
1959
	$fstabpath = "/tmp/{$gslice}/etc/fstab";
1960

    
1961
	exec("/bin/mkdir {$tmppath}");
1962
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
1963
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
1964
	exec("/bin/cp /etc/fstab {$fstabpath}");
1965

    
1966
	if (!file_exists($fstabpath)) {
1967
		$fstab = <<<EOF
1968
/dev/ufs/{$gslice} / ufs ro 1 1
1969
/dev/ufs/cf /cf ufs ro 1 1
1970
EOF;
1971
		if (file_put_contents($fstabpath, $fstab))
1972
			$status = true;
1973
		else
1974
			$status = false;
1975
	} else {
1976
		$status = exec("sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
1977
	}
1978
	exec("/sbin/umount {$tmppath}");
1979
	exec("/bin/rmdir {$tmppath}");
1980

    
1981
	return $status;
1982
}
1983
function nanobsd_detect_slice_info() {
1984
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
1985
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
1986
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
1987

    
1988
	$BOOT_DEVICE=nanobsd_get_boot_slice();
1989
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
1990
	$BOOT_DRIVE=nanobsd_get_boot_drive();
1991
	$ACTIVE_SLICE=nanobsd_get_active_slice();
1992

    
1993
	// Detect which slice is active and set information.
1994
	if(strstr($REAL_BOOT_DEVICE, "s1")) {
1995
		$SLICE="2";
1996
		$OLDSLICE="1";
1997
		$GLABEL_SLICE="pfsense1";
1998
		$UFS_ID="1";
1999
		$OLD_UFS_ID="0";
2000

    
2001
	} else {
2002
		$SLICE="1";
2003
		$OLDSLICE="2";
2004
		$GLABEL_SLICE="pfsense0";
2005
		$UFS_ID="0";
2006
		$OLD_UFS_ID="1";
2007
	}
2008
	$TOFLASH="{$BOOT_DRIVE}s{$SLICE}";
2009
	$COMPLETE_PATH="{$BOOT_DRIVE}s{$SLICE}a";
2010
	$COMPLETE_BOOT_PATH="{$BOOT_DRIVE}s{$OLDSLICE}";
2011
	$BOOTFLASH="{$BOOT_DRIVE}s{$OLDSLICE}";
2012
}
2013

    
2014
function get_include_contents($filename) {
2015
    if (is_file($filename)) {
2016
        ob_start();
2017
        include $filename;
2018
        $contents = ob_get_contents();
2019
        ob_end_clean();
2020
        return $contents;
2021
    }
2022
    return false;
2023
}
2024

    
2025
?>
(29-29/50)