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-2007 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
		usleep(1000);
777
		mwexec("/sbin/ifconfig carp{$x} delete");
778
		if($needed_carp_interfaces < $carp_counter) {
779
			$needed_carp_interfaces--;
780
			//log_error("Destroying carp interface.");
781
			//mwexec("/sbin/ifconfig carp{$x} destroy");
782
		}
783
	}
784
	find_number_of_created_carp_interfaces(true);
785
	sleep(1);
786
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
787
	interfaces_carp_configure();
788
	usleep(1000);
789
	interfaces_carp_bring_up_final();
790
}
791

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1010
	setup_polling_defaults();
1011

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1336
	return $interface_arr_cache;
1337
}
1338

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1508
	return $bridge_interface_count_cache;
1509
}
1510

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1756
	for ($a=0; $a < 6; $a++)
1757
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1758

    
1759
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1760

    
1761
	for ($a = 1; $a <= 16; $a++)
1762
		$msg .= $hw_addr;
1763

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

    
1780
	return false;
1781
}
1782

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

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

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

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

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

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

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

    
1921
";
1922

    
1923
	$errno = "";
1924
	$errstr = "";
1925
	$fp = fsockopen($server, $port, $errno, $errstr);
1926
	if (!$fp) {
1927
		return false;
1928
	}
1929

    
1930
	fputs($fp, $headers);
1931
	fputs($fp, $urlencoded);
1932

    
1933
	$ret = "";
1934
	while (!feof($fp))
1935
		$ret.= fgets($fp, 1024);
1936
	fclose($fp);
1937

    
1938
	return $ret;
1939
}
1940

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

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

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

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

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

    
2048
	/* cdrom is ro. */
2049
	if($g['platform'] == "cdrom")
2050
		return false;
2051

    
2052
	if (!is_file($path) && !is_dir($path))
2053
		return mkdir($path, $mode);
2054
	else
2055
		return false;
2056
}
2057

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

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

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

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

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

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

    
2189

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

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

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

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

    
2259
	$shutdown_webgui_needed = false;
2260

    
2261
	touch("{$g['tmp_path']}/reloading_all");
2262

    
2263
	if($debug)
2264
		log_error("reload_interfaces_sync() is starting.");
2265

    
2266
	if(file_exists("{$g['tmp_path']}/config.cache"))
2267
		unlink("{$g['tmp_path']}/config.cache");
2268

    
2269
	/* parse config.xml again */
2270
	$config = parse_config(true);
2271

    
2272
	$wan_if = $config['interfaces']['wan']['if'];
2273
	$lan_if = $config['interfaces']['lan']['if'];
2274

    
2275
	if($debug)
2276
		log_error("Cleaning up Interfaces");
2277

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

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

    
2299
	/* set up VLAN virtual interfaces */
2300
	if($debug)
2301
		log_error("Configuring VLANS");
2302
	interfaces_vlan_configure();
2303

    
2304
	/* set up LAN interface */
2305
	if($debug)
2306
		log_error("Configuring LAN");
2307
	interfaces_lan_configure();
2308

    
2309
	/* set up WAN interface */
2310
	if($debug)
2311
		log_error("Configuring WAN");
2312
	interfaces_wan_configure();
2313

    
2314
	/* set up Optional interfaces */
2315
	if($debug)
2316
		log_error("Configuring optional interfaces");
2317
	interfaces_optional_configure();
2318

    
2319
	/* set up static routes */
2320
	if($debug)
2321
		log_error("Configuring system Routing");
2322
	system_routing_configure();
2323

    
2324
	/* enable routing */
2325
	if($debug)
2326
		log_error("Enabling system routing");
2327
	system_routing_enable();
2328

    
2329
	/* setup captive portal if needed */
2330
	if($debug)
2331
		log_error("Configuring Captive portal");
2332
	captiveportal_configure();
2333

    
2334
	/* bring up carp interfaces */
2335
	if($debug)
2336
		log_error("Configuring CARP");
