Project

General

Profile

Download (112 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/pfsense-utils
3
 * NAME
4
 *   pfsense-utils.inc - Utilities specific to pfSense
5
 * DESCRIPTION
6
 *   This include contains various pfSense specific functions.
7
 * HISTORY
8
 *   $Id$
9
 ******
10
 *
11
 * Copyright (C) 2004-2006 Scott Ullrich (sullrich@gmail.com)
12
 * All rights reserved.
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *
16
 * 1. Redistributions of source code must retain the above copyright notice,
17
 * this list of conditions and the following disclaimer.
18
 *
19
 * 2. Redistributions in binary form must reproduce the above copyright
20
 * notice, this list of conditions and the following disclaimer in the
21
 * documentation and/or other materials provided with the distribution.
22
 *
23
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
27
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
 * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 * POSSIBILITY OF SUCH DAMAGE.
33
 *
34
 */
35
 
36
 /****f* pfsense-utils/does_url_exist
37
 * NAME
38
 *   does_url_exist
39
 * INPUTS
40
 *	 none
41
 * RESULT
42
 *   returns true if a url is available
43
 ******/
44
function does_url_exist($url) {
45
	$fd = fopen("$url","r");
46
	if($fd) {
47
		fclose($fd);
48
   		return true;    
49
	} else {
50
        return false;
51
	}
52
}
53

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

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

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

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

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

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

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

    
166
		$int = "";
167

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

    
171
		$curwanip = get_current_wan_address();
172

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
362
			}
363

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

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

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

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

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

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

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

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

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

    
506
	tdr_get_next_ipfw_rule();
507

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

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

    
519
	return $line;
520

    
521
}
522

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
857
/****f* pfsense-utils/setup_glxsb
858
 * NAME
859
 *   setup_glxsb - loads or unloads glxsb module as needed
860
 * INPUTS
861
 *   null
862
 * RESULT
863
 *   null
864
 ******/
865
function setup_glxsb() {
866
        global $config, $g;
867
        $is_loaded = `/sbin/kldstat | /usr/bin/grep -c glxsb`;
868
        if (!isset($config['system']['disableglxsb']) && ($is_loaded == 0)) {
869
                mwexec("/sbin/kldload glxsb");
870
        } elseif (isset($config['system']['disableglxsb']) && ($is_loaded > 0)) {
871
                mwexec("/sbin/kldunload glxsb");
872
        }
873
        
874
}
875

    
876
/****f* pfsense-utils/return_dir_as_array
877
 * NAME
878
 *   return_dir_as_array - Return a directory's contents as an array.
879
 * INPUTS
880
 *   $dir	- string containing the path to the desired directory.
881
 * RESULT
882
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
883
 ******/
884
function return_dir_as_array($dir) {
885
	$dir_array = array();
886
	if (is_dir($dir)) {
887
		if ($dh = opendir($dir)) {
888
			while (($file = readdir($dh)) !== false) {
889
				$canadd = 0;
890
				if($file == ".") $canadd = 1;
891
				if($file == "..") $canadd = 1;
892
				if($canadd == 0)
893
					array_push($dir_array, $file);
894
			}
895
			closedir($dh);
896
		}
897
	}
898
	return $dir_array;
899
}
900

    
901
/****f* pfsense-utils/enable_hardware_offloading
902
 * NAME
903
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
904
 * INPUTS
905
 *   $interface	- string containing the physical interface to work on.
906
 * RESULT
907
 *   null
908
 * NOTES
909
 *   This function only supports the fxp driver's loadable microcode.
910
 ******/
911
function enable_hardware_offloading($interface) {
912
	global $g, $config;
913

    
914
	if(stristr($interface,"lnc"))
915
		return;
916

    
917
	/* translate wan, lan, opt -> real interface if needed */
918
	$int = filter_translate_type_to_real_interface($interface);
919
	if($int <> "") $interface = $int;
920
	$int_family = preg_split("/[0-9]+/", $int);
921
	$options = strtolower(`/sbin/ifconfig -m {$interface} | grep capabilities`);
922
	$supported_ints = array('fxp');
923
	if (in_array($int_family, $supported_ints)) {
924
        	if(isset($config['system']['do_not_use_nic_microcode']))
925
                        continue;
926
		mwexec("/sbin/ifconfig {$interface} link0");
927
        }
928

    
929
	/* skip vlans for checksumming and polling */
930
	if(stristr($interface, "vlan")) 
931
		return;
932

    
933
	if($config['system']['disablechecksumoffloading']) {
934
                if(stristr($options, "txcsum") == true)
935
                        mwexec("/sbin/ifconfig {$interface} -txcsum 2>/dev/null");
936
                if(stristr($options, "rxcsum") == true)
937
                        mwexec("/sbin/ifconfig {$interface} -rxcsum 2>/dev/null");
938
	} else {
939
               	if(stristr($options, "txcsum") == true)
940
                        mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
941
        	if(stristr($options, "rxcsum") == true)
942
                        mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
943
        }
944

    
945
	/* if the NIC supports polling *AND* it is enabled in the GUI */
946
	if(interface_supports_polling($interface)) {
947
		$polling = isset($config['system']['polling']);	
948
		if($polling) {
949
			mwexec("sysctl kern.polling.enable=1");
950
                        mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
951
		} else {
952
			mwexec("sysctl kern.polling.enable=0");
953
		}
954
	}
955
	return;
956
}
957

    
958
/****f* pfsense-utils/interface_supports_polling
959
 * NAME
960
 *   checks to see if an interface supports polling according to man polling
961
 * INPUTS
962
 *
963
 * RESULT
964
 *   true or false
965
 * NOTES
966
 *
967
 ******/
968
function interface_supports_polling($iface) {
969
	$pattern = '/([a-z].*)[0-9]/';
970
	preg_match($pattern, $iface, $iface2);
971
	$interface=$iface2[1];
972
	$supported_ints = array("bge",
973
		"dc",
974
		"em",
975
		"fwe",
976
		"fwip",
977
		"fxp",
978
		"ixgb",
979
		"nfe",
980
		"vge",
981
		"re",
982
		"rl",
983
		"sf",
984
		"sis",
985
		"ste",
986
		"stge",    
987
		"vge",
988
		"vr",
989
		"xl");
990
	if(in_array($interface, $supported_ints))
991
		return true;
992
	return false;
993
}
994

    
995
/****f* pfsense-utils/is_alias_inuse
996
 * NAME
997
 *   checks to see if an alias is currently in use by a rule
998
 * INPUTS
999
 *
1000
 * RESULT
1001
 *   true or false
1002
 * NOTES
1003
 *
1004
 ******/
1005
function is_alias_inuse($alias) {
1006
	global $g, $config;
1007

    
1008
	if($alias == "") return false;
1009
	/* loop through firewall rules looking for alias in use */
1010
	if(is_array($config['filter']['rule']))
1011
		foreach($config['filter']['rule'] as $rule) {
1012
			if($rule['source']['address'])
1013
				if($rule['source']['address'] == $alias)
1014
					return true;
1015
			if($rule['destination']['address'])
1016
				if($rule['destination']['address'] == $alias)
1017
					return true;
1018
		}
1019
	/* loop through nat rules looking for alias in use */
1020
	if(is_array($config['nat']['rule']))
1021
		foreach($config['nat']['rule'] as $rule) {
1022
			if($rule['target'] == $alias)
1023
				return true;
1024
			if($rule['external-address'] == $alias)
1025
				return true;
1026
		}
1027
	return false;
1028
}
1029

    
1030
/****f* pfsense-utils/is_schedule_inuse
1031
 * NAME
1032
 *   checks to see if a schedule is currently in use by a rule
1033
 * INPUTS
1034
 *
1035
 * RESULT
1036
 *   true or false
1037
 * NOTES
1038
 *
1039
 ******/
1040
function is_schedule_inuse($schedule) {
1041
	global $g, $config;
1042

    
1043
	if($schedule == "") return false;
1044
	/* loop through firewall rules looking for schedule in use */
1045
	if(is_array($config['filter']['rule']))
1046
		foreach($config['filter']['rule'] as $rule) {
1047
			if($rule['sched'] == $schedule)
1048
				return true;
1049
		}
1050
	return false;
1051
}
1052

    
1053
/****f* pfsense-utils/setup_polling_defaults
1054
 * NAME
1055
 *   sets up sysctls for pollingS
1056
 * INPUTS
1057
 *
1058
 * RESULT
1059
 *   null
1060
 * NOTES
1061
 *
1062
 ******/
1063
function setup_polling_defaults() {
1064
	global $g, $config;
1065
	if($config['system']['polling_each_burst'])
1066
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
1067
	if($config['system']['polling_burst_max'])
1068
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
1069
	if($config['system']['polling_user_frac'])
1070
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
1071
}
1072

    
1073
/****f* pfsense-utils/setup_polling
1074
 * NAME
1075
 *   sets up polling
1076
 * INPUTS
1077
 *
1078
 * RESULT
1079
 *   null
1080
 * NOTES
1081
 *
1082
 ******/
1083
function setup_polling() {
1084
	global $g, $config;
1085

    
1086
	setup_polling_defaults();
1087

    
1088
	$supported_ints = array('bge', 'dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'nfe', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'stge', 'vge', 'vr', 'xl');
1089

    
1090
	/* build an array of interfaces to work with */
1091
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1092
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1093
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1094

    
1095
	foreach ($iflist as $ifent => $ifname) {
1096
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
1097
		$ifdevice = substr($real_interface, 0, -1); 
1098
		if(!in_array($ifdevice, $supported_ints)) {
1099
			continue;
1100
 		}
1101
		if(isset($config['system']['polling'])) {
1102
			mwexec("/sbin/ifconfig {$real_interface} polling");
1103
			mwexec("/sbin/sysctl kern.polling.idle_poll=1");
1104
		} else {
1105
			mwexec("/sbin/ifconfig {$real_interface} -polling");
1106
		}
1107
	}
1108
}
1109

    
1110
/****f* pfsense-utils/setup_microcode
1111
 * NAME
1112
 *   enumerates all interfaces and calls enable_hardware_offloading which
1113
 *   enables a NIC's supported hardware features.
1114
 * INPUTS
1115
 *
1116
 * RESULT
1117
 *   null
1118
 * NOTES
1119
 *   This function only supports the fxp driver's loadable microcode.
1120
 ******/
1121
function setup_microcode() {
1122
	global $config;
1123

    
1124
	$ifdescrs = array('wan', 'lan');
1125
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1126
		$ifdescrs['opt' . $j] = "opt" . $j;
1127
	}
1128
	foreach($ifdescrs as $if)
1129
		enable_hardware_offloading($if);
1130
}
1131

    
1132
/****f* pfsense-utils/return_filename_as_array
1133
 * NAME
1134
 *   return_filename_as_array - Return a file's contents as an array.
1135
 * INPUTS
1136
 *   $filename	- string containing the path to the desired file.
1137
 *   $strip	- array of characters to strip - default is '#'.
1138
 * RESULT
1139
 *   $file	- array containing the file's contents.
1140
 * NOTES
1141
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
1142
 ******/
1143
function return_filename_as_array($filename, $strip = array('#')) {
1144
	if(file_exists($filename)) $file = file($filename);
1145
	if(is_array($file)) {
1146
		foreach($file as $line) $line = trim($line);
1147
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
1148
	}
1149
	return $file;
1150
}
1151

    
1152
/****f* pfsense-utils/file_put_contents
1153
 * NAME
1154
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
1155
 * RESULT
1156
 *   none
1157
 ******/
1158
if(!function_exists("file_put_contents")) {
1159
	function file_put_contents($filename, $data) {
1160
		$fd = fopen($filename,"w");
1161
		fwrite($fd, $data);
1162
		fclose($fd);
1163
	}
1164
}
1165

    
1166
/****f* pfsense-utils/get_carp_status
1167
 * NAME
1168
 *   get_carp_status - Return whether CARP is enabled or disabled.
1169
 * RESULT
1170
 *   boolean	- true if CARP is enabled, false if otherwise.
1171
 ******/
1172
function get_carp_status() {
1173
    /* grab the current status of carp */
1174
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
1175
    if(intval($status) == "0") return false;
1176
    return true;
1177
}
1178

    
1179
/****f* pfsense-utils/is_carp_defined
1180
 * NAME
1181
 *   is_carp_defined - Return whether CARP is detected in the kernel.
1182
 * RESULT
1183
 *   boolean	- true if CARP is detected, false otherwise.
1184
 ******/
