Project

General

Profile

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

    
36
/****f* pfsense-utils/have_natonetooneruleint_access
37
 * NAME
38
 *   have_natonetooneruleint_access
39
 * INPUTS
40
 *	 none
41
 * RESULT
42
 *   returns true if user has access to edit a specific firewall nat one to one interface
43
 ******/
44
function have_natonetooneruleint_access($if) {
45
	global $config, $g, $HTTP_SERVER_VARS;
46
	$allowed = $g['privs'];
47
	if (isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) 
48
		return true;
49
	$security_url = "firewall_nat_1to1_edit.php?if=". strtolower($if);
50
	if(in_array($security_url, $allowed)) 
51
		return true;
52
	return false;
53
}
54

    
55
/****f* pfsense-utils/have_natpfruleint_access
56
 * NAME
57
 *   have_natpfruleint_access
58
 * INPUTS
59
 *	 none
60
 * RESULT
61
 *   returns true if user has access to edit a specific firewall nat port forward interface
62
 ******/
63
function have_natpfruleint_access($if) {
64
	global $config, $g, $HTTP_SERVER_VARS, $allowed;
65
	if(!$allowed)
66
		$allowed = $g['privs'];
67
	if (isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) 
68
		return true;
69
	$security_url = "firewall_nat_edit.php?if=". strtolower($if);
70
	if(in_array($security_url, $allowed)) 
71
		return true;
72
	return false;
73
}
74

    
75
/****f* pfsense-utils/have_ruleint_access
76
 * NAME
77
 *   have_ruleint_access
78
 * INPUTS
79
 *	 none
80
 * RESULT
81
 *   returns true if user has access to edit a specific firewall interface
82
 ******/
83
function have_ruleint_access($if) {
84
	global $config, $g, $HTTP_SERVER_VARS;
85
	$allowed = $g['privs'];
86
	if (isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) 
87
		return true;
88
	$security_url = "firewall_rules.php?if=". strtolower($if);
89
	if(is_array($allowed))
90
		if(in_array($security_url, $allowed)) 
91
			return true;
92
	return false;
93
}
94

    
95
/****f* pfsense-utils/does_url_exist
96
 * NAME
97
 *   does_url_exist
98
 * INPUTS
99
 *	 none
100
 * RESULT
101
 *   returns true if a url is available
102
 ******/
103
function does_url_exist($url) {
104
	$fd = fopen("$url","r");
105
	if($fd) {
106
		fclose($fd);
107
   		return true;    
108
	} else {
109
        return false;
110
	}
111
}
112

    
113
/****f* pfsense-utils/is_private_ip
114
 * NAME
115
 *   is_private_ip
116
 * INPUTS
117
 *	 none
118
 * RESULT
119
 *   returns true if an ip address is in a private range
120
 ******/
121
function is_private_ip($iptocheck) {
122
        $isprivate = false;
123
        $ip_private_list=array(
124
               "10.0.0.0/8",
125
               "172.16.0.0/12",
126
               "192.168.0.0/16",
127
               "99.0.0.0/8"
128
        );
129
        foreach($ip_private_list as $private) {
130
                if(ip_in_subnet($iptocheck,$private)==true)
131
                        $isprivate = true;
132
        }
133
        return $isprivate;
134
}
135

    
136
/****f* pfsense-utils/get_tmp_file
137
 * NAME
138
 *   get_tmp_file
139
 * INPUTS
140
 *	 none
141
 * RESULT
142
 *   returns a temporary filename
143
 ******/
144
function get_tmp_file() {
145
	return "/tmp/tmp-" . time();
146
}
147

    
148
/****f* pfsense-utils/tdr_install_cron
149
 * NAME
150
 *   tdr_install_cron
151
 * INPUTS
152
 *   $should_install true if the cron entry should be installed, false
153
 *   if the entry should be removed if it is present
154
 * RESULT
155
 *   none
156
 ******/
157
function tdr_install_cron($should_install) {
158
	global $config, $g;
159
	if($g['booting']==true) 
160
		return;
161
	$is_installed = false;
162
	if(!$config['cron']['item'])
163
		return;
164
	$x=0;
165
	foreach($config['cron']['item'] as $item) {
166
		if(strstr($item['command'], "filter_configure_sync")) {
167
			$is_installed = true;
168
			break;
169
		}
170
		$x++;
171
	}
172
	switch($should_install) {
173
		case true:
174
			if(!$is_installed) {
175
				$cron_item = array();
176
				$cron_item['minute'] = "0,15,30,45";
177
				$cron_item['hour'] = "*";
178
				$cron_item['mday'] = "*";
179
				$cron_item['month'] = "*";
180
				$cron_item['wday'] = "*";
181
				$cron_item['who'] = "root";
182
				$cron_item['command'] = "/etc/rc.filter_configure_sync";		
183
				$config['cron']['item'][] = $cron_item;
184
				write_config("Installed 15 minute filter reload for Time Based Rules");
185
				configure_cron();
186
			}
187
		break;
188
		case false:
189
			if($is_installed == true) {
190
				if($x > 0) {
191
					unset($config['cron']['item'][$x]);
192
					write_config();
193
				}
194
				configure_cron();
195
			}
196
		break;
197
	}
198
}
199

    
200
/****f* pfsense-utils/tdr_create_ipfw_rule
201
 * NAME
202
 *   tdr_create_ipfw_rule
203
 * INPUTS
204
 *   $rule xml firewall rule array, $type allow or deny
205
 * RESULT
206
 *   text string with ipfw rule already formatted
207
 ******/
208
function tdr_create_ipfw_rule($rule, $type) {
209
		global $config, $g, $tdr_get_next_ipfw_rule;
210

    
211
		$wancfg = $config['interfaces']['wan'];
212
		$lancfg = $config['interfaces']['lan'];
213
		$pptpdcfg = $config['pptpd'];
214
		$pppoecfg = $config['pppoe'];
215

    
216
		$lanif = $lancfg['if'];
217
		$wanif = get_real_wan_interface();
218

    
219
		$lanip = $lancfg['ipaddr'];
220
		$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
221
		$lansn = $lancfg['subnet'];
222

    
223
		$int = "";
224

    
225
		$optcfg = array();
226
		generate_optcfg_array($optcfg);
227

    
228
		$curwanip = get_current_wan_address();
229

    
230
		/* don't include disabled rules */
231
		if (isset($rule['disabled'])) {
232
			return "";
233
		}
234

    
235
		$pptpdcfg = $config['pptpd'];
236
		$pppoecfg = $config['pppoe'];
237

    
238
		if ($pptpdcfg['mode'] == "server") {
239
			$pptpip = $pptpdcfg['localip'];
240
			$pptpsa = $pptpdcfg['remoteip'];
241
			$pptpsn = $g['pptp_subnet'];
242
			if($config['pptp']['pptp_subnet'] <> "")
243
				$pptpsn = $config['pptp']['pptp_subnet'];
244
		}
245

    
246
		if ($pppoecfg['mode'] == "server") {
247
			$pppoeip = $pppoecfg['localip'];
248
			$pppoesa = $pppoecfg['remoteip'];
249
			$pppoesn = $g['pppoe_subnet'];
250
			if($config['pppoe']['pppoe_subnet'] <> "")
251
				$pppoesn = $config['pppoe']['pppoe_subnet'];
252
		}
253

    
254
		/* does the rule deal with a PPTP interface? */
255
		if ($rule['interface'] == "pptp") {
256
			if ($pptpdcfg['mode'] != "server")
257
				return "";
258
			$nif = $g['n_pptp_units'];
259
			if($config['pptp']['n_pptp_units'] <> "")
260
				$nif = $config['pptp']['n_pptp_units'];
261
			$ispptp = true;
262
		} else if($rule['interface'] == "pppoe") {
263
			if ($pppoecfg['mode'] != "server") {
264
				return " # Error creating pppoe rule";
265
			}
266
			$nif = $g['n_pppoe_units'];
267
			if($config['pppoe']['n_pppoe_units'] <> "")
268
				$nif = $config['pppoe']['n_pppoe_units'];
269
			$ispppoe = true;
270
		} else {
271

    
272
			/* Check to see if the interface is opt and in our opt list */
273
			if (strstr($rule['interface'], "opt")) {
274
 				if (!array_key_exists($rule['interface'], $optcfg)) {
275
					$item = "";
276
					foreach($optcfg as $oc) $item .= $oc['if'];
277
					return "# {$real_int} {$item} {$rule['interface']} array key does not exist for " . $rule['descr'];
278
				}
279
			}
280

    
281
			$nif = 1;
282
			$ispptp = false;
283
			$ispppoe = false;
284
		}
285
		if ($pptpdcfg['mode'] != "server") {
286
			if (($rule['source']['network'] == "pptp") ||
287
				($rule['destination']['network'] == "pptp")) {
288
					return "# source network or destination network == pptp on " . $rule['descr'];
289
				}
290
		}
291
		if ($rule['source']['network'] && strstr($rule['source']['network'], "opt")) {
292
			if (!array_key_exists($rule['source']['network'], $optcfg)) {
293
				$optmatch = "";
294
				if(preg_match("/opt([0-999])/", $rule['source']['network'], $optmatch)) {
295
					$real_opt_int = convert_friendly_interface_to_real_interface_name("opt" . $optmatch[1]);
296
					$opt_ip = find_interface_ip($real_opt_int);
297
					if(!$opt_ip)
298
						return "# unresolvable optarray $real_opt_int - $optmatch[0] - $opt_ip";
299
				} else {
300
					return "# {$rule['source']['network']} !array_key_exists source network " . $rule['descr'];
301
				}
302
			}
303
		}
304
		if ($rule['destination']['network'] && strstr($rule['destination']['network'], "opt")) {
305
			if (!array_key_exists($rule['destination']['network'], $optcfg)) {
306
				if(preg_match("/opt([0-999])/", $rule['destination']['network'], $optmatch)) {
307
					$real_opt_int = convert_friendly_interface_to_real_interface_name("opt" . $optmatch[1]);
308
					$opt_ip = find_interface_ip($real_opt_int);
309
					if(!$opt_ip)
310
						return "# unresolvable oparray $real_opt_int - $optmatch[0] - $opt_ip";
311
				} else {
312
					return "# {$item} {$rule['destination']['network']} !array_key_exists dest network " . $rule['descr'];
313
				}
314
			}
315
		}
316
		/* check for unresolvable aliases */
317
		if ($rule['source']['address'] && !alias_expand($rule['source']['address'])) {
318
			file_notice("Filter_Reload", "# unresolvable source aliases {$rule['descr']}");
319
			return "# tdr unresolvable source aliases {$rule['descr']}";
320
		}
321
		if ($rule['destination']['address'] && !alias_expand($rule['destination']['address'])) {
322
			file_notice("Filter_Reload", "# unresolvable dest aliases {$rule['descr']}");
323
			return "# tdr unresolvable dest aliases {$rule['descr']}";
324
		}
325

    
326
		$ifdescrs = array();
327
		for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
328
			$ifdescrs[] = "opt" . $i;
329

    
330
		for ($iif = 0; $iif < $nif; $iif++) {
331

    
332
			if ($ispptp) {
333
				$aline['interface'] = "\$pptp ";
334
			} else if ($ispppoe) {
335
				$aline['interface'] = "\$pppoe ";
336
			} else {
337
				// translate wan, man, lan, opt to real interface.
338
				$interface = $rule['interface'];
339
				$temp = filter_get_opt_interface_descr($interface);
340
				if($temp <> "") $interface = $temp;
341
				$aline['interface'] = convert_friendly_interface_to_real_interface_name($rule['interface']) . " ";
342
			}
343

    
344
			if (isset($rule['protocol'])) {
345
				if($rule['protocol'] == "tcp/udp")
346
					$aline['prot'] = "ip ";
347
				elseif($rule['protocol'] == "icmp")
348
					$aline['prot'] = "icmp ";
349
				else
350
					$aline['prot'] = "{$rule['protocol']} ";
351
			} else {
352
				if($rule['source']['port'] <> "" || $rule['destination']['port'] <> "") {
353
					$aline['prot'] = "tcp ";
354
				}
355
			}
356

    
357
			/* source address */
358
			if (isset($rule['source']['any'])) {
359
				$src = "any";
360
			} else if ($rule['source']['network']) {
361

    
362
				if (strstr($rule['source']['network'], "opt")) {
363
					$src = $optcfg[$rule['source']['network']]['sa'] . "/" .
364
						$optcfg[$rule['source']['network']]['sn'];
365
					if (isset($rule['source']['not'])) $src = " not {$src}";
366
					/* check for opt$NUMip here */
367
					$matches = "";
368
					if (preg_match("/opt([0-9999])ip/", $rule['source']['network'], $matches)) {
369
						$optnum = $matches[1];
370
						$real_int = convert_friendly_interface_to_real_interface_name("opt{$optnum}");
371
						$src = find_interface_ip($real_int);
372
					}
373
				} else {
374
					switch ($rule['source']['network']) {
375
						case 'wanip':
376
							$src = $curwanip;
377
							break;
378
						case 'lanip':
379
							$src = $lanip;
380
							break;
381
						case 'lan':
382
							$src = "{$lansa}/{$lansn}";
383
							break;
384
						case 'pptp':
385
							$src = "{$pptpsa}/{$pptpsn}";
386
							break;
387
						case 'pppoe':
388
							$src = "{$pppoesa}/{$pppoesn}";
389
							break;
390
					}
391
					if (isset($rule['source']['not'])) $src = " not {$src}";
392
				}
393
			} else if ($rule['source']['address']) {
394
				$expsrc = alias_expand_value($rule['source']['address']);
395
				if(!$expsrc) 
396
					$expsrc = $rule['source']['address'];
397
					
398
				if (isset($rule['source']['not']))
399
					$not = " not";
400
				else
401
					$not = "";
402

    
403
				if(alias_expand_value($rule['source']['address'])) {
404
					$src = "{";
405
					$first_item = true;
406
					foreach(preg_split("/[\s]+/", alias_expand_value($rule['source']['address'])) as $item) {
407
						if($item != "") {
408
							if(!$first_item) 
409
								$src .= " or";
410
							$src .= " {$not}{$item}";
411
							$first_item = false;
412
						}
413
					}
414
					$src .= " }";
415
				} else {
416
					$src = "{$not}" . $expsrc;
417
				}
418

    
419
			}
420

    
421
			if (!$src || ($src == "/")) {
422
				return "# tdr at the break!";
423
			}
424

    
425
			$aline['src'] = "from $src ";
426
			$srcporta = "";
427
			if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
428
				if ($rule['source']['port']) {
429
					$srcport = explode("-", $rule['source']['port']);
430
					if(alias_expand($srcport[0])) {
431
						$first_time = true;
432
						foreach(preg_split("/[\s]+/", alias_expand_value($srcport[0])) as $item) {
433
							if(!$first_time) 
434
								$srcporta .= ",";				
435
							$srcporta .= $item;
436
							$first_time = false;
437
						}
438
					} else {
439
						$srcporta = $srcport[0];
440
					}
441
					if ((!$srcport[1]) || ($srcport[0] == $srcport[1])) {
442
						if(alias_expand($srcport[0]))
443
							$aline['srcport'] = "{$srcporta} ";
444
						else
445
							$aline['srcport'] = "{$srcporta} ";
446
					} else if (($srcport[0] == 1) && ($srcport[1] == 65535)) {
447
						/* no need for a port statement here */
448
					} else if ($srcport[1] == 65535) {
449
						$aline['srcport'] = ">={$srcport[0]} ";
450
					} else if ($srcport[0] == 1) {
451
						$aline['srcport']= "<={$srcport[1]} ";
452
					} else {
453
						$aline['srcport'] = "{$srcport[0]}-{$srcport[1]} ";
454
					}
455
				}
456
			}
457

    
458
			/* destination address */
459
			if (isset($rule['destination']['any'])) {
460
				$dst = "any";
461
			} else if ($rule['destination']['network']) {
462

    
463
				if (strstr($rule['destination']['network'], "opt")) {
464
					$dst = $optcfg[$rule['destination']['network']]['sa'] . "/" .
465
						$optcfg[$rule['destination']['network']]['sn'];
466
					/* check for opt$NUMip here */
467
					$matches = "";
468
					if (preg_match("/opt([0-9999])ip/", $rule['destination']['network'], $matches)) {
469
						$optnum = $matches[1];
470
						$real_int = convert_friendly_interface_to_real_interface_name("opt{$optnum}");
471
						$dst = find_interface_ip($real_int);
472
					}
473
					if (isset($rule['destination']['not'])) $dst = " not {$dst}";
474
				} else {
475
					switch ($rule['destination']['network']) {
476
						case 'wanip':
477
							$dst = $curwanip;
478
							break;
479
						case 'lanip':
480
							$dst = $lanip;
481
							break;
482
						case 'lan':
483
							$dst = "{$lansa}/{$lansn}";
484
							break;
485
						case 'pptp':
486
							$dst = "{$pptpsa}/{$pptpsn}";
487
							break;
488
						case 'pppoe':
489
							$dst = "{$ppoesa}/{$pppoesn}";
490
							break;
491
					}
492
					if (isset($rule['destination']['not'])) $dst = " not {$dst}";
493
				}
494
			} else if ($rule['destination']['address']) {
495
				$expdst = alias_expand_value($rule['destination']['address']);
496
				if(!$expdst) 
497
					$expdst = $rule['destination']['address'];
498

    
499
				if (isset($rule['destination']['not']))
500
					$not = " not ";
501
				else
502
					$not = "";
503

    
504
				if(alias_expand_value($rule['destination']['address'])) {
505
					$dst = "{";
506
					$first_item = true;
507
					foreach(preg_split("/[\s]+/", alias_expand_value($rule['destination']['address'])) as $item) {
508
						if($item != "") {
509
							if(!$first_item) 
510
								$dst .= " or";
511
							$dst .= " {$not}{$item}";
512
							$first_item = false;
513
						}
514
					}
515
					$dst .= " }";
516
				} else {
517
					$dst = "{$not}" . $expdst;
518
				}
519
			}
520

    
521
			if (!$dst || ($dst == "/")) {
522
				return "# returning at dst $dst == \"/\"";
523
			}
524

    
525
			$aline['dst'] = "to $dst ";
526
			$dstporta = "";
527
			if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
528
				if ($rule['destination']['port']) {
529
					$dstport = explode("-", $rule['destination']['port']);
530
					if(alias_expand($dstport[0])) {
531
						$first_time = true;
532
						foreach(preg_split("/[\s]+/", alias_expand_value($dstport[0])) as $item) {
533
							if(!$first_time)
534
							 	$dstporta .= ",";
535
							$dstporta .= $item;			
536
							$first_time = false;
537
						}
538
					} else {
539
						$dstporta = $dstport[0];
540
					}
541
					if ((!$dstport[1]) || ($dstport[0] == $dstport[1])) {
542
						if(alias_expand($dstport[0]))
543
							$aline['dstport'] = "{$dstporta} ";
544
						else
545
							$aline['dstport'] = "{$dstporta} ";
546
					} else if (($dstport[0] == 1) && ($dstport[1] == 65535)) {
547
						/* no need for a port statement here */
548
					} else if ($dstport[1] == 65535) {
549
						$aline['dstport'] = ">= {$dstport[0]} ";
550
					} else if ($dstport[0] == 1) {
551
						$aline['dstport'] = "<= {$dstport[1]} ";
552
					}  else {
553
						$aline['dstport'] = "{$dstport[0]}-{$dstport[1]} ";
554
					}
555
				}
556
			}
