Project

General

Profile

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

    
36
/****f* pfsense-utils/have_natonetooneruleint_access
37
 * NAME
38
 *   have_natonetooneruleint_access
39
 * INPUTS
40
 *	 none
41
 * RESULT
42
 *   returns true if user has access to edit a specific firewall nat one to one interface
43
 ******/
44
function have_natonetooneruleint_access($if) {
45
	$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;
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
		$optcfg = array();
212
		generate_optcfg_array($optcfg);
213

    
214
		$curwanip = get_interface_ip();
215

    
216
		/* don't include disabled rules */
217
		if (isset($rule['disabled'])) {
218
			return "";
219
		}
220

    
221
		$pptpdcfg = $config['pptpd'];
222
		$pppoecfg = $config['pppoe'];
223

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

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

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

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

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

    
312
		/* if list */
313
        	$ifdescrs = get_configured_interface_list();
314

    
315
		for ($iif = 0; $iif < $nif; $iif++) {
316

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

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

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

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

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

    
404
			}
405

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

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

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

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

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

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

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

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

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

    
548
	tdr_get_next_ipfw_rule();
549

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

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

    
561
	return $line;
562

    
563
}
564

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
929
	if(stristr($interface,"lnc"))
930
		return;
931
	if(isset($config['system']['do_not_use_nic_microcode']))
932
		return;
933

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

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

    
947
	if(stristr($options, "txcsum") == true)
948
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
949
	if(stristr($options, "rxcsum") == true)
950
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
951
	if(stristr($options, "polling") == true)
952
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
953
	} else {
954
		mwexec("sysctl kern.polling.enable=0");
955
	}
956
	return;
957
}
958

    
959
/****f* pfsense-utils/is_alias_inuse
960
 * NAME
961
 *   checks to see if an alias is currently in use by a rule
962
 * INPUTS
963
 *
964
 * RESULT
965
 *   true or false
966
 * NOTES
967
 *
968
 ******/
969
function is_alias_inuse($alias) {
970
	global $g, $config;
971

    
972
	if($alias == "") return false;
973
	/* loop through firewall rules looking for alias in use */
974
	if(is_array($config['filter']['rule']))
975
		foreach($config['filter']['rule'] as $rule) {
976
			if($rule['source']['address'])
977
				if($rule['source']['address'] == $alias)
978
					return true;
979
			if($rule['destination']['address'])
980
				if($rule['destination']['address'] == $alias)
981
					return true;
982
		}
983
	/* loop through nat rules looking for alias in use */
984
	if(is_array($config['nat']['rule']))
985
		foreach($config['nat']['rule'] as $rule) {
986
			if($rule['target'] == $alias)
987
				return true;
988
			if($rule['external-address'] == $alias)
989
				return true;
990
		}
991
	return false;
992
}
993

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

    
1007
	if($schedule == "") return false;
1008
	/* loop through firewall rules looking for schedule in use */
1009
	if(is_array($config['filter']['rule']))
1010
		foreach($config['filter']['rule'] as $rule) {
1011
			if($rule['sched'] == $schedule)
1012
				return true;
1013
		}
1014
	return false;
1015
}
1016

    
1017
/****f* pfsense-utils/setup_polling_defaults
1018
 * NAME
1019
 *   sets up sysctls for pollingS
1020
 * INPUTS
1021
 *
1022
 * RESULT
1023
 *   null
1024
 * NOTES
1025
 *
1026
 ******/
1027
function setup_polling_defaults() {
1028
	global $g, $config;
1029
	if($config['system']['polling_each_burst'])
1030
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
1031
	if($config['system']['polling_burst_max'])
1032
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
1033
	if($config['system']['polling_user_frac'])
1034
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
1035
}
1036

    
1037
/****f* pfsense-utils/setup_polling
1038
 * NAME
1039
 *   sets up polling
1040
 * INPUTS
1041
 *
1042
 * RESULT
1043
 *   null
1044
 * NOTES
1045
 *
1046
 ******/
1047
function setup_polling() {
1048
	global $g, $config;
1049

    
1050
	setup_polling_defaults();
1051

    
1052
	if(isset($config['system']['polling']))
1053
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
1054
	else
1055
		$supported_ints = array();
1056

    
1057
	/* if list */
1058
        $iflist = get_configured_interface_list();
1059

    
1060
	foreach ($iflist as $ifent => $ifname) {
1061
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
1062
		if(!in_array($real_interface, $supported_ints)) {
1063
			continue;
1064
                }
1065
		if(isset($config['system']['polling'])) {
1066
			mwexec("/sbin/ifconfig {$real_interface} polling");
1067
		} else {
1068
			mwexec("/sbin/ifconfig {$real_interface} -polling");
1069
		}
1070
	}
1071
}
1072

    
1073
/****f* pfsense-utils/setup_microcode
1074
 * NAME
1075
 *   enumerates all interfaces and calls enable_hardware_offloading which
1076
 *   enables a NIC's supported hardware features.
1077
 * INPUTS
1078
 *
1079
 * RESULT
1080
 *   null
1081
 * NOTES
1082
 *   This function only supports the fxp driver's loadable microcode.
1083
 ******/
1084
function setup_microcode() {
1085

    
1086
	/* if list */
1087
        $ifdescrs = get_configured_interface_list();
1088

    
1089
	foreach($ifdescrs as $if)
1090
		enable_hardware_offloading($if);
1091
}
1092

    
1093
/****f* pfsense-utils/return_filename_as_array
1094
 * NAME
1095
 *   return_filename_as_array - Return a file's contents as an array.
1096
 * INPUTS
1097
 *   $filename	- string containing the path to the desired file.
1098
 *   $strip	- array of characters to strip - default is '#'.
1099
 * RESULT
1100
 *   $file	- array containing the file's contents.
1101
 * NOTES
1102
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
1103
 ******/
1104
function return_filename_as_array($filename, $strip = array('#')) {
1105
	if(file_exists($filename)) $file = file($filename);
1106
	if(is_array($file)) {
1107
		foreach($file as $line) $line = trim($line);
1108
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
1109
	}
1110
	return $file;
1111
}
1112

    
1113
/****f* pfsense-utils/file_put_contents
1114
 * NAME
1115
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
1116
 * RESULT
1117
 *   none
1118
 ******/
1119
if(!function_exists("file_put_contents")) {
1120
	function file_put_contents($filename, $data) {
1121
		$fd = fopen($filename,"w");
1122
		fwrite($fd, $data);
1123
		fclose($fd);
1124
	}
1125
}
1126

    
1127
/****f* pfsense-utils/get_carp_status
1128
 * NAME
1129
 *   get_carp_status - Return whether CARP is enabled or disabled.
1130
 * RESULT
1131
 *   boolean	- true if CARP is enabled, false if otherwise.
1132
 ******/
1133
function get_carp_status() {
1134
    /* grab the current status of carp */
1135
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
1136
    if(intval($status) == "0") return false;
1137
    return true;
1138
}
1139

    
1140
/****f* pfsense-utils/is_carp_defined
1141
 * NAME
1142
 *   is_carp_defined - Return whether CARP is detected in the kernel.
1143
 * RESULT
1144
 *   boolean	- true if CARP is detected, false otherwise.
1145
 ******/
1146
function is_carp_defined() {
1147
	/* is carp compiled into the kernel and userland? */
1148
	$command = "/sbin/sysctl -a | grep carp";
1149
	$fd = popen($command . " 2>&1 ", "r");
1150
	if(!$fd) {
1151
		log_error("Warning, could not execute command {$command}");
1152
		return 0;
1153
	}
1154
	while(!feof($fd)) {
1155
		$tmp .= fread($fd,49);
1156
	}
1157
	fclose($fd);
1158

    
1159
	if($tmp == "")
1160
		return false;
1161
	else
1162
		return true;
1163
}
1164

    
1165
/****f* pfsense-utils/get_interface_mtu
1166
 * NAME
1167
 *   get_interface_mtu - Return the mtu of an interface
1168
 * RESULT
1169
 *   $tmp	- Returns the mtu of an interface
1170
 ******/