1185
function is_carp_defined() {
1186
	/* is carp compiled into the kernel and userland? */
1187
	$command = "/sbin/sysctl -a | grep carp";
1188
	$fd = popen($command . " 2>&1 ", "r");
1189
	if(!$fd) {
1190
		log_error("Warning, could not execute command {$command}");
1191
		return 0;
1192
	}
1193
	while(!feof($fd)) {
1194
		$tmp .= fread($fd,49);
1195
	}
1196
	fclose($fd);
1197

    
1198
	if($tmp == "")
1199
		return false;
1200
	else
1201
		return true;
1202
}
1203

    
1204
/****f* pfsense-utils/get_interface_mtu
1205
 * NAME
1206
 *   get_interface_mtu - Return the mtu of an interface
1207
 * RESULT
1208
 *   $tmp	- Returns the mtu of an interface
1209
 ******/
1210
function get_interface_mtu($interface) {
1211
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f6`;
1212
	return $mtu;
1213
}
1214

    
1215
/****f* pfsense-utils/is_interface_wireless
1216
 * NAME
1217
 *   is_interface_wireless - Returns if an interface is wireless
1218
 * RESULT
1219
 *   $tmp	- Returns if an interface is wireless
1220
 ******/
1221
function is_interface_wireless($interface) {
1222
	global $config, $g;
1223
	$interface = convert_real_interface_to_friendly_interface_name($interface);
1224
	if(isset($config['interfaces'][$interface]['wireless']))
1225
		return true;
1226
	else
1227
		return false;
1228
}
1229

    
1230
/****f* pfsense-utils/find_number_of_created_carp_interfaces
1231
 * NAME
1232
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
1233
 * RESULT
1234
 *   $tmp	- Number of currently created CARP interfaces.
1235
 ******/
1236
function find_number_of_created_carp_interfaces($flush = false) {
1237
	global $carp_interface_count_cache;
1238

    
1239
	if (!isset($carp_interface_count_cache) or $flush) {
1240
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
1241
		$fd = popen($command . " 2>&1 ", "r");
1242
		if(!$fd) {
1243
			log_error("Warning, could not execute command {$command}");
1244
			return 0;
1245
		}
1246
		while(!feof($fd)) {
1247
			$tmp .= fread($fd,49);
1248
		}
1249
		fclose($fd);
1250
		$carp_interface_count_cache = intval($tmp);
1251
	}
1252
	return $carp_interface_count_cache;
1253
}
1254

    
1255
/****f* pfsense-utils/link_int_to_bridge_interface
1256
 * NAME
1257
 *   link_int_to_bridge_interface - Finds out a bridge group for an interface
1258
 * INPUTS
1259
 *   $ip
1260
 * RESULT
1261
 *   bridge[0-99]
1262
 ******/
1263
function link_int_to_bridge_interface($int) {
1264
	global $config, $g;
1265
	$real_int = convert_friendly_interface_to_real_interface_name($int);
1266
	$num_bridges = find_number_of_created_bridges();
1267
	for($x=0; $x<$num_bridges; $x++) {
1268
		$matches = "";
1269
		$bridge_info = `/sbin/ifconfig bridge{$x}`;
1270
		if(stristr($bridge_info, "member: {$real_int}")) {
1271
			return "bridge{$x}";
1272
		}
1273
	}
1274
}
1275

    
1276
function link_carp_interface_to_parent($interface) {
1277
	global $config;
1278
	if($interface == "") return;
1279

    
1280
	$ifdescrs = array("wan" => "wan", "lan" => "lan");
1281
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1282
		$ifdescrs['opt' . $j] = "opt" . $j;
1283

    
1284
	$carp_int = $interface;
1285
	$carp_ip = find_interface_ip($interface);
1286
	$carp_subnet = find_virtual_ip_netmask($carp_ip);
1287
	$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1288
	$carp_ints = "";
1289
	$num_carp_ints = find_number_of_created_carp_interfaces();
1290

    
1291
	foreach ($ifdescrs as $ifdescr => $ifname) {
1292
		if(interface_has_gateway($ifname)) {
1293
			$interfaceip = $config['interfaces'][$ifname]['ipaddr'];
1294
			$subnet_bits = $config['interfaces'][$ifname]['subnet'];
1295
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
1296
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}")) {
1297
				return $ifname;
1298
			}
1299
		}
1300
	}
1301
	return $carp_ints;
1302
}
1303

    
1304
/****f* pfsense-utils/link_ip_to_carp_interface
1305
 * NAME
1306
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
1307
 * INPUTS
1308
 *   $ip
1309
 * RESULT
1310
 *   $carp_ints
1311
 ******/
1312
function link_ip_to_carp_interface($ip) {
1313
	global $config;
1314
	if($ip == "") return;
1315

    
1316
	$ifdescrs = array('wan', 'lan');
1317
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1318
		$ifdescrs['opt' . $j] = "opt" . $j;
1319

    
1320
	$ft = split("\.", $ip);
1321
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
1322

    
1323
	$carp_ints = "";
1324
	$num_carp_ints = find_number_of_created_carp_interfaces();
1325
	foreach ($ifdescrs as $ifdescr => $ifname) {
1326
		for($x=0; $x<$num_carp_ints; $x++) {
1327
			$carp_int = "carp{$x}";
1328
			$carp_ip = find_interface_ip($carp_int);
1329
			$carp_subnet = find_virtual_ip_netmask($carp_ip);
1330
			$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1331
			if(ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
1332
				if(!stristr($carp_ints, $carp_int))
1333
					$carp_ints .= " " . $carp_int;
1334
		}
1335
	}
1336
	return $carp_ints;
1337
}
1338

    
1339
/****f* pfsense-utils/find_virtual_ip_netmask
1340
 * NAME
1341
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
1342
 * INPUTS
1343
 *   $ip - ip address to locate subnet mask of
1344
 * RESULT
1345
 *   String containing the command's result.
1346
 * NOTES
1347
 *   This function returns the command's stdout and stderr.
1348
 ******/
1349
function find_virtual_ip_netmask($ip) {
1350
        global $config;
1351
        foreach($config['virtualip']['vip'] as $vip) {
1352
                if($ip == $vip['subnet'])
1353
                        return $vip['subnet_bits'];
1354
        }
1355
}
1356

    
1357
/****f* pfsense-utils/exec_command
1358
 * NAME
1359
 *   exec_command - Execute a command and return a string of the result.
1360
 * INPUTS
1361
 *   $command	- String of the command to be executed.
1362
 * RESULT
1363
 *   String containing the command's result.
1364
 * NOTES
1365
 *   This function returns the command's stdout and stderr.
1366
 ******/
1367
function exec_command($command) {
1368
	$output = array();
1369
	exec($command . ' 2>&1 ', $output);
1370
	return(implode("\n", $output));
1371
}
1372

    
1373
/****f* interfaces/is_jumbo_capable
1374
 * NAME
1375
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
1376
 * INPUTS
1377
 *   $int             - string containing interface name
1378
 * RESULT
1379
 *   boolean          - true or false
1380
 ******/
1381
function is_jumbo_capable($int) {
1382
	/* Per:
1383
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
1384
	 * Only the following drivers support large frames
1385
         *
1386
	 * 'de' chipset purposely left out of this list
1387
	 * requires defining BIG_PACKET in the
1388
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
1389
	 * kernel or module.  The hack works only for the 21041,
1390
	 * 21140, and 21140A chips.
1391
	 */
1392
	global $g;
1393

    
1394
	$capable = $g['vlan_long_frame'];
1395

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

    
1398
	if (in_array($int_family[0], $capable))
1399
		return true;
1400
	else
1401
		return false;
1402
}
1403

    
1404
/*
1405
 * Return the interface array
1406
 */
1407
function get_interface_arr($flush = false) {
1408
	global $interface_arr_cache;
1409

    
1410
	/* If the cache doesn't exist, build it */
1411
	if (!isset($interface_arr_cache) or $flush)
1412
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
1413

    
1414
	return $interface_arr_cache;
1415
}
1416

    
1417
/*
1418
 * does_interface_exist($interface): return true or false if a interface is
1419
 * detected.
1420
 */
1421
function does_interface_exist($interface) {
1422
	if(!$interface) 
1423
		return false;
1424
	$ints = get_interface_arr();
1425

    
1426
	if(stristr($ints, $interface) !== false)
1427
		return true;
1428
	else
1429
		return false;
1430
}
1431

    
1432
/*
1433
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
1434
 */
1435
function convert_ip_to_network_format($ip, $subnet) {
1436
	$ipsplit = split('[.]', $ip);
1437
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
1438
	return $string;
1439
}
1440

    
1441
/*
1442
 * find_interface_ip($interface): return the interface ip (first found)
1443
 */
1444
function find_interface_ip($interface, $flush = false) {
1445
	global $interface_ip_arr_cache;
1446
	$interface = str_replace("\n", "", $interface);
1447
	if(does_interface_exist($interface) == false) return;
1448
	/* Setup IP cache */
1449
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
1450
		$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");
1451
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
1452
	}
1453

    
1454
	return $interface_ip_arr_cache[$interface];
1455
}
1456

    
1457
function guess_interface_from_ip($ipaddress) {
1458
        exec("netstat -rn", $output, $ret);
1459
        foreach($output as $line) {
1460
                if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
1461
                        $fields = preg_split("/[ ]+/", $line);
1462
                        if(ip_in_subnet($ipaddress, $fields[0])) {
1463
                                return $fields[5];
1464
                        }
1465
                }
1466
        }
1467
        $ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
1468
        if(empty($ret)) {
1469
                return false;
1470
        }
1471
        return $ret;
1472
}
1473

    
1474
function filter_opt_interface_to_real($opt) {
1475
	global $config;
1476
	return $config['interfaces'][$opt]['if'];
1477
}
1478

    
1479
function filter_get_opt_interface_descr($opt) {
1480
	global $config;
1481
	return $config['interfaces'][$opt]['descr'];
1482
}
1483

    
1484
function get_friendly_interface_list_as_array() {
1485
	global $config;
1486
	$ints = array();
1487
	$ifdescrs = get_interface_list();
1488
	foreach ($ifdescrs as $ifdescr => $ifname) {
1489
		array_push($ints,$ifdescr);
1490
	}
1491
	return $ints;
1492
}
1493

    
1494
/*
1495
 * find_ip_interface($ip): return the interface where an ip is defined
1496
 */
1497
function find_ip_interface($ip) {
1498
	global $config;
1499
	$ifdescrs = array('wan', 'lan');
1500
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1501
		$ifdescrs['opt' . $j] = "opt" . $j;
1502
	}
1503
	foreach ($ifdescrs as $ifdescr => $ifname) {
1504
		$int = filter_translate_type_to_real_interface($ifname);
1505
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
1506
	if(stristr($ifconfig,$ip) <> false)
1507
		return $int;
1508
	}
1509
	return false;
1510
}
1511

    
1512
/*
1513
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
1514
 *                                                       for a friendly interface.  ie: wan
1515
 */
1516
function filter_translate_type_to_real_interface($interface) {
1517
	global $config;
1518
	if($config['interfaces'][$interface]['if'] <> "") {
1519
		return $config['interfaces'][$interface]['if'];
1520
	} else {
1521
		return $interface;
1522
	}
1523
}
1524

    
1525
/*
1526
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
1527
 */
1528
function get_carp_interface_status($carpinterface) {
1529
	/* basically cache the contents of ifconfig statement
1530
	to speed up this routine */
1531
	global $carp_query;
1532
	if($carp_query == "")
1533
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
1534
	$found_interface = 0;
1535
	foreach($carp_query as $int) {
1536
		if($found_interface == 1) {
1537
			if(stristr($int, "MASTER")) return "MASTER";
1538
			if(stristr($int, "BACKUP")) return "BACKUP";
1539
			if(stristr($int, "INIT")) return "INIT";
1540
			return false;
1541
		}
1542
		if(stristr($int, $carpinterface) == true)
1543
		$found_interface=1;
1544
	}
1545
	return;
1546
}
1547

    
1548
/*
1549
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
1550
 */
1551
function get_pfsync_interface_status($pfsyncinterface) {
1552
    $result = does_interface_exist($pfsyncinterface);
1553
    if($result <> true) return;
1554
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
1555
    return $status;
1556
}
1557

    
1558
/*
1559
 * find_carp_interface($ip): return the carp interface where an ip is defined
1560
 */
1561
function find_carp_interface($ip) {
1562
	global $find_carp_ifconfig;
1563
	if($find_carp_ifconfig == "") {
1564
		$find_carp_ifconfig = array();
1565
		$num_carp_ints = find_number_of_created_carp_interfaces();
1566
		for($x=0; $x<$num_carp_ints; $x++) {
1567
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
1568
		}
1569
	}
1570
	$carps = 0;
1571
	foreach($find_carp_ifconfig as $fci) {
1572
		if(stristr($fci, $ip . " ") == true)		
1573
			return "carp{$carps}";
1574
		$carps++;
1575
	}
1576
}
1577

    
1578
/*
1579
 * setup_filter_bridge(): toggle filtering bridge
1580
 *
1581
 * disabled 20080805 - this is of no use with if_bridge, in the sense it was
1582
 * with m0n0 (where this came from)
1583
 * --cmb
1584
function setup_filter_bridge() {
1585
	global $config, $g;
1586
	if(isset($config['bridge']['filteringbridge'])) {
1587
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
1588
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
1589
	} else {
1590
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
1591
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
1592
	}
1593
}
1594
*/
1595

    
1596
/*
1597
 * find_number_of_created_bridges(): returns the number of currently created bridges
1598
 */
1599
function find_number_of_created_bridges($flush = false) {
1600
	global $bridge_interface_count_cache;
1601
	if(!isset($bridge_interface_count_cache) or $flush)
1602
		$bridge_interface_count_cache = exec_command('/sbin/ifconfig | /usr/bin/grep "bridge[0-999]" | /usr/bin/wc -l');
1603

    
1604
	return $bridge_interface_count_cache;
1605
}
1606

    
1607
/*
1608
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
1609
 */
1610
function add_rule_to_anchor($anchor, $rule, $label) {
1611
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
1612
}
1613

    
1614
/*
1615
 * remove_text_from_file
1616
 * remove $text from file $file
1617
 */
1618
function remove_text_from_file($file, $text) {
1619
	global $fd_log;
1620
	if($fd_log)
1621
		fwrite($fd_log, "Adding needed text items:\n");
1622
	$filecontents = file_get_contents($file);
1623
	$textTMP = str_replace($text, "", $filecontents);
1624
	$text = $textTMP;
1625
	if($fd_log)
1626
		fwrite($fd_log, $text);
1627
	$fd = fopen($file, "w");
1628
	fwrite($fd, $text);
1629
	fclose($fd);
1630
}
1631

    
1632
/*
1633
 * add_text_to_file($file, $text): adds $text to $file.
1634
 * replaces the text if it already exists.
1635
 */
1636
function add_text_to_file($file, $text) {
1637
	if(file_exists($file) and is_writable($file)) {
1638
		$filecontents = split("\n", file_get_contents($file));
1639
		$fout = fopen($file, "w");
1640
		$new_file_text = "";
1641
		foreach($filecontents as $line) {
1642
			if($line)
1643
				$new_file_text .= rtrim($line) . "\n";
1644
		}
1645
		$new_file_text .= $text . "\n";
1646
		$file_text = str_replace("\n\n", "\n", $new_file_text);
1647
		fwrite($fout, $file_text);
1648
		fclose($fout);
1649
		return true;
1650
	} else {
1651
		return false;
1652
	}
1653
}
1654

    
1655
/*
1656
 *   after_sync_bump_adv_skew(): create skew values by 1S
1657
 */
1658
function after_sync_bump_adv_skew() {
1659
	global $config, $g;
1660
	$processed_skew = 1;
1661
	$a_vip = &$config['virtualip']['vip'];
1662
	foreach ($a_vip as $vipent) {
1663
		if($vipent['advskew'] <> "") {
1664
			$processed_skew = 1;
1665
			$vipent['advskew'] = $vipent['advskew']+1;
1666
		}
1667
	}
1668
	if($processed_skew == 1)
1669
		write_config("After synch increase advertising skew");
1670
}
1671

    
1672
/*
1673
 * get_filename_from_url($url): converts a url to its filename.
1674
 */
1675
function get_filename_from_url($url) {
1676
	return basename($url);
1677
}
1678

    
1679
/*
1680
 *   update_output_window: update bottom textarea dynamically.
1681
 */
1682
function update_output_window($text) {
1683
	global $pkg_interface;
1684
	$log = ereg_replace("\n", "\\n", $text);
1685
	if($pkg_interface == "console") {
1686
		/* too chatty */
1687
	} else {
1688
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1689
	}
1690
	/* ensure that contents are written out */
1691
	ob_flush();
1692
}
1693

    
1694
/*
1695
 *   get_dir: return an array of $dir
1696
 */
1697
function get_dir($dir) {
1698
	$dir_array = array();
1699
	$d = dir($dir);
1700
	while (false !== ($entry = $d->read())) {
1701
		array_push($dir_array, $entry);
1702
	}
1703
	$d->close();
1704
	return $dir_array;
1705
}
1706

    
1707
/*
1708
 *   update_output_window: update top textarea dynamically.
1709
 */
1710
function update_status($status) {
1711
	global $pkg_interface;
1712
	if($pkg_interface == "console") {
1713
		echo $status . "\n";
1714
	} else {
1715
		echo "\n<script type=\"text/javascript\">document.forms[0].status.value=\"" . $status . "\";</script>";
1716
	}
1717
	/* ensure that contents are written out */
1718
	ob_flush();
1719
}
1720

    
1721
/*
1722
 *   exec_command_and_return_text_array: execute command and return output
1723
 */
1724
function exec_command_and_return_text_array($command) {
1725
	$fd = popen($command . " 2>&1 ", "r");
1726
	while(!feof($fd)) {
1727
		$tmp .= fread($fd,49);
1728
	}
1729
	fclose($fd);
1730
	$temp_array = split("\n", $tmp);
1731
	return $temp_array;
1732
}
1733

    
1734
/*
1735
 *   exec_command_and_return_text: execute command and return output
1736
 */
1737
function exec_command_and_return_text($command) {
1738
	return exec_command($command);
1739
}
1740

    
1741
/*
1742
 *   exec_command_and_return_text: execute command and update output window dynamically
1743
 */
1744
function execute_command_return_output($command) {
1745
	global $fd_log, $pkg_interface;
1746
	$fd = popen($command . " 2>&1 ", "r");
1747
	if($pkg_interface <> "console") {
1748
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1749
	}
1750
	$counter = 0;
1751
	$counter2 = 0;
1752
	while(!feof($fd)) {
1753
		$tmp = fread($fd, 50);
1754
		$tmp1 = ereg_replace("\n","\\n", $tmp);
1755
		$text = ereg_replace("\"","'", $tmp1);
1756
		$lasttext = "";
1757
		if($lasttext == "..") {
1758
			$text = "";
1759
			$lasttext = "";
1760
			$counter=$counter-2;
1761
		} else {
1762
			$lasttext .= $text;
1763
		}
1764
		if($counter > 51) {
1765
			$counter = 0;
1766
			$extrabreak = "\\n";
1767
		} else {
1768
	    $extrabreak = "";
1769
	    $counter++;
1770
		}
1771
		if($counter2 > 600) {
1772
			if($pkg_interface <> "console") {
1773
				echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1774
			}
1775
			$counter2 = 0;
1776
		} else
1777
			$counter2++;
1778
		if($pkg_interface <> "console") {
1779
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
1780
		}
1781
	}
1782
	fclose($fd);
1783
}
1784

    
1785
/*
1786
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
1787
 */
1788
function convert_friendly_interface_to_real_interface_name($interface) {
1789
	global $config;
1790
	if($config['interfaces'][$interface]['ipaddr'] == "pppoe" or $config['interfaces'][$interface]['ipaddr'] == "pptp")
1791
		return "ng0";
1792
	$lc_interface = strtolower($interface);
1793
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
1794
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
1795
	$ifdescrs = array();
1796
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1797
		$ifdescrs['opt' . $j] = "opt" . $j;
1798
	foreach ($ifdescrs as $ifdescr => $ifname) {
1799
		if(strtolower($ifname) == $lc_interface)
1800
	    return $config['interfaces'][$ifname]['if'];
1801
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
1802
			return $config['interfaces'][$ifname]['if'];
1803
   }
1804
   return $interface;
1805
}
1806

    
1807
/*
1808
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
1809
 */
1810
function convert_real_interface_to_friendly_interface_name($interface) {
1811
	global $config;
1812
	$ifdescrs = array('wan', 'lan');
1813
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1814
		$ifdescrs['opt' . $j] = "opt" . $j;
1815
	foreach ($ifdescrs as $ifdescr => $ifname) {
1816
		if($config['interfaces']['$ifname']['if'] == $interface)
1817
			return $ifname;
1818
		$int = filter_translate_type_to_real_interface($ifname);
1819
		if($ifname == $interface) return $ifname;
1820
		if($int == $interface) return $ifname;
1821
	}
1822
	return $interface;
1823
}
1824

    
1825
/*
1826
 * update_progress_bar($percent): updates the javascript driven progress bar.
1827
 */
1828
function update_progress_bar($percent) {
1829
	global $pkg_interface;
1830
	if($percent > 100) $percent = 1;
1831
	if($pkg_interface <> "console") {
1832
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1833
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1834
		echo "\n</script>";
1835
	} else {
1836
		echo " {$percent}%";
1837
	}
1838
}
1839

    
1840
/****f* pfsense-utils/WakeOnLan
1841
 * NAME
1842
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
1843
 * RESULT
1844
 *   true/false - true if the operation was successful
1845
 ******/
1846
function WakeOnLan($addr, $mac)
1847
{
1848
	$addr_byte = explode(':', $mac);
1849
	$hw_addr = '';
1850

    
1851
	for ($a=0; $a < 6; $a++)
1852
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1853

    
1854
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1855

    
1856
	for ($a = 1; $a <= 16; $a++)
1857
		$msg .= $hw_addr;
1858

    
1859
	// send it to the broadcast address using UDP
1860
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1861
	if ($s == false) {
1862
		log_error("Error creating socket!");
1863
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
1864
	} else {
1865
		// setting a broadcast option to socket:
1866
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1867
		if($opt_ret < 0)
1868
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1869
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1870
		socket_close($s);
1871
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1872
		return true;
1873
	}
1874

    
1875
	return false;
1876
}
1877

    
1878
/*
1879
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
1880
 *                             is queuename|qlength|measured_packets
1881
 *                             NOTE: this command takes 5 seconds to run
1882
 */
1883
function gather_altq_queue_stats($dont_return_root_queues) {
1884
	mwexec("/usr/bin/killall -9 pfctl", true);
1885
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
1886
	$stats_array = split("\n", $stats);
1887
	$queue_stats = array();
1888
	foreach ($stats_array as $stats_line) {
1889
		$match_array = "";
1890
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
1891
			$queue_name = $match_array[1][0];
1892
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
1893
			$speed = $match_array[1][0];
1894
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
1895
			$borrows = $match_array[1][0];
1896
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
1897
			$suspends = $match_array[1][0];
1898
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
1899
			$drops = $match_array[1][0];
1900
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
1901
			$measured = $match_array[1][0];
1902
			if($dont_return_root_queues == true)
1903
				if(stristr($queue_name,"root_") == false)
1904
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
1905
		}
1906
	}
1907
	return $queue_stats;
1908
}
1909

    
1910
/*
1911
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1912
 *					 Useful for finding paths and stripping file extensions.
1913
 */
1914
function reverse_strrchr($haystack, $needle) {
1915
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1916
}
1917

    
1918
/*
1919
 *  backup_config_section($section): returns as an xml file string of
1920
 *                                   the configuration section
1921
 */
1922
function backup_config_section($section) {
1923
	global $config;
1924
	$new_section = &$config[$section];
1925
	/* generate configuration XML */
1926
	$xmlconfig = dump_xml_config($new_section, $section);
1927
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1928
	return $xmlconfig;
1929
}
1930

    
1931
/*
1932
 *  backup_vip_config_section($section): returns as an xml file string of
1933
 *                                   the configuration section
1934
 */
1935
function backup_vip_config_section() {
1936
	global $config;
1937
	$new_section = &$config['virtualip'];
1938
	foreach($new_section['vip'] as $section) {
1939
		if($section['mode'] == "proxyarp") {
1940
			unset($section);
1941
		}
1942
		if($section['advskew'] <> "") {
1943
			$section_val = intval($section['advskew']);
1944
			$section_val=$section_val+100;
1945
			if($section_val > 255)
1946
				$section_val = 255;
1947
			$section['advskew'] = $section_val;
1948
		}
1949
		$temp['vip'][] = $section;
1950
   }
1951
   return $temp;
1952
}
1953

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

    
1973
/*
1974
 *  merge_config_section($section, new_contents):   restore a configuration section,
1975
 *                                                  and write the configuration out
1976
 *                                                  to disk/cf.  But preserve the prior
1977
 * 													structure if needed
1978
 */
1979
function merge_config_section($section, $new_contents) {
1980
	global $config;
1981
	conf_mount_rw();
1982
	$fname = get_tmp_filename();
1983
	$fout = fopen($fname, "w");
1984
	fwrite($fout, $new_contents);
1985
	fclose($fout);
1986
	$section_xml = parse_xml_config($fname, $section);
1987
	$config[$section] = $section_xml;
1988
	unlink($fname);
1989
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1990
	conf_mount_ro();
1991
	return;
1992
}
1993

    
1994
/*
1995
 * http_post($server, $port, $url, $vars): does an http post to a web server
1996
 *                                         posting the vars array.
1997
 * written by nf@bigpond.net.au
1998
 */
1999
function http_post($server, $port, $url, $vars) {
2000
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
2001
	$urlencoded = "";
2002
	while (list($key,$value) = each($vars))
2003
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
2004
	$urlencoded = substr($urlencoded,0,-1);
2005
	$content_length = strlen($urlencoded);
2006
	$headers = "POST $url HTTP/1.1
2007
Accept: */*
2008
Accept-Language: en-au
2009
Content-Type: application/x-www-form-urlencoded
2010
User-Agent: $user_agent
2011
Host: $server
2012
Connection: Keep-Alive
2013
Cache-Control: no-cache
2014
Content-Length: $content_length
2015

    
2016
";
2017

    
2018
	$errno = "";
2019
	$errstr = "";
2020
	$fp = fsockopen($server, $port, $errno, $errstr);
2021
	if (!$fp) {
2022
		return false;
2023
	}
2024

    
2025
	fputs($fp, $headers);
2026
	fputs($fp, $urlencoded);
2027

    
2028
	$ret = "";
2029
	while (!feof($fp))
2030
		$ret.= fgets($fp, 1024);
2031
	fclose($fp);
2032

    
2033
	return $ret;
2034
}
2035

    
2036
/*
2037
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
2038
 */
2039
if (!function_exists('php_check_syntax')){
2040
	function php_check_syntax($code_to_check, &$errormessage){
2041
		return false;
2042
		$fout = fopen("/tmp/codetocheck.php","w");
2043
		$code = $_POST['content'];
2044
		$code = str_replace("<?php", "", $code);
2045
		$code = str_replace("?>", "", $code);
2046
		fwrite($fout, "<?php\n\n");
2047
		fwrite($fout, $code_to_check);
2048
		fwrite($fout, "\n\n?>\n");
2049
		fclose($fout);
2050
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
2051
		$output = exec_command($command);
2052
		if (stristr($output, "Errors parsing") == false) {
2053
			echo "false\n";
2054
			$errormessage = '';
2055
			return(false);
2056
		} else {
2057
			$errormessage = $output;
2058
			return(true);
2059
		}
2060
	}
2061
}
2062

    
2063
/*
2064
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
2065
 */
2066
if (!function_exists('php_check_syntax')){
2067
	function php_check_syntax($code_to_check, &$errormessage){
2068
		return false;
2069
		$command = "/usr/local/bin/php -l " . $code_to_check;
2070
		$output = exec_command($command);
2071
		if (stristr($output, "Errors parsing") == false) {
2072
			echo "false\n";
2073
			$errormessage = '';
2074
			return(false);
2075
		} else {
2076
			$errormessage = $output;
2077
			return(true);
2078
		}
2079
	}
2080
}
2081

    
2082
/*
2083
 * rmdir_recursive($path,$follow_links=false)
2084
 * Recursively remove a directory tree (rm -rf path)
2085
 * This is for directories _only_
2086
 */
2087
function rmdir_recursive($path,$follow_links=false) {
2088
	$to_do = glob($path);
2089
	if(!is_array($to_do)) $to_do = array($to_do);
2090
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
2091
		if(file_exists($workingdir)) {
2092
			if(is_dir($workingdir)) {
2093
				$dir = opendir($workingdir);
2094
				while ($entry = readdir($dir)) {
2095
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
2096
						unlink("$workingdir/$entry");
2097
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
2098
						rmdir_recursive("$workingdir/$entry");
2099
				}
2100
				closedir($dir);
2101
				rmdir($workingdir);
2102
			} elseif (is_file($workingdir)) {
2103
				unlink($workingdir);
2104
			}
2105
               	}
2106
	}
2107
	return;
2108
}
2109

    
2110
/*
2111
 *     get_memory()
2112
 *     returns an array listing the amount of
2113
 *     memory installed in the hardware
2114
 *     [0]real and [1]available
2115
 */
2116
function get_memory() {
2117
	if(file_exists("/var/log/dmesg.boot")) {
2118
		$mem = `cat /var/log/dmesg.boot | grep memory`;
2119
		$matches = "";
2120
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2121
			$real = $matches[1];
2122
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2123
			$avail = $matches[1];
2124
		return array($real[0],$avail[0]);
2125
	} else {
2126
		$mem = `dmesg -a`;
2127
		$matches = "";
2128
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2129
			$real = $matches[1];
2130
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2131
			$avail = $matches[1];
2132
		return array($real[0],$avail[0]);
2133
	}
2134
}
2135

    
2136
/*
2137
 *    safe_mkdir($path, $mode = 0755)
2138
 *    create directory if it doesn't already exist and isn't a file!
2139
 */
2140
function safe_mkdir($path, $mode=0755) {
2141
	global $g;
2142

    
2143
	/* cdrom is ro. */
2144
	if($g['platform'] == "cdrom")
2145
		return false;
2146

    
2147
	if (!is_file($path) && !is_dir($path))
2148
		return mkdir($path, $mode);
2149
	else
2150
		return false;
2151
}
2152

    
2153
/*
2154
 * make_dirs($path, $mode = 0755)
2155
 * create directory tree recursively (mkdir -p)
2156
 */
2157
function make_dirs($path, $mode = 0755) {
2158
	$base = '';
2159
	foreach (explode('/', $path) as $dir) {
2160
		$base .= "/$dir";
2161
		if (!is_dir($base)) {
2162
			if (!@mkdir($base, $mode))
2163
				return false;
2164
		}
2165
	}
2166
	return true;
2167
}
2168

    
2169
/*
2170
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
2171
 */
2172
function call_pfsense_method($method, $params, $timeout = 0) {
2173
	$ip = gethostbyname('www.pfsense.com');
2174
	if($ip == "www.pfsense.com")
2175
		return false;
2176
	global $g, $config;
2177
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
2178
	$xmlrpc_path = $g['xmlrpcpath'];
2179
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
2180
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
2181
	$resp = $cli->send($msg, $timeout);
2182
	if(!$resp) {
2183
		log_error("XMLRPC communication error: " . $cli->errstr);
2184
		return false;
2185
	} elseif($resp->faultCode()) {
2186
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
2187
		return false;
2188
	} else {
2189
		return XML_RPC_Decode($resp->value());
2190
	}
2191
}
2192

    
2193
/*
2194
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
2195
 */
2196
function check_firmware_version($tocheck = "all", $return_php = true) {
2197
	global $g, $config;
2198
	$ip = gethostbyname('www.pfsense.com');
2199
	if($ip == "www.pfsense.com")
2200
		return false;
2201
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
2202
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
2203
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
2204
		"platform" => trim(file_get_contents('/etc/platform'))
2205
		);
2206
	if($tocheck == "all") {
2207
		$params = $rawparams;
2208
	} else {
2209
		foreach($tocheck as $check) {
2210
			$params['check'] = $rawparams['check'];
2211
			$params['platform'] = $rawparams['platform'];
2212
		}
2213
	}
2214
	if($config['system']['firmware']['branch']) {
2215
		$params['branch'] = $config['system']['firmware']['branch'];
2216
	}
2217
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
2218
		return false;
2219
	} else {
2220
		$versions["current"] = $params;
2221
	}
2222
	return $versions;
2223
}
2224

    
2225
function get_disk_info() {
2226
	$diskout = "";
2227
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
2228
	return explode(' ', $diskout[0]);
2229
	// $size, $used, $avail, $cap
2230
}
2231

    
2232
function run_plugins($directory) {
2233
	global $config, $g;
2234
	/* process packager manager custom rules */
2235
	$files = return_dir_as_array($directory);
2236
	if($files <> "") {
2237
		foreach ($files as $file) {
2238
			if($file) {
2239
				$text = file_get_contents($directory . $file);
2240
				if($text) {
2241
					if(stristr($file, ".sh") == true) {
2242
						mwexec($directory . $file . " start");
2243
					} else {
2244
						if(!stristr($file,"CVS")) {
2245
							if($g['booting'] == true)
2246
								echo "\t{$file}... ";
2247
							require_once($directory . "/" . $file);
2248
						}
2249
					}
2250
				}
2251
			}
2252
		}
2253
	}	
2254
}
2255

    
2256
/****f* pfsense-utils/display_top_tabs
2257
 * NAME
2258
 *   display_top_tabs - display tabs with rounded edges
2259
 * INPUTS
2260
 *   $text	- array of tabs
2261
 * RESULT
2262
 *   null
2263
 ******/
2264
function display_top_tabs($tab_array) {
2265
	$tabcharcount = 0;
2266
	foreach ($tab_array as $ta) 
2267
		$tabcharcount = $tabcharcount + strlen($ta[0]);
2268
	// If the character count of the tab names is > 82
2269
	// then show a select item dropdown menubox.
2270
	if($tabcharcount > 82) {
2271
		echo "Currently viewing: ";
2272
		echo "<select name='TabSelect'>\n";
2273
		foreach ($tab_array as $ta) {
2274
			if($ta[1]=="true")	
2275
				$selected = " SELECTED";
2276
			else 
2277
				$selected = "";
2278
			echo "<option onClick=\"document.location='{$ta[2]}';\"{$selected}>{$ta['0']}</option>\n";
2279
		}
2280
		echo "</select>\n<p/>";
2281
	}  else {
2282
		echo "<table cellpadding='0' cellspacing='0'>\n";
2283
		echo " <tr height='1'>\n";
2284
		$tabscounter = 0;
2285
		foreach ($tab_array as $ta) {
2286
			if($ta[1] == true) {
2287
				echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
2288
			} else {
2289
				echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
2290
			}
2291
			$tabscounter++;
2292
		}
2293
		echo "</tr>\n<tr>\n";
2294
		foreach ($tab_array as $ta) {
2295
			if($ta[1] == true) {
2296
				echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
2297
				echo "&nbsp;&nbsp;&nbsp;";
2298
				echo "<font size='-12'>&nbsp;</td>\n";
2299
			} else {
2300
				echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
2301
				echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
2302
				echo "<font size='-12'>&nbsp;</td>\n";
2303
			}
2304
		}
2305
		echo "</tr>\n<tr height='5px'>\n";
2306
		foreach ($tab_array as $ta) {
2307
			if($ta[1] == true) {
2308
				echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2309
			} else {
2310
				echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2311
			}
2312
			$tabscounter++;
2313
		}
2314
		echo " </tr>\n";
2315
		echo "</table>\n";
2316

    
2317
		echo "<script type=\"text/javascript\">";
2318
		echo "NiftyCheck();\n";
2319
		echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
2320
		for($x=0; $x<$tabscounter; $x++)
2321
			echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
2322
		echo "</script>";
2323
	}
2324
}
2325

    
2326
/****f* pfsense-utils/display_topbar
2327
 * NAME
2328
 *   display_topbar - top a table off with rounded edges
2329
 * INPUTS
2330
 *   $text	- (optional) Text to include in bar
2331
 * RESULT
2332
 *   null
2333
 ******/
2334
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
2335
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
2336
	echo "       <tr height='1'>\n";
2337
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
2338
	echo "		<div id='topbar'></div></td>\n";
2339
	echo "       </tr>\n";
2340
	echo "       <tr height='1'>\n";
2341
	if ($text != "")
2342
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
2343
	else
2344
		echo "         <td height='1' class='listtopic'></td>\n";
2345
	echo "       </tr>\n";
2346
	echo "     </table>";
2347
	echo "<script type=\"text/javascript\">";
2348
	echo "NiftyCheck();\n";
2349
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
2350
	echo "</script>";
2351
}
2352

    
2353
/****f* pfsense-utils/generate_random_mac_address
2354
 * NAME
2355
 *   generate_random_mac - generates a random mac address
2356
 * INPUTS
2357
 *   none
2358
 * RESULT
2359
 *   $mac - a random mac address
2360
 ******/
2361
function generate_random_mac_address() {
2362
	$mac = "02";
2363
	for($x=0; $x<5; $x++)
2364
		$mac .= ":" . dechex(rand(16, 255));
2365
	return $mac;
2366
}
2367

    
2368
/****f* pfsense-utils/strncpy
2369
 * NAME
2370
 *   strncpy - copy strings
2371
 * INPUTS
2372
 *   &$dst, $src, $length
2373
 * RESULT
2374
 *   none
2375
 ******/
2376
function strncpy(&$dst, $src, $length) {
2377
	if (strlen($src) > $length) {
2378
		$dst = substr($src, 0, $length);
2379
	} else {
2380
		$dst = $src;
2381
	}
2382
}
2383

    
2384
/****f* pfsense-utils/reload_interfaces_sync
2385
 * NAME
2386
 *   reload_interfaces - reload all interfaces
2387
 * INPUTS
2388
 *   none
2389
 * RESULT
2390
 *   none
2391
 ******/
2392
function reload_interfaces_sync() {
2393
	global $config, $g, $debug;
2394

    
2395
	$shutdown_webgui_needed = false;
2396

    
2397
	touch("{$g['tmp_path']}/reloading_all");
2398

    
2399
	if($debug)
2400
		log_error("reload_interfaces_sync() is starting.");
2401

    
2402
	if(file_exists("{$g['tmp_path']}/config.cache"))
2403
		unlink("{$g['tmp_path']}/config.cache");
2404

    
2405
	/* parse config.xml again */
2406
	$config = parse_config(true);
2407

    
2408
	$wan_if = $config['interfaces']['wan']['if'];
2409
	$lan_if = $config['interfaces']['lan']['if'];
2410

    
2411
	if($debug)
2412
		log_error("Cleaning up Interfaces");
2413

    
2414
	/* build an array of interfaces to work with */
2415
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2416
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2417
		$iflist['opt' . $i] = "opt{$i}";
2418

    
2419
	foreach ($iflist as $ifent => $ifname) {
2420
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2421
		if(stristr($ifname, "lo0") == true)
2422
			continue;
2423
		/* do not process wan interface, its mandatory */
2424
		if(stristr($ifname, "$wan_if") == true)
2425
			continue;
2426
		/* do not process lan interface, its mandatory */
2427
		if(stristr($ifname, "$lan_if") == true)
2428
			continue;
2429
		if($debug)
2430
			log_error("Downing and deleting $ifname_real - $ifname");
2431
		mwexec("/sbin/ifconfig {$ifname_real} down");
2432
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2433
	}
2434

    
2435
	/* set up VLAN virtual interfaces */
2436
	if($debug)
2437
		log_error("Configuring VLANS");
2438
	interfaces_vlan_configure();
2439

    
2440
	/* set up LAN interface */
2441
	if($debug)
2442
		log_error("Configuring LAN");
2443
	interfaces_lan_configure();
2444

    
2445
	/* set up WAN interface */
2446
	if($debug)
2447
		log_error("Configuring WAN");
2448
	interfaces_wan_configure();
2449

    
2450
	/* set up Optional interfaces */
2451
	if($debug)
2452
		log_error("Configuring optional interfaces");
2453
	interfaces_optional_configure();
2454

    
2455
	/* set up static routes */
2456
	if($debug)
2457
		log_error("Configuring system Routing");
2458
	system_routing_configure();
2459

    
2460
	/* enable routing */
2461
	if($debug)
2462
		log_error("Enabling system routing");
2463
	system_routing_enable();
2464

    
2465
	/* setup captive portal if needed */
2466
	if($debug)
2467
		log_error("Configuring Captive portal");
2468
	captiveportal_configure();
2469

    
2470
	/* bring up carp interfaces */
2471
	if($debug)
2472
		log_error("Configuring CARP");
2473
	interfaces_carp_configure();
2474

    
2475
	/* bring up carp interfaces*/
2476
	if($debug)
2477
		log_error("Bringing up CARP interfaces");
2478
	interfaces_carp_bring_up_final();
2479

    
2480
	/* restart webConfigurator if needed */
2481
	if($shutdown_webgui_needed == true)
2482
		touch("/tmp/restart_webgui");
2483

    
2484
	/* start devd back up */
2485
	mwexec("/bin/rm /tmp/reload*");
2486

    
2487
	/* remove reloading_all trigger */
2488
	if($debug)
2489
		log_error("Removing {$g['tmp_path']}/reloading_all");
2490
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2491
}
2492

    
2493
/****f* pfsense-utils/reload_all
2494
 * NAME
2495
 *   reload_all - triggers a reload of all settings
2496
 *   * INPUTS
2497
 *   none
2498
 * RESULT
2499
 *   none
2500
 ******/
2501
function reload_all() {
2502
	touch("/tmp/reload_all");
2503
}
2504

    
2505
/****f* pfsense-utils/reload_interfaces
2506
 * NAME
2507
 *   reload_interfaces - triggers a reload of all interfaces
2508
 * INPUTS
2509
 *   none
2510
 * RESULT
2511
 *   none
2512
 ******/
2513
function reload_interfaces() {
2514
	touch("/tmp/reload_interfaces");
2515
}
2516

    
2517
/****f* pfsense-utils/sync_webgui_passwords
2518
 * NAME
2519
 *   sync_webgui_passwords - syncs webgui and ssh passwords
2520
 * INPUTS
2521
 *   none
2522
 * RESULT
2523
 *   none
2524
 ******/
2525
function sync_webgui_passwords() {
2526
	global $config, $g;
2527
	conf_mount_rw();
2528
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
2529
	if (!$fd) {
2530
		printf("Error: cannot open htpasswd in system_password_configure().\n");
2531
		return 1;
2532
	}
2533
	/* set admin account */
2534
	$username = $config['system']['username'];
2535

    
2536
	/* set defined user account */
2537
	if($username <> "admin") {
2538
		$username = $config['system']['username'];
2539
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
2540
	} else {
2541
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
2542
	}
2543
	fclose($fd);
2544
	chmod("{$g['varrun_path']}/htpasswd", 0600);
2545
	$crypted_pw = $config['system']['password'];
2546
	if(file_exists("/etc/pwd.db.tmp")) 
2547
		unlink("/etc/pwd.db.tmp");
2548
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2549
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2550
	/* sync root */
2551
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
2552
	fwrite($fd, $crypted_pw);
2553
	pclose($fd);
2554
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
2555
	/* sync admin */
2556
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
2557
	fwrite($fd, $crypted_pw);
2558
	pclose($fd);
2559
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
2560
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2561
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2562
	conf_mount_ro();
2563
}
2564

    
2565
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
2566
 * NAME
2567
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
2568
 *   * INPUTS
2569
 *   optional interface number
2570
 * RESULT
2571
 *   none
2572
 ******/
2573
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
2574
	/*	move all the interfaces up.  for example:
2575
	*		opt1 --> opt1
2576
	*		opt2 --> delete
2577
	*		opt3 --> opt2
2578
	*		opt4 --> opt3
2579
	*/
2580
	global $g, $config;
2581
	config_lock();
2582
	conf_mount_rw();
2583
	unlink_if_exists("{$g['tmp_path']}/config.cache");
2584
	$config_file = file_get_contents("/cf/conf/config.xml");
2585
	/* loop through and reassign deleted items */
2586
	$orig = array('opt'.$opt_interface_num,'OPT'.$opt_interface_num);
2587
	$repl = array('optXXXX','OPTXXXX');
2588
	for ($i = $opt_interface_num+1; isset ($config['interfaces']['opt' . $i]); $i++) {
2589
		array_push($orig,'opt'.$i);
2590
		array_push($repl,'opt'.($i -1));
2591
		array_push($orig,'OPT'.$i);
2592
		array_push($repl,'OPT'.($i -1));
2593
	}
2594
	$config_file = str_replace($orig, $repl, $config_file);
2595
	$fd = fopen("/cf/conf/config.xml", "w");
2596
	fwrite($fd, $config_file);
2597
	fclose($fd);
2598
	$config = parse_config(true);
2599
	/* loop through and delete old rules */
2600
	$num_rules = count($config['filter']['rule']);
2601
	for($x = $num_rules; $x > 0; $x--) {
2602
		if($config['filter']['rule'][$x])
2603
			if($config['filter']['rule'][$x]['interface'] == "optXXXX")
2604
		 		unset($config['filter']['rule'][$x]['interface']);
2605
	}
2606
	$num_rules = count($config['nat']['advancedoutbound']['rule']);
2607
	for($x = $num_rules; $x > 0; $x--) {
2608
		if($config['nat']['advancedoutbound']['rule'][$x])
2609
			if($config['nat']['advancedoutbound']['rule'][$x]['interface'] == "optXXXX")
2610
		 		unset($config['nat']['advancedoutbound']['rule'][$x]['interface']);
2611
	}
2612
	$num_rules = count($config['nat']['rule']);
2613
	for($x = $num_rules; $x > 0; $x--) {
2614
		if($config['nat']['rule'][$x])
2615
			if($config['nat']['rule'][$x]['interface'] == "optXXXX")
2616
		 		unset($config['nat']['rule'][$x]['interface']);
2617
	}
2618
	write_config();
2619
	conf_mount_ro();
2620
	config_unlock();
2621
	return true;
2622
}
2623

    
2624
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
2625
 * NAME
2626
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
2627
 *   		amount of netgraph interfaces needed for system wans
2628
 *   * INPUTS
2629
 *   none
2630
 * RESULT
2631
 *   number of needed netgraph (ng) interfaces
2632
 ******/
2633
function get_number_of_wan_netgraph_interfaces_needed() {
2634
	global $config, $g;
2635
	/* build an array of interfaces to work with */
2636
	$iflist = array("wan" => "WAN");
2637
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2638
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2639
	$ng_interfaces_needed = 0;
2640
	foreach ($iflist as $ifent => $ifname) {
2641
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2642
			$ng_interfaces_needed++;
2643
		}
2644
	}
2645
	return $ng_interfaces_needed;
2646
}
2647

    
2648
function get_netgaph_interface_assignment($friendly_interface) {
2649
	global $config, $g;
2650
	/* build an array of interfaces to work with */
2651
	$iflist = array("wan" => "WAN");
2652
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2653
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2654
		$ng_interfaces_needed = 0;
2655
		$ng_interfaces_number = 0;
2656
		foreach ($iflist as $ifent => $ifname) {
2657
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2658
			$ng_interfaces_number++;
2659
		}
2660
		if($friendly_interface == $ifname)
2661
			break;
2662
	}
2663
	return $ng_interfaces_number;
2664
}
2665

    
2666
/****f* pfsense-utils/reload_all_sync
2667
 * NAME
2668
 *   reload_all - reload all settings
2669
 *   * INPUTS
2670
 *   none
2671
 * RESULT
2672
 *   none
2673
 ******/
2674
function reload_all_sync() {
2675
	global $config, $g;
2676

    
2677
	$g['booting'] = false;
2678

    
2679
	touch("{$g['tmp_path']}/reloading_all");
2680

    
2681
	$shutdown_webgui_needed = false;
2682

    
2683
	if(file_exists("{$g['tmp_path']}/config.cache"))
2684
		unlink("{$g['tmp_path']}/config.cache");
2685

    
2686
	/* parse config.xml again */
2687
	$config = parse_config(true);
2688

    
2689
	/* set up our timezone */
2690
	system_timezone_configure();
2691

    
2692
	/* set up our hostname */
2693
	system_hostname_configure();
2694

    
2695
	/* make hosts file */
2696
	system_hosts_generate();
2697

    
2698
	/* generate resolv.conf */
2699
	system_resolvconf_generate();
2700

    
2701
	/* Set up our loopback interface */
2702
	interfaces_loopback_configure();
2703

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

    
2707
	$wan_if = $config['interfaces']['wan']['if'];
2708
	$lan_if = $config['interfaces']['lan']['if'];
2709

    
2710
	/* build an array of interfaces to work with */
2711
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2712
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2713
		$iflist['opt' . $i] = "opt{$i}";
2714

    
2715
	foreach ($iflist as $ifent => $ifname) {
2716
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2717
		if(stristr($ifname, "lo0") == true)
2718
			continue;
2719
		/* do not process wan interface, its mandatory */
2720
		if($wan_if == $ifname_real)
2721
			continue;
2722
		/* do not process lan interface, its mandatory */
2723
		if($lan_if == $ifname_real)
2724
			continue;
2725
		mwexec("/sbin/ifconfig {$ifname_real} down");
2726
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2727
	}
2728

    
2729
	/* set up VLAN virtual interfaces */
2730
	interfaces_vlan_configure();
2731

    
2732
	/* set up LAN interface */
2733
	interfaces_lan_configure();
2734

    
2735
	/* set up WAN interface */
2736
	interfaces_wan_configure();
2737

    
2738
	/* set up Optional interfaces */
2739
	interfaces_optional_configure();
2740

    
2741
	/* bring up carp interfaces */
2742
	interfaces_carp_configure();
2743

    
2744
	/* set up static routes */
2745
	system_routing_configure();
2746

    
2747
	/* enable routing */
2748
	system_routing_enable();
2749

    
2750
	/* ensure passwords are sync'd */
2751
	system_password_configure();
2752

    
2753
	/* start dnsmasq service */
2754
	services_dnsmasq_configure();
2755

    
2756
	/* start dyndns service */
2757
	services_dyndns_configure();
2758

    
2759
	/* start DHCP service */
2760
	services_dhcpd_configure();
2761

    
2762
	/* configure cron service */
2763
	configure_cron();
2764

    
2765
	/* start the NTP client */
2766
	system_ntp_configure();
2767

    
2768
	/* start ftp proxy helpers if they are enabled */
2769
	system_start_ftp_helpers();
2770

    
2771
	/* start the captive portal */
2772
	captiveportal_configure();
2773

    
2774
        /* reload the filter */
2775
	filter_configure_sync();
2776

    
2777
	/* bring up carp interfaces*/
2778
	interfaces_carp_bring_up_final();
2779

    
2780
	/* sync pw database */
2781
	conf_mount_rw();
2782
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2783
	conf_mount_ro();
2784

    
2785
	/* restart sshd */
2786
	touch("/tmp/start_sshd");
2787

    
2788
	/* restart webConfigurator if needed */
2789
	if($shutdown_webgui_needed == true)
2790
		touch("/tmp/restart_webgui");
2791

    
2792
	mwexec("/bin/rm /tmp/reload*");
2793

    
2794
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2795

    
2796
}
2797

    
2798
function auto_login($status) {
2799
	$gettytab = file_get_contents("/etc/gettytab");
2800
	$getty_split = split("\n", $gettytab);
2801
	conf_mount_rw();
2802
	$fd = fopen("/etc/gettytab", "w");
2803
	foreach($getty_split as $gs) {
2804
		if(stristr($gs, ":ht:np:sp#115200") ) {
2805
			if($status == true) {
2806
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
2807
			} else {
2808
				fwrite($fd, "	:ht:np:sp#115200:\n");
2809
			}
2810
		} else {
2811
			fwrite($fd, "{$gs}\n");
2812
		}
2813
	}
2814
	fclose($fd);
2815
	conf_mount_ro();
2816
}
2817

    
2818
function setup_serial_port() {
2819
	global $g, $config;
2820
	conf_mount_rw();
2821
	/* serial console - write out /boot.config */
2822
	if(file_exists("/boot.config"))
2823
		$boot_config = file_get_contents("/boot.config");
2824
	else
2825
		$boot_config = "";
2826

    
2827
	if($g['platform'] <> "cdrom") {
2828
		$boot_config_split = split("\n", $boot_config);
2829
		$fd = fopen("/boot.config","w");
2830
		if($fd) {
2831
			foreach($boot_config_split as $bcs) {
2832
				if(stristr($bcs, "-D")) {
2833
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2834
				} else {
2835
					if($bcs <> "")
2836
						fwrite($fd, "{$bcs}\n");
2837
				}
2838
			}
2839
			if(isset($config['system']['enableserial'])) {
2840
				fwrite($fd, "-D");
2841
			}
2842
			fclose($fd);
2843
		}
2844
		/* serial console - write out /boot/loader.conf */
2845
		$boot_config = file_get_contents("/boot/loader.conf");
2846
		$boot_config_split = split("\n", $boot_config);
2847
		$fd = fopen("/boot/loader.conf","w");
2848
		if($fd) {
2849
			foreach($boot_config_split as $bcs) {
2850
				if(stristr($bcs, "console")) {
2851
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2852
				} else {
2853
					if($bcs <> "")
2854
						fwrite($fd, "{$bcs}\n");
2855
				}
2856
			}
2857
			if(isset($config['system']['enableserial'])) {
2858
				fwrite($fd, "console=\"comconsole\"\n");
2859
			}
2860
			fclose($fd);
2861
		}
2862
	}
2863
	$ttys = file_get_contents("/etc/ttys");
2864
	$ttys_split = split("\n", $ttys);
2865
	$fd = fopen("/etc/ttys", "w");
2866
	foreach($ttys_split as $tty) {
2867
		if(stristr($tty, "ttyd0")) {
2868
			if(isset($config['system']['enableserial'])) {
2869
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
2870
			} else {
2871
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
2872
			}
2873
		} else {
2874
			fwrite($fd, $tty . "\n");
2875
		}
2876
	}
2877
	fclose($fd);
2878
	if(isset($config['system']['disableconsolemenu'])) {
2879
		auto_login(false);
2880
	} else {
2881
		auto_login(true);
2882
	}
2883
	conf_mount_ro();
2884
	return;
2885
}
2886

    
2887
function print_value_list($list, $count = 10, $separator = ",") {
2888
	$list = implode($separator, array_slice($list, 0, $count));
2889
	if(count($list) < $count) {
2890
		$list .= ".";
2891
	} else {
2892
		$list .= "...";
2893
	}
2894
	return $list;
2895
}
2896

    
2897
function convert_friendly_interface_to_friendly_descr($interface) {
2898
	global $config;
2899
	/* attempt to resolve interface to friendly descr */
2900
	if($config['interfaces'][$interface]['descr'])
2901
		return $config['interfaces'][$interface]['descr'];
2902
	$tmp = convert_real_interface_to_friendly_descr($interface);
2903
	/* could not resolve, return back what was passed */
2904
	return $interface;
2905
}
2906

    
2907
function convert_real_interface_to_friendly_descr($interface) {
2908
	global $config;
2909
	if($interface == $config['interfaces']['wan']['if'])
2910
		return "wan";
2911
	if($interface == $config['interfaces']['lan']['if'])
2912
		return "lan";
2913
	/* attempt to resolve interface to friendly descr */
2914
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
2915
	if($config['interfaces'][$friendly_int]['descr'])
2916
		return $config['interfaces'][$friendly_int]['descr'];
2917
	/* could not resolve, return back what was passed */
2918
	return $interface;
2919
}
2920

    
2921
function enable_rrd_graphing() {
2922
	global $config, $g;
2923

    
2924
	if($g['booting']) 
2925
		echo "Generating RRD graphs...";
2926

    
2927
	$rrddbpath = "/var/db/rrd/";
2928
	$rrdgraphpath = "/usr/local/www/rrd";
2929

    
2930
	$traffic = "-traffic.rrd";
2931
	$packets = "-packets.rrd";
2932
	$states = "-states.rrd";
2933
	$quality = "-quality.rrd";
2934
	$queues = "-queues.rrd";
2935
	$queuesdrop = "-queuesdrop.rrd";
2936
	$spamd = "-spamd.rrd";
2937
	$proc = "-processor.rrd";
2938

    
2939
	$rrdtool = "/usr/local/bin/rrdtool";
2940
	$netstat = "/usr/bin/netstat";
2941
	$awk = "/usr/bin/awk";
2942
	$tar = "/usr/bin/tar";
2943
	$pfctl = "/sbin/pfctl";
2944
	$php = "/usr/local/bin/php";
2945
	$top = "/usr/bin/top";
2946
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2947

    
2948
	$rrdtrafficinterval = 60;
2949
	$rrdqualityinterval = 60;
2950
	$rrdqueuesinterval = 60;
2951
	$rrdqueuesdropinterval = 60;
2952
	$rrdpacketsinterval = 60;
2953
	$rrdstatesinterval = 60;
2954
	$rrdspamdinterval = 60;
2955
	$rrdlbpoolinterval = 60;
2956
	$rrdprocinterval = 60;
2957

    
2958
	$trafficvalid = $rrdtrafficinterval * 2;
2959
	$qualityvalid = $rrdqualityinterval * 2;
2960
	$queuesvalid = $rrdqueuesinterval * 2;
2961
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2962
	$packetsvalid = $rrdpacketsinterval * 2;
2963
	$statesvalid = $rrdstatesinterval*2;
2964
	$spamdvalid = $rrdspamdinterval * 2;
2965
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2966
	$procvalid = $rrdlbpoolinterval * 2;
2967

    
2968
	/* Asume GigE for now */
2969
	$downstream = 125000000;
2970
	$upstream = 125000000;
2971

    
2972
	$rrdrestore = "";
2973
	$rrdreturn = "";
2974

    
2975
	if (isset ($config['rrd']['enable'])) {
2976

    
2977
		/* create directory if needed */
2978
		if (!is_dir("$rrddbpath")) {
2979
			mkdir("$rrddbpath", 0755);
2980
		}
2981

    
2982
		if ($g['booting']) {
2983
			if ($g['platform'] != "pfSense") {
2984
				/* restore the databases, if we have one */
2985
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
2986
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2987
					if((int)$rrdrestore <> 0) {
2988
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
2989
					}
2990
				}
2991
			}
2992
		}
2993

    
2994
		/* db update script */
2995
		$rrdupdatesh = "#!/bin/sh\n";
2996
		$rrdupdatesh .= "\n";
2997
		$rrdupdatesh .= "counter=1\n";
2998
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2999
		$rrdupdatesh .= "do\n";
3000
		$rrdupdatesh .= "";
3001

    
3002
		$i = 0;
3003
		$vfaces = array (
3004
			"vlan.?*",
3005
			"enc.?*"
3006
		);
3007
		$ifdescrs = get_interface_list(true, true, $vfaces);
3008
		$ifdescrs['enc0']['friendly'] = "ipsec";
3009
		$ifdescrs['enc0']['descr'] = "IPSEC";
3010
		$ifdescrs['enc0']['up'] = true;
3011

    
3012
		foreach ($ifdescrs as $realif => $ifdescr) {
3013
			$ifname = $ifdescr['friendly'];
3014
			$state = $ifdescr['up'];
3015

    
3016
			/* skip interfaces that do not have a friendly name */
3017
			if ("$ifname" == "") {
3018
				continue;
3019
			}
3020

    
3021
			/* or are down */
3022
			if (!$state) {
3023
				continue;
3024
			}
3025

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

    
3042
				$rrdcreateoutput = array();
3043
				$rrdcreatereturn = "";
3044

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

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

    
3057
			$rrdupdatesh .= "\n";
3058
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
3059
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
3060
			if(! is_macaddr(get_interface_mac($realif))) {
3061
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$6 \":\" \$9}'`\n";
3062
			} else {
3063
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7 \":\" \$10}'`\n";
3064
			}