2337
	interfaces_carp_configure();
2338

    
2339
	/* bring up carp interfaces*/
2340
	if($debug)
2341
		log_error("Bringing up CARP interfaces");
2342
	interfaces_carp_bring_up_final();
2343

    
2344
	/* restart webConfigurator if needed */
2345
	if($shutdown_webgui_needed == true)
2346
		touch("/tmp/restart_webgui");
2347

    
2348
	/* start devd back up */
2349
	mwexec("/bin/rm /tmp/reload*");
2350

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

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

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

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

    
2392
	conf_mount_rw();
2393
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
2394

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

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

    
2406
	fclose($fd);
2407
	chmod("{$g['varrun_path']}/htpasswd", 0600);
2408

    
2409
	if ($config['system']['user']) {
2410
		$root =& getUNIXRoot();
2411
		$crypted_pw = $root['password'];
2412
	}
2413

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

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

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

    
2435
		if(! is_dir($home_base))
2436
			mkdir($home_base, 0755);
2437

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

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

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

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

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

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

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

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

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

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

    
2488
				if (file_exists("{$home_base}/scponly"))
2489
					mwexec("chmod 0660 {$home_base}/scponly");
2490

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

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

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

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

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

    
2619
	$g['booting'] = false;
2620

    
2621
	touch("{$g['tmp_path']}/reloading_all");
2622

    
2623
	$shutdown_webgui_needed = false;
2624

    
2625
	if(file_exists("{$g['tmp_path']}/config.cache"))
2626
		unlink("{$g['tmp_path']}/config.cache");
2627

    
2628
	/* parse config.xml again */
2629
	$config = parse_config(true);
2630

    
2631
	/* set up our timezone */
2632
	system_timezone_configure();
2633

    
2634
	/* set up our hostname */
2635
	system_hostname_configure();
2636

    
2637
	/* make hosts file */
2638
	system_hosts_generate();
2639

    
2640
	/* generate resolv.conf */
2641
	system_resolvconf_generate();
2642

    
2643
	/* Set up our loopback interface */
2644
	interfaces_loopback_configure();
2645

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

    
2649
	$wan_if = $config['interfaces']['wan']['if'];
2650
	$lan_if = $config['interfaces']['lan']['if'];
2651

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

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

    
2671
	/* set up VLAN virtual interfaces */
2672
	interfaces_vlan_configure();
2673

    
2674
	/* set up LAN interface */
2675
	interfaces_lan_configure();
2676

    
2677
	/* set up WAN interface */
2678
	interfaces_wan_configure();
2679

    
2680
	/* set up Optional interfaces */
2681
	interfaces_optional_configure();
2682

    
2683
	/* bring up carp interfaces */
2684
	interfaces_carp_configure();
2685

    
2686
	/* set up static routes */
2687
	system_routing_configure();
2688

    
2689
	/* enable routing */
2690
	system_routing_enable();
2691

    
2692
	/* ensure passwords are sync'd */
2693
	system_password_configure();
2694

    
2695
	/* start dnsmasq service */
2696
	services_dnsmasq_configure();
2697

    
2698
	/* start dyndns service */
2699
	services_dyndns_configure();
2700

    
2701
	/* start DHCP service */
2702
	services_dhcpd_configure();
2703

    
2704
	/* configure cron service */
2705
	configure_cron();
2706

    
2707
	/* start the NTP client */
2708
	system_ntp_configure();
2709

    
2710
	/* start ftp proxy helpers if they are enabled */
2711
	system_start_ftp_helpers();
2712

    
2713
	/* start the captive portal */
2714
	captiveportal_configure();
2715

    
2716
        /* reload the filter */
2717
	filter_configure_sync();
2718

    
2719
	/* bring up carp interfaces*/
2720
	interfaces_carp_bring_up_final();
2721

    
2722
	/* sync pw database */
2723
	conf_mount_rw();
2724
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2725
	conf_mount_ro();
2726

    
2727
	/* restart sshd */
2728
	touch("/tmp/start_sshd");
