Project

General

Profile

Download (111 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
        exec("netstat -rn", $output, $ret);
1438
        foreach($output as $line) {
1439
                if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
1440
                        $fields = preg_split("/[ ]+/", $line);
1441
                        if(ip_in_subnet($ipaddress, $fields[0])) {
1442
                                return $fields[5];
1443
                        }
1444
                }
1445
        }
1446
        $ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
1447
        if(empty($ret)) {
1448
                return false;
1449
        }
1450
        return $ret;
1451
}
1452

    
1453
function filter_opt_interface_to_real($opt) {
1454
	global $config;
1455
	return $config['interfaces'][$opt]['if'];
1456
}
1457

    
1458
function filter_get_opt_interface_descr($opt) {
1459
	global $config;
1460
	return $config['interfaces'][$opt]['descr'];
1461
}
1462

    
1463
function get_friendly_interface_list_as_array() {
1464
	global $config;
1465
	$ints = array();
1466
	$ifdescrs = get_interface_list();
1467
	foreach ($ifdescrs as $ifdescr => $ifname) {
1468
		array_push($ints,$ifdescr);
1469
	}
1470
	return $ints;
1471
}
1472

    
1473
/*
1474
 * find_ip_interface($ip): return the interface where an ip is defined
1475
 */
1476
function find_ip_interface($ip) {
1477
	global $config;
1478
	$ifdescrs = array('wan', 'lan');
1479
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1480
		$ifdescrs['opt' . $j] = "opt" . $j;
1481
	}
1482
	foreach ($ifdescrs as $ifdescr => $ifname) {
1483
		$int = filter_translate_type_to_real_interface($ifname);
1484
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
1485
	if(stristr($ifconfig,$ip) <> false)
1486
		return $int;
1487
	}
1488
	return false;
1489
}
1490

    
1491
/*
1492
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
1493
 *                                                       for a friendly interface.  ie: wan
1494
 */
1495
function filter_translate_type_to_real_interface($interface) {
1496
	global $config;
1497
	if($config['interfaces'][$interface]['if'] <> "") {
1498
		return $config['interfaces'][$interface]['if'];
1499
	} else {
1500
		return $interface;
1501
	}
1502
}
1503

    
1504
/*
1505
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
1506
 */
1507
function get_carp_interface_status($carpinterface) {
1508
	/* basically cache the contents of ifconfig statement
1509
	to speed up this routine */
1510
	global $carp_query;
1511
	if($carp_query == "")
1512
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
1513
	$found_interface = 0;
1514
	foreach($carp_query as $int) {
1515
		if($found_interface == 1) {
1516
			if(stristr($int, "MASTER")) return "MASTER";
1517
			if(stristr($int, "BACKUP")) return "BACKUP";
1518
			if(stristr($int, "INIT")) return "INIT";
1519
			return false;
1520
		}
1521
		if(stristr($int, $carpinterface) == true)
1522
		$found_interface=1;
1523
	}
1524
	return;
1525
}
1526

    
1527
/*
1528
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
1529
 */
1530
function get_pfsync_interface_status($pfsyncinterface) {
1531
    $result = does_interface_exist($pfsyncinterface);
1532
    if($result <> true) return;
1533
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
1534
    return $status;
1535
}
1536

    
1537
/*
1538
 * find_carp_interface($ip): return the carp interface where an ip is defined
1539
 */
1540
function find_carp_interface($ip) {
1541
	global $find_carp_ifconfig;
1542
	if($find_carp_ifconfig == "") {
1543
		$find_carp_ifconfig = array();
1544
		$num_carp_ints = find_number_of_created_carp_interfaces();
1545
		for($x=0; $x<$num_carp_ints; $x++) {
1546
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
1547
		}
1548
	}
1549
	$carps = 0;
1550
	foreach($find_carp_ifconfig as $fci) {
1551
		if(stristr($fci, $ip . " ") == true)		
1552
			return "carp{$carps}";
1553
		$carps++;
1554
	}
1555
}
1556

    
1557
/*
1558
 * setup_filter_bridge(): toggle filtering bridge
1559
 *
1560
 * disabled 20080805 - this is of no use with if_bridge, in the sense it was
1561
 * with m0n0 (where this came from)
1562
 * --cmb
1563
function setup_filter_bridge() {
1564
	global $config, $g;
1565
	if(isset($config['bridge']['filteringbridge'])) {
1566
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
1567
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
1568
	} else {
1569
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
1570
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
1571
	}
1572
}
1573
*/
1574

    
1575
/*
1576
 * find_number_of_created_bridges(): returns the number of currently created bridges
1577
 */
1578
function find_number_of_created_bridges($flush = false) {
1579
	global $bridge_interface_count_cache;
1580
	if(!isset($bridge_interface_count_cache) or $flush)
1581
		$bridge_interface_count_cache = exec_command('/sbin/ifconfig | /usr/bin/grep "bridge[0-999]" | /usr/bin/wc -l');
1582

    
1583
	return $bridge_interface_count_cache;
1584
}
1585

    
1586
/*
1587
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
1588
 */
1589
function add_rule_to_anchor($anchor, $rule, $label) {
1590
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
1591
}
1592

    
1593
/*
1594
 * remove_text_from_file
1595
 * remove $text from file $file
1596
 */
1597
function remove_text_from_file($file, $text) {
1598
	global $fd_log;
1599
	if($fd_log)
1600
		fwrite($fd_log, "Adding needed text items:\n");
1601
	$filecontents = file_get_contents($file);
1602
	$textTMP = str_replace($text, "", $filecontents);
1603
	$text = $textTMP;
1604
	if($fd_log)
1605
		fwrite($fd_log, $text);
1606
	$fd = fopen($file, "w");
1607
	fwrite($fd, $text);
1608
	fclose($fd);
1609
}
1610

    
1611
/*
1612
 * add_text_to_file($file, $text): adds $text to $file.
1613
 * replaces the text if it already exists.
1614
 */
