Project

General

Profile

Download (116 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
	$security_url = "firewall_nat_1to1_edit.php?if=". strtolower($if);
46
	if(isAllowedPage($security_url, $allowed)) 
47
		return true;
48
	return false;
49
}
50

    
51
/****f* pfsense-utils/have_natpfruleint_access
52
 * NAME
53
 *   have_natpfruleint_access
54
 * INPUTS
55
 *	 none
56
 * RESULT
57
 *   returns true if user has access to edit a specific firewall nat port forward interface
58
 ******/
59
function have_natpfruleint_access($if) {
60
	$security_url = "firewall_nat_edit.php?if=". strtolower($if);
61
	if(isAllowedPage($security_url, $allowed)) 
62
		return true;
63
	return false;
64
}
65

    
66
/****f* pfsense-utils/have_ruleint_access
67
 * NAME
68
 *   have_ruleint_access
69
 * INPUTS
70
 *	 none
71
 * RESULT
72
 *   returns true if user has access to edit a specific firewall interface
73
 ******/
74
function have_ruleint_access($if) {
75
	$security_url = "firewall_rules.php?if=". strtolower($if);
76
	if(isAllowedPage($security_url)) 
77
		return true;
78
	return false;
79
}
80

    
81
/****f* pfsense-utils/does_url_exist
82
 * NAME
83
 *   does_url_exist
84
 * INPUTS
85
 *	 none
86
 * RESULT
87
 *   returns true if a url is available
88
 ******/
89
function does_url_exist($url) {
90
	$fd = fopen("$url","r");
91
	if($fd) {
92
		fclose($fd);
93
   		return true;    
94
	} else {
95
        return false;
96
	}
97
}
98

    
99
/****f* pfsense-utils/is_private_ip
100
 * NAME
101
 *   is_private_ip
102
 * INPUTS
103
 *	 none
104
 * RESULT
105
 *   returns true if an ip address is in a private range
106
 ******/
107
function is_private_ip($iptocheck) {
108
        $isprivate = false;
109
        $ip_private_list=array(
110
               "10.0.0.0/8",
111
               "172.16.0.0/12",
112
               "192.168.0.0/16",
113
               "99.0.0.0/8"
114
        );
115
        foreach($ip_private_list as $private) {
116
                if(ip_in_subnet($iptocheck,$private)==true)
117
                        $isprivate = true;
118
        }
119
        return $isprivate;
120
}
121

    
122
/****f* pfsense-utils/get_tmp_file
123
 * NAME
124
 *   get_tmp_file
125
 * INPUTS
126
 *	 none
127
 * RESULT
128
 *   returns a temporary filename
129
 ******/
130
function get_tmp_file() {
131
	return "/tmp/tmp-" . time();
132
}
133

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

    
186
/****f* pfsense-utils/tdr_create_ipfw_rule
187
 * NAME
188
 *   tdr_create_ipfw_rule
189
 * INPUTS
190
 *   $rule xml firewall rule array, $type allow or deny
191
 * RESULT
192
 *   text string with ipfw rule already formatted
193
 ******/
194
function tdr_create_ipfw_rule($rule, $type) {
195
		global $config, $g, $tdr_get_next_ipfw_rule, $FilterIflist;
196

    
197
		$wancfg = $config['interfaces']['wan'];
198
		$lancfg = $config['interfaces']['lan'];
199
		$pptpdcfg = $config['pptpd'];
200
		$pppoecfg = $config['pppoe'];
201

    
202
		$lanif = $lancfg['if'];
203
		$wanif = get_real_interface();
204

    
205
		$lanip = $lancfg['ipaddr'];
206
		$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
207
		$lansn = $lancfg['subnet'];
208

    
209
		$int = "";
210

    
211
		$curwanip = get_interface_ip();
212

    
213
		/* don't include disabled rules */
214
		if (isset($rule['disabled'])) {
215
			return "";
216
		}
217

    
218
		$pptpdcfg = $config['pptpd'];
219
		$pppoecfg = $config['pppoe'];
220

    
221
		if ($pptpdcfg['mode'] == "server") {
222
			$pptpip = $pptpdcfg['localip'];
223
			$pptpsa = $pptpdcfg['remoteip'];
224
			$pptpsn = $g['pptp_subnet'];
225
			if($config['pptp']['pptp_subnet'] <> "")
226
				$pptpsn = $config['pptp']['pptp_subnet'];
227
		}
228

    
229
		if ($pppoecfg['mode'] == "server") {
230
			$pppoeip = $pppoecfg['localip'];
231
			$pppoesa = $pppoecfg['remoteip'];
232
			$pppoesn = $g['pppoe_subnet'];
233
			if($config['pppoe']['pppoe_subnet'] <> "")
234
				$pppoesn = $config['pppoe']['pppoe_subnet'];
235
		}
236

    
237
		/* does the rule deal with a PPTP interface? */
238
		if ($rule['interface'] == "pptp") {
239
			if ($pptpdcfg['mode'] != "server")
240
				return "";
241
			$nif = $g['n_pptp_units'];
242
			if($config['pptp']['n_pptp_units'] <> "")
243
				$nif = $config['pptp']['n_pptp_units'];
244
			$ispptp = true;
245
		} else if($rule['interface'] == "pppoe") {
246
			if ($pppoecfg['mode'] != "server") {
247
				return " # Error creating pppoe rule";
248
			}
249
			$nif = $g['n_pppoe_units'];
250
			if($config['pppoe']['n_pppoe_units'] <> "")
251
				$nif = $config['pppoe']['n_pppoe_units'];
252
			$ispppoe = true;
253
		} else {
254

    
255
			/* Check to see if the interface is opt and in our opt list */
256
			if (strstr($rule['interface'], "opt")) {
257
 				if (!array_key_exists($rule['interface'], $FilterIflist)) {
258
					$item = "";
259
					foreach($FilterIflist as $oc) 
260
						$item .= $oc['if'];
261
					return "# {$real_int} {$item} {$rule['interface']} array key does not exist for " . $rule['descr'];
262
				}
263
			}
264

    
265
			$nif = 1;
266
			$ispptp = false;
267
			$ispppoe = false;
268
		}
269
		if ($pptpdcfg['mode'] != "server") {
270
			if (($rule['source']['network'] == "pptp") ||
271
				($rule['destination']['network'] == "pptp")) {
272
					return "# source network or destination network == pptp on " . $rule['descr'];
273
				}
274
		}
275
		if ($rule['source']['network'] && strstr($rule['source']['network'], "opt")) {
276
			if (!array_key_exists($rule['source']['network'], $FilterIflist)) {
277
				$optmatch = "";
278
				if(preg_match("/opt([0-999])/", $rule['source']['network'], $optmatch)) {
279
					$real_opt_int = convert_friendly_interface_to_real_interface_name("opt" . $optmatch[1]);
280
					$opt_ip = find_interface_ip($real_opt_int);
281
					if(!$opt_ip)
282
						return "# unresolvable optarray $real_opt_int - $optmatch[0] - $opt_ip";
283
				} else {
284
					return "# {$rule['source']['network']} !array_key_exists source network " . $rule['descr'];
285
				}
286
			}
287
		}
288
		if ($rule['destination']['network'] && strstr($rule['destination']['network'], "opt")) {
289
			if (!array_key_exists($rule['destination']['network'], $FilterIflist)) {
290
				if(preg_match("/opt([0-999])/", $rule['destination']['network'], $optmatch)) {
291
					$real_opt_int = convert_friendly_interface_to_real_interface_name("opt" . $optmatch[1]);
292
					$opt_ip = find_interface_ip($real_opt_int);
293
					if(!$opt_ip)
294
						return "# unresolvable oparray $real_opt_int - $optmatch[0] - $opt_ip";
295
				} else {
296
					return "# {$item} {$rule['destination']['network']} !array_key_exists dest network " . $rule['descr'];
297
				}
298
			}
299
		}
300
		/* check for unresolvable aliases */
301
		if ($rule['source']['address'] && !alias_expand($rule['source']['address'])) {
302
			file_notice("Filter_Reload", "# unresolvable source aliases {$rule['descr']}");
303
			return "# tdr unresolvable source aliases {$rule['descr']}";
304
		}
305
		if ($rule['destination']['address'] && !alias_expand($rule['destination']['address'])) {
306
			file_notice("Filter_Reload", "# unresolvable dest aliases {$rule['descr']}");
307
			return "# tdr unresolvable dest aliases {$rule['descr']}";
308
		}
309

    
310
		/* if list */
311
        	$ifdescrs = get_configured_interface_list();
312

    
313
		for ($iif = 0; $iif < $nif; $iif++) {
314

    
315
			if ($ispptp) {
316
				$aline['interface'] = "\$pptp ";
317
			} else if ($ispppoe) {
318
				$aline['interface'] = "\$pppoe ";
319
			} else {
320
				// translate wan, man, lan, opt to real interface.
321
				$interface = $rule['interface'];
322
				$temp = $config['interfaces'][$interface]['descr'];
323
				if($temp <> "") $interface = $temp;
324
				$aline['interface'] = convert_friendly_interface_to_real_interface_name($rule['interface']) . " ";
325
			}
326

    
327
			if (isset($rule['protocol'])) {
328
				if($rule['protocol'] == "tcp/udp")
329
					$aline['prot'] = "ip ";
330
				elseif($rule['protocol'] == "icmp")
331
					$aline['prot'] = "icmp ";
332
				else
333
					$aline['prot'] = "{$rule['protocol']} ";
334
			} else {
335
				if($rule['source']['port'] <> "" || $rule['destination']['port'] <> "") {
336
					$aline['prot'] = "tcp ";
337
				}
338
			}
339

    
340
			/* source address */
341
			if (isset($rule['source']['any'])) {
342
				$src = "any";
343
			} else if ($rule['source']['network']) {
344

    
345
				if (strstr($rule['source']['network'], "opt")) {
346
					$src = $FilterIflist[$rule['source']['network']]['sa'] . "/" .
347
						$FilterIflist[$rule['source']['network']]['sn'];
348
					if (isset($rule['source']['not'])) $src = " not {$src}";
349
					/* check for opt$NUMip here */
350
					$matches = "";
351
					if (preg_match("/opt([0-9999])ip/", $rule['source']['network'], $matches)) {
352
						$optnum = $matches[1];
353
						$real_int = convert_friendly_interface_to_real_interface_name("opt{$optnum}");
354
						$src = find_interface_ip($real_int);
355
					}
356
				} else {
357
					switch ($rule['source']['network']) {
358
						case 'wanip':
359
							$src = $curwanip;
360
							break;
361
						case 'lanip':
362
							$src = $lanip;
363
							break;
364
						case 'lan':
365
							$src = "{$lansa}/{$lansn}";
366
							break;
367
						case 'pptp':
368
							$src = "{$pptpsa}/{$pptpsn}";
369
							break;
370
						case 'pppoe':
371
							$src = "{$pppoesa}/{$pppoesn}";
372
							break;
373
					}
374
					if (isset($rule['source']['not'])) $src = " not {$src}";
375
				}
376
			} else if ($rule['source']['address']) {
377
				$expsrc = alias_expand_value($rule['source']['address']);
378
				if(!$expsrc) 
379
					$expsrc = $rule['source']['address'];
380
					
381
				if (isset($rule['source']['not']))
382
					$not = " not";
383
				else
384
					$not = "";
385

    
386
				if(alias_expand_value($rule['source']['address'])) {
387
					$src = "{";
388
					$first_item = true;
389
					foreach(preg_split("/[\s]+/", alias_expand_value($rule['source']['address'])) as $item) {
390
						if($item != "") {
391
							if(!$first_item) 
392
								$src .= " or";
393
							$src .= " {$not}{$item}";
394
							$first_item = false;
395
						}
396
					}
397
					$src .= " }";
398
				} else {
399
					$src = "{$not}" . $expsrc;
400
				}
401

    
402
			}
403

    
404
			if (!$src || ($src == "/")) {
405
				return "# tdr at the break!";
406
			}
407

    
408
			$aline['src'] = "from $src ";
409
			$srcporta = "";
410
			if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
411
				if ($rule['source']['port']) {
412
					$srcport = explode("-", $rule['source']['port']);
413
					if(alias_expand($srcport[0])) {
414
						$first_time = true;
415
						foreach(preg_split("/[\s]+/", alias_expand_value($srcport[0])) as $item) {
416
							if(!$first_time) 
417
								$srcporta .= ",";				
418
							$srcporta .= $item;
419
							$first_time = false;
420
						}
421
					} else {
422
						$srcporta = $srcport[0];
423
					}
424
					if ((!$srcport[1]) || ($srcport[0] == $srcport[1])) {
425
						if(alias_expand($srcport[0]))
426
							$aline['srcport'] = "{$srcporta} ";
427
						else
428
							$aline['srcport'] = "{$srcporta} ";
429
					} else if (($srcport[0] == 1) && ($srcport[1] == 65535)) {
430
						/* no need for a port statement here */
431
					} else if ($srcport[1] == 65535) {
432
						$aline['srcport'] = ">={$srcport[0]} ";
433
					} else if ($srcport[0] == 1) {
434
						$aline['srcport']= "<={$srcport[1]} ";
435
					} else {
436
						$aline['srcport'] = "{$srcport[0]}-{$srcport[1]} ";
437
					}
438
				}
439
			}
440

    
441
			/* destination address */
442
			if (isset($rule['destination']['any'])) {
443
				$dst = "any";
444
			} else if ($rule['destination']['network']) {
445

    
446
				if (strstr($rule['destination']['network'], "opt")) {
447
					$dst = $FilerIflist[$rule['destination']['network']]['sa'] . "/" .
448
						$FilterIflist[$rule['destination']['network']]['sn'];
449
					/* check for opt$NUMip here */
450
					$matches = "";
451
					if (preg_match("/opt([0-9999])ip/", $rule['destination']['network'], $matches)) {
452
						$optnum = $matches[1];
453
						$real_int = convert_friendly_interface_to_real_interface_name("opt{$optnum}");
454
						$dst = find_interface_ip($real_int);
455
					}
456
					if (isset($rule['destination']['not'])) $dst = " not {$dst}";
457
				} else {
458
					switch ($rule['destination']['network']) {
459
						case 'wanip':
460
							$dst = $curwanip;
461
							break;
462
						case 'lanip':
463
							$dst = $lanip;
464
							break;
465
						case 'lan':
466
							$dst = "{$lansa}/{$lansn}";
467
							break;
468
						case 'pptp':
469
							$dst = "{$pptpsa}/{$pptpsn}";
470
							break;
471
						case 'pppoe':
472
							$dst = "{$ppoesa}/{$pppoesn}";
473
							break;
474
					}
475
					if (isset($rule['destination']['not'])) $dst = " not {$dst}";
476
				}
477
			} else if ($rule['destination']['address']) {
478
				$expdst = alias_expand_value($rule['destination']['address']);
479
				if(!$expdst) 
480
					$expdst = $rule['destination']['address'];
481

    
482
				if (isset($rule['destination']['not']))
483
					$not = " not ";
484
				else
485
					$not = "";
486

    
487
				if(alias_expand_value($rule['destination']['address'])) {
488
					$dst = "{";
489
					$first_item = true;
490
					foreach(preg_split("/[\s]+/", alias_expand_value($rule['destination']['address'])) as $item) {
491
						if($item != "") {
492
							if(!$first_item) 
493
								$dst .= " or";
494
							$dst .= " {$not}{$item}";
495
							$first_item = false;
496
						}
497
					}
498
					$dst .= " }";
499
				} else {
500
					$dst = "{$not}" . $expdst;
501
				}
502
			}
503

    
504
			if (!$dst || ($dst == "/")) {
505
				return "# returning at dst $dst == \"/\"";
506
			}
507

    
508
			$aline['dst'] = "to $dst ";
509
			$dstporta = "";
510
			if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
511
				if ($rule['destination']['port']) {
512
					$dstport = explode("-", $rule['destination']['port']);
513
					if(alias_expand($dstport[0])) {
514
						$first_time = true;
515
						foreach(preg_split("/[\s]+/", alias_expand_value($dstport[0])) as $item) {
516
							if(!$first_time)
517
							 	$dstporta .= ",";
518
							$dstporta .= $item;			
519
							$first_time = false;
520
						}
521
					} else {
522
						$dstporta = $dstport[0];
523
					}
524
					if ((!$dstport[1]) || ($dstport[0] == $dstport[1])) {
525
						if(alias_expand($dstport[0]))
526
							$aline['dstport'] = "{$dstporta} ";
527
						else
528
							$aline['dstport'] = "{$dstporta} ";
529
					} else if (($dstport[0] == 1) && ($dstport[1] == 65535)) {
530
						/* no need for a port statement here */
531
					} else if ($dstport[1] == 65535) {
532
						$aline['dstport'] = ">= {$dstport[0]} ";
533
					} else if ($dstport[0] == 1) {
534
						$aline['dstport'] = "<= {$dstport[1]} ";
535
					}  else {
536
						$aline['dstport'] = "{$dstport[0]}-{$dstport[1]} ";
537
					}
538
				}
539
			}
