Project

General

Profile

Download (76.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/pfsense-utils
3
 * NAME
4
 *   pfsense-utils.inc - Utilities specific to pfSense
5
 * DESCRIPTION
6
 *   This include contains various pfSense specific functions.
7
 * HISTORY
8
 *   $Id$
9
 ******
10
 *
11
 * Copyright (C) 2004-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($config['system']['disablechecksumoffloading'])
202
		return;
203

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

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

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

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

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

    
284
	setup_polling_defaults();
285

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

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

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

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

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

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

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

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

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

    
400
	if($tmp == "")
401
		return false;
402
	else
403
		return true;
404
}
405

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

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

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

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

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

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

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

    
494
	$ft = split("\.", $ip);
495
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
496

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

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

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

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

    
568
	$capable = $g['vlan_long_frame'];
569

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

    
572
	if (in_array($int_family[0], $capable))
573
		return true;
574
	else
575
		return false;
576
}
577

    
578
/*
579
 * Return the interface array
580
 */
581
function get_interface_arr($flush = false) {
582
	global $interface_arr_cache;
583

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

    
588
	return $interface_arr_cache;
589
}
590

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

    
598
	if(stristr($ints, $interface) !== false)
599
		return true;
600
	else
601
		return false;
602
}
603

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

    
613
/*
614
 * find_interface_ip($interface): return the interface ip (first found)
615
 */
616
function find_interface_ip($interface, $flush = false) {
617
	global $interface_ip_arr_cache;
618
	$interface = str_replace("\n", "", $interface);
619
	if(does_interface_exist($interface) == false) return;
620
	/* Setup IP cache */
621
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
622
		$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");
623
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
624
	}
625

    
626
	return $interface_ip_arr_cache[$interface];
627
}
628

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

    
635
function filter_opt_interface_to_real($opt) {
636
	global $config;
637
	return $config['interfaces'][$opt]['if'];
638
}
639

    
640
function filter_get_opt_interface_descr($opt) {
641
	global $config;
642
	return $config['interfaces'][$opt]['descr'];
643
}
644

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

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

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

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

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

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

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

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

    
765
	return $bridge_interface_count_cache;
766
}
767

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

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

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

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

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

    
840
/*
841
 *   update_output_window: update bottom textarea dynamically.
842
 */
843
function update_output_window($text) {
844
	global $pkg_interface;
845
	$log = ereg_replace("\n", "\\n", $text);
846
	if($pkg_interface == "console") {
847
		echo " $log";
848
	} else {
849
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
850
	}
851
	/* ensure that contents are written out */
852
	ob_flush();
853
}
854

    
855
/*
856
 *   get_dir: return an array of $dir
857
 */
858
function get_dir($dir) {
859
	$dir_array = array();
860
	$d = dir($dir);
861
	while (false !== ($entry = $d->read())) {
862
		array_push($dir_array, $entry);
863
	}
864
	$d->close();
865
	return $dir_array;
866
}
867

    
868
/*
869
 *   update_output_window: update top textarea dynamically.
870
 */
871
function update_status($status) {
872
	echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
873
	/* ensure that contents are written out */
874
	ob_flush();
875
}
876

    
877
/*
878
 *   exec_command_and_return_text_array: execute command and return output
879
 */
880
function exec_command_and_return_text_array($command) {
881
	$fd = popen($command . " 2>&1 ", "r");
882
	while(!feof($fd)) {
883
		$tmp .= fread($fd,49);
884
	}
885
	fclose($fd);
886
	$temp_array = split("\n", $tmp);
887
	return $temp_array;
888
}
889

    
890
/*
891
 *   exec_command_and_return_text: execute command and return output
892
 */
893
function exec_command_and_return_text($command) {
894
	return exec_command($command);
895
}
896

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

    
935
/*
936
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
937
 */
938
function convert_friendly_interface_to_real_interface_name($interface) {
939
	global $config;
940
	$lc_interface = strtolower($interface);
941
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
942
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
943
	$ifdescrs = array();
944
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
945
		$ifdescrs['opt' . $j] = "opt" . $j;
946
	foreach ($ifdescrs as $ifdescr => $ifname) {
947
		if(strtolower($ifname) == $lc_interface)
948
	    return $config['interfaces'][$ifname]['if'];
949
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
950
			return $config['interfaces'][$ifname]['if'];
951
   }
952
   return $interface;
953
}
954

    
955
/*
956
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
957
 */
958
function convert_real_interface_to_friendly_interface_name($interface) {
959
	global $config;
960
	$ifdescrs = array('wan', 'lan');
961
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
962
		$ifdescrs['opt' . $j] = "opt" . $j;
963
	foreach ($ifdescrs as $ifdescr => $ifname) {
964
		if($config['interfaces']['$ifname']['if'] == $interface)
965
			return $ifname;
966
		$int = filter_translate_type_to_real_interface($ifname);
967
		if($ifname == $interface) return $ifname;
968
		if($int == $interface) return $ifname;
969
	}
970
	return $interface;
971
}
972

    
973
/*
974
 * update_progress_bar($percent): updates the javascript driven progress bar.
975
 */
976
function update_progress_bar($percent) {
977
	if($percent > 100) $percent = 1;
978
	echo "\n<script type=\"text/javascript\" language=\"javascript\">";
979
	echo "\ndocument.progressbar.style.width='" . $percent . "%';";
980
	echo "\n</script>";
981
}
982

    
983
/****f* pfsense-utils/WakeOnLan
984
 * NAME
985
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
986
 * RESULT
987
 *   true/false - true if the operation was successful
988
 ******/
989
function WakeOnLan($addr, $mac)
990
{
991
	$addr_byte = explode(':', $mac);
992
	$hw_addr = '';
993

    
994
	for ($a=0; $a < 6; $a++)
995
		$hw_addr .= chr(hexdec($addr_byte[$a]));
996

    
997
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
998

    
999
	for ($a = 1; $a <= 16; $a++)
1000
		$msg .= $hw_addr;
1001

    
1002
	// send it to the broadcast address using UDP
1003
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1004
	if ($s == false) {
1005
		log_error("Error creating socket!");
1006
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
1007
	} else {
1008
		// setting a broadcast option to socket:
1009
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1010
		if($opt_ret < 0)
1011
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1012
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1013
		socket_close($s);
1014
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1015
		return true;
1016
	}
1017

    
1018
	return false;
1019
}
1020

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

    
1053
/*
1054
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1055
 *					 Useful for finding paths and stripping file extensions.
1056
 */
1057
function reverse_strrchr($haystack, $needle) {
1058
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1059
}
1060

    
1061
/*
1062
 *  backup_config_section($section): returns as an xml file string of
1063
 *                                   the configuration section
1064
 */
1065
function backup_config_section($section) {
1066
	global $config;
1067
	$new_section = &$config[$section];
1068
	/* generate configuration XML */
1069
	$xmlconfig = dump_xml_config($new_section, $section);
1070
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1071
	return $xmlconfig;
1072
}
1073

    
1074
/*
1075
 *  backup_vip_config_section($section): returns as an xml file string of
1076
 *                                   the configuration section
1077
 */
