Project

General

Profile

Download (62.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/pfsense-utils
3
 * NAME
4
 *   pfsense-utils.inc - Utilities specific to pfSense
5
 * DESCRIPTION
6
 *   This include contains various pfSense specific functions.
7
 * HISTORY
8
 *   $Id$
9
 ******
10
 *
11
 * Copyright (C) 2004-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/reset_carp
41
 * NAME
42
 *   reset_carp - resets carp after primary interface changes
43
 * INPUTS
44
 *   null
45
 * RESULT
46
 *   null
47
 ******/
48
function reset_carp() {
49
	$carp_counter=find_number_of_created_carp_interfaces();
50
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
51
	for($x=0; $x<$carp_counter; $x++) {
52
		mwexec("/sbin/ifconfig carp{$x} down");
53
		mwexec("/sbin/ifconfig carp{$x} destroy");
54
	}
55
	sleep(1);
56
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
57
	interfaces_carp_configure();
58
	interfaces_carp_bring_up_final();
59
}
60

    
61
/****f* pfsense-utils/get_dns_servers
62
 * NAME
63
 *   get_dns_servres - get system dns servers
64
 * INPUTS
65
 *   $dns_servers - an array of the dns servers
66
 * RESULT
67
 *   null
68
 ******/
69
function get_dns_servers() {
70
	$dns_servers = array();
71
	$dns = `cat /etc/resolv.conf`;
72
	$dns_s = split("\n", $dns);
73
	foreach($dns_s as $dns) {
74
		$matches = "";
75
		if (preg_match("/nameserver (.*)/", $dns, $matches))
76
			$dns_servers[] = $matches[1];		
77
	}
78
	$dns_server_master = array();
79
	sort($dns_servers);
80
	$lastseen = "";
81
	foreach($dns_servers as $t) {
82
		if($t <> $lastseen)
83
			if($t <> "")
84
				$dns_server_master[] = $t;
85
		$lastseen = $t;
86
	}
87
	return $dns_server_master;
88
}
89
 	
90
/****f* pfsense-utils/log_error
91
* NAME
92
*   log_error  - Sends a string to syslog.
93
* INPUTS
94
*   $error     - string containing the syslog message.
95
* RESULT
96
*   null
97
******/
98
function log_error($error) {
99
	$page = $_SERVER['SCRIPT_NAME'];
100
	syslog(LOG_WARNING, "$page: $error");
101
	return;
102
}
103

    
104
/****f* pfsense-utils/get_interface_mac_address
105
 * NAME
106
 *   get_interface_mac_address - Return a interfaces mac address
107
 * INPUTS
108
 *   $interface	- interface to obtain mac address from
109
 * RESULT
110
 *   $mac - the mac address of the interface
111
 ******/
112
function get_interface_mac_address($interface) {
113
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
114
	return trim($mac);
115
}
116

    
117
/****f* pfsense-utils/return_dir_as_array
118
 * NAME
119
 *   return_dir_as_array - Return a directory's contents as an array.
120
 * INPUTS
121
 *   $dir	- string containing the path to the desired directory.
122
 * RESULT
123
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
124
 ******/
125
function return_dir_as_array($dir) {
126
	$dir_array = array();
127
	if (is_dir($dir)) {
128
		if ($dh = opendir($dir)) {
129
			while (($file = readdir($dh)) !== false) {
130
				$canadd = 0;
131
				if($file == ".") $canadd = 1;
132
				if($file == "..") $canadd = 1;
133
				if($canadd == 0)
134
					array_push($dir_array, $file);
135
			}
136
			closedir($dh);
137
		}
138
	}
139
	return $dir_array;
140
}
141

    
142
/****f* pfsense-utils/enable_hardware_offloading
143
 * NAME
144
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
145
 * INPUTS
146
 *   $interface	- string containing the physical interface to work on.
147
 * RESULT
148
 *   null
149
 * NOTES
150
 *   This function only supports the fxp driver's loadable microcode.
151
 ******/
152
function enable_hardware_offloading($interface) {
153
	global $g, $config;
154

    
155
	if(stristr($interface,"lnc"))
156
		return;
157
	if(isset($config['system']['do_not_use_nic_microcode']))
158
		return;
159

    
160
	if($g['booting']) {
161
	/* translate wan, lan, opt -> real interface if needed */
162
	$int = filter_translate_type_to_real_interface($interface);
163
	if($int <> "") $interface = $int;
164
	$int_family = preg_split("/[0-9]+/", $int);
165
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
166
	$supported_ints = array('fxp');
167
	if (in_array($int_family, $supported_ints))
168
		mwexec("/sbin/ifconfig {$interface} link0");
169

    
170
	if(stristr($options, "txcsum") == true)
171
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
172
	if(stristr($options, "rxcsum") == true)    
173
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");    
174
	if(stristr($options, "polling") == true)
175
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
176
	} else {
177
		mwexec("sysctl kern.polling.enable=0");
178
	}
179
	return;
180
}
181

    
182
/****f* pfsense-utils/is_alias_inuse
183
 * NAME
184
 *   checks to see if an alias is currently in use by a rule
185
 * INPUTS
186
 *   
187
 * RESULT
188
 *   true or false
189
 * NOTES
190
 *   
191
 ******/
192
function is_alias_inuse($alias) {
193
	global $g, $config;
194

    
195
	if($alias == "") return false;
196
	/* loop through firewall rules looking for alias in use */
197
	if(is_array($config['nat']['rule']))
198
		foreach($config['filter']['rule'] as $rule) {
199
			if(is_array($rule['source']['address']))
200
				if($rule['source']['address'] == $alias)
201
					return true;
202
			if(is_array($rule['destination']['address']))
203
				if($rule['destination']['address'] == $alias)
204
					return true;
205
		}
206
	/* loop through nat rules looking for alias in use */
207
	if(is_array($config['nat']['rule']))
208
		foreach($config['nat']['rule'] as $rule) {
209
			if($rule['target'] == $alias)
210
				return true;
211
			if($rule['external-address'] == $alias)
212
				return true;	
213
		}
214
	return false;
215
}
216

    
217
/****f* pfsense-utils/setup_polling_defaults
218
 * NAME
219
 *   sets up sysctls for pollingS
220
 * INPUTS
221
 *   
222
 * RESULT
223
 *   null
224
 * NOTES
225
 *   
226
 ******/
227
function setup_polling_defaults() {
228
	global $g, $config;
229
	if($config['system']['polling_each_burst'])
230
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
231
	if($config['system']['polling_burst_max'])
232
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
233
	if($config['system']['polling_user_frac'])
234
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");		
235
}
236

    
237
/****f* pfsense-utils/setup_polling
238
 * NAME
239
 *   sets up polling
240
 * INPUTS
241
 *   
242
 * RESULT
243
 *   null
244
 * NOTES
245
 *   
246
 ******/
247
function setup_polling() {
248
	global $g, $config;		
249

    
250
	setup_polling_defaults();
251
	
252
	if(isset($config['system']['polling']))
253
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
254
	else
255
		$supported_ints = array();
256

    
257
	/* build an array of interfaces to work with */
258
	$iflist = array("lan" => "LAN", "wan" => "WAN");
259
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
260
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];			
261

    
262
	foreach ($iflist as $ifent => $ifname) {
263
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
264
		$supported = false;
265
		foreach($supported_ints as $supported) {
266
			if(stristr($real_interface, $supported)) {
267
				$supported = true;
268
			} 
269
		}
270
		if ($supported == true) {
271
			mwexec("/sbin/ifconfig {$real_interface} polling");
272
		} else {
273
			mwexec("/sbin/ifconfig {$real_interface} -polling");
274
		}
275
	}
276
}
277

    
278
/****f* pfsense-utils/setup_microcode
279
 * NAME
280
 *   enumerates all interfaces and calls enable_hardware_offloading which
281
 *   enables a NIC's supported hardware features.
282
 * INPUTS
283
 *   
284
 * RESULT
285
 *   null
286
 * NOTES
287
 *   This function only supports the fxp driver's loadable microcode.
288
 ******/
289
function setup_microcode() {
290
	global $config;
291

    
292
	$ifdescrs = array('wan', 'lan');
293
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
294
		$ifdescrs['opt' . $j] = "opt" . $j;
295
	}
296
	foreach($ifdescrs as $if)
297
		enable_hardware_offloading($if);
298
}
299

    
300
/****f* pfsense-utils/return_filename_as_array
301
 * NAME
302
 *   return_filename_as_array - Return a file's contents as an array.
303
 * INPUTS
304
 *   $filename	- string containing the path to the desired file.
305
 *   $strip	- array of characters to strip - default is '#'.
306
 * RESULT
307
 *   $file	- array containing the file's contents.
308
 * NOTES
309
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
310
 ******/
311
function return_filename_as_array($filename, $strip = array('#')) {
312
	if(file_exists($filename)) $file = file($filename);
313
	if(is_array($file)) {
314
		foreach($file as $line) $line = trim($line);
315
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
316
	}
317
	return $file;
318
}
319

    
320
/****f* pfsense-utils/file_put_contents
321
 * NAME
322
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
323
 * RESULT
324
 *   none
325
 ******/
