Project

General

Profile

Download (56.7 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
	write_config("Restored {$section} of config file (maybe from CARP partner)");
646
	conf_mount_ro();
647
	return;
648
}
649

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

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

    
693
";
694

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

    
702
	fputs($fp, $headers);
703
	fputs($fp, $urlencoded);
704

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

    
710
	return $ret;
711
}
712

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

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

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

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

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

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

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

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

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

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

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

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

    
897
	/* parse config.xml again */
898
	$config = parse_config(true);
899

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

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

    
908
	/* set up interfaces */
909
	interfaces_configure();
910

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

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

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

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

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

    
956
	$g['booting'] = false;
957

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

    
965
	/* parse config.xml again */
966
	$config = parse_config(true);
967

    
968
	/* set up our timezone */
969
	system_timezone_configure();
970

    
971
	/* set up our hostname */
972
	system_hostname_configure();
973

    
974
	/* make hosts file */
975
	system_hosts_generate();
976

    
977
	/* generate resolv.conf */
978
	system_resolvconf_generate();
979

    
980
	/* enable routing */
981
	system_routing_enable();
982

    
983
	/* set up interfaces */
984
	interfaces_configure();
985

    
986
	/* start dyndns service */
987
	services_dyndns_configure();
988

    
989
	/* configure cron service */
990
	configure_cron();
991

    
992
	/* start the NTP client */
993
	system_ntp_configure();
994

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

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

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

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

    
1010
function auto_login() {
1011
	global $config;
1012

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

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

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

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

    
1110
	conf_mount_ro();
1111
	return;
1112
}
1113

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

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

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

    
1134
	$Iflist = get_configured_interface_list();
1135

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

    
1143
	return $dhcpdenable;
