Project

General

Profile

Download (113 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_wan_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_current_wan_address();
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
	global $debug;
652
	/* no schedule? rule should be installed */
653
	if($schedule == "") 
654
		return true;
655
	/*
656
	 * iterate through time blocks and deterimine
657
	 * if the rule should be installed or not.
658
	 */
659
	foreach($schedule['timerange'] as $timeday) {
660
		if($timeday['month']) 
661
			$month = $timeday['month'];
662
		else 
663
			$week = "";	
664
		if($timeday['day']) 
665
			$day = $timeday['day'];
666
		else 
667
			$day = "";
668
		if($timeday['hour']) 
669
			$hour = $timeday['hour'];
670
		else 
671
			$hour = "";
672
		if($timeday['position']) 
673
			$position = $timeday['position'];
674
		else 
675
			$position = "";
676
		if($timeday['desc']) 
677
			$desc = $timeday['desc'];
678
		else 
679
			$desc = "";
680
		if($month) {
681
			$monthstatus = tdr_month($month);
682
		} else {
683
			$monthstatus = true;
684
		}
685
		if($day) {
686
			$daystatus = tdr_day($day);
687
		} else {
688
			$daystatus = true;
689
		}
690
		if($hour) {
691
			$hourstatus = tdr_hour($hour);
692
		} else {
693
			$hourstatus = true;
694
		}
695
		if($position) {
696
			$positionstatus = tdr_position($position);
697
		} else {
698
			$positionstatus = true;
699
		}
700

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

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

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

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

    
768
function tdr_month($schedule) {
769
	/*
770
	 * Calculate month
771
	 */
772
	global $debug;
773
	$todays_month = date("n");
774
	$months = split(",", $schedule);
775
	log_error("[TDR DEBUG] tdr_month($schedule)");
776
	foreach($months as $month) {
777
		if($month == $todays_month) {
778
			return true;
779
		}
780
	}
781
	return false;
782
}
783

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

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

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

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

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

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

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

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

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

    
946
	if($config['system']['disablechecksumoffloading'])
947
		return;
948

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

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

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

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

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

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

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

    
1052
	setup_polling_defaults();
1053

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

    
1059
	/* if list */
1060
        $iflist = get_configured_interface_list();
1061

    
1062
	foreach ($iflist as $ifent => $ifname) {
1063
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
1064
		$supported = false;
1065
		foreach($supported_ints as $supported) {
1066
			if(stristr($real_interface, $supported)) {
1067
				$supported = true;
1068
			}
1069
		}
1070
		if ($supported == true) {
1071
			mwexec("/sbin/ifconfig {$real_interface} polling");
1072
		} else {
1073
			mwexec("/sbin/ifconfig {$real_interface} -polling");
1074
		}
1075
	}
1076
}
1077

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

    
1091
	/* if list */
1092
        $ifdescrs = get_configured_interface_list();
1093

    
1094
	foreach($ifdescrs as $if)
1095
		enable_hardware_offloading($if);
1096
}
1097

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

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

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

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

    
1164
	if($tmp == "")
1165
		return false;
1166
	else
1167
		return true;
1168
}
1169

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

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

    
1202
/****f* pfsense-utils/find_number_of_created_carp_interfaces
1203
 * NAME
1204
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
1205
 * RESULT
1206
 *   $tmp	- Number of currently created CARP interfaces.
1207
 ******/
1208
function find_number_of_created_carp_interfaces($flush = false) {
1209
	global $carp_interface_count_cache;
1210

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

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

    
1244
function link_carp_interface_to_parent($interface) {
1245
	global $config;
1246
	if($interface == "") return;
1247

    
1248
	/* if list */
1249
        $ifdescrs = get_configured_interface_list();
1250

    
1251
	$carp_int = $interface;
1252
	$carp_ip = find_interface_ip($interface);
1253
	$carp_subnet = find_virtual_ip_netmask($carp_ip);
1254
	$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1255
	$carp_ints = "";
1256
	$num_carp_ints = find_number_of_created_carp_interfaces();
1257

    
1258
	foreach ($ifdescrs as $ifdescr => $ifname) {
1259
		if(interface_has_gateway($ifname)) {
1260
			$interfaceip = $config['interfaces'][$ifname]['ipaddr'];
1261
			$subnet_bits = $config['interfaces'][$ifname]['subnet'];
1262
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
1263
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}")) {
1264
				return $ifname;
1265
			}
1266
		}
1267
	}
1268
	return $carp_ints;
1269
}
1270

    
1271
/****f* pfsense-utils/link_ip_to_carp_interface
1272
 * NAME
1273
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
1274
 * INPUTS
1275
 *   $ip
1276
 * RESULT
1277
 *   $carp_ints
1278
 ******/
1279
function link_ip_to_carp_interface($ip) {
1280
	global $config;
1281
	if($ip == "") return;
1282

    
1283
	/* if list */
1284
        $ifdescrs = get_configured_interface_list();
1285

    
1286
	$ft = split("\.", $ip);
1287
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
1288

    
1289
	$carp_ints = "";
1290
	$num_carp_ints = find_number_of_created_carp_interfaces();
1291
	foreach ($ifdescrs as $ifdescr => $ifname) {
1292
		for($x=0; $x<$num_carp_ints; $x++) {
1293
			$carp_int = "carp{$x}";
1294
			$carp_ip = find_interface_ip($carp_int);
1295
			$carp_subnet = find_virtual_ip_netmask($carp_ip);
1296
			$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1297
			if(ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
1298
				if(!stristr($carp_ints, $carp_int))
1299
					$carp_ints .= " " . $carp_int;
1300
		}
1301
	}
1302
	return $carp_ints;
1303
}
1304

    
1305
/****f* pfsense-utils/find_virtual_ip_netmask
1306
 * NAME
1307
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
1308
 * INPUTS
1309
 *   $ip - ip address to locate subnet mask of
1310
 * RESULT
1311
 *   String containing the command's result.
1312
 * NOTES
1313
 *   This function returns the command's stdout and stderr.
1314
 ******/
1315
function find_virtual_ip_netmask($ip) {
1316
        global $config;
1317
        foreach($config['virtualip']['vip'] as $vip) {
1318
                if($ip == $vip['subnet'])
1319
                        return $vip['subnet_bits'];
1320
        }
1321
}
1322

    
1323
/****f* pfsense-utils/exec_command
1324
 * NAME
1325
 *   exec_command - Execute a command and return a string of the result.
1326
 * INPUTS
1327
 *   $command	- String of the command to be executed.
1328
 * RESULT
1329
 *   String containing the command's result.
1330
 * NOTES
1331
 *   This function returns the command's stdout and stderr.
1332
 ******/
1333
function exec_command($command) {
1334
	$output = array();
1335
	exec($command . ' 2>&1 ', $output);
1336
	return(implode("\n", $output));
1337
}
1338

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

    
1360
	$capable = $g['vlan_long_frame'];
1361

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

    
1364
	if (in_array($int_family[0], $capable))
1365
		return true;
1366
	else
1367
		return false;
1368
}
1369

    
1370
/*
1371
 * Return the interface array
1372
 */
1373
function get_interface_arr($flush = false) {
1374
	global $interface_arr_cache;
1375

    
1376
	/* If the cache doesn't exist, build it */
1377
	if (!isset($interface_arr_cache) or $flush)
1378
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
1379

    
1380
	return $interface_arr_cache;
1381
}
1382

    
1383
/*
1384
 * does_interface_exist($interface): return true or false if a interface is
1385
 * detected.
1386
 */
1387
function does_interface_exist($interface) {
1388
	global $config;
1389

    
1390
	if(!$interface)
1391
		return false;
1392
		
1393
	$ints = get_interface_arr();
1394

    
1395
	if(strtolower($interface) == "lan")
1396
		if(!$config['interfaces']['lan']) 
1397
			return false;
1398

    
1399
	if(stristr($ints, $interface) !== false)
1400
		return true;
1401
	else
1402
		return false;
1403
}
1404

    
1405
/*
1406
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
1407
 */
1408
function convert_ip_to_network_format($ip, $subnet) {
1409
	$ipsplit = split('[.]', $ip);
1410
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
1411
	return $string;
1412
}
1413

    
1414
/*
1415
 * find_interface_ip($interface): return the interface ip (first found)
1416
 */
1417
function find_interface_ip($interface, $flush = false) {
1418
	global $interface_ip_arr_cache;
1419
	$interface = str_replace("\n", "", $interface);
1420
	if(does_interface_exist($interface) == false) return;
1421
	/* Setup IP cache */
1422
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
1423
		$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");
1424
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
1425
	}
1426

    
1427
	return $interface_ip_arr_cache[$interface];
1428
}
1429

    
1430
function guess_interface_from_ip($ipaddress) {
1431
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2; };'");
1432
	return $ret;
1433
}
1434

    
1435
/*
1436
 * find_ip_interface($ip): return the interface where an ip is defined
1437
 */
1438
function find_ip_interface($ip) {
1439

    
1440
	/* if list */
1441
        $ifdescrs = get_configured_interface_list();
1442

    
1443
	foreach ($ifdescrs as $ifdescr => $ifname) {
1444
		$int = convert_friendly_interface_to_real_interface_name($ifname);
1445
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
1446
		if(stristr($ifconfig,$ip) <> false)
1447
			return $int;
1448
	}
1449
	return false;
1450
}
1451

    
1452
/*
1453
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
1454
 *                                                       for a friendly interface.  ie: wan
1455
 */
1456
function filter_translate_type_to_real_interface($interface) {
1457
	global $config;
1458
	if(isset($config['interfaces'][$interface]['pointtopoint']))
1459
		return "ppp0";
1460
	if($config['interfaces'][$interface]['if'] <> "") {
1461
		return $config['interfaces'][$interface]['if'];
1462
	} else {
1463
		return $interface;
1464
	}
1465
}
1466

    
1467
/*
1468
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
1469
 */
1470
function get_carp_interface_status($carpinterface) {
1471
	/* basically cache the contents of ifconfig statement
1472
	to speed up this routine */
1473
	global $carp_query;
1474
	if($carp_query == "")
1475
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
1476
	$found_interface = 0;
1477
	foreach($carp_query as $int) {
1478
		if($found_interface == 1) {
1479
			if(stristr($int, "MASTER")) return "MASTER";
1480
			if(stristr($int, "BACKUP")) return "BACKUP";
1481
			if(stristr($int, "INIT")) return "INIT";
1482
			return false;
1483
		}
1484
		if(stristr($int, $carpinterface) == true)
1485
		$found_interface=1;
1486
	}
1487
	return;
1488
}
1489

    
1490
/*
1491
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
1492
 */
1493
function get_pfsync_interface_status($pfsyncinterface) {
1494
    $result = does_interface_exist($pfsyncinterface);
1495
    if($result <> true) return;
1496
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
1497
    return $status;
1498
}
1499

    
1500
/*
1501
 * find_carp_interface($ip): return the carp interface where an ip is defined
1502
 */
