Project

General

Profile

Download (81.8 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
	return false;
124
}
125

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

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

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

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

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

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

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

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

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

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

    
330
	if(stristr($interface,"lnc"))
331
		return;
332
	if(isset($config['system']['do_not_use_nic_microcode']))
333
		return;
334

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

    
345
	if($config['system']['disablechecksumoffloading'])
346
		return;
347

    
348
	if(stristr($options, "txcsum") == true)
349
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
350
	if(stristr($options, "rxcsum") == true)
351
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
352
	if(stristr($options, "polling") == true)
353
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
354
	} else {
355
		mwexec("sysctl kern.polling.enable=0");
356
	}
357
	return;
358
}
359

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

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

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

    
415
/****f* pfsense-utils/setup_polling
416
 * NAME
417
 *   sets up polling
418
 * INPUTS
419
 *
420
 * RESULT
421
 *   null
422
 * NOTES
423
 *
424
 ******/
425
function setup_polling() {
426
	global $g, $config;
427

    
428
	setup_polling_defaults();
429

    
430
	if(isset($config['system']['polling']))
431
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
432
	else
433
		$supported_ints = array();
434

    
435
	/* build an array of interfaces to work with */
436
	$iflist = array("lan" => "LAN", "wan" => "WAN");
437
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
438
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
439

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

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

    
470
	$ifdescrs = array('wan', 'lan');
471
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
472
		$ifdescrs['opt' . $j] = "opt" . $j;
473
	}
474
	foreach($ifdescrs as $if)
475
		enable_hardware_offloading($if);
476
}
477

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

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

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

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

    
544
	if($tmp == "")
545
		return false;
546
	else
547
		return true;
548
}
549

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

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

    
576
/****f* pfsense-utils/find_number_of_created_carp_interfaces
577
 * NAME
578
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
579
 * RESULT
580
 *   $tmp	- Number of currently created CARP interfaces.
581
 ******/
582
function find_number_of_created_carp_interfaces($flush = false) {
583
	global $carp_interface_count_cache;
584

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

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

    
622
function link_carp_interface_to_parent($interface) {
623
	global $config;
624
	if($interface == "") return;
625

    
626
	$ifdescrs = array('wan', 'lan');
627
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
628
		$ifdescrs['opt' . $j] = "opt" . $j;
629

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

    
644
/****f* pfsense-utils/link_ip_to_carp_interface
645
 * NAME
646
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
647
 * INPUTS
648
 *   $ip
649
 * RESULT
650
 *   $carp_ints
651
 ******/
652
function link_ip_to_carp_interface($ip) {
653
	global $config;
654
	if($ip == "") return;
655

    
656
	$ifdescrs = array('wan', 'lan');
657
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
658
		$ifdescrs['opt' . $j] = "opt" . $j;
659

    
660
	$ft = split("\.", $ip);
661
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
662

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

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

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

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

    
734
	$capable = $g['vlan_long_frame'];
735

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

    
738
	if (in_array($int_family[0], $capable))
739
		return true;
740
	else
741
		return false;
742
}
743

    
744
/*
745
 * Return the interface array
746
 */
747
function get_interface_arr($flush = false) {
748
	global $interface_arr_cache;
749

    
750
	/* If the cache doesn't exist, build it */
751
	if (!isset($interface_arr_cache) or $flush)
752
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
753

    
754
	return $interface_arr_cache;
755
}
756

    
757
/*
758
 * does_interface_exist($interface): return true or false if a interface is
759
 * detected.
760
 */
761
function does_interface_exist($interface) {
762
        $ints = get_interface_arr();
763

    
764
	if(stristr($ints, $interface) !== false)
765
		return true;
766
	else
767
		return false;
768
}
769

    
770
/*
771
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
772
 */
773
function convert_ip_to_network_format($ip, $subnet) {
774
	$ipsplit = split('[.]', $ip);
775
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
776
	return $string;
777
}
778

    
779
/*
780
 * find_interface_ip($interface): return the interface ip (first found)
781
 */
782
function find_interface_ip($interface, $flush = false) {
783
	global $interface_ip_arr_cache;
784
	$interface = str_replace("\n", "", $interface);
785
	if(does_interface_exist($interface) == false) return;
786
	/* Setup IP cache */
787
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
788
		$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");
789
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
790
	}
791

    
792
	return $interface_ip_arr_cache[$interface];
793
}
794

    
795
function guess_interface_from_ip($ipaddress) {
796
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2
797
; };'");
798
	return $ret;
799
}
800

    
801
function filter_opt_interface_to_real($opt) {
802
	global $config;
803
	return $config['interfaces'][$opt]['if'];
804
}
805

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

    
811
function get_friendly_interface_list_as_array() {
812
	global $config;
813
	$ints = array();
814
	$ifdescrs = get_interface_list();
815
	foreach ($ifdescrs as $ifdescr => $ifname) {
816
		array_push($ints,$ifdescr);
817
	}
818
	return $ints;
819
}
820

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

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

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

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

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

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

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

    
927
	return $bridge_interface_count_cache;