557

    
558
	}
559
	
560
	if($aline['prot'] == "")
561
		$aline['prot'] = "ip ";
562

    
563
	tdr_get_next_ipfw_rule();
564

    
565
 	/* piece together the actual user rule */
566
	if($type == "skipto") {
567
		$next_rule = tdr_get_next_ipfw_rule();
568
		$next_rule = $next_rule+1;
569
		$type = "skipto $next_rule";
570
	}
571

    
572
	/* piece together the actual user rule */
573
	$line .= $type . " " . $aline['prot'] . $aline['src'] . 
574
	$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in recv " . $aline['interface'];
575

    
576
	return $line;
577

    
578
}
579

    
580
/****f* pfsense-utils/tdr_install_rule
581
 * NAME
582
 *   tdr_install_rule
583
 * INPUTS
584
 *   $rule - ascii string containing the ifpw rule to add
585
 * RESULT
586
 *   none
587
 ******/
588
function tdr_install_rule($rule) {
589
	global $tdr_next_ipfw_rule;
590
	mwexec("/sbin/ipfw -f add $tdr_next_ipfw_rule set 9 $rule");
591
	$tdr_next_ipfw_rule++;
592
}
593

    
594
/****f* pfsense-utils/tdr_get_next_ipfw_rule
595
 * NAME
596
 *   tdr_get_next_ipfw_rule
597
 * INPUTS
598
 *  none
599
 * RESULT
600
 *   returns the next available ipfw rule number
601
 ******/
602
function tdr_get_next_ipfw_rule() {
603
	global $tdr_next_ipfw_rule;
604
	if(intval($tdr_next_ipfw_rule) < 2) 
605
		$tdr_next_ipfw_rule = 2;
606
	return $tdr_next_ipfw_rule;
607
 }
608

    
609
/****f* pfsense-utils/tdr_install_set
610
 * NAME
611
 *   tdr_install_set
612
 * INPUTS
613
 *  none
614
 * RESULT
615
 *   swaps in the temporary ipfw time based rule set
616
 ******/
617
function tdr_install_set() {
618
	global $config;
619
	
620
	mwexec("/sbin/ipfw delete 1");
621
	mwexec("/sbin/ipfw add 1 check-state");
622
	mwexec("/sbin/ipfw delete 65534");
623
	mwexec("/sbin/ipfw add 1 allow all from me to any keep-state");
624
	if (!isset ($config['system']['webgui']['noantilockout'])) {
625
		/* lan ip lockout */
626
		$lancfg = $config['interfaces']['lan'];
627
		$lanip = $lancfg['ipaddr'];
628
		$lansn = $lancfg['subnet'];
629
		$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
630
		mwexec("/sbin/ipfw add 1 allow all from {$lansa}/{$lansn} to $lanip keep-state");
631
	}
632
	mwexec("/sbin/ipfw add 65534 check-state");
633
	/* set 8 contains time based rules */
634
	mwexec("/sbin/ipfw -f delete set 8");
635
	mwexec("/sbin/ipfw -f set swap 9 8");
636
}
637

    
638
/****f* pfsense-utils/get_time_based_rule_status
639
 * NAME
640
 *   get_time_based_rule_status
641
 * INPUTS
642
 *   xml schedule block
643
 * RESULT
644
 *   true/false - true if the rule should be installed
645
 ******/
646
/*
647
 <schedules>
648
   <schedule>
649
     <name>ScheduleMultipleTime</name>
650
     <descr>main descr</descr>
651
     <time>
652
       <position>0,1,2</position>
653
       <hour>0:0-24:0</hour>
654
       <desc>time range 2</desc>
655
     </time>
656
     <time>
657
       <position>4,5,6</position>
658
       <hour>0:0-24:0</hour>
659
       <desc>time range 1</desc>
660
     </time>
661
   </schedule>
662
 </schedules>
663
*/
664
function get_time_based_rule_status($schedule) {
665
	$should_add_rule = false;
666
	global $debug;
667
	/* no schedule? rule should be installed */
668
	if($schedule == "") 
669
		return true;
670
	/*
671
	 * iterate through time blocks and deterimine
672
	 * if the rule should be installed or not.
673
	 */
674
	foreach($schedule['timerange'] as $timeday) {
675
		if($timeday['month']) 
676
			$month = $timeday['month'];
677
		else 
678
			$week = "";	
679
		if($timeday['day']) 
680
			$day = $timeday['day'];
681
		else 
682
			$day = "";
683
		if($timeday['hour']) 
684
			$hour = $timeday['hour'];
685
		else 
686
			$hour = "";
687
		if($timeday['position']) 
688
			$position = $timeday['position'];
689
		else 
690
			$position = "";
691
		if($timeday['desc']) 
692
			$desc = $timeday['desc'];
693
		else 
694
			$desc = "";
695
		if($month) {
696
			$monthstatus = tdr_month($month);
697
		} else {
698
			$monthstatus = true;
699
		}
700
		if($day) {
701
			$daystatus = tdr_day($day);
702
		} else {
703
			$daystatus = true;
704
		}
705
		if($hour) {
706
			$hourstatus = tdr_hour($hour);
707
		} else {
708
			$hourstatus = true;
709
		}
710
		if($position) {
711
			$positionstatus = tdr_position($position);
712
		} else {
713
			$positionstatus = true;
714
		}
715

    
716
		if($monthstatus == true) 
717
			if($daystatus == true) 
718
				if($positionstatus == true) 
719
					if($hourstatus == true) {
720
						$should_add_rule = true;
721
					}
722
	}
723
	
724
	return $should_add_rule;
725
}
726

    
727
function tdr_day($schedule) {
728
	/*
729
	 * Calculate day of month. 
730
	 * IE: 29th of may
731
	 */
732
	global $debug;
733
	$weekday	= date("w");
734
	if ($weekday == 0)
735
		$weekday = 7;
736
	$date	 	= date("d");
737
	$defined_days = split(",", $schedule);
738
	log_error("[TDR DEBUG] tdr_day($schedule)");
739
	foreach($defined_days as $dd) {
740
		if($date == $dd) {
741
			return true;
742
		}
743
	}
744
	return false;
745
}
746

    
747
function tdr_hour($schedule) {
748
	/* $schedule should be a string such as 16:00-19:00 */
749
	global $debug;
750
	$tmp = split("-", $schedule);
751
	$starting_time = strtotime($tmp[0]);
752
	$ending_time = strtotime($tmp[1]);
753
	$now = strtotime("now");
754
	log_error("[TDR DEBUG] S: $starting_time E: $ending_time N: $now");
755
	if($now >= $starting_time and $now <= $ending_time) {
756
		return true;
757
	}
758
	return false;
759
}
760

    
761
function tdr_position($schedule) {
762
	/*
763
	 * Calculate possition, ie: day of week.
764
	 * Sunday = 7, Monday = 1, Tuesday = 2
765
	 * Weds = 3, Thursday = 4, Friday = 5,
766
	 * Saturday = 6
767
	 * ...
768
	 */
769
	global $debug;
770
	$weekday	= date("w");
771
	log_error("[TDR DEBUG] tdr_position($schedule) $weekday");
772
	if ($weekday == 0)
773
		$weekday = 7;
774
	$schedule_days = split(",", $schedule);
775
	foreach($schedule_days as $day) {
776
		if($day == $weekday) {
777
			return true;
778
		}
779
	}
780
	return false;
781
}
782

    
783
function tdr_month($schedule) {
784
	/*
785
	 * Calculate month
786
	 */
787
	global $debug;
788
	$todays_month = date("n");
789
	$months = split(",", $schedule);
790
	log_error("[TDR DEBUG] tdr_month($schedule)");
791
	foreach($months as $month) {
792
		if($month == $todays_month) {
793
			return true;
794
		}
795
	}
796
	return false;
797
}
798

    
799
/****f* pfsense-utils/find_number_of_needed_carp_interfaces
800
 * NAME
801
 *   find_number_of_needed_carp_interfaces
802
 * INPUTS
803
 *   null
804
 * RESULT
805
 *   the number of needed carp interfacs
806
 ******/