540

    
541
	}
542
	
543
	if($aline['prot'] == "")
544
		$aline['prot'] = "ip ";
545

    
546
	tdr_get_next_ipfw_rule();
547

    
548
 	/* piece together the actual user rule */
549
	if($type == "skipto") {
550
		$next_rule = tdr_get_next_ipfw_rule();
551
		$next_rule = $next_rule+1;
552
		$type = "skipto $next_rule";
553
	}
554

    
555
	/* piece together the actual user rule */
556
	$line .= $type . " " . $aline['prot'] . $aline['src'] . 
557
	$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in recv " . $aline['interface'];
558

    
559
	return $line;
560

    
561
}
562

    
563
/****f* pfsense-utils/tdr_install_rule
564
 * NAME
565
 *   tdr_install_rule
566
 * INPUTS
567
 *   $rule - ascii string containing the ifpw rule to add
568
 * RESULT
569
 *   none
570
 ******/
571
function tdr_install_rule($rule) {
572
	global $tdr_next_ipfw_rule;
573
	mwexec("/sbin/ipfw -f add $tdr_next_ipfw_rule set 9 $rule");
574
	$tdr_next_ipfw_rule++;
575
}
576

    
577
/****f* pfsense-utils/tdr_get_next_ipfw_rule
578
 * NAME
579
 *   tdr_get_next_ipfw_rule
580
 * INPUTS
581
 *  none
582
 * RESULT
583
 *   returns the next available ipfw rule number
584
 ******/
585
function tdr_get_next_ipfw_rule() {
586
	global $tdr_next_ipfw_rule;
587
	if(intval($tdr_next_ipfw_rule) < 2) 
588
		$tdr_next_ipfw_rule = 2;
589
	return $tdr_next_ipfw_rule;
590
 }
591

    
592
/****f* pfsense-utils/tdr_install_set
593
 * NAME
594
 *   tdr_install_set
595
 * INPUTS
596
 *  none
597
 * RESULT
598
 *   swaps in the temporary ipfw time based rule set
599
 ******/
600
function tdr_install_set() {
601
	global $config;
602
	
603
	mwexec("/sbin/ipfw delete 1");
604
	mwexec("/sbin/ipfw add 1 check-state");
605
	mwexec("/sbin/ipfw delete 65534");
606
	mwexec("/sbin/ipfw add 1 allow all from me to any keep-state");
607
	if (!isset ($config['system']['webgui']['noantilockout'])) {
608
		/* lan ip lockout */
609
		$lancfg = $config['interfaces']['lan'];
610
		$lanip = $lancfg['ipaddr'];
611
		$lansn = $lancfg['subnet'];
612
		$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
613
		mwexec("/sbin/ipfw add 1 allow all from {$lansa}/{$lansn} to $lanip keep-state");
614
	}
615
	mwexec("/sbin/ipfw add 65534 check-state");
616
	/* set 8 contains time based rules */
617
	mwexec("/sbin/ipfw -f delete set 8");
618
	mwexec("/sbin/ipfw -f set swap 9 8");
619
}
620

    
621
/****f* pfsense-utils/get_time_based_rule_status
622
 * NAME
623
 *   get_time_based_rule_status
624
 * INPUTS
625
 *   xml schedule block
626
 * RESULT
627
 *   true/false - true if the rule should be installed
628
 ******/
629
/*
630
 <schedules>
631
   <schedule>
632
     <name>ScheduleMultipleTime</name>
633
     <descr>main descr</descr>
634
     <time>
635
       <position>0,1,2</position>
636
       <hour>0:0-24:0</hour>
637
       <desc>time range 2</desc>
638
     </time>
639
     <time>
640
       <position>4,5,6</position>
641
       <hour>0:0-24:0</hour>
642
       <desc>time range 1</desc>
643
     </time>
644
   </schedule>
645
 </schedules>
646
*/
647
function get_time_based_rule_status($schedule) {
648
	$should_add_rule = false;
649
	/* no schedule? rule should be installed */
650
	if($schedule == "") 
651
		return true;
652
	/*
653
	 * iterate through time blocks and deterimine
654
	 * if the rule should be installed or not.
655
	 */
656
	foreach($schedule['timerange'] as $timeday) {
657
		if($timeday['month']) 
658
			$month = $timeday['month'];
659
		else 
660
			$week = "";	
661
		if($timeday['day']) 
662
			$day = $timeday['day'];
663
		else 
664
			$day = "";
665
		if($timeday['hour']) 
666
			$hour = $timeday['hour'];
667
		else 
668
			$hour = "";
669
		if($timeday['position']) 
670
			$position = $timeday['position'];
671
		else 
672
			$position = "";
673
		if($timeday['desc']) 
674
			$desc = $timeday['desc'];
675
		else 
676
			$desc = "";
677
		if($month) {
678
			$monthstatus = tdr_month($month);
679
		} else {
680
			$monthstatus = true;
681
		}
682
		if($day) {
683
			$daystatus = tdr_day($day);
684
		} else {
685
			$daystatus = true;
686
		}
687
		if($hour) {
688
			$hourstatus = tdr_hour($hour);
689
		} else {
690
			$hourstatus = true;
691
		}
692
		if($position) {
693
			$positionstatus = tdr_position($position);
694
		} else {
695
			$positionstatus = true;
696
		}
697

    
698
		if($monthstatus == true) 
699
			if($daystatus == true) 
700
				if($positionstatus == true) 
701
					if($hourstatus == true) {
702
						$should_add_rule = true;
703
					}
704
	}
705
	
706
	return $should_add_rule;
707
}
708

    
709
function tdr_day($schedule) {
710
	/*
711
	 * Calculate day of month. 
712
	 * IE: 29th of may
713
	 */
714
	$weekday	= date("w");
715
	if ($weekday == 0)
716
		$weekday = 7;
717
	$date	 	= date("d");
718
	$defined_days = split(",", $schedule);
719
	log_error("[TDR DEBUG] tdr_day($schedule)");
720
	foreach($defined_days as $dd) {
721
		if($date == $dd) {
722
			return true;
723
		}
724
	}
725
	return false;
726
}
727

    
728
function tdr_hour($schedule) {
729
	/* $schedule should be a string such as 16:00-19:00 */
730
	$tmp = split("-", $schedule);
731
	$starting_time = strtotime($tmp[0]);
732
	$ending_time = strtotime($tmp[1]);
733
	$now = strtotime("now");
734
	log_error("[TDR DEBUG] S: $starting_time E: $ending_time N: $now");
735
	if($now >= $starting_time and $now <= $ending_time) {
736
		return true;
737
	}
738
	return false;
739
}
740

    
741
function tdr_position($schedule) {
742
	/*
743
	 * Calculate possition, ie: day of week.
744
	 * Sunday = 7, Monday = 1, Tuesday = 2
745
	 * Weds = 3, Thursday = 4, Friday = 5,
746
	 * Saturday = 6
747
	 * ...
748
	 */
749
	$weekday	= date("w");
750
	log_error("[TDR DEBUG] tdr_position($schedule) $weekday");
751
	if ($weekday == 0)
752
		$weekday = 7;
753
	$schedule_days = split(",", $schedule);
754
	foreach($schedule_days as $day) {
755
		if($day == $weekday) {
756
			return true;
757
		}
758
	}
759
	return false;
760
}
761

    
762
function tdr_month($schedule) {
763
	/*
764
	 * Calculate month
765
	 */
766
	$todays_month = date("n");
767
	$months = split(",", $schedule);
768
	log_error("[TDR DEBUG] tdr_month($schedule)");
769
	foreach($months as $month) {
770
		if($month == $todays_month) {
771
			return true;
772
		}
773
	}
774
	return false;
775
}
776

    
777
/****f* pfsense-utils/find_number_of_needed_carp_interfaces
778
 * NAME
779
 *   find_number_of_needed_carp_interfaces
780
 * INPUTS
781
 *   null
782
 * RESULT
783
 *   the number of needed carp interfacs
784
 ******/
785
function find_number_of_needed_carp_interfaces() {
786
	global $config, $g;
787
	$carp_counter=0;
788
	if(!$config['virtualip'])
789
		return 0;
790
	if(!$config['virtualip']['vip'])
791
		return 0;
792
	foreach($config['virtualip']['vip'] as $vip) {
793
		if($vip['mode'] == "carp")
794
			$carp_counter++;
795
	}
796
	return $carp_counter;
797
}
798

    
799
/****f* pfsense-utils/reset_carp
800
 * NAME
801
 *   reset_carp - resets carp after primary interface changes
802
 * INPUTS
803
 *   null
804
 * RESULT
805
 *   null
806
 ******/
807
function reset_carp() {
808
	$carp_counter=find_number_of_created_carp_interfaces();
809
	$needed_carp_interfaces = find_number_of_needed_carp_interfaces();
810
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
811
	for($x=0; $x<$carp_counter; $x++) {
812
		mwexec("/sbin/ifconfig carp{$x} down");
813
		usleep(1000);
814
		mwexec("/sbin/ifconfig carp{$x} delete");
815
		if($needed_carp_interfaces < $carp_counter) {
816
			$needed_carp_interfaces--;
817
			//log_error("Destroying carp interface.");
818
			//mwexec("/sbin/ifconfig carp{$x} destroy");
819
		}
820
	}
821
	find_number_of_created_carp_interfaces(true);
822
	sleep(1);
823
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
824
	interfaces_carp_configure();
825
}
826

    
827
/****f* pfsense-utils/get_dns_servers
828
 * NAME
829
 *   get_dns_servres - get system dns servers
830
 * INPUTS
831
 *   $dns_servers - an array of the dns servers
832
 * RESULT
833
 *   null
834
 ******/
835
function get_dns_servers() {
836
	$dns_servers = array();
837
	$dns = `cat /etc/resolv.conf`;
838
	$dns_s = split("\n", $dns);
839
	foreach($dns_s as $dns) {
840
		$matches = "";
841
		if (preg_match("/nameserver (.*)/", $dns, $matches))
842
			$dns_servers[] = $matches[1];
843
	}
844
	$dns_server_master = array();
845
	$lastseen = "";
846
	foreach($dns_servers as $t) {
847
		if($t <> $lastseen)
848
			if($t <> "")
849
				$dns_server_master[] = $t;
850
		$lastseen = $t;
851
	}
852
	return $dns_server_master;
853
}
854

    
855
/****f* pfsense-utils/log_error
856
* NAME
857
*   log_error  - Sends a string to syslog.
858
* INPUTS
859
*   $error     - string containing the syslog message.
860
* RESULT
861
*   null
862
******/
863
function log_error($error) {
864
	global $g;
865
	$page = $_SERVER['SCRIPT_NAME'];
866
	syslog(LOG_WARNING, "$page: $error");
867
	if ($g['debug'])
868
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
869
	return;
870
}
871

    
872
/****f* pfsense-utils/get_interface_mac_address
873
 * NAME
874
 *   get_interface_mac_address - Return a interfaces mac address
875
 * INPUTS
876
 *   $interface	- interface to obtain mac address from
877
 * RESULT
878
 *   $mac - the mac address of the interface
879
 ******/
880
function get_interface_mac_address($interface) {
881
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
882
	if(is_macaddr($mac)) {
883
		return trim($mac);
884
	} else {
885
		return "";
886
	}
887
}
888

    
889
/****f* pfsense-utils/return_dir_as_array
890
 * NAME
891
 *   return_dir_as_array - Return a directory's contents as an array.
892
 * INPUTS
893
 *   $dir	- string containing the path to the desired directory.
894
 * RESULT
895
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
896
 ******/
897
function return_dir_as_array($dir) {
898
	$dir_array = array();
899
	if (is_dir($dir)) {
900
		if ($dh = opendir($dir)) {
901
			while (($file = readdir($dh)) !== false) {
902
				$canadd = 0;
903
				if($file == ".") $canadd = 1;
904
				if($file == "..") $canadd = 1;
905
				if($canadd == 0)
906
					array_push($dir_array, $file);
907
			}
908
			closedir($dh);
909
		}
910
	}
911
	return $dir_array;
912
}
913

    
914
/****f* pfsense-utils/enable_hardware_offloading
915
 * NAME
916
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
917
 * INPUTS
918
 *   $interface	- string containing the physical interface to work on.
919
 * RESULT
920
 *   null
921
 * NOTES
922
 *   This function only supports the fxp driver's loadable microcode.
923
 ******/
