Project

General

Profile

Download (107 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
				write_config("Installed 15 minute filter reload for Time Based Rules");
126
				configure_cron();
127
			}
128
		break;
129
		case false:
130
			if($is_installed == true) {
131
				if($x > 0) {
132
					unset($config['cron']['item'][$x]);
133
					write_config();
134
				}
135
				configure_cron();
136
			}
137
		break;
138
	}
139
}
140

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

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

    
157
		$lanif = $lancfg['if'];
158
		$wanif = get_real_wan_interface();
159

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

    
164
		$int = "";
165

    
166
		$optcfg = array();
167
		generate_optcfg_array($optcfg);
168

    
169
		$curwanip = get_current_wan_address();
170

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

    
176
		$pptpdcfg = $config['pptpd'];
177
		$pppoecfg = $config['pppoe'];
178

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

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

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

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

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

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

    
271
		for ($iif = 0; $iif < $nif; $iif++) {
272

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

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

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

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

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

    
360
			}
361

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

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

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

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

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

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

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

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

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

    
504
	tdr_get_next_ipfw_rule();
505

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

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

    
517
	return $line;
518

    
519
}
520

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

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

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

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

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

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

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

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

    
724
function tdr_month($schedule) {
725
	/*
726
	 * Calculate month
727
	 */
728
	global $debug;
729
	$todays_month = date("n");
730
	$months = split(",", $schedule);
731
	log_error("[TDR DEBUG] tdr_month($schedule)");
732
	foreach($months as $month) {
733
		if($month == $todays_month) {
734
			return true;
735
		}
736
	}
737
	return false;
738
}
739

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

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

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

    
819
/****f* pfsense-utils/log_error
820
* NAME
821
*   log_error  - Sends a string to syslog.
822
* INPUTS
823
*   $error     - string containing the syslog message.
824
* RESULT
825
*   null
826
******/
827
function log_error($error) {
828
	$page = $_SERVER['SCRIPT_NAME'];
829
	syslog(LOG_WARNING, "$page: $error");
830
	return;
831
}
832

    
833
/****f* pfsense-utils/get_interface_mac_address
834
 * NAME
835
 *   get_interface_mac_address - Return a interfaces mac address
836
 * INPUTS
837
 *   $interface	- interface to obtain mac address from
838
 * RESULT
839
 *   $mac - the mac address of the interface
840
 ******/
841
function get_interface_mac_address($interface) {
842
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
843
	if(is_macaddr($mac)) {
844
		return trim($mac);
845
	} else {
846
		return "";
847
	}
848
}
849

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

    
875
/****f* pfsense-utils/enable_hardware_offloading
876
 * NAME
877
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
878
 * INPUTS
879
 *   $interface	- string containing the physical interface to work on.
880
 * RESULT
881
 *   null
882
 * NOTES
883
 *   This function only supports the fxp driver's loadable microcode.
884
 ******/
885
function enable_hardware_offloading($interface) {
886
	global $g, $config;
887

    
888
	if(stristr($interface,"lnc"))
889
		return;
890
	if(isset($config['system']['do_not_use_nic_microcode']))
891
		return;
892

    
893
	if($g['booting']) {
894
	/* translate wan, lan, opt -> real interface if needed */
895
	$int = filter_translate_type_to_real_interface($interface);
896
	if($int <> "") $interface = $int;
897
	$int_family = preg_split("/[0-9]+/", $int);
898
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
899
	$supported_ints = array('fxp');
900
	if (in_array($int_family, $supported_ints))
901
		mwexec("/sbin/ifconfig {$interface} link0");
902

    
903
	if($config['system']['disablechecksumoffloading'])
904
		return;
905

    
906
	if(stristr($options, "txcsum") == true)
907
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
908
	if(stristr($options, "rxcsum") == true)
909
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
910
	if(stristr($options, "polling") == true)
911
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
912
	} else {
913
		mwexec("sysctl kern.polling.enable=0");
914
	}
915
	return;
916
}
917

    
918
/****f* pfsense-utils/is_alias_inuse
919
 * NAME
920
 *   checks to see if an alias is currently in use by a rule
921
 * INPUTS
922
 *
923
 * RESULT
924
 *   true or false
925
 * NOTES
926
 *
927
 ******/
928
function is_alias_inuse($alias) {
929
	global $g, $config;
930

    
931
	if($alias == "") return false;
932
	/* loop through firewall rules looking for alias in use */
933
	if(is_array($config['filter']['rule']))
934
		foreach($config['filter']['rule'] as $rule) {
935
			if($rule['source']['address'])
936
				if($rule['source']['address'] == $alias)
937
					return true;
938
			if($rule['destination']['address'])
939
				if($rule['destination']['address'] == $alias)
940
					return true;
941
		}
942
	/* loop through nat rules looking for alias in use */
943
	if(is_array($config['nat']['rule']))
944
		foreach($config['nat']['rule'] as $rule) {
945
			if($rule['target'] == $alias)
946
				return true;
947
			if($rule['external-address'] == $alias)
948
				return true;
949
		}
950
	return false;
951
}
952

    
953
/****f* pfsense-utils/is_schedule_inuse
954
 * NAME
955
 *   checks to see if a schedule is currently in use by a rule
956
 * INPUTS
957
 *
958
 * RESULT
959
 *   true or false
960
 * NOTES
961
 *
962
 ******/
963
function is_schedule_inuse($schedule) {
964
	global $g, $config;
965

    
966
	if($schedule == "") return false;
967
	/* loop through firewall rules looking for schedule in use */
968
	if(is_array($config['filter']['rule']))
969
		foreach($config['filter']['rule'] as $rule) {
970
			if($rule['sched'] == $schedule)
971
				return true;
972
		}
973
	return false;
974
}
975

    
976
/****f* pfsense-utils/setup_polling_defaults
977
 * NAME
978
 *   sets up sysctls for pollingS
979
 * INPUTS
980
 *
981
 * RESULT
982
 *   null
983
 * NOTES
984
 *
985
 ******/
986
function setup_polling_defaults() {
987
	global $g, $config;
988
	if($config['system']['polling_each_burst'])
989
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
990
	if($config['system']['polling_burst_max'])
991
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
992
	if($config['system']['polling_user_frac'])
993
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
994
}
995

    
996
/****f* pfsense-utils/setup_polling
997
 * NAME
998
 *   sets up polling
999
 * INPUTS
1000
 *
1001
 * RESULT
1002
 *   null
1003
 * NOTES
1004
 *
1005
 ******/
1006
function setup_polling() {
1007
	global $g, $config;
1008

    
1009
	setup_polling_defaults();
1010

    
1011
	if(isset($config['system']['polling']))
1012
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
1013
	else
1014
		$supported_ints = array();
1015

    
1016
	/* build an array of interfaces to work with */
1017
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1018
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1019
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1020

    
1021
	foreach ($iflist as $ifent => $ifname) {
1022
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
1023
		$supported = false;
1024
		foreach($supported_ints as $supported) {
1025
			if(stristr($real_interface, $supported)) {
1026
				$supported = true;
1027
			}
1028
		}
1029
		if ($supported == true) {
1030
			mwexec("/sbin/ifconfig {$real_interface} polling");
1031
		} else {
1032
			mwexec("/sbin/ifconfig {$real_interface} -polling");
1033
		}
1034
	}
1035
}
1036

    
1037
/****f* pfsense-utils/setup_microcode
1038
 * NAME
1039
 *   enumerates all interfaces and calls enable_hardware_offloading which
1040
 *   enables a NIC's supported hardware features.
1041
 * INPUTS
1042
 *
1043
 * RESULT
1044
 *   null
1045
 * NOTES
1046
 *   This function only supports the fxp driver's loadable microcode.
1047
 ******/
1048
function setup_microcode() {
1049
	global $config;
1050

    
1051
	$ifdescrs = array('wan', 'lan');
1052
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1053
		$ifdescrs['opt' . $j] = "opt" . $j;
1054
	}
1055
	foreach($ifdescrs as $if)
1056
		enable_hardware_offloading($if);
1057
}
1058

    
1059
/****f* pfsense-utils/return_filename_as_array
1060
 * NAME
1061
 *   return_filename_as_array - Return a file's contents as an array.
1062
 * INPUTS
1063
 *   $filename	- string containing the path to the desired file.
1064
 *   $strip	- array of characters to strip - default is '#'.
1065
 * RESULT
1066
 *   $file	- array containing the file's contents.
1067
 * NOTES
1068
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
1069
 ******/
1070
function return_filename_as_array($filename, $strip = array('#')) {
1071
	if(file_exists($filename)) $file = file($filename);
1072
	if(is_array($file)) {
1073
		foreach($file as $line) $line = trim($line);
1074
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
1075
	}
1076
	return $file;
1077
}
1078

    
1079
/****f* pfsense-utils/file_put_contents
1080
 * NAME
1081
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
1082
 * RESULT
1083
 *   none
1084
 ******/
1085
if(!function_exists("file_put_contents")) {
1086
	function file_put_contents($filename, $data) {
1087
		$fd = fopen($filename,"w");
1088
		fwrite($fd, $data);
1089
		fclose($fd);
1090
	}
1091
}
1092

    
1093
/****f* pfsense-utils/get_carp_status
1094
 * NAME
1095
 *   get_carp_status - Return whether CARP is enabled or disabled.
1096
 * RESULT
1097
 *   boolean	- true if CARP is enabled, false if otherwise.
1098
 ******/
1099
function get_carp_status() {
1100
    /* grab the current status of carp */
1101
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
1102
    if(intval($status) == "0") return false;
1103
    return true;
1104
}
1105

    
1106
/****f* pfsense-utils/is_carp_defined
1107
 * NAME
1108
 *   is_carp_defined - Return whether CARP is detected in the kernel.
1109
 * RESULT
1110
 *   boolean	- true if CARP is detected, false otherwise.
1111
 ******/
1112
function is_carp_defined() {
1113
	/* is carp compiled into the kernel and userland? */
1114
	$command = "/sbin/sysctl -a | grep carp";
1115
	$fd = popen($command . " 2>&1 ", "r");
1116
	if(!$fd) {
1117
		log_error("Warning, could not execute command {$command}");
1118
		return 0;
1119
	}
1120
	while(!feof($fd)) {
1121
		$tmp .= fread($fd,49);
1122
	}
1123
	fclose($fd);
1124

    
1125
	if($tmp == "")
1126
		return false;
1127
	else
1128
		return true;
1129
}
1130

    
1131
/****f* pfsense-utils/get_interface_mtu
1132
 * NAME
1133
 *   get_interface_mtu - Return the mtu of an interface
1134
 * RESULT
1135
 *   $tmp	- Returns the mtu of an interface
1136
 ******/
