Project

General

Profile

Download (58 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) 2005 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['PHP_SELF'];
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
	$ints = `/sbin/ifconfig -l`;
515
	$ints_split = split(" ", $ints);
516
	$ip_subnet_split = split("\.", $ipaddress);
517
	$ip_subnet = $ip_subnet_split[0] . "." . $ip_subnet_split[1] . "." . $ip_subnet_split[2] . ".";
518
	/* check first 3 octets */
519
	foreach($ints_split as $int) {
520
		$ip = find_interface_ip($int);
521
		$ip_split = split("\.", $ip);
522
		$ip_tocheck = $ip_split[0] . "." . $ip_split[1] . "." . $ip_split[2] . ".";
523
		if(stristr($ip_subnet, $ip_tocheck) != false) return $int;
524
	}
525
	/* check first 2 octets since nothing found while checking 3 */
526
	foreach($ints_split as $int) {
527
		$ip = find_interface_ip($int);
528
		$ip_split = split("\.", $ip);
529
		$ip_tocheck = $ip_split[0] . "." . $ip_split[1] . ".";
530
		if(stristr($ip_subnet, $ip_tocheck) != false) return $int;
531
	}
532
}
533

    
534
function filter_opt_interface_to_real($opt) {
535
	global $config;
536
	return $config['interfaces'][$opt]['if'];
537
}
538

    
539
function filter_get_opt_interface_descr($opt) {
540
	global $config;
541
	return $config['interfaces'][$opt]['descr'];
542
}
543

    
544
function get_friendly_interface_list_as_array() {
545
	global $config;
546
	$ints = array();
547
	$ifdescrs = array('wan', 'lan');
548
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
549
		$ifdescrs['opt' . $j] = "opt" . $j;
550
	}
551
	$ifdescrs = get_interface_list();
552
	foreach ($ifdescrs as $ifdescr => $ifname) {
553
		array_push($ints,$ifdescr);
554
	}
555
	return $ints;
556
}
557

    
558
/*
559
 * find_ip_interface($ip): return the interface where an ip is defined
560
 */
561
function find_ip_interface($ip) {
562
	global $config;
563
	$ifdescrs = array('wan', 'lan');
564
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
565
		$ifdescrs['opt' . $j] = "opt" . $j;
566
	}
567
	foreach ($ifdescrs as $ifdescr => $ifname) {
568
		$int = filter_translate_type_to_real_interface($ifname);
569
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
570
	if(stristr($ifconfig,$ip) <> false)
571
		return $int;
572
	}
573
	return false;
574
}
575

    
576
/*
577
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
578
 *                                                       for a friendly interface.  ie: wan
579
 */
580
function filter_translate_type_to_real_interface($interface) {
581
	global $config;
582
	if($config['interfaces'][$interface]['if'] <> "") {
583
		return $config['interfaces'][$interface]['if'];
584
	} else {
585
		return $interface;
586
	}
587
}
588

    
589
/*
590
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
591
 */
592
function get_carp_interface_status($carpinterface) {
593
	/* basically cache the contents of ifconfig statement
594
	to speed up this routine */
595
	global $carp_query;
596
	if($carp_query == "")
597
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
598
	$found_interface = 0;
599
	foreach($carp_query as $int) {
600
		if($found_interface == 1) {
601
			if(stristr($int, "MASTER") == true) return "MASTER";
602
			if(stristr($int, "BACKUP") == true) return "BACKUP";
603
			if(stristr($int, "INIT") == true) return "INIT";
604
			return false;
605
		}
606
		if(stristr($int, $carpinterface) == true)
607
		$found_interface=1;
608
	}
609
	return;
610
}
611

    
612
/*
613
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
614
 */
615
function get_pfsync_interface_status($pfsyncinterface) {
616
    $result = does_interface_exist($pfsyncinterface);
617
    if($result <> true) return;
618
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
619
    return $status;
620
}
621

    
622
/*
623
 * find_carp_interface($ip): return the carp interface where an ip is defined
624
 */
625
function find_carp_interface($ip) {
626
	global $find_carp_ifconfig;
627
	if($find_carp_ifconfig == "") {
628
		$find_carp_ifconfig = array();
629
		$num_carp_ints = find_number_of_created_carp_interfaces();
630
		for($x=0; $x<$num_carp_ints; $x++) {
631
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
632
		}
633
	}
634
	$carps = 0;
635
	foreach($find_carp_ifconfig as $fci) {
636
		if(stristr($fci, $ip) == true)
637
			return "carp{$carps}";
638
		$carps++;
639
	}
640
}
641

    
642
/*
643
 * setup_filter_bridge(): toggle filtering bridge
644
 */
645
function setup_filter_bridge() {
646
	global $config, $g;
647
	if(isset($config['bridge']['filteringbridge'])) {
648
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
649
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
650
	} else {		
651
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
652
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
653
	}
654
}
655

    
656
/*
657
 * find_number_of_created_bridges(): returns the number of currently created bridges
658
 */
659
function find_number_of_created_bridges() {
660
	return `/sbin/ifconfig | grep \"bridge[0-999]\:" | wc -l`;
661
}
662

    
663
/*
664
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
665
 */
666
function add_rule_to_anchor($anchor, $rule, $label) {
667
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
668
}
669

    
670
/*
671
 * remove_text_from_file
672
 * remove $text from file $file
673
 */
674
function remove_text_from_file($file, $text) {
675
	global $fd_log;
676
	fwrite($fd_log, "Adding needed text items:\n");
677
	$filecontents = exec_command_and_return_text("cat " . $file);
678
	$textTMP = str_replace($text, "", $filecontents);
679
	$text .= $textTMP;
680
	fwrite($fd_log, $text . "\n");
681
	$fd = fopen($file, "w");
682
	fwrite($fd, $text);
683
	fclose($fd);
684
}
685

    
686
/*
687
 * add_text_to_file($file, $text): adds $text to $file.
688
 * replaces the text if it already exists.
689
 */