1615
function add_text_to_file($file, $text) {
1616
	if(file_exists($file) and is_writable($file)) {
1617
		$filecontents = split("\n", file_get_contents($file));
1618
		$fout = fopen($file, "w");
1619
		$new_file_text = "";
1620
		foreach($filecontents as $line) {
1621
			if($line)
1622
				$new_file_text .= rtrim($line) . "\n";
1623
		}
1624
		$new_file_text .= $text . "\n";
1625
		$file_text = str_replace("\n\n", "\n", $new_file_text);
1626
		fwrite($fout, $file_text);
1627
		fclose($fout);
1628
		return true;
1629
	} else {
1630
		return false;
1631
	}
1632
}
1633

    
1634
/*
1635
 *   after_sync_bump_adv_skew(): create skew values by 1S
1636
 */
1637
function after_sync_bump_adv_skew() {
1638
	global $config, $g;
1639
	$processed_skew = 1;
1640
	$a_vip = &$config['virtualip']['vip'];
1641
	foreach ($a_vip as $vipent) {
1642
		if($vipent['advskew'] <> "") {
1643
			$processed_skew = 1;
1644
			$vipent['advskew'] = $vipent['advskew']+1;
1645
		}
1646
	}
1647
	if($processed_skew == 1)
1648
		write_config("After synch increase advertising skew");
1649
}
1650

    
1651
/*
1652
 * get_filename_from_url($url): converts a url to its filename.
1653
 */
1654
function get_filename_from_url($url) {
1655
	return basename($url);
1656
}
1657

    
1658
/*
1659
 *   update_output_window: update bottom textarea dynamically.
1660
 */
1661
function update_output_window($text) {
1662
	global $pkg_interface;
1663
	$log = ereg_replace("\n", "\\n", $text);
1664
	if($pkg_interface == "console") {
1665
		/* too chatty */
1666
	} else {
1667
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1668
	}
1669
	/* ensure that contents are written out */
1670
	ob_flush();
1671
}
1672

    
1673
/*
1674
 *   get_dir: return an array of $dir
1675
 */
1676
function get_dir($dir) {
1677
	$dir_array = array();
1678
	$d = dir($dir);
1679
	while (false !== ($entry = $d->read())) {
1680
		array_push($dir_array, $entry);
1681
	}
1682
	$d->close();
1683
	return $dir_array;
1684
}
1685

    
1686
/*
1687
 *   update_output_window: update top textarea dynamically.
1688
 */
1689
function update_status($status) {
1690
	global $pkg_interface;
1691
	if($pkg_interface == "console") {
1692
		echo $status . "\n";
1693
	} else {
1694
		echo "\n<script type=\"text/javascript\">document.forms[0].status.value=\"" . $status . "\";</script>";
1695
	}
1696
	/* ensure that contents are written out */
1697
	ob_flush();
1698
}
1699

    
1700
/*
1701
 *   exec_command_and_return_text_array: execute command and return output
1702
 */
1703
function exec_command_and_return_text_array($command) {
1704
	$fd = popen($command . " 2>&1 ", "r");
1705
	while(!feof($fd)) {
1706
		$tmp .= fread($fd,49);
1707
	}
1708
	fclose($fd);
1709
	$temp_array = split("\n", $tmp);
1710
	return $temp_array;
1711
}
1712

    
1713
/*
1714
 *   exec_command_and_return_text: execute command and return output
1715
 */
1716
function exec_command_and_return_text($command) {
1717
	return exec_command($command);
1718
}
1719

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

    
1764
/*
1765
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
1766
 */
1767
function convert_friendly_interface_to_real_interface_name($interface) {
1768
	global $config;
1769
	if($config['interfaces'][$interface]['ipaddr'] == "pppoe" or $config['interfaces'][$interface]['ipaddr'] == "pptp")
1770
		return "ng0";
1771
	$lc_interface = strtolower($interface);
1772
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
1773
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
1774
	$ifdescrs = array();
1775
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1776
		$ifdescrs['opt' . $j] = "opt" . $j;
1777
	foreach ($ifdescrs as $ifdescr => $ifname) {
1778
		if(strtolower($ifname) == $lc_interface)
1779
	    return $config['interfaces'][$ifname]['if'];
1780
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
1781
			return $config['interfaces'][$ifname]['if'];
1782
   }
1783
   return $interface;
1784
}
1785

    
1786
/*
1787
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
1788
 */
1789
function convert_real_interface_to_friendly_interface_name($interface) {
1790
	global $config;
1791
	$ifdescrs = array('wan', 'lan');
1792
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1793
		$ifdescrs['opt' . $j] = "opt" . $j;
1794
	foreach ($ifdescrs as $ifdescr => $ifname) {
1795
		if($config['interfaces']['$ifname']['if'] == $interface)
1796
			return $ifname;
1797
		$int = filter_translate_type_to_real_interface($ifname);
1798
		if($ifname == $interface) return $ifname;
1799
		if($int == $interface) return $ifname;
1800
	}
1801
	return $interface;
1802
}
1803

    
1804
/*
1805
 * update_progress_bar($percent): updates the javascript driven progress bar.
1806
 */