1171
function get_interface_mtu($interface) {
1172
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f6`;
1173
	return $mtu;
1174
}
1175

    
1176
/****f* pfsense-utils/is_interface_wireless
1177
 * NAME
1178
 *   is_interface_wireless - Returns if an interface is wireless
1179
 * RESULT
1180
 *   $tmp	- Returns if an interface is wireless
1181
 ******/
1182
function is_interface_wireless($interface) {
1183
	global $config, $g;
1184
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
1185
	if(!is_array($config['interfaces'][$friendly]['wireless'])) {
1186
		if (preg_match($g['wireless_regex'], $interface)) {
1187
			$config['interfaces'][$friendly]['wireless'] = array();
1188
			return true;
1189
		}
1190
		unset($config['interfaces'][$friendly]['wireless']);
1191
		return false;
1192
	} else {
1193
		return true;
1194
	}
1195
}
1196

    
1197
/****f* pfsense-utils/find_number_of_created_carp_interfaces
1198
 * NAME
1199
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
1200
 * RESULT
1201
 *   $tmp	- Number of currently created CARP interfaces.
1202
 ******/
1203
function find_number_of_created_carp_interfaces($flush = false) {
1204
	global $carp_interface_count_cache;
1205

    
1206
	if (!isset($carp_interface_count_cache) or $flush) {
1207
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
1208
		$fd = popen($command . " 2>&1 ", "r");
1209
		if(!$fd) {
1210
			log_error("Warning, could not execute command {$command}");
1211
			return 0;
1212
		}
1213
		while(!feof($fd)) {
1214
			$tmp .= fread($fd,49);
1215
		}
1216
		fclose($fd);
1217
		$carp_interface_count_cache = intval($tmp);
1218
	}
1219
	return $carp_interface_count_cache;
1220
}
1221

    
1222
/****f* pfsense-utils/link_interface_to_bridge
1223
 * NAME
1224
 *   link_interface_to_bridge - Finds out a bridge group for an interface
1225
 * INPUTS
1226
 *   $ip
1227
 * RESULT
1228
 *   bridge[0-99]
1229
 ******/
1230
function link_interface_to_bridge($int) {
1231
	global $config;
1232
	
1233
	if (is_array($config['bridges']['bridged']))
1234
		foreach ($config['bridges']['bridged'] as $bridge) 
1235
			if(stristr($bridge['members'], "{$int}")) 
1236
				return "{$bridge['bridgeif']}";
1237
}
1238

    
1239
function link_interface_to_gre($interface) {
1240
        global $config;
1241

    
1242
        if (is_array($config['gres']['gre']))
1243
                foreach ($config['gres']['gre'] as $gre)
1244
                        if($gre['if'] == $interface)
1245
                                return "{$gre['greif']}";
1246
}
1247

    
1248
function link_interface_to_gif($interface) {
1249
        global $config;
1250

    
1251
        if (is_array($config['gifs']['gif']))
1252
                foreach ($config['gifs']['gif'] as $gif)
1253
                        if($gif['if'] == $interface)
1254
                                return "{$gif['gifif']}";
1255
}
1256

    
1257
function link_carp_interface_to_parent($interface) {
1258
	global $config;
1259
	if($interface == "") return;
1260

    
1261
	/* if list */
1262
        $ifdescrs = get_configured_interface_list();
1263

    
1264
	$carp_int = $interface;
1265
	$carp_ip = find_interface_ip($interface);
1266
	$carp_subnet = find_virtual_ip_netmask($carp_ip);
1267
	$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1268
	$carp_ints = "";
1269
	$num_carp_ints = find_number_of_created_carp_interfaces();
1270

    
1271
	foreach ($ifdescrs as $ifdescr => $ifname) {
1272
		if(interface_has_gateway($ifname)) {
1273
			$interfaceip = $config['interfaces'][$ifname]['ipaddr'];
1274
			$subnet_bits = $config['interfaces'][$ifname]['subnet'];
1275
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
1276
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}")) {
1277
				return $ifname;
1278
			}
1279
		}
1280
	}
1281
	return $carp_ints;
1282
}
1283

    
1284
/****f* pfsense-utils/link_ip_to_carp_interface
1285
 * NAME
1286
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
1287
 * INPUTS
1288
 *   $ip
1289
 * RESULT
1290
 *   $carp_ints
1291
 ******/
1292
function link_ip_to_carp_interface($ip) {
1293
	global $config;
1294
	if($ip == "") return;
1295

    
1296
	/* if list */
1297
        $ifdescrs = get_configured_interface_list();
1298

    
1299
	$ft = split("\.", $ip);
1300
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
1301

    
1302
	$carp_ints = "";
1303
	$num_carp_ints = find_number_of_created_carp_interfaces();
1304
	foreach ($ifdescrs as $ifdescr => $ifname) {
1305
		for($x=0; $x<$num_carp_ints; $x++) {
1306
			$carp_int = "carp{$x}";
1307
			$carp_ip = find_interface_ip($carp_int);
1308
			$carp_subnet = find_virtual_ip_netmask($carp_ip);
1309
			$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1310
			if(ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
1311
				if(!stristr($carp_ints, $carp_int))
1312
					$carp_ints .= " " . $carp_int;
1313
		}
1314
	}
1315
	return $carp_ints;
1316
}
1317

    
1318
/****f* pfsense-utils/find_virtual_ip_netmask
1319
 * NAME
1320
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
1321
 * INPUTS
1322
 *   $ip - ip address to locate subnet mask of
1323
 * RESULT
1324
 *   String containing the command's result.
1325
 * NOTES
1326
 *   This function returns the command's stdout and stderr.
1327
 ******/
1328
function find_virtual_ip_netmask($ip) {
1329
        global $config;
1330
        foreach($config['virtualip']['vip'] as $vip) {
1331
                if($ip == $vip['subnet'])
1332
                        return $vip['subnet_bits'];
1333
        }
1334
}
1335

    
1336
/****f* pfsense-utils/exec_command
1337
 * NAME
1338
 *   exec_command - Execute a command and return a string of the result.
1339
 * INPUTS
1340
 *   $command	- String of the command to be executed.
1341
 * RESULT
1342
 *   String containing the command's result.
1343
 * NOTES
1344
 *   This function returns the command's stdout and stderr.
1345
 ******/
1346
function exec_command($command) {
1347
	$output = array();
1348
	exec($command . ' 2>&1 ', $output);
1349
	return(implode("\n", $output));
1350
}
1351

    
1352
/****f* interfaces/is_jumbo_capable
1353
 * NAME
1354
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
1355
 * INPUTS
1356
 *   $int             - string containing interface name
1357
 * RESULT
1358
 *   boolean          - true or false
1359
 ******/
1360
function is_jumbo_capable($int) {
1361
	/* Per:
1362
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
1363
	 * Only the following drivers support large frames
1364
         *
1365
	 * 'de' chipset purposely left out of this list
1366
	 * requires defining BIG_PACKET in the
1367
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
1368
	 * kernel or module.  The hack works only for the 21041,
1369
	 * 21140, and 21140A chips.
1370
	 */
1371
	global $g;
1372

    
1373
	$capable = $g['vlan_long_frame'];
1374

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

    
1377
	if (in_array($int_family[0], $capable))
1378
		return true;
1379
	else
1380
		return false;
1381
}
1382

    
1383
/*
1384
 * Return the interface array
1385
 */
1386
function get_interface_arr($flush = false) {
1387
	global $interface_arr_cache;
1388

    
1389
	/* If the cache doesn't exist, build it */
1390
	if (!isset($interface_arr_cache) or $flush)
1391
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
1392

    
1393
	return $interface_arr_cache;
1394
}
1395

    
1396
/*
1397
 * does_interface_exist($interface): return true or false if a interface is
1398
 * detected.
1399
 */
1400
function does_interface_exist($interface) {
1401
	global $config;
1402

    
1403
	if(!$interface)
1404
		return false;
1405
		
1406
	$ints = get_interface_arr();
1407

    
1408
	if(stristr($ints, $interface) !== false)
1409
		return true;
1410
	else
1411
		return false;
1412
}
1413

    
1414
/*
1415
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
1416
 */
1417
function convert_ip_to_network_format($ip, $subnet) {
1418
	$ipsplit = split('[.]', $ip);
1419
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
1420
	return $string;
1421
}
1422

    
1423
/*
1424
 * find_interface_ip($interface): return the interface ip (first found)
1425
 */
1426
function find_interface_ip($interface, $flush = false) {
1427
	global $interface_ip_arr_cache;
1428
	
1429
	$interface = str_replace("\n", "", $interface);
1430
	if(does_interface_exist($interface) == false) 
1431
		return;
1432

    
1433
	/* Setup IP cache */
1434
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
1435
		$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");
1436
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
1437
	}
1438

    
1439
	return $interface_ip_arr_cache[$interface];
1440
}
1441

    
1442
function find_interface_subnet($interface, $flush = false) 
1443
{
1444
	global $interface_sn_arr_cache;
1445
	
1446
	$interface = str_replace("\n", "", $interface);
1447
	if (does_interface_exist($interface) == false)
1448
		return;
1449

    
1450
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
1451
		$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");
1452
		$interface_sn_arr_cache[$interface] = strlen(str_replace("0", "", base_convert(str_replace("\n", "", $interface_sn_arr_cache[$interface]),16, 2)));
1453
	}
1454

    
1455
	return $interface_sn_arr_cache[$interface];
1456
}
1457

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

    
1463
/*
1464
 * find_ip_interface($ip): return the interface where an ip is defined
1465
 */
1466
function find_ip_interface($ip) {
1467

    
1468
	/* if list */
1469
        $ifdescrs = get_configured_interface_list();
1470

    
1471
	foreach ($ifdescrs as $ifdescr => $ifname) {
1472
		$int = convert_friendly_interface_to_real_interface_name($ifname);
1473
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
1474
		if(stristr($ifconfig,$ip) <> false)
1475
			return $int;
1476
	}
1477
	return false;
1478
}
1479

    
1480
/*
1481
 *  filter_translate_type_to_real_interface($interface): 
1482
 *		returns the real hardware interface name for a friendly interface.  ie: wan
1483
 */
1484
function filter_translate_type_to_real_interface($interface) {
1485
	global $config;
1486
	if($config['interfaces'][$interface]['if'] <> "") {
1487
		return $config['interfaces'][$interface]['if'];
1488
	} else {
1489
		return $interface;
1490
	}
1491
}
1492

    
1493
/*
1494
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
1495
 */
1496
function get_carp_interface_status($carpinterface) {
1497
	/* basically cache the contents of ifconfig statement
1498
	to speed up this routine */
1499
	global $carp_query;
1500
	if($carp_query == "")
1501
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
1502
	$found_interface = 0;
1503
	foreach($carp_query as $int) {
1504
		if($found_interface == 1) {
1505
			if(stristr($int, "MASTER")) return "MASTER";
1506
			if(stristr($int, "BACKUP")) return "BACKUP";
1507
			if(stristr($int, "INIT")) return "INIT";
1508
			return false;
1509
		}
1510
		if(stristr($int, $carpinterface) == true)
1511
		$found_interface=1;
1512
	}
1513
	return;
1514
}
1515

    
1516
/*
1517
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
1518
 */
1519
function get_pfsync_interface_status($pfsyncinterface) {
1520
    $result = does_interface_exist($pfsyncinterface);
1521
    if($result <> true) return;
1522
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
1523
    return $status;
1524
}
1525

    
1526
/*
1527
 * find_carp_interface($ip): return the carp interface where an ip is defined
1528
 */
1529
function find_carp_interface($ip) {
1530
	global $find_carp_ifconfig;
1531
	if($find_carp_ifconfig == "") {
1532
		$find_carp_ifconfig = array();
1533
		$num_carp_ints = find_number_of_created_carp_interfaces();
1534
		for($x=0; $x<$num_carp_ints; $x++) {
1535
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
1536
		}
1537
	}
1538
	$carps = 0;
1539
	foreach($find_carp_ifconfig as $fci) {
1540
		if(stristr($fci, $ip) == true)
1541
			return "carp{$carps}";
1542
		$carps++;
1543
	}
1544
}
1545

    
1546
/*
1547
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
1548
 */
1549
function add_rule_to_anchor($anchor, $rule, $label) {
1550
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
1551
}
1552

    
1553
/*
1554
 * remove_text_from_file
1555
 * remove $text from file $file
1556
 */
1557
function remove_text_from_file($file, $text) {
1558
	global $fd_log;
1559
	if($fd_log)
1560
		fwrite($fd_log, "Adding needed text items:\n");
1561
	$filecontents = file_get_contents($file);
1562
	$textTMP = str_replace($text, "", $filecontents);
1563
	$text = $textTMP;
1564
	if($fd_log)
1565
		fwrite($fd_log, $text);
1566
	$fd = fopen($file, "w");
1567
	fwrite($fd, $text);
1568
	fclose($fd);
1569
}
1570

    
1571
/*
1572
 * add_text_to_file($file, $text): adds $text to $file.
1573
 * replaces the text if it already exists.
1574
 */
1575
function add_text_to_file($file, $text, $replace = false) {
1576
	if(file_exists($file) and is_writable($file)) {
1577
		$filecontents = file($file);
1578
		$fout = fopen($file, "w");
1579

    
1580
		$filecontents = array_map('rtrim', $filecontents);
1581
		array_push($filecontents, $text);
1582
		if ($replace)
1583
			$filecontents = array_unique($filecontents);
1584

    
1585
		$file_text = implode("\n", $filecontents);
1586

    
1587
		fwrite($fout, $file_text);
1588
		fclose($fout);
1589
		return true;
1590
	} else {
1591
		return false;
1592
	}
1593
}
1594

    
1595
/*
1596
 *   after_sync_bump_adv_skew(): create skew values by 1S
1597
 */
1598
function after_sync_bump_adv_skew() {
1599
	global $config, $g;
1600
	$processed_skew = 1;
1601
	$a_vip = &$config['virtualip']['vip'];
1602
	foreach ($a_vip as $vipent) {
1603
		if($vipent['advskew'] <> "") {
1604
			$processed_skew = 1;
1605
			$vipent['advskew'] = $vipent['advskew']+1;
1606
		}
1607
	}
1608
	if($processed_skew == 1)
1609
		write_config("After synch increase advertising skew");
1610
}
1611

    
1612
/*
1613
 * get_filename_from_url($url): converts a url to its filename.
1614
 */
1615
function get_filename_from_url($url) {
1616
	return basename($url);
1617
}
1618

    
1619
/*
1620
 *   update_output_window: update bottom textarea dynamically.
1621
 */
1622
function update_output_window($text) {
1623
	global $pkg_interface;
1624
	$log = ereg_replace("\n", "\\n", $text);
1625
	if($pkg_interface == "console") {
1626
		/* too chatty */
1627
	} else {
1628
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1629
	}
1630
	/* ensure that contents are written out */
1631
	ob_flush();
1632
}
1633

    
1634
/*
1635
 *   get_dir: return an array of $dir
1636
 */
1637
function get_dir($dir) {
1638
	$dir_array = array();
1639
	$d = dir($dir);
1640
	while (false !== ($entry = $d->read())) {
1641
		array_push($dir_array, $entry);
1642
	}
1643
	$d->close();
1644
	return $dir_array;
1645
}
1646

    
1647
/*
1648
 *   update_output_window: update top textarea dynamically.
1649
 */
1650
function update_status($status) {
1651
	global $pkg_interface;
1652
	if($pkg_interface == "console") {
1653
		echo $status . "\n";
1654
	} else {
1655
		echo "\n<script type=\"text/javascript\">document.forms[0].status.value=\"" . $status . "\";</script>";
1656
	}
1657
	/* ensure that contents are written out */
1658
	ob_flush();
1659
}
1660

    
1661
/*
1662
 *   exec_command_and_return_text_array: execute command and return output
1663
 */
1664
function exec_command_and_return_text_array($command) {
1665
	$fd = popen($command . " 2>&1 ", "r");
1666
	while(!feof($fd)) {
1667
		$tmp .= fread($fd,49);
1668
	}
1669
	fclose($fd);
1670
	$temp_array = split("\n", $tmp);
1671
	return $temp_array;
1672
}
1673

    
1674
/*
1675
 *   exec_command_and_return_text: execute command and return output
1676
 */
1677
function exec_command_and_return_text($command) {
1678
	return exec_command($command);
1679
}
1680

    
1681
/*
1682
 *   exec_command_and_return_output: execute command and update output window dynamically
1683
 */
1684
function execute_command_return_output($command) {
1685
	global $fd_log, $pkg_interface;
1686
	$fd = popen($command . " 2>&1 ", "r");
1687
	if($pkg_interface <> "console") {
1688
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1689
	}
1690
	$counter = 0;
1691
	$counter2 = 0;
1692
	while(!feof($fd)) {
1693
		$tmp = fread($fd, 50);
1694
		$tmp1 = ereg_replace("\n","\\n", $tmp);
1695
		$text = ereg_replace("\"","'", $tmp1);
1696
		$lasttext = "";
1697
		if($lasttext == "..") {
1698
			$text = "";
1699
			$lasttext = "";
1700
			$counter=$counter-2;
1701
		} else {
1702
			$lasttext .= $text;
1703
		}
1704
		if($counter > 51) {
1705
			$counter = 0;
1706
			$extrabreak = "\\n";
1707
		} else {
1708
	    $extrabreak = "";
1709
	    $counter++;
1710
		}
1711
		if($counter2 > 600) {
1712
			if($pkg_interface <> "console") {
1713
				echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
1714
			}
1715
			$counter2 = 0;
1716
		} else
1717
			$counter2++;
1718
		if($pkg_interface <> "console") {
1719
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
1720
		}
1721
	}
1722
	fclose($fd);
1723
}
1724

    
1725
/*
1726
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
1727
 */
1728
function convert_friendly_interface_to_real_interface_name($interface) {
1729
	global $config;
1730

    
1731
	$wanif = $interface;
1732
	switch ($interface) {
1733
		case "pptp":
1734
			$wanif = "pptp";
1735
			break;
1736
		case "pppoe":
1737
			$wanif = "pppoe";
1738
			break;
1739
		case "openvpn":
1740
			$wanif = "openvpn";
1741
			break;
1742
		case "enc0":
1743
			$wanif = "enc0";
1744
			break;
1745
		/* XXX: dial in support?!
1746
		case "ppp":
1747
			$wanif = "ppp";
1748
			break;
1749
		*/
1750
		default:
1751
			$iflist = get_configured_interface_with_descr(false,true);
1752

    
1753
		foreach ($iflist as $if => $ifdesc) {
1754
			if ($interface == $if || $interface == $ifdesc) {
1755

    
1756
			$cfg = $config['interfaces'][$if];
1757

    
1758
			switch ($cfg['ipaddr']) {
1759
			case "carpdev-dhcp":
1760
				$viparr = &$config['virtualip']['vip'];
1761
				$counter = 0;
1762
				if(is_array($viparr))
1763
				foreach ($viparr as $vip) {
1764
					if ($vip['mode'] == "carpdev-dhcp") {
1765
						if($vip['interface'] == $if) {
1766
							$wanif =  "carp{$counter}";
1767
							break;
1768
						}
1769
						$counter++;
1770
					} else if ($vip['mode'] = "carp") 
1771
						$counter++;
1772
				}
1773
				break;
1774
			case "pppoe": 
1775
				if ($if == "wan")
1776
					$wanif = "pppoe0";
1777
				else
1778
					$wanif = "pppoe" . substr($if,3);
1779
				break;
1780
			case "pptp": 
1781
				if ($if == "wan")
1782
					$wanif = "pptp0";
1783
				else
1784
					$wanif = "pptp" . substr($if, 3);
1785
				break;
1786
			default:
1787
				if (isset($cfg['ispointtopoint']) && $cfg['pointtopoint'])
1788
					$wanif = "ppp0"; // XXX: PPP needs to convert to mpd
1789
				else	
1790
					$wanif = $cfg['if'];
1791
				break;
1792
			}
1793
			break;
1794

    
1795
			break;
1796
			}
1797
		}
1798
		break;
1799
	}
1800

    
1801
    return $wanif;
1802
}
1803

    
1804
/*
1805
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
1806
 */
1807
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
1808
	global $config;
1809
	
1810
	if (stristr($interface, "pppoe")) {
1811
		$index = substr($interface, 5);
1812
		if (intval($index) > 0)
1813
			return "opt{$index}";
1814
		else
1815
			return "wan";
1816
	} else if (stristr($interface, "pptp")) {
1817
		$index = substr($interface, 4);
1818
                if (intval($index) > 0)
1819
                        return "opt{$index}";
1820
                else
1821
                        return "wan";	
1822
	} else if (stristr($interface, "carp")) {
1823
		$index = substr($interface, 4);
1824
		$counter = 0;
1825
		foreach ($config['virtualip']['vip'] as $vip) {
1826
			if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
1827
				if (intval($index) == $counter)
1828
					return $vip['interface'];
1829
				$counter++;
1830
			}
1831
		}
1832
	}
1833
		
1834
	/* if list */
1835
        $ifdescrs = get_configured_interface_list(false, true);
1836

    
1837
	foreach ($ifdescrs as $if => $ifname) {
1838
		if($config['interfaces'][$if]['if'] == $interface)
1839
			return $ifname;
1840

    
1841
		/* XXX: ermal - The 3 lines below are totally bogus code. */
1842
		$int = filter_translate_type_to_real_interface($if);
1843
		if($ifname == $interface) 
1844
			return $ifname;
1845

    
1846
		if($int == $interface) 
1847
			return $ifname;
1848
	}
1849
	return NULL;
1850
}
1851

    
1852
/* attempt to resolve interface to friendly descr */
1853
function convert_friendly_interface_to_friendly_descr($interface) {
1854
        global $config;
1855

    
1856
        switch ($interface) {
1857
        	case "pptp":
1858
				$ifdesc = "PPTP";
1859
				break;
1860
       		case "pppoe":
1861
				$ifdesc = "PPPoE";
1862
				break;
1863
        	case "openvpn":
1864
				$ifdesc = "OpenVPN";
1865
				break;
1866
        	case "enc0":
1867
			case "ipsec":
1868
				$ifdesc = "IPsec";
1869
				break;
1870
        default:
1871
        	/* if list */
1872
        	$ifdescrs = get_configured_interface_with_descr(false, true);
1873
        	foreach ($ifdescrs as $if => $ifname) {
1874
				if ($if == $interface || $ifname == $interface)
1875
					return $ifname;
1876
        	}
1877
		break;
1878
	}
1879

    
1880
        return $ifdesc;
1881
}
1882

    
1883
function convert_real_interface_to_friendly_descr($interface) {
1884
        global $config;
1885

    
1886
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
1887

    
1888
	if ($ifdesc) {
1889
		$iflist = get_configured_interface_with_descr();
1890
		return $iflist[$ifdesc];
1891
	}
1892
	
1893
        return $interface;
1894
}
1895

    
1896
/*
1897
 * update_progress_bar($percent): updates the javascript driven progress bar.
1898
 */
1899
function update_progress_bar($percent) {
1900
	global $pkg_interface;
1901
	if($percent > 100) $percent = 1;
1902
	if($pkg_interface <> "console") {
1903
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1904
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1905
		echo "\n</script>";
1906
	} else {
1907
		echo " {$percent}%";
1908
	}
1909
}
1910

    
1911
/****f* pfsense-utils/WakeOnLan
1912
 * NAME
1913
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
1914
 * RESULT
1915
 *   true/false - true if the operation was successful
1916
 ******/
1917
function WakeOnLan($addr, $mac)
1918
{
1919
	$addr_byte = explode(':', $mac);
1920
	$hw_addr = '';
1921

    
1922
	for ($a=0; $a < 6; $a++)
1923
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1924

    
1925
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1926

    
1927
	for ($a = 1; $a <= 16; $a++)
1928
		$msg .= $hw_addr;
1929

    
1930
	// send it to the broadcast address using UDP
1931
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1932
	if ($s == false) {
1933
		log_error("Error creating socket!");
1934
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
1935
	} else {
1936
		// setting a broadcast option to socket:
1937
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1938
		if($opt_ret < 0)
1939
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1940
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1941
		socket_close($s);
1942
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1943
		return true;
1944
	}
1945

    
1946
	return false;
1947
}
1948

    
1949
/*
1950
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
1951
 *                             is queuename|qlength|measured_packets
1952
 *                             NOTE: this command takes 5 seconds to run
1953
 */
1954
function gather_altq_queue_stats($dont_return_root_queues) {
1955
	$stats = exec("/sbin/pfctl -vvsq");
1956
	$stats_array = split("\n", $stats);
1957
	$queue_stats = array();
1958
	foreach ($stats_array as $stats_line) {
1959
		$match_array = "";
1960
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
1961
			$queue_name = $match_array[1][0];
1962
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
1963
			$speed = $match_array[1][0];
1964
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
1965
			$borrows = $match_array[1][0];
1966
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
1967
			$suspends = $match_array[1][0];
1968
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
1969
			$drops = $match_array[1][0];
1970
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
1971
			$measured = $match_array[1][0];
1972
			if($dont_return_root_queues == true)
1973
				if(stristr($queue_name,"root_") == false)
1974
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
1975
		}
1976
	}
1977
	return $queue_stats;
1978
}
1979

    
1980
/*
1981
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1982
 *					 Useful for finding paths and stripping file extensions.
1983
 */
1984
function reverse_strrchr($haystack, $needle) {
1985
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1986
}
1987

    
1988
/*
1989
 *  backup_config_section($section): returns as an xml file string of
1990
 *                                   the configuration section
1991
 */
1992
function backup_config_section($section) {
1993
	global $config;
1994
	$new_section = &$config[$section];
1995
	/* generate configuration XML */
1996
	$xmlconfig = dump_xml_config($new_section, $section);
1997
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1998
	return $xmlconfig;
1999
}
2000

    
2001
/*
2002
 *  backup_vip_config_section($section): returns as an xml file string of
2003
 *                                   the configuration section
2004
 */
2005
function backup_vip_config_section() {
2006
	global $config;
2007
	$new_section = &$config['virtualip'];
2008
	foreach($new_section['vip'] as $section) {
2009
		if($section['mode'] == "proxyarp") {
2010
			unset($section);
2011
		}
2012
		if($section['advskew'] <> "") {
2013
			$section_val = intval($section['advskew']);
2014
			$section_val=$section_val+100;
2015
			if($section_val > 255)
2016
				$section_val = 255;
2017
			$section['advskew'] = $section_val;
2018
		}
2019
		$temp['vip'][] = $section;
2020
   }
2021
   return $temp;
2022
}
2023

    
2024
/*
2025
 *  restore_config_section($section, new_contents): restore a configuration section,
2026
 *                                                  and write the configuration out
2027
 *                                                  to disk/cf.
2028
 */
2029
function restore_config_section($section, $new_contents) {
2030
	global $config, $g;
2031
	conf_mount_rw();
2032
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
2033
	fwrite($fout, $new_contents);
2034
	fclose($fout);
2035
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
2036
	$config[$section] = &$section_xml;
2037
	unlink($g['tmp_path'] . "/tmpxml");
2038
	write_config("Restored {$section} of config file (maybe from CARP partner)");
2039
	conf_mount_ro();
2040
	return;
2041
}
2042

    
2043
/*
2044
 *  merge_config_section($section, new_contents):   restore a configuration section,
2045
 *                                                  and write the configuration out
2046
 *                                                  to disk/cf.  But preserve the prior
2047
 * 													structure if needed
2048
 */
2049
function merge_config_section($section, $new_contents) {
2050
	global $config;
2051
	conf_mount_rw();
2052
	$fname = get_tmp_filename();
2053
	$fout = fopen($fname, "w");
2054
	fwrite($fout, $new_contents);
2055
	fclose($fout);
2056
	$section_xml = parse_xml_config($fname, $section);
2057
	$config[$section] = $section_xml;
2058
	unlink($fname);
2059
	write_config("Restored {$section} of config file (maybe from CARP partner)");
2060
	conf_mount_ro();
2061
	return;
2062
}
2063

    
2064
/*
2065
 * http_post($server, $port, $url, $vars): does an http post to a web server
2066
 *                                         posting the vars array.
2067
 * written by nf@bigpond.net.au
2068
 */
2069
function http_post($server, $port, $url, $vars) {
2070
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
2071
	$urlencoded = "";
2072
	while (list($key,$value) = each($vars))
2073
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
2074
	$urlencoded = substr($urlencoded,0,-1);
2075
	$content_length = strlen($urlencoded);
2076
	$headers = "POST $url HTTP/1.1
2077
Accept: */*
2078
Accept-Language: en-au
2079
Content-Type: application/x-www-form-urlencoded
2080
User-Agent: $user_agent
2081
Host: $server
2082
Connection: Keep-Alive
2083
Cache-Control: no-cache
2084
Content-Length: $content_length
2085

    
2086
";
2087

    
2088
	$errno = "";
2089
	$errstr = "";
2090
	$fp = fsockopen($server, $port, $errno, $errstr);
2091
	if (!$fp) {
2092
		return false;
2093
	}
2094

    
2095
	fputs($fp, $headers);
2096
	fputs($fp, $urlencoded);
2097

    
2098
	$ret = "";
2099
	while (!feof($fp))
2100
		$ret.= fgets($fp, 1024);
2101
	fclose($fp);
2102

    
2103
	return $ret;
2104
}
2105

    
2106
/*
2107
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
2108
 */
2109
if (!function_exists('php_check_syntax')){
2110
	function php_check_syntax($code_to_check, &$errormessage){
2111
		return false;
2112
		$fout = fopen("/tmp/codetocheck.php","w");
2113
		$code = $_POST['content'];
2114
		$code = str_replace("<?php", "", $code);
2115
		$code = str_replace("?>", "", $code);
2116
		fwrite($fout, "<?php\n\n");
2117
		fwrite($fout, $code_to_check);
2118
		fwrite($fout, "\n\n?>\n");
2119
		fclose($fout);
2120
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
2121
		$output = exec_command($command);
2122
		if (stristr($output, "Errors parsing") == false) {
2123
			echo "false\n";
2124
			$errormessage = '';
2125
			return(false);
2126
		} else {
2127
			$errormessage = $output;
2128
			return(true);
2129
		}
2130
	}
2131
}
2132

    
2133
/*
2134
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
2135
 */
2136
if (!function_exists('php_check_syntax')){
2137
	function php_check_syntax($code_to_check, &$errormessage){
2138
		return false;
2139
		$command = "/usr/local/bin/php -l " . $code_to_check;
2140
		$output = exec_command($command);
2141
		if (stristr($output, "Errors parsing") == false) {
2142
			echo "false\n";
2143
			$errormessage = '';
2144
			return(false);
2145
		} else {
2146
			$errormessage = $output;
2147
			return(true);
2148
		}
2149
	}
2150
}
2151

    
2152
/*
2153
 * rmdir_recursive($path,$follow_links=false)
2154
 * Recursively remove a directory tree (rm -rf path)
2155
 * This is for directories _only_
2156
 */
2157
function rmdir_recursive($path,$follow_links=false) {
2158
	$to_do = glob($path);
2159
	if(!is_array($to_do)) $to_do = array($to_do);
2160
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
2161
		if(file_exists($workingdir)) {
2162
			if(is_dir($workingdir)) {
2163
				$dir = opendir($workingdir);
2164
				while ($entry = readdir($dir)) {
2165
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
2166
						unlink("$workingdir/$entry");
2167
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
2168
						rmdir_recursive("$workingdir/$entry");
2169
				}
2170
				closedir($dir);
2171
				rmdir($workingdir);
2172
			} elseif (is_file($workingdir)) {
2173
				unlink($workingdir);
2174
			}
2175
               	}
2176
	}
2177
	return;
2178
}
2179

    
2180
/*
2181
 *     get_memory()
2182
 *     returns an array listing the amount of
2183
 *     memory installed in the hardware
2184
 *     [0]real and [1]available
2185
 */
2186
function get_memory() {
2187
	if(file_exists("/var/log/dmesg.boot")) {
2188
		$mem = `cat /var/log/dmesg.boot | grep memory`;
2189
		$matches = "";
2190
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2191
			$real = $matches[1];
2192
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2193
			$avail = $matches[1];
2194
		return array($real[0],$avail[0]);
2195
	} else {
2196
		$mem = `dmesg -a`;
2197
		$matches = "";
2198
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2199
			$real = $matches[1];
2200
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2201
			$avail = $matches[1];
2202
		return array($real[0],$avail[0]);
2203
	}
2204
}
2205

    
2206
/*
2207
 *    safe_mkdir($path, $mode = 0755)
2208
 *    create directory if it doesn't already exist and isn't a file!
2209
 */
2210
function safe_mkdir($path, $mode=0755) {
2211
	global $g;
2212

    
2213
	if (!is_file($path) && !is_dir($path)) {
2214
		return @mkdir($path, $mode);
2215
	} else {
2216
		return false;
2217
	}
2218
}
2219

    
2220
/*
2221
 * make_dirs($path, $mode = 0755)
2222
 * create directory tree recursively (mkdir -p)
2223
 */
2224
function make_dirs($path, $mode = 0755) {
2225
	$base = '';
2226
	foreach (explode('/', $path) as $dir) {
2227
		$base .= "/$dir";
2228
		if (!is_dir($base)) {
2229
			if (!@mkdir($base, $mode))
2230
				return false;
2231
		}
2232
	}
2233
	return true;
2234
}
2235

    
2236
/*
2237
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
2238
 */
2239
function call_pfsense_method($method, $params, $timeout = 0) {
2240
	global $g, $config;
2241

    
2242
	$ip = gethostbyname($g['product_website']);
2243
	if($ip == $g['product_website'])
2244
		return false;
2245
	global $g, $config;
2246
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
2247
	$xmlrpc_path = $g['xmlrpcpath'];
2248
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
2249
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
2250
	$resp = $cli->send($msg, $timeout);
2251
	if(!$resp) {
2252
		log_error("XMLRPC communication error: " . $cli->errstr);
2253
		return false;
2254
	} elseif($resp->faultCode()) {
2255
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
2256
		return false;
2257
	} else {
2258
		return XML_RPC_Decode($resp->value());
2259
	}
2260
}
2261

    
2262
/*
2263
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
2264
 */
2265
function check_firmware_version($tocheck = "all", $return_php = true) {
2266
	global $g, $config;
2267
	$ip = gethostbyname($g['product_website']);
2268
	if($ip == $g['product_website'])
2269
		return false;
2270
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
2271
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
2272
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
2273
		"platform" => trim(file_get_contents('/etc/platform'))
2274
		);
2275
	if($tocheck == "all") {
2276
		$params = $rawparams;
2277
	} else {
2278
		foreach($tocheck as $check) {
2279
			$params['check'] = $rawparams['check'];
2280
			$params['platform'] = $rawparams['platform'];
2281
		}
2282
	}
2283
	if($config['system']['firmware']['branch']) {
2284
		$params['branch'] = $config['system']['firmware']['branch'];
2285
	}
2286
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
2287
		return false;
2288
	} else {
2289
		$versions["current"] = $params;
2290
	}
2291
	return $versions;
2292
}
2293

    
2294
function get_disk_info() {
2295
	$diskout = "";
2296
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
2297
	return explode(' ', $diskout[0]);
2298
	// $size, $used, $avail, $cap
2299
}
2300

    
2301
function run_plugins($directory) {
2302
	global $config, $g;
2303
	/* process packager manager custom rules */
2304
	$files = return_dir_as_array($directory);
2305
	if($files <> "") {
2306
		foreach ($files as $file) {
2307
			if($file) {
2308
				$text = file_get_contents($directory . $file);
2309
				if($text) {
2310
					if(stristr($file, ".sh") == true) {
2311
						mwexec($directory . $file . " start");
2312
					} else {
2313
						if(!stristr($file,"CVS")) {
2314
							if($g['booting'] == true)
2315
								echo "\t{$file}... ";
2316
							require_once($directory . $file);
2317
						}
2318
					}
2319
				}
2320
			}
2321
		}
2322
	}	
2323
}
2324

    
2325
/****f* pfsense-utils/display_top_tabs
2326
 * NAME
2327
 *   display_top_tabs - display tabs with rounded edges
2328
 * INPUTS
2329
 *   $text      - array of tabs
2330
 * RESULT
2331
 *   null
2332
 ******/
2333
function display_top_tabs(& $tab_array) {
2334
	global $HTTP_SERVER_VARS;
2335
	global $config;
2336
	global $g;
2337

    
2338
	/*  does the user have access to this tab?
2339
	 *  master user has access to everything.
2340
	 *  if the user does not have access, simply
2341
	 *  unset the tab item.
2342
	 */
2343

    
2344
	$tab_temp = array ();
2345
	foreach ($tab_array as $ta)
2346
		if(isAllowedPage($ta[2]))
2347
			$tab_temp[] = $ta;
2348
	/*
2349
		// FIXME :	if the checks are not good enough
2350
		//			in isAllowedPage, it needs to be
2351
		//			fixed instead of kludging here
2352

    
2353
		// TODO: humm what shall we do with pkg_edit.php and pkg.php?
2354
		if ((strpos($link, "pkg.php")) !== false || (strpos($link, "pkg_edit.php")) !== false) {
2355
			$pos_equal = strpos($link, "=");
2356
			$pos_xmlsuffix = strpos($link, ".xml");
2357
			// do we match an absolute url including ?xml= foo
2358
			if(!isAllowedPage($link, $allowed))
2359
				$link = substr($link, $pos_equal +1, ($pos_xmlsuffix - $pos_equal +3));
2360
		}
2361
		// next check - what if the basename contains a query string?
2362
		if ((strpos($link, "?")) !== false) {
2363
			$pos_qmark = strpos($link, "?");
2364
			$link = substr($link, 0, $pos_qmark);
2365
		}
2366
		$authorized_text = print_r($allowed, true);
2367
		if(is_array($authorized))
2368
			if (in_array(basename($link), $authorized))
2369
	*/
2370

    
2371
	unset ($tab_array);
2372
	$tab_array = & $tab_temp;
2373

    
2374
	$tab_active_bg   = "#EEEEEE";
2375
	$tab_inactive_bg = "#777777";
2376
	$nifty_tabs_corners = "#FFF";
2377
	$font_color = "white";
2378
	
2379
	/* if tabcontrols.php exist for a theme, allow it to be overriden */
2380
	$themename = $config['theme'];
2381
	$filename = "/usr/local/www/themes/{$themename}/tabcontrols.php";
2382
	if(file_exists($filename)) {
2383
		$eval_code = file_get_contents($filename);
2384
		eval($eval_code);
2385
	}
2386
	
2387
	echo "<table cellpadding='0' cellspacing='0'>\n";
2388
	echo " <tr>\n";
2389
	$tabscounter = 0;
2390
	foreach ($tab_array as $ta) {
2391
		if ($ta[1] == true) {
2392
			echo "  <td bgcolor='{$tab_active_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
2393
		} else {
2394
			echo "  <td bgcolor='{$tab_inactive_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
2395
		}
2396
		$tabscounter++;
2397
	}
2398
	echo "</tr>\n<tr>\n";
2399
	foreach ($tab_array as $ta) {
2400
		if ($ta[1] == true) {
2401
			echo "  <td height=\"15\" valign=\"middle\" bgcolor='{$tab_active_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
2402
			echo "&nbsp;&nbsp;&nbsp;";
2403
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2404
		} else {
2405
			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]}'>";
2406
			echo "<font color='{$font_color}'>{$ta[0]}</font></a>&nbsp;&nbsp;&nbsp;";
2407
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2408
		}
2409
	}
2410
	echo "</tr>\n<tr>\n";
2411
	foreach ($tab_array as $ta) {
2412
		if ($ta[1] == true) {
2413
			echo "  <td bgcolor='{$tab_active_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2414
		} else {
2415
			echo "  <td bgcolor='{$tab_inactive_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2416
		}
2417
		$tabscounter++;
2418
	}
2419
	echo " </tr>\n";
2420
	echo "</table>\n";
2421

    
2422
	echo "<script type=\"text/javascript\">";
2423
	echo "NiftyCheck();\n";
2424
	echo "Rounded(\"div#tabactive\",\"top\",\"{$nifty_tabs_corners}\",\"{$tab_active_bg}\",\"smooth\");\n";
2425
	for ($x = 0; $x < $tabscounter; $x++)
2426
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"{$nifty_tabs_corners}\",\"{$tab_inactive_bg}\",\"smooth\");\n";
2427
	echo "</script>";
2428
}
2429

    
2430

    
2431
/****f* pfsense-utils/display_topbar
2432
 * NAME
2433
 *   display_topbar - top a table off with rounded edges
2434
 * INPUTS
2435
 *   $text	- (optional) Text to include in bar
2436
 * RESULT
2437
 *   null
2438
 ******/
2439
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
2440
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
2441
	echo "       <tr height='1'>\n";
2442
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
2443
	echo "		<div id='topbar'></div></td>\n";
2444
	echo "       </tr>\n";
2445
	echo "       <tr height='1'>\n";
2446
	if ($text != "")
2447
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
2448
	else
2449
		echo "         <td height='1' class='listtopic'></td>\n";
2450
	echo "       </tr>\n";
2451
	echo "     </table>";
2452
	echo "<script type=\"text/javascript\">";
2453
	echo "NiftyCheck();\n";
2454
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
2455
	echo "</script>";
2456
}
2457

    
2458
/****f* pfsense-utils/generate_random_mac_address
2459
 * NAME
2460
 *   generate_random_mac - generates a random mac address
2461
 * INPUTS
2462
 *   none
2463
 * RESULT
2464
 *   $mac - a random mac address
2465
 ******/
2466
function generate_random_mac_address() {
2467
	$mac = "02";
2468
	for($x=0; $x<5; $x++)
2469
		$mac .= ":" . dechex(rand(16, 255));
2470
	return $mac;
2471
}
2472

    
2473
/****f* pfsense-utils/strncpy
2474
 * NAME
2475
 *   strncpy - copy strings
2476
 * INPUTS
2477
 *   &$dst, $src, $length
2478
 * RESULT
2479
 *   none
2480
 ******/
2481
function strncpy(&$dst, $src, $length) {
2482
	if (strlen($src) > $length) {
2483
		$dst = substr($src, 0, $length);
2484
	} else {
2485
		$dst = $src;
2486
	}
2487
}
2488

    
2489
/****f* pfsense-utils/reload_interfaces_sync
2490
 * NAME
2491
 *   reload_interfaces - reload all interfaces
2492
 * INPUTS
2493
 *   none
2494
 * RESULT
2495
 *   none
2496
 ******/
2497
function reload_interfaces_sync() {
2498
	global $config, $g;
2499

    
2500
	$shutdown_webgui_needed = false;
2501

    
2502
	touch("{$g['tmp_path']}/reloading_all");
2503

    
2504
	if($g['debug'])
2505
		log_error("reload_interfaces_sync() is starting.");
2506

    
2507
	if(file_exists("{$g['tmp_path']}/config.cache"))
2508
		unlink("{$g['tmp_path']}/config.cache");
2509

    
2510
	/* parse config.xml again */
2511
	$config = parse_config(true);
2512

    
2513
	$wan_if = $config['interfaces']['wan']['if'];
2514
	if (isset($config['interfaces']['lan']))
2515
                $lan_if = $config['interfaces']['lan']['if'];
2516
        else
2517
                $lan_if = "";
2518

    
2519
	if($g['debug'])
2520
		log_error("Cleaning up Interfaces");
2521

    
2522
	/* if list */
2523
        $iflist = get_configured_interface_list(true);
2524

    
2525
	foreach ($iflist as $ifent => $ifname) {
2526
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2527

    
2528
		if(stristr($ifname, "lo0") == true)
2529
			continue;
2530
		/* do not process wan interface, its mandatory */
2531
                if(stristr($ifname, "$wan_if") == true)
2532
                        continue;
2533
                /* do not process lan interface, its mandatory */
2534
                if(stristr($ifname, "$lan_if") == true)
2535
                        continue;
2536
		if($g['debug'])
2537
			log_error("Downing and deleting $ifname_real - $ifname");
2538
		mwexec("/sbin/ifconfig {$ifname_real} down");
2539
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2540
	}
2541

    
2542
	/* set up interfaces */
2543
	interfaces_configure();
2544

    
2545
	/* set up static routes */
2546
	if($g['debug'])
2547
		log_error("Configuring system Routing");
2548
	system_routing_configure();
2549

    
2550
	/* enable routing */
2551
	if($g['debug'])
2552
		log_error("Enabling system routing");
2553
	system_routing_enable();
2554

    
2555
	/* setup captive portal if needed */
2556
	if($g['debug'])
2557
		log_error("Configuring Captive portal");
2558
	captiveportal_configure();
2559

    
2560
	/* restart webConfigurator if needed */
2561
	if($shutdown_webgui_needed == true)
2562
		touch("/tmp/restart_webgui");
2563

    
2564
	/* start devd back up */
2565
	mwexec("/bin/rm /tmp/reload*");
2566

    
2567
	/* remove reloading_all trigger */
2568
	if($g['debug'])
2569
		log_error("Removing {$g['tmp_path']}/reloading_all");
2570
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2571
}
2572

    
2573
/****f* pfsense-utils/reload_all
2574
 * NAME
2575
 *   reload_all - triggers a reload of all settings
2576
 *   * INPUTS
2577
 *   none
2578
 * RESULT
2579
 *   none
2580
 ******/
2581
function reload_all() {
2582
	touch("/tmp/reload_all");
2583
}
2584

    
2585
/****f* pfsense-utils/reload_interfaces
2586
 * NAME
2587
 *   reload_interfaces - triggers a reload of all interfaces
2588
 * INPUTS
2589
 *   none
2590
 * RESULT
2591
 *   none
2592
 ******/
2593
function reload_interfaces() {
2594
	touch("/tmp/reload_interfaces");
2595
}
2596

    
2597
/****f* pfsense-utils/reload_all_sync
2598
 * NAME
2599
 *   reload_all - reload all settings
2600
 *   * INPUTS
2601
 *   none
2602
 * RESULT
2603
 *   none
2604
 ******/
2605
function reload_all_sync() {
2606
	global $config, $g;
2607

    
2608
	$g['booting'] = false;
2609

    
2610
	touch("{$g['tmp_path']}/reloading_all");
2611

    
2612
	$shutdown_webgui_needed = false;
2613

    
2614
	if(file_exists("{$g['tmp_path']}/config.cache"))
2615
		unlink("{$g['tmp_path']}/config.cache");
2616

    
2617
	/* parse config.xml again */
2618
	$config = parse_config(true);
2619

    
2620
	/* set up our timezone */
2621
	system_timezone_configure();
2622

    
2623
	/* set up our hostname */
2624
	system_hostname_configure();
2625

    
2626
	/* make hosts file */
2627
	system_hosts_generate();
2628

    
2629
	/* generate resolv.conf */
2630
	system_resolvconf_generate();
2631

    
2632
	/* Set up our loopback interface */
2633
	interfaces_loopback_configure();
2634

    
2635
	$wan_if = $config['interfaces']['wan']['if'];
2636
	if (isset($config['interfaces']['lan']))
2637
		$lan_if = $config['interfaces']['lan']['if'];
2638
	else
2639
		$lan_if = "";
2640

    
2641
	/* if list */
2642
	$iflist = get_configured_interface_list();
2643

    
2644
	foreach ($iflist as $ifent => $ifname) {
2645
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2646
		if(stristr($ifname, "lo0") == true)
2647
			continue;
2648
		/* do not process wan interface, its mandatory */
2649
		if($wan_if == $ifname_real)
2650
			continue;
2651
		/* do not process lan interface, its mandatory */
2652
		if($lan_if == $ifname_real)
2653
			continue;
2654
		mwexec("/sbin/ifconfig {$ifname_real} down");
2655
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2656
	}
2657

    
2658
	/* set up interfaces */
2659
	interfaces_configure();
2660

    
2661
	/* set up static routes */
2662
	system_routing_configure();
2663

    
2664
	/* enable routing */
2665
	system_routing_enable();
2666

    
2667
	/* ensure passwords are sync'd */
2668
//	system_password_configure();
2669

    
2670
	/* start dnsmasq service */
2671
	services_dnsmasq_configure();
2672

    
2673
	/* start dyndns service */
2674
	services_dyndns_configure();
2675

    
2676
	/* start DHCP service */
2677
	services_dhcpd_configure();
2678

    
2679
	/* configure cron service */
2680
	configure_cron();
2681

    
2682
	/* start the NTP client */
2683
	system_ntp_configure();
2684

    
2685
	/* start ftp proxy helpers if they are enabled */
2686
	system_start_ftp_helpers();
2687

    
2688
	/* start the captive portal */
2689
	captiveportal_configure();
2690

    
2691
        /* reload the filter */
2692
	filter_configure_sync();
2693

    
2694
	/* sync pw database */
2695
	conf_mount_rw();
2696
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2697
	conf_mount_ro();
2698

    
2699
	/* restart sshd */
2700
	touch("/tmp/start_sshd");
2701

    
2702
	/* restart webConfigurator if needed */
2703
	if($shutdown_webgui_needed == true)
2704
		touch("/tmp/restart_webgui");
2705

    
2706
	mwexec("/bin/rm /tmp/reload*");
2707

    
2708
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2709

    
2710
}
2711

    
2712
function auto_login($status) {
2713
	$gettytab = file_get_contents("/etc/gettytab");
2714
	$getty_split = split("\n", $gettytab);
2715
	conf_mount_rw();
2716
	$fd = fopen("/etc/gettytab", "w");
2717
	foreach($getty_split as $gs) {
2718
		if(stristr($gs, ":ht:np:sp#115200") ) {
2719
			if($status == true) {
2720
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
2721
			} else {
2722
				fwrite($fd, "	:ht:np:sp#115200:\n");
2723
			}
2724
		} else {
2725
			fwrite($fd, "{$gs}\n");
2726
		}
2727
	}
2728
	fclose($fd);
2729
	conf_mount_ro();
2730
}
2731

    
2732
function setup_serial_port() {
2733
	global $g, $config;
2734
	conf_mount_rw();
2735
	/* serial console - write out /boot.config */
2736
	if(file_exists("/boot.config"))
2737
		$boot_config = file_get_contents("/boot.config");
2738
	else
2739
		$boot_config = "";
2740

    
2741
	if($g['platform'] <> "cdrom") {
2742
		$boot_config_split = split("\n", $boot_config);
2743
		$fd = fopen("/boot.config","w");
2744
		if($fd) {
2745
			foreach($boot_config_split as $bcs) {
2746
				if(stristr($bcs, "-D")) {
2747
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2748
				} else {
2749
					if($bcs <> "")
2750
						fwrite($fd, "{$bcs}\n");
2751
				}
2752
			}
2753
			if(isset($config['system']['enableserial'])) {
2754
				fwrite($fd, "-D");
2755
			}
2756
			fclose($fd);
2757
		}
2758
		/* serial console - write out /boot/loader.conf */
2759
		$boot_config = file_get_contents("/boot/loader.conf");
2760
		$boot_config_split = split("\n", $boot_config);
2761
		$fd = fopen("/boot/loader.conf","w");
2762
		if($fd) {
2763
			foreach($boot_config_split as $bcs) {
2764
				if(stristr($bcs, "console")) {
2765
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2766
				} else {
2767
					if($bcs <> "")
2768
						fwrite($fd, "{$bcs}\n");
2769
				}
2770
			}
2771
			if(isset($config['system']['enableserial'])) {
2772
				fwrite($fd, "console=\"comconsole\"\n");
2773
			}
2774
			fclose($fd);
2775
		}
2776
	}
2777
	$ttys = file_get_contents("/etc/ttys");
2778
	$ttys_split = split("\n", $ttys);
2779
	$fd = fopen("/etc/ttys", "w");
2780
	foreach($ttys_split as $tty) {
2781
		if(stristr($tty, "ttyd0")) {
2782
			if(isset($config['system']['enableserial'])) {
2783
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
2784
			} else {
2785
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
2786
			}
2787
		} else {
2788
			fwrite($fd, $tty . "\n");
2789
		}
2790
	}
2791
	fclose($fd);
2792
	if(isset($config['system']['disableconsolemenu'])) {
2793
		auto_login(false);
2794
	} else {
2795
		auto_login(true);
2796
	}
2797
	conf_mount_ro();
2798
	return;
2799
}
2800

    
2801
function print_value_list($list, $count = 10, $separator = ",") {
2802
	$list = implode($separator, array_slice($list, 0, $count));
2803
	if(count($list) < $count) {
2804
		$list .= ".";
2805
	} else {
2806
		$list .= "...";
2807
	}
2808
	return $list;
2809
}
2810

    
2811
function enable_rrd_graphing() {
2812
	global $config, $g, $altq_list_queues;
2813

    
2814
	if($g['booting']) 
2815
		echo "Generating RRD graphs...";
2816

    
2817
	$rrddbpath = "/var/db/rrd/";
2818
	$rrdgraphpath = "/usr/local/www/rrd";
2819

    
2820
	$traffic = "-traffic.rrd";
2821
	$packets = "-packets.rrd";
2822
	$states = "-states.rrd";
2823
	$quality = "-quality.rrd";
2824
	$wireless = "-wireless.rrd";
2825
	$queues = "-queues.rrd";
2826
	$queuesdrop = "-queuedrops.rrd";
2827
	$spamd = "-spamd.rrd";
2828
	$proc = "-processor.rrd";
2829
	$mem = "-memory.rrd";
2830

    
2831
	$rrdtool = "/usr/local/bin/rrdtool";
2832
	$netstat = "/usr/bin/netstat";
2833
	$awk = "/usr/bin/awk";
2834
	$tar = "/usr/bin/tar";
2835
	$pfctl = "/sbin/pfctl";
2836
	$sysctl = "/sbin/sysctl";
2837
	$php = "/usr/local/bin/php";
2838
	$top = "/usr/bin/top";
2839
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2840
	$ifconfig = "/sbin/ifconfig";
2841
	$pingcmd = "/sbin/ping";
2842

    
2843
	$rrdtrafficinterval = 60;
2844
	$rrdqualityinterval = 60;
2845
	$rrdwirelessinterval = 60;
2846
	$rrdqueuesinterval = 60;
2847
	$rrdqueuesdropinterval = 60;
2848
	$rrdpacketsinterval = 60;
2849
	$rrdstatesinterval = 60;
2850
	$rrdspamdinterval = 60;
2851
	$rrdlbpoolinterval = 60;
2852
	$rrdprocinterval = 60;
2853
	$rrdmeminterval = 60;
2854

    
2855
	$trafficvalid = $rrdtrafficinterval * 2;
2856
	$qualityvalid = $rrdqualityinterval * 2;
2857
	$wirelessvalid = $rrdwirelessinterval * 2;
2858
	$queuesvalid = $rrdqueuesinterval * 2;
2859
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2860
	$packetsvalid = $rrdpacketsinterval * 2;
2861
	$statesvalid = $rrdstatesinterval*2;
2862
	$spamdvalid = $rrdspamdinterval * 2;
2863
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2864
	$procvalid = $rrdlbpoolinterval * 2;
2865
	$memvalid = $rrdmeminterval * 2;
2866

    
2867
	/* Asume GigE for now */
2868
	$downstream = 125000000;
2869
	$upstream = 125000000;
2870

    
2871
	/* read the shaper config */
2872
	read_altq_config();
2873

    
2874
	$rrdrestore = "";
2875
	$rrdreturn = "";
2876

    
2877
	if (isset ($config['rrd']['enable'])) {
2878

    
2879
		/* create directory if needed */
2880
		if (!is_dir("$rrddbpath")) {
2881
			mkdir("$rrddbpath", 0755);
2882
		}
2883

    
2884
		if ($g['booting']) {
2885
			if ($g['platform'] != "pfSense") {
2886
				/* restore the databases, if we have one */
2887
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
2888
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2889
					if((int)$rrdrestore <> 0) {
2890
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
2891
					}
2892
				}
2893
			}
2894
		}
2895

    
2896
		/* db update script */
2897
		$rrdupdatesh = "#!/bin/sh\n";
2898
		$rrdupdatesh .= "\n";
2899
		$rrdupdatesh .= "counter=1\n";
2900
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2901
		$rrdupdatesh .= "do\n";
2902
		$rrdupdatesh .= "";
2903

    
2904
		$i = 0;
2905
		$vfaces = array (
2906
			"vlan.?*",
2907
			"enc.?*"
2908
		);
2909
		$ifdescrs = get_interface_list(true, true, $vfaces);
2910
		$ifdescrs['enc0']['friendly'] = "ipsec";
2911
		$ifdescrs['enc0']['descr'] = "IPsec";
2912
		$ifdescrs['enc0']['up'] = true;
2913

    
2914
		foreach ($ifdescrs as $realif => $ifdescr) {
2915
			$ifname = $ifdescr['friendly'];
2916
			$state = $ifdescr['up'];
2917

    
2918
			/* skip interfaces that do not have a friendly name */
2919
			if ("$ifname" == "") {
2920
				continue;
2921
			}
2922

    
2923
			/* or are down */
2924
			if (!$state) {
2925
				continue;
2926
			}
2927

    
2928
			/* TRAFFIC, set up the rrd file */
2929
			if (!file_exists("$rrddbpath$ifname$traffic")) {
2930
				/* create rrd file if it does not exist */
2931
				log_error("Create RRD database $rrddbpath$ifname$traffic");
2932
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
2933
				$rrdcreate .= "DS:in:COUNTER:$trafficvalid:0:$downstream ";
2934
				$rrdcreate .= "DS:out:COUNTER:$trafficvalid:0:$upstream ";
2935
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2936
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2937
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2938
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2939
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
2940

    
2941
				$rrdcreateoutput = array();
2942
				$rrdcreatereturn = "";
2943

    
2944
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2945
				if ($rrdcreatereturn != 0) {
2946
					log_error("RRD create failed exited with $rrdcreatereturn, the
2947
							error is: $rrdcreateoutput[0]\n");
2948
				}
2949
			}
2950

    
2951
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2952
			if($g['booting']) {
2953
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
2954
			}
2955

    
2956
			$rrdupdatesh .= "\n";
2957
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
2958
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
2959
			if(! is_macaddr(get_interface_mac($realif))) {
2960
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$6 \":\" \$9}'`\n";
2961
			} else {
2962
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7 \":\" \$10}'`\n";
2963
			}