690
function add_text_to_file($file, $text) {
691
	if(file_exists($file) and is_writable($file)) {
692
		$filecontents = file($file);
693
		$filecontents[] = $text;
694
		$tmpfile = get_tmp_file();
695
		$fout = fopen($tmpfile, "w");
696
		foreach($filecontents as $line) {
697
			fwrite($fout, rtrim($line) . "\n");
698
		}
699
		fclose($fout);
700
		rename($tmpfile, $file);
701
		return true;
702
	} else {
703
		return false;
704
	}
705
}
706

    
707
/*
708
 *   after_sync_bump_adv_skew(): create skew values by 1S
709
 */
710
function after_sync_bump_adv_skew() {
711
	global $config, $g;
712
	$processed_skew = 1;
713
	$a_vip = &$config['virtualip']['vip'];
714
	foreach ($a_vip as $vipent) {
715
		if($vipent['advskew'] <> "") {
716
			$processed_skew = 1;
717
			$vipent['advskew'] = $vipent['advskew']+1;
718
		}
719
	}
720
	if($processed_skew == 1)
721
		write_config("After synch increase advertising skew");
722
}
723

    
724
/*
725
 * get_filename_from_url($url): converts a url to its filename.
726
 */
727
function get_filename_from_url($url) {
728
	return basename($url);
729
}
730

    
731
/*
732
 *   update_output_window: update bottom textarea dynamically.
733
 */
734
function update_output_window($text) {
735
	$log = ereg_replace("\n", "\\n", $text);
736
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
737
	/* ensure that contents are written out */
738
	ob_flush();
739
}
740

    
741
/*
742
 *   get_dir: return an array of $dir
743
 */
744
function get_dir($dir) {
745
	$dir_array = array();
746
	$d = dir($dir);
747
	while (false !== ($entry = $d->read())) {
748
		array_push($dir_array, $entry);
749
	}
750
	$d->close();
751
	return $dir_array;
752
}
753

    
754
/*
755
 *   update_output_window: update top textarea dynamically.
756
 */
757
function update_status($status) {
758
	echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
759
	/* ensure that contents are written out */
760
	ob_flush();
761
}
762

    
763
/*
764
 *   exec_command_and_return_text_array: execute command and return output
765
 */
766
function exec_command_and_return_text_array($command) {
767
	$fd = popen($command . " 2>&1 ", "r");
768
	while(!feof($fd)) {
769
		$tmp .= fread($fd,49);
770
	}
771
	fclose($fd);
772
	$temp_array = split("\n", $tmp);
773
	return $temp_array;
774
}
775

    
776
/*
777
 *   exec_command_and_return_text: execute command and return output
778
 */
779
function exec_command_and_return_text($command) {
780
	return exec_command($command);
781
}
782

    
783
/*
784
 *   exec_command_and_return_text: execute command and update output window dynamically
785
 */
786
function execute_command_return_output($command) {
787
	global $fd_log;
788
	$fd = popen($command . " 2>&1 ", "r");
789
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
790
	$counter = 0;
791
	$counter2 = 0;
792
	while(!feof($fd)) {
793
		$tmp = fread($fd, 50);
794
		$tmp1 = ereg_replace("\n","\\n", $tmp);
795
		$text = ereg_replace("\"","'", $tmp1);
796
		$lasttext = "";
797
		if($lasttext == "..") {
798
			$text = "";
799
			$lasttext = "";
800
			$counter=$counter-2;
801
		} else {
802
			$lasttext .= $text;
803
		}
804
		if($counter > 51) {
805
			$counter = 0;
806
			$extrabreak = "\\n";
807
		} else {
808
	    $extrabreak = "";
809
	    $counter++;
810
		}
811
		if($counter2 > 600) {
812
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
813
			$counter2 = 0;
814
		} else
815
			$counter2++;
816
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
817
	}
818
	fclose($fd);
819
}
820

    
821
/*
822
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
823
 */
824
function convert_friendly_interface_to_real_interface_name($interface) {
825
	global $config;
826
	$lc_interface = strtolower($interface);
827
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
828
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
829
	$ifdescrs = array();
830
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
831
		$ifdescrs['opt' . $j] = "opt" . $j;
832
	foreach ($ifdescrs as $ifdescr => $ifname) {
833
		if(strtolower($ifname) == $lc_interface)
834
	    return $config['interfaces'][$ifname]['if'];
835
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
836
			return $config['interfaces'][$ifname]['if'];
837
   }
838
   return $interface;
839
}
840

    
841
/*
842
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
843
 */
844
function convert_real_interface_to_friendly_interface_name($interface) {
845
	global $config;
846
	$ifdescrs = array('wan', 'lan');
847
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
848
		$ifdescrs['opt' . $j] = "opt" . $j;
849
	foreach ($ifdescrs as $ifdescr => $ifname) {
850
		$int = filter_translate_type_to_real_interface($ifname);
851
		if($ifname == $interface) return $ifname;
852
		if($int == $interface) return $ifname;
853
	}
854
	return $interface;
855
}
856

    
857
/*
858
 * update_progress_bar($percent): updates the javascript driven progress bar.
859
 */
860
function update_progress_bar($percent) {
861
	if($percent > 100) $percent = 1;
862
	echo "\n<script type=\"text/javascript\" language=\"javascript\">";
863
	echo "\ndocument.progressbar.style.width='" . $percent . "%';";
864
	echo "\n</script>";
865
}
866

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

    
905
/*
906
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
907
 *                             is queuename|qlength|measured_packets
908
 *                             NOTE: this command takes 5 seconds to run
909
 */
910
function gather_altq_queue_stats($dont_return_root_queues) {
911
	mwexec("/usr/bin/killall -9 pfctl");
912
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
913
	$stats_array = split("\n", $stats);
914
	$queue_stats = array();
915
	foreach ($stats_array as $stats_line) {
916
		$match_array = "";
917
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
918
			$queue_name = $match_array[1][0];
919
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
920
			$speed = $match_array[1][0];
921
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
922
			$borrows = $match_array[1][0];
923
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
924
			$suspends = $match_array[1][0];
925
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
926
			$drops = $match_array[1][0];
927
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
928
			$measured = $match_array[1][0];
929
			if($dont_return_root_queues == true)
930
				if(stristr($queue_name,"root_") == false)
931
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
932
		}
933
	}
