Project

General

Profile

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

    
36
/****f* pfsense-utils/have_natonetooneruleint_access
37
 * NAME
38
 *   have_natonetooneruleint_access
39
 * INPUTS
40
 *	 none
41
 * RESULT
42
 *   returns true if user has access to edit a specific firewall nat one to one interface
43
 ******/
44
function have_natonetooneruleint_access($if) {
45
	$security_url = "firewall_nat_1to1_edit.php?if=". strtolower($if);
46
	if(isAllowedPage($security_url, $allowed)) 
47
		return true;
48
	return false;
49
}
50

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

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

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

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

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

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

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

    
197
	if (isset($rule['disabled']))
198
		return "";
199
	$pptpdcfg = $config['pptpd'];
200
	$pppoecfg = $config['pppoe'];
201
	$int = "";
202
	/* Check to see if the interface is in our list */
203
	if (isset($rule['floating'])) {
204
		if (isset($rule['interface']) && $rule['interface'] <> "") 
205
			$aline['interface'] = "multiple"; /* XXX */
206
		else
207
			$aline['interface'] = "";
208
	} else if (!array_key_exists($rule['interface'], $FilterIflist)) 
209
			return "# {$rule['interface']} does not exist or is disabled for " . $rule['descr'];
210
	else {
211
		if ($rule['interface'] == "pptp" || $rule['interface'] == "pppoe")
212
			$aline['interface'] = "ng*";
213
		else
214
			$aline['interface'] = " " . $FilterIflist[$rule['interface']]['if'] . " ";
215
	}
216

    
217
	$ifcfg = $FilterIflist[$rule['interface']];
218
	if ($pptpdcfg['mode'] != "server") {
219
		if (($rule['source']['network'] == "pptp") ||
220
			($rule['destination']['network'] == "pptp")) 
221
				return "# source network or destination network == pptp on " . $rule['descr'];
222
	}
223
	if ($rule['source']['network'] && strstr($rule['source']['network'], "opt")) {
224
		if (!array_key_exists($rule['source']['network'], $FilterIflist)) {
225
			$optmatch = "";
226
			if (preg_match("/opt([0-999])/", $rule['source']['network'], $optmatch)) {
227
				$opt_ip = $FilterIflist["opt{$optmatch[1]}"]['ip'];
228
				if(!is_ipaddr($opt_ip))
229
					return "# unresolvable optarray $optmatch[0] - $opt_ip";
230
			} else {
231
				return "# tdr {$rule['source']['network']} !array_key_exists source network " . $rule['descr'];
232
			}
233
		}
234
	}
235
	if ($rule['destination']['network'] && strstr($rule['destination']['network'], "opt")) {
236
		if (!array_key_exists($rule['destination']['network'], $FilterIflist)) {
237
			if(preg_match("/opt([0-999])/", $rule['destination']['network'], $optmatch)) {
238
				$opt_ip = $FilterIflist["opt{$optmatch[1]}"]['ip'];
239
				if(!is_ipaddr($opt_ip))
240
					return "# unresolvable oparray $optmatch[0] - $opt_ip";
241
			} else {
242
				return "# tdr {$item} {$rule['destination']['network']} !array_key_exists dest network " . $rule['descr'];
243
			}
244
		}
245
	}
246
	/* check for unresolvable aliases */
247
	if ($rule['source']['address'] && !alias_expand($rule['source']['address'])) {
248
		file_notice("Filter_Reload", "# unresolvable source aliases {$rule['descr']}");
249
		return "# tdr unresolvable source aliases {$rule['descr']}";
250
	}
251
	if ($rule['destination']['address'] && !alias_expand($rule['destination']['address'])) {
252
		file_notice("Filter_Reload", "# unresolvable dest aliases {$rule['descr']}");
253
		return "# tdr unresolvable dest aliases {$rule['descr']}";
254
	}
255

    
256
	if (isset($rule['protocol'])) {
257
		if($rule['protocol'] == "tcp/udp")
258
			$aline['prot'] = "ip ";
259
		else if($rule['protocol'] == "icmp")
260
			$aline['prot'] = "icmp ";
261
		else
262
			$aline['prot'] = "{$rule['protocol']} ";
263
	} else {
264
		if($rule['source']['port'] <> "" || $rule['destination']['port'] <> "")
265
			$aline['prot'] = "tcp ";
266
	}
267

    
268
	/* source address */
269
	if (isset($rule['source']['any']))
270
		$src = "any";
