Project

General

Profile

Download (72.8 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-2006 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
function get_tmp_file() {
37
	return "/tmp/tmp-" . time();
38
}
39

    
40
/****f* pfsense-utils/find_number_of_needed_carp_interfaces
41
 * NAME
42
 *   find_number_of_needed_carp_interfaces
43
 * INPUTS
44
 *   null
45
 * RESULT
46
 *   the number of needed carp interfacs
47
 ******/
48
function find_number_of_needed_carp_interfaces() {
49
	global $config, $g;
50
	$carp_counter=0;
51
	if(!$config['virtualip'])
52
		return 0;
53
	if(!$config['virtualip']['vip'])
54
		return 0;
55
	foreach($config['virtualip']['vip'] as $vip) {
56
		if($vip['mode'] == "carp")
57
			$carp_counter++;
58
	}
59
	return $carp_counter;
60
}
61

    
62
/****f* pfsense-utils/reset_carp
63
 * NAME
64
 *   reset_carp - resets carp after primary interface changes
65
 * INPUTS
66
 *   null
67
 * RESULT
68
 *   null
69
 ******/
70
function reset_carp() {
71
	$carp_counter=find_number_of_created_carp_interfaces();
72
	$needed_carp_interfaces = find_number_of_needed_carp_interfaces();
73
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
74
	for($x=0; $x<$carp_counter; $x++) {
75
		mwexec("/sbin/ifconfig carp{$x} down");
76
		mwexec("/sbin/ifconfig carp{$x} delete");
77
		log_error("CARP: $needed_carp_interfaces < $carp_counter");
78
		if($needed_carp_interfaces < $carp_counter) {
79
			$needed_carp_interfaces--;
80
			log_error("Destroying carp interface.");
81
			mwexec("/sbin/ifconfig carp{$x} destroy");
82
		}
83
	}
84
	find_number_of_created_carp_interfaces(true);
85
	sleep(1);
86
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
87
	interfaces_carp_configure();
88
	usleep(1000);
89
	interfaces_carp_bring_up_final();
90
}
91

    
92
/****f* pfsense-utils/get_dns_servers
93
 * NAME
94
 *   get_dns_servres - get system dns servers
95
 * INPUTS
96
 *   $dns_servers - an array of the dns servers
97
 * RESULT
98
 *   null
99
 ******/
100
function get_dns_servers() {
101
	$dns_servers = array();
102
	$dns = `cat /etc/resolv.conf`;
103
	$dns_s = split("\n", $dns);
104
	foreach($dns_s as $dns) {
105
		$matches = "";
106
		if (preg_match("/nameserver (.*)/", $dns, $matches))
107
			$dns_servers[] = $matches[1];
108
	}
109
	$dns_server_master = array();
110
	sort($dns_servers);
111
	$lastseen = "";
112
	foreach($dns_servers as $t) {
113
		if($t <> $lastseen)
114
			if($t <> "")
115
				$dns_server_master[] = $t;
116
		$lastseen = $t;
117
	}
118
	return $dns_server_master;
119
}
120

    
121
/****f* pfsense-utils/log_error
122
* NAME
123
*   log_error  - Sends a string to syslog.
124
* INPUTS
125
*   $error     - string containing the syslog message.
126
* RESULT
127
*   null
128
******/
129
function log_error($error) {
130
	$page = $_SERVER['SCRIPT_NAME'];
131
	syslog(LOG_WARNING, "$page: $error");
132
	return;
133
}
134

    
135
/****f* pfsense-utils/get_interface_mac_address
136
 * NAME
137
 *   get_interface_mac_address - Return a interfaces mac address
138
 * INPUTS
139
 *   $interface	- interface to obtain mac address from
140
 * RESULT
141
 *   $mac - the mac address of the interface
142
 ******/
143
function get_interface_mac_address($interface) {
144
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
145
	return trim($mac);
146
}
147

    
148
/****f* pfsense-utils/return_dir_as_array
149
 * NAME
150
 *   return_dir_as_array - Return a directory's contents as an array.
151
 * INPUTS
152
 *   $dir	- string containing the path to the desired directory.
153
 * RESULT
154
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
155
 ******/
156
function return_dir_as_array($dir) {
157
	$dir_array = array();
158
	if (is_dir($dir)) {
159
		if ($dh = opendir($dir)) {
160
			while (($file = readdir($dh)) !== false) {
161
				$canadd = 0;
162
				if($file == ".") $canadd = 1;
163
				if($file == "..") $canadd = 1;
164
				if($canadd == 0)
165
					array_push($dir_array, $file);
166
			}
167
			closedir($dh);
168
		}
169
	}
170
	return $dir_array;
171
}
172

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

    
186
	if(stristr($interface,"lnc"))
187
		return;
188
	if(isset($config['system']['do_not_use_nic_microcode']))
189
		return;
190

    
191
	if($g['booting']) {
192
	/* translate wan, lan, opt -> real interface if needed */
193
	$int = filter_translate_type_to_real_interface($interface);
194
	if($int <> "") $interface = $int;
195
	$int_family = preg_split("/[0-9]+/", $int);
196
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
197
	$supported_ints = array('fxp');
198
	if (in_array($int_family, $supported_ints))
199
		mwexec("/sbin/ifconfig {$interface} link0");
200

    
201
	if(stristr($options, "txcsum") == true)
202
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
203
	if(stristr($options, "rxcsum") == true)
204
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
205
	if(stristr($options, "polling") == true)
206
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
207
	} else {
208
		mwexec("sysctl kern.polling.enable=0");
209
	}
210
	return;
211
}
212

    
213
/****f* pfsense-utils/is_alias_inuse
214
 * NAME
215
 *   checks to see if an alias is currently in use by a rule
216
 * INPUTS
217
 *
218
 * RESULT
219
 *   true or false
220
 * NOTES
221
 *
222
 ******/
223
function is_alias_inuse($alias) {
224
	global $g, $config;
225

    
226
	if($alias == "") return false;
227
	/* loop through firewall rules looking for alias in use */
228
	if(is_array($config['nat']['rule']))
229
		foreach($config['filter']['rule'] as $rule) {
230
			if(is_array($rule['source']['address']))
231
				if($rule['source']['address'] == $alias)
232
					return true;
233
			if(is_array($rule['destination']['address']))
234
				if($rule['destination']['address'] == $alias)
235
					return true;
236
		}
237
	/* loop through nat rules looking for alias in use */
238
	if(is_array($config['nat']['rule']))
239
		foreach($config['nat']['rule'] as $rule) {
240
			if($rule['target'] == $alias)
241
				return true;
242
			if($rule['external-address'] == $alias)
243
				return true;
244
		}
245
	return false;
246
}
247

    
248
/****f* pfsense-utils/setup_polling_defaults
249
 * NAME
250
 *   sets up sysctls for pollingS
251
 * INPUTS
252
 *
253
 * RESULT
254
 *   null
255
 * NOTES
256
 *
257
 ******/
258
function setup_polling_defaults() {
259
	global $g, $config;
260
	if($config['system']['polling_each_burst'])
261
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
262
	if($config['system']['polling_burst_max'])
263
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
264
	if($config['system']['polling_user_frac'])
265
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
266
}
267

    
268
/****f* pfsense-utils/setup_polling
269
 * NAME
270
 *   sets up polling
271
 * INPUTS
272
 *
273
 * RESULT
274
 *   null
275
 * NOTES
276
 *
277
 ******/
278
function setup_polling() {
279
	global $g, $config;
280

    
281
	setup_polling_defaults();
282

    
283
	if(isset($config['system']['polling']))
284
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
285
	else
286
		$supported_ints = array();
287

    
288
	/* build an array of interfaces to work with */
289
	$iflist = array("lan" => "LAN", "wan" => "WAN");
290
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
291
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
292

    
293
	foreach ($iflist as $ifent => $ifname) {
294
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
295
		$supported = false;
296
		foreach($supported_ints as $supported) {
297
			if(stristr($real_interface, $supported)) {
298
				$supported = true;
299
			}
300
		}
301
		if ($supported == true) {
302
			mwexec("/sbin/ifconfig {$real_interface} polling");
303
		} else {
304
			mwexec("/sbin/ifconfig {$real_interface} -polling");
305
		}
306
	}
307
}
308

    
309
/****f* pfsense-utils/setup_microcode
310
 * NAME
311
 *   enumerates all interfaces and calls enable_hardware_offloading which
312
 *   enables a NIC's supported hardware features.
313
 * INPUTS
314
 *
315
 * RESULT
316
 *   null
317
 * NOTES
318
 *   This function only supports the fxp driver's loadable microcode.
319
 ******/
320
function setup_microcode() {
321
	global $config;
322

    
323
	$ifdescrs = array('wan', 'lan');
324
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
325
		$ifdescrs['opt' . $j] = "opt" . $j;
326
	}
327
	foreach($ifdescrs as $if)
328
		enable_hardware_offloading($if);
329
}
330

    
331
/****f* pfsense-utils/return_filename_as_array
332
 * NAME
333
 *   return_filename_as_array - Return a file's contents as an array.
334
 * INPUTS
335
 *   $filename	- string containing the path to the desired file.
336
 *   $strip	- array of characters to strip - default is '#'.
337
 * RESULT
338
 *   $file	- array containing the file's contents.
339
 * NOTES
340
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
341
 ******/
342
function return_filename_as_array($filename, $strip = array('#')) {
343
	if(file_exists($filename)) $file = file($filename);
344
	if(is_array($file)) {
345
		foreach($file as $line) $line = trim($line);
346
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
347
	}
348
	return $file;
349
}
350

    
351
/****f* pfsense-utils/file_put_contents
352
 * NAME
353
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
354
 * RESULT
355
 *   none
356
 ******/
357
if(!function_exists("file_put_contents")) {
358
	function file_put_contents($filename, $data) {
359
		$fd = fopen($filename,"w");
360
		fwrite($fd, $data);
361
		fclose($fd);
362
	}
363
}
364

    
365
/****f* pfsense-utils/get_carp_status
366
 * NAME
367
 *   get_carp_status - Return whether CARP is enabled or disabled.
368
 * RESULT
369
 *   boolean	- true if CARP is enabled, false if otherwise.
370
 ******/