924
function enable_hardware_offloading($interface) {
925
	global $g, $config;
926

    
927
	if(stristr($interface,"lnc"))
928
		return;
929

    
930
	if(isset($config['system']['do_not_use_nic_microcode']))
931
		return;
932

    
933
	/* translate wan, lan, opt -> real interface if needed */
934
	$int = filter_translate_type_to_real_interface($interface);
935
	if($int <> "")	
936
		$interface = $int;
937
	$int_family = preg_split("/[0-9]+/", $int);
938
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
939
	$supported_ints = array('fxp');
940
	if (in_array($int_family, $supported_ints))
941
		mwexec("/sbin/ifconfig {$interface} link0");
942

    
943
	if($config['system']['disablechecksumoffloading'])
944
		return;
945

    
946
	if(stristr($options, "txcsum") == true)
947
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
948

    
949
	if(stristr($options, "rxcsum") == true)
950
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
951

    
952
	/* if the NIC supports polling *AND* it is enabled in the GUI */
953
	if(interface_supports_polling($interface)) {
954
		$polling = isset($config['system']['polling']);	
955
		if($polling) {
956
			mwexec("sysctl kern.polling.enable=1");
957
	    	mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
958
		} else {
959
			mwexec("sysctl kern.polling.enable=0");
960
		}
961
	}
962
	return;
963
}
964

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

    
1002
/****f* pfsense-utils/is_alias_inuse
1003
 * NAME
1004
 *   checks to see if an alias is currently in use by a rule
1005
 * INPUTS
1006
 *
1007
 * RESULT
1008
 *   true or false
1009
 * NOTES
1010
 *
1011
 ******/
1012
function is_alias_inuse($alias) {
1013
	global $g, $config;
1014

    
1015
	if($alias == "") return false;
1016
	/* loop through firewall rules looking for alias in use */
1017
	if(is_array($config['filter']['rule']))
1018
		foreach($config['filter']['rule'] as $rule) {
1019
			if($rule['source']['address'])
1020
				if($rule['source']['address'] == $alias)
1021
					return true;
1022
			if($rule['destination']['address'])
1023
				if($rule['destination']['address'] == $alias)
1024
					return true;
1025
		}
1026
	/* loop through nat rules looking for alias in use */
1027
	if(is_array($config['nat']['rule']))
1028
		foreach($config['nat']['rule'] as $rule) {
1029
			if($rule['target'] == $alias)
1030
				return true;
1031
			if($rule['external-address'] == $alias)
1032
				return true;
1033
		}
1034
	return false;
1035
}
1036

    
1037
/****f* pfsense-utils/is_schedule_inuse
1038
 * NAME
1039
 *   checks to see if a schedule is currently in use by a rule
1040
 * INPUTS
1041
 *
1042
 * RESULT
1043
 *   true or false
1044
 * NOTES
1045
 *
1046
 ******/
1047
function is_schedule_inuse($schedule) {
1048
	global $g, $config;
1049

    
1050
	if($schedule == "") return false;
1051
	/* loop through firewall rules looking for schedule in use */
1052
	if(is_array($config['filter']['rule']))
1053
		foreach($config['filter']['rule'] as $rule) {
1054
			if($rule['sched'] == $schedule)
1055
				return true;
1056
		}
1057
	return false;
1058
}
1059

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

    
1080
/****f* pfsense-utils/setup_polling
1081
 * NAME
1082
 *   sets up polling
1083
 * INPUTS
1084
 *
1085
 * RESULT
1086
 *   null
1087
 * NOTES
1088
 *
1089
 ******/
1090
function setup_polling() {
1091
	global $g, $config;
1092

    
1093
	setup_polling_defaults();
1094

    
1095
	if(isset($config['system']['polling']))
1096
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
1097
	else
1098
		$supported_ints = array();
1099

    
1100
	/* if list */
1101
        $iflist = get_configured_interface_list();
1102

    
1103
	foreach ($iflist as $ifent => $ifname) {
1104
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
1105
		if(!in_array($real_interface, $supported_ints)) {
1106
			continue;
1107
                }
1108
		if(isset($config['system']['polling'])) {
1109
			mwexec("/sbin/ifconfig {$real_interface} polling");
1110
		} else {
1111
			mwexec("/sbin/ifconfig {$real_interface} -polling");
1112
		}
1113
	}
1114
}
1115

    
1116
/****f* pfsense-utils/setup_microcode
1117
 * NAME
1118
 *   enumerates all interfaces and calls enable_hardware_offloading which
1119
 *   enables a NIC's supported hardware features.
1120
 * INPUTS
1121
 *
1122
 * RESULT
1123
 *   null
1124
 * NOTES
1125
 *   This function only supports the fxp driver's loadable microcode.
1126
 ******/
1127
function setup_microcode() {
1128

    
1129
	/* if list */
1130
        $ifdescrs = get_configured_interface_list();
1131

    
1132
	foreach($ifdescrs as $if)
1133
		enable_hardware_offloading($if);
1134
}
1135

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

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

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

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

    
1202
	if($tmp == "")
1203
		return false;
1204
	else
1205
		return true;
1206
}
1207

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

    
1219
/****f* pfsense-utils/is_interface_wireless
1220
 * NAME
1221
 *   is_interface_wireless - Returns if an interface is wireless
1222
 * RESULT
1223
 *   $tmp	- Returns if an interface is wireless
1224
 ******/
1225
function is_interface_wireless($interface) {
1226
	global $config, $g;
1227
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
1228
	if(!is_array($config['interfaces'][$friendly]['wireless'])) {
1229
		if (preg_match($g['wireless_regex'], $interface)) {
1230
			$config['interfaces'][$friendly]['wireless'] = array();
1231
			return true;
1232
		}
1233
		unset($config['interfaces'][$friendly]['wireless']);
1234
		return false;
1235
	} else {
1236
		return true;
1237
	}
1238
}
1239

    
1240
/****f* pfsense-utils/find_number_of_created_carp_interfaces
1241
 * NAME
1242
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
1243
 * RESULT
1244
 *   $tmp	- Number of currently created CARP interfaces.
1245
 ******/
1246
function find_number_of_created_carp_interfaces($flush = false) {
1247
	global $carp_interface_count_cache;
1248

    
1249
	if (!isset($carp_interface_count_cache) or $flush) {
1250
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
1251
		$fd = popen($command . " 2>&1 ", "r");
1252
		if(!$fd) {
1253
			log_error("Warning, could not execute command {$command}");
1254
			return 0;
1255
		}
1256
		while(!feof($fd)) {
1257
			$tmp .= fread($fd,49);
1258
		}
1259
		fclose($fd);
1260
		$carp_interface_count_cache = intval($tmp);
1261
	}
1262
	return $carp_interface_count_cache;
1263
}
1264

    
1265
/****f* pfsense-utils/link_interface_to_bridge
1266
 * NAME
1267
 *   link_interface_to_bridge - Finds out a bridge group for an interface
1268
 * INPUTS
1269
 *   $ip
1270
 * RESULT
1271
 *   bridge[0-99]
1272
 ******/
1273
function link_interface_to_bridge($int) {
1274
	global $config;
1275
	
1276
	if (is_array($config['bridges']['bridged']))
1277
		foreach ($config['bridges']['bridged'] as $bridge) 
1278
			if(stristr($bridge['members'], "{$int}")) 
1279
				return "{$bridge['bridgeif']}";
1280
}
1281

    
1282
function link_interface_to_gre($interface) {
1283
        global $config;
1284

    
1285
        if (is_array($config['gres']['gre']))
1286
                foreach ($config['gres']['gre'] as $gre)
1287
                        if($gre['if'] == $interface)
1288
                                return "{$gre['greif']}";
1289
}
1290

    
1291
function link_interface_to_gif($interface) {
1292
        global $config;
1293

    
1294
        if (is_array($config['gifs']['gif']))
1295
                foreach ($config['gifs']['gif'] as $gif)
1296
                        if($gif['if'] == $interface)
1297
                                return "{$gif['gifif']}";
1298
}
1299

    
1300
function link_carp_interface_to_parent($interface) {
1301
	global $config;
1302
	if($interface == "") return;
1303

    
1304
	/* if list */
1305
        $ifdescrs = get_configured_interface_list();
1306

    
1307
	$carp_int = $interface;
1308
	$carp_ip = find_interface_ip($interface);
1309
	$carp_subnet = find_virtual_ip_netmask($carp_ip);
1310
	$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1311
	$carp_ints = "";
1312
	$num_carp_ints = find_number_of_created_carp_interfaces();
1313

    
1314
	foreach ($ifdescrs as $ifdescr => $ifname) {
1315
		if(interface_has_gateway($ifname)) {
1316
			$interfaceip = $config['interfaces'][$ifname]['ipaddr'];
1317
			$subnet_bits = $config['interfaces'][$ifname]['subnet'];
1318
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
1319
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}")) {
1320
				return $ifname;
1321
			}
1322
		}
1323
	}
1324
	return $carp_ints;
1325
}
1326

    
1327
/****f* pfsense-utils/link_ip_to_carp_interface
1328
 * NAME
1329
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
1330
 * INPUTS
1331
 *   $ip
1332
 * RESULT
1333
 *   $carp_ints
1334
 ******/
1335
function link_ip_to_carp_interface($ip) {
1336
	global $config;
1337
	if($ip == "") return;
1338

    
1339
	/* if list */
1340
        $ifdescrs = get_configured_interface_list();
1341

    
1342
	$ft = split("\.", $ip);
1343
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
1344

    
1345
	$carp_ints = "";
1346
	$num_carp_ints = find_number_of_created_carp_interfaces();
1347
	foreach ($ifdescrs as $ifdescr => $ifname) {
1348
		for($x=0; $x<$num_carp_ints; $x++) {
1349
			$carp_int = "carp{$x}";
1350
			$carp_ip = find_interface_ip($carp_int);
1351
			$carp_subnet = find_virtual_ip_netmask($carp_ip);
1352
			$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1353
			if(ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
1354
				if(!stristr($carp_ints, $carp_int))
1355
					$carp_ints .= " " . $carp_int;
1356
		}
1357
	}
1358
	return $carp_ints;
1359
}
1360

    
1361
/****f* pfsense-utils/find_virtual_ip_netmask
1362
 * NAME
1363
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
1364
 * INPUTS
1365
 *   $ip - ip address to locate subnet mask of
1366
 * RESULT
1367
 *   String containing the command's result.
1368
 * NOTES
1369
 *   This function returns the command's stdout and stderr.
1370
 ******/
1371
function find_virtual_ip_netmask($ip) {
1372
        global $config;
1373
        foreach($config['virtualip']['vip'] as $vip) {
1374
                if($ip == $vip['subnet'])
1375
                        return $vip['subnet_bits'];
1376
        }
1377
}
1378

    
1379
/****f* pfsense-utils/exec_command
1380
 * NAME
1381
 *   exec_command - Execute a command and return a string of the result.
1382
 * INPUTS
1383
 *   $command	- String of the command to be executed.
1384
 * RESULT
1385
 *   String containing the command's result.
1386
 * NOTES
1387
 *   This function returns the command's stdout and stderr.
1388
 ******/
1389
function exec_command($command) {
1390
	$output = array();
1391
	exec($command . ' 2>&1 ', $output);
1392
	return(implode("\n", $output));
1393
}
1394

    
1395
/****f* interfaces/is_jumbo_capable
1396
 * NAME
1397
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
1398
 * INPUTS
1399
 *   $int             - string containing interface name
1400
 * RESULT
1401
 *   boolean          - true or false
1402
 ******/
1403
function is_jumbo_capable($int) {
1404
	/* Per:
1405
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
1406
	 * Only the following drivers support large frames
1407
         *
1408
	 * 'de' chipset purposely left out of this list
1409
	 * requires defining BIG_PACKET in the
1410
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
1411
	 * kernel or module.  The hack works only for the 21041,
1412
	 * 21140, and 21140A chips.
1413
	 */
1414
	global $g;
1415

    
1416
	$capable = $g['vlan_long_frame'];
1417

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

    
1420
	if (in_array($int_family[0], $capable))
1421
		return true;
1422
	else
1423
		return false;
1424
}
1425

    
1426
/*
1427
 * Return the interface array
1428
 */
1429
function get_interface_arr($flush = false) {
1430
	global $interface_arr_cache;
1431

    
1432
	/* If the cache doesn't exist, build it */
1433
	if (!isset($interface_arr_cache) or $flush)
1434
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
1435

    
1436
	return $interface_arr_cache;
1437
}
1438

    
1439
/*
1440
 * does_interface_exist($interface): return true or false if a interface is
1441
 * detected.
1442
 */
1443
function does_interface_exist($interface) {
1444
	global $config;
1445

    
1446
	if(!$interface)
1447
		return false;
1448
		
1449
	$ints = get_interface_arr();
1450

    
1451
	if(stristr($ints, $interface) !== false)
1452
		return true;
1453
	else
1454
		return false;
1455
}
1456

    
1457
/*
1458
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
1459
 */
1460
function convert_ip_to_network_format($ip, $subnet) {
1461
	$ipsplit = split('[.]', $ip);
1462
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
1463
	return $string;
1464
}
1465

    
1466
/*
1467
 * find_interface_ip($interface): return the interface ip (first found)
1468
 */
1469
function find_interface_ip($interface, $flush = false) {
1470
	global $interface_ip_arr_cache;
1471
	
1472
	$interface = str_replace("\n", "", $interface);
1473
	if(does_interface_exist($interface) == false) 
1474
		return;
1475

    
1476
	/* Setup IP cache */
1477
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
1478
		$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");
1479
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
1480
	}
1481

    
1482
	return $interface_ip_arr_cache[$interface];
1483
}
1484

    
1485
function find_interface_subnet($interface, $flush = false) 
1486
{
1487
	global $interface_sn_arr_cache;
1488
	
1489
	$interface = str_replace("\n", "", $interface);
1490
	if (does_interface_exist($interface) == false)
1491
		return;
1492

    
1493
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
1494
		$interface_sn_arr_cache[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 4 | /usr/bin/head -1");
1495
		$interface_sn_arr_cache[$interface] = strlen(str_replace("0", "", base_convert(str_replace("\n", "", $interface_sn_arr_cache[$interface]),16, 2)));
1496
	}
1497

    
1498
	return $interface_sn_arr_cache[$interface];
1499
}
1500

    
1501
function guess_interface_from_ip($ipaddress) {
1502
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2; };'");
1503
	return $ret;
1504
}
1505

    
1506
/*
1507
 * find_ip_interface($ip): return the interface where an ip is defined
1508
 */
