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

    
37
if(!$groupindex) 
38
	$groupindex = index_groups();
39
if(!$userindex)
40
	$userindex = index_users();
41

    
42
/****f* pfsense-utils/does_url_exist
43
 * NAME
44
 *   does_url_exist
45
 * INPUTS
46
 *	 none
47
 * RESULT
48
 *   returns true if a url is available
49
 ******/
50
function does_url_exist($url) {
51
	$fd = fopen("$url","r");
52
	if($fd) {
53
		fclose($fd);
54
   		return true;    
55
	} else {
56
        return false;
57
	}
58
}
59

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

    
83
/****f* pfsense-utils/get_tmp_file
84
 * NAME
85
 *   get_tmp_file
86
 * INPUTS
87
 *	 none
88
 * RESULT
89
 *   returns a temporary filename
90
 ******/
91
function get_tmp_file() {
92
	return "/tmp/tmp-" . time();
93
}
94

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

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

    
158
		$wancfg = $config['interfaces']['wan'];
159
		$lancfg = $config['interfaces']['lan'];
160
		$pptpdcfg = $config['pptpd'];
161
		$pppoecfg = $config['pppoe'];
162

    
163
		$lanif = $lancfg['if'];
164
		$wanif = get_real_wan_interface();
165

    
166
		$lanip = $lancfg['ipaddr'];
167
		$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
168
		$lansn = $lancfg['subnet'];
169

    
170
		$int = "";
171

    
172
		$optcfg = array();
173
		generate_optcfg_array($optcfg);
174

    
175
		$curwanip = get_current_wan_address();
176

    
177
		/* don't include disabled rules */
178
		if (isset($rule['disabled'])) {
179
			return "";
180
		}
181

    
182
		$pptpdcfg = $config['pptpd'];
183
		$pppoecfg = $config['pppoe'];
184

    
185
		if ($pptpdcfg['mode'] == "server") {
186
			$pptpip = $pptpdcfg['localip'];
187
			$pptpsa = $pptpdcfg['remoteip'];
188
			$pptpsn = $g['pptp_subnet'];
189
			if($config['pptp']['pptp_subnet'] <> "")
190
				$pptpsn = $config['pptp']['pptp_subnet'];
191
		}
192

    
193
		if ($pppoecfg['mode'] == "server") {
194
			$pppoeip = $pppoecfg['localip'];
195
			$pppoesa = $pppoecfg['remoteip'];
196
			$pppoesn = $g['pppoe_subnet'];
197
			if($config['pppoe']['pppoe_subnet'] <> "")
198
				$pppoesn = $config['pppoe']['pppoe_subnet'];
199
		}
200

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

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

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

    
273
		$ifdescrs = array();
274
		for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
275
			$ifdescrs[] = "opt" . $i;
276

    
277
		for ($iif = 0; $iif < $nif; $iif++) {
278

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

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

    
304
			/* source address */
305
			if (isset($rule['source']['any'])) {
306
				$src = "any";
307
			} else if ($rule['source']['network']) {
308

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

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

    
366
			}
367

    
368
			if (!$src || ($src == "/")) {
369
				return "# tdr at the break!";
370
			}
371

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

    
405
			/* destination address */
406
			if (isset($rule['destination']['any'])) {
407
				$dst = "any";
408
			} else if ($rule['destination']['network']) {
409

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

    
446
				if (isset($rule['destination']['not']))
447
					$not = " not ";
448
				else
449
					$not = "";
450

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

    
468
			if (!$dst || ($dst == "/")) {
469
				return "# returning at dst $dst == \"/\"";
470
			}
471

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

    
505
	}
506
	
507
	if($aline['prot'] == "")
508
		$aline['prot'] = "ip ";
509

    
510
	tdr_get_next_ipfw_rule();
511

    
512
 	/* piece together the actual user rule */
513
	if($type == "skipto") {
514
		$next_rule = tdr_get_next_ipfw_rule();
515
		$next_rule = $next_rule+1;
516
		$type = "skipto $next_rule";
517
	}
518

    
519
	/* piece together the actual user rule */
520
	$line .= $type . " " . $aline['prot'] . $aline['src'] . 
521
	$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in recv " . $aline['interface'];
522

    
523
	return $line;
524

    
525
}
526

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

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

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

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

    
663
		if($monthstatus == true) 
664
			if($daystatus == true) 
665
				if($positionstatus == true) 
666
					if($hourstatus == true) {
667
						$should_add_rule = true;
668
					}
669
	}
670
	
671
	return $should_add_rule;
672
}
673

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

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

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

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

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

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

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

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

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

    
857
/****f* pfsense-utils/return_dir_as_array
858
 * NAME
859
 *   return_dir_as_array - Return a directory's contents as an array.
860
 * INPUTS
861
 *   $dir	- string containing the path to the desired directory.
862
 * RESULT
863
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
864
 ******/
865
function return_dir_as_array($dir) {
866
	$dir_array = array();
867
	if (is_dir($dir)) {
868
		if ($dh = opendir($dir)) {
869
			while (($file = readdir($dh)) !== false) {
870
				$canadd = 0;
871
				if($file == ".") $canadd = 1;
872
				if($file == "..") $canadd = 1;
873
				if($canadd == 0)
874
					array_push($dir_array, $file);
875
			}
876
			closedir($dh);
877
		}
878
	}
879
	return $dir_array;
880
}
881

    
882
/****f* pfsense-utils/enable_hardware_offloading
883
 * NAME
884
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
885
 * INPUTS
886
 *   $interface	- string containing the physical interface to work on.
887
 * RESULT
888
 *   null
889
 * NOTES
890
 *   This function only supports the fxp driver's loadable microcode.
891
 ******/
892
function enable_hardware_offloading($interface) {
893
	global $g, $config;
894

    
895
	if(stristr($interface,"lnc"))
896
		return;
897
	if(isset($config['system']['do_not_use_nic_microcode']))
898
		return;
899

    
900
	if($g['booting']) {
901
	/* translate wan, lan, opt -> real interface if needed */
902
	$int = filter_translate_type_to_real_interface($interface);
903
	if($int <> "") $interface = $int;
904
	$int_family = preg_split("/[0-9]+/", $int);
905
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
906
	$supported_ints = array('fxp');
907
	if (in_array($int_family, $supported_ints))
908
		mwexec("/sbin/ifconfig {$interface} link0");
909

    
910
	if($config['system']['disablechecksumoffloading'])
911
		return;
912

    
913
	if(stristr($options, "txcsum") == true)
914
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
915
	if(stristr($options, "rxcsum") == true)
916
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
917
	if(stristr($options, "polling") == true)
918
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
919
	} else {
920
		mwexec("sysctl kern.polling.enable=0");
921
	}
922
	return;
923
}
924

    
925
/****f* pfsense-utils/is_alias_inuse
926
 * NAME
927
 *   checks to see if an alias is currently in use by a rule
928
 * INPUTS
929
 *
930
 * RESULT
931
 *   true or false
932
 * NOTES
933
 *
934
 ******/
935
function is_alias_inuse($alias) {
936
	global $g, $config;
937

    
938
	if($alias == "") return false;
939
	/* loop through firewall rules looking for alias in use */
940
	if(is_array($config['filter']['rule']))
941
		foreach($config['filter']['rule'] as $rule) {
942
			if($rule['source']['address'])
943
				if($rule['source']['address'] == $alias)
944
					return true;
945
			if($rule['destination']['address'])
946
				if($rule['destination']['address'] == $alias)
947
					return true;
948
		}
949
	/* loop through nat rules looking for alias in use */
950
	if(is_array($config['nat']['rule']))
951
		foreach($config['nat']['rule'] as $rule) {
952
			if($rule['target'] == $alias)
953
				return true;
954
			if($rule['external-address'] == $alias)
955
				return true;
956
		}
957
	return false;
958
}
959

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

    
973
	if($schedule == "") return false;
974
	/* loop through firewall rules looking for schedule in use */
975
	if(is_array($config['filter']['rule']))
976
		foreach($config['filter']['rule'] as $rule) {
977
			if($rule['sched'] == $schedule)
978
				return true;
979
		}
980
	return false;
981
}
982

    
983
/****f* pfsense-utils/setup_polling_defaults
984
 * NAME
985
 *   sets up sysctls for pollingS
986
 * INPUTS
987
 *
988
 * RESULT
989
 *   null
990
 * NOTES
991
 *
992
 ******/
993
function setup_polling_defaults() {
994
	global $g, $config;
995
	if($config['system']['polling_each_burst'])
996
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
997
	if($config['system']['polling_burst_max'])
998
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
999
	if($config['system']['polling_user_frac'])
1000
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
1001
}
1002

    
1003
/****f* pfsense-utils/setup_polling
1004
 * NAME
1005
 *   sets up polling
1006
 * INPUTS
1007
 *
1008
 * RESULT
1009
 *   null
1010
 * NOTES
1011
 *
1012
 ******/
1013
function setup_polling() {
1014
	global $g, $config;
1015

    
1016
	setup_polling_defaults();
1017

    
1018
	if(isset($config['system']['polling']))
1019
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
1020
	else
1021
		$supported_ints = array();
1022

    
1023
	/* build an array of interfaces to work with */
1024
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1025
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1026
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1027

    
1028
	foreach ($iflist as $ifent => $ifname) {
1029
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
1030
		$supported = false;
1031
		foreach($supported_ints as $supported) {
1032
			if(stristr($real_interface, $supported)) {
1033
				$supported = true;
1034
			}
1035
		}
1036
		if ($supported == true) {
1037
			mwexec("/sbin/ifconfig {$real_interface} polling");
1038
		} else {
1039
			mwexec("/sbin/ifconfig {$real_interface} -polling");
1040
		}
1041
	}
1042
}
1043

    
1044
/****f* pfsense-utils/setup_microcode
1045
 * NAME
1046
 *   enumerates all interfaces and calls enable_hardware_offloading which
1047
 *   enables a NIC's supported hardware features.
1048
 * INPUTS
1049
 *
1050
 * RESULT
1051
 *   null
1052
 * NOTES
1053
 *   This function only supports the fxp driver's loadable microcode.
1054
 ******/
1055
function setup_microcode() {
1056
	global $config;
1057

    
1058
	$ifdescrs = array('wan', 'lan');
1059
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1060
		$ifdescrs['opt' . $j] = "opt" . $j;
1061
	}
1062
	foreach($ifdescrs as $if)
1063
		enable_hardware_offloading($if);
1064
}
1065

    
1066
/****f* pfsense-utils/return_filename_as_array
1067
 * NAME
1068
 *   return_filename_as_array - Return a file's contents as an array.
1069
 * INPUTS
1070
 *   $filename	- string containing the path to the desired file.
1071
 *   $strip	- array of characters to strip - default is '#'.
1072
 * RESULT
1073
 *   $file	- array containing the file's contents.
1074
 * NOTES
1075
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
1076
 ******/
1077
function return_filename_as_array($filename, $strip = array('#')) {
1078
	if(file_exists($filename)) $file = file($filename);
1079
	if(is_array($file)) {
1080
		foreach($file as $line) $line = trim($line);
1081
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
1082
	}
1083
	return $file;
1084
}
1085

    
1086
/****f* pfsense-utils/file_put_contents
1087
 * NAME
1088
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
1089
 * RESULT
1090
 *   none
1091
 ******/
1092
if(!function_exists("file_put_contents")) {
1093
	function file_put_contents($filename, $data) {
1094
		$fd = fopen($filename,"w");
1095
		fwrite($fd, $data);
1096
		fclose($fd);
1097
	}
1098
}
1099

    
1100
/****f* pfsense-utils/get_carp_status
1101
 * NAME
1102
 *   get_carp_status - Return whether CARP is enabled or disabled.
1103
 * RESULT
1104
 *   boolean	- true if CARP is enabled, false if otherwise.
1105
 ******/