2964

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

    
2978
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2979
				if ($rrdcreatereturn != 0) {
2980
					log_error("RRD create failed exited with $rrdcreatereturn, the
2981
							error is: $rrdcreateoutput[0]\n");
2982
				}
2983
			}
2984

    
2985
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2986
			if($g['booting']) {
2987
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
2988
			}
2989

    
2990
			$rrdupdatesh .= "\n";
2991
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
2992
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
2993
			if(! is_macaddr(get_interface_mac($realif))) {
2994
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$4 \":\" \$7}'`\n";
2995
			} else {
2996
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5 \":\" \$8}'`\n";
2997
			}
2998

    
2999
			/* QUALITY, create link quality database */
3000
			/* if the interface has a gateway defined, use it */
3001
			if(interface_has_gateway($ifname)) {
3002
				if (!file_exists("$rrddbpath$ifname$quality")) {
3003
					/* create rrd file if it does not exist */
3004
					log_error("Create RRD database $rrddbpath$ifname$quality");
3005
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
3006
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
3007
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
3008
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3009
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3010
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3011
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3012
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3013

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

    
3020
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3021
				if($g['booting']) {
3022
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
3023
				}
3024
				
3025
				$numpings = 5;
3026
				if(isset($config['interfaces'][$ifname]['gateway'])) {
3027
					$monitorip = lookup_gateway_monitor_ip_by_name($config['interfaces'][$ifname]['gateway']);
3028
				} else {
3029
					$monitorip = lookup_gateway_monitor_ip_by_name($ifname);
3030
				}
3031
				if(!is_ipaddr($monitorip)) {
3032
					$monitorip = get_interface_gateway($ifname);
3033
				}
3034
				if(!is_ipaddr($monitorip)) {
3035
					/* still no monitor IP, don't write a collector and pass the batton */
3036
					continue;
3037
				}
3038
				/* the ping test function. We call this on the last line */
3039
				$rrdupdatesh .= "# Quality collector for {$ifname}\n";
3040
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
3041
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
3042
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
3043
				$rrdupdatesh .= "	local out_{$ifname}\n";
3044
				$rrdupdatesh .= "	out_{$ifname}=`$pingcmd -c $numpings -q $monitorip`\n";
3045
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
3046
				$rrdupdatesh .= "		packetloss_{$ifname}=`echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1`\n";
3047
				$rrdupdatesh .= "		roundtrip_{$ifname}=`echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/'`\n";
3048
				$rrdupdatesh .= "	fi\n";
3049
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
3050
				$rrdupdatesh .= "}\n\n";
3051

    
3052
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
3053
			}
3054

    
3055
			/* WIRELESS, set up the rrd file */
3056
			if($config['interfaces'][$ifname]['wireless']['mode'] == "bss") {
3057
				if (!file_exists("$rrddbpath$ifname$wireless")) {
3058
					/* create rrd file if it does not exist */
3059
					log_error("Create RRD database $rrddbpath$ifname$wireless");
3060
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$wireless --step $rrdwirelessinterval ";
3061
					$rrdcreate .= "DS:snr:GAUGE:$wirelessvalid:0:1000 ";
3062
					$rrdcreate .= "DS:rate:GAUGE:$wirelessvalid:0:1000 ";
3063
					$rrdcreate .= "DS:channel:GAUGE:$wirelessvalid:0:1000 ";
3064
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3065
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3066
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3067
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3068
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3069
	
3070
					$rrdcreateoutput = array();
3071
					$rrdcreatereturn = "";
3072

    
3073
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3074
					if ($rrdcreatereturn != 0) {
3075
						log_error("RRD create failed exited with $rrdcreatereturn, the
3076
								error is: $rrdcreateoutput[0]\n");
3077
					}
3078
				}
3079

    
3080
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3081
				if($g['booting']) {
3082
					exec("$rrdtool update $rrddbpath$ifname$wireless N:U:U:U");
3083
				}
3084

    
3085
				$rrdupdatesh .= "\n";
3086
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
3087
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\\\n";
3088
				$rrdupdatesh .= "`$ifconfig {$realif} list ap| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
3089
			}
3090

    
3091
				/* QUEUES, set up the queues databases */
3092
				if ($altq_list_queues[$ifname]) {
3093
					$altq =& $altq_list_queues[$ifname];
3094
					/* NOTE: Is it worth as its own function?! */
3095
					switch ($altq->GetBwscale()) {
3096
                                        case "Gb":
3097
                                        	$factor = 1000 * 1000 * 1000;
3098
                                                break;
3099
                                        case "Mb":
3100
                                                $factor = 1000 * 1000;
3101
                                                break;
3102
                                        case "Kb":
3103
                                                $factor = 1000;
3104
                                                break;
3105
                                        case "b":
3106
                                        default:
3107
                                                $factor = 1;
3108
                                                break;
3109
                                        }
3110
					$qbandwidth = $altq->GetBandwidth() * $factor;
3111
					if ($qbandwidth <=0)
3112
						$qbandwidth = 100 * 1000 * 1000; /* 100Mbit */
3113
					$qlist =& $altq->get_queue_list($notused);
3114
					if (!file_exists("$rrddbpath$ifname$queues")) {
3115
						/* create rrd file if it does not exist */
3116
						log_error("Create RRD database $rrddbpath$ifname$queues");
3117
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
3118
						/* loop list of shaper queues */
3119
						$q = 0;
3120
						foreach ($qlist as $qname => $q) {
3121
							$rrdcreate .= "DS:$qname:COUNTER:$queuesvalid:0:$qbandwidth ";
3122
						}
3123

    
3124
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3125
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3126
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3127
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3128
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3129

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

    
3137
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
3138
						/* create rrd file if it does not exist */
3139
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
3140
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
3141
						/* loop list of shaper queues */
3142
						$q = 0;
3143
						foreach ($qlist as $qname => $q) {
3144
							$rrdcreate .= "DS:$qname:COUNTER:$queuesdropvalid:0:$qbandwidth ";
3145
						}
3146

    
3147
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3148
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3149
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3150
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3151
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3152

    
3153
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3154
						if ($rrdcreatereturn != 0) {
3155
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3156
						}
3157
					}
3158

    
3159
					if($g['booting']) {
3160
						$rrdqcommand = "-t ";
3161
						$rrducommand = "N";
3162
						$q = 0;
3163
						foreach ($qlist as $qname => $q) {
3164
							if($q == 0) {
3165
								$rrdqcommand .= "{$qname}";
3166
							} else {
3167
								$rrdqcommand .= ":{$qname}";
3168
							}
3169
							$q++;
3170
							$rrducommand .= ":U";
3171
						}
3172
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3173
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3174
					}
3175

    
3176
					/* awk function to gather shaper data */
3177
					/* yes, it's special */
3178
					$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
3179
					$rrdupdatesh .= "{ ";
3180
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3181
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3182
					$rrdupdatesh .= "q=1; ";
3183
					$rrdupdatesh .= "} ";
3184
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3185
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
3186
					$rrdupdatesh .= "q=0; ";
3187
					$rrdupdatesh .= "} ";
3188
					$rrdupdatesh .= "} END { ";
3189
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3190
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3191
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3192
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3193

    
3194
					$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
3195
					$rrdupdatesh .= "{ ";
3196
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3197
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3198
					$rrdupdatesh .= "q=1; ";
3199
					$rrdupdatesh .= "} ";
3200
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3201
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
3202
					$rrdupdatesh .= "q=0; ";
3203
					$rrdupdatesh .= "} ";
3204
					$rrdupdatesh .= "} END { ";
3205
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3206
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3207
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3208
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3209
				}
3210
		}
3211
		$i++;
3212

    
3213
		/* System only statistics */
3214
		$ifname = "system";
3215

    
3216
			/* STATES, create pf states database */
3217
			if(! file_exists("$rrddbpath$ifname$states")) {
3218
				/* create rrd file if it does not exist */
3219
				log_error("Create RRD database $rrddbpath$ifname$states");
3220
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3221
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3222
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3223
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3224
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3225
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3226
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3227
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3228
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3229
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3230
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3231

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

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

    
3244
 			/* the pf states gathering function. */
3245
 			$rrdupdatesh .= "\n";
3246
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
3247
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
3248
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3249
 			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3250
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3251
 			$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";
3252
 			$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";
3253
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3254

    
3255
			/* End pf states statistics */
3256

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

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

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

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

    
3301
			/* End CPU statistics */
3302

    
3303
			/* Memory, create Memory statistics database */
3304
			if(! file_exists("$rrddbpath$ifname$mem")) {
3305
				/* create rrd file if it does not exist */
3306
				log_error("Create RRD database $rrddbpath$ifname$mem");
3307
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$mem --step $rrdmeminterval ";
3308
				$rrdcreate .= "DS:active:GAUGE:$memvalid:0:10000000 ";
3309
				$rrdcreate .= "DS:inactive:GAUGE:$memvalid:0:10000000 ";
3310
				$rrdcreate .= "DS:free:GAUGE:$memvalid:0:10000000 ";
3311
				$rrdcreate .= "DS:cache:GAUGE:$memvalid:0:10000000 ";
3312
				$rrdcreate .= "DS:wire:GAUGE:$memvalid:0:10000000 ";
3313
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3314
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3315
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3316
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3317
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3318
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3319
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3320
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3321
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3322
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3323
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3324
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3325

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

    
3333
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3334
			if($g['booting']) {
3335
				exec("$rrdtool update $rrddbpath$ifname$mem N:U:U:U:U:U");
3336
			}
3337

    
3338
 			/* the Memory stats gathering function. */
3339
 			$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 | ";
3340
			$rrdupdatesh .= " $awk '{getline active;getline inactive;getline free;getline cache;getline wire;printf \"$rrdtool update $rrddbpath$ifname$mem N:\"";
3341
			$rrdupdatesh .= "((active/$0) * 100)\":\"((inactive/$0) * 100)\":\"((free/$0) * 100)\":\"((cache/$0) * 100)\":\"(wire/$0 * 100)}'`\n\n";
3342
			
3343
			/* End Memory statistics */
3344

    
3345
			/* SPAMD, set up the spamd rrd file */
3346
			if (isset($config['installedpackages']['spamdsettings']) &&
3347
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
3348
				/* set up the spamd rrd file */
3349
				if (!file_exists("$rrddbpath$ifname$spamd")) {
3350
						/* create rrd file if it does not exist */
3351
						log_error("Create RRD database $rrddbpath$ifname$spamd");
3352
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
3353
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
3354
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
3355
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3356
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3357
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3358
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3359
						$rrdcreate .= "RRA:MIN:0.5:1440:1500 ";
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:AVERAGE:0.5:1440:1500 ";
3365
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3366
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3367
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3368
						$rrdcreate .= "RRA:MAX:0.5:720:1000 ";
3369
						$rrdcreate .= "RRA:MAX:0.5:1440:1500 ";
3370

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

    
3378
				$rrdupdatesh .= "\n";
3379
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3380
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3381
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3382

    
3383
			}
3384
		/* End System statistics */
3385

    
3386
		$rrdupdatesh .= "sleep 60\n";
3387
		$rrdupdatesh .= "done\n";
3388
		log_error("Creating rrd update script");
3389
		/* write the rrd update script */
3390
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3391
		$fd = fopen("$updaterrdscript", "w");
3392
		fwrite($fd, "$rrdupdatesh");
3393
		fclose($fd);
3394

    
3395
		/* kill off traffic collectors */
3396
		kill_traffic_collector();
3397

    
3398
		/* start traffic collector */
3399
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3400

    
3401
	} else {
3402
		/* kill off traffic collectors */
3403
		kill_traffic_collector();
3404
	}
3405

    
3406
	if($g['booting']) 
3407
		echo "done.\n";
3408
		
3409
}
3410

    
3411
function kill_traffic_collector() {
3412
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
3413
}
3414

    
3415
function update_filter_reload_status($text) {
3416
	global $g;
3417
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3418
	fwrite($fd, $text);
3419
	fclose($fd);
3420
}
3421

    
3422
function get_interface_gateway($interface) {
3423
        global $config, $g;
3424

    
3425
	$iflist = get_configured_interface_with_descr();
3426
	/* 
3427
	 * XXX: This is silly at first, but we may be called with the interface
3428
	 *	descr for no apparent reason!!!
3429
	 */
3430
	foreach ($iflist as $ifent => $ifdesc) {
3431
		if ($ifent == $interface || $ifdesc == $interface) {
3432
			$interface = $ifent;
3433
			break;
3434
		}
3435
	}
3436

    
3437
	$gw = NULL;
3438

    
3439
	$gwcfg = $config['interfaces'][$interface];
3440
        if (is_ipaddr($gwcfg['gateway'])) 
3441
        	$gw = $gwcfg['gateway'];
3442
        else if ($gwcfg['gateway'] <> "") {
3443
        	if (is_array($config['gateways']['gateway_item']))
3444
                	foreach($config['gateways']['gateway_item'] as $gateway) {
3445
                                if($gateway['name'] == $gwcfg['gateway']) {
3446
                                        $gw = $gateway['gateway'];
3447
                        		break;
3448
                		}
3449
        		}
3450
        } 
3451
	
3452
	// for dynamic interfaces we handle them through the $interface_router file.
3453
	if (!is_ipaddr($gw)) {
3454
        	$realif = get_real_interface($interface);
3455
        	if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
3456
                	$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3457
                	$gw = rtrim($gw);
3458
        	}
3459
	}
3460

    
3461
        /* return gateway */
3462
        return $gw;
3463
}
3464

    
3465
/* DHCP enabled on any interfaces? */
3466
function is_dhcp_server_enabled() 
3467
{
3468
	global $config;
3469

    
3470
	$dhcpdenable = false;
3471
	
3472
	if (!is_array($config['dhcpd']))
3473
		return false;
3474

    
3475
	$Iflist = get_configured_interface_list();
3476

    
3477
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
3478
		if (isset($dhcpifconf['enable']) && isset($Iflist[$dhcpif])) {
3479
			$dhcpdenable = true;
3480
			break;
3481
		}
3482
	}
3483

    
3484
	return $dhcpdenable;
3485
}
3486

    
3487
/* return outside interfaces with a gateway */
3488
function get_interfaces_with_gateway() {
3489
	global $config;
3490
	$ints = array();
3491
	$vfaces = array(
3492
			'bridge.?*',
3493
			'ppp.?*',
3494
			'sl.?*',
3495
			'gif.?*',
3496
			'faith.?*',
3497
			'lo.?*',
3498
			'ng.?*',
3499
			'vlan.?*',
3500
			'pflog.?*',
3501
			'pfsync.?*',
3502
			'enc.?*',
3503
			'tun.?*',
3504
			'carp.?*'
3505
		);
3506
	$ifdescrs = get_interface_list("active","physical",$vfaces);
3507

    
3508
	/* loop interfaces, check config for outbound */
3509
	foreach ($ifdescrs as $ifdescr => $ifname) {
3510
		$friendly = $ifname['friendly'];
3511
		switch ($config['interfaces'][$friendly]['ipaddr']) {
3512
		case "dhcp":
3513
		case "carpdev-dhcp":
3514
		case "pppoe":
3515
		case "pptp":
3516
			$ints[] = $friendly;
3517
			break;	
3518
		default:
3519
			if ($config['interfaces'][$friendly]['pointtopoint']) 
3520
				$ints[] = $friendly;
3521
			else if ($config['interfaces'][$friendly]['gateway'] <> "")
3522
				$ints[] = $friendly;
3523
			break;
3524
		}
3525
	}
3526
	return $ints;
3527
}
3528

    
3529
/* return true if interface has a gateway */
3530
function interface_has_gateway($friendly) {
3531
	$friendly = strtolower($friendly);
3532
	if(in_array($friendly, get_interfaces_with_gateway())) {
3533
		return true;
3534
	} else {
3535
		/* extra check for real interface names if it falls through */
3536
		$friendly = convert_real_interface_to_friendly_interface_name($friendly);
3537
		return(in_array($friendly, get_interfaces_with_gateway()));
3538
	}
3539
}
3540

    
3541
/****f* pfsense-utils/isAjax
3542
 * NAME
3543
 *   isAjax - reports if the request is driven from prototype
3544
 * INPUTS
3545
 *   none
3546
 * RESULT
3547
 *   true/false
3548
 ******/