1509
function find_ip_interface($ip) {
1510

    
1511
	/* if list */
1512
        $ifdescrs = get_configured_interface_list();
1513

    
1514
	foreach ($ifdescrs as $ifdescr => $ifname) {
1515
		$int = convert_friendly_interface_to_real_interface_name($ifname);
1516
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
1517
		if(stristr($ifconfig,$ip) <> false)
1518
			return $int;
1519
	}
1520
	return false;
1521
}
1522

    
1523
/*
1524
 *  filter_translate_type_to_real_interface($interface): 
1525
 *		returns the real hardware interface name for a friendly interface.  ie: wan
1526
 */
1527
function filter_translate_type_to_real_interface($interface) {
1528
	global $config;
1529
	if($config['interfaces'][$interface]['if'] <> "") {
1530
		return $config['interfaces'][$interface]['if'];
1531
	} else {
1532
		return $interface;
1533
	}
1534
}
1535

    
1536
/*
1537
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
1538
 */
1539
function get_carp_interface_status($carpinterface) {
1540
	/* basically cache the contents of ifconfig statement
1541
	to speed up this routine */
1542
	global $carp_query;
1543
	if($carp_query == "")
1544
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
1545
	$found_interface = 0;
1546
	foreach($carp_query as $int) {
1547
		if($found_interface == 1) {
1548
			if(stristr($int, "MASTER")) return "MASTER";
1549
			if(stristr($int, "BACKUP")) return "BACKUP";
1550
			if(stristr($int, "INIT")) return "INIT";
1551
			return false;
1552
		}
1553
		if(stristr($int, $carpinterface) == true)
1554
		$found_interface=1;
1555
	}
1556
	return;
1557
}
1558

    
1559
/*
1560
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
1561
 */
1562
function get_pfsync_interface_status($pfsyncinterface) {
1563
    $result = does_interface_exist($pfsyncinterface);
1564
    if($result <> true) return;
1565
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
1566
    return $status;
1567
}
1568

    
1569
/*
1570
 * find_carp_interface($ip): return the carp interface where an ip is defined
1571
 */
1572
function find_carp_interface($ip) {
1573
	global $find_carp_ifconfig;
1574
	if($find_carp_ifconfig == "") {
1575
		$find_carp_ifconfig = array();
1576
		$num_carp_ints = find_number_of_created_carp_interfaces();
1577
		for($x=0; $x<$num_carp_ints; $x++) {
1578
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
1579
		}
1580
	}
1581
	$carps = 0;
1582
	foreach($find_carp_ifconfig as $fci) {
1583
		if(stristr($fci, $ip) == true)
1584
			return "carp{$carps}";
1585
		$carps++;
1586
	}
1587
}
1588

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

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

    
1614
/*
1615
 * add_text_to_file($file, $text): adds $text to $file.
1616
 * replaces the text if it already exists.
1617
 */
1618
function add_text_to_file($file, $text, $replace = false) {
1619
	if(file_exists($file) and is_writable($file)) {
1620
		$filecontents = file($file);
1621
		$fout = fopen($file, "w");
1622

    
1623
		$filecontents = array_map('rtrim', $filecontents);
1624
		array_push($filecontents, $text);
1625
		if ($replace)
1626
			$filecontents = array_unique($filecontents);
1627

    
1628
		$file_text = implode("\n", $filecontents);
1629

    
1630
		fwrite($fout, $file_text);
1631
		fclose($fout);
1632
		return true;
1633
	} else {
1634
		return false;
1635
	}
1636
}
1637

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

    
1655
/*
1656
 * get_filename_from_url($url): converts a url to its filename.
1657
 */
1658
function get_filename_from_url($url) {
1659
	return basename($url);
1660
}
1661

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

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

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

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

    
1717
/*
1718
 *   exec_command_and_return_text: execute command and return output
1719
 */
1720
function exec_command_and_return_text($command) {
1721
	return exec_command($command);
1722
}
1723

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

    
1768
/*
1769
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
1770
 */
1771
function convert_friendly_interface_to_real_interface_name($interface) {
1772
	global $config;
1773

    
1774
	$wanif = $interface;
1775
	switch ($interface) {
1776
		case "pptp":
1777
			$wanif = "pptp";
1778
			break;
1779
		case "pppoe":
1780
			$wanif = "pppoe";
1781
			break;
1782
		case "openvpn":
1783
			$wanif = "openvpn";
1784
			break;
1785
		case "enc0":
1786
			$wanif = "enc0";
1787
			break;
1788
		/* XXX: dial in support?!
1789
		case "ppp":
1790
			$wanif = "ppp";
1791
			break;
1792
		*/
1793
		default:
1794
			$iflist = get_configured_interface_with_descr(false,true);
1795

    
1796
		foreach ($iflist as $if => $ifdesc) {
1797
			if ($interface == $if || $interface == $ifdesc) {
1798

    
1799
			$cfg = $config['interfaces'][$if];
1800

    
1801
			switch ($cfg['ipaddr']) {
1802
			case "carpdev-dhcp":
1803
				$viparr = &$config['virtualip']['vip'];
1804
				$counter = 0;
1805
				if(is_array($viparr))
1806
				foreach ($viparr as $vip) {
1807
					if ($vip['mode'] == "carpdev-dhcp") {
1808
						if($vip['interface'] == $if) {
1809
							$wanif =  "carp{$counter}";
1810
							break;
1811
						}
1812
						$counter++;
1813
					} else if ($vip['mode'] = "carp") 
1814
						$counter++;
1815
				}
1816
				break;
1817
			case "pppoe": 
1818
				if ($if == "wan")
1819
					$wanif = "pppoe0";
1820
				else
1821
					$wanif = "pppoe" . substr($if,3);
1822
				break;
1823
			case "pptp": 
1824
				if ($if == "wan")
1825
					$wanif = "pptp0";
1826
				else
1827
					$wanif = "pptp" . substr($if, 3);
1828
				break;
1829
			default:
1830
				if (isset($cfg['ispointtopoint']) && $cfg['pointtopoint'])
1831
					$wanif = "ppp0"; // XXX: PPP needs to convert to mpd
1832
				else	
1833
					$wanif = $cfg['if'];
1834
				break;
1835
			}
1836
			break;
1837

    
1838
			break;
1839
			}
1840
		}
1841
		break;
1842
	}
1843

    
1844
    return $wanif;
1845
}
1846

    
1847
/*
1848
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
1849
 */
1850
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
1851
	global $config;
1852
	
1853
	if (stristr($interface, "pppoe")) {
1854
		$index = substr($interface, 5);
1855
		if (intval($index) > 0)
1856
			return "opt{$index}";
1857
		else
1858
			return "wan";
1859
	} else if (stristr($interface, "pptp")) {
1860
		$index = substr($interface, 4);
1861
                if (intval($index) > 0)
1862
                        return "opt{$index}";
1863
                else
1864
                        return "wan";	
1865
	} else if (stristr($interface, "carp")) {
1866
		$index = substr($interface, 4);
1867
		$counter = 0;
1868
		foreach ($config['virtualip']['vip'] as $vip) {
1869
			if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
1870
				if (intval($index) == $counter)
1871
					return $vip['interface'];
1872
				$counter++;
1873
			}
1874
		}
1875
	}
1876
		
1877
	/* if list */
1878
        $ifdescrs = get_configured_interface_list(false, true);
1879

    
1880
	foreach ($ifdescrs as $if => $ifname) {
1881
		if($config['interfaces'][$if]['if'] == $interface)
1882
			return $ifname;
1883

    
1884
		/* XXX: ermal - The 3 lines below are totally bogus code. */
1885
		$int = filter_translate_type_to_real_interface($if);
1886
		if($ifname == $interface) 
1887
			return $ifname;
1888

    
1889
		if($int == $interface) 
1890
			return $ifname;
1891
	}
1892
	return NULL;
1893
}
1894

    
1895
/* attempt to resolve interface to friendly descr */
1896
function convert_friendly_interface_to_friendly_descr($interface) {
1897
        global $config;
1898

    
1899
        switch ($interface) {
1900
        	case "pptp":
1901
				$ifdesc = "PPTP";
1902
				break;
1903
       		case "pppoe":
1904
				$ifdesc = "PPPoE";
1905
				break;
1906
        	case "openvpn":
1907
				$ifdesc = "OpenVPN";
1908
				break;
1909
        	case "enc0":
1910
			case "ipsec":
1911
				$ifdesc = "IPsec";
1912
				break;
1913
        default:
1914
        	/* if list */
1915
        	$ifdescrs = get_configured_interface_with_descr(false, true);
1916
        	foreach ($ifdescrs as $if => $ifname) {
1917
				if ($if == $interface || $ifname == $interface)
1918
					return $ifname;
1919
        	}
1920
		break;
1921
	}
1922

    
1923
        return $ifdesc;
1924
}
1925

    
1926
function convert_real_interface_to_friendly_descr($interface) {
1927
        global $config;
1928

    
1929
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
1930

    
1931
	if ($ifdesc) {
1932
		$iflist = get_configured_interface_with_descr();
1933
		return $iflist[$ifdesc];
1934
	}
1935
	
1936
        return $interface;
1937
}
1938

    
1939
/*
1940
 * update_progress_bar($percent): updates the javascript driven progress bar.
1941
 */
1942
function update_progress_bar($percent) {
1943
	global $pkg_interface;
1944
	if($percent > 100) $percent = 1;
1945
	if($pkg_interface <> "console") {
1946
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1947
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1948
		echo "\n</script>";
1949
	} else {
1950
		echo " {$percent}%";
1951
	}
1952
}
1953

    
1954
/****f* pfsense-utils/WakeOnLan
1955
 * NAME
1956
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
1957
 * RESULT
1958
 *   true/false - true if the operation was successful
1959
 ******/
1960
function WakeOnLan($addr, $mac)
1961
{
1962
	$addr_byte = explode(':', $mac);
1963
	$hw_addr = '';
1964

    
1965
	for ($a=0; $a < 6; $a++)
1966
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1967

    
1968
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1969

    
1970
	for ($a = 1; $a <= 16; $a++)
1971
		$msg .= $hw_addr;
1972

    
1973
	// send it to the broadcast address using UDP
1974
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1975
	if ($s == false) {
1976
		log_error("Error creating socket!");
1977
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
1978
	} else {
1979
		// setting a broadcast option to socket:
1980
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1981
		if($opt_ret < 0)
1982
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1983
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1984
		socket_close($s);
1985
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1986
		return true;
1987
	}
1988

    
1989
	return false;
1990
}
1991

    
1992
/*
1993
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
1994
 *                             is queuename|qlength|measured_packets
1995
 *                             NOTE: this command takes 5 seconds to run
1996
 */
1997
function gather_altq_queue_stats($dont_return_root_queues) {
1998
	$stats = exec("/sbin/pfctl -vvsq");
1999
	$stats_array = split("\n", $stats);
2000
	$queue_stats = array();
2001
	foreach ($stats_array as $stats_line) {
2002
		$match_array = "";
2003
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
2004
			$queue_name = $match_array[1][0];
2005
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
2006
			$speed = $match_array[1][0];
2007
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
2008
			$borrows = $match_array[1][0];
2009
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
2010
			$suspends = $match_array[1][0];
2011
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
2012
			$drops = $match_array[1][0];
2013
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
2014
			$measured = $match_array[1][0];
2015
			if($dont_return_root_queues == true)
2016
				if(stristr($queue_name,"root_") == false)
2017
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
2018
		}
2019
	}
2020
	return $queue_stats;
2021
}
2022

    
2023
/*
2024
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
2025
 *					 Useful for finding paths and stripping file extensions.
2026
 */
2027
function reverse_strrchr($haystack, $needle) {
2028
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
2029
}
2030

    
2031
/*
2032
 *  backup_config_section($section): returns as an xml file string of
2033
 *                                   the configuration section
2034
 */
2035
function backup_config_section($section) {
2036
	global $config;
2037
	$new_section = &$config[$section];
2038
	/* generate configuration XML */
2039
	$xmlconfig = dump_xml_config($new_section, $section);
2040
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
2041
	return $xmlconfig;
2042
}
2043

    
2044
/*
2045
 *  backup_vip_config_section($section): returns as an xml file string of
2046
 *                                   the configuration section
2047
 */
2048
function backup_vip_config_section() {
2049
	global $config;
2050
	$new_section = &$config['virtualip'];
2051
	foreach($new_section['vip'] as $section) {
2052
		if($section['mode'] == "proxyarp") {
2053
			unset($section);
2054
		}
2055
		if($section['advskew'] <> "") {
2056
			$section_val = intval($section['advskew']);
2057
			$section_val=$section_val+100;
2058
			if($section_val > 255)
2059
				$section_val = 255;
2060
			$section['advskew'] = $section_val;
2061
		}
2062
		$temp['vip'][] = $section;
2063
   }
2064
   return $temp;
2065
}
2066

    
2067
/*
2068
 *  restore_config_section($section, new_contents): restore a configuration section,
2069
 *                                                  and write the configuration out
2070
 *                                                  to disk/cf.
2071
 */
2072
function restore_config_section($section, $new_contents) {
2073
	global $config, $g;
2074
	conf_mount_rw();
2075
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
2076
	fwrite($fout, $new_contents);
2077
	fclose($fout);
2078
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
2079
	$config[$section] = &$section_xml;
2080
	unlink($g['tmp_path'] . "/tmpxml");
2081
	write_config("Restored {$section} of config file (maybe from CARP partner)");
2082
	conf_mount_ro();
2083
	return;
2084
}
2085

    
2086
/*
2087
 *  merge_config_section($section, new_contents):   restore a configuration section,
2088
 *                                                  and write the configuration out
2089
 *                                                  to disk/cf.  But preserve the prior
2090
 * 													structure if needed
2091
 */
2092
function merge_config_section($section, $new_contents) {
2093
	global $config;
2094
	conf_mount_rw();
2095
	$fname = get_tmp_filename();
2096
	$fout = fopen($fname, "w");
2097
	fwrite($fout, $new_contents);
2098
	fclose($fout);
2099
	$section_xml = parse_xml_config($fname, $section);
2100
	$config[$section] = $section_xml;
2101
	unlink($fname);
2102
	write_config("Restored {$section} of config file (maybe from CARP partner)");
2103
	conf_mount_ro();
2104
	return;
2105
}
2106

    
2107
/*
2108
 * http_post($server, $port, $url, $vars): does an http post to a web server
2109
 *                                         posting the vars array.
2110
 * written by nf@bigpond.net.au
2111
 */