1106
function get_carp_status() {
1107
    /* grab the current status of carp */
1108
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
1109
    if(intval($status) == "0") return false;
1110
    return true;
1111
}
1112

    
1113
/****f* pfsense-utils/is_carp_defined
1114
 * NAME
1115
 *   is_carp_defined - Return whether CARP is detected in the kernel.
1116
 * RESULT
1117
 *   boolean	- true if CARP is detected, false otherwise.
1118
 ******/
1119
function is_carp_defined() {
1120
	/* is carp compiled into the kernel and userland? */
1121
	$command = "/sbin/sysctl -a | grep carp";
1122
	$fd = popen($command . " 2>&1 ", "r");
1123
	if(!$fd) {
1124
		log_error("Warning, could not execute command {$command}");
1125
		return 0;
1126
	}
1127
	while(!feof($fd)) {
1128
		$tmp .= fread($fd,49);
1129
	}
1130
	fclose($fd);
1131

    
1132
	if($tmp == "")
1133
		return false;
1134
	else
1135
		return true;
1136
}
1137

    
1138
/****f* pfsense-utils/get_interface_mtu
1139
 * NAME
1140
 *   get_interface_mtu - Return the mtu of an interface
1141
 * RESULT
1142
 *   $tmp	- Returns the mtu of an interface
1143
 ******/