928
}
929

    
930
/*
931
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
932
 */
933
function add_rule_to_anchor($anchor, $rule, $label) {
934
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
935
}
936

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

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

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

    
995
/*
996
 * get_filename_from_url($url): converts a url to its filename.
997
 */
998
function get_filename_from_url($url) {
999
	return basename($url);
1000
}
1001

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

    
1017
/*
1018
 *   get_dir: return an array of $dir
1019
 */
1020
function get_dir($dir) {
1021
	$dir_array = array();
1022
	$d = dir($dir);
1023
	while (false !== ($entry = $d->read())) {
1024
		array_push($dir_array, $entry);
1025
	}
1026
	$d->close();
1027
	return $dir_array;
1028
}
1029

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

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

    
1057
/*
1058
 *   exec_command_and_return_text: execute command and return output
1059
 */
1060
function exec_command_and_return_text($command) {
1061
	return exec_command($command);
1062
}
1063

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

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

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

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

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

    
1172
	for ($a=0; $a < 6; $a++)
1173
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1174

    
1175
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1176

    
1177
	for ($a = 1; $a <= 16; $a++)
1178
		$msg .= $hw_addr;
1179

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

    
1196
	return false;
1197
}
1198

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

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

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

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

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

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

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

    
1337
";
1338

    
1339
	$errno = "";
1340
	$errstr = "";
1341
	$fp = fsockopen($server, $port, $errno, $errstr);
1342
	if (!$fp) {
1343
		return false;
1344
	}
1345

    
1346
	fputs($fp, $headers);
1347
	fputs($fp, $urlencoded);
1348

    
1349
	$ret = "";
1350
	while (!feof($fp))
1351
		$ret.= fgets($fp, 1024);
1352
	fclose($fp);
1353

    
1354
	return $ret;
1355
}
1356

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

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

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

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

    
1457
/*
1458
 *    safe_mkdir($path, $mode = 0755)
1459
 *    create directory if it doesn't already exist and isn't a file!
1460
 */
1461
function safe_mkdir($path, $mode=0755) {
1462
	global $g;
1463

    
1464
	/* cdrom is ro. */
1465
	if($g['platform'] == "cdrom")
1466
		return false;
1467

    
1468
	if (!is_file($path) && !is_dir($path))
1469
		return mkdir($path, $mode);
1470
	else
1471
		return false;
1472
}
1473

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

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

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

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

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

    
1597
	echo "<script type=\"text/javascript\">";
1598
	echo "NiftyCheck();\n";
1599
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1600
	for($x=0; $x<$tabscounter; $x++)
1601
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1602
	echo "</script>";
1603
}
1604

    
1605

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

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

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

    
1664
/****f* pfsense-utils/reload_interfaces_sync
1665
 * NAME
1666
 *   reload_interfaces - reload all interfaces
1667
 * INPUTS
1668
 *   none
1669
 * RESULT
1670
 *   none
1671
 ******/