934
	return $queue_stats;
935
}
936

    
937
/*
938
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
939
 *					 Useful for finding paths and stripping file extensions.
940
 */
941
function reverse_strrchr($haystack, $needle) {
942
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
943
}
944

    
945
/*
946
 *  backup_config_section($section): returns as an xml file string of
947
 *                                   the configuration section
948
 */
949
function backup_config_section($section) {
950
	global $config;
951
	$new_section = &$config[$section];
952
	/* generate configuration XML */
953
	$xmlconfig = dump_xml_config($new_section, $section);
954
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
955
	return $xmlconfig;
956
}
957

    
958
/*
959
 *  backup_vip_config_section($section): returns as an xml file string of
960
 *                                   the configuration section
961
 */
962
function backup_vip_config_section() {
963
	global $config;
964
	$new_section = &$config['virtualip'];
965
	foreach($new_section['vip'] as $section) {
966
		if($section['mode'] == "proxyarp") {
967
			unset($section);		
968
		}
969
		if($section['advskew'] <> "") {
970
			$section_val = intval($section['advskew']);
971
			$section_val=$section_val+100;
972
			if($section_val > 255)
973
				$section_val = 255;
974
			$section['advskew'] = $section_val;
975
		}
976
		$temp['vip'][] = $section;
977
   }
978
   return $temp;
979
}
980

    
981
/*
982
 *  restore_config_section($section, new_contents): restore a configuration section,
983
 *                                                  and write the configuration out
984
 *                                                  to disk/cf.
985
 */
986
function restore_config_section($section, $new_contents) {
987
	global $config, $g;
988
	conf_mount_rw();
989
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
990
	fwrite($fout, $new_contents);
991
	fclose($fout);
992
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
993
	$config[$section] = &$section_xml;
994
	unlink($g['tmp_path'] . "/tmpxml");
995
	write_config("Restored {$section} of config file (maybe from CARP partner)");
996
	conf_mount_ro();
997
	return;
998
}
999

    
1000
/*
1001
 * http_post($server, $port, $url, $vars): does an http post to a web server
1002
 *                                         posting the vars array.
1003
 * written by nf@bigpond.net.au
1004
 */
1005
function http_post($server, $port, $url, $vars) {
1006
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
1007
	$urlencoded = "";
1008
	while (list($key,$value) = each($vars))
1009
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
1010
	$urlencoded = substr($urlencoded,0,-1);
1011
	$content_length = strlen($urlencoded);
1012
	$headers = "POST $url HTTP/1.1
1013
Accept: */*
1014
Accept-Language: en-au
1015
Content-Type: application/x-www-form-urlencoded
1016
User-Agent: $user_agent
1017
Host: $server
1018
Connection: Keep-Alive
1019
Cache-Control: no-cache
1020
Content-Length: $content_length
1021

    
1022
";
1023

    
1024
	$errno = "";
1025
	$errstr = "";
1026
	$fp = fsockopen($server, $port, $errno, $errstr);
1027
	if (!$fp) {
1028
		return false;
1029
	}
1030

    
1031
	fputs($fp, $headers);
1032
	fputs($fp, $urlencoded);
1033

    
1034
	$ret = "";
1035
	while (!feof($fp))
1036
		$ret.= fgets($fp, 1024);
1037
	fclose($fp);
1038

    
1039
	return $ret;
1040
}
1041

    
1042
/*
1043
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
1044
 */
1045
if (!function_exists('php_check_syntax')){
1046
	function php_check_syntax($code_to_check, &$errormessage){
1047
		return false;
1048
		$fout = fopen("/tmp/codetocheck.php","w");
1049
		$code = $_POST['content'];
1050
		$code = str_replace("<?php", "", $code);
1051
		$code = str_replace("?>", "", $code);
1052
		fwrite($fout, "<?php\n\n");
1053
		fwrite($fout, $code_to_check);
1054
		fwrite($fout, "\n\n?>\n");
1055
		fclose($fout);
1056
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1057
		$output = exec_command($command);
1058
		if (stristr($output, "Errors parsing") == false) {
1059
			echo "false\n";
1060
			$errormessage = '';
1061
			return(false);
1062
		} else {
1063
			$errormessage = $output;
1064
			return(true);
1065
		}
1066
	}
1067
}
1068

    
1069
/*
1070
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1071
 */
1072
if (!function_exists('php_check_syntax')){
1073
	function php_check_syntax($code_to_check, &$errormessage){
1074
		return false;
1075
		$command = "/usr/local/bin/php -l " . $code_to_check;
1076
		$output = exec_command($command);
1077
		if (stristr($output, "Errors parsing") == false) {
1078
			echo "false\n";
1079
			$errormessage = '';
1080
			return(false);
1081
		} else {
1082
			$errormessage = $output;
1083
			return(true);
1084
		}
1085
	}
1086
}
1087

    
1088
/*
1089
 * rmdir_recursive($path,$follow_links=false)
1090
 * Recursively remove a directory tree (rm -rf path)
1091
 * This is for directories _only_
1092
 */
1093
function rmdir_recursive($path,$follow_links=false) {
1094
	$to_do = glob($path);
1095
	if(!is_array($to_do)) $to_do = array($to_do);
1096
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1097
		if(file_exists($workingdir)) {
1098
			if(is_dir($workingdir)) {
1099
				$dir = opendir($workingdir);
1100
				while ($entry = readdir($dir)) {
1101
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1102
						unlink("$workingdir/$entry");
1103
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
1104
						rmdir_recursive("$workingdir/$entry");
1105
				}
1106
				closedir($dir);
1107
				rmdir($workingdir);
1108
			} elseif (is_file($workingdir)) {
1109
				unlink($workingdir);
1110
			}
1111
               	}
1112
	}
1113
	return;
1114
}
1115

    
1116
/*
1117
 *     get_memory()
1118
 *     returns an array listing the amount of
1119
 *     memory installed in the hardware
1120
 *     [0]real and [1]available
1121
 */