1144
function get_interface_mtu($interface) {
1145
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f4`;
1146
	return $mtu;
1147
}
1148

    
1149
/****f* pfsense-utils/is_interface_wireless
1150
 * NAME
1151
 *   is_interface_wireless - Returns if an interface is wireless
1152
 * RESULT
1153
 *   $tmp	- Returns if an interface is wireless
1154
 ******/
1155
function is_interface_wireless($interface) {
1156
	global $config, $g;
1157
	$interface = convert_real_interface_to_friendly_interface_name($interface);
1158
	if(isset($config['interfaces'][$interface]['wireless']))
1159
		return true;
1160
	else
1161
		return false;
1162
}
1163

    
1164
/****f* pfsense-utils/find_number_of_created_carp_interfaces
1165
 * NAME
1166
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
1167
 * RESULT
1168
 *   $tmp	- Number of currently created CARP interfaces.
1169
 ******/
1170
function find_number_of_created_carp_interfaces($flush = false) {
1171
	global $carp_interface_count_cache;
1172

    
1173
	if (!isset($carp_interface_count_cache) or $flush) {
1174
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
1175
		$fd = popen($command . " 2>&1 ", "r");
1176
		if(!$fd) {
1177
			log_error("Warning, could not execute command {$command}");
1178
			return 0;
1179
		}
1180
		while(!feof($fd)) {
1181
			$tmp .= fread($fd,49);
1182
		}
1183
		fclose($fd);
1184
		$carp_interface_count_cache = intval($tmp);
1185
	}
1186
	return $carp_interface_count_cache;
1187
}
1188

    
1189
/****f* pfsense-utils/link_int_to_bridge_interface
1190
 * NAME
1191
 *   link_int_to_bridge_interface - Finds out a bridge group for an interface
1192
 * INPUTS
1193
 *   $ip
1194
 * RESULT
1195
 *   bridge[0-99]
1196
 ******/
1197
function link_int_to_bridge_interface($int) {
1198
	global $config, $g;
1199
	$real_int = convert_friendly_interface_to_real_interface_name($int);
1200
	$num_bridges = find_number_of_created_bridges();
1201
	for($x=0; $x<$num_bridges; $x++) {
1202
		$matches = "";
1203
		$bridge_info = `/sbin/ifconfig bridge{$x}`;
1204
		if(stristr($bridge_info, "member: {$real_int}")) {
1205
			return "bridge{$x}";
1206
		}
1207
	}
1208
}
1209

    
1210
function link_carp_interface_to_parent($interface) {
1211
	global $config;
1212
	if($interface == "") return;
1213

    
1214
	$ifdescrs = array('wan', 'lan');
1215
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1216
		$ifdescrs['opt' . $j] = "opt" . $j;
1217

    
1218
	$carp_ints = "";
1219
	$num_carp_ints = find_number_of_created_carp_interfaces();
1220
	foreach ($ifdescrs as $ifdescr => $ifname) {
1221
		$carp_int = $interface;
1222
		$carp_ip = find_interface_ip($interface);
1223
		$carp_subnet = find_virtual_ip_netmask($carp_ip);
1224
		$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1225
		if(ip_in_subnet($starting_ip, "{$carp_ip}/{$carp_subnet}"))
1226
			if(!stristr($carp_ints, $carp_int))
1227
				return $ifname;
1228
	}
1229
	return $carp_ints;
1230
}
1231

    
1232
/****f* pfsense-utils/link_ip_to_carp_interface
1233
 * NAME
1234
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
1235
 * INPUTS
1236
 *   $ip
1237
 * RESULT
1238
 *   $carp_ints
1239
 ******/
1240
function link_ip_to_carp_interface($ip) {
1241
	global $config;
1242
	if($ip == "") return;
1243

    
1244
	$ifdescrs = array('wan', 'lan');
1245
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1246
		$ifdescrs['opt' . $j] = "opt" . $j;
1247

    
1248
	$ft = split("\.", $ip);
1249
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
1250

    
1251
	$carp_ints = "";
1252
	$num_carp_ints = find_number_of_created_carp_interfaces();
1253
	foreach ($ifdescrs as $ifdescr => $ifname) {
1254
		for($x=0; $x<$num_carp_ints; $x++) {
1255
			$carp_int = "carp{$x}";
1256
			$carp_ip = find_interface_ip($carp_int);
1257
			$carp_subnet = find_virtual_ip_netmask($carp_ip);
1258
			$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
1259
			if(ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
1260
				if(!stristr($carp_ints, $carp_int))
1261
					$carp_ints .= " " . $carp_int;
1262
		}
1263
	}
1264
	return $carp_ints;
1265
}
1266

    
1267
/****f* pfsense-utils/find_virtual_ip_netmask
1268
 * NAME
1269
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
1270
 * INPUTS
1271
 *   $ip - ip address to locate subnet mask of
1272
 * RESULT
1273
 *   String containing the command's result.
1274
 * NOTES
1275
 *   This function returns the command's stdout and stderr.
1276
 ******/
1277
function find_virtual_ip_netmask($ip) {
1278
        global $config;
1279
        foreach($config['virtualip']['vip'] as $vip) {
1280
                if($ip == $vip['subnet'])
1281
                        return $vip['subnet_bits'];
1282
        }
1283
}
1284

    
1285
/****f* pfsense-utils/exec_command
1286
 * NAME
1287
 *   exec_command - Execute a command and return a string of the result.
1288
 * INPUTS
1289
 *   $command	- String of the command to be executed.
1290
 * RESULT
1291
 *   String containing the command's result.
1292
 * NOTES
1293
 *   This function returns the command's stdout and stderr.
1294
 ******/
1295
function exec_command($command) {
1296
	$output = array();
1297
	exec($command . ' 2>&1 ', $output);
1298
	return(implode("\n", $output));
1299
}
1300

    
1301
/****f* interfaces/is_jumbo_capable
1302
 * NAME
1303
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
1304
 * INPUTS
1305
 *   $int             - string containing interface name
1306
 * RESULT
1307
 *   boolean          - true or false
1308
 ******/
1309
function is_jumbo_capable($int) {
1310
	/* Per:
1311
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
1312
	 * Only the following drivers support large frames
1313
         *
1314
	 * 'de' chipset purposely left out of this list
1315
	 * requires defining BIG_PACKET in the
1316
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
1317
	 * kernel or module.  The hack works only for the 21041,
1318
	 * 21140, and 21140A chips.
1319
	 */
1320
	global $g;
1321

    
1322
	$capable = $g['vlan_long_frame'];
1323

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

    
1326
	if (in_array($int_family[0], $capable))
1327
		return true;
1328
	else
1329
		return false;
1330
}
1331

    
1332
/*
1333
 * Return the interface array
1334
 */
1335
function get_interface_arr($flush = false) {
1336
	global $interface_arr_cache;
1337

    
1338
	/* If the cache doesn't exist, build it */
1339
	if (!isset($interface_arr_cache) or $flush)
1340
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
1341

    
1342
	return $interface_arr_cache;
1343
}
1344

    
1345
/*
1346
 * does_interface_exist($interface): return true or false if a interface is
1347
 * detected.
1348
 */
1349
function does_interface_exist($interface) {
1350
        $ints = get_interface_arr();
1351

    
1352
	if(stristr($ints, $interface) !== false)
1353
		return true;
1354
	else
1355
		return false;
1356
}
1357

    
1358
/*
1359
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
1360
 */
1361
function convert_ip_to_network_format($ip, $subnet) {
1362
	$ipsplit = split('[.]', $ip);
1363
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
1364
	return $string;
1365
}
1366

    
1367
/*
1368
 * find_interface_ip($interface): return the interface ip (first found)
1369
 */
1370
function find_interface_ip($interface, $flush = false) {
1371
	global $interface_ip_arr_cache;
1372
	$interface = str_replace("\n", "", $interface);
1373
	if(does_interface_exist($interface) == false) return;
1374
	/* Setup IP cache */
1375
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
1376
		$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");
1377
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
1378
	}
1379

    
1380
	return $interface_ip_arr_cache[$interface];
1381
}
1382

    
1383
function guess_interface_from_ip($ipaddress) {
1384
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2; };'");
1385
	return $ret;
1386
}
1387

    
1388
function filter_opt_interface_to_real($opt) {
1389
	global $config;
1390
	return $config['interfaces'][$opt]['if'];
1391
}
1392

    
1393
function filter_get_opt_interface_descr($opt) {
1394
	global $config;
1395
	return $config['interfaces'][$opt]['descr'];
1396
}
1397

    
1398
function get_friendly_interface_list_as_array() {
1399
	global $config;
1400
	$ints = array();
1401
	$ifdescrs = get_interface_list();
1402
	foreach ($ifdescrs as $ifdescr => $ifname) {
1403
		array_push($ints,$ifdescr);
1404
	}
1405
	return $ints;
1406
}
1407

    
1408
/*
1409
 * find_ip_interface($ip): return the interface where an ip is defined
1410
 */
1411
function find_ip_interface($ip) {
1412
	global $config;
1413
	$ifdescrs = array('wan', 'lan');
1414
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
1415
		$ifdescrs['opt' . $j] = "opt" . $j;
1416
	}
1417
	foreach ($ifdescrs as $ifdescr => $ifname) {
1418
		$int = filter_translate_type_to_real_interface($ifname);
1419
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
1420
	if(stristr($ifconfig,$ip) <> false)
1421
		return $int;
1422
	}
1423
	return false;
1424
}
1425

    
1426
/*
1427
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
1428
 *                                                       for a friendly interface.  ie: wan
1429
 */
1430
function filter_translate_type_to_real_interface($interface) {
1431
	global $config;
1432
	if($config['interfaces'][$interface]['if'] <> "") {
1433
		return $config['interfaces'][$interface]['if'];
1434
	} else {
1435
		return $interface;
1436
	}
1437
}
1438

    
1439
/*
1440
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
1441
 */
1442
function get_carp_interface_status($carpinterface) {
1443
	/* basically cache the contents of ifconfig statement
1444
	to speed up this routine */
1445
	global $carp_query;
1446
	if($carp_query == "")
1447
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
1448
	$found_interface = 0;
1449
	foreach($carp_query as $int) {
1450
		if($found_interface == 1) {
1451
			if(stristr($int, "MASTER")) return "MASTER";
1452
			if(stristr($int, "BACKUP")) return "BACKUP";
1453
			if(stristr($int, "INIT")) return "INIT";
1454
			return false;
1455
		}
1456
		if(stristr($int, $carpinterface) == true)
1457
		$found_interface=1;
1458
	}
1459
	return;
1460
}
1461

    
1462
/*
1463
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
1464
 */
1465
function get_pfsync_interface_status($pfsyncinterface) {
1466
    $result = does_interface_exist($pfsyncinterface);
1467
    if($result <> true) return;
1468
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
1469
    return $status;
1470
}
1471

    
1472
/*
1473
 * find_carp_interface($ip): return the carp interface where an ip is defined
1474
 */
1475
function find_carp_interface($ip) {
1476
	global $find_carp_ifconfig;
1477
	if($find_carp_ifconfig == "") {
1478
		$find_carp_ifconfig = array();
1479
		$num_carp_ints = find_number_of_created_carp_interfaces();
1480
		for($x=0; $x<$num_carp_ints; $x++) {
1481
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
1482
		}
1483
	}
1484
	$carps = 0;
1485
	foreach($find_carp_ifconfig as $fci) {
1486
		if(stristr($fci, $ip) == true)
1487
			return "carp{$carps}";
1488
		$carps++;
1489
	}
1490
}
1491

    
1492
/*
1493
 * setup_filter_bridge(): toggle filtering bridge
1494
 */
1495
function setup_filter_bridge() {
1496
	global $config, $g;
1497
	if(isset($config['bridge']['filteringbridge'])) {
1498
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
1499
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
1500
	} else {
1501
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
1502
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
1503
	}
1504
}
1505

    
1506
/*
1507
 * find_number_of_created_bridges(): returns the number of currently created bridges
1508
 */
1509
function find_number_of_created_bridges($flush = false) {
1510
	global $bridge_interface_count_cache;
1511
	if(!isset($bridge_interface_count_cache) or $flush)
1512
		$bridge_interface_count_cache = exec_command('/sbin/ifconfig | /usr/bin/grep "bridge[0-999]" | /usr/bin/wc -l');
1513

    
1514
	return $bridge_interface_count_cache;
1515
}
1516

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

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

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

    
1551
		$filecontents = array_map('rtrim', $filecontents);
1552
		array_push($filecontents, $text);
1553
		if ($replace)
1554
			$filecontents = array_unique($filecontents);
1555

    
1556
		$file_text = implode("\n", $filecontents);
1557

    
1558
		fwrite($fout, $file_text);
1559
		fclose($fout);
1560
		return true;
1561
	} else {
1562
		return false;
1563
	}
1564
}
1565

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

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

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

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

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

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

    
1645
/*
1646
 *   exec_command_and_return_text: execute command and return output
1647
 */
1648
function exec_command_and_return_text($command) {
1649
	return exec_command($command);
1650
}
1651

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

    
1696
/*
1697
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
1698
 */
1699
function convert_friendly_interface_to_real_interface_name($interface) {
1700
	global $config;
1701
	if($config['interfaces'][$interface]['ipaddr'] == "pppoe")
1702
		return "ng0";
1703
	$lc_interface = strtolower($interface);
1704
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
1705
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
1706
	$ifdescrs = array();
1707
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1708
		$ifdescrs['opt' . $j] = "opt" . $j;
1709
	foreach ($ifdescrs as $ifdescr => $ifname) {
1710
		if(strtolower($ifname) == $lc_interface)
1711
	    return $config['interfaces'][$ifname]['if'];
1712
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
1713
			return $config['interfaces'][$ifname]['if'];
1714
   }
1715
   return $interface;
1716
}
1717

    
1718
/*
1719
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
1720
 */
1721
function convert_real_interface_to_friendly_interface_name($interface) {
1722
	global $config;
1723
	$ifdescrs = array('wan', 'lan');
1724
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
1725
		$ifdescrs['opt' . $j] = "opt" . $j;
1726
	foreach ($ifdescrs as $ifdescr => $ifname) {
1727
		if($config['interfaces']['$ifname']['if'] == $interface)
1728
			return $ifname;
1729
		$int = filter_translate_type_to_real_interface($ifname);
1730
		if($ifname == $interface) return $ifname;
1731
		if($int == $interface) return $ifname;
1732
	}
1733
	return $interface;
1734
}
1735

    
1736
/*
1737
 * update_progress_bar($percent): updates the javascript driven progress bar.
1738
 */
1739
function update_progress_bar($percent) {
1740
	global $pkg_interface;
1741
	if($percent > 100) $percent = 1;
1742
	if($pkg_interface <> "console") {
1743
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1744
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1745
		echo "\n</script>";
1746
	} else {
1747
		echo " {$percent}%";
1748
	}
1749
}
1750

    
1751
/****f* pfsense-utils/WakeOnLan
1752
 * NAME
1753
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
1754
 * RESULT
1755
 *   true/false - true if the operation was successful
1756
 ******/
1757
function WakeOnLan($addr, $mac)
1758
{
1759
	$addr_byte = explode(':', $mac);
1760
	$hw_addr = '';
1761

    
1762
	for ($a=0; $a < 6; $a++)
1763
		$hw_addr .= chr(hexdec($addr_byte[$a]));
1764

    
1765
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
1766

    
1767
	for ($a = 1; $a <= 16; $a++)
1768
		$msg .= $hw_addr;
1769

    
1770
	// send it to the broadcast address using UDP
1771
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1772
	if ($s == false) {
1773
		log_error("Error creating socket!");
1774
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
1775
	} else {
1776
		// setting a broadcast option to socket:
1777
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
1778
		if($opt_ret < 0)
1779
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
1780
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
1781
		socket_close($s);
1782
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
1783
		return true;
1784
	}
1785

    
1786
	return false;
1787
}
1788

    
1789
/*
1790
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
1791
 *                             is queuename|qlength|measured_packets
1792
 *                             NOTE: this command takes 5 seconds to run
1793
 */
1794
function gather_altq_queue_stats($dont_return_root_queues) {
1795
	mwexec("/usr/bin/killall -9 pfctl");
1796
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
1797
	$stats_array = split("\n", $stats);
1798
	$queue_stats = array();
1799
	foreach ($stats_array as $stats_line) {
1800
		$match_array = "";
1801
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
1802
			$queue_name = $match_array[1][0];
1803
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
1804
			$speed = $match_array[1][0];
1805
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
1806
			$borrows = $match_array[1][0];
1807
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
1808
			$suspends = $match_array[1][0];
1809
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
1810
			$drops = $match_array[1][0];
1811
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
1812
			$measured = $match_array[1][0];
1813
			if($dont_return_root_queues == true)
1814
				if(stristr($queue_name,"root_") == false)
1815
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
1816
		}
1817
	}
1818
	return $queue_stats;
1819
}
1820

    
1821
/*
1822
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1823
 *					 Useful for finding paths and stripping file extensions.
1824
 */
1825
function reverse_strrchr($haystack, $needle) {
1826
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1827
}
1828

    
1829
/*
1830
 *  backup_config_section($section): returns as an xml file string of
1831
 *                                   the configuration section
1832
 */
1833
function backup_config_section($section) {
1834
	global $config;
1835
	$new_section = &$config[$section];
1836
	/* generate configuration XML */
1837
	$xmlconfig = dump_xml_config($new_section, $section);
1838
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1839
	return $xmlconfig;
1840
}
1841

    
1842
/*
1843
 *  backup_vip_config_section($section): returns as an xml file string of
1844
 *                                   the configuration section
1845
 */
1846
function backup_vip_config_section() {
1847
	global $config;
1848
	$new_section = &$config['virtualip'];
1849
	foreach($new_section['vip'] as $section) {
1850
		if($section['mode'] == "proxyarp") {
1851
			unset($section);
1852
		}
1853
		if($section['advskew'] <> "") {
1854
			$section_val = intval($section['advskew']);
1855
			$section_val=$section_val+100;
1856
			if($section_val > 255)
1857
				$section_val = 255;
1858
			$section['advskew'] = $section_val;
1859
		}
1860
		$temp['vip'][] = $section;
1861
   }
1862
   return $temp;
1863
}
1864

    
1865
/*
1866
 *  restore_config_section($section, new_contents): restore a configuration section,
1867
 *                                                  and write the configuration out
1868
 *                                                  to disk/cf.
1869
 */
1870
function restore_config_section($section, $new_contents) {
1871
	global $config, $g;
1872
	conf_mount_rw();
1873
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
1874
	fwrite($fout, $new_contents);
1875
	fclose($fout);
1876
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
1877
	$config[$section] = &$section_xml;
1878
	unlink($g['tmp_path'] . "/tmpxml");
1879
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1880
	conf_mount_ro();
1881
	return;
1882
}
1883

    
1884
/*
1885
 *  merge_config_section($section, new_contents):   restore a configuration section,
1886
 *                                                  and write the configuration out
1887
 *                                                  to disk/cf.  But preserve the prior
1888
 * 													structure if needed
1889
 */
1890
function merge_config_section($section, $new_contents) {
1891
	global $config;
1892
	conf_mount_rw();
1893
	$fname = get_tmp_filename();
1894
	$fout = fopen($fname, "w");
1895
	fwrite($fout, $new_contents);
1896
	fclose($fout);
1897
	$section_xml = parse_xml_config($fname, $section);
1898
	$config[$section] = $section_xml;
1899
	unlink($fname);
1900
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1901
	conf_mount_ro();
1902
	return;
1903
}
1904

    
1905
/*
1906
 * http_post($server, $port, $url, $vars): does an http post to a web server
1907
 *                                         posting the vars array.
1908
 * written by nf@bigpond.net.au
1909
 */
1910
function http_post($server, $port, $url, $vars) {
1911
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
1912
	$urlencoded = "";
1913
	while (list($key,$value) = each($vars))
1914
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
1915
	$urlencoded = substr($urlencoded,0,-1);
1916
	$content_length = strlen($urlencoded);
1917
	$headers = "POST $url HTTP/1.1
1918
Accept: */*
1919
Accept-Language: en-au
1920
Content-Type: application/x-www-form-urlencoded
1921
User-Agent: $user_agent
1922
Host: $server
1923
Connection: Keep-Alive
1924
Cache-Control: no-cache
1925
Content-Length: $content_length
1926

    
1927
";
1928

    
1929
	$errno = "";
1930
	$errstr = "";
1931
	$fp = fsockopen($server, $port, $errno, $errstr);
1932
	if (!$fp) {
1933
		return false;
1934
	}
1935

    
1936
	fputs($fp, $headers);
1937
	fputs($fp, $urlencoded);
1938

    
1939
	$ret = "";
1940
	while (!feof($fp))
1941
		$ret.= fgets($fp, 1024);
1942
	fclose($fp);
1943

    
1944
	return $ret;
1945
}
1946

    
1947
/*
1948
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
1949
 */
1950
if (!function_exists('php_check_syntax')){
1951
	function php_check_syntax($code_to_check, &$errormessage){
1952
		return false;
1953
		$fout = fopen("/tmp/codetocheck.php","w");
1954
		$code = $_POST['content'];
1955
		$code = str_replace("<?php", "", $code);
1956
		$code = str_replace("?>", "", $code);
1957
		fwrite($fout, "<?php\n\n");
1958
		fwrite($fout, $code_to_check);
1959
		fwrite($fout, "\n\n?>\n");
1960
		fclose($fout);
1961
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1962
		$output = exec_command($command);
1963
		if (stristr($output, "Errors parsing") == false) {
1964
			echo "false\n";
1965
			$errormessage = '';
1966
			return(false);
1967
		} else {
1968
			$errormessage = $output;
1969
			return(true);
1970
		}
1971
	}
1972
}
1973

    
1974
/*
1975
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1976
 */
1977
if (!function_exists('php_check_syntax')){
1978
	function php_check_syntax($code_to_check, &$errormessage){
1979
		return false;
1980
		$command = "/usr/local/bin/php -l " . $code_to_check;
1981
		$output = exec_command($command);
1982
		if (stristr($output, "Errors parsing") == false) {
1983
			echo "false\n";
1984
			$errormessage = '';
1985
			return(false);
1986
		} else {
1987
			$errormessage = $output;
1988
			return(true);
1989
		}
1990
	}
1991
}
1992

    
1993
/*
1994
 * rmdir_recursive($path,$follow_links=false)
1995
 * Recursively remove a directory tree (rm -rf path)
1996
 * This is for directories _only_
1997
 */
1998
function rmdir_recursive($path,$follow_links=false) {
1999
	$to_do = glob($path);
2000
	if(!is_array($to_do)) $to_do = array($to_do);
2001
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
2002
		if(file_exists($workingdir)) {
2003
			if(is_dir($workingdir)) {
2004
				$dir = opendir($workingdir);
2005
				while ($entry = readdir($dir)) {
2006
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
2007
						unlink("$workingdir/$entry");
2008
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
2009
						rmdir_recursive("$workingdir/$entry");
2010
				}
2011
				closedir($dir);
2012
				rmdir($workingdir);
2013
			} elseif (is_file($workingdir)) {
2014
				unlink($workingdir);
2015
			}
2016
               	}
2017
	}
2018
	return;
2019
}
2020

    
2021
/*
2022
 *     get_memory()
2023
 *     returns an array listing the amount of
2024
 *     memory installed in the hardware
2025
 *     [0]real and [1]available
2026
 */
2027
function get_memory() {
2028
	if(file_exists("/var/log/dmesg.boot")) {
2029
		$mem = `cat /var/log/dmesg.boot | grep memory`;
2030
		$matches = "";
2031
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2032
			$real = $matches[1];
2033
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2034
			$avail = $matches[1];
2035
		return array($real[0],$avail[0]);
2036
	} else {
2037
		$mem = `dmesg -a`;
2038
		$matches = "";
2039
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
2040
			$real = $matches[1];
2041
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
2042
			$avail = $matches[1];
2043
		return array($real[0],$avail[0]);
2044
	}
2045
}
2046

    
2047
/*
2048
 *    safe_mkdir($path, $mode = 0755)
2049
 *    create directory if it doesn't already exist and isn't a file!
2050
 */
2051
function safe_mkdir($path, $mode=0755) {
2052
	global $g;
2053

    
2054
	/* cdrom is ro. */
2055
	if($g['platform'] == "cdrom")
2056
		return false;
2057

    
2058
	if (!is_file($path) && !is_dir($path))
2059
		return mkdir($path, $mode);
2060
	else
2061
		return false;
2062
}
2063

    
2064
/*
2065
 * make_dirs($path, $mode = 0755)
2066
 * create directory tree recursively (mkdir -p)
2067
 */
2068
function make_dirs($path, $mode = 0755) {
2069
	$base = '';
2070
	foreach (explode('/', $path) as $dir) {
2071
		$base .= "/$dir";
2072
		if (!is_dir($base)) {
2073
			if (!@mkdir($base, $mode))
2074
				return false;
2075
		}
2076
	}
2077
	return true;
2078
}
2079

    
2080
/*
2081
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
2082
 */
2083
function call_pfsense_method($method, $params, $timeout = 0) {
2084
	$ip = gethostbyname('www.pfsense.com');
2085
	if($ip == "www.pfsense.com")
2086
		return false;
2087
	global $g, $config;
2088
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
2089
	$xmlrpc_path = $g['xmlrpcpath'];
2090
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
2091
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
2092
	$resp = $cli->send($msg, $timeout);
2093
	if(!$resp) {
2094
		log_error("XMLRPC communication error: " . $cli->errstr);
2095
		return false;
2096
	} elseif($resp->faultCode()) {
2097
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
2098
		return false;
2099
	} else {
2100
		return XML_RPC_Decode($resp->value());
2101
	}
2102
}
2103

    
2104
/*
2105
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
2106
 */
2107
function check_firmware_version($tocheck = "all", $return_php = true) {
2108
	global $g, $config;
2109
	$ip = gethostbyname('www.pfsense.com');
2110
	if($ip == "www.pfsense.com")
2111
		return false;
2112
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
2113
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
2114
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
2115
		"platform" => trim(file_get_contents('/etc/platform'))
2116
		);
2117
	if($tocheck == "all") {
2118
		$params = $rawparams;
2119
	} else {
2120
		foreach($tocheck as $check) {
2121
			$params['check'] = $rawparams['check'];
2122
			$params['platform'] = $rawparams['platform'];
2123
		}
2124
	}
2125
	if($config['system']['firmware']['branch']) {
2126
		$params['branch'] = $config['system']['firmware']['branch'];
2127
	}
2128
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
2129
		return false;
2130
	} else {
2131
		$versions["current"] = $params;
2132
	}
2133
	return $versions;
2134
}
2135

    
2136
function get_disk_info() {
2137
	$diskout = "";
2138
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
2139
	return explode(' ', $diskout[0]);
2140
	// $size, $used, $avail, $cap
2141
}
2142

    
2143
/****f* pfsense-utils/display_top_tabs
2144
 * NAME
2145
 *   display_top_tabs - display tabs with rounded edges
2146
 * INPUTS
2147
 *   $text      - array of tabs
2148
 * RESULT
2149
 *   null
2150
 ******/
2151
function display_top_tabs(& $tab_array) {
2152
	global $HTTP_SERVER_VARS;
2153
	global $config;
2154
	
2155
	$auth_user = $HTTP_SERVER_VARS['AUTH_USER'];
2156

    
2157
	$groupindex = index_groups();
2158
	$userindex = index_users();
2159

    
2160
	$allowed = array ();
2161
	$allowed[] = '';
2162
	if (!isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER']))
2163
	    if (isset($config['system']['group'][$groupindex[$config['system']['user'][$userindex[$auth_user]]['groupname']]]['pages'])) 
2164
			$allowed = &$config['system']['group'][$groupindex[$config['system']['user'][$userindex[$auth_user]]['groupname']]]['pages'];
2165
	
2166
	/*   does the user have access to this tab?
2167
	 *   master user has access to everything.
2168
	*   if the user does not have access, simply
2169
	*   unset the tab item.
2170
	*/
2171

    
2172
	if (!isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
2173
		$authorized = & $allowed;
2174
		$tab_temp = array ();
2175
		foreach ($tab_array as $ta) {
2176
			$link = $ta[2];
2177
			// TODO: humm what shall we do with pkg_edit.php and pkg.php?
2178
			if ((strpos($link, "pkg.php")) !== false || (strpos($link, "pkg_edit.php")) !== false) {
2179
				$pos_equal = strpos($link, "=");
2180
				$pos_xmlsuffix = strpos($link, ".xml");
2181
				$link = substr($link, $pos_equal +1, ($pos_xmlsuffix - $pos_equal +3));
2182
			}
2183
			// next check - what if the basename contains a query string?
2184
			if ((strpos($link, "?")) !== false) {
2185
				$pos_qmark = strpos($link, "?");
2186
				$link = substr($link, 0, $pos_qmark);
2187
			}
2188
			if (in_array(basename($link), $authorized))
2189
				$tab_temp[] = $ta;
2190
		}
2191
		unset ($tab_array);
2192
		$tab_array = & $tab_temp;
2193
	}
2194

    
2195
	echo "<table cellpadding='0' cellspacing='0'>\n";
2196
	echo " <tr>\n";
2197
	$tabscounter = 0;
2198
	foreach ($tab_array as $ta) {
2199
		if ($ta[1] == true) {
2200
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
2201
		} else {
2202
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
2203
		}
2204
		$tabscounter++;
2205
	}
2206
	echo "</tr>\n<tr>\n";
2207
	foreach ($tab_array as $ta) {
2208
		if ($ta[1] == true) {
2209
			echo "  <td height=\"15\" valign=\"middle\" bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
2210
			echo "&nbsp;&nbsp;&nbsp;";
2211
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2212
		} else {
2213
			echo "  <td height=\"15\" valign=\"middle\" bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
2214
			echo "<font color='white'>{$ta[0]}</font></a>&nbsp;&nbsp;&nbsp;";
2215
			echo "<font size='-12'>&nbsp;</font></B></td>\n";
2216
		}
2217
	}
2218
	echo "</tr>\n<tr>\n";
2219
	foreach ($tab_array as $ta) {
2220
		if ($ta[1] == true) {
2221
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2222
		} else {
2223
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
2224
		}
2225
		$tabscounter++;
2226
	}
2227
	echo " </tr>\n";
2228
	echo "</table>\n";
2229

    
2230
	echo "<script type=\"text/javascript\">";
2231
	echo "NiftyCheck();\n";
2232
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
2233
	for ($x = 0; $x < $tabscounter; $x++)
2234
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
2235
	echo "</script>";
2236
}
2237

    
2238

    
2239
/****f* pfsense-utils/display_topbar
2240
 * NAME
2241
 *   display_topbar - top a table off with rounded edges
2242
 * INPUTS
2243
 *   $text	- (optional) Text to include in bar
2244
 * RESULT
2245
 *   null
2246
 ******/
2247
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
2248
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
2249
	echo "       <tr height='1'>\n";
2250
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
2251
	echo "		<div id='topbar'></div></td>\n";
2252
	echo "       </tr>\n";
2253
	echo "       <tr height='1'>\n";
2254
	if ($text != "")
2255
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
2256
	else
2257
		echo "         <td height='1' class='listtopic'></td>\n";
2258
	echo "       </tr>\n";
2259
	echo "     </table>";
2260
	echo "<script type=\"text/javascript\">";
2261
	echo "NiftyCheck();\n";
2262
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
2263
	echo "</script>";
2264
}
2265

    
2266
/****f* pfsense-utils/generate_random_mac_address
2267
 * NAME
2268
 *   generate_random_mac - generates a random mac address
2269
 * INPUTS
2270
 *   none
2271
 * RESULT
2272
 *   $mac - a random mac address
2273
 ******/
2274
function generate_random_mac_address() {
2275
	$mac = "02";
2276
	for($x=0; $x<5; $x++)
2277
		$mac .= ":" . dechex(rand(16, 255));
2278
	return $mac;
2279
}
2280

    
2281
/****f* pfsense-utils/strncpy
2282
 * NAME
2283
 *   strncpy - copy strings
2284
 * INPUTS
2285
 *   &$dst, $src, $length
2286
 * RESULT
2287
 *   none
2288
 ******/
2289
function strncpy(&$dst, $src, $length) {
2290
	if (strlen($src) > $length) {
2291
		$dst = substr($src, 0, $length);
2292
	} else {
2293
		$dst = $src;
2294
	}
2295
}
2296

    
2297
/****f* pfsense-utils/reload_interfaces_sync
2298
 * NAME
2299
 *   reload_interfaces - reload all interfaces
2300
 * INPUTS
2301
 *   none
2302
 * RESULT
2303
 *   none
2304
 ******/
2305
function reload_interfaces_sync() {
2306
	global $config, $g, $debug;
2307

    
2308
	$shutdown_webgui_needed = false;
2309

    
2310
	touch("{$g['tmp_path']}/reloading_all");
2311

    
2312
	if($debug)
2313
		log_error("reload_interfaces_sync() is starting.");
2314

    
2315
	if(file_exists("{$g['tmp_path']}/config.cache"))
2316
		unlink("{$g['tmp_path']}/config.cache");
2317

    
2318
	/* parse config.xml again */
2319
	$config = parse_config(true);
2320

    
2321
	$wan_if = $config['interfaces']['wan']['if'];
2322
	$lan_if = $config['interfaces']['lan']['if'];
2323

    
2324
	if($debug)
2325
		log_error("Cleaning up Interfaces");
2326

    
2327
	/* build an array of interfaces to work with */
2328
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2329
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2330
		$iflist['opt' . $i] = "opt{$i}";
2331

    
2332
	foreach ($iflist as $ifent => $ifname) {
2333
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2334
		if(stristr($ifname, "lo0") == true)
2335
			continue;
2336
		/* do not process wan interface, its mandatory */
2337
		if(stristr($ifname, "$wan_if") == true)
2338
			continue;
2339
		/* do not process lan interface, its mandatory */
2340
		if(stristr($ifname, "$lan_if") == true)
2341
			continue;
2342
		if($debug)
2343
			log_error("Downing and deleting $ifname_real - $ifname");
2344
		mwexec("/sbin/ifconfig {$ifname_real} down");
2345
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2346
	}
2347

    
2348
	/* set up VLAN virtual interfaces */
2349
	if($debug)
2350
		log_error("Configuring VLANS");
2351
	interfaces_vlan_configure();
2352

    
2353
	/* set up LAN interface */
2354
	if($debug)
2355
		log_error("Configuring LAN");
2356
	interfaces_lan_configure();
2357

    
2358
	/* set up WAN interface */
2359
	if($debug)
2360
		log_error("Configuring WAN");
2361
	interfaces_wan_configure();
2362

    
2363
	/* set up Optional interfaces */
2364
	if($debug)
2365
		log_error("Configuring optional interfaces");
2366
	interfaces_optional_configure();
2367

    
2368
	/* set up static routes */
2369
	if($debug)
2370
		log_error("Configuring system Routing");
2371
	system_routing_configure();
2372

    
2373
	/* enable routing */
2374
	if($debug)
2375
		log_error("Enabling system routing");
2376
	system_routing_enable();
2377

    
2378
	/* setup captive portal if needed */
2379
	if($debug)
2380
		log_error("Configuring Captive portal");
2381
	captiveportal_configure();
2382

    
2383
	/* bring up carp interfaces */
2384
	if($debug)
2385
		log_error("Configuring CARP");
2386
	interfaces_carp_configure();
2387

    
2388
	/* bring up carp interfaces*/
2389
	if($debug)
2390
		log_error("Bringing up CARP interfaces");
2391
	interfaces_carp_bring_up_final();
2392

    
2393
	/* restart webConfigurator if needed */
2394
	if($shutdown_webgui_needed == true)
2395
		touch("/tmp/restart_webgui");
2396

    
2397
	/* start devd back up */
2398
	mwexec("/bin/rm /tmp/reload*");
2399

    
2400
	/* remove reloading_all trigger */
2401
	if($debug)
2402
		log_error("Removing {$g['tmp_path']}/reloading_all");
2403
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2404
}
2405

    
2406
/****f* pfsense-utils/reload_all
2407
 * NAME
2408
 *   reload_all - triggers a reload of all settings
2409
 *   * INPUTS
2410
 *   none
2411
 * RESULT
2412
 *   none
2413
 ******/
2414
function reload_all() {
2415
	touch("/tmp/reload_all");
2416
}
2417

    
2418
/****f* pfsense-utils/reload_interfaces
2419
 * NAME
2420
 *   reload_interfaces - triggers a reload of all interfaces
2421
 * INPUTS
2422
 *   none
2423
 * RESULT
2424
 *   none
2425
 ******/
2426
function reload_interfaces() {
2427
	touch("/tmp/reload_interfaces");
2428
}
2429

    
2430
/****f* pfsense-utils/sync_webgui_passwords
2431
 * NAME
2432
 *   sync_webgui_passwords - syncs webgui and ssh passwords
2433
 * INPUTS
2434
 *   none
2435
 * RESULT
2436
 *   none
2437
 ******/
2438
function sync_webgui_passwords() {
2439
	global $config, $g, $groupindex, $userindex;
2440

    
2441
	conf_mount_rw();
2442
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
2443

    
2444
	if (!$fd) {
2445
		log_error("Error: cannot open htpasswd in sync_webgui_passwords().\n");
2446
		return 1;
2447
	}
2448

    
2449
	/* loop through custom users and add "virtual" entries */
2450
	if ($config['system']['user']) {
2451
		foreach ($config['system']['user'] as $user)
2452
			fwrite($fd, "{$user['name']}:{$user['password']}\n");
2453
	}
2454

    
2455
	fclose($fd);
2456
	chmod("{$g['varrun_path']}/htpasswd", 0600);
2457

    
2458
	if ($config['system']['user']) {
2459
		$root =& getUNIXRoot();
2460
		$crypted_pw = &$root['password'];
2461
	}
2462

    
2463
	if (empty ($crypted_pw)) {
2464
		log_error("Error: cannot determine root pwd in sync_webgui_passwords().\nRoot user struct follows:\n");
2465
		empty($root) ? log_error("Unable to determine root user!\n") : print_r($root);
2466
		log_error("Testing whether your system has the necessary users... ");
2467
		empty($config['system']['user']) ? log_error("users are missing.\n") : log_error("users found.\n");
2468
		return 1;
2469
	}
2470

    
2471
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2472
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2473
	/* sync root */
2474
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
2475
	fwrite($fd, $crypted_pw);
2476
	pclose($fd);
2477
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
2478

    
2479
	/* and again for shell users */
2480
	/* only users with hasShellAccess() == true should be synced */
2481
	if($config['system']['user']) {
2482
		$home_base = $g['platform'] == "pfSense" ? "/home" : "/var/home";
2483

    
2484
		if(! is_dir($home_base))
2485
			mkdir($home_base, 0755);
2486

    
2487
		foreach($config['system']['user'] as $user) {
2488
			if (hasShellAccess($user['name']) || isAllowedToCopyFiles($user['name'])) {
2489
				$home  = hasShellAccess($user['name']) ? "{$home_base}/{$user['name']}" : "{$home_base}/scponly";
2490
				$shell = isAllowedToCopyFiles($user['name']) ? "/usr/local/bin/scponly" : "/etc/rc.initial";
2491
				if (isAllowedToCopyFiles($user['name']))
2492
					$user['groupname'] = "scponly";
2493

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

    
2498
				if (strpos($pwread, "unknown group") !== false) {
2499
					$groupname = $user['groupname'];
2500
					$group = $config['system']['group'][$groupindex[$groupname]];
2501

    
2502
					if (isset($group) && is_array($group)) {
2503
						$fd = popen("/usr/sbin/pw groupadd -g {$group['gid']} -n {$group['name']}", "r");
2504
						pclose($fd);
2505
					} elseif (isAllowedToCopyFiles($user['name'])) {
2506
						$fd = popen("/usr/sbin/pw groupadd -g 100 -n scponly", "r");
2507
						pclose($fd);
2508
					}
2509
				}
2510

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

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

    
2517
				if (strpos($pwread, "no such user") === false) {
2518
					$fd = popen("/usr/sbin/pw usermod -n {$user['name']} -g ${user['groupname']} -G {$group} -H 0", "w");
2519
					fwrite($fd, $user['password']);
2520
					pclose($fd);
2521
				} else {
2522
					$fd = popen("/usr/sbin/pw useradd -u {$user['uid']} -n {$user['name']} -c '{$user['fullname']}' -g ${user['groupname']} -G {$group} -H 0", "w");
2523
					fwrite($fd, $user['password']);
2524
					pclose($fd);
2525
				}
2526

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

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

    
2533
				if (isAllowedToCopyFiles($user['name'])) {
2534
					mwexec("/usr/sbin/pw usermod -n {$user['name']} -g scponly");
2535
				}
2536

    
2537
				if (file_exists("{$home_base}/scponly"))
2538
					mwexec("chmod 0660 {$home_base}/scponly");
2539

    
2540
				if(isset($config['system']['ssh']['sshdkeyonly']) && ! isAllowedToCopyFiles($user['name'])) {
2541
					create_authorized_keys($user['name'], $home);
2542
				}
2543
			}
2544
		}
2545
	}
2546

    
2547
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
2548
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
2549
	conf_mount_ro();
2550
}
2551
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
2552
 * NAME
2553
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
2554
 *   * INPUTS
2555
 *   optional interface number
2556
 * RESULT
2557
 *   none
2558
 ******/
2559
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
2560
	/*	move all the interfaces up.  for example:
2561
	*		opt1 --> opt1
2562
	*		opt2 --> delete
2563
	*		opt3 --> opt2
2564
	*		opt4 --> opt3
2565
	*/
2566
	global $g, $config;
2567
	config_lock();
2568
	conf_mount_rw();
2569
	unlink_if_exists("{$g['tmp_path']}/config.cache");
2570
	$config_file = file_get_contents("/cf/conf/config.xml");
2571
	/* loop through and reassign deleted items */
2572
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
2573
		if ($i < $opt_interface_num)
2574
			break;
2575
		if ($i == $opt_interface_num) {
2576
			/* item should be deleted */
2577
			str_replace("opt" . $i, "optXXXX", $config_file);
2578
		}
2579
	}
2580
	/* loop through and reassign optional items */
2581
	for ($i = 500; isset ($config['interfaces']['opt' . $i]); $i--) {
2582
		if ($i < $opt_interface_num)
2583
			break;
2584
		/* replace opt$i with $i -1 */
2585
		str_replace("opt" . $i, "opt" . ($i -1), $config_file);
2586
	}
2587
	$fd = fopen("/cf/conf/config.xml", "w");
2588
	fwrite($fd, $config_file);
2589
	fclose($fd);
2590
	$config = parse_config(true);
2591
	/* loop through and delete old rules */
2592
	$num_rules = count($config['filter']['rule']);
2593
	for($x = $num_rules; $x > 0; $x--) {
2594
		if($config['filter']['rule'][$x])
2595
			if($config['filter']['rule'][$x]['interface'] == "optXXXX")
2596
		 		unset($config['filter']['rule'][$x]['interface']);
2597
	}
2598
	$num_rules = count($config['nat']['advancedoutbound']['rule']);
2599
	for($x = $num_rules; $x > 0; $x--) {
2600
		if($config['nat']['advancedoutbound']['rule'][$x])
2601
			if($config['nat']['advancedoutbound']['rule'][$x]['interface'] == "optXXXX")
2602
		 		unset($config['nat']['advancedoutbound']['rule'][$x]['interface']);
2603
	}
2604
	$num_rules = count($config['nat']['rule']);
2605
	for($x = $num_rules; $x > 0; $x--) {
2606
		if($config['nat']['rule'][$x])
2607
			if($config['nat']['rule'][$x]['interface'] == "optXXXX")
2608
		 		unset($config['nat']['rule'][$x]['interface']);
2609
	}
2610
	conf_mount_ro();
2611
	config_unlock();
2612
	return true;
2613
}
2614

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

    
2639
function get_netgaph_interface_assignment($friendly_interface) {
2640
	global $config, $g;
2641
	/* build an array of interfaces to work with */
2642
	$iflist = array("wan" => "WAN");
2643
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2644
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
2645
		$ng_interfaces_needed = 0;
2646
		$ng_interfaces_number = 0;
2647
		foreach ($iflist as $ifent => $ifname) {
2648
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
2649
			$ng_interfaces_number++;
2650
		}
2651
		if($friendly_interface == $ifname)
2652
			break;
2653
	}
2654
	return $ng_interfaces_number;
2655
}
2656

    
2657
/****f* pfsense-utils/reload_all_sync
2658
 * NAME
2659
 *   reload_all - reload all settings
2660
 *   * INPUTS
2661
 *   none
2662
 * RESULT
2663
 *   none
2664
 ******/
2665
function reload_all_sync() {
2666
	global $config, $g;
2667

    
2668
	$g['booting'] = false;
2669

    
2670
	touch("{$g['tmp_path']}/reloading_all");
2671

    
2672
	$shutdown_webgui_needed = false;
2673

    
2674
	if(file_exists("{$g['tmp_path']}/config.cache"))
2675
		unlink("{$g['tmp_path']}/config.cache");
2676

    
2677
	/* parse config.xml again */
2678
	$config = parse_config(true);
2679

    
2680
	/* set up our timezone */
2681
	system_timezone_configure();
2682

    
2683
	/* set up our hostname */
2684
	system_hostname_configure();
2685

    
2686
	/* make hosts file */
2687
	system_hosts_generate();
2688

    
2689
	/* generate resolv.conf */
2690
	system_resolvconf_generate();
2691

    
2692
	/* Set up our loopback interface */
2693
	interfaces_loopback_configure();
2694

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

    
2698
	$wan_if = $config['interfaces']['wan']['if'];
2699
	$lan_if = $config['interfaces']['lan']['if'];
2700

    
2701
	/* build an array of interfaces to work with */
2702
	$iflist = array("lan" => "LAN", "wan" => "WAN");
2703
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
2704
		$iflist['opt' . $i] = "opt{$i}";
2705

    
2706
	foreach ($iflist as $ifent => $ifname) {
2707
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
2708
		if(stristr($ifname, "lo0") == true)
2709
			continue;
2710
		/* do not process wan interface, its mandatory */
2711
		if($wan_if == $ifname_real)
2712
			continue;
2713
		/* do not process lan interface, its mandatory */
2714
		if($lan_if == $ifname_real)
2715
			continue;
2716
		mwexec("/sbin/ifconfig {$ifname_real} down");
2717
		mwexec("/sbin/ifconfig {$ifname_real} delete");
2718
	}
2719

    
2720
	/* set up VLAN virtual interfaces */
2721
	interfaces_vlan_configure();
2722

    
2723
	/* set up LAN interface */
2724
	interfaces_lan_configure();
2725

    
2726
	/* set up WAN interface */
2727
	interfaces_wan_configure();
2728

    
2729
	/* set up Optional interfaces */
2730
	interfaces_optional_configure();
2731

    
2732
	/* bring up carp interfaces */
2733
	interfaces_carp_configure();
2734

    
2735
	/* set up static routes */
2736
	system_routing_configure();
2737

    
2738
	/* enable routing */
2739
	system_routing_enable();
2740

    
2741
	/* ensure passwords are sync'd */
2742
	system_password_configure();
2743

    
2744
	/* start dnsmasq service */
2745
	services_dnsmasq_configure();
2746

    
2747
	/* start dyndns service */
2748
	services_dyndns_configure();
2749

    
2750
	/* start DHCP service */
2751
	services_dhcpd_configure();
2752

    
2753
	/* configure cron service */
2754
	configure_cron();
2755

    
2756
	/* start the NTP client */
2757
	system_ntp_configure();
2758

    
2759
	/* start ftp proxy helpers if they are enabled */
2760
	system_start_ftp_helpers();
2761

    
2762
	/* start the captive portal */
2763
	captiveportal_configure();
2764

    
2765
        /* reload the filter */
2766
	filter_configure_sync();
2767

    
2768
	/* bring up carp interfaces*/
2769
	interfaces_carp_bring_up_final();
2770

    
2771
	/* sync pw database */
2772
	conf_mount_rw();
2773
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
2774
	conf_mount_ro();
2775

    
2776
	/* restart sshd */
2777
	touch("/tmp/start_sshd");
2778

    
2779
	/* restart webConfigurator if needed */
2780
	if($shutdown_webgui_needed == true)
2781
		touch("/tmp/restart_webgui");
2782

    
2783
	mwexec("/bin/rm /tmp/reload*");
2784

    
2785
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
2786

    
2787
}
2788

    
2789
function auto_login($status) {
2790
	$gettytab = file_get_contents("/etc/gettytab");
2791
	$getty_split = split("\n", $gettytab);
2792
	conf_mount_rw();
2793
	$fd = fopen("/etc/gettytab", "w");
2794
	foreach($getty_split as $gs) {
2795
		if(stristr($gs, ":ht:np:sp#115200") ) {
2796
			if($status == true) {
2797
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
2798
			} else {
2799
				fwrite($fd, "	:ht:np:sp#115200:\n");
2800
			}
2801
		} else {
2802
			fwrite($fd, "{$gs}\n");
2803
		}
2804
	}
2805
	fclose($fd);
2806
	conf_mount_ro();
2807
}
2808

    
2809
function setup_serial_port() {
2810
	global $g, $config;
2811
	conf_mount_rw();
2812
	/* serial console - write out /boot.config */
2813
	if(file_exists("/boot.config"))
2814
		$boot_config = file_get_contents("/boot.config");
2815
	else
2816
		$boot_config = "";
2817

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

    
2878
function print_value_list($list, $count = 10, $separator = ",") {
2879
	$list = implode($separator, array_slice($list, 0, $count));
2880
	if(count($list) < $count) {
2881
		$list .= ".";
2882
	} else {
2883
		$list .= "...";
2884
	}
2885
	return $list;
2886
}
2887

    
2888
function convert_friendly_interface_to_friendly_descr($interface) {
2889
	global $config;
2890
	/* attempt to resolve interface to friendly descr */
2891
	if($config['interfaces'][$interface]['descr'])
2892
		return $config['interfaces'][$interface]['descr'];
2893
	$tmp = convert_real_interface_to_friendly_descr($interface);
2894
	/* could not resolve, return back what was passed */
2895
	return $interface;
2896
}
2897

    
2898
function convert_real_interface_to_friendly_descr($interface) {
2899
	global $config;
2900
	if($interface == $config['interfaces']['wan']['if'])
2901
		return "wan";
2902
	if($interface == $config['interfaces']['lan']['if'])
2903
		return "lan";
2904
	/* attempt to resolve interface to friendly descr */
2905
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
2906
	if($config['interfaces'][$friendly_int]['descr'])
2907
		return $config['interfaces'][$friendly_int]['descr'];
2908
	/* could not resolve, return back what was passed */
2909
	return $interface;
2910
}
2911

    
2912
function enable_rrd_graphing() {
2913
	global $config, $g;
2914

    
2915
	if($g['booting']) 
2916
		echo "Generating RRD graphs...";
2917

    
2918
	$rrddbpath = "/var/db/rrd/";
2919
	$rrdgraphpath = "/usr/local/www/rrd";
2920

    
2921
	$traffic = "-traffic.rrd";
2922
	$packets = "-packets.rrd";
2923
	$states = "-states.rrd";
2924
	$quality = "-quality.rrd";
2925
	$wireless = "-wireless.rrd";
2926
	$queues = "-queues.rrd";
2927
	$queuesdrop = "-queuesdrop.rrd";
2928
	$spamd = "-spamd.rrd";
2929
	$proc = "-processor.rrd";
2930

    
2931
	$rrdtool = "/usr/local/bin/rrdtool";
2932
	$netstat = "/usr/bin/netstat";
2933
	$awk = "/usr/bin/awk";
2934
	$tar = "/usr/bin/tar";
2935
	$pfctl = "/sbin/pfctl";
2936
	$php = "/usr/local/bin/php";
2937
	$top = "/usr/bin/top";
2938
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
2939
	$ifconfig = "/sbin/ifconfig";
2940

    
2941
	$rrdtrafficinterval = 60;
2942
	$rrdqualityinterval = 60;
2943
	$rrdwirelessinterval = 60;
2944
	$rrdqueuesinterval = 60;
2945
	$rrdqueuesdropinterval = 60;
2946
	$rrdpacketsinterval = 60;
2947
	$rrdstatesinterval = 60;
2948
	$rrdspamdinterval = 60;
2949
	$rrdlbpoolinterval = 60;
2950
	$rrdprocinterval = 60;
2951

    
2952
	$trafficvalid = $rrdtrafficinterval * 2;
2953
	$qualityvalid = $rrdqualityinterval * 2;
2954
	$wirelessvalid = $rrdwirelessinterval * 2;
2955
	$queuesvalid = $rrdqueuesinterval * 2;
2956
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
2957
	$packetsvalid = $rrdpacketsinterval * 2;
2958
	$statesvalid = $rrdstatesinterval*2;
2959
	$spamdvalid = $rrdspamdinterval * 2;
2960
	$lbpoolvalid = $rrdlbpoolinterval * 2;
2961
	$procvalid = $rrdlbpoolinterval * 2;
2962

    
2963
	/* Asume GigE for now */
2964
	$downstream = 125000000;
2965
	$upstream = 125000000;
2966

    
2967
	$rrdrestore = "";
2968
	$rrdreturn = "";
2969

    
2970
	if (isset ($config['rrd']['enable'])) {
2971

    
2972
		/* create directory if needed */
2973
		if (!is_dir("$rrddbpath")) {
2974
			mkdir("$rrddbpath", 0755);
2975
		}
2976

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

    
2989
		/* db update script */
2990
		$rrdupdatesh = "#!/bin/sh\n";
2991
		$rrdupdatesh .= "\n";
2992
		$rrdupdatesh .= "counter=1\n";
2993
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2994
		$rrdupdatesh .= "do\n";
2995
		$rrdupdatesh .= "";
2996

    
2997
		$i = 0;
2998
		$vfaces = array (
2999
			"vlan.?*",
3000
			"enc.?*"
3001
		);
3002
		$ifdescrs = get_interface_list(true, true, $vfaces);
3003
		$ifdescrs['enc0']['friendly'] = "ipsec";
3004
		$ifdescrs['enc0']['descr'] = "IPSEC";
3005
		$ifdescrs['enc0']['up'] = true;
3006

    
3007
		foreach ($ifdescrs as $realif => $ifdescr) {
3008
			$ifname = $ifdescr['friendly'];
3009
			$state = $ifdescr['up'];
3010

    
3011
			/* skip interfaces that do not have a friendly name */
3012
			if ("$ifname" == "") {
3013
				continue;
3014
			}
3015

    
3016
			/* or are down */
3017
			if (!$state) {
3018
				continue;
3019
			}
3020

    
3021
			/* TRAFFIC, set up the rrd file */
3022
			if (!file_exists("$rrddbpath$ifname$traffic")) {
3023
				/* create rrd file if it does not exist */
3024
				log_error("Create RRD database $rrddbpath$ifname$traffic");
3025
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
3026
				$rrdcreate .= "DS:in:COUNTER:$trafficvalid:0:$downstream ";
3027
				$rrdcreate .= "DS:out:COUNTER:$trafficvalid:0:$upstream ";
3028
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3029
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3030
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3031
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3032
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3033

    
3034
				$rrdcreateoutput = array();
3035
				$rrdcreatereturn = "";
3036

    
3037
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3038
				if ($rrdcreatereturn != 0) {
3039
					log_error("RRD create failed exited with $rrdcreatereturn, the
3040
							error is: $rrdcreateoutput[0]\n");
3041
				}
3042
			}
3043

    
3044
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3045
			if($g['booting']) {
3046
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
3047
			}
3048

    
3049
			$rrdupdatesh .= "\n";
3050
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
3051
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
3052
			if(! is_macaddr(get_interface_mac($realif))) {
3053
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$6 \":\" \$9}'`\n";
3054
			} else {
3055
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7 \":\" \$10}'`\n";
3056
			}
