Project

General

Profile

Download (110 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
 /****f* pfsense-utils/does_url_exist
37
 * NAME
38
 *   does_url_exist
39
 * INPUTS
40
 *	 none
41
 * RESULT
42
 *   returns true if a url is available
43
 ******/
44
function does_url_exist($url) {
45
	$fd = fopen("$url","r");
46
	if($fd) {
47
		fclose($fd);
48
   		return true;    
49
	} else {
50
        return false;
51
	}
52
}
53

    
54
/****f* pfsense-utils/is_private_ip
55
 * NAME
56
 *   is_private_ip
57
 * INPUTS
58
 *	 none
59
 * RESULT
60
 *   returns true if an ip address is in a private range
61
 ******/
62
function is_private_ip($iptocheck) {
63
        $isprivate = false;
64
        $ip_private_list=array(
65
               "10.0.0.0/8",
66
               "172.16.0.0/12",
67
               "192.168.0.0/16",
68
               "99.0.0.0/8"
69
        );
70
        foreach($ip_private_list as $private) {
71
                if(ip_in_subnet($iptocheck,$private)==true)
72
                        $isprivate = true;
73
        }
74
        return $isprivate;
75
}
76

    
77
/****f* pfsense-utils/get_tmp_file
78
 * NAME
79
 *   get_tmp_file
80
 * INPUTS
81
 *	 none
82
 * RESULT
83
 *   returns a temporary filename
84
 ******/
85
function get_tmp_file() {
86
	return "/tmp/tmp-" . time();
87
}
88

    
89
/****f* pfsense-utils/tdr_install_cron
90
 * NAME
91
 *   tdr_install_cron
92
 * INPUTS
93
 *   $should_install true if the cron entry should be installed, false
94
 *   if the entry should be removed if it is present
95
 * RESULT
96
 *   none
97
 ******/
98
function tdr_install_cron($should_install) {
99
	global $config, $g;
100
	if($g['booting']==true) 
101
		return;
102
	$is_installed = false;
103
	if(!$config['cron']['item'])
104
		return;
105
	$x=0;
106
	foreach($config['cron']['item'] as $item) {
107
		if(strstr($item['command'], "filter_configure_sync")) {
108
			$is_installed = true;
109
			break;
110
		}
111
		$x++;
112
	}
113
	switch($should_install) {
114
		case true:
115
			if(!$is_installed) {
116
				$cron_item = array();
117
				$cron_item['minute'] = "0,15,30,45";
118
				$cron_item['hour'] = "*";
119
				$cron_item['mday'] = "*";
120
				$cron_item['month'] = "*";
121
				$cron_item['wday'] = "*";
122
				$cron_item['who'] = "root";
123
				$cron_item['command'] = "/etc/rc.filter_configure_sync";		
124
				$config['cron']['item'][] = $cron_item;
125
				parse_config(true);
126
				write_config("Installed 15 minute filter reload for Time Based Rules");
127
				configure_cron();
128
			}
129
		break;
130
		case false:
131
			if($is_installed == true) {
132
				if($x > 0) {
133
					unset($config['cron']['item'][$x]);
134
					parse_config(true);
135
					write_config();
136
				}
137
				configure_cron();
138
			}
139
		break;
140
	}
141
}
142

    
143
/****f* pfsense-utils/tdr_create_ipfw_rule
144
 * NAME
145
 *   tdr_create_ipfw_rule
146
 * INPUTS
147
 *   $rule xml firewall rule array, $type allow or deny
148
 * RESULT
149
 *   text string with ipfw rule already formatted
150
 ******/
151
function tdr_create_ipfw_rule($rule, $type) {
152
		global $config, $g, $tdr_get_next_ipfw_rule;
153

    
154
		$wancfg = $config['interfaces']['wan'];
155
		$lancfg = $config['interfaces']['lan'];
156
		$pptpdcfg = $config['pptpd'];
157
		$pppoecfg = $config['pppoe'];
158

    
159
		$lanif = $lancfg['if'];
160
		$wanif = get_real_wan_interface();
161

    
162
		$lanip = $lancfg['ipaddr'];
163
		$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
164
		$lansn = $lancfg['subnet'];
165

    
166
		$int = "";
167

    
168
		$optcfg = array();
169
		generate_optcfg_array($optcfg);
170

    
171
		$curwanip = get_current_wan_address();
172

    
173
		/* don't include disabled rules */
174
		if (isset($rule['disabled'])) {
175
			return "";
176
		}
177

    
178
		$pptpdcfg = $config['pptpd'];
179
		$pppoecfg = $config['pppoe'];
180

    
181
		if ($pptpdcfg['mode'] == "server") {
182
			$pptpip = $pptpdcfg['localip'];
183
			$pptpsa = $pptpdcfg['remoteip'];
184
			$pptpsn = $g['pptp_subnet'];
185
			if($config['pptp']['pptp_subnet'] <> "")
186
				$pptpsn = $config['pptp']['pptp_subnet'];
187
		}
188

    
189
		if ($pppoecfg['mode'] == "server") {
190
			$pppoeip = $pppoecfg['localip'];
191
			$pppoesa = $pppoecfg['remoteip'];
192
			$pppoesn = $g['pppoe_subnet'];
193
			if($config['pppoe']['pppoe_subnet'] <> "")
194
				$pppoesn = $config['pppoe']['pppoe_subnet'];
195
		}
196

    
197
		/* does the rule deal with a PPTP interface? */
198
		if ($rule['interface'] == "pptp") {
199
			if ($pptpdcfg['mode'] != "server")
200
				return "";
201
			$nif = $g['n_pptp_units'];
202
			if($config['pptp']['n_pptp_units'] <> "")
203
				$nif = $config['pptp']['n_pptp_units'];
204
			$ispptp = true;
205
		} else if($rule['interface'] == "pppoe") {
206
			if ($pppoecfg['mode'] != "server") {
207
				return " # Error creating pppoe rule";
208
			}
209
			$nif = $g['n_pppoe_units'];
210
			if($config['pppoe']['n_pppoe_units'] <> "")
211
				$nif = $config['pppoe']['n_pppoe_units'];
212
			$ispppoe = true;
213
		} else {
214

    
215
			/* Check to see if the interface is opt and in our opt list */
216
			if (strstr($rule['interface'], "opt")) {
217
 				if (!array_key_exists($rule['interface'], $optcfg)) {
218
					$item = "";
219
					foreach($optcfg as $oc) $item .= $oc['if'];
220
					return "# {$real_int} {$item} {$rule['interface']} array key does not exist for " . $rule['descr'];
221
				}
222
			}
223

    
224
			$nif = 1;
225
			$ispptp = false;
226
			$ispppoe = false;
227
		}
228
		if ($pptpdcfg['mode'] != "server") {
229
			if (($rule['source']['network'] == "pptp") ||
230
				($rule['destination']['network'] == "pptp")) {
231
					return "# source network or destination network == pptp on " . $rule['descr'];
232
				}
233
		}
234
		if ($rule['source']['network'] && strstr($rule['source']['network'], "opt")) {
235
			if (!array_key_exists($rule['source']['network'], $optcfg)) {
236
				$optmatch = "";
237
				if(preg_match("/opt([0-999])/", $rule['source']['network'], $optmatch)) {
238
					$real_opt_int = convert_friendly_interface_to_real_interface_name("opt" . $optmatch[1]);
239
					$opt_ip = find_interface_ip($real_opt_int);
240
					if(!$opt_ip)
241
						return "# unresolvable optarray $real_opt_int - $optmatch[0] - $opt_ip";
242
				} else {
243
					return "# {$rule['source']['network']} !array_key_exists source network " . $rule['descr'];
244
				}
245
			}
246
		}
247
		if ($rule['destination']['network'] && strstr($rule['destination']['network'], "opt")) {
248
			if (!array_key_exists($rule['destination']['network'], $optcfg)) {
249
				if(preg_match("/opt([0-999])/", $rule['destination']['network'], $optmatch)) {
250
					$real_opt_int = convert_friendly_interface_to_real_interface_name("opt" . $optmatch[1]);
251
					$opt_ip = find_interface_ip($real_opt_int);
252
					if(!$opt_ip)
253
						return "# unresolvable oparray $real_opt_int - $optmatch[0] - $opt_ip";
254
				} else {
255
					return "# {$item} {$rule['destination']['network']} !array_key_exists dest network " . $rule['descr'];
256
				}
257
			}
258
		}
259
		/* check for unresolvable aliases */
260
		if ($rule['source']['address'] && !alias_expand($rule['source']['address'])) {
261
			file_notice("Filter_Reload", "# unresolvable source aliases {$rule['descr']}");
262
			return "# tdr unresolvable source aliases {$rule['descr']}";
263
		}
264
		if ($rule['destination']['address'] && !alias_expand($rule['destination']['address'])) {
265
			file_notice("Filter_Reload", "# unresolvable dest aliases {$rule['descr']}");
266
			return "# tdr unresolvable dest aliases {$rule['descr']}";
267
		}
268

    
269
		$ifdescrs = array();
270
		for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
271
			$ifdescrs[] = "opt" . $i;
272

    
273
		for ($iif = 0; $iif < $nif; $iif++) {
274

    
275
			if ($ispptp) {
276
				$aline['interface'] = "\$pptp ";
277
			} else if ($ispppoe) {
278
				$aline['interface'] = "\$pppoe ";
279
			} else {
280
				// translate wan, man, lan, opt to real interface.
281
				$interface = $rule['interface'];
282
				$temp = filter_get_opt_interface_descr($interface);
283
				if($temp <> "") $interface = $temp;
284
				$aline['interface'] = convert_friendly_interface_to_real_interface_name($rule['interface']) . " ";
285
			}
286

    
287
			if (isset($rule['protocol'])) {
288
				if($rule['protocol'] == "tcp/udp")
289
					$aline['prot'] = "ip ";
290
				elseif($rule['protocol'] == "icmp")
291
					$aline['prot'] = "icmp ";
292
				else
293
					$aline['prot'] = "{$rule['protocol']} ";
294
			} else {
295
				if($rule['source']['port'] <> "" || $rule['destination']['port'] <> "") {
296
					$aline['prot'] = "tcp ";
297
				}
298
			}
299

    
300
			/* source address */
301
			if (isset($rule['source']['any'])) {
302
				$src = "any";
303
			} else if ($rule['source']['network']) {
304

    
305
				if (strstr($rule['source']['network'], "opt")) {
306
					$src = $optcfg[$rule['source']['network']]['sa'] . "/" .
307
						$optcfg[$rule['source']['network']]['sn'];
308
					if (isset($rule['source']['not'])) $src = " not {$src}";
309
					/* check for opt$NUMip here */
310
					$matches = "";
311
					if (preg_match("/opt([0-9999])ip/", $rule['source']['network'], $matches)) {
312
						$optnum = $matches[1];
313
						$real_int = convert_friendly_interface_to_real_interface_name("opt{$optnum}");
314
						$src = find_interface_ip($real_int);
315
					}
316
				} else {
317
					switch ($rule['source']['network']) {
318
						case 'wanip':
319
							$src = $curwanip;
320
							break;
321
						case 'lanip':
322
							$src = $lanip;
323
							break;
324
						case 'lan':
325
							$src = "{$lansa}/{$lansn}";
326
							break;
327
						case 'pptp':
328
							$src = "{$pptpsa}/{$pptpsn}";
329
							break;
330
						case 'pppoe':
331
							$src = "{$pppoesa}/{$pppoesn}";
332
							break;
333
					}
334
					if (isset($rule['source']['not'])) $src = " not {$src}";
335
				}
336
			} else if ($rule['source']['address']) {
337
				$expsrc = alias_expand_value($rule['source']['address']);
338
				if(!$expsrc) 
339
					$expsrc = $rule['source']['address'];
340
					
341
				if (isset($rule['source']['not']))
342
					$not = " not";
343
				else
344
					$not = "";
345

    
346
				if(alias_expand_value($rule['source']['address'])) {
347
					$src = "{";
348
					$first_item = true;
349
					foreach(preg_split("/[\s]+/", alias_expand_value($rule['source']['address'])) as $item) {
350
						if($item != "") {
351
							if(!$first_item) 
352
								$src .= " or";
353
							$src .= " {$not}{$item}";
354
							$first_item = false;
355
						}
356
					}
357
					$src .= " }";
358
				} else {
359
					$src = "{$not}" . $expsrc;
360
				}
361

    
362
			}
363

    
364
			if (!$src || ($src == "/")) {
365
				return "# tdr at the break!";
366
			}
367

    
368
			$aline['src'] = "from $src ";
369
			$srcporta = "";
370
			if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
371
				if ($rule['source']['port']) {
372
					$srcport = explode("-", $rule['source']['port']);
373
					if(alias_expand($srcport[0])) {
374
						$first_time = true;
375
						foreach(preg_split("/[\s]+/", alias_expand_value($srcport[0])) as $item) {
376
							if(!$first_time) 
377
								$srcporta .= ",";				
378
							$srcporta .= $item;
379
							$first_time = false;
380
						}
381
					} else {
382
						$srcporta = $srcport[0];
383
					}
384
					if ((!$srcport[1]) || ($srcport[0] == $srcport[1])) {
385
						if(alias_expand($srcport[0]))
386
							$aline['srcport'] = "{$srcporta} ";
387
						else
388
							$aline['srcport'] = "{$srcporta} ";
389
					} else if (($srcport[0] == 1) && ($srcport[1] == 65535)) {
390
						/* no need for a port statement here */
391
					} else if ($srcport[1] == 65535) {
392
						$aline['srcport'] = ">={$srcport[0]} ";
393
					} else if ($srcport[0] == 1) {
394
						$aline['srcport']= "<={$srcport[1]} ";
395
					} else {
396
						$aline['srcport'] = "{$srcport[0]}-{$srcport[1]} ";
397
					}
398
				}
399
			}
400

    
401
			/* destination address */
402
			if (isset($rule['destination']['any'])) {
403
				$dst = "any";
404
			} else if ($rule['destination']['network']) {
405

    
406
				if (strstr($rule['destination']['network'], "opt")) {
407
					$dst = $optcfg[$rule['destination']['network']]['sa'] . "/" .
408
						$optcfg[$rule['destination']['network']]['sn'];
409
					/* check for opt$NUMip here */
410
					$matches = "";
411
					if (preg_match("/opt([0-9999])ip/", $rule['destination']['network'], $matches)) {
412
						$optnum = $matches[1];
413
						$real_int = convert_friendly_interface_to_real_interface_name("opt{$optnum}");
414
						$dst = find_interface_ip($real_int);
415
					}
416
					if (isset($rule['destination']['not'])) $dst = " not {$dst}";
417
				} else {
418
					switch ($rule['destination']['network']) {
419
						case 'wanip':
420
							$dst = $curwanip;
421
							break;
422
						case 'lanip':
423
							$dst = $lanip;
424
							break;
425
						case 'lan':
426
							$dst = "{$lansa}/{$lansn}";
427
							break;
428
						case 'pptp':
429
							$dst = "{$pptpsa}/{$pptpsn}";
430
							break;
431
						case 'pppoe':
432
							$dst = "{$ppoesa}/{$pppoesn}";
433
							break;
434
					}
435
					if (isset($rule['destination']['not'])) $dst = " not {$dst}";
436
				}
437
			} else if ($rule['destination']['address']) {
438
				$expdst = alias_expand_value($rule['destination']['address']);
439
				if(!$expdst) 
440
					$expdst = $rule['destination']['address'];
441

    
442
				if (isset($rule['destination']['not']))
443
					$not = " not ";
444
				else
445
					$not = "";
446

    
447
				if(alias_expand_value($rule['destination']['address'])) {
448
					$dst = "{";
449
					$first_item = true;
450
					foreach(preg_split("/[\s]+/", alias_expand_value($rule['destination']['address'])) as $item) {
451
						if($item != "") {
452
							if(!$first_item) 
453
								$dst .= " or";
454
							$dst .= " {$not}{$item}";
455
							$first_item = false;
456
						}
457
					}
458
					$dst .= " }";
459
				} else {
460
					$dst = "{$not}" . $expdst;
461
				}
462
			}
463

    
464
			if (!$dst || ($dst == "/")) {
465
				return "# returning at dst $dst == \"/\"";
466
			}
467

    
468
			$aline['dst'] = "to $dst ";
469
			$dstporta = "";
470
			if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
471
				if ($rule['destination']['port']) {
472
					$dstport = explode("-", $rule['destination']['port']);
473
					if(alias_expand($dstport[0])) {
474
						$first_time = true;
475
						foreach(preg_split("/[\s]+/", alias_expand_value($dstport[0])) as $item) {
476
							if(!$first_time)
477
							 	$dstporta .= ",";
478
							$dstporta .= $item;			
479
							$first_time = false;
480
						}
481
					} else {
482
						$dstporta = $dstport[0];
483
					}
484
					if ((!$dstport[1]) || ($dstport[0] == $dstport[1])) {
485
						if(alias_expand($dstport[0]))
486
							$aline['dstport'] = "{$dstporta} ";
487
						else
488
							$aline['dstport'] = "{$dstporta} ";
489
					} else if (($dstport[0] == 1) && ($dstport[1] == 65535)) {
490
						/* no need for a port statement here */
491
					} else if ($dstport[1] == 65535) {
492
						$aline['dstport'] = ">= {$dstport[0]} ";
493
					} else if ($dstport[0] == 1) {
494
						$aline['dstport'] = "<= {$dstport[1]} ";
495
					}  else {
496
						$aline['dstport'] = "{$dstport[0]}-{$dstport[1]} ";
497
					}
498
				}
499
			}
500

    
501
	}