3065

    
3066
			/* PACKETS, set up the rrd file */
3067
			if (!file_exists("$rrddbpath$ifname$packets")) {
3068
				/* create rrd file if it does not exist */
3069
				log_error("Create RRD database $rrddbpath$ifname$packets");
3070
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
3071
				$rrdcreate .= "DS:in:COUNTER:$packetsvalid:0:$downstream ";
3072
				$rrdcreate .= "DS:out:COUNTER:$packetsvalid:0:$upstream ";
3073
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3074
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3075
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3076
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3077
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3078
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3079
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3080
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3081

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

    
3089
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3090
			if($g['booting']) {
3091
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
3092
			}
3093

    
3094
			$rrdupdatesh .= "\n";
3095
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
3096
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
3097
			if(! is_macaddr(get_interface_mac($realif))) {
3098
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$4 \":\" \$7}'`\n";
3099
			} else {
3100
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5 \":\" \$8}'`\n";
3101
			}
3102
			/* if an alternative gateway is defined, use it */
3103
			if ($config['interfaces'][$ifname]['use_rrd_gateway'] <> "") {
3104
				$gatewayip = get_interface_gateway($ifname);
3105
				$monitorip = $config['interfaces'][$ifname]['use_rrd_gateway'];
3106
				mwexec("/sbin/route add -host {$monitorip} {$gatewayip} 2>&1");
3107
			} else {
3108
				$monitorip = get_interface_gateway($ifname);
3109
			}
3110
			$numpings = 5;
3111
			$btick = '`';
3112

    
3113
			if($monitorip <> "") {
3114
				/* QUALITY, create link quality database */
3115
				if (!file_exists("$rrddbpath$ifname$quality")) {
3116
					/* create rrd file if it does not exist */
3117
					log_error("Create RRD database $rrddbpath$ifname$quality");
3118
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
3119
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
3120
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
3121
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3122
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3123
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3124
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3125

    
3126
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3127
					if ($rrdcreatereturn != 0) {
3128
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3129
					}
3130
				}
3131

    
3132
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3133
				if($g['booting']) {
3134
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
3135
				}
3136

    
3137
				/* the ping test function. We call this on the last line */
3138
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
3139
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
3140
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
3141
				$rrdupdatesh .= "	local out_{$ifname}\n";
3142
				$rrdupdatesh .= "	out_{$ifname}=$btick ping -c $numpings -q $monitorip $btick\n";
3143
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
3144
				$rrdupdatesh .= "		packetloss_{$ifname}=$btick echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1 $btick\n";
3145
				$rrdupdatesh .= "		roundtrip_{$ifname}=$btick echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/' $btick\n";
3146
				$rrdupdatesh .= "	fi\n";
3147
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
3148
				$rrdupdatesh .= "}\n\n";
3149

    
3150
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
3151
			}
3152

    
3153
			/* WAN interface only statistics */
3154
			if ("$ifname" == "wan") {
3155

    
3156
				/* QUEUES, set up the queues databases */
3157
				if (!is_array($config['shaper']['queue'])) {
3158
					$config['shaper']['queue'] = array ();
3159
				}
3160
				$a_queues = & $config['shaper']['queue'];
3161

    
3162
				if (isset ($config['shaper']['enable'])) {
3163
					if (!file_exists("$rrddbpath$ifname$queues")) {
3164
						/* create rrd file if it does not exist */
3165
						log_error("Create RRD database $rrddbpath$ifname$queues");
3166
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
3167
						/* loop list of shaper queues */
3168
						$q = 0;
3169
						foreach ($a_queues as $queue) {
3170
							$name = $queue['name'];
3171
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream ";
3172
						}
3173

    
3174
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3175
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3176
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3177
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3178

    
3179
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3180
						if ($rrdcreatereturn != 0) {
3181
							log_error("RRD create failed exited with $rrdcreatereturn, the
3182
									error is: $rrdcreateoutput[0]\n");
3183
						}
3184
					}
3185

    
3186
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
3187
						/* create rrd file if it does not exist */
3188
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
3189
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
3190
						/* loop list of shaper queues */
3191
						$q = 0;
3192
						foreach ($a_queues as $queue) {
3193
							$name = $queue['name'];
3194
							$rrdcreate .= "DS:$name:COUNTER:$queuesdropvalid:0:$downstream ";
3195
						}
3196

    
3197
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3198
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3199
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3200
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000";
3201

    
3202
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3203
						if ($rrdcreatereturn != 0) {
3204
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3205
						}
3206
					}
3207

    
3208
					if($g['booting']) {
3209
						$rrdqcommand = "-t ";
3210
						$rrducommand = "N";
3211
						$q = 0;
3212
						foreach ($a_queues as $queue) {
3213
							if($q == 0) {
3214
								$rrdqcommand .= "{$queue['name']}";
3215
							} else {
3216
								$rrdqcommand .= ":{$queue['name']}";
3217
							}
3218
							$q++;
3219
							$rrducommand .= ":U";
3220
						}
3221
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3222
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3223
					}
3224

    
3225
					/* awk function to gather shaper data */
3226
					/* yes, it's special */
3227
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
3228
					$rrdupdatesh .= "{ ";
3229
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3230
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3231
					$rrdupdatesh .= "q=1; ";
3232
					$rrdupdatesh .= "} ";
3233
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3234
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
3235
					$rrdupdatesh .= "q=0; ";
3236
					$rrdupdatesh .= "} ";
3237
					$rrdupdatesh .= "} END { ";
3238
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3239
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3240
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3241
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3242

    
3243
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
3244
					$rrdupdatesh .= "{ ";
3245
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3246
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3247
					$rrdupdatesh .= "q=1; ";
3248
					$rrdupdatesh .= "} ";
3249
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3250
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
3251
					$rrdupdatesh .= "q=0; ";
3252
					$rrdupdatesh .= "} ";
3253
					$rrdupdatesh .= "} END { ";
3254
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3255
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3256
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3257
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3258
				}
3259
			}
3260
		}
