Project

General

Profile

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

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

    
40
/****f* pfsense-utils/get_time_based_rule_status
41
 * NAME
42
 *   get_time_based_rule_status
43
 * INPUTS
44
 *   xml schedule block
45
 * RESULT
46
 *   true/false - true if the rule should be installed
47
 ******/
48
/*
49
 <schedules>
50
   <schedule>
51
     <name>ScheduleMultipleTime</name>
52
     <descr>main descr</descr>
53
     <time>
54
       <day>0,1,2</day>
55
       <hour>0:0-24:0</hour>
56
       <desc>time range 2</desc>
57
     </time>
58
     <time>
59
       <day>4,5,6</day>
60
       <hour>0:0-24:0</hour>
61
       <desc>time range 1</desc>
62
     </time>
63
   </schedule>
64
 </schedules>
65
*/
66
function get_time_based_rule_status($schedule) {
67
	$should_add_rule = true;
68
	global $debug;
69
	/* no schedule? rule should be installed */
70
	if($schedule == "") 
71
		return true;
72
	/*
73
	 * iterate through time blocks and deterimine
74
	 * if the rule should be installed or not.
75
	 */
76
	foreach($schedule['time'] as $time) {
77
		if($timeday['week']) 
78
			$week = $timeday['week'];
79
		else 
80
			$week = "";	
81
		if($timeday['day']) 
82
			$day = $timeday['day'];
83
		else 
84
			$day = "";
85
		if($timeday['hour']) 
86
			$hour = $timeday['hour'];
87
		else 
88
			$hour = "";
89
		if($timeday['position']) 
90
			$position = $timeday['position'];
91
		else 
92
			$position = "";
93
		if($timeday['desc']) 
94
			$desc = $timeday['desc'];
95
		else 
96
			$desc = "";
97
		if($week) {
98
			$weekstatus = tdr_week($week);
99
		}
100
		if($day) {
101
			$daystatus = tdr_day($day);
102
		}
103
		if($hour) {
104
			$hourstatus = tdr_hour($hour);
105
		}
106
		if($position) {
107
			$positionstatus = tdr_position($position);
108
		}
109
	}
110

    
111
	/* TODO: reset open states affected by this rule */
112
	return $should_add_rule;
113
}
114

    
115
function tdr_day($schedule) {
116
	/*
117
	 * Calculate day of month. 
118
	 * IE: 29th of may
119
	 */
120
	global $debug;
121
	$weekday	= date("w");
122
	$date	 	= date("d");
123
	$defined_days = split(",", $schedule);
124
	foreach($defined_days as $dd) {
125
		if($date == $dd)
126
			return true;
127
	}
128
	return false;
129
}
130

    
131
function tdr_hour($schedule) {
132
	/* $schedule should be a string such as 16:00-19:00 */
133
	global $debug;
134
	$tmp = split("-", $schedule);
135
	$starting_time = strtotime($tmp[0]);
136
	$ending_time = strtotime($tmp[1]);
137
	$now = strtotime("now");
138
	if($debug) 
139
		echo "S: $starting_time E: $ending_time N: $now \n";
140
	if($now > $starting_time and $now < $ending_time) 
141
		return true;
142
	return false;
143
}
144

    
145
function tdr_position($schedule) {
146
	/*
147
	 * Calculate possition, ie: day of week.
148
	 * Sunday = 0, Monday = 1, Tuesday = 2
149
	 * Weds = 3, Thursday = 4, Friday = 5,
150
	 * Saturday = 6
151
	 * ...
152
	 */
153
	global $debug;
154
	$weekdays = array(0 => "Sunday", 
155
					  1 => "Monday",
156
					  2 => "Tuesday",
157
					  3 => "Wednesday",
158
					  4 => "Thursday",
159
					  5 => "Friday",
160
					  6 => "Saturday");
161
	$weekday	= date("w");
162
	$schedule_days = split(",", $schedule);
163
	foreach($schedule_days as $day) {
164
		if($day == $weekday) 
165
			return true;
166
	}
167
	return false;
168
}
169

    
170
function tdr_week($schedule) {
171
	/*
172
	 * Calculate week, ie:
173
	 * week 1, week 2, week 3, week 4
174
	 */
175
	global $debug;
176
	$todays_week 		= date("W");
177
	$weeks = split(",", $schedule);
178
	foreach($weeks as $week) {
179
		if($week == $todays_week) 
180
			return true;
181
	}
182
	return false;
183
}
184

    
185
/****f* pfsense-utils/find_number_of_needed_carp_interfaces
186
 * NAME
187
 *   find_number_of_needed_carp_interfaces
188
 * INPUTS
189
 *   null
190
 * RESULT
191
 *   the number of needed carp interfacs
192
 ******/
193
function find_number_of_needed_carp_interfaces() {
194
	global $config, $g;
195
	$carp_counter=0;
196
	if(!$config['virtualip'])
197
		return 0;
198
	if(!$config['virtualip']['vip'])
199
		return 0;
200
	foreach($config['virtualip']['vip'] as $vip) {
201
		if($vip['mode'] == "carp")
202
			$carp_counter++;
203
	}
204
	return $carp_counter;
205
}
206

    
207
/****f* pfsense-utils/reset_carp
208
 * NAME
209
 *   reset_carp - resets carp after primary interface changes
210
 * INPUTS
211
 *   null
212
 * RESULT
213
 *   null
214
 ******/
215
function reset_carp() {
216
	$carp_counter=find_number_of_created_carp_interfaces();
217
	$needed_carp_interfaces = find_number_of_needed_carp_interfaces();
218
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
219
	for($x=0; $x<$carp_counter; $x++) {
220
		mwexec("/sbin/ifconfig carp{$x} down");
221
		mwexec("/sbin/ifconfig carp{$x} delete");
222
		log_error("CARP: $needed_carp_interfaces < $carp_counter");
223
		if($needed_carp_interfaces < $carp_counter) {
224
			$needed_carp_interfaces--;
225
			log_error("Destroying carp interface.");
226
			mwexec("/sbin/ifconfig carp{$x} destroy");
227
		}
228
	}
229
	find_number_of_created_carp_interfaces(true);
230
	sleep(1);
231
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
232
	interfaces_carp_configure();
233
	usleep(1000);
234
	interfaces_carp_bring_up_final();
235
}
236

    
237
/****f* pfsense-utils/get_dns_servers
238
 * NAME
239
 *   get_dns_servres - get system dns servers
240
 * INPUTS
241
 *   $dns_servers - an array of the dns servers
242
 * RESULT
243
 *   null
244
 ******/
245
function get_dns_servers() {
246
	$dns_servers = array();
247
	$dns = `cat /etc/resolv.conf`;
248
	$dns_s = split("\n", $dns);
249
	foreach($dns_s as $dns) {
250
		$matches = "";
251
		if (preg_match("/nameserver (.*)/", $dns, $matches))
252
			$dns_servers[] = $matches[1];
253
	}
254
	$dns_server_master = array();
255
	sort($dns_servers);
256
	$lastseen = "";
257
	foreach($dns_servers as $t) {
258
		if($t <> $lastseen)
259
			if($t <> "")
260
				$dns_server_master[] = $t;
261
		$lastseen = $t;
262
	}
263
	return $dns_server_master;
264
}
265

    
266
/****f* pfsense-utils/log_error
267
* NAME
268
*   log_error  - Sends a string to syslog.
269
* INPUTS
270
*   $error     - string containing the syslog message.
271
* RESULT
272
*   null
273
******/
274
function log_error($error) {
275
	$page = $_SERVER['SCRIPT_NAME'];
276
	syslog(LOG_WARNING, "$page: $error");
277
	return;
278
}
279

    
280
/****f* pfsense-utils/get_interface_mac_address
281
 * NAME
282
 *   get_interface_mac_address - Return a interfaces mac address
283
 * INPUTS
284
 *   $interface	- interface to obtain mac address from
285
 * RESULT
286
 *   $mac - the mac address of the interface
287
 ******/
288
function get_interface_mac_address($interface) {
289
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
290
	if(is_macaddr($mac)) {
291
		return trim($mac);
292
	} else {
293
		return "";
294
	}
295
}
296

    
297
/****f* pfsense-utils/return_dir_as_array
298
 * NAME
299
 *   return_dir_as_array - Return a directory's contents as an array.
300
 * INPUTS
301
 *   $dir	- string containing the path to the desired directory.
302
 * RESULT
303
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
304
 ******/
305
function return_dir_as_array($dir) {
306
	$dir_array = array();
307
	if (is_dir($dir)) {
308
		if ($dh = opendir($dir)) {
309
			while (($file = readdir($dh)) !== false) {
310
				$canadd = 0;
311
				if($file == ".") $canadd = 1;
312
				if($file == "..") $canadd = 1;
313
				if($canadd == 0)
314
					array_push($dir_array, $file);
315
			}
316
			closedir($dh);
317
		}
318
	}
319
	return $dir_array;
320
}
321

    
322
/****f* pfsense-utils/enable_hardware_offloading
323
 * NAME
324
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
325
 * INPUTS
326
 *   $interface	- string containing the physical interface to work on.
327
 * RESULT
328
 *   null
329
 * NOTES
330
 *   This function only supports the fxp driver's loadable microcode.
331
 ******/
332
function enable_hardware_offloading($interface) {
333
	global $g, $config;
334

    
335
	if(stristr($interface,"lnc"))
336
		return;
337
	if(isset($config['system']['do_not_use_nic_microcode']))
338
		return;
339

    
340
	if($g['booting']) {
341
	/* translate wan, lan, opt -> real interface if needed */
342
	$int = filter_translate_type_to_real_interface($interface);
343
	if($int <> "") $interface = $int;
344
	$int_family = preg_split("/[0-9]+/", $int);
345
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
346
	$supported_ints = array('fxp');
347
	if (in_array($int_family, $supported_ints))
348
		mwexec("/sbin/ifconfig {$interface} link0");
349

    
350
	if($config['system']['disablechecksumoffloading'])
351
		return;
352

    
353
	if(stristr($options, "txcsum") == true)
354
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
355
	if(stristr($options, "rxcsum") == true)
356
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
357
	if(stristr($options, "polling") == true)
358
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
359
	} else {
360
		mwexec("sysctl kern.polling.enable=0");
361
	}
362
	return;
363
}
364

    
365
/****f* pfsense-utils/is_alias_inuse
366
 * NAME
367
 *   checks to see if an alias is currently in use by a rule
368
 * INPUTS
369
 *
370
 * RESULT
371
 *   true or false
372
 * NOTES
373
 *
374
 ******/