1122
function get_memory() {
1123
	if(file_exists("/var/log/dmesg.boot")) {
1124
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1125
		$matches = "";
1126
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1127
			$real = $matches[1];
1128
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1129
			$avail = $matches[1];
1130
		return array($real[0],$avail[0]);
1131
	} else {
1132
		$mem = `dmesg -a`;
1133
		$matches = "";
1134
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1135
			$real = $matches[1];
1136
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1137
			$avail = $matches[1];
1138
		return array($real[0],$avail[0]);	
1139
	}
1140
	return array("64","64");
1141
}
1142

    
1143
/*
1144
 *    safe_mkdir($path, $mode = 0755)
1145
 *    create directory if it doesn't already exist and isn't a file!
1146
 */
1147
function safe_mkdir($path, $mode=0755) {
1148
	global $g;
1149

    
1150
	/* cdrom is ro. */
1151
	if($g['platform'] == "cdrom")
1152
		return false;
1153
	
1154
	if (!is_file($path) && !is_dir($path))
1155
		return mkdir($path, $mode);
1156
	else
1157
		return false;
1158
}
1159

    
1160
/*
1161
 * make_dirs($path, $mode = 0755)
1162
 * create directory tree recursively (mkdir -p)
1163
 */
1164
function make_dirs($path, $mode = 0755) {
1165
	/* is dir already created? */
1166
	if(is_dir($path)) return;
1167
	/* create directory in question */
1168
	$to_create = explode("/", $path);
1169
	foreach($to_create as $tc) 
1170
		if(!is_dir($tc))
1171
			safe_mkdir($path, $mode);
1172
}
1173

    
1174
/*
1175
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
1176
 */
1177
function call_pfsense_method($method, $params, $timeout = 0) {
1178
	global $g, $config;
1179
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
1180
	$xmlrpc_path = $g['xmlrpcpath'];
1181
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
1182
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
1183
	$resp = $cli->send($msg, $timeout);
1184
	if(!$resp) {
1185
		log_error("XMLRPC communication error: " . $cli->errstr);
1186
		return false;
1187
	} elseif($resp->faultCode()) {
1188
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
1189
		return false;
1190
	} else {
1191
		return XML_RPC_Decode($resp->value());
1192
	}
1193
}
1194

    
1195
/*
1196
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1197
 */
1198
function check_firmware_version($tocheck = "all", $return_php = true) {
1199
	global $g, $config;
1200
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
1201
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
1202
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
1203
		"platform" => trim(file_get_contents('/etc/platform'))
1204
		);
1205
	if($tocheck == "all") {
1206
		$params = $rawparams;
1207
	} else {
1208
		foreach($tocheck as $check) {
1209
			$params['check'] = $rawparams['check'];
1210
			$params['platform'] = $rawparams['platform'];
1211
		}
1212
	}
1213
	if($config['system']['firmware']['branch']) {
1214
		$params['branch'] = $config['system']['firmware']['branch'];
1215
	}
1216
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
1217
		return false;
1218
	} else {
1219
		$versions["current"] = $params;
1220
	}
1221
	return $versions;
1222
}
1223

    
1224
function get_disk_info() {
1225
	$diskout = "";
1226
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
1227
	return explode(' ', $diskout[0]);
1228
	// $size, $used, $avail, $cap
1229
}
1230

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

    
1283

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

    
1311
/****f* pfsense-utils/generate_random_mac_address
1312
 * NAME
1313
 *   generate_random_mac - generates a random mac address
1314
 * INPUTS
1315
 *   none
1316
 * RESULT
1317
 *   $mac - a random mac address
1318
 ******/
1319
function generate_random_mac_address() {
1320
	$mac = "00:a0:8e";
1321
	for($x=0; $x<3; $x++) 
1322
		$mac .= ":" . dechex(rand(16, 255));
1323

    
1324
	return $mac;
1325
}
1326

    
1327
/****f* pfsense-utils/strncpy
1328
 * NAME
1329
 *   strncpy - copy strings
1330
 * INPUTS
1331
 *   &$dst, $src, $length
1332
 * RESULT
1333
 *   none
1334
 ******/
1335
function strncpy(&$dst, $src, $length) {
1336
	if (strlen($src) > $length) {
1337
		$dst = substr($src, 0, $length);
1338
	} else {
1339
		$dst = $src;
1340
	}
1341
}
1342

    
1343
/****f* pfsense-utils/reload_interfaces_sync
1344
 * NAME
1345
 *   reload_interfaces - reload all interfaces
1346
 * INPUTS
1347
 *   none
1348
 * RESULT
1349
 *   none
1350
 ******/