502
	
503
	if($aline['prot'] == "")
504
		$aline['prot'] = "ip ";
505

    
506
	tdr_get_next_ipfw_rule();
507

    
508
 	/* piece together the actual user rule */
509
	if($type == "skipto") {
510
		$next_rule = tdr_get_next_ipfw_rule();
511
		$next_rule = $next_rule+1;
512
		$type = "skipto $next_rule";
513
	}
514

    
515
	/* piece together the actual user rule */
516
	$line .= $type . " " . $aline['prot'] . $aline['src'] . 
517
	$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in recv " . $aline['interface'];
518

    
519
	return $line;
520

    
521
}
522

    
523
/****f* pfsense-utils/tdr_install_rule
524
 * NAME
525
 *   tdr_install_rule
526
 * INPUTS
527
 *   $rule - ascii string containing the ifpw rule to add
528
 * RESULT
529
 *   none
530
 ******/
531
function tdr_install_rule($rule) {
532
	global $tdr_next_ipfw_rule;
533
	mwexec("/sbin/ipfw -f add $tdr_next_ipfw_rule set 9 $rule");
534
	$tdr_next_ipfw_rule++;
535
}
536

    
537
/****f* pfsense-utils/tdr_get_next_ipfw_rule
538
 * NAME
539
 *   tdr_get_next_ipfw_rule
540
 * INPUTS
541
 *  none
542
 * RESULT
543
 *   returns the next available ipfw rule number
544
 ******/
545
function tdr_get_next_ipfw_rule() {
546
	global $tdr_next_ipfw_rule;
547
	if(intval($tdr_next_ipfw_rule) < 2) 
548
		$tdr_next_ipfw_rule = 2;
549
	return $tdr_next_ipfw_rule;
550
 }
551

    
552
/****f* pfsense-utils/tdr_install_set
553
 * NAME
554
 *   tdr_install_set
555
 * INPUTS
556
 *  none
557
 * RESULT
558
 *   swaps in the temporary ipfw time based rule set
559
 ******/
560
function tdr_install_set() {
561
	global $config;
562
	
563
	mwexec("/sbin/ipfw delete 1");
564
	mwexec("/sbin/ipfw add 1 check-state");
565
	mwexec("/sbin/ipfw delete 65534");
566
	mwexec("/sbin/ipfw add 1 allow all from me to any keep-state");
567
	if (!isset ($config['system']['webgui']['noantilockout'])) {
568
		/* lan ip lockout */
569
		$lancfg = $config['interfaces']['lan'];
570
		$lanip = $lancfg['ipaddr'];
571
		$lansn = $lancfg['subnet'];
572
		$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
573
		mwexec("/sbin/ipfw add 1 allow all from {$lansa}/{$lansn} to $lanip keep-state");
574
	}
575
	mwexec("/sbin/ipfw add 65534 check-state");
576
	/* set 8 contains time based rules */
577
	mwexec("/sbin/ipfw -f delete set 8");
578
	mwexec("/sbin/ipfw -f set swap 9 8");
579
}
580

    
581
/****f* pfsense-utils/get_time_based_rule_status
582
 * NAME
583
 *   get_time_based_rule_status
584
 * INPUTS
585
 *   xml schedule block
586
 * RESULT
587
 *   true/false - true if the rule should be installed
588
 ******/
589
/*
590
 <schedules>
591
   <schedule>
592
     <name>ScheduleMultipleTime</name>
593
     <descr>main descr</descr>
594
     <time>
595
       <position>0,1,2</position>
596
       <hour>0:0-24:0</hour>
597
       <desc>time range 2</desc>
598
     </time>
599
     <time>
600
       <position>4,5,6</position>
601
       <hour>0:0-24:0</hour>
602
       <desc>time range 1</desc>
603
     </time>
604
   </schedule>
605
 </schedules>
606
*/
607
function get_time_based_rule_status($schedule) {
608
	$should_add_rule = false;
609
	global $debug;
610
	/* no schedule? rule should be installed */
611
	if($schedule == "") 
612
		return true;
613
	/*
614
	 * iterate through time blocks and deterimine
615
	 * if the rule should be installed or not.
616
	 */
617
	foreach($schedule['timerange'] as $timeday) {
618
		if($timeday['month']) 
619
			$month = $timeday['month'];
620
		else 
621
			$week = "";	
622
		if($timeday['day']) 
623
			$day = $timeday['day'];
624
		else 
625
			$day = "";
626
		if($timeday['hour']) 
627
			$hour = $timeday['hour'];
628
		else 
629
			$hour = "";
630
		if($timeday['position']) 
631
			$position = $timeday['position'];
632
		else 
633
			$position = "";
634
		if($timeday['desc']) 
635
			$desc = $timeday['desc'];
636
		else 
637
			$desc = "";
638
		if($month) {
639
			$monthstatus = tdr_month($month);
640
		} else {
641
			$monthstatus = true;
642
		}
643
		if($day) {
644
			$daystatus = tdr_day($day);
645
		} else {
646
			$daystatus = true;
647
		}
648
		if($hour) {
649
			$hourstatus = tdr_hour($hour);
650
		} else {
651
			$hourstatus = true;
652
		}
653
		if($position) {
654
			$positionstatus = tdr_position($position);
655
		} else {
656
			$positionstatus = true;
657
		}
658

    
659
		if($monthstatus == true) 
660
			if($daystatus == true) 
661
				if($positionstatus == true) 
662
					if($hourstatus == true) {
663
						$should_add_rule = true;
664
					}
665
	}
666
	
667
	return $should_add_rule;
668
}
669

    
670
function tdr_day($schedule) {
671
	/*
672
	 * Calculate day of month. 
673
	 * IE: 29th of may
674
	 */
675
	global $debug;
676
	$weekday	= date("w");
677
	if ($weekday == 0)
678
		$weekday = 7;
679
	$date	 	= date("d");
680
	$defined_days = split(",", $schedule);
681
	if($g['debug'])
682
		log_error("[TDR DEBUG] tdr_day($schedule)");
683
	foreach($defined_days as $dd) {
684
		if($date == $dd) {
685
			return true;
686
		}
687
	}
688
	return false;
689
}
690

    
691
function tdr_hour($schedule) {
692
	/* $schedule should be a string such as 16:00-19:00 */
693
	global $debug;
694
	$tmp = split("-", $schedule);
695
	$starting_time = strtotime($tmp[0]);
696
	$ending_time = strtotime($tmp[1]);
697
	$now = strtotime("now");
698
	if($g['debug'])
699
		log_error("[TDR DEBUG] S: $starting_time E: $ending_time N: $now");
700
	if($now >= $starting_time and $now <= $ending_time) {
701
		return true;
702
	}
703
	return false;
704
}
705

    
706
function tdr_position($schedule) {
707
	/*
708
	 * Calculate possition, ie: day of week.
709
	 * Sunday = 7, Monday = 1, Tuesday = 2
710
	 * Weds = 3, Thursday = 4, Friday = 5,
711
	 * Saturday = 6
712
	 * ...
713
	 */
714
	global $debug;
715
	$weekday	= date("w");
716
	if($g['debug'])
717
		log_error("[TDR DEBUG] tdr_position($schedule) $weekday");
718
	if ($weekday == 0)
719
		$weekday = 7;
720
	$schedule_days = split(",", $schedule);
721
	foreach($schedule_days as $day) {
722
		if($day == $weekday) {
723
			return true;
724
		}
725
	}
726
	return false;
727
}
728

    
729
function tdr_month($schedule) {
730
	/*
731
	 * Calculate month
732
	 */
733
	global $debug;
734
	$todays_month = date("n");
735
	$months = split(",", $schedule);
736
	if($g['debug'])
737
		log_error("[TDR DEBUG] tdr_month($schedule)");
738
	foreach($months as $month) {
739
		if($month == $todays_month) {
740
			return true;
741
		}
742
	}
743
	return false;
744
}
745

    
746
/****f* pfsense-utils/find_number_of_needed_carp_interfaces
747
 * NAME
748
 *   find_number_of_needed_carp_interfaces
749
 * INPUTS
750
 *   null
751
 * RESULT
752
 *   the number of needed carp interfacs
753
 ******/
754
function find_number_of_needed_carp_interfaces() {
755
	global $config, $g;
756
	$carp_counter=0;
757
	if(!$config['virtualip'])
758
		return 0;
759
	if(!$config['virtualip']['vip'])
760
		return 0;
761
	foreach($config['virtualip']['vip'] as $vip) {
762
		if($vip['mode'] == "carp")
763
			$carp_counter++;
764
	}
765
	return $carp_counter;
766
}
767

    
768
/****f* pfsense-utils/reset_carp
769
 * NAME
770
 *   reset_carp - resets carp after primary interface changes
771
 * INPUTS
772
 *   null
773
 * RESULT
774
 *   null
775
 ******/
776
function reset_carp() {
777
	$carp_counter=find_number_of_created_carp_interfaces();
778
	$needed_carp_interfaces = find_number_of_needed_carp_interfaces();
779
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
780
	for($x=0; $x<$carp_counter; $x++) {
781
		mwexec("/sbin/ifconfig carp{$x} down");
782
		usleep(1000);
783
		mwexec("/sbin/ifconfig carp{$x} delete");
784
		if($needed_carp_interfaces < $carp_counter) {
785
			$needed_carp_interfaces--;
786
			//log_error("Destroying carp interface.");
787
			//mwexec("/sbin/ifconfig carp{$x} destroy");
788
		}
789
	}
790
	find_number_of_created_carp_interfaces(true);
791
	sleep(1);
792
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
793
	interfaces_carp_configure();
794
	usleep(1000);
795
	interfaces_carp_bring_up_final();
796
}
797

    
798
/****f* pfsense-utils/get_dns_servers
799
 * NAME
800
 *   get_dns_servres - get system dns servers
801
 * INPUTS
802
 *   $dns_servers - an array of the dns servers
803
 * RESULT
804
 *   null
805
 ******/
806
function get_dns_servers() {
807
	$dns_servers = array();
808
	$dns = `cat /etc/resolv.conf`;
809
	$dns_s = split("\n", $dns);
810
	foreach($dns_s as $dns) {
811
		$matches = "";
812
		if (preg_match("/nameserver (.*)/", $dns, $matches))
813
			$dns_servers[] = $matches[1];
814
	}
815
	$dns_server_master = array();
816
	$lastseen = "";
817
	foreach($dns_servers as $t) {
818
		if($t <> $lastseen)
819
			if($t <> "")
820
				$dns_server_master[] = $t;
821
		$lastseen = $t;
822
	}
823
	return $dns_server_master;
824
}
825

    
826
/****f* pfsense-utils/log_error
827
* NAME
828
*   log_error  - Sends a string to syslog.
829
* INPUTS
830
*   $error     - string containing the syslog message.
831
* RESULT
832
*   null
833
******/
834
function log_error($error) {
835
	$page = $_SERVER['SCRIPT_NAME'];
836
	syslog(LOG_WARNING, "$page: $error");
837
	return;
838
}
839

    
840
/****f* pfsense-utils/get_interface_mac_address
841
 * NAME
842
 *   get_interface_mac_address - Return a interfaces mac address
843
 * INPUTS
844
 *   $interface	- interface to obtain mac address from
845
 * RESULT
846
 *   $mac - the mac address of the interface
847
 ******/
848
function get_interface_mac_address($interface) {
849
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
850
	if(is_macaddr($mac)) {
851
		return trim($mac);
852
	} else {
853
		return "";
854
	}
855
}
856

    
857
/****f* pfsense-utils/return_dir_as_array
858
 * NAME
859
 *   return_dir_as_array - Return a directory's contents as an array.
860
 * INPUTS
861
 *   $dir	- string containing the path to the desired directory.
862
 * RESULT
863
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
864
 ******/
865
function return_dir_as_array($dir) {
866
	$dir_array = array();
867
	if (is_dir($dir)) {
868
		if ($dh = opendir($dir)) {
869
			while (($file = readdir($dh)) !== false) {
870
				$canadd = 0;
871
				if($file == ".") $canadd = 1;
872
				if($file == "..") $canadd = 1;
873
				if($canadd == 0)
874
					array_push($dir_array, $file);
875
			}
876
			closedir($dh);
877
		}
878
	}
879
	return $dir_array;
880
}
881

    
882
/****f* pfsense-utils/enable_hardware_offloading
883
 * NAME
884
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
885
 * INPUTS
886
 *   $interface	- string containing the physical interface to work on.
887
 * RESULT
888
 *   null
889
 * NOTES
890
 *   This function only supports the fxp driver's loadable microcode.
891
 ******/
892
function enable_hardware_offloading($interface) {
893
	global $g, $config;
894

    
895
	if(stristr($interface,"lnc"))
896
		return;
897

    
898
	if(isset($config['system']['do_not_use_nic_microcode']))
899
		return;
900

    
901
	/* translate wan, lan, opt -> real interface if needed */
902
	$int = filter_translate_type_to_real_interface($interface);
903
	if($int <> "") $interface = $int;
904
	$int_family = preg_split("/[0-9]+/", $int);
905
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
906
	$supported_ints = array('fxp');
907
	if (in_array($int_family, $supported_ints))
908
		mwexec("/sbin/ifconfig {$interface} link0");
909

    
910
	if($config['system']['disablechecksumoffloading'])
911
		return;
912

    
913
	/* skip vlans for checksumming and polling */
914
	if(stristr($interface, "vlan")) 
915
		return;
916

    
917
	if(stristr($options, "txcsum") == true)
918
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
919

    
920
	if(stristr($options, "rxcsum") == true)
921
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
922

    
923
	/* if the NIC supports polling *AND* it is enabled in the GUI */
924
	if(interface_supports_polling($interface)) {
925
		$polling = isset($config['system']['polling']);	
926
		if($polling) {
927
			mwexec("sysctl kern.polling.enable=1");
928
	    	mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
929
		} else {
930
			mwexec("sysctl kern.polling.enable=0");
931
		}
932
	}
933
	return;
934
}
935

    
936
/****f* pfsense-utils/interface_supports_polling
937
 * NAME
938
 *   checks to see if an interface supports polling according to man polling
939
 * INPUTS
940
 *
941
 * RESULT
942
 *   true or false
943
 * NOTES
944
 *
945
 ******/
