Project

General

Profile

Download (64.1 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/pfsense-utils
3
 * NAME
4
 *   pfsense-utils.inc - Utilities specific to pfSense
5
 * DESCRIPTION
6
 *   This include contains various pfSense specific functions.
7
 * HISTORY
8
 *   $Id$
9
 ******
10
 *
11
 * Copyright (C) 2004-2006 Scott Ullrich (sullrich@gmail.com)
12
 * All rights reserved.
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *
16
 * 1. Redistributions of source code must retain the above copyright notice,
17
 * this list of conditions and the following disclaimer.
18
 *
19
 * 2. Redistributions in binary form must reproduce the above copyright
20
 * notice, this list of conditions and the following disclaimer in the
21
 * documentation and/or other materials provided with the distribution.
22
 *
23
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
27
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
 * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 * POSSIBILITY OF SUCH DAMAGE.
33
 *
34
 */
35

    
36
function get_tmp_file() {
37
	return "/tmp/tmp-" . time();
38
}
39

    
40
/****f* pfsense-utils/reset_carp
41
 * NAME
42
 *   reset_carp - resets carp after primary interface changes
43
 * INPUTS
44
 *   null
45
 * RESULT
46
 *   null
47
 ******/
48
function reset_carp() {
49
	$carp_counter=find_number_of_created_carp_interfaces();
50
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
51
	for($x=0; $x<$carp_counter; $x++) {
52
		mwexec("/sbin/ifconfig carp{$x} down");
53
		mwexec("/sbin/ifconfig carp{$x} destroy");
54
	}
55
	sleep(1);
56
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
57
	interfaces_carp_configure();
58
	interfaces_carp_bring_up_final();
59
}
60

    
61
/****f* pfsense-utils/get_dns_servers
62
 * NAME
63
 *   get_dns_servres - get system dns servers
64
 * INPUTS
65
 *   $dns_servers - an array of the dns servers
66
 * RESULT
67
 *   null
68
 ******/
69
function get_dns_servers() {
70
	$dns_servers = array();
71
	$dns = `cat /etc/resolv.conf`;
72
	$dns_s = split("\n", $dns);
73
	foreach($dns_s as $dns) {
74
		$matches = "";
75
		if (preg_match("/nameserver (.*)/", $dns, $matches))
76
			$dns_servers[] = $matches[1];
77
	}
78
	$dns_server_master = array();
79
	sort($dns_servers);
80
	$lastseen = "";
81
	foreach($dns_servers as $t) {
82
		if($t <> $lastseen)
83
			if($t <> "")
84
				$dns_server_master[] = $t;
85
		$lastseen = $t;
86
	}
87
	return $dns_server_master;
88
}
89

    
90
/****f* pfsense-utils/log_error
91
* NAME
92
*   log_error  - Sends a string to syslog.
93
* INPUTS
94
*   $error     - string containing the syslog message.
95
* RESULT
96
*   null
97
******/
98
function log_error($error) {
99
	$page = $_SERVER['SCRIPT_NAME'];
100
	syslog(LOG_WARNING, "$page: $error");
101
	return;
102
}
103

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

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

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

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

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

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

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

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

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

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

    
250
	setup_polling_defaults();
251

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
515
	$capable = $g['vlan_long_frame'];
516

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
895
/****f* pfsense-utils/WakeOnLan
896
 * NAME
897
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
898
 * RESULT
899
 *   true/false - true if the operation was successful
900
 ******/
901
function WakeOnLan($addr, $mac)
902
{
903
	$addr_byte = explode(':', $mac);
904
	$hw_addr = '';
905

    
906
	for ($a=0; $a < 6; $a++)
907
		$hw_addr .= chr(hexdec($addr_byte[$a]));
908

    
909
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
910

    
911
	for ($a = 1; $a <= 16; $a++)
912
		$msg .= $hw_addr;
913

    
914
	// send it to the broadcast address using UDP
915
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
916
	if ($s == false) {
917
		log_error("Error creating socket!");
918
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
919
	} else {
920
		// setting a broadcast option to socket:
921
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
922
		if($opt_ret < 0)
923
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
924
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
925
		socket_close($s);
926
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
927
		return true;
928
	}
929

    
930
	return false;
931
}
932

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

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

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

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

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

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

    
1050
";
1051

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

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

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

    
1067
	return $ret;
1068
}
1069

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

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

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

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

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

    
1177
	/* cdrom is ro. */
1178
	if($g['platform'] == "cdrom")
1179
		return false;
1180

    
1181
	if (!is_file($path) && !is_dir($path))
1182
		return mkdir($path, $mode);
1183
	else
1184
		return false;