271
	else if ($rule['source']['network']) {
272
		if (strstr($rule['source']['network'], "opt")) {
273
			$src = $FilterIflist[$rule['source']['network']]['sa'] . "/" .
274
				$FilterIflist[$rule['source']['network']]['sn'];
275
			if (isset($rule['source']['not'])) 
276
				$src = " not {$src}";
277
			/* check for opt$NUMip here */
278
			$matches = "";
279
			if (preg_match("/opt([0-9999])ip/", $rule['source']['network'], $matches)) {
280
				$optnum = $matches[1];
281
				$src = $FilterIflist["opt{$optnum}"]['ip'];
282
			}
283
		} else {
284
			switch ($rule['source']['network']) {
285
				case 'wanip':
286
					$src = $FilterIflist["wan"]['ip'];
287
					break;
288
				case 'lanip':
289
					$src = $FilterIflist["lan"]['ip'];
290
					break;
291
				case 'lan':
292
					$lansa = $FilterIflist['lan']['sa'];
293
					$lansn = $FilterIflist['lan']['sn'];
294
					$src = "{$lansa}/{$lansn}";
295
					break;
296
				case 'pptp':
297
					$pptpsa = gen_subnet($FilterIflist['pptp']['ip'], $FilterIflist['pptp']['sn']);
298
					$pptpsn = $FilterIflist['pptp']['sn'];
299
					$src = "{$pptpsa}/{$pptpsn}";
300
					break;
301
				case 'pppoe':
302
					$pppoesa = gen_subnet($FilterIflist['pppoe']['ip'], $FilterIflist['pppoe']['sn']);
303
					$pppoesn = $FilterIflist['pppoe']['sn'];
304
					$src = "{$pppoesa}/{$pppoesn}";
305
					break;
306
			}
307
			if (isset($rule['source']['not'])) 
308
				$src = " not {$src}";
309
		}
310
	} else if ($rule['source']['address']) {
311
		$expsrc = alias_expand_value($rule['source']['address']);
312
		if(!$expsrc) 
313
			$expsrc = $rule['source']['address'];
314
				
315
		if (isset($rule['source']['not']))
316
			$not = " not";
317
		else
318
			$not = "";
319

    
320
		if (alias_expand_value($rule['source']['address'])) {
321
			$src = "{";
322
			$first_item = true;
323
			foreach(preg_split("/[\s]+/", alias_expand_value($rule['source']['address'])) as $item) {
324
				if($item != "") {
325
					if(!$first_item) 
326
						$src .= " or";
327
						$src .= " {$not}{$item}";
328
						$first_item = false;
329
					}
330
				}
331
					$src .= " }";
332
		} else
333
			$src = "{$not}" . $expsrc;
334
	}
335
	if (!$src || ($src == "/")) 
336
		return "# tdr at the break!";
337
	
338
	$aline['src'] = "from $src ";
339

    
340
	$srcporta = "";
341
	if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
342
		if ($rule['source']['port']) {
343
			$srcport = explode("-", $rule['source']['port']);
344
			if(alias_expand($srcport[0])) {
345
				$first_time = true;
346
				foreach(preg_split("/[\s]+/", alias_expand_value($srcport[0])) as $item) {
347
					if(!$first_time) 
348
						$srcporta .= ",";				
349
					$srcporta .= $item;
350
					$first_time = false;
351
				}
352
			} else 
353
				$srcporta = $srcport[0];
354
			
355
			if ((!$srcport[1]) || ($srcport[0] == $srcport[1])) {
356
				if(alias_expand($srcport[0]))
357
					$aline['srcport'] = "{$srcporta} ";
358
				else
359
					$aline['srcport'] = "{$srcporta} ";
360
			} else if (($srcport[0] == 1) && ($srcport[1] == 65535)) {
361
				/* no need for a port statement here */
362
			} else if ($srcport[1] == 65535) 
363
				$aline['srcport'] = ">={$srcport[0]} ";
364
			else if ($srcport[0] == 1) 
365
				$aline['srcport']= "<={$srcport[1]} ";
366
			else 
367
				$aline['srcport'] = "{$srcport[0]}-{$srcport[1]} ";
368
		}
369
	}
370

    
371
	/* destination address */
372
	if (isset($rule['destination']['any']))
373
		$dst = "any";
374
	else if ($rule['destination']['network']) {
375
		if (strstr($rule['destination']['network'], "opt")) {
376
			$dst = $FilterIflist[$rule['destination']['network']]['sa'] . "/" .
377
				$FilterIflist[$rule['destination']['network']]['sn'];
378
			if (isset($rule['destination']['not'])) 
379
				$dst = " not {$dst}";
380
			/* check for opt$NUMip here */
381
			$matches = "";
382
			if (preg_match("/opt([0-9999])ip/", $rule['destination']['network'], $matches)) {
383
				$optnum = $matches[1];
384
				$dst = $FilterIflist["opt{$optnum}"]['ip'];
385
			}
386
		} else {
387
			switch ($rule['source']['network']) {
388
				case 'wanip':
389
					$dst = $FilterIflist["wan"]['ip'];
390
					break;
391
				case 'lanip':
392
					$dst = $FilterIflist["lan"]['ip'];
393
					break;
394
				case 'lan':
395
					$lansa = $FilterIflist['lan']['sa'];
396
					$lansn = $FilterIflist['lan']['sn'];
397
					$dst = "{$lansa}/{$lansn}";
398
					break;
399
				case 'pptp':
400
					$pptpsa = gen_subnet($FilterIflist['pptp']['ip'], $FilterIflist['pptp']['sn']);
401
					$pptpsn = $FilterIflist['pptp']['sn'];
402
					$dst = "{$pptpsa}/{$pptpsn}";
403
					break;
404
				case 'pppoe':
405
					$pppoesa = gen_subnet($FilterIflist['pppoe']['ip'], $FilterIflist['pppoe']['sn']);
406
					$pppoesn = $FilterIflist['pppoe']['sn'];
407
					$dst = "{$pppoesa}/{$pppoesn}";
408
					break;
409
			}
410
			if (isset($rule['destination']['not'])) 
411
				$dst = " not {$dst}";
412
		}
413
	} else if ($rule['destination']['address']) {
414
		$expdst = alias_expand_value($rule['destination']['address']);
415
		if(!$expdst) 
416
			$expdst = $rule['destination']['address'];
417
				
418
		if (isset($rule['destination']['not']))
419
			$not = " not";
420
		else
421
			$not = "";
422

    
423
		if (alias_expand_value($rule['destination']['address'])) {
424
			$dst = "{";
425
			$first_item = true;
426
			foreach(preg_split("/[\s]+/", alias_expand_value($rule['destination']['address'])) as $item) {
427
				if($item != "") {
428
					if(!$first_item) 
429
						$dst .= " or";
430
						$dst .= " {$not}{$item}";
431
						$first_item = false;
432
					}
433
				}
434
					$dst .= " }";
435
		} else
436
			$dst = "{$not}" . $expdst;
437
	}