375
function is_alias_inuse($alias) {
376
	global $g, $config;
377

    
378
	if($alias == "") return false;
379
	/* loop through firewall rules looking for alias in use */
380
	if(is_array($config['nat']['rule']))
381
		foreach($config['filter']['rule'] as $rule) {
382
			if(is_array($rule['source']['address']))
383
				if($rule['source']['address'] == $alias)
384
					return true;
385
			if(is_array($rule['destination']['address']))
386
				if($rule['destination']['address'] == $alias)
387
					return true;
388
		}
389
	/* loop through nat rules looking for alias in use */
390
	if(is_array($config['nat']['rule']))
391
		foreach($config['nat']['rule'] as $rule) {
392
			if($rule['target'] == $alias)
393
				return true;
394
			if($rule['external-address'] == $alias)
395
				return true;
396
		}
397
	return false;
398
}
399

    
400
/****f* pfsense-utils/setup_polling_defaults
401
 * NAME
402
 *   sets up sysctls for pollingS
403
 * INPUTS
404
 *
405
 * RESULT
406
 *   null
407
 * NOTES
408
 *
409
 ******/
410
function setup_polling_defaults() {
411
	global $g, $config;
412
	if($config['system']['polling_each_burst'])
413
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
414
	if($config['system']['polling_burst_max'])
415
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
416
	if($config['system']['polling_user_frac'])
417
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
418
}
419

    
420
/****f* pfsense-utils/setup_polling
421
 * NAME
422
 *   sets up polling
423
 * INPUTS
424
 *
425
 * RESULT
426
 *   null
427
 * NOTES
428
 *
429
 ******/
430
function setup_polling() {
431
	global $g, $config;
432

    
433
	setup_polling_defaults();
434

    
435
	if(isset($config['system']['polling']))
436
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
437
	else
438
		$supported_ints = array();
439

    
440
	/* build an array of interfaces to work with */
441
	$iflist = array("lan" => "LAN", "wan" => "WAN");
442
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
443
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
444

    
445
	foreach ($iflist as $ifent => $ifname) {
446
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
447
		$supported = false;
448
		foreach($supported_ints as $supported) {
449
			if(stristr($real_interface, $supported)) {
450
				$supported = true;
451
			}
452
		}
453
		if ($supported == true) {
454
			mwexec("/sbin/ifconfig {$real_interface} polling");
455
		} else {
456
			mwexec("/sbin/ifconfig {$real_interface} -polling");
457
		}
458
	}
459
}
460

    
461
/****f* pfsense-utils/setup_microcode
462
 * NAME
463
 *   enumerates all interfaces and calls enable_hardware_offloading which
464
 *   enables a NIC's supported hardware features.
465
 * INPUTS
466
 *
467
 * RESULT
468
 *   null
469
 * NOTES
470
 *   This function only supports the fxp driver's loadable microcode.
471
 ******/
472
function setup_microcode() {
473
	global $config;
474

    
475
	$ifdescrs = array('wan', 'lan');
476
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
477
		$ifdescrs['opt' . $j] = "opt" . $j;
478
	}
479
	foreach($ifdescrs as $if)
480
		enable_hardware_offloading($if);
481
}
482

    
483
/****f* pfsense-utils/return_filename_as_array
484
 * NAME
485
 *   return_filename_as_array - Return a file's contents as an array.
486
 * INPUTS
487
 *   $filename	- string containing the path to the desired file.
488
 *   $strip	- array of characters to strip - default is '#'.
489
 * RESULT
490
 *   $file	- array containing the file's contents.
491
 * NOTES
492
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
493
 ******/
494
function return_filename_as_array($filename, $strip = array('#')) {
495
	if(file_exists($filename)) $file = file($filename);
496
	if(is_array($file)) {
497
		foreach($file as $line) $line = trim($line);
498
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
499
	}
500
	return $file;
501
}
502

    
503
/****f* pfsense-utils/file_put_contents
504
 * NAME
505
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
506
 * RESULT
507
 *   none
508
 ******/
509
if(!function_exists("file_put_contents")) {
510
	function file_put_contents($filename, $data) {
511
		$fd = fopen($filename,"w");
512
		fwrite($fd, $data);
513
		fclose($fd);
514
	}
515
}
516

    
517
/****f* pfsense-utils/get_carp_status
518
 * NAME
519
 *   get_carp_status - Return whether CARP is enabled or disabled.
520
 * RESULT
521
 *   boolean	- true if CARP is enabled, false if otherwise.
522
 ******/
523
function get_carp_status() {
524
    /* grab the current status of carp */
525
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
526
    if(intval($status) == "0") return false;
527
    return true;
528
}
529

    
530
/****f* pfsense-utils/is_carp_defined
531
 * NAME
532
 *   is_carp_defined - Return whether CARP is detected in the kernel.
533
 * RESULT
534
 *   boolean	- true if CARP is detected, false otherwise.
535
 ******/
536
function is_carp_defined() {
537
	/* is carp compiled into the kernel and userland? */
538
	$command = "/sbin/sysctl -a | grep carp";
539
	$fd = popen($command . " 2>&1 ", "r");
540
	if(!$fd) {
541
		log_error("Warning, could not execute command {$command}");
542
		return 0;
543
	}
544
	while(!feof($fd)) {
545
		$tmp .= fread($fd,49);
546
	}
547
	fclose($fd);
548

    
549
	if($tmp == "")
550
		return false;
551
	else
552
		return true;
553
}
554

    
555
/****f* pfsense-utils/get_interface_mtu
556
 * NAME
557
 *   get_interface_mtu - Return the mtu of an interface
558
 * RESULT
559
 *   $tmp	- Returns the mtu of an interface
560
 ******/