1137
function get_interface_mtu($interface) {
1138
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f4`;
1139
	return $mtu;
1140
}
1141

    
1142
/****f* pfsense-utils/is_interface_wireless
1143
 * NAME
1144
 *   is_interface_wireless - Returns if an interface is wireless
1145
 * RESULT
1146
 *   $tmp	- Returns if an interface is wireless
1147
 ******/
1148
function is_interface_wireless($interface) {
1149
	global $config, $g;
1150
	$interface = convert_real_interface_to_friendly_interface_name($interface);
1151
	if(isset($config['interfaces'][$interface]['wireless']))
1152
		return true;
1153
	else
1154
		return false;
1155
}
1156

    
1157
/****f* pfsense-utils/find_number_of_created_carp_interfaces
1158
 * NAME
1159
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
1160
 * RESULT
1161
 *   $tmp	- Number of currently created CARP interfaces.
1162
 ******/
1163
function find_number_of_created_carp_interfaces($flush = false) {
1164
	global $carp_interface_count_cache;
1165

    
1166
	if (!isset($carp_interface_count_cache) or $flush) {
1167
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
1168
		$fd = popen($command . " 2>&1 ", "r");
1169
		if(!$fd) {
1170
			log_error("Warning, could not execute command {$command}");
1171
			return 0;
1172
		}
1173
		while(!feof($fd)) {
1174
			$tmp .= fread($fd,49);
1175
		}
1176
		fclose($fd);
1177
		$carp_interface_count_cache = intval($tmp);
1178
	}
1179
	return $carp_interface_count_cache;
1180
}
1181

    
1182
/****f* pfsense-utils/link_int_to_bridge_interface
1183
 * NAME
1184
 *   link_int_to_bridge_interface - Finds out a bridge group for an interface
1185
 * INPUTS
1186
 *   $ip
1187
 * RESULT
1188
 *   bridge[0-99]
1189
 ******/
1190
function link_int_to_bridge_interface($int) {
1191
	global $config, $g;
1192
	$real_int = convert_friendly_interface_to_real_interface_name($int);
1193
	$num_bridges = find_number_of_created_bridges();
1194
	for($x=0; $x<$num_bridges; $x++) {
1195
		$matches = "";
1196
		$bridge_info = `/sbin/ifconfig bridge{$x}`;
1197
		if(stristr($bridge_info, "member: {$real_int}")) {
1198
			return "bridge{$x}";
1199
		}
1200
	}
1201
}
1202

    
1203
function link_carp_interface_to_parent($interface) {
1204
	global $config;
1205
	if($interface == "") return;
1206

    
1207
	$ifdescrs = array('wan', 'lan');
1208
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1209
		$ifdescrs['opt' . $j] = "opt" . $j;
1210

    
1211
	$carp_ints = "";
1212
	$num_carp_ints = find_number_of_created_carp_interfaces();
1213
	foreach ($ifdescrs as $ifdescr => $ifname) {
1214
		$carp_int = $interface;
1215
		$carp_ip = find_interface_ip($interface);
1216
		$carp_subnet = find_virtual_ip_netmask($carp_ip);
1217
		$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1218
		if(ip_in_subnet($starting_ip, "{$carp_ip}/{$carp_subnet}"))
1219
			if(!stristr($carp_ints, $carp_int))
1220
				return $ifname;
1221
	}
1222
	return $carp_ints;
1223
}
1224

    
1225
/****f* pfsense-utils/link_ip_to_carp_interface
1226
 * NAME
1227
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
1228
 * INPUTS
1229
 *   $ip
1230
 * RESULT
1231
 *   $carp_ints
1232
 ******/
1233
function link_ip_to_carp_interface($ip) {
1234
	global $config;
1235
	if($ip == "") return;
1236

    
1237
	$ifdescrs = array('wan', 'lan');
1238
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1239
		$ifdescrs['opt' . $j] = "opt" . $j;
1240

    
1241
	$ft = split("\.", $ip);
1242
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
1243

    
1244
	$carp_ints = "";
1245
	$num_carp_ints = find_number_of_created_carp_interfaces();
1246
	foreach ($ifdescrs as $ifdescr => $ifname) {
1247
		for($x=0; $x<$num_carp_ints; $x++) {
1248
			$carp_int = "carp{$x}";
1249
			$carp_ip = find_interface_ip($carp_int);
1250
			$carp_subnet = find_virtual_ip_netmask($carp_ip);
1251
			$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1252
			if(ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
1253
				if(!stristr($carp_ints, $carp_int))
1254
					$carp_ints .= " " . $carp_int;
1255
		}
1256
	}
1257
	return $carp_ints;
1258
}
1259

    
1260
/****f* pfsense-utils/find_virtual_ip_netmask
1261
 * NAME
1262
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
1263
 * INPUTS
1264
 *   $ip - ip address to locate subnet mask of
1265
 * RESULT
1266
 *   String containing the command's result.
1267
 * NOTES
1268
 *   This function returns the command's stdout and stderr.
1269
 ******/
1270
function find_virtual_ip_netmask($ip) {
1271
        global $config;
1272
        foreach($config['virtualip']['vip'] as $vip) {
1273
                if($ip == $vip['subnet'])
1274
                        return $vip['subnet_bits'];
1275
        }
1276
}
1277

    
1278
/****f* pfsense-utils/exec_command
1279
 * NAME
1280
 *   exec_command - Execute a command and return a string of the result.
1281
 * INPUTS
1282
 *   $command	- String of the command to be executed.
1283
 * RESULT
1284
 *   String containing the command's result.
1285
 * NOTES
1286
 *   This function returns the command's stdout and stderr.
1287
 ******/
1288
function exec_command($command) {
1289
	$output = array();
1290
	exec($command . ' 2>&1 ', $output);
1291
	return(implode("\n", $output));
1292
}
1293

    
1294
/****f* interfaces/is_jumbo_capable
1295
 * NAME
1296
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
1297
 * INPUTS
1298
 *   $int             - string containing interface name
1299
 * RESULT
1300
 *   boolean          - true or false
1301
 ******/
1302
function is_jumbo_capable($int) {
1303
	/* Per:
1304
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
1305
	 * Only the following drivers support large frames
1306
         *
1307
	 * 'de' chipset purposely left out of this list
1308
	 * requires defining BIG_PACKET in the
1309
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
1310
	 * kernel or module.  The hack works only for the 21041,
1311
	 * 21140, and 21140A chips.
1312
	 */
1313
	global $g;
1314

    
1315
	$capable = $g['vlan_long_frame'];
1316

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

    
1319
	if (in_array($int_family[0], $capable))
1320
		return true;
1321
	else
1322
		return false;
1323
}
1324

    
1325
/*
1326
 * Return the interface array
1327
 */
1328
function get_interface_arr($flush = false) {
1329
	global $interface_arr_cache;
1330

    
1331
	/* If the cache doesn't exist, build it */
1332
	if (!isset($interface_arr_cache) or $flush)
1333
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
1334

    
1335
	return $interface_arr_cache;
1336
}
1337

    
1338
/*
1339
 * does_interface_exist($interface): return true or false if a interface is
1340
 * detected.
1341
 */
1342
function does_interface_exist($interface) {
1343
        $ints = get_interface_arr();
1344

    
1345
	if(stristr($ints, $interface) !== false)
1346
		return true;
1347
	else
1348
		return false;
1349
}
1350

    
1351
/*
1352
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
1353
 */
1354
function convert_ip_to_network_format($ip, $subnet) {
1355
	$ipsplit = split('[.]', $ip);
1356
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
1357
	return $string;
1358
}
1359

    
1360
/*
1361
 * find_interface_ip($interface): return the interface ip (first found)
1362
 */
1363
function find_interface_ip($interface, $flush = false) {
1364
	global $interface_ip_arr_cache;
1365
	$interface = str_replace("\n", "", $interface);
1366
	if(does_interface_exist($interface) == false) return;
1367
	/* Setup IP cache */
1368
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
1369
		$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");
1370
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
1371
	}
1372

    
1373
	return $interface_ip_arr_cache[$interface];
1374
}
1375

    
1376
function guess_interface_from_ip($ipaddress) {
1377
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2; };'");
1378
	return $ret;
1379
}
1380

    
1381
function filter_opt_interface_to_real($opt) {
1382
	global $config;
1383
	return $config['interfaces'][$opt]['if'];
1384
}
1385

    
1386
function filter_get_opt_interface_descr($opt) {
1387
	global $config;
1388
	return $config['interfaces'][$opt]['descr'];
1389
}
1390

    
1391
function get_friendly_interface_list_as_array() {
1392
	global $config;
1393
	$ints = array();
1394
	$ifdescrs = get_interface_list();
1395
	foreach ($ifdescrs as $ifdescr => $ifname) {
1396
		array_push($ints,$ifdescr);
1397
	}
1398
	return $ints;
1399
}
1400

    
1401
/*
1402
 * find_ip_interface($ip): return the interface where an ip is defined
1403
 */
1404
function find_ip_interface($ip) {
1405
	global $config;
1406
	$ifdescrs = array('wan', 'lan');
1407
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1408
		$ifdescrs['opt' . $j] = "opt" . $j;
1409
	}
1410
	foreach ($ifdescrs as $ifdescr => $ifname) {
1411
		$int = filter_translate_type_to_real_interface($ifname);
1412
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
1413
	if(stristr($ifconfig,$ip) <> false)
1414
		return $int;
1415
	}
1416
	return false;
1417
}
1418

    
1419
/*
1420
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
1421
 *                                                       for a friendly interface.  ie: wan
1422
 */
1423
function filter_translate_type_to_real_interface($interface) {
1424
	global $config;
1425
	if($config['interfaces'][$interface]['if'] <> "") {
1426
		return $config['interfaces'][$interface]['if'];
1427
	} else {
1428
		return $interface;
1429
	}
1430
}
1431

    
1432
/*
1433
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
1434
 */
1435
function get_carp_interface_status($carpinterface) {
1436
	/* basically cache the contents of ifconfig statement
1437
	to speed up this routine */
1438
	global $carp_query;
1439
	if($carp_query == "")
1440
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
1441
	$found_interface = 0;
1442
	foreach($carp_query as $int) {
1443
		if($found_interface == 1) {
1444
			if(stristr($int, "MASTER")) return "MASTER";
1445
			if(stristr($int, "BACKUP")) return "BACKUP";
1446
			if(stristr($int, "INIT")) return "INIT";
1447
			return false;
1448
		}
1449
		if(stristr($int, $carpinterface) == true)
1450
		$found_interface=1;
1451
	}
1452
	return;
1453
}
1454

    
1455
/*
1456
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
1457
 */
1458
function get_pfsync_interface_status($pfsyncinterface) {
1459
    $result = does_interface_exist($pfsyncinterface);
1460
    if($result <> true) return;
1461
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
1462
    return $status;
1463
}
1464

    
1465
/*
1466
 * find_carp_interface($ip): return the carp interface where an ip is defined
1467
 */
1468
function find_carp_interface($ip) {
1469
	global $find_carp_ifconfig;
1470
	if($find_carp_ifconfig == "") {
1471
		$find_carp_ifconfig = array();
1472
		$num_carp_ints = find_number_of_created_carp_interfaces();
1473
		for($x=0; $x<$num_carp_ints; $x++) {
1474
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
1475
		}
1476
	}
1477
	$carps = 0;
1478
	foreach($find_carp_ifconfig as $fci) {
1479
		if(stristr($fci, $ip) == true)
1480
			return "carp{$carps}";
1481
		$carps++;
1482
	}
1483
}
1484

    
1485
/*
1486
 * setup_filter_bridge(): toggle filtering bridge
1487
 */
1488
function setup_filter_bridge() {
1489
	global $config, $g;
1490
	if(isset($config['bridge']['filteringbridge'])) {
1491
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
1492
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
1493
	} else {
1494
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
1495
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
1496
	}
1497
}
1498

    
1499
/*
1500
 * find_number_of_created_bridges(): returns the number of currently created bridges
1501
 */
1502
function find_number_of_created_bridges($flush = false) {
1503
	global $bridge_interface_count_cache;
1504
	if(!isset($bridge_interface_count_cache) or $flush)
1505
		$bridge_interface_count_cache = exec_command('/sbin/ifconfig | /usr/bin/grep "bridge[0-999]" | /usr/bin/wc -l');
1506

    
1507
	return $bridge_interface_count_cache;
1508
}
1509

    
1510
/*
1511
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
1512
 */
1513
function add_rule_to_anchor($anchor, $rule, $label) {
1514
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
1515
}
1516

    
1517
/*
1518
 * remove_text_from_file
1519
 * remove $text from file $file
1520
 */
1521
function remove_text_from_file($file, $text) {
1522
	global $fd_log;
1523
	if($fd_log)
1524
		fwrite($fd_log, "Adding needed text items:\n");
1525
	$filecontents = file_get_contents($file);
1526
	$textTMP = str_replace($text, "", $filecontents);
1527
	$text = $textTMP;
1528
	if($fd_log)
1529
		fwrite($fd_log, $text);
1530
	$fd = fopen($file, "w");
1531
	fwrite($fd, $text);
1532
	fclose($fd);
1533
}
1534

    
1535
/*
1536
 * add_text_to_file($file, $text): adds $text to $file.
1537
 * replaces the text if it already exists.
1538
 */
1539
function add_text_to_file($file, $text, $replace = false) {
1540
	if(file_exists($file) and is_writable($file)) {
1541
		$filecontents = file($file);
1542
		$fout = fopen($file, "w");
1543

    
1544
		$filecontents = array_map('rtrim', $filecontents);
1545
		array_push($filecontents, $text);
1546
		if ($replace)
1547
			$filecontents = array_unique($filecontents);
1548

    
1549
		$file_text = implode("\n", $filecontents);
1550

    
1551
		fwrite($fout, $file_text);
1552
		fclose($fout);
1553
		return true;
1554
	} else {
1555
		return false;
1556
	}
1557
}
1558

    
1559
/*
1560
 *   after_sync_bump_adv_skew(): create skew values by 1S
1561
 */
1562
function after_sync_bump_adv_skew() {
1563
	global $config, $g;
1564
	$processed_skew = 1;
1565
	$a_vip = &$config['virtualip']['vip'];
1566
	foreach ($a_vip as $vipent) {
1567
		if($vipent['advskew'] <> "") {
1568
			$processed_skew = 1;
1569
			$vipent['advskew'] = $vipent['advskew']+1;
1570
		}
1571
	}
1572
	if($processed_skew == 1)
1573
		write_config("After synch increase advertising skew");
1574
}
1575

    
1576
/*
1577
 * get_filename_from_url($url): converts a url to its filename.
1578
 */
1579
function get_filename_from_url($url) {
1580
	return basename($url);
1581
}
1582

    
1583
/*
1584
 *   update_output_window: update bottom textarea dynamically.
1585
 */
1586
function update_output_window($text) {
1587
	global $pkg_interface;
1588
	$log = ereg_replace("\n", "\\n", $text);
1589
	if($pkg_interface == "console") {
1590
		/* too chatty */
1591
	} else {
1592
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1593
	}
1594
	/* ensure that contents are written out */
1595
	ob_flush();
1596
}
1597

    
1598
/*
1599
 *   get_dir: return an array of $dir
1600
 */
1601
function get_dir($dir) {
1602
	$dir_array = array();
1603
	$d = dir($dir);
1604
	while (false !== ($entry = $d->read())) {
1605
		array_push($dir_array, $entry);
1606
	}
1607
	$d->close();
1608
	return $dir_array;
1609
}
1610

    
1611
/*
1612
 *   update_output_window: update top textarea dynamically.
1613
 */
1614
function update_status($status) {
1615
	global $pkg_interface;
1616
	if($pkg_interface == "console") {
1617
		echo $status . "\n";
1618
	} else {
1619
		echo "\n<script type=\"text/javascript\">document.forms[0].status.value=\"" . $status . "\";</script>";
1620
	}
1621
	/* ensure that contents are written out */
1622
	ob_flush();
1623
}
1624

    
1625
/*
1626
 *   exec_command_and_return_text_array: execute command and return output
1627
 */
1628
function exec_command_and_return_text_array($command) {
1629
	$fd = popen($command . " 2>&1 ", "r");
1630
	while(!feof($fd)) {
1631
		$tmp .= fread($fd,49);
1632
	}
1633
	fclose($fd);
1634
	$temp_array = split("\n", $tmp);
1635
	return $temp_array;
1636
}
1637

    
1638
/*
1639
 *   exec_command_and_return_text: execute command and return output
1640
 */
1641
function exec_command_and_return_text($command) {
1642
	return exec_command($command);
1643
}
1644

    
1645
/*
1646
 *   exec_command_and_return_text: execute command and update output window dynamically
1647
 */
1648
function execute_command_return_output($command) {
1649
	global $fd_log, $pkg_interface;
1650
	$fd = popen($command . " 2>&1 ", "r");
1651
	if($pkg_interface <> "console") {
1652
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1653
	}
1654
	$counter = 0;
1655
	$counter2 = 0;
1656
	while(!feof($fd)) {
1657
		$tmp = fread($fd, 50);
1658
		$tmp1 = ereg_replace("\n","\\n", $tmp);
1659
		$text = ereg_replace("\"","'", $tmp1);
1660
		$lasttext = "";
1661
		if($lasttext == "..") {
1662
			$text = "";
1663
			$lasttext = "";
1664
			$counter=$counter-2;
1665
		} else {
1666
			$lasttext .= $text;
1667
		}
1668
		if($counter > 51) {
1669
			$counter = 0;
1670
			$extrabreak = "\\n";
1671
		} else {
1672
	    $extrabreak = "";
1673
	    $counter++;
1674
		}
1675
		if($counter2 > 600) {
1676
			if($pkg_interface <> "console") {
1677
				echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1678
			}
1679
			$counter2 = 0;
1680
		} else
1681
			$counter2++;
1682
		if($pkg_interface <> "console") {
1683
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
1684
		}
1685
	}
1686
	fclose($fd);
1687
}
1688

    
1689
/*
1690
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
1691
 */
1692
function convert_friendly_interface_to_real_interface_name($interface) {
1693
	global $config;
1694
	$lc_interface = strtolower($interface);
1695
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
1696
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
1697
	$ifdescrs = array();
1698
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1699
		$ifdescrs['opt' . $j] = "opt" . $j;
1700
	foreach ($ifdescrs as $ifdescr => $ifname) {
1701
		if(strtolower($ifname) == $lc_interface)
1702
	    return $config['interfaces'][$ifname]['if'];
1703
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
1704
			return $config['interfaces'][$ifname]['if'];
1705
   }
1706
   return $interface;
1707
}
1708

    
1709
/*
1710
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
1711
 */
1712
function convert_real_interface_to_friendly_interface_name($interface) {
1713
	global $config;
1714
	$ifdescrs = array('wan', 'lan');
1715
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1716
		$ifdescrs['opt' . $j] = "opt" . $j;
1717
	foreach ($ifdescrs as $ifdescr => $ifname) {
1718
		if($config['interfaces']['$ifname']['if'] == $interface)
1719
			return $ifname;
1720
		$int = filter_translate_type_to_real_interface($ifname);
1721
		if($ifname == $interface) return $ifname;
1722
		if($int == $interface) return $ifname;
1723
	}
1724
	return $interface;
1725
}
1726

    
1727
/*
1728
 * update_progress_bar($percent): updates the javascript driven progress bar.
1729
 */
1730
function update_progress_bar($percent) {
1731
	global $pkg_interface;
1732
	if($percent > 100) $percent = 1;
1733
	if($pkg_interface <> "console") {
1734
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1735
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1736
		echo "\n</script>";
1737
	} else {
1738
		echo " {$percent}%";
1739
	}
1740
}
1741

    
1742
/****f* pfsense-utils/WakeOnLan
1743
 * NAME
1744
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
1745
 * RESULT
1746
 *   true/false - true if the operation was successful
1747
 ******/
1748
function WakeOnLan($addr, $mac)
1749
{
1750
	$addr_byte = explode(':', $mac);
1751
	$hw_addr = '';
1752

    
1753
	for ($a=0; $a < 6; $a++)
1754
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1755

    
1756
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1757

    
1758
	for ($a = 1; $a <= 16; $a++)
1759
		$msg .= $hw_addr;
1760

    
1761
	// send it to the broadcast address using UDP
1762
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1763
	if ($s == false) {
1764
		log_error("Error creating socket!");
1765
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
1766
	} else {
1767
		// setting a broadcast option to socket:
1768
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1769
		if($opt_ret < 0)
1770
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1771
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1772
		socket_close($s);
1773
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1774
		return true;
1775
	}
1776

    
1777
	return false;
1778
}
1779

    
1780
/*
1781
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
1782
 *                             is queuename|qlength|measured_packets
1783
 *                             NOTE: this command takes 5 seconds to run
1784
 */
1785
function gather_altq_queue_stats($dont_return_root_queues) {
1786
	mwexec("/usr/bin/killall -9 pfctl");
1787
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
1788
	$stats_array = split("\n", $stats);
1789
	$queue_stats = array();
1790
	foreach ($stats_array as $stats_line) {
1791
		$match_array = "";
1792
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
1793
			$queue_name = $match_array[1][0];
1794
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
1795
			$speed = $match_array[1][0];
1796
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
1797
			$borrows = $match_array[1][0];
1798
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
1799
			$suspends = $match_array[1][0];
1800
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
1801
			$drops = $match_array[1][0];
1802
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
1803
			$measured = $match_array[1][0];
1804
			if($dont_return_root_queues == true)
1805
				if(stristr($queue_name,"root_") == false)
1806
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
1807
		}
1808
	}
1809
	return $queue_stats;
1810
}
1811

    
1812
/*
1813
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1814
 *					 Useful for finding paths and stripping file extensions.
1815
 */
1816
function reverse_strrchr($haystack, $needle) {
1817
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1818
}
1819

    
1820
/*
1821
 *  backup_config_section($section): returns as an xml file string of
1822
 *                                   the configuration section
1823
 */
1824
function backup_config_section($section) {
1825
	global $config;
1826
	$new_section = &$config[$section];
1827
	/* generate configuration XML */
1828
	$xmlconfig = dump_xml_config($new_section, $section);
1829
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1830
	return $xmlconfig;
1831
}
1832

    
1833
/*
1834
 *  backup_vip_config_section($section): returns as an xml file string of
1835
 *                                   the configuration section
1836
 */
1837
function backup_vip_config_section() {
1838
	global $config;
1839
	$new_section = &$config['virtualip'];
1840
	foreach($new_section['vip'] as $section) {
1841
		if($section['mode'] == "proxyarp") {
1842
			unset($section);
1843
		}
1844
		if($section['advskew'] <> "") {
1845
			$section_val = intval($section['advskew']);
1846
			$section_val=$section_val+100;
1847
			if($section_val > 255)
1848
				$section_val = 255;
1849
			$section['advskew'] = $section_val;
1850
		}
1851
		$temp['vip'][] = $section;
1852
   }
1853
   return $temp;
1854
}
1855

    
1856
/*
1857
 *  restore_config_section($section, new_contents): restore a configuration section,
1858
 *                                                  and write the configuration out
1859
 *                                                  to disk/cf.
1860
 */
1861
function restore_config_section($section, $new_contents) {
1862
	global $config, $g;
1863
	conf_mount_rw();
1864
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
1865
	fwrite($fout, $new_contents);
1866
	fclose($fout);
1867
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
1868
	$config[$section] = &$section_xml;
1869
	unlink($g['tmp_path'] . "/tmpxml");
1870
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1871
	conf_mount_ro();
1872
	return;
1873
}
1874

    
1875
/*
1876
 *  merge_config_section($section, new_contents):   restore a configuration section,
1877
 *                                                  and write the configuration out
1878
 *                                                  to disk/cf.  But preserve the prior
1879
 * 													structure if needed
1880
 */
1881
function merge_config_section($section, $new_contents) {
1882
	global $config;
1883
	conf_mount_rw();
1884
	$fname = get_tmp_filename();
1885
	$fout = fopen($fname, "w");
1886
	fwrite($fout, $new_contents);
1887
	fclose($fout);
1888
	$section_xml = parse_xml_config($fname, $section);
1889
	$config[$section] = $section_xml;
1890
	unlink($fname);
1891
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1892
	conf_mount_ro();
1893
	return;
1894
}
1895

    
1896
/*
1897
 * http_post($server, $port, $url, $vars): does an http post to a web server
1898
 *                                         posting the vars array.
1899
 * written by nf@bigpond.net.au
1900
 */
1901
function http_post($server, $port, $url, $vars) {
1902
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
1903
	$urlencoded = "";
1904
	while (list($key,$value) = each($vars))
1905
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
1906
	$urlencoded = substr($urlencoded,0,-1);
1907
	$content_length = strlen($urlencoded);
1908
	$headers = "POST $url HTTP/1.1
1909
Accept: */*
1910
Accept-Language: en-au
1911
Content-Type: application/x-www-form-urlencoded
1912
User-Agent: $user_agent
1913
Host: $server
1914
Connection: Keep-Alive
1915
Cache-Control: no-cache
1916
Content-Length: $content_length
1917

    
1918
";
1919

    
1920
	$errno = "";
1921
	$errstr = "";
1922
	$fp = fsockopen($server, $port, $errno, $errstr);
1923
	if (!$fp) {
1924
		return false;
1925
	}
1926

    
1927
	fputs($fp, $headers);
1928
	fputs($fp, $urlencoded);
1929

    
1930
	$ret = "";
1931
	while (!feof($fp))
1932
		$ret.= fgets($fp, 1024);
1933
	fclose($fp);
1934

    
1935
	return $ret;
1936
}
1937

    
1938
/*
1939
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
1940
 */
1941
if (!function_exists('php_check_syntax')){
1942
	function php_check_syntax($code_to_check, &$errormessage){
1943
		return false;
1944
		$fout = fopen("/tmp/codetocheck.php","w");
1945
		$code = $_POST['content'];
1946
		$code = str_replace("<?php", "", $code);
1947
		$code = str_replace("?>", "", $code);
1948
		fwrite($fout, "<?php\n\n");
1949
		fwrite($fout, $code_to_check);
1950
		fwrite($fout, "\n\n?>\n");
1951
		fclose($fout);
1952
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1953
		$output = exec_command($command);
1954
		if (stristr($output, "Errors parsing") == false) {
1955
			echo "false\n";
1956
			$errormessage = '';
1957
			return(false);
1958
		} else {
1959
			$errormessage = $output;
1960
			return(true);
1961
		}
1962
	}
1963
}
1964

    
1965
/*
1966
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1967
 */
1968
if (!function_exists('php_check_syntax')){
1969
	function php_check_syntax($code_to_check, &$errormessage){
1970
		return false;
1971
		$command = "/usr/local/bin/php -l " . $code_to_check;
1972
		$output = exec_command($command);
1973
		if (stristr($output, "Errors parsing") == false) {
1974
			echo "false\n";
1975
			$errormessage = '';
1976
			return(false);
1977
		} else {
1978
			$errormessage = $output;
1979
			return(true);
1980
		}
1981
	}
1982
}
1983

    
1984
/*
1985
 * rmdir_recursive($path,$follow_links=false)
1986
 * Recursively remove a directory tree (rm -rf path)
1987
 * This is for directories _only_
1988
 */
1989
function rmdir_recursive($path,$follow_links=false) {
1990
	$to_do = glob($path);
1991
	if(!is_array($to_do)) $to_do = array($to_do);
1992
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1993
		if(file_exists($workingdir)) {
1994
			if(is_dir($workingdir)) {
1995
				$dir = opendir($workingdir);
1996
				while ($entry = readdir($dir)) {
1997
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1998
						unlink("$workingdir/$entry");
1999
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
2000
						rmdir_recursive("$workingdir/$entry");
2001
				}
2002
				closedir($dir);
2003
				rmdir($workingdir);
2004
			} elseif (is_file($workingdir)) {
2005
				unlink($workingdir);
2006
			}
2007
               	}
2008
	}
2009
	return;
2010
}
2011

    
2012
/*
2013
 *     get_memory()
2014
 *     returns an array listing the amount of
2015
 *     memory installed in the hardware
2016
 *     [0]real and [1]available
2017
 */
2018
function get_memory() {
2019
	if(file_exists("/var/log/dmesg.boot")) {
2020
		$mem = `cat /var/log/dmesg.boot | grep memory`;
2021
		$matches = "";
2022
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2023
			$real = $matches[1];
2024
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2025
			$avail = $matches[1];
2026
		return array($real[0],$avail[0]);
2027
	} else {
2028
		$mem = `dmesg -a`;
2029
		$matches = "";
2030
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2031
			$real = $matches[1];
2032
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2033
			$avail = $matches[1];
2034
		return array($real[0],$avail[0]);
2035
	}
2036
}
2037

    
2038
/*
2039
 *    safe_mkdir($path, $mode = 0755)
2040
 *    create directory if it doesn't already exist and isn't a file!
2041
 */
2042
function safe_mkdir($path, $mode=0755) {
2043
	global $g;
2044

    
2045
	/* cdrom is ro. */
2046
	if($g['platform'] == "cdrom")
2047
		return false;
2048

    
2049
	if (!is_file($path) && !is_dir($path))
2050
		return mkdir($path, $mode);
2051
	else
2052
		return false;
2053
}
2054

    
2055
/*
2056
 * make_dirs($path, $mode = 0755)
2057
 * create directory tree recursively (mkdir -p)
2058
 */
2059
function make_dirs($path, $mode = 0755) {
2060
	$base = '';
2061
	foreach (explode('/', $path) as $dir) {
2062
		$base .= "/$dir";
2063
		if (!is_dir($base)) {
2064
			if (!@mkdir($base, $mode))
2065
				return false;
2066
		}
2067
	}
2068
	return true;
2069
}
2070

    
2071
/*
2072
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
2073
 */
2074
function call_pfsense_method($method, $params, $timeout = 0) {
2075
	$ip = gethostbyname('www.pfsense.com');
2076
	if($ip == "www.pfsense.com")
2077
		return false;
2078
	global $g, $config;
2079
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
2080
	$xmlrpc_path = $g['xmlrpcpath'];
2081
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
2082
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
2083
	$resp = $cli->send($msg, $timeout);
2084
	if(!$resp) {
2085
		log_error("XMLRPC communication error: " . $cli->errstr);
2086
		return false;
2087
	} elseif($resp->faultCode()) {
2088
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
2089
		return false;
2090
	} else {
2091
		return XML_RPC_Decode($resp->value());
2092
	}
2093
}
2094

    
2095
/*
2096
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
2097
 */
2098
function check_firmware_version($tocheck = "all", $return_php = true) {
2099
	global $g, $config;
2100
	$ip = gethostbyname('www.pfsense.com');
2101
	if($ip == "www.pfsense.com")
2102
		return false;
2103
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
2104
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
2105
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
2106
		"platform" => trim(file_get_contents('/etc/platform'))
2107
		);
2108
	if($tocheck == "all") {
2109
		$params = $rawparams;
2110
	} else {
2111
		foreach($tocheck as $check) {
2112
			$params['check'] = $rawparams['check'];
2113
			$params['platform'] = $rawparams['platform'];
2114
		}
2115
	}
2116
	if($config['system']['firmware']['branch']) {
2117
		$params['branch'] = $config['system']['firmware']['branch'];
2118
	}
2119
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
2120
		return false;
2121
	} else {
2122
		$versions["current"] = $params;
2123
	}
2124
	return $versions;
2125
}
2126

    
2127
function get_disk_info() {
2128
	$diskout = "";
2129
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
2130
	return explode(' ', $diskout[0]);
2131
	// $size, $used, $avail, $cap
2132
}
2133

    
2134
/****f* pfsense-utils/display_top_tabs
2135
 * NAME
2136
 *   display_top_tabs - display tabs with rounded edges
2137
 * INPUTS
2138
 *   $text	- array of tabs
2139
 * RESULT
2140
 *   null
2141
 ******/
2142
function display_top_tabs($tab_array) {
2143
	echo "<table cellpadding='0' cellspacing='0'>\n";
2144
	echo " <tr height='1'>\n";
2145
	$tabscounter = 0;
2146
	foreach ($tab_array as $ta) {
2147
		if($ta[1] == true) {
2148
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
2149
		} else {
2150
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
2151
		}
2152
		$tabscounter++;
2153
	}
2154
	echo "</tr>\n<tr>\n";
2155
	foreach ($tab_array as $ta) {
2156
		if($ta[1] == true) {
2157
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
2158
			echo "&nbsp;&nbsp;&nbsp;";
2159
			echo "<font size='-12'>&nbsp;</td>\n";
2160
		} else {
2161
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
2162
			echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
2163
			echo "<font size='-12'>&nbsp;</td>\n";
2164
		}
2165
	}
2166
	echo "</tr>\n<tr height='5px'>\n";
2167
	foreach ($tab_array as $ta) {
2168
		if($ta[1] == true) {
2169
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2170
		} else {
2171
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2172
		}
2173
		$tabscounter++;
2174
	}
2175
	echo " </tr>\n";
2176
	echo "</table>\n";
2177

    
2178
	echo "<script type=\"text/javascript\">";
2179
	echo "NiftyCheck();\n";
2180
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
2181
	for($x=0; $x<$tabscounter; $x++)
2182
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
2183
	echo "</script>";
2184
}
2185

    
2186

    
2187
/****f* pfsense-utils/display_topbar
2188
 * NAME
2189
 *   display_topbar - top a table off with rounded edges
2190
 * INPUTS
2191
 *   $text	- (optional) Text to include in bar
2192
 * RESULT
2193
 *   null
2194
 ******/
2195
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
2196
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
2197
	echo "       <tr height='1'>\n";
2198
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
2199
	echo "		<div id='topbar'></div></td>\n";
2200
	echo "       </tr>\n";
2201
	echo "       <tr height='1'>\n";
2202
	if ($text != "")
2203
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
2204
	else
2205
		echo "         <td height='1' class='listtopic'></td>\n";
2206
	echo "       </tr>\n";
2207
	echo "     </table>";
2208
	echo "<script type=\"text/javascript\">";
2209
	echo "NiftyCheck();\n";
2210
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
2211
	echo "</script>";
2212
}
2213

    
2214
/****f* pfsense-utils/generate_random_mac_address
2215
 * NAME
2216
 *   generate_random_mac - generates a random mac address
2217
 * INPUTS
2218
 *   none
2219
 * RESULT
2220
 *   $mac - a random mac address
2221
 ******/
2222
function generate_random_mac_address() {
2223
	$mac = "02";
2224
	for($x=0; $x<5; $x++)
2225
		$mac .= ":" . dechex(rand(16, 255));
2226
	return $mac;
2227
}
2228

    
2229
/****f* pfsense-utils/strncpy
2230
 * NAME
2231
 *   strncpy - copy strings
2232
 * INPUTS
2233
 *   &$dst, $src, $length
2234
 * RESULT
2235
 *   none
2236
 ******/
2237
function strncpy(&$dst, $src, $length) {
2238
	if (strlen($src) > $length) {
2239
		$dst = substr($src, 0, $length);
2240
	} else {
2241
		$dst = $src;
2242
	}
2243
}
2244

    
2245
/****f* pfsense-utils/reload_interfaces_sync
2246
 * NAME
2247
 *   reload_interfaces - reload all interfaces
2248
 * INPUTS
2249
 *   none
2250
 * RESULT
2251
 *   none
2252
 ******/
2253
function reload_interfaces_sync() {
2254
	global $config, $g, $debug;
2255

    
2256
	$shutdown_webgui_needed = false;
2257

    
2258
	touch("{$g['tmp_path']}/reloading_all");
2259

    
2260
	if($debug)
2261
		log_error("reload_interfaces_sync() is starting.");
2262

    
2263
	if(file_exists("{$g['tmp_path']}/config.cache"))
2264
		unlink("{$g['tmp_path']}/config.cache");
2265

    
2266
	/* parse config.xml again */
2267
	$config = parse_config(true);
2268

    
2269
	$wan_if = $config['interfaces']['wan']['if'];
2270
	$lan_if = $config['interfaces']['lan']['if'];
2271

    
2272
	if($debug)
2273
		log_error("Cleaning up Interfaces");
2274

    
2275
	/* build an array of interfaces to work with */
2276
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2277
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2278
		$iflist['opt' . $i] = "opt{$i}";
2279

    
2280
	foreach ($iflist as $ifent => $ifname) {
2281
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2282
		if(stristr($ifname, "lo0") == true)
2283
			continue;
2284
		/* do not process wan interface, its mandatory */
2285
		if(stristr($ifname, "$wan_if") == true)
2286
			continue;
2287
		/* do not process lan interface, its mandatory */
2288
		if(stristr($ifname, "$lan_if") == true)
2289
			continue;
2290
		if($debug)
2291
			log_error("Downing and deleting $ifname_real - $ifname");
2292
		mwexec("/sbin/ifconfig {$ifname_real} down");
2293
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2294
	}
2295

    
2296
	/* set up VLAN virtual interfaces */
2297
	if($debug)
2298
		log_error("Configuring VLANS");
2299
	interfaces_vlan_configure();
2300

    
2301
	/* set up LAN interface */
2302
	if($debug)
2303
		log_error("Configuring LAN");
2304
	interfaces_lan_configure();
2305

    
2306
	/* set up WAN interface */
2307
	if($debug)
2308
		log_error("Configuring WAN");
2309
	interfaces_wan_configure();
2310

    
2311
	/* set up Optional interfaces */
2312
	if($debug)
2313
		log_error("Configuring optional interfaces");
2314
	interfaces_optional_configure();
2315

    
2316
	/* set up static routes */
2317
	if($debug)
2318
		log_error("Configuring system Routing");
2319
	system_routing_configure();
2320

    
2321
	/* enable routing */
2322
	if($debug)
2323
		log_error("Enabling system routing");
2324
	system_routing_enable();
2325

    
2326
	/* setup captive portal if needed */
2327
	if($debug)
2328
		log_error("Configuring Captive portal");
2329
	captiveportal_configure();
2330

    
2331
	/* bring up carp interfaces */
2332
	if($debug)
2333
		log_error("Configuring CARP");
2334
	interfaces_carp_configure();
2335

    
2336
	/* bring up carp interfaces*/
2337
	if($debug)
2338
		log_error("Bringing up CARP interfaces");
2339
	interfaces_carp_bring_up_final();
2340

    
2341
	/* restart webConfigurator if needed */
2342
	if($shutdown_webgui_needed == true)
2343
		touch("/tmp/restart_webgui");
2344

    
2345
	/* start devd back up */
2346
	mwexec("/bin/rm /tmp/reload*");
2347

    
2348
	/* remove reloading_all trigger */
2349
	if($debug)
2350
		log_error("Removing {$g['tmp_path']}/reloading_all");
2351
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2352
}
2353

    
2354
/****f* pfsense-utils/reload_all
2355
 * NAME
2356
 *   reload_all - triggers a reload of all settings
2357
 *   * INPUTS
2358
 *   none
2359
 * RESULT
2360
 *   none
2361
 ******/
2362
function reload_all() {
2363
	touch("/tmp/reload_all");
2364
}
2365

    
2366
/****f* pfsense-utils/reload_interfaces
2367
 * NAME
2368
 *   reload_interfaces - triggers a reload of all interfaces
2369
 * INPUTS
2370
 *   none
2371
 * RESULT
2372
 *   none
2373
 ******/
2374
function reload_interfaces() {
2375
	touch("/tmp/reload_interfaces");
2376
}
2377

    
2378
/****f* pfsense-utils/sync_webgui_passwords
2379
 * NAME
2380
 *   sync_webgui_passwords - syncs webgui and ssh passwords
2381
 * INPUTS
2382
 *   none
2383
 * RESULT
2384
 *   none
2385
 ******/
2386
function sync_webgui_passwords() {
2387
	global $config, $g, $groupindex, $userindex;
2388

    
2389
	conf_mount_rw();
2390
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
2391

    
2392
	if (!$fd) {
2393
		log_error("Error: cannot open htpasswd in sync_webgui_passwords().\n");
2394
		return 1;
2395
	}
2396

    
2397
	/* loop through custom users and add "virtual" entries */
2398
	if ($config['system']['user']) {
2399
		foreach ($config['system']['user'] as $user)
2400
			fwrite($fd, "{$user['name']}:{$user['password']}\n");
2401
	}
2402

    
2403
	fclose($fd);
2404
	chmod("{$g['varrun_path']}/htpasswd", 0600);
2405

    
2406
	if ($config['system']['user']) {
2407
		$root =& getUNIXRoot();
2408
		$crypted_pw = $root['password'];
2409
	}
2410

    
2411
	if (empty ($crypted_pw)) {
2412
		log_error("Error: cannot determine root pwd in sync_webgui_passwords().\nRoot user struct follows:\n");
2413
		empty($root) ? log_error("Unable to determine root user!\n") : print_r($root);
2414
		log_error("Testing whether your system has the necessary users... ");
2415
		empty($config['system']['user']) ? log_error("users are missing.\n") : log_error("users found.\n");
2416
		return 1;
2417
	}
2418

    
2419
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2420
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2421
	/* sync root */
2422
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
2423
	fwrite($fd, $crypted_pw);
2424
	pclose($fd);
2425
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
2426

    
2427
	/* and again for shell users */
2428
	/* only users with hasShellAccess() == true should be synced */
2429
	if($config['system']['user']) {
2430
		$home_base = $g['platform'] == "pfSense" ? "/home" : "/var/home";
2431

    
2432
		if(! is_dir($home_base))
2433
			mkdir($home_base, 0755);
2434

    
2435
		foreach($config['system']['user'] as $user) {
2436
			if (hasShellAccess($user['name']) || isAllowedToCopyFiles($user['name'])) {
2437
				$home  = hasShellAccess($user['name']) ? "{$home_base}/{$user['name']}" : "{$home_base}/scponly";
2438
				$shell = isAllowedToCopyFiles($user['name']) ? "/usr/local/bin/scponly" : "/etc/rc.initial";
2439
				if (isAllowedToCopyFiles($user['name']))
2440
					$user['groupname'] = "scponly";
2441

    
2442
				$fd = popen("/usr/sbin/pw groupshow -n {$user['groupname']} 2>&1", "r");
2443
				$pwread = fgets($fd, 4096);
2444
				pclose($fd);
2445

    
2446
				if (strpos($pwread, "unknown group") !== false) {
2447
					$groupname = $user['groupname'];
2448
					$group = $config['system']['group'][$groupindex[$groupname]];
2449

    
2450
					if (isset($group) && is_array($group)) {
2451
						$fd = popen("/usr/sbin/pw groupadd -g {$group['gid']} -n {$group['name']}", "r");
2452
						pclose($fd);
2453
					} elseif (isAllowedToCopyFiles($user['name'])) {
2454
						$fd = popen("/usr/sbin/pw groupadd -g 100 -n scponly", "r");
2455
						pclose($fd);
2456
					}
2457
				}
2458

    
2459
				$fd = popen("/usr/sbin/pw usershow -n {$user['name']} 2>&1", "r");
2460
				$pwread = fgets($fd, 4096);
2461
				pclose($fd);
2462

    
2463
				isSystemAdmin($user['name']) ? $group = "wheel" : $group = "staff";
2464

    
2465
				if (strpos($pwread, "no such user") === false) {
2466
					$fd = popen("/usr/sbin/pw usermod -n {$user['name']} -g ${user['groupname']} -G {$group} -H 0", "w");
2467
					fwrite($fd, $user['password']);
2468
					pclose($fd);
2469
				} else {
2470
					$fd = popen("/usr/sbin/pw useradd -u {$user['uid']} -n {$user['name']} -c '{$user['fullname']}' -g ${user['groupname']} -G {$group} -H 0", "w");
2471
					fwrite($fd, $user['password']);
2472
					pclose($fd);
2473
				}
2474

    
2475
				/* common user related operations */
2476
				mwexec("/usr/sbin/pw usermod -n {$user['name']} -s {$shell}");
2477

    
2478
				if(! is_dir($home)) mkdir($home, 0755);
2479
				mwexec("/usr/sbin/pw usermod -n {$user['name']} -d {$home} -m");
2480

    
2481
				if (isAllowedToCopyFiles($user['name'])) {
2482
					mwexec("/usr/sbin/pw usermod -n {$user['name']} -g scponly");
2483
				}
2484

    
2485
				if (file_exists("{$home_base}/scponly"))
2486
					mwexec("chmod 0660 {$home_base}/scponly");
2487

    
2488
				if(isset($config['system']['ssh']['sshdkeyonly']) && ! isAllowedToCopyFiles($user['name'])) {
2489
					create_authorized_keys($user['name'], $home);
2490
				}
2491
			}
2492
		}
2493
	}
2494

    
2495
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2496
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2497
	conf_mount_ro();
2498
}
2499
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
2500
 * NAME
2501
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
2502
 *   * INPUTS
2503
 *   optional interface number
2504
 * RESULT
2505
 *   none
2506
 ******/
2507
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
2508
	/*	move all the interfaces up.  for example:
2509
	*		opt1 --> opt1
2510
	*		opt2 --> delete
2511
	*		opt3 --> opt2
2512
	*		opt4 --> opt3
2513
	*/
2514
	global $g, $config;
2515
	config_lock();
2516
	conf_mount_rw();
2517
	unlink_if_exists("{$g['tmp_path']}/config.cache");
2518
	$config_file = file_get_contents("/cf/conf/config.xml");
2519
	/* loop through and reassign deleted items */
2520
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
2521
		if ($i < $opt_interface_num)
2522
			break;
2523
		if ($i == $opt_interface_num) {
2524
			/* item should be deleted */
2525
			str_replace("opt" . $i, "optXXXX", $config_file);
2526
		}
2527
	}
2528
	/* loop through and reassign optional items */
2529
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
2530
		if ($i < $opt_interface_num)
2531
			break;
2532
		/* replace opt$i with $i -1 */
2533
		str_replace("opt" . $i, "opt" . ($i -1), $config_file);
2534
	}
2535
	$fd = fopen("/cf/conf/config.xml", "w");
2536
	fwrite($fd, $config_file);
2537
	fclose($fd);
2538
	$config = parse_config(true);
2539
	/* loop through and delete old rules */
2540
	$num_rules = count($config['filter']['rule']);
2541
	for($x = $num_rules; $x > 0; $x--) {
2542
		if($config['filter']['rule'][$x])
2543
			if($config['filter']['rule'][$x]['interface'] == "optXXXX")
2544
		 		unset($config['filter']['rule'][$x]['interface']);
2545
	}
2546
	$num_rules = count($config['nat']['advancedoutbound']['rule']);
2547
	for($x = $num_rules; $x > 0; $x--) {
2548
		if($config['nat']['advancedoutbound']['rule'][$x])
2549
			if($config['nat']['advancedoutbound']['rule'][$x]['interface'] == "optXXXX")
2550
		 		unset($config['nat']['advancedoutbound']['rule'][$x]['interface']);
2551
	}
2552
	$num_rules = count($config['nat']['rule']);
2553
	for($x = $num_rules; $x > 0; $x--) {
2554
		if($config['nat']['rule'][$x])
2555
			if($config['nat']['rule'][$x]['interface'] == "optXXXX")
2556
		 		unset($config['nat']['rule'][$x]['interface']);
2557
	}
2558
	conf_mount_ro();
2559
	config_unlock();
2560
	return true;
2561
}
2562

    
2563
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
2564
 * NAME
2565
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
2566
 *   		amount of netgraph interfaces needed for system wans
2567
 *   * INPUTS
2568
 *   none
2569
 * RESULT
2570
 *   number of needed netgraph (ng) interfaces
2571
 ******/
2572
function get_number_of_wan_netgraph_interfaces_needed() {
2573
	global $config, $g;
2574
	/* build an array of interfaces to work with */
2575
	$iflist = array("wan" => "WAN");
2576
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2577
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2578
	$ng_interfaces_needed = 0;
2579
	foreach ($iflist as $ifent => $ifname) {
2580
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2581
			$ng_interfaces_needed++;
2582
		}
2583
	}
2584
	return $ng_interfaces_needed;
2585
}
2586

    
2587
function get_netgaph_interface_assignment($friendly_interface) {
2588
	global $config, $g;
2589
	/* build an array of interfaces to work with */
2590
	$iflist = array("wan" => "WAN");
2591
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2592
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2593
		$ng_interfaces_needed = 0;
2594
		$ng_interfaces_number = 0;
2595
		foreach ($iflist as $ifent => $ifname) {
2596
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2597
			$ng_interfaces_number++;
2598
		}
2599
		if($friendly_interface == $ifname)
2600
			break;
2601
	}
2602
	return $ng_interfaces_number;
2603
}
2604

    
2605
/****f* pfsense-utils/reload_all_sync
2606
 * NAME
2607
 *   reload_all - reload all settings
2608
 *   * INPUTS
2609
 *   none
2610
 * RESULT
2611
 *   none
2612
 ******/
2613
function reload_all_sync() {
2614
	global $config, $g;
2615

    
2616
	$g['booting'] = false;
2617

    
2618
	touch("{$g['tmp_path']}/reloading_all");
2619

    
2620
	$shutdown_webgui_needed = false;
2621

    
2622
	if(file_exists("{$g['tmp_path']}/config.cache"))
2623
		unlink("{$g['tmp_path']}/config.cache");
2624

    
2625
	/* parse config.xml again */
2626
	$config = parse_config(true);
2627

    
2628
	/* set up our timezone */
2629
	system_timezone_configure();
2630

    
2631
	/* set up our hostname */
2632
	system_hostname_configure();
2633

    
2634
	/* make hosts file */
2635
	system_hosts_generate();
2636

    
2637
	/* generate resolv.conf */
2638
	system_resolvconf_generate();
2639

    
2640
	/* Set up our loopback interface */
2641
	interfaces_loopback_configure();
2642

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

    
2646
	$wan_if = $config['interfaces']['wan']['if'];
2647
	$lan_if = $config['interfaces']['lan']['if'];
2648

    
2649
	/* build an array of interfaces to work with */
2650
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2651
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2652
		$iflist['opt' . $i] = "opt{$i}";
2653

    
2654
	foreach ($iflist as $ifent => $ifname) {
2655
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2656
		if(stristr($ifname, "lo0") == true)
2657
			continue;
2658
		/* do not process wan interface, its mandatory */
2659
		if($wan_if == $ifname_real)
2660
			continue;
2661
		/* do not process lan interface, its mandatory */
2662
		if($lan_if == $ifname_real)
2663
			continue;
2664
		mwexec("/sbin/ifconfig {$ifname_real} down");
2665
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2666
	}
2667

    
2668
	/* set up VLAN virtual interfaces */
2669
	interfaces_vlan_configure();
2670

    
2671
	/* set up LAN interface */
2672
	interfaces_lan_configure();
2673

    
2674
	/* set up WAN interface */
2675
	interfaces_wan_configure();
2676

    
2677
	/* set up Optional interfaces */
2678
	interfaces_optional_configure();
2679

    
2680
	/* bring up carp interfaces */
2681
	interfaces_carp_configure();
2682

    
2683
	/* set up static routes */
2684
	system_routing_configure();
2685

    
2686
	/* enable routing */
2687
	system_routing_enable();
2688

    
2689
	/* ensure passwords are sync'd */
2690
	system_password_configure();
2691

    
2692
	/* start dnsmasq service */
2693
	services_dnsmasq_configure();
2694

    
2695
	/* start dyndns service */
2696
	services_dyndns_configure();
2697

    
2698
	/* start DHCP service */
2699
	services_dhcpd_configure();
2700

    
2701
	/* configure cron service */
2702
	configure_cron();
2703

    
2704
	/* start the NTP client */
2705
	system_ntp_configure();
2706

    
2707
	/* start ftp proxy helpers if they are enabled */
2708
	system_start_ftp_helpers();
2709

    
2710
	/* start the captive portal */
2711
	captiveportal_configure();
2712

    
2713
        /* reload the filter */
2714
	filter_configure_sync();
2715

    
2716
	/* bring up carp interfaces*/
2717
	interfaces_carp_bring_up_final();
2718

    
2719
	/* sync pw database */
2720
	conf_mount_rw();
2721
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2722
	conf_mount_ro();
2723

    
2724
	/* restart sshd */
2725
	touch("/tmp/start_sshd");
2726

    
2727
	/* restart webConfigurator if needed */
2728
	if($shutdown_webgui_needed == true)
2729
		touch("/tmp/restart_webgui");
2730

    
2731
	mwexec("/bin/rm /tmp/reload*");
2732

    
2733
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2734

    
2735
}
2736

    
2737
function auto_login($status) {
2738
	$gettytab = file_get_contents("/etc/gettytab");
2739
	$getty_split = split("\n", $gettytab);
2740
	conf_mount_rw();
2741
	$fd = fopen("/etc/gettytab", "w");
2742
	foreach($getty_split as $gs) {
2743
		if(stristr($gs, ":ht:np:sp#115200") ) {
2744
			if($status == true) {
2745
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
2746
			} else {
2747
				fwrite($fd, "	:ht:np:sp#115200:\n");
2748
			}
2749
		} else {
2750
			fwrite($fd, "{$gs}\n");
2751
		}
2752
	}
2753
	fclose($fd);
2754
	conf_mount_ro();
2755
}
2756

    
2757
function setup_serial_port() {
2758
	global $g, $config;
2759
	conf_mount_rw();
2760
	/* serial console - write out /boot.config */
2761
	if(file_exists("/boot.config"))
2762
		$boot_config = file_get_contents("/boot.config");
2763
	else
2764
		$boot_config = "";
2765

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

    
2826
function print_value_list($list, $count = 10, $separator = ",") {
2827
	$list = implode($separator, array_slice($list, 0, $count));
2828
	if(count($list) < $count) {
2829
		$list .= ".";
2830
	} else {
2831
		$list .= "...";
2832
	}
2833
	return $list;
2834
}
2835

    
2836
function convert_friendly_interface_to_friendly_descr($interface) {
2837
	global $config;
2838
	/* attempt to resolve interface to friendly descr */
2839
	if($config['interfaces'][$interface]['descr'])
2840
		return $config['interfaces'][$interface]['descr'];
2841
	$tmp = convert_real_interface_to_friendly_descr($interface);
2842
	/* could not resolve, return back what was passed */
2843
	return $interface;
2844
}
2845

    
2846
function convert_real_interface_to_friendly_descr($interface) {
2847
	global $config;
2848
	if($interface == $config['interfaces']['wan']['if'])
2849
		return "wan";
2850
	if($interface == $config['interfaces']['lan']['if'])
2851
		return "lan";
2852
	/* attempt to resolve interface to friendly descr */
2853
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
2854
	if($config['interfaces'][$friendly_int]['descr'])
2855
		return $config['interfaces'][$friendly_int]['descr'];
2856
	/* could not resolve, return back what was passed */
2857
	return $interface;
2858
}
2859

    
2860
function enable_rrd_graphing() {
2861
	global $config, $g;
2862

    
2863
	if($g['booting']) 
2864
		echo "Generating RRD graphs...";
2865

    
2866
	$rrddbpath = "/var/db/rrd/";
2867
	$rrdgraphpath = "/usr/local/www/rrd";
2868

    
2869
	$traffic = "-traffic.rrd";
2870
	$packets = "-packets.rrd";
2871
	$states = "-states.rrd";
2872
	$quality = "-quality.rrd";
2873
	$queues = "-queues.rrd";
2874
	$queuesdrop = "-queuesdrop.rrd";
2875
	$spamd = "-spamd.rrd";
2876
	$proc = "-processor.rrd";
2877

    
2878
	$rrdtool = "/usr/local/bin/rrdtool";
2879
	$netstat = "/usr/bin/netstat";
2880
	$awk = "/usr/bin/awk";
2881
	$tar = "/usr/bin/tar";
2882
	$pfctl = "/sbin/pfctl";
2883
	$php = "/usr/local/bin/php";
2884
	$top = "/usr/bin/top";
2885
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2886

    
2887
	$rrdtrafficinterval = 60;
2888
	$rrdqualityinterval = 60;
2889
	$rrdqueuesinterval = 60;
2890
	$rrdqueuesdropinterval = 60;
2891
	$rrdpacketsinterval = 60;
2892
	$rrdstatesinterval = 60;
2893
	$rrdspamdinterval = 60;
2894
	$rrdlbpoolinterval = 60;
2895
	$rrdprocinterval = 60;
2896

    
2897
	$trafficvalid = $rrdtrafficinterval * 2;
2898
	$qualityvalid = $rrdqualityinterval * 2;
2899
	$queuesvalid = $rrdqueuesinterval * 2;
2900
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2901
	$packetsvalid = $rrdpacketsinterval * 2;
2902
	$statesvalid = $rrdstatesinterval*2;
2903
	$spamdvalid = $rrdspamdinterval * 2;
2904
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2905
	$procvalid = $rrdlbpoolinterval * 2;
2906

    
2907
	/* Asume GigE for now */
2908
	$downstream = 125000000;
2909
	$upstream = 125000000;
2910

    
2911
	$rrdrestore = "";
2912
	$rrdreturn = "";
2913

    
2914
	$config['rrd']['enable'] = true;
2915

    
2916
	if (isset ($config['rrd']['enable'])) {
2917

    
2918
		/* create directory if needed */
2919
		if (!is_dir("$rrddbpath")) {
2920
			mkdir("$rrddbpath", 0755);
2921
		}
2922

    
2923
		if ($g['booting']) {
2924
			if ($g['platform'] != "pfSense") {
2925
				/* restore the databases, if we have one */
2926
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
2927
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2928
					if((int)$rrdrestore <> 0) {
2929
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
2930
					}
2931
				}
2932
			}
2933
		}
2934

    
2935
		/* db update script */
2936
		$rrdupdatesh = "#!/bin/sh\n";
2937
		$rrdupdatesh .= "\n";
2938
		$rrdupdatesh .= "counter=1\n";
2939
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2940
		$rrdupdatesh .= "do\n";
2941
		$rrdupdatesh .= "";
2942

    
2943
		$i = 0;
2944
		$vfaces = array (
2945
			"vlan.?*",
2946
			"enc.?*"
2947
		);
2948
		$ifdescrs = get_interface_list(true, true, $vfaces);
2949
		$ifdescrs['enc0']['friendly'] = "ipsec";
2950
		$ifdescrs['enc0']['descr'] = "IPSEC";
2951
		$ifdescrs['enc0']['up'] = true;
2952

    
2953
		foreach ($ifdescrs as $realif => $ifdescr) {
2954
			$ifname = $ifdescr['friendly'];
2955
			$state = $ifdescr['up'];
2956

    
2957
			/* skip interfaces that do not have a friendly name */
2958
			if ("$ifname" == "") {
2959
				continue;
2960
			}
2961

    
2962
			/* or are down */
2963
			if (!$state) {
2964
				continue;
2965
			}
2966

    
2967
			/* TRAFFIC, set up the rrd file */
2968
			if (!file_exists("$rrddbpath$ifname$traffic")) {
2969
				/* create rrd file if it does not exist */
2970
				log_error("Create RRD database $rrddbpath$ifname$traffic");
2971
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
2972
				$rrdcreate .= "DS:in:COUNTER:$trafficvalid:0:$downstream ";
2973
				$rrdcreate .= "DS:out:COUNTER:$trafficvalid:0:$upstream ";
2974
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2975
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2976
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2977
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2978
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
2979
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
2980
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
2981
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
2982

    
2983
				$rrdcreateoutput = array();
2984
				$rrdcreatereturn = "";
2985

    
2986
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2987
				if ($rrdcreatereturn != 0) {
2988
					log_error("RRD create failed exited with $rrdcreatereturn, the
2989
							error is: $rrdcreateoutput[0]\n");
2990
				}
2991
			}
2992

    
2993
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2994
			if($g['booting']) {
2995
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
2996
			}
2997

    
2998
			$rrdupdatesh .= "\n";
2999
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
3000
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
3001
			if(! is_macaddr(get_interface_mac($realif))) {
3002
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$6 \":\" \$9}'`\n";
3003
			} else {
3004
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7 \":\" \$10}'`\n";
3005
			}