1144
}
1145

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

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

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

    
1184
//returns interface information
1185
function get_interface_info($ifdescr) {
1186
	global $config, $linkinfo, $netstatrninfo, $g;
1187

    
1188
	$ifinfo = array();
1189
	/* if list */
1190
	$iflist = get_configured_interface_with_descr(false,true);
1191

    
1192
	$found = false;
1193
    	foreach ($iflist as $if => $ifname) {
1194
    		if ($ifdescr == $if || $ifdescr == $ifname) {
1195
			$ifinfo['hwif'] = $config['interfaces'][$if]['if'];
1196
			$ifinfo['if'] = get_real_interface($if);
1197
			$found = true;
1198
			break;
1199
		}
1200
	}
1201
	if ($found == false)
1202
		return;
1203

    
1204
	/* run netstat to determine link info */
1205

    
1206
	unset($linkinfo);
1207
	$chkif = $ifinfo['if'];
1208

    
1209
	exec("/usr/bin/netstat -I {$chkif} -nWb -f link", $linkinfo);
1210
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
1211

    
1212
	$ifinfotmp = pfSense_get_interface_addresses($chkif);
1213
	$ifinfo['status'] = $ifinfotmp['status'];
1214
	$ifinfo['macaddr'] = $ifinfotmp['macaddr'];
1215
	$ifinfo['ipaddr'] = $ifinfotmp['ipaddr'];
1216
	$ifinfo['subnet'] = $ifinfotmp['subnet'];
1217
	if (isset($ifinfotmp['link0']))
1218
		$link0 = "down";
1219

    
1220
	
1221
	if (preg_match("/^enc|^tun|^ppp|^pptp|^ovpn/i", $chkif)) {
1222
		$ifinfo['inpkts'] = $linkinfo[3];
1223
		$ifinfo['outpkts'] = $linkinfo[6];
1224
	} else {
1225
		$ifinfo['inerrs'] = $linkinfo[5];
1226
		$ifinfo['outerrs'] = $linkinfo[9];
1227
		$ifinfo['collisions'] = $linkinfo[11];
1228
	}
1229

    
1230
	/* Use pfctl for non wrapping 64 bit counters */
1231
	/* Pass */
1232
	exec("/sbin/pfctl -vvsI -i {$chkif}", $pfctlstats);
1233
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1234
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1235
	$in4_pass = $pf_in4_pass[5];
1236
	$out4_pass = $pf_out4_pass[5];
1237
	$in4_pass_packets = $pf_in4_pass[3];
1238
	$out4_pass_packets = $pf_out4_pass[3];
1239
	$ifinfo['inbytespass'] = $in4_pass;
1240
	$ifinfo['outbytespass'] = $out4_pass;
1241
	$ifinfo['inpktspass'] = $in4_pass_packets;
1242
	$ifinfo['outpktspass'] = $out4_pass_packets;
1243

    
1244
	/* Block */
1245
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1246
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1247
	$in4_block = $pf_in4_block[5];
1248
	$out4_block = $pf_out4_block[5];
1249
	$in4_block_packets = $pf_in4_block[3];
1250
	$out4_block_packets = $pf_out4_block[3];
1251
	$ifinfo['inbytesblock'] = $in4_block;
1252
	$ifinfo['outbytesblock'] = $out4_block;
1253
	$ifinfo['inpktsblock'] = $in4_block_packets;
1254
	$ifinfo['outpktsblock'] = $out4_block_packets;
1255

    
1256
	$ifinfo['inbytes'] = $in4_pass + $in4_block;
1257
	$ifinfo['outbytes'] = $out4_pass + $out4_block;
1258
	$ifinfo['inpkts'] = $in4_pass_packets + $in4_block_packets;
1259
	$ifinfo['outpkts'] = $in4_pass_packets + $out4_block_packets;
1260
		
1261
	$ifconfiginfo = "";
1262
	
1263
	unset($linkinfo);
1264
	exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
1265
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
1266
	
1267
	switch ($config['interfaces'][$ifdescr]['ipaddr']) {
1268
	 /* DHCP? -> see if dhclient is up */
1269
	case "dhcp":
1270
	case "carpdev-dhcp":
1271
		/* see if dhclient is up */
1272
		if (find_dhclient_process($ifinfo['if']) <> "")
1273
			$ifinfo['dhcplink'] = "up";
1274
		else
1275
			$ifinfo['dhcplink'] = "down";
1276

    
1277
		break;
1278
	/* PPPoE interface? -> get status from virtual interface */
1279
	case "pppoe":
1280
		if ("{$ifinfo['if']}*" == $linkinfo[0])
1281
			$ifinfo['pppoelink'] = "down";
1282
		else if ($ifinfo['if'] == $linkinfo[0] && !isset($link0))
1283
			/* get PPPoE link status for dial on demand */
1284
			$ifinfo['pppoelink'] = "up";
1285
		else
1286
			$ifinfo['pppoelink'] = "down";
1287

    
1288
		break;
1289
	/* PPTP interface? -> get status from virtual interface */
1290
	case "pptp":
1291
		if ("{$ifinfo['if']}*" == $linkinfo[0])
1292
			$ifinfo['pptplink'] = "down";
1293
		else if ($ifinfo['if'] == $linkinfo[0] && !isset($link0))
1294
			/* get PPTP link status for dial on demand */
1295
			$ifinfo['pptplink'] = "up";
1296
		else
1297
			$ifinfo['pptplink'] = "down";
1298
		break;
1299
	/* PPP interface? -> get uptime for this session and cumulative uptime from the persistant log file in conf */
1300
	case "ppp":
1301
		if ("{$ifinfo['if']}*" == $linkinfo[0])
1302
			$ifinfo['ppplink'] = "down";
1303
		else if ($ifinfo['if'] == $linkinfo[0])
1304
			$ifinfo['ppplink'] = "up";
1305
		else
1306
			$ifinfo['ppplink'] = "down" ;
1307
		if (empty($ifinfo['status']))
1308
			$ifinfo['status'] = "down";
1309

    
1310
		$dev = $config['interfaces'][$if]['if'];
1311
		if (empty($dev))
1312
			break;
1313
		if (file_exists("/dev/{$dev}")) {
1314
			if (file_exists("{$g['varrun_path']}/ppp_{$if}.pid")) {
1315
				$ifinfo['pppinfo'] = "{$ifinfo['if']}";
1316
				$sec = trim(`/usr/local/sbin/ppp-uptime.sh {$ifinfo['if']}`);
1317
        		$ifinfo['ppp_uptime'] = convert_seconds_to_hms($sec);
1318
			}
1319
		} else {
1320
			$ifinfo['nodevice'] = 1;
1321
			$ifinfo['pppinfo'] = $dev . " device not present! Is the modem attached to the system?";	
1322
		}
1323
		// Calculate cumulative uptime for PPP link. Useful for connections that have per minute/hour contracts so you don't go over!
1324
		$ifinfo['ppp_uptime_accumulated'] = get_ppp_uptime($ifinfo['if']);
1325

    
1326
		break;
1327
	default:
1328
		break;
1329
	}
1330

    
1331
	if ($ifinfo['status'] == "up") {
1332
		/* try to determine media with ifconfig */
1333
		unset($ifconfiginfo);
1334
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1335
		$wifconfiginfo = array();
1336
		if(is_interface_wireless($ifdescr)) {
1337
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1338
			array_shift($wifconfiginfo);
1339
		}
1340
		$matches = "";
1341
		foreach ($ifconfiginfo as $ici) {
1342

    
1343
			/* don't list media/speed for wireless cards, as it always
1344
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1345
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1346
				$ifinfo['media'] = $matches[1];
1347
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1348
				$ifinfo['media'] = $matches[1];
1349
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1350
				$ifinfo['media'] = $matches[1];
1351
			}
1352

    
1353
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
1354
				if ($matches[1] != "active")
1355
					$ifinfo['status'] = $matches[1];
1356
				if($ifinfo['status'] == "running")
1357
					$ifinfo['status'] = "up";
1358
			}
1359
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
1360
				$ifinfo['channel'] = $matches[1];
1361
			}
1362
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
1363
				if ($matches[1][0] == '"')
1364
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
1365
				else
1366
					$ifinfo['ssid'] = $matches[1];
1367
			}
1368
		}
1369
		foreach($wifconfiginfo as $ici) {
1370
			$elements = preg_split("/[ ]+/i", $ici);
1371
			if ($elements[0] != "") {
1372
				$ifinfo['bssid'] = $elements[0];
1373
			}
1374
			if ($elements[3] != "") {
1375
				$ifinfo['rate'] = $elements[3];
1376
			}
1377
			if ($elements[4] != "") {
1378
				$ifinfo['rssi'] = $elements[4];
1379
			}
1380

    
1381
		}
1382
		/* lookup the gateway */
1383
		if (interface_has_gateway($if)) 
1384
			$ifinfo['gateway'] = get_interface_gateway($if);
1385
	}
1386

    
1387
	$bridge = "";
1388
	$bridge = link_interface_to_bridge($ifdescr);
1389
	if($bridge) {
1390
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1391
		if(stristr($bridge_text, "blocking") <> false) {
1392
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
1393
			$ifinfo['bridgeint'] = $bridge;
1394
		} else if(stristr($bridge_text, "learning") <> false) {
1395
			$ifinfo['bridge'] = "learning";
1396
			$ifinfo['bridgeint'] = $bridge;
1397
		} else if(stristr($bridge_text, "forwarding") <> false) {
1398
			$ifinfo['bridge'] = "forwarding";
1399
			$ifinfo['bridgeint'] = $bridge;
1400
		}
1401
	}
1402

    
1403
	return $ifinfo;
1404
}
1405

    
1406
//returns cpu speed of processor. Good for determining capabilities of machine
1407
function get_cpu_speed() {
1408
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
1409
}
1410

    
1411
function add_hostname_to_watch($hostname) {
1412
	if(!is_dir("/var/db/dnscache")) {
1413
		mkdir("/var/db/dnscache");
1414
	}
1415
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1416
		$domrecords = array();
1417
		$domips = array();
1418
		exec("host -t A $hostname", $domrecords, $rethost);
1419
		if($rethost == 0) {
1420
			foreach($domrecords as $domr) {
1421
				$doml = explode(" ", $domr);
1422
				$domip = $doml[3];
1423
				/* fill array with domain ip addresses */
1424
				if(is_ipaddr($domip)) {
1425
					$domips[] = $domip;
1426
				}
1427
			}
1428
		}
1429
		sort($domips);
1430
		$contents = "";
1431
		if(! empty($domips)) {
1432
			foreach($domips as $ip) {
1433
				$contents .= "$ip\n";
1434
			}
1435
		}
1436
		file_put_contents("/var/db/dnscache/$hostname", $contents);
1437
	}
1438
}
1439

    
1440
function is_fqdn($fqdn) {
1441
	$hostname = false;
1442
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1443
		$hostname = true;
1444
	}