1672
function reload_interfaces_sync() {
1673
	global $config, $g, $debug;
1674

    
1675
	$shutdown_webgui_needed = false;
1676

    
1677
	touch("{$g['tmp_path']}/reloading_all");
1678

    
1679
	if($debug)
1680
		log_error("reload_interfaces_sync() is starting.");
1681

    
1682
	if(file_exists("{$g['tmp_path']}/config.cache"))
1683
		unlink("{$g['tmp_path']}/config.cache");
1684

    
1685
	/* parse config.xml again */
1686
	$config = parse_config(true);
1687

    
1688
	$wan_if = $config['interfaces']['wan']['if'];
1689
	$lan_if = $config['interfaces']['lan']['if'];
1690

    
1691
	if($debug)
1692
		log_error("Cleaning up Interfaces");
1693

    
1694
	/* build an array of interfaces to work with */
1695
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1696
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1697
		$iflist['opt' . $i] = "opt{$i}";
1698

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

    
1715
	/* set up VLAN virtual interfaces */
1716
	if($debug)
1717
		log_error("Configuring VLANS");
1718
	interfaces_vlan_configure();
1719

    
1720
	/* set up LAN interface */
1721
	if($debug)
1722
		log_error("Configuring LAN");
1723
	interfaces_lan_configure();
1724

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

    
1730
	/* set up Optional interfaces */
1731
	if($debug)
1732
		log_error("Configuring optional interfaces");
1733
	interfaces_optional_configure();
1734

    
1735
	/* set up static routes */
1736
	if($debug)
1737
		log_error("Configuring system Routing");
1738
	system_routing_configure();
1739

    
1740
	/* enable routing */
1741
	if($debug)
1742
		log_error("Enabling system routing");
1743
	system_routing_enable();
1744

    
1745
	/* setup captive portal if needed */
1746
	if($debug)
1747
		log_error("Configuring Captive portal");
1748
	captiveportal_configure();
1749

    
1750
	/* bring up carp interfaces */
1751
	if($debug)
1752
		log_error("Configuring CARP");
1753
	interfaces_carp_configure();
1754

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

    
1760
	/* restart webConfigurator if needed */
1761
	if($shutdown_webgui_needed == true)
1762
		touch("/tmp/restart_webgui");
1763

    
1764
	/* start devd back up */
1765
	mwexec("/bin/rm /tmp/reload*");
1766

    
1767
	/* remove reloading_all trigger */
1768
	if($debug)
1769
		log_error("Removing {$g['tmp_path']}/reloading_all");
1770
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1771
}
1772

    
1773
/****f* pfsense-utils/reload_all
1774
 * NAME
1775
 *   reload_all - triggers a reload of all settings
1776
 *   * INPUTS
1777
 *   none
1778
 * RESULT
1779
 *   none
1780
 ******/
1781
function reload_all() {
1782
	touch("/tmp/reload_all");
1783
}
1784

    
1785
/****f* pfsense-utils/reload_interfaces
1786
 * NAME
1787
 *   reload_interfaces - triggers a reload of all interfaces
1788
 * INPUTS
1789
 *   none
1790
 * RESULT
1791
 *   none
1792
 ******/
1793
function reload_interfaces() {
1794
	touch("/tmp/reload_interfaces");
1795
}
1796

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

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

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

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

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

    
1949
/****f* pfsense-utils/reload_all_sync
1950
 * NAME
1951
 *   reload_all - reload all settings
1952
 *   * INPUTS
1953
 *   none
1954
 * RESULT
1955
 *   none
1956
 ******/