2729

    
2730
	/* restart webConfigurator if needed */
2731
	if($shutdown_webgui_needed == true)
2732
		touch("/tmp/restart_webgui");
2733

    
2734
	mwexec("/bin/rm /tmp/reload*");
2735

    
2736
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2737

    
2738
}
2739

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

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

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

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

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

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

    
2863
function enable_rrd_graphing() {
2864
	global $config, $g;
2865

    
2866
	if($g['booting']) 
2867
		echo "Generating RRD graphs...";
2868

    
2869
	$rrddbpath = "/var/db/rrd/";
2870
	$rrdgraphpath = "/usr/local/www/rrd";
2871

    
2872
	$traffic = "-traffic.rrd";
2873
	$packets = "-packets.rrd";
2874
	$states = "-states.rrd";
2875
	$quality = "-quality.rrd";
2876
	$queues = "-queues.rrd";
2877
	$queuesdrop = "-queuesdrop.rrd";
2878
	$spamd = "-spamd.rrd";
2879
	$proc = "-processor.rrd";
2880

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

    
2890
	$rrdtrafficinterval = 60;
2891
	$rrdqualityinterval = 60;
2892
	$rrdqueuesinterval = 60;
2893
	$rrdqueuesdropinterval = 60;
2894
	$rrdpacketsinterval = 60;
2895
	$rrdstatesinterval = 60;
2896
	$rrdspamdinterval = 60;
2897
	$rrdlbpoolinterval = 60;
2898
	$rrdprocinterval = 60;
2899

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

    
2910
	/* Asume GigE for now */
2911
	$downstream = 125000000;
2912
	$upstream = 125000000;
2913

    
2914
	$rrdrestore = "";
2915
	$rrdreturn = "";
2916

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

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

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

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

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

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

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

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

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

    
2981
				$rrdcreateoutput = array();
2982
				$rrdcreatereturn = "";
2983

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

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

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

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

    
3018
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3019
				if ($rrdcreatereturn != 0) {
3020
					log_error("RRD create failed exited with $rrdcreatereturn, the
3021
							error is: $rrdcreateoutput[0]\n");
3022
				}
3023
			}
3024

    
3025
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3026
			if($g['booting']) {
3027
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
3028
			}
3029

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

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

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

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

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

    
3087
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
3088
			}
3089

    
3090
			/* WAN interface only statistics */