1445
	if(preg_match("/\.\./", $fqdn)) {
1446
		$hostname = false;
1447
	}
1448
	if(preg_match("/^\./i", $fqdn)) { 
1449
		$hostname = false;
1450
	}
1451
	if(preg_match("/\//i", $fqdn)) {
1452
		$hostname = false;
1453
	}
1454
	return($hostname);
1455
}
1456

    
1457
function pfsense_default_state_size() {
1458
  /* get system memory amount */
1459
  $memory = get_memory();
1460
  $avail = $memory[0];
1461
  /* Be cautious and only allocate 10% of system memory to the state table */
1462
  $max_states = (int) ($avail/10)*1000;
1463
  return $max_states;
1464
}
1465

    
1466
/* Compare the current hostname DNS to the DNS cache we made
1467
 * if it has changed we return the old records
1468
 * if no change we return true */
1469
function compare_hostname_to_dnscache($hostname) {
1470
	if(!is_dir("/var/db/dnscache")) {
1471
		mkdir("/var/db/dnscache");
1472
	}
1473
	$hostname = trim($hostname);
1474
	if(is_readable("/var/db/dnscache/{$hostname}")) {
1475
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
1476
	} else {
1477
		$oldcontents = "";
1478
	}
1479
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1480
		$domrecords = array();
1481
		$domips = array();
1482
		exec("host -t A $hostname", $domrecords, $rethost);
1483
		if($rethost == 0) {
1484
			foreach($domrecords as $domr) {
1485
				$doml = explode(" ", $domr);
1486
				$domip = $doml[3];
1487
				/* fill array with domain ip addresses */
1488
				if(is_ipaddr($domip)) {
1489
					$domips[] = $domip;
1490
				}
1491
			}
1492
		}
1493
		sort($domips);
1494
		$contents = "";
1495
		if(! empty($domips)) {
1496
			foreach($domips as $ip) {
1497
				$contents .= "$ip\n";
1498
			}
1499
		}
1500
	}