1807
function update_progress_bar($percent) {
1808
	global $pkg_interface;
1809
	if($percent > 100) $percent = 1;
1810
	if($pkg_interface <> "console") {
1811
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1812
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1813
		echo "\n</script>";
1814
	} else {
1815
		echo " {$percent}%";
1816
	}
1817
}
1818

    
1819
/****f* pfsense-utils/WakeOnLan
1820
 * NAME
1821
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
1822
 * RESULT
1823
 *   true/false - true if the operation was successful
1824
 ******/
1825
function WakeOnLan($addr, $mac)
1826
{
1827
	$addr_byte = explode(':', $mac);
1828
	$hw_addr = '';
1829

    
1830
	for ($a=0; $a < 6; $a++)
1831
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1832

    
1833
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1834

    
1835
	for ($a = 1; $a <= 16; $a++)
1836
		$msg .= $hw_addr;
1837

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

    
1854
	return false;
1855
}
1856

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

    
1889
/*
1890
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1891
 *					 Useful for finding paths and stripping file extensions.
1892
 */
1893
function reverse_strrchr($haystack, $needle) {
1894
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1895
}
1896

    
1897
/*
1898
 *  backup_config_section($section): returns as an xml file string of
1899
 *                                   the configuration section
1900
 */
1901
function backup_config_section($section) {
1902
	global $config;
1903
	$new_section = &$config[$section];
1904
	/* generate configuration XML */
1905
	$xmlconfig = dump_xml_config($new_section, $section);
1906
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1907
	return $xmlconfig;
1908
}
1909

    
1910
/*
1911
 *  backup_vip_config_section($section): returns as an xml file string of
1912
 *                                   the configuration section
1913
 */
1914
function backup_vip_config_section() {
1915
	global $config;
1916
	$new_section = &$config['virtualip'];
1917
	foreach($new_section['vip'] as $section) {
1918
		if($section['mode'] == "proxyarp") {
1919
			unset($section);
1920
		}
1921
		if($section['advskew'] <> "") {
1922
			$section_val = intval($section['advskew']);
1923
			$section_val=$section_val+100;
1924
			if($section_val > 255)
1925
				$section_val = 255;
1926
			$section['advskew'] = $section_val;
1927
		}
1928
		$temp['vip'][] = $section;
1929
   }
1930
   return $temp;
1931
}
1932

    
1933
/*
1934
 *  restore_config_section($section, new_contents): restore a configuration section,
1935
 *                                                  and write the configuration out
1936
 *                                                  to disk/cf.
1937
 */
1938
function restore_config_section($section, $new_contents) {
1939
	global $config, $g;
1940
	conf_mount_rw();
1941
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
1942
	fwrite($fout, $new_contents);
1943
	fclose($fout);
1944
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
1945
	$config[$section] = &$section_xml;
1946
	unlink($g['tmp_path'] . "/tmpxml");
1947
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1948
	conf_mount_ro();
1949
	return;
1950
}
1951

    
1952
/*
1953
 *  merge_config_section($section, new_contents):   restore a configuration section,
1954
 *                                                  and write the configuration out
1955
 *                                                  to disk/cf.  But preserve the prior
1956
 * 													structure if needed
1957
 */
1958
function merge_config_section($section, $new_contents) {
1959
	global $config;
1960
	conf_mount_rw();
1961
	$fname = get_tmp_filename();
1962
	$fout = fopen($fname, "w");
1963
	fwrite($fout, $new_contents);
1964
	fclose($fout);
1965
	$section_xml = parse_xml_config($fname, $section);
1966
	$config[$section] = $section_xml;
1967
	unlink($fname);
1968
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1969
	conf_mount_ro();
1970
	return;
1971
}
1972

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

    
1995
";
1996

    
1997
	$errno = "";
1998
	$errstr = "";
1999
	$fp = fsockopen($server, $port, $errno, $errstr);
2000
	if (!$fp) {
2001
		return false;
2002
	}
2003

    
2004
	fputs($fp, $headers);
2005
	fputs($fp, $urlencoded);
2006

    
2007
	$ret = "";
2008
	while (!feof($fp))
2009
		$ret.= fgets($fp, 1024);
2010
	fclose($fp);
2011

    
2012
	return $ret;
2013
}
2014

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

    
2042
/*
2043
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
2044
 */
2045
if (!function_exists('php_check_syntax')){
2046
	function php_check_syntax($code_to_check, &$errormessage){
2047
		return false;
2048
		$command = "/usr/local/bin/php -l " . $code_to_check;
2049
		$output = exec_command($command);
2050
		if (stristr($output, "Errors parsing") == false) {
2051
			echo "false\n";
2052
			$errormessage = '';
2053
			return(false);
2054
		} else {
2055
			$errormessage = $output;
2056
			return(true);
2057
		}
2058
	}
2059
}
2060

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

    
2089
/*
2090
 *     get_memory()
2091
 *     returns an array listing the amount of
2092
 *     memory installed in the hardware
2093
 *     [0]real and [1]available
2094
 */
2095
function get_memory() {
2096
	if(file_exists("/var/log/dmesg.boot")) {
2097
		$mem = `cat /var/log/dmesg.boot | grep memory`;
2098
		$matches = "";
2099
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2100
			$real = $matches[1];
2101
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2102
			$avail = $matches[1];
2103
		return array($real[0],$avail[0]);
2104
	} else {
2105
		$mem = `dmesg -a`;
2106
		$matches = "";
2107
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2108
			$real = $matches[1];
2109
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2110
			$avail = $matches[1];
2111
		return array($real[0],$avail[0]);
2112
	}
2113
}
2114

    
2115
/*
2116
 *    safe_mkdir($path, $mode = 0755)
2117
 *    create directory if it doesn't already exist and isn't a file!
2118
 */