1185
}
1186

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

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

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

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

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

    
1310
	echo "<script type=\"text/javascript\">";
1311
	echo "NiftyCheck();\n";
1312
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1313
	for($x=0; $x<$tabscounter; $x++)
1314
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1315
	echo "</script>";
1316
}
1317

    
1318

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

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

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

    
1377
/****f* pfsense-utils/reload_interfaces_sync
1378
 * NAME
1379
 *   reload_interfaces - reload all interfaces
1380
 * INPUTS
1381
 *   none
1382
 * RESULT
1383
 *   none
1384
 ******/
1385
function reload_interfaces_sync() {
1386
	global $config, $g, $debug;
1387

    
1388
	$shutdown_webgui_needed = false;
1389

    
1390
	touch("{$g['tmp_path']}/reloading_all");
1391

    
1392
	if($debug)
1393
		log_error("reload_interfaces_sync() is starting.");
1394

    
1395
	if(file_exists("{$g['tmp_path']}/config.cache"))
1396
		unlink("{$g['tmp_path']}/config.cache");
1397

    
1398
	/* parse config.xml again */
1399
	$config = parse_config(true);
1400

    
1401
	$wan_if = $config['interfaces']['wan']['if'];
1402
	$lan_if = $config['interfaces']['lan']['if'];
1403

    
1404
	if($debug)
1405
		log_error("Cleaning up Interfaces");
1406

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

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

    
1428
	/* set up VLAN virtual interfaces */
1429
	if($debug)
1430
		log_error("Configuring VLANS");
1431
	interfaces_vlan_configure();
1432

    
1433
	/* set up LAN interface */
1434
	if($debug)
1435
		log_error("Configuring LAN");
1436
	interfaces_lan_configure();
1437

    
1438
	/* set up WAN interface */
1439
	if($debug)
1440
		log_error("Configuring WAN");
1441
	interfaces_wan_configure();
1442

    
1443
	/* set up Optional interfaces */
1444
	if($debug)
1445
		log_error("Configuring optional interfaces");
1446
	interfaces_optional_configure();
1447

    
1448
	/* set up static routes */
1449
	if($debug)
1450
		log_error("Configuring system Routing");
1451
	system_routing_configure();
1452

    
1453
	/* enable routing */
1454
	if($debug)
1455
		log_error("Enabling system routing");
1456
	system_routing_enable();
1457

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

    
1463
	/* bring up carp interfaces */
1464
	if($debug)
1465
		log_error("Configuring CARP");
1466
	interfaces_carp_configure();
1467

    
1468
	/* bring up carp interfaces*/
1469
	if($debug)
1470
		log_error("Bringing up CARP interfaces");
1471
	interfaces_carp_bring_up_final();
1472

    
1473
	/* restart webConfigurator if needed */
1474
	if($shutdown_webgui_needed == true)
1475
		touch("/tmp/restart_webgui");
1476

    
1477
	/* start devd back up */
1478
	mwexec("/bin/rm /tmp/reload*");
1479

    
1480
	/* remove reloading_all trigger */
1481
	if($debug)
1482
		log_error("Removing {$g['tmp_path']}/reloading_all");
1483
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1484
}
1485

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

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

    
1510
/****f* pfsense-utils/sync_webgui_passwords
1511
 * NAME
1512
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1513
 * INPUTS
1514
 *   none
1515
 * RESULT
1516
 *   none
1517
 ******/
1518
function sync_webgui_passwords() {
1519
	global $config, $g;
1520
	conf_mount_rw();
1521
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
1522
	if (!$fd) {
1523
		printf("Error: cannot open htpasswd in system_password_configure().\n");
1524
		return 1;
1525
	}
1526
	/* set admin account */
1527
	$username = $config['system']['username'];
1528

    
1529
	/* set defined user account */
1530
	if($username <> "admin") {
1531
		$username = $config['system']['username'];
1532
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1533
	} else {
1534
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1535
	}
1536
	fclose($fd);
1537
	chmod("{$g['varrun_path']}/htpasswd", 0600);
1538
	$crypted_pw = $config['system']['password'];
1539
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1540
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1541
	/* sync root */
1542
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
1543
	fwrite($fd, $crypted_pw);
1544
	pclose($fd);
1545
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
1546
	/* sync admin */
1547
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
1548
	fwrite($fd, $crypted_pw);
1549
	pclose($fd);
1550
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
1551
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1552
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1553
	conf_mount_ro();
1554
}
1555

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

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

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

    
1629
/****f* pfsense-utils/reload_all_sync
1630
 * NAME
1631
 *   reload_all - reload all settings
1632
 *   * INPUTS
1633
 *   none
1634
 * RESULT
1635
 *   none
1636
 ******/