3549
function isAjax() {
3550
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
3551
}
3552

    
3553
//returns interface information
3554
function get_interface_info($ifdescr) {
3555
	global $config, $linkinfo, $netstatrninfo;
3556

    
3557
	$ifinfo = array();
3558
	/* if list */
3559
	$iflist = get_configured_interface_with_descr(false,true);
3560
	
3561
	$found = false;
3562
    	foreach ($iflist as $if => $ifname) {
3563
    	if ($ifdescr == $if || $ifdescr == $ifname) {
3564
			$ifinfo['hwif'] = $config['interfaces'][$if]['if'];
3565
			$ifinfo['if'] = get_real_interface($if);
3566
			$found = true;
3567
			break;
3568
		}
3569
	}
3570
	if ($found == false)
3571
		return;
3572

    
3573
	/* run netstat to determine link info */
3574

    
3575
	unset($linkinfo);
3576
	exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3577
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3578
	if (preg_match("/\*$/", $linkinfo[0])) {
3579
		$ifinfo['status'] = "down";
3580
	} else {
3581
		$ifinfo['status'] = "up";
3582
	}
3583

    
3584
	if (preg_match("/^enc|^tun|^ppp|^pptp|^ovpn/i", $ifinfo['if'])) {
3585
		$ifinfo['inpkts'] = $linkinfo[3];
3586
                $ifinfo['inbytes'] = $linkinfo[5];
3587
                $ifinfo['outpkts'] = $linkinfo[6];
3588
                $ifinfo['outbytes'] = $linkinfo[8];
3589
	} else {
3590
		$ifinfo['macaddr'] = $linkinfo[3];
3591
		$ifinfo['inpkts'] = $linkinfo[4];
3592
		$ifinfo['inerrs'] = $linkinfo[5];
3593
		$ifinfo['inbytes'] = $linkinfo[6];
3594
		$ifinfo['outpkts'] = $linkinfo[7];
3595
		$ifinfo['outerrs'] = $linkinfo[8];
3596
		$ifinfo['outbytes'] = $linkinfo[9];
3597
		$ifinfo['collisions'] = $linkinfo[10];
3598
	}
3599

    
3600
	$ifconfiginfo = "";
3601
	unset($ifconfiginfo);
3602
	exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3603
	foreach ($ifconfiginfo as $ici) {
3604
		if (preg_match("/inet (\S+)/", $ici, $matches)) 
3605
			$ifinfo['ipaddr'] = $matches[1];
3606
		if (preg_match("/netmask (\S+)/", $ici, $matches)) 
3607
			if (preg_match("/^0x/", $matches[1]))
3608
				$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
3609
	}
3610

    
3611
	switch ($config['interfaces'][$if]['ipaddr']) {
3612
	/* DHCP? -> see if dhclient is up */
3613
	case "dhcp":
3614
	case "carpdev-dhcp":
3615
        /* see if dhclient is up */
3616
        if (is_dhcp_running($ifinfo['if']) == true)
3617
        	$ifinfo['dhcplink'] = "up";
3618
        else
3619
            $ifinfo['dhcplink'] = "down";
3620

    
3621
		break;
3622
	/* PPPoE interface? -> get status from virtual interface */
3623
	case "pppoe":
3624
		unset($linkinfo);
3625
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3626
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3627
		if (preg_match("/\*$/", $linkinfo[0])) {
3628
			$ifinfo['pppoelink'] = "down";
3629
		} else {
3630
			/* get PPPoE link status for dial on demand */
3631
			$ifinfo['pppoelink'] = "up";
3632

    
3633
			foreach ($ifconfiginfo as $ici) {
3634
				if (strpos($ici, 'LINK0') !== false)
3635
					$ifinfo['pppoelink'] = "down";
3636
			}
3637
		}
3638
		break;
3639
	/* PPTP interface? -> get status from virtual interface */
3640
	case "pptp":
3641
		unset($linkinfo);
3642
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3643
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3644
		if (preg_match("/\*$/", $linkinfo[0])) {
3645
			$ifinfo['pptplink'] = "down";
3646
		} else {
3647
			/* get PPTP link status for dial on demand */
3648
			$ifinfo['pptplink'] = "up";
3649

    
3650
			foreach ($ifconfiginfo as $ici) {
3651
				if (strpos($ici, 'LINK0') !== false)
3652
					$ifinfo['pptplink'] = "down";
3653
			}
3654
		}
3655
		break;
3656
	default:
3657
		break;
3658
	}
3659

    
3660
	if ($ifinfo['status'] == "up") {
3661
		/* try to determine media with ifconfig */
3662
		unset($ifconfiginfo);
3663
		exec("/sbin/ifconfig " . $ifinfo['hwif'], $ifconfiginfo);
3664
		$matches = "";
3665
		foreach ($ifconfiginfo as $ici) {
3666

    
3667
			/* don't list media/speed for wireless cards, as it always
3668
			   displays 2 Mbps even though clients can connect at 11 Mbps */
3669
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
3670
				$ifinfo['media'] = $matches[1];
3671
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
3672
				$ifinfo['media'] = $matches[1];
3673
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
3674
				$ifinfo['media'] = $matches[1];
3675
			}
3676

    
3677
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
3678
				if ($matches[1] != "active")
3679
					$ifinfo['status'] = $matches[1];
3680
			}
3681
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
3682
				$ifinfo['channel'] = $matches[1];
3683
			}