438

    
439
	if (!$dst || ($dst == "/")) 
440
		return "# returning at dst $dst == \"/\"";
441

    
442
	$aline['dst'] = "to $dst ";
443
	$dstporta = "";
444
	if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
445
		if ($rule['destination']['port']) {
446
			$dstport = explode("-", $rule['destination']['port']);
447
			if(alias_expand($dstport[0])) {
448
				$first_time = true;
449
				foreach(preg_split("/[\s]+/", alias_expand_value($dstport[0])) as $item) {
450
					if(!$first_time)
451
				 		$dstporta .= ",";
452
					$dstporta .= $item;			
453
					$first_time = false;
454
				}
455
			} else 
456
				$dstporta = $dstport[0];
457
		
458
			if ((!$dstport[1]) || ($dstport[0] == $dstport[1])) {
459
				if(alias_expand($dstport[0]))
460
					$aline['dstport'] = "{$dstporta} ";
461
				else
462
					$aline['dstport'] = "{$dstporta} ";
463
			} else if (($dstport[0] == 1) && ($dstport[1] == 65535)) {
464
				/* no need for a port statement here */
465
			} else if ($dstport[1] == 65535) 
466
				$aline['dstport'] = ">= {$dstport[0]} ";
467
			else if ($dstport[0] == 1)
468
				$aline['dstport'] = "<= {$dstport[1]} ";
469
			else
470
				$aline['dstport'] = "{$dstport[0]}-{$dstport[1]} ";
471
		}
472
	}
473
	
474
	if($aline['prot'] == "")
475
		$aline['prot'] = "ip ";
476

    
477
	tdr_get_next_ipfw_rule();
478

    
479
 	/* piece together the actual user rule */
480
	if($type == "skipto") {
481
		$next_rule = tdr_get_next_ipfw_rule();
482
		$next_rule = $next_rule+1;
483
		$type = "skipto $next_rule";
484
	}
485

    
486
	/* piece together the actual user rule */
487
	if ($aline['interface'] == "multiple") {
488
		$tmpline = $type . " " . $aline['prot'] . $aline['src'] . 
489
			$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in recv ";
490
		$interfaces = explode(",", $rule['interface']);
491
		$ifliste = "";
492
		foreach ($interfaces as $iface) {
493
			if (array_key_exists($iface, $FilterIflist)) 
494
				$line .= "{$tmpline} " . $FilterIflist[$iface]['if'] . "; ";/* XXX */
495
		}
496
	} else if ($aline['interface'] == "")
497
		$line .= $type . " " . $aline['prot'] . $aline['src'] . 
498
			$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in ";
499
	else
500
		$line .= $type . " " . $aline['prot'] . $aline['src'] . 
501
			$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in recv " .
502
			$aline['interface'];
503

    
504
	return $line;
505
}
506

    
507
/****f* pfsense-utils/tdr_install_rule
508
 * NAME
509
 *   tdr_install_rule
510
 * INPUTS
511
 *   $rule - ascii string containing the ifpw rule to add
512
 * RESULT
513
 *   none
514
 ******/
515
function tdr_install_rule($rule) {
516
	global $tdr_next_ipfw_rule, $g;
517

    
518
	log_error("installing {$rule}");
519
	$lines = explode(";", $rule);
520
	if (count($lines) > 1) {
521
		foreach ($lines as $line) {
522
			if ($g['debug'])
523
				log_error("Executing /sbin/ipfw -f add {$tdr_next_ipfw_rule} set 9 $line");
524
			mwexec("/sbin/ipfw -f add {$tdr_next_ipfw_rule} set 9 $line");
525
			$tdr_next_ipfw_rule++;
526
		}
527
	} else {
528
		if ($g['debug'])
529
			log_error("Executing /sbin/ipfw -f add {$tdr_next_ipfw_rule} set 9 $rules");
530
		mwexec("/sbin/ipfw -f add $tdr_next_ipfw_rule set 9 $rule");
531
	}
532
	$tdr_next_ipfw_rule++;
533
}
534

    
535
/****f* pfsense-utils/tdr_get_next_ipfw_rule
536
 * NAME
537
 *   tdr_get_next_ipfw_rule
538
 * INPUTS
539
 *  none
540
 * RESULT
541
 *   returns the next available ipfw rule number
542
 ******/