561
function get_interface_mtu($interface) {
562
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f4`;
563
	return $mtu;
564
}
565

    
566
/****f* pfsense-utils/is_interface_wireless
567
 * NAME
568
 *   is_interface_wireless - Returns if an interface is wireless
569
 * RESULT
570
 *   $tmp	- Returns if an interface is wireless
571
 ******/
572
function is_interface_wireless($interface) {
573
	global $config, $g;
574
	$interface = convert_real_interface_to_friendly_interface_name($interface);
575
	if(isset($config['interfaces'][$interface]['wireless']))
576
		return true;
577
	else
578
		return false;
579
}
580

    
581
/****f* pfsense-utils/find_number_of_created_carp_interfaces
582
 * NAME
583
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
584
 * RESULT
585
 *   $tmp	- Number of currently created CARP interfaces.
586
 ******/
587
function find_number_of_created_carp_interfaces($flush = false) {
588
	global $carp_interface_count_cache;
589

    
590
	if (!isset($carp_interface_count_cache) or $flush) {
591
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
592
		$fd = popen($command . " 2>&1 ", "r");
593
		if(!$fd) {
594
			log_error("Warning, could not execute command {$command}");
595
			return 0;
596
		}
597
		while(!feof($fd)) {
598
			$tmp .= fread($fd,49);
599
		}
600
		fclose($fd);
601
		$carp_interface_count_cache = intval($tmp);
602
	}
603
	return $carp_interface_count_cache;
604
}
605

    
606
/****f* pfsense-utils/link_int_to_bridge_interface
607
 * NAME
608
 *   link_int_to_bridge_interface - Finds out a bridge group for an interface
609
 * INPUTS
610
 *   $ip
611
 * RESULT
612
 *   bridge[0-99]
613
 ******/
614
function link_int_to_bridge_interface($int) {
615
	global $config, $g;
616
	$real_int = convert_friendly_interface_to_real_interface_name($int);
617
	$num_bridges = find_number_of_created_bridges();
618
	for($x=0; $x<$num_bridges; $x++) {
619
		$matches = "";
620
		$bridge_info = `/sbin/ifconfig bridge{$x}`;
621
		if(stristr($bridge_info, "member: {$real_int}")) {
622
			return "bridge{$x}";
623
		}
624
	}
625
}
626

    
627
function link_carp_interface_to_parent($interface) {
628
	global $config;
629
	if($interface == "") return;
630

    
631
	$ifdescrs = array('wan', 'lan');
632
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
633
		$ifdescrs['opt' . $j] = "opt" . $j;
634

    
635
	$carp_ints = "";
636
	$num_carp_ints = find_number_of_created_carp_interfaces();
637
	foreach ($ifdescrs as $ifdescr => $ifname) {
638
		$carp_int = $interface;
639
		$carp_ip = find_interface_ip($interface);
640
		$carp_subnet = find_virtual_ip_netmask($carp_ip);
641
		$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
642
		if(ip_in_subnet($starting_ip, "{$carp_ip}/{$carp_subnet}"))
643
			if(!stristr($carp_ints, $carp_int))
644
				return $ifname;
645
	}
646
	return $carp_ints;
647
}
648

    
649
/****f* pfsense-utils/link_ip_to_carp_interface
650
 * NAME
651
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
652
 * INPUTS
653
 *   $ip
654
 * RESULT
655
 *   $carp_ints
656
 ******/
657
function link_ip_to_carp_interface($ip) {
658
	global $config;
659
	if($ip == "") return;
660

    
661
	$ifdescrs = array('wan', 'lan');
662
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
663
		$ifdescrs['opt' . $j] = "opt" . $j;
664

    
665
	$ft = split("\.", $ip);
666
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
667

    
668
	$carp_ints = "";
669
	$num_carp_ints = find_number_of_created_carp_interfaces();
670
	foreach ($ifdescrs as $ifdescr => $ifname) {
671
		for($x=0; $x<$num_carp_ints; $x++) {
672
			$carp_int = "carp{$x}";
673
			$carp_ip = find_interface_ip($carp_int);
674
			$carp_subnet = find_virtual_ip_netmask($carp_ip);
675
			$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
676
			if(ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
677
				if(!stristr($carp_ints, $carp_int))
678
					$carp_ints .= " " . $carp_int;
679
		}
680
	}
681
	return $carp_ints;
682
}
683

    
684
/****f* pfsense-utils/find_virtual_ip_netmask
685
 * NAME
686
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
687
 * INPUTS
688
 *   $ip - ip address to locate subnet mask of
689
 * RESULT
690
 *   String containing the command's result.
691
 * NOTES
692
 *   This function returns the command's stdout and stderr.
693
 ******/
694
function find_virtual_ip_netmask($ip) {
695
        global $config;
696
        foreach($config['virtualip']['vip'] as $vip) {
697
                if($ip == $vip['subnet'])
698
                        return $vip['subnet_bits'];
699
        }
700
}
701

    
702
/****f* pfsense-utils/exec_command
703
 * NAME
704
 *   exec_command - Execute a command and return a string of the result.
705
 * INPUTS
706
 *   $command	- String of the command to be executed.
707
 * RESULT
708
 *   String containing the command's result.
709
 * NOTES
710
 *   This function returns the command's stdout and stderr.
711
 ******/
712
function exec_command($command) {
713
	$output = array();
714
	exec($command . ' 2>&1 ', $output);
715
	return(implode("\n", $output));
716
}
717

    
718
/****f* interfaces/is_jumbo_capable
719
 * NAME
720
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
721
 * INPUTS
722
 *   $int             - string containing interface name
723
 * RESULT
724
 *   boolean          - true or false
725
 ******/
726
function is_jumbo_capable($int) {
727
	/* Per:
728
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
729
	 * Only the following drivers support large frames
730
         *
731
	 * 'de' chipset purposely left out of this list
732
	 * requires defining BIG_PACKET in the
733
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
734
	 * kernel or module.  The hack works only for the 21041,
735
	 * 21140, and 21140A chips.
736
	 */
737
	global $g;
738

    
739
	$capable = $g['vlan_long_frame'];
740

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

    
743
	if (in_array($int_family[0], $capable))
744
		return true;
745
	else
746
		return false;
747
}
748

    
749
/*
750
 * Return the interface array
751
 */
752
function get_interface_arr($flush = false) {
753
	global $interface_arr_cache;
754

    
755
	/* If the cache doesn't exist, build it */
756
	if (!isset($interface_arr_cache) or $flush)
757
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
758

    
759
	return $interface_arr_cache;
760
}
761

    
762
/*
763
 * does_interface_exist($interface): return true or false if a interface is
764
 * detected.
765
 */
766
function does_interface_exist($interface) {
767
        $ints = get_interface_arr();
768

    
769
	if(stristr($ints, $interface) !== false)
770
		return true;
771
	else
772
		return false;
773
}
774

    
775
/*
776
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
777
 */
778
function convert_ip_to_network_format($ip, $subnet) {
779
	$ipsplit = split('[.]', $ip);
780
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
781
	return $string;
782
}
783

    
784
/*
785
 * find_interface_ip($interface): return the interface ip (first found)
786
 */
787
function find_interface_ip($interface, $flush = false) {
788
	global $interface_ip_arr_cache;
789
	$interface = str_replace("\n", "", $interface);
790
	if(does_interface_exist($interface) == false) return;
791
	/* Setup IP cache */
792
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
793
		$interface_ip_arr_cache[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2| /usr/bin/head -1");
794
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
795
	}
796

    
797
	return $interface_ip_arr_cache[$interface];
798
}
799

    
800
function guess_interface_from_ip($ipaddress) {
801
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2
802
; };'");
803
	return $ret;
804
}
805

    
806
function filter_opt_interface_to_real($opt) {
807
	global $config;
808
	return $config['interfaces'][$opt]['if'];
809
}
810

    
811
function filter_get_opt_interface_descr($opt) {
812
	global $config;
813
	return $config['interfaces'][$opt]['descr'];
814
}
815

    
816
function get_friendly_interface_list_as_array() {
817
	global $config;
818
	$ints = array();
819
	$ifdescrs = get_interface_list();
820
	foreach ($ifdescrs as $ifdescr => $ifname) {
821
		array_push($ints,$ifdescr);
822
	}
823
	return $ints;
824
}
825

    
826
/*
827
 * find_ip_interface($ip): return the interface where an ip is defined
828
 */
829
function find_ip_interface($ip) {
830
	global $config;
831
	$ifdescrs = array('wan', 'lan');
832
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
833
		$ifdescrs['opt' . $j] = "opt" . $j;
834
	}
835
	foreach ($ifdescrs as $ifdescr => $ifname) {
836
		$int = filter_translate_type_to_real_interface($ifname);
837
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
838
	if(stristr($ifconfig,$ip) <> false)
839
		return $int;
840
	}
841
	return false;
842
}
843

    
844
/*
845
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
846
 *                                                       for a friendly interface.  ie: wan
847
 */
848
function filter_translate_type_to_real_interface($interface) {
849
	global $config;
850
	if($config['interfaces'][$interface]['if'] <> "") {
851
		return $config['interfaces'][$interface]['if'];
852
	} else {
853
		return $interface;
854
	}
855
}
856

    
857
/*
858
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
859
 */
860
function get_carp_interface_status($carpinterface) {
861
	/* basically cache the contents of ifconfig statement
862
	to speed up this routine */
863
	global $carp_query;
864
	if($carp_query == "")
865
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
866
	$found_interface = 0;
867
	foreach($carp_query as $int) {
868
		if($found_interface == 1) {
869
			if(stristr($int, "MASTER")) return "MASTER";
870
			if(stristr($int, "BACKUP")) return "BACKUP";
871
			if(stristr($int, "INIT")) return "INIT";
872
			return false;
873
		}
874
		if(stristr($int, $carpinterface) == true)
875
		$found_interface=1;
876
	}
877
	return;
878
}
879

    
880
/*
881
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
882
 */
883
function get_pfsync_interface_status($pfsyncinterface) {
884
    $result = does_interface_exist($pfsyncinterface);
885
    if($result <> true) return;
886
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
887
    return $status;
888
}
889

    
890
/*
891
 * find_carp_interface($ip): return the carp interface where an ip is defined
892
 */
893
function find_carp_interface($ip) {
894
	global $find_carp_ifconfig;
895
	if($find_carp_ifconfig == "") {
896
		$find_carp_ifconfig = array();
897
		$num_carp_ints = find_number_of_created_carp_interfaces();
898
		for($x=0; $x<$num_carp_ints; $x++) {
899
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
900
		}
901
	}
902
	$carps = 0;
903
	foreach($find_carp_ifconfig as $fci) {
904
		if(stristr($fci, $ip) == true)
905
			return "carp{$carps}";
906
		$carps++;
907
	}
908
}
909

    
910
/*
911
 * setup_filter_bridge(): toggle filtering bridge
912
 */
913
function setup_filter_bridge() {
914
	global $config, $g;
915
	if(isset($config['bridge']['filteringbridge'])) {
916
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
917
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
918
	} else {
919
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
920
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
921
	}
922
}
923

    
924
/*
925
 * find_number_of_created_bridges(): returns the number of currently created bridges
926
 */
927
function find_number_of_created_bridges($flush = false) {
928
	global $bridge_interface_count_cache;
929
	if(!isset($bridge_interface_count_cache) or $flush)
930
		$bridge_interface_count_cache = exec_command('/sbin/ifconfig | /usr/bin/grep "bridge[0-999]" | /usr/bin/wc -l');
931

    
932
	return $bridge_interface_count_cache;
933
}
934

    
935
/*
936
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
937
 */
938
function add_rule_to_anchor($anchor, $rule, $label) {
939
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
940
}
941

    
942
/*
943
 * remove_text_from_file
944
 * remove $text from file $file
945
 */
946
function remove_text_from_file($file, $text) {
947
	global $fd_log;
948
	if($fd_log)
949
		fwrite($fd_log, "Adding needed text items:\n");
950
	$filecontents = file_get_contents($file);
951
	$textTMP = str_replace($text, "", $filecontents);
952
	$text = $textTMP;
953
	if($fd_log)
954
		fwrite($fd_log, $text);
955
	$fd = fopen($file, "w");
956
	fwrite($fd, $text);
957
	fclose($fd);
958
}
959

    
960
/*
961
 * add_text_to_file($file, $text): adds $text to $file.
962
 * replaces the text if it already exists.
963
 */
964
function add_text_to_file($file, $text) {
965
	if(file_exists($file) and is_writable($file)) {
966
		$filecontents = split("\n", file_get_contents($file));
967
		$fout = fopen($file, "w");
968
		$new_file_text = "";
969
		foreach($filecontents as $line) {
970
			if($line)
971
				$new_file_text .= rtrim($line) . "\n";
972
		}
973
		$new_file_text .= $text . "\n";
974
		$file_text = str_replace("\n\n", "\n", $new_file_text);
975
		fwrite($fout, $file_text);
976
		fclose($fout);
977
		return true;
978
	} else {
979
		return false;
980
	}
981
}
982

    
983
/*
984
 *   after_sync_bump_adv_skew(): create skew values by 1S
985
 */
986
function after_sync_bump_adv_skew() {
987
	global $config, $g;
988
	$processed_skew = 1;
989
	$a_vip = &$config['virtualip']['vip'];
990
	foreach ($a_vip as $vipent) {
991
		if($vipent['advskew'] <> "") {
992
			$processed_skew = 1;
993
			$vipent['advskew'] = $vipent['advskew']+1;
994
		}
995
	}
996
	if($processed_skew == 1)
997
		write_config("After synch increase advertising skew");
998
}
999

    
1000
/*
1001
 * get_filename_from_url($url): converts a url to its filename.
1002
 */
1003
function get_filename_from_url($url) {
1004
	return basename($url);
1005
}
1006

    
1007
/*
1008
 *   update_output_window: update bottom textarea dynamically.
1009
 */
1010
function update_output_window($text) {
1011
	global $pkg_interface;
1012
	$log = ereg_replace("\n", "\\n", $text);
1013
	if($pkg_interface == "console") {
1014
		/* too chatty */
1015
	} else {
1016
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1017
	}
1018
	/* ensure that contents are written out */
1019
	ob_flush();
1020
}
1021

    
1022
/*
1023
 *   get_dir: return an array of $dir
1024
 */
1025
function get_dir($dir) {
1026
	$dir_array = array();
1027
	$d = dir($dir);
1028
	while (false !== ($entry = $d->read())) {
1029
		array_push($dir_array, $entry);
1030
	}
1031
	$d->close();
1032
	return $dir_array;
1033
}
1034

    
1035
/*
1036
 *   update_output_window: update top textarea dynamically.
1037
 */
1038
function update_status($status) {
1039
	global $pkg_interface;
1040
	if($pkg_interface == "console") {
1041
		echo $status . "\n";
1042
	} else {
1043
		echo "\n<script type=\"text/javascript\">document.forms[0].status.value=\"" . $status . "\";</script>";
1044
	}
1045
	/* ensure that contents are written out */
1046
	ob_flush();
1047
}
1048

    
1049
/*
1050
 *   exec_command_and_return_text_array: execute command and return output
1051
 */
1052
function exec_command_and_return_text_array($command) {
1053
	$fd = popen($command . " 2>&1 ", "r");
1054
	while(!feof($fd)) {
1055
		$tmp .= fread($fd,49);
1056
	}
1057
	fclose($fd);
1058
	$temp_array = split("\n", $tmp);
1059
	return $temp_array;
1060
}
1061

    
1062
/*
1063
 *   exec_command_and_return_text: execute command and return output
1064
 */
1065
function exec_command_and_return_text($command) {
1066
	return exec_command($command);
1067
}
1068

    
1069
/*
1070
 *   exec_command_and_return_text: execute command and update output window dynamically
1071
 */
1072
function execute_command_return_output($command) {
1073
	global $fd_log, $pkg_interface;
1074
	$fd = popen($command . " 2>&1 ", "r");
1075
	if($pkg_interface <> "console") {
1076
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1077
	}
1078
	$counter = 0;
1079
	$counter2 = 0;
1080
	while(!feof($fd)) {
1081
		$tmp = fread($fd, 50);
1082
		$tmp1 = ereg_replace("\n","\\n", $tmp);
1083
		$text = ereg_replace("\"","'", $tmp1);
1084
		$lasttext = "";
1085
		if($lasttext == "..") {
1086
			$text = "";
1087
			$lasttext = "";
1088
			$counter=$counter-2;
1089
		} else {
1090
			$lasttext .= $text;
1091
		}
1092
		if($counter > 51) {
1093
			$counter = 0;
1094
			$extrabreak = "\\n";
1095
		} else {
1096
	    $extrabreak = "";
1097
	    $counter++;
1098
		}
1099
		if($counter2 > 600) {
1100
			if($pkg_interface <> "console") {
1101
				echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1102
			}
1103
			$counter2 = 0;
1104
		} else
1105
			$counter2++;
1106
		if($pkg_interface <> "console") {
1107
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
1108
		}
1109
	}
1110
	fclose($fd);
1111
}
1112

    
1113
/*
1114
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
1115
 */
1116
function convert_friendly_interface_to_real_interface_name($interface) {
1117
	global $config;
1118
	$lc_interface = strtolower($interface);
1119
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
1120
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
1121
	$ifdescrs = array();
1122
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1123
		$ifdescrs['opt' . $j] = "opt" . $j;
1124
	foreach ($ifdescrs as $ifdescr => $ifname) {
1125
		if(strtolower($ifname) == $lc_interface)
1126
	    return $config['interfaces'][$ifname]['if'];
1127
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
1128
			return $config['interfaces'][$ifname]['if'];
1129
   }
1130
   return $interface;
1131
}
1132

    
1133
/*
1134
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
1135
 */
1136
function convert_real_interface_to_friendly_interface_name($interface) {
1137
	global $config;
1138
	$ifdescrs = array('wan', 'lan');
1139
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1140
		$ifdescrs['opt' . $j] = "opt" . $j;
1141
	foreach ($ifdescrs as $ifdescr => $ifname) {
1142
		if($config['interfaces']['$ifname']['if'] == $interface)
1143
			return $ifname;
1144
		$int = filter_translate_type_to_real_interface($ifname);
1145
		if($ifname == $interface) return $ifname;
1146
		if($int == $interface) return $ifname;
1147
	}
1148
	return $interface;
1149
}
1150

    
1151
/*
1152
 * update_progress_bar($percent): updates the javascript driven progress bar.
1153
 */
1154
function update_progress_bar($percent) {
1155
	global $pkg_interface;
1156
	if($percent > 100) $percent = 1;
1157
	if($pkg_interface <> "console") {
1158
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1159
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1160
		echo "\n</script>";
1161
	} else {
1162
		echo " {$percent}%";
1163
	}
1164
}
1165

    
1166
/****f* pfsense-utils/WakeOnLan
1167
 * NAME
1168
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
1169
 * RESULT
1170
 *   true/false - true if the operation was successful
1171
 ******/
1172
function WakeOnLan($addr, $mac)
1173
{
1174
	$addr_byte = explode(':', $mac);
1175
	$hw_addr = '';
1176

    
1177
	for ($a=0; $a < 6; $a++)
1178
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1179

    
1180
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1181

    
1182
	for ($a = 1; $a <= 16; $a++)
1183
		$msg .= $hw_addr;
1184

    
1185
	// send it to the broadcast address using UDP
1186
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1187
	if ($s == false) {
1188
		log_error("Error creating socket!");
1189
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
1190
	} else {
1191
		// setting a broadcast option to socket:
1192
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1193
		if($opt_ret < 0)
1194
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1195
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1196
		socket_close($s);
1197
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1198
		return true;
1199
	}
1200

    
1201
	return false;
1202
}
1203

    
1204
/*
1205
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
1206
 *                             is queuename|qlength|measured_packets
1207
 *                             NOTE: this command takes 5 seconds to run
1208
 */
1209
function gather_altq_queue_stats($dont_return_root_queues) {
1210
	mwexec("/usr/bin/killall -9 pfctl");
1211
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
1212
	$stats_array = split("\n", $stats);
1213
	$queue_stats = array();
1214
	foreach ($stats_array as $stats_line) {
1215
		$match_array = "";
1216
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
1217
			$queue_name = $match_array[1][0];
1218
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
1219
			$speed = $match_array[1][0];
1220
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
1221
			$borrows = $match_array[1][0];
1222
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
1223
			$suspends = $match_array[1][0];
1224
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
1225
			$drops = $match_array[1][0];
1226
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
1227
			$measured = $match_array[1][0];
1228
			if($dont_return_root_queues == true)
1229
				if(stristr($queue_name,"root_") == false)
1230
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
1231
		}
1232
	}
1233
	return $queue_stats;
1234
}
1235

    
1236
/*
1237
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1238
 *					 Useful for finding paths and stripping file extensions.
1239
 */
1240
function reverse_strrchr($haystack, $needle) {
1241
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1242
}
1243

    
1244
/*
1245
 *  backup_config_section($section): returns as an xml file string of
1246
 *                                   the configuration section
1247
 */
1248
function backup_config_section($section) {
1249
	global $config;
1250
	$new_section = &$config[$section];
1251
	/* generate configuration XML */
1252
	$xmlconfig = dump_xml_config($new_section, $section);
1253
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1254
	return $xmlconfig;
1255
}
1256

    
1257
/*
1258
 *  backup_vip_config_section($section): returns as an xml file string of
1259
 *                                   the configuration section
1260
 */
1261
function backup_vip_config_section() {
1262
	global $config;
1263
	$new_section = &$config['virtualip'];
1264
	foreach($new_section['vip'] as $section) {
1265
		if($section['mode'] == "proxyarp") {
1266
			unset($section);
1267
		}
1268
		if($section['advskew'] <> "") {
1269
			$section_val = intval($section['advskew']);
1270
			$section_val=$section_val+100;
1271
			if($section_val > 255)
1272
				$section_val = 255;
1273
			$section['advskew'] = $section_val;
1274
		}
1275
		$temp['vip'][] = $section;
1276
   }
1277
   return $temp;
1278
}
1279

    
1280
/*
1281
 *  restore_config_section($section, new_contents): restore a configuration section,
1282
 *                                                  and write the configuration out
1283
 *                                                  to disk/cf.
1284
 */
1285
function restore_config_section($section, $new_contents) {
1286
	global $config, $g;
1287
	conf_mount_rw();
1288
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
1289
	fwrite($fout, $new_contents);
1290
	fclose($fout);
1291
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
1292
	$config[$section] = &$section_xml;
1293
	unlink($g['tmp_path'] . "/tmpxml");
1294
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1295
	conf_mount_ro();
1296
	return;
1297
}
1298

    
1299
/*
1300
 *  merge_config_section($section, new_contents):   restore a configuration section,
1301
 *                                                  and write the configuration out
1302
 *                                                  to disk/cf.  But preserve the prior
1303
 * 													structure if needed
1304
 */
1305
function merge_config_section($section, $new_contents) {
1306
	global $config;
1307
	conf_mount_rw();
1308
	$fname = get_tmp_filename();
1309
	$fout = fopen($fname, "w");
1310
	fwrite($fout, $new_contents);
1311
	fclose($fout);
1312
	$section_xml = parse_xml_config($fname, $section);
1313
	$config[$section] = $section_xml;
1314
	unlink($fname);
1315
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1316
	conf_mount_ro();
1317
	return;
1318
}
1319

    
1320
/*
1321
 * http_post($server, $port, $url, $vars): does an http post to a web server
1322
 *                                         posting the vars array.
1323
 * written by nf@bigpond.net.au
1324
 */
1325
function http_post($server, $port, $url, $vars) {
1326
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
1327
	$urlencoded = "";
1328
	while (list($key,$value) = each($vars))
1329
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
1330
	$urlencoded = substr($urlencoded,0,-1);
1331
	$content_length = strlen($urlencoded);
1332
	$headers = "POST $url HTTP/1.1
1333
Accept: */*
1334
Accept-Language: en-au
1335
Content-Type: application/x-www-form-urlencoded
1336
User-Agent: $user_agent
1337
Host: $server
1338
Connection: Keep-Alive
1339
Cache-Control: no-cache
1340
Content-Length: $content_length
1341

    
1342
";
1343

    
1344
	$errno = "";
1345
	$errstr = "";
1346
	$fp = fsockopen($server, $port, $errno, $errstr);
1347
	if (!$fp) {
1348
		return false;
1349
	}
1350

    
1351
	fputs($fp, $headers);
1352
	fputs($fp, $urlencoded);
1353

    
1354
	$ret = "";
1355
	while (!feof($fp))
1356
		$ret.= fgets($fp, 1024);
1357
	fclose($fp);
1358

    
1359
	return $ret;
1360
}
1361

    
1362
/*
1363
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
1364
 */
1365
if (!function_exists('php_check_syntax')){
1366
	function php_check_syntax($code_to_check, &$errormessage){
1367
		return false;
1368
		$fout = fopen("/tmp/codetocheck.php","w");
1369
		$code = $_POST['content'];
1370
		$code = str_replace("<?php", "", $code);
1371
		$code = str_replace("?>", "", $code);
1372
		fwrite($fout, "<?php\n\n");
1373
		fwrite($fout, $code_to_check);
1374
		fwrite($fout, "\n\n?>\n");
1375
		fclose($fout);
1376
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1377
		$output = exec_command($command);
1378
		if (stristr($output, "Errors parsing") == false) {
1379
			echo "false\n";
1380
			$errormessage = '';
1381
			return(false);
1382
		} else {
1383
			$errormessage = $output;
1384
			return(true);
1385
		}
1386
	}
1387
}
1388

    
1389
/*
1390
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1391
 */
1392
if (!function_exists('php_check_syntax')){
1393
	function php_check_syntax($code_to_check, &$errormessage){
1394
		return false;
1395
		$command = "/usr/local/bin/php -l " . $code_to_check;
1396
		$output = exec_command($command);
1397
		if (stristr($output, "Errors parsing") == false) {
1398
			echo "false\n";
1399
			$errormessage = '';
1400
			return(false);
1401
		} else {
1402
			$errormessage = $output;
1403
			return(true);
1404
		}
1405
	}
1406
}
1407

    
1408
/*
1409
 * rmdir_recursive($path,$follow_links=false)
1410
 * Recursively remove a directory tree (rm -rf path)
1411
 * This is for directories _only_
1412
 */
1413
function rmdir_recursive($path,$follow_links=false) {
1414
	$to_do = glob($path);
1415
	if(!is_array($to_do)) $to_do = array($to_do);
1416
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1417
		if(file_exists($workingdir)) {
1418
			if(is_dir($workingdir)) {
1419
				$dir = opendir($workingdir);
1420
				while ($entry = readdir($dir)) {
1421
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1422
						unlink("$workingdir/$entry");
1423
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
1424
						rmdir_recursive("$workingdir/$entry");
1425
				}
1426
				closedir($dir);
1427
				rmdir($workingdir);
1428
			} elseif (is_file($workingdir)) {
1429
				unlink($workingdir);
1430
			}
1431
               	}
1432
	}
1433
	return;
1434
}
1435

    
1436
/*
1437
 *     get_memory()
1438
 *     returns an array listing the amount of
1439
 *     memory installed in the hardware
1440
 *     [0]real and [1]available
1441
 */
1442
function get_memory() {
1443
	if(file_exists("/var/log/dmesg.boot")) {
1444
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1445
		$matches = "";
1446
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1447
			$real = $matches[1];
1448
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1449
			$avail = $matches[1];
1450
		return array($real[0],$avail[0]);
1451
	} else {
1452
		$mem = `dmesg -a`;
1453
		$matches = "";
1454
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1455
			$real = $matches[1];
1456
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1457
			$avail = $matches[1];
1458
		return array($real[0],$avail[0]);
1459
	}
1460
}
1461

    
1462
/*
1463
 *    safe_mkdir($path, $mode = 0755)
1464
 *    create directory if it doesn't already exist and isn't a file!
1465
 */
1466
function safe_mkdir($path, $mode=0755) {
1467
	global $g;
1468

    
1469
	/* cdrom is ro. */
1470
	if($g['platform'] == "cdrom")
1471
		return false;
1472

    
1473
	if (!is_file($path) && !is_dir($path))
1474
		return mkdir($path, $mode);
1475
	else
1476
		return false;
1477
}
1478

    
1479
/*
1480
 * make_dirs($path, $mode = 0755)
1481
 * create directory tree recursively (mkdir -p)
1482
 */
1483
function make_dirs($path, $mode = 0755) {
1484
	$base = '';
1485
	foreach (explode('/', $path) as $dir) {
1486
		$base .= "/$dir";
1487
		if (!is_dir($base)) {
1488
			if (!@mkdir($base, $mode))
1489
				return false;
1490
		}
1491
	}
1492
	return true;
1493
}
1494

    
1495
/*
1496
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
1497
 */
1498
function call_pfsense_method($method, $params, $timeout = 0) {
1499
	$ip = gethostbyname('www.pfsense.com');
1500
	if($ip == "www.pfsense.com")
1501
		return false;
1502
	global $g, $config;
1503
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
1504
	$xmlrpc_path = $g['xmlrpcpath'];
1505
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
1506
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
1507
	$resp = $cli->send($msg, $timeout);
1508
	if(!$resp) {
1509
		log_error("XMLRPC communication error: " . $cli->errstr);
1510
		return false;
1511
	} elseif($resp->faultCode()) {
1512
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
1513
		return false;
1514
	} else {
1515
		return XML_RPC_Decode($resp->value());
1516
	}
1517
}
1518

    
1519
/*
1520
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1521
 */
1522
function check_firmware_version($tocheck = "all", $return_php = true) {
1523
	global $g, $config;
1524
	$ip = gethostbyname('www.pfsense.com');
1525
	if($ip == "www.pfsense.com")
1526
		return false;
1527
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
1528
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
1529
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
1530
		"platform" => trim(file_get_contents('/etc/platform'))
1531
		);
1532
	if($tocheck == "all") {
1533
		$params = $rawparams;
1534
	} else {
1535
		foreach($tocheck as $check) {
1536
			$params['check'] = $rawparams['check'];
1537
			$params['platform'] = $rawparams['platform'];
1538
		}
1539
	}
1540
	if($config['system']['firmware']['branch']) {
1541
		$params['branch'] = $config['system']['firmware']['branch'];
1542
	}
1543
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
1544
		return false;
1545
	} else {
1546
		$versions["current"] = $params;
1547
	}
1548
	return $versions;
1549
}
1550

    
1551
function get_disk_info() {
1552
	$diskout = "";
1553
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
1554
	return explode(' ', $diskout[0]);
1555
	// $size, $used, $avail, $cap
1556
}
1557

    
1558
/****f* pfsense-utils/display_top_tabs
1559
 * NAME
1560
 *   display_top_tabs - display tabs with rounded edges
1561
 * INPUTS
1562
 *   $text	- array of tabs
1563
 * RESULT
1564
 *   null
1565
 ******/
1566
function display_top_tabs($tab_array) {
1567
	echo "<table cellpadding='0' cellspacing='0'>\n";
1568
	echo " <tr height='1'>\n";
1569
	$tabscounter = 0;
1570
	foreach ($tab_array as $ta) {
1571
		if($ta[1] == true) {
1572
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
1573
		} else {
1574
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
1575
		}
1576
		$tabscounter++;
1577
	}
1578
	echo "</tr>\n<tr>\n";
1579
	foreach ($tab_array as $ta) {
1580
		if($ta[1] == true) {
1581
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
1582
			echo "&nbsp;&nbsp;&nbsp;";
1583
			echo "<font size='-12'>&nbsp;</td>\n";
1584
		} else {
1585
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
1586
			echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
1587
			echo "<font size='-12'>&nbsp;</td>\n";
1588
		}
1589
	}
1590
	echo "</tr>\n<tr height='5px'>\n";
1591
	foreach ($tab_array as $ta) {
1592
		if($ta[1] == true) {
1593
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1594
		} else {
1595
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1596
		}
1597
		$tabscounter++;
1598
	}
1599
	echo " </tr>\n";
1600
	echo "</table>\n";
1601

    
1602
	echo "<script type=\"text/javascript\">";
1603
	echo "NiftyCheck();\n";
1604
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1605
	for($x=0; $x<$tabscounter; $x++)
1606
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1607
	echo "</script>";
1608
}
1609

    
1610

    
1611
/****f* pfsense-utils/display_topbar
1612
 * NAME
1613
 *   display_topbar - top a table off with rounded edges
1614
 * INPUTS
1615
 *   $text	- (optional) Text to include in bar
1616
 * RESULT
1617
 *   null
1618
 ******/
1619
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
1620
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
1621
	echo "       <tr height='1'>\n";
1622
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
1623
	echo "		<div id='topbar'></div></td>\n";
1624
	echo "       </tr>\n";
1625
	echo "       <tr height='1'>\n";
1626
	if ($text != "")
1627
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
1628
	else
1629
		echo "         <td height='1' class='listtopic'></td>\n";
1630
	echo "       </tr>\n";
1631
	echo "     </table>";
1632
	echo "<script type=\"text/javascript\">";
1633
	echo "NiftyCheck();\n";
1634
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
1635
	echo "</script>";
1636
}
1637

    
1638
/****f* pfsense-utils/generate_random_mac_address
1639
 * NAME
1640
 *   generate_random_mac - generates a random mac address
1641
 * INPUTS
1642
 *   none
1643
 * RESULT
1644
 *   $mac - a random mac address
1645
 ******/
1646
function generate_random_mac_address() {
1647
	$mac = "02";
1648
	for($x=0; $x<5; $x++)
1649
		$mac .= ":" . dechex(rand(16, 255));
1650
	return $mac;
1651
}
1652

    
1653
/****f* pfsense-utils/strncpy
1654
 * NAME
1655
 *   strncpy - copy strings
1656
 * INPUTS
1657
 *   &$dst, $src, $length
1658
 * RESULT
1659
 *   none
1660
 ******/
1661
function strncpy(&$dst, $src, $length) {
1662
	if (strlen($src) > $length) {
1663
		$dst = substr($src, 0, $length);
1664
	} else {
1665
		$dst = $src;
1666
	}
1667
}
1668

    
1669
/****f* pfsense-utils/reload_interfaces_sync
1670
 * NAME
1671
 *   reload_interfaces - reload all interfaces
1672
 * INPUTS
1673
 *   none
1674
 * RESULT
1675
 *   none
1676
 ******/
1677
function reload_interfaces_sync() {
1678
	global $config, $g, $debug;
1679

    
1680
	$shutdown_webgui_needed = false;
1681

    
1682
	touch("{$g['tmp_path']}/reloading_all");
1683

    
1684
	if($debug)
1685
		log_error("reload_interfaces_sync() is starting.");
1686

    
1687
	if(file_exists("{$g['tmp_path']}/config.cache"))
1688
		unlink("{$g['tmp_path']}/config.cache");
1689

    
1690
	/* parse config.xml again */
1691
	$config = parse_config(true);
1692

    
1693
	$wan_if = $config['interfaces']['wan']['if'];
1694
	$lan_if = $config['interfaces']['lan']['if'];
1695

    
1696
	if($debug)
1697
		log_error("Cleaning up Interfaces");
1698

    
1699
	/* build an array of interfaces to work with */
1700
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1701
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1702
		$iflist['opt' . $i] = "opt{$i}";
1703

    
1704
	foreach ($iflist as $ifent => $ifname) {
1705
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1706
		if(stristr($ifname, "lo0") == true)
1707
			continue;
1708
		/* do not process wan interface, its mandatory */
1709
		if(stristr($ifname, "$wan_if") == true)
1710
			continue;
1711
		/* do not process lan interface, its mandatory */
1712
		if(stristr($ifname, "$lan_if") == true)
1713
			continue;
1714
		if($debug)
1715
			log_error("Downing and deleting $ifname_real - $ifname");
1716
		mwexec("/sbin/ifconfig {$ifname_real} down");
1717
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1718
	}
1719

    
1720
	/* set up VLAN virtual interfaces */
1721
	if($debug)
1722
		log_error("Configuring VLANS");
1723
	interfaces_vlan_configure();
1724

    
1725
	/* set up LAN interface */
1726
	if($debug)
1727
		log_error("Configuring LAN");
1728
	interfaces_lan_configure();
1729

    
1730
	/* set up WAN interface */
1731
	if($debug)
1732
		log_error("Configuring WAN");
1733
	interfaces_wan_configure();
1734

    
1735
	/* set up Optional interfaces */
1736
	if($debug)
1737
		log_error("Configuring optional interfaces");
1738
	interfaces_optional_configure();
1739

    
1740
	/* set up static routes */
1741
	if($debug)
1742
		log_error("Configuring system Routing");
1743
	system_routing_configure();
1744

    
1745
	/* enable routing */
1746
	if($debug)
1747
		log_error("Enabling system routing");
1748
	system_routing_enable();
1749

    
1750
	/* setup captive portal if needed */
1751
	if($debug)
1752
		log_error("Configuring Captive portal");
1753
	captiveportal_configure();
1754

    
1755
	/* bring up carp interfaces */
1756
	if($debug)
1757
		log_error("Configuring CARP");
1758
	interfaces_carp_configure();
1759

    
1760
	/* bring up carp interfaces*/
1761
	if($debug)
1762
		log_error("Bringing up CARP interfaces");
1763
	interfaces_carp_bring_up_final();
1764

    
1765
	/* restart webConfigurator if needed */
1766
	if($shutdown_webgui_needed == true)
1767
		touch("/tmp/restart_webgui");
1768

    
1769
	/* start devd back up */
1770
	mwexec("/bin/rm /tmp/reload*");
1771

    
1772
	/* remove reloading_all trigger */
1773
	if($debug)
1774
		log_error("Removing {$g['tmp_path']}/reloading_all");
1775
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1776
}
1777

    
1778
/****f* pfsense-utils/reload_all
1779
 * NAME
1780
 *   reload_all - triggers a reload of all settings
1781
 *   * INPUTS
1782
 *   none
1783
 * RESULT
1784
 *   none
1785
 ******/
1786
function reload_all() {
1787
	touch("/tmp/reload_all");
1788
}
1789

    
1790
/****f* pfsense-utils/reload_interfaces
1791
 * NAME
1792
 *   reload_interfaces - triggers a reload of all interfaces
1793
 * INPUTS
1794
 *   none
1795
 * RESULT
1796
 *   none
1797
 ******/
1798
function reload_interfaces() {
1799
	touch("/tmp/reload_interfaces");
1800
}
1801

    
1802
/****f* pfsense-utils/sync_webgui_passwords
1803
 * NAME
1804
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1805
 * INPUTS
1806
 *   none
1807
 * RESULT
1808
 *   none
1809
 ******/
1810
function sync_webgui_passwords() {
1811
	global $config, $g;
1812
	conf_mount_rw();
1813
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
1814
	if (!$fd) {
1815
		printf("Error: cannot open htpasswd in system_password_configure().\n");
1816
		return 1;
1817
	}
1818
	/* set admin account */
1819
	$username = $config['system']['username'];
1820

    
1821
	/* set defined user account */
1822
	if($username <> "admin") {
1823
		$username = $config['system']['username'];
1824
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1825
	} else {
1826
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1827
	}
1828
	fclose($fd);
1829
	chmod("{$g['varrun_path']}/htpasswd", 0600);
1830
	$crypted_pw = $config['system']['password'];
1831
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1832
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1833
	/* sync root */
1834
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
1835
	fwrite($fd, $crypted_pw);
1836
	pclose($fd);
1837
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
1838
	/* sync admin */
1839
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
1840
	fwrite($fd, $crypted_pw);
1841
	pclose($fd);
1842
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
1843
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1844
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1845
	conf_mount_ro();
1846
}
1847

    
1848
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
1849
 * NAME
1850
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
1851
 *   * INPUTS
1852
 *   optional interface number
1853
 * RESULT
1854
 *   none
1855
 ******/
1856
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
1857
	/*	move all the interfaces up.  for example:
1858
	*		opt1 --> opt1
1859
	*		opt2 --> delete
1860
	*		opt3 --> opt2
1861
	*		opt4 --> opt3
1862
	*/
1863
	global $g, $config;
1864
	config_lock();
1865
	conf_mount_rw();
1866
	unlink_if_exists("{$g['tmp_path']}/config.cache");
1867
	$config_file = file_get_contents("/cf/conf/config.xml");
1868
	/* loop through and reassign deleted items */
1869
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
1870
		if ($i < $opt_interface_num)
1871
			break;
1872
		if ($i == $opt_interface_num) {
1873
			/* item should be deleted */
1874
			str_replace("opt" . $i, "optXXXX", $config_file);
1875
		}
1876
	}
1877
	/* loop through and reassign optional items */
1878
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
1879
		if ($i < $opt_interface_num)
1880
			break;
1881
		/* replace opt$i with $i -1 */
1882
		str_replace("opt" . $i, "opt" . ($i -1), $config_file);
1883
	}
1884
	$fd = fopen("/cf/conf/config.xml", "w");
1885
	fwrite($fd, $config_file);
1886
	fclose($fd);
1887
	$config = parse_config(true);
1888
	/* loop through and delete old rules */
1889
	$num_rules = count($config['filter']['rule']);
1890
	for($x = $num_rules; $x > 0; $x--) {
1891
		if($config['filter']['rule'][$x])
1892
			if($config['filter']['rule'][$x]['interface'] == "optXXXX")
1893
		 		unset($config['filter']['rule'][$x]['interface']);
1894
	}
1895
	$num_rules = count($config['nat']['advancedoutbound']['rule']);
1896
	for($x = $num_rules; $x > 0; $x--) {
1897
		if($config['nat']['advancedoutbound']['rule'][$x])
1898
			if($config['nat']['advancedoutbound']['rule'][$x]['interface'] == "optXXXX")
1899
		 		unset($config['nat']['advancedoutbound']['rule'][$x]['interface']);
1900
	}
1901
	$num_rules = count($config['nat']['rule']);
1902
	for($x = $num_rules; $x > 0; $x--) {
1903
		if($config['nat']['rule'][$x])
1904
			if($config['nat']['rule'][$x]['interface'] == "optXXXX")
1905
		 		unset($config['nat']['rule'][$x]['interface']);
1906
	}
1907
	conf_mount_ro();
1908
	config_unlock();
1909
	return true;
1910
}
1911

    
1912
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
1913
 * NAME
1914
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
1915
 *   		amount of netgraph interfaces needed for system wans
1916
 *   * INPUTS
1917
 *   none
1918
 * RESULT
1919
 *   number of needed netgraph (ng) interfaces
1920
 ******/
1921
function get_number_of_wan_netgraph_interfaces_needed() {
1922
	global $config, $g;
1923
	/* build an array of interfaces to work with */
1924
	$iflist = array("wan" => "WAN");
1925
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1926
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1927
	$ng_interfaces_needed = 0;
1928
	foreach ($iflist as $ifent => $ifname) {
1929
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1930
			$ng_interfaces_needed++;
1931
		}
1932
	}
1933
	return $ng_interfaces_needed;
1934
}
1935

    
1936
function get_netgaph_interface_assignment($friendly_interface) {
1937
	global $config, $g;
1938
	/* build an array of interfaces to work with */
1939
	$iflist = array("wan" => "WAN");
1940
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1941
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1942
		$ng_interfaces_needed = 0;
1943
		$ng_interfaces_number = 0;
1944
		foreach ($iflist as $ifent => $ifname) {
1945
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1946
			$ng_interfaces_number++;
1947
		}
1948
		if($friendly_interface == $ifname)
1949
			break;
1950
	}
1951
	return $ng_interfaces_number;
1952
}
1953

    
1954
/****f* pfsense-utils/reload_all_sync
1955
 * NAME
1956
 *   reload_all - reload all settings
1957
 *   * INPUTS
1958
 *   none
1959
 * RESULT
1960
 *   none
1961
 ******/
1962
function reload_all_sync() {
1963
	global $config, $g;
1964

    
1965
	$g['booting'] = false;
1966

    
1967
	touch("{$g['tmp_path']}/reloading_all");
1968

    
1969
	$shutdown_webgui_needed = false;
1970

    
1971
	if(file_exists("{$g['tmp_path']}/config.cache"))
1972
		unlink("{$g['tmp_path']}/config.cache");
1973

    
1974
	/* parse config.xml again */
1975
	$config = parse_config(true);
1976

    
1977
	/* set up our timezone */
1978
	system_timezone_configure();
1979

    
1980
	/* set up our hostname */
1981
	system_hostname_configure();
1982

    
1983
	/* make hosts file */
1984
	system_hosts_generate();
1985

    
1986
	/* generate resolv.conf */
1987
	system_resolvconf_generate();
1988

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

    
1992
	$wan_if = $config['interfaces']['wan']['if'];
1993
	$lan_if = $config['interfaces']['lan']['if'];
1994

    
1995
	/* build an array of interfaces to work with */
1996
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1997
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1998
		$iflist['opt' . $i] = "opt{$i}";
1999

    
2000
	foreach ($iflist as $ifent => $ifname) {
2001
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2002
		if(stristr($ifname, "lo0") == true)
2003
			continue;
2004
		/* do not process wan interface, its mandatory */
2005
		if($wan_if == $ifname_real)
2006
			continue;
2007
		/* do not process lan interface, its mandatory */
2008
		if($lan_if == $ifname_real)
2009
			continue;
2010
		mwexec("/sbin/ifconfig {$ifname_real} down");
2011
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2012
	}
2013

    
2014
	/* set up VLAN virtual interfaces */
2015
	interfaces_vlan_configure();
2016

    
2017
	/* set up LAN interface */
2018
	interfaces_lan_configure();
2019

    
2020
	/* set up WAN interface */
2021
	interfaces_wan_configure();
2022

    
2023
	/* set up Optional interfaces */
2024
	interfaces_optional_configure();
2025

    
2026
	/* bring up carp interfaces */
2027
	interfaces_carp_configure();
2028

    
2029
	/* set up static routes */
2030
	system_routing_configure();
2031

    
2032
	/* enable routing */
2033
	system_routing_enable();
2034

    
2035
	/* ensure passwords are sync'd */
2036
	system_password_configure();
2037

    
2038
	/* start dnsmasq service */
2039
	services_dnsmasq_configure();
2040

    
2041
	/* start dyndns service */
2042
	services_dyndns_configure();
2043

    
2044
	/* start DHCP service */
2045
	services_dhcpd_configure();
2046

    
2047
	/* configure cron service */
2048
	configure_cron();
2049

    
2050
	/* start the NTP client */
2051
	system_ntp_configure();
2052

    
2053
	/* start ftp proxy helpers if they are enabled */
2054
	system_start_ftp_helpers();
2055

    
2056
	/* start the captive portal */
2057
	captiveportal_configure();
2058

    
2059
        /* reload the filter */
2060
	filter_configure_sync();
2061

    
2062
	/* bring up carp interfaces*/
2063
	interfaces_carp_bring_up_final();
2064

    
2065
	/* sync pw database */
2066
	conf_mount_rw();
2067
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2068
	conf_mount_ro();
2069

    
2070
	/* restart sshd */
2071
	touch("/tmp/start_sshd");
2072

    
2073
	/* restart webConfigurator if needed */
2074
	if($shutdown_webgui_needed == true)
2075
		touch("/tmp/restart_webgui");
2076

    
2077
	mwexec("/bin/rm /tmp/reload*");
2078

    
2079
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2080

    
2081
}
2082

    
2083
function auto_login($status) {
2084
	$gettytab = file_get_contents("/etc/gettytab");
2085
	$getty_split = split("\n", $gettytab);
2086
	conf_mount_rw();
2087
	$fd = fopen("/etc/gettytab", "w");
2088
	foreach($getty_split as $gs) {
2089
		if(stristr($gs, ":ht:np:sp#115200") ) {
2090
			if($status == true) {
2091
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
2092
			} else {
2093
				fwrite($fd, "	:ht:np:sp#115200:\n");
2094
			}
2095
		} else {
2096
			fwrite($fd, "{$gs}\n");
2097
		}
2098
	}
2099
	fclose($fd);
2100
	conf_mount_ro();
2101
}
2102

    
2103
function setup_serial_port() {
2104
	global $g, $config;
2105
	conf_mount_rw();
2106
	/* serial console - write out /boot.config */
2107
	if(file_exists("/boot.config"))
2108
		$boot_config = file_get_contents("/boot.config");
2109
	else
2110
		$boot_config = "";
2111

    
2112
	if($g['platform'] <> "cdrom") {
2113
		$boot_config_split = split("\n", $boot_config);
2114
		$fd = fopen("/boot.config","w");
2115
		if($fd) {
2116
			foreach($boot_config_split as $bcs) {
2117
				if(stristr($bcs, "-D")) {
2118
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2119
				} else {
2120
					if($bcs <> "")
2121
						fwrite($fd, "{$bcs}\n");
2122
				}
2123
			}
2124
			if(isset($config['system']['enableserial'])) {
2125
				fwrite($fd, "-D");
2126
			}
2127
			fclose($fd);
2128
		}
2129
		/* serial console - write out /boot/loader.conf */
2130
		$boot_config = file_get_contents("/boot/loader.conf");
2131
		$boot_config_split = split("\n", $boot_config);
2132
		$fd = fopen("/boot/loader.conf","w");
2133
		if($fd) {
2134
			foreach($boot_config_split as $bcs) {
2135
				if(stristr($bcs, "console")) {
2136
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2137
				} else {
2138
					if($bcs <> "")
2139
						fwrite($fd, "{$bcs}\n");
2140
				}
2141
			}
2142
			if(isset($config['system']['enableserial'])) {
2143
				fwrite($fd, "console=\"comconsole\"\n");
2144
			}
2145
			fclose($fd);
2146
		}
2147
	}
2148
	$ttys = file_get_contents("/etc/ttys");
2149
	$ttys_split = split("\n", $ttys);
2150
	$fd = fopen("/etc/ttys", "w");
2151
	foreach($ttys_split as $tty) {
2152
		if(stristr($tty, "ttyd0")) {
2153
			if(isset($config['system']['enableserial'])) {
2154
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
2155
			} else {
2156
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
2157
			}
2158
		} else {
2159
			fwrite($fd, $tty . "\n");
2160
		}
2161
	}
2162
	fclose($fd);
2163
	if(isset($config['system']['disableconsolemenu'])) {
2164
		auto_login(false);
2165
	} else {
2166
		auto_login(true);
2167
	}
2168
	conf_mount_ro();
2169
	return;
2170
}
2171

    
2172
function print_value_list($list, $count = 10, $separator = ",") {
2173
	$list = implode($separator, array_slice($list, 0, $count));
2174
	if(count($list) < $count) {
2175
		$list .= ".";
2176
	} else {
2177
		$list .= "...";
2178
	}
2179
	return $list;
2180
}
2181

    
2182
function convert_friendly_interface_to_friendly_descr($interface) {
2183
	global $config;
2184
	/* attempt to resolve interface to friendly descr */
2185
	if($config['interfaces'][$interface]['descr'])
2186
		return $config['interfaces'][$interface]['descr'];
2187
	$tmp = convert_real_interface_to_friendly_descr($interface);
2188
	/* could not resolve, return back what was passed */
2189
	return $interface;
2190
}
2191

    
2192
function convert_real_interface_to_friendly_descr($interface) {
2193
	global $config;
2194
	if($interface == $config['interfaces']['wan']['if'])
2195
		return "wan";
2196
	if($interface == $config['interfaces']['lan']['if'])
2197
		return "lan";
2198
	/* attempt to resolve interface to friendly descr */
2199
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
2200
	if($config['interfaces'][$friendly_int]['descr'])
2201
		return $config['interfaces'][$friendly_int]['descr'];
2202
	/* could not resolve, return back what was passed */
2203
	return $interface;
2204
}
2205

    
2206
function enable_rrd_graphing() {
2207
	global $config, $g;
2208

    
2209
	if($g['booting']) 
2210
		echo "Generating RRD graphs...";
2211

    
2212
	$rrddbpath = "/var/db/rrd/";
2213
	$rrdgraphpath = "/usr/local/www/rrd";
2214

    
2215
	$traffic = "-traffic.rrd";
2216
	$packets = "-packets.rrd";
2217
	$states = "-states.rrd";
2218
	$quality = "-quality.rrd";
2219
	$queues = "-queues.rrd";
2220
	$queuesdrop = "-queuesdrop.rrd";
2221
	$spamd = "-spamd.rrd";
2222
	$proc = "-processor.rrd";
2223

    
2224
	$rrdtool = "/usr/local/bin/rrdtool";
2225
	$netstat = "/usr/bin/netstat";
2226
	$awk = "/usr/bin/awk";
2227
	$tar = "/usr/bin/tar";
2228
	$pfctl = "/sbin/pfctl";
2229
	$php = "/usr/local/bin/php";
2230
	$top = "/usr/bin/top";
2231
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2232

    
2233
	$rrdtrafficinterval = 60;
2234
	$rrdqualityinterval = 60;
2235
	$rrdqueuesinterval = 60;
2236
	$rrdqueuesdropinterval = 60;
2237
	$rrdpacketsinterval = 60;
2238
	$rrdstatesinterval = 60;
2239
	$rrdspamdinterval = 60;
2240
	$rrdlbpoolinterval = 60;
2241
	$rrdprocinterval = 60;
2242

    
2243
	$trafficvalid = $rrdtrafficinterval * 2;
2244
	$qualityvalid = $rrdqualityinterval * 2;
2245
	$queuesvalid = $rrdqueuesinterval * 2;
2246
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2247
	$packetsvalid = $rrdpacketsinterval * 2;
2248
	$statesvalid = $rrdstatesinterval*2;
2249
	$spamdvalid = $rrdspamdinterval * 2;
2250
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2251
	$procvalid = $rrdlbpoolinterval * 2;
2252

    
2253
	/* Asume GigE for now */
2254
	$downstream = 125000000;
2255
	$upstream = 125000000;
2256

    
2257
	$rrdrestore = "";
2258
	$rrdreturn = "";
2259

    
2260
	$config['rrd']['enable'] = true;
2261

    
2262
	if (isset ($config['rrd']['enable'])) {
2263

    
2264
		/* create directory if needed */
2265
		if (!is_dir("$rrddbpath")) {
2266
			mkdir("$rrddbpath", 0755);
2267
		}
2268

    
2269
		if ($g['booting']) {
2270
			if ($g['platform'] != "pfSense") {
2271
				/* restore the databases, if we have one */
2272
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
2273
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2274
					if((int)$rrdrestore <> 0) {
2275
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
2276
					}
2277
				}
2278
			}
2279
		}
2280

    
2281
		/* db update script */
2282
		$rrdupdatesh = "#!/bin/sh\n";
2283
		$rrdupdatesh .= "\n";
2284
		$rrdupdatesh .= "counter=1\n";
2285
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2286
		$rrdupdatesh .= "do\n";
2287
		$rrdupdatesh .= "";
2288

    
2289
		$i = 0;
2290
		$vfaces = array (
2291
			"vlan.?*",
2292
			"enc.?*"
2293
		);
2294
		$ifdescrs = get_interface_list(true, true, $vfaces);
2295
		$ifdescrs['enc0']['friendly'] = "ipsec";
2296
		$ifdescrs['enc0']['descr'] = "IPSEC";
2297
		$ifdescrs['enc0']['up'] = true;
2298

    
2299
		foreach ($ifdescrs as $realif => $ifdescr) {
2300
			$ifname = $ifdescr['friendly'];
2301
			$state = $ifdescr['up'];
2302

    
2303
			/* skip interfaces that do not have a friendly name */
2304
			if ("$ifname" == "") {
2305
				continue;
2306
			}
2307

    
2308
			/* or are down */
2309
			if (!$state) {
2310
				continue;
2311
			}
2312

    
2313
			/* TRAFFIC, set up the rrd file */
2314
			if (!file_exists("$rrddbpath$ifname$traffic")) {
2315
				/* create rrd file if it does not exist */
2316
				log_error("Create RRD database $rrddbpath$ifname$traffic");
2317
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
2318
				$rrdcreate .= "DS:in:COUNTER:$trafficvalid:0:$downstream ";
2319
				$rrdcreate .= "DS:out:COUNTER:$trafficvalid:0:$upstream ";
2320
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2321
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2322
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2323
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2324
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2325
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2326
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2327
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
2328

    
2329
				$rrdcreateoutput = array();
2330
				$rrdcreatereturn = "";
2331

    
2332
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2333
				if ($rrdcreatereturn != 0) {
2334
					log_error("RRD create failed exited with $rrdcreatereturn, the
2335
							error is: $rrdcreateoutput[0]\n");
2336
				}
2337
			}
2338

    
2339
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2340
			if($g['booting']) {
2341
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
2342
			}
2343

    
2344
			$rrdupdatesh .= "\n";
2345
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
2346
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
2347
			if(! is_macaddr(get_interface_mac($realif))) {
2348
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$6 \":\" \$9}'`\n";
2349
			} else {
2350
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7 \":\" \$10}'`\n";
2351
			}