1501

    
1502
	if(trim($oldcontents) != trim($contents)) {
1503
		if($g['debug']) {
1504
			log_error("DNSCACHE: Found old IP {$oldcontents} and new IP {$contents}");
1505
		}
1506
		return ($oldcontents);
1507
	} else {
1508
		return false;
1509
	}
1510
}
1511

    
1512
/*
1513
 * load_glxsb() - Load the glxsb crypto module if enabled in config.
1514
 */
1515
function load_glxsb() {
1516
	global $config, $g;
1517
	$is_loaded = `/sbin/kldstat | /usr/bin/grep -c glxsb`;
1518
	if (isset($config['system']['glxsb_enable']) && ($is_loaded == 0)) {
1519
		mwexec("/sbin/kldload glxsb");
1520
	}
1521
}
1522

    
1523
/****f* pfsense-utils/isvm
1524
 * NAME
1525
 *   isvm
1526
 * INPUTS
1527
 *	 none
1528
 * RESULT
1529
 *   returns true if machine is running under a virtual environment
1530
 ******/
1531
function isvm() {
1532
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86");
1533
	$bios_vendor = strtolower(`/bin/kenv | /usr/bin/awk -F= '/smbios.bios.vendor/ {print $2}'`);
1534
	if(in_array($bios_vendor, $virtualenvs)) 
1535
		return true;
1536
	else
1537
		return false;
1538
}
1539

    
1540
function get_freebsd_version() {
1541
	$version = trim(`/usr/bin/uname -r | /usr/bin/cut  -d'.' -f1`);
1542
	return $version;
1543
}
1544

    
1545
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body') {
1546
        global $ch, $fout, $file_size, $downloaded;
1547
        $file_size  = 1;
1548
        $downloaded = 1;
1549
        /* open destination file */
1550
        $fout = fopen($destination_file, "wb");
1551

    
1552
        /*
1553
         *      Originally by Author: Keyvan Minoukadeh
1554
         *      Modified by Scott Ullrich to return Content-Length size
1555
         */
1556

    
1557
        $ch = curl_init();
1558
        curl_setopt($ch, CURLOPT_URL, $url_file);
1559
        curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1560
        curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1561
        curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1562
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, '5');
1563
        curl_setopt($ch, CURLOPT_TIMEOUT, 0);
1564

    
1565
        curl_exec($ch);
1566
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1567
        if($fout)
1568
                fclose($fout);
1569
        curl_close($ch);
1570
        return ($http_code == 200) ? true : $http_code;
1571
}
1572

    
1573
function read_header($ch, $string) {
1574
        global $file_size, $fout;
1575
        $length = strlen($string);
1576
        $regs = "";
1577
        ereg("(Content-Length:) (.*)", $string, $regs);
1578
        if($regs[2] <> "") {
1579
                $file_size = intval($regs[2]);
1580
        }
1581
        ob_flush();
1582
        return $length;
1583
}
1584

    
1585
function read_body($ch, $string) {
1586
        global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen;
1587
        $length = strlen($string);
1588
        $downloaded += intval($length);
1589
        $downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1590
        $downloadProgress = 100 - $downloadProgress;
1591
        if($lastseen <> $downloadProgress and $downloadProgress < 101) {
1592
                if($sendto == "status") {
1593
                        $tostatus = $static_status . $downloadProgress . "%";
1594
                        update_status($tostatus);
1595
                } else {
1596
                        $tooutput = $static_output . $downloadProgress . "%";
1597
                        update_output_window($tooutput);
1598
                }
1599
                update_progress_bar($downloadProgress);
1600
                $lastseen = $downloadProgress;
1601
        }
1602
        if($fout)
1603
                fwrite($fout, $string);
1604
        ob_flush();
1605
        return $length;
1606
}
1607

    
1608
/*
1609
 *   update_output_window: update bottom textarea dynamically.
1610
 */
1611
function update_output_window($text) {
1612
        global $pkg_interface;
1613
        $log = ereg_replace("\n", "\\n", $text);
1614
        if($pkg_interface == "console") {
1615
                /* too chatty */
1616
        } else {
1617
                echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1618
        }
1619
        /* ensure that contents are written out */
1620
        ob_flush();
1621
}
1622

    
1623
/*
1624
 *   update_output_window: update top textarea dynamically.
1625
 */