371
function get_carp_status() {
372
    /* grab the current status of carp */
373
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
374
    if(intval($status) == "0") return false;
375
    return true;
376
}
377

    
378
/****f* pfsense-utils/is_carp_defined
379
 * NAME
380
 *   is_carp_defined - Return whether CARP is detected in the kernel.
381
 * RESULT
382
 *   boolean	- true if CARP is detected, false otherwise.
383
 ******/
384
function is_carp_defined() {
385
	/* is carp compiled into the kernel and userland? */
386
	$command = "/sbin/sysctl -a | grep carp";
387
	$fd = popen($command . " 2>&1 ", "r");
388
	if(!$fd) {
389
		log_error("Warning, could not execute command {$command}");
390
		return 0;
391
	}
392
	while(!feof($fd)) {
393
		$tmp .= fread($fd,49);
394
	}
395
	fclose($fd);
396

    
397
	if($tmp == "")
398
		return false;
399
	else
400
		return true;
401
}
402

    
403
/****f* pfsense-utils/get_interface_mtu
404
 * NAME
405
 *   get_interface_mtu - Return the mtu of an interface
406
 * RESULT
407
 *   $tmp	- Returns the mtu of an interface
408
 ******/
409
function get_interface_mtu($interface) {
410
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f4`;
411
	return $mtu;
412
}
413

    
414
/****f* pfsense-utils/is_interface_wireless
415
 * NAME
416
 *   is_interface_wireless - Returns if an interface is wireless
417
 * RESULT
418
 *   $tmp	- Returns if an interface is wireless
419
 ******/
420
function is_interface_wireless($interface) {
421
	global $config, $g;
422
	$interface = convert_real_interface_to_friendly_interface_name($interface);
423
	if(isset($config['interfaces'][$interface]['wireless']))
424
		return true;
425
	else
426
		return false;
427
}
428

    
429
/****f* pfsense-utils/find_number_of_created_carp_interfaces
430
 * NAME
431
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
432
 * RESULT
433
 *   $tmp	- Number of currently created CARP interfaces.
434
 ******/
435
function find_number_of_created_carp_interfaces($flush = false) {
436
	global $carp_interface_count_cache;
437

    
438
	if (!isset($carp_interface_count_cache) or $flush) {
439
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
440
		$fd = popen($command . " 2>&1 ", "r");
441
		if(!$fd) {
442
			log_error("Warning, could not execute command {$command}");
443
			return 0;
444
		}
445
		while(!feof($fd)) {
446
			$tmp .= fread($fd,49);
447
		}
448
		fclose($fd);
449
		$carp_interface_count_cache = intval($tmp);
450
	}
451
	return $carp_interface_count_cache;
452
}
453

    
454
/****f* pfsense-utils/link_int_to_bridge_interface
455
 * NAME
456
 *   link_int_to_bridge_interface - Finds out a bridge group for an interface
457
 * INPUTS
458
 *   $ip
459
 * RESULT
460
 *   bridge[0-99]
461
 ******/
462
function link_int_to_bridge_interface($int) {
463
	global $config, $g;
464
	$real_int = convert_friendly_interface_to_real_interface_name($int);
465
	$num_bridges = find_number_of_created_bridges();
466
	for($x=0; $x<$num_bridges; $x++) {
467
		$matches = "";
468
		$bridge_info = `/sbin/ifconfig bridge{$x}`;
469
		if(stristr($bridge_info, "member: {$real_int}")) {
470
			return "bridge{$x}";
471
		}
472
	}
473
}
474

    
475
/****f* pfsense-utils/link_ip_to_carp_interface
476
 * NAME
477
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
478
 * INPUTS
479
 *   $ip
480
 * RESULT
481
 *   $carp_ints
482
 ******/
483
function link_ip_to_carp_interface($ip) {
484
	global $config;
485
	if($ip == "") return;
486

    
487
	$ifdescrs = array('wan', 'lan');
488
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
489
		$ifdescrs['opt' . $j] = "opt" . $j;
490

    
491
	$ft = split("\.", $ip);
492
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
493

    
494
	$carp_ints = "";
495
	$num_carp_ints = find_number_of_created_carp_interfaces();
496
	foreach ($ifdescrs as $ifdescr => $ifname) {
497
		for($x=0; $x<$num_carp_ints; $x++) {
498
			$carp_int = "carp{$x}";
499
			$carp_ip = find_interface_ip($carp_int);
500
			$carp_subnet = find_virtual_ip_netmask($carp_ip);
501
			$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
502
			if(ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
503
				if(!stristr($carp_ints, $carp_int))
504
					$carp_ints .= " " . $carp_int;
505
		}
506
	}
507
	return $carp_ints;
508
}
509

    
510
/****f* pfsense-utils/find_virtual_ip_netmask
511
 * NAME
512
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
513
 * INPUTS
514
 *   $ip - ip address to locate subnet mask of
515
 * RESULT
516
 *   String containing the command's result.
517
 * NOTES
518
 *   This function returns the command's stdout and stderr.
519
 ******/
520
function find_virtual_ip_netmask($ip) {
521
        global $config;
522
        foreach($config['virtualip']['vip'] as $vip) {
523
                if($ip == $vip['subnet'])
524
                        return $vip['subnet_bits'];
525
        }
526
}
527

    
528
/****f* pfsense-utils/exec_command
529
 * NAME
530
 *   exec_command - Execute a command and return a string of the result.
531
 * INPUTS
532
 *   $command	- String of the command to be executed.
533
 * RESULT
534
 *   String containing the command's result.
535
 * NOTES
536
 *   This function returns the command's stdout and stderr.
537
 ******/
538
function exec_command($command) {
539
	$output = array();
540
	exec($command . ' 2>&1 ', $output);
541
	return(implode("\n", $output));
542
}
543

    
544
/****f* interfaces/is_jumbo_capable
545
 * NAME
546
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
547
 * INPUTS
548
 *   $int             - string containing interface name
549
 * RESULT
550
 *   boolean          - true or false
551
 ******/
552
function is_jumbo_capable($int) {
553
	/* Per:
554
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
555
	 * Only the following drivers support large frames
556
         *
557
	 * 'de' chipset purposely left out of this list
558
	 * requires defining BIG_PACKET in the
559
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
560
	 * kernel or module.  The hack works only for the 21041,
561
	 * 21140, and 21140A chips.
562
	 */
563
	global $g;
564

    
565
	$capable = $g['vlan_long_frame'];
566

    
567
	$int_family = preg_split("/[0-9]+/", $int);
568

    
569
	if (in_array($int_family[0], $capable))
570
		return true;
571
	else
572
		return false;
573
}
574

    
575
/*
576
 * Return the interface array
577
 */
578
function get_interface_arr($flush = false) {
579
	global $interface_arr_cache;
580

    
581
	/* If the cache doesn't exist, build it */
582
	if (!isset($interface_arr_cache) or $flush)
583
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
584

    
585
	return $interface_arr_cache;
586
}
587

    
588
/*
589
 * does_interface_exist($interface): return true or false if a interface is
590
 * detected.
591
 */
592
function does_interface_exist($interface) {
593
        $ints = get_interface_arr();
594

    
595
	if(stristr($ints, $interface) !== false)
596
		return true;
597
	else
598
		return false;
599
}
600

    
601
/*
602
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
603
 */
604
function convert_ip_to_network_format($ip, $subnet) {
605
	$ipsplit = split('[.]', $ip);
606
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
607
	return $string;
608
}
609

    
610
/*
611
 * find_interface_ip($interface): return the interface ip (first found)
612
 */
613
function find_interface_ip($interface, $flush = false) {
614
	global $interface_ip_arr_cache;
615
	$interface = str_replace("\n", "", $interface);
616
	if(does_interface_exist($interface) == false) return;
617
	/* Setup IP cache */
618
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
619
		$interface_ip_arr_cache[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2| /usr/bin/head -1");
620
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
621
	}
622

    
623
	return $interface_ip_arr_cache[$interface];
624
}
625

    
626
function guess_interface_from_ip($ipaddress) {
627
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2
628
; };'");
629
	return $ret;
630
}
631

    
632
function filter_opt_interface_to_real($opt) {
633
	global $config;
634
	return $config['interfaces'][$opt]['if'];
635
}
636

    
637
function filter_get_opt_interface_descr($opt) {
638
	global $config;
639
	return $config['interfaces'][$opt]['descr'];
640
}
641

    
642
function get_friendly_interface_list_as_array() {
643
	global $config;
644
	$ints = array();
645
	$ifdescrs = array('wan', 'lan');
646
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
647
		$ifdescrs['opt' . $j] = "opt" . $j;
648
	}
649
	$ifdescrs = get_interface_list();
650
	foreach ($ifdescrs as $ifdescr => $ifname) {
651
		array_push($ints,$ifdescr);
652
	}
653
	return $ints;
654
}
655

    
656
/*
657
 * find_ip_interface($ip): return the interface where an ip is defined
658
 */
659
function find_ip_interface($ip) {
660
	global $config;
661
	$ifdescrs = array('wan', 'lan');
662
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
663
		$ifdescrs['opt' . $j] = "opt" . $j;
664
	}
665
	foreach ($ifdescrs as $ifdescr => $ifname) {
666
		$int = filter_translate_type_to_real_interface($ifname);
667
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
668
	if(stristr($ifconfig,$ip) <> false)
669
		return $int;
670
	}
671
	return false;
672
}
673

    
674
/*
675
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
676
 *                                                       for a friendly interface.  ie: wan
677
 */
678
function filter_translate_type_to_real_interface($interface) {
679
	global $config;
680
	if($config['interfaces'][$interface]['if'] <> "") {
681
		return $config['interfaces'][$interface]['if'];
682
	} else {
683
		return $interface;
684
	}
685
}
686

    
687
/*
688
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
689
 */
690
function get_carp_interface_status($carpinterface) {
691
	/* basically cache the contents of ifconfig statement
692
	to speed up this routine */
693
	global $carp_query;
694
	if($carp_query == "")
695
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
696
	$found_interface = 0;
697
	foreach($carp_query as $int) {
698
		if($found_interface == 1) {
699
			if(stristr($int, "MASTER")) return "MASTER";
700
			if(stristr($int, "BACKUP")) return "BACKUP";
701
			if(stristr($int, "INIT")) return "INIT";
702
			return false;
703
		}
704
		if(stristr($int, $carpinterface) == true)
705
		$found_interface=1;
706
	}
707
	return;
708
}
709

    
710
/*
711
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
712
 */
713
function get_pfsync_interface_status($pfsyncinterface) {
714
    $result = does_interface_exist($pfsyncinterface);
715
    if($result <> true) return;
716
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
717
    return $status;
718
}
719

    
720
/*
721
 * find_carp_interface($ip): return the carp interface where an ip is defined
722
 */
723
function find_carp_interface($ip) {
724
	global $find_carp_ifconfig;
725
	if($find_carp_ifconfig == "") {
726
		$find_carp_ifconfig = array();
727
		$num_carp_ints = find_number_of_created_carp_interfaces();
728
		for($x=0; $x<$num_carp_ints; $x++) {
729
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
730
		}
731
	}
732
	$carps = 0;
733
	foreach($find_carp_ifconfig as $fci) {
734
		if(stristr($fci, $ip) == true)
735
			return "carp{$carps}";
736
		$carps++;
737
	}
738
}
739

    
740
/*
741
 * setup_filter_bridge(): toggle filtering bridge
742
 */
743
function setup_filter_bridge() {
744
	global $config, $g;
745
	if(isset($config['bridge']['filteringbridge'])) {
746
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
747
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
748
	} else {
749
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
750
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
751
	}
752
}
753

    
754
/*
755
 * find_number_of_created_bridges(): returns the number of currently created bridges
756
 */
757
function find_number_of_created_bridges($flush = false) {
758
	global $bridge_interface_count_cache;
759
	if(!isset($bridge_interface_count_cache) or $flush)
760
		$bridge_interface_count_cache = exec_command('/sbin/ifconfig | /usr/bin/grep "bridge[0-999]" | /usr/bin/wc -l');
761

    
762
	return $bridge_interface_count_cache;
763
}
764

    
765
/*
766
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
767
 */
768
function add_rule_to_anchor($anchor, $rule, $label) {
769
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
770
}
771

    
772
/*
773
 * remove_text_from_file
774
 * remove $text from file $file
775
 */
776
function remove_text_from_file($file, $text) {
777
	global $fd_log;
778
	if($fd_log)
779
		fwrite($fd_log, "Adding needed text items:\n");
780
	$filecontents = file_get_contents($file);
781
	$textTMP = str_replace($text, "", $filecontents);
782
	$text = $textTMP;
783
	if($fd_log)
784
		fwrite($fd_log, $text);
785
	$fd = fopen($file, "w");
786
	fwrite($fd, $text);
787
	fclose($fd);
788
}
789

    
790
/*
791
 * add_text_to_file($file, $text): adds $text to $file.
792
 * replaces the text if it already exists.
793
 */
794
function add_text_to_file($file, $text) {
795
	if(file_exists($file) and is_writable($file)) {
796
		$filecontents = split("\n", file_get_contents($file));
797
		$fout = fopen($file, "w");
798
		$new_file_text = "";
799
		foreach($filecontents as $line) {
800
			if($line)
801
				$new_file_text .= rtrim($line) . "\n";
802
		}
803
		$new_file_text .= $text . "\n";
804
		$file_text = str_replace("\n\n", "\n", $new_file_text);
805
		fwrite($fout, $file_text);
806
		fclose($fout);
807
		return true;
808
	} else {
809
		return false;
810
	}
811
}
812

    
813
/*
814
 *   after_sync_bump_adv_skew(): create skew values by 1S
815
 */
816
function after_sync_bump_adv_skew() {
817
	global $config, $g;
818
	$processed_skew = 1;
819
	$a_vip = &$config['virtualip']['vip'];
820
	foreach ($a_vip as $vipent) {
821
		if($vipent['advskew'] <> "") {
822
			$processed_skew = 1;
823
			$vipent['advskew'] = $vipent['advskew']+1;
824
		}
825
	}
826
	if($processed_skew == 1)
827
		write_config("After synch increase advertising skew");
828
}
829

    
830
/*
831
 * get_filename_from_url($url): converts a url to its filename.
832
 */
833
function get_filename_from_url($url) {
834
	return basename($url);
835
}
836

    
837
/*
838
 *   update_output_window: update bottom textarea dynamically.
839
 */
840
function update_output_window($text) {
841
	$log = ereg_replace("\n", "\\n", $text);
842
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
843
	/* ensure that contents are written out */
844
	ob_flush();
845
}
846

    
847
/*
848
 *   get_dir: return an array of $dir
849
 */
850
function get_dir($dir) {
851
	$dir_array = array();
852
	$d = dir($dir);
853
	while (false !== ($entry = $d->read())) {
854
		array_push($dir_array, $entry);
855
	}
856
	$d->close();
857
	return $dir_array;
858
}
859

    
860
/*
861
 *   update_output_window: update top textarea dynamically.
862
 */
863
function update_status($status) {
864
	echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
865
	/* ensure that contents are written out */
866
	ob_flush();
867
}
868

    
869
/*
870
 *   exec_command_and_return_text_array: execute command and return output
871
 */
872
function exec_command_and_return_text_array($command) {
873
	$fd = popen($command . " 2>&1 ", "r");
874
	while(!feof($fd)) {
875
		$tmp .= fread($fd,49);
876
	}
877
	fclose($fd);
878
	$temp_array = split("\n", $tmp);
879
	return $temp_array;
880
}
881

    
882
/*
883
 *   exec_command_and_return_text: execute command and return output
884
 */
885
function exec_command_and_return_text($command) {
886
	return exec_command($command);
887
}
888

    
889
/*
890
 *   exec_command_and_return_text: execute command and update output window dynamically
891
 */
892
function execute_command_return_output($command) {
893
	global $fd_log;
894
	$fd = popen($command . " 2>&1 ", "r");
895
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
896
	$counter = 0;
897
	$counter2 = 0;
898
	while(!feof($fd)) {
899
		$tmp = fread($fd, 50);
900
		$tmp1 = ereg_replace("\n","\\n", $tmp);
901
		$text = ereg_replace("\"","'", $tmp1);
902
		$lasttext = "";
903
		if($lasttext == "..") {
904
			$text = "";
905
			$lasttext = "";
906
			$counter=$counter-2;
907
		} else {
908
			$lasttext .= $text;
909
		}
910
		if($counter > 51) {
911
			$counter = 0;
912
			$extrabreak = "\\n";
913
		} else {
914
	    $extrabreak = "";
915
	    $counter++;
916
		}
917
		if($counter2 > 600) {
918
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
919
			$counter2 = 0;
920
		} else
921
			$counter2++;
922
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
923
	}
924
	fclose($fd);
925
}
926

    
927
/*
928
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
929
 */
930
function convert_friendly_interface_to_real_interface_name($interface) {
931
	global $config;
932
	$lc_interface = strtolower($interface);
933
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
934
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
935
	$ifdescrs = array();
936
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
937
		$ifdescrs['opt' . $j] = "opt" . $j;
938
	foreach ($ifdescrs as $ifdescr => $ifname) {
939
		if(strtolower($ifname) == $lc_interface)
940
	    return $config['interfaces'][$ifname]['if'];
941
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
942
			return $config['interfaces'][$ifname]['if'];
943
   }
944
   return $interface;
945
}
946

    
947
/*
948
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
949
 */
950
function convert_real_interface_to_friendly_interface_name($interface) {
951
	global $config;
952
	$ifdescrs = array('wan', 'lan');
953
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
954
		$ifdescrs['opt' . $j] = "opt" . $j;
955
	foreach ($ifdescrs as $ifdescr => $ifname) {
956
		$int = filter_translate_type_to_real_interface($ifname);
957
		if($ifname == $interface) return $ifname;
958
		if($int == $interface) return $ifname;
959
	}
960
	return $interface;
961
}
962

    
963
/*
964
 * update_progress_bar($percent): updates the javascript driven progress bar.
965
 */
966
function update_progress_bar($percent) {
967
	if($percent > 100) $percent = 1;
968
	echo "\n<script type=\"text/javascript\" language=\"javascript\">";
969
	echo "\ndocument.progressbar.style.width='" . $percent . "%';";
970
	echo "\n</script>";
971
}
972

    
973
/****f* pfsense-utils/WakeOnLan
974
 * NAME
975
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
976
 * RESULT
977
 *   true/false - true if the operation was successful
978
 ******/
979
function WakeOnLan($addr, $mac)
980
{
981
	$addr_byte = explode(':', $mac);
982
	$hw_addr = '';
983

    
984
	for ($a=0; $a < 6; $a++)
985
		$hw_addr .= chr(hexdec($addr_byte[$a]));
986

    
987
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
988

    
989
	for ($a = 1; $a <= 16; $a++)
990
		$msg .= $hw_addr;
991

    
992
	// send it to the broadcast address using UDP
993
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
994
	if ($s == false) {
995
		log_error("Error creating socket!");
996
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
997
	} else {
998
		// setting a broadcast option to socket:
999
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1000
		if($opt_ret < 0)
1001
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1002
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1003
		socket_close($s);
1004
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1005
		return true;
1006
	}
1007

    
1008
	return false;
1009
}
1010

    
1011
/*
1012
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
1013
 *                             is queuename|qlength|measured_packets
1014
 *                             NOTE: this command takes 5 seconds to run
1015
 */
1016
function gather_altq_queue_stats($dont_return_root_queues) {
1017
	mwexec("/usr/bin/killall -9 pfctl");
1018
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
1019
	$stats_array = split("\n", $stats);
1020
	$queue_stats = array();
1021
	foreach ($stats_array as $stats_line) {
1022
		$match_array = "";
1023
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
1024
			$queue_name = $match_array[1][0];
1025
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
1026
			$speed = $match_array[1][0];
1027
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
1028
			$borrows = $match_array[1][0];
1029
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
1030
			$suspends = $match_array[1][0];
1031
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
1032
			$drops = $match_array[1][0];
1033
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
1034
			$measured = $match_array[1][0];
1035
			if($dont_return_root_queues == true)
1036
				if(stristr($queue_name,"root_") == false)
1037
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
1038
		}
1039
	}
1040
	return $queue_stats;
1041
}
1042

    
1043
/*
1044
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1045
 *					 Useful for finding paths and stripping file extensions.
1046
 */
1047
function reverse_strrchr($haystack, $needle) {
1048
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1049
}
1050

    
1051
/*
1052
 *  backup_config_section($section): returns as an xml file string of
1053
 *                                   the configuration section
1054
 */
1055
function backup_config_section($section) {
1056
	global $config;
1057
	$new_section = &$config[$section];
1058
	/* generate configuration XML */
1059
	$xmlconfig = dump_xml_config($new_section, $section);
1060
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1061
	return $xmlconfig;
1062
}
1063

    
1064
/*
1065
 *  backup_vip_config_section($section): returns as an xml file string of
1066
 *                                   the configuration section
1067
 */
1068
function backup_vip_config_section() {
1069
	global $config;
1070
	$new_section = &$config['virtualip'];
1071
	foreach($new_section['vip'] as $section) {
1072
		if($section['mode'] == "proxyarp") {
1073
			unset($section);
1074
		}
1075
		if($section['advskew'] <> "") {
1076
			$section_val = intval($section['advskew']);
1077
			$section_val=$section_val+100;
1078
			if($section_val > 255)
1079
				$section_val = 255;
1080
			$section['advskew'] = $section_val;
1081
		}
1082
		$temp['vip'][] = $section;
1083
   }
1084
   return $temp;
1085
}
1086

    
1087
/*
1088
 *  restore_config_section($section, new_contents): restore a configuration section,
1089
 *                                                  and write the configuration out
1090
 *                                                  to disk/cf.
1091
 */
1092
function restore_config_section($section, $new_contents) {
1093
	global $config, $g;
1094
	conf_mount_rw();
1095
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
1096
	fwrite($fout, $new_contents);
1097
	fclose($fout);
1098
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
1099
	$config[$section] = &$section_xml;
1100
	unlink($g['tmp_path'] . "/tmpxml");
1101
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1102
	conf_mount_ro();
1103
	return;
1104
}
1105

    
1106
/*
1107
 * http_post($server, $port, $url, $vars): does an http post to a web server
1108
 *                                         posting the vars array.
1109
 * written by nf@bigpond.net.au
1110
 */
1111
function http_post($server, $port, $url, $vars) {
1112
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
1113
	$urlencoded = "";
1114
	while (list($key,$value) = each($vars))
1115
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
1116
	$urlencoded = substr($urlencoded,0,-1);
1117
	$content_length = strlen($urlencoded);
1118
	$headers = "POST $url HTTP/1.1
1119
Accept: */*
1120
Accept-Language: en-au
1121
Content-Type: application/x-www-form-urlencoded
1122
User-Agent: $user_agent
1123
Host: $server
1124
Connection: Keep-Alive
1125
Cache-Control: no-cache
1126
Content-Length: $content_length
1127

    
1128
";
1129

    
1130
	$errno = "";
1131
	$errstr = "";
1132
	$fp = fsockopen($server, $port, $errno, $errstr);
1133
	if (!$fp) {
1134
		return false;
1135
	}
1136

    
1137
	fputs($fp, $headers);
1138
	fputs($fp, $urlencoded);
1139

    
1140
	$ret = "";
1141
	while (!feof($fp))
1142
		$ret.= fgets($fp, 1024);
1143
	fclose($fp);
1144

    
1145
	return $ret;
1146
}
1147

    
1148
/*
1149
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
1150
 */
1151
if (!function_exists('php_check_syntax')){
1152
	function php_check_syntax($code_to_check, &$errormessage){
1153
		return false;
1154
		$fout = fopen("/tmp/codetocheck.php","w");
1155
		$code = $_POST['content'];
1156
		$code = str_replace("<?php", "", $code);
1157
		$code = str_replace("?>", "", $code);
1158
		fwrite($fout, "<?php\n\n");
1159
		fwrite($fout, $code_to_check);
1160
		fwrite($fout, "\n\n?>\n");
1161
		fclose($fout);
1162
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1163
		$output = exec_command($command);
1164
		if (stristr($output, "Errors parsing") == false) {
1165
			echo "false\n";
1166
			$errormessage = '';
1167
			return(false);
1168
		} else {
1169
			$errormessage = $output;
1170
			return(true);
1171
		}
1172
	}
1173
}
1174

    
1175
/*
1176
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1177
 */
1178
if (!function_exists('php_check_syntax')){
1179
	function php_check_syntax($code_to_check, &$errormessage){
1180
		return false;
1181
		$command = "/usr/local/bin/php -l " . $code_to_check;
1182
		$output = exec_command($command);
1183
		if (stristr($output, "Errors parsing") == false) {
1184
			echo "false\n";
1185
			$errormessage = '';
1186
			return(false);
1187
		} else {
1188
			$errormessage = $output;
1189
			return(true);
1190
		}
1191
	}
1192
}
1193

    
1194
/*
1195
 * rmdir_recursive($path,$follow_links=false)
1196
 * Recursively remove a directory tree (rm -rf path)
1197
 * This is for directories _only_
1198
 */
1199
function rmdir_recursive($path,$follow_links=false) {
1200
	$to_do = glob($path);
1201
	if(!is_array($to_do)) $to_do = array($to_do);
1202
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1203
		if(file_exists($workingdir)) {
1204
			if(is_dir($workingdir)) {
1205
				$dir = opendir($workingdir);
1206
				while ($entry = readdir($dir)) {
1207
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1208
						unlink("$workingdir/$entry");
1209
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
1210
						rmdir_recursive("$workingdir/$entry");
1211
				}
1212
				closedir($dir);
1213
				rmdir($workingdir);
1214
			} elseif (is_file($workingdir)) {
1215
				unlink($workingdir);
1216
			}
1217
               	}
1218
	}
1219
	return;
1220
}
1221

    
1222
/*
1223
 *     get_memory()
1224
 *     returns an array listing the amount of
1225
 *     memory installed in the hardware
1226
 *     [0]real and [1]available
1227
 */
1228
function get_memory() {
1229
	if(file_exists("/var/log/dmesg.boot")) {
1230
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1231
		$matches = "";
1232
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1233
			$real = $matches[1];
1234
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1235
			$avail = $matches[1];
1236
		return array($real[0],$avail[0]);
1237
	} else {
1238
		$mem = `dmesg -a`;
1239
		$matches = "";
1240
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1241
			$real = $matches[1];
1242
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1243
			$avail = $matches[1];
1244
		return array($real[0],$avail[0]);
1245
	}
1246
}
1247

    
1248
/*
1249
 *    safe_mkdir($path, $mode = 0755)
1250
 *    create directory if it doesn't already exist and isn't a file!
1251
 */
1252
function safe_mkdir($path, $mode=0755) {
1253
	global $g;
1254

    
1255
	/* cdrom is ro. */
1256
	if($g['platform'] == "cdrom")
1257
		return false;
1258

    
1259
	if (!is_file($path) && !is_dir($path))
1260
		return mkdir($path, $mode);
1261
	else
1262
		return false;
1263
}
1264

    
1265
/*
1266
 * make_dirs($path, $mode = 0755)
1267
 * create directory tree recursively (mkdir -p)
1268
 */
1269
function make_dirs($path, $mode = 0755) {
1270
	$base = '';
1271
	foreach (explode('/', $path) as $dir) {
1272
		$base .= "/$dir";
1273
		if (!is_dir($base)) {
1274
			if (!@mkdir($base, $mode))
1275
				return false;
1276
		}
1277
	}
1278
	return true;
1279
}
1280

    
1281
/*
1282
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
1283
 */
1284
function call_pfsense_method($method, $params, $timeout = 0) {
1285
	$ip = gethostbyname('www.pfsense.com');
1286
	if($ip == "www.pfsense.com")
1287
		return false;
1288
	global $g, $config;
1289
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
1290
	$xmlrpc_path = $g['xmlrpcpath'];
1291
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
1292
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
1293
	$resp = $cli->send($msg, $timeout);
1294
	if(!$resp) {
1295
		log_error("XMLRPC communication error: " . $cli->errstr);
1296
		return false;
1297
	} elseif($resp->faultCode()) {
1298
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
1299
		return false;
1300
	} else {
1301
		return XML_RPC_Decode($resp->value());
1302
	}
1303
}
1304

    
1305
/*
1306
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1307
 */
1308
function check_firmware_version($tocheck = "all", $return_php = true) {
1309
	global $g, $config;
1310
	$ip = gethostbyname('www.pfsense.com');
1311
	if($ip == "www.pfsense.com")
1312
		return false;
1313
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
1314
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
1315
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
1316
		"platform" => trim(file_get_contents('/etc/platform'))
1317
		);
1318
	if($tocheck == "all") {
1319
		$params = $rawparams;
1320
	} else {
1321
		foreach($tocheck as $check) {
1322
			$params['check'] = $rawparams['check'];
1323
			$params['platform'] = $rawparams['platform'];
1324
		}
1325
	}
1326
	if($config['system']['firmware']['branch']) {
1327
		$params['branch'] = $config['system']['firmware']['branch'];
1328
	}
1329
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
1330
		return false;
1331
	} else {
1332
		$versions["current"] = $params;
1333
	}
1334
	return $versions;
1335
}
1336

    
1337
function get_disk_info() {
1338
	$diskout = "";
1339
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
1340
	return explode(' ', $diskout[0]);
1341
	// $size, $used, $avail, $cap
1342
}
1343

    
1344
/****f* pfsense-utils/display_top_tabs
1345
 * NAME
1346
 *   display_top_tabs - display tabs with rounded edges
1347
 * INPUTS
1348
 *   $text	- array of tabs
1349
 * RESULT
1350
 *   null
1351
 ******/
1352
function display_top_tabs($tab_array) {
1353
	echo "<table cellpadding='0' cellspacing='0'>\n";
1354
	echo " <tr height='1'>\n";
1355
	$tabscounter = 0;
1356
	foreach ($tab_array as $ta) {
1357
		if($ta[1] == true) {
1358
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
1359
		} else {
1360
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
1361
		}
1362
		$tabscounter++;
1363
	}
1364
	echo "</tr>\n<tr>\n";
1365
	foreach ($tab_array as $ta) {
1366
		if($ta[1] == true) {
1367
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
1368
			echo "&nbsp;&nbsp;&nbsp;";
1369
			echo "<font size='-12'>&nbsp;</td>\n";
1370
		} else {
1371
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
1372
			echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
1373
			echo "<font size='-12'>&nbsp;</td>\n";
1374
		}
1375
	}
1376
	echo "</tr>\n<tr height='5px'>\n";
1377
	foreach ($tab_array as $ta) {
1378
		if($ta[1] == true) {
1379
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1380
		} else {
1381
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1382
		}
1383
		$tabscounter++;
1384
	}
1385
	echo " </tr>\n";
1386
	echo "</table>\n";
1387

    
1388
	echo "<script type=\"text/javascript\">";
1389
	echo "NiftyCheck();\n";
1390
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1391
	for($x=0; $x<$tabscounter; $x++)
1392
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1393
	echo "</script>";
1394
}
1395

    
1396

    
1397
/****f* pfsense-utils/display_topbar
1398
 * NAME
1399
 *   display_topbar - top a table off with rounded edges
1400
 * INPUTS
1401
 *   $text	- (optional) Text to include in bar
1402
 * RESULT
1403
 *   null
1404
 ******/
1405
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
1406
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
1407
	echo "       <tr height='1'>\n";
1408
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
1409
	echo "		<div id='topbar'></div></td>\n";
1410
	echo "       </tr>\n";
1411
	echo "       <tr height='1'>\n";
1412
	if ($text != "")
1413
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
1414
	else
1415
		echo "         <td height='1' class='listtopic'></td>\n";
1416
	echo "       </tr>\n";
1417
	echo "     </table>";
1418
	echo "<script type=\"text/javascript\">";
1419
	echo "NiftyCheck();\n";
1420
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
1421
	echo "</script>";
1422
}
1423

    
1424
/****f* pfsense-utils/generate_random_mac_address
1425
 * NAME
1426
 *   generate_random_mac - generates a random mac address
1427
 * INPUTS
1428
 *   none
1429
 * RESULT
1430
 *   $mac - a random mac address
1431
 ******/
1432
function generate_random_mac_address() {
1433
	$mac = "02";
1434
	for($x=0; $x<5; $x++)
1435
		$mac .= ":" . dechex(rand(16, 255));
1436
	return $mac;
1437
}
1438

    
1439
/****f* pfsense-utils/strncpy
1440
 * NAME
1441
 *   strncpy - copy strings
1442
 * INPUTS
1443
 *   &$dst, $src, $length
1444
 * RESULT
1445
 *   none
1446
 ******/
1447
function strncpy(&$dst, $src, $length) {
1448
	if (strlen($src) > $length) {
1449
		$dst = substr($src, 0, $length);
1450
	} else {
1451
		$dst = $src;
1452
	}
1453
}
1454

    
1455
/****f* pfsense-utils/reload_interfaces_sync
1456
 * NAME
1457
 *   reload_interfaces - reload all interfaces
1458
 * INPUTS
1459
 *   none
1460
 * RESULT
1461
 *   none
1462
 ******/
1463
function reload_interfaces_sync() {
1464
	global $config, $g, $debug;
1465

    
1466
	$shutdown_webgui_needed = false;
1467

    
1468
	touch("{$g['tmp_path']}/reloading_all");
1469

    
1470
	if($debug)
1471
		log_error("reload_interfaces_sync() is starting.");
1472

    
1473
	if(file_exists("{$g['tmp_path']}/config.cache"))
1474
		unlink("{$g['tmp_path']}/config.cache");
1475

    
1476
	/* parse config.xml again */
1477
	$config = parse_config(true);
1478

    
1479
	$wan_if = $config['interfaces']['wan']['if'];
1480
	$lan_if = $config['interfaces']['lan']['if'];
1481

    
1482
	if($debug)
1483
		log_error("Cleaning up Interfaces");
1484

    
1485
	/* build an array of interfaces to work with */
1486
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1487
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1488
		$iflist['opt' . $i] = "opt{$i}";
1489

    
1490
	foreach ($iflist as $ifent => $ifname) {
1491
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1492
		if(stristr($ifname, "lo0") == true)
1493
			continue;
1494
		/* do not process wan interface, its mandatory */
1495
		if(stristr($ifname, "$wan_if") == true)
1496
			continue;
1497
		/* do not process lan interface, its mandatory */
1498
		if(stristr($ifname, "$lan_if") == true)
1499
			continue;
1500
		if($debug)
1501
			log_error("Downing and deleting $ifname_real - $ifname");
1502
		mwexec("/sbin/ifconfig {$ifname_real} down");
1503
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1504
	}
1505

    
1506
	/* set up VLAN virtual interfaces */
1507
	if($debug)
1508
		log_error("Configuring VLANS");
1509
	interfaces_vlan_configure();
1510

    
1511
	/* set up LAN interface */
1512
	if($debug)
1513
		log_error("Configuring LAN");
1514
	interfaces_lan_configure();
1515

    
1516
	/* set up WAN interface */
1517
	if($debug)
1518
		log_error("Configuring WAN");
1519
	interfaces_wan_configure();
1520

    
1521
	/* set up Optional interfaces */
1522
	if($debug)
1523
		log_error("Configuring optional interfaces");
1524
	interfaces_optional_configure();
1525

    
1526
	/* set up static routes */
1527
	if($debug)
1528
		log_error("Configuring system Routing");
1529
	system_routing_configure();
1530

    
1531
	/* enable routing */
1532
	if($debug)
1533
		log_error("Enabling system routing");
1534
	system_routing_enable();
1535

    
1536
	/* setup captive portal if needed */
1537
	if($debug)
1538
		log_error("Configuring Captive portal");
1539
	captiveportal_configure();
1540

    
1541
	/* bring up carp interfaces */
1542
	if($debug)
1543
		log_error("Configuring CARP");
1544
	interfaces_carp_configure();
1545

    
1546
	/* bring up carp interfaces*/
1547
	if($debug)
1548
		log_error("Bringing up CARP interfaces");
1549
	interfaces_carp_bring_up_final();
1550

    
1551
	/* restart webConfigurator if needed */
1552
	if($shutdown_webgui_needed == true)
1553
		touch("/tmp/restart_webgui");
1554

    
1555
	/* start devd back up */
1556
	mwexec("/bin/rm /tmp/reload*");
1557

    
1558
	/* remove reloading_all trigger */
1559
	if($debug)
1560
		log_error("Removing {$g['tmp_path']}/reloading_all");
1561
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1562
}
1563

    
1564
/****f* pfsense-utils/reload_all
1565
 * NAME
1566
 *   reload_all - triggers a reload of all settings
1567
 *   * INPUTS
1568
 *   none
1569
 * RESULT
1570
 *   none
1571
 ******/
1572
function reload_all() {
1573
	touch("/tmp/reload_all");
1574
}
1575

    
1576
/****f* pfsense-utils/reload_interfaces
1577
 * NAME
1578
 *   reload_interfaces - triggers a reload of all interfaces
1579
 * INPUTS
1580
 *   none
1581
 * RESULT
1582
 *   none
1583
 ******/
1584
function reload_interfaces() {
1585
	touch("/tmp/reload_interfaces");
1586
}
1587

    
1588
/****f* pfsense-utils/sync_webgui_passwords
1589
 * NAME
1590
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1591
 * INPUTS
1592
 *   none
1593
 * RESULT
1594
 *   none
1595
 ******/
1596
function sync_webgui_passwords() {
1597
	global $config, $g;
1598
	conf_mount_rw();
1599
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
1600
	if (!$fd) {
1601
		printf("Error: cannot open htpasswd in system_password_configure().\n");
1602
		return 1;
1603
	}
1604
	/* set admin account */
1605
	$username = $config['system']['username'];
1606

    
1607
	/* set defined user account */
1608
	if($username <> "admin") {
1609
		$username = $config['system']['username'];
1610
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1611
	} else {
1612
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1613
	}
1614
	fclose($fd);
1615
	chmod("{$g['varrun_path']}/htpasswd", 0600);
1616
	$crypted_pw = $config['system']['password'];
1617
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1618
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1619
	/* sync root */
1620
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
1621
	fwrite($fd, $crypted_pw);
1622
	pclose($fd);
1623
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
1624
	/* sync admin */
1625
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
1626
	fwrite($fd, $crypted_pw);
1627
	pclose($fd);
1628
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
1629
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1630
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1631
	conf_mount_ro();
1632
}
1633

    
1634
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
1635
 * NAME
1636
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
1637
 *   * INPUTS
1638
 *   optional interface number
1639
 * RESULT
1640
 *   none
1641
 ******/
1642
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
1643
	global $config;
1644
	config_lock();
1645
	conf_mount_rw();
1646
	unlink_if_exists("/tmp/config.cache");
1647
	$config_file = file_get_contents("/cf/conf/config.xml");
1648
	/* loop through and reassign optional items */
1649
	for ($i = 255; isset($config['interfaces']['opt' . $i]); $i--) {
1650
		if($i < $opt_interface_num)
1651
			break;
1652
		/* replace opt$i with $i -1 */
1653
		str_replace("opt" . $i, "opt" . ($i-1), $config_file);
1654
	}
1655
	conf_mount_rw();
1656
	$fd = fopen("/cf/conf/config.xml", "w");
1657
	fwrite($fd, $config_file);
1658
	fclose($fd);
1659
	$config = parse_config(true);
1660
	conf_mount_ro();
1661
	config_unlock();
1662
	return true;
1663
}
1664

    
1665
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
1666
 * NAME
1667
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
1668
 *   		amount of netgraph interfaces needed for system wans
1669
 *   * INPUTS
1670
 *   none
1671
 * RESULT
1672
 *   number of needed netgraph (ng) interfaces
1673
 ******/
1674
function get_number_of_wan_netgraph_interfaces_needed() {
1675
	global $config, $g;
1676
	/* build an array of interfaces to work with */
1677
	$iflist = array("wan" => "WAN");
1678
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1679
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1680
	$ng_interfaces_needed = 0;
1681
	foreach ($iflist as $ifent => $ifname) {
1682
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1683
			$ng_interfaces_needed++;
1684
		}
1685
	}
1686
	return $ng_interfaces_needed;
1687
}
1688

    
1689
function get_netgaph_interface_assignment($friendly_interface) {
1690
	global $config, $g;
1691
	/* build an array of interfaces to work with */
1692
	$iflist = array("wan" => "WAN");
1693
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1694
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1695
		$ng_interfaces_needed = 0;
1696
		$ng_interfaces_number = 0;
1697
		foreach ($iflist as $ifent => $ifname) {
1698
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1699
			$ng_interfaces_number++;
1700
		}
1701
		if($friendly_interface == $ifname)
1702
			break;
1703
	}
1704
	return $ng_interfaces_number;
1705
}
1706

    
1707
/****f* pfsense-utils/reload_all_sync
1708
 * NAME
1709
 *   reload_all - reload all settings
1710
 *   * INPUTS
1711
 *   none
1712
 * RESULT
1713
 *   none
1714
 ******/
1715
function reload_all_sync() {
1716
	global $config, $g;
1717

    
1718
	$g['booting'] = false;
1719

    
1720
	touch("{$g['tmp_path']}/reloading_all");
1721

    
1722
	$shutdown_webgui_needed = false;
1723

    
1724
	if(file_exists("{$g['tmp_path']}/config.cache"))
1725
		unlink("{$g['tmp_path']}/config.cache");
1726

    
1727
	/* parse config.xml again */
1728
	$config = parse_config(true);
1729

    
1730
	/* set up our timezone */
1731
	system_timezone_configure();
1732

    
1733
	/* set up our hostname */
1734
	system_hostname_configure();
1735

    
1736
	/* make hosts file */
1737
	system_hosts_generate();
1738

    
1739
	/* generate resolv.conf */
1740
	system_resolvconf_generate();
1741

    
1742
	/* delete all old interface information */
1743
	$iflist = split(" ", str_replace("\n", "", `/sbin/ifconfig -l`));
1744

    
1745
	$wan_if = $config['interfaces']['wan']['if'];
1746
	$lan_if = $config['interfaces']['lan']['if'];
1747

    
1748
	/* build an array of interfaces to work with */
1749
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1750
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1751
		$iflist['opt' . $i] = "opt{$i}";
1752

    
1753
	foreach ($iflist as $ifent => $ifname) {
1754
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1755
		if(stristr($ifname, "lo0") == true)
1756
			continue;
1757
		/* do not process wan interface, its mandatory */
1758
		if($wan_if == $ifname_real)
1759
			continue;
1760
		/* do not process lan interface, its mandatory */
1761
		if($lan_if == $ifname_real)
1762
			continue;
1763
		mwexec("/sbin/ifconfig {$ifname_real} down");
1764
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1765
	}
1766

    
1767
	/* set up VLAN virtual interfaces */
1768
	interfaces_vlan_configure();
1769

    
1770
	/* set up LAN interface */
1771
	interfaces_lan_configure();
1772

    
1773
	/* set up WAN interface */
1774
	interfaces_wan_configure();
1775

    
1776
	/* set up Optional interfaces */
1777
	interfaces_optional_configure();
1778

    
1779
	/* bring up carp interfaces */
1780
	interfaces_carp_configure();
1781

    
1782
	/* set up static routes */
1783
	system_routing_configure();
1784

    
1785
	/* enable routing */
1786
	system_routing_enable();
1787

    
1788
	/* ensure passwords are sync'd */
1789
	system_password_configure();
1790

    
1791
	/* start dnsmasq service */
1792
	services_dnsmasq_configure();
1793

    
1794
	/* start dyndns service */
1795
	services_dyndns_configure();
1796

    
1797
	/* start DHCP service */
1798
	services_dhcpd_configure();
1799

    
1800
	/* start the NTP client */
1801
	system_ntp_configure();
1802

    
1803
	/* start ftp proxy helpers if they are enabled */
1804
	system_start_ftp_helpers();
1805

    
1806
	/* start the captive portal */
1807
	captiveportal_configure();
1808

    
1809
        /* reload the filter */
1810
	filter_configure_sync();
1811

    
1812
	/* bring up carp interfaces*/
1813
	interfaces_carp_bring_up_final();
1814

    
1815
	/* sync pw database */
1816
	conf_mount_rw();
1817
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1818
	conf_mount_ro();
1819

    
1820
	/* restart sshd */
1821
	touch("/tmp/start_sshd");
1822

    
1823
	/* restart webConfigurator if needed */
1824
	if($shutdown_webgui_needed == true)
1825
		touch("/tmp/restart_webgui");
1826

    
1827
	mwexec("/bin/rm /tmp/reload*");
1828

    
1829
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1830

    
1831
}
1832

    
1833
function auto_login($status) {
1834
	$gettytab = file_get_contents("/etc/gettytab");
1835
	$getty_split = split("\n", $gettytab);
1836
	conf_mount_rw();
1837
	$fd = fopen("/etc/gettytab", "w");
1838
	foreach($getty_split as $gs) {
1839
		if(stristr($gs, ":ht:np:sp#115200") ) {
1840
			if($status == true) {
1841
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
1842
			} else {
1843
				fwrite($fd, "	:ht:np:sp#115200:\n");
1844
			}
1845
		} else {
1846
			fwrite($fd, "{$gs}\n");
1847
		}
1848
	}
1849
	fclose($fd);
1850
	conf_mount_ro();
1851
}
1852

    
1853
function setup_serial_port() {
1854
	global $g, $config;
1855
	conf_mount_rw();
1856
	/* serial console - write out /boot.config */
1857
	if(file_exists("/boot.config"))
1858
		$boot_config = file_get_contents("/boot.config");
1859
	else
1860
		$boot_config = "";
1861

    
1862
	if($g['platform'] <> "cdrom") {
1863
		$boot_config_split = split("\n", $boot_config);
1864
		$fd = fopen("/boot.config","w");
1865
		if($fd) {
1866
			foreach($boot_config_split as $bcs) {
1867
				if(stristr($bcs, "-D")) {
1868
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1869
				} else {
1870
					if($bcs <> "")
1871
						fwrite($fd, "{$bcs}\n");
1872
				}
1873
			}
1874
			if(isset($config['system']['enableserial'])) {
1875
				fwrite($fd, "-D");
1876
			}
1877
			fclose($fd);
1878
		}
1879
		/* serial console - write out /boot/loader.conf */
1880
		$boot_config = file_get_contents("/boot/loader.conf");
1881
		$boot_config_split = split("\n", $boot_config);
1882
		$fd = fopen("/boot/loader.conf","w");
1883
		if($fd) {
1884
			foreach($boot_config_split as $bcs) {
1885
				if(stristr($bcs, "console")) {
1886
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1887
				} else {
1888
					if($bcs <> "")
1889
						fwrite($fd, "{$bcs}\n");
1890
				}
1891
			}
1892
			if(isset($config['system']['enableserial'])) {
1893
				fwrite($fd, "console=\"comconsole\"\n");
1894
			}
1895
			fclose($fd);
1896
		}
1897
	}
1898
	$ttys = file_get_contents("/etc/ttys");
1899
	$ttys_split = split("\n", $ttys);
1900
	$fd = fopen("/etc/ttys", "w");
1901
	foreach($ttys_split as $tty) {
1902
		if(stristr($tty, "ttyd0")) {
1903
			if(isset($config['system']['enableserial'])) {
1904
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
1905
			} else {
1906
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
1907
			}
1908
		} else {
1909
			fwrite($fd, $tty . "\n");
1910
		}
1911
	}
1912
	fclose($fd);
1913
	if(isset($config['system']['disableconsolemenu'])) {
1914
		auto_login(false);
1915
	} else {
1916
		auto_login(true);
1917
	}
1918
	conf_mount_ro();
1919
	return;
1920
}
1921

    
1922
function print_value_list($list, $count = 10, $separator = ",") {
1923
	$list = implode($separator, array_slice($list, 0, $count));
1924
	if(count($list) < $count) {
1925
		$list .= ".";
1926
	} else {
1927
		$list .= "...";
1928
	}
1929
	return $list;
1930
}
1931

    
1932
function convert_friendly_interface_to_friendly_descr($interface) {
1933
	global $config;
1934
	/* attempt to resolve interface to friendly descr */
1935
	if($config['interfaces'][$interface]['descr'])
1936
		return $config['interfaces'][$interface]['descr'];
1937
	$tmp = convert_real_interface_to_friendly_descr($interface);
1938
	/* could not resolve, return back what was passed */
1939
	return $interface;
1940
}
1941

    
1942
function convert_real_interface_to_friendly_descr($interface) {
1943
	global $config;
1944
	if($interface == $config['interfaces']['wan']['if'])
1945
		return "wan";
1946
	if($interface == $config['interfaces']['lan']['if'])
1947
		return "lan";
1948
	/* attempt to resolve interface to friendly descr */
1949
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
1950
	if($config['interfaces'][$friendly_int]['descr'])
1951
		return $config['interfaces'][$friendly_int]['descr'];
1952
	/* could not resolve, return back what was passed */
1953
	return $interface;
1954
}
1955

    
1956
function enable_rrd_graphing() {
1957

    
1958
	global $config, $g;
1959

    
1960
	$rrddbpath = "/var/db/rrd/";
1961
	$rrdgraphpath = "/usr/local/www/rrd";
1962

    
1963
	$traffic = "-traffic.rrd";
1964
	$packets = "-packets.rrd";
1965
	$states = "-states.rrd";
1966
	$quality = "-quality.rrd";
1967
	$queues = "-queues.rrd";
1968
	$queuesdrop = "-queuesdrop.rrd";
1969
	$spamd = "-spamd.rrd";
1970
	$proc = "-processor.rrd";
1971

    
1972
	$rrdtool = "/usr/local/bin/rrdtool";
1973
	$netstat = "/usr/bin/netstat";
1974
	$awk = "/usr/bin/awk";
1975
	$tar = "/usr/bin/tar";
1976
	$pfctl = "/sbin/pfctl";
1977
	$php = "/usr/local/bin/php";
1978
	$top = "/usr/bin/top";
1979
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
1980

    
1981
	/* if an alternative gateway is defined, use it */
1982
	if ($config['system']['use_rrd_gateway'] <> "")
1983
		$gatewayip = $config['system']['use_rrd_gateway'];
1984
	else
1985
		$gatewayip = exec("/sbin/route -n get default | /usr/bin/grep gateway | /usr/bin/awk '{print $2}'");
1986

    
1987
	$numpings = 5;
1988
	$btick = '`';
1989

    
1990
	$rrdtrafficinterval = 60;
1991
	$rrdqualityinterval = 60;
1992
	$rrdqueuesinterval = 60;
1993
	$rrdqueuesdropinterval = 60;
1994
	$rrdpacketsinterval = 60;
1995
	$rrdstatesinterval = 60;
1996
	$rrdspamdinterval = 60;
1997
	$rrdlbpoolinterval = 60;
1998
	$rrdprocinterval = 60;
1999

    
2000
	$trafficvalid = $rrdtrafficinterval * 2;
2001
	$qualityvalid = $rrdqualityinterval * 2;
2002
	$queuesvalid = $rrdqueuesinterval * 2;
2003
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2004
	$packetsvalid = $rrdpacketsinterval * 2;
2005
	$statesvalid = $rrdstatesinterval*2;
2006
	$spamdvalid = $rrdspamdinterval * 2;
2007
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2008
	$procvalid = $rrdlbpoolinterval * 2;
2009

    
2010
	/* Asume GigE for now */
2011
	$downstream = 125000000;
2012
	$upstream = 125000000;
2013

    
2014
	$rrdrestore = "";
2015
	$rrdreturn = "";
2016

    
2017
	$config['rrd']['enable'] = true;
2018

    
2019
	if (isset ($config['rrd']['enable'])) {
2020

    
2021
		/* create directory if needed */
2022
		if (!is_dir("$rrddbpath")) {
2023
			mkdir("$rrddbpath", 0755);
2024
		}
2025

    
2026
		if ($g['booting']) {
2027
			/* if we are on livecd or embedded use a memoryfs. */
2028
			/* 6MB is enough for everyone. *cough* */
2029
			if ($g['platform'] != "pfSense") {
2030
				/* determine highest MD device */
2031
				$mdnr = `mount |grep md | awk -F"md" '{print $2}'|tail -1 |cut -c 1`;
2032
				$mdnr = $mdnr +1;
2033
				system("/sbin/mdmfs -M -s 6m md$mdnr $rrddbpath");
2034

    
2035
				/* we now have something to write "on", restore the databases if we have them */
2036
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
2037
					exec("cd /;/usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2038
					if((int)$rrdrestore <> 0) {
2039
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
2040
					}
2041
				}
2042
			}
2043
		}
2044

    
2045
		/* db update script */
2046
		$rrdupdatesh = "#!/bin/sh\n";
2047
		$rrdupdatesh .= "\n";
2048
		$rrdupdatesh .= "counter=1\n";
2049
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2050
		$rrdupdatesh .= "do\n";
2051
		$rrdupdatesh .= "";
2052

    
2053
		$i = 0;
2054
		$vfaces = array (
2055
			"vlan.?*"
2056
		);
2057
		$ifdescrs = get_interface_list(true, true, $vfaces);
2058
		foreach ($ifdescrs as $realif => $ifdescr) {
2059
			$ifname = $ifdescr['friendly'];
2060
			$state = $ifdescr['up'];
2061

    
2062
			/* skip interfaces that do not have a friendly name */
2063
			if ("$ifname" == "") {
2064
				continue;
2065
			}
2066

    
2067
			/* or are down */
2068
			if (!$state) {
2069
				continue;
2070
			}
2071

    
2072
			/* TRAFFIC, set up the rrd file */
2073
			if (!file_exists("$rrddbpath$ifname$traffic")) {
2074
				/* create rrd file if it does not exist */
2075
				log_error("Create RRD database $rrddbpath$ifname$traffic");
2076
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval \
2077
						DS:in:COUNTER:$trafficvalid:0:$downstream \
2078
						DS:out:COUNTER:$trafficvalid:0:$upstream \
2079
						RRA:AVERAGE:0.5:1:1000 \
2080
						RRA:AVERAGE:0.5:5:1000 \
2081
						RRA:AVERAGE:0.5:60:1000 \
2082
						RRA:AVERAGE:0.5:720:1000 \
2083
						RRA:MAX:0.5:1:1000 \
2084
						RRA:MAX:0.5:5:1000 \
2085
						RRA:MAX:0.5:60:1000 \
2086
						RRA:MAX:0.5:720:1000";
2087

    
2088
				$rrdcreateoutput = array();
2089
				$rrdcreatereturn = "";
2090

    
2091
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2092
				if ($rrdcreatereturn != 0) {
2093
					log_error("RRD create failed exited with $rrdcreatereturn, the
2094
							error is: $rrdcreateoutput[0]\n");
2095
				}
2096
			}
2097

    
2098
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2099
			if($g['booting']) {
2100
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
2101
			}
2102

    
2103
			$rrdupdatesh .= "\n";
2104
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
2105
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
2106
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7}'`:\\\n";
2107
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$10}'`\n\n";
2108

    
2109
			/* PACKETS, set up the rrd file */
2110
			if (!file_exists("$rrddbpath$ifname$packets")) {
2111
				/* create rrd file if it does not exist */
2112
				log_error("Create RRD database $rrddbpath$ifname$packets");
2113
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval \
2114
						DS:in:COUNTER:$packetsvalid:0:$downstream \
2115
						DS:out:COUNTER:$packetsvalid:0:$upstream \
2116
						RRA:AVERAGE:0.5:1:1000 \
2117
						RRA:AVERAGE:0.5:5:1000 \
2118
						RRA:AVERAGE:0.5:60:1000 \
2119
						RRA:AVERAGE:0.5:720:1000 \
2120
						RRA:MAX:0.5:1:1000 \
2121
						RRA:MAX:0.5:5:1000 \
2122
						RRA:MAX:0.5:60:1000 \
2123
						RRA:MAX:0.5:720:1000";
2124

    
2125
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2126
				if ($rrdcreatereturn != 0) {
2127
					log_error("RRD create failed exited with $rrdcreatereturn, the
2128
							error is: $rrdcreateoutput[0]\n");
2129
				}
2130
			}
2131

    
2132
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2133
			if($g['booting']) {
2134
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
2135
			}
2136

    
2137
			$rrdupdatesh .= "\n";
2138
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
2139
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
2140
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5}'`:\\\n";
2141
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$8}'`\n\n";
2142

    
2143
			/* WAN interface only statistics */
2144
			if ("$ifname" == "wan") {
2145

    
2146
				/* QUALITY, create link quality database */
2147
				if (!file_exists("$rrddbpath$ifname$quality")) {
2148
					/* create rrd file if it does not exist */
2149
					log_error("Create RRD database $rrddbpath$ifname$quality");
2150
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval \
2151
							DS:loss:GAUGE:$qualityvalid:0:100 \
2152
							DS:roundtrip:GAUGE:$qualityvalid:0:10000 \
2153
							RRA:AVERAGE:0.5:1:1000 \
2154
							RRA:AVERAGE:0.5:5:1000 \
2155
							RRA:AVERAGE:0.5:60:1000 \
2156
							RRA:AVERAGE:0.5:720:1000";
2157

    
2158
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2159
					if ($rrdcreatereturn != 0) {
2160
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2161
					}
2162
				}
2163

    
2164
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2165
				if($g['booting']) {
2166
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
2167
				}
2168

    
2169
				/* the ping test function. We call this on the last line */
2170
				$rrdupdatesh .= "get_ping_stats () {
2171
							packetloss=100
2172
							roundtrip=0
2173
							local out
2174
							out=$btick ping -c $numpings -q $gatewayip $btick
2175
							if [ $? -eq 0 ]; then
2176
							packetloss=$btick echo \$out | cut -f18 -d' ' | cut -c -1 $btick
2177
							roundtrip=$btick echo \$out | cut -f24 -d' ' | cut -f2 -d'/' $btick
2178
							fi
2179
							$rrdtool update $rrddbpath$ifname$quality N:\$packetloss:\$roundtrip
2180
							}\n\n";
2181

    
2182
				$rrdupdatesh .= "get_ping_stats &\n\n";
2183

    
2184
				/* QUEUES, set up the queues databases */
2185
				if (!is_array($config['shaper']['queue'])) {
2186
					$config['shaper']['queue'] = array ();
2187
				}
2188
				$a_queues = & $config['shaper']['queue'];
2189

    
2190
				if (isset ($config['shaper']['enable'])) {
2191
					if (!file_exists("$rrddbpath$ifname$queues")) {
2192
						/* create rrd file if it does not exist */
2193
						log_error("Create RRD database $rrddbpath$ifname$queues");
2194
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval \\\n";
2195
						/* loop list of shaper queues */
2196
						$q = 0;
2197
						foreach ($a_queues as $queue) {
2198
							$name = $queue['name'];
2199
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream \\\n";
2200
						}
2201

    
2202
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 \
2203
								RRA:AVERAGE:0.5:5:1000 \
2204
								RRA:AVERAGE:0.5:60:1000 \
2205
								RRA:AVERAGE:0.5:720:1000";
2206

    
2207
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2208
						if ($rrdcreatereturn != 0) {
2209
							log_error("RRD create failed exited with $rrdcreatereturn, the
2210
									error is: $rrdcreateoutput[0]\n");
2211
						}
2212
					}
2213

    
2214
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
2215
						/* create rrd file if it does not exist */
2216
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
2217
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval \\\n";
2218
						/* loop list of shaper queues */
2219
						$q = 0;
2220
						foreach ($a_queues as $queue) {
2221
							$name = $queue['name'];
2222
							$rrdcreate .= "DS:$name:COUNTER:$queuesdropvalid:0:$downstream \\\n";
2223
						}
2224

    
2225
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 \
2226
	                                                        RRA:AVERAGE:0.5:5:1000 \
2227
	                                                        RRA:AVERAGE:0.5:60:1000 \
2228
	                                                        RRA:AVERAGE:0.5:720:1000";
2229

    
2230
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2231
						if ($rrdcreatereturn != 0) {
2232
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2233
						}
2234
					}
2235

    
2236
					if($g['booting']) {
2237
						$rrdqcommand = "-t ";
2238
						$rrducommand = "N";
2239
						$q = 0;
2240
						foreach ($a_queues as $queue) {
2241
							if($q == 0) {
2242
								$rrdqcommand .= "{$queue['name']}";
2243
							} else {
2244
								$rrdqcommand .= ":{$queue['name']}";
2245
							}
2246
							$q++;
2247
							$rrducommand .= ":U";
2248
						}
2249
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
2250
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
2251
					}
2252

    
2253
					/* awk function to gather shaper data */
2254
					/* yes, it's special */
2255
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } \\
2256
								{ \\
2257
								if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { \\
2258
								dsname = dsname \":\" \$2 ; \\
2259
								q=1; \\
2260
								} \\
2261
								else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { \\
2262
								dsdata = dsdata \":\" \$5 ; \\
2263
								q=0; \\
2264
								} \\
2265
								} END { \\
2266
								dsname = substr(dsname,2); \\
2267
								dsdata = substr(dsdata,2); \\
2268
								printf \"-t \" dsname \" N:\" dsdata }' \\
2269
								dsname=\"\" dsdata=\"\"`\n\n";
2270

    
2271
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } \\
2272
								{ \\
2273
								if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { \\
2274
								dsname = dsname \":\" \$2 ; \\
2275
								q=1; \\
2276
								} \\
2277
								else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { \\
2278
								dsdata = dsdata \":\" \$8 ; \\
2279
								q=0; \\
2280
								} \\
2281
								} END { \\
2282
								dsname = substr(dsname,2); \\
2283
								dsdata = substr(dsdata,2); \\
2284
								printf \"-t \" dsname \" N:\" dsdata }' \\
2285
								dsname=\"\" dsdata=\"\"`\n\n";
2286
				}
2287
			}