3006

    
3007
			/* PACKETS, set up the rrd file */
3008
			if (!file_exists("$rrddbpath$ifname$packets")) {
3009
				/* create rrd file if it does not exist */
3010
				log_error("Create RRD database $rrddbpath$ifname$packets");
3011
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
3012
				$rrdcreate .= "DS:in:COUNTER:$packetsvalid:0:$downstream ";
3013
				$rrdcreate .= "DS:out:COUNTER:$packetsvalid:0:$upstream ";
3014
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3015
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3016
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3017
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3018
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3019
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3020
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3021
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3022

    
3023
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3024
				if ($rrdcreatereturn != 0) {
3025
					log_error("RRD create failed exited with $rrdcreatereturn, the
3026
							error is: $rrdcreateoutput[0]\n");
3027
				}
3028
			}
3029

    
3030
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3031
			if($g['booting']) {
3032
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
3033
			}
3034

    
3035
			$rrdupdatesh .= "\n";
3036
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
3037
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
3038
			if(! is_macaddr(get_interface_mac($realif))) {
3039
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$4 \":\" \$7}'`\n";
3040
			} else {
3041
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5 \":\" \$8}'`\n";
3042
			}
3043
			/* if an alternative gateway is defined, use it */
3044
			if ($config['interfaces'][$ifname]['use_rrd_gateway'] <> "") {
3045
				$gatewayip = get_interface_gateway($ifname);
3046
				$monitorip = $config['system']['interfaces'][$ifname]['use_rrd_gateway'];
3047
				mwexec("/sbin/route add -host {$monitorip} {$gatewayip} 1> /dev/null 2>&1");
3048
			} else {
3049
				$monitorip = get_interface_gateway($ifname);
3050
			}
3051
			$numpings = 5;
3052
			$btick = '`';
3053

    
3054
			if($monitorip <> "") {
3055
				/* QUALITY, create link quality database */
3056
				if (!file_exists("$rrddbpath$ifname$quality")) {
3057
					/* create rrd file if it does not exist */
3058
					log_error("Create RRD database $rrddbpath$ifname$quality");
3059
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
3060
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
3061
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
3062
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3063
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3064
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3065
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3066

    
3067
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3068
					if ($rrdcreatereturn != 0) {
3069
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3070
					}
3071
				}
3072

    
3073
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3074
				if($g['booting']) {
3075
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
3076
				}
3077

    
3078
				/* the ping test function. We call this on the last line */
3079
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
3080
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
3081
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
3082
				$rrdupdatesh .= "	local out_{$ifname}\n";
3083
				$rrdupdatesh .= "	out_{$ifname}=$btick ping -c $numpings -q $monitorip $btick\n";
3084
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
3085
				$rrdupdatesh .= "		packetloss_{$ifname}=$btick echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1 $btick\n";
3086
				$rrdupdatesh .= "		roundtrip_{$ifname}=$btick echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/' $btick\n";
3087
				$rrdupdatesh .= "	fi\n";
3088
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
3089
				$rrdupdatesh .= "}\n\n";
3090

    
3091
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
3092
			}
3093

    
3094
			/* WAN interface only statistics */
3095
			if ("$ifname" == "wan") {
3096

    
3097
				/* QUEUES, set up the queues databases */
3098
				if (!is_array($config['shaper']['queue'])) {
3099
					$config['shaper']['queue'] = array ();
3100
				}
3101
				$a_queues = & $config['shaper']['queue'];
3102

    
3103
				if (isset ($config['shaper']['enable'])) {
3104
					if (!file_exists("$rrddbpath$ifname$queues")) {
3105
						/* create rrd file if it does not exist */
3106
						log_error("Create RRD database $rrddbpath$ifname$queues");
3107
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
3108
						/* loop list of shaper queues */
3109
						$q = 0;
3110
						foreach ($a_queues as $queue) {
3111
							$name = $queue['name'];
3112
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream ";
3113
						}
3114

    
3115
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3116
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3117
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3118
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3119

    
3120
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3121
						if ($rrdcreatereturn != 0) {
3122
							log_error("RRD create failed exited with $rrdcreatereturn, the
3123
									error is: $rrdcreateoutput[0]\n");
3124
						}
3125
					}
3126

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

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

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

    
3149
					if($g['booting']) {
3150
						$rrdqcommand = "-t ";
3151
						$rrducommand = "N";
3152
						$q = 0;
3153
						foreach ($a_queues as $queue) {
3154
							if($q == 0) {
3155
								$rrdqcommand .= "{$queue['name']}";
3156
							} else {
3157
								$rrdqcommand .= ":{$queue['name']}";
3158
							}
3159
							$q++;
3160
							$rrducommand .= ":U";
3161
						}
3162
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3163
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3164
					}
3165

    
3166
					/* awk function to gather shaper data */
3167
					/* yes, it's special */
3168
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
3169
					$rrdupdatesh .= "{ ";
3170
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3171
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3172
					$rrdupdatesh .= "q=1; ";
3173
					$rrdupdatesh .= "} ";
3174
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3175
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
3176
					$rrdupdatesh .= "q=0; ";
3177
					$rrdupdatesh .= "} ";
3178
					$rrdupdatesh .= "} END { ";
3179
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3180
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3181
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3182
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3183

    
3184
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
3185
					$rrdupdatesh .= "{ ";
3186
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3187
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3188
					$rrdupdatesh .= "q=1; ";
3189
					$rrdupdatesh .= "} ";
3190
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3191
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
3192
					$rrdupdatesh .= "q=0; ";
3193
					$rrdupdatesh .= "} ";
3194
					$rrdupdatesh .= "} END { ";
3195
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3196
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3197
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3198
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3199
				}
3200
			}
3201
		}
3202
		$i++;
3203

    
3204
		/* System only statistics */
3205
		$ifname = "system";
3206

    
3207
			/* STATES, create pf states database */
3208
			if(! file_exists("$rrddbpath$ifname$states")) {
3209
				/* create rrd file if it does not exist */
3210
				log_error("Create RRD database $rrddbpath$ifname$states");
3211
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3212
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3213
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3214
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3215
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3216
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3217
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3218
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3219
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3220
				$rrdcreate .= "RRA:MIN:0.5:360:1000 ";
3221
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3222
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3223
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3224
				$rrdcreate .= "RRA:AVERAGE:0.5:360:1000 ";
3225
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3226
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3227
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3228
				$rrdcreate .= "RRA:MAX:0.5:360:1000";
3229

    
3230
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3231
				if($rrdcreatereturn != 0) {
3232
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3233
						error is: $rrdcreateoutput[0]\n");
3234
				}
3235
			}
3236

    
3237
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3238
			if($g['booting']) {
3239
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
3240
			}
3241

    
3242
 			/* the pf states gathering function. */
3243
 			$rrdupdatesh .= "\n";
3244
 			$rrdupdatesh .= "pfrate=\"` $pfctl -si | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3245
 			$rrdupdatesh .= "pfstates=\"` $pfctl -ss | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3246
			$rrdupdatesh .= "pfnat=\"` $pfctl -ss | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3247
 			$rrdupdatesh .= "srcip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '\\->' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
3248
 			$rrdupdatesh .= "dstip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '<\\-' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
3249
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3250

    
3251
			/* End pf states statistics */
3252

    
3253
			/* CPU, create CPU statistics database */
3254
			if(! file_exists("$rrddbpath$ifname$proc")) {
3255
				/* create rrd file if it does not exist */
3256
				log_error("Create RRD database $rrddbpath$ifname$proc");
3257
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3258
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3259
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3260
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3261
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3262
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3263
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3264
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3265
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3266
				$rrdcreate .= "RRA:MIN:0.5:360:1000 ";
3267
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3268
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3269
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3270
				$rrdcreate .= "RRA:AVERAGE:0.5:360:1000 ";
3271
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3272
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3273
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3274
				$rrdcreate .= "RRA:MAX:0.5:360:1000";
3275

    
3276
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3277
				if($rrdcreatereturn != 0) {
3278
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3279
						error is: $rrdcreateoutput[0]\n");
3280
				}
3281
			}
3282

    
3283
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3284
			if($g['booting']) {
3285
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
3286
			}
3287

    
3288
 			/* the CPU stats gathering function. */
3289
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { ";
3290
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } ";
3291
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { ";
3292
			$rrdupdatesh .= "processes = \$1; ";
3293
			$rrdupdatesh .= "} ";
3294
			$rrdupdatesh .= "else if ( \$1 == \"CPU\" ) { ";
3295
			$rrdupdatesh .= "user = \$3; ";
3296
			$rrdupdatesh .= "nice = \$5; ";
3297
			$rrdupdatesh .= "sys = \$7; ";
3298
			$rrdupdatesh .= "interrupt = \$9; ";
3299
			$rrdupdatesh .= "} ";
3300
			$rrdupdatesh .= "} END { ";
3301
			$rrdupdatesh .= "printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes ";
3302
			$rrdupdatesh .= "}'`\n\n";
3303

    
3304
			/* End CPU statistics */
3305

    
3306
			/* SPAMD, set up the spamd rrd file */
3307
			if (isset($config['installedpackages']['spamdsettings']) &&
3308
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
3309
				/* set up the spamd rrd file */
3310
				if (!file_exists("$rrddbpath$ifname$spamd")) {
3311
						/* create rrd file if it does not exist */
3312
						log_error("Create RRD database $rrddbpath$ifname$spamd");
3313
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
3314
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
3315
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
3316
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3317
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3318
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3319
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3320
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3321
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3322
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3323
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3324
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3325
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3326
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3327
						$rrdcreate .= "RRA:MAX:0.5:720:1000";
3328

    
3329
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3330
					if ($rrdcreatereturn != 0) {
3331
						log_error("RRD create failed exited with $rrdcreatereturn, the
3332
							error is: $rrdcreateoutput[0]\n");
3333
					}
3334
				}
3335

    
3336
				$rrdupdatesh .= "\n";
3337
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3338
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3339
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3340

    
3341
			}
3342
		/* End System statistics */
3343

    
3344
		$rrdupdatesh .= "sleep 60\n";
3345
		$rrdupdatesh .= "done\n";
3346
		log_error("Creating rrd update script");
3347
		/* write the rrd update script */
3348
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3349
		$fd = fopen("$updaterrdscript", "w");
3350
		fwrite($fd, "$rrdupdatesh");
3351
		fclose($fd);
3352

    
3353
		/* kill off traffic collectors */
3354
		kill_traffic_collector();
3355

    
3356
		/* start traffic collector */
3357
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3358

    
3359
	} else {
3360
		/* kill off traffic collectors */
3361
		kill_traffic_collector();
3362
	}
3363

    
3364
	if($g['booting']) 
3365
		echo "done.\n";
3366
		
3367
}
3368

    
3369
function kill_traffic_collector() {
3370
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
3371
}
3372

    
3373
function update_filter_reload_status($text) {
3374
	global $g;
3375
	config_lock();
3376
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3377
	fwrite($fd, $text);
3378
	fclose($fd);
3379
	config_unlock();
3380
}
3381

    
3382
function get_interface_gateway($interface) {
3383
	global $config, $g;
3384
	$interface = strtolower($interface);
3385
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
3386
	 *  grab the address from the configuration file.
3387
	 */
3388
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
3389
	if($tmpif <> $interface)
3390
		$interface = $tmpif;
3391
	$realif = $config['interfaces'][$interface]['if'];
3392
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
3393
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3394
		$gw = rtrim($gw);
3395
	} else {
3396
		$gw = $config['interfaces'][$interface]['gateway'];
3397
	}
3398
	/* if wan is requested, return it */
3399
	if($interface == "wan")
3400
		return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
3401
	/* return gateway */
3402
	return $gw;
3403
}
3404

    
3405
function is_dhcp_server_enabled() {
3406
	/* DHCP enabled on any interfaces? */
3407
	global $config, $g;
3408
	$dhcpdcfg = $config['dhcpd'];
3409
	$dhcpdenable = false;
3410
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
3411
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3412
			$dhcpdenable = true;
3413
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3414
			$dhcpdenable = true;
3415
	}