3057

    
3058
			/* PACKETS, set up the rrd file */
3059
			if (!file_exists("$rrddbpath$ifname$packets")) {
3060
				/* create rrd file if it does not exist */
3061
				log_error("Create RRD database $rrddbpath$ifname$packets");
3062
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
3063
				$rrdcreate .= "DS:in:COUNTER:$packetsvalid:0:$downstream ";
3064
				$rrdcreate .= "DS:out:COUNTER:$packetsvalid:0:$upstream ";
3065
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3066
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3067
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3068
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3069
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3070

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

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

    
3083
			$rrdupdatesh .= "\n";
3084
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
3085
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
3086
			if(! is_macaddr(get_interface_mac($realif))) {
3087
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$4 \":\" \$7}'`\n";
3088
			} else {
3089
				$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5 \":\" \$8}'`\n";
3090
			}
3091
			/* if an alternative gateway is defined, use it */
3092
			if ($config['interfaces'][$ifname]['use_rrd_gateway'] <> "") {
3093
				$gatewayip = get_interface_gateway($ifname);
3094
				$monitorip = $config['interfaces'][$ifname]['use_rrd_gateway'];
3095
				mwexec("/sbin/route add -host {$monitorip} {$gatewayip} 1> /dev/null 2>&1");
3096
			} else {
3097
				$monitorip = get_interface_gateway($ifname);
3098
			}
3099
			$numpings = 5;
3100
			$btick = '`';
3101

    
3102
			if($monitorip <> "") {
3103
				/* QUALITY, create link quality database */
3104
				if (!file_exists("$rrddbpath$ifname$quality")) {
3105
					/* create rrd file if it does not exist */
3106
					log_error("Create RRD database $rrddbpath$ifname$quality");
3107
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval ";
3108
					$rrdcreate .= "DS:loss:GAUGE:$qualityvalid:0:100 ";
3109
					$rrdcreate .= "DS:roundtrip:GAUGE:$qualityvalid:0:10000 ";
3110
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3111
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3112
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3113
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3114
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3115

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

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

    
3127
				/* the ping test function. We call this on the last line */
3128
				$rrdupdatesh .= "get_quality_stats_{$ifname} () {\n";
3129
				$rrdupdatesh .= "	packetloss_{$ifname}=100\n";
3130
				$rrdupdatesh .= "	roundtrip_{$ifname}=0\n";
3131
				$rrdupdatesh .= "	local out_{$ifname}\n";
3132
				$rrdupdatesh .= "	out_{$ifname}=$btick ping -c $numpings -q $monitorip $btick\n";
3133
				$rrdupdatesh .= "	if [ $? -eq 0 ]; then\n";
3134
				$rrdupdatesh .= "		packetloss_{$ifname}=$btick echo \$out_{$ifname} | cut -f18 -d' ' | cut -c -1 $btick\n";
3135
				$rrdupdatesh .= "		roundtrip_{$ifname}=$btick echo \$out_{$ifname} | cut -f24 -d' ' | cut -f2 -d'/' $btick\n";
3136
				$rrdupdatesh .= "	fi\n";
3137
				$rrdupdatesh .= "	$rrdtool update $rrddbpath$ifname$quality N:\$packetloss_{$ifname}:\$roundtrip_{$ifname}\n";
3138
				$rrdupdatesh .= "}\n\n";
3139

    
3140
				$rrdupdatesh .= "get_quality_stats_{$ifname} &\n\n";
3141
			}
3142

    
3143
			/* WIRELESS, set up the rrd file */
3144
			if($config['interfaces'][$ifname]['wireless']['mode'] == "bss") {
3145
				if (!file_exists("$rrddbpath$ifname$wireless")) {
3146
					/* create rrd file if it does not exist */
3147
					log_error("Create RRD database $rrddbpath$ifname$wireless");
3148
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$wireless --step $rrdwirelessinterval ";
3149
					$rrdcreate .= "DS:snr:GAUGE:$wirelessvalid:0:1000 ";
3150
					$rrdcreate .= "DS:rate:GAUGE:$wirelessvalid:0:1000 ";
3151
					$rrdcreate .= "DS:channel:GAUGE:$wirelessvalid:0:1000 ";
3152
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3153
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3154
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3155
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3156
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3157
	
3158
					$rrdcreateoutput = array();
3159
					$rrdcreatereturn = "";
3160

    
3161
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3162
					if ($rrdcreatereturn != 0) {
3163
						log_error("RRD create failed exited with $rrdcreatereturn, the
3164
								error is: $rrdcreateoutput[0]\n");
3165
					}
3166
				}
3167

    
3168
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3169
				if($g['booting']) {
3170
					exec("$rrdtool update $rrddbpath$ifname$wireless N:U:U:U");
3171
				}
3172

    
3173
				$rrdupdatesh .= "\n";
3174
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
3175
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\\\n";
3176
				$rrdupdatesh .= "`$ifconfig {$realif} list ap| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
3177
			}
3178

    
3179
			/* WAN interface only statistics */
3180
			if ("$ifname" == "wan") {
3181

    
3182
				/* QUEUES, set up the queues databases */
3183
				if (!is_array($config['shaper']['queue'])) {
3184
					$config['shaper']['queue'] = array ();
3185
				}
3186
				$a_queues = & $config['shaper']['queue'];
3187

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

    
3200
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3201
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3202
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3203
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3204
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3205

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

    
3213
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
3214
						/* create rrd file if it does not exist */
3215
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
3216
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
3217
						/* loop list of shaper queues */
3218
						$q = 0;
3219
						foreach ($a_queues as $queue) {
3220
							$name = $queue['name'];
3221
							$rrdcreate .= "DS:$name:COUNTER:$queuesdropvalid:0:$downstream ";
3222
						}
3223

    
3224
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3225
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3226
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3227
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3228
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3229

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

    
3236
					if($g['booting']) {
3237
						$rrdqcommand = "-t ";
3238
						$rrducommand = "N";
3239
						$q = 0;
3240
						foreach ($a_queues as $queue) {
3241
							if($q == 0) {
3242
								$rrdqcommand .= "{$queue['name']}";
3243
							} else {
3244
								$rrdqcommand .= ":{$queue['name']}";
3245
							}
3246
							$q++;
3247
							$rrducommand .= ":U";
3248
						}
3249
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3250
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3251
					}
3252

    
3253
					/* awk function to gather shaper data */
3254
					/* yes, it's special */
3255
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
3256
					$rrdupdatesh .= "{ ";
3257
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3258
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3259
					$rrdupdatesh .= "q=1; ";
3260
					$rrdupdatesh .= "} ";
3261
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3262
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
3263
					$rrdupdatesh .= "q=0; ";
3264
					$rrdupdatesh .= "} ";
3265
					$rrdupdatesh .= "} END { ";
3266
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3267
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3268
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3269
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3270

    
3271
					$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
3272
					$rrdupdatesh .= "{ ";
3273
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3274
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3275
					$rrdupdatesh .= "q=1; ";
3276
					$rrdupdatesh .= "} ";
3277
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3278
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
3279
					$rrdupdatesh .= "q=0; ";
3280
					$rrdupdatesh .= "} ";
3281
					$rrdupdatesh .= "} END { ";
3282
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3283
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3284
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3285
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3286
				}
3287
			}
3288
		}
3289
		$i++;
3290

    
3291
		/* System only statistics */
3292
		$ifname = "system";
3293

    
3294
			/* STATES, create pf states database */
3295
			if(! file_exists("$rrddbpath$ifname$states")) {
3296
				/* create rrd file if it does not exist */
3297
				log_error("Create RRD database $rrddbpath$ifname$states");
3298
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3299
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3300
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3301
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3302
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3303
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3304
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3305
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3306
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3307
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3308
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3309

    
3310
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3311
				if($rrdcreatereturn != 0) {
3312
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3313
						error is: $rrdcreateoutput[0]\n");
3314
				}
3315
			}
3316

    
3317
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3318
			if($g['booting']) {
3319
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
3320
			}
3321

    
3322
 			/* the pf states gathering function. */
3323
 			$rrdupdatesh .= "\n";
3324
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
3325
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
3326
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3327
 			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3328
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3329
 			$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";
3330
 			$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";
3331
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3332

    
3333
			/* End pf states statistics */
3334

    
3335
			/* CPU, create CPU statistics database */
3336
			if(! file_exists("$rrddbpath$ifname$proc")) {
3337
				/* create rrd file if it does not exist */
3338
				log_error("Create RRD database $rrddbpath$ifname$proc");
3339
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3340
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3341
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3342
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3343
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3344
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3345
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3346
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3347
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3348
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3349
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3350

    
3351
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3352
				if($rrdcreatereturn != 0) {
3353
			                log_error("RRD create failed exited with $rrdcreatereturn, the
3354
						error is: $rrdcreateoutput[0]\n");
3355
				}
3356
			}
3357

    
3358
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3359
			if($g['booting']) {
3360
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
3361
			}
3362

    
3363
 			/* the CPU stats gathering function. */
3364
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { ";
3365
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } ";
3366
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { ";
3367
			$rrdupdatesh .= "processes = \$1; ";
3368
			$rrdupdatesh .= "} ";
3369
			$rrdupdatesh .= "else if ( \$1 == \"CPU\" ) { ";
3370
			$rrdupdatesh .= "user = \$3; ";
3371
			$rrdupdatesh .= "nice = \$5; ";
3372
			$rrdupdatesh .= "sys = \$7; ";
3373
			$rrdupdatesh .= "interrupt = \$9; ";
3374
			$rrdupdatesh .= "} ";
3375
			$rrdupdatesh .= "} END { ";
3376
			$rrdupdatesh .= "printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes ";
3377
			$rrdupdatesh .= "}'`\n\n";
3378

    
3379
			/* End CPU statistics */
3380

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

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

    
3414
				$rrdupdatesh .= "\n";
3415
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3416
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3417
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3418

    
3419
			}
3420
		/* End System statistics */
3421

    
3422
		$rrdupdatesh .= "sleep 60\n";
3423
		$rrdupdatesh .= "done\n";
3424
		log_error("Creating rrd update script");
3425
		/* write the rrd update script */
3426
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3427
		$fd = fopen("$updaterrdscript", "w");
3428
		fwrite($fd, "$rrdupdatesh");
3429
		fclose($fd);
3430

    
3431
		/* kill off traffic collectors */
3432
		kill_traffic_collector();
3433

    
3434
		/* start traffic collector */
3435
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3436

    
3437
	} else {
3438
		/* kill off traffic collectors */
3439
		kill_traffic_collector();
3440
	}
3441

    
3442
	if($g['booting']) 
3443
		echo "done.\n";
3444
		
3445
}
3446

    
3447
function kill_traffic_collector() {
3448
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
3449
}
3450

    
3451
function update_filter_reload_status($text) {
3452
	global $g;
3453
	config_lock();
3454
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3455
	fwrite($fd, $text);
3456
	fclose($fd);
3457
	config_unlock();
3458
}
3459

    
3460
function get_interface_gateway($interface) {
3461
	global $config, $g;
3462
	$interface = strtolower($interface);
3463
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
3464
	 *  grab the address from the configuration file.
3465
	 */
3466
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
3467
	if($tmpif <> $interface)
3468
		$interface = $tmpif;
3469
	$realif = $config['interfaces'][$interface]['if'];
3470
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
3471
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3472
		$gw = rtrim($gw);
3473
	} else {
3474
		if(is_array($config['gateways'])) {
3475
			foreach($config['gateways']['gateway_item'] as $gateway) {
3476
				if($gateway['name'] == $gateway['name']) {
3477
					$gatewayip = $gateway['gateway'];
3478
					$interfacegw = $gateway['interface'];
3479
				}
3480
			}
3481
			$gw = $gatewayip;
3482
		} else {
3483
			$gw = $config['interfaces'][$interface]['gateway'];
3484
		}
3485
	}