1078
function backup_vip_config_section() {
1079
	global $config;
1080
	$new_section = &$config['virtualip'];
1081
	foreach($new_section['vip'] as $section) {
1082
		if($section['mode'] == "proxyarp") {
1083
			unset($section);
1084
		}
1085
		if($section['advskew'] <> "") {
1086
			$section_val = intval($section['advskew']);
1087
			$section_val=$section_val+100;
1088
			if($section_val > 255)
1089
				$section_val = 255;
1090
			$section['advskew'] = $section_val;
1091
		}
1092
		$temp['vip'][] = $section;
1093
   }
1094
   return $temp;
1095
}
1096

    
1097
/*
1098
 *  restore_config_section($section, new_contents): restore a configuration section,
1099
 *                                                  and write the configuration out
1100
 *                                                  to disk/cf.
1101
 */
1102
function restore_config_section($section, $new_contents) {
1103
	global $config, $g;
1104
	conf_mount_rw();
1105
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
1106
	fwrite($fout, $new_contents);
1107
	fclose($fout);
1108
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
1109
	$config[$section] = &$section_xml;
1110
	unlink($g['tmp_path'] . "/tmpxml");
1111
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1112
	conf_mount_ro();
1113
	return;
1114
}
1115

    
1116
/*
1117
 *  merge_config_section($section, new_contents):   restore a configuration section,
1118
 *                                                  and write the configuration out
1119
 *                                                  to disk/cf.  But preserve the prior
1120
 * 													structure if needed
1121
 */
1122
function merge_config_section($section, $new_contents) {
1123
	global $config;
1124
	conf_mount_rw();
1125
	$fname = get_tmp_filename();
1126
	$fout = fopen($fname, "w");
1127
	fwrite($fout, $new_contents);
1128
	fclose($fout);
1129
	$section_xml = parse_xml_config($fname, $section);
1130
	$config[$section] = $section_xml;
1131
	unlink($fname);
1132
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1133
	conf_mount_ro();
1134
	return;
1135
}
1136

    
1137
/*
1138
 * http_post($server, $port, $url, $vars): does an http post to a web server
1139
 *                                         posting the vars array.
1140
 * written by nf@bigpond.net.au
1141
 */
1142
function http_post($server, $port, $url, $vars) {
1143
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
1144
	$urlencoded = "";
1145
	while (list($key,$value) = each($vars))
1146
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
1147
	$urlencoded = substr($urlencoded,0,-1);
1148
	$content_length = strlen($urlencoded);
1149
	$headers = "POST $url HTTP/1.1
1150
Accept: */*
1151
Accept-Language: en-au
1152
Content-Type: application/x-www-form-urlencoded
1153
User-Agent: $user_agent
1154
Host: $server
1155
Connection: Keep-Alive
1156
Cache-Control: no-cache
1157
Content-Length: $content_length
1158

    
1159
";
1160

    
1161
	$errno = "";
1162
	$errstr = "";
1163
	$fp = fsockopen($server, $port, $errno, $errstr);
1164
	if (!$fp) {
1165
		return false;
1166
	}
1167

    
1168
	fputs($fp, $headers);
1169
	fputs($fp, $urlencoded);
1170

    
1171
	$ret = "";
1172
	while (!feof($fp))
1173
		$ret.= fgets($fp, 1024);
1174
	fclose($fp);
1175

    
1176
	return $ret;
1177
}
1178

    
1179
/*
1180
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
1181
 */
1182
if (!function_exists('php_check_syntax')){
1183
	function php_check_syntax($code_to_check, &$errormessage){
1184
		return false;
1185
		$fout = fopen("/tmp/codetocheck.php","w");
1186
		$code = $_POST['content'];
1187
		$code = str_replace("<?php", "", $code);
1188
		$code = str_replace("?>", "", $code);
1189
		fwrite($fout, "<?php\n\n");
1190
		fwrite($fout, $code_to_check);
1191
		fwrite($fout, "\n\n?>\n");
1192
		fclose($fout);
1193
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1194
		$output = exec_command($command);
1195
		if (stristr($output, "Errors parsing") == false) {
1196
			echo "false\n";
1197
			$errormessage = '';
1198
			return(false);
1199
		} else {
1200
			$errormessage = $output;
1201
			return(true);
1202
		}
1203
	}
1204
}
1205

    
1206
/*
1207
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1208
 */
1209
if (!function_exists('php_check_syntax')){
1210
	function php_check_syntax($code_to_check, &$errormessage){
1211
		return false;
1212
		$command = "/usr/local/bin/php -l " . $code_to_check;
1213
		$output = exec_command($command);
1214
		if (stristr($output, "Errors parsing") == false) {
1215
			echo "false\n";
1216
			$errormessage = '';
1217
			return(false);
1218
		} else {
1219
			$errormessage = $output;
1220
			return(true);
1221
		}
1222
	}
1223
}
1224

    
1225
/*
1226
 * rmdir_recursive($path,$follow_links=false)
1227
 * Recursively remove a directory tree (rm -rf path)
1228
 * This is for directories _only_
1229
 */
1230
function rmdir_recursive($path,$follow_links=false) {
1231
	$to_do = glob($path);
1232
	if(!is_array($to_do)) $to_do = array($to_do);
1233
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1234
		if(file_exists($workingdir)) {
1235
			if(is_dir($workingdir)) {
1236
				$dir = opendir($workingdir);
1237
				while ($entry = readdir($dir)) {
1238
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1239
						unlink("$workingdir/$entry");
1240
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
1241
						rmdir_recursive("$workingdir/$entry");
1242
				}
1243
				closedir($dir);
1244
				rmdir($workingdir);
1245
			} elseif (is_file($workingdir)) {
1246
				unlink($workingdir);
1247
			}
1248
               	}
1249
	}
1250
	return;
1251
}
1252

    
1253
/*
1254
 *     get_memory()
1255
 *     returns an array listing the amount of
1256
 *     memory installed in the hardware
1257
 *     [0]real and [1]available
1258
 */
1259
function get_memory() {
1260
	if(file_exists("/var/log/dmesg.boot")) {
1261
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1262
		$matches = "";
1263
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1264
			$real = $matches[1];
1265
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1266
			$avail = $matches[1];
1267
		return array($real[0],$avail[0]);
1268
	} else {
1269
		$mem = `dmesg -a`;
1270
		$matches = "";
1271
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1272
			$real = $matches[1];
1273
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1274
			$avail = $matches[1];
1275
		return array($real[0],$avail[0]);
1276
	}
1277
}
1278

    
1279
/*
1280
 *    safe_mkdir($path, $mode = 0755)
1281
 *    create directory if it doesn't already exist and isn't a file!
1282
 */