946
function interface_supports_polling($iface) {
947
	$pattern = '/([a-z].*)[0-9]/';
948
	preg_match($pattern, $iface, $iface2);
949
	$interface=$iface2[1];
950
	$supported_ints = array("bge",
951
		"dc",
952
		"em",
953
		"fwe",
954
		"fwip",
955
		"fxp",
956
		"ixgb",
957
		"nfe",
958
		"vge",
959
		"re",
960
		"rl",
961
		"sf",
962
		"sis",
963
		"ste",
964
		"stge",    
965
		"vge",
966
		"vr",
967
		"xl");
968
	if(in_array($interface, $supported_ints))
969
		return true;
970
	return false;
971
}
972

    
973
/****f* pfsense-utils/is_alias_inuse
974
 * NAME
975
 *   checks to see if an alias is currently in use by a rule
976
 * INPUTS
977
 *
978
 * RESULT
979
 *   true or false
980
 * NOTES
981
 *
982
 ******/
983
function is_alias_inuse($alias) {
984
	global $g, $config;
985

    
986
	if($alias == "") return false;
987
	/* loop through firewall rules looking for alias in use */
988
	if(is_array($config['filter']['rule']))
989
		foreach($config['filter']['rule'] as $rule) {
990
			if($rule['source']['address'])
991
				if($rule['source']['address'] == $alias)
992
					return true;
993
			if($rule['destination']['address'])
994
				if($rule['destination']['address'] == $alias)
995
					return true;
996
		}
997
	/* loop through nat rules looking for alias in use */
998
	if(is_array($config['nat']['rule']))
999
		foreach($config['nat']['rule'] as $rule) {
1000
			if($rule['target'] == $alias)
1001
				return true;
1002
			if($rule['external-address'] == $alias)
1003
				return true;
1004
		}
1005
	return false;
1006
}
1007

    
1008
/****f* pfsense-utils/is_schedule_inuse
1009
 * NAME
1010
 *   checks to see if a schedule is currently in use by a rule
1011
 * INPUTS
1012
 *
1013
 * RESULT
1014
 *   true or false
1015
 * NOTES
1016
 *
1017
 ******/
1018
function is_schedule_inuse($schedule) {
1019
	global $g, $config;
1020

    
1021
	if($schedule == "") return false;
1022
	/* loop through firewall rules looking for schedule in use */
1023
	if(is_array($config['filter']['rule']))
1024
		foreach($config['filter']['rule'] as $rule) {
1025
			if($rule['sched'] == $schedule)
1026
				return true;
1027
		}
1028
	return false;
1029
}
1030

    
1031
/****f* pfsense-utils/setup_polling_defaults
1032
 * NAME
1033
 *   sets up sysctls for pollingS
1034
 * INPUTS
1035
 *
1036
 * RESULT
1037
 *   null
1038
 * NOTES
1039
 *
1040
 ******/
1041
function setup_polling_defaults() {
1042
	global $g, $config;
1043
	if($config['system']['polling_each_burst'])
1044
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
1045
	if($config['system']['polling_burst_max'])
1046
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
1047
	if($config['system']['polling_user_frac'])
1048
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
1049
}
1050

    
1051
/****f* pfsense-utils/setup_polling
1052
 * NAME
1053
 *   sets up polling
1054
 * INPUTS
1055
 *
1056
 * RESULT
1057
 *   null
1058
 * NOTES
1059
 *
1060
 ******/
1061
function setup_polling() {
1062
	global $g, $config;
1063

    
1064
	setup_polling_defaults();
1065

    
1066
	if(isset($config['system']['polling']))
1067
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
1068
	else
1069
		$supported_ints = array();
1070

    
1071
	/* build an array of interfaces to work with */
1072
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1073
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1074
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1075

    
1076
	foreach ($iflist as $ifent => $ifname) {
1077
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
1078
		if(!in_array($real_interface, $supported_ints)) {
1079
			continue;
1080
 		}
1081
		if(isset($config['system']['polling'])) {
1082
			mwexec("/sbin/ifconfig {$real_interface} polling");
1083
		} else {
1084
			mwexec("/sbin/ifconfig {$real_interface} -polling");
1085
		}
1086
	}
1087
}
1088

    
1089
/****f* pfsense-utils/setup_microcode
1090
 * NAME
1091
 *   enumerates all interfaces and calls enable_hardware_offloading which
1092
 *   enables a NIC's supported hardware features.
1093
 * INPUTS
1094
 *
1095
 * RESULT
1096
 *   null
1097
 * NOTES
1098
 *   This function only supports the fxp driver's loadable microcode.
1099
 ******/
1100
function setup_microcode() {
1101
	global $config;
1102

    
1103
	$ifdescrs = array('wan', 'lan');
1104
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1105
		$ifdescrs['opt' . $j] = "opt" . $j;
1106
	}
1107
	foreach($ifdescrs as $if)
1108
		enable_hardware_offloading($if);
1109
}
1110

    
1111
/****f* pfsense-utils/return_filename_as_array
1112
 * NAME
1113
 *   return_filename_as_array - Return a file's contents as an array.
1114
 * INPUTS
1115
 *   $filename	- string containing the path to the desired file.
1116
 *   $strip	- array of characters to strip - default is '#'.
1117
 * RESULT
1118
 *   $file	- array containing the file's contents.
1119
 * NOTES
1120
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
1121
 ******/
1122
function return_filename_as_array($filename, $strip = array('#')) {
1123
	if(file_exists($filename)) $file = file($filename);
1124
	if(is_array($file)) {
1125
		foreach($file as $line) $line = trim($line);
1126
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
1127
	}
1128
	return $file;
1129
}
1130

    
1131
/****f* pfsense-utils/file_put_contents
1132
 * NAME
1133
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
1134
 * RESULT
1135
 *   none
1136
 ******/
1137
if(!function_exists("file_put_contents")) {
1138
	function file_put_contents($filename, $data) {
1139
		$fd = fopen($filename,"w");
1140
		fwrite($fd, $data);
1141
		fclose($fd);
1142
	}
1143
}
1144

    
1145
/****f* pfsense-utils/get_carp_status
1146
 * NAME
1147
 *   get_carp_status - Return whether CARP is enabled or disabled.
1148
 * RESULT
1149
 *   boolean	- true if CARP is enabled, false if otherwise.
1150
 ******/
1151
function get_carp_status() {
1152
    /* grab the current status of carp */
1153
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
1154
    if(intval($status) == "0") return false;
1155
    return true;
1156
}
1157

    
1158
/****f* pfsense-utils/is_carp_defined
1159
 * NAME
1160
 *   is_carp_defined - Return whether CARP is detected in the kernel.
1161
 * RESULT
1162
 *   boolean	- true if CARP is detected, false otherwise.
1163
 ******/
1164
function is_carp_defined() {
1165
	/* is carp compiled into the kernel and userland? */
1166
	$command = "/sbin/sysctl -a | grep carp";
1167
	$fd = popen($command . " 2>&1 ", "r");
1168
	if(!$fd) {
1169
		log_error("Warning, could not execute command {$command}");
1170
		return 0;
1171
	}
1172
	while(!feof($fd)) {
1173
		$tmp .= fread($fd,49);
1174
	}
1175
	fclose($fd);
1176

    
1177
	if($tmp == "")
1178
		return false;
1179
	else
1180
		return true;
1181
}
1182

    
1183
/****f* pfsense-utils/get_interface_mtu
1184
 * NAME
1185
 *   get_interface_mtu - Return the mtu of an interface
1186
 * RESULT
1187
 *   $tmp	- Returns the mtu of an interface
1188
 ******/