2288
		}
2289
		$i++;
2290

    
2291
		/* System only statistics */
2292
		$ifname = "system";
2293

    
2294
			/* STATES, create pf states database */
2295
			if(! file_exists("$rrddbpath$ifname$states")) {
2296
				/* create rrd file if it does not exist */
2297
				log_error("Create RRD database $rrddbpath$ifname$states");
2298
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval \
2299
						DS:pfrate:GAUGE:$statesvalid:0:10000000 \
2300
						DS:pfstates:GAUGE:$statesvalid:0:10000000 \
2301
						DS:pfnat:GAUGE:$statesvalid:0:10000000 \
2302
						DS:srcip:GAUGE:$statesvalid:0:10000000 \
2303
						DS:dstip:GAUGE:$statesvalid:0:10000000 \
2304
						RRA:MIN:0.5:1:1000 \
2305
						RRA:MIN:0.5:5:1000 \
2306
						RRA:MIN:0.5:60:1000 \
2307
						RRA:MIN:0.5:360:1000 \
2308
						RRA:AVERAGE:0.5:1:1000 \
2309
						RRA:AVERAGE:0.5:5:1000 \
2310
						RRA:AVERAGE:0.5:60:1000 \
2311
						RRA:AVERAGE:0.5:360:1000 \
2312
						RRA:MAX:0.5:1:1000 \
2313
						RRA:MAX:0.5:5:1000 \
2314
						RRA:MAX:0.5:60:1000 \
2315
						RRA:MAX:0.5:360:1000";
2316

    
2317
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2318
				if($rrdcreatereturn != 0) {
2319
			                log_error("RRD create failed exited with $rrdcreatereturn, the
2320
						error is: $rrdcreateoutput[0]\n");
2321
				}
2322
			}
2323

    
2324
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2325
			if($g['booting']) {
2326
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
2327
			}
2328

    
2329
 			/* the pf states gathering function. */
2330
 			$rrdupdatesh .= "
2331
 				pfrate=\"` $pfctl -si | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"
2332
 				pfstates=\"` $pfctl -ss | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"
2333
 				pfnat=\"` $pfctl -ss | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"
2334
 				srcip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '\\->' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"
2335
 				dstip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '<\\-' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"
2336

    
2337
				$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip
2338
				\n\n";
2339

    
2340
			/* End pf states statistics */
2341

    
2342
			/* CPU, create CPU statistics database */
2343
			if(! file_exists("$rrddbpath$ifname$proc")) {
2344
				/* create rrd file if it does not exist */
2345
				log_error("Create RRD database $rrddbpath$ifname$proc");
2346
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval \
2347
						DS:user:GAUGE:$procvalid:0:10000000 \
2348
						DS:nice:GAUGE:$procvalid:0:10000000 \
2349
						DS:system:GAUGE:$procvalid:0:10000000 \
2350
						DS:interrupt:GAUGE:$procvalid:0:10000000 \
2351
						DS:processes:GAUGE:$procvalid:0:10000000 \
2352
						RRA:MIN:0.5:1:1000 \
2353
						RRA:MIN:0.5:5:1000 \
2354
						RRA:MIN:0.5:60:1000 \
2355
						RRA:MIN:0.5:360:1000 \
2356
						RRA:AVERAGE:0.5:1:1000 \
2357
						RRA:AVERAGE:0.5:5:1000 \
2358
						RRA:AVERAGE:0.5:60:1000 \
2359
						RRA:AVERAGE:0.5:360:1000 \
2360
						RRA:MAX:0.5:1:1000 \
2361
						RRA:MAX:0.5:5:1000 \
2362
						RRA:MAX:0.5:60:1000 \
2363
						RRA:MAX:0.5:360:1000";
2364

    
2365
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2366
				if($rrdcreatereturn != 0) {
2367
			                log_error("RRD create failed exited with $rrdcreatereturn, the
2368
						error is: $rrdcreateoutput[0]\n");
2369
				}
2370
			}
2371

    
2372
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2373
			if($g['booting']) {
2374
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
2375
			}
2376

    
2377
 			/* the CPU stats gathering function. */
2378
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { \\
2379
							printf \"$rrdtool update $rrddbpath$ifname$proc \" } \\
2380
							{ if ( \$2 == \"processes:\" ) { \\
2381
								processes = \$1; \\
2382
							} \\
2383
							else if ( \$1 == \"CPU\" ) { \\
2384
								user = \$3; \\
2385
								nice = \$5; \\
2386
								sys = \$7; \\
2387
								interrupt = \$9; \\
2388
							} \\
2389
						} END { \\
2390
							printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes \\
2391
						}'`\n\n";
2392

    
2393
			/* End CPU statistics */
2394

    
2395
			/* SPAMD, set up the spamd rrd file */
2396
			if (isset($config['installedpackages']['spamdsettings']) &&
2397
				isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
2398
				/* Move old name to new name */
2399
				if (file_exists("{$rrddbpath}spamd.rrd")) {
2400
					rename("{$rrddbpath}spamd.rrd", "$rrddbpath$ifname$spamd");
2401
				}
2402
				/* set up the spamd rrd file */
2403
				if (!file_exists("$rrddbpath$ifname$spamd")) {
2404
						/* create rrd file if it does not exist */
2405
						log_error("Create RRD database $rrddbpath$ifname$spamd");
2406
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval \
2407
							DS:conn:GAUGE:$spamdvalid:0:10000 \
2408
							DS:time:GAUGE:$spamdvalid:0:86400 \
2409
							RRA:MIN:0.5:1:1000 \
2410
							RRA:MIN:0.5:5:1000 \
2411
							RRA:MIN:0.5:60:1000 \
2412
							RRA:MIN:0.5:720:1000 \
2413
							RRA:AVERAGE:0.5:1:1000 \
2414
							RRA:AVERAGE:0.5:5:1000 \
2415
							RRA:AVERAGE:0.5:60:1000 \
2416
							RRA:AVERAGE:0.5:720:1000 \
2417
							RRA:MAX:0.5:1:1000 \
2418
							RRA:MAX:0.5:5:1000 \
2419
							RRA:MAX:0.5:60:1000 \
2420
							RRA:MAX:0.5:720:1000";
2421

    
2422
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2423
					if ($rrdcreatereturn != 0) {
2424
						log_error("RRD create failed exited with $rrdcreatereturn, the
2425
							error is: $rrdcreateoutput[0]\n");
2426
					}
2427
				}
2428

    
2429
				$rrdupdatesh .= "\n";
2430
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
2431
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
2432
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
2433

    
2434
			}
2435
		/* End System statistics */
2436

    
2437
		$rrdupdatesh .= "sleep 60\n";
2438
		$rrdupdatesh .= "done\n";
2439
		log_error("Creating rrd update script");
2440
		/* write the rrd update script */
2441
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
2442
		$fd = fopen("$updaterrdscript", "w");
2443
		fwrite($fd, "$rrdupdatesh");
2444
		fclose($fd);
2445

    
2446
		/* kill off traffic collectors */
2447
		kill_traffic_collector();
2448

    
2449
		/* start traffic collector */
2450
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
2451

    
2452
	} else {
2453
		/* unmount and remove */
2454
		system("/sbin/umount $rrddbpath");
2455
		exec("/sbin/mdconfig -d -u 2");
2456
		/* kill off traffic collectors */
2457
		kill_traffic_collector();
2458
	}
2459
}
2460

    
2461
function kill_traffic_collector() {
2462
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
2463
}
2464

    
2465
function update_filter_reload_status($text) {
2466
	global $g;
2467
	config_lock();
2468
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
2469
	fwrite($fd, $text);
2470
	fclose($fd);
2471
	config_unlock();
2472
}
2473

    
2474
function get_interface_gateway($interface) {
2475
	global $config, $g;
2476
	$interface = strtolower($interface);
2477
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
2478
	 *  grab the address from the configuration file.
2479
	 */
2480
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
2481
	if($tmpif <> $interface)
2482
		$interface = $tmpif;
2483
	$realif = $config['interfaces'][$interface]['if'];
2484
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
2485
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
2486
		$gw = rtrim($gw);
2487
	} else {
2488
		$gw = $config['interfaces'][$interface]['gateway'];
2489
	}
2490
	/* if wan is requested, return it */
2491
	if($interface == "wan")
2492
		return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
2493
	/* return gateway */
2494
	return $gw;
2495
}
2496

    
2497
function is_dhcp_server_enabled() {
2498
	/* DHCP enabled on any interfaces? */
2499
	global $config, $g;
2500
	$dhcpdcfg = $config['dhcpd'];
2501
	$dhcpdenable = false;
2502
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
2503
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2504
			$dhcpdenable = true;
2505
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2506
			$dhcpdenable = true;
2507
	}
2508
	return $dhcpdenable;
2509
}
2510

    
2511
?>
(14-14/27)