1283
function safe_mkdir($path, $mode=0755) {
1284
	global $g;
1285

    
1286
	/* cdrom is ro. */
1287
	if($g['platform'] == "cdrom")
1288
		return false;
1289

    
1290
	if (!is_file($path) && !is_dir($path))
1291
		return mkdir($path, $mode);
1292
	else
1293
		return false;
1294
}
1295

    
1296
/*
1297
 * make_dirs($path, $mode = 0755)
1298
 * create directory tree recursively (mkdir -p)
1299
 */
1300
function make_dirs($path, $mode = 0755) {
1301
	$base = '';
1302
	foreach (explode('/', $path) as $dir) {
1303
		$base .= "/$dir";
1304
		if (!is_dir($base)) {
1305
			if (!@mkdir($base, $mode))
1306
				return false;
1307
		}
1308
	}
1309
	return true;
1310
}
1311

    
1312
/*
1313
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
1314
 */
1315
function call_pfsense_method($method, $params, $timeout = 0) {
1316
	$ip = gethostbyname('www.pfsense.com');
1317
	if($ip == "www.pfsense.com")
1318
		return false;
1319
	global $g, $config;
1320
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
1321
	$xmlrpc_path = $g['xmlrpcpath'];
1322
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
1323
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
1324
	$resp = $cli->send($msg, $timeout);
1325
	if(!$resp) {
1326
		log_error("XMLRPC communication error: " . $cli->errstr);
1327
		return false;
1328
	} elseif($resp->faultCode()) {
1329
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
1330
		return false;
1331
	} else {
1332
		return XML_RPC_Decode($resp->value());
1333
	}
1334
}
1335

    
1336
/*
1337
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1338
 */
1339
function check_firmware_version($tocheck = "all", $return_php = true) {
1340
	global $g, $config;
1341
	$ip = gethostbyname('www.pfsense.com');
1342
	if($ip == "www.pfsense.com")
1343
		return false;
1344
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
1345
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
1346
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
1347
		"platform" => trim(file_get_contents('/etc/platform'))
1348
		);
1349
	if($tocheck == "all") {
1350
		$params = $rawparams;
1351
	} else {
1352
		foreach($tocheck as $check) {
1353
			$params['check'] = $rawparams['check'];
1354
			$params['platform'] = $rawparams['platform'];
1355
		}
1356
	}
1357
	if($config['system']['firmware']['branch']) {
1358
		$params['branch'] = $config['system']['firmware']['branch'];
1359
	}
1360
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
1361
		return false;
1362
	} else {
1363
		$versions["current"] = $params;
1364
	}
1365
	return $versions;
1366
}
1367

    
1368
function get_disk_info() {
1369
	$diskout = "";
1370
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
1371
	return explode(' ', $diskout[0]);
1372
	// $size, $used, $avail, $cap
1373
}
1374

    
1375
/****f* pfsense-utils/display_top_tabs
1376
 * NAME
1377
 *   display_top_tabs - display tabs with rounded edges
1378
 * INPUTS
1379
 *   $text	- array of tabs
1380
 * RESULT
1381
 *   null
1382
 ******/
1383
function display_top_tabs($tab_array) {
1384
	echo "<table cellpadding='0' cellspacing='0'>\n";
1385
	echo " <tr height='1'>\n";
1386
	$tabscounter = 0;
1387
	foreach ($tab_array as $ta) {
1388
		if($ta[1] == true) {
1389
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
1390
		} else {
1391
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
1392
		}
1393
		$tabscounter++;
1394
	}
1395
	echo "</tr>\n<tr>\n";
1396
	foreach ($tab_array as $ta) {
1397
		if($ta[1] == true) {
1398
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
1399
			echo "&nbsp;&nbsp;&nbsp;";
1400
			echo "<font size='-12'>&nbsp;</td>\n";
1401
		} else {
1402
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
1403
			echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
1404
			echo "<font size='-12'>&nbsp;</td>\n";
1405
		}
1406
	}
1407
	echo "</tr>\n<tr height='5px'>\n";
1408
	foreach ($tab_array as $ta) {
1409
		if($ta[1] == true) {
1410
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1411
		} else {
1412
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1413
		}
1414
		$tabscounter++;
1415
	}
1416
	echo " </tr>\n";
1417
	echo "</table>\n";
1418

    
1419
	echo "<script type=\"text/javascript\">";
1420
	echo "NiftyCheck();\n";
1421
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1422
	for($x=0; $x<$tabscounter; $x++)
1423
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1424
	echo "</script>";
1425
}
1426

    
1427

    
1428
/****f* pfsense-utils/display_topbar
1429
 * NAME
1430
 *   display_topbar - top a table off with rounded edges
1431
 * INPUTS
1432
 *   $text	- (optional) Text to include in bar
1433
 * RESULT
1434
 *   null
1435
 ******/
1436
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
1437
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
1438
	echo "       <tr height='1'>\n";
1439
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
1440
	echo "		<div id='topbar'></div></td>\n";
1441
	echo "       </tr>\n";
1442
	echo "       <tr height='1'>\n";
1443
	if ($text != "")
1444
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
1445
	else
1446
		echo "         <td height='1' class='listtopic'></td>\n";
1447
	echo "       </tr>\n";
1448
	echo "     </table>";
1449
	echo "<script type=\"text/javascript\">";
1450
	echo "NiftyCheck();\n";
1451
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
1452
	echo "</script>";
1453
}
1454

    
1455
/****f* pfsense-utils/generate_random_mac_address
1456
 * NAME
1457
 *   generate_random_mac - generates a random mac address
1458
 * INPUTS
1459
 *   none
1460
 * RESULT
1461
 *   $mac - a random mac address
1462
 ******/
1463
function generate_random_mac_address() {
1464
	$mac = "02";
1465
	for($x=0; $x<5; $x++)
1466
		$mac .= ":" . dechex(rand(16, 255));
1467
	return $mac;
1468
}
1469

    
1470
/****f* pfsense-utils/strncpy
1471
 * NAME
1472
 *   strncpy - copy strings
1473
 * INPUTS
1474
 *   &$dst, $src, $length
1475
 * RESULT
1476
 *   none
1477
 ******/
1478
function strncpy(&$dst, $src, $length) {
1479
	if (strlen($src) > $length) {
1480
		$dst = substr($src, 0, $length);
1481
	} else {
1482
		$dst = $src;
1483
	}
1484
}
1485

    
1486
/****f* pfsense-utils/reload_interfaces_sync
1487
 * NAME
1488
 *   reload_interfaces - reload all interfaces
1489
 * INPUTS
1490
 *   none
1491
 * RESULT
1492
 *   none
1493
 ******/