1503
function find_carp_interface($ip) {
1504
	global $find_carp_ifconfig;
1505
	if($find_carp_ifconfig == "") {
1506
		$find_carp_ifconfig = array();
1507
		$num_carp_ints = find_number_of_created_carp_interfaces();
1508
		for($x=0; $x<$num_carp_ints; $x++) {
1509
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
1510
		}
1511
	}
1512
	$carps = 0;
1513
	foreach($find_carp_ifconfig as $fci) {
1514
		if(stristr($fci, $ip) == true)
1515
			return "carp{$carps}";
1516
		$carps++;
1517
	}
1518
}
1519

    
1520
/*
1521
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
1522
 */
1523
function add_rule_to_anchor($anchor, $rule, $label) {
1524
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
1525
}
1526

    
1527
/*
1528
 * remove_text_from_file
1529
 * remove $text from file $file
1530
 */
1531
function remove_text_from_file($file, $text) {
1532
	global $fd_log;
1533
	if($fd_log)
1534
		fwrite($fd_log, "Adding needed text items:\n");
1535
	$filecontents = file_get_contents($file);
1536
	$textTMP = str_replace($text, "", $filecontents);
1537
	$text = $textTMP;
1538
	if($fd_log)
1539
		fwrite($fd_log, $text);
1540
	$fd = fopen($file, "w");
1541
	fwrite($fd, $text);
1542
	fclose($fd);
1543
}
1544

    
1545
/*
1546
 * add_text_to_file($file, $text): adds $text to $file.
1547
 * replaces the text if it already exists.
1548
 */
1549
function add_text_to_file($file, $text, $replace = false) {
1550
	if(file_exists($file) and is_writable($file)) {
1551
		$filecontents = file($file);
1552
		$fout = fopen($file, "w");
1553

    
1554
		$filecontents = array_map('rtrim', $filecontents);
1555
		array_push($filecontents, $text);
1556
		if ($replace)
1557
			$filecontents = array_unique($filecontents);
1558

    
1559
		$file_text = implode("\n", $filecontents);
1560

    
1561
		fwrite($fout, $file_text);
1562
		fclose($fout);
1563
		return true;
1564
	} else {
1565
		return false;
1566
	}
1567
}
1568

    
1569
/*
1570
 *   after_sync_bump_adv_skew(): create skew values by 1S
1571
 */
1572
function after_sync_bump_adv_skew() {
1573
	global $config, $g;
1574
	$processed_skew = 1;
1575
	$a_vip = &$config['virtualip']['vip'];
1576
	foreach ($a_vip as $vipent) {
1577
		if($vipent['advskew'] <> "") {
1578
			$processed_skew = 1;
1579
			$vipent['advskew'] = $vipent['advskew']+1;
1580
		}
1581
	}
1582
	if($processed_skew == 1)
1583
		write_config("After synch increase advertising skew");
1584
}
1585

    
1586
/*
1587
 * get_filename_from_url($url): converts a url to its filename.
1588
 */
1589
function get_filename_from_url($url) {
1590
	return basename($url);
1591
}
1592

    
1593
/*
1594
 *   update_output_window: update bottom textarea dynamically.
1595
 */
1596
function update_output_window($text) {
1597
	global $pkg_interface;
1598
	$log = ereg_replace("\n", "\\n", $text);
1599
	if($pkg_interface == "console") {
1600
		/* too chatty */
1601
	} else {
1602
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1603
	}
1604
	/* ensure that contents are written out */
1605
	ob_flush();
1606
}
1607

    
1608
/*
1609
 *   get_dir: return an array of $dir
1610
 */
1611
function get_dir($dir) {
1612
	$dir_array = array();
1613
	$d = dir($dir);
1614
	while (false !== ($entry = $d->read())) {
1615
		array_push($dir_array, $entry);
1616
	}
1617
	$d->close();
1618
	return $dir_array;
1619
}
1620

    
1621
/*
1622
 *   update_output_window: update top textarea dynamically.
1623
 */
1624
function update_status($status) {
1625
	global $pkg_interface;
1626
	if($pkg_interface == "console") {
1627
		echo $status . "\n";
1628
	} else {
1629
		echo "\n<script type=\"text/javascript\">document.forms[0].status.value=\"" . $status . "\";</script>";
1630
	}
1631
	/* ensure that contents are written out */
1632
	ob_flush();
1633
}
1634

    
1635
/*
1636
 *   exec_command_and_return_text_array: execute command and return output
1637
 */
1638
function exec_command_and_return_text_array($command) {
1639
	$fd = popen($command . " 2>&1 ", "r");
1640
	while(!feof($fd)) {
1641
		$tmp .= fread($fd,49);
1642
	}
1643
	fclose($fd);
1644
	$temp_array = split("\n", $tmp);
1645
	return $temp_array;
1646
}
1647

    
1648
/*
1649
 *   exec_command_and_return_text: execute command and return output
1650
 */
1651
function exec_command_and_return_text($command) {
1652
	return exec_command($command);
1653
}
1654

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

    
1699
/*
1700
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
1701
 */
1702
function convert_friendly_interface_to_real_interface_name($interface) {
1703
	global $config;
1704

    
1705
	$wanif = $interface;
1706
	switch ($interface) {
1707
		case "pptp":
1708
			$wanif = "pptp";
1709
			break;
1710
		case "pppoe":
1711
			$wanif = "pppoe";
1712
			break;
1713
		case "openvpn":
1714
			$wanif = "openvpn";
1715
			break;
1716
		case "enc0":
1717
			$wanif = "enc0";
1718
			break;
1719
		/* XXX: dial in support?!
1720
		case "ppp":
1721
			$wanif = "ppp";
1722
			break;
1723
		*/
1724
		default:
1725
			$iflist = get_configured_interface_with_descr(false,true);
1726

    
1727
		foreach ($iflist as $if => $ifdesc) {
1728
			if ($interface == $if || $interface == $ifdesc) {
1729

    
1730
			$cfg = $config['interfaces'][$if];
1731

    
1732
			switch ($cfg['ipaddr']) {
1733
			case "carpdev-dhcp":
1734
				$viparr = &$config['virtualip']['vip'];
1735
				$counter = 0;
1736
				if(is_array($viparr))
1737
				foreach ($viparr as $vip) {
1738
					if ($vip['mode'] == "carpdev-dhcp") {
1739
						if($vip['interface'] == $if) {
1740
							$wanif =  "carp{$counter}";
1741
							break;
1742
						}
1743
						$counter++;
1744
					} else if ($vip['mode'] = "carp") 
1745
						$counter++;
1746
				}
1747
				break;
1748
			case "pppoe": 
1749
				if ($if == "wan")
1750
					$wanif = "pppoe0";
1751
				else
1752
					$wanif = "pppoe" . substr($if,3);
1753
				break;
1754
			case "pptp": 
1755
				if ($if == "wan")
1756
					$wanif = "pptp0";
1757
				else
1758
					$wanif = "pptp" . substr($if, 3);
1759
				break;
1760
			default:
1761
				if (isset($cfg['ispointtopoint']) && $cfg['pointtopoint'])
1762
					$wanif = "ppp0"; // XXX: PPP needs to convert to mpd
1763
				else	
1764
					$wanif = $cfg['if'];
1765
				break;
1766
			}
1767
			break;
1768

    
1769
			break;
1770
			}
1771
		}
1772
		break;
1773
	}
1774

    
1775
    return $wanif;
1776
}
1777

    
1778
/*
1779
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
1780
 */
1781
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
1782
	global $config;
1783
	
1784
	if (stristr($interface, "pppoe")) {
1785
		$index = substr($interface, 5);
1786
		if (intval($index) > 0)
1787
			return "opt{$index}";
1788
		else
1789
			return "wan";
1790
	} else if (stristr($interface, "pptp")) {
1791
		$index = substr($interface, 4);
1792
                if (intval($index) > 0)
1793
                        return "opt{$index}";
1794
                else
1795
                        return "wan";	
1796
	} else if (stristr($interface, "carp")) {
1797
		$index = substr($interface, 4);
1798
		$counter = 0;
1799
		foreach ($config['virtualip']['vip'] as $vip) {
1800
			if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
1801
				if (intval($index) == $counter)
1802
					return $vip['interface'];
1803
				$counter++;
1804
			}
1805
		}
1806
	}
1807
		
1808
	/* if list */
1809
        $ifdescrs = get_configured_interface_list();
1810

    
1811
	foreach ($ifdescrs as $if => $ifname) {
1812
		if($config['interfaces'][$if]['if'] == $interface)
1813
			return $ifname;
1814

    
1815
		/* XXX: ermal - The 3 lines below are totally bogus code. */
1816
		$int = filter_translate_type_to_real_interface($if);
1817
		if($ifname == $interface) 
1818
			return $ifname;
1819

    
1820
		if($int == $interface) 
1821
			return $ifname;
1822
	}
1823
	return NULL;
1824
}
1825

    
1826
/* attempt to resolve interface to friendly descr */
1827
function convert_friendly_interface_to_friendly_descr($interface) {
1828
        global $config;
1829

    
1830
        switch ($interface) {
1831
        	case "pptp":
1832
				$ifdesc = "PPTP";
1833
				break;
1834
       		case "pppoe":
1835
				$ifdesc = "PPPoE";
1836
				break;
1837
        	case "openvpn":
1838
				$ifdesc = "OpenVPN";
1839
				break;
1840
        	case "enc0":
1841
			case "ipsec":
1842
				$ifdesc = "IPsec";
1843
				break;
1844
        default:
1845
        	/* if list */
1846
        	$ifdescrs = get_configured_interface_with_descr();
1847
        	foreach ($ifdescrs as $if => $ifname) {
1848
				if ($if == $interface || $ifname == $interface)
1849
					return $ifname;
1850
        	}
1851
		break;
1852
	}
1853

    
1854
        return $ifdesc;
1855
}
1856

    
1857
function convert_real_interface_to_friendly_descr($interface) {
1858
        global $config;
1859

    
1860
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
1861

    
1862
	if ($ifdesc) {
1863
		$iflist = get_configured_interface_with_descr();
1864
		return $iflist[$ifdesc];
1865
	}
1866
	
1867
        return $interface;
1868
}
1869

    
1870
/*
1871
 * update_progress_bar($percent): updates the javascript driven progress bar.
1872
 */
1873
function update_progress_bar($percent) {
1874
	global $pkg_interface;
1875
	if($percent > 100) $percent = 1;
1876
	if($pkg_interface <> "console") {
1877
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1878
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1879
		echo "\n</script>";
1880
	} else {
1881
		echo " {$percent}%";
1882
	}
1883
}
1884

    
1885
/****f* pfsense-utils/WakeOnLan
1886
 * NAME
1887
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
1888
 * RESULT
1889
 *   true/false - true if the operation was successful
1890
 ******/