3091
			if ("$ifname" == "wan") {
3092

    
3093
				/* QUEUES, set up the queues databases */
3094
				if (!is_array($config['shaper']['queue'])) {
3095
					$config['shaper']['queue'] = array ();
3096
				}
3097
				$a_queues = & $config['shaper']['queue'];
3098

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

    
3111
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3112
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3113
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3114
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3115
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3116

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

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

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

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

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

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

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

    
3202
		/* System only statistics */
3203
		$ifname = "system";
3204

    
3205
			/* STATES, create pf states database */
3206
			if(! file_exists("$rrddbpath$ifname$states")) {
3207
				/* create rrd file if it does not exist */
3208
				log_error("Create RRD database $rrddbpath$ifname$states");
3209
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3210
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3211
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3212
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3213
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3214
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3215
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3216
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3217
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3218
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3219
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3220

    
3221
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3222
				if($rrdcreatereturn != 0) {
3223
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3224
						error is: $rrdcreateoutput[0]\n");
3225
				}
3226
			}
3227

    
3228
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3229
			if($g['booting']) {
3230
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
3231
			}
3232

    
3233
 			/* the pf states gathering function. */
3234
 			$rrdupdatesh .= "\n";
3235
 			$rrdupdatesh .= "pfrate=\"` $pfctl -si | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3236
 			$rrdupdatesh .= "pfstates=\"` $pfctl -ss | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3237
			$rrdupdatesh .= "pfnat=\"` $pfctl -ss | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3238
 			$rrdupdatesh .= "srcip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '\\->' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
3239
 			$rrdupdatesh .= "dstip=\"` $pfctl -ss | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '<\\-' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
3240
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3241

    
3242
			/* End pf states statistics */
3243

    
3244
			/* CPU, create CPU statistics database */
3245
			if(! file_exists("$rrddbpath$ifname$proc")) {
3246
				/* create rrd file if it does not exist */
3247
				log_error("Create RRD database $rrddbpath$ifname$proc");
3248
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3249
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3250
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3251
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3252
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3253
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3254
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3255
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3256
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3257
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3258
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3259

    
3260
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3261
				if($rrdcreatereturn != 0) {
3262
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3263
						error is: $rrdcreateoutput[0]\n");
3264
				}
3265
			}
3266

    
3267
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3268
			if($g['booting']) {
3269
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
3270
			}
3271

    
3272
 			/* the CPU stats gathering function. */
3273
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { ";
3274
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } ";
3275
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { ";
3276
			$rrdupdatesh .= "processes = \$1; ";
3277
			$rrdupdatesh .= "} ";
3278
			$rrdupdatesh .= "else if ( \$1 == \"CPU\" ) { ";
3279
			$rrdupdatesh .= "user = \$3; ";
3280
			$rrdupdatesh .= "nice = \$5; ";
3281
			$rrdupdatesh .= "sys = \$7; ";
3282
			$rrdupdatesh .= "interrupt = \$9; ";
3283
			$rrdupdatesh .= "} ";
3284
			$rrdupdatesh .= "} END { ";
3285
			$rrdupdatesh .= "printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes ";
3286
			$rrdupdatesh .= "}'`\n\n";
3287

    
3288
			/* End CPU statistics */
3289

    
3290
			/* SPAMD, set up the spamd rrd file */
3291
			if (isset($config['installedpackages']['spamdsettings']) &&
3292
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
3293
				/* set up the spamd rrd file */
3294
				if (!file_exists("$rrddbpath$ifname$spamd")) {
3295
						/* create rrd file if it does not exist */
3296
						log_error("Create RRD database $rrddbpath$ifname$spamd");
3297
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
3298
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
3299
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
3300
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3301
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3302
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3303
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3304
						$rrdcreate .= "RRA:MIN:0.5:1440:1500 ";
3305
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3306
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3307
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3308
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3309
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3310
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3311
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3312
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3313
						$rrdcreate .= "RRA:MAX:0.5:720:1000 ";
3314
						$rrdcreate .= "RRA:MAX:0.5:1440:1500 ";
3315

    
3316
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3317
					if ($rrdcreatereturn != 0) {
3318
						log_error("RRD create failed exited with $rrdcreatereturn, the
3319
							error is: $rrdcreateoutput[0]\n");
3320
					}
3321
				}
3322

    
3323
				$rrdupdatesh .= "\n";
3324
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3325
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3326
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3327

    
3328
			}
3329
		/* End System statistics */
3330

    
3331
		$rrdupdatesh .= "sleep 60\n";
3332
		$rrdupdatesh .= "done\n";
3333
		log_error("Creating rrd update script");
3334
		/* write the rrd update script */
3335
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3336
		$fd = fopen("$updaterrdscript", "w");
3337
		fwrite($fd, "$rrdupdatesh");
3338
		fclose($fd);
3339

    
3340
		/* kill off traffic collectors */
3341
		kill_traffic_collector();
3342

    
3343
		/* start traffic collector */
3344
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3345

    
3346
	} else {
3347
		/* kill off traffic collectors */
3348
		kill_traffic_collector();
3349
	}
3350

    
3351
	if($g['booting']) 
3352
		echo "done.\n";
3353
		
3354
}
3355

    
3356
function kill_traffic_collector() {
3357
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
3358
}
3359

    
3360
function update_filter_reload_status($text) {
3361
	global $g;
3362
	config_lock();
3363
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3364
	fwrite($fd, $text);
3365
	fclose($fd);
3366
	config_unlock();
3367
}
3368

    
3369
function get_interface_gateway($interface) {
3370
	global $config, $g;
3371
	$interface = strtolower($interface);
3372
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
3373
	 *  grab the address from the configuration file.
3374
	 */
3375
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
3376
	if($tmpif <> $interface)
3377
		$interface = $tmpif;
3378
	$realif = $config['interfaces'][$interface]['if'];
3379
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
3380
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3381
		$gw = rtrim($gw);
3382
	} else {
3383
		$gw = $config['interfaces'][$interface]['gateway'];
3384
	}
3385
	/* if wan is requested, return it */
3386
	if($interface == "wan")
3387
		return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
3388
	/* return gateway */
3389
	return $gw;
3390
}
3391

    
3392
function is_dhcp_server_enabled() {
3393
	/* DHCP enabled on any interfaces? */
3394
	global $config, $g;
3395
	$dhcpdcfg = $config['dhcpd'];
3396
	$dhcpdenable = false;
3397
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
3398
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3399
			$dhcpdenable = true;
3400
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3401
			$dhcpdenable = true;
3402
	}