543
function tdr_get_next_ipfw_rule() {
544
	global $tdr_next_ipfw_rule;
545
	if(intval($tdr_next_ipfw_rule) < 2) 
546
		$tdr_next_ipfw_rule = 2;
547
	return $tdr_next_ipfw_rule;
548
 }
549

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

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

    
656
		if($monthstatus == true) 
657
			if($daystatus == true) 
658
				if($positionstatus == true) 
659
					if($hourstatus == true) {
660
						$should_add_rule = true;
661
					}
662
	}
663
	
664
	return $should_add_rule;
665
}
666

    
667
function tdr_day($schedule) {
668
	/*
669
	 * Calculate day of month. 
670
	 * IE: 29th of may
671
	 */
672
	$weekday	= date("w");
673
	if ($weekday == 0)
674
		$weekday = 7;
675
	$date	 	= date("d");
676
	$defined_days = split(",", $schedule);
677
	log_error("[TDR DEBUG] tdr_day($schedule)");
678
	foreach($defined_days as $dd) {
679
		if($date == $dd) {
680
			return true;
681
		}
682
	}
683
	return false;
684
}
685

    
686
function tdr_hour($schedule) {
687
	/* $schedule should be a string such as 16:00-19:00 */
688
	$tmp = split("-", $schedule);
689
	$starting_time = strtotime($tmp[0]);
690
	$ending_time = strtotime($tmp[1]);
691
	$now = strtotime("now");
692
	log_error("[TDR DEBUG] S: $starting_time E: $ending_time N: $now");
693
	if($now >= $starting_time and $now <= $ending_time) {
694
		return true;
695
	}
696
	return false;
697
}
698

    
699
function tdr_position($schedule) {
700
	/*
701
	 * Calculate possition, ie: day of week.
702
	 * Sunday = 7, Monday = 1, Tuesday = 2
703
	 * Weds = 3, Thursday = 4, Friday = 5,
704
	 * Saturday = 6
705
	 * ...
706
	 */
707
	$weekday	= date("w");
708
	log_error("[TDR DEBUG] tdr_position($schedule) $weekday");
709
	if ($weekday == 0)
710
		$weekday = 7;
711
	$schedule_days = split(",", $schedule);
712
	foreach($schedule_days as $day) {
713
		if($day == $weekday) {
714
			return true;
715
		}
716
	}
717
	return false;
718
}
719

    
720
function tdr_month($schedule) {
721
	/*
722
	 * Calculate month
723
	 */
724
	$todays_month = date("n");
725
	$months = split(",", $schedule);
726
	log_error("[TDR DEBUG] tdr_month($schedule)");
727
	foreach($months as $month) {
728
		if($month == $todays_month) {
729
			return true;
730
		}
731
	}
732
	return false;
733
}
734

    
735
/****f* pfsense-utils/find_number_of_needed_carp_interfaces
736
 * NAME
737
 *   find_number_of_needed_carp_interfaces
738
 * INPUTS
739
 *   null
740
 * RESULT
741
 *   the number of needed carp interfacs
742
 ******/
743
function find_number_of_needed_carp_interfaces() {
744
	global $config, $g;
745
	$carp_counter=0;
746
	if(!$config['virtualip'])
747
		return 0;
748
	if(!$config['virtualip']['vip'])
749
		return 0;
750
	foreach($config['virtualip']['vip'] as $vip) {
751
		if($vip['mode'] == "carp")
752
			$carp_counter++;
753
	}
754
	return $carp_counter;
755
}
756

    
757
/****f* pfsense-utils/reset_carp
758
 * NAME
759
 *   reset_carp - resets carp after primary interface changes
760
 * INPUTS
761
 *   null
762
 * RESULT
763
 *   null
764
 ******/
765
function reset_carp() {
766
	$carp_counter=find_number_of_created_carp_interfaces();
767
	$needed_carp_interfaces = find_number_of_needed_carp_interfaces();
768
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
769
	for($x=0; $x<$carp_counter; $x++) {
770
		mwexec("/sbin/ifconfig carp{$x} down");
771
		usleep(1000);
772
		mwexec("/sbin/ifconfig carp{$x} delete");
773
		if($needed_carp_interfaces < $carp_counter) {
774
			$needed_carp_interfaces--;
775
			//log_error("Destroying carp interface.");
776
			//mwexec("/sbin/ifconfig carp{$x} destroy");
777
		}
778
	}
779
	find_number_of_created_carp_interfaces(true);
780
	sleep(1);
781
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
782
	interfaces_carp_configure();
783
}
784

    
785
/****f* pfsense-utils/get_dns_servers
786
 * NAME
787
 *   get_dns_servres - get system dns servers
788
 * INPUTS
789
 *   $dns_servers - an array of the dns servers
790
 * RESULT
791
 *   null
792
 ******/