2112
function http_post($server, $port, $url, $vars) {
2113
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
2114
	$urlencoded = "";
2115
	while (list($key,$value) = each($vars))
2116
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
2117
	$urlencoded = substr($urlencoded,0,-1);
2118
	$content_length = strlen($urlencoded);
2119
	$headers = "POST $url HTTP/1.1
2120
Accept: */*
2121
Accept-Language: en-au
2122
Content-Type: application/x-www-form-urlencoded
2123
User-Agent: $user_agent
2124
Host: $server
2125
Connection: Keep-Alive
2126
Cache-Control: no-cache
2127
Content-Length: $content_length
2128

    
2129
";
2130

    
2131
	$errno = "";
2132
	$errstr = "";
2133
	$fp = fsockopen($server, $port, $errno, $errstr);
2134
	if (!$fp) {
2135
		return false;
2136
	}
2137

    
2138
	fputs($fp, $headers);
2139
	fputs($fp, $urlencoded);
2140

    
2141
	$ret = "";
2142
	while (!feof($fp))
2143
		$ret.= fgets($fp, 1024);
2144
	fclose($fp);
2145

    
2146
	return $ret;
2147
}
2148

    
2149
/*
2150
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
2151
 */
2152
if (!function_exists('php_check_syntax')){
2153
	function php_check_syntax($code_to_check, &$errormessage){
2154
		return false;
2155
		$fout = fopen("/tmp/codetocheck.php","w");
2156
		$code = $_POST['content'];
2157
		$code = str_replace("<?php", "", $code);
2158
		$code = str_replace("?>", "", $code);
2159
		fwrite($fout, "<?php\n\n");
2160
		fwrite($fout, $code_to_check);
2161
		fwrite($fout, "\n\n?>\n");
2162
		fclose($fout);
2163
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
2164
		$output = exec_command($command);
2165
		if (stristr($output, "Errors parsing") == false) {
2166
			echo "false\n";
2167
			$errormessage = '';
2168
			return(false);
2169
		} else {
2170
			$errormessage = $output;
2171
			return(true);
2172
		}
2173
	}
2174
}
2175

    
2176
/*
2177
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
2178
 */
2179
if (!function_exists('php_check_syntax')){
2180
	function php_check_syntax($code_to_check, &$errormessage){
2181
		return false;
2182
		$command = "/usr/local/bin/php -l " . $code_to_check;
2183
		$output = exec_command($command);
2184
		if (stristr($output, "Errors parsing") == false) {
2185
			echo "false\n";
2186
			$errormessage = '';
2187
			return(false);
2188
		} else {
2189
			$errormessage = $output;
2190
			return(true);
2191
		}
2192
	}
2193
}
2194

    
2195
/*
2196
 * rmdir_recursive($path,$follow_links=false)
2197
 * Recursively remove a directory tree (rm -rf path)
2198
 * This is for directories _only_
2199
 */
2200
function rmdir_recursive($path,$follow_links=false) {
2201
	$to_do = glob($path);
2202
	if(!is_array($to_do)) $to_do = array($to_do);
2203
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
2204
		if(file_exists($workingdir)) {
2205
			if(is_dir($workingdir)) {
2206
				$dir = opendir($workingdir);
2207
				while ($entry = readdir($dir)) {
2208
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
2209
						unlink("$workingdir/$entry");
2210
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
2211
						rmdir_recursive("$workingdir/$entry");
2212
				}
2213
				closedir($dir);
2214
				rmdir($workingdir);
2215
			} elseif (is_file($workingdir)) {
2216
				unlink($workingdir);
2217
			}
2218
               	}
2219
	}
2220
	return;
2221
}
2222

    
2223
/*
2224
 *     get_memory()
2225
 *     returns an array listing the amount of
2226
 *     memory installed in the hardware
2227
 *     [0]real and [1]available
2228
 */
2229
function get_memory() {
2230
	if(file_exists("/var/log/dmesg.boot")) {
2231
		$mem = `cat /var/log/dmesg.boot | grep memory`;
2232
		$matches = "";
2233
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2234
			$real = $matches[1];
2235
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2236
			$avail = $matches[1];
2237
		return array($real[0],$avail[0]);
2238
	} else {
2239
		$mem = `dmesg -a`;
2240
		$matches = "";
2241
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2242
			$real = $matches[1];
2243
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2244
			$avail = $matches[1];
2245
		return array($real[0],$avail[0]);
2246
	}
2247
}
2248

    
2249
/*
2250
 *    safe_mkdir($path, $mode = 0755)
2251
 *    create directory if it doesn't already exist and isn't a file!
2252
 */
2253
function safe_mkdir($path, $mode=0755) {
2254
	global $g;
2255

    
2256
	if (!is_file($path) && !is_dir($path)) {
2257
		return @mkdir($path, $mode);
2258
	} else {
2259
		return false;
2260
	}
2261
}
2262

    
2263
/*
2264
 * make_dirs($path, $mode = 0755)
2265
 * create directory tree recursively (mkdir -p)
2266
 */
2267
function make_dirs($path, $mode = 0755) {
2268
	$base = '';
2269
	foreach (explode('/', $path) as $dir) {
2270
		$base .= "/$dir";
2271
		if (!is_dir($base)) {
2272
			if (!@mkdir($base, $mode))
2273
				return false;
2274
		}
2275
	}
2276
	return true;
2277
}
2278

    
2279
/*
2280
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
2281
 */
2282
function call_pfsense_method($method, $params, $timeout = 0) {
2283
	global $g, $config;
2284

    
2285
	$ip = gethostbyname($g['product_website']);
2286
	if($ip == $g['product_website'])
2287
		return false;
2288
	global $g, $config;
2289
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
2290
	$xmlrpc_path = $g['xmlrpcpath'];
2291
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
2292
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
2293
	$resp = $cli->send($msg, $timeout);
2294
	if(!$resp) {
2295
		log_error("XMLRPC communication error: " . $cli->errstr);
2296
		return false;
2297
	} elseif($resp->faultCode()) {
2298
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
2299
		return false;
2300
	} else {
2301
		return XML_RPC_Decode($resp->value());
2302
	}
2303
}
2304

    
2305
/*
2306
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
2307
 */
2308
function check_firmware_version($tocheck = "all", $return_php = true) {
2309
	global $g, $config;
2310
	$ip = gethostbyname($g['product_website']);
2311
	if($ip == $g['product_website'])
2312
		return false;
2313
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
2314
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
2315
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
2316
		"platform" => trim(file_get_contents('/etc/platform'))
2317
		);
2318
	if($tocheck == "all") {
2319
		$params = $rawparams;
2320
	} else {
2321
		foreach($tocheck as $check) {
2322
			$params['check'] = $rawparams['check'];
2323
			$params['platform'] = $rawparams['platform'];
2324
		}
2325
	}
2326
	if($config['system']['firmware']['branch']) {
2327
		$params['branch'] = $config['system']['firmware']['branch'];
2328
	}
2329
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
2330
		return false;
2331
	} else {
2332
		$versions["current"] = $params;
2333
	}
2334
	return $versions;
2335
}
2336

    
2337
function get_disk_info() {
2338
	$diskout = "";
2339
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
2340
	return explode(' ', $diskout[0]);
2341
	// $size, $used, $avail, $cap
2342
}
2343

    
2344
function run_plugins($directory) {
2345
	global $config, $g;
2346
	/* process packager manager custom rules */
2347
	$files = return_dir_as_array($directory);
2348
	if($files <> "") {
2349
		foreach ($files as $file) {
2350
			if($file) {
2351
				$text = file_get_contents($directory . $file);
2352
				if($text) {
2353
					if(stristr($file, ".sh") == true) {
2354
						mwexec($directory . $file . " start");
2355
					} else {
2356
						if(!stristr($file,"CVS")) {
2357
							if($g['booting'] == true)
2358
								echo "\t{$file}... ";
2359
							require_once($directory . $file);
2360
						}
2361
					}
2362
				}
2363
			}
2364
		}
2365
	}	
2366
}
2367

    
2368
/****f* pfsense-utils/display_top_tabs
2369
 * NAME
2370
 *   display_top_tabs - display tabs with rounded edges
2371
 * INPUTS
2372
 *   $text      - array of tabs
2373
 * RESULT
2374
 *   null
2375
 ******/
2376
function display_top_tabs(& $tab_array) {
2377
	global $HTTP_SERVER_VARS;
2378
	global $config;
2379
	global $g;
2380

    
2381
	/*  does the user have access to this tab?
2382
	 *  master user has access to everything.
2383
	 *  if the user does not have access, simply
2384
	 *  unset the tab item.
2385
	 */
2386

    
2387
	$tab_temp = array ();
2388
	foreach ($tab_array as $ta)
2389
		if(isAllowedPage($ta[2]))
2390
			$tab_temp[] = $ta;
2391
	/*
2392
		// FIXME :	if the checks are not good enough
2393
		//			in isAllowedPage, it needs to be
2394
		//			fixed instead of kludging here
2395

    
2396
		// TODO: humm what shall we do with pkg_edit.php and pkg.php?
2397
		if ((strpos($link, "pkg.php")) !== false || (strpos($link, "pkg_edit.php")) !== false) {
2398
			$pos_equal = strpos($link, "=");
2399
			$pos_xmlsuffix = strpos($link, ".xml");
2400
			// do we match an absolute url including ?xml= foo
2401
			if(!isAllowedPage($link, $allowed))
2402
				$link = substr($link, $pos_equal +1, ($pos_xmlsuffix - $pos_equal +3));
2403
		}
2404
		// next check - what if the basename contains a query string?
2405
		if ((strpos($link, "?")) !== false) {
2406
			$pos_qmark = strpos($link, "?");
2407
			$link = substr($link, 0, $pos_qmark);
2408
		}
2409
		$authorized_text = print_r($allowed, true);
2410
		if(is_array($authorized))
2411
			if (in_array(basename($link), $authorized))
2412
	*/
2413

    
2414
	unset ($tab_array);
2415
	$tab_array = & $tab_temp;
2416

    
2417
	$tab_active_bg   = "#EEEEEE";
2418
	$tab_inactive_bg = "#777777";
2419
	$nifty_tabs_corners = "#FFF";
2420
	$font_color = "white";
2421
	
2422
	/* if tabcontrols.php exist for a theme, allow it to be overriden */
2423
	$themename = $config['theme'];
2424
	$filename = "/usr/local/www/themes/{$themename}/tabcontrols.php";
2425
	if(file_exists($filename)) {
2426
		$eval_code = file_get_contents($filename);
2427
		eval($eval_code);
2428
	}
2429
	
2430
	echo "<table cellpadding='0' cellspacing='0'>\n";
2431
	echo " <tr>\n";
2432
	$tabscounter = 0;
2433
	foreach ($tab_array as $ta) {
2434
		if ($ta[1] == true) {
2435
			echo "  <td bgcolor='{$tab_active_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
2436
		} else {
2437
			echo "  <td bgcolor='{$tab_inactive_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
2438
		}
2439
		$tabscounter++;
2440
	}
2441
	echo "</tr>\n<tr>\n";
2442
	foreach ($tab_array as $ta) {
2443
		if ($ta[1] == true) {
2444
			echo "  <td height=\"15\" valign=\"middle\" bgcolor='{$tab_active_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
2445
			echo "&nbsp;&nbsp;&nbsp;";
2446
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2447
		} else {
2448
			echo "  <td height=\"15\" valign=\"middle\" bgcolor='{$tab_inactive_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
2449
			echo "<font color='{$font_color}'>{$ta[0]}</font></a>&nbsp;&nbsp;&nbsp;";
2450
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2451
		}
2452
	}
2453
	echo "</tr>\n<tr>\n";
2454
	foreach ($tab_array as $ta) {
2455
		if ($ta[1] == true) {
2456
			echo "  <td bgcolor='{$tab_active_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2457
		} else {
2458
			echo "  <td bgcolor='{$tab_inactive_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2459
		}
2460
		$tabscounter++;
2461
	}
2462
	echo " </tr>\n";
2463
	echo "</table>\n";
2464

    
2465
	echo "<script type=\"text/javascript\">";
2466
	echo "NiftyCheck();\n";
2467
	echo "Rounded(\"div#tabactive\",\"top\",\"{$nifty_tabs_corners}\",\"{$tab_active_bg}\",\"smooth\");\n";
2468
	for ($x = 0; $x < $tabscounter; $x++)
2469
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"{$nifty_tabs_corners}\",\"{$tab_inactive_bg}\",\"smooth\");\n";
2470
	echo "</script>";
2471
}
2472

    
2473

    
2474
/****f* pfsense-utils/display_topbar
2475
 * NAME
2476
 *   display_topbar - top a table off with rounded edges
2477
 * INPUTS
2478
 *   $text	- (optional) Text to include in bar
2479
 * RESULT
2480
 *   null
2481
 ******/
2482
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
2483
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
2484
	echo "       <tr height='1'>\n";
2485
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
2486
	echo "		<div id='topbar'></div></td>\n";
2487
	echo "       </tr>\n";
2488
	echo "       <tr height='1'>\n";
2489
	if ($text != "")
2490
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
2491
	else
2492
		echo "         <td height='1' class='listtopic'></td>\n";
2493
	echo "       </tr>\n";
2494
	echo "     </table>";
2495
	echo "<script type=\"text/javascript\">";
2496
	echo "NiftyCheck();\n";
2497
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
2498
	echo "</script>";
2499
}
2500

    
2501
/****f* pfsense-utils/generate_random_mac_address
2502
 * NAME
2503
 *   generate_random_mac - generates a random mac address
2504
 * INPUTS
2505
 *   none
2506
 * RESULT
2507
 *   $mac - a random mac address
2508
 ******/
2509
function generate_random_mac_address() {
2510
	$mac = "02";
2511
	for($x=0; $x<5; $x++)
2512
		$mac .= ":" . dechex(rand(16, 255));
2513
	return $mac;
2514
}
2515

    
2516
/****f* pfsense-utils/strncpy
2517
 * NAME
2518
 *   strncpy - copy strings
2519
 * INPUTS
2520
 *   &$dst, $src, $length
2521
 * RESULT
2522
 *   none
2523
 ******/
2524
function strncpy(&$dst, $src, $length) {
2525
	if (strlen($src) > $length) {
2526
		$dst = substr($src, 0, $length);
2527
	} else {
2528
		$dst = $src;
2529
	}
2530
}
2531

    
2532
/****f* pfsense-utils/reload_interfaces_sync
2533
 * NAME
2534
 *   reload_interfaces - reload all interfaces
2535
 * INPUTS
2536
 *   none
2537
 * RESULT
2538
 *   none
2539
 ******/