1891
function WakeOnLan($addr, $mac)
1892
{
1893
	$addr_byte = explode(':', $mac);
1894
	$hw_addr = '';
1895

    
1896
	for ($a=0; $a < 6; $a++)
1897
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1898

    
1899
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1900

    
1901
	for ($a = 1; $a <= 16; $a++)
1902
		$msg .= $hw_addr;
1903

    
1904
	// send it to the broadcast address using UDP
1905
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1906
	if ($s == false) {
1907
		log_error("Error creating socket!");
1908
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
1909
	} else {
1910
		// setting a broadcast option to socket:
1911
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1912
		if($opt_ret < 0)
1913
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1914
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1915
		socket_close($s);
1916
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1917
		return true;
1918
	}
1919

    
1920
	return false;
1921
}
1922

    
1923
/*
1924
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
1925
 *                             is queuename|qlength|measured_packets
1926
 *                             NOTE: this command takes 5 seconds to run
1927
 */
1928
function gather_altq_queue_stats($dont_return_root_queues) {
1929
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5`;
1930
	$stats_array = split("\n", $stats);
1931
	$queue_stats = array();
1932
	foreach ($stats_array as $stats_line) {
1933
		$match_array = "";
1934
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
1935
			$queue_name = $match_array[1][0];
1936
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
1937
			$speed = $match_array[1][0];
1938
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
1939
			$borrows = $match_array[1][0];
1940
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
1941
			$suspends = $match_array[1][0];
1942
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
1943
			$drops = $match_array[1][0];
1944
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
1945
			$measured = $match_array[1][0];
1946
			if($dont_return_root_queues == true)
1947
				if(stristr($queue_name,"root_") == false)
1948
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
1949
		}
1950
	}
1951
	return $queue_stats;
1952
}
1953

    
1954
/*
1955
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1956
 *					 Useful for finding paths and stripping file extensions.
1957
 */
1958
function reverse_strrchr($haystack, $needle) {
1959
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1960
}
1961

    
1962
/*
1963
 *  backup_config_section($section): returns as an xml file string of
1964
 *                                   the configuration section
1965
 */
1966
function backup_config_section($section) {
1967
	global $config;
1968
	$new_section = &$config[$section];
1969
	/* generate configuration XML */
1970
	$xmlconfig = dump_xml_config($new_section, $section);
1971
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1972
	return $xmlconfig;
1973
}
1974

    
1975
/*
1976
 *  backup_vip_config_section($section): returns as an xml file string of
1977
 *                                   the configuration section
1978
 */
1979
function backup_vip_config_section() {
1980
	global $config;
1981
	$new_section = &$config['virtualip'];
1982
	foreach($new_section['vip'] as $section) {
1983
		if($section['mode'] == "proxyarp") {
1984
			unset($section);
1985
		}
1986
		if($section['advskew'] <> "") {
1987
			$section_val = intval($section['advskew']);
1988
			$section_val=$section_val+100;
1989
			if($section_val > 255)
1990
				$section_val = 255;
1991
			$section['advskew'] = $section_val;
1992
		}
1993
		$temp['vip'][] = $section;
1994
   }
1995
   return $temp;
1996
}
1997

    
1998
/*
1999
 *  restore_config_section($section, new_contents): restore a configuration section,
2000
 *                                                  and write the configuration out
2001
 *                                                  to disk/cf.
2002
 */
2003
function restore_config_section($section, $new_contents) {
2004
	global $config, $g;
2005
	conf_mount_rw();
2006
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
2007
	fwrite($fout, $new_contents);
2008
	fclose($fout);
2009
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
2010
	$config[$section] = &$section_xml;
2011
	unlink($g['tmp_path'] . "/tmpxml");
2012
	write_config("Restored {$section} of config file (maybe from CARP partner)");
2013
	conf_mount_ro();
2014
	return;
2015
}
2016

    
2017
/*
2018
 *  merge_config_section($section, new_contents):   restore a configuration section,
2019
 *                                                  and write the configuration out
2020
 *                                                  to disk/cf.  But preserve the prior
2021
 * 													structure if needed
2022
 */
2023
function merge_config_section($section, $new_contents) {
2024
	global $config;
2025
	conf_mount_rw();
2026
	$fname = get_tmp_filename();
2027
	$fout = fopen($fname, "w");
2028
	fwrite($fout, $new_contents);
2029
	fclose($fout);
2030
	$section_xml = parse_xml_config($fname, $section);
2031
	$config[$section] = $section_xml;
2032
	unlink($fname);
2033
	write_config("Restored {$section} of config file (maybe from CARP partner)");
2034
	conf_mount_ro();
2035
	return;
2036
}
2037

    
2038
/*
2039
 * http_post($server, $port, $url, $vars): does an http post to a web server
2040
 *                                         posting the vars array.
2041
 * written by nf@bigpond.net.au
2042
 */
2043
function http_post($server, $port, $url, $vars) {
2044
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
2045
	$urlencoded = "";
2046
	while (list($key,$value) = each($vars))
2047
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
2048
	$urlencoded = substr($urlencoded,0,-1);
2049
	$content_length = strlen($urlencoded);
2050
	$headers = "POST $url HTTP/1.1
2051
Accept: */*
2052
Accept-Language: en-au
2053
Content-Type: application/x-www-form-urlencoded
2054
User-Agent: $user_agent
2055
Host: $server
2056
Connection: Keep-Alive
2057
Cache-Control: no-cache
2058
Content-Length: $content_length
2059

    
2060
";
2061

    
2062
	$errno = "";
2063
	$errstr = "";
2064
	$fp = fsockopen($server, $port, $errno, $errstr);
2065
	if (!$fp) {
2066
		return false;
2067
	}
2068

    
2069
	fputs($fp, $headers);
2070
	fputs($fp, $urlencoded);
2071

    
2072
	$ret = "";
2073
	while (!feof($fp))
2074
		$ret.= fgets($fp, 1024);
2075
	fclose($fp);
2076

    
2077
	return $ret;
2078
}
2079

    
2080
/*
2081
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
2082
 */
2083
if (!function_exists('php_check_syntax')){
2084
	function php_check_syntax($code_to_check, &$errormessage){
2085
		return false;
2086
		$fout = fopen("/tmp/codetocheck.php","w");
2087
		$code = $_POST['content'];
2088
		$code = str_replace("<?php", "", $code);
2089
		$code = str_replace("?>", "", $code);
2090
		fwrite($fout, "<?php\n\n");
2091
		fwrite($fout, $code_to_check);
2092
		fwrite($fout, "\n\n?>\n");
2093
		fclose($fout);
2094
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
2095
		$output = exec_command($command);
2096
		if (stristr($output, "Errors parsing") == false) {
2097
			echo "false\n";
2098
			$errormessage = '';
2099
			return(false);
2100
		} else {
2101
			$errormessage = $output;
2102
			return(true);
2103
		}
2104
	}
2105
}
2106

    
2107
/*
2108
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
2109
 */
2110
if (!function_exists('php_check_syntax')){
2111
	function php_check_syntax($code_to_check, &$errormessage){
2112
		return false;
2113
		$command = "/usr/local/bin/php -l " . $code_to_check;
2114
		$output = exec_command($command);
2115
		if (stristr($output, "Errors parsing") == false) {
2116
			echo "false\n";
2117
			$errormessage = '';
2118
			return(false);
2119
		} else {
2120
			$errormessage = $output;
2121
			return(true);
2122
		}
2123
	}
2124
}
2125

    
2126
/*
2127
 * rmdir_recursive($path,$follow_links=false)
2128
 * Recursively remove a directory tree (rm -rf path)
2129
 * This is for directories _only_
2130
 */
2131
function rmdir_recursive($path,$follow_links=false) {
2132
	$to_do = glob($path);
2133
	if(!is_array($to_do)) $to_do = array($to_do);
2134
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
2135
		if(file_exists($workingdir)) {
2136
			if(is_dir($workingdir)) {
2137
				$dir = opendir($workingdir);
2138
				while ($entry = readdir($dir)) {
2139
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
2140
						unlink("$workingdir/$entry");
2141
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
2142
						rmdir_recursive("$workingdir/$entry");
2143
				}
2144
				closedir($dir);
2145
				rmdir($workingdir);
2146
			} elseif (is_file($workingdir)) {
2147
				unlink($workingdir);
2148
			}
2149
               	}
2150
	}
2151
	return;
2152
}
2153

    
2154
/*
2155
 *     get_memory()
2156
 *     returns an array listing the amount of
2157
 *     memory installed in the hardware
2158
 *     [0]real and [1]available
2159
 */
2160
function get_memory() {
2161
	if(file_exists("/var/log/dmesg.boot")) {
2162
		$mem = `cat /var/log/dmesg.boot | grep memory`;
2163
		$matches = "";
2164
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2165
			$real = $matches[1];
2166
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2167
			$avail = $matches[1];
2168
		return array($real[0],$avail[0]);
2169
	} else {
2170
		$mem = `dmesg -a`;
2171
		$matches = "";
2172
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2173
			$real = $matches[1];
2174
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2175
			$avail = $matches[1];
2176
		return array($real[0],$avail[0]);
2177
	}
2178
}
2179

    
2180
/*
2181
 *    safe_mkdir($path, $mode = 0755)
2182
 *    create directory if it doesn't already exist and isn't a file!
2183
 */
2184
function safe_mkdir($path, $mode=0755) {
2185
	global $g;
2186

    
2187
	if (!is_file($path) && !is_dir($path)) {
2188
		return @mkdir($path, $mode);
2189
	} else {
2190
		return false;
2191
	}
2192
}
2193

    
2194
/*
2195
 * make_dirs($path, $mode = 0755)
2196
 * create directory tree recursively (mkdir -p)
2197
 */
2198
function make_dirs($path, $mode = 0755) {
2199
	$base = '';
2200
	foreach (explode('/', $path) as $dir) {
2201
		$base .= "/$dir";
2202
		if (!is_dir($base)) {
2203
			if (!@mkdir($base, $mode))
2204
				return false;
2205
		}
2206
	}
2207
	return true;
2208
}
2209

    
2210
/*
2211
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
2212
 */
2213
function call_pfsense_method($method, $params, $timeout = 0) {
2214
	global $g, $config;
2215

    
2216
	$ip = gethostbyname($g['product_website']);
2217
	if($ip == $g['product_website'])
2218
		return false;
2219
	global $g, $config;
2220
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
2221
	$xmlrpc_path = $g['xmlrpcpath'];
2222
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
2223
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
2224
	$resp = $cli->send($msg, $timeout);
2225
	if(!$resp) {
2226
		log_error("XMLRPC communication error: " . $cli->errstr);
2227
		return false;
2228
	} elseif($resp->faultCode()) {
2229
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
2230
		return false;
2231
	} else {
2232
		return XML_RPC_Decode($resp->value());
2233
	}
2234
}
2235

    
2236
/*
2237
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
2238
 */
2239
function check_firmware_version($tocheck = "all", $return_php = true) {
2240
	global $g, $config;
2241
	$ip = gethostbyname($g['product_website']);
2242
	if($ip == $g['product_website'])
2243
		return false;
2244
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
2245
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
2246
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
2247
		"platform" => trim(file_get_contents('/etc/platform'))
2248
		);
2249
	if($tocheck == "all") {
2250
		$params = $rawparams;
2251
	} else {
2252
		foreach($tocheck as $check) {
2253
			$params['check'] = $rawparams['check'];
2254
			$params['platform'] = $rawparams['platform'];
2255
		}
2256
	}
2257
	if($config['system']['firmware']['branch']) {
2258
		$params['branch'] = $config['system']['firmware']['branch'];
2259
	}
2260
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
2261
		return false;
2262
	} else {
2263
		$versions["current"] = $params;
2264
	}
2265
	return $versions;
2266
}
2267

    
2268
function get_disk_info() {
2269
	$diskout = "";
2270
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
2271
	return explode(' ', $diskout[0]);
2272
	// $size, $used, $avail, $cap
2273
}
2274

    
2275
/****f* pfsense-utils/display_top_tabs
2276
 * NAME
2277
 *   display_top_tabs - display tabs with rounded edges
2278
 * INPUTS
2279
 *   $text      - array of tabs
2280
 * RESULT
2281
 *   null
2282
 ******/
2283
function display_top_tabs(& $tab_array) {
2284
	global $HTTP_SERVER_VARS;
2285
	global $config;
2286
	global $g;
2287

    
2288
	/*  does the user have access to this tab?
2289
	 *  master user has access to everything.
2290
	 *  if the user does not have access, simply
2291
	 *  unset the tab item.
2292
	 */
2293

    
2294
	$tab_temp = array ();
2295
	foreach ($tab_array as $ta)
2296
		if(isAllowedPage($ta[2]))
2297
			$tab_temp[] = $ta;
2298
	/*
2299
		// FIXME :	if the checks are not good enough
2300
		//			in isAllowedPage, it needs to be
2301
		//			fixed instead of kludging here
2302

    
2303
		// TODO: humm what shall we do with pkg_edit.php and pkg.php?
2304
		if ((strpos($link, "pkg.php")) !== false || (strpos($link, "pkg_edit.php")) !== false) {
2305
			$pos_equal = strpos($link, "=");
2306
			$pos_xmlsuffix = strpos($link, ".xml");
2307
			// do we match an absolute url including ?xml= foo
2308
			if(!isAllowedPage($link, $allowed))
2309
				$link = substr($link, $pos_equal +1, ($pos_xmlsuffix - $pos_equal +3));
2310
		}
2311
		// next check - what if the basename contains a query string?
2312
		if ((strpos($link, "?")) !== false) {
2313
			$pos_qmark = strpos($link, "?");
2314
			$link = substr($link, 0, $pos_qmark);
2315
		}
2316
		$authorized_text = print_r($allowed, true);
2317
		if(is_array($authorized))
2318
			if (in_array(basename($link), $authorized))
2319
	*/
2320

    
2321
	unset ($tab_array);
2322
	$tab_array = & $tab_temp;
2323

    
2324
	echo "<table cellpadding='0' cellspacing='0'>\n";
2325
	echo " <tr>\n";
2326
	$tabscounter = 0;
2327
	foreach ($tab_array as $ta) {
2328
		if ($ta[1] == true) {
2329
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
2330
		} else {
2331
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
2332
		}
2333
		$tabscounter++;
2334
	}
2335
	echo "</tr>\n<tr>\n";
2336
	foreach ($tab_array as $ta) {
2337
		if ($ta[1] == true) {
2338
			echo "  <td height=\"15\" valign=\"middle\" bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
2339
			echo "&nbsp;&nbsp;&nbsp;";
2340
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2341
		} else {
2342
			echo "  <td height=\"15\" valign=\"middle\" bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
2343
			echo "<font color='white'>{$ta[0]}</font></a>&nbsp;&nbsp;&nbsp;";
2344
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2345
		}
2346
	}
2347
	echo "</tr>\n<tr>\n";
2348
	foreach ($tab_array as $ta) {
2349
		if ($ta[1] == true) {
2350
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2351
		} else {
2352
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2353
		}
2354
		$tabscounter++;
2355
	}
2356
	echo " </tr>\n";
2357
	echo "</table>\n";
2358

    
2359
	echo "<script type=\"text/javascript\">";
2360
	echo "NiftyCheck();\n";
2361
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
2362
	for ($x = 0; $x < $tabscounter; $x++)
2363
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
2364
	echo "</script>";
2365
}
2366

    
2367

    
2368
/****f* pfsense-utils/display_topbar
2369
 * NAME
2370
 *   display_topbar - top a table off with rounded edges
2371
 * INPUTS
2372
 *   $text	- (optional) Text to include in bar
2373
 * RESULT
2374
 *   null
2375
 ******/
2376
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
2377
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
2378
	echo "       <tr height='1'>\n";
2379
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
2380
	echo "		<div id='topbar'></div></td>\n";
2381
	echo "       </tr>\n";
2382
	echo "       <tr height='1'>\n";
2383
	if ($text != "")
2384
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
2385
	else
2386
		echo "         <td height='1' class='listtopic'></td>\n";
2387
	echo "       </tr>\n";
2388
	echo "     </table>";
2389
	echo "<script type=\"text/javascript\">";
2390
	echo "NiftyCheck();\n";
2391
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
2392
	echo "</script>";
2393
}
2394

    
2395
/****f* pfsense-utils/generate_random_mac_address
2396
 * NAME
2397
 *   generate_random_mac - generates a random mac address
2398
 * INPUTS
2399
 *   none
2400
 * RESULT
2401
 *   $mac - a random mac address
2402
 ******/
2403
function generate_random_mac_address() {
2404
	$mac = "02";
2405
	for($x=0; $x<5; $x++)
2406
		$mac .= ":" . dechex(rand(16, 255));
2407
	return $mac;
2408
}
2409

    
2410
/****f* pfsense-utils/strncpy
2411
 * NAME
2412
 *   strncpy - copy strings
2413
 * INPUTS
2414
 *   &$dst, $src, $length
2415
 * RESULT
2416
 *   none
2417
 ******/
2418
function strncpy(&$dst, $src, $length) {
2419
	if (strlen($src) > $length) {
2420
		$dst = substr($src, 0, $length);
2421
	} else {
2422
		$dst = $src;
2423
	}
2424
}
2425

    
2426
/****f* pfsense-utils/reload_interfaces_sync
2427
 * NAME
2428
 *   reload_interfaces - reload all interfaces
2429
 * INPUTS
2430
 *   none
2431
 * RESULT
2432
 *   none
2433
 ******/
2434
function reload_interfaces_sync() {
2435
	global $config, $g, $debug;
2436

    
2437
	$shutdown_webgui_needed = false;
2438

    
2439
	touch("{$g['tmp_path']}/reloading_all");
2440

    
2441
	if($debug)
2442
		log_error("reload_interfaces_sync() is starting.");
2443

    
2444
	if(file_exists("{$g['tmp_path']}/config.cache"))
2445
		unlink("{$g['tmp_path']}/config.cache");
2446

    
2447
	/* parse config.xml again */
2448
	$config = parse_config(true);
2449

    
2450
	$wan_if = $config['interfaces']['wan']['if'];
2451
	$lan_if = $config['interfaces']['lan']['if'];
2452

    
2453
	if($debug)
2454
		log_error("Cleaning up Interfaces");
2455

    
2456
	/* if list */
2457
        $iflist = get_configured_interface_list(true);
2458

    
2459
	foreach ($iflist as $ifent => $ifname) {
2460
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2461

    
2462
		if(stristr($ifname, "lo0") == true)
2463
			continue;
2464
		/* do not process wan interface, its mandatory */
2465
                if(stristr($ifname, "$wan_if") == true)
2466
                        continue;
2467
                /* do not process lan interface, its mandatory */
2468
                if(stristr($ifname, "$lan_if") == true)
2469
                        continue;
2470
		if($debug)
2471
			log_error("Downing and deleting $ifname_real - $ifname");
2472
		mwexec("/sbin/ifconfig {$ifname_real} down");
2473
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2474
	}
2475

    
2476
	/* set up interfaces */
2477
	interfaces_configure();
2478

    
2479
	/* set up static routes */
2480
	if($debug)
2481
		log_error("Configuring system Routing");
2482
	system_routing_configure();
2483

    
2484
	/* enable routing */
2485
	if($debug)
2486
		log_error("Enabling system routing");
2487
	system_routing_enable();
2488

    
2489
	/* setup captive portal if needed */
2490
	if($debug)
2491
		log_error("Configuring Captive portal");
2492
	captiveportal_configure();
2493

    
2494
	/* restart webConfigurator if needed */
2495
	if($shutdown_webgui_needed == true)
2496
		touch("/tmp/restart_webgui");
2497

    
2498
	/* start devd back up */
2499
	mwexec("/bin/rm /tmp/reload*");
2500

    
2501
	/* remove reloading_all trigger */
2502
	if($debug)
2503
		log_error("Removing {$g['tmp_path']}/reloading_all");
2504
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2505
}
2506

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

    
2519
/****f* pfsense-utils/reload_interfaces
2520
 * NAME
2521
 *   reload_interfaces - triggers a reload of all interfaces
2522
 * INPUTS
2523
 *   none
2524
 * RESULT
2525
 *   none
2526
 ******/
2527
function reload_interfaces() {
2528
	touch("/tmp/reload_interfaces");
2529
}
2530

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

    
2542
	$g['booting'] = false;
2543

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

    
2546
	$shutdown_webgui_needed = false;
2547

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

    
2551
	/* parse config.xml again */
2552
	$config = parse_config(true);
2553

    
2554
	/* set up our timezone */
2555
	system_timezone_configure();
2556

    
2557
	/* set up our hostname */
2558
	system_hostname_configure();
2559

    
2560
	/* make hosts file */
2561
	system_hosts_generate();
2562

    
2563
	/* generate resolv.conf */
2564
	system_resolvconf_generate();
2565

    
2566
	/* Set up our loopback interface */
2567
	interfaces_loopback_configure();
2568

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

    
2572
	$wan_if = $config['interfaces']['wan']['if'];
2573
	$lan_if = $config['interfaces']['lan']['if'];
2574

    
2575
	/* if list */
2576
	$iflist = get_configured_interface_list();
2577

    
2578
	foreach ($iflist as $ifent => $ifname) {
2579
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2580
		if(stristr($ifname, "lo0") == true)
2581
			continue;
2582
		/* do not process wan interface, its mandatory */
2583
		if($wan_if == $ifname_real)
2584
			continue;
2585
		/* do not process lan interface, its mandatory */
2586
		if($lan_if == $ifname_real)
2587
			continue;
2588
		mwexec("/sbin/ifconfig {$ifname_real} down");
2589
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2590
	}
2591

    
2592
	/* set up interfaces */
2593
	interfaces_configure();
2594

    
2595
	/* set up static routes */
2596
	system_routing_configure();
2597

    
2598
	/* enable routing */
2599
	system_routing_enable();
2600

    
2601
	/* ensure passwords are sync'd */
2602
//	system_password_configure();
2603

    
2604
	/* start dnsmasq service */
2605
	services_dnsmasq_configure();
2606

    
2607
	/* start dyndns service */
2608
	services_dyndns_configure();
2609

    
2610
	/* start DHCP service */
2611
	services_dhcpd_configure();
2612

    
2613
	/* configure cron service */
2614
	configure_cron();
2615

    
2616
	/* start the NTP client */
2617
	system_ntp_configure();
2618

    
2619
	/* start ftp proxy helpers if they are enabled */
2620
	system_start_ftp_helpers();
2621

    
2622
	/* start the captive portal */
2623
	captiveportal_configure();
2624

    
2625
        /* reload the filter */
2626
	filter_configure_sync();
2627

    
2628
	/* sync pw database */
2629
	conf_mount_rw();
2630
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2631
	conf_mount_ro();
2632

    
2633
	/* restart sshd */
2634
	touch("/tmp/start_sshd");
2635

    
2636
	/* restart webConfigurator if needed */
2637
	if($shutdown_webgui_needed == true)
2638
		touch("/tmp/restart_webgui");
2639

    
2640
	mwexec("/bin/rm /tmp/reload*");
2641

    
2642
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2643

    
2644
}
2645

    
2646
function auto_login($status) {
2647
	$gettytab = file_get_contents("/etc/gettytab");
2648
	$getty_split = split("\n", $gettytab);
2649
	conf_mount_rw();
2650
	$fd = fopen("/etc/gettytab", "w");
2651
	foreach($getty_split as $gs) {
2652
		if(stristr($gs, ":ht:np:sp#115200") ) {
2653
			if($status == true) {
2654
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
2655
			} else {
2656
				fwrite($fd, "	:ht:np:sp#115200:\n");
2657
			}
2658
		} else {
2659
			fwrite($fd, "{$gs}\n");
2660
		}
2661
	}
2662
	fclose($fd);
2663
	conf_mount_ro();
2664
}
2665

    
2666
function setup_serial_port() {
2667
	global $g, $config;
2668
	conf_mount_rw();
2669
	/* serial console - write out /boot.config */
2670
	if(file_exists("/boot.config"))
2671
		$boot_config = file_get_contents("/boot.config");
2672
	else
2673
		$boot_config = "";
2674

    
2675
	if($g['platform'] <> "cdrom") {
2676
		$boot_config_split = split("\n", $boot_config);
2677
		$fd = fopen("/boot.config","w");
2678
		if($fd) {
2679
			foreach($boot_config_split as $bcs) {
2680
				if(stristr($bcs, "-D")) {
2681
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2682
				} else {
2683
					if($bcs <> "")
2684
						fwrite($fd, "{$bcs}\n");
2685
				}
2686
			}
2687
			if(isset($config['system']['enableserial'])) {
2688
				fwrite($fd, "-D");
2689
			}
2690
			fclose($fd);
2691
		}
2692
		/* serial console - write out /boot/loader.conf */
2693
		$boot_config = file_get_contents("/boot/loader.conf");
2694
		$boot_config_split = split("\n", $boot_config);
2695
		$fd = fopen("/boot/loader.conf","w");
2696
		if($fd) {
2697
			foreach($boot_config_split as $bcs) {
2698
				if(stristr($bcs, "console")) {
2699
					/* DONT WRITE OUT, WE'LL DO IT LATER */
2700
				} else {
2701
					if($bcs <> "")
2702
						fwrite($fd, "{$bcs}\n");
2703
				}
2704
			}
2705
			if(isset($config['system']['enableserial'])) {
2706
				fwrite($fd, "console=\"comconsole\"\n");
2707
			}
2708
			fclose($fd);
2709
		}
2710
	}
2711
	$ttys = file_get_contents("/etc/ttys");
2712
	$ttys_split = split("\n", $ttys);
2713
	$fd = fopen("/etc/ttys", "w");
2714
	foreach($ttys_split as $tty) {
2715
		if(stristr($tty, "ttyd0")) {
2716
			if(isset($config['system']['enableserial'])) {
2717
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
2718
			} else {
2719
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
2720
			}
2721
		} else {
2722
			fwrite($fd, $tty . "\n");
2723
		}
2724
	}
2725
	fclose($fd);
2726
	if(isset($config['system']['disableconsolemenu'])) {
2727
		auto_login(false);
2728
	} else {
2729
		auto_login(true);
2730
	}
2731
	conf_mount_ro();
2732
	return;
2733
}
2734

    
2735
function print_value_list($list, $count = 10, $separator = ",") {
2736
	$list = implode($separator, array_slice($list, 0, $count));
2737
	if(count($list) < $count) {
2738
		$list .= ".";
2739
	} else {
2740
		$list .= "...";
2741
	}
2742
	return $list;
2743
}
2744

    
2745
function enable_rrd_graphing() {
2746
	global $config, $g, $altq_list_queues;
2747

    
2748
	if($g['booting']) 
2749
		echo "Generating RRD graphs...";
2750

    
2751
	$rrddbpath = "/var/db/rrd/";
2752
	$rrdgraphpath = "/usr/local/www/rrd";
2753

    
2754
	$traffic = "-traffic.rrd";
2755
	$packets = "-packets.rrd";
2756
	$states = "-states.rrd";
2757
	$quality = "-quality.rrd";
2758
	$wireless = "-wireless.rrd";
2759
	$queues = "-queues.rrd";
2760
	$queuesdrop = "-queuedrops.rrd";
2761
	$spamd = "-spamd.rrd";
2762
	$proc = "-processor.rrd";
2763
	$mem = "-memory.rrd";
2764

    
2765
	$rrdtool = "/usr/local/bin/rrdtool";
2766
	$netstat = "/usr/bin/netstat";
2767
	$awk = "/usr/bin/awk";
2768
	$tar = "/usr/bin/tar";
2769
	$pfctl = "/sbin/pfctl";
2770
	$sysctl = "/sbin/sysctl";
2771
	$php = "/usr/local/bin/php";
2772
	$top = "/usr/bin/top";
2773
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2774
	$ifconfig = "/sbin/ifconfig";
2775

    
2776
	$rrdtrafficinterval = 60;
2777
	$rrdqualityinterval = 60;
2778
	$rrdwirelessinterval = 60;
2779
	$rrdqueuesinterval = 60;
2780
	$rrdqueuesdropinterval = 60;
2781
	$rrdpacketsinterval = 60;
2782
	$rrdstatesinterval = 60;
2783
	$rrdspamdinterval = 60;
2784
	$rrdlbpoolinterval = 60;
2785
	$rrdprocinterval = 60;
2786
	$rrdmeminterval = 60;
2787

    
2788
	$trafficvalid = $rrdtrafficinterval * 2;
2789
	$qualityvalid = $rrdqualityinterval * 2;
2790
	$wirelessvalid = $rrdwirelessinterval * 2;
2791
	$queuesvalid = $rrdqueuesinterval * 2;
2792
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2793
	$packetsvalid = $rrdpacketsinterval * 2;
2794
	$statesvalid = $rrdstatesinterval*2;
2795
	$spamdvalid = $rrdspamdinterval * 2;
2796
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2797
	$procvalid = $rrdlbpoolinterval * 2;
2798
	$memvalid = $rrdmeminterval * 2;
2799

    
2800
	/* Asume GigE for now */
2801
	$downstream = 125000000;
2802
	$upstream = 125000000;
2803

    
2804
	/* read the shaper config */
2805
	read_altq_config();
2806

    
2807
	$rrdrestore = "";
2808
	$rrdreturn = "";
2809

    
2810
	if (isset ($config['rrd']['enable'])) {
2811

    
2812
		/* create directory if needed */
2813
		if (!is_dir("$rrddbpath")) {
2814
			mkdir("$rrddbpath", 0755);
2815
		}
2816

    
2817
		if ($g['booting']) {
2818
			if ($g['platform'] != "pfSense") {
2819
				/* restore the databases, if we have one */
2820
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
2821
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2822
					if((int)$rrdrestore <> 0) {
2823
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore[0]\n");
2824
					}
2825
				}
2826
			}
2827
		}
2828

    
2829
		/* db update script */
2830
		$rrdupdatesh = "#!/bin/sh\n";
2831
		$rrdupdatesh .= "\n";
2832
		$rrdupdatesh .= "counter=1\n";
2833
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2834
		$rrdupdatesh .= "do\n";
2835
		$rrdupdatesh .= "";
2836

    
2837
		$i = 0;
2838
		$vfaces = array (
2839
			"vlan.?*",
2840
			"enc.?*"
2841
		);
2842
		$ifdescrs = get_interface_list(true, true, $vfaces);
2843
		$ifdescrs['enc0']['friendly'] = "ipsec";
2844
		$ifdescrs['enc0']['descr'] = "IPsec";
2845
		$ifdescrs['enc0']['up'] = true;
2846

    
2847
		foreach ($ifdescrs as $realif => $ifdescr) {
2848
			$ifname = $ifdescr['friendly'];
2849
			$state = $ifdescr['up'];
2850

    
2851
			/* skip interfaces that do not have a friendly name */
2852
			if ("$ifname" == "") {
2853
				continue;
2854
			}
2855

    
2856
			/* or are down */
2857
			if (!$state) {
2858
				continue;
2859
			}
2860

    
2861
			/* TRAFFIC, set up the rrd file */
2862
			if (!file_exists("$rrddbpath$ifname$traffic")) {
2863
				/* create rrd file if it does not exist */
2864
				log_error("Create RRD database $rrddbpath$ifname$traffic");
2865
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
2866
				$rrdcreate .= "DS:in:COUNTER:$trafficvalid:0:$downstream ";
2867
				$rrdcreate .= "DS:out:COUNTER:$trafficvalid:0:$upstream ";
2868
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2869
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2870
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2871
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2872
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
2873

    
2874
				$rrdcreateoutput = array();
2875
				$rrdcreatereturn = "";
2876

    
2877
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2878
				if ($rrdcreatereturn != 0) {
2879
					log_error("RRD create failed exited with $rrdcreatereturn, the
2880
							error is: $rrdcreateoutput[0]\n");
2881
				}
2882
			}
2883

    
2884
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2885
			if($g['booting']) {
2886
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
2887
			}
2888

    
2889
			$rrdupdatesh .= "\n";
2890
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
2891
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
2892
			if(! is_macaddr(get_interface_mac($realif))) {
2893
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$6 \":\" \$9}'`\n";
2894
			} else {
2895
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7 \":\" \$10}'`\n";
2896
			}