1189
function get_interface_mtu($interface) {
1190
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f6`;
1191
	return $mtu;
1192
}
1193

    
1194
/****f* pfsense-utils/is_interface_wireless
1195
 * NAME
1196
 *   is_interface_wireless - Returns if an interface is wireless
1197
 * RESULT
1198
 *   $tmp	- Returns if an interface is wireless
1199
 ******/
1200
function is_interface_wireless($interface) {
1201
	global $config, $g;
1202
	$interface = convert_real_interface_to_friendly_interface_name($interface);
1203
	if(isset($config['interfaces'][$interface]['wireless']))
1204
		return true;
1205
	else
1206
		return false;
1207
}
1208

    
1209
/****f* pfsense-utils/find_number_of_created_carp_interfaces
1210
 * NAME
1211
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
1212
 * RESULT
1213
 *   $tmp	- Number of currently created CARP interfaces.
1214
 ******/
1215
function find_number_of_created_carp_interfaces($flush = false) {
1216
	global $carp_interface_count_cache;
1217

    
1218
	if (!isset($carp_interface_count_cache) or $flush) {
1219
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
1220
		$fd = popen($command . " 2>&1 ", "r");
1221
		if(!$fd) {
1222
			log_error("Warning, could not execute command {$command}");
1223
			return 0;
1224
		}
1225
		while(!feof($fd)) {
1226
			$tmp .= fread($fd,49);
1227
		}
1228
		fclose($fd);
1229
		$carp_interface_count_cache = intval($tmp);
1230
	}
1231
	return $carp_interface_count_cache;
1232
}
1233

    
1234
/****f* pfsense-utils/link_int_to_bridge_interface
1235
 * NAME
1236
 *   link_int_to_bridge_interface - Finds out a bridge group for an interface
1237
 * INPUTS
1238
 *   $ip
1239
 * RESULT
1240
 *   bridge[0-99]
1241
 ******/
1242
function link_int_to_bridge_interface($int) {
1243
	global $config, $g;
1244
	$real_int = convert_friendly_interface_to_real_interface_name($int);
1245
	$num_bridges = find_number_of_created_bridges();
1246
	for($x=0; $x<$num_bridges; $x++) {
1247
		$matches = "";
1248
		$bridge_info = `/sbin/ifconfig bridge{$x}`;
1249
		if(stristr($bridge_info, "member: {$real_int}")) {
1250
			return "bridge{$x}";
1251
		}
1252
	}
1253
}
1254

    
1255
function link_carp_interface_to_parent($interface) {
1256
	global $config;
1257
	if($interface == "") return;
1258

    
1259
	$ifdescrs = array("wan" => "wan", "lan" => "lan");
1260
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1261
		$ifdescrs['opt' . $j] = "opt" . $j;
1262

    
1263
	$carp_int = $interface;
1264
	$carp_ip = find_interface_ip($interface);
1265
	$carp_subnet = find_virtual_ip_netmask($carp_ip);
1266
	$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1267
	$carp_ints = "";
1268
	$num_carp_ints = find_number_of_created_carp_interfaces();
1269

    
1270
	foreach ($ifdescrs as $ifdescr => $ifname) {
1271
		if(interface_has_gateway($ifname)) {
1272
			$interfaceip = $config['interfaces'][$ifname]['ipaddr'];
1273
			$subnet_bits = $config['interfaces'][$ifname]['subnet'];
1274
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
1275
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}")) {
1276
				return $ifname;
1277
			}
1278
		}
1279
	}
1280
	return $carp_ints;
1281
}
1282

    
1283
/****f* pfsense-utils/link_ip_to_carp_interface
1284
 * NAME
1285
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
1286
 * INPUTS
1287
 *   $ip
1288
 * RESULT
1289
 *   $carp_ints
1290
 ******/
1291
function link_ip_to_carp_interface($ip) {
1292
	global $config;
1293
	if($ip == "") return;
1294

    
1295
	$ifdescrs = array('wan', 'lan');
1296
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1297
		$ifdescrs['opt' . $j] = "opt" . $j;
1298

    
1299
	$ft = split("\.", $ip);
1300
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
1301

    
1302
	$carp_ints = "";
1303
	$num_carp_ints = find_number_of_created_carp_interfaces();
1304
	foreach ($ifdescrs as $ifdescr => $ifname) {
1305
		for($x=0; $x<$num_carp_ints; $x++) {
1306
			$carp_int = "carp{$x}";
1307
			$carp_ip = find_interface_ip($carp_int);
1308
			$carp_subnet = find_virtual_ip_netmask($carp_ip);
1309
			$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1310
			if(ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
1311
				if(!stristr($carp_ints, $carp_int))
1312
					$carp_ints .= " " . $carp_int;
1313
		}
1314
	}
1315
	return $carp_ints;
1316
}
1317

    
1318
/****f* pfsense-utils/find_virtual_ip_netmask
1319
 * NAME
1320
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
1321
 * INPUTS
1322
 *   $ip - ip address to locate subnet mask of
1323
 * RESULT
1324
 *   String containing the command's result.
1325
 * NOTES
1326
 *   This function returns the command's stdout and stderr.
1327
 ******/
1328
function find_virtual_ip_netmask($ip) {
1329
        global $config;
1330
        foreach($config['virtualip']['vip'] as $vip) {
1331
                if($ip == $vip['subnet'])
1332
                        return $vip['subnet_bits'];
1333
        }
1334
}
1335

    
1336
/****f* pfsense-utils/exec_command
1337
 * NAME
1338
 *   exec_command - Execute a command and return a string of the result.
1339
 * INPUTS
1340
 *   $command	- String of the command to be executed.
1341
 * RESULT
1342
 *   String containing the command's result.
1343
 * NOTES
1344
 *   This function returns the command's stdout and stderr.
1345
 ******/
1346
function exec_command($command) {
1347
	$output = array();
1348
	exec($command . ' 2>&1 ', $output);
1349
	return(implode("\n", $output));
1350
}
1351

    
1352
/****f* interfaces/is_jumbo_capable
1353
 * NAME
1354
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
1355
 * INPUTS
1356
 *   $int             - string containing interface name
1357
 * RESULT
1358
 *   boolean          - true or false
1359
 ******/
1360
function is_jumbo_capable($int) {
1361
	/* Per:
1362
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
1363
	 * Only the following drivers support large frames
1364
         *
1365
	 * 'de' chipset purposely left out of this list
1366
	 * requires defining BIG_PACKET in the
1367
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
1368
	 * kernel or module.  The hack works only for the 21041,
1369
	 * 21140, and 21140A chips.
1370
	 */
1371
	global $g;
1372

    
1373
	$capable = $g['vlan_long_frame'];
1374

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

    
1377
	if (in_array($int_family[0], $capable))
1378
		return true;
1379
	else
1380
		return false;
1381
}
1382

    
1383
/*
1384
 * Return the interface array
1385
 */
1386
function get_interface_arr($flush = false) {
1387
	global $interface_arr_cache;
1388

    
1389
	/* If the cache doesn't exist, build it */
1390
	if (!isset($interface_arr_cache) or $flush)
1391
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
1392

    
1393
	return $interface_arr_cache;
1394
}
1395

    
1396
/*
1397
 * does_interface_exist($interface): return true or false if a interface is
1398
 * detected.
1399
 */
1400
function does_interface_exist($interface) {
1401
	if(!$interface) 
1402
		return false;
1403
	$ints = get_interface_arr();
1404

    
1405
	if(stristr($ints, $interface) !== false)
1406
		return true;
1407
	else
1408
		return false;
1409
}
1410

    
1411
/*
1412
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
1413
 */
1414
function convert_ip_to_network_format($ip, $subnet) {
1415
	$ipsplit = split('[.]', $ip);
1416
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
1417
	return $string;
1418
}
1419

    
1420
/*
1421
 * find_interface_ip($interface): return the interface ip (first found)
1422
 */
1423
function find_interface_ip($interface, $flush = false) {
1424
	global $interface_ip_arr_cache;
1425
	$interface = str_replace("\n", "", $interface);
1426
	if(does_interface_exist($interface) == false) return;
1427
	/* Setup IP cache */
1428
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
1429
		$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");
1430
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
1431
	}
1432

    
1433
	return $interface_ip_arr_cache[$interface];
1434
}
1435

    
1436
function guess_interface_from_ip($ipaddress) {
1437
	$ret = exec_command("/usr/bin/netstat -rn | /usr/bin/awk '/^{$ipaddress}/ {print $6}'");
1438
	if(empty($ret)) {
1439
		return false;
1440
	}
1441
	return $ret;
1442
}
1443

    
1444
function filter_opt_interface_to_real($opt) {
1445
	global $config;
1446
	return $config['interfaces'][$opt]['if'];
1447
}
1448

    
1449
function filter_get_opt_interface_descr($opt) {
1450
	global $config;
1451
	return $config['interfaces'][$opt]['descr'];
1452
}
1453

    
1454
function get_friendly_interface_list_as_array() {
1455
	global $config;
1456
	$ints = array();
1457
	$ifdescrs = get_interface_list();
1458
	foreach ($ifdescrs as $ifdescr => $ifname) {
1459
		array_push($ints,$ifdescr);
1460
	}
1461
	return $ints;
1462
}
1463

    
1464
/*
1465
 * find_ip_interface($ip): return the interface where an ip is defined
1466
 */
1467
function find_ip_interface($ip) {
1468
	global $config;
1469
	$ifdescrs = array('wan', 'lan');
1470
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1471
		$ifdescrs['opt' . $j] = "opt" . $j;
1472
	}
1473
	foreach ($ifdescrs as $ifdescr => $ifname) {
1474
		$int = filter_translate_type_to_real_interface($ifname);
1475
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
1476
	if(stristr($ifconfig,$ip) <> false)
1477
		return $int;
1478
	}
1479
	return false;
1480
}
1481

    
1482
/*
1483
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
1484
 *                                                       for a friendly interface.  ie: wan
1485
 */
1486
function filter_translate_type_to_real_interface($interface) {
1487
	global $config;
1488
	if($config['interfaces'][$interface]['if'] <> "") {
1489
		return $config['interfaces'][$interface]['if'];
1490
	} else {
1491
		return $interface;
1492
	}
1493
}
1494

    
1495
/*
1496
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
1497
 */
1498
function get_carp_interface_status($carpinterface) {
1499
	/* basically cache the contents of ifconfig statement
1500
	to speed up this routine */
1501
	global $carp_query;
1502
	if($carp_query == "")
1503
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
1504
	$found_interface = 0;
1505
	foreach($carp_query as $int) {
1506
		if($found_interface == 1) {
1507
			if(stristr($int, "MASTER")) return "MASTER";
1508
			if(stristr($int, "BACKUP")) return "BACKUP";
1509
			if(stristr($int, "INIT")) return "INIT";
1510
			return false;
1511
		}
1512
		if(stristr($int, $carpinterface) == true)
1513
		$found_interface=1;
1514
	}
1515
	return;
1516
}
1517

    
1518
/*
1519
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
1520
 */
1521
function get_pfsync_interface_status($pfsyncinterface) {
1522
    $result = does_interface_exist($pfsyncinterface);
1523
    if($result <> true) return;
1524
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
1525
    return $status;
1526
}
1527

    
1528
/*
1529
 * find_carp_interface($ip): return the carp interface where an ip is defined
1530
 */
1531
function find_carp_interface($ip) {
1532
	global $find_carp_ifconfig;
1533
	if($find_carp_ifconfig == "") {
1534
		$find_carp_ifconfig = array();
1535
		$num_carp_ints = find_number_of_created_carp_interfaces();
1536
		for($x=0; $x<$num_carp_ints; $x++) {
1537
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
1538
		}
1539
	}
1540
	$carps = 0;
1541
	foreach($find_carp_ifconfig as $fci) {
1542
		if(stristr($fci, $ip) == true)
1543
			return "carp{$carps}";
1544
		$carps++;
1545
	}
1546
}
1547

    
1548
/*
1549
 * setup_filter_bridge(): toggle filtering bridge
1550
 *
1551
 * disabled 20080805 - this is of no use with if_bridge, in the sense it was
1552
 * with m0n0 (where this came from)
1553
 * --cmb
1554
function setup_filter_bridge() {
1555
	global $config, $g;
1556
	if(isset($config['bridge']['filteringbridge'])) {
1557
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
1558
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
1559
	} else {
1560
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
1561
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
1562
	}
1563
}
1564
*/
1565

    
1566
/*
1567
 * find_number_of_created_bridges(): returns the number of currently created bridges
1568
 */
1569
function find_number_of_created_bridges($flush = false) {
1570
	global $bridge_interface_count_cache;
1571
	if(!isset($bridge_interface_count_cache) or $flush)
1572
		$bridge_interface_count_cache = exec_command('/sbin/ifconfig | /usr/bin/grep "bridge[0-999]" | /usr/bin/wc -l');
1573

    
1574
	return $bridge_interface_count_cache;
1575
}
1576

    
1577
/*
1578
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
1579
 */
1580
function add_rule_to_anchor($anchor, $rule, $label) {
1581
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
1582
}
1583

    
1584
/*
1585
 * remove_text_from_file
1586
 * remove $text from file $file
1587
 */
1588
function remove_text_from_file($file, $text) {
1589
	global $fd_log;
1590
	if($fd_log)
1591
		fwrite($fd_log, "Adding needed text items:\n");
1592
	$filecontents = file_get_contents($file);
1593
	$textTMP = str_replace($text, "", $filecontents);
1594
	$text = $textTMP;
1595
	if($fd_log)
1596
		fwrite($fd_log, $text);
1597
	$fd = fopen($file, "w");
1598
	fwrite($fd, $text);
1599
	fclose($fd);
1600
}
1601

    
1602
/*
1603
 * add_text_to_file($file, $text): adds $text to $file.
1604
 * replaces the text if it already exists.
1605
 */
1606
function add_text_to_file($file, $text) {
1607
	if(file_exists($file) and is_writable($file)) {
1608
		$filecontents = split("\n", file_get_contents($file));
1609
		$fout = fopen($file, "w");
1610
		$new_file_text = "";
1611
		foreach($filecontents as $line) {
1612
			if($line)
1613
				$new_file_text .= rtrim($line) . "\n";
1614
		}
1615
		$new_file_text .= $text . "\n";
1616
		$file_text = str_replace("\n\n", "\n", $new_file_text);
1617
		fwrite($fout, $file_text);
1618
		fclose($fout);
1619
		return true;
1620
	} else {
1621
		return false;
1622
	}
1623
}
1624

    
1625
/*
1626
 *   after_sync_bump_adv_skew(): create skew values by 1S
1627
 */
1628
function after_sync_bump_adv_skew() {
1629
	global $config, $g;
1630
	$processed_skew = 1;
1631
	$a_vip = &$config['virtualip']['vip'];
1632
	foreach ($a_vip as $vipent) {
1633
		if($vipent['advskew'] <> "") {
1634
			$processed_skew = 1;
1635
			$vipent['advskew'] = $vipent['advskew']+1;
1636
		}
1637
	}
1638
	if($processed_skew == 1)
1639
		write_config("After synch increase advertising skew");
1640
}
1641

    
1642
/*
1643
 * get_filename_from_url($url): converts a url to its filename.
1644
 */
1645
function get_filename_from_url($url) {
1646
	return basename($url);
1647
}
1648

    
1649
/*
1650
 *   update_output_window: update bottom textarea dynamically.
1651
 */
1652
function update_output_window($text) {
1653
	global $pkg_interface;
1654
	$log = ereg_replace("\n", "\\n", $text);
1655
	if($pkg_interface == "console") {
1656
		/* too chatty */
1657
	} else {
1658
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1659
	}
1660
	/* ensure that contents are written out */
1661
	ob_flush();
1662
}
1663

    
1664
/*
1665
 *   get_dir: return an array of $dir
1666
 */
1667
function get_dir($dir) {
1668
	$dir_array = array();
1669
	$d = dir($dir);
1670
	while (false !== ($entry = $d->read())) {
1671
		array_push($dir_array, $entry);
1672
	}
1673
	$d->close();
1674
	return $dir_array;
1675
}
1676

    
1677
/*
1678
 *   update_output_window: update top textarea dynamically.
1679
 */
1680
function update_status($status) {
1681
	global $pkg_interface;
1682
	if($pkg_interface == "console") {
1683
		echo $status . "\n";
1684
	} else {
1685
		echo "\n<script type=\"text/javascript\">document.forms[0].status.value=\"" . $status . "\";</script>";
1686
	}
1687
	/* ensure that contents are written out */
1688
	ob_flush();
1689
}
1690

    
1691
/*
1692
 *   exec_command_and_return_text_array: execute command and return output
1693
 */
1694
function exec_command_and_return_text_array($command) {
1695
	$fd = popen($command . " 2>&1 ", "r");
1696
	while(!feof($fd)) {
1697
		$tmp .= fread($fd,49);
1698
	}
1699
	fclose($fd);
1700
	$temp_array = split("\n", $tmp);
1701
	return $temp_array;
1702
}
1703

    
1704
/*
1705
 *   exec_command_and_return_text: execute command and return output
1706
 */
1707
function exec_command_and_return_text($command) {
1708
	return exec_command($command);
1709
}
1710

    
1711
/*
1712
 *   exec_command_and_return_text: execute command and update output window dynamically
1713
 */
1714
function execute_command_return_output($command) {
1715
	global $fd_log, $pkg_interface;
1716
	$fd = popen($command . " 2>&1 ", "r");
1717
	if($pkg_interface <> "console") {
1718
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1719
	}
1720
	$counter = 0;
1721
	$counter2 = 0;
1722
	while(!feof($fd)) {
1723
		$tmp = fread($fd, 50);
1724
		$tmp1 = ereg_replace("\n","\\n", $tmp);
1725
		$text = ereg_replace("\"","'", $tmp1);
1726
		$lasttext = "";
1727
		if($lasttext == "..") {
1728
			$text = "";
1729
			$lasttext = "";
1730
			$counter=$counter-2;
1731
		} else {
1732
			$lasttext .= $text;
1733
		}
1734
		if($counter > 51) {
1735
			$counter = 0;
1736
			$extrabreak = "\\n";
1737
		} else {
1738
	    $extrabreak = "";
1739
	    $counter++;
1740
		}
1741
		if($counter2 > 600) {
1742
			if($pkg_interface <> "console") {
1743
				echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1744
			}
1745
			$counter2 = 0;
1746
		} else
1747
			$counter2++;
1748
		if($pkg_interface <> "console") {
1749
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
1750
		}
1751
	}
1752
	fclose($fd);
1753
}
1754

    
1755
/*
1756
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
1757
 */
1758
function convert_friendly_interface_to_real_interface_name($interface) {
1759
	global $config;
1760
	if($config['interfaces'][$interface]['ipaddr'] == "pppoe")
1761
		return "ng0";
1762
	$lc_interface = strtolower($interface);
1763
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
1764
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
1765
	$ifdescrs = array();
1766
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1767
		$ifdescrs['opt' . $j] = "opt" . $j;
1768
	foreach ($ifdescrs as $ifdescr => $ifname) {
1769
		if(strtolower($ifname) == $lc_interface)
1770
	    return $config['interfaces'][$ifname]['if'];
1771
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
1772
			return $config['interfaces'][$ifname]['if'];
1773
   }
1774
   return $interface;
1775
}
1776

    
1777
/*
1778
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
1779
 */
1780
function convert_real_interface_to_friendly_interface_name($interface) {
1781
	global $config;
1782
	$ifdescrs = array('wan', 'lan');
1783
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1784
		$ifdescrs['opt' . $j] = "opt" . $j;
1785
	foreach ($ifdescrs as $ifdescr => $ifname) {
1786
		if($config['interfaces']['$ifname']['if'] == $interface)
1787
			return $ifname;
1788
		$int = filter_translate_type_to_real_interface($ifname);
1789
		if($ifname == $interface) return $ifname;
1790
		if($int == $interface) return $ifname;
1791
	}
1792
	return $interface;
1793
}
1794

    
1795
/*
1796
 * update_progress_bar($percent): updates the javascript driven progress bar.
1797
 */
1798
function update_progress_bar($percent) {
1799
	global $pkg_interface;
1800
	if($percent > 100) $percent = 1;
1801
	if($pkg_interface <> "console") {
1802
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1803
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1804
		echo "\n</script>";
1805
	} else {
1806
		echo " {$percent}%";
1807
	}
1808
}
1809

    
1810
/****f* pfsense-utils/WakeOnLan
1811
 * NAME
1812
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
1813
 * RESULT
1814
 *   true/false - true if the operation was successful
1815
 ******/
1816
function WakeOnLan($addr, $mac)
1817
{
1818
	$addr_byte = explode(':', $mac);
1819
	$hw_addr = '';
1820

    
1821
	for ($a=0; $a < 6; $a++)
1822
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1823

    
1824
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1825

    
1826
	for ($a = 1; $a <= 16; $a++)
1827
		$msg .= $hw_addr;
1828

    
1829
	// send it to the broadcast address using UDP
1830
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1831
	if ($s == false) {
1832
		log_error("Error creating socket!");
1833
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
1834
	} else {
1835
		// setting a broadcast option to socket:
1836
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1837
		if($opt_ret < 0)
1838
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1839
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1840
		socket_close($s);
1841
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1842
		return true;
1843
	}
1844

    
1845
	return false;
1846
}
1847

    
1848
/*
1849
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
1850
 *                             is queuename|qlength|measured_packets
1851
 *                             NOTE: this command takes 5 seconds to run
1852
 */
1853
function gather_altq_queue_stats($dont_return_root_queues) {
1854
	mwexec("/usr/bin/killall -9 pfctl", true);
1855
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
1856
	$stats_array = split("\n", $stats);
1857
	$queue_stats = array();
1858
	foreach ($stats_array as $stats_line) {
1859
		$match_array = "";
1860
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
1861
			$queue_name = $match_array[1][0];
1862
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
1863
			$speed = $match_array[1][0];
1864
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
1865
			$borrows = $match_array[1][0];
1866
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
1867
			$suspends = $match_array[1][0];
1868
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
1869
			$drops = $match_array[1][0];
1870
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
1871
			$measured = $match_array[1][0];
1872
			if($dont_return_root_queues == true)
1873
				if(stristr($queue_name,"root_") == false)
1874
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
1875
		}
1876
	}
1877
	return $queue_stats;
1878
}
1879

    
1880
/*
1881
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1882
 *					 Useful for finding paths and stripping file extensions.
1883
 */
1884
function reverse_strrchr($haystack, $needle) {
1885
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1886
}
1887

    
1888
/*
1889
 *  backup_config_section($section): returns as an xml file string of
1890
 *                                   the configuration section
1891
 */
1892
function backup_config_section($section) {
1893
	global $config;
1894
	$new_section = &$config[$section];
1895
	/* generate configuration XML */
1896
	$xmlconfig = dump_xml_config($new_section, $section);
1897
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1898
	return $xmlconfig;
1899
}
1900

    
1901
/*
1902
 *  backup_vip_config_section($section): returns as an xml file string of
1903
 *                                   the configuration section
1904
 */
1905
function backup_vip_config_section() {
1906
	global $config;
1907
	$new_section = &$config['virtualip'];
1908
	foreach($new_section['vip'] as $section) {
1909
		if($section['mode'] == "proxyarp") {
1910
			unset($section);
1911
		}
1912
		if($section['advskew'] <> "") {
1913
			$section_val = intval($section['advskew']);
1914
			$section_val=$section_val+100;
1915
			if($section_val > 255)
1916
				$section_val = 255;
1917
			$section['advskew'] = $section_val;
1918
		}
1919
		$temp['vip'][] = $section;
1920
   }
1921
   return $temp;
1922
}
1923

    
1924
/*
1925
 *  restore_config_section($section, new_contents): restore a configuration section,
1926
 *                                                  and write the configuration out
1927
 *                                                  to disk/cf.
1928
 */
1929
function restore_config_section($section, $new_contents) {
1930
	global $config, $g;
1931
	conf_mount_rw();
1932
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
1933
	fwrite($fout, $new_contents);
1934
	fclose($fout);
1935
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
1936
	$config[$section] = &$section_xml;
1937
	unlink($g['tmp_path'] . "/tmpxml");
1938
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1939
	conf_mount_ro();
1940
	return;
1941
}
1942

    
1943
/*
1944
 *  merge_config_section($section, new_contents):   restore a configuration section,
1945
 *                                                  and write the configuration out
1946
 *                                                  to disk/cf.  But preserve the prior
1947
 * 													structure if needed
1948
 */
1949
function merge_config_section($section, $new_contents) {
1950
	global $config;
1951
	conf_mount_rw();
1952
	$fname = get_tmp_filename();
1953
	$fout = fopen($fname, "w");
1954
	fwrite($fout, $new_contents);
1955
	fclose($fout);
1956
	$section_xml = parse_xml_config($fname, $section);
1957
	$config[$section] = $section_xml;
1958
	unlink($fname);
1959
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1960
	conf_mount_ro();
1961
	return;
1962
}
1963

    
1964
/*
1965
 * http_post($server, $port, $url, $vars): does an http post to a web server
1966
 *                                         posting the vars array.
1967
 * written by nf@bigpond.net.au
1968
 */
1969
function http_post($server, $port, $url, $vars) {
1970
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
1971
	$urlencoded = "";
1972
	while (list($key,$value) = each($vars))
1973
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
1974
	$urlencoded = substr($urlencoded,0,-1);
1975
	$content_length = strlen($urlencoded);
1976
	$headers = "POST $url HTTP/1.1
1977
Accept: */*
1978
Accept-Language: en-au
1979
Content-Type: application/x-www-form-urlencoded
1980
User-Agent: $user_agent
1981
Host: $server
1982
Connection: Keep-Alive
1983
Cache-Control: no-cache
1984
Content-Length: $content_length
1985

    
1986
";
1987

    
1988
	$errno = "";
1989
	$errstr = "";
1990
	$fp = fsockopen($server, $port, $errno, $errstr);
1991
	if (!$fp) {
1992
		return false;
1993
	}
1994

    
1995
	fputs($fp, $headers);
1996
	fputs($fp, $urlencoded);
1997

    
1998
	$ret = "";
1999
	while (!feof($fp))
2000
		$ret.= fgets($fp, 1024);
2001
	fclose($fp);
2002

    
2003
	return $ret;
2004
}
2005

    
2006
/*
2007
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
2008
 */
2009
if (!function_exists('php_check_syntax')){
2010
	function php_check_syntax($code_to_check, &$errormessage){
2011
		return false;
2012
		$fout = fopen("/tmp/codetocheck.php","w");
2013
		$code = $_POST['content'];
2014
		$code = str_replace("<?php", "", $code);
2015
		$code = str_replace("?>", "", $code);
2016
		fwrite($fout, "<?php\n\n");
2017
		fwrite($fout, $code_to_check);
2018
		fwrite($fout, "\n\n?>\n");
2019
		fclose($fout);
2020
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
2021
		$output = exec_command($command);
2022
		if (stristr($output, "Errors parsing") == false) {
2023
			echo "false\n";
2024
			$errormessage = '';
2025
			return(false);
2026
		} else {
2027
			$errormessage = $output;
2028
			return(true);
2029
		}
2030
	}
2031
}
2032

    
2033
/*
2034
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
2035
 */
2036
if (!function_exists('php_check_syntax')){
2037
	function php_check_syntax($code_to_check, &$errormessage){
2038
		return false;
2039
		$command = "/usr/local/bin/php -l " . $code_to_check;
2040
		$output = exec_command($command);
2041
		if (stristr($output, "Errors parsing") == false) {
2042
			echo "false\n";
2043
			$errormessage = '';
2044
			return(false);
2045
		} else {
2046
			$errormessage = $output;
2047
			return(true);
2048
		}
2049
	}
2050
}
2051

    
2052
/*
2053
 * rmdir_recursive($path,$follow_links=false)
2054
 * Recursively remove a directory tree (rm -rf path)
2055
 * This is for directories _only_
2056
 */
2057
function rmdir_recursive($path,$follow_links=false) {
2058
	$to_do = glob($path);
2059
	if(!is_array($to_do)) $to_do = array($to_do);
2060
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
2061
		if(file_exists($workingdir)) {
2062
			if(is_dir($workingdir)) {
2063
				$dir = opendir($workingdir);
2064
				while ($entry = readdir($dir)) {
2065
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
2066
						unlink("$workingdir/$entry");
2067
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
2068
						rmdir_recursive("$workingdir/$entry");
2069
				}
2070
				closedir($dir);
2071
				rmdir($workingdir);
2072
			} elseif (is_file($workingdir)) {
2073
				unlink($workingdir);
2074
			}
2075
               	}
2076
	}
2077
	return;
2078
}
2079

    
2080
/*
2081
 *     get_memory()
2082
 *     returns an array listing the amount of
2083
 *     memory installed in the hardware
2084
 *     [0]real and [1]available
2085
 */
2086
function get_memory() {
2087
	if(file_exists("/var/log/dmesg.boot")) {
2088
		$mem = `cat /var/log/dmesg.boot | grep memory`;
2089
		$matches = "";
2090
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2091
			$real = $matches[1];
2092
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2093
			$avail = $matches[1];
2094
		return array($real[0],$avail[0]);
2095
	} else {
2096
		$mem = `dmesg -a`;
2097
		$matches = "";
2098
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2099
			$real = $matches[1];
2100
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2101
			$avail = $matches[1];
2102
		return array($real[0],$avail[0]);
2103
	}
2104
}
2105

    
2106
/*
2107
 *    safe_mkdir($path, $mode = 0755)
2108
 *    create directory if it doesn't already exist and isn't a file!
2109
 */
2110
function safe_mkdir($path, $mode=0755) {
2111
	global $g;
2112

    
2113
	/* cdrom is ro. */
2114
	if($g['platform'] == "cdrom")
2115
		return false;
2116

    
2117
	if (!is_file($path) && !is_dir($path))
2118
		return mkdir($path, $mode);
2119
	else
2120
		return false;
2121
}
2122

    
2123
/*
2124
 * make_dirs($path, $mode = 0755)
2125
 * create directory tree recursively (mkdir -p)
2126
 */
2127
function make_dirs($path, $mode = 0755) {
2128
	$base = '';
2129
	foreach (explode('/', $path) as $dir) {
2130
		$base .= "/$dir";
2131
		if (!is_dir($base)) {
2132
			if (!@mkdir($base, $mode))
2133
				return false;
2134
		}
2135
	}
2136
	return true;
2137
}
2138

    
2139
/*
2140
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
2141
 */
2142
function call_pfsense_method($method, $params, $timeout = 0) {
2143
	$ip = gethostbyname('www.pfsense.com');
2144
	if($ip == "www.pfsense.com")
2145
		return false;
2146
	global $g, $config;
2147
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
2148
	$xmlrpc_path = $g['xmlrpcpath'];
2149
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
2150
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
2151
	$resp = $cli->send($msg, $timeout);
2152
	if(!$resp) {
2153
		log_error("XMLRPC communication error: " . $cli->errstr);
2154
		return false;
2155
	} elseif($resp->faultCode()) {
2156
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
2157
		return false;
2158
	} else {
2159
		return XML_RPC_Decode($resp->value());
2160
	}
2161
}
2162

    
2163
/*
2164
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
2165
 */
2166
function check_firmware_version($tocheck = "all", $return_php = true) {
2167
	global $g, $config;
2168
	$ip = gethostbyname('www.pfsense.com');
2169
	if($ip == "www.pfsense.com")
2170
		return false;
2171
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
2172
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
2173
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
2174
		"platform" => trim(file_get_contents('/etc/platform'))
2175
		);
2176
	if($tocheck == "all") {
2177
		$params = $rawparams;
2178
	} else {
2179
		foreach($tocheck as $check) {
2180
			$params['check'] = $rawparams['check'];
2181
			$params['platform'] = $rawparams['platform'];
2182
		}
2183
	}
2184
	if($config['system']['firmware']['branch']) {
2185
		$params['branch'] = $config['system']['firmware']['branch'];
2186
	}
2187
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
2188
		return false;
2189
	} else {
2190
		$versions["current"] = $params;
2191
	}
2192
	return $versions;
2193
}
2194

    
2195
function get_disk_info() {
2196
	$diskout = "";
2197
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
2198
	return explode(' ', $diskout[0]);
2199
	// $size, $used, $avail, $cap
2200
}
2201

    
2202
function run_plugins($directory) {
2203
	global $config, $g;
2204
	/* process packager manager custom rules */
2205
	$files = return_dir_as_array($directory);
2206
	if($files <> "") {
2207
		foreach ($files as $file) {
2208
			if($file) {
2209
				$text = file_get_contents($directory . $file);
2210
				if($text) {
2211
					if(stristr($file, ".sh") == true) {
2212
						mwexec($directory . $file . " start");
2213
					} else {
2214
						if(!stristr($file,"CVS")) {
2215
							if($g['booting'] == true)
2216
								echo "\t{$file}... ";
2217
							require_once($directory . $file);
2218
						}
2219
					}
2220
				}
2221
			}
2222
		}
2223
	}	
2224
}
2225

    
2226
/****f* pfsense-utils/display_top_tabs
2227
 * NAME
2228
 *   display_top_tabs - display tabs with rounded edges
2229
 * INPUTS
2230
 *   $text	- array of tabs
2231
 * RESULT
2232
 *   null
2233
 ******/
2234
function display_top_tabs($tab_array) {
2235
	echo "<table cellpadding='0' cellspacing='0'>\n";
2236
	echo " <tr height='1'>\n";
2237
	$tabscounter = 0;
2238
	foreach ($tab_array as $ta) {
2239
		if($ta[1] == true) {
2240
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
2241
		} else {
2242
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
2243
		}
2244
		$tabscounter++;
2245
	}
2246
	echo "</tr>\n<tr>\n";
2247
	foreach ($tab_array as $ta) {
2248
		if($ta[1] == true) {
2249
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
2250
			echo "&nbsp;&nbsp;&nbsp;";
2251
			echo "<font size='-12'>&nbsp;</td>\n";
2252
		} else {
2253
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
2254
			echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
2255
			echo "<font size='-12'>&nbsp;</td>\n";
2256
		}
2257
	}
2258
	echo "</tr>\n<tr height='5px'>\n";
2259
	foreach ($tab_array as $ta) {
2260
		if($ta[1] == true) {
2261
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2262
		} else {
2263
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2264
		}
2265
		$tabscounter++;
2266
	}
2267
	echo " </tr>\n";
2268
	echo "</table>\n";
2269

    
2270
	echo "<script type=\"text/javascript\">";
2271
	echo "NiftyCheck();\n";
2272
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
2273
	for($x=0; $x<$tabscounter; $x++)
2274
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
2275
	echo "</script>";
2276
}
2277

    
2278

    
2279
/****f* pfsense-utils/display_topbar
2280
 * NAME
2281
 *   display_topbar - top a table off with rounded edges
2282
 * INPUTS
2283
 *   $text	- (optional) Text to include in bar
2284
 * RESULT
2285
 *   null
2286
 ******/
2287
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
2288
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
2289
	echo "       <tr height='1'>\n";
2290
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
2291
	echo "		<div id='topbar'></div></td>\n";
2292
	echo "       </tr>\n";
2293
	echo "       <tr height='1'>\n";
2294
	if ($text != "")
2295
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
2296
	else
2297
		echo "         <td height='1' class='listtopic'></td>\n";
2298
	echo "       </tr>\n";
2299
	echo "     </table>";
2300
	echo "<script type=\"text/javascript\">";
2301
	echo "NiftyCheck();\n";
2302
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
2303
	echo "</script>";
2304
}
2305

    
2306
/****f* pfsense-utils/generate_random_mac_address
2307
 * NAME
2308
 *   generate_random_mac - generates a random mac address
2309
 * INPUTS
2310
 *   none
2311
 * RESULT
2312
 *   $mac - a random mac address
2313
 ******/
2314
function generate_random_mac_address() {
2315
	$mac = "02";
2316
	for($x=0; $x<5; $x++)
2317
		$mac .= ":" . dechex(rand(16, 255));
2318
	return $mac;
2319
}
2320

    
2321
/****f* pfsense-utils/strncpy
2322
 * NAME
2323
 *   strncpy - copy strings
2324
 * INPUTS
2325
 *   &$dst, $src, $length
2326
 * RESULT
2327
 *   none
2328
 ******/
2329
function strncpy(&$dst, $src, $length) {
2330
	if (strlen($src) > $length) {
2331
		$dst = substr($src, 0, $length);
2332
	} else {
2333
		$dst = $src;
2334
	}
2335
}
2336

    
2337
/****f* pfsense-utils/reload_interfaces_sync
2338
 * NAME
2339
 *   reload_interfaces - reload all interfaces
2340
 * INPUTS
2341
 *   none
2342
 * RESULT
2343
 *   none
2344
 ******/
2345
function reload_interfaces_sync() {
2346
	global $config, $g, $debug;
2347

    
2348
	$shutdown_webgui_needed = false;
2349

    
2350
	touch("{$g['tmp_path']}/reloading_all");
2351

    
2352
	if($debug)
2353
		log_error("reload_interfaces_sync() is starting.");
2354

    
2355
	if(file_exists("{$g['tmp_path']}/config.cache"))
2356
		unlink("{$g['tmp_path']}/config.cache");
2357

    
2358
	/* parse config.xml again */
2359
	$config = parse_config(true);
2360

    
2361
	$wan_if = $config['interfaces']['wan']['if'];
2362
	$lan_if = $config['interfaces']['lan']['if'];
2363

    
2364
	if($debug)
2365
		log_error("Cleaning up Interfaces");
2366

    
2367
	/* build an array of interfaces to work with */
2368
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2369
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2370
		$iflist['opt' . $i] = "opt{$i}";
2371

    
2372
	foreach ($iflist as $ifent => $ifname) {
2373
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2374
		if(stristr($ifname, "lo0") == true)
2375
			continue;
2376
		/* do not process wan interface, its mandatory */
2377
		if(stristr($ifname, "$wan_if") == true)
2378
			continue;
2379
		/* do not process lan interface, its mandatory */
2380
		if(stristr($ifname, "$lan_if") == true)
2381
			continue;
2382
		if($debug)
2383
			log_error("Downing and deleting $ifname_real - $ifname");
2384
		mwexec("/sbin/ifconfig {$ifname_real} down");
2385
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2386
	}
2387

    
2388
	/* set up VLAN virtual interfaces */
2389
	if($debug)
2390
		log_error("Configuring VLANS");
2391
	interfaces_vlan_configure();
2392

    
2393
	/* set up LAN interface */
2394
	if($debug)
2395
		log_error("Configuring LAN");
2396
	interfaces_lan_configure();
2397

    
2398
	/* set up WAN interface */
2399
	if($debug)
2400
		log_error("Configuring WAN");
2401
	interfaces_wan_configure();
2402

    
2403
	/* set up Optional interfaces */
2404
	if($debug)
2405
		log_error("Configuring optional interfaces");
2406
	interfaces_optional_configure();
2407

    
2408
	/* set up static routes */
2409
	if($debug)
2410
		log_error("Configuring system Routing");
2411
	system_routing_configure();
2412

    
2413
	/* enable routing */
2414
	if($debug)
2415
		log_error("Enabling system routing");
2416
	system_routing_enable();
2417

    
2418
	/* setup captive portal if needed */
2419
	if($debug)
2420
		log_error("Configuring Captive portal");
2421
	captiveportal_configure();
2422

    
2423
	/* bring up carp interfaces */
2424
	if($debug)
2425
		log_error("Configuring CARP");
2426
	interfaces_carp_configure();
2427

    
2428
	/* bring up carp interfaces*/
2429
	if($debug)
2430
		log_error("Bringing up CARP interfaces");
2431
	interfaces_carp_bring_up_final();
2432

    
2433
	/* restart webConfigurator if needed */
2434
	if($shutdown_webgui_needed == true)
2435
		touch("/tmp/restart_webgui");
2436

    
2437
	/* start devd back up */
2438
	mwexec("/bin/rm /tmp/reload*");
2439

    
2440
	/* remove reloading_all trigger */
2441
	if($debug)
2442
		log_error("Removing {$g['tmp_path']}/reloading_all");
2443
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2444
}
2445

    
2446
/****f* pfsense-utils/reload_all
2447
 * NAME
2448
 *   reload_all - triggers a reload of all settings
2449
 *   * INPUTS
2450
 *   none
2451
 * RESULT
2452
 *   none
2453
 ******/
2454
function reload_all() {
2455
	touch("/tmp/reload_all");
2456
}
2457

    
2458
/****f* pfsense-utils/reload_interfaces
2459
 * NAME
2460
 *   reload_interfaces - triggers a reload of all interfaces
2461
 * INPUTS
2462
 *   none
2463
 * RESULT
2464
 *   none
2465
 ******/
2466
function reload_interfaces() {
2467
	touch("/tmp/reload_interfaces");
2468
}
2469

    
2470
/****f* pfsense-utils/sync_webgui_passwords
2471
 * NAME
2472
 *   sync_webgui_passwords - syncs webgui and ssh passwords
2473
 * INPUTS
2474
 *   none
2475
 * RESULT
2476
 *   none
2477
 ******/
2478
function sync_webgui_passwords() {
2479
	global $config, $g;
2480
	conf_mount_rw();
2481
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
2482
	if (!$fd) {
2483
		printf("Error: cannot open htpasswd in system_password_configure().\n");
2484
		return 1;
2485
	}
2486
	/* set admin account */
2487
	$username = $config['system']['username'];
2488

    
2489
	/* set defined user account */
2490
	if($username <> "admin") {
2491
		$username = $config['system']['username'];
2492
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
2493
	} else {
2494
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
2495
	}
2496
	fclose($fd);
2497
	chmod("{$g['varrun_path']}/htpasswd", 0600);
2498
	$crypted_pw = $config['system']['password'];
2499
	if(file_exists("/etc/pwd.db.tmp")) 
2500
		unlink("/etc/pwd.db.tmp");
2501
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2502
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2503
	/* sync root */
2504
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
2505
	fwrite($fd, $crypted_pw);
2506
	pclose($fd);
2507
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
2508
	/* sync admin */
2509
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
2510
	fwrite($fd, $crypted_pw);
2511
	pclose($fd);
2512
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
2513
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2514
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2515
	conf_mount_ro();
2516
}
2517

    
2518
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
2519
 * NAME
2520
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
2521
 *   * INPUTS
2522
 *   optional interface number
2523
 * RESULT
2524
 *   none
2525
 ******/
2526
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
2527
	/*	move all the interfaces up.  for example:
2528
	*		opt1 --> opt1
2529
	*		opt2 --> delete
2530
	*		opt3 --> opt2
2531
	*		opt4 --> opt3
2532
	*/
2533
	global $g, $config;
2534
	config_lock();
2535
	conf_mount_rw();
2536
	unlink_if_exists("{$g['tmp_path']}/config.cache");
2537
	$config_file = file_get_contents("/cf/conf/config.xml");
2538
	/* loop through and reassign deleted items */
2539
	$orig = array('opt'.$opt_interface_num,'OPT'.$opt_interface_num);
2540
	$repl = array('optXXXX','OPTXXXX');
2541
	for ($i = $opt_interface_num+1; isset ($config['interfaces']['opt' . $i]); $i++) {
2542
		array_push($orig,'opt'.$i);
2543
		array_push($repl,'opt'.($i -1));
2544
		array_push($orig,'OPT'.$i);
2545
		array_push($repl,'OPT'.($i -1));
2546
	}
2547
	$config_file = str_replace($orig, $repl, $config_file);
2548
	$fd = fopen("/cf/conf/config.xml", "w");
2549
	fwrite($fd, $config_file);
2550
	fclose($fd);
2551
	$config = parse_config(true);
2552
	/* loop through and delete old rules */
2553
	$num_rules = count($config['filter']['rule']);
2554
	for($x = $num_rules; $x > 0; $x--) {
2555
		if($config['filter']['rule'][$x])
2556
			if($config['filter']['rule'][$x]['interface'] == "optXXXX")
2557
		 		unset($config['filter']['rule'][$x]['interface']);
2558
	}
2559
	$num_rules = count($config['nat']['advancedoutbound']['rule']);
2560
	for($x = $num_rules; $x > 0; $x--) {
2561
		if($config['nat']['advancedoutbound']['rule'][$x])
2562
			if($config['nat']['advancedoutbound']['rule'][$x]['interface'] == "optXXXX")
2563
		 		unset($config['nat']['advancedoutbound']['rule'][$x]['interface']);
2564
	}
2565
	$num_rules = count($config['nat']['rule']);
2566
	for($x = $num_rules; $x > 0; $x--) {
2567
		if($config['nat']['rule'][$x])
2568
			if($config['nat']['rule'][$x]['interface'] == "optXXXX")
2569
		 		unset($config['nat']['rule'][$x]['interface']);
2570
	}
2571
	write_config();
2572
	conf_mount_ro();
2573
	config_unlock();
2574
	return true;
2575
}
2576

    
2577
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
2578
 * NAME
2579
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
2580
 *   		amount of netgraph interfaces needed for system wans
2581
 *   * INPUTS
2582
 *   none
2583
 * RESULT
2584
 *   number of needed netgraph (ng) interfaces
2585
 ******/
2586
function get_number_of_wan_netgraph_interfaces_needed() {
2587
	global $config, $g;
2588
	/* build an array of interfaces to work with */
2589
	$iflist = array("wan" => "WAN");
2590
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2591
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2592
	$ng_interfaces_needed = 0;
2593
	foreach ($iflist as $ifent => $ifname) {
2594
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2595
			$ng_interfaces_needed++;
2596
		}
2597
	}
2598
	return $ng_interfaces_needed;
2599
}
2600

    
2601
function get_netgaph_interface_assignment($friendly_interface) {
2602
	global $config, $g;
2603
	/* build an array of interfaces to work with */
2604
	$iflist = array("wan" => "WAN");
2605
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2606
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2607
		$ng_interfaces_needed = 0;
2608
		$ng_interfaces_number = 0;
2609
		foreach ($iflist as $ifent => $ifname) {
2610
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2611
			$ng_interfaces_number++;
2612
		}
2613
		if($friendly_interface == $ifname)
2614
			break;
2615
	}
2616
	return $ng_interfaces_number;
2617
}
2618

    
2619
/****f* pfsense-utils/reload_all_sync
2620
 * NAME
2621
 *   reload_all - reload all settings
2622
 *   * INPUTS
2623
 *   none
2624
 * RESULT
2625
 *   none
2626
 ******/
2627
function reload_all_sync() {
2628
	global $config, $g;
2629

    
2630
	$g['booting'] = false;
2631

    
2632
	touch("{$g['tmp_path']}/reloading_all");
2633

    
2634
	$shutdown_webgui_needed = false;
2635

    
2636
	if(file_exists("{$g['tmp_path']}/config.cache"))
2637
		unlink("{$g['tmp_path']}/config.cache");
2638

    
2639
	/* parse config.xml again */
2640
	$config = parse_config(true);
2641

    
2642
	/* set up our timezone */
2643
	system_timezone_configure();
2644

    
2645
	/* set up our hostname */
2646
	system_hostname_configure();
2647

    
2648
	/* make hosts file */
2649
	system_hosts_generate();
2650

    
2651
	/* generate resolv.conf */
2652
	system_resolvconf_generate();
2653

    
2654
	/* Set up our loopback interface */
2655
	interfaces_loopback_configure();
2656

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

    
2660
	$wan_if = $config['interfaces']['wan']['if'];
2661
	$lan_if = $config['interfaces']['lan']['if'];
2662

    
2663
	/* build an array of interfaces to work with */
2664
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2665
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2666
		$iflist['opt' . $i] = "opt{$i}";
2667

    
2668
	foreach ($iflist as $ifent => $ifname) {
2669
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2670
		if(stristr($ifname, "lo0") == true)
2671
			continue;
2672
		/* do not process wan interface, its mandatory */
2673
		if($wan_if == $ifname_real)
2674
			continue;
2675
		/* do not process lan interface, its mandatory */
2676
		if($lan_if == $ifname_real)
2677
			continue;
2678
		mwexec("/sbin/ifconfig {$ifname_real} down");
2679
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2680
	}
2681

    
2682
	/* set up VLAN virtual interfaces */
2683
	interfaces_vlan_configure();
2684

    
2685
	/* set up LAN interface */
2686
	interfaces_lan_configure();
2687

    
2688
	/* set up WAN interface */
2689
	interfaces_wan_configure();
2690

    
2691
	/* set up Optional interfaces */
2692
	interfaces_optional_configure();
2693

    
2694
	/* bring up carp interfaces */
2695
	interfaces_carp_configure();
2696

    
2697
	/* set up static routes */
2698
	system_routing_configure();
2699

    
2700
	/* enable routing */
2701
	system_routing_enable();
2702

    
2703
	/* ensure passwords are sync'd */
2704
	system_password_configure();
2705

    
2706
	/* start dnsmasq service */
2707
	services_dnsmasq_configure();
2708

    
2709
	/* start dyndns service */
2710
	services_dyndns_configure();
2711

    
2712
	/* start DHCP service */
2713
	services_dhcpd_configure();
2714

    
2715
	/* configure cron service */
2716
	configure_cron();
2717

    
2718
	/* start the NTP client */
2719
	system_ntp_configure();
2720

    
2721
	/* start ftp proxy helpers if they are enabled */
2722
	system_start_ftp_helpers();
2723

    
2724
	/* start the captive portal */
2725
	captiveportal_configure();
2726

    
2727
        /* reload the filter */
2728
	filter_configure_sync();
2729

    
2730
	/* bring up carp interfaces*/
2731
	interfaces_carp_bring_up_final();
2732

    
2733
	/* sync pw database */
2734
	conf_mount_rw();
2735
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2736
	conf_mount_ro();
2737

    
2738
	/* restart sshd */
2739
	touch("/tmp/start_sshd");
2740

    
2741
	/* restart webConfigurator if needed */
2742
	if($shutdown_webgui_needed == true)
2743
		touch("/tmp/restart_webgui");
2744

    
2745
	mwexec("/bin/rm /tmp/reload*");
2746

    
2747
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2748

    
2749
}
2750

    
2751
function auto_login($status) {
2752
	$gettytab = file_get_contents("/etc/gettytab");
2753
	$getty_split = split("\n", $gettytab);
2754
	conf_mount_rw();
2755
	$fd = fopen("/etc/gettytab", "w");
2756
	foreach($getty_split as $gs) {
2757
		if(stristr($gs, ":ht:np:sp#115200") ) {
2758
			if($status == true) {
2759
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
2760
			} else {
2761
				fwrite($fd, "	:ht:np:sp#115200:\n");
2762
			}
2763
		} else {
2764
			fwrite($fd, "{$gs}\n");
2765
		}
2766
	}
2767
	fclose($fd);
2768
	conf_mount_ro();
2769
}
2770

    
2771
function setup_serial_port() {
2772
	global $g, $config;
2773
	conf_mount_rw();
2774
	/* serial console - write out /boot.config */
2775
	if(file_exists("/boot.config"))
2776
		$boot_config = file_get_contents("/boot.config");
2777
	else
2778
		$boot_config = "";
2779

    
2780
	if($g['platform'] <> "cdrom") {
2781
		$boot_config_split = split("\n", $boot_config);
2782
		$fd = fopen("/boot.config","w");
2783
		if($fd) {
2784
			foreach($boot_config_split as $bcs) {
2785
				if(stristr($bcs, "-D")) {
2786
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2787
				} else {
2788
					if($bcs <> "")
2789
						fwrite($fd, "{$bcs}\n");
2790
				}
2791
			}
2792
			if(isset($config['system']['enableserial'])) {
2793
				fwrite($fd, "-D");
2794
			}
2795
			fclose($fd);
2796
		}
2797
		/* serial console - write out /boot/loader.conf */
2798
		$boot_config = file_get_contents("/boot/loader.conf");
2799
		$boot_config_split = split("\n", $boot_config);
2800
		$fd = fopen("/boot/loader.conf","w");
2801
		if($fd) {
2802
			foreach($boot_config_split as $bcs) {
2803
				if(stristr($bcs, "console")) {
2804
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2805
				} else {
2806
					if($bcs <> "")
2807
						fwrite($fd, "{$bcs}\n");
2808
				}
2809
			}
2810
			if(isset($config['system']['enableserial'])) {
2811
				fwrite($fd, "console=\"comconsole\"\n");
2812
			}
2813
			fclose($fd);
2814
		}
2815
	}
2816
	$ttys = file_get_contents("/etc/ttys");
2817
	$ttys_split = split("\n", $ttys);
2818
	$fd = fopen("/etc/ttys", "w");
2819
	foreach($ttys_split as $tty) {
2820
		if(stristr($tty, "ttyd0")) {
2821
			if(isset($config['system']['enableserial'])) {
2822
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
2823
			} else {
2824
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
2825
			}
2826
		} else {
2827
			fwrite($fd, $tty . "\n");
2828
		}
2829
	}
2830
	fclose($fd);
2831
	if(isset($config['system']['disableconsolemenu'])) {
2832
		auto_login(false);
2833
	} else {
2834
		auto_login(true);
2835
	}
2836
	conf_mount_ro();
2837
	return;
2838
}
2839

    
2840
function print_value_list($list, $count = 10, $separator = ",") {
2841
	$list = implode($separator, array_slice($list, 0, $count));
2842
	if(count($list) < $count) {
2843
		$list .= ".";
2844
	} else {
2845
		$list .= "...";
2846
	}
2847
	return $list;
2848
}
2849

    
2850
function convert_friendly_interface_to_friendly_descr($interface) {
2851
	global $config;
2852
	/* attempt to resolve interface to friendly descr */
2853
	if($config['interfaces'][$interface]['descr'])
2854
		return $config['interfaces'][$interface]['descr'];
2855
	$tmp = convert_real_interface_to_friendly_descr($interface);
2856
	/* could not resolve, return back what was passed */
2857
	return $interface;
2858
}
2859

    
2860
function convert_real_interface_to_friendly_descr($interface) {
2861
	global $config;
2862
	if($interface == $config['interfaces']['wan']['if'])
2863
		return "wan";
2864
	if($interface == $config['interfaces']['lan']['if'])
2865
		return "lan";
2866
	/* attempt to resolve interface to friendly descr */
2867
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
2868
	if($config['interfaces'][$friendly_int]['descr'])
2869
		return $config['interfaces'][$friendly_int]['descr'];
2870
	/* could not resolve, return back what was passed */
2871
	return $interface;
2872
}
2873

    
2874
function enable_rrd_graphing() {
2875
	global $config, $g;
2876

    
2877
	if($g['booting']) 
2878
		echo "Generating RRD graphs...";
2879

    
2880
	$rrddbpath = "/var/db/rrd/";
2881
	$rrdgraphpath = "/usr/local/www/rrd";
2882

    
2883
	$traffic = "-traffic.rrd";
2884
	$packets = "-packets.rrd";
2885
	$states = "-states.rrd";
2886
	$quality = "-quality.rrd";
2887
	$queues = "-queues.rrd";
2888
	$queuesdrop = "-queuesdrop.rrd";
2889
	$spamd = "-spamd.rrd";
2890
	$proc = "-processor.rrd";
2891

    
2892
	$rrdtool = "/usr/local/bin/rrdtool";
2893
	$netstat = "/usr/bin/netstat";
2894
	$awk = "/usr/bin/awk";
2895
	$tar = "/usr/bin/tar";
2896
	$pfctl = "/sbin/pfctl";
2897
	$php = "/usr/local/bin/php";
2898
	$top = "/usr/bin/top";
2899
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2900

    
2901
	$rrdtrafficinterval = 60;
2902
	$rrdqualityinterval = 60;
2903
	$rrdqueuesinterval = 60;
2904
	$rrdqueuesdropinterval = 60;
2905
	$rrdpacketsinterval = 60;
2906
	$rrdstatesinterval = 60;
2907
	$rrdspamdinterval = 60;
2908
	$rrdlbpoolinterval = 60;
2909
	$rrdprocinterval = 60;
2910

    
2911
	$trafficvalid = $rrdtrafficinterval * 2;
2912
	$qualityvalid = $rrdqualityinterval * 2;
2913
	$queuesvalid = $rrdqueuesinterval * 2;
2914
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2915
	$packetsvalid = $rrdpacketsinterval * 2;
2916
	$statesvalid = $rrdstatesinterval*2;
2917
	$spamdvalid = $rrdspamdinterval * 2;
2918
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2919
	$procvalid = $rrdlbpoolinterval * 2;
2920

    
2921
	/* Asume GigE for now */
2922
	$downstream = 125000000;
2923
	$upstream = 125000000;
2924

    
2925
	$rrdrestore = "";
2926
	$rrdreturn = "";
2927

    
2928
	if (isset ($config['rrd']['enable'])) {
2929

    
2930
		/* create directory if needed */
2931
		if (!is_dir("$rrddbpath")) {
2932
			mkdir("$rrddbpath", 0755);
2933
		}
2934

    
2935
		if ($g['booting']) {
2936
			if ($g['platform'] != "pfSense") {
2937
				/* restore the databases, if we have one */
2938
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
2939
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2940
					if((int)$rrdrestore <> 0) {
2941
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
2942
					}
2943
				}
2944
			}
2945
		}
2946

    
2947
		/* db update script */
2948
		$rrdupdatesh = "#!/bin/sh\n";
2949
		$rrdupdatesh .= "\n";
2950
		$rrdupdatesh .= "counter=1\n";
2951
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2952
		$rrdupdatesh .= "do\n";
2953
		$rrdupdatesh .= "";
2954

    
2955
		$i = 0;
2956
		$vfaces = array (
2957
			"vlan.?*",
2958
			"enc.?*"
2959
		);
2960
		$ifdescrs = get_interface_list(true, true, $vfaces);
2961
		$ifdescrs['enc0']['friendly'] = "ipsec";
2962
		$ifdescrs['enc0']['descr'] = "IPSEC";
2963
		$ifdescrs['enc0']['up'] = true;
2964

    
2965
		foreach ($ifdescrs as $realif => $ifdescr) {
2966
			$ifname = $ifdescr['friendly'];
2967
			$state = $ifdescr['up'];
2968

    
2969
			/* skip interfaces that do not have a friendly name */
2970
			if ("$ifname" == "") {
2971
				continue;
2972
			}
2973

    
2974
			/* or are down */
2975
			if (!$state) {
2976
				continue;
2977
			}
2978

    
2979
			/* TRAFFIC, set up the rrd file */
2980
			if (!file_exists("$rrddbpath$ifname$traffic")) {
2981
				/* create rrd file if it does not exist */
2982
				log_error("Create RRD database $rrddbpath$ifname$traffic");
2983
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
2984
				$rrdcreate .= "DS:in:COUNTER:$trafficvalid:0:$downstream ";
2985
				$rrdcreate .= "DS:out:COUNTER:$trafficvalid:0:$upstream ";
2986
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2987
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2988
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2989
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2990
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2991
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2992
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2993
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
2994

    
2995
				$rrdcreateoutput = array();
2996
				$rrdcreatereturn = "";
2997

    
2998
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2999
				if ($rrdcreatereturn != 0) {
3000
					log_error("RRD create failed exited with $rrdcreatereturn, the
3001
							error is: $rrdcreateoutput[0]\n");
3002
				}
3003
			}
3004

    
3005
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3006
			if($g['booting']) {
3007
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
3008
			}
3009

    
3010
			$rrdupdatesh .= "\n";
3011
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
3012
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
3013
			if(! is_macaddr(get_interface_mac($realif))) {
3014
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$6 \":\" \$9}'`\n";
3015
			} else {
3016
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7 \":\" \$10}'`\n";
3017
			}