3416
	return $dhcpdenable;
3417
}
3418

    
3419
/* return outside interfaces with a gateway */
3420
function get_interfaces_with_gateway() {
3421
	global $config;
3422
	$ints = array();
3423
	$vfaces = array(
3424
			'bridge.?*',
3425
			'ppp.?*',
3426
			'sl.?*',
3427
			'gif.?*',
3428
			'faith.?*',
3429
			'lo.?*',
3430
			'ng.?*',
3431
			'vlan.?*',
3432
			'pflog.?*',
3433
			'pfsync.?*',
3434
			'enc.?*',
3435
			'tun.?*',
3436
			'carp.?*'
3437
		);
3438
	$ifdescrs = get_interface_list("active","physical",$vfaces);
3439

    
3440
	/* loop interfaces, check config for outbound */
3441
	foreach ($ifdescrs as $ifdescr => $ifname) {
3442
		$friendly = $ifname['friendly'];
3443
		if ($config['interfaces'][$friendly]['ipaddr'] == "dhcp") {
3444
			$ints[] = $friendly;
3445
			continue;
3446
		}
3447
		if ($config['interfaces'][$friendly]['ipaddr'] == "pppoe") {
3448
			$ints[] = $friendly;
3449
			continue;
3450
		}
3451
		if ($config['interfaces'][$friendly]['ipaddr'] == "pptp") {
3452
			$ints[] = $friendly;
3453
			continue;
3454
		}
3455
		if ($config['interfaces'][$friendly]['gateway'] <> "") {
3456
			$ints[] = $friendly;
3457
			continue;
3458
		}
3459
	}
3460
	return $ints;
3461
}
3462

    
3463
/* return true if interface has a gateway */
3464
function interface_has_gateway($friendly) {
3465
	$friendly = strtolower($friendly);
3466
	if(in_array($friendly, get_interfaces_with_gateway())) {
3467
		return true;
3468
	} else {
3469
		/* extra check for real interface names if it falls through */
3470
		$friendly = convert_real_interface_to_friendly_interface_name($friendly);
3471
		return(in_array($friendly, get_interfaces_with_gateway()));
3472
	}
3473
}
3474

    
3475
/****f* pfsense-utils/isAjax
3476
 * NAME
3477
 *   isAjax - reports if the request is driven from prototype
3478
 * INPUTS
3479
 *   none
3480
 * RESULT
3481
 *   true/false
3482
 ******/
3483
function isAjax() {
3484
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
3485
}
3486

    
3487
//returns interface information
3488
function get_interface_info($ifdescr) {
3489
	global $config, $linkinfo, $netstatrninfo;
3490

    
3491
	$ifinfo = array();
3492

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

    
3500
	/* run netstat to determine link info */
3501

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

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

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

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

    
3560
			$ifinfo['pppoelink'] = "up";
3561

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

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

    
3581
			$ifinfo['pptplink'] = "up";
3582

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

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

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

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

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

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

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

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

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

    
3675
	return $ifinfo;
3676
}
3677

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

    
3683
?>
(15-15/29)