2897

    
2898
			/* PACKETS, set up the rrd file */
2899
			if (!file_exists("$rrddbpath$ifname$packets")) {
2900
				/* create rrd file if it does not exist */
2901
				log_error("Create RRD database $rrddbpath$ifname$packets");
2902
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
2903
				$rrdcreate .= "DS:in:COUNTER:$packetsvalid:0:$downstream ";
2904
				$rrdcreate .= "DS:out:COUNTER:$packetsvalid:0:$upstream ";
2905
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2906
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2907
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2908
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2909
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
2910

    
2911
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2912
				if ($rrdcreatereturn != 0) {
2913
					log_error("RRD create failed exited with $rrdcreatereturn, the
2914
							error is: $rrdcreateoutput[0]\n");
2915
				}
2916
			}
2917

    
2918
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2919
			if($g['booting']) {
2920
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
2921
			}
2922

    
2923
			$rrdupdatesh .= "\n";
2924
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
2925
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
2926
			if(! is_macaddr(get_interface_mac($realif))) {
2927
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$4 \":\" \$7}'`\n";
2928
			} else {
2929
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5 \":\" \$8}'`\n";
2930
			}
2931

    
2932
			/* QUALITY, create link quality database */
2933
			/* if the interface has a gateway defined, use it */
2934
			if(interface_has_gateway($ifname)) {
2935
				if (!file_exists("$rrddbpath$ifname$quality")) {
2936
					/* create rrd file if it does not exist */
2937
					log_error("Create RRD database $rrddbpath$ifname$quality");
2938
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
2939
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
2940
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
2941
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2942
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2943
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2944
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2945
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
2946

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

    
2953
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
2954
				if($g['booting']) {
2955
					exec("$rrdtool update $rrddbpath$ifname$quality N:U:U");
2956
				}
2957
				
2958
				$numpings = 5;
2959
				$monitorip = lookup_gateway_monitor_ip_by_name($config['interfaces'][$ifname]['gateway']);
2960
				/* the ping test function. We call this on the last line */
2961
				$rrdupdatesh .= "# Quality collector for {$ifname}\n";
2962
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
2963
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
2964
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
2965
				$rrdupdatesh .= "	local out_{$ifname}\n";
2966
				$rrdupdatesh .= "	out_{$ifname}=`ping -c $numpings -q $monitorip`\n";
2967
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
2968
				$rrdupdatesh .= "		packetloss_{$ifname}=`echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1`\n";
2969
				$rrdupdatesh .= "		roundtrip_{$ifname}=`echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/'`\n";
2970
				$rrdupdatesh .= "	fi\n";
2971
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
2972
				$rrdupdatesh .= "}\n\n";
2973

    
2974
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
2975
			}
2976

    
2977
			/* WIRELESS, set up the rrd file */
2978
			if($config['interfaces'][$ifname]['wireless']['mode'] == "bss") {
2979
				if (!file_exists("$rrddbpath$ifname$wireless")) {
2980
					/* create rrd file if it does not exist */
2981
					log_error("Create RRD database $rrddbpath$ifname$wireless");
2982
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$wireless --step $rrdwirelessinterval ";
2983
					$rrdcreate .= "DS:snr:GAUGE:$wirelessvalid:0:1000 ";
2984
					$rrdcreate .= "DS:rate:GAUGE:$wirelessvalid:0:1000 ";
2985
					$rrdcreate .= "DS:channel:GAUGE:$wirelessvalid:0:1000 ";
2986
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
2987
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
2988
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
2989
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
2990
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
2991
	
2992
					$rrdcreateoutput = array();
2993
					$rrdcreatereturn = "";
2994

    
2995
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2996
					if ($rrdcreatereturn != 0) {
2997
						log_error("RRD create failed exited with $rrdcreatereturn, the
2998
								error is: $rrdcreateoutput[0]\n");
2999
					}
3000
				}
3001

    
3002
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3003
				if($g['booting']) {
3004
					exec("$rrdtool update $rrddbpath$ifname$wireless N:U:U:U");
3005
				}
3006

    
3007
				$rrdupdatesh .= "\n";
3008
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
3009
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\\\n";
3010
				$rrdupdatesh .= "`$ifconfig {$realif} list ap| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
3011
			}
3012

    
3013
				/* QUEUES, set up the queues databases */
3014
				if ($altq_list_queues[$ifname]) {
3015
					$altq =& $altq_list_queues[$ifname];
3016
					/* NOTE: Is it worth as its own function?! */
3017
					switch ($altq->GetBwscale()) {
3018
                                        case "Gb":
3019
                                        	$factor = 1000 * 1000 * 1000;
3020
                                                break;
3021
                                        case "Mb":
3022
                                                $factor = 1000 * 1000;
3023
                                                break;
3024
                                        case "Kb":
3025
                                                $factor = 1000;
3026
                                                break;
3027
                                        case "b":
3028
                                        default:
3029
                                                $factor = 1;
3030
                                                break;
3031
                                        }
3032
					$qbandwidth = $altq->GetBandwidth() * $factor;
3033
					if ($qbandwidth <=0)
3034
						$qbandwidth = 100 * 1000 * 1000; /* 100Mbit */
3035
					$qlist =& $altq->get_queue_list($notused);
3036
					if (!file_exists("$rrddbpath$ifname$queues")) {
3037
						/* create rrd file if it does not exist */
3038
						log_error("Create RRD database $rrddbpath$ifname$queues");
3039
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
3040
						/* loop list of shaper queues */
3041
						$q = 0;
3042
						foreach ($qlist as $qname => $q) {
3043
							$rrdcreate .= "DS:$qname:COUNTER:$queuesvalid:0:$qbandwidth ";
3044
						}
3045

    
3046
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3047
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3048
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3049
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3050
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3051

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

    
3059
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
3060
						/* create rrd file if it does not exist */
3061
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
3062
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
3063
						/* loop list of shaper queues */
3064
						$q = 0;
3065
						foreach ($qlist as $qname => $q) {
3066
							$rrdcreate .= "DS:$qname:COUNTER:$queuesdropvalid:0:$qbandwidth ";
3067
						}
3068

    
3069
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3070
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3071
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3072
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3073
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3074

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

    
3081
					if($g['booting']) {
3082
						$rrdqcommand = "-t ";
3083
						$rrducommand = "N";
3084
						$q = 0;
3085
						foreach ($qlist as $qname => $q) {
3086
							if($q == 0) {
3087
								$rrdqcommand .= "{$qname}";
3088
							} else {
3089
								$rrdqcommand .= ":{$qname}";
3090
							}
3091
							$q++;
3092
							$rrducommand .= ":U";
3093
						}
3094
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3095
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3096
					}
3097

    
3098
					/* awk function to gather shaper data */
3099
					/* yes, it's special */
3100
					$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
3101
					$rrdupdatesh .= "{ ";
3102
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3103
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3104
					$rrdupdatesh .= "q=1; ";
3105
					$rrdupdatesh .= "} ";
3106
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3107
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
3108
					$rrdupdatesh .= "q=0; ";
3109
					$rrdupdatesh .= "} ";
3110
					$rrdupdatesh .= "} END { ";
3111
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3112
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3113
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3114
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3115

    
3116
					$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
3117
					$rrdupdatesh .= "{ ";
3118
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3119
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3120
					$rrdupdatesh .= "q=1; ";
3121
					$rrdupdatesh .= "} ";
3122
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3123
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
3124
					$rrdupdatesh .= "q=0; ";
3125
					$rrdupdatesh .= "} ";
3126
					$rrdupdatesh .= "} END { ";
3127
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3128
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3129
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3130
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3131
				}
3132
		}
3133
		$i++;
3134

    
3135
		/* System only statistics */
3136
		$ifname = "system";
3137

    
3138
			/* STATES, create pf states database */
3139
			if(! file_exists("$rrddbpath$ifname$states")) {
3140
				/* create rrd file if it does not exist */
3141
				log_error("Create RRD database $rrddbpath$ifname$states");
3142
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3143
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3144
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3145
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3146
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3147
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3148
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3149
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3150
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3151
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3152
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3153

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

    
3161
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3162
			if($g['booting']) {
3163
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
3164
			}
3165

    
3166
 			/* the pf states gathering function. */
3167
 			$rrdupdatesh .= "\n";
3168
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
3169
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
3170
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3171
 			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3172
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3173
 			$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";
3174
 			$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";
3175
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3176

    
3177
			/* End pf states statistics */
3178

    
3179
			/* CPU, create CPU statistics database */
3180
			if(! file_exists("$rrddbpath$ifname$proc")) {
3181
				/* create rrd file if it does not exist */
3182
				log_error("Create RRD database $rrddbpath$ifname$proc");
3183
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3184
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3185
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3186
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3187
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3188
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3189
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3190
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3191
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3192
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3193
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3194

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

    
3202
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3203
			if($g['booting']) {
3204
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
3205
			}
3206

    
3207
 			/* the CPU stats gathering function. */
3208
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { ";
3209
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } ";
3210
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { ";
3211
			$rrdupdatesh .= "processes = \$1; ";
3212
			$rrdupdatesh .= "} ";
3213
			$rrdupdatesh .= "else if ( \$1 == \"CPU\" ) { ";
3214
			$rrdupdatesh .= "user = \$3; ";
3215
			$rrdupdatesh .= "nice = \$5; ";
3216
			$rrdupdatesh .= "sys = \$7; ";
3217
			$rrdupdatesh .= "interrupt = \$9; ";
3218
			$rrdupdatesh .= "} ";
3219
			$rrdupdatesh .= "} END { ";
3220
			$rrdupdatesh .= "printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes ";
3221
			$rrdupdatesh .= "}'`\n\n";
3222

    
3223
			/* End CPU statistics */
3224

    
3225
			/* Memory, create Memory statistics database */
3226
			if(! file_exists("$rrddbpath$ifname$mem")) {
3227
				/* create rrd file if it does not exist */
3228
				log_error("Create RRD database $rrddbpath$ifname$mem");
3229
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$mem --step $rrdmeminterval ";
3230
				$rrdcreate .= "DS:active:GAUGE:$memvalid:0:10000000 ";
3231
				$rrdcreate .= "DS:inactive:GAUGE:$memvalid:0:10000000 ";
3232
				$rrdcreate .= "DS:free:GAUGE:$memvalid:0:10000000 ";
3233
				$rrdcreate .= "DS:cache:GAUGE:$memvalid:0:10000000 ";
3234
				$rrdcreate .= "DS:wire:GAUGE:$memvalid:0:10000000 ";
3235
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3236
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3237
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3238
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3239
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3240
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3241
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3242
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3243
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3244
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3245
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3246
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3247

    
3248
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3249
				if($rrdcreatereturn != 0) {
3250
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3251
						error is: $rrdcreateoutput[0]\n");
3252
				}
3253
			}
3254

    
3255
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3256
			if($g['booting']) {
3257
				exec("$rrdtool update $rrddbpath$ifname$mem N:U:U:U:U:U");
3258
			}
3259

    
3260
 			/* the Memory stats gathering function. */
3261
 			$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 | ";
3262
			$rrdupdatesh .= " $awk '{getline active;getline inactive;getline free;getline cache;getline wire;printf \"$rrdtool update $rrddbpath$ifname$mem N:\"";
3263
			$rrdupdatesh .= "((active/$0) * 100)\":\"((inactive/$0) * 100)\":\"((free/$0) * 100)\":\"((cache/$0) * 100)\":\"(wire/$0 * 100)}'`\n\n";
3264
			
3265
			/* End Memory statistics */
3266

    
3267
			/* SPAMD, set up the spamd rrd file */
3268
			if (isset($config['installedpackages']['spamdsettings']) &&
3269
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
3270
				/* set up the spamd rrd file */
3271
				if (!file_exists("$rrddbpath$ifname$spamd")) {
3272
						/* create rrd file if it does not exist */
3273
						log_error("Create RRD database $rrddbpath$ifname$spamd");
3274
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
3275
						$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
3276
						$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
3277
						$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3278
						$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3279
						$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3280
						$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3281
						$rrdcreate .= "RRA:MIN:0.5:1440:1500 ";
3282
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3283
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3284
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3285
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3286
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3287
						$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3288
						$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3289
						$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3290
						$rrdcreate .= "RRA:MAX:0.5:720:1000 ";
3291
						$rrdcreate .= "RRA:MAX:0.5:1440:1500 ";
3292

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

    
3300
				$rrdupdatesh .= "\n";
3301
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3302
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3303
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3304

    
3305
			}
3306
		/* End System statistics */
3307

    
3308
		$rrdupdatesh .= "sleep 60\n";
3309
		$rrdupdatesh .= "done\n";
3310
		log_error("Creating rrd update script");
3311
		/* write the rrd update script */
3312
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3313
		$fd = fopen("$updaterrdscript", "w");
3314
		fwrite($fd, "$rrdupdatesh");
3315
		fclose($fd);
3316

    
3317
		/* kill off traffic collectors */
3318
		kill_traffic_collector();
3319

    
3320
		/* start traffic collector */
3321
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3322

    
3323
	} else {
3324
		/* kill off traffic collectors */
3325
		kill_traffic_collector();
3326
	}
3327

    
3328
	if($g['booting']) 
3329
		echo "done.\n";
3330
		
3331
}
3332

    
3333
function kill_traffic_collector() {
3334
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
3335
}
3336

    
3337
function update_filter_reload_status($text) {
3338
	global $g;
3339
	config_lock();
3340
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3341
	fwrite($fd, $text);
3342
	fclose($fd);
3343
	config_unlock();
3344
}
3345

    
3346
function get_interface_gateway($interface) {
3347
        global $config, $g;
3348

    
3349
        /* if wan is requested, return it */
3350
        if($interface == "wan")
3351
                return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
3352

    
3353
	$iflist = get_configured_interface_with_descr();
3354
	/* 
3355
	 * XXX: This is silly at first, but we may be called with the interface
3356
	 *	descr for no apparent reason!!!
3357
	 */
3358
	foreach ($iflist as $ifent => $ifdesc) {
3359
		if ($ifent == $interface || $ifdesc == $interface) {
3360
			$interface = $ifent;
3361
			break;
3362
		}
3363
	}
3364

    
3365
	$gw = NULL;
3366

    
3367
	$gwcfg = $config['interfaces'][$interface];
3368
        if (is_ipaddr($gwcfg['gateway']))
3369
        	$gw = $gwcfg['gateway'];
3370
        else if ($gwcfg['gateway'] <> "") {
3371
        	if (is_array($config['gateways']['gateway_item']))
3372
                	foreach($config['gateways']['gateway_item'] as $gateway) {
3373
                                if($gateway['name'] == $gwcfg['gateway']) {
3374
                                        $gw = $gateway['gateway'];
3375
                        		break;
3376
                		}
3377
        		}
3378
        } 
3379
	
3380
	// for dynamic interfaces we handle them through the $interface_router file.
3381
	if (!is_ipaddr($gw)) {
3382
        	$realif = get_real_wan_interface($interface);
3383
        	if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
3384
                	$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3385
                	$gw = rtrim($gw);
3386
        	}
3387
	}
3388

    
3389
        /* return gateway */
3390
        return $gw;
3391
}
3392

    
3393
/* DHCP enabled on any interfaces? */
3394
function is_dhcp_server_enabled() 
3395
{
3396
	global $config, $g;
3397

    
3398
	$dhcpdenable = false;
3399
	
3400
	if (!is_array($config['dhcpd']))
3401
		return false;
3402

    
3403
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
3404
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!link_int_to_bridge_interface($dhcpif)))))
3405
			$dhcpdenable = true;
3406
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!link_int_to_bridge_interface($dhcpif)))))
3407
			$dhcpdenable = true;