3261
		$i++;
3262

    
3263
		/* System only statistics */
3264
		$ifname = "system";
3265

    
3266
			/* STATES, create pf states database */
3267
			if(! file_exists("$rrddbpath$ifname$states")) {
3268
				/* create rrd file if it does not exist */
3269
				log_error("Create RRD database $rrddbpath$ifname$states");
3270
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3271
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3272
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3273
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3274
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3275
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3276
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3277
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3278
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3279
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3280
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3281
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3282
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3283
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3284
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3285
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3286
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3287
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3288

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

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

    
3301
 			/* the pf states gathering function. */
3302
 			$rrdupdatesh .= "\n";
3303
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
3304
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
3305
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3306
			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3307
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3308
			$rrdupdatesh .= "srcip=\"` cat /tmp/pfctl_ss_out | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '\\->' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
3309
			$rrdupdatesh .= "dstip=\"` cat /tmp/pfctl_ss_out | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '<\\-' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
3310
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3311

    
3312
			/* End pf states statistics */
3313

    
3314
			/* CPU, create CPU statistics database */
3315
			if(! file_exists("$rrddbpath$ifname$proc")) {
3316
				/* create rrd file if it does not exist */
3317
				log_error("Create RRD database $rrddbpath$ifname$proc");
3318
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3319
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3320
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3321
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3322
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3323
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3324
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3325
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3326
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3327
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3328
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3329
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3330
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3331
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3332
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3333
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3334
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3335
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3336

    
3337
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3338
				if($rrdcreatereturn != 0) {
3339
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3340
						error is: $rrdcreateoutput[0]\n");
3341
				}
3342
			}
3343

    
3344
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3345
			if($g['booting']) {
3346
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
3347
			}
3348

    
3349
 			/* the CPU stats gathering function. */
3350
                        $rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { \\\n";
3351
                        $rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } \\\n";
3352
                        $rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { processes = \$1; } \\\n";
3353
                        $rrdupdatesh .= "else if ( \$1 == \"CPU:\" ) { user = \$2; nice = \$4; sys = \$6; interrupt = \$8; } \\\n";
3354
                        $rrdupdatesh .= "} END { printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes }'`\n\n";
3355

    
3356
			/* End CPU statistics */
3357

    
3358
			/* SPAMD, set up the spamd rrd file */
3359
			if (isset($config['installedpackages']['spamdsettings']) &&
3360
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
3361
				/* set up the spamd rrd file */
3362
				if (!file_exists("$rrddbpath$ifname$spamd")) {
3363
						/* create rrd file if it does not exist */
3364
						log_error("Create RRD database $rrddbpath$ifname$spamd");
3365
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
3366
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
3367
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
3368
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3369
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3370
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3371
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3372
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3373
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3374
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3375
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3376
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3377
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3378
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3379
						$rrdcreate .= "RRA:MAX:0.5:720:1000";
3380

    
3381
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3382
					if ($rrdcreatereturn != 0) {
3383
						log_error("RRD create failed exited with $rrdcreatereturn, the
3384
							error is: $rrdcreateoutput[0]\n");
3385
					}
3386
				}
3387

    
3388
				$rrdupdatesh .= "\n";
3389
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3390
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3391
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3392

    
3393
			}
3394
		/* End System statistics */
3395

    
3396
		$rrdupdatesh .= "sleep 60\n";
3397
		$rrdupdatesh .= "done\n";
3398
		log_error("Creating rrd update script");
3399
		/* write the rrd update script */
3400
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3401
		$fd = fopen("$updaterrdscript", "w");
3402
		fwrite($fd, "$rrdupdatesh");
3403
		fclose($fd);
3404

    
3405
		/* kill off traffic collectors */
3406
		kill_traffic_collector();
3407

    
3408
		/* start traffic collector */
3409
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3410

    
3411
	} else {
3412
		/* kill off traffic collectors */
3413
		kill_traffic_collector();
3414
	}
3415

    
3416
	if($g['booting']) 
3417
		echo "done.\n";
3418
		
3419
}
3420

    
3421
function kill_traffic_collector() {
3422
		mwexec("/usr/bin/killall -9 rrdtool");
3423
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill -9");
3424
}
3425

    
3426
function update_filter_reload_status($text) {
3427
	global $g;
3428
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3429
	fwrite($fd, $text);
3430
	fclose($fd);
3431
}
3432

    
3433
function get_interface_gateway($interface) {
3434
	global $config, $g;
3435
	$interface = strtolower($interface);
3436
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
3437
	 *  grab the address from the configuration file.
3438
	 */
3439
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
3440
	if($tmpif <> $interface)
3441
		$interface = $tmpif;
3442
	$realif = $config['interfaces'][$interface]['if'];
3443
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
3444
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3445
		$gw = rtrim($gw);
3446
	} else {
3447
		$gw = $config['interfaces'][$interface]['gateway'];
3448
	}