2352

    
2353
			/* PACKETS, set up the rrd file */
2354
			if (!file_exists("$rrddbpath$ifname$packets")) {
2355
				/* create rrd file if it does not exist */
2356
				log_error("Create RRD database $rrddbpath$ifname$packets");
2357
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
2358
				$rrdcreate .= "DS:in:COUNTER:$packetsvalid:0:$downstream ";
2359
				$rrdcreate .= "DS:out:COUNTER:$packetsvalid:0:$upstream ";
2360
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2361
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2362
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2363
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2364
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2365
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2366
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2367
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
2368

    
2369
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2370
				if ($rrdcreatereturn != 0) {
2371
					log_error("RRD create failed exited with $rrdcreatereturn, the
2372
							error is: $rrdcreateoutput[0]\n");
2373
				}
2374
			}
2375

    
2376
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2377
			if($g['booting']) {
2378
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
2379
			}
2380

    
2381
			$rrdupdatesh .= "\n";
2382
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
2383
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
2384
			if(! is_macaddr(get_interface_mac($realif))) {
2385
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$4 \":\" \$7}'`\n";
2386
			} else {
2387
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5 \":\" \$8}'`\n";
2388
			}
2389
			/* if an alternative gateway is defined, use it */
2390
			if ($config['system']['interfaces'][$ifname]['use_rrd_gateway'] <> "") {
2391
				$gatewayip = get_interface_gateway($ifname);
2392
				$monitorip = $config['system']['interfaces'][$ifname]['use_rrd_gateway'];
2393
				mwexec("/sbin/route add -host {$monitorip} {$gatewayip} 1> /dev/null 2>&1");
2394
			} else {
2395
				$monitorip = get_interface_gateway($ifname);
2396
			}
2397
			$numpings = 5;
2398
			$btick = '`';
2399

    
2400
			if($monitorip <> "") {
2401
				/* QUALITY, create link quality database */
2402
				if (!file_exists("$rrddbpath$ifname$quality")) {
2403
					/* create rrd file if it does not exist */
2404
					log_error("Create RRD database $rrddbpath$ifname$quality");
2405
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
2406
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
2407
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
2408
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2409
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2410
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2411
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
2412

    
2413
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2414
					if ($rrdcreatereturn != 0) {
2415
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2416
					}
2417
				}
2418

    
2419
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2420
				if($g['booting']) {
2421
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
2422
				}
2423

    
2424
				/* the ping test function. We call this on the last line */
2425
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
2426
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
2427
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
2428
				$rrdupdatesh .= "	local out_{$ifname}\n";
2429
				$rrdupdatesh .= "	out_{$ifname}=$btick ping -c $numpings -q $monitorip $btick\n";
2430
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
2431
				$rrdupdatesh .= "		packetloss_{$ifname}=$btick echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1 $btick\n";
2432
				$rrdupdatesh .= "		roundtrip_{$ifname}=$btick echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/' $btick\n";
2433
				$rrdupdatesh .= "	fi\n";
2434
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
2435
				$rrdupdatesh .= "}\n\n";
2436

    
2437
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
2438
			}
2439

    
2440
			/* WAN interface only statistics */
2441
			if ("$ifname" == "wan") {
2442

    
2443
				/* QUEUES, set up the queues databases */
2444
				if (!is_array($config['shaper']['queue'])) {
2445
					$config['shaper']['queue'] = array ();
2446
				}
2447
				$a_queues = & $config['shaper']['queue'];
2448

    
2449
				if (isset ($config['shaper']['enable'])) {
2450
					if (!file_exists("$rrddbpath$ifname$queues")) {
2451
						/* create rrd file if it does not exist */
2452
						log_error("Create RRD database $rrddbpath$ifname$queues");
2453
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
2454
						/* loop list of shaper queues */
2455
						$q = 0;
2456
						foreach ($a_queues as $queue) {
2457
							$name = $queue['name'];
2458
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream ";
2459
						}
2460

    
2461
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2462
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2463
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2464
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
2465

    
2466
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2467
						if ($rrdcreatereturn != 0) {
2468
							log_error("RRD create failed exited with $rrdcreatereturn, the
2469
									error is: $rrdcreateoutput[0]\n");
2470
						}
2471
					}
2472

    
2473
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
2474
						/* create rrd file if it does not exist */
2475
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
2476
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
2477
						/* loop list of shaper queues */
2478
						$q = 0;
2479
						foreach ($a_queues as $queue) {
2480
							$name = $queue['name'];
2481
							$rrdcreate .= "DS:$name:COUNTER:$queuesdropvalid:0:$downstream ";
2482
						}
2483

    
2484
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2485
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2486
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2487
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
2488

    
2489
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2490
						if ($rrdcreatereturn != 0) {
2491
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2492
						}
2493
					}
2494

    
2495
					if($g['booting']) {
2496
						$rrdqcommand = "-t ";
2497
						$rrducommand = "N";
2498
						$q = 0;
2499
						foreach ($a_queues as $queue) {
2500
							if($q == 0) {
2501
								$rrdqcommand .= "{$queue['name']}";
2502
							} else {
2503
								$rrdqcommand .= ":{$queue['name']}";
2504
							}
2505
							$q++;
2506
							$rrducommand .= ":U";
2507
						}
2508
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
2509
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
2510
					}
2511

    
2512
					/* awk function to gather shaper data */
2513
					/* yes, it's special */
2514
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
2515
					$rrdupdatesh .= "{ ";
2516
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
2517
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
2518
					$rrdupdatesh .= "q=1; ";
2519
					$rrdupdatesh .= "} ";
2520
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
2521
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
2522
					$rrdupdatesh .= "q=0; ";
2523
					$rrdupdatesh .= "} ";
2524
					$rrdupdatesh .= "} END { ";
2525
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
2526
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
2527
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
2528
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
2529

    
2530
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
2531
					$rrdupdatesh .= "{ ";
2532
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
2533
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
2534
					$rrdupdatesh .= "q=1; ";
2535
					$rrdupdatesh .= "} ";
2536
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
2537
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
2538
					$rrdupdatesh .= "q=0; ";
2539
					$rrdupdatesh .= "} ";
2540
					$rrdupdatesh .= "} END { ";
2541
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
2542
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
2543
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
2544
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
2545
				}
2546
			}
2547
		}