3684
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
3685
				if ($matches[1][0] == '"')
3686
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
3687
				else
3688
					$ifinfo['ssid'] = $matches[1];
3689
			}
3690
		}
3691
		/* lookup the gateway */
3692
		if (interface_has_gateway($if)) 
3693
			$ifinfo['gateway'] = get_interface_gateway($if);
3694
	}
3695

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

    
3712
	return $ifinfo;
3713
}
3714

    
3715
//returns cpu speed of processor. Good for determining capabilities of machine
3716
function get_cpu_speed() {
3717
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
3718
}
3719

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

    
3739
function add_hostname_to_watch($hostname) {
3740
	if(!is_dir("/var/db/dnscache")) {
3741
		mkdir("/var/db/dnscache");
3742
	}
3743
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
3744
		$domrecords = array();
3745
		$domips = array();
3746
		exec("host -t A $hostname", $domrecords, $rethost);
3747
		if($rethost == 0) {
3748
			foreach($domrecords as $domr) {
3749
				$doml = explode(" ", $domr);
3750
				$domip = $doml[3];
3751
				/* fill array with domain ip addresses */
3752
				if(is_ipaddr($domip)) {
3753
					$domips[] = $domip;
3754
				}
3755
			}
3756
		}
3757
		sort($domips);
3758
		$contents = "";
3759
		if(! empty($domips)) {
3760
			foreach($domips as $ip) {
3761
				$contents .= "$ip\n";
3762
			}
3763
		}
3764
		file_put_contents("/var/db/dnscache/$hostname", $contents);
3765
	}