3486
	/* if wan is requested, return it */
3487
	if($interface == "wan")
3488
		return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
3489
	/* return gateway */
3490
	return $gw;
3491
}
3492

    
3493
function is_dhcp_server_enabled() {
3494
	/* DHCP enabled on any interfaces? */
3495
	global $config, $g;
3496
	$dhcpdcfg = $config['dhcpd'];
3497
	$dhcpdenable = false;
3498
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
3499
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3500
			$dhcpdenable = true;
3501
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
3502
			$dhcpdenable = true;
3503
	}
3504
	return $dhcpdenable;
3505
}
3506

    
3507
/* return outside interfaces with a gateway */
3508
function get_interfaces_with_gateway() {
3509
	global $config;
3510
	$ints = array();
3511
	$vfaces = array(
3512
			'bridge.?*',
3513
			'ppp.?*',
3514
			'sl.?*',
3515
			'gif.?*',
3516
			'faith.?*',
3517
			'lo.?*',
3518
			'ng.?*',
3519
			'vlan.?*',
3520
			'pflog.?*',
3521
			'pfsync.?*',
3522
			'enc.?*',
3523
			'tun.?*',
3524
			'carp.?*'
3525
		);
3526
	$ifdescrs = get_interface_list("active","physical",$vfaces);
3527

    
3528
	/* loop interfaces, check config for outbound */
3529
	foreach ($ifdescrs as $ifdescr => $ifname) {
3530
		$friendly = $ifname['friendly'];
3531
		if ($config['interfaces'][$friendly]['ipaddr'] == "dhcp") {
3532
			$ints[] = $friendly;
3533
			continue;
3534
		}
3535
		if ($config['interfaces'][$friendly]['ipaddr'] == "pppoe") {
3536
			$ints[] = $friendly;
3537
			continue;
3538
		}
3539
		if ($config['interfaces'][$friendly]['ipaddr'] == "pptp") {
3540
			$ints[] = $friendly;
3541
			continue;
3542
		}
3543
		if ($config['interfaces'][$friendly]['gateway'] <> "") {
3544
			$ints[] = $friendly;
3545
			continue;
3546
		}
3547
	}
3548
	return $ints;
3549
}
3550

    
3551
/* return true if interface has a gateway */
3552
function interface_has_gateway($friendly) {
3553
	$friendly = strtolower($friendly);
3554
	if(in_array($friendly, get_interfaces_with_gateway())) {
3555
		return true;
3556
	} else {
3557
		/* extra check for real interface names if it falls through */
3558
		$friendly = convert_real_interface_to_friendly_interface_name($friendly);
3559
		return(in_array($friendly, get_interfaces_with_gateway()));
3560
	}
3561
}
3562

    
3563
/****f* pfsense-utils/isAjax
3564
 * NAME
3565
 *   isAjax - reports if the request is driven from prototype
3566
 * INPUTS
3567
 *   none
3568
 * RESULT
3569
 *   true/false
3570
 ******/