2548
		$i++;
2549

    
2550
		/* System only statistics */
2551
		$ifname = "system";
2552

    
2553
			/* STATES, create pf states database */
2554
			if(! file_exists("$rrddbpath$ifname$states")) {
2555
				/* create rrd file if it does not exist */
2556
				log_error("Create RRD database $rrddbpath$ifname$states");
2557
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
2558
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
2559
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
2560
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
2561
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
2562
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
2563
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
2564
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
2565
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
2566
				$rrdcreate .= "RRA:MIN:0.5:360:1000 ";
2567
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2568
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2569
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2570
				$rrdcreate .= "RRA:AVERAGE:0.5:360:1000 ";
2571
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2572
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2573
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2574
				$rrdcreate .= "RRA:MAX:0.5:360:1000";
2575

    
2576
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2577
				if($rrdcreatereturn != 0) {
2578
			                log_error("RRD create failed exited with $rrdcreatereturn, the
2579
						error is: $rrdcreateoutput[0]\n");
2580
				}
2581
			}
2582

    
2583
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2584
			if($g['booting']) {
2585
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
2586
			}
2587

    
2588
 			/* the pf states gathering function. */
2589
 			$rrdupdatesh .= "\n";
2590
 			$rrdupdatesh .= "pfrate=\"` $pfctl -si | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
2591
 			$rrdupdatesh .= "pfstates=\"` $pfctl -ss | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
2592
			$rrdupdatesh .= "pfnat=\"` $pfctl -ss | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
2593
 			$rrdupdatesh .= "srcip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '\\->' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
2594
 			$rrdupdatesh .= "dstip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '<\\-' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
2595
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
2596

    
2597
			/* End pf states statistics */
2598

    
2599
			/* CPU, create CPU statistics database */
2600
			if(! file_exists("$rrddbpath$ifname$proc")) {
2601
				/* create rrd file if it does not exist */
2602
				log_error("Create RRD database $rrddbpath$ifname$proc");
2603
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
2604
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
2605
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
2606
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
2607
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
2608
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
2609
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
2610
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
2611
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
2612
				$rrdcreate .= "RRA:MIN:0.5:360:1000 ";
2613
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2614
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2615
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2616
				$rrdcreate .= "RRA:AVERAGE:0.5:360:1000 ";
2617
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2618
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2619
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2620
				$rrdcreate .= "RRA:MAX:0.5:360:1000";
2621

    
2622
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2623
				if($rrdcreatereturn != 0) {
2624
			                log_error("RRD create failed exited with $rrdcreatereturn, the
2625
						error is: $rrdcreateoutput[0]\n");
2626
				}
2627
			}
2628

    
2629
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2630
			if($g['booting']) {
2631
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
2632
			}
2633

    
2634
 			/* the CPU stats gathering function. */
2635
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { ";
2636
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } ";
2637
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { ";
2638
			$rrdupdatesh .= "processes = \$1; ";
2639
			$rrdupdatesh .= "} ";
2640
			$rrdupdatesh .= "else if ( \$1 == \"CPU\" ) { ";
2641
			$rrdupdatesh .= "user = \$3; ";
2642
			$rrdupdatesh .= "nice = \$5; ";
2643
			$rrdupdatesh .= "sys = \$7; ";
2644
			$rrdupdatesh .= "interrupt = \$9; ";
2645
			$rrdupdatesh .= "} ";
2646
			$rrdupdatesh .= "} END { ";
2647
			$rrdupdatesh .= "printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes ";
2648
			$rrdupdatesh .= "}'`\n\n";
2649

    
2650
			/* End CPU statistics */
2651

    
2652
			/* SPAMD, set up the spamd rrd file */
2653
			if (isset($config['installedpackages']['spamdsettings']) &&
2654
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
2655
				/* set up the spamd rrd file */
2656
				if (!file_exists("$rrddbpath$ifname$spamd")) {
2657
						/* create rrd file if it does not exist */
2658
						log_error("Create RRD database $rrddbpath$ifname$spamd");
2659
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
2660
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
2661
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
2662
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
2663
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
2664
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
2665
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
2666
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2667
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2668
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2669
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2670
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2671
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2672
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2673
						$rrdcreate .= "RRA:MAX:0.5:720:1000";
2674

    
2675
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2676
					if ($rrdcreatereturn != 0) {
2677
						log_error("RRD create failed exited with $rrdcreatereturn, the
2678
							error is: $rrdcreateoutput[0]\n");
2679
					}
2680
				}
2681

    
2682
				$rrdupdatesh .= "\n";
2683
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
2684
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
2685
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
2686

    
2687
			}
2688
		/* End System statistics */
2689

    
2690
		$rrdupdatesh .= "sleep 60\n";
2691
		$rrdupdatesh .= "done\n";
2692
		log_error("Creating rrd update script");
2693
		/* write the rrd update script */
2694
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
2695
		$fd = fopen("$updaterrdscript", "w");
2696
		fwrite($fd, "$rrdupdatesh");
2697
		fclose($fd);
2698

    
2699
		/* kill off traffic collectors */
2700
		kill_traffic_collector();
2701

    
2702
		/* start traffic collector */
2703
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
2704

    
2705
	} else {
2706
		/* kill off traffic collectors */
2707
		kill_traffic_collector();
2708
	}
2709

    
2710
	if($g['booting']) 
2711
		echo "done.\n";
2712
		
2713
}
2714

    
2715
function kill_traffic_collector() {
2716
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
2717
}
2718

    
2719
function update_filter_reload_status($text) {
2720
	global $g;
2721
	config_lock();
2722
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
2723
	fwrite($fd, $text);
2724
	fclose($fd);
2725
	config_unlock();
2726
}
2727

    
2728
function get_interface_gateway($interface) {
2729
	global $config, $g;
2730
	$interface = strtolower($interface);
2731
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
2732
	 *  grab the address from the configuration file.
2733
	 */
2734
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
2735
	if($tmpif <> $interface)
2736
		$interface = $tmpif;
2737
	$realif = $config['interfaces'][$interface]['if'];
2738
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
2739
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
2740
		$gw = rtrim($gw);
2741
	} else {
2742
		$gw = $config['interfaces'][$interface]['gateway'];
2743
	}
2744
	/* if wan is requested, return it */
2745
	if($interface == "wan")
2746
		return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
2747
	/* return gateway */
2748
	return $gw;
2749
}
2750

    
2751
function is_dhcp_server_enabled() {
2752
	/* DHCP enabled on any interfaces? */
2753
	global $config, $g;
2754
	$dhcpdcfg = $config['dhcpd'];
2755
	$dhcpdenable = false;
2756
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
2757
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2758
			$dhcpdenable = true;
2759
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2760
			$dhcpdenable = true;
2761
	}
2762
	return $dhcpdenable;
2763
}
2764

    
2765
/* return outside interfaces with a gateway */
2766
function get_interfaces_with_gateway() {
2767
	global $config;
2768
	$ints = array();
2769
	$ifdescrs = get_interface_list();
2770

    
2771
	/* loop interfaces, check config for outbound */
2772
	foreach ($ifdescrs as $ifdescr => $ifname) {
2773
		$friendly = $ifname['friendly'];
2774
		if ($config['interfaces'][$friendly]['ipaddr'] == "dhcp") {
2775
			$ints[] = $friendly;
2776
			continue;
2777
		}
2778
		if ($config['interfaces'][$friendly]['ipaddr'] == "pppoe") {
2779
			$ints[] = $friendly;
2780
			continue;
2781
		}
2782
		if ($config['interfaces'][$friendly]['ipaddr'] == "pptp") {
2783
			$ints[] = $friendly;
2784
			continue;
2785
		}
2786
		if ($config['interfaces'][$friendly]['gateway'] <> "") {
2787
			$ints[] = $friendly;
2788
			continue;
2789
		}
2790
	}
2791
	return $ints;
2792
}
2793

    
2794
/* return true if interface has a gateway */
2795
function interface_has_gateway($friendly) {
2796
	$friendly = strtolower($friendly);
2797
	if(in_array($friendly, get_interfaces_with_gateway())) {
2798
		return true;
2799
	} else {
2800
		/* extra check for real interface names if it falls through */
2801
		$friendly = convert_real_interface_to_friendly_interface_name($friendly);
2802
		return(in_array($friendly, get_interfaces_with_gateway()));
2803
	}
2804
}
2805

    
2806
?>
(14-14/27)