1351
function reload_interfaces_sync() {
1352
	global $config, $g, $debug;
1353
	
1354
	$shutdown_webgui_needed = false;
1355
	
1356
	touch("{$g['tmp_path']}/reloading_all");
1357
	
1358
	$memory = get_memory();
1359
	$avail = $memory[0];
1360
	/* we have way too little memory.  shutdown webConfigurator temporarily */
1361
	if($avail > 0 and $avail < 66) {
1362
		log_error("Not enough ram for reload.  Temporarily unloading webConfigurator.");
1363
		$shutdown_webgui_needed = true;
1364
		config_lock();
1365
		/* kill any running lighttpd */
1366
		killbypid("{$g['varrun_path']}/lighty-webConfigurator.pid");
1367
		config_unlock();
1368
	}
1369
	
1370
	if($debug)
1371
		log_error("reload_interfaces_sync() is starting.");
1372
	
1373
	if(file_exists("{$g['tmp_path']}/config.cache"))
1374
		unlink("{$g['tmp_path']}/config.cache");
1375
	
1376
	/* parse config.xml again */
1377
	$config = parse_config(true);
1378
	
1379
	$wan_if = $config['interfaces']['wan']['if'];
1380
	$lan_if = $config['interfaces']['lan']['if'];
1381
	
1382
	if($debug)
1383
		log_error("Cleaning up Interfaces");
1384
	
1385
	foreach ($iflist as $ifent => $ifname) {
1386
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1387
		if(stristr($ifname, "lo0") == true)
1388
			continue;
1389
		/* do not process wan interface, its mandatory */
1390
		if(stristr($ifname, "$wan_if") == true)
1391
			continue;
1392
		/* do not process lan interface, its mandatory */
1393
		if(stristr($ifname, "$lan_if") == true)
1394
			continue;
1395
		if($debug)
1396
			log_error("Downing and deleting $ifname_real - $ifname");
1397
		mwexec("/sbin/ifconfig {$ifname_real} down");
1398
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1399
	}
1400

    
1401
	/* set up VLAN virtual interfaces */
1402
	if($debug)
1403
		log_error("Configuring VLANS");
1404
	interfaces_vlan_configure();
1405
	
1406
	/* set up LAN interface */
1407
	if($debug)
1408
		log_error("Configuring LAN");
1409
	interfaces_lan_configure();
1410

    
1411
	/* set up WAN interface */
1412
	if($debug)
1413
		log_error("Configuring WAN");
1414
	interfaces_wan_configure();
1415
	
1416
	/* set up Optional interfaces */
1417
	if($debug)
1418
		log_error("Configuring optional interfaces");
1419
	interfaces_optional_configure();
1420
	    
1421
	/* set up static routes */
1422
	if($debug)
1423
		log_error("Configuring system Routing");
1424
	system_routing_configure();
1425
	
1426
	/* enable routing */
1427
	if($debug)
1428
		log_error("Enabling system routing");
1429
	system_routing_enable();
1430

    
1431
	/* setup captive portal if needed */
1432
	if($debug)
1433
		log_error("Configuring Captive portal");
1434
	captiveportal_configure();
1435

    
1436
	/* bring up carp interfaces */
1437
	if($debug)
1438
		log_error("Configuring CARP");
1439
	interfaces_carp_configure();
1440
	
1441
	/* bring up carp interfaces*/
1442
	if($debug)
1443
		log_error("Bringing up CARP interfaces");
1444
	interfaces_carp_bring_up_final();
1445
	
1446
	/* restart webConfigurator if needed */
1447
	if($shutdown_webgui_needed == true) 
1448
		touch("/tmp/restart_webgui");
1449
	
1450
	reset_terminals();
1451
	
1452
	/* remove reloading_all trigger */
1453
	if($debug)
1454
		log_error("Removing {$g['tmp_path']}/reloading_all");
1455
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1456
}
1457

    
1458
function reset_terminals() {
1459
	$tokill = array(split("\n", `ps awwwux | grep initial | grep -v grep | cut -d" " -f7`));
1460
	foreach ($tokill as $killme) {
1461
		mwexec("/bin/kill $killme");
1462
	}
1463
	$tokill = array(split("\n", `ps awwwux | grep rc.banner | grep -v grep | cut -d" " -f5`));
1464
	foreach ($tokill as $killme) {
1465
		mwexec("/bin/kill $killme");
1466
	}
1467
}
1468

    
1469
/****f* pfsense-utils/reload_all
1470
 * NAME
1471
 *   reload_all - triggers a reload of all settings
1472
 *   * INPUTS
1473
 *   none
1474
 * RESULT
1475
 *   none
1476
 ******/
1477
function reload_all() {
1478
	touch("/tmp/reload_all");
1479
}
1480

    
1481
/****f* pfsense-utils/reload_interfaces
1482
 * NAME
1483
 *   reload_interfaces - triggers a reload of all interfaces
1484
 * INPUTS
1485
 *   none
1486
 * RESULT
1487
 *   none
1488
 ******/
1489
function reload_interfaces() {
1490
	touch("/tmp/reload_interfaces");
1491
}
1492

    
1493
/****f* pfsense-utils/sync_webgui_passwords
1494
 * NAME
1495
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1496
 * INPUTS
1497
 *   none
1498
 * RESULT
1499
 *   none
1500
 ******/
1501
function sync_webgui_passwords() {
1502
	global $config, $g;
1503
	conf_mount_rw();
1504
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
1505
	if (!$fd) {
1506
		printf("Error: cannot open htpasswd in system_password_configure().\n");
1507
		return 1;
1508
	}
1509
	/* set admin account */
1510
	$username = $config['system']['username'];
1511
	
1512
	/* set defined user account */
1513
	if($username <> "admin") {
1514
		$username = $config['system']['username'];
1515
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1516
	} else {
1517
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");	
1518
	}	
1519
	fclose($fd);
1520
	chmod("{$g['varrun_path']}/htpasswd", 0600);	
1521
	$crypted_pw = $config['system']['password'];
1522
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1523
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1524
	/* sync root */
1525
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
1526
	fwrite($fd, $crypted_pw);
1527
	pclose($fd);
1528
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
1529
	/* sync admin */
1530
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
1531
	fwrite($fd, $crypted_pw);
1532
	pclose($fd);
1533
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
1534
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1535
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1536
	conf_mount_ro();
1537
}
1538

    
1539
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
1540
 * NAME
1541
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
1542
 *   * INPUTS
1543
 *   optional interface number
1544
 * RESULT
1545
 *   none
1546
 ******/
1547
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
1548
	global $config;
1549
	unlink_if_exists("/tmp/config.cache");
1550
	$config_file = file_get_contents("/cf/conf/config.xml");
1551
	/* loop through and reassign optional items */
1552
	for ($i = 255; isset($config['interfaces']['opt' . $i]); $i--) {
1553
		if($i < $opt_interface_num)
1554
			break;
1555
		/* replace opt$i with $i -1 */
1556
		str_replace("opt" . $i, "opt" . ($i-1), $config_file);
1557
	}
1558
	$fd = fopen("/cf/conf/config.xml", "w");
1559
	fwrite($fd, $config_file);
1560
	fclose($fd);
1561
	$config = parse_config(true);
1562
	return true;
1563
}
1564

    
1565
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
1566
 * NAME