326
if(!function_exists("file_put_contents")) {
327
	function file_put_contents($filename, $data) {
328
		$fd = fopen($filename,"w");
329
		fwrite($fd, $data);
330
		fclose($fd);
331
	}
332
}
333

    
334
/****f* pfsense-utils/get_carp_status
335
 * NAME
336
 *   get_carp_status - Return whether CARP is enabled or disabled.
337
 * RESULT
338
 *   boolean	- true if CARP is enabled, false if otherwise.
339
 ******/
340
function get_carp_status() {
341
    /* grab the current status of carp */
342
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
343
    if(intval($status) == "0") return false;
344
    return true;
345
}
346

    
347
/****f* pfsense-utils/is_carp_defined
348
 * NAME
349
 *   is_carp_defined - Return whether CARP is detected in the kernel.
350
 * RESULT
351
 *   boolean	- true if CARP is detected, false otherwise.
352
 ******/
353
function is_carp_defined() {
354
	/* is carp compiled into the kernel and userland? */
355
	$command = "/sbin/sysctl -a | grep carp";
356
	$fd = popen($command . " 2>&1 ", "r");
357
	if(!$fd) {
358
		log_error("Warning, could not execute command {$command}");
359
		return 0;
360
	}
361
	while(!feof($fd)) {
362
		$tmp .= fread($fd,49);
363
	}
364
	fclose($fd);
365

    
366
	if($tmp == "")
367
		return false;
368
	else
369
		return true;
370
}
371

    
372
/****f* pfsense-utils/get_interface_mtu
373
 * NAME
374
 *   get_interface_mtu - Return the mtu of an interface
375
 * RESULT
376
 *   $tmp	- Returns the mtu of an interface
377
 ******/