3766
}
3767

    
3768
function find_dns_aliases() {
3769
	global $config, $g;
3770
	foreach((array) $config['aliases']['alias'] as $alias) {
3771
		$alias_value = $alias['address'];
3772
		$alias_name = $alias['name'];
3773
		if(stristr($alias_value, " ")) {
3774
			$alias_split = split(" ", $alias_value);
3775
			foreach($alias_split as $as) {
3776
				if(is_fqdn($as)) 
3777
					add_hostname_to_watch($as);			
3778
			}
3779
		} else {
3780
			if(is_fqdn($alias_value)) 
3781
				add_hostname_to_watch($alias_value);
3782
		}
3783
	}
3784
}
3785

    
3786
function is_fqdn($fqdn) {
3787
	$hostname = false;
3788
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
3789
		$hostname = true;
3790
	}
3791
	if(preg_match("/\.\./", $fqdn)) {
3792
		$hostname = false;
3793
	}
3794
	if(preg_match("/^\./i", $fqdn)) { 
3795
		$hostname = false;
3796
	}
3797
	if(preg_match("/\//i", $fqdn)) {
3798
		$hostname = false;
3799
	}
3800
	return($hostname);
3801
}
3802

    
3803
function pfsense_default_state_size() {
3804
  /* get system memory amount */
3805
  $memory = get_memory();
3806
  $avail = $memory[0];
3807
  /* Be cautious and only allocate 10% of system memory to the state table */
3808
  $max_states = (int) ($avail/10)*1000;
3809
  return $max_states;
3810
}
3811

    
3812
function lookup_gateway_ip_by_name($name) {
3813
	global $config;
3814
	if(is_array($config['gateways'])) {
3815
		foreach($config['gateways']['gateway_item'] as $gateway) {
3816
			if($gateway['name'] == $name) {
3817
				$gatewayip = $gateway['gateway'];
3818
				$interfacegw = $gateway['interface'];
3819
				return($gatewayip);
3820
			}
3821
		}
3822
	} else {
3823
		return(false);
3824
	}
3825
}
3826

    
3827
function lookup_gateway_monitor_ip_by_name($name) {
3828
	global $config;
3829
	$gateways_arr = return_gateways_array();
3830

    
3831
	foreach($gateways_arr as $gateway) {
3832
		if($gateway['name'] == "$name") {
3833
			$monitorip = $gateway['monitor'];
3834
			if($monitorip == "")
3835
				$monitorip = $gateway['gateway'];
3836

    
3837
			return($monitorip);
3838
		}
3839
	}
3840
	return(false);
3841
}
3842

    
3843
function lookup_gateway_interface_by_name($name) {
3844
	global $config;
3845
	$gateways_arr = return_gateways_array();
3846

    
3847
	foreach($gateways_arr as $gateway) {
3848
		if($gateway['name'] == "$name") {
3849
			$gatewayip = $gateway['gateway'];
3850
			$interfacegw = $gateway['interface'];
3851
			return($interfacegw);
3852
		}
3853
	}
3854
	return(false);
3855
}
3856

    
3857
/****f* pfsense-utils/safe_write_file
3858
 * NAME
3859
 *   safe_write_file - Write a file out atomically
3860
 * DESCRIPTION
3861
 *   safe_write_file() Writes a file out atomically by first writing to a
3862
 *   temporary file of the same name but ending with the pid of the current
3863
 *   process, them renaming the temporary file over the original.
3864
 * INPUTS
3865
 *   $filename  - string containing the filename of the file to write
3866
 *   $content   - string containing the file content to write to file
3867
 *   $force_binary      - boolean denoting whether we should force binary
3868
 *   mode writing.
3869
 * RESULT
3870
 *   boolean - true if successful, false if not
3871
 ******/