3571
function isAjax() {
3572
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
3573
}
3574

    
3575
//returns interface information
3576
function get_interface_info($ifdescr) {
3577
	global $config, $linkinfo, $netstatrninfo;
3578

    
3579
	$ifinfo = array();
3580

    
3581
	/* find out interface name */
3582
	$ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if'];
3583
	if ($ifdescr == "wan")
3584
		$ifinfo['if'] = get_real_wan_interface();
3585
	else
3586
		$ifinfo['if'] = $ifinfo['hwif'];
3587

    
3588
	/* run netstat to determine link info */
3589

    
3590
	unset($linkinfo);
3591
	exec("/usr/bin/netstat -I " . $ifinfo['hwif'] . " -nWb -f link", $linkinfo);
3592
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3593
	if (preg_match("/\*$/", $linkinfo[0])) {
3594
		$ifinfo['status'] = "down";
3595
	} else {
3596
		$ifinfo['status'] = "up";
3597
	}
3598

    
3599
	if (!strstr($ifinfo['if'],'tun')) {
3600
		$ifinfo['macaddr'] = $linkinfo[3];
3601
		$ifinfo['inpkts'] = $linkinfo[4];
3602
		$ifinfo['inerrs'] = $linkinfo[5];
3603
		$ifinfo['inbytes'] = $linkinfo[6];
3604
		$ifinfo['outpkts'] = $linkinfo[7];
3605
		$ifinfo['outerrs'] = $linkinfo[8];
3606
		$ifinfo['outbytes'] = $linkinfo[9];
3607
		$ifinfo['collisions'] = $linkinfo[10];
3608
	} else {
3609
		$ifinfo['inpkts'] = $linkinfo[3];
3610
		$ifinfo['inbytes'] = $linkinfo[5];
3611
		$ifinfo['outpkts'] = $linkinfo[6];
3612
		$ifinfo['outbytes'] = $linkinfo[8];
3613
	}
3614

    
3615
	/* DHCP? -> see if dhclient is up */
3616
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "dhcp")) {
3617
		/* see if dhclient is up */
3618
		if (is_dhcp_running("wan") == true)
3619
			$ifinfo['dhcplink'] = "up";
3620
		else
3621
			$ifinfo['dhcplink'] = "down";
3622
	}