378
function get_interface_mtu($interface) {
379
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f4`;
380
	return $mtu;
381
}
382

    
383
/****f* pfsense-utils/is_interface_wireless
384
 * NAME
385
 *   is_interface_wireless - Returns if an interface is wireless
386
 * RESULT
387
 *   $tmp	- Returns if an interface is wireless
388
 ******/
389
function is_interface_wireless($interface) {
390
	global $config, $g;
391
	$interface = convert_real_interface_to_friendly_interface_name($interface);
392
	if(isset($config['interfaces'][$interface]['wireless']))
393
		return true;
394
	else
395
		return false;
396
}
397

    
398
/****f* pfsense-utils/find_number_of_created_carp_interfaces
399
 * NAME
400
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
401
 * RESULT
402
 *   $tmp	- Number of currently created CARP interfaces.
403
 ******/
404
function find_number_of_created_carp_interfaces() {
405
	$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
406
	$fd = popen($command . " 2>&1 ", "r");
407
	if(!$fd) {
408
		log_error("Warning, could not execute command {$command}");
409
		return 0;
410
	}
411
	while(!feof($fd)) {
412
		$tmp .= fread($fd,49);
413
	}
414
	fclose($fd);
415
	$tmp = intval($tmp);
416
	return $tmp;
417
}
418

    
419
/****f* pfsense-utils/link_int_to_bridge_interface
420
 * NAME
421
 *   link_int_to_bridge_interface - Finds out a bridge group for an interface
422
 * INPUTS
423
 *   $ip
424
 * RESULT
425
 *   bridge[0-99]
426
 ******/
427
function link_int_to_bridge_interface($int) {
428
	global $config, $g;
429
	$real_int = convert_friendly_interface_to_real_interface_name($int);
430
	$num_bridges = find_number_of_created_bridges();
431
	for($x=0; $x<$num_bridges; $x++) {
432
		$matches = "";
433
		$bridge_info = `/sbin/ifconfig bridge{$x}`;
434
		if(stristr($bridge_info, "member: {$real_int}")) {
435
			return "bridge{$x}";
436
		}
437
	}	
438
}
439

    
440
/****f* pfsense-utils/link_ip_to_carp_interface
441
 * NAME
442
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
443
 * INPUTS
444
 *   $ip
445
 * RESULT
446
 *   $carp_ints
447
 ******/
448
function link_ip_to_carp_interface($ip) {
449
	global $config;
450
	if($ip == "") return;
451

    
452
	$ifdescrs = array('wan', 'lan');
453
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
454
		$ifdescrs['opt' . $j] = "opt" . $j;
455
	}
456

    
457
	$ft = split("\.", $ip);
458
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
459

    
460
	$carp_ints = "";
461
	$num_carp_ints = find_number_of_created_carp_interfaces();
462
	foreach ($ifdescrs as $ifdescr => $ifname) {
463
		for($x=0; $x<$num_carp_ints; $x++) {
464
			$carp_int = "carp{$x}";
465
			$carp_ip = find_interface_ip($carp_int);
466
			$carp_ft = split("\.", $carp_ip);
467
			$carp_ft_ip = $carp_ft[0] . "." . $carp_ft[1] . "." . $carp_ft[2] . ".";
468
			$result = does_interface_exist($carp_int);
469
			if($result <> true) break;
470
			if($ft_ip == $carp_ft_ip)
471
			if(stristr($carp_ints,$carp_int) == false)
472
			$carp_ints .= " " . $carp_int;
473
		}
474
	}
475
	return $carp_ints;
476
}
477

    
478
/****f* pfsense-utils/exec_command
479
 * NAME
480
 *   exec_command - Execute a command and return a string of the result.
481
 * INPUTS
482
 *   $command	- String of the command to be executed.
483
 * RESULT
484
 *   String containing the command's result.
485
 * NOTES
486
 *   This function returns the command's stdout and stderr.
487
 ******/
488
function exec_command($command) {
489
	$output = array();
490
	exec($command . ' 2>&1 ', $output);
491
	return(implode("\n", $output));
492
}
493

    
494
/****f* interfaces/is_jumbo_capable
495
 * NAME
496
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
497
 * INPUTS
498
 *   $int             - string containing interface name
499
 * RESULT
500
 *   boolean          - true or false
501
 ******/
502
function is_jumbo_capable($int) {
503
	/* Per:
504
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
505
	 * Only the following drivers support large frames
506
         * 
507
	 * 'de' chipset purposely left out of this list
508
	 * requires defining BIG_PACKET in the
509
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
510
	 * kernel or module.  The hack works only for the 21041,
511
	 * 21140, and 21140A chips.
512
	 */
513
	global $g;
514
	
515
	$capable = $g['vlan_long_frame'];
516
	
517
	$int_family = preg_split("/[0-9]+/", $int);
518

    
519
	if (in_array($int_family[0], $capable))
520
		return true;
521
	else
522
		return false;
523
}
524

    
525
/*
526
 * does_interface_exist($interface): return true or false if a interface is detected.
527
 */
528
function does_interface_exist($interface) {
529
	$ints = exec_command("/sbin/ifconfig -l");
530
	if(stristr($ints, $interface) !== false)
531
		return true;
532
	else
533
		return false;
534
}
535

    
536
/*
537
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
538
 */
539
function convert_ip_to_network_format($ip, $subnet) {
540
	$ipsplit = split('[.]', $ip);
541
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
542
	return $string;
543
}
544

    
545
/*
546
 * find_interface_ip($interface): return the interface ip (first found)
547
 */
548
function find_interface_ip($interface) {
549
	$interface = str_replace("\n", "", $interface);
550
	if(does_interface_exist($interface) == false) return;
551
	$ip = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2");
552
	$ip = str_replace("\n","",$ip);
553
	return $ip;
554
}
555

    
556
function guess_interface_from_ip($ipaddress) {
557
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2
558
; };'");
559
	return $ret;
560
}
561

    
562
function filter_opt_interface_to_real($opt) {
563
	global $config;
564
	return $config['interfaces'][$opt]['if'];
565
}
566

    
567
function filter_get_opt_interface_descr($opt) {
568
	global $config;
569
	return $config['interfaces'][$opt]['descr'];
570
}
571

    
572
function get_friendly_interface_list_as_array() {
573
	global $config;
574
	$ints = array();
575
	$ifdescrs = array('wan', 'lan');
576
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
577
		$ifdescrs['opt' . $j] = "opt" . $j;
578
	}
579
	$ifdescrs = get_interface_list();
580
	foreach ($ifdescrs as $ifdescr => $ifname) {
581
		array_push($ints,$ifdescr);
582
	}
583
	return $ints;
584
}
585

    
586
/*
587
 * find_ip_interface($ip): return the interface where an ip is defined
588
 */
589
function find_ip_interface($ip) {
590
	global $config;
591
	$ifdescrs = array('wan', 'lan');
592
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
593
		$ifdescrs['opt' . $j] = "opt" . $j;
594
	}
595
	foreach ($ifdescrs as $ifdescr => $ifname) {
596
		$int = filter_translate_type_to_real_interface($ifname);
597
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
598
	if(stristr($ifconfig,$ip) <> false)
599
		return $int;
600
	}
601
	return false;
602
}
603

    
604
/*
605
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
606
 *                                                       for a friendly interface.  ie: wan
607
 */
608
function filter_translate_type_to_real_interface($interface) {
609
	global $config;
610
	if($config['interfaces'][$interface]['if'] <> "") {
611
		return $config['interfaces'][$interface]['if'];
612
	} else {
613
		return $interface;
614
	}
615
}
616

    
617
/*
618
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
619
 */
620
function get_carp_interface_status($carpinterface) {
621
	/* basically cache the contents of ifconfig statement
622
	to speed up this routine */
623
	global $carp_query;
624
	if($carp_query == "")
625
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
626
	$found_interface = 0;
627
	foreach($carp_query as $int) {
628
		if($found_interface == 1) {
629
			if(stristr($int, "MASTER")) return "MASTER";
630
			if(stristr($int, "BACKUP")) return "BACKUP";
631
			if(stristr($int, "INIT")) return "INIT";
632
			return false;
633
		}
634
		if(stristr($int, $carpinterface) == true)
635
		$found_interface=1;
636
	}
637
	return;
638
}
639

    
640
/*
641
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
642
 */
643
function get_pfsync_interface_status($pfsyncinterface) {
644
    $result = does_interface_exist($pfsyncinterface);
645
    if($result <> true) return;
646
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
647
    return $status;
648
}
649

    
650
/*
651
 * find_carp_interface($ip): return the carp interface where an ip is defined
652
 */
653
function find_carp_interface($ip) {
654
	global $find_carp_ifconfig;
655
	if($find_carp_ifconfig == "") {
656
		$find_carp_ifconfig = array();
657
		$num_carp_ints = find_number_of_created_carp_interfaces();
658
		for($x=0; $x<$num_carp_ints; $x++) {
659
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
660
		}
661
	}
662
	$carps = 0;
663
	foreach($find_carp_ifconfig as $fci) {
664
		if(stristr($fci, $ip) == true)
665
			return "carp{$carps}";
666
		$carps++;
667
	}
668
}
669

    
670
/*
671
 * setup_filter_bridge(): toggle filtering bridge
672
 */
673
function setup_filter_bridge() {
674
	global $config, $g;
675
	if(isset($config['bridge']['filteringbridge'])) {
676
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
677
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
678
	} else {		
679
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
680
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
681
	}
682
}
683

    
684
/*
685
 * find_number_of_created_bridges(): returns the number of currently created bridges
686
 */
687
function find_number_of_created_bridges() {
688
	return `/sbin/ifconfig | grep "bridge[0-999]" | wc -l`;
689
}
690

    
691
/*
692
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
693
 */
694
function add_rule_to_anchor($anchor, $rule, $label) {
695
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
696
}
697

    
698
/*
699
 * remove_text_from_file
700
 * remove $text from file $file
701
 */
702
function remove_text_from_file($file, $text) {
703
	global $fd_log;
704
	fwrite($fd_log, "Adding needed text items:\n");
705
	$filecontents = exec_command_and_return_text("cat " . $file);
706
	$textTMP = str_replace($text, "", $filecontents);
707
	$text .= $textTMP;
708
	fwrite($fd_log, $text . "\n");
709
	$fd = fopen($file, "w");
710
	fwrite($fd, $text);
711
	fclose($fd);
712
}
713

    
714
/*
715
 * add_text_to_file($file, $text): adds $text to $file.
716
 * replaces the text if it already exists.
717
 */
718
function add_text_to_file($file, $text) {
719
	if(file_exists($file) and is_writable($file)) {
720
		$filecontents = file($file);
721
		$filecontents[] = $text;
722
		$tmpfile = get_tmp_file();
723
		$fout = fopen($tmpfile, "w");
724
		foreach($filecontents as $line) {
725
			fwrite($fout, rtrim($line) . "\n");
726
		}
727
		fclose($fout);
728
		rename($tmpfile, $file);
729
		return true;
730
	} else {
731
		return false;
732
	}
733
}
734

    
735
/*
736
 *   after_sync_bump_adv_skew(): create skew values by 1S
737
 */
738
function after_sync_bump_adv_skew() {
739
	global $config, $g;
740
	$processed_skew = 1;
741
	$a_vip = &$config['virtualip']['vip'];
742
	foreach ($a_vip as $vipent) {
743
		if($vipent['advskew'] <> "") {
744
			$processed_skew = 1;
745
			$vipent['advskew'] = $vipent['advskew']+1;
746
		}
747
	}
748
	if($processed_skew == 1)
749
		write_config("After synch increase advertising skew");
750
}
751

    
752
/*
753
 * get_filename_from_url($url): converts a url to its filename.
754
 */
755
function get_filename_from_url($url) {
756
	return basename($url);
757
}
758

    
759
/*
760
 *   update_output_window: update bottom textarea dynamically.
761
 */
762
function update_output_window($text) {
763
	$log = ereg_replace("\n", "\\n", $text);
764
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
765
	/* ensure that contents are written out */
766
	ob_flush();
767
}
768

    
769
/*
770
 *   get_dir: return an array of $dir
771
 */
772
function get_dir($dir) {
773
	$dir_array = array();
774
	$d = dir($dir);
775
	while (false !== ($entry = $d->read())) {
776
		array_push($dir_array, $entry);
777
	}
778
	$d->close();
779
	return $dir_array;
780
}
781

    
782
/*
783
 *   update_output_window: update top textarea dynamically.
784
 */
785
function update_status($status) {
786
	echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
787
	/* ensure that contents are written out */
788
	ob_flush();
789
}
790

    
791
/*
792
 *   exec_command_and_return_text_array: execute command and return output
793
 */
794
function exec_command_and_return_text_array($command) {
795
	$fd = popen($command . " 2>&1 ", "r");
796
	while(!feof($fd)) {
797
		$tmp .= fread($fd,49);
798
	}
799
	fclose($fd);
800
	$temp_array = split("\n", $tmp);
801
	return $temp_array;
802
}
803

    
804
/*
805
 *   exec_command_and_return_text: execute command and return output
806
 */
807
function exec_command_and_return_text($command) {
808
	return exec_command($command);
809
}
810

    
811
/*
812
 *   exec_command_and_return_text: execute command and update output window dynamically
813
 */
814
function execute_command_return_output($command) {
815
	global $fd_log;
816
	$fd = popen($command . " 2>&1 ", "r");
817
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
818
	$counter = 0;
819
	$counter2 = 0;
820
	while(!feof($fd)) {
821
		$tmp = fread($fd, 50);
822
		$tmp1 = ereg_replace("\n","\\n", $tmp);
823
		$text = ereg_replace("\"","'", $tmp1);
824
		$lasttext = "";
825
		if($lasttext == "..") {
826
			$text = "";
827
			$lasttext = "";
828
			$counter=$counter-2;
829
		} else {
830
			$lasttext .= $text;
831
		}
832
		if($counter > 51) {
833
			$counter = 0;
834
			$extrabreak = "\\n";
835
		} else {
836
	    $extrabreak = "";
837
	    $counter++;
838
		}
839
		if($counter2 > 600) {
840
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
841
			$counter2 = 0;
842
		} else
843
			$counter2++;
844
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
845
	}
846
	fclose($fd);
847
}
848

    
849
/*
850
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
851
 */
852
function convert_friendly_interface_to_real_interface_name($interface) {
853
	global $config;
854
	$lc_interface = strtolower($interface);
855
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
856
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
857
	$ifdescrs = array();
858
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
859
		$ifdescrs['opt' . $j] = "opt" . $j;
860
	foreach ($ifdescrs as $ifdescr => $ifname) {
861
		if(strtolower($ifname) == $lc_interface)
862
	    return $config['interfaces'][$ifname]['if'];
863
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
864
			return $config['interfaces'][$ifname]['if'];
865
   }
866
   return $interface;
867
}
868

    
869
/*
870
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
871
 */
872
function convert_real_interface_to_friendly_interface_name($interface) {
873
	global $config;
874
	$ifdescrs = array('wan', 'lan');
875
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
876
		$ifdescrs['opt' . $j] = "opt" . $j;
877
	foreach ($ifdescrs as $ifdescr => $ifname) {
878
		$int = filter_translate_type_to_real_interface($ifname);
879
		if($ifname == $interface) return $ifname;
880
		if($int == $interface) return $ifname;
881
	}
882
	return $interface;
883
}
884

    
885
/*
886
 * update_progress_bar($percent): updates the javascript driven progress bar.
887
 */
888
function update_progress_bar($percent) {
889
	if($percent > 100) $percent = 1;
890
	echo "\n<script type=\"text/javascript\" language=\"javascript\">";
891
	echo "\ndocument.progressbar.style.width='" . $percent . "%';";
892
	echo "\n</script>";
893
}
894

    
895
/****f* pfsense-utils/WakeOnLan
896
 * NAME
897
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
898
 * RESULT
899
 *   true/false - true if the operation was successful
900
 ******/
901
function WakeOnLan($addr, $mac)
902
{
903
	$addr_byte = explode(':', $mac);
904
	$hw_addr = '';
905
	
906
	for ($a=0; $a < 6; $a++)
907
		$hw_addr .= chr(hexdec($addr_byte[$a]));
908
	
909
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
910
	
911
	for ($a = 1; $a <= 16; $a++)
912
		$msg .= $hw_addr;
913
	
914
	// send it to the broadcast address using UDP
915
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
916
	if ($s == false) {
917
		log_error("Error creating socket!");
918
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
919
	} else {
920
		// setting a broadcast option to socket:
921
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
922
		if($opt_ret < 0)
923
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
924
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
925
		socket_close($s);
926
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
927
		return true;
928
	}
929
	
930
	return false;
931
}
932

    
933
/*
934
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
935
 *                             is queuename|qlength|measured_packets
936
 *                             NOTE: this command takes 5 seconds to run
937
 */
938
function gather_altq_queue_stats($dont_return_root_queues) {
939
	mwexec("/usr/bin/killall -9 pfctl");
940
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
941
	$stats_array = split("\n", $stats);
942
	$queue_stats = array();
943
	foreach ($stats_array as $stats_line) {
944
		$match_array = "";
945
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
946
			$queue_name = $match_array[1][0];
947
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
948
			$speed = $match_array[1][0];
949
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
950
			$borrows = $match_array[1][0];
951
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
952
			$suspends = $match_array[1][0];
953
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
954
			$drops = $match_array[1][0];
955
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
956
			$measured = $match_array[1][0];
957
			if($dont_return_root_queues == true)
958
				if(stristr($queue_name,"root_") == false)
959
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
960
		}
961
	}
962
	return $queue_stats;
963
}
964

    
965
/*
966
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
967
 *					 Useful for finding paths and stripping file extensions.
968
 */
969
function reverse_strrchr($haystack, $needle) {
970
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
971
}
972

    
973
/*
974
 *  backup_config_section($section): returns as an xml file string of
975
 *                                   the configuration section
976
 */
977
function backup_config_section($section) {
978
	global $config;
979
	$new_section = &$config[$section];
980
	/* generate configuration XML */
981
	$xmlconfig = dump_xml_config($new_section, $section);
982
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
983
	return $xmlconfig;
984
}
985

    
986
/*
987
 *  backup_vip_config_section($section): returns as an xml file string of
988
 *                                   the configuration section
989
 */
990
function backup_vip_config_section() {
991
	global $config;
992
	$new_section = &$config['virtualip'];
993
	foreach($new_section['vip'] as $section) {
994
		if($section['mode'] == "proxyarp") {
995
			unset($section);		
996
		}
997
		if($section['advskew'] <> "") {
998
			$section_val = intval($section['advskew']);
999
			$section_val=$section_val+100;
1000
			if($section_val > 255)
1001
				$section_val = 255;
1002
			$section['advskew'] = $section_val;
1003
		}
1004
		$temp['vip'][] = $section;
1005
   }
1006
   return $temp;
1007
}
1008

    
1009
/*
1010
 *  restore_config_section($section, new_contents): restore a configuration section,
1011
 *                                                  and write the configuration out
1012
 *                                                  to disk/cf.
1013
 */
1014
function restore_config_section($section, $new_contents) {
1015
	global $config, $g;
1016
	conf_mount_rw();
1017
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
1018
	fwrite($fout, $new_contents);
1019
	fclose($fout);
1020
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
1021
	$config[$section] = &$section_xml;
1022
	unlink($g['tmp_path'] . "/tmpxml");
1023
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1024
	conf_mount_ro();
1025
	return;
1026
}
1027

    
1028
/*
1029
 * http_post($server, $port, $url, $vars): does an http post to a web server
1030
 *                                         posting the vars array.
1031
 * written by nf@bigpond.net.au
1032
 */
1033
function http_post($server, $port, $url, $vars) {
1034
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
1035
	$urlencoded = "";
1036
	while (list($key,$value) = each($vars))
1037
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
1038
	$urlencoded = substr($urlencoded,0,-1);
1039
	$content_length = strlen($urlencoded);
1040
	$headers = "POST $url HTTP/1.1
1041
Accept: */*
1042
Accept-Language: en-au
1043
Content-Type: application/x-www-form-urlencoded
1044
User-Agent: $user_agent
1045
Host: $server
1046
Connection: Keep-Alive
1047
Cache-Control: no-cache
1048
Content-Length: $content_length
1049

    
1050
";
1051

    
1052
	$errno = "";
1053
	$errstr = "";
1054
	$fp = fsockopen($server, $port, $errno, $errstr);
1055
	if (!$fp) {
1056
		return false;
1057
	}
1058

    
1059
	fputs($fp, $headers);
1060
	fputs($fp, $urlencoded);
1061

    
1062
	$ret = "";
1063
	while (!feof($fp))
1064
		$ret.= fgets($fp, 1024);
1065
	fclose($fp);
1066

    
1067
	return $ret;
1068
}
1069

    
1070
/*
1071
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
1072
 */
1073
if (!function_exists('php_check_syntax')){
1074
	function php_check_syntax($code_to_check, &$errormessage){
1075
		return false;
1076
		$fout = fopen("/tmp/codetocheck.php","w");
1077
		$code = $_POST['content'];
1078
		$code = str_replace("<?php", "", $code);
1079
		$code = str_replace("?>", "", $code);
1080
		fwrite($fout, "<?php\n\n");
1081
		fwrite($fout, $code_to_check);
1082
		fwrite($fout, "\n\n?>\n");
1083
		fclose($fout);
1084
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1085
		$output = exec_command($command);
1086
		if (stristr($output, "Errors parsing") == false) {
1087
			echo "false\n";
1088
			$errormessage = '';
1089
			return(false);
1090
		} else {
1091
			$errormessage = $output;
1092
			return(true);
1093
		}
1094
	}
1095
}
1096

    
1097
/*
1098
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1099
 */
1100
if (!function_exists('php_check_syntax')){
1101
	function php_check_syntax($code_to_check, &$errormessage){
1102
		return false;
1103
		$command = "/usr/local/bin/php -l " . $code_to_check;
1104
		$output = exec_command($command);
1105
		if (stristr($output, "Errors parsing") == false) {
1106
			echo "false\n";
1107
			$errormessage = '';
1108
			return(false);
1109
		} else {
1110
			$errormessage = $output;
1111
			return(true);
1112
		}
1113
	}
1114
}
1115

    
1116
/*
1117
 * rmdir_recursive($path,$follow_links=false)
1118
 * Recursively remove a directory tree (rm -rf path)
1119
 * This is for directories _only_
1120
 */
1121
function rmdir_recursive($path,$follow_links=false) {
1122
	$to_do = glob($path);
1123
	if(!is_array($to_do)) $to_do = array($to_do);
1124
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1125
		if(file_exists($workingdir)) {
1126
			if(is_dir($workingdir)) {
1127
				$dir = opendir($workingdir);
1128
				while ($entry = readdir($dir)) {
1129
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1130
						unlink("$workingdir/$entry");
1131
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
1132
						rmdir_recursive("$workingdir/$entry");
1133
				}
1134
				closedir($dir);
1135
				rmdir($workingdir);
1136
			} elseif (is_file($workingdir)) {
1137
				unlink($workingdir);
1138
			}
1139
               	}
1140
	}
1141
	return;
1142
}
1143

    
1144
/*
1145
 *     get_memory()
1146
 *     returns an array listing the amount of
1147
 *     memory installed in the hardware
1148
 *     [0]real and [1]available
1149
 */
1150
function get_memory() {
1151
	if(file_exists("/var/log/dmesg.boot")) {
1152
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1153
		$matches = "";
1154
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1155
			$real = $matches[1];
1156
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1157
			$avail = $matches[1];
1158
		return array($real[0],$avail[0]);
1159
	} else {
1160
		$mem = `dmesg -a`;
1161
		$matches = "";
1162
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1163
			$real = $matches[1];
1164
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1165
			$avail = $matches[1];
1166
		return array($real[0],$avail[0]);	
1167
	}
1168
}
1169

    
1170
/*
1171
 *    safe_mkdir($path, $mode = 0755)
1172
 *    create directory if it doesn't already exist and isn't a file!
1173
 */
1174
function safe_mkdir($path, $mode=0755) {
1175
	global $g;
1176

    
1177
	/* cdrom is ro. */
1178
	if($g['platform'] == "cdrom")
1179
		return false;
1180
	
1181
	if (!is_file($path) && !is_dir($path))
1182
		return mkdir($path, $mode);
1183
	else
1184
		return false;
1185
}
1186

    
1187
/*
1188
 * make_dirs($path, $mode = 0755)
1189
 * create directory tree recursively (mkdir -p)
1190
 */
1191
function make_dirs($path, $mode = 0755) {
1192
	$base = '';
1193
	foreach (explode('/', $path) as $dir) {
1194
		$base .= "/$dir";
1195
		if (!is_dir($base)) {
1196
			if (!@mkdir($base, $mode))
1197
				return false;
1198
		}
1199
	}
1200
	return true;
1201
}
1202

    
1203
/*
1204
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
1205
 */
1206
function call_pfsense_method($method, $params, $timeout = 0) {
1207
	$ip = gethostbyname('www.pfsense.com');
1208
	if($ip == "www.pfsense.com")
1209
		return false;	
1210
	global $g, $config;
1211
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
1212
	$xmlrpc_path = $g['xmlrpcpath'];
1213
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
1214
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
1215
	$resp = $cli->send($msg, $timeout);
1216
	if(!$resp) {
1217
		log_error("XMLRPC communication error: " . $cli->errstr);
1218
		return false;
1219
	} elseif($resp->faultCode()) {
1220
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
1221
		return false;
1222
	} else {
1223
		return XML_RPC_Decode($resp->value());
1224
	}
1225
}
1226

    
1227
/*
1228
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1229
 */
1230
function check_firmware_version($tocheck = "all", $return_php = true) {
1231
	global $g, $config;
1232
	$ip = gethostbyname('www.pfsense.com');
1233
	if($ip == "www.pfsense.com")
1234
		return false;		
1235
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
1236
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
1237
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
1238
		"platform" => trim(file_get_contents('/etc/platform'))
1239
		);
1240
	if($tocheck == "all") {
1241
		$params = $rawparams;
1242
	} else {
1243
		foreach($tocheck as $check) {
1244
			$params['check'] = $rawparams['check'];
1245
			$params['platform'] = $rawparams['platform'];
1246
		}
1247
	}
1248
	if($config['system']['firmware']['branch']) {
1249
		$params['branch'] = $config['system']['firmware']['branch'];
1250
	}
1251
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
1252
		return false;
1253
	} else {
1254
		$versions["current"] = $params;
1255
	}
1256
	return $versions;
1257
}
1258

    
1259
function get_disk_info() {
1260
	$diskout = "";
1261
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
1262
	return explode(' ', $diskout[0]);
1263
	// $size, $used, $avail, $cap
1264
}
1265

    
1266
/****f* pfsense-utils/display_top_tabs
1267
 * NAME
1268
 *   display_top_tabs - display tabs with rounded edges
1269
 * INPUTS
1270
 *   $text	- array of tabs
1271
 * RESULT
1272
 *   null
1273
 ******/
1274
function display_top_tabs($tab_array) {
1275
	echo "<table cellpadding='0' cellspacing='0'>\n";
1276
	echo " <tr height='1'>\n";
1277
	$tabscounter = 0;
1278
	foreach ($tab_array as $ta) {
1279
		if($ta[1] == true) {
1280
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
1281
		} else {
1282
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
1283
		}
1284
		$tabscounter++;
1285
	}
1286
	echo "</tr>\n<tr>\n";
1287
	foreach ($tab_array as $ta) {
1288
		if($ta[1] == true) {
1289
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
1290
			echo "&nbsp;&nbsp;&nbsp;";
1291
			echo "<font size='-12'>&nbsp;</td>\n";
1292
		} else {
1293
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
1294
			echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
1295
			echo "<font size='-12'>&nbsp;</td>\n";
1296
		}
1297
	}
1298
	echo "</tr>\n<tr height='5px'>\n";
1299
	foreach ($tab_array as $ta) {
1300
		if($ta[1] == true) {
1301
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1302
		} else {
1303
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1304
		}
1305
		$tabscounter++;
1306
	}
1307
	echo " </tr>\n";
1308
	echo "</table>\n";
1309
	    
1310
	echo "<script type=\"text/javascript\">";
1311
	echo "NiftyCheck();\n";
1312
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1313
	for($x=0; $x<$tabscounter; $x++) 
1314
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1315
	echo "</script>";
1316
}
1317

    
1318

    
1319
/****f* pfsense-utils/display_topbar
1320
 * NAME
1321
 *   display_topbar - top a table off with rounded edges
1322
 * INPUTS
1323
 *   $text	- (optional) Text to include in bar
1324
 * RESULT
1325
 *   null
1326
 ******/
1327
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {	    
1328
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
1329
	echo "       <tr height='1'>\n";
1330
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
1331
	echo "		<div id='topbar'></div></td>\n";
1332
	echo "       </tr>\n";
1333
	echo "       <tr height='1'>\n";
1334
	if ($text != "")
1335
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
1336
	else
1337
		echo "         <td height='1' class='listtopic'></td>\n";
1338
	echo "       </tr>\n";
1339
	echo "     </table>";
1340
	echo "<script type=\"text/javascript\">";
1341
	echo "NiftyCheck();\n";
1342
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
1343
	echo "</script>";
1344
}
1345

    
1346
/****f* pfsense-utils/generate_random_mac_address
1347
 * NAME
1348
 *   generate_random_mac - generates a random mac address
1349
 * INPUTS
1350
 *   none
1351
 * RESULT
1352
 *   $mac - a random mac address
1353
 ******/
1354
function generate_random_mac_address() {
1355
	$mac = "00:a0:8e";
1356
	for($x=0; $x<3; $x++) 
1357
		$mac .= ":" . dechex(rand(16, 255));
1358

    
1359
	return $mac;
1360
}
1361

    
1362
/****f* pfsense-utils/strncpy
1363
 * NAME
1364
 *   strncpy - copy strings
1365
 * INPUTS
1366
 *   &$dst, $src, $length
1367
 * RESULT
1368
 *   none
1369
 ******/
1370
function strncpy(&$dst, $src, $length) {
1371
	if (strlen($src) > $length) {
1372
		$dst = substr($src, 0, $length);
1373
	} else {
1374
		$dst = $src;
1375
	}
1376
}
1377

    
1378
/****f* pfsense-utils/reload_interfaces_sync
1379
 * NAME
1380
 *   reload_interfaces - reload all interfaces
1381
 * INPUTS
1382
 *   none
1383
 * RESULT
1384
 *   none
1385
 ******/
1386
function reload_interfaces_sync() {
1387
	global $config, $g, $debug;
1388
	
1389
	$shutdown_webgui_needed = false;
1390
	
1391
	touch("{$g['tmp_path']}/reloading_all");
1392
	
1393
	if($debug)
1394
		log_error("reload_interfaces_sync() is starting.");
1395
	
1396
	if(file_exists("{$g['tmp_path']}/config.cache"))
1397
		unlink("{$g['tmp_path']}/config.cache");
1398
	
1399
	/* parse config.xml again */
1400
	$config = parse_config(true);
1401
	
1402
	$wan_if = $config['interfaces']['wan']['if'];
1403
	$lan_if = $config['interfaces']['lan']['if'];
1404
	
1405
	if($debug)
1406
		log_error("Cleaning up Interfaces");
1407

    
1408
	/* build an array of interfaces to work with */
1409
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1410
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1411
		$iflist['opt' . $i] = "opt{$i}";
1412

    
1413
	foreach ($iflist as $ifent => $ifname) {
1414
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1415
		if(stristr($ifname, "lo0") == true)
1416
			continue;
1417
		/* do not process wan interface, its mandatory */
1418
		if(stristr($ifname, "$wan_if") == true)
1419
			continue;
1420
		/* do not process lan interface, its mandatory */
1421
		if(stristr($ifname, "$lan_if") == true)
1422
			continue;
1423
		if($debug)
1424
			log_error("Downing and deleting $ifname_real - $ifname");
1425
		mwexec("/sbin/ifconfig {$ifname_real} down");
1426
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1427
	}
1428

    
1429
	/* set up VLAN virtual interfaces */
1430
	if($debug)
1431
		log_error("Configuring VLANS");
1432
	interfaces_vlan_configure();
1433
	
1434
	/* set up LAN interface */
1435
	if($debug)
1436
		log_error("Configuring LAN");
1437
	interfaces_lan_configure();
1438

    
1439
	/* set up WAN interface */
1440
	if($debug)
1441
		log_error("Configuring WAN");
1442
	interfaces_wan_configure();
1443
	
1444
	/* set up Optional interfaces */
1445
	if($debug)
1446
		log_error("Configuring optional interfaces");
1447
	interfaces_optional_configure();
1448
	    
1449
	/* set up static routes */
1450
	if($debug)
1451
		log_error("Configuring system Routing");
1452
	system_routing_configure();
1453
	
1454
	/* enable routing */
1455
	if($debug)
1456
		log_error("Enabling system routing");
1457
	system_routing_enable();
1458

    
1459
	/* setup captive portal if needed */
1460
	if($debug)
1461
		log_error("Configuring Captive portal");
1462
	captiveportal_configure();
1463

    
1464
	/* bring up carp interfaces */
1465
	if($debug)
1466
		log_error("Configuring CARP");
1467
	interfaces_carp_configure();
1468
	
1469
	/* bring up carp interfaces*/
1470
	if($debug)
1471
		log_error("Bringing up CARP interfaces");
1472
	interfaces_carp_bring_up_final();
1473
	
1474
	/* restart webConfigurator if needed */
1475
	if($shutdown_webgui_needed == true) 
1476
		touch("/tmp/restart_webgui");
1477
	
1478
	/* start devd back up */
1479
	mwexec("/bin/rm /tmp/reload*");
1480
	
1481
	/* remove reloading_all trigger */
1482
	if($debug)
1483
		log_error("Removing {$g['tmp_path']}/reloading_all");
1484
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1485
}
1486

    
1487
/****f* pfsense-utils/reload_all
1488
 * NAME
1489
 *   reload_all - triggers a reload of all settings
1490
 *   * INPUTS
1491
 *   none
1492
 * RESULT
1493
 *   none
1494
 ******/
1495
function reload_all() {
1496
	touch("/tmp/reload_all");
1497
}
1498

    
1499
/****f* pfsense-utils/reload_interfaces
1500
 * NAME
1501
 *   reload_interfaces - triggers a reload of all interfaces
1502
 * INPUTS
1503
 *   none
1504
 * RESULT
1505
 *   none
1506
 ******/
1507
function reload_interfaces() {
1508
	touch("/tmp/reload_interfaces");
1509
}
1510

    
1511
/****f* pfsense-utils/sync_webgui_passwords
1512
 * NAME
1513
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1514
 * INPUTS
1515
 *   none
1516
 * RESULT
1517
 *   none
1518
 ******/
1519
function sync_webgui_passwords() {
1520
	global $config, $g;
1521
	conf_mount_rw();
1522
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
1523
	if (!$fd) {
1524
		printf("Error: cannot open htpasswd in system_password_configure().\n");
1525
		return 1;
1526
	}
1527
	/* set admin account */
1528
	$username = $config['system']['username'];
1529
	
1530
	/* set defined user account */
1531
	if($username <> "admin") {
1532
		$username = $config['system']['username'];
1533
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1534
	} else {
1535
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");	
1536
	}	
1537
	fclose($fd);
1538
	chmod("{$g['varrun_path']}/htpasswd", 0600);	
1539
	$crypted_pw = $config['system']['password'];
1540
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1541
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1542
	/* sync root */
1543
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
1544
	fwrite($fd, $crypted_pw);
1545
	pclose($fd);
1546
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
1547
	/* sync admin */
1548
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
1549
	fwrite($fd, $crypted_pw);
1550
	pclose($fd);
1551
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
1552
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1553
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1554
	conf_mount_ro();
1555
}
1556

    
1557
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
1558
 * NAME
1559
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
1560
 *   * INPUTS
1561
 *   optional interface number
1562
 * RESULT
1563
 *   none
1564
 ******/
1565
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
1566
	global $config;
1567
	unlink_if_exists("/tmp/config.cache");
1568
	$config_file = file_get_contents("/cf/conf/config.xml");
1569
	/* loop through and reassign optional items */
1570
	for ($i = 255; isset($config['interfaces']['opt' . $i]); $i--) {
1571
		if($i < $opt_interface_num)
1572
			break;
1573
		/* replace opt$i with $i -1 */
1574
		str_replace("opt" . $i, "opt" . ($i-1), $config_file);
1575
	}
1576
	$fd = fopen("/cf/conf/config.xml", "w");
1577
	fwrite($fd, $config_file);
1578
	fclose($fd);
1579
	$config = parse_config(true);
1580
	return true;
1581
}
1582

    
1583
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
1584
 * NAME
1585
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
1586
 *   		amount of netgraph interfaces needed for system wans
1587
 *   * INPUTS
1588
 *   none
1589
 * RESULT
1590
 *   number of needed netgraph (ng) interfaces
1591
 ******/
1592
function get_number_of_wan_netgraph_interfaces_needed() {
1593
	global $config, $g;
1594
	/* build an array of interfaces to work with */
1595
	$iflist = array("wan" => "WAN");
1596
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1597
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1598
	$ng_interfaces_needed = 0;
1599
	foreach ($iflist as $ifent => $ifname) {
1600
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1601
			$ng_interfaces_needed++;
1602
		}
1603
	}
1604
	return $ng_interfaces_needed;
1605
}
1606

    
1607
function get_netgaph_interface_assignment($friendly_interface) {
1608
	global $config, $g;
1609
	/* build an array of interfaces to work with */
1610
	$iflist = array("wan" => "WAN");
1611
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1612
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1613
		$ng_interfaces_needed = 0;
1614
		$ng_interfaces_number = 0;
1615
		foreach ($iflist as $ifent => $ifname) {
1616
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1617
			$ng_interfaces_number++;
1618
		}
1619
		if($friendly_interface == $ifname)
1620
			break;
1621
	}
1622
	return $ng_interfaces_number;	
1623
}
1624

    
1625
/****f* pfsense-utils/reload_all_sync
1626
 * NAME
1627
 *   reload_all - reload all settings
1628
 *   * INPUTS
1629
 *   none
1630
 * RESULT
1631
 *   none
1632
 ******/
1633
function reload_all_sync() {
1634
	global $config, $g;
1635
	
1636
	$g['booting'] = false;
1637
	
1638
	touch("{$g['tmp_path']}/reloading_all");
1639
	
1640
	$shutdown_webgui_needed = false;
1641
	
1642
	if(file_exists("{$g['tmp_path']}/config.cache"))
1643
		unlink("{$g['tmp_path']}/config.cache");
1644
	
1645
	/* parse config.xml again */
1646
	$config = parse_config(true);
1647

    
1648
	/* set up our timezone */
1649
	system_timezone_configure();
1650

    
1651
	/* set up our hostname */
1652
	system_hostname_configure();
1653

    
1654
	/* make hosts file */
1655
	system_hosts_generate();
1656

    
1657
	/* generate resolv.conf */
1658
	system_resolvconf_generate();
1659

    
1660
	/* delete all old interface information */
1661
	$iflist = split(" ", str_replace("\n", "", `/sbin/ifconfig -l`));
1662
	
1663
	$wan_if = $config['interfaces']['wan']['if'];
1664
	$lan_if = $config['interfaces']['lan']['if'];
1665

    
1666
	/* build an array of interfaces to work with */
1667
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1668
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1669
		$iflist['opt' . $i] = "opt{$i}";
1670

    
1671
	foreach ($iflist as $ifent => $ifname) {
1672
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1673
		if(stristr($ifname, "lo0") == true)
1674
			continue;
1675
		/* do not process wan interface, its mandatory */
1676
		if($wan_if == $ifname_real)
1677
			continue;
1678
		/* do not process lan interface, its mandatory */
1679
		if($lan_if == $ifname_real)
1680
			continue;
1681
		mwexec("/sbin/ifconfig {$ifname_real} down");
1682
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1683
	}
1684

    
1685
	/* set up VLAN virtual interfaces */
1686
	interfaces_vlan_configure();
1687
	
1688
	/* set up LAN interface */
1689
	interfaces_lan_configure();
1690

    
1691
	/* set up WAN interface */
1692
	interfaces_wan_configure();
1693

    
1694
	/* set up Optional interfaces */
1695
	interfaces_optional_configure();
1696
        
1697
	/* bring up carp interfaces */
1698
	interfaces_carp_configure();
1699
	
1700
	/* set up static routes */
1701
	system_routing_configure();
1702

    
1703
	/* enable routing */
1704
	system_routing_enable();
1705
	
1706
	/* ensure passwords are sync'd */
1707
	system_password_configure();
1708

    
1709
	/* start dnsmasq service */
1710
	services_dnsmasq_configure();
1711

    
1712
	/* start dyndns service */
1713
	services_dyndns_configure();
1714

    
1715
	/* start DHCP service */
1716
	services_dhcpd_configure();
1717

    
1718
	/* start the NTP client */
1719
	system_ntp_configure();
1720

    
1721
	/* start ftp proxy helpers if they are enabled */
1722
	system_start_ftp_helpers();
1723

    
1724
	/* start the captive portal */
1725
	captiveportal_configure();
1726

    
1727
        /* reload the filter */
1728
	filter_configure_sync();
1729

    
1730
	/* bring up carp interfaces*/
1731
	interfaces_carp_bring_up_final();
1732
	
1733
	/* sync pw database */
1734
	conf_mount_rw();
1735
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1736
	conf_mount_ro();
1737

    
1738
	/* restart sshd */
1739
	touch("/tmp/start_sshd");
1740
	
1741
	/* restart webConfigurator if needed */
1742
	if($shutdown_webgui_needed == true) 
1743
		touch("/tmp/restart_webgui");
1744
	
1745
	mwexec("/bin/rm /tmp/reload*");
1746
	
1747
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1748
	
1749
}
1750

    
1751
function auto_login($status) {
1752
	$gettytab = file_get_contents("/etc/gettytab");
1753
	$getty_split = split("\n", $gettytab);
1754
	conf_mount_rw();
1755
	$fd = fopen("/etc/gettytab", "w");
1756
	foreach($getty_split as $gs) {
1757
		if(stristr($gs, ":ht:np:sp#115200") ) {
1758
			if($status == true) {
1759
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
1760
			} else {
1761
				fwrite($fd, "	:ht:np:sp#115200:\n");
1762
			}
1763
		} else {
1764
			fwrite($fd, "{$gs}\n");
1765
		}
1766
	}
1767
	fclose($fd);
1768
	conf_mount_ro();	
1769
}
1770

    
1771
function setup_serial_port() {
1772
	global $g, $config;
1773
	conf_mount_rw();
1774
	/* serial console - write out /boot.config */
1775
	if(file_exists("/boot.config"))
1776
		$boot_config = file_get_contents("/boot.config");
1777
	else
1778
		$boot_config = "";
1779
	
1780
	if($g['platform'] <> "cdrom") {
1781
		$boot_config_split = split("\n", $boot_config);
1782
		$fd = fopen("/boot.config","w");
1783
		if($fd) {
1784
			foreach($boot_config_split as $bcs) {
1785
				if(stristr($bcs, "-D")) {
1786
					/* DONT WRITE OUT, WE'LL DO IT LATER */	
1787
				} else {
1788
					if($bcs <> "")
1789
						fwrite($fd, "{$bcs}\n");
1790
				}
1791
			}
1792
			if(isset($config['system']['enableserial'])) {
1793
				fwrite($fd, "-D");
1794
			}			
1795
			fclose($fd);
1796
		}
1797
		/* serial console - write out /boot/loader.conf */
1798
		$boot_config = file_get_contents("/boot/loader.conf");	
1799
		$boot_config_split = split("\n", $boot_config);
1800
		$fd = fopen("/boot/loader.conf","w");
1801
		if($fd) {
1802
			foreach($boot_config_split as $bcs) {
1803
				if(stristr($bcs, "console")) {
1804
					/* DONT WRITE OUT, WE'LL DO IT LATER */	
1805
				} else {
1806
					if($bcs <> "")
1807
						fwrite($fd, "{$bcs}\n");
1808
				}
1809
			}
1810
			if(isset($config['system']['enableserial'])) {
1811
				fwrite($fd, "console=\"comconsole\"\n");
1812
			}
1813
			fclose($fd);
1814
		}
1815
	}
1816
	if(isset($config['system']['disableconsolemenu'])) {
1817
		auto_login(false);
1818
	} else {
1819
		auto_login(true);
1820
	}	
1821
	conf_mount_ro();
1822
	return;	
1823
}
1824

    
1825
function print_value_list($list, $count = 10, $separator = ",") {
1826
	$list = implode($separator, array_slice($list, 0, $count));
1827
	if(count($list) < $count) {
1828
		$list .= ".";
1829
	} else {
1830
		$list .= "...";
1831
	}
1832
	return $list;
1833
}
1834

    
1835
function convert_friendly_interface_to_friendly_descr($interface) {
1836
	global $config;
1837
	/* attempt to resolve interface to friendly descr */
1838
	if($config['interfaces'][$interface]['descr']) 
1839
		return $config['interfaces'][$interface]['descr'];
1840
	$tmp = convert_real_interface_to_friendly_descr($interface);
1841
	/* could not resolve, return back what was passed */
1842
	return $interface;
1843
}
1844

    
1845
function convert_real_interface_to_friendly_descr($interface) {
1846
	global $config;
1847
	if($interface == $config['interfaces']['wan']['if'])
1848
		return "wan";
1849
	if($interface == $config['interfaces']['lan']['if'])
1850
		return "lan";
1851
	/* attempt to resolve interface to friendly descr */
1852
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
1853
	if($config['interfaces'][$friendly_int]['descr'])
1854
		return $config['interfaces'][$friendly_int]['descr'];
1855
	/* could not resolve, return back what was passed */
1856
	return $interface;
1857
}
1858

    
1859
function enable_rrd_graphing()
1860
{
1861
// consider syncing the rrd files to usb storage/xml (cdrom, embbedded)
1862

    
1863
	global $config, $g;
1864

    
1865
    $rrddbpath = "/var/db/rrd/";
1866
    $rrdgraphpath = "/usr/local/www/rrd";
1867
	$rrdtrafficinterval = 60;
1868
	$rrdqualityinterval = 60;
1869
	$rrdqueuesinterval = 60;
1870
	$rrdpacketsinterval = 60;
1871
	$rrdspamdinterval = 60;
1872

    
1873
	$traffic = "-traffic.rrd";
1874
	$packets = "-packets.rrd";
1875
	$quality = "-quality.rrd";
1876
	$queues = "-queues.rrd";
1877
	$spamd = "spamd.rrd";
1878
	$rrdtool = "/usr/local/bin/rrdtool";
1879
	$netstat = "/usr/bin/netstat";
1880
	$awk = "/usr/bin/awk";
1881
	$tar = "/usr/bin/tar";
1882
	$php = "/usr/local/bin/php";
1883
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
1884

    
1885
	$gatewayip = exec("/sbin/route -n get default | /usr/bin/grep gateway | /usr/bin/awk '{print $2}'");
1886
	/* if an alternative gateway is defined, use it. */
1887
	if($config['system']['use_rrd_gateway'])
1888
		$gatewayip = $config['system']['use_rrd_gateway'];
1889
	$numpings = 5;
1890
	$btick = '`';
1891

    
1892
	$trafficvalid = $rrdtrafficinterval*2 ;
1893
	$qualityvalid = $rrdqualityinterval*2 ;
1894
	$queuesvalid = $rrdqueuesinterval*2 ;
1895
	$packetsvalid = $rrdpacketsinterval*2 ;
1896
	$spamdvalid = $rrdspamdinterval*2 ;
1897

    
1898
	/* Asume GigE for now */
1899
	$downstream = 125000000;
1900
	$upstream   = 125000000;
1901
	
1902
	$rrdrestore = "";
1903
	$rrdreturn = "";	
1904

    
1905
	$config['rrd']['enable'] = true;
1906

    
1907
	if (isset($config['rrd']['enable'])) {
1908

    
1909
		/* create directory if needed */
1910
		if(!is_dir("$rrddbpath")) { 	                 
1911
			mkdir("$rrddbpath", 0755); 	 
1912
		}
1913

    
1914
		if($g['booting']) {
1915
			/* if we are on livecd or embedded use a memoryfs. */
1916
			/* 3MB is enough for everyone. *cough* */
1917
			if($g['platform'] != "pfSense") {
1918
				/* determine highest MD device */
1919
				$mdnr = `mount |grep md | awk -F"md" '{print $2}'|tail -1 |cut -c 1`;
1920
				$mdnr = $mdnr +1;
1921
				system("/sbin/mdmfs -M -s 3m md$mdnr $rrddbpath");
1922

    
1923
				/* we now have something to write "on", restore the databases if we have them */
1924
				if(file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
1925
					exec("cd /;/usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
1926
					if($rrdrestore != 0) {
1927
						log_error("RRD restore failed exited with $rrdreturn, the
1928
							error is: $rrdrestore[0]\n");
1929
					}
1930
				}
1931
			}
1932

    
1933
		}
1934

    
1935
		/* db update script */
1936
		$rrdupdatesh = "#!/bin/sh\n";
1937
		$rrdupdatesh .= "\n";
1938
		$rrdupdatesh .= "counter=1\n";
1939
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
1940
		$rrdupdatesh .= "do\n";
1941
		$rrdupdatesh .= "";
1942

    
1943
		/* directory index */
1944
		$rrdgraphindexhtml = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">
1945
<HTML>
1946
<HEAD>
1947
    <TITLE>MRTG Index Page</TITLE>
1948
    <META HTTP-EQUIV=\"Refresh\" CONTENT=\"360\">
1949
    <META HTTP-EQUIV=\"Cache-Control\" content=\"no-cache\">
1950
    <META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">
1951
    <META HTTP-EQUIV=\"Expires\" CONTENT=\"Tue, 22 May 2001 09:22:45 GMT\">
1952
</HEAD>
1953
<BODY bgcolor=\"#ffffff\" text=\"#000000\" link=\"#000000\" vlink=\"#000000\" alink=\"#000000\">
1954
<H1>MRTG Index Page</H1>
1955
<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=10>";
1956

    
1957
       		$i = 0;
1958
                $vfaces = array("vlan.?*");
1959
                $ifdescrs = get_interface_list(true, true, $vfaces);
1960
       		foreach ($ifdescrs as $realif => $ifdescr) {
1961
			$ifname = $ifdescr['friendly'];
1962
			$state = $ifdescr['up'];
1963

    
1964
			/* skip interfaces that do not have a friendly name */
1965
			if("$ifname" == "") {
1966
				continue;
1967
			}
1968
			
1969
			/* or are down */
1970
			if(! $state) {
1971
				continue;
1972
			}
1973

    
1974
			/* set up the rrd file */
1975
			if(! file_exists("$rrddbpath$ifname$traffic")) {
1976
				/* create rrd file if it does not exist */
1977
				log_error("Create RRD database $rrddbpath$ifname$traffic");
1978
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval \
1979
					DS:in:COUNTER:$trafficvalid:0:$downstream \
1980
					DS:out:COUNTER:$trafficvalid:0:$upstream \
1981
					RRA:AVERAGE:0.5:1:1000 \
1982
					RRA:AVERAGE:0.5:5:1000 \
1983
					RRA:AVERAGE:0.5:60:1000 \
1984
					RRA:AVERAGE:0.5:360:1000 \
1985
					RRA:MAX:0.5:1:1000 \
1986
					RRA:MAX:0.5:5:1000 \
1987
					RRA:MAX:0.5:60:1000 \
1988
					RRA:MAX:0.5:3600:1000";
1989
					
1990
				$rrdcreateoutput = "";
1991
				$rrdcreatereturn = "";
1992

    
1993
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
1994
				if($rrdcreatereturn != 0) {
1995
			                log_error("RRD create failed exited with $rrdcreatereturn, the 
1996
						error is: $rrdcreateoutput[0]\n");
1997
				}
1998
			}
1999

    
2000
			$rrdupdatesh .= "\n";
2001
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
2002
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
2003
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7}'`:\\\n";
2004
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$10}'`\n\n";
2005

    
2006
			/* set up the rrd file */
2007
			if(! file_exists("$rrddbpath$ifname$packets")) {
2008
				/* create rrd file if it does not exist */
2009
				log_error("Create RRD database $rrddbpath$ifname$packets");
2010
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval \
2011
					DS:in:COUNTER:$packetsvalid:0:$downstream \
2012
					DS:out:COUNTER:$packetsvalid:0:$upstream \
2013
					RRA:AVERAGE:0.5:1:1000 \
2014
					RRA:AVERAGE:0.5:5:1000 \
2015
					RRA:AVERAGE:0.5:60:1000 \
2016
					RRA:AVERAGE:0.5:360:1000 \
2017
					RRA:MAX:0.5:1:1000 \
2018
					RRA:MAX:0.5:5:1000 \
2019
					RRA:MAX:0.5:60:1000 \
2020
					RRA:MAX:0.5:360:1000";
2021

    
2022
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2023
				if($rrdcreatereturn != 0) {
2024
			                log_error("RRD create failed exited with $rrdcreatereturn, the 
2025
						error is: $rrdcreateoutput[0]\n");
2026
				}
2027
			}
2028

    
2029
			$rrdupdatesh .= "\n";
2030
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
2031
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
2032
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5}'`:\\\n";
2033
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$8}'`\n\n";
2034

    
2035
			$rrdgraphindexhtml .= "<TR>
2036
<TD><DIV><B>Traffic Analysis for $ifname -- day</B></DIV>
2037
<DIV><IMG BORDER=1 ALT=\"$ifname Traffic Graph\" SRC=\"$ifname-day.png\">
2038
<BR>
2039
</TD>
2040
<TD><DIV><B>Traffic Analysis for $ifname -- week</B></DIV>
2041
<DIV><IMG BORDER=1 ALT=\"$ifname Traffic Graph\" SRC=\"$ifname-week.png\">
2042
<BR>
2043
</TD>
2044
</TR>";
2045

    
2046
			if("$ifname" == "wan") {
2047
				/* create link quality database */
2048
				if(! file_exists("$rrddbpath$ifname$quality")) {
2049
					/* create rrd file if it does not exist */
2050
					log_error("Create RRD database $rrddbpath$ifname$quality");
2051
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval \
2052
							DS:loss:GAUGE:$qualityvalid:0:100 \
2053
							DS:roundtrip:GAUGE:$qualityvalid:0:10000 \
2054
							RRA:AVERAGE:0.5:1:1000 \
2055
							RRA:AVERAGE:0.5:5:1000 \
2056
							RRA:AVERAGE:0.5:60:1000 \
2057
							RRA:AVERAGE:0.5:360:1000";
2058

    
2059
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2060
					if($rrdcreatereturn != 0) {
2061
				                log_error("RRD create failed exited with $rrdcreatereturn, the 
2062
							error is: $rrdcreateoutput[0]\n");
2063
					}
2064
				}
2065

    
2066
				/* the ping test function. We call this on the last line */
2067
				$rrdupdatesh .= "get_ping_stats () {
2068
					packetloss=100
2069
					roundtrip=0
2070
					local out
2071
					out=$btick ping -c $numpings -q $gatewayip $btick
2072
					if [ $? -eq 0 ]; then
2073
						packetloss=$btick echo \$out | cut -f18 -d' ' | cut -c -1 $btick
2074
						roundtrip=$btick echo \$out | cut -f24 -d' ' | cut -f2 -d'/' $btick
2075
					fi
2076
					$rrdtool update $rrddbpath$ifname$quality N:\$packetloss:\$roundtrip
2077
				}\n\n";
2078

    
2079
				$rrdupdatesh .= "get_ping_stats &\n\n";
2080

    
2081
				if (!is_array($config['shaper']['queue'])) {
2082
					$config['shaper']['queue'] = array();
2083
				}
2084
				$a_queues = &$config['shaper']['queue'];
2085

    
2086
				if(isset($config['shaper']['enable'])) {
2087
					if(!file_exists("$rrddbpath$ifname$queues")) {
2088
						/* create rrd file if it does not exist */
2089
						log_error("Create RRD database $rrddbpath$ifname$queues");
2090
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval \\\n";
2091
						/* loop list of shaper queues */
2092
						$q = 0;
2093
						 foreach ($a_queues as $queue) {
2094
							$name = $queue['name'];
2095
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream \\\n";
2096
						}
2097

    
2098
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 \
2099
							RRA:AVERAGE:0.5:5:1000 \
2100
							RRA:AVERAGE:0.5:60:1000 \
2101
							RRA:AVERAGE:0.5:360:1000";
2102

    
2103
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2104
						if($rrdcreatereturn != 0) {
2105
				        	        log_error("RRD create failed exited with $rrdcreatereturn, the 
2106
								error is: $rrdcreateoutput[0]\n");
2107
						}
2108
					}
2109

    
2110
				/* awk function to gather shaper data */
2111
				/* yes, it's special */
2112
				$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } \\
2113
					{ \
2114
					if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { \\
2115
					        dsname = dsname \":\" \$2 ; \\
2116
					        q=1; \\
2117
					} \\
2118
					else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { \\
2119
					        dsdata = dsdata \":\" \$5 ; \\
2120
					        q=0; \\
2121
					} \\
2122
					} END { \\
2123
						dsname = substr(dsname,2); \\
2124
						dsdata = substr(dsdata,2); \\
2125
						printf \"-t \" dsname \" N:\" dsdata }' \\
2126
						dsname=\"\" dsdata=\"\"`\n\n";
2127
				}
2128
			}
2129

    
2130
	        }
2131
       		$i++;
2132

    
2133
		$rrdgraphindexhtml .= "</TABLE>
2134
</BODY>
2135
</HTML>";
2136

    
2137
		if(isset($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
2138
			/* set up the spamd rrd file */
2139
			if(! file_exists("$rrddbpath$spamd")) {
2140
				/* create rrd file if it does not exist */
2141
				log_error("Create RRD database $rrddbpath$spamd");
2142
				$rrdcreate = "$rrdtool create $rrddbpath$spamd --step $rrdspamdinterval \
2143
					DS:conn:GAUGE:$trafficvalid:0:10000 \
2144
					DS:time:GAUGE:$trafficvalid:0:86400 \
2145
					RRA:MIN:0.5:1:1000 \
2146
					RRA:MIN:0.5:5:1000 \
2147
					RRA:MIN:0.5:60:1000 \
2148
					RRA:MIN:0.5:360:1000 \
2149
					RRA:AVERAGE:0.5:1:1000 \
2150
					RRA:AVERAGE:0.5:5:1000 \
2151
					RRA:AVERAGE:0.5:60:1000 \
2152
					RRA:AVERAGE:0.5:360:1000 \
2153
					RRA:MAX:0.5:1:1000 \
2154
					RRA:MAX:0.5:5:1000 \
2155
					RRA:MAX:0.5:60:1000 \
2156
					RRA:MAX:0.5:360:1000";
2157

    
2158
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2159
				if($rrdcreatereturn != 0) {
2160
		        	        log_error("RRD create failed exited with $rrdcreatereturn, the 
2161
						error is: $rrdcreateoutput[0]\n");
2162
				}
2163
			}
2164
		
2165
			$rrdupdatesh .= "\n";
2166
			$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
2167
			$rrdupdatesh .= "$rrdtool update $rrddbpath$spamd \\\n";
2168
			$rrdupdatesh .= "`$php -q $spamd_gather`\n";
2169

    
2170
		}
2171
	
2172
		$rrdupdatesh .= "sleep 60\n";
2173
		$rrdupdatesh .= "done\n";
2174
		log_error("Creating rrd update script");
2175
		/* write the rrd update script */
2176
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
2177
		$fd = fopen("$updaterrdscript", "w");
2178
		fwrite($fd, "$rrdupdatesh");
2179
		fclose($fd);
2180

    
2181
		log_error("Creating rrd graph index");
2182
		/* write the index.html script */
2183
		$rrdgraphindex = "{$g['vardb_path']}/rrd/index.html";
2184
		$fd = fopen("$rrdgraphindex", "w");
2185
		fwrite($fd, "$rrdgraphindexhtml");
2186
		fclose($fd);
2187
	
2188
		/* kill off traffic collectors */
2189
		kill_traffic_collector();
2190

    
2191
		/* start traffic collector */
2192
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
2193

    
2194
	} else {
2195
		/* unmount and remove */
2196
		system("/sbin/umount $rrddbpath");
2197
		exec("/sbin/mdconfig -d -u 2");
2198
		/* kill off traffic collectors */
2199
		kill_traffic_collector();
2200
	}
2201
}
2202

    
2203
function kill_traffic_collector() {
2204
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
2205
}
2206

    
2207
function update_filter_reload_status($text) {
2208
	global $g;
2209
	config_lock();
2210
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
2211
	fwrite($fd, $text);
2212
	fclose($fd);
2213
	config_unlock();
2214
}
2215

    
2216
?>
(14-14/27)