1637
function reload_all_sync() {
1638
	global $config, $g;
1639

    
1640
	$g['booting'] = false;
1641

    
1642
	touch("{$g['tmp_path']}/reloading_all");
1643

    
1644
	$shutdown_webgui_needed = false;
1645

    
1646
	if(file_exists("{$g['tmp_path']}/config.cache"))
1647
		unlink("{$g['tmp_path']}/config.cache");
1648

    
1649
	/* parse config.xml again */
1650
	$config = parse_config(true);
1651

    
1652
	/* set up our timezone */
1653
	system_timezone_configure();
1654

    
1655
	/* set up our hostname */
1656
	system_hostname_configure();
1657

    
1658
	/* make hosts file */
1659
	system_hosts_generate();
1660

    
1661
	/* generate resolv.conf */
1662
	system_resolvconf_generate();
1663

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

    
1667
	$wan_if = $config['interfaces']['wan']['if'];
1668
	$lan_if = $config['interfaces']['lan']['if'];
1669

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

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

    
1689
	/* set up VLAN virtual interfaces */
1690
	interfaces_vlan_configure();
1691

    
1692
	/* set up LAN interface */
1693
	interfaces_lan_configure();
1694

    
1695
	/* set up WAN interface */
1696
	interfaces_wan_configure();
1697

    
1698
	/* set up Optional interfaces */
1699
	interfaces_optional_configure();
1700

    
1701
	/* bring up carp interfaces */
1702
	interfaces_carp_configure();
1703

    
1704
	/* set up static routes */
1705
	system_routing_configure();
1706

    
1707
	/* enable routing */
1708
	system_routing_enable();
1709

    
1710
	/* ensure passwords are sync'd */
1711
	system_password_configure();
1712

    
1713
	/* start dnsmasq service */
1714
	services_dnsmasq_configure();
1715

    
1716
	/* start dyndns service */
1717
	services_dyndns_configure();
1718

    
1719
	/* start DHCP service */
1720
	services_dhcpd_configure();
1721

    
1722
	/* start the NTP client */
1723
	system_ntp_configure();
1724

    
1725
	/* start ftp proxy helpers if they are enabled */
1726
	system_start_ftp_helpers();
1727

    
1728
	/* start the captive portal */
1729
	captiveportal_configure();
1730

    
1731
        /* reload the filter */
1732
	filter_configure_sync();
1733

    
1734
	/* bring up carp interfaces*/
1735
	interfaces_carp_bring_up_final();
1736

    
1737
	/* sync pw database */
1738
	conf_mount_rw();
1739
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1740
	conf_mount_ro();
1741

    
1742
	/* restart sshd */
1743
	touch("/tmp/start_sshd");
1744

    
1745
	/* restart webConfigurator if needed */
1746
	if($shutdown_webgui_needed == true)
1747
		touch("/tmp/restart_webgui");
1748

    
1749
	mwexec("/bin/rm /tmp/reload*");
1750

    
1751
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1752

    
1753
}
1754

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

    
1775
function setup_serial_port() {
1776
	global $g, $config;
1777
	conf_mount_rw();
1778
	/* serial console - write out /boot.config */
1779
	if(file_exists("/boot.config"))
1780
		$boot_config = file_get_contents("/boot.config");
1781
	else
1782
		$boot_config = "";
1783

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

    
1829
function print_value_list($list, $count = 10, $separator = ",") {
1830
	$list = implode($separator, array_slice($list, 0, $count));
1831
	if(count($list) < $count) {
1832
		$list .= ".";
1833
	} else {
1834
		$list .= "...";
1835
	}
1836
	return $list;
1837
}
1838

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

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

    
1863
function enable_rrd_graphing()
1864
{
1865
// consider syncing the rrd files to usb storage/xml (cdrom, embbedded)
1866

    
1867
	global $config, $g;
1868

    
1869
    $rrddbpath = "/var/db/rrd/";
1870
    $rrdgraphpath = "/usr/local/www/rrd";
1871
	$rrdtrafficinterval = 60;
1872
	$rrdqualityinterval = 60;
1873
	$rrdqueuesinterval = 60;
1874
	$rrdpacketsinterval = 60;
1875
	$rrdspamdinterval = 60;
1876

    
1877
	$traffic = "-traffic.rrd";
1878
	$packets = "-packets.rrd";
1879
	$quality = "-quality.rrd";
1880
	$queues = "-queues.rrd";
1881
	$spamd = "spamd.rrd";
1882
	$rrdtool = "/usr/local/bin/rrdtool";
1883
	$netstat = "/usr/bin/netstat";
1884
	$awk = "/usr/bin/awk";
1885
	$tar = "/usr/bin/tar";
1886
	$php = "/usr/local/bin/php";
1887
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
1888

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

    
1896
	$trafficvalid = $rrdtrafficinterval*2 ;
1897
	$qualityvalid = $rrdqualityinterval*2 ;
1898
	$queuesvalid = $rrdqueuesinterval*2 ;
1899
	$packetsvalid = $rrdpacketsinterval*2 ;
1900
	$spamdvalid = $rrdspamdinterval*2 ;
1901

    
1902
	/* Asume GigE for now */
1903
	$downstream = 125000000;
1904
	$upstream   = 125000000;
1905

    
1906
	$rrdrestore = "";
1907
	$rrdreturn = "";
1908

    
1909
	$config['rrd']['enable'] = true;
1910

    
1911
	if (isset($config['rrd']['enable'])) {
1912

    
1913
		/* create directory if needed */
1914
		if(!is_dir("$rrddbpath")) {
1915
			mkdir("$rrddbpath", 0755);
1916
		}
1917

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

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

    
1937
		}
1938

    
1939
		/* db update script */
1940
		$rrdupdatesh = "#!/bin/sh\n";
1941
		$rrdupdatesh .= "\n";
1942
		$rrdupdatesh .= "counter=1\n";
1943
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
1944
		$rrdupdatesh .= "do\n";
1945
		$rrdupdatesh .= "";
1946

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

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

    
1968
			/* skip interfaces that do not have a friendly name */
1969
			if("$ifname" == "") {
1970
				continue;
1971
			}
1972

    
1973
			/* or are down */
1974
			if(! $state) {
1975
				continue;
1976
			}
1977

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

    
1994
				$rrdcreateoutput = "";
1995
				$rrdcreatereturn = "";
1996

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

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

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

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

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

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

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

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

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

    
2083
				$rrdupdatesh .= "get_ping_stats &\n\n";
2084

    
2085
				if (!is_array($config['shaper']['queue'])) {
2086
					$config['shaper']['queue'] = array();
2087
				}
2088
				$a_queues = &$config['shaper']['queue'];
2089

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

    
2102
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 \
2103
							RRA:AVERAGE:0.5:5:1000 \
2104
							RRA:AVERAGE:0.5:60:1000 \
2105
							RRA:AVERAGE:0.5:360:1000";
2106

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

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

    
2134
	        }
2135
       		$i++;
2136

    
2137
		$rrdgraphindexhtml .= "</TABLE>
2138
</BODY>
2139
</HTML>";
2140

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

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

    
2169
			$rrdupdatesh .= "\n";
2170
			$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
2171
			$rrdupdatesh .= "$rrdtool update $rrddbpath$spamd \\\n";
2172
			$rrdupdatesh .= "`$php -q $spamd_gather`\n";
2173

    
2174
		}