807
function find_number_of_needed_carp_interfaces() {
808
	global $config, $g;
809
	$carp_counter=0;
810
	if(!$config['virtualip'])
811
		return 0;
812
	if(!$config['virtualip']['vip'])
813
		return 0;
814
	foreach($config['virtualip']['vip'] as $vip) {
815
		if($vip['mode'] == "carp")
816
			$carp_counter++;
817
	}
818
	return $carp_counter;
819
}
820

    
821
/****f* pfsense-utils/reset_carp
822
 * NAME
823
 *   reset_carp - resets carp after primary interface changes
824
 * INPUTS
825
 *   null
826
 * RESULT
827
 *   null
828
 ******/
829
function reset_carp() {
830
	$carp_counter=find_number_of_created_carp_interfaces();
831
	$needed_carp_interfaces = find_number_of_needed_carp_interfaces();
832
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
833
	for($x=0; $x<$carp_counter; $x++) {
834
		mwexec("/sbin/ifconfig carp{$x} down");
835
		usleep(1000);
836
		mwexec("/sbin/ifconfig carp{$x} delete");
837
		if($needed_carp_interfaces < $carp_counter) {
838
			$needed_carp_interfaces--;
839
			//log_error("Destroying carp interface.");
840
			//mwexec("/sbin/ifconfig carp{$x} destroy");
841
		}
842
	}
843
	find_number_of_created_carp_interfaces(true);
844
	sleep(1);
845
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
846
	interfaces_carp_configure();
847
	usleep(1000);
848
	interfaces_carp_bring_up_final();
849
}
850

    
851
/****f* pfsense-utils/get_dns_servers
852
 * NAME
853
 *   get_dns_servres - get system dns servers
854
 * INPUTS
855
 *   $dns_servers - an array of the dns servers
856
 * RESULT
857
 *   null
858
 ******/
859
function get_dns_servers() {
860
	$dns_servers = array();
861
	$dns = `cat /etc/resolv.conf`;
862
	$dns_s = split("\n", $dns);
863
	foreach($dns_s as $dns) {
864
		$matches = "";
865
		if (preg_match("/nameserver (.*)/", $dns, $matches))
866
			$dns_servers[] = $matches[1];
867
	}
868
	$dns_server_master = array();
869
	$lastseen = "";
870
	foreach($dns_servers as $t) {
871
		if($t <> $lastseen)
872
			if($t <> "")
873
				$dns_server_master[] = $t;
874
		$lastseen = $t;
875
	}
876
	return $dns_server_master;
877
}
878

    
879
/****f* pfsense-utils/log_error
880
* NAME
881
*   log_error  - Sends a string to syslog.
882
* INPUTS
883
*   $error     - string containing the syslog message.
884
* RESULT
885
*   null
886
******/
887
function log_error($error) {
888
	$page = $_SERVER['SCRIPT_NAME'];
889
	syslog(LOG_WARNING, "$page: $error");
890
	return;
891
}
892

    
893
/****f* pfsense-utils/get_interface_mac_address
894
 * NAME
895
 *   get_interface_mac_address - Return a interfaces mac address
896
 * INPUTS
897
 *   $interface	- interface to obtain mac address from
898
 * RESULT
899
 *   $mac - the mac address of the interface
900
 ******/
901
function get_interface_mac_address($interface) {
902
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
903
	if(is_macaddr($mac)) {
904
		return trim($mac);
905
	} else {
906
		return "";
907
	}
908
}
909

    
910
/****f* pfsense-utils/return_dir_as_array
911
 * NAME
912
 *   return_dir_as_array - Return a directory's contents as an array.
913
 * INPUTS
914
 *   $dir	- string containing the path to the desired directory.
915
 * RESULT
916
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
917
 ******/
918
function return_dir_as_array($dir) {
919
	$dir_array = array();
920
	if (is_dir($dir)) {
921
		if ($dh = opendir($dir)) {
922
			while (($file = readdir($dh)) !== false) {
923
				$canadd = 0;
924
				if($file == ".") $canadd = 1;
925
				if($file == "..") $canadd = 1;
926
				if($canadd == 0)
927
					array_push($dir_array, $file);
928
			}
929
			closedir($dh);
930
		}
931
	}
932
	return $dir_array;
933
}
934

    
935
/****f* pfsense-utils/enable_hardware_offloading
936
 * NAME
937
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
938
 * INPUTS
939
 *   $interface	- string containing the physical interface to work on.
940
 * RESULT
941
 *   null
942
 * NOTES
943
 *   This function only supports the fxp driver's loadable microcode.
944
 ******/
945
function enable_hardware_offloading($interface) {
946
	global $g, $config;
947

    
948
	if(stristr($interface,"lnc"))
949
		return;
950
	if(isset($config['system']['do_not_use_nic_microcode']))
951
		return;
952

    
953
	if($g['booting']) {
954
	/* translate wan, lan, opt -> real interface if needed */
955
	$int = filter_translate_type_to_real_interface($interface);
956
	if($int <> "") $interface = $int;
957
	$int_family = preg_split("/[0-9]+/", $int);
958
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
959
	$supported_ints = array('fxp');
960
	if (in_array($int_family, $supported_ints))
961
		mwexec("/sbin/ifconfig {$interface} link0");
962

    
963
	if($config['system']['disablechecksumoffloading'])
964
		return;
965

    
966
	if(stristr($options, "txcsum") == true)
967
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
968
	if(stristr($options, "rxcsum") == true)
969
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
970
	if(stristr($options, "polling") == true)
971
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
972
	} else {
973
		mwexec("sysctl kern.polling.enable=0");
974
	}
975
	return;
976
}
977

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

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

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

    
1026
	if($schedule == "") return false;
1027
	/* loop through firewall rules looking for schedule in use */
1028
	if(is_array($config['filter']['rule']))
1029
		foreach($config['filter']['rule'] as $rule) {
1030
			if($rule['sched'] == $schedule)
1031
				return true;
1032
		}
1033
	return false;
1034
}
1035

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

    
1056
/****f* pfsense-utils/setup_polling
1057
 * NAME
1058
 *   sets up polling
1059
 * INPUTS
1060
 *
1061
 * RESULT
1062
 *   null
1063
 * NOTES
1064
 *
1065
 ******/
1066
function setup_polling() {
1067
	global $g, $config;
1068

    
1069
	setup_polling_defaults();
1070

    
1071
	if(isset($config['system']['polling']))
1072
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
1073
	else
1074
		$supported_ints = array();
1075

    
1076
	/* build an array of interfaces to work with */
1077
	if($config['interfaces']['lan']) 
1078
		$iflist = array ("lan" => "LAN","wan" => "WAN");
1079
	else 
1080
		$iflist = array ("wan" => "WAN");	
1081
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1082
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1083

    
1084
	foreach ($iflist as $ifent => $ifname) {
1085
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
1086
		$supported = false;
1087
		foreach($supported_ints as $supported) {
1088
			if(stristr($real_interface, $supported)) {
1089
				$supported = true;
1090
			}
1091
		}
1092
		if ($supported == true) {
1093
			mwexec("/sbin/ifconfig {$real_interface} polling");
1094
		} else {
1095
			mwexec("/sbin/ifconfig {$real_interface} -polling");
1096
		}
1097
	}
1098
}
1099

    
1100
/****f* pfsense-utils/setup_microcode
1101
 * NAME
1102
 *   enumerates all interfaces and calls enable_hardware_offloading which
1103
 *   enables a NIC's supported hardware features.
1104
 * INPUTS
1105
 *
1106
 * RESULT
1107
 *   null
1108
 * NOTES
1109
 *   This function only supports the fxp driver's loadable microcode.
1110
 ******/
1111
function setup_microcode() {
1112
	global $config;
1113

    
1114
	if($config['interfaces']['lan']) 
1115
		$ifdescrs = array('wan', 'lan');
1116
	else 
1117
		$ifdescrs = array('wan');
1118

    
1119
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1120
		$ifdescrs['opt' . $j] = "opt" . $j;
1121
	}
1122
	foreach($ifdescrs as $if)
1123
		enable_hardware_offloading($if);
1124
}
1125

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

    
1146
/****f* pfsense-utils/file_put_contents
1147
 * NAME
1148
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
1149
 * RESULT
1150
 *   none
1151
 ******/
1152
if(!function_exists("file_put_contents")) {
1153
	function file_put_contents($filename, $data) {
1154
		$fd = fopen($filename,"w");
1155
		fwrite($fd, $data);
1156
		fclose($fd);
1157
	}
1158
}
1159

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

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

    
1192
	if($tmp == "")
1193
		return false;
1194
	else
1195
		return true;
1196
}
1197

    
1198
/****f* pfsense-utils/get_interface_mtu
1199
 * NAME
1200
 *   get_interface_mtu - Return the mtu of an interface
1201
 * RESULT
1202
 *   $tmp	- Returns the mtu of an interface
1203
 ******/