793
function get_dns_servers() {
794
	$dns_servers = array();
795
	$dns = `cat /etc/resolv.conf`;
796
	$dns_s = split("\n", $dns);
797
	foreach($dns_s as $dns) {
798
		$matches = "";
799
		if (preg_match("/nameserver (.*)/", $dns, $matches))
800
			$dns_servers[] = $matches[1];
801
	}
802
	$dns_server_master = array();
803
	$lastseen = "";
804
	foreach($dns_servers as $t) {
805
		if($t <> $lastseen)
806
			if($t <> "")
807
				$dns_server_master[] = $t;
808
		$lastseen = $t;
809
	}
810
	return $dns_server_master;
811
}
812

    
813
/****f* pfsense-utils/log_error
814
* NAME
815
*   log_error  - Sends a string to syslog.
816
* INPUTS
817
*   $error     - string containing the syslog message.
818
* RESULT
819
*   null
820
******/
821
function log_error($error) {
822
	global $g;
823
	$page = $_SERVER['SCRIPT_NAME'];
824
	syslog(LOG_WARNING, "$page: $error");
825
	if ($g['debug'])
826
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
827
	return;
828
}
829

    
830
/****f* pfsense-utils/get_interface_mac_address
831
 * NAME
832
 *   get_interface_mac_address - Return a interfaces mac address
833
 * INPUTS
834
 *   $interface	- interface to obtain mac address from
835
 * RESULT
836
 *   $mac - the mac address of the interface
837
 ******/
838
function get_interface_mac_address($interface) {
839
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
840
	if(is_macaddr($mac)) {
841
		return trim($mac);
842
	} else {
843
		return "";
844
	}
845
}
846

    
847
/****f* pfsense-utils/return_dir_as_array
848
 * NAME
849
 *   return_dir_as_array - Return a directory's contents as an array.
850
 * INPUTS
851
 *   $dir	- string containing the path to the desired directory.
852
 * RESULT
853
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
854
 ******/
855
function return_dir_as_array($dir) {
856
	$dir_array = array();
857
	if (is_dir($dir)) {
858
		if ($dh = opendir($dir)) {
859
			while (($file = readdir($dh)) !== false) {
860
				$canadd = 0;
861
				if($file == ".") $canadd = 1;
862
				if($file == "..") $canadd = 1;
863
				if($canadd == 0)
864
					array_push($dir_array, $file);
865
			}
866
			closedir($dh);
867
		}
868
	}
869
	return $dir_array;
870
}
871

    
872
/****f* pfsense-utils/enable_hardware_offloading
873
 * NAME
874
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
875
 * INPUTS
876
 *   $interface	- string containing the physical interface to work on.
877
 * RESULT
878
 *   null
879
 * NOTES
880
 *   This function only supports the fxp driver's loadable microcode.
881
 ******/
882
function enable_hardware_offloading($interface) {
883
	global $g, $config;
884

    
885
	if(stristr($interface,"lnc"))
886
		return;
887

    
888
	if(isset($config['system']['do_not_use_nic_microcode']))
889
		return;
890

    
891
	/* translate wan, lan, opt -> real interface if needed */
892
	$int = filter_translate_type_to_real_interface($interface);
893
	if($int <> "")	
894
		$interface = $int;
895
	$int_family = preg_split("/[0-9]+/", $int);
896
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
897
	$supported_ints = array('fxp');
898
	if (in_array($int_family, $supported_ints))
899
		mwexec("/sbin/ifconfig {$interface} link0");
900

    
901
	if($config['system']['disablechecksumoffloading'])
902
		return;
903

    
904
	if(stristr($options, "txcsum") == true)
905
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
906

    
907
	if(stristr($options, "rxcsum") == true)
908
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
909

    
910
	/* if the NIC supports polling *AND* it is enabled in the GUI */
911
	if(interface_supports_polling($interface)) {
912
		$polling = isset($config['system']['polling']);	
913
		if($polling) {
914
			mwexec("sysctl kern.polling.enable=1");
915
	    	mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
916
		} else {
917
			mwexec("sysctl kern.polling.enable=0");
918
		}
919
	}
920
	return;
921
}
922

    
923
/****f* pfsense-utils/interface_supports_polling
924
 * NAME
925
 *   checks to see if an interface supports polling according to man polling
926
 * INPUTS
927
 *
928
 * RESULT
929
 *   true or false
930
 * NOTES
931
 *
932
 ******/
933
function interface_supports_polling($iface) {
934
	$pattern = '/([a-z].*)[0-9]/';
935
	preg_match($pattern, $iface, $iface2);
936
	$interface=$iface2[1];
937
	$supported_ints = array("bge",
938
		"dc",
939
		"em",
940
		"fwe",
941
		"fwip",
942
		"fxp",
943
		"ixgb",
944
		"nfe",
945
		"vge",
946
		"re",
947
		"rl",
948
		"sf",
949
		"sis",
950
		"ste",
951
		"stge",    
952
		"vge",
953
		"vr",
954
		"xl");
955
	if(in_array($interface, $supported_ints))
956
		return true;
957
	return false;
958
}
959

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

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

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

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

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

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

    
1051
	setup_polling_defaults();