3403
	return $dhcpdenable;
3404
}
3405

    
3406
/* return outside interfaces with a gateway */
3407
function get_interfaces_with_gateway() {
3408
	global $config;
3409
	$ints = array();
3410
	$vfaces = array(
3411
			'bridge.?*',
3412
			'ppp.?*',
3413
			'sl.?*',
3414
			'gif.?*',
3415
			'faith.?*',
3416
			'lo.?*',
3417
			'ng.?*',
3418
			'vlan.?*',
3419
			'pflog.?*',
3420
			'pfsync.?*',
3421
			'enc.?*',
3422
			'tun.?*',
3423
			'carp.?*'
3424
		);
3425
	$ifdescrs = get_interface_list("active","physical",$vfaces);
3426

    
3427
	/* loop interfaces, check config for outbound */
3428
	foreach ($ifdescrs as $ifdescr => $ifname) {
3429
		$friendly = $ifname['friendly'];
3430
		if ($config['interfaces'][$friendly]['ipaddr'] == "dhcp") {
3431
			$ints[] = $friendly;
3432
			continue;
3433
		}
3434
		if ($config['interfaces'][$friendly]['ipaddr'] == "pppoe") {
3435
			$ints[] = $friendly;
3436
			continue;
3437
		}
3438
		if ($config['interfaces'][$friendly]['ipaddr'] == "pptp") {
3439
			$ints[] = $friendly;
3440
			continue;
3441
		}
3442
		if ($config['interfaces'][$friendly]['gateway'] <> "") {
3443
			$ints[] = $friendly;
3444
			continue;
3445
		}
3446
	}
3447
	return $ints;
3448
}
3449

    
3450
/* return true if interface has a gateway */
3451
function interface_has_gateway($friendly) {
3452
	$friendly = strtolower($friendly);
3453
	if(in_array($friendly, get_interfaces_with_gateway())) {
3454
		return true;
3455
	} else {
3456
		/* extra check for real interface names if it falls through */
3457
		$friendly = convert_real_interface_to_friendly_interface_name($friendly);
3458
		return(in_array($friendly, get_interfaces_with_gateway()));
3459
	}
3460
}
3461

    
3462
/****f* pfsense-utils/isAjax
3463
 * NAME
3464
 *   isAjax - reports if the request is driven from prototype
3465
 * INPUTS
3466
 *   none
3467
 * RESULT
3468
 *   true/false
3469
 ******/