1204
function get_interface_mtu($interface) {
1205
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f4`;
1206
	return $mtu;
1207
}
1208

    
1209
/****f* pfsense-utils/is_interface_wireless
1210
 * NAME
1211
 *   is_interface_wireless - Returns if an interface is wireless
1212
 * RESULT
1213
 *   $tmp	- Returns if an interface is wireless
1214
 ******/
1215
function is_interface_wireless($interface) {
1216
	global $config, $g;
1217
	$interface = convert_real_interface_to_friendly_interface_name($interface);
1218
	if(isset($config['interfaces'][$interface]['wireless']))
1219
		return true;
1220
	else
1221
		return false;
1222
}
1223

    
1224
/****f* pfsense-utils/find_number_of_created_carp_interfaces
1225
 * NAME
1226
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
1227
 * RESULT
1228
 *   $tmp	- Number of currently created CARP interfaces.
1229
 ******/
1230
function find_number_of_created_carp_interfaces($flush = false) {
1231
	global $carp_interface_count_cache;
1232

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

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

    
1270
function link_carp_interface_to_parent($interface) {
1271
	global $config;
1272
	if($interface == "") return;
1273

    
1274
	if($config['interfaces']['lan']) 
1275
		$ifdescrs = array('wan', 'lan');
1276
	else 
1277
		$ifdescrs = array('wan');
1278

    
1279
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1280
		$ifdescrs['opt' . $j] = "opt" . $j;
1281

    
1282
	$carp_ints = "";
1283
	$num_carp_ints = find_number_of_created_carp_interfaces();
1284
	foreach ($ifdescrs as $ifdescr => $ifname) {
1285
		$carp_int = $interface;
1286
		$carp_ip = find_interface_ip($interface);
1287
		$carp_subnet = find_virtual_ip_netmask($carp_ip);
1288
		$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1289
		if(ip_in_subnet($starting_ip, "{$carp_ip}/{$carp_subnet}"))
1290
			if(!stristr($carp_ints, $carp_int))
1291
				return $ifname;
1292
	}
1293
	return $carp_ints;
1294
}
1295

    
1296
/****f* pfsense-utils/link_ip_to_carp_interface
1297
 * NAME
1298
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
1299
 * INPUTS
1300
 *   $ip
1301
 * RESULT
1302
 *   $carp_ints
1303
 ******/
1304
function link_ip_to_carp_interface($ip) {
1305
	global $config;
1306
	if($ip == "") return;
1307

    
1308
	if($config['interfaces']['lan']) 
1309
		$ifdescrs = array('wan', 'lan');
1310
	else 
1311
		$ifdescrs = array('wan');
1312

    
1313
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1314
		$ifdescrs['opt' . $j] = "opt" . $j;
1315

    
1316
	$ft = split("\.", $ip);
1317
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
1318

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

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

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

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

    
1390
	$capable = $g['vlan_long_frame'];
1391

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

    
1394
	if (in_array($int_family[0], $capable))
1395
		return true;
1396
	else
1397
		return false;
1398
}
1399

    
1400
/*
1401
 * Return the interface array
1402
 */
1403
function get_interface_arr($flush = false) {
1404
	global $interface_arr_cache;
1405

    
1406
	/* If the cache doesn't exist, build it */
1407
	if (!isset($interface_arr_cache) or $flush)
1408
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
1409

    
1410
	return $interface_arr_cache;
1411
}
1412

    
1413
/*
1414
 * does_interface_exist($interface): return true or false if a interface is
1415
 * detected.
1416
 */
1417
function does_interface_exist($interface) {
1418
	global $config;
1419

    
1420
	if(!$interface)
1421
		return false;
1422
		
1423
	$ints = get_interface_arr();
1424

    
1425
	if(strtolower($interface) == "lan")
1426
		if(!$config['interfaces']['lan']) 
1427
			return false;
1428

    
1429
	if(stristr($ints, $interface) !== false)
1430
		return true;
1431
	else
1432
		return false;
1433
}
1434

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

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

    
1457
	return $interface_ip_arr_cache[$interface];
1458
}
1459

    
1460
function guess_interface_from_ip($ipaddress) {
1461
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2; };'");
1462
	return $ret;
1463
}
1464

    
1465
function filter_opt_interface_to_real($opt) {
1466
	global $config;
1467
	if(isset($config['interfaces'][$opt]['pointtopoint']))
1468
		return "ppp0";
1469
	return $config['interfaces'][$opt]['if'];
1470
}
1471

    
1472
function filter_get_opt_interface_descr($opt) {
1473
	global $config;
1474
	return $config['interfaces'][$opt]['descr'];
1475
}
1476

    
1477
function get_friendly_interface_list_as_array() {
1478
	global $config;
1479
	$ints = array();
1480
	$ifdescrs = get_interface_list();
1481
	foreach ($ifdescrs as $ifdescr => $ifname) {
1482
		array_push($ints,$ifdescr);
1483
	}
1484
	return $ints;
1485
}
1486

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

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

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

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

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

    
1576
/*
1577
 * setup_filter_bridge(): toggle filtering bridge
1578
 */
1579
function setup_filter_bridge() {
1580
	global $config, $g;
1581
	if(isset($config['bridge']['filteringbridge'])) {
1582
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
1583
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
1584
	} else {
1585
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
1586
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
1587
	}
1588
}
1589

    
1590
/*
1591
 * find_number_of_created_bridges(): returns the number of currently created bridges
1592
 */
1593
function find_number_of_created_bridges($flush = false) {
1594
	global $bridge_interface_count_cache;
1595
	if(!isset($bridge_interface_count_cache) or $flush)
1596
		$bridge_interface_count_cache = exec_command('/sbin/ifconfig | /usr/bin/grep "bridge[0-999]" | /usr/bin/wc -l');
1597

    
1598
	return $bridge_interface_count_cache;
1599
}
1600

    
1601
/*
1602
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
1603
 */
1604
function add_rule_to_anchor($anchor, $rule, $label) {
1605
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
1606
}
1607

    
1608
/*
1609
 * remove_text_from_file
1610
 * remove $text from file $file
1611
 */
1612
function remove_text_from_file($file, $text) {
1613
	global $fd_log;
1614
	if($fd_log)
1615
		fwrite($fd_log, "Adding needed text items:\n");
1616
	$filecontents = file_get_contents($file);
1617
	$textTMP = str_replace($text, "", $filecontents);
1618
	$text = $textTMP;
1619
	if($fd_log)
1620
		fwrite($fd_log, $text);
1621
	$fd = fopen($file, "w");
1622
	fwrite($fd, $text);
1623
	fclose($fd);
1624
}
1625

    
1626
/*
1627
 * add_text_to_file($file, $text): adds $text to $file.
1628
 * replaces the text if it already exists.
1629
 */
1630
function add_text_to_file($file, $text, $replace = false) {
1631
	if(file_exists($file) and is_writable($file)) {
1632
		$filecontents = file($file);
1633
		$fout = fopen($file, "w");
1634

    
1635
		$filecontents = array_map('rtrim', $filecontents);
1636
		array_push($filecontents, $text);
1637
		if ($replace)
1638
			$filecontents = array_unique($filecontents);
1639

    
1640
		$file_text = implode("\n", $filecontents);
1641

    
1642
		fwrite($fout, $file_text);
1643
		fclose($fout);
1644
		return true;
1645
	} else {
1646
		return false;
1647
	}
1648
}
1649

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

    
1667
/*
1668
 * get_filename_from_url($url): converts a url to its filename.
1669
 */
1670
function get_filename_from_url($url) {
1671
	return basename($url);
1672
}
1673

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

    
1689
/*
1690
 *   get_dir: return an array of $dir
1691
 */
1692
function get_dir($dir) {
1693
	$dir_array = array();
1694
	$d = dir($dir);
1695
	while (false !== ($entry = $d->read())) {
1696
		array_push($dir_array, $entry);
1697
	}
1698
	$d->close();
1699
	return $dir_array;
1700
}
1701

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

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

    
1729
/*
1730
 *   exec_command_and_return_text: execute command and return output
1731
 */
1732
function exec_command_and_return_text($command) {
1733
	return exec_command($command);
1734
}
1735

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

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

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

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

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

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

    
1856
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1857

    
1858
	for ($a = 1; $a <= 16; $a++)
1859
		$msg .= $hw_addr;
1860

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

    
1877
	return false;
1878
}
1879

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

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

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

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

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

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

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

    
2018
";
2019

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

    
2027
	fputs($fp, $headers);
2028
	fputs($fp, $urlencoded);
2029

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

    
2035
	return $ret;
2036
}
2037

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

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

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

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

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

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

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

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

    
2171
/*
2172
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
2173
 */
2174
function call_pfsense_method($method, $params, $timeout = 0) {
2175
	global $g, $config;
2176

    
2177
	$ip = gethostbyname($g['product_website']);
2178
	if($ip == $g['product_website'])
2179
		return false;
2180
	global $g, $config;
2181
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
2182
	$xmlrpc_path = $g['xmlrpcpath'];
2183
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
2184
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
2185
	$resp = $cli->send($msg, $timeout);
2186
	if(!$resp) {
2187
		log_error("XMLRPC communication error: " . $cli->errstr);
2188
		return false;
2189
	} elseif($resp->faultCode()) {
2190
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
2191
		return false;
2192
	} else {
2193
		return XML_RPC_Decode($resp->value());
2194
	}
2195
}
2196

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

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

    
2236
/****f* pfsense-utils/display_top_tabs
2237
 * NAME
2238
 *   display_top_tabs - display tabs with rounded edges
2239
 * INPUTS
2240
 *   $text      - array of tabs
2241
 * RESULT
2242
 *   null
2243
 ******/
2244
function display_top_tabs(& $tab_array) {
2245
	global $HTTP_SERVER_VARS;
2246
	global $config;
2247
	global $g;
2248
	$allowed = $g['privs'];
2249

    
2250
	/*   does the user have access to this tab?
2251
	 *   master user has access to everything.
2252
	*   if the user does not have access, simply
2253
	*   unset the tab item.
2254
	*/
2255

    
2256
	if (!isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
2257
		$authorized = & $allowed;
2258
		$tab_temp = array ();
2259
		foreach ($tab_array as $ta) {
2260
			$link = $ta[2];
2261
			// TODO: humm what shall we do with pkg_edit.php and pkg.php?
2262
			if ((strpos($link, "pkg.php")) !== false || (strpos($link, "pkg_edit.php")) !== false) {
2263
				$pos_equal = strpos($link, "=");
2264
				$pos_xmlsuffix = strpos($link, ".xml");
2265
				/* do we match an absolute url including ?xml= foo */
2266
				if(!in_array($link, $allowed)) 
2267
					$link = substr($link, $pos_equal +1, ($pos_xmlsuffix - $pos_equal +3));
2268
			}
2269
			// next check - what if the basename contains a query string?
2270
			if ((strpos($link, "?")) !== false) {
2271
				$pos_qmark = strpos($link, "?");
2272
				$link = substr($link, 0, $pos_qmark);
2273
			}
2274
			$authorized_text = print_r($allowed, true);
2275
//			log_error("comparing " . basename($link) . " {$authorized_text}");
2276
			if(is_array($authorized))
2277
				if (in_array(basename($link), $authorized))
2278
					$tab_temp[] = $ta;
2279
		}
2280
		unset ($tab_array);
2281
		$tab_array = & $tab_temp;
2282
	}
2283

    
2284
	echo "<table cellpadding='0' cellspacing='0'>\n";
2285
	echo " <tr>\n";
2286
	$tabscounter = 0;
2287
	foreach ($tab_array as $ta) {
2288
		if ($ta[1] == true) {
2289
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
2290
		} else {
2291
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
2292
		}
2293
		$tabscounter++;
2294
	}
2295
	echo "</tr>\n<tr>\n";
2296
	foreach ($tab_array as $ta) {
2297
		if ($ta[1] == true) {
2298
			echo "  <td height=\"15\" valign=\"middle\" bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
2299
			echo "&nbsp;&nbsp;&nbsp;";
2300
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2301
		} else {
2302
			echo "  <td height=\"15\" valign=\"middle\" bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
2303
			echo "<font color='white'>{$ta[0]}</font></a>&nbsp;&nbsp;&nbsp;";
2304
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2305
		}
2306
	}
2307
	echo "</tr>\n<tr>\n";
2308
	foreach ($tab_array as $ta) {
2309
		if ($ta[1] == true) {
2310
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2311
		} else {
2312
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2313
		}
2314
		$tabscounter++;
2315
	}
2316
	echo " </tr>\n";
2317
	echo "</table>\n";
2318

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

    
2327

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

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

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

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

    
2397
	$shutdown_webgui_needed = false;
2398

    
2399
	touch("{$g['tmp_path']}/reloading_all");
2400

    
2401
	if($debug)
2402
		log_error("reload_interfaces_sync() is starting.");
2403

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

    
2407
	/* parse config.xml again */
2408
	$config = parse_config(true);
2409

    
2410
	$wan_if = $config['interfaces']['wan']['if'];
2411
	$lan_if = $config['interfaces']['lan']['if'];
2412

    
2413
	if($debug)
2414
		log_error("Cleaning up Interfaces");
2415

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

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

    
2440
	/* set up VLAN virtual interfaces */
2441
	if($debug)
2442
		log_error("Configuring VLANS");
2443
	interfaces_vlan_configure();
2444

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

    
2450
	/* set up WAN interface */
2451
	if($debug)
2452
		log_error("Configuring WAN");
2453
	interfaces_wan_configure();
2454

    
2455
	/* set up Optional interfaces */
2456
	if($debug)
2457
		log_error("Configuring optional interfaces");
2458
	interfaces_optional_configure();
2459

    
2460
	/* set up static routes */
2461
	if($debug)
2462
		log_error("Configuring system Routing");
2463
	system_routing_configure();
2464

    
2465
	/* enable routing */
2466
	if($debug)
2467
		log_error("Enabling system routing");
2468
	system_routing_enable();
2469

    
2470
	/* setup captive portal if needed */
2471
	if($debug)
2472
		log_error("Configuring Captive portal");
2473
	captiveportal_configure();
2474

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

    
2480
	/* bring up carp interfaces*/
2481
	if($debug)
2482
		log_error("Bringing up CARP interfaces");
2483
	interfaces_carp_bring_up_final();
2484

    
2485
	/* restart webConfigurator if needed */
2486
	if($shutdown_webgui_needed == true)
2487
		touch("/tmp/restart_webgui");
2488

    
2489
	/* start devd back up */
2490
	mwexec("/bin/rm /tmp/reload*");
2491

    
2492
	/* remove reloading_all trigger */
2493
	if($debug)
2494
		log_error("Removing {$g['tmp_path']}/reloading_all");
2495
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2496
}
2497

    
2498
/****f* pfsense-utils/reload_all
2499
 * NAME
2500
 *   reload_all - triggers a reload of all settings
2501
 *   * INPUTS
2502
 *   none
2503
 * RESULT
2504
 *   none
2505
 ******/
2506
function reload_all() {
2507
	touch("/tmp/reload_all");
2508
}
2509

    
2510
/****f* pfsense-utils/reload_interfaces
2511
 * NAME
2512
 *   reload_interfaces - triggers a reload of all interfaces
2513
 * INPUTS
2514
 *   none
2515
 * RESULT
2516
 *   none
2517
 ******/
2518
function reload_interfaces() {
2519
	touch("/tmp/reload_interfaces");
2520
}
2521

    
2522
/****f* pfsense-utils/sync_webgui_passwords
2523
 * NAME
2524
 *   sync_webgui_passwords - syncs webgui and ssh passwords
2525
 * INPUTS
2526
 *   none
2527
 * RESULT
2528
 *   none
2529
 ******/
2530
function sync_webgui_passwords() {
2531
	global $config, $g, $groupindex, $userindex;
2532

    
2533
	conf_mount_rw();
2534
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
2535

    
2536
	if (!$fd) {
2537
		log_error("Error: cannot open htpasswd in sync_webgui_passwords().\n");
2538
		return 1;
2539
	}
2540

    
2541
	/* loop through custom users and add "virtual" entries */
2542
	if ($config['system']['user']) {
2543
		foreach ($config['system']['user'] as $user)
2544
			fwrite($fd, "{$user['name']}:{$user['password']}\n");
2545
	}
2546

    
2547
	fclose($fd);
2548
	chmod("{$g['varrun_path']}/htpasswd", 0600);
2549

    
2550
	if ($config['system']['user']) {
2551
		$root =& getUNIXRoot();
2552
		$crypted_pw = &$root['password'];
2553
	}
2554

    
2555
	if (!$crypted_pw) {
2556
		log_error("Error: cannot determine root pwd in sync_webgui_passwords().\nRoot user struct follows:\n");
2557
		if(!$root) 
2558
			 log_error("Unable to determine root user" . print_r($root, true));
2559
		log_error("Testing whether your system has the necessary users... ");
2560
		empty($config['system']['user']) ? log_error("users are missing.\n") : log_error("users found.\n");
2561
		return 1;
2562
	}
2563

    
2564
	if(file_exists("/etc/pwd.db.tmp")) 
2565
		unlink("/etc/pwd.db.tmp");
2566

    
2567
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2568
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2569
	/* sync root */
2570
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
2571
	fwrite($fd, $crypted_pw);
2572
	pclose($fd);
2573
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
2574

    
2575
	/* and again for shell users */
2576
	/* only users with hasShellAccess() == true should be synced */
2577
	if($config['system']['user']) {
2578
		$home_base = $g['platform'] == "pfSense" ? "/home" : "/var/home";
2579

    
2580
		if(! is_dir($home_base))
2581
			mkdir($home_base, 0755);
2582

    
2583
		foreach($config['system']['user'] as $user) {
2584
			if (hasShellAccess($user['name']) || isAllowedToCopyFiles($user['name'])) {
2585
				$home  = hasShellAccess($user['name']) ? "{$home_base}/{$user['name']}" : "{$home_base}/scponly";
2586
				$shell = isAllowedToCopyFiles($user['name']) ? "/usr/local/bin/scponly" : "/etc/rc.initial";
2587
				if (isAllowedToCopyFiles($user['name']))
2588
					$user['groupname'] = "scponly";
2589

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

    
2594
				if (strpos($pwread, "unknown group") !== false) {
2595
					$groupname = $user['groupname'];
2596
					$group = $config['system']['group'][$groupindex[$groupname]];
2597

    
2598
					if (isset($group) && is_array($group)) {
2599
						$fd = popen("/usr/sbin/pw groupadd -g {$group['gid']} -n {$group['name']}", "r");
2600
						pclose($fd);
2601
					} elseif (isAllowedToCopyFiles($user['name'])) {
2602
						$fd = popen("/usr/sbin/pw groupadd -g 100 -n scponly", "r");
2603
						pclose($fd);
2604
					}
2605
				}
2606

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

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

    
2613
				if (strpos($pwread, "no such user") === false) {
2614
					$fd = popen("/usr/sbin/pw usermod -n {$user['name']} -g ${user['groupname']} -G {$group} -H 0", "w");
2615
					fwrite($fd, $user['password']);
2616
					pclose($fd);
2617
				} else {
2618
					$fd = popen("/usr/sbin/pw useradd -u {$user['uid']} -n {$user['name']} -c '{$user['fullname']}' -g ${user['groupname']} -G {$group} -H 0", "w");
2619
					fwrite($fd, $user['password']);
2620
					pclose($fd);
2621
				}
2622

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

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

    
2629
				if (isAllowedToCopyFiles($user['name'])) {
2630
					mwexec("/usr/sbin/pw usermod -n {$user['name']} -g scponly");
2631
				}
2632

    
2633
				if (file_exists("{$home_base}/scponly"))
2634
					mwexec("chmod 0660 {$home_base}/scponly");
2635

    
2636
				if(isset($config['system']['ssh']['sshdkeyonly']) && ! isAllowedToCopyFiles($user['name'])) {
2637
					create_authorized_keys($user['name'], $home);
2638
				}
2639
			}
2640
		}
2641
	}
2642

    
2643
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2644
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2645
	conf_mount_ro();
2646
}
2647
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
2648
 * NAME
2649
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
2650
 *   * INPUTS
2651
 *   optional interface number
2652
 * RESULT
2653
 *   none
2654
 ******/
2655
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
2656
	/*	move all the interfaces up.  for example:
2657
	*		opt1 --> opt1
2658
	*		opt2 --> delete
2659
	*		opt3 --> opt2
2660
	*		opt4 --> opt3
2661
	*/
2662
	global $g, $config;
2663
	config_lock();
2664
	conf_mount_rw();
2665
	unlink_if_exists("{$g['tmp_path']}/config.cache");
2666
	$config_file = file_get_contents("/cf/conf/config.xml");
2667
	/* loop through and reassign deleted items */
2668
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
2669
		if ($i < $opt_interface_num)
2670
			break;
2671
		if ($i == $opt_interface_num) {
2672
			/* item should be deleted */
2673
			str_replace("opt" . $i, "optXXXX", $config_file);
2674
		}
2675
	}
2676
	/* loop through and reassign optional items */
2677
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
2678
		if ($i < $opt_interface_num)
2679
			break;
2680
		/* replace opt$i with $i -1 */
2681
		str_replace("opt" . $i, "opt" . ($i -1), $config_file);
2682
	}
2683
	$fd = fopen("/cf/conf/config.xml", "w");
2684
	fwrite($fd, $config_file);
2685
	fclose($fd);
2686
	$config = parse_config(true);
2687
	/* loop through and delete old rules */
2688
	$num_rules = count($config['filter']['rule']);
2689
	for($x = $num_rules; $x > 0; $x--) {
2690
		if($config['filter']['rule'][$x])
2691
			if($config['filter']['rule'][$x]['interface'] == "optXXXX")
2692
		 		unset($config['filter']['rule'][$x]['interface']);
2693
	}
2694
	$num_rules = count($config['nat']['advancedoutbound']['rule']);
2695
	for($x = $num_rules; $x > 0; $x--) {
2696
		if($config['nat']['advancedoutbound']['rule'][$x])
2697
			if($config['nat']['advancedoutbound']['rule'][$x]['interface'] == "optXXXX")
2698
		 		unset($config['nat']['advancedoutbound']['rule'][$x]['interface']);
2699
	}
2700
	$num_rules = count($config['nat']['rule']);
2701
	for($x = $num_rules; $x > 0; $x--) {
2702
		if($config['nat']['rule'][$x])
2703
			if($config['nat']['rule'][$x]['interface'] == "optXXXX")
2704
		 		unset($config['nat']['rule'][$x]['interface']);
2705
	}
2706
	conf_mount_ro();
2707
	config_unlock();
2708
	return true;
2709
}
2710

    
2711
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
2712
 * NAME
2713
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
2714
 *   		amount of netgraph interfaces needed for system wans
2715
 *   * INPUTS
2716
 *   none
2717
 * RESULT
2718
 *   number of needed netgraph (ng) interfaces
2719
 ******/
2720
function get_number_of_wan_netgraph_interfaces_needed() {
2721
	global $config, $g;
2722
	/* build an array of interfaces to work with */
2723
	$iflist = array("wan" => "WAN");
2724
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2725
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2726
	$ng_interfaces_needed = 0;
2727
	foreach ($iflist as $ifent => $ifname) {
2728
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2729
			$ng_interfaces_needed++;
2730
		}
2731
	}
2732
	return $ng_interfaces_needed;
2733
}
2734

    
2735
function get_netgaph_interface_assignment($friendly_interface) {
2736
	global $config, $g;
2737
	/* build an array of interfaces to work with */
2738
	$iflist = array("wan" => "WAN");
2739
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2740
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2741
		$ng_interfaces_needed = 0;
2742
		$ng_interfaces_number = 0;
2743
		foreach ($iflist as $ifent => $ifname) {
2744
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2745
			$ng_interfaces_number++;
2746
		}
2747
		if($friendly_interface == $ifname)
2748
			break;
2749
	}
2750
	return $ng_interfaces_number;
2751
}
2752

    
2753
/****f* pfsense-utils/reload_all_sync
2754
 * NAME
2755
 *   reload_all - reload all settings
2756
 *   * INPUTS
2757
 *   none
2758
 * RESULT
2759
 *   none
2760
 ******/
2761
function reload_all_sync() {
2762
	global $config, $g;
2763

    
2764
	$g['booting'] = false;
2765

    
2766
	touch("{$g['tmp_path']}/reloading_all");
2767

    
2768
	$shutdown_webgui_needed = false;
2769

    
2770
	if(file_exists("{$g['tmp_path']}/config.cache"))
2771
		unlink("{$g['tmp_path']}/config.cache");
2772

    
2773
	/* parse config.xml again */
2774
	$config = parse_config(true);
2775

    
2776
	/* set up our timezone */
2777
	system_timezone_configure();
2778

    
2779
	/* set up our hostname */
2780
	system_hostname_configure();
2781

    
2782
	/* make hosts file */
2783
	system_hosts_generate();
2784

    
2785
	/* generate resolv.conf */
2786
	system_resolvconf_generate();
2787

    
2788
	/* Set up our loopback interface */
2789
	interfaces_loopback_configure();
2790

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

    
2794
	$wan_if = $config['interfaces']['wan']['if'];
2795
	$lan_if = $config['interfaces']['lan']['if'];
2796

    
2797
	/* build an array of interfaces to work with */
2798
	if($config['interfaces']['lan']) 
2799
		$iflist = array ("lan" => "LAN","wan" => "WAN");
2800
	else 
2801
		$iflist = array ("wan" => "WAN");
2802

    
2803
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2804
		$iflist['opt' . $i] = "opt{$i}";
2805

    
2806
	foreach ($iflist as $ifent => $ifname) {
2807
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2808
		if(stristr($ifname, "lo0") == true)
2809
			continue;
2810
		/* do not process wan interface, its mandatory */
2811
		if($wan_if == $ifname_real)
2812
			continue;
2813
		/* do not process lan interface, its mandatory */
2814
		if($lan_if == $ifname_real)
2815
			continue;
2816
		mwexec("/sbin/ifconfig {$ifname_real} down");
2817
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2818
	}
2819

    
2820
	/* set up VLAN virtual interfaces */
2821
	interfaces_vlan_configure();
2822

    
2823
	/* set up LAN interface */
2824
	interfaces_lan_configure();
2825

    
2826
	/* set up WAN interface */
2827
	interfaces_wan_configure();
2828

    
2829
	/* set up Optional interfaces */
2830
	interfaces_optional_configure();
2831

    
2832
	/* bring up carp interfaces */
2833
	interfaces_carp_configure();
2834

    
2835
	/* set up static routes */
2836
	system_routing_configure();
2837

    
2838
	/* enable routing */
2839
	system_routing_enable();
2840

    
2841
	/* ensure passwords are sync'd */
2842
	system_password_configure();
2843

    
2844
	/* start dnsmasq service */
2845
	services_dnsmasq_configure();
2846

    
2847
	/* start dyndns service */
2848
	services_dyndns_configure();
2849

    
2850
	/* start DHCP service */
2851
	services_dhcpd_configure();
2852

    
2853
	/* configure cron service */
2854
	configure_cron();
2855

    
2856
	/* start the NTP client */
2857
	system_ntp_configure();
2858

    
2859
	/* start ftp proxy helpers if they are enabled */
2860
	system_start_ftp_helpers();
2861

    
2862
	/* start the captive portal */
2863
	captiveportal_configure();
2864

    
2865
        /* reload the filter */
2866
	filter_configure_sync();
2867

    
2868
	/* bring up carp interfaces*/
2869
	interfaces_carp_bring_up_final();
2870

    
2871
	/* sync pw database */
2872
	conf_mount_rw();
2873
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2874
	conf_mount_ro();
2875

    
2876
	/* restart sshd */
2877
	touch("/tmp/start_sshd");
2878

    
2879
	/* restart webConfigurator if needed */
2880
	if($shutdown_webgui_needed == true)
2881
		touch("/tmp/restart_webgui");
2882

    
2883
	mwexec("/bin/rm /tmp/reload*");
2884

    
2885
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2886

    
2887
}
2888

    
2889
function auto_login($status) {
2890
	$gettytab = file_get_contents("/etc/gettytab");
2891
	$getty_split = split("\n", $gettytab);
2892
	conf_mount_rw();
2893
	$fd = fopen("/etc/gettytab", "w");
2894
	foreach($getty_split as $gs) {
2895
		if(stristr($gs, ":ht:np:sp#115200") ) {
2896
			if($status == true) {
2897
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
2898
			} else {
2899
				fwrite($fd, "	:ht:np:sp#115200:\n");
2900
			}
2901
		} else {
2902
			fwrite($fd, "{$gs}\n");
2903
		}
2904
	}
2905
	fclose($fd);
2906
	conf_mount_ro();
2907
}
2908

    
2909
function setup_serial_port() {
2910
	global $g, $config;
2911
	conf_mount_rw();
2912
	/* serial console - write out /boot.config */
2913
	if(file_exists("/boot.config"))
2914
		$boot_config = file_get_contents("/boot.config");
2915
	else
2916
		$boot_config = "";
2917

    
2918
	if($g['platform'] <> "cdrom") {
2919
		$boot_config_split = split("\n", $boot_config);
2920
		$fd = fopen("/boot.config","w");
2921
		if($fd) {
2922
			foreach($boot_config_split as $bcs) {
2923
				if(stristr($bcs, "-D")) {
2924
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2925
				} else {
2926
					if($bcs <> "")
2927
						fwrite($fd, "{$bcs}\n");
2928
				}
2929
			}
2930
			if(isset($config['system']['enableserial'])) {
2931
				fwrite($fd, "-D");
2932
			}
2933
			fclose($fd);
2934
		}
2935
		/* serial console - write out /boot/loader.conf */
2936
		$boot_config = file_get_contents("/boot/loader.conf");
2937
		$boot_config_split = split("\n", $boot_config);
2938
		$fd = fopen("/boot/loader.conf","w");
2939
		if($fd) {
2940
			foreach($boot_config_split as $bcs) {
2941
				if(stristr($bcs, "console")) {
2942
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2943
				} else {
2944
					if($bcs <> "")
2945
						fwrite($fd, "{$bcs}\n");
2946
				}
2947
			}
2948
			if(isset($config['system']['enableserial'])) {
2949
				fwrite($fd, "console=\"comconsole\"\n");
2950
			}
2951
			fclose($fd);
2952
		}
2953
	}
2954
	$ttys = file_get_contents("/etc/ttys");
2955
	$ttys_split = split("\n", $ttys);
2956
	$fd = fopen("/etc/ttys", "w");
2957
	foreach($ttys_split as $tty) {
2958
		if(stristr($tty, "ttyd0")) {
2959
			if(isset($config['system']['enableserial'])) {
2960
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
2961
			} else {
2962
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
2963
			}
2964
		} else {
2965
			fwrite($fd, $tty . "\n");
2966
		}
2967
	}
2968
	fclose($fd);
2969
	if(isset($config['system']['disableconsolemenu'])) {
2970
		auto_login(false);
2971
	} else {
2972
		auto_login(true);
2973
	}
2974
	conf_mount_ro();
2975
	return;
2976
}
2977

    
2978
function print_value_list($list, $count = 10, $separator = ",") {
2979
	$list = implode($separator, array_slice($list, 0, $count));
2980
	if(count($list) < $count) {
2981
		$list .= ".";
2982
	} else {
2983
		$list .= "...";
2984
	}
2985
	return $list;
2986
}
2987

    
2988
function convert_friendly_interface_to_friendly_descr($interface) {
2989
	global $config;
2990
	/* attempt to resolve interface to friendly descr */
2991
	if($config['interfaces'][$interface]['descr'])
2992
		return $config['interfaces'][$interface]['descr'];
2993
	$tmp = convert_real_interface_to_friendly_descr($interface);
2994
	/* could not resolve, return back what was passed */
2995
	return $interface;
2996
}
2997

    
2998
function convert_real_interface_to_friendly_descr($interface) {
2999
	global $config;
3000
	if($interface == $config['interfaces']['wan']['if'])
3001
		return "wan";
3002
	if($interface == $config['interfaces']['lan']['if'])
3003
		return "lan";
3004
	/* attempt to resolve interface to friendly descr */
3005
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
3006
	if($config['interfaces'][$friendly_int]['descr'])
3007
		return $config['interfaces'][$friendly_int]['descr'];
3008
	/* could not resolve, return back what was passed */
3009
	return $interface;
3010
}
3011

    
3012
function enable_rrd_graphing() {
3013
	global $config, $g;
3014

    
3015
	if($g['booting']) 
3016
		echo "Generating RRD graphs...";
3017

    
3018
	$rrddbpath = "/var/db/rrd/";
3019
	$rrdgraphpath = "/usr/local/www/rrd";
3020

    
3021
	$traffic = "-traffic.rrd";
3022
	$packets = "-packets.rrd";
3023
	$states = "-states.rrd";
3024
	$quality = "-quality.rrd";
3025
	$wireless = "-wireless.rrd";
3026
	$queues = "-queues.rrd";
3027
	$queuesdrop = "-queuesdrop.rrd";
3028
	$spamd = "-spamd.rrd";
3029
	$proc = "-processor.rrd";
3030

    
3031
	$rrdtool = "/usr/local/bin/rrdtool";
3032
	$netstat = "/usr/bin/netstat";
3033
	$awk = "/usr/bin/awk";
3034
	$tar = "/usr/bin/tar";
3035
	$pfctl = "/sbin/pfctl";
3036
	$php = "/usr/local/bin/php";
3037
	$top = "/usr/bin/top";
3038
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
3039
	$ifconfig = "/sbin/ifconfig";
3040

    
3041
	$rrdtrafficinterval = 60;
3042
	$rrdqualityinterval = 60;
3043
	$rrdwirelessinterval = 60;
3044
	$rrdqueuesinterval = 60;
3045
	$rrdqueuesdropinterval = 60;
3046
	$rrdpacketsinterval = 60;
3047
	$rrdstatesinterval = 60;
3048
	$rrdspamdinterval = 60;
3049
	$rrdlbpoolinterval = 60;
3050
	$rrdprocinterval = 60;
3051

    
3052
	$trafficvalid = $rrdtrafficinterval * 2;
3053
	$qualityvalid = $rrdqualityinterval * 2;
3054
	$wirelessvalid = $rrdwirelessinterval * 2;
3055
	$queuesvalid = $rrdqueuesinterval * 2;
3056
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
3057
	$packetsvalid = $rrdpacketsinterval * 2;
3058
	$statesvalid = $rrdstatesinterval*2;
3059
	$spamdvalid = $rrdspamdinterval * 2;
3060
	$lbpoolvalid = $rrdlbpoolinterval * 2;
3061
	$procvalid = $rrdlbpoolinterval * 2;
3062

    
3063
	/* Asume GigE for now */
3064
	$downstream = 125000000;
3065
	$upstream = 125000000;
3066

    
3067
	$rrdrestore = "";
3068
	$rrdreturn = "";
3069

    
3070
	if (isset ($config['rrd']['enable'])) {
3071

    
3072
		/* create directory if needed */
3073
		if (!is_dir("$rrddbpath")) {
3074
			mkdir("$rrddbpath", 0755);
3075
		}
3076

    
3077
		if ($g['booting']) {
3078
			if ($g['platform'] != "pfSense") {
3079
				/* restore the databases, if we have one */
3080
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
3081
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
3082
					if((int)$rrdrestore <> 0) {
3083
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
3084
					}
3085
				}
3086
			}
3087
		}
3088

    
3089
		/* db update script */
3090
		$rrdupdatesh = "#!/bin/sh\n";
3091
		$rrdupdatesh .= "\n";
3092
		$rrdupdatesh .= "counter=1\n";
3093
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
3094
		$rrdupdatesh .= "do\n";
3095
		$rrdupdatesh .= "";
3096

    
3097
		$i = 0;
3098
		$vfaces = array (
3099
			"vlan.?*",
3100
			"enc.?*"
3101
		);
3102
		$ifdescrs = get_interface_list(true, true, $vfaces);
3103
		$ifdescrs['enc0']['friendly'] = "ipsec";
3104
		$ifdescrs['enc0']['descr'] = "IPsec";
3105
		$ifdescrs['enc0']['up'] = true;
3106

    
3107
		foreach ($ifdescrs as $realif => $ifdescr) {
3108
			$ifname = $ifdescr['friendly'];
3109
			$state = $ifdescr['up'];
3110

    
3111
			/* skip interfaces that do not have a friendly name */
3112
			if ("$ifname" == "") {
3113
				continue;
3114
			}
3115

    
3116
			/* or are down */
3117
			if (!$state) {
3118
				continue;
3119
			}
3120

    
3121
			/* TRAFFIC, set up the rrd file */
3122
			if (!file_exists("$rrddbpath$ifname$traffic")) {
3123
				/* create rrd file if it does not exist */
3124
				log_error("Create RRD database $rrddbpath$ifname$traffic");
3125
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
3126
				$rrdcreate .= "DS:in:COUNTER:$trafficvalid:0:$downstream ";
3127
				$rrdcreate .= "DS:out:COUNTER:$trafficvalid:0:$upstream ";
3128
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3129
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3130
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3131
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3132
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3133

    
3134
				$rrdcreateoutput = array();
3135
				$rrdcreatereturn = "";
3136

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

    
3144
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3145
			if($g['booting']) {
3146
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
3147
			}
3148

    
3149
			$rrdupdatesh .= "\n";
3150
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
3151
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
3152
			if(! is_macaddr(get_interface_mac($realif))) {
3153
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$6 \":\" \$9}'`\n";
3154
			} else {
3155
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7 \":\" \$10}'`\n";
3156
			}