1567
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
1568
 *   		amount of netgraph interfaces needed for system wans
1569
 *   * INPUTS
1570
 *   none
1571
 * RESULT
1572
 *   number of needed netgraph (ng) interfaces
1573
 ******/
1574
function get_number_of_wan_netgraph_interfaces_needed() {
1575
	global $config, $g;
1576
	/* build an array of interfaces to work with */
1577
	$iflist = array("wan" => "WAN");
1578
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1579
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1580
	$ng_interfaces_needed = 0;
1581
	foreach ($iflist as $ifent => $ifname) {
1582
		if($config['inerfaces'][$ifname]['ipaddr'] == "pppoe") {
1583
			$ng_interfaces_needed++;
1584
		}
1585
	}
1586
	return $ng_interfaces_needed;
1587
}
1588

    
1589
function get_netgaph_interface_assignment($friendly_interface) {
1590
	global $config, $g;
1591
	/* build an array of interfaces to work with */
1592
	$iflist = array("wan" => "WAN");
1593
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1594
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1595
		$ng_interfaces_needed = 0;
1596
		$ng_interfaces_number = 0;
1597
		foreach ($iflist as $ifent => $ifname) {
1598
		if($config['inerfaces'][$ifname]['ipaddr'] == "pppoe") {
1599
			$ng_interfaces_number++;
1600
		}
1601
		if($friendly_interface == $ifname)
1602
			break;
1603
	}
1604
	return $ng_interfaces_number;	
1605
}
1606

    
1607
/****f* pfsense-utils/reload_all_sync
1608
 * NAME
1609
 *   reload_all - reload all settings
1610
 *   * INPUTS
1611
 *   none
1612
 * RESULT
1613
 *   none
1614
 ******/