2175

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

    
2185
		log_error("Creating rrd graph index");
2186
		/* write the index.html script */
2187
		$rrdgraphindex = "{$g['vardb_path']}/rrd/index.html";
2188
		$fd = fopen("$rrdgraphindex", "w");
2189
		fwrite($fd, "$rrdgraphindexhtml");
2190
		fclose($fd);
2191

    
2192
		/* kill off traffic collectors */
2193
		kill_traffic_collector();
2194

    
2195
		/* start traffic collector */
2196
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
2197

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

    
2207
function kill_traffic_collector() {
2208
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
2209
}
2210

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

    
2220
function get_interface_gateway($interface) {
2221
	global $config, $g;
2222
	$interface = strtolower($interface);
2223
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
2224
	 *  grab the address from the configuration file.
2225
	 */
2226
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
2227
	if($tmpif <> $interface)
2228
		$interface = $tmpif;
2229
	$realif = $config['interfaces'][$interface]['if'];
2230
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
2231
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
2232
		$gw = rtrim($gw);
2233
	} else {
2234
		$gw = $config['interfaces'][$interface]['gateway'];
2235
	}
2236
	/* if wan is requested, return it */
2237
	if($interface == "wan")
2238
		return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
2239
	/* return gateway */
2240
	return $gw;
2241
}
2242

    
2243
function is_dhcp_server_enabled() {
2244
	/* DHCP enabled on any interfaces? */
2245
	global $config, $g;
2246
	$dhcpdcfg = $config['dhcpd'];
2247
	$dhcpdenable = false;
2248
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
2249
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2250
			$dhcpdenable = true;
2251
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2252
			$dhcpdenable = true;
2253
	}
2254
	return $dhcpdenable;
2255
}
2256

    
2257
?>
(14-14/27)