3157

    
3158
			/* PACKETS, set up the rrd file */
3159
			if (!file_exists("$rrddbpath$ifname$packets")) {
3160
				/* create rrd file if it does not exist */
3161
				log_error("Create RRD database $rrddbpath$ifname$packets");
3162
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
3163
				$rrdcreate .= "DS:in:COUNTER:$packetsvalid:0:$downstream ";
3164
				$rrdcreate .= "DS:out:COUNTER:$packetsvalid:0:$upstream ";
3165
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3166
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3167
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3168
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3169
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3170

    
3171
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3172
				if ($rrdcreatereturn != 0) {
3173
					log_error("RRD create failed exited with $rrdcreatereturn, the
3174
							error is: $rrdcreateoutput[0]\n");
3175
				}
3176
			}
3177

    
3178
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3179
			if($g['booting']) {
3180
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
3181
			}
3182

    
3183
			$rrdupdatesh .= "\n";
3184
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
3185
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
3186
			if(! is_macaddr(get_interface_mac($realif))) {
3187
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$4 \":\" \$7}'`\n";
3188
			} else {
3189
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5 \":\" \$8}'`\n";
3190
			}
3191
			/* if an alternative gateway is defined, use it */
3192
			if ($config['interfaces'][$ifname]['use_rrd_gateway'] <> "") {
3193
				$gatewayip = get_interface_gateway($ifname);
3194
				$monitorip = $config['interfaces'][$ifname]['use_rrd_gateway'];
3195
				mwexec("/sbin/route add -host {$monitorip} {$gatewayip} 1> /dev/null 2>&1");
3196
			} else {
3197
				$monitorip = get_interface_gateway($ifname);
3198
			}
3199
			$numpings = 5;
3200
			$btick = '`';
3201

    
3202
			if($monitorip <> "") {
3203
				/* QUALITY, create link quality database */
3204
				if (!file_exists("$rrddbpath$ifname$quality")) {
3205
					/* create rrd file if it does not exist */
3206
					log_error("Create RRD database $rrddbpath$ifname$quality");
3207
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
3208
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
3209
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
3210
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3211
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3212
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3213
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3214
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3215

    
3216
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3217
					if ($rrdcreatereturn != 0) {
3218
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3219
					}
3220
				}
3221

    
3222
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3223
				if($g['booting']) {
3224
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
3225
				}
3226

    
3227
				/* the ping test function. We call this on the last line */
3228
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
3229
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
3230
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
3231
				$rrdupdatesh .= "	local out_{$ifname}\n";
3232
				$rrdupdatesh .= "	out_{$ifname}=$btick ping -c $numpings -q $monitorip $btick\n";
3233
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
3234
				$rrdupdatesh .= "		packetloss_{$ifname}=$btick echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1 $btick\n";
3235
				$rrdupdatesh .= "		roundtrip_{$ifname}=$btick echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/' $btick\n";
3236
				$rrdupdatesh .= "	fi\n";
3237
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
3238
				$rrdupdatesh .= "}\n\n";
3239

    
3240
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
3241
			}
3242

    
3243
			/* WIRELESS, set up the rrd file */
3244
			if($config['interfaces'][$ifname]['wireless']['mode'] == "bss") {
3245
				if (!file_exists("$rrddbpath$ifname$wireless")) {
3246
					/* create rrd file if it does not exist */
3247
					log_error("Create RRD database $rrddbpath$ifname$wireless");
3248
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$wireless --step $rrdwirelessinterval ";
3249
					$rrdcreate .= "DS:snr:GAUGE:$wirelessvalid:0:1000 ";
3250
					$rrdcreate .= "DS:rate:GAUGE:$wirelessvalid:0:1000 ";
3251
					$rrdcreate .= "DS:channel:GAUGE:$wirelessvalid:0:1000 ";
3252
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3253
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3254
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3255
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3256
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3257
	
3258
					$rrdcreateoutput = array();
3259
					$rrdcreatereturn = "";
3260

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

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

    
3273
				$rrdupdatesh .= "\n";
3274
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
3275
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\\\n";
3276
				$rrdupdatesh .= "`$ifconfig {$realif} list ap| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
3277
			}
3278

    
3279
			/* WAN interface only statistics */
3280
			if ("$ifname" == "wan") {
3281

    
3282
				/* QUEUES, set up the queues databases */
3283
				if (!is_array($GLOBALS['allqueue_list'])) 
3284
	                                read_altq_config();
3285

    
3286
				if (is_array($config['shaper']['queue'])) {
3287
					if (!file_exists("$rrddbpath$ifname$queues")) {
3288
						/* create rrd file if it does not exist */
3289
						log_error("Create RRD database $rrddbpath$ifname$queues");
3290
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
3291
						/* loop list of shaper queues */
3292
						$q = 0;
3293
						foreach ($GLOBALS['allqueue_list'] as $qname) {
3294
							$rrdcreate .= "DS:$qname:COUNTER:$queuesvalid:0:$downstream ";
3295
						}
3296

    
3297
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3298
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3299
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3300
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3301
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3302

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

    
3310
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
3311
						/* create rrd file if it does not exist */
3312
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
3313
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
3314
						/* loop list of shaper queues */
3315
						$q = 0;
3316
						foreach ($GLOBALS['allqueue_list'] as $queue) {
3317
							$rrdcreate .= "DS:$queue:COUNTER:$queuesdropvalid:0:$downstream ";
3318
						}
3319

    
3320
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3321
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3322
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3323
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3324
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3325

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

    
3332
					if($g['booting']) {
3333
						$rrdqcommand = "-t ";
3334
						$rrducommand = "N";
3335
						$q = 0;
3336
						foreach ($GLOBALS['allqueue_list'] as $queue) {
3337
							if($q == 0) {
3338
								$rrdqcommand .= "{$queue}";
3339
							} else {
3340
								$rrdqcommand .= ":{$queue}";
3341
							}
3342
							$q++;
3343
							$rrducommand .= ":U";
3344
						}
3345
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3346
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3347
					}
3348

    
3349
					/* awk function to gather shaper data */
3350
					/* yes, it's special */
3351
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
3352
					$rrdupdatesh .= "{ ";
3353
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3354
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3355
					$rrdupdatesh .= "q=1; ";
3356
					$rrdupdatesh .= "} ";
3357
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3358
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
3359
					$rrdupdatesh .= "q=0; ";
3360
					$rrdupdatesh .= "} ";
3361
					$rrdupdatesh .= "} END { ";
3362
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3363
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3364
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3365
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3366

    
3367
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
3368
					$rrdupdatesh .= "{ ";
3369
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3370
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3371
					$rrdupdatesh .= "q=1; ";
3372
					$rrdupdatesh .= "} ";
3373
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3374
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
3375
					$rrdupdatesh .= "q=0; ";
3376
					$rrdupdatesh .= "} ";
3377
					$rrdupdatesh .= "} END { ";
3378
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3379
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3380
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3381
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3382
				}
3383
			}
3384
		}
3385
		$i++;
3386

    
3387
		/* System only statistics */
3388
		$ifname = "system";
3389

    
3390
			/* STATES, create pf states database */
3391
			if(! file_exists("$rrddbpath$ifname$states")) {
3392
				/* create rrd file if it does not exist */
3393
				log_error("Create RRD database $rrddbpath$ifname$states");
3394
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3395
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3396
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3397
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3398
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3399
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3400
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3401
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3402
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3403
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3404
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3405

    
3406
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3407
				if($rrdcreatereturn != 0) {
3408
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3409
						error is: $rrdcreateoutput[0]\n");
3410
				}
3411
			}
3412

    
3413
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3414
			if($g['booting']) {
3415
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
3416
			}
3417

    
3418
 			/* the pf states gathering function. */
3419
 			$rrdupdatesh .= "\n";
3420
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
3421
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
3422
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3423
 			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3424
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3425
 			$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";
3426
 			$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";
3427
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3428

    
3429
			/* End pf states statistics */
3430

    
3431
			/* CPU, create CPU statistics database */
3432
			if(! file_exists("$rrddbpath$ifname$proc")) {
3433
				/* create rrd file if it does not exist */
3434
				log_error("Create RRD database $rrddbpath$ifname$proc");
3435
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3436
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3437
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3438
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3439
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3440
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3441
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3442
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3443
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3444
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3445
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3446

    
3447
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3448
				if($rrdcreatereturn != 0) {
3449
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3450
						error is: $rrdcreateoutput[0]\n");
3451
				}
3452
			}
3453

    
3454
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3455
			if($g['booting']) {
3456
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
3457
			}
3458

    
3459
 			/* the CPU stats gathering function. */
3460
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { ";
3461
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } ";
3462
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { ";
3463
			$rrdupdatesh .= "processes = \$1; ";
3464
			$rrdupdatesh .= "} ";
3465
			$rrdupdatesh .= "else if ( \$1 == \"CPU\" ) { ";
3466
			$rrdupdatesh .= "user = \$3; ";
3467
			$rrdupdatesh .= "nice = \$5; ";
3468
			$rrdupdatesh .= "sys = \$7; ";
3469
			$rrdupdatesh .= "interrupt = \$9; ";
3470
			$rrdupdatesh .= "} ";
3471
			$rrdupdatesh .= "} END { ";
3472
			$rrdupdatesh .= "printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes ";
3473
			$rrdupdatesh .= "}'`\n\n";
3474

    
3475
			/* End CPU statistics */
3476

    
3477
			/* SPAMD, set up the spamd rrd file */
3478
			if (isset($config['installedpackages']['spamdsettings']) &&
3479
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
3480
				/* set up the spamd rrd file */
3481
				if (!file_exists("$rrddbpath$ifname$spamd")) {
3482
						/* create rrd file if it does not exist */
3483
						log_error("Create RRD database $rrddbpath$ifname$spamd");
3484
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
3485
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
3486
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
3487
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3488
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3489
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3490
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3491
						$rrdcreate .= "RRA:MIN:0.5:1440:1500 ";
3492
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3493
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3494
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3495
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3496
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3497
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3498
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3499
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3500
						$rrdcreate .= "RRA:MAX:0.5:720:1000 ";
3501
						$rrdcreate .= "RRA:MAX:0.5:1440:1500 ";
3502

    
3503
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3504
					if ($rrdcreatereturn != 0) {
3505
						log_error("RRD create failed exited with $rrdcreatereturn, the
3506
							error is: $rrdcreateoutput[0]\n");
3507
					}
3508
				}
3509

    
3510
				$rrdupdatesh .= "\n";
3511
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3512
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3513
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3514

    
3515
			}
3516
		/* End System statistics */
3517

    
3518
		$rrdupdatesh .= "sleep 60\n";
3519
		$rrdupdatesh .= "done\n";
3520
		log_error("Creating rrd update script");
3521
		/* write the rrd update script */
3522
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3523
		$fd = fopen("$updaterrdscript", "w");
3524
		fwrite($fd, "$rrdupdatesh");
3525
		fclose($fd);
3526

    
3527
		/* kill off traffic collectors */
3528
		kill_traffic_collector();
3529

    
3530
		/* start traffic collector */
3531
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3532

    
3533
	} else {
3534
		/* kill off traffic collectors */
3535
		kill_traffic_collector();
3536
	}
3537

    
3538
	if($g['booting']) 
3539
		echo "done.\n";
3540
		
3541
}
3542

    
3543
function kill_traffic_collector() {
3544
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
3545
}
3546

    
3547
function update_filter_reload_status($text) {
3548
	global $g;
3549
	config_lock();
3550
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3551
	fwrite($fd, $text);
3552
	fclose($fd);
3553
	config_unlock();
3554
}
3555

    
3556
function get_interface_gateway($interface) {
3557
	global $config, $g;
3558
	$interface = strtolower($interface);
3559
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
3560
	 *  grab the address from the configuration file.
3561
	 */
3562
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
3563
	if($tmpif <> $interface)
3564
		$interface = $tmpif;
3565
	$realif = $config['interfaces'][$interface]['if'];
3566
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
3567
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3568
		$gw = rtrim($gw);
3569
	} else {
3570
		if(is_array($config['gateways'])) {
3571
			foreach($config['gateways']['gateway_item'] as $gateway) {
3572
				if($gateway['name'] == $gateway['name']) {
3573
					$gatewayip = $gateway['gateway'];
3574
					$interfacegw = $gateway['interface'];
3575
				}
3576
			}
3577
			$gw = $gatewayip;
3578
		} else {
3579
			$gw = $config['interfaces'][$interface]['gateway'];
3580
		}
3581
	}
3582
	/* if wan is requested, return it */
3583
	if($interface == "wan")
3584
		return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
3585
	/* return gateway */
3586
	return $gw;
3587
}
3588

    
3589
function is_dhcp_server_enabled() {
3590
	/* DHCP enabled on any interfaces? */
3591
	global $config, $g;
3592
	$dhcpdcfg = $config['dhcpd'];
3593
	$dhcpdenable = false;
3594
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
3595
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3596
			$dhcpdenable = true;
3597
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3598
			$dhcpdenable = true;
3599
	}
3600
	return $dhcpdenable;
3601
}
3602

    
3603
/* return outside interfaces with a gateway */
3604
function get_interfaces_with_gateway() {
3605
	global $config;
3606
	$ints = array();
3607
	$vfaces = array(
3608
			'bridge.?*',
3609
			'ppp.?*',
3610
			'sl.?*',
3611
			'gif.?*',
3612
			'faith.?*',
3613
			'lo.?*',
3614
			'ng.?*',
3615
			'vlan.?*',
3616
			'pflog.?*',
3617
			'pfsync.?*',
3618
			'enc.?*',
3619
			'tun.?*',
3620
			'carp.?*'
3621
		);
3622
	$ifdescrs = get_interface_list("active","physical",$vfaces);
3623

    
3624
	/* loop interfaces, check config for outbound */
3625
	foreach ($ifdescrs as $ifdescr => $ifname) {
3626
		$friendly = $ifname['friendly'];
3627
		if ($config['interfaces'][$friendly]['ipaddr'] == "dhcp") {
3628
			$ints[] = $friendly;
3629
			continue;
3630
		}
3631
		if ($config['interfaces'][$friendly]['ipaddr'] == "pppoe") {
3632
			$ints[] = $friendly;
3633
			continue;
3634
		}
3635
		if ($config['interfaces'][$friendly]['ipaddr'] == "pptp") {
3636
			$ints[] = $friendly;
3637
			continue;
3638
		}
3639
		if ($config['interfaces'][$friendly]['gateway'] <> "") {
3640
			$ints[] = $friendly;
3641
			continue;
3642
		}
3643
	}
3644
	return $ints;
3645
}
3646

    
3647
/* return true if interface has a gateway */
3648
function interface_has_gateway($friendly) {
3649
	$friendly = strtolower($friendly);
3650
	if(in_array($friendly, get_interfaces_with_gateway())) {
3651
		return true;
3652
	} else {
3653
		/* extra check for real interface names if it falls through */
3654
		$friendly = convert_real_interface_to_friendly_interface_name($friendly);
3655
		return(in_array($friendly, get_interfaces_with_gateway()));
3656
	}
3657
}
3658

    
3659
/****f* pfsense-utils/isAjax
3660
 * NAME
3661
 *   isAjax - reports if the request is driven from prototype
3662
 * INPUTS
3663
 *   none
3664
 * RESULT
3665
 *   true/false
3666
 ******/