1615
function reload_all_sync() {
1616
	global $config, $g;
1617
	
1618
	touch("{$g['tmp_path']}/reloading_all");
1619

    
1620
	$shutdown_webgui_needed = false;
1621

    
1622
	$memory = get_memory();
1623
	$avail = $memory[0];
1624
	/* we have way too little memory.  shutdown webConfigurator temporarily */
1625
	if($avail > 0 and $avail < 66) {
1626
		log_error("Not enough ram for reload.  Temporarily unloading webConfigurator.");
1627
		$shutdown_webgui_needed = true;
1628
		config_lock();
1629
		/* kill any running lighttpd */
1630
		killbypid("{$g['varrun_path']}/lighty-webConfigurator.pid");
1631
		config_unlock();
1632
	}
1633
	
1634
	if(file_exists("{$g['tmp_path']}/config.cache"))
1635
		unlink("{$g['tmp_path']}/config.cache");
1636
	
1637
	/* parse config.xml again */
1638
	$config = parse_config(true);
1639

    
1640
	/* set up our timezone */
1641
	system_timezone_configure();
1642

    
1643
	/* set up our hostname */
1644
	system_hostname_configure();
1645

    
1646
	/* make hosts file */
1647
	system_hosts_generate();
1648

    
1649
	/* generate resolv.conf */
1650
	system_resolvconf_generate();
1651

    
1652
	/* delete all old interface information */
1653
	$iflist = split(" ", str_replace("\n", "", `/sbin/ifconfig -l`));
1654
	
1655
	$wan_if = $config['interfaces']['wan']['if'];
1656
	$lan_if = $config['interfaces']['lan']['if'];
1657
	
1658
	foreach ($iflist as $ifent => $ifname) {
1659
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1660
		if(stristr($ifname, "lo0") == true)
1661
			continue;
1662
		/* do not process wan interface, its mandatory */
1663
		if($wan_if == $ifname_real)
1664
			continue;
1665
		/* do not process lan interface, its mandatory */
1666
		if($lan_if == $ifname_real)
1667
			continue;
1668
		mwexec("/sbin/ifconfig {$ifname_real} down");
1669
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1670
	}
1671

    
1672
	/* set up VLAN virtual interfaces */
1673
	interfaces_vlan_configure();
1674
	
1675
	/* set up LAN interface */
1676
	interfaces_lan_configure();
1677

    
1678
	/* set up WAN interface */
1679
	interfaces_wan_configure();
1680

    
1681
	/* set up Optional interfaces */
1682
	interfaces_optional_configure();
1683
        
1684
	/* bring up carp interfaces */
1685
	interfaces_carp_configure();
1686
	
1687
	/* set up static routes */
1688
	system_routing_configure();
1689

    
1690
	/* enable routing */
1691
	system_routing_enable();
1692
	
1693
	/* ensure passwords are sync'd */
1694
	system_password_configure();
1695

    
1696
	/* start dnsmasq service */
1697
	services_dnsmasq_configure();
1698

    
1699
	/* start dyndns service */
1700
	services_dyndns_configure();
1701

    
1702
	/* start DHCP service */
1703
	services_dhcpd_configure();
1704

    
1705
	/* start the NTP client */
1706
	system_ntp_configure();
1707

    
1708
	/* start ftp proxy helpers if they are enabled */
1709
	system_start_ftp_helpers();
1710

    
1711
	/* start the captive portal */
1712
	captiveportal_configure();
1713

    
1714
        /* reload the filter */
1715
	filter_configure_sync();
1716

    
1717
	/* bring up carp interfaces*/
1718
	interfaces_carp_bring_up_final();
1719
	
1720
	/* sync pw database */
1721
	conf_mount_rw();
1722
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1723
	conf_mount_ro();
1724

    
1725
	/* restart sshd */
1726
	touch("/tmp/start_sshd");
1727

    
1728
	/* restart webConfigurator if needed */
1729
	if($shutdown_webgui_needed == true) 
1730
		touch("/tmp/restart_webgui");
1731
	
1732
	reset_terminals();
1733
	
1734
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1735
	
1736
}
1737

    
1738
function auto_login($status) {
1739
	$gettytab = file_get_contents("/etc/gettytab");
1740
	$getty_split = split("\n", $gettytab);
1741
	conf_mount_rw();
1742
	$fd = fopen("/etc/gettytab", "w");
1743
	foreach($getty_split as $gs) {
1744
		if(stristr($gs, "\:ht\:np\:sp\#115200") == true) {
1745
			if($status == true) {
1746
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
1747
			} else {
1748
				fwrite($fd, "	:ht:np:sp#115200:\n");
1749
			}
1750
		} else {
1751
			fwrite($fd, "{$gs}\n");
1752
		}
1753
	}
1754
	fclose($fd);
1755
	conf_mount_ro();	
1756
}
1757

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

    
1812
function print_value_list($list, $count = 10, $separator = ",") {
1813
	$list = implode($separator, array_slice($list, 0, $count));
1814
	if(count($list) < $count) {
1815
		$list .= ".";
1816
	} else {
1817
		$list .= "...";
1818
	}
1819
	return $list;
1820
}
1821

    
1822
function convert_friendly_interface_to_friendly_descr($interface) {
1823
	global $config;
1824
	/* attempt to resolve interface to friendly descr */
1825
	if($config['interfaces'][$interface]['descr']) 
1826
		return $config['interfaces'][$interface]['descr'];
1827
	$tmp = convert_real_interface_to_friendly_descr($interface);
1828
	/* could not resolve, return back what was passed */
1829
	return $interface;
1830
}
1831

    
1832
function convert_real_interface_to_friendly_descr($interface) {
1833
	global $config;
1834
	if($interface == $config['interfaces']['wan']['if'])
1835
		return "wan";
1836
	if($interface == $config['interfaces']['lan']['if'])
1837
		return "lan";
1838
	/* attempt to resolve interface to friendly descr */
1839
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
1840
	if($config['interfaces'][$friendly_int]['descr'])
1841
		return $config['interfaces'][$friendly_int]['descr'];
1842
	/* could not resolve, return back what was passed */
1843
	return $interface;
1844
}
1845

    
1846
function enable_rrd_graphing()
1847
{
1848
// create a silent cron job for every 1 minute (because of GigE)
1849
// consider syncing the rrd files to usb storage (cdrom, embbedded)
1850
// FIXME: remove_text_from_file is broken and adds text instead
1851
// Needs to be called on rc.new_wan_ip, assign interface and boottime
1852

    
1853
	global $config, $g;
1854

    
1855
	$rrddbpath = "/var/db/rrd/";
1856
	$rrdgraphpath = "/usr/local/www/rrd";
1857
	$rrdtrafficinterval = 60;
1858
	$rrdqualityinterval = 60;
1859
	$rrdqueuesinterval = 60;
1860

    
1861
	$traffic = "-traffic.rrd";
1862
	$quality = "-quality.rrd";
1863
	$queues = "-queues.rrd";
1864
	$rrdtool = "/usr/local/bin/rrdtool";
1865
	$netstat = "/usr/bin/netstat";
1866
	$awk = "/usr/bin/awk";
1867
	$gatewayip = exec("route -n get default | grep gateway | awk '{print $2}'");
1868
	/* if an alternative gateway is defined, use it. */
1869
	if($config['system']['use_rrd_gateway'])
1870
		$gatewayip = $config['system']['use_rrd_gateway'];
1871
	$numpings = 15;
1872
	$btick = '`';
1873

    
1874
	$trafficvalid = $rrdtrafficinterval*2 ;
1875
	$qualityvalid = $rrdtrafficinterval*2 ;
1876
	$queuesvalid = $rrdtrafficinterval*2 ;
1877
	/* Asume GigE for now */
1878
	$downstream = 12500000;
1879
	$upstream = 12500000;
1880

    
1881
	$config['rrd']['enable'] = true;
1882

    
1883
	if (isset($config['rrd']['enable'])) {
1884

    
1885
		/* create directory if needed */
1886
		if(!is_dir("$rrddbpath")) {
1887
			mkdir("$rrddbpath", 0755);
1888
		}
1889

    
1890
		/* if we are on livecd or embedded use a memoryfs. */
1891
		/* 3MB is enough for everyone. *cough* */
1892
		if($g['platform'] != "pfSense") {
1893
			system("/sbin/mdmfs -M -s 3m md2 $rrddbpath");
1894
		}
1895

    
1896
		/* create symlink if needed */
1897
		if(!is_link("$rrdgraphpath")) {
1898
			exec("ln -s $rrddbpath $rrdgraphpath");
1899
		}
1900

    
1901
		/* db update script */
1902
		$rrdupdatesh = "#!/bin/sh\n";
1903
		$rrdupdatesh .= "\n";
1904
		$rrdupdatesh .= "counter=1\n";
1905
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
1906
		$rrdupdatesh .= "do\n";
1907
		$rrdupdatesh .= "";
1908

    
1909
		/* directory index */
1910
		$rrdgraphindexhtml = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">
1911
<HTML>
1912
<HEAD>
1913
    <TITLE>MRTG Index Page</TITLE>
1914
    <META HTTP-EQUIV=\"Refresh\" CONTENT=\"360\">
1915
    <META HTTP-EQUIV=\"Cache-Control\" content=\"no-cache\">
1916
    <META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">
1917
    <META HTTP-EQUIV=\"Expires\" CONTENT=\"Tue, 22 May 2001 09:22:45 GMT\">
1918
</HEAD>
1919
<BODY bgcolor=\"#ffffff\" text=\"#000000\" link=\"#000000\" vlink=\"#000000\" alink=\"#000000\">
1920
<H1>MRTG Index Page</H1>
1921
<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=10>";
1922

    
1923
       		$i = 0;
1924
		$ifdescrs = get_interface_list();
1925
       		foreach ($ifdescrs as $realif => $ifdescr) {
1926
			$ifname = $ifdescr['friendly'];
1927
			$state = $ifdescr['up'];
1928

    
1929
			/* skip interfaces that do not have a friendly name */
1930
			if("$ifname" == "") {
1931
				continue;
1932
			}
1933
			
1934
			/* or are down */
1935
			if(! $state) {
1936
				continue;
1937
			}
1938

    
1939
			/* set up the rrd file */
1940
			if(! file_exists("$rrddbpath$ifname$traffic")) {
1941
				/* create rrd file if it does not exist */
1942
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval \
1943
					DS:in:COUNTER:$trafficvalid:0:$downstream \
1944
					DS:out:COUNTER:$trafficvalid:0:$upstream \
1945
					RRA:AVERAGE:0.5:1:2000 \
1946
					RRA:AVERAGE:0.5:6:2000 \
1947
					RRA:AVERAGE:0.5:24:2000 \
1948
					RRA:AVERAGE:0.5:288:2000 \
1949
					RRA:MAX:0.5:1:2000 \
1950
					RRA:MAX:0.5:6:2000 \
1951
					RRA:MAX:0.5:24:2000 \
1952
					RRA:MAX:0.5:288:2000";
1953

    
1954
				$rrdcreatel .= exec("$rrdcreate 2>&1");
1955
			}
1956

    
1957
			$rrdupdatesh .= "\n";
1958
			$rrdupdatesh .= "# polling for interface $ifname $realif \n";
1959

    
1960
	                /* use the lan ip address for polling snmp stats*/
1961
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
1962
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7}'`:\\\n";
1963
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$10}'`\n";
1964

    
1965
			$rrdgraphindexhtml .= "<TR>
1966
<TD><DIV><B>Traffic Analysis for $ifname -- day</B></DIV>
1967
<DIV><IMG BORDER=1 ALT=\"$ifname Traffic Graph\" SRC=\"$ifname-day.png\">
1968
<BR>
1969
</TD>
1970
<TD><DIV><B>Traffic Analysis for $ifname -- week</B></DIV>
1971
<DIV><IMG BORDER=1 ALT=\"$ifname Traffic Graph\" SRC=\"$ifname-week.png\">
1972
<BR>
1973
</TD>
1974
</TR>";
1975

    
1976
			if("$ifname" == "wan") {
1977
				if(! file_exists("$rrddbpath$ifname$quality")) {
1978
					/* create rrd file if it does not exist */
1979
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval \
1980
							DS:loss:GAUGE:$qualityvalid:0:100 \
1981
							DS:roundtrip:GAUGE:$qualityvalid:0:10000 \
1982
							RRA:AVERAGE:0.5:1:120 \
1983
							RRA:AVERAGE:0.5:3:320 \
1984
							RRA:AVERAGE:0.5:10:288";
1985

    
1986
					$rrdcreatel .= exec("$rrdcreate 2>&1");
1987
				}
1988

    
1989
				/* the ping test function. We call this on the last line */
1990
				$rrdupdatesh .= "get_ping_stats () {
1991
					packetloss=100
1992
					roundtrip=0
1993
					local out
1994
					out=$btick ping -c $numpings -q $gatewayip $btick
1995
					if [ $? -eq 0 ]; then
1996
						packetloss=$btick echo \$out | cut -f18 -d' ' | cut -c -1 $btick
1997
						roundtrip=$btick echo \$out | cut -f24 -d' ' | cut -f2 -d'/' $btick
1998
					fi
1999
					$rrdtool update $rrddbpath$ifname$quality N:\$packetloss:\$roundtrip
2000
				}\n";
2001

    
2002
				$rrdupdatesh .= "get_ping_stats &\n";
2003

    
2004
				if(! file_exists("$rrddbpath$ifname$queues")) {
2005
					/* create rrd file if it does not exist */
2006
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval \
2007
						DS:pr0:COUNTER:$queuesvalid:0:$downstream \
2008
						DS:pr1:COUNTER:$queuesvalid:0:$downstream \
2009
						DS:pr2:COUNTER:$queuesvalid:0:$downstream \
2010
						DS:pr0u:COUNTER:$queuesvalid:0:$upstream  \
2011
						DS:pr1u:COUNTER:$queuesvalid:0:$upstream  \
2012
						DS:pr2u:COUNTER:$queuesvalid:0:$upstream  \
2013
						RRA:AVERAGE:0.5:1:120 \
2014
						RRA:AVERAGE:0.5:3:320 \
2015
						RRA:AVERAGE:0.5:10:288";
2016

    
2017
					$rrdcreatel .= exec("$rrdcreate 2>&1");
2018
					$rrdcreatel .= "\n";
2019
				}
2020
			}