1494
function reload_interfaces_sync() {
1495
	global $config, $g, $debug;
1496

    
1497
	$shutdown_webgui_needed = false;
1498

    
1499
	touch("{$g['tmp_path']}/reloading_all");
1500

    
1501
	if($debug)
1502
		log_error("reload_interfaces_sync() is starting.");
1503

    
1504
	if(file_exists("{$g['tmp_path']}/config.cache"))
1505
		unlink("{$g['tmp_path']}/config.cache");
1506

    
1507
	/* parse config.xml again */
1508
	$config = parse_config(true);
1509

    
1510
	$wan_if = $config['interfaces']['wan']['if'];
1511
	$lan_if = $config['interfaces']['lan']['if'];
1512

    
1513
	if($debug)
1514
		log_error("Cleaning up Interfaces");
1515

    
1516
	/* build an array of interfaces to work with */
1517
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1518
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1519
		$iflist['opt' . $i] = "opt{$i}";
1520

    
1521
	foreach ($iflist as $ifent => $ifname) {
1522
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1523
		if(stristr($ifname, "lo0") == true)
1524
			continue;
1525
		/* do not process wan interface, its mandatory */
1526
		if(stristr($ifname, "$wan_if") == true)
1527
			continue;
1528
		/* do not process lan interface, its mandatory */
1529
		if(stristr($ifname, "$lan_if") == true)
1530
			continue;
1531
		if($debug)
1532
			log_error("Downing and deleting $ifname_real - $ifname");
1533
		mwexec("/sbin/ifconfig {$ifname_real} down");
1534
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1535
	}
1536

    
1537
	/* set up VLAN virtual interfaces */
1538
	if($debug)
1539
		log_error("Configuring VLANS");
1540
	interfaces_vlan_configure();
1541

    
1542
	/* set up LAN interface */
1543
	if($debug)
1544
		log_error("Configuring LAN");
1545
	interfaces_lan_configure();
1546

    
1547
	/* set up WAN interface */
1548
	if($debug)
1549
		log_error("Configuring WAN");
1550
	interfaces_wan_configure();
1551

    
1552
	/* set up Optional interfaces */
1553
	if($debug)
1554
		log_error("Configuring optional interfaces");
1555
	interfaces_optional_configure();
1556

    
1557
	/* set up static routes */
1558
	if($debug)
1559
		log_error("Configuring system Routing");
1560
	system_routing_configure();
1561

    
1562
	/* enable routing */
1563
	if($debug)
1564
		log_error("Enabling system routing");
1565
	system_routing_enable();
1566

    
1567
	/* setup captive portal if needed */
1568
	if($debug)
1569
		log_error("Configuring Captive portal");
1570
	captiveportal_configure();
1571

    
1572
	/* bring up carp interfaces */
1573
	if($debug)
1574
		log_error("Configuring CARP");
1575
	interfaces_carp_configure();
1576

    
1577
	/* bring up carp interfaces*/
1578
	if($debug)
1579
		log_error("Bringing up CARP interfaces");
1580
	interfaces_carp_bring_up_final();
1581

    
1582
	/* restart webConfigurator if needed */
1583
	if($shutdown_webgui_needed == true)
1584
		touch("/tmp/restart_webgui");
1585

    
1586
	/* start devd back up */
1587
	mwexec("/bin/rm /tmp/reload*");
1588

    
1589
	/* remove reloading_all trigger */
1590
	if($debug)
1591
		log_error("Removing {$g['tmp_path']}/reloading_all");
1592
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1593
}
1594

    
1595
/****f* pfsense-utils/reload_all
1596
 * NAME
1597
 *   reload_all - triggers a reload of all settings
1598
 *   * INPUTS
1599
 *   none
1600
 * RESULT
1601
 *   none
1602
 ******/
1603
function reload_all() {
1604
	touch("/tmp/reload_all");
1605
}
1606

    
1607
/****f* pfsense-utils/reload_interfaces
1608
 * NAME
1609
 *   reload_interfaces - triggers a reload of all interfaces
1610
 * INPUTS
1611
 *   none
1612
 * RESULT
1613
 *   none
1614
 ******/
1615
function reload_interfaces() {
1616
	touch("/tmp/reload_interfaces");
1617
}
1618

    
1619
/****f* pfsense-utils/sync_webgui_passwords
1620
 * NAME
1621
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1622
 * INPUTS
1623
 *   none
1624
 * RESULT
1625
 *   none
1626
 ******/
1627
function sync_webgui_passwords() {
1628
	global $config, $g;
1629
	conf_mount_rw();
1630
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
1631
	if (!$fd) {
1632
		printf("Error: cannot open htpasswd in system_password_configure().\n");
1633
		return 1;
1634
	}
1635
	/* set admin account */
1636
	$username = $config['system']['username'];
1637

    
1638
	/* set defined user account */
1639
	if($username <> "admin") {
1640
		$username = $config['system']['username'];
1641
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1642
	} else {
1643
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1644
	}
1645
	fclose($fd);
1646
	chmod("{$g['varrun_path']}/htpasswd", 0600);
1647
	$crypted_pw = $config['system']['password'];
1648
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1649
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1650
	/* sync root */
1651
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
1652
	fwrite($fd, $crypted_pw);
1653
	pclose($fd);
1654
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
1655
	/* sync admin */
1656
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
1657
	fwrite($fd, $crypted_pw);
1658
	pclose($fd);
1659
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
1660
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1661
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1662
	conf_mount_ro();
1663
}
1664

    
1665
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
1666
 * NAME
1667
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
1668
 *   * INPUTS
1669
 *   optional interface number
1670
 * RESULT
1671
 *   none
1672
 ******/
1673
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
1674
	/*	move all the interfaces up.  for example:
1675
	*		opt1 --> opt1
1676
	*		opt2 --> delete
1677
	*		opt3 --> opt2
1678
	*		opt4 --> opt3
1679
	*/
1680
	global $g, $config;
1681
	config_lock();
1682
	conf_mount_rw();
1683
	unlink_if_exists("{$g['tmp_path']}/config.cache");
1684
	$config_file = file_get_contents("/cf/conf/config.xml");
1685
	/* loop through and reassign deleted items */
1686
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
1687
		if ($i < $opt_interface_num)
1688
			break;
1689
		if ($i == $opt_interface_num) {
1690
			/* item should be deleted */
1691
			str_replace("opt" . $i, "optXXXX", $config_file);
1692
		}
1693
	}
1694
	/* loop through and reassign optional items */
1695
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
1696
		if ($i < $opt_interface_num)
1697
			break;
1698
		/* replace opt$i with $i -1 */
1699
		str_replace("opt" . $i, "opt" . ($i -1), $config_file);
1700
	}
1701
	$fd = fopen("/cf/conf/config.xml", "w");
1702
	fwrite($fd, $config_file);
1703
	fclose($fd);
1704
	$config = parse_config(true);
1705
	/* loop through and delete old rules */
1706
	$num_rules = count($config['filter']['rule']);
1707
	for($x = $num_rules; $x > 0; $x--) {
1708
		if($config['filter']['rule'][$x])
1709
			if($config['filter']['rule'][$x]['interface'] == "optXXXX")
1710
		 		unset($config['filter']['rule'][$x]['interface']);
1711
	}
1712
	$num_rules = count($config['nat']['advancedoutbound']['rule']);
1713
	for($x = $num_rules; $x > 0; $x--) {
1714
		if($config['nat']['advancedoutbound']['rule'][$x])
1715
			if($config['nat']['advancedoutbound']['rule'][$x]['interface'] == "optXXXX")
1716
		 		unset($config['nat']['advancedoutbound']['rule'][$x]['interface']);
1717
	}