3408
	}
3409

    
3410
	return $dhcpdenable;
3411
}
3412

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

    
3434
	/* loop interfaces, check config for outbound */
3435
	foreach ($ifdescrs as $ifdescr => $ifname) {
3436
		$friendly = $ifname['friendly'];
3437
		switch ($config['interfaces'][$friendly]['ipaddr']) {
3438
		case "dhcp":
3439
		case "carpdev-dhcp":
3440
		case "pppoe":
3441
		case "pptp":
3442
			$ints[] = $friendly;
3443
			break;	
3444
		default:
3445
			if ($config['interfaces'][$friendly]['pointtopoint']) 
3446
				$ints[] = $friendly;
3447
			else if ($config['interfaces'][$friendly]['gateway'] <> "")
3448
				$ints[] = $friendly;
3449
			break;
3450
		}
3451
	}
3452
	return $ints;
3453
}
3454

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

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

    
3479
//returns interface information
3480
function get_interface_info($ifdescr) {
3481
	global $config, $linkinfo, $netstatrninfo;
3482

    
3483
	$ifinfo = array();
3484
	/* if list */
3485
	$iflist = get_configured_interface_with_descr(false,true);
3486
	
3487
	$found = false;
3488
    	foreach ($iflist as $if => $ifname) {
3489
    	if ($ifdescr == $if || $ifdescr == $ifname) {
3490
			$ifinfo['hwif'] = $config['interfaces'][$if]['if'];
3491
			$ifinfo['if'] = get_real_wan_interface($if);
3492
			$found = true;
3493
			break;
3494
		}
3495
	}
3496
	if ($found == false)
3497
		return;
3498

    
3499
	/* run netstat to determine link info */
3500

    
3501
	unset($linkinfo);
3502
	exec("/usr/bin/netstat -I " . $ifinfo['hwif'] . " -nWb -f link", $linkinfo);
3503
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3504
	if (preg_match("/\*$/", $linkinfo[0])) {
3505
		$ifinfo['status'] = "down";
3506
	} else {
3507
		$ifinfo['status'] = "up";
3508
	}
3509

    
3510
	if (!strstr($ifinfo['if'],'ovpn')) {
3511
		$ifinfo['macaddr'] = $linkinfo[3];
3512
		$ifinfo['inpkts'] = $linkinfo[4];
3513
		$ifinfo['inerrs'] = $linkinfo[5];
3514
		$ifinfo['inbytes'] = $linkinfo[6];
3515
		$ifinfo['outpkts'] = $linkinfo[7];
3516
		$ifinfo['outerrs'] = $linkinfo[8];
3517
		$ifinfo['outbytes'] = $linkinfo[9];
3518
		$ifinfo['collisions'] = $linkinfo[10];
3519
	} else {
3520
		$ifinfo['inpkts'] = $linkinfo[3];
3521
		$ifinfo['inbytes'] = $linkinfo[5];
3522
		$ifinfo['outpkts'] = $linkinfo[6];
3523
		$ifinfo['outbytes'] = $linkinfo[8];
3524
	}
3525

    
3526
	$ifconfiginfo = "";
3527
	unset($ifconfiginfo);
3528
	exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3529
	foreach ($ifconfiginfo as $ici) {
3530
		if (preg_match("/inet (\S+)/", $ici, $matches)) 
3531
			$ifinfo['ipaddr'] = $matches[1];
3532
		if (preg_match("/netmask (\S+)/", $ici, $matches)) 
3533
			if (preg_match("/^0x/", $matches[1]))
3534
				$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
3535
	}
3536

    
3537
	switch ($config['interfaces'][$if]['ipaddr']) {
3538
	/* DHCP? -> see if dhclient is up */
3539
	case "dhcp":
3540
	case "carpdev-dhcp":
3541
        /* see if dhclient is up */
3542
        if (is_dhcp_running($ifinfo['if']) == true)
3543
        	$ifinfo['dhcplink'] = "up";
3544
        else
3545
            $ifinfo['dhcplink'] = "down";
3546

    
3547
		break;
3548
	/* PPPoE interface? -> get status from virtual interface */
3549
	case "pppoe":
3550
		unset($linkinfo);
3551
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3552
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3553
		if (preg_match("/\*$/", $linkinfo[0])) {
3554
			$ifinfo['pppoelink'] = "down";
3555
		} else {
3556
			/* get PPPoE link status for dial on demand */
3557
			$ifinfo['pppoelink'] = "up";
3558

    
3559
			foreach ($ifconfiginfo as $ici) {
3560
				if (strpos($ici, 'LINK0') !== false)
3561
					$ifinfo['pppoelink'] = "down";
3562
			}
3563
		}
3564
		break;
3565
	/* PPTP interface? -> get status from virtual interface */
3566
	case "pptp":
3567
		unset($linkinfo);
3568
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3569
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3570
		if (preg_match("/\*$/", $linkinfo[0])) {
3571
			$ifinfo['pptplink'] = "down";
3572
		} else {
3573
			/* get PPTP link status for dial on demand */
3574
			$ifinfo['pptplink'] = "up";
3575

    
3576
			foreach ($ifconfiginfo as $ici) {
3577
				if (strpos($ici, 'LINK0') !== false)
3578
					$ifinfo['pptplink'] = "down";
3579
			}
3580
		}
3581
		break;
3582
	default:
3583
		break;
3584
	}
3585

    
3586
	if ($ifinfo['status'] == "up") {
3587
		/* try to determine media with ifconfig */
3588
		unset($ifconfiginfo);
3589
		exec("/sbin/ifconfig " . $ifinfo['hwif'], $ifconfiginfo);
3590
		$matches = "";
3591
		foreach ($ifconfiginfo as $ici) {
3592

    
3593
			/* don't list media/speed for wireless cards, as it always
3594
			   displays 2 Mbps even though clients can connect at 11 Mbps */
3595
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
3596
				$ifinfo['media'] = $matches[1];
3597
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
3598
				$ifinfo['media'] = $matches[1];
3599
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
3600
				$ifinfo['media'] = $matches[1];
3601
			}
3602

    
3603
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
3604
				if ($matches[1] != "active")
3605
					$ifinfo['status'] = $matches[1];
3606
			}
3607
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
3608
				$ifinfo['channel'] = $matches[1];
3609
			}