3449
	/* if wan is requested, return it */
3450
	if($interface == "wan")
3451
		return str_replace("\n", "", `/usr/bin/netstat -rn | /usr/bin/awk '/default/ {print $2}'`);
3452
	/* return gateway */
3453
	return $gw;
3454
}
3455

    
3456
function is_dhcp_server_enabled() {
3457
	/* DHCP enabled on any interfaces? */
3458
	global $config, $g;
3459
	$dhcpdcfg = $config['dhcpd'];
3460
	$dhcpdenable = false;
3461
	if($config['dhcpd']) {
3462
		foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
3463
			if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3464
				$dhcpdenable = true;
3465
			if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3466
				$dhcpdenable = true;
3467
		}
3468
	}
3469
	return $dhcpdenable;
3470
}
3471

    
3472
/* return outside interfaces with a gateway */
3473
function get_interfaces_with_gateway() {
3474
	global $config;
3475
	$ints = array();
3476
	$vfaces = array(
3477
			'bridge.?*',
3478
			'ppp.?*',
3479
			'sl.?*',
3480
			'gif.?*',
3481
			'faith.?*',
3482
			'lo.?*',
3483
			'ng.?*',
3484
			'vlan.?*',
3485
			'pflog.?*',
3486
			'pfsync.?*',
3487
			'enc.?*',
3488
			'tun.?*',
3489
			'carp.?*'
3490
		);	
3491
	$ifdescrs = get_interface_list("active","physical",$vfaces);
3492

    
3493

    
3494
	/* loop interfaces, check config for outbound */
3495
	foreach ($ifdescrs as $ifdescr => $ifname) {
3496
		$friendly = $ifname['friendly'];
3497
		if ($config['interfaces'][$friendly]['ipaddr'] == "dhcp") {
3498
			$ints[] = $friendly;
3499
			continue;
3500
		}
3501
		if ($config['interfaces'][$friendly]['ipaddr'] == "pppoe") {
3502
			$ints[] = $friendly;
3503
			continue;
3504
		}
3505
		if ($config['interfaces'][$friendly]['ipaddr'] == "pptp") {
3506
			$ints[] = $friendly;
3507
			continue;
3508
		}
3509
		if ($config['interfaces'][$friendly]['gateway'] <> "") {
3510
			$ints[] = $friendly;
3511
			continue;
3512
		}
3513
	}
3514
	return $ints;
3515
}
3516

    
3517
/* return true if interface has a gateway */
3518
function interface_has_gateway($friendly) {
3519
	$friendly = strtolower($friendly);
3520
	if(in_array($friendly, get_interfaces_with_gateway())) {
3521
		return true;
3522
	} else {
3523
		/* extra check for real interface names if it falls through */
3524
		$friendly = convert_real_interface_to_friendly_interface_name($friendly);
3525
		return(in_array($friendly, get_interfaces_with_gateway()));
3526
	}
3527
}
3528

    
3529
//returns interface information
3530
function get_interface_info($ifdescr) {
3531
	global $config, $linkinfo, $netstatrninfo;
3532

    
3533
	$ifinfo = array();
3534

    
3535
	/* find out interface name */
3536
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
3537
	if ($ifdescr == "wan")
3538
		$ifinfo['if'] = get_real_wan_interface();
3539
	else
3540
		$ifinfo['if'] = $ifinfo['hwif'];
3541

    
3542
	/* run netstat to determine link info */
3543

    
3544
	unset($linkinfo);
3545
	exec("/usr/bin/netstat -I " . $ifinfo['hwif'] . " -nWb -f link", $linkinfo);
3546
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3547
	if (preg_match("/\*$/", $linkinfo[0])) {
3548
		$ifinfo['status'] = "down";
3549
	} else {
3550
		$ifinfo['status'] = "up";
3551
	}
3552

    
3553
	if (!strstr($ifinfo['if'],'tun')) {
3554
		$ifinfo['macaddr'] = $linkinfo[3];
3555
		$ifinfo['inpkts'] = $linkinfo[4];
3556
		$ifinfo['inerrs'] = $linkinfo[5];
3557
		$ifinfo['inbytes'] = $linkinfo[6];
3558
		$ifinfo['outpkts'] = $linkinfo[7];
3559
		$ifinfo['outerrs'] = $linkinfo[8];
3560
		$ifinfo['outbytes'] = $linkinfo[9];
3561
		$ifinfo['collisions'] = $linkinfo[10];
3562
	} else {
3563
		$ifinfo['inpkts'] = $linkinfo[3];
3564
		$ifinfo['inbytes'] = $linkinfo[5];
3565
		$ifinfo['outpkts'] = $linkinfo[6];
3566
		$ifinfo['outbytes'] = $linkinfo[8];
3567
	}
3568

    
3569
	/* DHCP? -> see if dhclient is up */
3570
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "dhcp")) {
3571
		/* see if dhclient is up */
3572
		if (is_dhcp_running("wan") == true)
3573
			$ifinfo['dhcplink'] = "up";
3574
		else
3575
			$ifinfo['dhcplink'] = "down";
3576
	}