3018

    
3019
			/* PACKETS, set up the rrd file */
3020
			if (!file_exists("$rrddbpath$ifname$packets")) {
3021
				/* create rrd file if it does not exist */
3022
				log_error("Create RRD database $rrddbpath$ifname$packets");
3023
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
3024
				$rrdcreate .= "DS:in:COUNTER:$packetsvalid:0:$downstream ";
3025
				$rrdcreate .= "DS:out:COUNTER:$packetsvalid:0:$upstream ";
3026
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3027
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3028
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3029
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3030
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3031
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3032
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3033
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3034

    
3035
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3036
				if ($rrdcreatereturn != 0) {
3037
					log_error("RRD create failed exited with $rrdcreatereturn, the
3038
							error is: $rrdcreateoutput[0]\n");
3039
				}
3040
			}
3041

    
3042
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3043
			if($g['booting']) {
3044
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
3045
			}
3046

    
3047
			$rrdupdatesh .= "\n";
3048
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
3049
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
3050
			if(! is_macaddr(get_interface_mac($realif))) {
3051
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$4 \":\" \$7}'`\n";
3052
			} else {
3053
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5 \":\" \$8}'`\n";
3054
			}
3055
			/* if an alternative gateway is defined, use it */
3056
			if ($config['interfaces'][$ifname]['use_rrd_gateway'] <> "") {
3057
				$gatewayip = get_interface_gateway($ifname);
3058
				$monitorip = $config['interfaces'][$ifname]['use_rrd_gateway'];
3059
				mwexec("/sbin/route add -host {$monitorip} {$gatewayip} 2>&1");
3060
			} else {
3061
				$monitorip = get_interface_gateway($ifname);
3062
			}
3063
			$numpings = 5;
3064
			$btick = '`';
3065

    
3066
			if($monitorip <> "") {
3067
				/* QUALITY, create link quality database */
3068
				if (!file_exists("$rrddbpath$ifname$quality")) {
3069
					/* create rrd file if it does not exist */
3070
					log_error("Create RRD database $rrddbpath$ifname$quality");
3071
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
3072
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
3073
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
3074
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3075
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3076
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3077
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3078

    
3079
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3080
					if ($rrdcreatereturn != 0) {
3081
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3082
					}
3083
				}
3084

    
3085
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3086
				if($g['booting']) {
3087
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
3088
				}
3089

    
3090
				/* the ping test function. We call this on the last line */
3091
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
3092
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
3093
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
3094
				$rrdupdatesh .= "	local out_{$ifname}\n";
3095
				$rrdupdatesh .= "	out_{$ifname}=$btick ping -c $numpings -q $monitorip $btick\n";
3096
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
3097
				$rrdupdatesh .= "		packetloss_{$ifname}=$btick echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1 $btick\n";
3098
				$rrdupdatesh .= "		roundtrip_{$ifname}=$btick echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/' $btick\n";
3099
				$rrdupdatesh .= "	fi\n";
3100
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
3101
				$rrdupdatesh .= "}\n\n";
3102

    
3103
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
3104
			}
3105

    
3106
			/* WAN interface only statistics */
3107
			if ("$ifname" == "wan") {
3108

    
3109
				/* QUEUES, set up the queues databases */
3110
				if (!is_array($config['shaper']['queue'])) {
3111
					$config['shaper']['queue'] = array ();
3112
				}
3113
				$a_queues = & $config['shaper']['queue'];
3114

    
3115
				if (isset ($config['shaper']['enable'])) {
3116
					if (!file_exists("$rrddbpath$ifname$queues")) {
3117
						/* create rrd file if it does not exist */
3118
						log_error("Create RRD database $rrddbpath$ifname$queues");
3119
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
3120
						/* loop list of shaper queues */
3121
						$q = 0;
3122
						foreach ($a_queues as $queue) {
3123
							$name = $queue['name'];
3124
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream ";
3125
						}
3126

    
3127
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3128
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3129
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3130
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3131

    
3132
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3133
						if ($rrdcreatereturn != 0) {
3134
							log_error("RRD create failed exited with $rrdcreatereturn, the
3135
									error is: $rrdcreateoutput[0]\n");
3136
						}
3137
					}
3138

    
3139
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
3140
						/* create rrd file if it does not exist */
3141
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
3142
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
3143
						/* loop list of shaper queues */
3144
						$q = 0;
3145
						foreach ($a_queues as $queue) {
3146
							$name = $queue['name'];
3147
							$rrdcreate .= "DS:$name:COUNTER:$queuesdropvalid:0:$downstream ";
3148
						}
3149

    
3150
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3151
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3152
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3153
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3154

    
3155
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3156
						if ($rrdcreatereturn != 0) {
3157
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3158
						}
3159
					}
3160

    
3161
					if($g['booting']) {
3162
						$rrdqcommand = "-t ";
3163
						$rrducommand = "N";
3164
						$q = 0;
3165
						foreach ($a_queues as $queue) {
3166
							if($q == 0) {
3167
								$rrdqcommand .= "{$queue['name']}";
3168
							} else {
3169
								$rrdqcommand .= ":{$queue['name']}";
3170
							}
3171
							$q++;
3172
							$rrducommand .= ":U";
3173
						}
3174
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3175
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3176
					}
3177

    
3178
					/* awk function to gather shaper data */
3179
					/* yes, it's special */
3180
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
3181
					$rrdupdatesh .= "{ ";
3182
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3183
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3184
					$rrdupdatesh .= "q=1; ";
3185
					$rrdupdatesh .= "} ";
3186
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3187
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
3188
					$rrdupdatesh .= "q=0; ";
3189
					$rrdupdatesh .= "} ";
3190
					$rrdupdatesh .= "} END { ";
3191
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3192
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3193
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3194
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3195

    
3196
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
3197
					$rrdupdatesh .= "{ ";
3198
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3199
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3200
					$rrdupdatesh .= "q=1; ";
3201
					$rrdupdatesh .= "} ";
3202
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3203
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
3204
					$rrdupdatesh .= "q=0; ";
3205
					$rrdupdatesh .= "} ";
3206
					$rrdupdatesh .= "} END { ";
3207
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3208
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3209
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3210
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3211
				}
3212
			}
3213
		}