2119
function safe_mkdir($path, $mode=0755) {
2120
	global $g;
2121

    
2122
	/* cdrom is ro. */
2123
	if($g['platform'] == "cdrom")
2124
		return false;
2125

    
2126
	if (!is_file($path) && !is_dir($path))
2127
		return mkdir($path, $mode);
2128
	else
2129
		return false;
2130
}
2131

    
2132
/*
2133
 * make_dirs($path, $mode = 0755)
2134
 * create directory tree recursively (mkdir -p)
2135
 */
2136
function make_dirs($path, $mode = 0755) {
2137
	$base = '';
2138
	foreach (explode('/', $path) as $dir) {
2139
		$base .= "/$dir";
2140
		if (!is_dir($base)) {
2141
			if (!@mkdir($base, $mode))
2142
				return false;
2143
		}
2144
	}
2145
	return true;
2146
}
2147

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

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

    
2204
function get_disk_info() {
2205
	$diskout = "";
2206
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
2207
	return explode(' ', $diskout[0]);
2208
	// $size, $used, $avail, $cap
2209
}
2210

    
2211
function run_plugins($directory) {
2212
	global $config, $g;
2213
	/* process packager manager custom rules */
2214
	$files = return_dir_as_array($directory);
2215
	if($files <> "") {
2216
		foreach ($files as $file) {
2217
			if($file) {
2218
				$text = file_get_contents($directory . $file);
2219
				if($text) {
2220
					if(stristr($file, ".sh") == true) {
2221
						mwexec($directory . $file . " start");
2222
					} else {
2223
						if(!stristr($file,"CVS")) {
2224
							if($g['booting'] == true)
2225
								echo "\t{$file}... ";
2226
							require_once($directory . $file);
2227
						}
2228
					}
2229
				}
2230
			}
2231
		}
2232
	}	
2233
}
2234

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

    
2279
	echo "<script type=\"text/javascript\">";
2280
	echo "NiftyCheck();\n";
2281
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
2282
	for($x=0; $x<$tabscounter; $x++)
2283
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
2284
	echo "</script>";
2285
}
2286

    
2287

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

    
2315
/****f* pfsense-utils/generate_random_mac_address
2316
 * NAME
2317
 *   generate_random_mac - generates a random mac address
2318
 * INPUTS
2319
 *   none
2320
 * RESULT
2321
 *   $mac - a random mac address
2322
 ******/
2323
function generate_random_mac_address() {
2324
	$mac = "02";
2325
	for($x=0; $x<5; $x++)
2326
		$mac .= ":" . dechex(rand(16, 255));
2327
	return $mac;
2328
}
2329

    
2330
/****f* pfsense-utils/strncpy
2331
 * NAME
2332
 *   strncpy - copy strings
2333
 * INPUTS
2334
 *   &$dst, $src, $length
2335
 * RESULT
2336
 *   none
2337
 ******/
2338
function strncpy(&$dst, $src, $length) {
2339
	if (strlen($src) > $length) {
2340
		$dst = substr($src, 0, $length);
2341
	} else {
2342
		$dst = $src;
2343
	}
2344
}
2345

    
2346
/****f* pfsense-utils/reload_interfaces_sync
2347
 * NAME
2348
 *   reload_interfaces - reload all interfaces
2349
 * INPUTS
2350
 *   none
2351
 * RESULT
2352
 *   none
2353
 ******/
2354
function reload_interfaces_sync() {
2355
	global $config, $g, $debug;
2356

    
2357
	$shutdown_webgui_needed = false;
2358

    
2359
	touch("{$g['tmp_path']}/reloading_all");
2360

    
2361
	if($debug)
2362
		log_error("reload_interfaces_sync() is starting.");
2363

    
2364
	if(file_exists("{$g['tmp_path']}/config.cache"))
2365
		unlink("{$g['tmp_path']}/config.cache");
2366

    
2367
	/* parse config.xml again */
2368
	$config = parse_config(true);
2369

    
2370
	$wan_if = $config['interfaces']['wan']['if'];
2371
	$lan_if = $config['interfaces']['lan']['if'];
2372

    
2373
	if($debug)
2374
		log_error("Cleaning up Interfaces");
2375

    
2376
	/* build an array of interfaces to work with */
2377
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2378
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2379
		$iflist['opt' . $i] = "opt{$i}";
2380

    
2381
	foreach ($iflist as $ifent => $ifname) {
2382
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2383
		if(stristr($ifname, "lo0") == true)
2384
			continue;
2385
		/* do not process wan interface, its mandatory */
2386
		if(stristr($ifname, "$wan_if") == true)
2387
			continue;
2388
		/* do not process lan interface, its mandatory */
2389
		if(stristr($ifname, "$lan_if") == true)
2390
			continue;
2391
		if($debug)
2392
			log_error("Downing and deleting $ifname_real - $ifname");
2393
		mwexec("/sbin/ifconfig {$ifname_real} down");
2394
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2395
	}
2396

    
2397
	/* set up VLAN virtual interfaces */
2398
	if($debug)
2399
		log_error("Configuring VLANS");
2400
	interfaces_vlan_configure();
2401

    
2402
	/* set up LAN interface */
2403
	if($debug)
2404
		log_error("Configuring LAN");
2405
	interfaces_lan_configure();
2406

    
2407
	/* set up WAN interface */
2408
	if($debug)
2409
		log_error("Configuring WAN");
2410
	interfaces_wan_configure();
2411

    
2412
	/* set up Optional interfaces */
2413
	if($debug)
2414
		log_error("Configuring optional interfaces");
2415
	interfaces_optional_configure();
2416

    
2417
	/* set up static routes */
2418
	if($debug)
2419
		log_error("Configuring system Routing");
2420
	system_routing_configure();
2421

    
2422
	/* enable routing */
2423
	if($debug)
2424
		log_error("Enabling system routing");
2425
	system_routing_enable();
2426

    
2427
	/* setup captive portal if needed */
2428
	if($debug)
2429
		log_error("Configuring Captive portal");
2430
	captiveportal_configure();
2431

    
2432
	/* bring up carp interfaces */
2433
	if($debug)
2434
		log_error("Configuring CARP");
2435
	interfaces_carp_configure();
2436

    
2437
	/* bring up carp interfaces*/
2438
	if($debug)
2439
		log_error("Bringing up CARP interfaces");
2440
	interfaces_carp_bring_up_final();
2441

    
2442
	/* restart webConfigurator if needed */
2443
	if($shutdown_webgui_needed == true)
2444
		touch("/tmp/restart_webgui");
2445

    
2446
	/* start devd back up */
2447
	mwexec("/bin/rm /tmp/reload*");
2448

    
2449
	/* remove reloading_all trigger */
2450
	if($debug)
2451
		log_error("Removing {$g['tmp_path']}/reloading_all");
2452
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2453
}
2454

    
2455
/****f* pfsense-utils/reload_all
2456
 * NAME
2457
 *   reload_all - triggers a reload of all settings
2458
 *   * INPUTS
2459
 *   none
2460
 * RESULT
2461
 *   none
2462
 ******/