3577
	/* loop through optional interfaces looking to see if they are dhcp */
3578
        for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
3579
                $ifdescrs['opt' . $j] = $config['interfaces']['opt' . $j]['descr'];
3580
                if (($ifdescr == "opt{$j}") && ($config['interfaces']['opt' . $j]['ipaddr'] == "dhcp")) {
3581
                        /* see if dhclient is up */
3582
                        if (is_dhcp_running("opt{$j}") == true)
3583
                                $ifinfo['dhcplink'] = "up";
3584
                        else
3585
                                $ifinfo['dhcplink'] = "down";
3586
                }
3587
        }
3588

    
3589
	/* PPPoE interface? -> get status from virtual interface */
3590
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pppoe")) {
3591
		unset($linkinfo);
3592
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3593
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3594
		if (preg_match("/\*$/", $linkinfo[0])) {
3595
			$ifinfo['pppoelink'] = "down";
3596
		} else {
3597
			/* get PPPoE link status for dial on demand */
3598
			$ifconfiginfo = "";
3599
			unset($ifconfiginfo);
3600
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3601

    
3602
			$ifinfo['pppoelink'] = "up";
3603

    
3604
			foreach ($ifconfiginfo as $ici) {
3605
				if (strpos($ici, 'LINK0') !== false)
3606
					$ifinfo['pppoelink'] = "down";
3607
			}
3608
		}