3214
		$i++;
3215

    
3216
		/* System only statistics */
3217
		$ifname = "system";
3218

    
3219
			/* STATES, create pf states database */
3220
			if(! file_exists("$rrddbpath$ifname$states")) {
3221
				/* create rrd file if it does not exist */
3222
				log_error("Create RRD database $rrddbpath$ifname$states");
3223
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3224
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3225
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3226
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3227
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3228
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3229
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3230
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3231
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3232
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3233
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3234
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3235
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3236
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3237
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3238
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3239
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3240
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3241

    
3242
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3243
				if($rrdcreatereturn != 0) {
3244
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3245
						error is: $rrdcreateoutput[0]\n");
3246
				}
3247
			}
3248

    
3249
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3250
			if($g['booting']) {
3251
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
3252
			}
3253

    
3254
 			/* the pf states gathering function. */
3255
 			$rrdupdatesh .= "\n";
3256
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
3257
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
3258
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3259
			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3260
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3261
			$rrdupdatesh .= "srcip=\"` cat /tmp/pfctl_ss_out | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '\\->' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
3262
			$rrdupdatesh .= "dstip=\"` cat /tmp/pfctl_ss_out | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '<\\-' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
3263
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3264

    
3265
			/* End pf states statistics */
3266

    
3267
			/* CPU, create CPU statistics database */