3872
function safe_write_file($file, $content, $force_binary) {
3873
        $tmp_file = $file . "." . getmypid();
3874
        $write_mode = $force_binary ? "wb" : "w";
3875

    
3876
        $fd = fopen($tmp_file, $write_mode);
3877
        if (!$fd) {
3878
                // Unable to open temporary file for writing
3879
                return false;
3880
        }
3881
        if (!fwrite($fd, $content)) {
3882
                // Unable to write to temporary file
3883
                fclose($fd);
3884
                return false;
3885
        }
3886
        fclose($fd);
3887

    
3888
        if (!rename($tmp_file, $file)) {
3889
                // Unable to move temporary file to original
3890
                unlink($tmp_file);
3891
                return false;
3892
        }
3893
        return true;
3894
}
3895

    
3896
function rule_popup($src,$srcport,$dst,$dstport){
3897
global $config;
3898
$aliases_array = array();
3899
if($config['aliases']['alias'] <> "" and is_array($config['aliases']['alias']))
3900
{
3901
$span_begin = "";
3902
		$alias_src_span_begin = "";
3903
		$alias_src_span_end = "";
3904
		$alias_src_port_span_begin = "";
3905
		$alias_src_port_span_end = "";
3906
		$alias_dst_span_begin = "";
3907
		$alias_dst_span_end = "";
3908
		$alias_dst_port_span_begin = "";
3909
		$alias_dst_port_span_end = "";
3910
		$alias_content_text = "";
3911
	foreach($config['aliases']['alias'] as $alias_name) 
3912
	{	
3913
	 	$alias_addresses = explode (" ", $alias_name['address']);
3914
	 	$alias_details = explode ("||", $alias_name['detail']);
3915
	 	$alias_objects_with_details = "";
3916
	 	$counter = 0;
3917
	 	foreach($alias_addresses as $alias_ports_address)
3918
	 	{
3919
			$alias_objects_with_details .= $alias_addresses[$counter];
3920
			$alias_detail_default = strpos ($alias_details[$counter],"Entry added");
3921
			if ($alias_details[$counter] != "" && $alias_detail_default === False){
3922
				$alias_objects_with_details .=" - " . $alias_details[$counter];
3923
			}  
3924
			$alias_objects_with_details .= "<br>";
3925
			$counter++;
3926
		}			
3927
		//max character length for caption field
3928
		$maxlength = 60;
3929
		
3930
		$alias_descr_substr = $alias_name['descr'];
3931
		$alias_content_text = htmlspecialchars($alias_objects_with_details);
3932
		$alias_caption = htmlspecialchars($alias_descr_substr . ":");
3933
		$strlength = strlen ($alias_caption);
3934
		if ($strlength >= $maxlength) 
3935
			$alias_caption = substr($alias_caption, 0, $maxlength) . "...";		
3936
						
3937
		$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>";
3938
		
3939
		
3940
		if ($alias_name['name'] == $src)
3941
	 	{										
3942
			$alias_src_span_begin = $span_begin;
3943
		}
3944
	 	if ($alias_name['name'] == $srcport)
3945
	 	{									
3946
			$alias_src_port_span_begin = $span_begin;					
3947
		}
3948
		if ($alias_name['name'] == $dst)
3949
	 	{										
3950
			$alias_dst_span_begin = $span_begin;									
3951
		}
3952
		if ($alias_name['name'] == $dstport)
3953
	 	{											
3954
			$alias_dst_port_span_begin = $span_begin;											
3955
		}										
3956
		
3957
	}
3958
	$descriptions = array ();
3959
	$descriptions['src'] = $alias_src_span_begin;
3960
	$descriptions['srcport'] = $alias_src_port_span_begin;
3961
	$descriptions['dst'] = $alias_dst_span_begin;
3962
	$descriptions['dstport'] = $alias_dst_port_span_begin;
3963
	return $descriptions; 
3964
  }
3965
}
3966
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body') {
3967
	global $ch, $fout, $file_size, $downloaded;