1626
function update_status($status) {
1627
        global $pkg_interface;
1628
        if($pkg_interface == "console") {
1629
                echo $status . "\n";
1630
        } else {
1631
                echo "\n<script type=\"text/javascript\">this.document.forms[0].status.value=\"" . $status . "\";</script>";
1632
        }
1633
        /* ensure that contents are written out */
1634
        ob_flush();
1635
}
1636

    
1637
/*
1638
 * update_progress_bar($percent): updates the javascript driven progress bar.
1639
 */
1640
function update_progress_bar($percent) {
1641
        global $pkg_interface;
1642
        if($percent > 100) $percent = 1;
1643
        if($pkg_interface <> "console") {
1644
                echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1645
                echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1646
                echo "\n</script>";
1647
        } else {
1648
                echo " {$percent}%";
1649
        }
1650
}
1651

    
1652
/* 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. */
1653
if(!function_exists("split")) {
1654
	function split($seperator, $haystack, $limit = null) {
1655
		return preg_split($seperator, $haystack, $limit);
1656
	}
1657
}
1658

    
1659
function update_alias_names_upon_change($section, $subsection, $fielda, $fieldb, $new_alias_name, $origname) {
1660
	global $g, $config, $pconfig, $debug;
1661
	if(!$origname) 
1662
		return;
1663

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

    
1667
	if($fieldb) {
1668
		if($debug) fwrite($fd, "fieldb exists\n");
1669
		for ($i = 0; isset($config["$section"]["$subsection"][$i]["$fielda"]); $i++) {
1670
			if($debug) fwrite($fd, "$i\n");
1671
			if($config["$section"]["$subsection"][$i]["$fielda"]["$fieldb"] == $origname) {
1672
				if($debug) fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1673
				$config["$section"]["$subsection"][$i]["$fielda"]["$fieldb"] = $new_alias_name;
1674
			}
1675
		}	
1676
	} else {
1677
		if($debug) fwrite($fd, "fieldb does not exist\n");
1678
		for ($i = 0; isset($config["$section"]["$subsection"][$i]["$fielda"]); $i++) {
1679
			if($config["$section"]["$subsection"][$i]["$fielda"] == $origname) {
1680
				$config["$section"]["$subsection"][$i]["$fielda"] = $new_alias_name;
1681
				if($debug) fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1682
			}
1683
		}
1684
	}
1685

    
1686
	if($debug) fclose($fd);
1687

    
1688
}
1689

    
1690
function update_alias_url_data() {
1691
	global $config, $g;
1692
	/* item is a url type */
1693
	$lockkey = lock('config');
1694
	for($x=0; $x<count($config['aliases']['alias']); $x++) {
1695
		if($config['aliases']['alias'][$x]['aliasurl']) {
1696
			/* fetch down and add in */
1697
			$isfirst = 0;
1698
			$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
1699
			unlink($temp_filename);
1700
			$fda = fopen("{$g['tmp_path']}/tmpfetch","w");
1701
			fwrite($fda, "/usr/bin/fetch -q -o \"{$temp_filename}/aliases\" \"" . $config['aliases']['alias'][$x]['aliasurl'] . "\"");
1702
			fclose($fda);
1703
			mwexec("/bin/mkdir -p {$temp_filename}");
1704
			mwexec("/usr/bin/fetch -q -o \"{$temp_filename}/aliases\" \"" . $config['aliases']['alias'][$x]['aliasurl'] . "\"");
1705
			/* if the item is tar gzipped then extract */
1706
			if(stristr($config['aliases']['alias'][$x]['aliasurl'], ".tgz"))
1707
				process_alias_tgz($temp_filename);
1708
			if(stristr($config['aliases']['alias'][$x]['aliasurl'], ".zip"))
1709
				process_alias_unzip($temp_filename);
1710
			if(file_exists("{$temp_filename}/aliases")) {
1711
				$file_contents = file_get_contents("{$temp_filename}/aliases");
1712
				$file_contents = str_replace("#", "\n#", $file_contents);
1713
				$file_contents_split = split("\n", $file_contents);
1714
				foreach($file_contents_split as $fc) {
1715
					$tmp = trim($fc);
1716
					if(stristr($fc, "#")) {
1717
						$tmp_split = split("#", $tmp);
1718
						$tmp = trim($tmp_split[0]);
1719
					}
1720
					if(trim($tmp) <> "") {
1721
						if($isfirst == 1)
1722
							$address .= " ";
1723
						$address .= $tmp;
1724
						$isfirst = 1;
1725
					}
1726
				}
1727
				if($isfirst == 0) {
1728
					/* nothing was found */
1729
					$dont_update = true;
1730
					break;
1731
				}
1732
				if(!$dont_update) {
1733
					$config['aliases']['alias'][$x]['address'] = $address;
1734
					$updated = true;
1735
				}
1736
				mwexec("/bin/rm -rf {$temp_filename}");
1737
			}
1738
		}
1739
	}
1740
	if($updated)
1741
		write_config();
1742
	unlock($lockkey);
1743
}
1744

    
1745
function process_alias_unzip($temp_filename) {
1746
	if(!file_exists("/usr/local/bin/unzip"))
1747
		return;
1748
	mwexec("/bin/mv {$temp_filename}/aliases {$temp_filename}/aliases.zip");
1749
	mwexec("/usr/local/bin/unzip {$temp_filename}/aliases.tgz -d {$temp_filename}/aliases/");
1750
	unlink("{$temp_filename}/aliases.zip");
1751
	$files_to_process = return_dir_as_array("{$temp_filename}/");
1752
	/* foreach through all extracted files and build up aliases file */
1753
	$fd = fopen("{$temp_filename}/aliases", "w");
1754
	foreach($files_to_process as $f2p) {
1755
		$file_contents = file_get_contents($f2p);
1756
		fwrite($fd, $file_contents);
1757
		unlink($f2p);
1758
	}
1759
	fclose($fd);
1760
}
1761

    
1762
function process_alias_tgz($temp_filename) {
1763
	if(!file_exists("/usr/bin/tar"))
1764
		return;
1765
	mwexec("/bin/mv {$temp_filename}/aliases {$temp_filename}/aliases.tgz");
1766
	mwexec("/usr/bin/tar xzf {$temp_filename}/aliases.tgz -C {$temp_filename}/aliases/");
1767
	unlink("{$temp_filename}/aliases.tgz");
1768
	$files_to_process = return_dir_as_array("{$temp_filename}/");
1769
	/* foreach through all extracted files and build up aliases file */
1770
	$fd = fopen("{$temp_filename}/aliases", "w");
1771
	foreach($files_to_process as $f2p) {
1772
		$file_contents = file_get_contents($f2p);
1773
		fwrite($fd, $file_contents);
1774
		unlink($f2p);
1775
	}
1776
	fclose($fd);
1777
}
1778

    
1779
function version_compare_dates($a, $b) {
1780
	$a_time = strtotime($a);
1781
	$b_time = strtotime($b);
1782

    
1783
	if ((!$a_time) || (!$b_time)) {
1784
		return FALSE;
1785
	} else {
1786
		if ($a < $b)
1787
			return -1;
1788
		elseif ($a == $b)
1789
			return 0;
1790
		else
1791
			return 1;
1792
	}
1793
}
1794
function version_get_string_value($a) {
1795
	$strs = array(
1796
		0 => "ALPHA-ALPHA",
1797
		2 => "ALPHA",
1798
		3 => "BETA",
1799
		4 => "B",
1800
		5 => "RC",
1801
		6 => "RELEASE"
1802
	);
1803
	$major = 0;
1804
	$minor = 0;
1805
	foreach ($strs as $num => $str) {
1806
		if (substr($a, 0, strlen($str)) == $str) {
1807
			$major = $num;
1808
			$n = substr($a, strlen($str));
1809
			if (is_numeric($n))
1810
				$minor = $n;
1811
			break;
1812
		}
1813
	}
1814
	return "{$major}.{$minor}";
1815
}
1816
function version_compare_string($a, $b) {
1817
	return version_compare_numeric(version_get_string_value($a), version_get_string_value($b));
1818
}
1819
function version_compare_numeric($a, $b) {
1820
	$a_arr = explode('.', rtrim($a, '.0'));
1821
	$b_arr = explode('.', rtrim($b, '.0'));
1822

    
1823
	foreach ($a_arr as $n => $val) {
1824
		if (array_key_exists($n, $b_arr)) {
1825
			// So far so good, both have values at this minor version level. Compare.
1826
			if ($val > $b_arr[$n])
1827
				return 1;
1828
			elseif ($val < $b_arr[$n])
1829
				return -1;
1830
		} else {
1831
			// a is greater, since b doesn't have any minor version here.
1832
			return 1;
1833
		}
1834
	}
1835
	if (count($b_arr) > count($a_arr)) {
1836
		// b is longer than a, so it must be greater.
1837
		return -1;
1838
	} else {
1839
		// Both a and b are of equal length and value.
1840
		return 0;
1841
	}
1842
}
1843
function pfs_version_compare($cur_time, $cur_text, $remote) {
1844
	// First try date compare
1845
	$v = version_compare_dates($cur_time, $b);
1846
	if ($v === FALSE) {
1847
		// If that fails, try to compare by string
1848
		// Before anything else, simply test if the strings are equal
1849
		if ($cur_text == $remote)
1850
			return 0;
1851
		list($cur_num, $cur_str) = explode('-', $cur_text);
1852
		list($rem_num, $rem_str) = explode('-', $remote);
1853

    
1854
		// First try to compare the numeric parts of the version string.
1855
		$v = version_compare_numeric($cur_num, $rem_num);
1856

    
1857
		// If the numeric parts are the same, compare the string parts.
1858
		if ($v == 0)
1859
			return version_compare_string($cur_str, $rem_str);
1860
	}
1861
	return $v;
1862
}
1863
function process_alias_urltable($name, $url, $freq, $forceupdate=false) {
1864
	$urltable_prefix = "/var/db/aliastables/";
1865
	$urltable_filename = $urltable_prefix . $name . ".txt";
1866

    
1867
	// Make the aliases directory if it doesn't exist
1868
	if (!file_exists($urltable_prefix)) {
1869
		mkdir($urltable_prefix);
1870
	} elseif (!is_dir($urltable_prefix)) {
1871
		unlink($urltable_prefix);
1872
		mkdir($urltable_prefix);
1873
	}
1874

    
1875
	// If the file doesn't exist or is older than update_freq days, fetch a new copy.
1876
	if (!file_exists($urltable_filename)
1877
		|| ((time() - filemtime($urltable_filename)) > ($freq * 86400))
1878
		|| $forceupdate) {
1879

    
1880
		// Try to fetch the URL supplied
1881
		conf_mount_rw();
1882
		unlink_if_exists($urltable_filename . ".tmp");
1883
		// 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.
1884
		mwexec("/usr/bin/fetch -q -o " . escapeshellarg($urltable_filename . ".tmp") . " " . escapeshellarg($url));
1885
		// Remove comments. Might need some grep-fu to only allow lines that look like IPs/subnets
1886
		mwexec("/usr/bin/grep -v '^#' " . escapeshellarg($urltable_filename . ".tmp") . " > " . escapeshellarg($urltable_filename));
1887
		unlink_if_exists($urltable_filename . ".tmp");
1888
		conf_mount_ro();
1889
		if (filesize($urltable_filename)) {
1890
			return true;
1891
		} else {
1892
			// If it's unfetchable or an empty file, bail
1893
			return false;
1894
		}
1895
	} else {
1896
		// File exists, and it doesn't need updated.
1897
		return -1;
1898
	}
1899
}
1900
function get_real_slice_from_glabel($label) {
1901
	$label = escapeshellarg($label);
1902
	return trim(`/sbin/glabel list | /usr/bin/grep -B2 ufs/{$label} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`);
1903
}
1904
function nanobsd_get_boot_slice() {
1905
	return trim(`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`);
1906
}
1907
function nanobsd_get_boot_drive() {
1908
	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`);
1909
}
1910
function nanobsd_get_active_slice() {
1911
	$boot_drive = nanobsd_get_boot_drive();
1912
	$active = trim(`gpart show $boot_drive | grep '\[active\]' | awk '{print $3;}'`);
1913

    
1914
	return "{$boot_drive}s{$active}";
1915
}
1916
function nanobsd_get_size() {
1917
	return strtoupper(file_get_contents("/etc/nanosize.txt"));
1918
}
1919
function nanobsd_switch_boot_slice() {
1920
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
1921
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
1922
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
1923
	nanobsd_detect_slice_info();
1924

    
1925
	if ($BOOTFLASH == $ACTIVE_SLICE) {
1926
		$slice = $TOFLASH;
1927
	} else {
1928
		$slice = $BOOTFLASH;
1929
	}
1930

    
1931
	for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
1932
	ob_implicit_flush(1);
1933
	if(strstr($slice, "s2")) {
1934
		$ASLICE="2";
1935
		$AOLDSLICE="1";
1936
		$AGLABEL_SLICE="pfsense1";
1937
		$AUFS_ID="1";
1938
		$AOLD_UFS_ID="0";
1939
	} else {
1940
		$ASLICE="1";
1941
		$AOLDSLICE="2";
1942
		$AGLABEL_SLICE="pfsense0";
1943
		$AUFS_ID="0";
1944
		$AOLD_UFS_ID="1";
1945
	}
1946
	$ATOFLASH="{$BOOT_DRIVE}s{$ASLICE}";
1947
	$ACOMPLETE_PATH="{$BOOT_DRIVE}s{$ASLICE}a";
1948
	$ABOOTFLASH="{$BOOT_DRIVE}s{$AOLDSLICE}";
1949
	conf_mount_rw();
1950
	exec("sysctl kern.geom.debugflags=16");
1951
	exec("gpart set -a active -i {$ASLICE} {$BOOT_DRIVE}");
1952
	exec("/usr/sbin/boot0cfg -s {$ASLICE} -v /dev/{$BOOT_DRIVE}");
1953
	// We can't update these if they are mounted now.
1954
	if ($BOOTFLASH != $slice) {
1955
		exec("/sbin/tunefs -L ${AGLABEL_SLICE} /dev/$ACOMPLETE_PATH");
1956
		nanobsd_update_fstab($AGLABEL_SLICE, $ACOMPLETE_PATH, $AOLD_UFS_ID, $AUFS_ID);
1957
	}
1958
	exec("/sbin/sysctl kern.geom.debugflags=0");
1959
	conf_mount_ro();
1960
}
1961
function nanobsd_clone_slice() {
1962
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
1963
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
1964
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
1965
	nanobsd_detect_slice_info();
1966

    
1967
	for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
1968
	ob_implicit_flush(1);
1969
	exec("/sbin/sysctl kern.geom.debugflags=16");
1970
	exec("/bin/dd if=/dev/zero of=/dev/{$TOFLASH} bs=1m count=1");
1971
	exec("/bin/dd if=/dev/{$BOOTFLASH} of=/dev/{$TOFLASH} bs=64k");
1972
	exec("/sbin/tunefs -L {$GLABEL_SLICE} /dev/{$COMPLETE_PATH}");
1973
	$status = nanobsd_update_fstab($GLABEL_SLICE, $COMPLETE_PATH, $OLD_UFS_ID, $UFS_ID);
1974
	exec("/sbin/sysctl kern.geom.debugflags=0");
1975
	if($status) {
1976
		return false;
1977
	} else {
1978
		return true;
1979
	}
1980
}
1981
function nanobsd_update_fstab($gslice, $complete_path, $oldufs, $newufs) {
1982
	$tmppath = "/tmp/{$gslice}";
1983
	$fstabpath = "/tmp/{$gslice}/etc/fstab";
1984

    
1985
	exec("/bin/mkdir {$tmppath}");
1986
	exec("/sbin/fsck_ufs -y /dev/{$complete_path}");
1987
	exec("/sbin/mount /dev/ufs/{$gslice} {$tmppath}");
1988
	exec("/bin/cp /etc/fstab {$fstabpath}");
1989

    
1990
	if (!file_exists($fstabpath)) {
1991
		$fstab = <<<EOF
1992
/dev/ufs/{$gslice} / ufs ro 1 1
1993
/dev/ufs/cf /cf ufs ro 1 1
1994
EOF;
1995
		if (file_put_contents($fstabpath, $fstab))
1996
			$status = true;
1997
		else
1998
			$status = false;
1999
	} else {
2000
		$status = exec("sed -i \"\" \"s/pfsense{$oldufs}/pfsense{$newufs}/g\" {$fstabpath}");
2001
	}
2002
	exec("/sbin/umount {$tmppath}");
2003
	exec("/bin/rmdir {$tmppath}");
2004

    
2005
	return $status;
2006
}
2007
function nanobsd_detect_slice_info() {
2008
	global $SLICE, $OLDSLICE, $TOFLASH, $COMPLETE_PATH, $COMPLETE_BOOT_PATH;
2009
	global $GLABEL_SLICE, $UFS_ID, $OLD_UFS_ID, $BOOTFLASH;
2010
	global $BOOT_DEVICE, $REAL_BOOT_DEVICE, $BOOT_DRIVE, $ACTIVE_SLICE;
2011

    
2012
	$BOOT_DEVICE=nanobsd_get_boot_slice();
2013
	$REAL_BOOT_DEVICE=get_real_slice_from_glabel($BOOT_DEVICE);
2014
	$BOOT_DRIVE=nanobsd_get_boot_drive();
2015
	$ACTIVE_SLICE=nanobsd_get_active_slice();
2016

    
2017
	// Detect which slice is active and set information.
2018
	if(strstr($REAL_BOOT_DEVICE, "s1")) {
2019
		$SLICE="2";
2020
		$OLDSLICE="1";
2021
		$GLABEL_SLICE="pfsense1";
2022
		$UFS_ID="1";
2023
		$OLD_UFS_ID="0";
2024

    
2025
	} else {
2026
		$SLICE="1";
2027
		$OLDSLICE="2";
2028
		$GLABEL_SLICE="pfsense0";
2029
		$UFS_ID="0";
2030
		$OLD_UFS_ID="1";
2031
	}
2032
	$TOFLASH="{$BOOT_DRIVE}s{$SLICE}";
2033
	$COMPLETE_PATH="{$BOOT_DRIVE}s{$SLICE}a";
2034
	$COMPLETE_BOOT_PATH="{$BOOT_DRIVE}s{$OLDSLICE}";
2035
	$BOOTFLASH="{$BOOT_DRIVE}s{$OLDSLICE}";
2036
}
2037
?>
(29-29/50)