3268
			if(! file_exists("$rrddbpath$ifname$proc")) {
3269
				/* create rrd file if it does not exist */
3270
				log_error("Create RRD database $rrddbpath$ifname$proc");
3271
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3272
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3273
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3274
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3275
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3276
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3277
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3278
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3279
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3280
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3281
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3282
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3283
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3284
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3285
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3286
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3287
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3288
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3289

    
3290
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3291
				if($rrdcreatereturn != 0) {
3292
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3293
						error is: $rrdcreateoutput[0]\n");
3294
				}
3295
			}
3296

    
3297
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3298
			if($g['booting']) {
3299
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
3300
			}
3301

    
3302
 			/* the CPU stats gathering function. */
3303
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { ";
3304
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } ";
3305
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { ";
3306
			$rrdupdatesh .= "processes = \$1; ";
3307
			$rrdupdatesh .= "} ";
3308
			$rrdupdatesh .= "else if ( \$1 == \"CPU\" ) { ";
3309
			$rrdupdatesh .= "user = \$3; ";
3310
			$rrdupdatesh .= "nice = \$5; ";
3311
			$rrdupdatesh .= "sys = \$7; ";
3312
			$rrdupdatesh .= "interrupt = \$9; ";
3313
			$rrdupdatesh .= "} ";
3314
			$rrdupdatesh .= "} END { ";
3315
			$rrdupdatesh .= "printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes ";
3316
			$rrdupdatesh .= "}'`\n\n";
3317

    
3318
			/* End CPU statistics */
3319

    
3320
			/* SPAMD, set up the spamd rrd file */
3321
			if (isset($config['installedpackages']['spamdsettings']) &&
3322
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
3323
				/* set up the spamd rrd file */
3324
				if (!file_exists("$rrddbpath$ifname$spamd")) {
3325
						/* create rrd file if it does not exist */
3326
						log_error("Create RRD database $rrddbpath$ifname$spamd");
3327
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
3328
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
3329
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
3330
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3331
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3332
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3333
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3334
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3335
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3336
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3337
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3338
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3339
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3340
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3341
						$rrdcreate .= "RRA:MAX:0.5:720:1000";
3342

    
3343
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3344
					if ($rrdcreatereturn != 0) {
3345
						log_error("RRD create failed exited with $rrdcreatereturn, the
3346
							error is: $rrdcreateoutput[0]\n");
3347
					}
3348
				}
3349

    
3350
				$rrdupdatesh .= "\n";
3351
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3352
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3353
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3354

    
3355
			}
3356
		/* End System statistics */
3357

    
3358
		$rrdupdatesh .= "sleep 60\n";
3359
		$rrdupdatesh .= "done\n";
3360
		log_error("Creating rrd update script");
3361
		/* write the rrd update script */
3362
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3363
		$fd = fopen("$updaterrdscript", "w");
3364
		fwrite($fd, "$rrdupdatesh");
3365
		fclose($fd);
3366

    
3367
		/* kill off traffic collectors */
3368
		kill_traffic_collector();
3369

    
3370
		/* start traffic collector */
3371
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3372

    
3373
	} else {
3374
		/* kill off traffic collectors */
3375
		kill_traffic_collector();
3376
	}
3377

    
3378
	if($g['booting']) 
3379
		echo "done.\n";
3380
		
3381
}
3382

    
3383
function kill_traffic_collector() {
3384
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
3385
}
3386

    
3387
function update_filter_reload_status($text) {
3388
	global $g;
3389
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3390
	fwrite($fd, $text);
3391
	fclose($fd);
3392
}
3393

    
3394
function get_interface_gateway($interface) {
3395
	global $config, $g;
3396
	$interface = strtolower($interface);
3397
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
3398
	 *  grab the address from the configuration file.
3399
	 */
3400
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
3401
	if($tmpif <> $interface)
3402
		$interface = $tmpif;
3403
	$realif = $config['interfaces'][$interface]['if'];
3404
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
3405
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3406
		$gw = rtrim($gw);
3407
	} else {
3408
		$gw = $config['interfaces'][$interface]['gateway'];
3409
	}