2540
function reload_interfaces_sync() {
2541
	global $config, $g;
2542

    
2543
	$shutdown_webgui_needed = false;
2544

    
2545
	touch("{$g['tmp_path']}/reloading_all");
2546

    
2547
	if($g['debug'])
2548
		log_error("reload_interfaces_sync() is starting.");
2549

    
2550
	if(file_exists("{$g['tmp_path']}/config.cache"))
2551
		unlink("{$g['tmp_path']}/config.cache");
2552

    
2553
	/* parse config.xml again */
2554
	$config = parse_config(true);
2555

    
2556
	$wan_if = $config['interfaces']['wan']['if'];
2557
	if (isset($config['interfaces']['lan']))
2558
                $lan_if = $config['interfaces']['lan']['if'];
2559
        else
2560
                $lan_if = "";
2561

    
2562
	if($g['debug'])
2563
		log_error("Cleaning up Interfaces");
2564

    
2565
	/* if list */
2566
        $iflist = get_configured_interface_list(true);
2567

    
2568
	foreach ($iflist as $ifent => $ifname) {
2569
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2570

    
2571
		if(stristr($ifname, "lo0") == true)
2572
			continue;
2573
		/* do not process wan interface, its mandatory */
2574
                if(stristr($ifname, "$wan_if") == true)
2575
                        continue;
2576
                /* do not process lan interface, its mandatory */
2577
                if(stristr($ifname, "$lan_if") == true)
2578
                        continue;
2579
		if($g['debug'])
2580
			log_error("Downing and deleting $ifname_real - $ifname");
2581
		mwexec("/sbin/ifconfig {$ifname_real} down");
2582
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2583
	}
2584

    
2585
	/* set up interfaces */
2586
	interfaces_configure();
2587

    
2588
	/* set up static routes */
2589
	if($g['debug'])
2590
		log_error("Configuring system Routing");
2591
	system_routing_configure();
2592

    
2593
	/* enable routing */
2594
	if($g['debug'])
2595
		log_error("Enabling system routing");
2596
	system_routing_enable();
2597

    
2598
	/* setup captive portal if needed */
2599
	if($g['debug'])
2600
		log_error("Configuring Captive portal");
2601
	captiveportal_configure();
2602

    
2603
	/* restart webConfigurator if needed */
2604
	if($shutdown_webgui_needed == true)
2605
		touch("/tmp/restart_webgui");
2606

    
2607
	/* start devd back up */
2608
	mwexec("/bin/rm /tmp/reload*");
2609

    
2610
	/* remove reloading_all trigger */
2611
	if($g['debug'])
2612
		log_error("Removing {$g['tmp_path']}/reloading_all");
2613
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2614
}
2615

    
2616
/****f* pfsense-utils/reload_all
2617
 * NAME
2618
 *   reload_all - triggers a reload of all settings
2619
 *   * INPUTS
2620
 *   none
2621
 * RESULT
2622
 *   none
2623
 ******/
2624
function reload_all() {
2625
	touch("/tmp/reload_all");
2626
}
2627

    
2628
/****f* pfsense-utils/reload_interfaces
2629
 * NAME
2630
 *   reload_interfaces - triggers a reload of all interfaces
2631
 * INPUTS
2632
 *   none
2633
 * RESULT
2634
 *   none
2635
 ******/
2636
function reload_interfaces() {
2637
	touch("/tmp/reload_interfaces");
2638
}
2639

    
2640
/****f* pfsense-utils/reload_all_sync
2641
 * NAME
2642
 *   reload_all - reload all settings
2643
 *   * INPUTS
2644
 *   none
2645
 * RESULT
2646
 *   none
2647
 ******/