1718
	$num_rules = count($config['nat']['rule']);
1719
	for($x = $num_rules; $x > 0; $x--) {
1720
		if($config['nat']['rule'][$x])
1721
			if($config['nat']['rule'][$x]['interface'] == "optXXXX")
1722
		 		unset($config['nat']['rule'][$x]['interface']);
1723
	}
1724
	conf_mount_ro();
1725
	config_unlock();
1726
	return true;
1727
}
1728

    
1729
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
1730
 * NAME
1731
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
1732
 *   		amount of netgraph interfaces needed for system wans
1733
 *   * INPUTS
1734
 *   none
1735
 * RESULT
1736
 *   number of needed netgraph (ng) interfaces
1737
 ******/
1738
function get_number_of_wan_netgraph_interfaces_needed() {
1739
	global $config, $g;
1740
	/* build an array of interfaces to work with */
1741
	$iflist = array("wan" => "WAN");
1742
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1743
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1744
	$ng_interfaces_needed = 0;
1745
	foreach ($iflist as $ifent => $ifname) {
1746
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1747
			$ng_interfaces_needed++;
1748
		}
1749
	}
1750
	return $ng_interfaces_needed;
1751
}
1752

    
1753
function get_netgaph_interface_assignment($friendly_interface) {
1754
	global $config, $g;
1755
	/* build an array of interfaces to work with */
1756
	$iflist = array("wan" => "WAN");
1757
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1758
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1759
		$ng_interfaces_needed = 0;
1760
		$ng_interfaces_number = 0;
1761
		foreach ($iflist as $ifent => $ifname) {
1762
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1763
			$ng_interfaces_number++;
1764
		}
1765
		if($friendly_interface == $ifname)
1766
			break;
1767
	}
1768
	return $ng_interfaces_number;
1769
}
1770

    
1771
/****f* pfsense-utils/reload_all_sync
1772
 * NAME
1773
 *   reload_all - reload all settings
1774
 *   * INPUTS
1775
 *   none
1776
 * RESULT
1777
 *   none
1778
 ******/