2021

    
2022
	        }
2023
       		$i++;
2024

    
2025
		$rrdgraphindexhtml .= "</TABLE>
2026
</BODY>
2027
</HTML>";
2028
	
2029
		$rrdupdatesh .= "sleep 60\n";
2030
		$rrdupdatesh .= "done\n";
2031
		PRINT "Creating rrd update script\n";
2032
		/* write the rrd update script */
2033
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
2034
		$fd = fopen("$updaterrdscript", "w");
2035
		fwrite($fd, "$rrdupdatesh");
2036
		fclose($fd);
2037

    
2038
		PRINT "Creating rrd graph index\n";
2039
		/* write the index.html script */
2040
		$rrdgraphindex = "{$g['vardb_path']}/rrd/index.html";
2041
		$fd = fopen("$rrdgraphindex", "w");
2042
		fwrite($fd, "$rrdgraphindexhtml");
2043
		fclose($fd);
2044
	
2045
		/* print database creation errors. */
2046
		print "$rrdcreatel\n";
2047

    
2048
		/* kill off traffic collectors */
2049
		kill_traffic_collector();
2050

    
2051
		/* start traffic collector */
2052
		mwexec_bg("/bin/sh $updaterrdscript");
2053

    
2054
	} else {
2055
		/* unmount and remove */
2056
		system("/sbin/umount $rrddbpath");
2057
		exec("/sbin/mdconfig -d -u 2");
2058
		/* kill off traffic collectors */
2059
		kill_traffic_collector();
2060
	}
2061
}
2062

    
2063
function kill_traffic_collector() {
2064
		mwexec("ps awwwux | grep '/[v]ar/run/rrd/updaterrd.sh' | awk '{print $2}' | xargs kill");
2065
}
2066

    
2067
?>
(14-14/27)