Project

General

Profile

Download (61.2 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/get_dns_servers
41
 * NAME
42
 *   get_dns_servres - get system dns servers
43
 * INPUTS
44
 *   $dns_servers - an array of the dns servers
45
 * RESULT
46
 *   null
47
 ******/
48
function get_dns_servers() {
49
	$dns_servers = array();
50
	$dns = `cat /etc/resolv.conf`;
51
	$dns_s = split("\n", $dns);
52
	foreach($dns_s as $dns) {
53
		$matches = "";
54
		if (preg_match("/nameserver (.*)/", $dns, $matches))
55
			$dns_servers[] = $matches[1];		
56
	}
57
	$dns_server_master = array();
58
	sort($dns_servers);
59
	$lastseen = "";
60
	foreach($dns_servers as $t) {
61
		if($t <> $lastseen)
62
			if($t <> "")
63
				$dns_server_master[] = $t;
64
		$lastseen = $t;
65
	}
66
	return $dns_server_master;
67
}
68
 	
69
/****f* pfsense-utils/log_error
70
* NAME
71
*   log_error  - Sends a string to syslog.
72
* INPUTS
73
*   $error     - string containing the syslog message.
74
* RESULT
75
*   null
76
******/
77
function log_error($error) {
78
	$page = $_SERVER['SCRIPT_NAME'];
79
	syslog(LOG_WARNING, "$page: $error");
80
	return;
81
}
82

    
83
/****f* pfsense-utils/get_interface_mac_address
84
 * NAME
85
 *   get_interface_mac_address - Return a interfaces mac address
86
 * INPUTS
87
 *   $interface	- interface to obtain mac address from
88
 * RESULT
89
 *   $mac - the mac address of the interface
90
 ******/
91
function get_interface_mac_address($interface) {
92
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
93
	return trim($mac);
94
}
95

    
96
/****f* pfsense-utils/return_dir_as_array
97
 * NAME
98
 *   return_dir_as_array - Return a directory's contents as an array.
99
 * INPUTS
100
 *   $dir	- string containing the path to the desired directory.
101
 * RESULT
102
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
103
 ******/
104
function return_dir_as_array($dir) {
105
	$dir_array = array();
106
	if (is_dir($dir)) {
107
		if ($dh = opendir($dir)) {
108
			while (($file = readdir($dh)) !== false) {
109
				$canadd = 0;
110
				if($file == ".") $canadd = 1;
111
				if($file == "..") $canadd = 1;
112
				if($canadd == 0)
113
					array_push($dir_array, $file);
114
			}
115
			closedir($dh);
116
		}
117
	}
118
	return $dir_array;
119
}
120

    
121
/****f* pfsense-utils/enable_hardware_offloading
122
 * NAME
123
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
124
 * INPUTS
125
 *   $interface	- string containing the physical interface to work on.
126
 * RESULT
127
 *   null
128
 * NOTES
129
 *   This function only supports the fxp driver's loadable microcode.
130
 ******/
131
function enable_hardware_offloading($interface) {
132
	global $g, $config;
133

    
134
	if(stristr($interface,"lnc"))
135
		return;
136
	if(isset($config['system']['do_not_use_nic_microcode']))
137
		return;
138

    
139
	if($g['booting']) {
140
	/* translate wan, lan, opt -> real interface if needed */
141
	$int = filter_translate_type_to_real_interface($interface);
142
	if($int <> "") $interface = $int;
143
	$int_family = preg_split("/[0-9]+/", $int);
144
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
145
	$supported_ints = array('fxp');
146
	if (in_array($int_family, $supported_ints))
147
		mwexec("/sbin/ifconfig {$interface} link0");
148

    
149
	if(stristr($options, "txcsum") == true)
150
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
151
	if(stristr($options, "rxcsum") == true)    
152
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");    
153
	if(stristr($options, "polling") == true)
154
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
155
	} else {
156
		mwexec("sysctl kern.polling.enable=0");
157
	}
158
	return;
159
}
160

    
161
/****f* pfsense-utils/is_alias_inuse
162
 * NAME
163
 *   checks to see if an alias is currently in use by a rule
164
 * INPUTS
165
 *   
166
 * RESULT
167
 *   true or false
168
 * NOTES
169
 *   
170
 ******/
171
function is_alias_inuse($alias) {
172
	global $g, $config;
173

    
174
	if($alias == "") return false;
175
	/* loop through firewall rules looking for alias in use */
176
	if(is_array($config['nat']['rule']))
177
		foreach($config['filter']['rule'] as $rule) {
178
			if(is_array($rule['source']['address']))
179
				if($rule['source']['address'] == $alias)
180
					return true;
181
			if(is_array($rule['destination']['address']))
182
				if($rule['destination']['address'] == $alias)
183
					return true;
184
		}
185
	/* loop through nat rules looking for alias in use */
186
	if(is_array($config['nat']['rule']))
187
		foreach($config['nat']['rule'] as $rule) {
188
			if($rule['target'] == $alias)
189
				return true;
190
			if($rule['external-address'] == $alias)
191
				return true;	
192
		}
193
	return false;
194
}
195

    
196
/****f* pfsense-utils/setup_polling_defaults
197
 * NAME
198
 *   sets up sysctls for pollingS
199
 * INPUTS
200
 *   
201
 * RESULT
202
 *   null
203
 * NOTES
204
 *   
205
 ******/
206
function setup_polling_defaults() {
207
	global $g, $config;
208
	if($config['system']['polling_each_burst'])
209
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
210
	if($config['system']['polling_burst_max'])
211
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
212
	if($config['system']['polling_user_frac'])
213
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");		
214
}
215

    
216
/****f* pfsense-utils/setup_polling
217
 * NAME
218
 *   sets up polling
219
 * INPUTS
220
 *   
221
 * RESULT
222
 *   null
223
 * NOTES
224
 *   
225
 ******/
226
function setup_polling() {
227
	global $g, $config;		
228

    
229
	setup_polling_defaults();
230
	
231
	if(isset($config['system']['polling']))
232
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
233
	else
234
		$supported_ints = array();
235

    
236
	/* build an array of interfaces to work with */
237
	$iflist = array("lan" => "LAN", "wan" => "WAN");
238
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
239
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];			
240

    
241
	foreach ($iflist as $ifent => $ifname) {
242
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
243
		$supported = false;
244
		foreach($supported_ints as $supported) {
245
			if(stristr($real_interface, $supported)) {
246
				$supported = true;
247
			} 
248
		}
249
		if ($supported == true) {
250
			mwexec("/sbin/ifconfig {$real_interface} polling");
251
		} else {
252
			mwexec("/sbin/ifconfig {$real_interface} -polling");
253
		}
254
	}
255
}
256

    
257
/****f* pfsense-utils/setup_microcode
258
 * NAME
259
 *   enumerates all interfaces and calls enable_hardware_offloading which
260
 *   enables a NIC's supported hardware features.
261
 * INPUTS
262
 *   
263
 * RESULT
264
 *   null
265
 * NOTES
266
 *   This function only supports the fxp driver's loadable microcode.
267
 ******/
268
function setup_microcode() {
269
	global $config;
270

    
271
	$ifdescrs = array('wan', 'lan');
272
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
273
		$ifdescrs['opt' . $j] = "opt" . $j;
274
	}
275
	foreach($ifdescrs as $if)
276
		enable_hardware_offloading($if);
277
}
278

    
279
/****f* pfsense-utils/return_filename_as_array
280
 * NAME
281
 *   return_filename_as_array - Return a file's contents as an array.
282
 * INPUTS
283
 *   $filename	- string containing the path to the desired file.
284
 *   $strip	- array of characters to strip - default is '#'.
285
 * RESULT
286
 *   $file	- array containing the file's contents.
287
 * NOTES
288
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
289
 ******/
290
function return_filename_as_array($filename, $strip = array('#')) {
291
	if(file_exists($filename)) $file = file($filename);
292
	if(is_array($file)) {
293
		foreach($file as $line) $line = trim($line);
294
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
295
	}
296
	return $file;
297
}
298

    
299
/****f* pfsense-utils/file_put_contents
300
 * NAME
301
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
302
 * RESULT
303
 *   none
304
 ******/
305
if(!function_exists("file_put_contents")) {
306
	function file_put_contents($filename, $data) {
307
		$fd = fopen($filename,"w");
308
		fwrite($fd, $data);
309
		fclose($fd);
310
	}
311
}
312

    
313
/****f* pfsense-utils/get_carp_status
314
 * NAME
315
 *   get_carp_status - Return whether CARP is enabled or disabled.
316
 * RESULT
317
 *   boolean	- true if CARP is enabled, false if otherwise.
318
 ******/