3609
	}
3610

    
3611
	/* PPTP interface? -> get status from virtual interface */
3612
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pptp")) {
3613
		unset($linkinfo);
3614
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3615
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3616
		if (preg_match("/\*$/", $linkinfo[0])) {
3617
			$ifinfo['pptplink'] = "down";
3618
		} else {
3619
			/* get PPTP link status for dial on demand */
3620
			unset($ifconfiginfo);
3621
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3622

    
3623
			$ifinfo['pptplink'] = "up";
3624

    
3625
			foreach ($ifconfiginfo as $ici) {
3626
				if (strpos($ici, 'LINK0') !== false)
3627
					$ifinfo['pptplink'] = "down";
3628
			}
3629
		}
3630
	}
3631

    
3632
	if ($ifinfo['status'] == "up") {
3633
		/* try to determine media with ifconfig */
3634
		unset($ifconfiginfo);
3635
		exec("/sbin/ifconfig " . $ifinfo['hwif'], $ifconfiginfo);
3636
		$matches = "";
3637
		foreach ($ifconfiginfo as $ici) {
3638

    
3639
			/* don't list media/speed for wireless cards, as it always
3640
			   displays 2 Mbps even though clients can connect at 11 Mbps */
3641
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
3642
				$ifinfo['media'] = $matches[1];
3643
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
3644
				$ifinfo['media'] = $matches[1];
3645
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
3646
				$ifinfo['media'] = $matches[1];
3647
			}
3648

    
3649
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
3650
				if ($matches[1] != "active")
3651
					$ifinfo['status'] = $matches[1];
3652
			}