3410
	/* if wan is requested, return it */
3411
	if($interface == "wan")
3412
		return str_replace("\n", "", `/usr/bin/netstat -rn | /usr/bin/awk '/default/ {print $2}'`);
3413
	/* return gateway */
3414
	return $gw;
3415
}
3416

    
3417
function is_dhcp_server_enabled() {
3418
	/* DHCP enabled on any interfaces? */
3419
	global $config, $g;
3420
	$dhcpdcfg = $config['dhcpd'];
3421
	$dhcpdenable = false;
3422
	if($config['dhcpd']) {
3423
		foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
3424
			if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3425
				$dhcpdenable = true;
3426
			if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3427
				$dhcpdenable = true;
3428
		}
3429
	}
3430
	return $dhcpdenable;
3431
}
3432

    
3433
/* return outside interfaces with a gateway */
3434
function get_interfaces_with_gateway() {
3435
	global $config;
3436
	$ints = array();
3437
	$vfaces = array(
3438
			'bridge.?*',
3439
			'ppp.?*',
3440
			'sl.?*',
3441
			'gif.?*',
3442
			'faith.?*',
3443
			'lo.?*',
3444
			'ng.?*',
3445
			'vlan.?*',
3446
			'pflog.?*',
3447
			'pfsync.?*',
3448
			'enc.?*',
3449
			'tun.?*',
3450
			'carp.?*'
3451
		);	
3452
	$ifdescrs = get_interface_list("active","physical",$vfaces);
3453

    
3454

    
3455
	/* loop interfaces, check config for outbound */
3456
	foreach ($ifdescrs as $ifdescr => $ifname) {
3457
		$friendly = $ifname['friendly'];
3458
		if ($config['interfaces'][$friendly]['ipaddr'] == "dhcp") {
3459
			$ints[] = $friendly;
3460
			continue;
3461
		}
3462
		if ($config['interfaces'][$friendly]['ipaddr'] == "pppoe") {
3463
			$ints[] = $friendly;
3464
			continue;
3465
		}
3466
		if ($config['interfaces'][$friendly]['ipaddr'] == "pptp") {
3467
			$ints[] = $friendly;
3468
			continue;
3469
		}
3470
		if ($config['interfaces'][$friendly]['gateway'] <> "") {
3471
			$ints[] = $friendly;
3472
			continue;
3473
		}
3474
	}
3475
	return $ints;
3476
}
3477

    
3478
/* return true if interface has a gateway */
3479
function interface_has_gateway($friendly) {
3480
	$friendly = strtolower($friendly);
3481
	if(in_array($friendly, get_interfaces_with_gateway())) {
3482
		return true;
3483
	} else {
3484
		/* extra check for real interface names if it falls through */
3485
		$friendly = convert_real_interface_to_friendly_interface_name($friendly);
3486
		return(in_array($friendly, get_interfaces_with_gateway()));
3487
	}
3488
}
3489

    
3490
//returns interface information
3491
function get_interface_info($ifdescr) {
3492
	global $config, $linkinfo, $netstatrninfo;
3493

    
3494
	$ifinfo = array();
3495

    
3496
	/* find out interface name */
3497
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
3498
	if ($ifdescr == "wan")
3499
		$ifinfo['if'] = get_real_wan_interface();
3500
	else
3501
		$ifinfo['if'] = $ifinfo['hwif'];
3502

    
3503
	/* run netstat to determine link info */
3504

    
3505
	unset($linkinfo);
3506
	exec("/usr/bin/netstat -I " . $ifinfo['hwif'] . " -nWb -f link", $linkinfo);
3507
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3508
	if (preg_match("/\*$/", $linkinfo[0])) {
3509
		$ifinfo['status'] = "down";
3510
	} else {
3511
		$ifinfo['status'] = "up";
3512
	}
3513

    
3514
	if (!strstr($ifinfo['if'],'tun')) {
3515
		$ifinfo['macaddr'] = $linkinfo[3];
3516
		$ifinfo['inpkts'] = $linkinfo[4];
3517
		$ifinfo['inerrs'] = $linkinfo[5];
3518
		$ifinfo['inbytes'] = $linkinfo[6];
3519
		$ifinfo['outpkts'] = $linkinfo[7];
3520
		$ifinfo['outerrs'] = $linkinfo[8];
3521
		$ifinfo['outbytes'] = $linkinfo[9];
3522
		$ifinfo['collisions'] = $linkinfo[10];
3523
	} else {
3524
		$ifinfo['inpkts'] = $linkinfo[3];
3525
		$ifinfo['inbytes'] = $linkinfo[5];
3526
		$ifinfo['outpkts'] = $linkinfo[6];
3527
		$ifinfo['outbytes'] = $linkinfo[8];
3528
	}
3529

    
3530
	/* DHCP? -> see if dhclient is up */
3531
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "dhcp")) {
3532
		/* see if dhclient is up */
3533
		if (is_dhcp_running("wan") == true)
3534
			$ifinfo['dhcplink'] = "up";
3535
		else
3536
			$ifinfo['dhcplink'] = "down";
3537
	}
3538
	/* loop through optional interfaces looking to see if they are dhcp */
3539
        for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
3540
                $ifdescrs['opt' . $j] = $config['interfaces']['opt' . $j]['descr'];
3541
                if (($ifdescr == "opt{$j}") && ($config['interfaces']['opt' . $j]['ipaddr'] == "dhcp")) {
3542
                        /* see if dhclient is up */
3543
                        if (is_dhcp_running("opt{$j}") == true)
3544
                                $ifinfo['dhcplink'] = "up";
3545
                        else
3546
                                $ifinfo['dhcplink'] = "down";
3547
                }
3548
        }
3549

    
3550
	/* PPPoE interface? -> get status from virtual interface */
3551
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pppoe")) {
3552
		unset($linkinfo);
3553
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3554
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3555
		if (preg_match("/\*$/", $linkinfo[0])) {
3556
			$ifinfo['pppoelink'] = "down";
3557
		} else {
3558
			/* get PPPoE link status for dial on demand */
3559
			$ifconfiginfo = "";
3560
			unset($ifconfiginfo);
3561
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3562

    
3563
			$ifinfo['pppoelink'] = "up";
3564

    
3565
			foreach ($ifconfiginfo as $ici) {
3566
				if (strpos($ici, 'LINK0') !== false)
3567
					$ifinfo['pppoelink'] = "down";
3568
			}
3569
		}
3570
	}
3571

    
3572
	/* PPTP interface? -> get status from virtual interface */
3573
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pptp")) {
3574
		unset($linkinfo);
3575
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3576
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3577
		if (preg_match("/\*$/", $linkinfo[0])) {
3578
			$ifinfo['pptplink'] = "down";
3579
		} else {
3580
			/* get PPTP link status for dial on demand */
3581
			unset($ifconfiginfo);
3582
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3583

    
3584
			$ifinfo['pptplink'] = "up";
3585

    
3586
			foreach ($ifconfiginfo as $ici) {
3587
				if (strpos($ici, 'LINK0') !== false)
3588
					$ifinfo['pptplink'] = "down";
3589
			}
3590
		}
3591
	}
3592

    
3593
	if ($ifinfo['status'] == "up") {
3594
		/* try to determine media with ifconfig */
3595
		unset($ifconfiginfo);
3596
		exec("/sbin/ifconfig " . $ifinfo['hwif'], $ifconfiginfo);
3597
		$matches = "";
3598
		foreach ($ifconfiginfo as $ici) {
3599

    
3600
			/* don't list media/speed for wireless cards, as it always
3601
			   displays 2 Mbps even though clients can connect at 11 Mbps */
3602
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
3603
				$ifinfo['media'] = $matches[1];
3604
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
3605
				$ifinfo['media'] = $matches[1];
3606
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
3607
				$ifinfo['media'] = $matches[1];
3608
			}
3609

    
3610
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
3611
				if ($matches[1] != "active")
3612
					$ifinfo['status'] = $matches[1];
3613
			}
3614
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
3615
				$ifinfo['channel'] = $matches[1];
3616
			}
3617
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
3618
				if ($matches[1][0] == '"')
3619
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
3620
				else
3621
					$ifinfo['ssid'] = $matches[1];
3622
			}
3623
		}
3624

    
3625
		if ($ifinfo['pppoelink'] != "down" && $ifinfo['pptplink'] != "down") {
3626
			/* try to determine IP address and netmask with ifconfig */
3627
			unset($ifconfiginfo);
3628
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3629

    
3630
			foreach ($ifconfiginfo as $ici) {
3631
				if (preg_match("/inet (\S+)/", $ici, $matches)) {
3632
					$ifinfo['ipaddr'] = $matches[1];
3633
				}
3634
				if (preg_match("/netmask (\S+)/", $ici, $matches)) {
3635
					if (preg_match("/^0x/", $matches[1]))
3636
						$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
3637
				}
3638
			}
3639

    
3640
			if ($ifdescr == "wan") {
3641
				/* run netstat to determine the default gateway */
3642
				unset($netstatrninfo);
3643
				exec("/usr/bin/netstat -rnf inet", $netstatrninfo);
3644

    
3645
				foreach ($netstatrninfo as $nsr) {
3646
					if (preg_match("/^default\s*(\S+)/", $nsr, $matches)) {
3647
						$ifinfo['gateway'] = $matches[1];
3648
					}
3649
				}
3650
			} else {
3651
				/* deterimine interface gateway */
3652
				$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3653
				$gw = get_interface_gateway($int);
3654
				if($gw)
3655
					$ifinfo['gateway'] = $gw;
3656
			}
3657
		}
3658
	}
3659

    
3660
	$bridge = "";
3661
	$int = "";
3662
	$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3663
	$bridge = link_int_to_bridge_interface($int);
3664
	if($bridge) {
3665
		$bridge_text = `/sbin/ifconfig {$bridge}`;
3666
		if(stristr($bridge_text, "blocking") <> false) {
3667
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
3668
			$ifinfo['bridgeint'] = $bridge;
3669
		} else if(stristr($bridge_text, "learning") <> false) {
3670
			$ifinfo['bridge'] = "learning";
3671
			$ifinfo['bridgeint'] = $bridge;
3672
		} else if(stristr($bridge_text, "forwarding") <> false) {
3673
			$ifinfo['bridge'] = "forwarding";
3674
			$ifinfo['bridgeint'] = $bridge;
3675
		}
3676
	}
3677

    
3678
	return $ifinfo;
3679
}
3680

    
3681

    
3682
//returns cpu speed of processor. Good for determining capabilities of machine
3683
function get_cpu_speed() {
3684
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
3685
}
3686

    
3687
/* check if the wan interface is up
3688
 * Wait for a maximum of 10 seconds
3689
 * If the interface is up before then continue
3690
 */
3691
function is_wan_interface_up($interface) {
3692
	global $g;
3693
	global $config;
3694
	$i = 0;
3695
	while($i < 10) {
3696
		if(get_interface_gateway($interface)) {
3697
			return true;
3698
		} else {
3699
			sleep(1);
3700
		}
3701
		$i++;
3702
	}
3703
	return false;
3704
}
3705

    
3706
/****f* pfsense-utils/safe_write_file
3707
 * NAME
3708
 *   safe_write_file - Write a file out atomically
3709
 * DESCRIPTION
3710
 *   safe_write_file() Writes a file out atomically by first writing to a
3711
 *   temporary file of the same name but ending with the pid of the current
3712
 *   process, them renaming the temporary file over the original.
3713
 * INPUTS
3714
 *   $filename  - string containing the filename of the file to write
3715
 *   $content   - string containing the file content to write to file
3716
 *   $force_binary      - boolean denoting whether we should force binary
3717
 *   mode writing.
3718
 * RESULT
3719
 *   boolean - true if successful, false if not
3720
 ******/
3721
function safe_write_file($file, $content, $force_binary) {
3722
        $tmp_file = $file . "." . getmypid();
3723
        $write_mode = $force_binary ? "wb" : "w";
3724

    
3725
        $fd = fopen($tmp_file, $write_mode);
3726
        if (!$fd) {
3727
                // Unable to open temporary file for writing
3728
                return false;
3729
        }
3730
        if (!fwrite($fd, $content)) {
3731
                // Unable to write to temporary file
3732
                fclose($fd);
3733
                return false;
3734
        }
3735
        fclose($fd);
3736

    
3737
        if (!rename($tmp_file, $file)) {
3738
                // Unable to move temporary file to original
3739
                unlink($tmp_file);
3740
                return false;
3741
        }
3742
        return true;
3743
}
3744

    
3745
/* Write out all the found IP addresses to a file
3746
 * so we can compare it on change */
3747
function add_hostname_to_watch($hostname) {
3748
	if(!is_dir("/var/db/dnscache")) {
3749
		mkdir("/var/db/dnscache");
3750
	}
3751
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
3752
		$domrecords = array();
3753
		$domips = array();
3754
		exec("host -t A $hostname", $domrecords, $rethost);
3755
		if($rethost == 0) {
3756
			foreach($domrecords as $domr) {
3757
				$doml = explode(" ", $domr);
3758
				$domip = $doml[3];
3759
				/* fill array with domain ip addresses */
3760
				if(is_ipaddr($domip)) {
3761
					$domips[] = $domip;
3762
				}
3763
			}
3764
		}
3765
		sort($domips);
3766
		$contents = "";
3767
		if(! empty($domips)) {
3768
			foreach($domips as $ip) {
3769
				$contents .= "$ip\n";
3770
			}
3771
		}
3772
		file_put_contents("/var/db/dnscache/$hostname", $contents);
3773
	}
3774
}
3775

    
3776
/* Compare the current hostname DNS to the DNS cache we made
3777
 * if it has changed we return the old records
3778
 * if no change we return true */
3779
function compare_hostname_to_dnscache($hostname) {
3780
	if(!is_dir("/var/db/dnscache")) {
3781
		mkdir("/var/db/dnscache");
3782
	}
3783
	$hostname = trim($hostname);
3784
	if(is_readable("/var/db/dnscache/{$hostname}")) {
3785
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
3786
	} else {
3787
		$oldcontents = "";
3788
	}
3789
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
3790
		$domrecords = array();
3791
		$domips = array();
3792
		exec("host -t A $hostname", $domrecords, $rethost);
3793
		if($rethost == 0) {
3794
			foreach($domrecords as $domr) {
3795
				$doml = explode(" ", $domr);
3796
				$domip = $doml[3];
3797
				/* fill array with domain ip addresses */
3798
				if(is_ipaddr($domip)) {
3799
					$domips[] = $domip;
3800
				}
3801
			}
3802
		}
3803
		sort($domips);
3804
		$contents = "";
3805
		if(! empty($domips)) {
3806
			foreach($domips as $ip) {
3807
				$contents .= "$ip\n";
3808
			}
3809
		}
3810
	}
3811

    
3812
	if(trim($oldcontents) != trim($contents)) {
3813
		log_error("DNSCACHE: Found old IP {$oldcontents} and new IP {$contents}");
3814
		return ($oldcontents);
3815
	} else {
3816
		return false;
3817
	}
3818
}
3819

    
3820
function is_fqdn($fqdn) {
3821
	$hostname = false;
3822
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
3823
		$hostname = true;
3824
	}
3825
	if(preg_match("/\.\./", $fqdn)) {
3826
		$hostname = false;
3827
	}
3828
	if(preg_match("/^\./i", $fqdn)) { 
3829
		$hostname = false;
3830
	}
3831
	if(preg_match("/\//i", $fqdn)) {
3832
		$hostname = false;
3833
	}
3834
	return($hostname);
3835
}
3836

    
3837

    
3838
?>
(14-14/27)