1052

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1394
	return $interface_arr_cache;
1395
}
1396

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1802
    return $wanif;
1803
}
1804

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

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

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

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

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

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

    
1881
        return $ifdesc;
1882
}
1883

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

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

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

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

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

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

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

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

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

    
1947
	return false;
1948
}
1949

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

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

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

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

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

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

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

    
2087
";
2088

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

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

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

    
2104
	return $ret;
2105
}
2106

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2431

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

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

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

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

    
2501
	$shutdown_webgui_needed = false;
2502

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2613
	$shutdown_webgui_needed = false;
2614

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2711
}
2712

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

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

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

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

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

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

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

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

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

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

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

    
2864
	/* Asume GigE for now */
2865
	$downstream = 125000000;
2866
	$upstream = 125000000;
2867

    
2868
	/* read the shaper config */
2869
	read_altq_config();
2870

    
2871
	$rrdrestore = "";
2872
	$rrdreturn = "";
2873

    
2874
	if (isset ($config['rrd']['enable'])) {
2875

    
2876
		/* create directory if needed */
2877
		if (!is_dir("$rrddbpath")) {
2878
			mkdir("$rrddbpath", 0755);
2879
		}
2880

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

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

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

    
2911
		foreach ($ifdescrs as $realif => $ifdescr) {
2912
			$ifname = $ifdescr['friendly'];
2913
			$state = $ifdescr['up'];
2914

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

    
2920
			/* or are down */
2921
			if (!$state) {
2922
				continue;
2923
			}
2924

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

    
2938
				$rrdcreateoutput = array();
2939
				$rrdcreatereturn = "";
2940

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

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

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

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

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

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

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

    
2996
			/* WIRELESS, set up the rrd file */
2997
			if($config['interfaces'][$ifname]['wireless']['mode'] == "bss") {
2998
				if (!file_exists("$rrddbpath$ifname$wireless")) {
2999
					/* create rrd file if it does not exist */
3000
					log_error("Create RRD database $rrddbpath$ifname$wireless");
3001
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$wireless --step $rrdwirelessinterval ";
3002
					$rrdcreate .= "DS:snr:GAUGE:$wirelessvalid:0:1000 ";
3003
					$rrdcreate .= "DS:rate:GAUGE:$wirelessvalid:0:1000 ";
3004
					$rrdcreate .= "DS:channel:GAUGE:$wirelessvalid:0:1000 ";
3005
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3006
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3007
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3008
					$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3009
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3010
	
3011
					$rrdcreateoutput = array();
3012
					$rrdcreatereturn = "";
3013

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

    
3021
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
3022
				if($g['booting']) {
3023
					exec("$rrdtool update $rrddbpath$ifname$wireless N:U:U:U");
3024
				}
3025

    
3026
				$rrdupdatesh .= "\n";
3027
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
3028
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\\\n";
3029
				$rrdupdatesh .= "`$ifconfig {$realif} list ap| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
3030
			}
3031

    
3032
				/* QUEUES, set up the queues databases */
3033
				if ($altq_list_queues[$ifname]) {
3034
					$altq =& $altq_list_queues[$ifname];
3035
					/* NOTE: Is it worth as its own function?! */
3036
					switch ($altq->GetBwscale()) {
3037
                                        case "Gb":
3038
                                        	$factor = 1000 * 1000 * 1000;
3039
                                                break;
3040
                                        case "Mb":
3041
                                                $factor = 1000 * 1000;
3042
                                                break;
3043
                                        case "Kb":
3044
                                                $factor = 1000;
3045
                                                break;
3046
                                        case "b":
3047
                                        default:
3048
                                                $factor = 1;
3049
                                                break;
3050
                                        }
3051
					$qbandwidth = $altq->GetBandwidth() * $factor;
3052
					if ($qbandwidth <=0)
3053
						$qbandwidth = 100 * 1000 * 1000; /* 100Mbit */
3054
					$qlist =& $altq->get_queue_list($notused);
3055
					if (!file_exists("$rrddbpath$ifname$queues")) {
3056
						/* create rrd file if it does not exist */
3057
						log_error("Create RRD database $rrddbpath$ifname$queues");
3058
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
3059
						/* loop list of shaper queues */
3060
						$q = 0;
3061
						foreach ($qlist as $qname => $q) {
3062
							$rrdcreate .= "DS:$qname:COUNTER:$queuesvalid:0:$qbandwidth ";
3063
						}
3064

    
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
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
3079
						/* create rrd file if it does not exist */
3080
						log_error("Create RRD database $rrddbpath$ifname$queuesdrop");
3081
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
3082
						/* loop list of shaper queues */
3083
						$q = 0;
3084
						foreach ($qlist as $qname => $q) {
3085
							$rrdcreate .= "DS:$qname:COUNTER:$queuesdropvalid:0:$qbandwidth ";
3086
						}
3087

    
3088
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3089
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3090
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3091
						$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3092
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3093

    
3094
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
3095
						if ($rrdcreatereturn != 0) {
3096
							log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
3097
						}
3098
					}
3099

    
3100
					if($g['booting']) {
3101
						$rrdqcommand = "-t ";
3102
						$rrducommand = "N";
3103
						$q = 0;
3104
						foreach ($qlist as $qname => $q) {
3105
							if($q == 0) {
3106
								$rrdqcommand .= "{$qname}";
3107
							} else {
3108
								$rrdqcommand .= ":{$qname}";
3109
							}
3110
							$q++;
3111
							$rrducommand .= ":U";
3112
						}
3113
						exec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
3114
						exec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
3115
					}
3116

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

    
3135
					$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
3136
					$rrdupdatesh .= "{ ";
3137
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
3138
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
3139
					$rrdupdatesh .= "q=1; ";
3140
					$rrdupdatesh .= "} ";
3141
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
3142
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
3143
					$rrdupdatesh .= "q=0; ";
3144
					$rrdupdatesh .= "} ";
3145
					$rrdupdatesh .= "} END { ";
3146
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
3147
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
3148
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
3149
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
3150
				}
3151
		}
3152
		$i++;
3153

    
3154
		/* System only statistics */
3155
		$ifname = "system";
3156

    
3157
			/* STATES, create pf states database */
3158
			if(! file_exists("$rrddbpath$ifname$states")) {
3159
				/* create rrd file if it does not exist */
3160
				log_error("Create RRD database $rrddbpath$ifname$states");
3161
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
3162
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
3163
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
3164
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
3165
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
3166
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
3167
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3168
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3169
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3170
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3171
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3172

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

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

    
3185
 			/* the pf states gathering function. */
3186
 			$rrdupdatesh .= "\n";
3187
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
3188
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
3189
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
3190
 			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
3191
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
3192
 			$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";
3193
 			$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";
3194
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
3195

    
3196
			/* End pf states statistics */
3197

    
3198
			/* CPU, create CPU statistics database */
3199
			if(! file_exists("$rrddbpath$ifname$proc")) {
3200
				/* create rrd file if it does not exist */
3201
				log_error("Create RRD database $rrddbpath$ifname$proc");
3202
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
3203
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
3204
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
3205
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
3206
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
3207
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
3208
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3209
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3210
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3211
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3212
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:1500 ";
3213

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

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

    
3226
 			/* the CPU stats gathering function. */
3227
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { \\\n";
3228
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } \\\n";
3229
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { processes = \$1; } \\\n";
3230
			$rrdupdatesh .= "else if ( \$1 == \"CPU:\" ) { user = \$2; nice = \$4; sys = \$6; interrupt = \$8; } \\\n";
3231
			$rrdupdatesh .= "} END { printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes }'`\n\n";
3232

    
3233
			/* End CPU statistics */
3234

    
3235
			/* Memory, create Memory statistics database */
3236
			if(! file_exists("$rrddbpath$ifname$mem")) {
3237
				/* create rrd file if it does not exist */
3238
				log_error("Create RRD database $rrddbpath$ifname$mem");
3239
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$mem --step $rrdmeminterval ";
3240
				$rrdcreate .= "DS:active:GAUGE:$memvalid:0:10000000 ";
3241
				$rrdcreate .= "DS:inactive:GAUGE:$memvalid:0:10000000 ";
3242
				$rrdcreate .= "DS:free:GAUGE:$memvalid:0:10000000 ";
3243
				$rrdcreate .= "DS:cache:GAUGE:$memvalid:0:10000000 ";
3244
				$rrdcreate .= "DS:wire:GAUGE:$memvalid:0:10000000 ";
3245
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
3246
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
3247
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
3248
				$rrdcreate .= "RRA:MIN:0.5:720:1000 ";
3249
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
3250
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
3251
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
3252
				$rrdcreate .= "RRA:AVERAGE:0.5:720:1000 ";
3253
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
3254
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
3255
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
3256
				$rrdcreate .= "RRA:MAX:0.5:720:1000";
3257

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

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

    
3270
 			/* the Memory stats gathering function. */
3271
 			$rrdupdatesh .= "`$sysctl -n vm.stats.vm.v_page_count vm.stats.vm.v_active_count vm.stats.vm.v_inactive_count vm.stats.vm.v_free_count vm.stats.vm.v_cache_count vm.stats.vm.v_wire_count | ";
3272
			$rrdupdatesh .= " $awk '{getline active;getline inactive;getline free;getline cache;getline wire;printf \"$rrdtool update $rrddbpath$ifname$mem N:\"";
3273
			$rrdupdatesh .= "((active/$0) * 100)\":\"((inactive/$0) * 100)\":\"((free/$0) * 100)\":\"((cache/$0) * 100)\":\"(wire/$0 * 100)}'`\n\n";
3274
			
3275
			/* End Memory statistics */
3276

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

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

    
3310
				$rrdupdatesh .= "\n";
3311
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
3312
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
3313
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
3314

    
3315
			}
3316
		/* End System statistics */
3317

    
3318
		$rrdupdatesh .= "sleep 60\n";
3319
		$rrdupdatesh .= "done\n";
3320
		log_error("Creating rrd update script");
3321
		/* write the rrd update script */
3322
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
3323
		$fd = fopen("$updaterrdscript", "w");
3324
		fwrite($fd, "$rrdupdatesh");
3325
		fclose($fd);
3326

    
3327
		/* kill off traffic collectors */
3328
		kill_traffic_collector();
3329

    
3330
		/* start traffic collector */
3331
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
3332

    
3333
	} else {
3334
		/* kill off traffic collectors */
3335
		kill_traffic_collector();
3336
	}
3337

    
3338
	if($g['booting']) 
3339
		echo "done.\n";
3340
		
3341
}
3342

    
3343
function kill_traffic_collector() {
3344
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
3345
}
3346

    
3347
function update_filter_reload_status($text) {
3348
	global $g;
3349
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
3350
	fwrite($fd, $text);
3351
	fclose($fd);
3352
}
3353

    
3354
function get_interface_gateway($interface) {
3355
        global $config, $g;
3356

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

    
3369
	$gw = NULL;
3370

    
3371
	$gwcfg = $config['interfaces'][$interface];
3372
        if (is_ipaddr($gwcfg['gateway'])) 
3373
        	$gw = $gwcfg['gateway'];
3374
        else if (!empty($gwcfg['gateway']))
3375
		$gw = lookup_gateway_ip_by_name($gwcfg['gateway']);
3376
	
3377
	// for dynamic interfaces we handle them through the $interface_router file.
3378
	if (!is_ipaddr($gw)) {
3379
        	$realif = get_real_interface($interface);
3380
        	if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
3381
                	$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
3382
                	$gw = rtrim($gw);
3383
        	}
3384
	}
3385

    
3386
        /* return gateway */
3387
        return $gw;
3388
}
3389

    
3390
/* DHCP enabled on any interfaces? */
3391
function is_dhcp_server_enabled() 
3392
{
3393
	global $config;
3394

    
3395
	$dhcpdenable = false;
3396
	
3397
	if (!is_array($config['dhcpd']))
3398
		return false;
3399

    
3400
	$Iflist = get_configured_interface_list();
3401

    
3402
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
3403
		if (isset($dhcpifconf['enable']) && isset($Iflist[$dhcpif])) {
3404
			$dhcpdenable = true;
3405
			break;
3406
		}
3407
	}
3408

    
3409
	return $dhcpdenable;
3410
}
3411

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

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

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

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

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

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

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

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

    
3509
	if (preg_match("/^enc|^tun|^ppp|^pptp|^ovpn/i", $ifinfo['if'])) {
3510
		$ifinfo['inpkts'] = $linkinfo[3];
3511
                $ifinfo['inbytes'] = $linkinfo[5];
3512
                $ifinfo['outpkts'] = $linkinfo[6];
3513
                $ifinfo['outbytes'] = $linkinfo[8];
3514
	} else {
3515
		$ifinfo['macaddr'] = $linkinfo[3];
3516
		$ifinfo['inpkts'] = $linkinfo[4];
3517
		$ifinfo['inerrs'] = $linkinfo[5];
3518
		$ifinfo['inbytes'] = $linkinfo[6];
3519
		$ifinfo['outpkts'] = $linkinfo[7];
3520
		$ifinfo['outerrs'] = $linkinfo[8];
3521
		$ifinfo['outbytes'] = $linkinfo[9];
3522
		$ifinfo['collisions'] = $linkinfo[10];
3523
	}