2648
function reload_all_sync() {
2649
	global $config, $g;
2650

    
2651
	$g['booting'] = false;
2652

    
2653
	touch("{$g['tmp_path']}/reloading_all");
2654

    
2655
	$shutdown_webgui_needed = false;
2656

    
2657
	if(file_exists("{$g['tmp_path']}/config.cache"))
2658
		unlink("{$g['tmp_path']}/config.cache");
2659

    
2660
	/* parse config.xml again */
2661
	$config = parse_config(true);
2662

    
2663
	/* set up our timezone */
2664
	system_timezone_configure();
2665

    
2666
	/* set up our hostname */
2667
	system_hostname_configure();
2668

    
2669
	/* make hosts file */
2670
	system_hosts_generate();
2671

    
2672
	/* generate resolv.conf */
2673
	system_resolvconf_generate();
2674

    
2675
	/* Set up our loopback interface */
2676
	interfaces_loopback_configure();
2677

    
2678
	$wan_if = $config['interfaces']['wan']['if'];
2679
	if (isset($config['interfaces']['lan']))
2680
		$lan_if = $config['interfaces']['lan']['if'];
2681
	else
2682
		$lan_if = "";
2683

    
2684
	/* if list */
2685
	$iflist = get_configured_interface_list();
2686

    
2687
	foreach ($iflist as $ifent => $ifname) {
2688
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2689
		if(stristr($ifname, "lo0") == true)
2690
			continue;
2691
		/* do not process wan interface, its mandatory */
2692
		if($wan_if == $ifname_real)
2693
			continue;
2694
		/* do not process lan interface, its mandatory */
2695
		if($lan_if == $ifname_real)
2696
			continue;
2697
		mwexec("/sbin/ifconfig {$ifname_real} down");
2698
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2699
	}
2700

    
2701
	/* set up interfaces */
2702
	interfaces_configure();
2703

    
2704
	/* set up static routes */
2705
	system_routing_configure();
2706

    
2707
	/* enable routing */
2708
	system_routing_enable();
2709

    
2710
	/* ensure passwords are sync'd */
2711
//	system_password_configure();
2712

    
2713
	/* start dnsmasq service */
2714
	services_dnsmasq_configure();
2715

    
2716
	/* start dyndns service */
2717
	services_dyndns_configure();
2718

    
2719
	/* start DHCP service */
2720
	services_dhcpd_configure();
2721

    
2722
	/* configure cron service */
2723
	configure_cron();
2724

    
2725
	/* start the NTP client */
2726
	system_ntp_configure();
2727

    
2728
	/* start ftp proxy helpers if they are enabled */
2729
	system_start_ftp_helpers();
2730

    
2731
	/* start the captive portal */
2732
	captiveportal_configure();
2733

    
2734
        /* reload the filter */
2735
	filter_configure_sync();
2736

    
2737
	/* sync pw database */
2738
	conf_mount_rw();
2739
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2740
	conf_mount_ro();
2741

    
2742
	/* restart sshd */
2743
	touch("/tmp/start_sshd");
2744

    
2745
	/* restart webConfigurator if needed */
2746
	if($shutdown_webgui_needed == true)
2747
		touch("/tmp/restart_webgui");
2748

    
2749
	mwexec("/bin/rm /tmp/reload*");
2750

    
2751
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2752

    
2753
}
2754

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

    
2775
function setup_serial_port() {
2776
	global $g, $config;
2777
	conf_mount_rw();
2778
	/* serial console - write out /boot.config */
2779
	if(file_exists("/boot.config"))
2780
		$boot_config = file_get_contents("/boot.config");
2781
	else
2782
		$boot_config = "";
2783

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

    
2844
function print_value_list($list, $count = 10, $separator = ",") {
2845
	$list = implode($separator, array_slice($list, 0, $count));
2846
	if(count($list) < $count) {
2847
		$list .= ".";
2848
	} else {
2849
		$list .= "...";
2850
	}
2851
	return $list;
2852
}
2853

    
2854
function enable_rrd_graphing() {
2855
	global $config, $g, $altq_list_queues;
2856

    
2857
	if($g['booting']) 
2858
		echo "Generating RRD graphs...";
2859

    
2860
	$rrddbpath = "/var/db/rrd/";
2861
	$rrdgraphpath = "/usr/local/www/rrd";
2862

    
2863
	$traffic = "-traffic.rrd";
2864
	$packets = "-packets.rrd";
2865
	$states = "-states.rrd";
2866
	$quality = "-quality.rrd";
2867
	$wireless = "-wireless.rrd";
2868
	$queues = "-queues.rrd";
2869
	$queuesdrop = "-queuedrops.rrd";
2870
	$spamd = "-spamd.rrd";
2871
	$proc = "-processor.rrd";
2872
	$mem = "-memory.rrd";
2873

    
2874
	$rrdtool = "/usr/local/bin/rrdtool";
2875
	$netstat = "/usr/bin/netstat";
2876
	$awk = "/usr/bin/awk";
2877
	$tar = "/usr/bin/tar";
2878
	$pfctl = "/sbin/pfctl";
2879
	$sysctl = "/sbin/sysctl";
2880
	$php = "/usr/local/bin/php";
2881
	$top = "/usr/bin/top";
2882
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2883
	$ifconfig = "/sbin/ifconfig";
2884
	$pingcmd = "/sbin/ping";
2885

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

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

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

    
2914
	/* read the shaper config */
2915
	read_altq_config();
2916

    
2917
	$rrdrestore = "";
2918
	$rrdreturn = "";
2919

    
2920
	if (isset ($config['rrd']['enable'])) {
2921

    
2922
		/* create directory if needed */
2923
		if (!is_dir("$rrddbpath")) {
2924
			mkdir("$rrddbpath", 0755);
2925
		}
2926

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

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

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

    
2957
		foreach ($ifdescrs as $realif => $ifdescr) {
2958
			$ifname = $ifdescr['friendly'];
2959
			$state = $ifdescr['up'];
2960

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

    
2966
			/* or are down */
2967
			if (!$state) {
2968
				continue;
2969
			}
2970

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

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

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

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

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

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

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

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

    
3033
			$rrdupdatesh .= "\n";
3034
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
3035
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
3036
			if(! is_macaddr(get_interface_mac($realif))) {
3037
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$4 \":\" \$7}'`\n";
3038
			} else {
3039
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5 \":\" \$8}'`\n";
3040
			}
3041

    
3042
			/* QUALITY, create link quality database */
3043
			/* if the interface has a gateway defined, use it */
3044
			if(interface_has_gateway($ifname)) {
3045
				if (!file_exists("$rrddbpath$ifname$quality")) {
3046
					/* create rrd file if it does not exist */
3047
					log_error("Create RRD database $rrddbpath$ifname$quality");
3048
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
3049
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
3050
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
3051
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3052
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3053
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3054
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3055
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3056

    
3057
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3058
					if ($rrdcreatereturn != 0) {
3059
						log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3060
					}
3061
				}
3062

    
3063
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3064
				if($g['booting']) {
3065
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
3066
				}
3067
				
3068
				$numpings = 5;
3069
				if(isset($config['interfaces'][$ifname]['gateway'])) {
3070
					$monitorip = lookup_gateway_monitor_ip_by_name($config['interfaces'][$ifname]['gateway']);
3071
				} else {
3072
					$monitorip = lookup_gateway_monitor_ip_by_name($ifname);
3073
				}
3074
				if(!is_ipaddr($monitorip)) {
3075
					$monitorip = get_interface_gateway($ifname);
3076
				}
3077
				if(!is_ipaddr($monitorip)) {
3078
					/* still no monitor IP, don't write a collector and pass the batton */
3079
					continue;
3080
				}
3081
				/* the ping test function. We call this on the last line */
3082
				$rrdupdatesh .= "# Quality collector for {$ifname}\n";
3083
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
3084
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
3085
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
3086
				$rrdupdatesh .= "	local out_{$ifname}\n";
3087
				$rrdupdatesh .= "	out_{$ifname}=`$pingcmd -c $numpings -q $monitorip`\n";
3088
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
3089
				$rrdupdatesh .= "		packetloss_{$ifname}=`echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1`\n";
3090
				$rrdupdatesh .= "		roundtrip_{$ifname}=`echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/'`\n";
3091
				$rrdupdatesh .= "	fi\n";
3092
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
3093
				$rrdupdatesh .= "}\n\n";
3094

    
3095
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
3096
			}
3097

    
3098
			/* WIRELESS, set up the rrd file */
3099
			if($config['interfaces'][$ifname]['wireless']['mode'] == "bss") {
3100
				if (!file_exists("$rrddbpath$ifname$wireless")) {
3101
					/* create rrd file if it does not exist */
3102
					log_error("Create RRD database $rrddbpath$ifname$wireless");
3103
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$wireless --step $rrdwirelessinterval ";
3104
					$rrdcreate .= "DS:snr:GAUGE:$wirelessvalid:0:1000 ";
3105
					$rrdcreate .= "DS:rate:GAUGE:$wirelessvalid:0:1000 ";
3106
					$rrdcreate .= "DS:channel:GAUGE:$wirelessvalid:0:1000 ";
3107
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3108
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3109
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3110
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3111
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3112
	
3113
					$rrdcreateoutput = array();
3114
					$rrdcreatereturn = "";
3115

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

    
3123
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3124
				if($g['booting']) {
3125
					exec("$rrdtool update $rrddbpath$ifname$wireless N:U:U:U");
3126
				}
3127

    
3128
				$rrdupdatesh .= "\n";
3129
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
3130
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\\\n";
3131
				$rrdupdatesh .= "`$ifconfig {$realif} list ap| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
3132
			}
3133

    
3134
				/* QUEUES, set up the queues databases */
3135
				if ($altq_list_queues[$ifname]) {
3136
					$altq =& $altq_list_queues[$ifname];
3137
					/* NOTE: Is it worth as its own function?! */
3138
					switch ($altq->GetBwscale()) {
3139
                                        case "Gb":
3140
                                        	$factor = 1000 * 1000 * 1000;
3141
                                                break;
3142
                                        case "Mb":
3143
                                                $factor = 1000 * 1000;
3144
                                                break;
3145
                                        case "Kb":
3146
                                                $factor = 1000;
3147
                                                break;
3148
                                        case "b":
3149
                                        default:
3150
                                                $factor = 1;
3151
                                                break;
3152
                                        }
3153
					$qbandwidth = $altq->GetBandwidth() * $factor;
3154
					if ($qbandwidth <=0)
3155
						$qbandwidth = 100 * 1000 * 1000; /* 100Mbit */
3156
					$qlist =& $altq->get_queue_list($notused);
3157
					if (!file_exists("$rrddbpath$ifname$queues")) {
3158
						/* create rrd file if it does not exist */
3159
						log_error("Create RRD database $rrddbpath$ifname$queues");
3160
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
3161
						/* loop list of shaper queues */
3162
						$q = 0;
3163
						foreach ($qlist as $qname => $q) {
3164
							$rrdcreate .= "DS:$qname:COUNTER:$queuesvalid:0:$qbandwidth ";
3165
						}
3166

    
3167
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3168
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3169
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3170
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3171
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3172

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

    
3180
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
3181
						/* create rrd file if it does not exist */
3182
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
3183
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
3184
						/* loop list of shaper queues */
3185
						$q = 0;
3186
						foreach ($qlist as $qname => $q) {
3187
							$rrdcreate .= "DS:$qname:COUNTER:$queuesdropvalid:0:$qbandwidth ";
3188
						}
3189

    
3190
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3191
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3192
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3193
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3194
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3195

    
3196
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3197
						if ($rrdcreatereturn != 0) {
3198
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3199
						}
3200
					}
3201

    
3202
					if($g['booting']) {
3203
						$rrdqcommand = "-t ";
3204
						$rrducommand = "N";
3205
						$q = 0;
3206
						foreach ($qlist as $qname => $q) {
3207
							if($q == 0) {
3208
								$rrdqcommand .= "{$qname}";
3209
							} else {
3210
								$rrdqcommand .= ":{$qname}";
3211
							}
3212
							$q++;
3213
							$rrducommand .= ":U";
3214
						}
3215
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3216
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3217
					}
3218

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

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

    
3256
		/* System only statistics */
3257
		$ifname = "system";
3258

    
3259
			/* STATES, create pf states database */
3260
			if(! file_exists("$rrddbpath$ifname$states")) {
3261
				/* create rrd file if it does not exist */
3262
				log_error("Create RRD database $rrddbpath$ifname$states");
3263
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3264
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3265
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3266
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3267
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3268
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3269
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3270
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3271
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3272
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3273
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3274

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

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

    
3287
 			/* the pf states gathering function. */
3288
 			$rrdupdatesh .= "\n";
3289
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
3290
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
3291
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3292
 			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3293
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3294
 			$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";
3295
 			$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";
3296
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3297

    
3298
			/* End pf states statistics */
3299

    
3300
			/* CPU, create CPU statistics database */
3301
			if(! file_exists("$rrddbpath$ifname$proc")) {
3302
				/* create rrd file if it does not exist */
3303
				log_error("Create RRD database $rrddbpath$ifname$proc");
3304
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3305
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3306
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3307
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3308
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3309
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3310
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3311
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3312
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3313
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3314
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3315

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

    
3323
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3324
			if($g['booting']) {
3325
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
3326
			}
3327

    
3328
 			/* the CPU stats gathering function. */
3329
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { ";
3330
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } ";
3331
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { ";
3332
			$rrdupdatesh .= "processes = \$1; ";
3333
			$rrdupdatesh .= "} ";
3334
			$rrdupdatesh .= "else if ( \$1 == \"CPU\" ) { ";
3335
			$rrdupdatesh .= "user = \$3; ";
3336
			$rrdupdatesh .= "nice = \$5; ";
3337
			$rrdupdatesh .= "sys = \$7; ";
3338
			$rrdupdatesh .= "interrupt = \$9; ";
3339
			$rrdupdatesh .= "} ";
3340
			$rrdupdatesh .= "} END { ";
3341
			$rrdupdatesh .= "printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes ";
3342
			$rrdupdatesh .= "}'`\n\n";
3343

    
3344
			/* End CPU statistics */
3345

    
3346
			/* Memory, create Memory statistics database */
3347
			if(! file_exists("$rrddbpath$ifname$mem")) {
3348
				/* create rrd file if it does not exist */
3349
				log_error("Create RRD database $rrddbpath$ifname$mem");
3350
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$mem --step $rrdmeminterval ";
3351
				$rrdcreate .= "DS:active:GAUGE:$memvalid:0:10000000 ";
3352
				$rrdcreate .= "DS:inactive:GAUGE:$memvalid:0:10000000 ";
3353
				$rrdcreate .= "DS:free:GAUGE:$memvalid:0:10000000 ";
3354
				$rrdcreate .= "DS:cache:GAUGE:$memvalid:0:10000000 ";
3355
				$rrdcreate .= "DS:wire:GAUGE:$memvalid:0:10000000 ";
3356
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3357
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3358
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3359
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3360
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3361
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3362
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3363
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3364
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3365
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3366
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3367
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3368

    
3369
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3370
				if($rrdcreatereturn != 0) {
3371
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3372
						error is: $rrdcreateoutput[0]\n");
3373
				}
3374
			}
3375

    
3376
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3377
			if($g['booting']) {
3378
				exec("$rrdtool update $rrddbpath$ifname$mem N:U:U:U:U:U");
3379
			}
3380

    
3381
 			/* the Memory stats gathering function. */
3382
 			$rrdupdatesh .= "`$sysctl -n vm.stats.vm.v_page_count vm.stats.vm.v_active_count vm.stats.vm.v_inactive_count vm.stats.vm.v_free_count vm.stats.vm.v_cache_count vm.stats.vm.v_wire_count | ";
3383
			$rrdupdatesh .= " $awk '{getline active;getline inactive;getline free;getline cache;getline wire;printf \"$rrdtool update $rrddbpath$ifname$mem N:\"";
3384
			$rrdupdatesh .= "((active/$0) * 100)\":\"((inactive/$0) * 100)\":\"((free/$0) * 100)\":\"((cache/$0) * 100)\":\"(wire/$0 * 100)}'`\n\n";
3385
			
3386
			/* End Memory statistics */
3387

    
3388
			/* SPAMD, set up the spamd rrd file */
3389
			if (isset($config['installedpackages']['spamdsettings']) &&
3390
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
3391
				/* set up the spamd rrd file */
3392
				if (!file_exists("$rrddbpath$ifname$spamd")) {
3393
						/* create rrd file if it does not exist */
3394
						log_error("Create RRD database $rrddbpath$ifname$spamd");
3395
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
3396
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
3397
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
3398
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3399
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3400
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3401
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3402
						$rrdcreate .= "RRA:MIN:0.5:1440:1500 ";
3403
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3404
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3405
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3406
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3407
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3408
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3409
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3410
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3411
						$rrdcreate .= "RRA:MAX:0.5:720:1000 ";
3412
						$rrdcreate .= "RRA:MAX:0.5:1440:1500 ";
3413

    
3414
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3415
					if ($rrdcreatereturn != 0) {
3416
						log_error("RRD create failed exited with $rrdcreatereturn, the
3417
							error is: $rrdcreateoutput[0]\n");
3418
					}
3419
				}
3420

    
3421
				$rrdupdatesh .= "\n";
3422
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3423
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3424
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3425

    
3426
			}
3427
		/* End System statistics */
3428

    
3429
		$rrdupdatesh .= "sleep 60\n";
3430
		$rrdupdatesh .= "done\n";
3431
		log_error("Creating rrd update script");
3432
		/* write the rrd update script */
3433
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3434
		$fd = fopen("$updaterrdscript", "w");
3435
		fwrite($fd, "$rrdupdatesh");
3436
		fclose($fd);
3437

    
3438
		/* kill off traffic collectors */
3439
		kill_traffic_collector();
3440

    
3441
		/* start traffic collector */
3442
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3443

    
3444
	} else {
3445
		/* kill off traffic collectors */
3446
		kill_traffic_collector();
3447
	}
3448

    
3449
	if($g['booting']) 
3450
		echo "done.\n";
3451
		
3452
}
3453

    
3454
function kill_traffic_collector() {
3455
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
3456
}
3457

    
3458
function update_filter_reload_status($text) {
3459
	global $g;
3460
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3461
	fwrite($fd, $text);
3462
	fclose($fd);
3463
}
3464

    
3465
function get_interface_gateway($interface) {
3466
        global $config, $g;
3467

    
3468
	$iflist = get_configured_interface_with_descr();
3469
	/* 
3470
	 * XXX: This is silly at first, but we may be called with the interface
3471
	 *	descr for no apparent reason!!!
3472
	 */
3473
	foreach ($iflist as $ifent => $ifdesc) {
3474
		if ($ifent == $interface || $ifdesc == $interface) {
3475
			$interface = $ifent;
3476
			break;
3477
		}
3478
	}
3479

    
3480
	$gw = NULL;
3481

    
3482
	$gwcfg = $config['interfaces'][$interface];
3483
        if (is_ipaddr($gwcfg['gateway'])) 
3484
        	$gw = $gwcfg['gateway'];
3485
        else if ($gwcfg['gateway'] <> "") {
3486
        	if (is_array($config['gateways']['gateway_item']))
3487
                	foreach($config['gateways']['gateway_item'] as $gateway) {
3488
                                if($gateway['name'] == $gwcfg['gateway']) {
3489
                                        $gw = $gateway['gateway'];
3490
                        		break;
3491
                		}
3492
        		}
3493
        } 
3494
	
3495
	// for dynamic interfaces we handle them through the $interface_router file.
3496
	if (!is_ipaddr($gw)) {
3497
        	$realif = get_real_interface($interface);
3498
        	if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
3499
                	$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3500
                	$gw = rtrim($gw);
3501
        	}
3502
	}
3503

    
3504
        /* return gateway */
3505
        return $gw;
3506
}
3507

    
3508
/* DHCP enabled on any interfaces? */
3509
function is_dhcp_server_enabled() 
3510
{
3511
	global $config;
3512

    
3513
	$dhcpdenable = false;
3514
	
3515
	if (!is_array($config['dhcpd']))
3516
		return false;
3517

    
3518
	$Iflist = get_configured_interface_list();
3519

    
3520
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
3521
		if (isset($dhcpifconf['enable']) && isset($Iflist[$dhcpif])) {
3522
			$dhcpdenable = true;
3523
			break;
3524
		}
3525
	}
3526

    
3527
	return $dhcpdenable;
3528
}
3529

    
3530
/* return outside interfaces with a gateway */
3531
function get_interfaces_with_gateway() {
3532
	global $config;
3533
	$ints = array();
3534
	$vfaces = array(
3535
			'bridge.?*',
3536
			'ppp.?*',
3537
			'sl.?*',
3538
			'gif.?*',
3539
			'faith.?*',
3540
			'lo.?*',
3541
			'ng.?*',
3542
			'vlan.?*',
3543
			'pflog.?*',
3544
			'pfsync.?*',
3545
			'enc.?*',
3546
			'tun.?*',
3547
			'carp.?*'
3548
		);
3549
	$ifdescrs = get_interface_list("active","physical",$vfaces);
3550

    
3551
	/* loop interfaces, check config for outbound */
3552
	foreach ($ifdescrs as $ifdescr => $ifname) {
3553
		$friendly = $ifname['friendly'];
3554
		switch ($config['interfaces'][$friendly]['ipaddr']) {
3555
		case "dhcp":
3556
		case "carpdev-dhcp":
3557
		case "pppoe":
3558
		case "pptp":
3559
			$ints[] = $friendly;
3560
			break;	
3561
		default:
3562
			if ($config['interfaces'][$friendly]['pointtopoint']) 
3563
				$ints[] = $friendly;
3564
			else if ($config['interfaces'][$friendly]['gateway'] <> "")
3565
				$ints[] = $friendly;
3566
			break;
3567
		}
3568
	}
3569
	return $ints;
3570
}
3571

    
3572
/* return true if interface has a gateway */
3573
function interface_has_gateway($friendly) {
3574
	$friendly = strtolower($friendly);
3575
	if(in_array($friendly, get_interfaces_with_gateway())) {
3576
		return true;
3577
	} else {
3578
		/* extra check for real interface names if it falls through */
3579
		$friendly = convert_real_interface_to_friendly_interface_name($friendly);
3580
		return(in_array($friendly, get_interfaces_with_gateway()));
3581
	}
3582
}
3583

    
3584
/****f* pfsense-utils/isAjax
3585
 * NAME
3586
 *   isAjax - reports if the request is driven from prototype
3587
 * INPUTS
3588
 *   none
3589
 * RESULT
3590
 *   true/false
3591
 ******/
3592
function isAjax() {
3593
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
3594
}
3595

    
3596
//returns interface information
3597
function get_interface_info($ifdescr) {
3598
	global $config, $linkinfo, $netstatrninfo;
3599

    
3600
	$ifinfo = array();
3601
	/* if list */
3602
	$iflist = get_configured_interface_with_descr(false,true);
3603
	
3604
	$found = false;
3605
    	foreach ($iflist as $if => $ifname) {
3606
    	if ($ifdescr == $if || $ifdescr == $ifname) {
3607
			$ifinfo['hwif'] = $config['interfaces'][$if]['if'];
3608
			$ifinfo['if'] = get_real_interface($if);
3609
			$found = true;
3610
			break;
3611
		}
3612
	}
3613
	if ($found == false)
3614
		return;
3615

    
3616
	/* run netstat to determine link info */
3617

    
3618
	unset($linkinfo);
3619
	exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3620
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3621
	if (preg_match("/\*$/", $linkinfo[0])) {
3622
		$ifinfo['status'] = "down";
3623
	} else {
3624
		$ifinfo['status'] = "up";
3625
	}
3626

    
3627
	if (preg_match("/^enc|^tun|^ppp|^pptp|^ovpn/i", $ifinfo['if'])) {
3628
		$ifinfo['inpkts'] = $linkinfo[3];
3629
                $ifinfo['inbytes'] = $linkinfo[5];
3630
                $ifinfo['outpkts'] = $linkinfo[6];
3631
                $ifinfo['outbytes'] = $linkinfo[8];
3632
	} else {
3633
		$ifinfo['macaddr'] = $linkinfo[3];
3634
		$ifinfo['inpkts'] = $linkinfo[4];
3635
		$ifinfo['inerrs'] = $linkinfo[5];
3636
		$ifinfo['inbytes'] = $linkinfo[6];
3637
		$ifinfo['outpkts'] = $linkinfo[7];
3638
		$ifinfo['outerrs'] = $linkinfo[8];
3639
		$ifinfo['outbytes'] = $linkinfo[9];
3640
		$ifinfo['collisions'] = $linkinfo[10];
3641
	}
3642

    
3643
	$ifconfiginfo = "";
3644
	unset($ifconfiginfo);
3645
	exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3646
	foreach ($ifconfiginfo as $ici) {
3647
		if (preg_match("/inet (\S+)/", $ici, $matches)) 
3648
			$ifinfo['ipaddr'] = $matches[1];
3649
		if (preg_match("/netmask (\S+)/", $ici, $matches)) 
3650
			if (preg_match("/^0x/", $matches[1]))
3651
				$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
3652
	}
3653

    
3654
	switch ($config['interfaces'][$if]['ipaddr']) {
3655
	/* DHCP? -> see if dhclient is up */
3656
	case "dhcp":
3657
	case "carpdev-dhcp":
3658
        /* see if dhclient is up */
3659
        if (is_dhcp_running($ifinfo['if']) == true)
3660
        	$ifinfo['dhcplink'] = "up";
3661
        else
3662
            $ifinfo['dhcplink'] = "down";
3663

    
3664
		break;
3665
	/* PPPoE interface? -> get status from virtual interface */
3666
	case "pppoe":
3667
		unset($linkinfo);
3668
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3669
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3670
		if (preg_match("/\*$/", $linkinfo[0])) {
3671
			$ifinfo['pppoelink'] = "down";
3672
		} else {
3673
			/* get PPPoE link status for dial on demand */
3674
			$ifinfo['pppoelink'] = "up";
3675

    
3676
			foreach ($ifconfiginfo as $ici) {
3677
				if (strpos($ici, 'LINK0') !== false)
3678
					$ifinfo['pppoelink'] = "down";
3679
			}
3680
		}
3681
		break;
3682
	/* PPTP interface? -> get status from virtual interface */
3683
	case "pptp":
3684
		unset($linkinfo);
3685
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3686
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3687
		if (preg_match("/\*$/", $linkinfo[0])) {
3688
			$ifinfo['pptplink'] = "down";
3689
		} else {
3690
			/* get PPTP link status for dial on demand */
3691
			$ifinfo['pptplink'] = "up";
3692

    
3693
			foreach ($ifconfiginfo as $ici) {
3694
				if (strpos($ici, 'LINK0') !== false)
3695
					$ifinfo['pptplink'] = "down";
3696
			}
3697
		}
3698
		break;
3699
	default:
3700
		break;
3701
	}
3702

    
3703
	if ($ifinfo['status'] == "up") {
3704
		/* try to determine media with ifconfig */
3705
		unset($ifconfiginfo);
3706
		exec("/sbin/ifconfig " . $ifinfo['hwif'], $ifconfiginfo);
3707
		$matches = "";
3708
		foreach ($ifconfiginfo as $ici) {
3709

    
3710
			/* don't list media/speed for wireless cards, as it always
3711
			   displays 2 Mbps even though clients can connect at 11 Mbps */
3712
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
3713
				$ifinfo['media'] = $matches[1];
3714
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
3715
				$ifinfo['media'] = $matches[1];
3716
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
3717
				$ifinfo['media'] = $matches[1];
3718
			}
3719

    
3720
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
3721
				if ($matches[1] != "active")
3722
					$ifinfo['status'] = $matches[1];
3723
			}
3724
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
3725
				$ifinfo['channel'] = $matches[1];
3726
			}
3727
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
3728
				if ($matches[1][0] == '"')
3729
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
3730
				else
3731
					$ifinfo['ssid'] = $matches[1];
3732
			}
3733
		}
3734
		/* lookup the gateway */
3735
		if (interface_has_gateway($if)) 
3736
			$ifinfo['gateway'] = get_interface_gateway($if);
3737
	}
3738

    
3739
	$bridge = "";
3740
	$bridge = link_interface_to_bridge($ifdescr);
3741
	if($bridge) {
3742
		$bridge_text = `/sbin/ifconfig {$bridge}`;
3743
		if(stristr($bridge_text, "blocking") <> false) {
3744
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
3745
			$ifinfo['bridgeint'] = $bridge;
3746
		} else if(stristr($bridge_text, "learning") <> false) {
3747
			$ifinfo['bridge'] = "learning";
3748
			$ifinfo['bridgeint'] = $bridge;
3749
		} else if(stristr($bridge_text, "forwarding") <> false) {
3750
			$ifinfo['bridge'] = "forwarding";
3751
			$ifinfo['bridgeint'] = $bridge;
3752
		}
3753
	}
3754

    
3755
	return $ifinfo;
3756
}
3757

    
3758
//returns cpu speed of processor. Good for determining capabilities of machine
3759
function get_cpu_speed() {
3760
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
3761
}
3762

    
3763
/* check if the wan interface is up
3764
 * Wait for a maximum of 10 seconds
3765
 * If the interface is up before then continue
3766
 */
3767
function is_wan_interface_up($interface) {
3768
	global $g;
3769
	global $config;
3770
	$i = 0;
3771
	while($i < 10) {
3772
		if(get_interface_gateway($interface)) {
3773
			return true;
3774
		} else {
3775
			sleep(1);
3776
		}
3777
		$i++;
3778
	}
3779
	return false;
3780
}
3781

    
3782
function add_hostname_to_watch($hostname) {
3783
	if(!is_dir("/var/db/dnscache")) {
3784
		mkdir("/var/db/dnscache");
3785
	}
3786
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
3787
		$domrecords = array();
3788
		$domips = array();
3789
		exec("host -t A $hostname", $domrecords, $rethost);
3790
		if($rethost == 0) {
3791
			foreach($domrecords as $domr) {
3792
				$doml = explode(" ", $domr);
3793
				$domip = $doml[3];
3794
				/* fill array with domain ip addresses */
3795
				if(is_ipaddr($domip)) {
3796
					$domips[] = $domip;
3797
				}
3798
			}
3799
		}
3800
		sort($domips);
3801
		$contents = "";
3802
		if(! empty($domips)) {
3803
			foreach($domips as $ip) {
3804
				$contents .= "$ip\n";
3805
			}
3806
		}
3807
		file_put_contents("/var/db/dnscache/$hostname", $contents);
3808
	}
3809
}
3810

    
3811
function find_dns_aliases() {
3812
	global $config, $g;
3813
	foreach((array) $config['aliases']['alias'] as $alias) {
3814
		$alias_value = $alias['address'];
3815
		$alias_name = $alias['name'];
3816
		if(stristr($alias_value, " ")) {
3817
			$alias_split = split(" ", $alias_value);
3818
			foreach($alias_split as $as) {
3819
				if(is_fqdn($as)) 
3820
					add_hostname_to_watch($as);			
3821
			}
3822
		} else {
3823
			if(is_fqdn($alias_value)) 
3824
				add_hostname_to_watch($alias_value);
3825
		}
3826
	}
3827
}
3828

    
3829
function is_fqdn($fqdn) {
3830
	$hostname = false;
3831
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
3832
		$hostname = true;
3833
	}
3834
	if(preg_match("/\.\./", $fqdn)) {
3835
		$hostname = false;
3836
	}
3837
	if(preg_match("/^\./i", $fqdn)) { 
3838
		$hostname = false;
3839
	}
3840
	if(preg_match("/\//i", $fqdn)) {
3841
		$hostname = false;
3842
	}
3843
	return($hostname);
3844
}
3845

    
3846
function pfsense_default_state_size() {
3847
  /* get system memory amount */
3848
  $memory = get_memory();
3849
  $avail = $memory[0];
3850
  /* Be cautious and only allocate 10% of system memory to the state table */
3851
  $max_states = (int) ($avail/10)*1000;
3852
  return $max_states;
3853
}
3854

    
3855
function lookup_gateway_ip_by_name($name) {
3856
	global $config;
3857
	if(is_array($config['gateways'])) {
3858
		foreach($config['gateways']['gateway_item'] as $gateway) {
3859
			if($gateway['name'] == $name) {
3860
				$gatewayip = $gateway['gateway'];
3861
				$interfacegw = $gateway['interface'];
3862
				return($gatewayip);
3863
			}
3864
		}
3865
	} else {
3866
		return(false);
3867
	}
3868
}
3869

    
3870
function lookup_gateway_monitor_ip_by_name($name) {
3871
	global $config;
3872
	$gateways_arr = return_gateways_array();
3873

    
3874
	foreach($gateways_arr as $gateway) {
3875
		if($gateway['name'] == "$name") {
3876
			$monitorip = $gateway['monitor'];
3877
			if($monitorip == "")
3878
				$monitorip = $gateway['gateway'];
3879

    
3880
			return($monitorip);
3881
		}
3882
	}
3883
	return(false);
3884
}
3885

    
3886
function lookup_gateway_interface_by_name($name) {
3887
	global $config;
3888
	$gateways_arr = return_gateways_array();
3889

    
3890
	foreach($gateways_arr as $gateway) {
3891
		if($gateway['name'] == "$name") {
3892
			$gatewayip = $gateway['gateway'];
3893
			$interfacegw = $gateway['interface'];
3894
			return($interfacegw);
3895
		}
3896
	}
3897
	return(false);
3898
}
3899

    
3900
/****f* pfsense-utils/safe_write_file
3901
 * NAME
3902
 *   safe_write_file - Write a file out atomically
3903
 * DESCRIPTION
3904
 *   safe_write_file() Writes a file out atomically by first writing to a
3905
 *   temporary file of the same name but ending with the pid of the current
3906
 *   process, them renaming the temporary file over the original.
3907
 * INPUTS
3908
 *   $filename  - string containing the filename of the file to write
3909
 *   $content   - string containing the file content to write to file
3910
 *   $force_binary      - boolean denoting whether we should force binary
3911
 *   mode writing.
3912
 * RESULT
3913
 *   boolean - true if successful, false if not
3914
 ******/