1957
function reload_all_sync() {
1958
	global $config, $g;
1959

    
1960
	$g['booting'] = false;
1961

    
1962
	touch("{$g['tmp_path']}/reloading_all");
1963

    
1964
	$shutdown_webgui_needed = false;
1965

    
1966
	if(file_exists("{$g['tmp_path']}/config.cache"))
1967
		unlink("{$g['tmp_path']}/config.cache");
1968

    
1969
	/* parse config.xml again */
1970
	$config = parse_config(true);
1971

    
1972
	/* set up our timezone */
1973
	system_timezone_configure();
1974

    
1975
	/* set up our hostname */
1976
	system_hostname_configure();
1977

    
1978
	/* make hosts file */
1979
	system_hosts_generate();
1980

    
1981
	/* generate resolv.conf */
1982
	system_resolvconf_generate();
1983

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

    
1987
	$wan_if = $config['interfaces']['wan']['if'];
1988
	$lan_if = $config['interfaces']['lan']['if'];
1989

    
1990
	/* build an array of interfaces to work with */
1991
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1992
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1993
		$iflist['opt' . $i] = "opt{$i}";
1994

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

    
2009
	/* set up VLAN virtual interfaces */
2010
	interfaces_vlan_configure();
2011

    
2012
	/* set up LAN interface */
2013
	interfaces_lan_configure();
2014

    
2015
	/* set up WAN interface */
2016
	interfaces_wan_configure();
2017

    
2018
	/* set up Optional interfaces */
2019
	interfaces_optional_configure();
2020

    
2021
	/* bring up carp interfaces */
2022
	interfaces_carp_configure();
2023

    
2024
	/* set up static routes */
2025
	system_routing_configure();
2026

    
2027
	/* enable routing */
2028
	system_routing_enable();
2029

    
2030
	/* ensure passwords are sync'd */
2031
	system_password_configure();
2032

    
2033
	/* start dnsmasq service */
2034
	services_dnsmasq_configure();
2035

    
2036
	/* start dyndns service */
2037
	services_dyndns_configure();
2038

    
2039
	/* start DHCP service */
2040
	services_dhcpd_configure();
2041

    
2042
	/* configure cron service */
2043
	configure_cron();
2044

    
2045
	/* start the NTP client */
2046
	system_ntp_configure();
2047

    
2048
	/* start ftp proxy helpers if they are enabled */
2049
	system_start_ftp_helpers();
2050

    
2051
	/* start the captive portal */
2052
	captiveportal_configure();
2053

    
2054
        /* reload the filter */
2055
	filter_configure_sync();
2056

    
2057
	/* bring up carp interfaces*/
2058
	interfaces_carp_bring_up_final();
2059

    
2060
	/* sync pw database */
2061
	conf_mount_rw();
2062
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2063
	conf_mount_ro();
2064

    
2065
	/* restart sshd */
2066
	touch("/tmp/start_sshd");
2067

    
2068
	/* restart webConfigurator if needed */
2069
	if($shutdown_webgui_needed == true)
2070
		touch("/tmp/restart_webgui");
2071

    
2072
	mwexec("/bin/rm /tmp/reload*");
2073

    
2074
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2075

    
2076
}
2077

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

    
2098
function setup_serial_port() {
2099
	global $g, $config;
2100
	conf_mount_rw();
2101
	/* serial console - write out /boot.config */
2102
	if(file_exists("/boot.config"))
2103
		$boot_config = file_get_contents("/boot.config");
2104
	else
2105
		$boot_config = "";
2106

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

    
2167
function print_value_list($list, $count = 10, $separator = ",") {
2168
	$list = implode($separator, array_slice($list, 0, $count));
2169
	if(count($list) < $count) {
2170
		$list .= ".";
2171
	} else {
2172
		$list .= "...";
2173
	}
2174
	return $list;
2175
}
2176

    
2177
function convert_friendly_interface_to_friendly_descr($interface) {
2178
	global $config;
2179
	/* attempt to resolve interface to friendly descr */
2180
	if($config['interfaces'][$interface]['descr'])
2181
		return $config['interfaces'][$interface]['descr'];
2182
	$tmp = convert_real_interface_to_friendly_descr($interface);
2183
	/* could not resolve, return back what was passed */
2184
	return $interface;
2185
}
2186

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

    
2201
function enable_rrd_graphing() {
2202
	global $config, $g;
2203

    
2204
	if($g['booting']) 
2205
		echo "Generating RRD graphs...";
2206

    
2207
	$rrddbpath = "/var/db/rrd/";
2208
	$rrdgraphpath = "/usr/local/www/rrd";
2209

    
2210
	$traffic = "-traffic.rrd";
2211
	$packets = "-packets.rrd";
2212
	$states = "-states.rrd";
2213
	$quality = "-quality.rrd";
2214
	$queues = "-queues.rrd";
2215
	$queuesdrop = "-queuesdrop.rrd";
2216
	$spamd = "-spamd.rrd";
2217
	$proc = "-processor.rrd";
2218

    
2219
	$rrdtool = "/usr/local/bin/rrdtool";
2220
	$netstat = "/usr/bin/netstat";
2221
	$awk = "/usr/bin/awk";
2222
	$tar = "/usr/bin/tar";
2223
	$pfctl = "/sbin/pfctl";
2224
	$php = "/usr/local/bin/php";
2225
	$top = "/usr/bin/top";
2226
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2227

    
2228
	$rrdtrafficinterval = 60;
2229
	$rrdqualityinterval = 60;
2230
	$rrdqueuesinterval = 60;
2231
	$rrdqueuesdropinterval = 60;
2232
	$rrdpacketsinterval = 60;
2233
	$rrdstatesinterval = 60;
2234
	$rrdspamdinterval = 60;
2235
	$rrdlbpoolinterval = 60;
2236
	$rrdprocinterval = 60;
2237

    
2238
	$trafficvalid = $rrdtrafficinterval * 2;
2239
	$qualityvalid = $rrdqualityinterval * 2;
2240
	$queuesvalid = $rrdqueuesinterval * 2;
2241
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2242
	$packetsvalid = $rrdpacketsinterval * 2;
2243
	$statesvalid = $rrdstatesinterval*2;
2244
	$spamdvalid = $rrdspamdinterval * 2;
2245
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2246
	$procvalid = $rrdlbpoolinterval * 2;
2247

    
2248
	/* Asume GigE for now */
2249
	$downstream = 125000000;
2250
	$upstream = 125000000;
2251

    
2252
	$rrdrestore = "";
2253
	$rrdreturn = "";
2254

    
2255
	$config['rrd']['enable'] = true;
2256

    
2257
	if (isset ($config['rrd']['enable'])) {
2258

    
2259
		/* create directory if needed */
2260
		if (!is_dir("$rrddbpath")) {
2261
			mkdir("$rrddbpath", 0755);
2262
		}
2263

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

    
2276
		/* db update script */
2277
		$rrdupdatesh = "#!/bin/sh\n";
2278
		$rrdupdatesh .= "\n";
2279
		$rrdupdatesh .= "counter=1\n";
2280
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2281
		$rrdupdatesh .= "do\n";
2282
		$rrdupdatesh .= "";
2283

    
2284
		$i = 0;
2285
		$vfaces = array (
2286
			"vlan.?*",
2287
			"enc.?*"
2288
		);
2289
		$ifdescrs = get_interface_list(true, true, $vfaces);
2290
		$ifdescrs['enc0']['friendly'] = "ipsec";
2291
		$ifdescrs['enc0']['descr'] = "IPSEC";
2292
		$ifdescrs['enc0']['up'] = true;
2293

    
2294
		foreach ($ifdescrs as $realif => $ifdescr) {
2295
			$ifname = $ifdescr['friendly'];
2296
			$state = $ifdescr['up'];
2297

    
2298
			/* skip interfaces that do not have a friendly name */
2299
			if ("$ifname" == "") {
2300
				continue;
2301
			}
2302

    
2303
			/* or are down */
2304
			if (!$state) {
2305
				continue;
2306
			}
2307

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

    
2324
				$rrdcreateoutput = array();
2325
				$rrdcreatereturn = "";
2326

    
2327
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2328
				if ($rrdcreatereturn != 0) {
2329
					log_error("RRD create failed exited with $rrdcreatereturn, the
2330
							error is: $rrdcreateoutput[0]\n");
2331
				}
2332
			}
2333

    
2334
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2335
			if($g['booting']) {
2336
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
2337
			}
2338

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

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

    
2364
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2365
				if ($rrdcreatereturn != 0) {
2366
					log_error("RRD create failed exited with $rrdcreatereturn, the
2367
							error is: $rrdcreateoutput[0]\n");
2368
				}
2369
			}
2370

    
2371
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2372
			if($g['booting']) {
2373
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
2374
			}
2375

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

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

    
2408
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2409
					if ($rrdcreatereturn != 0) {
2410
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2411
					}
2412
				}
2413

    
2414
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2415
				if($g['booting']) {
2416
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
2417
				}
2418

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

    
2432
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
2433
			}
2434

    
2435
			/* WAN interface only statistics */
2436
			if ("$ifname" == "wan") {
2437

    
2438
				/* QUEUES, set up the queues databases */
2439
				if (!is_array($config['shaper']['queue'])) {
2440
					$config['shaper']['queue'] = array ();
2441
				}
2442
				$a_queues = & $config['shaper']['queue'];
2443

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

    
2456
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2457
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2458
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2459
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
2460

    
2461
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2462
						if ($rrdcreatereturn != 0) {
2463
							log_error("RRD create failed exited with $rrdcreatereturn, the
2464
									error is: $rrdcreateoutput[0]\n");
2465
						}
2466
					}
2467

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

    
2479
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2480
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2481
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2482
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
2483

    
2484
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2485
						if ($rrdcreatereturn != 0) {
2486
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2487
						}
2488
					}
2489

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

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

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

    
2545
		/* System only statistics */
2546
		$ifname = "system";
2547

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

    
2571
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2572
				if($rrdcreatereturn != 0) {
2573
			                log_error("RRD create failed exited with $rrdcreatereturn, the
2574
						error is: $rrdcreateoutput[0]\n");
2575
				}
2576
			}
2577

    
2578
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2579
			if($g['booting']) {
2580
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
2581
			}
2582

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

    
2592
			/* End pf states statistics */
2593

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

    
2617
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2618
				if($rrdcreatereturn != 0) {
2619
			                log_error("RRD create failed exited with $rrdcreatereturn, the
2620
						error is: $rrdcreateoutput[0]\n");
2621
				}
2622
			}
2623

    
2624
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2625
			if($g['booting']) {
2626
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
2627
			}
2628

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

    
2645
			/* End CPU statistics */
2646

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

    
2670
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2671
					if ($rrdcreatereturn != 0) {
2672
						log_error("RRD create failed exited with $rrdcreatereturn, the
2673
							error is: $rrdcreateoutput[0]\n");
2674
					}
2675
				}
2676

    
2677
				$rrdupdatesh .= "\n";
2678
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
2679
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
2680
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
2681

    
2682
			}
2683
		/* End System statistics */
2684

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

    
2694
		/* kill off traffic collectors */
2695
		kill_traffic_collector();
2696

    
2697
		/* start traffic collector */
2698
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
2699

    
2700
	} else {
2701
		/* kill off traffic collectors */
2702
		kill_traffic_collector();
2703
	}
2704

    
2705
	if($g['booting']) 
2706
		echo "done.\n";
2707
		
2708
}
2709

    
2710
function kill_traffic_collector() {
2711
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
2712
}
2713

    
2714
function update_filter_reload_status($text) {
2715
	global $g;
2716
	config_lock();
2717
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
2718
	fwrite($fd, $text);
2719
	fclose($fd);
2720
	config_unlock();
2721
}
2722

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

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

    
2760
/* return outside interfaces with a gateway */
2761
function get_interfaces_with_gateway() {
2762
	global $config;
2763
	$ints = array();
2764
	$ifdescrs = get_interface_list();
2765

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

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

    
2801
?>
(14-14/27)