3470
function isAjax() {
3471
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
3472
}
3473

    
3474
//returns interface information
3475
function get_interface_info($ifdescr) {
3476
	global $config, $linkinfo, $netstatrninfo;
3477

    
3478
	$ifinfo = array();
3479

    
3480
	/* find out interface name */
3481
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
3482
	if ($ifdescr == "wan")
3483
		$ifinfo['if'] = get_real_wan_interface();
3484
	else
3485
		$ifinfo['if'] = $ifinfo['hwif'];
3486

    
3487
	/* run netstat to determine link info */
3488

    
3489
	unset($linkinfo);
3490
	exec("/usr/bin/netstat -I " . $ifinfo['hwif'] . " -nWb -f link", $linkinfo);
3491
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3492
	if (preg_match("/\*$/", $linkinfo[0])) {
3493
		$ifinfo['status'] = "down";
3494
	} else {
3495
		$ifinfo['status'] = "up";
3496
	}
3497

    
3498
	if (!strstr($ifinfo['if'],'tun')) {
3499
		$ifinfo['macaddr'] = $linkinfo[3];
3500
		$ifinfo['inpkts'] = $linkinfo[4];
3501
		$ifinfo['inerrs'] = $linkinfo[5];
3502
		$ifinfo['inbytes'] = $linkinfo[6];
3503
		$ifinfo['outpkts'] = $linkinfo[7];
3504
		$ifinfo['outerrs'] = $linkinfo[8];
3505
		$ifinfo['outbytes'] = $linkinfo[9];
3506
		$ifinfo['collisions'] = $linkinfo[10];
3507
	} else {
3508
		$ifinfo['inpkts'] = $linkinfo[3];
3509
		$ifinfo['inbytes'] = $linkinfo[5];
3510
		$ifinfo['outpkts'] = $linkinfo[6];
3511
		$ifinfo['outbytes'] = $linkinfo[8];
3512
	}
3513

    
3514
	/* DHCP? -> see if dhclient is up */
3515
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "dhcp")) {
3516
		/* see if dhclient is up */
3517
		if (is_dhcp_running("wan") == true)
3518
			$ifinfo['dhcplink'] = "up";
3519
		else
3520
			$ifinfo['dhcplink'] = "down";
3521
	}
3522
	/* loop through optional interfaces looking to see if they are dhcp */
3523
        for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
3524
                $ifdescrs['opt' . $j] = $config['interfaces']['opt' . $j]['descr'];
3525
                if (($ifdescr == "opt{$j}") && ($config['interfaces']['opt' . $j]['ipaddr'] == "dhcp")) {
3526
                        /* see if dhclient is up */
3527
                        if (is_dhcp_running("opt{$j}") == true)
3528
                                $ifinfo['dhcplink'] = "up";
3529
                        else
3530
                                $ifinfo['dhcplink'] = "down";
3531
                }
3532
        }
3533

    
3534
	/* PPPoE interface? -> get status from virtual interface */
3535
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pppoe")) {
3536
		unset($linkinfo);
3537
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3538
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3539
		if (preg_match("/\*$/", $linkinfo[0])) {
3540
			$ifinfo['pppoelink'] = "down";
3541
		} else {
3542
			/* get PPPoE link status for dial on demand */
3543
			$ifconfiginfo = "";
3544
			unset($ifconfiginfo);
3545
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3546

    
3547
			$ifinfo['pppoelink'] = "up";
3548

    
3549
			foreach ($ifconfiginfo as $ici) {
3550
				if (strpos($ici, 'LINK0') !== false)
3551
					$ifinfo['pppoelink'] = "down";
3552
			}
3553
		}
3554
	}
3555

    
3556
	/* PPTP interface? -> get status from virtual interface */
3557
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pptp")) {
3558
		unset($linkinfo);
3559
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3560
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3561
		if (preg_match("/\*$/", $linkinfo[0])) {
3562
			$ifinfo['pptplink'] = "down";
3563
		} else {
3564
			/* get PPTP link status for dial on demand */
3565
			unset($ifconfiginfo);
3566
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3567

    
3568
			$ifinfo['pptplink'] = "up";
3569

    
3570
			foreach ($ifconfiginfo as $ici) {
3571
				if (strpos($ici, 'LINK0') !== false)
3572
					$ifinfo['pptplink'] = "down";
3573
			}
3574
		}
3575
	}