3623
	/* loop through optional interfaces looking to see if they are dhcp */
3624
        for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
3625
                $ifdescrs['opt' . $j] = $config['interfaces']['opt' . $j]['descr'];
3626
                if (($ifdescr == "opt{$j}") && ($config['interfaces']['opt' . $j]['ipaddr'] == "dhcp")) {
3627
                        /* see if dhclient is up */
3628
                        if (is_dhcp_running("opt{$j}") == true)
3629
                                $ifinfo['dhcplink'] = "up";
3630
                        else
3631
                                $ifinfo['dhcplink'] = "down";
3632
                }
3633
        }
3634

    
3635
	/* PPPoE interface? -> get status from virtual interface */
3636
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pppoe")) {
3637
		unset($linkinfo);
3638
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3639
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3640
		if (preg_match("/\*$/", $linkinfo[0])) {
3641
			$ifinfo['pppoelink'] = "down";
3642
		} else {
3643
			/* get PPPoE link status for dial on demand */
3644
			$ifconfiginfo = "";
3645
			unset($ifconfiginfo);
3646
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3647

    
3648
			$ifinfo['pppoelink'] = "up";
3649

    
3650
			foreach ($ifconfiginfo as $ici) {
3651
				if (strpos($ici, 'LINK0') !== false)
3652
					$ifinfo['pppoelink'] = "down";
3653
			}
3654
		}