3667
function isAjax() {
3668
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
3669
}
3670

    
3671
//returns interface information
3672
function get_interface_info($ifdescr) {
3673
	global $config, $linkinfo, $netstatrninfo;
3674

    
3675
	$ifinfo = array();
3676

    
3677
	/* find out interface name */
3678
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
3679
	if ($ifdescr == "wan")
3680
		$ifinfo['if'] = get_real_wan_interface();
3681
	else
3682
		$ifinfo['if'] = $ifinfo['hwif'];
3683

    
3684
	/* run netstat to determine link info */
3685

    
3686
	unset($linkinfo);
3687
	exec("/usr/bin/netstat -I " . $ifinfo['hwif'] . " -nWb -f link", $linkinfo);
3688
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3689
	if (preg_match("/\*$/", $linkinfo[0])) {
3690
		$ifinfo['status'] = "down";
3691
	} else {
3692
		$ifinfo['status'] = "up";
3693
	}
3694

    
3695
	if (!strstr($ifinfo['if'],'tun')) {
3696
		$ifinfo['macaddr'] = $linkinfo[3];
3697
		$ifinfo['inpkts'] = $linkinfo[4];
3698
		$ifinfo['inerrs'] = $linkinfo[5];
3699
		$ifinfo['inbytes'] = $linkinfo[6];
3700
		$ifinfo['outpkts'] = $linkinfo[7];
3701
		$ifinfo['outerrs'] = $linkinfo[8];
3702
		$ifinfo['outbytes'] = $linkinfo[9];
3703
		$ifinfo['collisions'] = $linkinfo[10];
3704
	} else {
3705
		$ifinfo['inpkts'] = $linkinfo[3];
3706
		$ifinfo['inbytes'] = $linkinfo[5];
3707
		$ifinfo['outpkts'] = $linkinfo[6];
3708
		$ifinfo['outbytes'] = $linkinfo[8];
3709
	}
3710

    
3711
	/* DHCP? -> see if dhclient is up */
3712
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "dhcp")) {
3713
		/* see if dhclient is up */
3714
		if (is_dhcp_running("wan") == true)
3715
			$ifinfo['dhcplink'] = "up";
3716
		else
3717
			$ifinfo['dhcplink'] = "down";
3718
	}