3576

    
3577
	if ($ifinfo['status'] == "up") {
3578
		/* try to determine media with ifconfig */
3579
		unset($ifconfiginfo);
3580
		exec("/sbin/ifconfig " . $ifinfo['hwif'], $ifconfiginfo);
3581
		$matches = "";
3582
		foreach ($ifconfiginfo as $ici) {
3583

    
3584
			/* don't list media/speed for wireless cards, as it always
3585
			   displays 2 Mbps even though clients can connect at 11 Mbps */
3586
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
3587
				$ifinfo['media'] = $matches[1];
3588
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
3589
				$ifinfo['media'] = $matches[1];
3590
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
3591
				$ifinfo['media'] = $matches[1];
3592
			}
3593

    
3594
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
3595
				if ($matches[1] != "active")
3596
					$ifinfo['status'] = $matches[1];
3597
			}
3598
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
3599
				$ifinfo['channel'] = $matches[1];
3600
			}
3601
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
3602
				if ($matches[1][0] == '"')
3603
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
3604
				else
3605
					$ifinfo['ssid'] = $matches[1];
3606
			}
3607
		}
3608

    
3609
		if ($ifinfo['pppoelink'] != "down" && $ifinfo['pptplink'] != "down") {
3610
			/* try to determine IP address and netmask with ifconfig */
3611
			unset($ifconfiginfo);
3612
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3613

    
3614
			foreach ($ifconfiginfo as $ici) {
3615
				if (preg_match("/inet (\S+)/", $ici, $matches)) {
3616
					$ifinfo['ipaddr'] = $matches[1];
3617
				}
3618
				if (preg_match("/netmask (\S+)/", $ici, $matches)) {
3619
					if (preg_match("/^0x/", $matches[1]))
3620
						$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
3621
				}
3622
			}
3623

    
3624
			if ($ifdescr == "wan") {
3625
				/* run netstat to determine the default gateway */
3626
				unset($netstatrninfo);
3627
				exec("/usr/bin/netstat -rnf inet", $netstatrninfo);
3628

    
3629
				foreach ($netstatrninfo as $nsr) {
3630
					if (preg_match("/^default\s*(\S+)/", $nsr, $matches)) {
3631
						$ifinfo['gateway'] = $matches[1];
3632
					}
3633
				}
3634
			} else {
3635
				/* deterimine interface gateway */
3636
				$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3637
				$gw = get_interface_gateway($int);
3638
				if($gw)
3639
					$ifinfo['gateway'] = $gw;
3640
			}
3641
		}
3642
	}
3643

    
3644
	$bridge = "";
3645
	$int = "";
3646
	$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3647
	$bridge = link_int_to_bridge_interface($int);
3648
	if($bridge) {
3649
		$bridge_text = `/sbin/ifconfig {$bridge}`;
3650
		if(stristr($bridge_text, "blocking") <> false) {
3651
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
3652
			$ifinfo['bridgeint'] = $bridge;
3653
		} else if(stristr($bridge_text, "learning") <> false) {
3654
			$ifinfo['bridge'] = "learning";
3655
			$ifinfo['bridgeint'] = $bridge;
3656
		} else if(stristr($bridge_text, "forwarding") <> false) {
3657
			$ifinfo['bridge'] = "forwarding";
3658
			$ifinfo['bridgeint'] = $bridge;
3659
		}
3660
	}
3661

    
3662
	return $ifinfo;
3663
}
3664

    
3665
//returns cpu speed of processor. Good for determining capabilities of machine
3666
function get_cpu_speed() {
3667
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
3668
}
3669

    
3670
/* check if the wan interface is up
3671
 * Wait for a maximum of 10 seconds
3672
 * If the interface is up before then continue
3673
 */
3674
function is_wan_interface_up($interface) {
3675
	global $g;
3676
	global $config;
3677
	$i = 0;
3678
	while($i < 10) {
3679
		if(get_interface_gateway($interface)) {
3680
			return true;
3681
		} else {
3682
			sleep(1);
3683
		}
3684
		$i++;
3685
	}
3686
	return false;
3687
}
3688
?>
(15-15/29)