3610
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
3611
				if ($matches[1][0] == '"')
3612
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
3613
				else
3614
					$ifinfo['ssid'] = $matches[1];
3615
			}
3616
		}
3617
		/* lookup the gateway */
3618
		if (interface_has_gateway($if)) 
3619
			$ifinfo['gateway'] = get_interface_gateway($if);
3620
	}
3621

    
3622
	$bridge = "";
3623
	$bridge = link_int_to_bridge_interface($ifdescr);
3624
	if($bridge) {
3625
		$bridge_text = `/sbin/ifconfig {$bridge}`;
3626
		if(stristr($bridge_text, "blocking") <> false) {
3627
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
3628
			$ifinfo['bridgeint'] = $bridge;
3629
		} else if(stristr($bridge_text, "learning") <> false) {
3630
			$ifinfo['bridge'] = "learning";
3631
			$ifinfo['bridgeint'] = $bridge;
3632
		} else if(stristr($bridge_text, "forwarding") <> false) {
3633
			$ifinfo['bridge'] = "forwarding";
3634
			$ifinfo['bridgeint'] = $bridge;
3635
		}
3636
	}
3637

    
3638
	return $ifinfo;
3639
}
3640

    
3641
//returns cpu speed of processor. Good for determining capabilities of machine
3642
function get_cpu_speed() {
3643
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
3644
}
3645

    
3646
/* check if the wan interface is up
3647
 * Wait for a maximum of 10 seconds
3648
 * If the interface is up before then continue
3649
 */