3653
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
3654
				$ifinfo['channel'] = $matches[1];
3655
			}
3656
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
3657
				if ($matches[1][0] == '"')
3658
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
3659
				else
3660
					$ifinfo['ssid'] = $matches[1];
3661
			}
3662
		}
3663

    
3664
		if ($ifinfo['pppoelink'] != "down" && $ifinfo['pptplink'] != "down") {
3665
			/* try to determine IP address and netmask with ifconfig */
3666
			unset($ifconfiginfo);
3667
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3668

    
3669
			foreach ($ifconfiginfo as $ici) {
3670
				if (preg_match("/inet (\S+)/", $ici, $matches)) {
3671
					$ifinfo['ipaddr'] = $matches[1];
3672
				}
3673
				if (preg_match("/netmask (\S+)/", $ici, $matches)) {
3674
					if (preg_match("/^0x/", $matches[1]))
3675
						$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
3676
				}
3677
			}
3678

    
3679
			if ($ifdescr == "wan") {
3680
				/* run netstat to determine the default gateway */
3681
				unset($netstatrninfo);
3682
				exec("/usr/bin/netstat -rnf inet", $netstatrninfo);
3683

    
3684
				foreach ($netstatrninfo as $nsr) {
3685
					if (preg_match("/^default\s*(\S+)/", $nsr, $matches)) {
3686
						$ifinfo['gateway'] = $matches[1];
3687
					}
3688
				}
3689
			} else {
3690
				/* deterimine interface gateway */
3691
				$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3692
				$gw = get_interface_gateway($int);
3693
				if($gw)
3694
					$ifinfo['gateway'] = $gw;
3695
			}
3696
		}
3697
	}
3698

    
3699
	$bridge = "";
3700
	$int = "";
3701
	$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3702
	$bridge = link_int_to_bridge_interface($int);
3703
	if($bridge) {
3704
		$bridge_text = `/sbin/ifconfig {$bridge}`;
3705
		if(stristr($bridge_text, "blocking") <> false) {
3706
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
3707
			$ifinfo['bridgeint'] = $bridge;
3708
		} else if(stristr($bridge_text, "learning") <> false) {
3709
			$ifinfo['bridge'] = "learning";
3710
			$ifinfo['bridgeint'] = $bridge;
3711
		} else if(stristr($bridge_text, "forwarding") <> false) {
3712
			$ifinfo['bridge'] = "forwarding";
3713
			$ifinfo['bridgeint'] = $bridge;
3714
		}
3715
	}
3716

    
3717
	return $ifinfo;
3718
}
3719

    
3720

    
3721
//returns cpu speed of processor. Good for determining capabilities of machine
3722
function get_cpu_speed() {
3723
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
3724
}
3725

    
3726
/* check if the wan interface is up
3727
 * Wait for a maximum of 10 seconds
3728
 * If the interface is up before then continue
3729
 */
3730
function is_wan_interface_up($interface) {
3731
	global $g;
3732
	global $config;
3733
	$i = 0;
3734
	while($i < 10) {
3735
		if(get_interface_gateway($interface)) {
3736
			return true;
3737
		} else {
3738
			sleep(1);
3739
		}
3740
		$i++;
3741
	}
3742
	return false;
3743
}
3744

    
3745
/****f* pfsense-utils/safe_write_file
3746
 * NAME
3747
 *   safe_write_file - Write a file out atomically
3748
 * DESCRIPTION
3749
 *   safe_write_file() Writes a file out atomically by first writing to a
3750
 *   temporary file of the same name but ending with the pid of the current
3751
 *   process, them renaming the temporary file over the original.
3752
 * INPUTS
3753
 *   $filename  - string containing the filename of the file to write
3754
 *   $content   - string containing the file content to write to file
3755
 *   $force_binary      - boolean denoting whether we should force binary
3756
 *   mode writing.
3757
 * RESULT
3758
 *   boolean - true if successful, false if not
3759
 ******/
3760
function safe_write_file($file, $content, $force_binary) {
3761
        $tmp_file = $file . "." . getmypid();
3762
        $write_mode = $force_binary ? "wb" : "w";
3763

    
3764
        $fd = fopen($tmp_file, $write_mode);
3765
        if (!$fd) {
3766
                // Unable to open temporary file for writing
3767
                return false;
3768
        }
3769
        if (!fwrite($fd, $content)) {
3770
                // Unable to write to temporary file
3771
                fclose($fd);
3772
                return false;
3773
        }
3774
        fclose($fd);
3775

    
3776
        if (!rename($tmp_file, $file)) {
3777
                // Unable to move temporary file to original
3778
                unlink($tmp_file);
3779
                return false;
3780
        }
3781
        return true;
3782
}
3783

    
3784
/* Write out all the found IP addresses to a file
3785
 * so we can compare it on change */
3786
function add_hostname_to_watch($hostname) {
3787
	if(!is_dir("/var/db/dnscache")) {
3788
		mkdir("/var/db/dnscache");
3789
	}
3790
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
3791
		$domrecords = array();
3792
		$domips = array();
3793
		exec("host -t A $hostname", $domrecords, $rethost);
3794
		if($rethost == 0) {
3795
			foreach($domrecords as $domr) {
3796
				$doml = explode(" ", $domr);
3797
				$domip = $doml[3];
3798
				/* fill array with domain ip addresses */
3799
				if(is_ipaddr($domip)) {
3800
					$domips[] = $domip;
3801
				}
3802
			}
3803
		}
3804
		sort($domips);
3805
		$contents = "";
3806
		if(! empty($domips)) {
3807
			foreach($domips as $ip) {
3808
				$contents .= "$ip\n";
3809
			}
3810
		}
3811
		file_put_contents("/var/db/dnscache/$hostname", $contents);
3812
	}
3813
}
3814

    
3815
/* Compare the current hostname DNS to the DNS cache we made
3816
 * if it has changed we return the old records
3817
 * if no change we return true */
3818
function compare_hostname_to_dnscache($hostname) {
3819
	if(!is_dir("/var/db/dnscache")) {
3820
		mkdir("/var/db/dnscache");
3821
	}
3822
	$hostname = trim($hostname);
3823
	if(is_readable("/var/db/dnscache/{$hostname}")) {
3824
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
3825
	} else {
3826
		$oldcontents = "";
3827
	}
3828
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
3829
		$domrecords = array();
3830
		$domips = array();
3831
		exec("host -t A $hostname", $domrecords, $rethost);
3832
		if($rethost == 0) {
3833
			foreach($domrecords as $domr) {
3834
				$doml = explode(" ", $domr);
3835
				$domip = $doml[3];
3836
				/* fill array with domain ip addresses */
3837
				if(is_ipaddr($domip)) {
3838
					$domips[] = $domip;
3839
				}
3840
			}
3841
		}
3842
		sort($domips);
3843
		$contents = "";
3844
		if(! empty($domips)) {
3845
			foreach($domips as $ip) {
3846
				$contents .= "$ip\n";
3847
			}
3848
		}
3849
	}
3850

    
3851
	if(trim($oldcontents) != trim($contents)) {
3852
		if($g['debug']) {
3853
			log_error("DNSCACHE: Found old IP {$oldcontents} and new IP {$contents}");
3854
		}
3855
		return ($oldcontents);
3856
	} else {
3857
		return false;
3858
	}
3859
}
3860

    
3861
function is_fqdn($fqdn) {
3862
	$hostname = false;
3863
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
3864
		$hostname = true;
3865
	}
3866
	if(preg_match("/\.\./", $fqdn)) {
3867
		$hostname = false;
3868
	}
3869
	if(preg_match("/^\./i", $fqdn)) { 
3870
		$hostname = false;
3871
	}
3872
	if(preg_match("/\//i", $fqdn)) {
3873
		$hostname = false;
3874
	}
3875
	return($hostname);
3876
}
3877

    
3878

    
3879
?>
(14-14/27)