3968
	$file_size  = 1;
3969
	$downloaded = 1;
3970
	/* open destination file */
3971
	$fout = fopen($destination_file, "wb");
3972

    
3973
	/*
3974
	 *	Originally by Author: Keyvan Minoukadeh
3975
	 *	Modified by Scott Ullrich to return Content-Length size
3976
         */
3977

    
3978
	$ch = curl_init();
3979
	curl_setopt($ch, CURLOPT_URL, $url_file);
3980
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
3981
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
3982
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
3983
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, '5');
3984

    
3985
	curl_exec($ch);
3986
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
3987
	if($fout)
3988
		fclose($fout);
3989
	curl_close($ch);
3990
	return ($http_code == 200) ? true : $http_code;
3991
}
3992

    
3993
function read_header($ch, $string) {
3994
	global $file_size, $fout;
3995
	$length = strlen($string);
3996
	$regs = "";
3997
	ereg("(Content-Length:) (.*)", $string, $regs);
3998
	if($regs[2] <> "") {
3999
		$file_size = intval($regs[2]);
4000
	}
4001
	ob_flush();
4002
	return $length;
4003
}
4004

    
4005
function read_body($ch, $string) {
4006
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen;
4007
	$length = strlen($string);
4008
	$downloaded += intval($length);
4009
	$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
4010
	$downloadProgress = 100 - $downloadProgress;
4011
	if($lastseen <> $downloadProgress and $downloadProgress < 101) {
4012
		if($sendto == "status") {
4013
			$tostatus = $static_status . $downloadProgress . "%";
4014
			update_status($tostatus);
4015
		} else {
4016
			$tooutput = $static_output . $downloadProgress . "%";
4017
			update_output_window($tooutput);
4018
		}
4019
		update_progress_bar($downloadProgress);
4020
		$lastseen = $downloadProgress;
4021
	}
4022
	if($fout)
4023
		fwrite($fout, $string);
4024
	ob_flush();
4025
	return $length;
4026
}
4027

    
4028
?>
(21-21/37)