3524

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

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

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

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

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

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

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

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

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

    
3637
	return $ifinfo;
3638
}
3639

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

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

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

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

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

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

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

    
3752
function lookup_gateway_monitor_ip_by_name($name) {
3753
	global $config;
3754
	$gateways_arr = return_gateways_array();
3755

    
3756
	foreach($gateways_arr as $gateway) {
3757
		if($gateway['name'] == "$name") {
3758
			$monitorip = $gateway['monitor'];
3759
			if($monitorip == "")
3760
				$monitorip = $gateway['gateway'];
3761

    
3762
			return($monitorip);
3763
		}
3764
	}
3765
	return(false);
3766
}
3767

    
3768
function lookup_gateway_interface_by_name($name) {
3769
	global $config;
3770
	$gateways_arr = return_gateways_array();
3771

    
3772
	foreach($gateways_arr as $gateway) {
3773
		if($gateway['name'] == "$name") {
3774
			$gatewayip = $gateway['gateway'];
3775
			$interfacegw = $gateway['interface'];
3776
			return($interfacegw);
3777
		}
3778
	}
3779
	return(false);
3780
}
3781

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

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

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

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

    
3898
	/*
3899
	 *	Originally by Author: Keyvan Minoukadeh
3900
	 *	Modified by Scott Ullrich to return Content-Length size
3901
         */
3902

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

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

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

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

    
3953
?>
(21-21/37)