319
function get_carp_status() {
320
    /* grab the current status of carp */
321
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
322
    if(intval($status) == "0") return false;
323
    return true;
324
}
325

    
326
/****f* pfsense-utils/is_carp_defined
327
 * NAME
328
 *   is_carp_defined - Return whether CARP is detected in the kernel.
329
 * RESULT
330
 *   boolean	- true if CARP is detected, false otherwise.
331
 ******/
332
function is_carp_defined() {
333
	/* is carp compiled into the kernel and userland? */
334
	$command = "/sbin/sysctl -a | grep carp";
335
	$fd = popen($command . " 2>&1 ", "r");
336
	if(!$fd) {
337
		log_error("Warning, could not execute command {$command}");
338
		return 0;
339
	}
340
	while(!feof($fd)) {
341
		$tmp .= fread($fd,49);
342
	}
343
	fclose($fd);
344

    
345
	if($tmp == "")
346
		return false;
347
	else
348
		return true;
349
}
350

    
351
/****f* pfsense-utils/get_interface_mtu
352
 * NAME
353
 *   get_interface_mtu - Return the mtu of an interface
354
 * RESULT
355
 *   $tmp	- Returns the mtu of an interface
356
 ******/
357
function get_interface_mtu($interface) {
358
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f4`;
359
	return $mtu;
360
}
361

    
362
/****f* pfsense-utils/is_interface_wireless
363
 * NAME
364
 *   is_interface_wireless - Returns if an interface is wireless
365
 * RESULT
366
 *   $tmp	- Returns if an interface is wireless
367
 ******/
368
function is_interface_wireless($interface) {
369
	global $config, $g;
370
	$interface = convert_real_interface_to_friendly_interface_name($interface);
371
	if(isset($config['interfaces'][$interface]['wireless']))
372
		return true;
373
	else
374
		return false;
375
}
376

    
377
/****f* pfsense-utils/find_number_of_created_carp_interfaces
378
 * NAME
379
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
380
 * RESULT
381
 *   $tmp	- Number of currently created CARP interfaces.
382
 ******/
383
function find_number_of_created_carp_interfaces() {
384
	$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
385
	$fd = popen($command . " 2>&1 ", "r");
386
	if(!$fd) {
387
		log_error("Warning, could not execute command {$command}");
388
		return 0;
389
	}
390
	while(!feof($fd)) {
391
		$tmp .= fread($fd,49);
392
	}
393
	fclose($fd);
394
	$tmp = intval($tmp);
395
	return $tmp;
396
}
397

    
398
/****f* pfsense-utils/link_ip_to_carp_interface
399
 * NAME
400
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
401
 * INPUTS
402
 *   $ip
403
 * RESULT
404
 *   $carp_ints
405
 ******/
406
function link_ip_to_carp_interface($ip) {
407
	global $config;
408
	if($ip == "") return;
409

    
410
	$ifdescrs = array('wan', 'lan');
411
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
412
		$ifdescrs['opt' . $j] = "opt" . $j;
413
	}
414

    
415
	$ft = split("\.", $ip);
416
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
417

    
418
	$carp_ints = "";
419
	$num_carp_ints = find_number_of_created_carp_interfaces();
420
	foreach ($ifdescrs as $ifdescr => $ifname) {
421
		for($x=0; $x<$num_carp_ints; $x++) {
422
			$carp_int = "carp{$x}";
423
			$carp_ip = find_interface_ip($carp_int);
424
			$carp_ft = split("\.", $carp_ip);
425
			$carp_ft_ip = $carp_ft[0] . "." . $carp_ft[1] . "." . $carp_ft[2] . ".";
426
			$result = does_interface_exist($carp_int);
427
			if($result <> true) break;
428
			if($ft_ip == $carp_ft_ip)
429
			if(stristr($carp_ints,$carp_int) == false)
430
			$carp_ints .= " " . $carp_int;
431
		}
432
	}
433
	return $carp_ints;
434
}
435

    
436
/****f* pfsense-utils/exec_command
437
 * NAME
438
 *   exec_command - Execute a command and return a string of the result.
439
 * INPUTS
440
 *   $command	- String of the command to be executed.
441
 * RESULT
442
 *   String containing the command's result.
443
 * NOTES
444
 *   This function returns the command's stdout and stderr.
445
 ******/
446
function exec_command($command) {
447
	$output = array();
448
	exec($command . ' 2>&1 ', $output);
449
	return(implode("\n", $output));
450
}
451

    
452
/****f* interfaces/is_jumbo_capable
453
 * NAME
454
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
455
 * INPUTS
456
 *   $int             - string containing interface name
457
 * RESULT
458
 *   boolean          - true or false
459
 ******/
460
function is_jumbo_capable($int) {
461
	/* Per:
462
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
463
	 * Only the following drivers support large frames
464
         * 
465
	 * 'de' chipset purposely left out of this list
466
	 * requires defining BIG_PACKET in the
467
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
468
	 * kernel or module.  The hack works only for the 21041,
469
	 * 21140, and 21140A chips.
470
	 */
471
	global $g;
472
	
473
	$capable = $g['vlan_long_frame'];
474
	
475
	$int_family = preg_split("/[0-9]+/", $int);
476

    
477
	if (in_array($int_family[0], $capable))
478
		return true;
479
	else
480
		return false;
481
}
482

    
483
/*
484
 * does_interface_exist($interface): return true or false if a interface is detected.
485
 */
486
function does_interface_exist($interface) {
487
	$ints = exec_command("/sbin/ifconfig -l");
488
	if(stristr($ints, $interface) !== false)
489
		return true;
490
	else
491
		return false;
492
}
493

    
494
/*
495
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
496
 */
497
function convert_ip_to_network_format($ip, $subnet) {
498
	$ipsplit = split('[.]', $ip);
499
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
500
	return $string;
501
}
502

    
503
/*
504
 * find_interface_ip($interface): return the interface ip (first found)
505
 */
506
function find_interface_ip($interface) {
507
	if(does_interface_exist($interface) == false) return;
508
	$ip = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2");
509
	$ip = str_replace("\n","",$ip);
510
	return $ip;
511
}
512

    
513
function guess_interface_from_ip($ipaddress) {
514
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2
515
; };'");
516
	return $ret;
517
}
518

    
519
function filter_opt_interface_to_real($opt) {
520
	global $config;
521
	return $config['interfaces'][$opt]['if'];
522
}
523

    
524
function filter_get_opt_interface_descr($opt) {
525
	global $config;
526
	return $config['interfaces'][$opt]['descr'];
527
}
528

    
529
function get_friendly_interface_list_as_array() {
530
	global $config;
531
	$ints = array();
532
	$ifdescrs = array('wan', 'lan');
533
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
534
		$ifdescrs['opt' . $j] = "opt" . $j;
535
	}
536
	$ifdescrs = get_interface_list();
537
	foreach ($ifdescrs as $ifdescr => $ifname) {
538
		array_push($ints,$ifdescr);
539
	}
540
	return $ints;
541
}
542

    
543
/*
544
 * find_ip_interface($ip): return the interface where an ip is defined
545
 */
546
function find_ip_interface($ip) {
547
	global $config;
548
	$ifdescrs = array('wan', 'lan');
549
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
550
		$ifdescrs['opt' . $j] = "opt" . $j;
551
	}
552
	foreach ($ifdescrs as $ifdescr => $ifname) {
553
		$int = filter_translate_type_to_real_interface($ifname);
554
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
555
	if(stristr($ifconfig,$ip) <> false)
556
		return $int;
557
	}
558
	return false;
559
}
560

    
561
/*
562
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
563
 *                                                       for a friendly interface.  ie: wan
564
 */
565
function filter_translate_type_to_real_interface($interface) {
566
	global $config;
567
	if($config['interfaces'][$interface]['if'] <> "") {
568
		return $config['interfaces'][$interface]['if'];
569
	} else {
570
		return $interface;
571
	}
572
}
573

    
574
/*
575
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
576
 */
577
function get_carp_interface_status($carpinterface) {
578
	/* basically cache the contents of ifconfig statement
579
	to speed up this routine */
580
	global $carp_query;
581
	if($carp_query == "")
582
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
583
	$found_interface = 0;
584
	foreach($carp_query as $int) {
585
		if($found_interface == 1) {
586
			if(stristr($int, "MASTER") == true) return "MASTER";
587
			if(stristr($int, "BACKUP") == true) return "BACKUP";
588
			if(stristr($int, "INIT") == true) return "INIT";
589
			return false;
590
		}
591
		if(stristr($int, $carpinterface) == true)
592
		$found_interface=1;
593
	}
594
	return;
595
}
596

    
597
/*
598
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
599
 */
600
function get_pfsync_interface_status($pfsyncinterface) {
601
    $result = does_interface_exist($pfsyncinterface);
602
    if($result <> true) return;
603
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
604
    return $status;
605
}
606

    
607
/*
608
 * find_carp_interface($ip): return the carp interface where an ip is defined
609
 */
610
function find_carp_interface($ip) {
611
	global $find_carp_ifconfig;
612
	if($find_carp_ifconfig == "") {
613
		$find_carp_ifconfig = array();
614
		$num_carp_ints = find_number_of_created_carp_interfaces();
615
		for($x=0; $x<$num_carp_ints; $x++) {
616
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
617
		}
618
	}
619
	$carps = 0;
620
	foreach($find_carp_ifconfig as $fci) {
621
		if(stristr($fci, $ip) == true)
622
			return "carp{$carps}";
623
		$carps++;
624
	}
625
}
626

    
627
/*
628
 * setup_filter_bridge(): toggle filtering bridge
629
 */
630
function setup_filter_bridge() {
631
	global $config, $g;
632
	if(isset($config['bridge']['filteringbridge'])) {
633
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
634
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
635
	} else {		
636
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
637
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
638
	}
639
}
640

    
641
/*
642
 * find_number_of_created_bridges(): returns the number of currently created bridges
643
 */
644
function find_number_of_created_bridges() {
645
	return `/sbin/ifconfig | grep "bridge[0-999]" | wc -l`;
646
}
647

    
648
/*
649
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
650
 */
651
function add_rule_to_anchor($anchor, $rule, $label) {
652
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
653
}
654

    
655
/*
656
 * remove_text_from_file
657
 * remove $text from file $file
658
 */
659
function remove_text_from_file($file, $text) {
660
	global $fd_log;
661
	fwrite($fd_log, "Adding needed text items:\n");
662
	$filecontents = exec_command_and_return_text("cat " . $file);
663
	$textTMP = str_replace($text, "", $filecontents);
664
	$text .= $textTMP;
665
	fwrite($fd_log, $text . "\n");
666
	$fd = fopen($file, "w");
667
	fwrite($fd, $text);
668
	fclose($fd);
669
}
670

    
671
/*
672
 * add_text_to_file($file, $text): adds $text to $file.
673
 * replaces the text if it already exists.
674
 */
675
function add_text_to_file($file, $text) {
676
	if(file_exists($file) and is_writable($file)) {
677
		$filecontents = file($file);
678
		$filecontents[] = $text;
679
		$tmpfile = get_tmp_file();
680
		$fout = fopen($tmpfile, "w");
681
		foreach($filecontents as $line) {
682
			fwrite($fout, rtrim($line) . "\n");
683
		}
684
		fclose($fout);
685
		rename($tmpfile, $file);
686
		return true;
687
	} else {
688
		return false;
689
	}
690
}
691

    
692
/*
693
 *   after_sync_bump_adv_skew(): create skew values by 1S
694
 */
695
function after_sync_bump_adv_skew() {
696
	global $config, $g;
697
	$processed_skew = 1;
698
	$a_vip = &$config['virtualip']['vip'];
699
	foreach ($a_vip as $vipent) {
700
		if($vipent['advskew'] <> "") {
701
			$processed_skew = 1;
702
			$vipent['advskew'] = $vipent['advskew']+1;
703
		}
704
	}
705
	if($processed_skew == 1)
706
		write_config("After synch increase advertising skew");
707
}
708

    
709
/*
710
 * get_filename_from_url($url): converts a url to its filename.
711
 */
712
function get_filename_from_url($url) {
713
	return basename($url);
714
}
715

    
716
/*
717
 *   update_output_window: update bottom textarea dynamically.
718
 */
719
function update_output_window($text) {
720
	$log = ereg_replace("\n", "\\n", $text);
721
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
722
	/* ensure that contents are written out */
723
	ob_flush();
724
}
725

    
726
/*
727
 *   get_dir: return an array of $dir
728
 */
729
function get_dir($dir) {
730
	$dir_array = array();
731
	$d = dir($dir);
732
	while (false !== ($entry = $d->read())) {
733
		array_push($dir_array, $entry);
734
	}
735
	$d->close();
736
	return $dir_array;
737
}
738

    
739
/*
740
 *   update_output_window: update top textarea dynamically.
741
 */
742
function update_status($status) {
743
	echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
744
	/* ensure that contents are written out */
745
	ob_flush();
746
}
747

    
748
/*
749
 *   exec_command_and_return_text_array: execute command and return output
750
 */
751
function exec_command_and_return_text_array($command) {
752
	$fd = popen($command . " 2>&1 ", "r");
753
	while(!feof($fd)) {
754
		$tmp .= fread($fd,49);
755
	}
756
	fclose($fd);
757
	$temp_array = split("\n", $tmp);
758
	return $temp_array;
759
}
760

    
761
/*
762
 *   exec_command_and_return_text: execute command and return output
763
 */
764
function exec_command_and_return_text($command) {
765
	return exec_command($command);
766
}
767

    
768
/*
769
 *   exec_command_and_return_text: execute command and update output window dynamically
770
 */
771
function execute_command_return_output($command) {
772
	global $fd_log;
773
	$fd = popen($command . " 2>&1 ", "r");
774
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
775
	$counter = 0;
776
	$counter2 = 0;
777
	while(!feof($fd)) {
778
		$tmp = fread($fd, 50);
779
		$tmp1 = ereg_replace("\n","\\n", $tmp);
780
		$text = ereg_replace("\"","'", $tmp1);
781
		$lasttext = "";
782
		if($lasttext == "..") {
783
			$text = "";
784
			$lasttext = "";
785
			$counter=$counter-2;
786
		} else {
787
			$lasttext .= $text;
788
		}
789
		if($counter > 51) {
790
			$counter = 0;
791
			$extrabreak = "\\n";
792
		} else {
793
	    $extrabreak = "";
794
	    $counter++;
795
		}
796
		if($counter2 > 600) {
797
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
798
			$counter2 = 0;
799
		} else
800
			$counter2++;
801
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
802
	}
803
	fclose($fd);
804
}
805

    
806
/*
807
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
808
 */
809
function convert_friendly_interface_to_real_interface_name($interface) {
810
	global $config;
811
	$lc_interface = strtolower($interface);
812
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
813
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
814
	$ifdescrs = array();
815
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
816
		$ifdescrs['opt' . $j] = "opt" . $j;
817
	foreach ($ifdescrs as $ifdescr => $ifname) {
818
		if(strtolower($ifname) == $lc_interface)
819
	    return $config['interfaces'][$ifname]['if'];
820
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
821
			return $config['interfaces'][$ifname]['if'];
822
   }
823
   return $interface;
824
}
825

    
826
/*
827
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
828
 */
829
function convert_real_interface_to_friendly_interface_name($interface) {
830
	global $config;
831
	$ifdescrs = array('wan', 'lan');
832
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
833
		$ifdescrs['opt' . $j] = "opt" . $j;
834
	foreach ($ifdescrs as $ifdescr => $ifname) {
835
		$int = filter_translate_type_to_real_interface($ifname);
836
		if($ifname == $interface) return $ifname;
837
		if($int == $interface) return $ifname;
838
	}
839
	return $interface;
840
}
841

    
842
/*
843
 * update_progress_bar($percent): updates the javascript driven progress bar.
844
 */
845
function update_progress_bar($percent) {
846
	if($percent > 100) $percent = 1;
847
	echo "\n<script type=\"text/javascript\" language=\"javascript\">";
848
	echo "\ndocument.progressbar.style.width='" . $percent . "%';";
849
	echo "\n</script>";
850
}
851

    
852
/****f* pfsense-utils/WakeOnLan
853
 * NAME
854
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
855
 * RESULT
856
 *   true/false - true if the operation was successful
857
 ******/
858
function WakeOnLan($addr, $mac)
859
{
860
	$addr_byte = explode(':', $mac);
861
	$hw_addr = '';
862
	
863
	for ($a=0; $a < 6; $a++)
864
		$hw_addr .= chr(hexdec($addr_byte[$a]));
865
	
866
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
867
	
868
	for ($a = 1; $a <= 16; $a++)
869
		$msg .= $hw_addr;
870
	
871
	// send it to the broadcast address using UDP
872
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
873
	if ($s == false) {
874
		log_error("Error creating socket!");
875
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
876
	} else {
877
		// setting a broadcast option to socket:
878
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
879
		if($opt_ret < 0)
880
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
881
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
882
		socket_close($s);
883
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
884
		return true;
885
	}
886
	
887
	return false;
888
}
889

    
890
/*
891
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
892
 *                             is queuename|qlength|measured_packets
893
 *                             NOTE: this command takes 5 seconds to run
894
 */
895
function gather_altq_queue_stats($dont_return_root_queues) {
896
	mwexec("/usr/bin/killall -9 pfctl");
897
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
898
	$stats_array = split("\n", $stats);
899
	$queue_stats = array();
900
	foreach ($stats_array as $stats_line) {
901
		$match_array = "";
902
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
903
			$queue_name = $match_array[1][0];
904
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
905
			$speed = $match_array[1][0];
906
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
907
			$borrows = $match_array[1][0];
908
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
909
			$suspends = $match_array[1][0];
910
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
911
			$drops = $match_array[1][0];
912
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
913
			$measured = $match_array[1][0];
914
			if($dont_return_root_queues == true)
915
				if(stristr($queue_name,"root_") == false)
916
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
917
		}
918
	}
919
	return $queue_stats;
920
}
921

    
922
/*
923
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
924
 *					 Useful for finding paths and stripping file extensions.
925
 */
926
function reverse_strrchr($haystack, $needle) {
927
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
928
}
929

    
930
/*
931
 *  backup_config_section($section): returns as an xml file string of
932
 *                                   the configuration section
933
 */
934
function backup_config_section($section) {
935
	global $config;
936
	$new_section = &$config[$section];
937
	/* generate configuration XML */
938
	$xmlconfig = dump_xml_config($new_section, $section);
939
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
940
	return $xmlconfig;
941
}
942

    
943
/*
944
 *  backup_vip_config_section($section): returns as an xml file string of
945
 *                                   the configuration section
946
 */
947
function backup_vip_config_section() {
948
	global $config;
949
	$new_section = &$config['virtualip'];
950
	foreach($new_section['vip'] as $section) {
951
		if($section['mode'] == "proxyarp") {
952
			unset($section);		
953
		}
954
		if($section['advskew'] <> "") {
955
			$section_val = intval($section['advskew']);
956
			$section_val=$section_val+100;
957
			if($section_val > 255)
958
				$section_val = 255;
959
			$section['advskew'] = $section_val;
960
		}
961
		$temp['vip'][] = $section;
962
   }
963
   return $temp;
964
}
965

    
966
/*
967
 *  restore_config_section($section, new_contents): restore a configuration section,
968
 *                                                  and write the configuration out
969
 *                                                  to disk/cf.
970
 */
971
function restore_config_section($section, $new_contents) {
972
	global $config, $g;
973
	conf_mount_rw();
974
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
975
	fwrite($fout, $new_contents);
976
	fclose($fout);
977
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
978
	$config[$section] = &$section_xml;
979
	unlink($g['tmp_path'] . "/tmpxml");
980
	write_config("Restored {$section} of config file (maybe from CARP partner)");
981
	conf_mount_ro();
982
	return;
983
}
984

    
985
/*
986
 * http_post($server, $port, $url, $vars): does an http post to a web server
987
 *                                         posting the vars array.
988
 * written by nf@bigpond.net.au
989
 */
990
function http_post($server, $port, $url, $vars) {
991
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
992
	$urlencoded = "";
993
	while (list($key,$value) = each($vars))
994
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
995
	$urlencoded = substr($urlencoded,0,-1);
996
	$content_length = strlen($urlencoded);
997
	$headers = "POST $url HTTP/1.1
998
Accept: */*
999
Accept-Language: en-au
1000
Content-Type: application/x-www-form-urlencoded
1001
User-Agent: $user_agent
1002
Host: $server
1003
Connection: Keep-Alive
1004
Cache-Control: no-cache
1005
Content-Length: $content_length
1006

    
1007
";
1008

    
1009
	$errno = "";
1010
	$errstr = "";
1011
	$fp = fsockopen($server, $port, $errno, $errstr);
1012
	if (!$fp) {
1013
		return false;
1014
	}
1015

    
1016
	fputs($fp, $headers);
1017
	fputs($fp, $urlencoded);
1018

    
1019
	$ret = "";
1020
	while (!feof($fp))
1021
		$ret.= fgets($fp, 1024);
1022
	fclose($fp);
1023

    
1024
	return $ret;
1025
}
1026

    
1027
/*
1028
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
1029
 */
1030
if (!function_exists('php_check_syntax')){
1031
	function php_check_syntax($code_to_check, &$errormessage){
1032
		return false;
1033
		$fout = fopen("/tmp/codetocheck.php","w");
1034
		$code = $_POST['content'];
1035
		$code = str_replace("<?php", "", $code);
1036
		$code = str_replace("?>", "", $code);
1037
		fwrite($fout, "<?php\n\n");
1038
		fwrite($fout, $code_to_check);
1039
		fwrite($fout, "\n\n?>\n");
1040
		fclose($fout);
1041
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1042
		$output = exec_command($command);
1043
		if (stristr($output, "Errors parsing") == false) {
1044
			echo "false\n";
1045
			$errormessage = '';
1046
			return(false);
1047
		} else {
1048
			$errormessage = $output;
1049
			return(true);
1050
		}
1051
	}
1052
}
1053

    
1054
/*
1055
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1056
 */
1057
if (!function_exists('php_check_syntax')){
1058
	function php_check_syntax($code_to_check, &$errormessage){
1059
		return false;
1060
		$command = "/usr/local/bin/php -l " . $code_to_check;
1061
		$output = exec_command($command);
1062
		if (stristr($output, "Errors parsing") == false) {
1063
			echo "false\n";
1064
			$errormessage = '';
1065
			return(false);
1066
		} else {
1067
			$errormessage = $output;
1068
			return(true);
1069
		}
1070
	}
1071
}
1072

    
1073
/*
1074
 * rmdir_recursive($path,$follow_links=false)
1075
 * Recursively remove a directory tree (rm -rf path)
1076
 * This is for directories _only_
1077
 */
1078
function rmdir_recursive($path,$follow_links=false) {
1079
	$to_do = glob($path);
1080
	if(!is_array($to_do)) $to_do = array($to_do);
1081
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1082
		if(file_exists($workingdir)) {
1083
			if(is_dir($workingdir)) {
1084
				$dir = opendir($workingdir);
1085
				while ($entry = readdir($dir)) {
1086
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1087
						unlink("$workingdir/$entry");
1088
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
1089
						rmdir_recursive("$workingdir/$entry");
1090
				}
1091
				closedir($dir);
1092
				rmdir($workingdir);
1093
			} elseif (is_file($workingdir)) {
1094
				unlink($workingdir);
1095
			}
1096
               	}
1097
	}
1098
	return;
1099
}
1100

    
1101
/*
1102
 *     get_memory()
1103
 *     returns an array listing the amount of
1104
 *     memory installed in the hardware
1105
 *     [0]real and [1]available
1106
 */
1107
function get_memory() {
1108
	if(file_exists("/var/log/dmesg.boot")) {
1109
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1110
		$matches = "";
1111
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1112
			$real = $matches[1];
1113
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1114
			$avail = $matches[1];
1115
		return array($real[0],$avail[0]);
1116
	} else {
1117
		$mem = `dmesg -a`;
1118
		$matches = "";
1119
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1120
			$real = $matches[1];
1121
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1122
			$avail = $matches[1];
1123
		return array($real[0],$avail[0]);	
1124
	}
1125
}
1126

    
1127
/*
1128
 *    safe_mkdir($path, $mode = 0755)
1129
 *    create directory if it doesn't already exist and isn't a file!
1130
 */
1131
function safe_mkdir($path, $mode=0755) {
1132
	global $g;
1133

    
1134
	/* cdrom is ro. */
1135
	if($g['platform'] == "cdrom")
1136
		return false;
1137
	
1138
	if (!is_file($path) && !is_dir($path))
1139
		return mkdir($path, $mode);
1140
	else
1141
		return false;
1142
}
1143

    
1144
/*
1145
 * make_dirs($path, $mode = 0755)
1146
 * create directory tree recursively (mkdir -p)
1147
 */
1148
function make_dirs($path, $mode = 0755) {
1149
	/* is dir already created? */
1150
	if(is_dir($path)) return;
1151
	/* create directory in question */
1152
	$to_create = explode("/", $path);
1153
	foreach($to_create as $tc) 
1154
		if(!is_dir($tc))
1155
			safe_mkdir($path, $mode);
1156
}
1157

    
1158
/*
1159
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
1160
 */
1161
function call_pfsense_method($method, $params, $timeout = 0) {
1162
	$ip = gethostbyname('www.pfsense.com');
1163
	if($ip == "www.pfsense.com")
1164
		return false;	
1165
	global $g, $config;
1166
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
1167
	$xmlrpc_path = $g['xmlrpcpath'];
1168
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
1169
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
1170
	$resp = $cli->send($msg, $timeout);
1171
	if(!$resp) {
1172
		log_error("XMLRPC communication error: " . $cli->errstr);
1173
		return false;
1174
	} elseif($resp->faultCode()) {
1175
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
1176
		return false;
1177
	} else {
1178
		return XML_RPC_Decode($resp->value());
1179
	}
1180
}
1181

    
1182
/*
1183
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1184
 */
1185
function check_firmware_version($tocheck = "all", $return_php = true) {
1186
	global $g, $config;
1187
	$ip = gethostbyname('www.pfsense.com');
1188
	if($ip == "www.pfsense.com")
1189
		return false;		
1190
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
1191
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
1192
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
1193
		"platform" => trim(file_get_contents('/etc/platform'))
1194
		);
1195
	if($tocheck == "all") {
1196
		$params = $rawparams;
1197
	} else {
1198
		foreach($tocheck as $check) {
1199
			$params['check'] = $rawparams['check'];
1200
			$params['platform'] = $rawparams['platform'];
1201
		}
1202
	}
1203
	if($config['system']['firmware']['branch']) {
1204
		$params['branch'] = $config['system']['firmware']['branch'];
1205
	}
1206
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
1207
		return false;
1208
	} else {
1209
		$versions["current"] = $params;
1210
	}
1211
	return $versions;
1212
}
1213

    
1214
function get_disk_info() {
1215
	$diskout = "";
1216
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
1217
	return explode(' ', $diskout[0]);
1218
	// $size, $used, $avail, $cap
1219
}
1220

    
1221
/****f* pfsense-utils/display_top_tabs
1222
 * NAME
1223
 *   display_top_tabs - display tabs with rounded edges
1224
 * INPUTS
1225
 *   $text	- array of tabs
1226
 * RESULT
1227
 *   null
1228
 ******/
1229
function display_top_tabs($tab_array) {
1230
	echo "<table cellpadding='0' cellspacing='0'>\n";
1231
	echo " <tr height='1'>\n";
1232
	$tabscounter = 0;
1233
	foreach ($tab_array as $ta) {
1234
		if($ta[1] == true) {
1235
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
1236
		} else {
1237
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
1238
		}
1239
		$tabscounter++;
1240
	}
1241
	echo "</tr>\n<tr>\n";
1242
	foreach ($tab_array as $ta) {
1243
		if($ta[1] == true) {
1244
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
1245
			echo "&nbsp;&nbsp;&nbsp;";
1246
			echo "<font size='-12'>&nbsp;</td>\n";
1247
		} else {
1248
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
1249
			echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
1250
			echo "<font size='-12'>&nbsp;</td>\n";
1251
		}
1252
	}
1253
	echo "</tr>\n<tr height='5px'>\n";
1254
	foreach ($tab_array as $ta) {
1255
		if($ta[1] == true) {
1256
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1257
		} else {
1258
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1259
		}
1260
		$tabscounter++;
1261
	}
1262
	echo " </tr>\n";
1263
	echo "</table>\n";
1264
	    
1265
	echo "<script type=\"text/javascript\">";
1266
	echo "NiftyCheck();\n";
1267
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1268
	for($x=0; $x<$tabscounter; $x++) 
1269
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1270
	echo "</script>";
1271
}
1272

    
1273

    
1274
/****f* pfsense-utils/display_topbar
1275
 * NAME
1276
 *   display_topbar - top a table off with rounded edges
1277
 * INPUTS
1278
 *   $text	- (optional) Text to include in bar
1279
 * RESULT
1280
 *   null
1281
 ******/
1282
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {	    
1283
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
1284
	echo "       <tr height='1'>\n";
1285
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
1286
	echo "		<div id='topbar'></div></td>\n";
1287
	echo "       </tr>\n";
1288
	echo "       <tr height='1'>\n";
1289
	if ($text != "")
1290
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
1291
	else
1292
		echo "         <td height='1' class='listtopic'></td>\n";
1293
	echo "       </tr>\n";
1294
	echo "     </table>";
1295
	echo "<script type=\"text/javascript\">";
1296
	echo "NiftyCheck();\n";
1297
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
1298
	echo "</script>";
1299
}
1300

    
1301
/****f* pfsense-utils/generate_random_mac_address
1302
 * NAME
1303
 *   generate_random_mac - generates a random mac address
1304
 * INPUTS
1305
 *   none
1306
 * RESULT
1307
 *   $mac - a random mac address
1308
 ******/
1309
function generate_random_mac_address() {
1310
	$mac = "00:a0:8e";
1311
	for($x=0; $x<3; $x++) 
1312
		$mac .= ":" . dechex(rand(16, 255));
1313

    
1314
	return $mac;
1315
}
1316

    
1317
/****f* pfsense-utils/strncpy
1318
 * NAME
1319
 *   strncpy - copy strings
1320
 * INPUTS
1321
 *   &$dst, $src, $length
1322
 * RESULT
1323
 *   none
1324
 ******/
1325
function strncpy(&$dst, $src, $length) {
1326
	if (strlen($src) > $length) {
1327
		$dst = substr($src, 0, $length);
1328
	} else {
1329
		$dst = $src;
1330
	}
1331
}
1332

    
1333
/****f* pfsense-utils/reload_interfaces_sync
1334
 * NAME
1335
 *   reload_interfaces - reload all interfaces
1336
 * INPUTS
1337
 *   none
1338
 * RESULT
1339
 *   none
1340
 ******/
1341
function reload_interfaces_sync() {
1342
	global $config, $g, $debug;
1343
	
1344
	$shutdown_webgui_needed = false;
1345
	
1346
	touch("{$g['tmp_path']}/reloading_all");
1347
	
1348
	if($debug)
1349
		log_error("reload_interfaces_sync() is starting.");
1350
	
1351
	if(file_exists("{$g['tmp_path']}/config.cache"))
1352
		unlink("{$g['tmp_path']}/config.cache");
1353
	
1354
	/* parse config.xml again */
1355
	$config = parse_config(true);
1356
	
1357
	$wan_if = $config['interfaces']['wan']['if'];
1358
	$lan_if = $config['interfaces']['lan']['if'];
1359
	
1360
	if($debug)
1361
		log_error("Cleaning up Interfaces");
1362

    
1363
	/* build an array of interfaces to work with */
1364
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1365
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1366
		$iflist['opt' . $i] = "opt{$i}";
1367

    
1368
	foreach ($iflist as $ifent => $ifname) {
1369
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1370
		if(stristr($ifname, "lo0") == true)
1371
			continue;
1372
		/* do not process wan interface, its mandatory */
1373
		if(stristr($ifname, "$wan_if") == true)
1374
			continue;
1375
		/* do not process lan interface, its mandatory */
1376
		if(stristr($ifname, "$lan_if") == true)
1377
			continue;
1378
		if($debug)
1379
			log_error("Downing and deleting $ifname_real - $ifname");
1380
		mwexec("/sbin/ifconfig {$ifname_real} down");
1381
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1382
	}
1383

    
1384
	/* set up VLAN virtual interfaces */
1385
	if($debug)
1386
		log_error("Configuring VLANS");
1387
	interfaces_vlan_configure();
1388
	
1389
	/* set up LAN interface */
1390
	if($debug)
1391
		log_error("Configuring LAN");
1392
	interfaces_lan_configure();
1393

    
1394
	/* set up WAN interface */
1395
	if($debug)
1396
		log_error("Configuring WAN");
1397
	interfaces_wan_configure();
1398
	
1399
	/* set up Optional interfaces */
1400
	if($debug)
1401
		log_error("Configuring optional interfaces");
1402
	interfaces_optional_configure();
1403
	    
1404
	/* set up static routes */
1405
	if($debug)
1406
		log_error("Configuring system Routing");
1407
	system_routing_configure();
1408
	
1409
	/* enable routing */
1410
	if($debug)
1411
		log_error("Enabling system routing");
1412
	system_routing_enable();
1413

    
1414
	/* setup captive portal if needed */
1415
	if($debug)
1416
		log_error("Configuring Captive portal");
1417
	captiveportal_configure();
1418

    
1419
	/* bring up carp interfaces */
1420
	if($debug)
1421
		log_error("Configuring CARP");
1422
	interfaces_carp_configure();
1423
	
1424
	/* bring up carp interfaces*/
1425
	if($debug)
1426
		log_error("Bringing up CARP interfaces");
1427
	interfaces_carp_bring_up_final();
1428
	
1429
	/* restart webConfigurator if needed */
1430
	if($shutdown_webgui_needed == true) 
1431
		touch("/tmp/restart_webgui");
1432
	
1433
	/* start devd back up */
1434
	mwexec("/bin/rm /tmp/reload*");
1435
	
1436
	/* remove reloading_all trigger */
1437
	if($debug)
1438
		log_error("Removing {$g['tmp_path']}/reloading_all");
1439
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1440
}
1441

    
1442
/****f* pfsense-utils/reload_all
1443
 * NAME
1444
 *   reload_all - triggers a reload of all settings
1445
 *   * INPUTS
1446
 *   none
1447
 * RESULT
1448
 *   none
1449
 ******/
1450
function reload_all() {
1451
	touch("/tmp/reload_all");
1452
}
1453

    
1454
/****f* pfsense-utils/reload_interfaces
1455
 * NAME
1456
 *   reload_interfaces - triggers a reload of all interfaces
1457
 * INPUTS
1458
 *   none
1459
 * RESULT
1460
 *   none
1461
 ******/
1462
function reload_interfaces() {
1463
	touch("/tmp/reload_interfaces");
1464
}
1465

    
1466
/****f* pfsense-utils/sync_webgui_passwords
1467
 * NAME
1468
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1469
 * INPUTS
1470
 *   none
1471
 * RESULT
1472
 *   none
1473
 ******/
1474
function sync_webgui_passwords() {
1475
	global $config, $g;
1476
	conf_mount_rw();
1477
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
1478
	if (!$fd) {
1479
		printf("Error: cannot open htpasswd in system_password_configure().\n");
1480
		return 1;
1481
	}
1482
	/* set admin account */
1483
	$username = $config['system']['username'];
1484
	
1485
	/* set defined user account */
1486
	if($username <> "admin") {
1487
		$username = $config['system']['username'];
1488
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1489
	} else {
1490
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");	
1491
	}	
1492
	fclose($fd);
1493
	chmod("{$g['varrun_path']}/htpasswd", 0600);	
1494
	$crypted_pw = $config['system']['password'];
1495
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1496
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1497
	/* sync root */
1498
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
1499
	fwrite($fd, $crypted_pw);
1500
	pclose($fd);
1501
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
1502
	/* sync admin */
1503
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
1504
	fwrite($fd, $crypted_pw);
1505
	pclose($fd);
1506
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
1507
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1508
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1509
	conf_mount_ro();
1510
}
1511

    
1512
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
1513
 * NAME
1514
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
1515
 *   * INPUTS
1516
 *   optional interface number
1517
 * RESULT
1518
 *   none
1519
 ******/
1520
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
1521
	global $config;
1522
	unlink_if_exists("/tmp/config.cache");
1523
	$config_file = file_get_contents("/cf/conf/config.xml");
1524
	/* loop through and reassign optional items */
1525
	for ($i = 255; isset($config['interfaces']['opt' . $i]); $i--) {
1526
		if($i < $opt_interface_num)
1527
			break;
1528
		/* replace opt$i with $i -1 */
1529
		str_replace("opt" . $i, "opt" . ($i-1), $config_file);
1530
	}
1531
	$fd = fopen("/cf/conf/config.xml", "w");
1532
	fwrite($fd, $config_file);
1533
	fclose($fd);
1534
	$config = parse_config(true);
1535
	return true;
1536
}
1537

    
1538
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
1539
 * NAME
1540
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
1541
 *   		amount of netgraph interfaces needed for system wans
1542
 *   * INPUTS
1543
 *   none
1544
 * RESULT
1545
 *   number of needed netgraph (ng) interfaces
1546
 ******/
1547
function get_number_of_wan_netgraph_interfaces_needed() {
1548
	global $config, $g;
1549
	/* build an array of interfaces to work with */
1550
	$iflist = array("wan" => "WAN");
1551
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1552
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1553
	$ng_interfaces_needed = 0;
1554
	foreach ($iflist as $ifent => $ifname) {
1555
		if($config['inerfaces'][$ifname]['ipaddr'] == "pppoe") {
1556
			$ng_interfaces_needed++;
1557
		}
1558
	}
1559
	return $ng_interfaces_needed;
1560
}
1561

    
1562
function get_netgaph_interface_assignment($friendly_interface) {
1563
	global $config, $g;
1564
	/* build an array of interfaces to work with */
1565
	$iflist = array("wan" => "WAN");
1566
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1567
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1568
		$ng_interfaces_needed = 0;
1569
		$ng_interfaces_number = 0;
1570
		foreach ($iflist as $ifent => $ifname) {
1571
		if($config['inerfaces'][$ifname]['ipaddr'] == "pppoe") {
1572
			$ng_interfaces_number++;
1573
		}
1574
		if($friendly_interface == $ifname)
1575
			break;
1576
	}
1577
	return $ng_interfaces_number;	
1578
}
1579

    
1580
/****f* pfsense-utils/reload_all_sync
1581
 * NAME
1582
 *   reload_all - reload all settings
1583
 *   * INPUTS
1584
 *   none
1585
 * RESULT
1586
 *   none
1587
 ******/
1588
function reload_all_sync() {
1589
	global $config, $g;
1590
	
1591
	touch("{$g['tmp_path']}/reloading_all");
1592
	
1593
	$shutdown_webgui_needed = false;
1594
	
1595
	if(file_exists("{$g['tmp_path']}/config.cache"))
1596
		unlink("{$g['tmp_path']}/config.cache");
1597
	
1598
	/* parse config.xml again */
1599
	$config = parse_config(true);
1600

    
1601
	/* set up our timezone */
1602
	system_timezone_configure();
1603

    
1604
	/* set up our hostname */
1605
	system_hostname_configure();
1606

    
1607
	/* make hosts file */
1608
	system_hosts_generate();
1609

    
1610
	/* generate resolv.conf */
1611
	system_resolvconf_generate();
1612

    
1613
	/* delete all old interface information */
1614
	$iflist = split(" ", str_replace("\n", "", `/sbin/ifconfig -l`));
1615
	
1616
	$wan_if = $config['interfaces']['wan']['if'];
1617
	$lan_if = $config['interfaces']['lan']['if'];
1618

    
1619
	/* build an array of interfaces to work with */
1620
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1621
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1622
		$iflist['opt' . $i] = "opt{$i}";
1623

    
1624
	foreach ($iflist as $ifent => $ifname) {
1625
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1626
		if(stristr($ifname, "lo0") == true)
1627
			continue;
1628
		/* do not process wan interface, its mandatory */
1629
		if($wan_if == $ifname_real)
1630
			continue;
1631
		/* do not process lan interface, its mandatory */
1632
		if($lan_if == $ifname_real)
1633
			continue;
1634
		mwexec("/sbin/ifconfig {$ifname_real} down");
1635
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1636
	}
1637

    
1638
	/* set up VLAN virtual interfaces */
1639
	interfaces_vlan_configure();
1640
	
1641
	/* set up LAN interface */
1642
	interfaces_lan_configure();
1643

    
1644
	/* set up WAN interface */
1645
	interfaces_wan_configure();
1646

    
1647
	/* set up Optional interfaces */
1648
	interfaces_optional_configure();
1649
        
1650
	/* bring up carp interfaces */
1651
	interfaces_carp_configure();
1652
	
1653
	/* set up static routes */
1654
	system_routing_configure();
1655

    
1656
	/* enable routing */
1657
	system_routing_enable();
1658
	
1659
	/* ensure passwords are sync'd */
1660
	system_password_configure();
1661

    
1662
	/* start dnsmasq service */
1663
	services_dnsmasq_configure();
1664

    
1665
	/* start dyndns service */
1666
	services_dyndns_configure();
1667

    
1668
	/* start DHCP service */
1669
	services_dhcpd_configure();
1670

    
1671
	/* start the NTP client */
1672
	system_ntp_configure();
1673

    
1674
	/* start ftp proxy helpers if they are enabled */
1675
	system_start_ftp_helpers();
1676

    
1677
	/* start the captive portal */
1678
	captiveportal_configure();
1679

    
1680
        /* reload the filter */
1681
	filter_configure_sync();
1682

    
1683
	/* bring up carp interfaces*/
1684
	interfaces_carp_bring_up_final();
1685
	
1686
	/* sync pw database */
1687
	conf_mount_rw();
1688
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1689
	conf_mount_ro();
1690

    
1691
	/* restart sshd */
1692
	touch("/tmp/start_sshd");
1693
	
1694
	/* restart webConfigurator if needed */
1695
	if($shutdown_webgui_needed == true) 
1696
		touch("/tmp/restart_webgui");
1697
	
1698
	mwexec("/bin/rm /tmp/reload*");
1699
	
1700
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1701
	
1702
}
1703

    
1704
function auto_login($status) {
1705
	$gettytab = file_get_contents("/etc/gettytab");
1706
	$getty_split = split("\n", $gettytab);
1707
	conf_mount_rw();
1708
	$fd = fopen("/etc/gettytab", "w");
1709
	foreach($getty_split as $gs) {
1710
		if(stristr($gs, "\:ht\:np\:sp\#115200") == true) {
1711
			if($status == true) {
1712
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
1713
			} else {
1714
				fwrite($fd, "	:ht:np:sp#115200:\n");
1715
			}
1716
		} else {
1717
			fwrite($fd, "{$gs}\n");
1718
		}
1719
	}
1720
	fclose($fd);
1721
	conf_mount_ro();	
1722
}
1723

    
1724
function setup_serial_port() {
1725
	global $g, $config;
1726
	conf_mount_rw();
1727
	/* serial console - write out /boot.config */
1728
	if(file_exists("/boot.config"))
1729
		$boot_config = file_get_contents("/boot.config");
1730
	else
1731
		$boot_config = "";
1732
	
1733
	if($g['platform'] <> "cdrom") {
1734
		$boot_config_split = split("\n", $boot_config);
1735
		$fd = fopen("/boot.config","w");
1736
		if($fd) {
1737
			foreach($boot_config_split as $bcs) {
1738
				if(stristr($bcs, "-D")) {
1739
					/* DONT WRITE OUT, WE'LL DO IT LATER */	
1740
				} else {
1741
					if($bcs <> "")
1742
						fwrite($fd, "{$bcs}\n");
1743
				}
1744
			}
1745
			if(isset($config['system']['enableserial'])) {
1746
				fwrite($fd, "-D");
1747
			}			
1748
			fclose($fd);
1749
		}
1750
		/* serial console - write out /boot/loader.conf */
1751
		$boot_config = file_get_contents("/boot/loader.conf");	
1752
		$boot_config_split = split("\n", $boot_config);
1753
		$fd = fopen("/boot/loader.conf","w");
1754
		if($fd) {
1755
			foreach($boot_config_split as $bcs) {
1756
				if(stristr($bcs, "console")) {
1757
					/* DONT WRITE OUT, WE'LL DO IT LATER */	
1758
				} else {
1759
					if($bcs <> "")
1760
						fwrite($fd, "{$bcs}\n");
1761
				}
1762
			}
1763
			if(isset($config['system']['enableserial'])) {
1764
				fwrite($fd, "console=\"comconsole\"\n");
1765
			}
1766
			fclose($fd);
1767
		}
1768
	}
1769
	if(isset($config['system']['disableconsolemenu'])) {
1770
		auto_login(true);
1771
	} else {
1772
		auto_login(false);
1773
	}	
1774
	conf_mount_ro();
1775
	return;	
1776
}
1777

    
1778
function print_value_list($list, $count = 10, $separator = ",") {
1779
	$list = implode($separator, array_slice($list, 0, $count));
1780
	if(count($list) < $count) {
1781
		$list .= ".";
1782
	} else {
1783
		$list .= "...";
1784
	}
1785
	return $list;
1786
}
1787

    
1788
function convert_friendly_interface_to_friendly_descr($interface) {
1789
	global $config;
1790
	/* attempt to resolve interface to friendly descr */
1791
	if($config['interfaces'][$interface]['descr']) 
1792
		return $config['interfaces'][$interface]['descr'];
1793
	$tmp = convert_real_interface_to_friendly_descr($interface);
1794
	/* could not resolve, return back what was passed */
1795
	return $interface;
1796
}
1797

    
1798
function convert_real_interface_to_friendly_descr($interface) {
1799
	global $config;
1800
	if($interface == $config['interfaces']['wan']['if'])
1801
		return "wan";
1802
	if($interface == $config['interfaces']['lan']['if'])
1803
		return "lan";
1804
	/* attempt to resolve interface to friendly descr */
1805
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
1806
	if($config['interfaces'][$friendly_int]['descr'])
1807
		return $config['interfaces'][$friendly_int]['descr'];
1808
	/* could not resolve, return back what was passed */
1809
	return $interface;
1810
}
1811

    
1812
function enable_rrd_graphing()
1813
{
1814
// consider syncing the rrd files to usb storage/xml (cdrom, embbedded)
1815

    
1816
	global $config, $g;
1817

    
1818
    $rrddbpath = "/var/db/rrd/";
1819
    $rrdgraphpath = "/usr/local/www/rrd";
1820
	$rrdtrafficinterval = 60;
1821
	$rrdqualityinterval = 60;
1822
	$rrdqueuesinterval = 60;
1823
	$rrdpacketsinterval = 60;
1824
	$rrdspamdinterval = 60;
1825

    
1826
	$traffic = "-traffic.rrd";
1827
	$packets = "-packets.rrd";
1828
	$quality = "-quality.rrd";
1829
	$queues = "-queues.rrd";
1830
	$spamd = "spamd.rrd";
1831
	$rrdtool = "/usr/local/bin/rrdtool";
1832
	$netstat = "/usr/bin/netstat";
1833
	$awk = "/usr/bin/awk";
1834
	$php = "/usr/local/bin/php";
1835
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
1836

    
1837
	$gatewayip = exec("/sbin/route -n get default | /usr/bin/grep gateway | /usr/bin/awk '{print $2}'");
1838
	/* if an alternative gateway is defined, use it. */
1839
	if($config['system']['use_rrd_gateway'])
1840
		$gatewayip = $config['system']['use_rrd_gateway'];
1841
	$numpings = 5;
1842
	$btick = '`';
1843

    
1844
	$trafficvalid = $rrdtrafficinterval*2 ;
1845
	$qualityvalid = $rrdqualityinterval*2 ;
1846
	$queuesvalid = $rrdqueuesinterval*2 ;
1847
	$packetsvalid = $rrdpacketsinterval*2 ;
1848
	$spamdvalid = $rrdspamdinterval*2 ;
1849

    
1850
	/* Asume GigE for now */
1851
	$downstream = 125000000;
1852
	$upstream   = 125000000;
1853

    
1854
	$config['rrd']['enable'] = true;
1855

    
1856
	if (isset($config['rrd']['enable'])) {
1857

    
1858
		/* create directory if needed */
1859
		safe_mkdir("$rrddbpath", 0755);
1860

    
1861
		/* if we are on livecd or embedded use a memoryfs. */
1862
		/* 3MB is enough for everyone. *cough* */
1863
		if($g['platform'] != "pfSense") {
1864
			/* determine highest MD device */
1865
			$mdnr = `mount |grep md | awk -F"md" '{print $2}'|tail -1 |cut -c 1`;
1866
			$mdnr = $mdnr +1;
1867
			system("/sbin/mdmfs -M -s 3m md$mdnr $rrddbpath");
1868
		}
1869

    
1870
		/* create symlink if needed */
1871
		if(!is_link("$rrdgraphpath")) {
1872
			exec("ln -s $rrddbpath $rrdgraphpath");
1873
		}
1874

    
1875
		/* db update script */
1876
		$rrdupdatesh = "#!/bin/sh\n";
1877
		$rrdupdatesh .= "\n";
1878
		$rrdupdatesh .= "counter=1\n";
1879
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
1880
		$rrdupdatesh .= "do\n";
1881
		$rrdupdatesh .= "";
1882

    
1883
		/* directory index */
1884
		$rrdgraphindexhtml = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">
1885
<HTML>
1886
<HEAD>
1887
    <TITLE>MRTG Index Page</TITLE>
1888
    <META HTTP-EQUIV=\"Refresh\" CONTENT=\"360\">
1889
    <META HTTP-EQUIV=\"Cache-Control\" content=\"no-cache\">
1890
    <META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">
1891
    <META HTTP-EQUIV=\"Expires\" CONTENT=\"Tue, 22 May 2001 09:22:45 GMT\">
1892
</HEAD>
1893
<BODY bgcolor=\"#ffffff\" text=\"#000000\" link=\"#000000\" vlink=\"#000000\" alink=\"#000000\">
1894
<H1>MRTG Index Page</H1>
1895
<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=10>";
1896

    
1897
       		$i = 0;
1898
                $vfaces = array("vlan.?*");
1899
                $ifdescrs = get_interface_list(true, true, $vfaces);
1900
       		foreach ($ifdescrs as $realif => $ifdescr) {
1901
			$ifname = $ifdescr['friendly'];
1902
			$state = $ifdescr['up'];
1903

    
1904
			/* skip interfaces that do not have a friendly name */
1905
			if("$ifname" == "") {
1906
				continue;
1907
			}
1908
			
1909
			/* or are down */
1910
			if(! $state) {
1911
				continue;
1912
			}
1913

    
1914
			/* set up the rrd file */
1915
			if(! file_exists("$rrddbpath$ifname$traffic")) {
1916
				/* create rrd file if it does not exist */
1917
				log_error("Create RRD database $rrddbpath$ifname$traffic");
1918
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval \
1919
					DS:in:COUNTER:$trafficvalid:0:$downstream \
1920
					DS:out:COUNTER:$trafficvalid:0:$upstream \
1921
					RRA:AVERAGE:0.5:1:1000 \
1922
					RRA:AVERAGE:0.5:5:1000 \
1923
					RRA:AVERAGE:0.5:60:1000 \
1924
					RRA:AVERAGE:0.5:360:1000 \
1925
					RRA:MAX:0.5:1:1000 \
1926
					RRA:MAX:0.5:5:1000 \
1927
					RRA:MAX:0.5:60:1000 \
1928
					RRA:MAX:0.5:3600:1000";
1929

    
1930
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
1931
				if($rrdcreatereturn != 0) {
1932
			                log_error("RRD create failed exited with $graphcmdreturn, the 
1933
						error is: $rrdcreateoutput[0]\n");
1934
				}
1935
			}
1936

    
1937
			$rrdupdatesh .= "\n";
1938
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
1939
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
1940
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7}'`:\\\n";
1941
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$10}'`\n\n";
1942

    
1943
			/* set up the rrd file */
1944
			if(! file_exists("$rrddbpath$ifname$packets")) {
1945
				/* create rrd file if it does not exist */
1946
				log_error("Create RRD database $rrddbpath$ifname$packets");
1947
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval \
1948
					DS:in:COUNTER:$packetsvalid:0:$downstream \
1949
					DS:out:COUNTER:$packetsvalid:0:$upstream \
1950
					RRA:AVERAGE:0.5:1:1000 \
1951
					RRA:AVERAGE:0.5:5:1000 \
1952
					RRA:AVERAGE:0.5:60:1000 \
1953
					RRA:AVERAGE:0.5:360:1000 \
1954
					RRA:MAX:0.5:1:1000 \
1955
					RRA:MAX:0.5:5:1000 \
1956
					RRA:MAX:0.5:60:1000 \
1957
					RRA:MAX:0.5:360:1000";
1958

    
1959
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
1960
				if($rrdcreatereturn != 0) {
1961
			                log_error("RRD create failed exited with $graphcmdreturn, the 
1962
						error is: $rrdcreateoutput[0]\n");
1963
				}
1964
			}
1965

    
1966
			$rrdupdatesh .= "\n";
1967
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
1968
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
1969
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5}'`:\\\n";
1970
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$8}'`\n\n";
1971

    
1972
			$rrdgraphindexhtml .= "<TR>
1973
<TD><DIV><B>Traffic Analysis for $ifname -- day</B></DIV>
1974
<DIV><IMG BORDER=1 ALT=\"$ifname Traffic Graph\" SRC=\"$ifname-day.png\">
1975
<BR>
1976
</TD>
1977
<TD><DIV><B>Traffic Analysis for $ifname -- week</B></DIV>
1978
<DIV><IMG BORDER=1 ALT=\"$ifname Traffic Graph\" SRC=\"$ifname-week.png\">
1979
<BR>
1980
</TD>
1981
</TR>";
1982

    
1983
			if("$ifname" == "wan") {
1984
				/* create link quality database */
1985
				if(! file_exists("$rrddbpath$ifname$quality")) {
1986
					/* create rrd file if it does not exist */
1987
					log_error("Create RRD database $rrddbpath$ifname$quality");
1988
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval \
1989
							DS:loss:GAUGE:$qualityvalid:0:100 \
1990
							DS:roundtrip:GAUGE:$qualityvalid:0:10000 \
1991
							RRA:AVERAGE:0.5:1:1000 \
1992
							RRA:AVERAGE:0.5:5:1000 \
1993
							RRA:AVERAGE:0.5:60:1000 \
1994
							RRA:AVERAGE:0.5:360:1000";
1995

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

    
2003
				/* the ping test function. We call this on the last line */
2004
				$rrdupdatesh .= "get_ping_stats () {
2005
					packetloss=100
2006
					roundtrip=0
2007
					local out
2008
					out=$btick ping -c $numpings -q $gatewayip $btick
2009
					if [ $? -eq 0 ]; then
2010
						packetloss=$btick echo \$out | cut -f18 -d' ' | cut -c -1 $btick
2011
						roundtrip=$btick echo \$out | cut -f24 -d' ' | cut -f2 -d'/' $btick
2012
					fi
2013
					$rrdtool update $rrddbpath$ifname$quality N:\$packetloss:\$roundtrip
2014
				}\n\n";
2015

    
2016
				$rrdupdatesh .= "get_ping_stats &\n\n";
2017

    
2018
				if (!is_array($config['shaper']['queue'])) {
2019
					$config['shaper']['queue'] = array();
2020
				}
2021
				$a_queues = &$config['shaper']['queue'];
2022

    
2023
				if(isset($config['shaper']['enable'])) {
2024
					if(!file_exists("$rrddbpath$ifname$queues")) {
2025
						/* create rrd file if it does not exist */
2026
						log_error("Create RRD database $rrddbpath$ifname$queues");
2027
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval \\\n";
2028
						/* loop list of shaper queues */
2029
						$q = 0;
2030
						 foreach ($a_queues as $queue) {
2031
							$name = $queue['name'];
2032
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream \\\n";
2033
						}
2034

    
2035
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 \
2036
							RRA:AVERAGE:0.5:5:1000 \
2037
							RRA:AVERAGE:0.5:60:1000 \
2038
							RRA:AVERAGE:0.5:360:1000";
2039

    
2040
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2041
						if($rrdcreatereturn != 0) {
2042
				        	        log_error("RRD create failed exited with $graphcmdreturn, the 
2043
								error is: $rrdcreateoutput[0]\n");
2044
						}
2045
					}
2046

    
2047
				/* awk function to gather shaper data */
2048
				/* yes, it's special */
2049
				$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } \\
2050
					{ \
2051
					if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { \\
2052
					        dsname = dsname \":\" \$2 ; \\
2053
					        q=1; \\
2054
					} \\
2055
					else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { \\
2056
					        dsdata = dsdata \":\" \$5 ; \\
2057
					        q=0; \\
2058
					} \\
2059
					} END { \\
2060
						dsname = substr(dsname,2); \\
2061
						dsdata = substr(dsdata,2); \\
2062
						printf \"-t \" dsname \" N:\" dsdata }' \\
2063
						dsname=\"\" dsdata=\"\"`\n\n";
2064
				}
2065
			}
2066

    
2067
	        }
2068
       		$i++;
2069

    
2070
		$rrdgraphindexhtml .= "</TABLE>
2071
</BODY>
2072
</HTML>";
2073

    
2074
		if(isset($config['installedpackages']['spamdsettings']['config']['enablerrd'])) {
2075
			/* set up the spamd rrd file */
2076
			if(! file_exists("$rrddbpath$spamd")) {
2077
				/* create rrd file if it does not exist */
2078
				log_error("Create RRD database $rrddbpath$spamd");
2079
				$rrdcreate = "$rrdtool create $rrddbpath$spamd --step $rrdspamdinterval \
2080
					DS:conn:GAUGE:$trafficvalid:0:10000 \
2081
					DS:time:GAUGE:$trafficvalid:0:86400 \
2082
					RRA:MIN:0.5:1:1000 \
2083
					RRA:MIN:0.5:5:1000 \
2084
					RRA:MIN:0.5:60:1000 \
2085
					RRA:MIN:0.5:360:1000 \
2086
					RRA:AVERAGE:0.5:1:1000 \
2087
					RRA:AVERAGE:0.5:5:1000 \
2088
					RRA:AVERAGE:0.5:60:1000 \
2089
					RRA:AVERAGE:0.5:360:1000 \
2090
					RRA:MAX:0.5:1:1000 \
2091
					RRA:MAX:0.5:5:1000 \
2092
					RRA:MAX:0.5:60:1000 \
2093
					RRA:MAX:0.5:360:1000";
2094

    
2095
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2096
				if($rrdcreatereturn != 0) {
2097
		        	        log_error("RRD create failed exited with $graphcmdreturn, the 
2098
						error is: $rrdcreateoutput[0]\n");
2099
				}
2100
			}
2101
		
2102
			$rrdupdatesh .= "\n";
2103
			$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
2104
			$rrdupdatesh .= "$rrdtool update $rrddbpath$spamd \\\n";
2105
			$rrdupdatesh .= "`$php -q $spamd_gather`\n";
2106

    
2107
		}
2108
	
2109
		$rrdupdatesh .= "sleep 60\n";
2110
		$rrdupdatesh .= "done\n";
2111
		log_error("Creating rrd update script");
2112
		/* write the rrd update script */
2113
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
2114
		$fd = fopen("$updaterrdscript", "w");
2115
		fwrite($fd, "$rrdupdatesh");
2116
		fclose($fd);
2117

    
2118
		log_error("Creating rrd graph index");
2119
		/* write the index.html script */
2120
		$rrdgraphindex = "{$g['vardb_path']}/rrd/index.html";
2121
		$fd = fopen("$rrdgraphindex", "w");
2122
		fwrite($fd, "$rrdgraphindexhtml");
2123
		fclose($fd);
2124
	
2125
		/* kill off traffic collectors */
2126
		kill_traffic_collector();
2127

    
2128
		/* start traffic collector */
2129
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
2130

    
2131
	} else {
2132
		/* unmount and remove */
2133
		system("/sbin/umount $rrddbpath");
2134
		exec("/sbin/mdconfig -d -u 2");
2135
		/* kill off traffic collectors */
2136
		kill_traffic_collector();
2137
	}
2138
}
2139

    
2140
function kill_traffic_collector() {
2141
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
2142
}
2143

    
2144
function update_filter_reload_status($text) {
2145
	global $g;
2146
	config_lock();
2147
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
2148
	fwrite($fd, $text);
2149
	fclose($fd);
2150
	config_unlock();
2151
}
2152

    
2153
?>
(14-14/27)