3915
function safe_write_file($file, $content, $force_binary) {
3916
        $tmp_file = $file . "." . getmypid();
3917
        $write_mode = $force_binary ? "wb" : "w";
3918

    
3919
        $fd = fopen($tmp_file, $write_mode);
3920
        if (!$fd) {
3921
                // Unable to open temporary file for writing
3922
                return false;
3923
        }
3924
        if (!fwrite($fd, $content)) {
3925
                // Unable to write to temporary file
3926
                fclose($fd);
3927
                return false;
3928
        }
3929
        fclose($fd);
3930

    
3931
        if (!rename($tmp_file, $file)) {
3932
                // Unable to move temporary file to original
3933
                unlink($tmp_file);
3934
                return false;
3935
        }
3936
        return true;
3937
}
3938

    
3939
function rule_popup($src,$srcport,$dst,$dstport){
3940
global $config;
3941
$aliases_array = array();
3942
if($config['aliases']['alias'] <> "" and is_array($config['aliases']['alias']))
3943
{
3944
$span_begin = "";
3945
		$alias_src_span_begin = "";
3946
		$alias_src_span_end = "";
3947
		$alias_src_port_span_begin = "";
3948
		$alias_src_port_span_end = "";
3949
		$alias_dst_span_begin = "";
3950
		$alias_dst_span_end = "";
3951
		$alias_dst_port_span_begin = "";
3952
		$alias_dst_port_span_end = "";
3953
		$alias_content_text = "";
3954
	foreach($config['aliases']['alias'] as $alias_name) 
3955
	{	
3956
	 	$alias_addresses = explode (" ", $alias_name['address']);
3957
	 	$alias_details = explode ("||", $alias_name['detail']);
3958
	 	$alias_objects_with_details = "";
3959
	 	$counter = 0;
3960
	 	foreach($alias_addresses as $alias_ports_address)
3961
	 	{
3962
			$alias_objects_with_details .= $alias_addresses[$counter];
3963
			$alias_detail_default = strpos ($alias_details[$counter],"Entry added");
3964
			if ($alias_details[$counter] != "" && $alias_detail_default === False){
3965
				$alias_objects_with_details .=" - " . $alias_details[$counter];
3966
			}  
3967
			$alias_objects_with_details .= "<br>";
3968
			$counter++;
3969
		}			
3970
		//max character length for caption field
3971
		$maxlength = 60;
3972
		
3973
		$alias_descr_substr = $alias_name['descr'];
3974
		$alias_content_text = htmlspecialchars($alias_objects_with_details);
3975
		$alias_caption = htmlspecialchars($alias_descr_substr . ":");
3976
		$strlength = strlen ($alias_caption);
3977
		if ($strlength >= $maxlength) 
3978
			$alias_caption = substr($alias_caption, 0, $maxlength) . "...";		
3979
						
3980
		$span_begin = "<span style=\"cursor: help;\" onmouseover=\"domTT_activate(this, event, 'content', '<h1>$alias_caption</h1><p>$alias_content_text</p>', 'trail', true, 'delay', 0, 'fade', 'both', 'fadeMax', 93, 'styleClass', 'niceTitle');\" onmouseout=\"this.style.color = ''; domTT_mouseout(this, event);\"><U>";
3981
		
3982
		
3983
		if ($alias_name['name'] == $src)
3984
	 	{										
3985
			$alias_src_span_begin = $span_begin;
3986
		}
3987
	 	if ($alias_name['name'] == $srcport)
3988
	 	{									
3989
			$alias_src_port_span_begin = $span_begin;					
3990
		}
3991
		if ($alias_name['name'] == $dst)
3992
	 	{										
3993
			$alias_dst_span_begin = $span_begin;									
3994
		}
3995
		if ($alias_name['name'] == $dstport)
3996
	 	{											
3997
			$alias_dst_port_span_begin = $span_begin;											
3998
		}										
3999
		
4000
	}
4001
	$descriptions = array ();
4002
	$descriptions['src'] = $alias_src_span_begin;
4003
	$descriptions['srcport'] = $alias_src_port_span_begin;
4004
	$descriptions['dst'] = $alias_dst_span_begin;
4005
	$descriptions['dstport'] = $alias_dst_port_span_begin;
4006
	return $descriptions; 
4007
  }
4008
}
4009
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body') {
4010
	global $ch, $fout, $file_size, $downloaded;
4011
	$file_size  = 1;
4012
	$downloaded = 1;
4013
	/* open destination file */
4014
	$fout = fopen($destination_file, "wb");
4015

    
4016
	/*
4017
	 *	Originally by Author: Keyvan Minoukadeh
4018
	 *	Modified by Scott Ullrich to return Content-Length size
4019
         */
4020

    
4021
	$ch = curl_init();
4022
	curl_setopt($ch, CURLOPT_URL, $url_file);
4023
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
4024
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
4025
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
4026
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, '5');
4027

    
4028
	curl_exec($ch);
4029
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
4030
	if($fout)
4031
		fclose($fout);
4032
	curl_close($ch);
4033
	return ($http_code == 200) ? true : $http_code;
4034
}
4035

    
4036
function read_header($ch, $string) {
4037
	global $file_size, $fout;
4038
	$length = strlen($string);
4039
	$regs = "";
4040
	ereg("(Content-Length:) (.*)", $string, $regs);
4041
	if($regs[2] <> "") {
4042
		$file_size = intval($regs[2]);
4043
	}
4044
	ob_flush();
4045
	return $length;
4046
}
4047

    
4048
function read_body($ch, $string) {
4049
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen;
4050
	$length = strlen($string);
4051
	$downloaded += intval($length);
4052
	$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
4053
	$downloadProgress = 100 - $downloadProgress;
4054
	if($lastseen <> $downloadProgress and $downloadProgress < 101) {
4055
		if($sendto == "status") {
4056
			$tostatus = $static_status . $downloadProgress . "%";
4057
			update_status($tostatus);
4058
		} else {
4059
			$tooutput = $static_output . $downloadProgress . "%";
4060
			update_output_window($tooutput);
4061
		}
4062
		update_progress_bar($downloadProgress);
4063
		$lastseen = $downloadProgress;
4064
	}
4065
	if($fout)
4066
		fwrite($fout, $string);
4067
	ob_flush();
4068
	return $length;
4069
}
4070

    
4071
?>
(21-21/37)