1779
function reload_all_sync() {
1780
	global $config, $g;
1781

    
1782
	$g['booting'] = false;
1783

    
1784
	touch("{$g['tmp_path']}/reloading_all");
1785

    
1786
	$shutdown_webgui_needed = false;
1787

    
1788
	if(file_exists("{$g['tmp_path']}/config.cache"))
1789
		unlink("{$g['tmp_path']}/config.cache");
1790

    
1791
	/* parse config.xml again */
1792
	$config = parse_config(true);
1793

    
1794
	/* set up our timezone */
1795
	system_timezone_configure();
1796

    
1797
	/* set up our hostname */
1798
	system_hostname_configure();
1799

    
1800
	/* make hosts file */
1801
	system_hosts_generate();
1802

    
1803
	/* generate resolv.conf */
1804
	system_resolvconf_generate();
1805

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

    
1809
	$wan_if = $config['interfaces']['wan']['if'];
1810
	$lan_if = $config['interfaces']['lan']['if'];
1811

    
1812
	/* build an array of interfaces to work with */
1813
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1814
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1815
		$iflist['opt' . $i] = "opt{$i}";
1816

    
1817
	foreach ($iflist as $ifent => $ifname) {
1818
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1819
		if(stristr($ifname, "lo0") == true)
1820
			continue;
1821
		/* do not process wan interface, its mandatory */
1822
		if($wan_if == $ifname_real)
1823
			continue;
1824
		/* do not process lan interface, its mandatory */
1825
		if($lan_if == $ifname_real)
1826
			continue;
1827
		mwexec("/sbin/ifconfig {$ifname_real} down");
1828
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1829
	}
1830

    
1831
	/* set up VLAN virtual interfaces */
1832
	interfaces_vlan_configure();
1833

    
1834
	/* set up LAN interface */
1835
	interfaces_lan_configure();
1836

    
1837
	/* set up WAN interface */
1838
	interfaces_wan_configure();
1839

    
1840
	/* set up Optional interfaces */
1841
	interfaces_optional_configure();
1842

    
1843
	/* bring up carp interfaces */
1844
	interfaces_carp_configure();
1845

    
1846
	/* set up static routes */
1847
	system_routing_configure();
1848

    
1849
	/* enable routing */
1850
	system_routing_enable();
1851

    
1852
	/* ensure passwords are sync'd */
1853
	system_password_configure();
1854

    
1855
	/* start dnsmasq service */
1856
	services_dnsmasq_configure();
1857

    
1858
	/* start dyndns service */
1859
	services_dyndns_configure();
1860

    
1861
	/* start DHCP service */
1862
	services_dhcpd_configure();
1863

    
1864
	/* configure cron service */
1865
	configure_cron();
1866

    
1867
	/* start the NTP client */
1868
	system_ntp_configure();
1869

    
1870
	/* start ftp proxy helpers if they are enabled */
1871
	system_start_ftp_helpers();
1872

    
1873
	/* start the captive portal */
1874
	captiveportal_configure();
1875

    
1876
        /* reload the filter */
1877
	filter_configure_sync();
1878

    
1879
	/* bring up carp interfaces*/
1880
	interfaces_carp_bring_up_final();
1881

    
1882
	/* sync pw database */
1883
	conf_mount_rw();
1884
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1885
	conf_mount_ro();
1886

    
1887
	/* restart sshd */
1888
	touch("/tmp/start_sshd");
1889

    
1890
	/* restart webConfigurator if needed */
1891
	if($shutdown_webgui_needed == true)
1892
		touch("/tmp/restart_webgui");
1893

    
1894
	mwexec("/bin/rm /tmp/reload*");
1895

    
1896
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1897

    
1898
}
1899

    
1900
function auto_login($status) {
1901
	$gettytab = file_get_contents("/etc/gettytab");
1902
	$getty_split = split("\n", $gettytab);
1903
	conf_mount_rw();
1904
	$fd = fopen("/etc/gettytab", "w");
1905
	foreach($getty_split as $gs) {
1906
		if(stristr($gs, ":ht:np:sp#115200") ) {
1907
			if($status == true) {
1908
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
1909
			} else {
1910
				fwrite($fd, "	:ht:np:sp#115200:\n");
1911
			}
1912
		} else {
1913
			fwrite($fd, "{$gs}\n");
1914
		}
1915
	}
1916
	fclose($fd);
1917
	conf_mount_ro();
1918
}
1919

    
1920
function setup_serial_port() {
1921
	global $g, $config;
1922
	conf_mount_rw();
1923
	/* serial console - write out /boot.config */
1924
	if(file_exists("/boot.config"))
1925
		$boot_config = file_get_contents("/boot.config");
1926
	else
1927
		$boot_config = "";
1928

    
1929
	if($g['platform'] <> "cdrom") {
1930
		$boot_config_split = split("\n", $boot_config);
1931
		$fd = fopen("/boot.config","w");
1932
		if($fd) {
1933
			foreach($boot_config_split as $bcs) {
1934
				if(stristr($bcs, "-D")) {
1935
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1936
				} else {
1937
					if($bcs <> "")
1938
						fwrite($fd, "{$bcs}\n");
1939
				}
1940
			}
1941
			if(isset($config['system']['enableserial'])) {
1942
				fwrite($fd, "-D");
1943
			}
1944
			fclose($fd);
1945
		}
1946
		/* serial console - write out /boot/loader.conf */
1947
		$boot_config = file_get_contents("/boot/loader.conf");
1948
		$boot_config_split = split("\n", $boot_config);
1949
		$fd = fopen("/boot/loader.conf","w");
1950
		if($fd) {
1951
			foreach($boot_config_split as $bcs) {
1952
				if(stristr($bcs, "console")) {
1953
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1954
				} else {
1955
					if($bcs <> "")
1956
						fwrite($fd, "{$bcs}\n");
1957
				}
1958
			}
1959
			if(isset($config['system']['enableserial'])) {
1960
				fwrite($fd, "console=\"comconsole\"\n");
1961
			}
1962
			fclose($fd);
1963
		}
1964
	}
1965
	$ttys = file_get_contents("/etc/ttys");
1966
	$ttys_split = split("\n", $ttys);
1967
	$fd = fopen("/etc/ttys", "w");
1968
	foreach($ttys_split as $tty) {
1969
		if(stristr($tty, "ttyd0")) {
1970
			if(isset($config['system']['enableserial'])) {
1971
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
1972
			} else {
1973
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
1974
			}
1975
		} else {
1976
			fwrite($fd, $tty . "\n");
1977
		}
1978
	}
1979
	fclose($fd);
1980
	if(isset($config['system']['disableconsolemenu'])) {
1981
		auto_login(false);
1982
	} else {
1983
		auto_login(true);
1984
	}
1985
	conf_mount_ro();
1986
	return;
1987
}
1988

    
1989
function print_value_list($list, $count = 10, $separator = ",") {
1990
	$list = implode($separator, array_slice($list, 0, $count));
1991
	if(count($list) < $count) {
1992
		$list .= ".";
1993
	} else {
1994
		$list .= "...";
1995
	}
1996
	return $list;
1997
}
1998

    
1999
function convert_friendly_interface_to_friendly_descr($interface) {
2000
	global $config;
2001
	/* attempt to resolve interface to friendly descr */
2002
	if($config['interfaces'][$interface]['descr'])
2003
		return $config['interfaces'][$interface]['descr'];
2004
	$tmp = convert_real_interface_to_friendly_descr($interface);
2005
	/* could not resolve, return back what was passed */
2006
	return $interface;
2007
}
2008

    
2009
function convert_real_interface_to_friendly_descr($interface) {
2010
	global $config;
2011
	if($interface == $config['interfaces']['wan']['if'])
2012
		return "wan";
2013
	if($interface == $config['interfaces']['lan']['if'])
2014
		return "lan";
2015
	/* attempt to resolve interface to friendly descr */
2016
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
2017
	if($config['interfaces'][$friendly_int]['descr'])
2018
		return $config['interfaces'][$friendly_int]['descr'];
2019
	/* could not resolve, return back what was passed */
2020
	return $interface;
2021
}
2022

    
2023
function enable_rrd_graphing() {
2024

    
2025
	global $config, $g;
2026

    
2027
	$rrddbpath = "/var/db/rrd/";
2028
	$rrdgraphpath = "/usr/local/www/rrd";
2029

    
2030
	$traffic = "-traffic.rrd";
2031
	$packets = "-packets.rrd";
2032
	$states = "-states.rrd";
2033
	$quality = "-quality.rrd";
2034
	$queues = "-queues.rrd";
2035
	$queuesdrop = "-queuesdrop.rrd";
2036
	$spamd = "-spamd.rrd";
2037
	$proc = "-processor.rrd";
2038

    
2039
	$rrdtool = "/usr/local/bin/rrdtool";
2040
	$netstat = "/usr/bin/netstat";
2041
	$awk = "/usr/bin/awk";
2042
	$tar = "/usr/bin/tar";
2043
	$pfctl = "/sbin/pfctl";
2044
	$php = "/usr/local/bin/php";
2045
	$top = "/usr/bin/top";
2046
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2047

    
2048
	$rrdtrafficinterval = 60;
2049
	$rrdqualityinterval = 60;
2050
	$rrdqueuesinterval = 60;
2051
	$rrdqueuesdropinterval = 60;
2052
	$rrdpacketsinterval = 60;
2053
	$rrdstatesinterval = 60;
2054
	$rrdspamdinterval = 60;
2055
	$rrdlbpoolinterval = 60;
2056
	$rrdprocinterval = 60;
2057

    
2058
	$trafficvalid = $rrdtrafficinterval * 2;
2059
	$qualityvalid = $rrdqualityinterval * 2;
2060
	$queuesvalid = $rrdqueuesinterval * 2;
2061
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2062
	$packetsvalid = $rrdpacketsinterval * 2;
2063
	$statesvalid = $rrdstatesinterval*2;
2064
	$spamdvalid = $rrdspamdinterval * 2;
2065
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2066
	$procvalid = $rrdlbpoolinterval * 2;
2067

    
2068
	/* Asume GigE for now */
2069
	$downstream = 125000000;
2070
	$upstream = 125000000;
2071

    
2072
	$rrdrestore = "";
2073
	$rrdreturn = "";
2074

    
2075
	$config['rrd']['enable'] = true;
2076

    
2077
	if (isset ($config['rrd']['enable'])) {
2078

    
2079
		/* create directory if needed */
2080
		if (!is_dir("$rrddbpath")) {
2081
			mkdir("$rrddbpath", 0755);
2082
		}
2083

    
2084
		if ($g['booting']) {
2085
			if ($g['platform'] != "pfSense") {
2086
				/* restore the databases, if we have one */
2087
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
2088
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2089
					if((int)$rrdrestore <> 0) {
2090
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
2091
					}
2092
				}
2093
			}
2094
		}
2095

    
2096
		/* db update script */
2097
		$rrdupdatesh = "#!/bin/sh\n";
2098
		$rrdupdatesh .= "\n";
2099
		$rrdupdatesh .= "counter=1\n";
2100
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2101
		$rrdupdatesh .= "do\n";
2102
		$rrdupdatesh .= "";
2103

    
2104
		$i = 0;
2105
		$vfaces = array (
2106
			"vlan.?*"
2107
		);
2108
		$ifdescrs = get_interface_list(true, true, $vfaces);
2109
		foreach ($ifdescrs as $realif => $ifdescr) {
2110
			$ifname = $ifdescr['friendly'];
2111
			$state = $ifdescr['up'];
2112

    
2113
			/* skip interfaces that do not have a friendly name */
2114
			if ("$ifname" == "") {
2115
				continue;
2116
			}
2117

    
2118
			/* or are down */
2119
			if (!$state) {
2120
				continue;
2121
			}
2122

    
2123
			/* TRAFFIC, set up the rrd file */
2124
			if (!file_exists("$rrddbpath$ifname$traffic")) {
2125
				/* create rrd file if it does not exist */
2126
				log_error("Create RRD database $rrddbpath$ifname$traffic");
2127
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
2128
				$rrdcreate .= "DS:in:COUNTER:$trafficvalid:0:$downstream ";
2129
				$rrdcreate .= "DS:out:COUNTER:$trafficvalid:0:$upstream ";
2130
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2131
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2132
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2133
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2134
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2135
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2136
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2137
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
2138

    
2139
				$rrdcreateoutput = array();
2140
				$rrdcreatereturn = "";
2141

    
2142
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2143
				if ($rrdcreatereturn != 0) {
2144
					log_error("RRD create failed exited with $rrdcreatereturn, the
2145
							error is: $rrdcreateoutput[0]\n");
2146
				}
2147
			}
2148

    
2149
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2150
			if($g['booting']) {
2151
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
2152
			}
2153

    
2154
			$rrdupdatesh .= "\n";
2155
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
2156
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
2157
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7}'`:\\\n";
2158
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$10}'`\n\n";
2159

    
2160
			/* PACKETS, set up the rrd file */
2161
			if (!file_exists("$rrddbpath$ifname$packets")) {
2162
				/* create rrd file if it does not exist */
2163
				log_error("Create RRD database $rrddbpath$ifname$packets");
2164
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
2165
				$rrdcreate .= "DS:in:COUNTER:$packetsvalid:0:$downstream ";
2166
				$rrdcreate .= "DS:out:COUNTER:$packetsvalid:0:$upstream ";
2167
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2168
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2169
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2170
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2171
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2172
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2173
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2174
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
2175

    
2176
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2177
				if ($rrdcreatereturn != 0) {
2178
					log_error("RRD create failed exited with $rrdcreatereturn, the
2179
							error is: $rrdcreateoutput[0]\n");
2180
				}
2181
			}
2182

    
2183
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2184
			if($g['booting']) {
2185
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
2186
			}
2187

    
2188
			$rrdupdatesh .= "\n";
2189
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
2190
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
2191
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5}'`:\\\n";
2192
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$8}'`\n\n";
2193

    
2194
			/* if an alternative gateway is defined, use it */