3655
	}
3656

    
3657
	/* PPTP interface? -> get status from virtual interface */
3658
	if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pptp")) {
3659
		unset($linkinfo);
3660
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
3661
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
3662
		if (preg_match("/\*$/", $linkinfo[0])) {
3663
			$ifinfo['pptplink'] = "down";
3664
		} else {
3665
			/* get PPTP link status for dial on demand */
3666
			unset($ifconfiginfo);
3667
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3668

    
3669
			$ifinfo['pptplink'] = "up";
3670

    
3671
			foreach ($ifconfiginfo as $ici) {
3672
				if (strpos($ici, 'LINK0') !== false)
3673
					$ifinfo['pptplink'] = "down";
3674
			}
3675
		}
3676
	}
3677

    
3678
	if ($ifinfo['status'] == "up") {
3679
		/* try to determine media with ifconfig */
3680
		unset($ifconfiginfo);
3681
		exec("/sbin/ifconfig " . $ifinfo['hwif'], $ifconfiginfo);
3682
		$matches = "";
3683
		foreach ($ifconfiginfo as $ici) {
3684

    
3685
			/* don't list media/speed for wireless cards, as it always
3686
			   displays 2 Mbps even though clients can connect at 11 Mbps */
3687
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
3688
				$ifinfo['media'] = $matches[1];
3689
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
3690
				$ifinfo['media'] = $matches[1];
3691
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
3692
				$ifinfo['media'] = $matches[1];
3693
			}
3694

    
3695
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
3696
				if ($matches[1] != "active")
3697
					$ifinfo['status'] = $matches[1];
3698
			}
3699
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
3700
				$ifinfo['channel'] = $matches[1];
3701
			}
3702
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
3703
				if ($matches[1][0] == '"')
3704
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
3705
				else
3706
					$ifinfo['ssid'] = $matches[1];
3707
			}
3708
		}
3709

    
3710
		if ($ifinfo['pppoelink'] != "down" && $ifinfo['pptplink'] != "down") {
3711
			/* try to determine IP address and netmask with ifconfig */
3712
			unset($ifconfiginfo);
3713
			exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
3714

    
3715
			foreach ($ifconfiginfo as $ici) {
3716
				if (preg_match("/inet (\S+)/", $ici, $matches)) {
3717
					$ifinfo['ipaddr'] = $matches[1];
3718
				}
3719
				if (preg_match("/netmask (\S+)/", $ici, $matches)) {
3720
					if (preg_match("/^0x/", $matches[1]))
3721
						$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
3722
				}
3723
			}
3724

    
3725
			if ($ifdescr == "wan") {
3726
				/* run netstat to determine the default gateway */
3727
				unset($netstatrninfo);
3728
				exec("/usr/bin/netstat -rnf inet", $netstatrninfo);
3729

    
3730
				foreach ($netstatrninfo as $nsr) {
3731
					if (preg_match("/^default\s*(\S+)/", $nsr, $matches)) {
3732
						$ifinfo['gateway'] = $matches[1];
3733
					}
3734
				}
3735
			} else {
3736
				/* deterimine interface gateway */
3737
				$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3738
				$gw = get_interface_gateway($int);
3739
				if($gw)
3740
					$ifinfo['gateway'] = $gw;
3741
			}
3742
		}
3743
	}
3744

    
3745
	$bridge = "";
3746
	$int = "";
3747
	$int = convert_friendly_interface_to_real_interface_name($ifdescr);
3748
	$bridge = link_int_to_bridge_interface($int);
3749
	if($bridge) {
3750
		$bridge_text = `/sbin/ifconfig {$bridge}`;
3751
		if(stristr($bridge_text, "blocking") <> false) {
3752
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
3753
			$ifinfo['bridgeint'] = $bridge;
3754
		} else if(stristr($bridge_text, "learning") <> false) {
3755
			$ifinfo['bridge'] = "learning";
3756
			$ifinfo['bridgeint'] = $bridge;
3757
		} else if(stristr($bridge_text, "forwarding") <> false) {
3758
			$ifinfo['bridge'] = "forwarding";
3759
			$ifinfo['bridgeint'] = $bridge;
3760
		}
3761
	}
3762

    
3763
	return $ifinfo;
3764
}
3765

    
3766
//returns cpu speed of processor. Good for determining capabilities of machine
3767
function get_cpu_speed() {
3768
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
3769
}
3770

    
3771
/* check if the wan interface is up
3772
 * Wait for a maximum of 10 seconds
3773
 * If the interface is up before then continue
3774
 */
3775
function is_wan_interface_up($interface) {
3776
	global $g;
3777
	global $config;
3778
	$i = 0;
3779
	while($i < 10) {
3780
		if(get_interface_gateway($interface)) {
3781
			return true;
3782
		} else {
3783
			sleep(1);
3784
		}
3785
		$i++;
3786
	}
3787
	return false;
3788
}
3789

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

    
3819
function find_dns_aliases() {
3820
	global $config, $g;
3821
	foreach((array) $config['aliases']['alias'] as $alias) {
3822
		$alias_value = $alias['address'];
3823
		$alias_name = $alias['name'];
3824
		if(stristr($alias_value, " ")) {
3825
			$alias_split = split(" ", $alias_value);
3826
			foreach($alias_split as $as) {
3827
				if(is_fqdn($as)) 
3828
					add_hostname_to_watch($as);			
3829
			}
3830
		} else {
3831
			if(is_fqdn($alias_value)) 
3832
				add_hostname_to_watch($alias_value);
3833
		}
3834
	}
3835
}
3836

    
3837
function is_fqdn($fqdn) {
3838
	$hostname = false;
3839
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
3840
		$hostname = true;
3841
	}
3842
	if(preg_match("/\.\./", $fqdn)) {
3843
		$hostname = false;
3844
	}
3845
	if(preg_match("/^\./i", $fqdn)) {
3846
		$hostname = false;
3847
	}
3848
	if(preg_match("/\//i", $fqdn)) {
3849
		$hostname = false;
3850
	}
3851
	return($hostname);
3852
}
3853

    
3854
function pfsense_default_state_size() {
3855
  /* get system memory amount */
3856
  $memory = get_memory();
3857
  $avail = $memory[0];
3858
  /* Be cautious and only allocate 10% of system memory to the state table */
3859
  $max_states = (int) ($avail/10)*1000;
3860
  return $max_states;
3861
}
3862

    
3863
function lookup_gateway_ip_by_name($name) {
3864
	global $config;
3865
	if(is_array($config['gateways'])) {
3866
		foreach($config['gateways']['gateway_item'] as $gateway) {
3867
			if($gateway['name'] == "$name") {
3868
				$gatewayip = $gateway['gateway'];
3869
				$interfacegw = $gateway['interface'];
3870
				return($gatewayip);
3871
			}
3872
		}
3873
	} else {
3874
		return(false);
3875
	}
3876
}
3877

    
3878
function lookup_gateway_interface_by_name($name) {
3879
	global $config;
3880
	if(is_array($config['gateways'])) {
3881
		foreach($config['gateways']['gateway_item'] as $gateway) {
3882
			if($gateway['name'] == "$name") {
3883
				$gatewayip = $gateway['gateway'];
3884
				$interfacegw = $gateway['interface'];
3885
				return($interfacegw);
3886
			}
3887
		}
3888
	} else {
3889
		return(false);
3890
	}
3891
}
3892

    
3893
?>
(15-15/29)