2463
function reload_all() {
2464
	touch("/tmp/reload_all");
2465
}
2466

    
2467
/****f* pfsense-utils/reload_interfaces
2468
 * NAME
2469
 *   reload_interfaces - triggers a reload of all interfaces
2470
 * INPUTS
2471
 *   none
2472
 * RESULT
2473
 *   none
2474
 ******/
2475
function reload_interfaces() {
2476
	touch("/tmp/reload_interfaces");
2477
}
2478

    
2479
/****f* pfsense-utils/sync_webgui_passwords
2480
 * NAME
2481
 *   sync_webgui_passwords - syncs webgui and ssh passwords
2482
 * INPUTS
2483
 *   none
2484
 * RESULT
2485
 *   none
2486
 ******/
2487
function sync_webgui_passwords() {
2488
	global $config, $g;
2489
	conf_mount_rw();
2490
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
2491
	if (!$fd) {
2492
		printf("Error: cannot open htpasswd in system_password_configure().\n");
2493
		return 1;
2494
	}
2495
	/* set admin account */
2496
	$username = $config['system']['username'];
2497

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

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

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

    
2610
function get_netgaph_interface_assignment($friendly_interface) {
2611
	global $config, $g;
2612
	/* build an array of interfaces to work with */
2613
	$iflist = array("wan" => "WAN");
2614
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2615
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2616
		$ng_interfaces_needed = 0;
2617
		$ng_interfaces_number = 0;
2618
		foreach ($iflist as $ifent => $ifname) {
2619
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2620
			$ng_interfaces_number++;
2621
		}
2622
		if($friendly_interface == $ifname)
2623
			break;
2624
	}
2625
	return $ng_interfaces_number;
2626
}
2627

    
2628
/****f* pfsense-utils/reload_all_sync
2629
 * NAME
2630
 *   reload_all - reload all settings
2631
 *   * INPUTS
2632
 *   none
2633
 * RESULT
2634
 *   none
2635
 ******/