3719
	/* loop through optional interfaces looking to see if they are dhcp */
3720
        for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
3721
                $ifdescrs['opt' . $j] = $config['interfaces']['opt' . $j]['descr'];
3722
                if (($ifdescr == "opt{$j}") && ($config['interfaces']['opt' . $j]['ipaddr'] == "dhcp")) {
3723
                        /* see if dhclient is up */
3724
                        if (is_dhcp_running("opt{$j}") == true)
3725
                                $ifinfo['dhcplink'] = "up";
3726
                        else
3727
                                $ifinfo['dhcplink'] = "down";
3728
                }
3729
        }
3730

    
3731
	/* PPPoE interface? -> get status from virtual interface */
3732
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pppoe")) {
3733
		unset($linkinfo);
3734
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3735
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3736
		if (preg_match("/\*$/", $linkinfo[0])) {
3737
			$ifinfo['pppoelink'] = "down";
3738
		} else {
3739
			/* get PPPoE link status for dial on demand */
3740
			$ifconfiginfo = "";
3741
			unset($ifconfiginfo);
3742
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3743

    
3744
			$ifinfo['pppoelink'] = "up";
3745

    
3746
			foreach ($ifconfiginfo as $ici) {
3747
				if (strpos($ici, 'LINK0') !== false)
3748
					$ifinfo['pppoelink'] = "down";
3749
			}
3750
		}