2195
			if ($config['system']['interfaces'][$ifname]['use_rrd_gateway'] <> "") {
2196
				$gatewayip = get_interface_gateway($ifname);
2197
				$monitorip = $config['system']['interfaces'][$ifname]['use_rrd_gateway'];
2198
				mwexec("/sbin/route add -host {$monitorip} {$gatewayip} 1> /dev/null 2>&1");
2199
			} else {
2200
				$monitorip = get_interface_gateway($ifname);
2201
			}
2202
			$numpings = 5;
2203
			$btick = '`';
2204

    
2205
			if($monitorip <> "") {
2206
				/* QUALITY, create link quality database */
2207
				if (!file_exists("$rrddbpath$ifname$quality")) {
2208
					/* create rrd file if it does not exist */
2209
					log_error("Create RRD database $rrddbpath$ifname$quality");
2210
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
2211
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
2212
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
2213
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2214
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2215
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2216
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
2217

    
2218
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2219
					if ($rrdcreatereturn != 0) {
2220
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2221
					}
2222
				}
2223

    
2224
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2225
				if($g['booting']) {
2226
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
2227
				}
2228

    
2229
				/* the ping test function. We call this on the last line */
2230
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
2231
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
2232
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
2233
				$rrdupdatesh .= "	local out_{$ifname}\n";
2234
				$rrdupdatesh .= "	out_{$ifname}=$btick ping -c $numpings -q $monitorip $btick\n";
2235
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
2236
				$rrdupdatesh .= "		packetloss_{$ifname}=$btick echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1 $btick\n";
2237
				$rrdupdatesh .= "		roundtrip_{$ifname}=$btick echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/' $btick\n";
2238
				$rrdupdatesh .= "	fi\n";
2239
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
2240
				$rrdupdatesh .= "}\n\n";
2241

    
2242
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
2243
			}
2244

    
2245
			/* WAN interface only statistics */
2246
			if ("$ifname" == "wan") {
2247

    
2248
				/* QUEUES, set up the queues databases */
2249
				if (!is_array($config['shaper']['queue'])) {
2250
					$config['shaper']['queue'] = array ();
2251
				}
2252
				$a_queues = & $config['shaper']['queue'];
2253

    
2254
				if (isset ($config['shaper']['enable'])) {
2255
					if (!file_exists("$rrddbpath$ifname$queues")) {
2256
						/* create rrd file if it does not exist */
2257
						log_error("Create RRD database $rrddbpath$ifname$queues");
2258
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
2259
						/* loop list of shaper queues */
2260
						$q = 0;
2261
						foreach ($a_queues as $queue) {
2262
							$name = $queue['name'];
2263
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream ";
2264
						}
2265

    
2266
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2267
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2268
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2269
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
2270

    
2271
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2272
						if ($rrdcreatereturn != 0) {
2273
							log_error("RRD create failed exited with $rrdcreatereturn, the
2274
									error is: $rrdcreateoutput[0]\n");
2275
						}
2276
					}
2277

    
2278
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
2279
						/* create rrd file if it does not exist */
2280
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
2281
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
2282
						/* loop list of shaper queues */
2283
						$q = 0;
2284
						foreach ($a_queues as $queue) {
2285
							$name = $queue['name'];
2286
							$rrdcreate .= "DS:$name:COUNTER:$queuesdropvalid:0:$downstream ";
2287
						}
2288

    
2289
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2290
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2291
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2292
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
2293

    
2294
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2295
						if ($rrdcreatereturn != 0) {
2296
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2297
						}
2298
					}
2299

    
2300
					if($g['booting']) {
2301
						$rrdqcommand = "-t ";
2302
						$rrducommand = "N";
2303
						$q = 0;
2304
						foreach ($a_queues as $queue) {
2305
							if($q == 0) {
2306
								$rrdqcommand .= "{$queue['name']}";
2307
							} else {
2308
								$rrdqcommand .= ":{$queue['name']}";
2309
							}
2310
							$q++;
2311
							$rrducommand .= ":U";
2312
						}
2313
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
2314
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
2315
					}
2316

    
2317
					/* awk function to gather shaper data */
2318
					/* yes, it's special */
2319
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
2320
					$rrdupdatesh .= "{ ";
2321
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
2322
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
2323
					$rrdupdatesh .= "q=1; ";
2324
					$rrdupdatesh .= "} ";
2325
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
2326
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
2327
					$rrdupdatesh .= "q=0; ";
2328
					$rrdupdatesh .= "} ";
2329
					$rrdupdatesh .= "} END { ";
2330
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
2331
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
2332
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
2333
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
2334

    
2335
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
2336
					$rrdupdatesh .= "{ ";
2337
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
2338
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
2339
					$rrdupdatesh .= "q=1; ";
2340
					$rrdupdatesh .= "} ";
2341
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
2342
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
2343
					$rrdupdatesh .= "q=0; ";
2344
					$rrdupdatesh .= "} ";
2345
					$rrdupdatesh .= "} END { ";
2346
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
2347
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
2348
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
2349
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
2350
				}
2351
			}