2636
function reload_all_sync() {
2637
	global $config, $g;
2638

    
2639
	$g['booting'] = false;
2640

    
2641
	touch("{$g['tmp_path']}/reloading_all");
2642

    
2643
	$shutdown_webgui_needed = false;
2644

    
2645
	if(file_exists("{$g['tmp_path']}/config.cache"))
2646
		unlink("{$g['tmp_path']}/config.cache");
2647

    
2648
	/* parse config.xml again */
2649
	$config = parse_config(true);
2650

    
2651
	/* set up our timezone */
2652
	system_timezone_configure();
2653

    
2654
	/* set up our hostname */
2655
	system_hostname_configure();
2656

    
2657
	/* make hosts file */
2658
	system_hosts_generate();
2659

    
2660
	/* generate resolv.conf */
2661
	system_resolvconf_generate();
2662

    
2663
	/* Set up our loopback interface */
2664
	interfaces_loopback_configure();
2665

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

    
2669
	$wan_if = $config['interfaces']['wan']['if'];
2670
	$lan_if = $config['interfaces']['lan']['if'];
2671

    
2672
	/* build an array of interfaces to work with */
2673
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2674
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2675
		$iflist['opt' . $i] = "opt{$i}";
2676

    
2677
	foreach ($iflist as $ifent => $ifname) {
2678
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2679
		if(stristr($ifname, "lo0") == true)
2680
			continue;
2681
		/* do not process wan interface, its mandatory */
2682
		if($wan_if == $ifname_real)
2683
			continue;
2684
		/* do not process lan interface, its mandatory */
2685
		if($lan_if == $ifname_real)
2686
			continue;
2687
		mwexec("/sbin/ifconfig {$ifname_real} down");
2688
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2689
	}
2690

    
2691
	/* set up VLAN virtual interfaces */
2692
	interfaces_vlan_configure();
2693

    
2694
	/* set up LAN interface */
2695
	interfaces_lan_configure();
2696

    
2697
	/* set up WAN interface */
2698
	interfaces_wan_configure();
2699

    
2700
	/* set up Optional interfaces */
2701
	interfaces_optional_configure();
2702

    
2703
	/* bring up carp interfaces */
2704
	interfaces_carp_configure();
2705

    
2706
	/* set up static routes */
2707
	system_routing_configure();
2708

    
2709
	/* enable routing */
2710
	system_routing_enable();
2711

    
2712
	/* ensure passwords are sync'd */
2713
	system_password_configure();
2714

    
2715
	/* start dnsmasq service */
2716
	services_dnsmasq_configure();
2717

    
2718
	/* start dyndns service */
2719
	services_dyndns_configure();
2720

    
2721
	/* start DHCP service */
2722
	services_dhcpd_configure();
2723

    
2724
	/* configure cron service */
2725
	configure_cron();
2726

    
2727
	/* start the NTP client */
2728
	system_ntp_configure();
2729

    
2730
	/* start ftp proxy helpers if they are enabled */
2731
	system_start_ftp_helpers();
2732

    
2733
	/* start the captive portal */
2734
	captiveportal_configure();
2735

    
2736
        /* reload the filter */
2737
	filter_configure_sync();
2738

    
2739
	/* bring up carp interfaces*/
2740
	interfaces_carp_bring_up_final();
2741

    
2742
	/* sync pw database */
2743
	conf_mount_rw();
2744
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2745
	conf_mount_ro();
2746

    
2747
	/* restart sshd */
2748
	touch("/tmp/start_sshd");
2749

    
2750
	/* restart webConfigurator if needed */
2751
	if($shutdown_webgui_needed == true)
2752
		touch("/tmp/restart_webgui");
2753

    
2754
	mwexec("/bin/rm /tmp/reload*");
2755

    
2756
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2757

    
2758
}
2759

    
2760
function auto_login($status) {
2761
	$gettytab = file_get_contents("/etc/gettytab");
2762
	$getty_split = split("\n", $gettytab);
2763
	conf_mount_rw();
2764
	$fd = fopen("/etc/gettytab", "w");
2765
	foreach($getty_split as $gs) {
2766
		if(stristr($gs, ":ht:np:sp#115200") ) {
2767
			if($status == true) {
2768
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
2769
			} else {
2770
				fwrite($fd, "	:ht:np:sp#115200:\n");
2771
			}
2772
		} else {
2773
			fwrite($fd, "{$gs}\n");
2774
		}
2775
	}
2776
	fclose($fd);
2777
	conf_mount_ro();
2778
}
2779

    
2780
function setup_serial_port() {
2781
	global $g, $config;
2782
	conf_mount_rw();
2783
	/* serial console - write out /boot.config */
2784
	if(file_exists("/boot.config"))
2785
		$boot_config = file_get_contents("/boot.config");
2786
	else
2787
		$boot_config = "";
2788

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

    
2849
function print_value_list($list, $count = 10, $separator = ",") {
2850
	$list = implode($separator, array_slice($list, 0, $count));
2851
	if(count($list) < $count) {
2852
		$list .= ".";
2853
	} else {
2854
		$list .= "...";
2855
	}
2856
	return $list;
2857
}
2858

    
2859
function convert_friendly_interface_to_friendly_descr($interface) {
2860
	global $config;
2861
	/* attempt to resolve interface to friendly descr */
2862
	if($config['interfaces'][$interface]['descr'])
2863
		return $config['interfaces'][$interface]['descr'];
2864
	$tmp = convert_real_interface_to_friendly_descr($interface);
2865
	/* could not resolve, return back what was passed */
2866
	return $interface;
2867
}
2868

    
2869
function convert_real_interface_to_friendly_descr($interface) {
2870
	global $config;
2871
	if($interface == $config['interfaces']['wan']['if'])
2872
		return "wan";
2873
	if($interface == $config['interfaces']['lan']['if'])
2874
		return "lan";
2875
	/* attempt to resolve interface to friendly descr */
2876
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
2877
	if($config['interfaces'][$friendly_int]['descr'])
2878
		return $config['interfaces'][$friendly_int]['descr'];
2879
	/* could not resolve, return back what was passed */
2880
	return $interface;
2881
}
2882

    
2883
function enable_rrd_graphing() {
2884
	global $config, $g;
2885

    
2886
	if($g['booting']) 
2887
		echo "Generating RRD graphs...";
2888

    
2889
	$rrddbpath = "/var/db/rrd/";
2890
	$rrdgraphpath = "/usr/local/www/rrd";
2891

    
2892
	$traffic = "-traffic.rrd";
2893
	$packets = "-packets.rrd";
2894
	$states = "-states.rrd";
2895
	$quality = "-quality.rrd";
2896
	$queues = "-queues.rrd";
2897
	$queuesdrop = "-queuesdrop.rrd";
2898
	$spamd = "-spamd.rrd";
2899
	$proc = "-processor.rrd";
2900

    
2901
	$rrdtool = "/usr/local/bin/rrdtool";
2902
	$netstat = "/usr/bin/netstat";
2903
	$awk = "/usr/bin/awk";
2904
	$tar = "/usr/bin/tar";
2905
	$pfctl = "/sbin/pfctl";
2906
	$php = "/usr/local/bin/php";
2907
	$top = "/usr/bin/top";
2908
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2909

    
2910
	$rrdtrafficinterval = 60;
2911
	$rrdqualityinterval = 60;
2912
	$rrdqueuesinterval = 60;
2913
	$rrdqueuesdropinterval = 60;
2914
	$rrdpacketsinterval = 60;
2915
	$rrdstatesinterval = 60;
2916
	$rrdspamdinterval = 60;
2917
	$rrdlbpoolinterval = 60;
2918
	$rrdprocinterval = 60;
2919

    
2920
	$trafficvalid = $rrdtrafficinterval * 2;
2921
	$qualityvalid = $rrdqualityinterval * 2;
2922
	$queuesvalid = $rrdqueuesinterval * 2;
2923
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2924
	$packetsvalid = $rrdpacketsinterval * 2;
2925
	$statesvalid = $rrdstatesinterval*2;
2926
	$spamdvalid = $rrdspamdinterval * 2;
2927
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2928
	$procvalid = $rrdlbpoolinterval * 2;
2929

    
2930
	/* Asume GigE for now */
2931
	$downstream = 125000000;
2932
	$upstream = 125000000;
2933

    
2934
	$rrdrestore = "";
2935
	$rrdreturn = "";
2936

    
2937
	if (isset ($config['rrd']['enable'])) {
2938

    
2939
		/* create directory if needed */
2940
		if (!is_dir("$rrddbpath")) {
2941
			mkdir("$rrddbpath", 0755);
2942
		}
2943

    
2944
		if ($g['booting']) {
2945
			if ($g['platform'] != "pfSense") {
2946
				/* restore the databases, if we have one */
2947
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
2948
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2949
					if((int)$rrdrestore <> 0) {
2950
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
2951
					}
2952
				}
2953
			}
2954
		}
2955

    
2956
		/* db update script */
2957
		$rrdupdatesh = "#!/bin/sh\n";
2958
		$rrdupdatesh .= "\n";
2959
		$rrdupdatesh .= "counter=1\n";
2960
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2961
		$rrdupdatesh .= "do\n";
2962
		$rrdupdatesh .= "";
2963

    
2964
		$i = 0;
2965
		$vfaces = array (
2966
			"vlan.?*",
2967
			"enc.?*"
2968
		);
2969
		$ifdescrs = get_interface_list(true, true, $vfaces);
2970
		$ifdescrs['enc0']['friendly'] = "ipsec";
2971
		$ifdescrs['enc0']['descr'] = "IPSEC";
2972
		$ifdescrs['enc0']['up'] = true;
2973

    
2974
		foreach ($ifdescrs as $realif => $ifdescr) {
2975
			$ifname = $ifdescr['friendly'];
2976
			$state = $ifdescr['up'];
2977

    
2978
			/* skip interfaces that do not have a friendly name */
2979
			if ("$ifname" == "") {
2980
				continue;
2981
			}
2982

    
2983
			/* or are down */
2984
			if (!$state) {
2985
				continue;
2986
			}
2987

    
2988
			/* TRAFFIC, set up the rrd file */
2989
			if (!file_exists("$rrddbpath$ifname$traffic")) {
2990
				/* create rrd file if it does not exist */
2991
				log_error("Create RRD database $rrddbpath$ifname$traffic");
2992
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
2993
				$rrdcreate .= "DS:in:COUNTER:$trafficvalid:0:$downstream ";
2994
				$rrdcreate .= "DS:out:COUNTER:$trafficvalid:0:$upstream ";
2995
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2996
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2997
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2998
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2999
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3000
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3001
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3002
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3003

    
3004
				$rrdcreateoutput = array();
3005
				$rrdcreatereturn = "";
3006

    
3007
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3008
				if ($rrdcreatereturn != 0) {
3009
					log_error("RRD create failed exited with $rrdcreatereturn, the
3010
							error is: $rrdcreateoutput[0]\n");
3011
				}
3012
			}
3013

    
3014
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3015
			if($g['booting']) {
3016
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
3017
			}
3018

    
3019
			$rrdupdatesh .= "\n";
3020
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
3021
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
3022
			if(! is_macaddr(get_interface_mac($realif))) {
3023
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$6 \":\" \$9}'`\n";
3024
			} else {
3025
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7 \":\" \$10}'`\n";
3026
			}
3027

    
3028
			/* PACKETS, set up the rrd file */
3029
			if (!file_exists("$rrddbpath$ifname$packets")) {
3030
				/* create rrd file if it does not exist */
3031
				log_error("Create RRD database $rrddbpath$ifname$packets");
3032
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
3033
				$rrdcreate .= "DS:in:COUNTER:$packetsvalid:0:$downstream ";
3034
				$rrdcreate .= "DS:out:COUNTER:$packetsvalid:0:$upstream ";
3035
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3036
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3037
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3038
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3039
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3040
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3041
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3042
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3043

    
3044
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3045
				if ($rrdcreatereturn != 0) {
3046
					log_error("RRD create failed exited with $rrdcreatereturn, the
3047
							error is: $rrdcreateoutput[0]\n");
3048
				}
3049
			}
3050

    
3051
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3052
			if($g['booting']) {
3053
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
3054
			}
3055

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

    
3075
			if($monitorip <> "") {
3076
				/* QUALITY, create link quality database */
3077
				if (!file_exists("$rrddbpath$ifname$quality")) {
3078
					/* create rrd file if it does not exist */
3079
					log_error("Create RRD database $rrddbpath$ifname$quality");
3080
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
3081
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
3082
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
3083
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3084
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3085
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3086
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3087

    
3088
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3089
					if ($rrdcreatereturn != 0) {
3090
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3091
					}
3092
				}
3093

    
3094
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3095
				if($g['booting']) {
3096
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
3097
				}
3098

    
3099
				/* the ping test function. We call this on the last line */
3100
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
3101
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
3102
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
3103
				$rrdupdatesh .= "	local out_{$ifname}\n";
3104
				$rrdupdatesh .= "	out_{$ifname}=$btick ping -c $numpings -q $monitorip $btick\n";
3105
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
3106
				$rrdupdatesh .= "		packetloss_{$ifname}=$btick echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1 $btick\n";
3107
				$rrdupdatesh .= "		roundtrip_{$ifname}=$btick echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/' $btick\n";
3108
				$rrdupdatesh .= "	fi\n";
3109
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
3110
				$rrdupdatesh .= "}\n\n";
3111

    
3112
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
3113
			}
3114

    
3115
			/* WAN interface only statistics */
3116
			if ("$ifname" == "wan") {
3117

    
3118
				/* QUEUES, set up the queues databases */
3119
				if (!is_array($config['shaper']['queue'])) {
3120
					$config['shaper']['queue'] = array ();
3121
				}
3122
				$a_queues = & $config['shaper']['queue'];
3123

    
3124
				if (isset ($config['shaper']['enable'])) {
3125
					if (!file_exists("$rrddbpath$ifname$queues")) {
3126
						/* create rrd file if it does not exist */
3127
						log_error("Create RRD database $rrddbpath$ifname$queues");
3128
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
3129
						/* loop list of shaper queues */
3130
						$q = 0;
3131
						foreach ($a_queues as $queue) {
3132
							$name = $queue['name'];
3133
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream ";
3134
						}
3135

    
3136
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3137
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3138
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3139
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3140

    
3141
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3142
						if ($rrdcreatereturn != 0) {
3143
							log_error("RRD create failed exited with $rrdcreatereturn, the
3144
									error is: $rrdcreateoutput[0]\n");
3145
						}
3146
					}
3147

    
3148
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
3149
						/* create rrd file if it does not exist */
3150
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
3151
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
3152
						/* loop list of shaper queues */
3153
						$q = 0;
3154
						foreach ($a_queues as $queue) {
3155
							$name = $queue['name'];
3156
							$rrdcreate .= "DS:$name:COUNTER:$queuesdropvalid:0:$downstream ";
3157
						}
3158

    
3159
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3160
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3161
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3162
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3163

    
3164
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3165
						if ($rrdcreatereturn != 0) {
3166
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3167
						}
3168
					}
3169

    
3170
					if($g['booting']) {
3171
						$rrdqcommand = "-t ";
3172
						$rrducommand = "N";
3173
						$q = 0;
3174
						foreach ($a_queues as $queue) {
3175
							if($q == 0) {
3176
								$rrdqcommand .= "{$queue['name']}";
3177
							} else {
3178
								$rrdqcommand .= ":{$queue['name']}";
3179
							}
3180
							$q++;
3181
							$rrducommand .= ":U";
3182
						}
3183
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3184
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3185
					}
3186

    
3187
					/* awk function to gather shaper data */
3188
					/* yes, it's special */
3189
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
3190
					$rrdupdatesh .= "{ ";
3191
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3192
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3193
					$rrdupdatesh .= "q=1; ";
3194
					$rrdupdatesh .= "} ";
3195
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3196
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
3197
					$rrdupdatesh .= "q=0; ";
3198
					$rrdupdatesh .= "} ";
3199
					$rrdupdatesh .= "} END { ";
3200
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3201
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3202
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3203
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3204

    
3205
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
3206
					$rrdupdatesh .= "{ ";
3207
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3208
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3209
					$rrdupdatesh .= "q=1; ";
3210
					$rrdupdatesh .= "} ";
3211
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3212
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
3213
					$rrdupdatesh .= "q=0; ";
3214
					$rrdupdatesh .= "} ";
3215
					$rrdupdatesh .= "} END { ";
3216
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3217
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3218
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3219
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3220
				}
3221
			}
3222
		}
3223
		$i++;
3224

    
3225
		/* System only statistics */
3226
		$ifname = "system";
3227

    
3228
			/* STATES, create pf states database */
3229
			if(! file_exists("$rrddbpath$ifname$states")) {
3230
				/* create rrd file if it does not exist */
3231
				log_error("Create RRD database $rrddbpath$ifname$states");
3232
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3233
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3234
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3235
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3236
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3237
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3238
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3239
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3240
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3241
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3242
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3243
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3244
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3245
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3246
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3247
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3248
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3249
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3250

    
3251
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3252
				if($rrdcreatereturn != 0) {
3253
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3254
						error is: $rrdcreateoutput[0]\n");
3255
				}
3256
			}
3257

    
3258
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3259
			if($g['booting']) {
3260
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
3261
			}
3262

    
3263
 			/* the pf states gathering function. */
3264
 			$rrdupdatesh .= "\n";
3265
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
3266
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
3267
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3268
			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3269
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3270
			$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";
3271
			$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";
3272
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3273

    
3274
			/* End pf states statistics */
3275

    
3276
			/* CPU, create CPU statistics database */
3277
			if(! file_exists("$rrddbpath$ifname$proc")) {
3278
				/* create rrd file if it does not exist */
3279
				log_error("Create RRD database $rrddbpath$ifname$proc");
3280
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3281
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3282
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3283
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3284
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3285
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3286
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3287
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3288
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3289
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3290
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3291
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3292
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3293
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3294
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3295
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3296
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3297
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3298

    
3299
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3300
				if($rrdcreatereturn != 0) {
3301
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3302
						error is: $rrdcreateoutput[0]\n");
3303
				}
3304
			}
3305

    
3306
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3307
			if($g['booting']) {
3308
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
3309
			}
3310

    
3311
 			/* the CPU stats gathering function. */
3312
                        $rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { \\\n";
3313
                        $rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } \\\n";
3314
                        $rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { processes = \$1; } \\\n";
3315
                        $rrdupdatesh .= "else if ( \$1 == \"CPU:\" ) { user = \$2; nice = \$4; sys = \$6; interrupt = \$8; } \\\n";
3316
                        $rrdupdatesh .= "} END { printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes }'`\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)