3650
function is_wan_interface_up($interface) {
3651
	global $g;
3652
	global $config;
3653
	$i = 0;
3654
	while($i < 10) {
3655
		if(get_interface_gateway($interface)) {
3656
			return true;
3657
		} else {
3658
			sleep(1);
3659
		}
3660
		$i++;
3661
	}
3662
	return false;
3663
}
3664

    
3665
function add_hostname_to_watch($hostname) {
3666
	if(!is_dir("/var/db/dnscache")) {
3667
		mkdir("/var/db/dnscache");
3668
	}
3669
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
3670
		$domrecords = array();
3671
		$domips = array();
3672
		exec("host -t A $hostname", $domrecords, $rethost);
3673
		if($rethost == 0) {
3674
			foreach($domrecords as $domr) {
3675
				$doml = explode(" ", $domr);
3676
				$domip = $doml[3];
3677
				/* fill array with domain ip addresses */
3678
				if(is_ipaddr($domip)) {
3679
					$domips[] = $domip;
3680
				}
3681
			}
3682
		}
3683
		sort($domips);
3684
		$contents = "";
3685
		if(! empty($domips)) {
3686
			foreach($domips as $ip) {
3687
				$contents .= "$ip\n";
3688
			}
3689
		}
3690
		file_put_contents("/var/db/dnscache/$hostname", $contents);
3691
	}