2352
		}
2353
		$i++;
2354

    
2355
		/* System only statistics */
2356
		$ifname = "system";
2357

    
2358
			/* STATES, create pf states database */
2359
			if(! file_exists("$rrddbpath$ifname$states")) {
2360
				/* create rrd file if it does not exist */
2361
				log_error("Create RRD database $rrddbpath$ifname$states");
2362
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
2363
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
2364
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
2365
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
2366
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
2367
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
2368
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
2369
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
2370
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
2371
				$rrdcreate .= "RRA:MIN:0.5:360:1000 ";
2372
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2373
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2374
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2375
				$rrdcreate .= "RRA:AVERAGE:0.5:360:1000 ";
2376
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2377
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2378
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2379
				$rrdcreate .= "RRA:MAX:0.5:360:1000";
2380

    
2381
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2382
				if($rrdcreatereturn != 0) {
2383
			                log_error("RRD create failed exited with $rrdcreatereturn, the
2384
						error is: $rrdcreateoutput[0]\n");
2385
				}
2386
			}
2387

    
2388
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2389
			if($g['booting']) {
2390
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
2391
			}
2392

    
2393
 			/* the pf states gathering function. */
2394
 			$rrdupdatesh .= "\n";
2395
 			$rrdupdatesh .= "pfrate=\"` $pfctl -si | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
2396
 			$rrdupdatesh .= "pfstates=\"` $pfctl -ss | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
2397
			$rrdupdatesh .= "pfnat=\"` $pfctl -ss | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
2398
 			$rrdupdatesh .= "srcip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '\\->' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
2399
 			$rrdupdatesh .= "dstip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '<\\-' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
2400
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
2401

    
2402
			/* End pf states statistics */
2403

    
2404
			/* CPU, create CPU statistics database */
2405
			if(! file_exists("$rrddbpath$ifname$proc")) {
2406
				/* create rrd file if it does not exist */
2407
				log_error("Create RRD database $rrddbpath$ifname$proc");
2408
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
2409
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
2410
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
2411
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
2412
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
2413
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
2414
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
2415
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
2416
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
2417
				$rrdcreate .= "RRA:MIN:0.5:360:1000 ";
2418
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2419
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2420
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2421
				$rrdcreate .= "RRA:AVERAGE:0.5:360:1000 ";
2422
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2423
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2424
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2425
				$rrdcreate .= "RRA:MAX:0.5:360:1000";
2426

    
2427
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2428
				if($rrdcreatereturn != 0) {
2429
			                log_error("RRD create failed exited with $rrdcreatereturn, the
2430
						error is: $rrdcreateoutput[0]\n");
2431
				}
2432
			}
2433

    
2434
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2435
			if($g['booting']) {
2436
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
2437
			}
2438

    
2439
 			/* the CPU stats gathering function. */
2440
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { ";
2441
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } ";
2442
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { ";
2443
			$rrdupdatesh .= "processes = \$1; ";
2444
			$rrdupdatesh .= "} ";
2445
			$rrdupdatesh .= "else if ( \$1 == \"CPU\" ) { ";
2446
			$rrdupdatesh .= "user = \$3; ";
2447
			$rrdupdatesh .= "nice = \$5; ";
2448
			$rrdupdatesh .= "sys = \$7; ";
2449
			$rrdupdatesh .= "interrupt = \$9; ";
2450
			$rrdupdatesh .= "} ";
2451
			$rrdupdatesh .= "} END { ";
2452
			$rrdupdatesh .= "printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes ";
2453
			$rrdupdatesh .= "}'`\n\n";
2454

    
2455
			/* End CPU statistics */
2456

    
2457
			/* SPAMD, set up the spamd rrd file */
2458
			if (isset($config['installedpackages']['spamdsettings']) &&
2459
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
2460
				/* set up the spamd rrd file */
2461
				if (!file_exists("$rrddbpath$ifname$spamd")) {
2462
						/* create rrd file if it does not exist */
2463
						log_error("Create RRD database $rrddbpath$ifname$spamd");
2464
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
2465
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
2466
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
2467
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
2468
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
2469
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
2470
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
2471
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2472
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2473
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2474
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2475
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2476
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2477
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2478
						$rrdcreate .= "RRA:MAX:0.5:720:1000";
2479

    
2480
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2481
					if ($rrdcreatereturn != 0) {
2482
						log_error("RRD create failed exited with $rrdcreatereturn, the
2483
							error is: $rrdcreateoutput[0]\n");
2484
					}
2485
				}
2486

    
2487
				$rrdupdatesh .= "\n";
2488
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
2489
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
2490
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
2491

    
2492
			}
2493
		/* End System statistics */
2494

    
2495
		$rrdupdatesh .= "sleep 60\n";
2496
		$rrdupdatesh .= "done\n";
2497
		log_error("Creating rrd update script");
2498
		/* write the rrd update script */
2499
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
2500
		$fd = fopen("$updaterrdscript", "w");
2501
		fwrite($fd, "$rrdupdatesh");
2502
		fclose($fd);
2503

    
2504
		/* kill off traffic collectors */
2505
		kill_traffic_collector();
2506

    
2507
		/* start traffic collector */
2508
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
2509

    
2510
	} else {
2511
		/* kill off traffic collectors */
2512
		kill_traffic_collector();
2513
	}
2514
}
2515
function kill_traffic_collector() {
2516
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
2517
}
2518

    
2519
function update_filter_reload_status($text) {
2520
	global $g;
2521
	config_lock();
2522
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
2523
	fwrite($fd, $text);
2524
	fclose($fd);
2525
	config_unlock();
2526
}
2527

    
2528
function get_interface_gateway($interface) {
2529
	global $config, $g;
2530
	$interface = strtolower($interface);
2531
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
2532
	 *  grab the address from the configuration file.
2533
	 */
2534
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
2535
	if($tmpif <> $interface)
2536
		$interface = $tmpif;
2537
	$realif = $config['interfaces'][$interface]['if'];
2538
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
2539
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
2540
		$gw = rtrim($gw);
2541
	} else {
2542
		$gw = $config['interfaces'][$interface]['gateway'];
2543
	}
2544
	/* if wan is requested, return it */
2545
	if($interface == "wan")
2546
		return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
2547
	/* return gateway */
2548
	return $gw;
2549
}
2550

    
2551
function is_dhcp_server_enabled() {
2552
	/* DHCP enabled on any interfaces? */
2553
	global $config, $g;
2554
	$dhcpdcfg = $config['dhcpd'];
2555
	$dhcpdenable = false;
2556
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
2557
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2558
			$dhcpdenable = true;
2559
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2560
			$dhcpdenable = true;
2561
	}
2562
	return $dhcpdenable;
2563
}
2564

    
2565
?>
(14-14/27)