3751
	}
3752

    
3753
	/* PPTP interface? -> get status from virtual interface */
3754
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pptp")) {
3755
		unset($linkinfo);
3756
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3757
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3758
		if (preg_match("/\*$/", $linkinfo[0])) {
3759
			$ifinfo['pptplink'] = "down";
3760
		} else {
3761
			/* get PPTP link status for dial on demand */
3762
			unset($ifconfiginfo);
3763
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3764

    
3765
			$ifinfo['pptplink'] = "up";
3766

    
3767
			foreach ($ifconfiginfo as $ici) {
3768
				if (strpos($ici, 'LINK0') !== false)
3769
					$ifinfo['pptplink'] = "down";
3770
			}
3771
		}
3772
	}
3773

    
3774
	if ($ifinfo['status'] == "up") {
3775
		/* try to determine media with ifconfig */
3776
		unset($ifconfiginfo);
3777
		exec("/sbin/ifconfig " . $ifinfo['hwif'], $ifconfiginfo);
3778
		$matches = "";
3779
		foreach ($ifconfiginfo as $ici) {
3780

    
3781
			/* don't list media/speed for wireless cards, as it always
3782
			   displays 2 Mbps even though clients can connect at 11 Mbps */
3783
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
3784
				$ifinfo['media'] = $matches[1];
3785
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
3786
				$ifinfo['media'] = $matches[1];
3787
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
3788
				$ifinfo['media'] = $matches[1];
3789
			}
3790

    
3791
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
3792
				if ($matches[1] != "active")
3793
					$ifinfo['status'] = $matches[1];
3794
			}
3795
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
3796
				$ifinfo['channel'] = $matches[1];
3797
			}
3798
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
3799
				if ($matches[1][0] == '"')
3800
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
3801
				else
3802
					$ifinfo['ssid'] = $matches[1];
3803
			}
3804
		}
3805

    
3806
		if ($ifinfo['pppoelink'] != "down" && $ifinfo['pptplink'] != "down") {
3807
			/* try to determine IP address and netmask with ifconfig */
3808
			unset($ifconfiginfo);
3809
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3810

    
3811
			foreach ($ifconfiginfo as $ici) {
3812
				if (preg_match("/inet (\S+)/", $ici, $matches)) {
3813
					$ifinfo['ipaddr'] = $matches[1];
3814
				}
3815
				if (preg_match("/netmask (\S+)/", $ici, $matches)) {
3816
					if (preg_match("/^0x/", $matches[1]))
3817
						$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
3818
				}
3819
			}
3820

    
3821
			if ($ifdescr == "wan") {
3822
				/* run netstat to determine the default gateway */
3823
				unset($netstatrninfo);
3824
				exec("/usr/bin/netstat -rnf inet", $netstatrninfo);
3825

    
3826
				foreach ($netstatrninfo as $nsr) {
3827
					if (preg_match("/^default\s*(\S+)/", $nsr, $matches)) {
3828
						$ifinfo['gateway'] = $matches[1];
3829
					}
3830
				}
3831
			} else {
3832
				/* deterimine interface gateway */
3833
				$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3834
				$gw = get_interface_gateway($int);
3835
				if($gw)
3836
					$ifinfo['gateway'] = $gw;
3837
			}
3838
		}
3839
	}
3840

    
3841
	$bridge = "";
3842
	$int = "";
3843
	$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3844
	$bridge = link_int_to_bridge_interface($int);
3845
	if($bridge) {
3846
		$bridge_text = `/sbin/ifconfig {$bridge}`;
3847
		if(stristr($bridge_text, "blocking") <> false) {
3848
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
3849
			$ifinfo['bridgeint'] = $bridge;
3850
		} else if(stristr($bridge_text, "learning") <> false) {
3851
			$ifinfo['bridge'] = "learning";
3852
			$ifinfo['bridgeint'] = $bridge;
3853
		} else if(stristr($bridge_text, "forwarding") <> false) {
3854
			$ifinfo['bridge'] = "forwarding";
3855
			$ifinfo['bridgeint'] = $bridge;
3856
		}
3857
	}
3858

    
3859
	return $ifinfo;
3860
}
3861

    
3862
//returns cpu speed of processor. Good for determining capabilities of machine
3863
function get_cpu_speed() {
3864
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
3865
}
3866

    
3867
/* check if the wan interface is up
3868
 * Wait for a maximum of 10 seconds
3869
 * If the interface is up before then continue
3870
 */
3871
function is_wan_interface_up($interface) {
3872
	global $g;
3873
	global $config;
3874
	$i = 0;
3875
	while($i < 10) {
3876
		if(get_interface_gateway($interface)) {
3877
			return true;
3878
		} else {
3879
			sleep(1);
3880
		}
3881
		$i++;
3882
	}
3883
	return false;
3884
}
3885

    
3886
function add_hostname_to_watch($hostname) {
3887
	if(!is_dir("/var/db/dnscache")) {
3888
		mkdir("/var/db/dnscache");
3889
	}
3890
	if(is_fqdn($hostname)) {
3891
		$domrecords = array();
3892
		$domips = array();
3893
		exec("host -t A $hostname", $domrecords, $rethost);
3894
		if($rethost == 0) {
3895
			foreach($domrecords as $domr) {
3896
				$doml = explode(" ", $domr);
3897
				$domip = $doml[3];
3898
				/* fill array with domain ip addresses */
3899
				if(is_ipaddr($domip)) {
3900
					$domips[] = $domip;
3901
				}
3902
			}
3903
		}
3904
		sort($domips);
3905
		$contents = "";
3906
		if(! empty($domips)) {
3907
			foreach($domips as $ip) {
3908
				$contents .= "$ip\n";
3909
			}
3910
		}
3911
		file_put_contents("/var/db/dnscache/$hostname", $contents);
3912
	}
3913
}
3914

    
3915
function find_dns_aliases() {
3916
	global $config, $g;
3917
	foreach((array) $config['aliases']['alias'] as $alias) {
3918
		$alias_value = $alias['address'];
3919
		$alias_name = $alias['name'];
3920
		if(stristr($alias_value, " ")) {
3921
			$alias_split = split(" ", $alias_value);
3922
			foreach($alias_split as $as) {
3923
				if(is_fqdn($as)) 
3924
					add_hostname_to_watch($as);			
3925
			}
3926
		} else {
3927
			if(is_fqdn($alias_value)) 
3928
				add_hostname_to_watch($alias_value);
3929
		}
3930
	}
3931
}
3932

    
3933
function is_fqdn($fqdn) {
3934
	$hostname = false;
3935
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
3936
		$hostname = true;
3937
	}
3938
	if(preg_match("/\.\./", $fqdn)) {
3939
		$hostname = false;
3940
	}
3941
	if(preg_match("/^\./i", $fqdn)) { 
3942
		$hostname = false;
3943
	}
3944
	if(preg_match("/\//i", $fqdn)) {
3945
		$hostname = false;
3946
	}
3947
	return($hostname);
3948
}
3949

    
3950
function pfsense_default_state_size() {
3951
  /* get system memory amount */
3952
  $memory = get_memory();
3953
  $avail = $memory[0];
3954
  /* Be cautious and only allocate 10% of system memory to the state table */
3955
  $max_states = (int) ($avail/10)*1000;
3956
  return $max_states;
3957
}
3958

    
3959
function lookup_gateway_ip_by_name($name) {
3960
	global $config;
3961
	if(is_array($config['gateways'])) {
3962
		foreach($config['gateways']['gateway_item'] as $gateway) {
3963
			if($gateway['name'] == "$name") {
3964
				$gatewayip = $gateway['gateway'];
3965
				$interfacegw = $gateway['interface'];
3966
				return($gatewayip);
3967
			}
3968
		}
3969
	} else {
3970
		return(false);
3971
	}
3972
}
3973

    
3974
function lookup_gateway_interface_by_name($name) {
3975
	global $config;
3976
	if(is_array($config['gateways'])) {
3977
		foreach($config['gateways']['gateway_item'] as $gateway) {
3978
			if($gateway['name'] == "$name") {
3979
				$gatewayip = $gateway['gateway'];
3980
				$interfacegw = $gateway['interface'];
3981
				return($interfacegw);
3982
			}
3983
		}
3984
	} else {
3985
		return(false);
3986
	}
3987
}
3988

    
3989
?>
(15-15/29)