3692
}
3693

    
3694
function find_dns_aliases() {
3695
	global $config, $g;
3696
	foreach((array) $config['aliases']['alias'] as $alias) {
3697
		$alias_value = $alias['address'];
3698
		$alias_name = $alias['name'];
3699
		if(stristr($alias_value, " ")) {
3700
			$alias_split = split(" ", $alias_value);
3701
			foreach($alias_split as $as) {
3702
				if(is_fqdn($as)) 
3703
					add_hostname_to_watch($as);			
3704
			}
3705
		} else {
3706
			if(is_fqdn($alias_value)) 
3707
				add_hostname_to_watch($alias_value);
3708
		}
3709
	}
3710
}
3711

    
3712
function is_fqdn($fqdn) {
3713
	$hostname = false;
3714
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
3715
		$hostname = true;
3716
	}
3717
	if(preg_match("/\.\./", $fqdn)) {
3718
		$hostname = false;
3719
	}
3720
	if(preg_match("/^\./i", $fqdn)) { 
3721
		$hostname = false;
3722
	}
3723
	if(preg_match("/\//i", $fqdn)) {
3724
		$hostname = false;
3725
	}
3726
	return($hostname);
3727
}
3728

    
3729
function pfsense_default_state_size() {
3730
  /* get system memory amount */
3731
  $memory = get_memory();
3732
  $avail = $memory[0];
3733
  /* Be cautious and only allocate 10% of system memory to the state table */
3734
  $max_states = (int) ($avail/10)*1000;
3735
  return $max_states;
3736
}
3737

    
3738
function lookup_gateway_ip_by_name($name) {
3739
	global $config;
3740
	if(is_array($config['gateways'])) {
3741
		foreach($config['gateways']['gateway_item'] as $gateway) {
3742
			if($gateway['name'] == $name) {
3743
				$gatewayip = $gateway['gateway'];
3744
				$interfacegw = $gateway['interface'];
3745
				return($gatewayip);
3746
			}
3747
		}
3748
	} else {
3749
		return(false);
3750
	}
3751
}
3752

    
3753
function lookup_gateway_monitor_ip_by_name($name) {
3754
	global $config;
3755
	if(is_array($config['gateways'])) {
3756
		foreach($config['gateways']['gateway_item'] as $gateway) {
3757
			if($gateway['name'] == "$name") {
3758
				$monitorip = $gateway['monitor'];
3759
				if($monitorip == "")
3760
					$monitorip = $gateway['gateway'];
3761

    
3762
				return($monitorip);
3763
			}
3764
		}
3765
	} else {
3766
		return(false);
3767
	}
3768
}
3769

    
3770
function lookup_gateway_interface_by_name($name) {
3771
	global $config;
3772
	if(is_array($config['gateways'])) {
3773
		foreach($config['gateways']['gateway_item'] as $gateway) {
3774
			if($gateway['name'] == "$name") {
3775
				$gatewayip = $gateway['gateway'];
3776
				$interfacegw = $gateway['interface'];
3777
				return($interfacegw);
3778
			}
3779
		}
3780
	} else {
3781
		return(false);
3782
	}
3783
}
3784

    
3785
/****f* pfsense-utils/safe_write_file
3786
 * NAME
3787
 *   safe_write_file - Write a file out atomically
3788
 * DESCRIPTION
3789
 *   safe_write_file() Writes a file out atomically by first writing to a
3790
 *   temporary file of the same name but ending with the pid of the current
3791
 *   process, them renaming the temporary file over the original.
3792
 * INPUTS
3793
 *   $filename  - string containing the filename of the file to write
3794
 *   $content   - string containing the file content to write to file
3795
 *   $force_binary      - boolean denoting whether we should force binary
3796
 *   mode writing.
3797
 * RESULT
3798
 *   boolean - true if successful, false if not
3799
 ******/
3800
function safe_write_file($file, $content, $force_binary) {
3801
        $tmp_file = $file . "." . getmypid();
3802
        $write_mode = $force_binary ? "wb" : "w";
3803

    
3804
        $fd = fopen($tmp_file, $write_mode);
3805
        if (!$fd) {
3806
                // Unable to open temporary file for writing
3807
                return false;
3808
        }
3809
        if (!fwrite($fd, $content)) {
3810
                // Unable to write to temporary file
3811
                fclose($fd);
3812
                return false;
3813
        }
3814
        fclose($fd);
3815

    
3816
        if (!rename($tmp_file, $file)) {
3817
                // Unable to move temporary file to original
3818
                unlink($tmp_file);
3819
                return false;
3820
        }
3821
        return true;
3822
}
3823

    
3824
function rule_popup($src,$srcport,$dst,$dstport){
3825
global $config;
3826
$aliases_array = array();
3827
if($config['aliases']['alias'] <> "" and is_array($config['aliases']['alias']))
3828
{
3829
$span_begin = "";
3830
		$alias_src_span_begin = "";
3831
		$alias_src_span_end = "";
3832
		$alias_src_port_span_begin = "";
3833
		$alias_src_port_span_end = "";
3834
		$alias_dst_span_begin = "";
3835
		$alias_dst_span_end = "";
3836
		$alias_dst_port_span_begin = "";
3837
		$alias_dst_port_span_end = "";
3838
		$alias_content_text = "";
3839
	foreach($config['aliases']['alias'] as $alias_name) 
3840
	{	
3841
	 	$alias_addresses = explode (" ", $alias_name['address']);
3842
	 	$alias_details = explode ("||", $alias_name['detail']);
3843
	 	$alias_objects_with_details = "";
3844
	 	$counter = 0;
3845
	 	foreach($alias_addresses as $alias_ports_address)
3846
	 	{
3847
			$alias_objects_with_details .= $alias_addresses[$counter];
3848
			$alias_detail_default = strpos ($alias_details[$counter],"Entry added");
3849
			if ($alias_details[$counter] != "" && $alias_detail_default === False){
3850
				$alias_objects_with_details .=" - " . $alias_details[$counter];
3851
			}  
3852
			$alias_objects_with_details .= "<br>";
3853
			$counter++;
3854
		}			
3855
		//max character length for caption field
3856
		$maxlength = 60;
3857
		
3858
		$alias_descr_substr = $alias_name['descr'];
3859
		$alias_content_text = htmlspecialchars($alias_objects_with_details);
3860
		$alias_caption = htmlspecialchars($alias_descr_substr . ":");
3861
		$strlength = strlen ($alias_caption);
3862
		if ($strlength >= $maxlength) 
3863
			$alias_caption = substr($alias_caption, 0, $maxlength) . "...";		
3864
						
3865
		$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>";
3866
		
3867
		
3868
		if ($alias_name['name'] == $src)
3869
	 	{										
3870
			$alias_src_span_begin = $span_begin;
3871
		}
3872
	 	if ($alias_name['name'] == $srcport)
3873
	 	{									
3874
			$alias_src_port_span_begin = $span_begin;					
3875
		}
3876
		if ($alias_name['name'] == $dst)
3877
	 	{										
3878
			$alias_dst_span_begin = $span_begin;									
3879
		}
3880
		if ($alias_name['name'] == $dstport)
3881
	 	{											
3882
			$alias_dst_port_span_begin = $span_begin;											
3883
		}										
3884
		
3885
	}
3886
	$descriptions = array ();
3887
	$descriptions['src'] = $alias_src_span_begin;
3888
	$descriptions['srcport'] = $alias_src_port_span_begin;
3889
	$descriptions['dst'] = $alias_dst_span_begin;
3890
	$descriptions['dstport'] = $alias_dst_port_span_begin;
3891
	return $descriptions; 
3892
  }
3893
}
3894
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body') {
3895
	global $ch, $fout, $file_size, $downloaded;
3896
	$file_size  = 1;
3897
	$downloaded = 1;
3898
	/* open destination file */
3899
	$fout = fopen($destination_file, "wb");
3900

    
3901
	/*
3902
	 *	Originally by Author: Keyvan Minoukadeh
3903
	 *	Modified by Scott Ullrich to return Content-Length size
3904
         */
3905

    
3906
	$ch = curl_init();
3907
	curl_setopt($ch, CURLOPT_URL, $url_file);
3908
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
3909
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
3910
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
3911
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, '5');
3912

    
3913
	curl_exec($ch);
3914
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
3915
	if($fout)
3916
		fclose($fout);
3917
	curl_close($ch);
3918
	return ($http_code == 200) ? true : $http_code;
3919
}
3920

    
3921
function read_header($ch, $string) {
3922
	global $file_size, $fout;
3923
	$length = strlen($string);
3924
	$regs = "";
3925
	ereg("(Content-Length:) (.*)", $string, $regs);
3926
	if($regs[2] <> "") {
3927
		$file_size = intval($regs[2]);
3928
	}
3929
	ob_flush();
3930
	return $length;
3931
}
3932

    
3933
function read_body($ch, $string) {
3934
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen;
3935
	$length = strlen($string);
3936
	$downloaded += intval($length);
3937
	$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
3938
	$downloadProgress = 100 - $downloadProgress;
3939
	if($lastseen <> $downloadProgress and $downloadProgress < 101) {
3940
		if($sendto == "status") {
3941
			$tostatus = $static_status . $downloadProgress . "%";
3942
			update_status($tostatus);
3943
		} else {
3944
			$tooutput = $static_output . $downloadProgress . "%";
3945
			update_output_window($tooutput);
3946
		}
3947
		update_progress_bar($downloadProgress);
3948
		$lastseen = $downloadProgress;
3949
	}
3950
	if($fout)
3951
		fwrite($fout, $string);
3952
	ob_flush();
3953
	return $length;
3954
}
3955

    
3956
?>
(21-21/37)