Project

General

Profile

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

    
36
/*
37
	pfSense_BUILDER_BINARIES:	/sbin/sysctl	/sbin/ifconfig	/sbin/pfctl	/usr/local/bin/php /usr/bin/netstat
38
	pfSense_BUILDER_BINARIES:	/bin/df	/usr/bin/grep	/usr/bin/awk	/bin/rm	/usr/sbin/pwd_mkdb	/usr/bin/host
39
	pfSense_BUILDER_BINARIES:	/sbin/kldload
40
	pfSense_MODULE:	utils
41
*/
42

    
43
/****f* pfsense-utils/have_natonetooneruleint_access
44
 * NAME
45
 *   have_natonetooneruleint_access
46
 * INPUTS
47
 *	 none
48
 * RESULT
49
 *   returns true if user has access to edit a specific firewall nat one to one interface
50
 ******/
51
function have_natonetooneruleint_access($if) {
52
	$security_url = "firewall_nat_1to1_edit.php?if=". strtolower($if);
53
	if(isAllowedPage($security_url, $allowed)) 
54
		return true;
55
	return false;
56
}
57

    
58
/****f* pfsense-utils/have_natpfruleint_access
59
 * NAME
60
 *   have_natpfruleint_access
61
 * INPUTS
62
 *	 none
63
 * RESULT
64
 *   returns true if user has access to edit a specific firewall nat port forward interface
65
 ******/
66
function have_natpfruleint_access($if) {
67
	$security_url = "firewall_nat_edit.php?if=". strtolower($if);
68
	if(isAllowedPage($security_url, $allowed)) 
69
		return true;
70
	return false;
71
}
72

    
73
/****f* pfsense-utils/have_ruleint_access
74
 * NAME
75
 *   have_ruleint_access
76
 * INPUTS
77
 *	 none
78
 * RESULT
79
 *   returns true if user has access to edit a specific firewall interface
80
 ******/
81
function have_ruleint_access($if) {
82
	$security_url = "firewall_rules.php?if=". strtolower($if);
83
	if(isAllowedPage($security_url)) 
84
		return true;
85
	return false;
86
}
87

    
88
/****f* pfsense-utils/does_url_exist
89
 * NAME
90
 *   does_url_exist
91
 * INPUTS
92
 *	 none
93
 * RESULT
94
 *   returns true if a url is available
95
 ******/
96
function does_url_exist($url) {
97
	$fd = fopen("$url","r");
98
	if($fd) {
99
		fclose($fd);
100
   		return true;    
101
	} else {
102
        return false;
103
	}
104
}
105

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

    
129
/****f* pfsense-utils/get_tmp_file
130
 * NAME
131
 *   get_tmp_file
132
 * INPUTS
133
 *	 none
134
 * RESULT
135
 *   returns a temporary filename
136
 ******/
137
function get_tmp_file() {
138
	global $g;
139
	return "{$g['tmp_path']}/tmp-" . time();
140
}
141

    
142
/****f* pfsense-utils/get_dns_servers
143
 * NAME
144
 *   get_dns_servres - get system dns servers
145
 * INPUTS
146
 *   $dns_servers - an array of the dns servers
147
 * RESULT
148
 *   null
149
 ******/
150
function get_dns_servers() {
151
	$dns_servers = array();
152
	$dns = `cat /etc/resolv.conf`;
153
	$dns_s = split("\n", $dns);
154
	foreach($dns_s as $dns) {
155
		$matches = "";
156
		if (preg_match("/nameserver (.*)/", $dns, $matches))
157
			$dns_servers[] = $matches[1];
158
	}
159
	$dns_server_master = array();
160
	$lastseen = "";
161
	foreach($dns_servers as $t) {
162
		if($t <> $lastseen)
163
			if($t <> "")
164
				$dns_server_master[] = $t;
165
		$lastseen = $t;
166
	}
167
	return $dns_server_master;
168
}
169

    
170
/****f* pfsense-utils/enable_hardware_offloading
171
 * NAME
172
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
173
 * INPUTS
174
 *   $interface	- string containing the physical interface to work on.
175
 * RESULT
176
 *   null
177
 * NOTES
178
 *   This function only supports the fxp driver's loadable microcode.
179
 ******/
180
function enable_hardware_offloading($interface) {
181
	global $g, $config;
182

    
183
	if(stristr($interface,"lnc"))
184
		return;
185

    
186
	/* translate wan, lan, opt -> real interface if needed */
187
	$int = get_real_interface($interface);
188
	if($int <> "") 
189
		$interface = $int;
190
	$int_family = preg_split("/[0-9]+/", $interface);
191
	$options = strtolower(`/sbin/ifconfig -m {$interface} | grep capabilities`);
192
	$supported_ints = array('fxp');
193
	if (in_array($int_family, $supported_ints)) {
194
		if(isset($config['system']['do_not_use_nic_microcode']))
195
			continue;
196
		if(does_interface_exist($interface)) 
197
			mwexec("/sbin/ifconfig {$interface} link0");
198
	}
199

    
200
	/* skip vlans for checksumming and polling */
201
	if(stristr($interface, "vlan")) 
202
		return;
203

    
204
	if($config['system']['disablechecksumoffloading']) {
205
		if(stristr($options, "txcsum") == true)
206
			mwexec("/sbin/ifconfig {$interface} -txcsum 2>/dev/null");
207
		if(stristr($options, "rxcsum") == true)
208
			mwexec("/sbin/ifconfig {$interface} -rxcsum 2>/dev/null");
209
	} else {
210
		if(stristr($options, "txcsum") == true)
211
			mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
212
		if(stristr($options, "rxcsum") == true)
213
			mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
214
	}
215

    
216
	/* if the NIC supports polling *AND* it is enabled in the GUI */
217
	if(interface_supports_polling($interface)) {
218
		$polling = isset($config['system']['polling']);	
219
		if($polling) {
220
			mwexec("sysctl kern.polling.enable=1");
221
			mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
222
		} else {
223
			mwexec("sysctl kern.polling.enable=0");
224
		}
225
	}
226
	return;
227
}
228

    
229
/****f* pfsense-utils/interface_supports_polling
230
 * NAME
231
 *   checks to see if an interface supports polling according to man polling
232
 * INPUTS
233
 *
234
 * RESULT
235
 *   true or false
236
 * NOTES
237
 *
238
 ******/
239
function interface_supports_polling($iface) {
240
	$pattern = '/([a-z].*)[0-9]/';
241
	preg_match($pattern, $iface, $iface2);
242
	$interface=$iface2[1];
243
	$supported_ints = array("bge",
244
		"dc",
245
		"em",
246
		"fwe",
247
		"fwip",
248
		"fxp",
249
		"ixgb",
250
		"nfe",
251
		"vge",
252
		"re",
253
		"rl",
254
		"sf",
255
		"sis",
256
		"ste",
257
		"stge",    
258
		"vge",
259
		"vr",
260
		"xl");
261
	if(in_array($interface, $supported_ints))
262
		return true;
263
	return false;
264
}
265

    
266
/****f* pfsense-utils/is_alias_inuse
267
 * NAME
268
 *   checks to see if an alias is currently in use by a rule
269
 * INPUTS
270
 *
271
 * RESULT
272
 *   true or false
273
 * NOTES
274
 *
275
 ******/
276
function is_alias_inuse($alias) {
277
	global $g, $config;
278

    
279
	if($alias == "") return false;
280
	/* loop through firewall rules looking for alias in use */
281
	if(is_array($config['filter']['rule']))
282
		foreach($config['filter']['rule'] as $rule) {
283
			if($rule['source']['address'])
284
				if($rule['source']['address'] == $alias)
285
					return true;
286
			if($rule['destination']['address'])
287
				if($rule['destination']['address'] == $alias)
288
					return true;
289
		}
290
	/* loop through nat rules looking for alias in use */
291
	if(is_array($config['nat']['rule']))
292
		foreach($config['nat']['rule'] as $rule) {
293
			if($rule['target'] == $alias)
294
				return true;
295
			if($rule['external-address'] == $alias)
296
				return true;
297
		}
298
	return false;
299
}
300

    
301
/****f* pfsense-utils/is_schedule_inuse
302
 * NAME
303
 *   checks to see if a schedule is currently in use by a rule
304
 * INPUTS
305
 *
306
 * RESULT
307
 *   true or false
308
 * NOTES
309
 *
310
 ******/
311
function is_schedule_inuse($schedule) {
312
	global $g, $config;
313

    
314
	if($schedule == "") return false;
315
	/* loop through firewall rules looking for schedule in use */
316
	if(is_array($config['filter']['rule']))
317
		foreach($config['filter']['rule'] as $rule) {
318
			if($rule['sched'] == $schedule)
319
				return true;
320
		}
321
	return false;
322
}
323

    
324
/****f* pfsense-utils/setup_polling_defaults
325
 * NAME
326
 *   sets up sysctls for pollingS
327
 * INPUTS
328
 *
329
 * RESULT
330
 *   null
331
 * NOTES
332
 *
333
 ******/
334
function setup_polling_defaults() {
335
	global $g, $config;
336
	if($config['system']['polling_each_burst'])
337
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
338
	if($config['system']['polling_burst_max'])
339
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
340
	if($config['system']['polling_user_frac'])
341
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
342
}
343

    
344
/****f* pfsense-utils/setup_polling
345
 * NAME
346
 *   sets up polling
347
 * INPUTS
348
 *
349
 * RESULT
350
 *   null
351
 * NOTES
352
 *
353
 ******/
354
function setup_polling() {
355
	global $g, $config;
356

    
357
	setup_polling_defaults();
358

    
359
	$supported_ints = array('bge', 'dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
360

    
361
	/* if list */
362
	$iflist = get_configured_interface_list();
363

    
364
	foreach ($iflist as $ifent => $ifname) {
365
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
366
		$ifdevice = substr($real_interface, 0, -1);
367
		if(!in_array($ifdevice, $supported_ints)) {
368
			continue;
369
        }
370
		if(isset($config['system']['polling'])) {
371
			mwexec("/sbin/ifconfig {$real_interface} polling");
372
			mwexec("/sbin/sysctl kern.polling.idle_poll=1");
373
		} else {
374
			mwexec("/sbin/ifconfig {$real_interface} -polling");
375
		}
376
	}
377
}
378

    
379
/****f* pfsense-utils/setup_microcode
380
 * NAME
381
 *   enumerates all interfaces and calls enable_hardware_offloading which
382
 *   enables a NIC's supported hardware features.
383
 * INPUTS
384
 *
385
 * RESULT
386
 *   null
387
 * NOTES
388
 *   This function only supports the fxp driver's loadable microcode.
389
 ******/
390
function setup_microcode() {
391

    
392
	/* if list */
393
        $ifdescrs = get_configured_interface_list();
394

    
395
	foreach($ifdescrs as $if)
396
		enable_hardware_offloading($if);
397
}
398

    
399
/****f* pfsense-utils/get_carp_status
400
 * NAME
401
 *   get_carp_status - Return whether CARP is enabled or disabled.
402
 * RESULT
403
 *   boolean	- true if CARP is enabled, false if otherwise.
404
 ******/
405
function get_carp_status() {
406
    /* grab the current status of carp */
407
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
408
    if(intval($status) == "0") return false;
409
    return true;
410
}
411

    
412
/*
413
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
414

    
415
 */
416
function convert_ip_to_network_format($ip, $subnet) {
417
	$ipsplit = split('[.]', $ip);
418
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
419
	return $string;
420
}
421

    
422
/*
423
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
424
 */
425
function get_carp_interface_status($carpinterface) {
426
	/* basically cache the contents of ifconfig statement
427
	to speed up this routine */
428
	global $carp_query;
429
	if($carp_query == "")
430
		$carp_query = split("\n", `/sbin/ifconfig $carpinterface | grep carp`);
431
	foreach($carp_query as $int) {
432
		if(stristr($int, "MASTER")) 
433
			return "MASTER";
434
		if(stristr($int, "BACKUP")) 
435
			return "BACKUP";
436
		if(stristr($int, "INIT")) 
437
			return "INIT";
438
	}
439
	return;
440
}
441

    
442
/*
443
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
444
 */
445
function get_pfsync_interface_status($pfsyncinterface) {
446
    $result = does_interface_exist($pfsyncinterface);
447
    if($result <> true) return;
448
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
449
    return $status;
450
}
451

    
452
/*
453
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
454
 */
455
function add_rule_to_anchor($anchor, $rule, $label) {
456
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
457
}
458

    
459
/*
460
 * remove_text_from_file
461
 * remove $text from file $file
462
 */
463
function remove_text_from_file($file, $text) {
464
	global $fd_log;
465
	if($fd_log)
466
		fwrite($fd_log, "Adding needed text items:\n");
467
	$filecontents = file_get_contents($file);
468
	$textTMP = str_replace($text, "", $filecontents);
469
	$text = $textTMP;
470
	if($fd_log)
471
		fwrite($fd_log, $text);
472
	$fd = fopen($file, "w");
473
	fwrite($fd, $text);
474
	fclose($fd);
475
}
476

    
477
/*
478
 * add_text_to_file($file, $text): adds $text to $file.
479
 * replaces the text if it already exists.
480
 */
481
function add_text_to_file($file, $text, $replace = false) {
482
	if(file_exists($file) and is_writable($file)) {
483
		$filecontents = file($file);
484
		$fout = fopen($file, "w");
485

    
486
		$filecontents = array_map('rtrim', $filecontents);
487
		array_push($filecontents, $text);
488
		if ($replace)
489
			$filecontents = array_unique($filecontents);
490

    
491
		$file_text = implode("\n", $filecontents);
492

    
493
		fwrite($fout, $file_text);
494
		fclose($fout);
495
		return true;
496
	} else {
497
		return false;
498
	}
499
}
500

    
501
/*
502
 *   after_sync_bump_adv_skew(): create skew values by 1S
503
 */
504
function after_sync_bump_adv_skew() {
505
	global $config, $g;
506
	$processed_skew = 1;
507
	$a_vip = &$config['virtualip']['vip'];
508
	foreach ($a_vip as $vipent) {
509
		if($vipent['advskew'] <> "") {
510
			$processed_skew = 1;
511
			$vipent['advskew'] = $vipent['advskew']+1;
512
		}
513
	}
514
	if($processed_skew == 1)
515
		write_config("After synch increase advertising skew");
516
}
517

    
518
/*
519
 * get_filename_from_url($url): converts a url to its filename.
520
 */
521
function get_filename_from_url($url) {
522
	return basename($url);
523
}
524

    
525
/*
526
 *   get_dir: return an array of $dir
527
 */
528
function get_dir($dir) {
529
	$dir_array = array();
530
	$d = dir($dir);
531
	while (false !== ($entry = $d->read())) {
532
		array_push($dir_array, $entry);
533
	}
534
	$d->close();
535
	return $dir_array;
536
}
537

    
538
/****f* pfsense-utils/WakeOnLan
539
 * NAME
540
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
541
 * RESULT
542
 *   true/false - true if the operation was successful
543
 ******/
544
function WakeOnLan($addr, $mac)
545
{
546
	$addr_byte = explode(':', $mac);
547
	$hw_addr = '';
548

    
549
	for ($a=0; $a < 6; $a++)
550
		$hw_addr .= chr(hexdec($addr_byte[$a]));
551

    
552
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
553

    
554
	for ($a = 1; $a <= 16; $a++)
555
		$msg .= $hw_addr;
556

    
557
	// send it to the broadcast address using UDP
558
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
559
	if ($s == false) {
560
		log_error("Error creating socket!");
561
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
562
	} else {
563
		// setting a broadcast option to socket:
564
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
565
		if($opt_ret < 0)
566
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
567
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
568
		socket_close($s);
569
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
570
		return true;
571
	}
572

    
573
	return false;
574
}
575

    
576
/*
577
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
578
 *                             is queuename|qlength|measured_packets
579
 *                             NOTE: this command takes 5 seconds to run
580
 */
581
function gather_altq_queue_stats($dont_return_root_queues) {
582
	exec("/sbin/pfctl -vvsq", $stats_array);
583
	$queue_stats = array();
584
	foreach ($stats_array as $stats_line) {
585
		$match_array = "";
586
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
587
			$queue_name = $match_array[1][0];
588
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
589
			$speed = $match_array[1][0];
590
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
591
			$borrows = $match_array[1][0];
592
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
593
			$suspends = $match_array[1][0];
594
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
595
			$drops = $match_array[1][0];
596
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
597
			$measured = $match_array[1][0];
598
			if($dont_return_root_queues == true)
599
				if(stristr($queue_name,"root_") == false)
600
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
601
		}
602
	}
603
	return $queue_stats;
604
}
605

    
606
/*
607
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
608
 *					 Useful for finding paths and stripping file extensions.
609
 */
610
function reverse_strrchr($haystack, $needle) {
611
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
612
}
613

    
614
/*
615
 *  backup_config_section($section): returns as an xml file string of
616
 *                                   the configuration section
617
 */
618
function backup_config_section($section) {
619
	global $config;
620
	$new_section = &$config[$section];
621
	/* generate configuration XML */
622
	$xmlconfig = dump_xml_config($new_section, $section);
623
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
624
	return $xmlconfig;
625
}
626

    
627
/*
628
 *  restore_config_section($section, new_contents): restore a configuration section,
629
 *                                                  and write the configuration out
630
 *                                                  to disk/cf.
631
 */
632
function restore_config_section($section, $new_contents) {
633
	global $config, $g;
634
	conf_mount_rw();
635
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
636
	fwrite($fout, $new_contents);
637
	fclose($fout);
638
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
639
	$config[$section] = &$section_xml;
640
	unlink($g['tmp_path'] . "/tmpxml");
641
	write_config("Restored {$section} of config file (maybe from CARP partner)");
642
	conf_mount_ro();
643
	return;
644
}
645

    
646
/*
647
 *  merge_config_section($section, new_contents):   restore a configuration section,
648
 *                                                  and write the configuration out
649
 *                                                  to disk/cf.  But preserve the prior
650
 * 													structure if needed
651
 */
652
function merge_config_section($section, $new_contents) {
653
	global $config;
654
	conf_mount_rw();
655
	$fname = get_tmp_filename();
656
	$fout = fopen($fname, "w");
657
	fwrite($fout, $new_contents);
658
	fclose($fout);
659
	$section_xml = parse_xml_config($fname, $section);
660
	$config[$section] = $section_xml;
661
	unlink($fname);
662
	write_config("Restored {$section} of config file (maybe from CARP partner)");
663
	conf_mount_ro();
664
	return;
665
}
666

    
667
/*
668
 * http_post($server, $port, $url, $vars): does an http post to a web server
669
 *                                         posting the vars array.
670
 * written by nf@bigpond.net.au
671
 */
672
function http_post($server, $port, $url, $vars) {
673
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
674
	$urlencoded = "";
675
	while (list($key,$value) = each($vars))
676
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
677
	$urlencoded = substr($urlencoded,0,-1);
678
	$content_length = strlen($urlencoded);
679
	$headers = "POST $url HTTP/1.1
680
Accept: */*
681
Accept-Language: en-au
682
Content-Type: application/x-www-form-urlencoded
683
User-Agent: $user_agent
684
Host: $server
685
Connection: Keep-Alive
686
Cache-Control: no-cache
687
Content-Length: $content_length
688

    
689
";
690

    
691
	$errno = "";
692
	$errstr = "";
693
	$fp = fsockopen($server, $port, $errno, $errstr);
694
	if (!$fp) {
695
		return false;
696
	}
697

    
698
	fputs($fp, $headers);
699
	fputs($fp, $urlencoded);
700

    
701
	$ret = "";
702
	while (!feof($fp))
703
		$ret.= fgets($fp, 1024);
704
	fclose($fp);
705

    
706
	return $ret;
707
}
708

    
709
/*
710
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
711
 */
712
if (!function_exists('php_check_syntax')){
713
	global $g;
714
	function php_check_syntax($code_to_check, &$errormessage){
715
		return false;
716
		$fout = fopen("{$g['tmp_path']}/codetocheck.php","w");
717
		$code = $_POST['content'];
718
		$code = str_replace("<?php", "", $code);
719
		$code = str_replace("?>", "", $code);
720
		fwrite($fout, "<?php\n\n");
721
		fwrite($fout, $code_to_check);
722
		fwrite($fout, "\n\n?>\n");
723
		fclose($fout);
724
		$command = "/usr/local/bin/php -l {$g['tmp_path']}/codetocheck.php";
725
		$output = exec_command($command);
726
		if (stristr($output, "Errors parsing") == false) {
727
			echo "false\n";
728
			$errormessage = '';
729
			return(false);
730
		} else {
731
			$errormessage = $output;
732
			return(true);
733
		}
734
	}
735
}
736

    
737
/*
738
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
739
 */
740
if (!function_exists('php_check_syntax')){
741
	function php_check_syntax($code_to_check, &$errormessage){
742
		return false;
743
		$command = "/usr/local/bin/php -l " . $code_to_check;
744
		$output = exec_command($command);
745
		if (stristr($output, "Errors parsing") == false) {
746
			echo "false\n";
747
			$errormessage = '';
748
			return(false);
749
		} else {
750
			$errormessage = $output;
751
			return(true);
752
		}
753
	}
754
}
755

    
756
/*
757
 * rmdir_recursive($path,$follow_links=false)
758
 * Recursively remove a directory tree (rm -rf path)
759
 * This is for directories _only_
760
 */
761
function rmdir_recursive($path,$follow_links=false) {
762
	$to_do = glob($path);
763
	if(!is_array($to_do)) $to_do = array($to_do);
764
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
765
		if(file_exists($workingdir)) {
766
			if(is_dir($workingdir)) {
767
				$dir = opendir($workingdir);
768
				while ($entry = readdir($dir)) {
769
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
770
						unlink("$workingdir/$entry");
771
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
772
						rmdir_recursive("$workingdir/$entry");
773
				}
774
				closedir($dir);
775
				rmdir($workingdir);
776
			} elseif (is_file($workingdir)) {
777
				unlink($workingdir);
778
			}
779
               	}
780
	}
781
	return;
782
}
783

    
784
/*
785
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
786
 */
787
function call_pfsense_method($method, $params, $timeout = 0) {
788
	global $g, $config;
789

    
790
	$ip = gethostbyname($g['product_website']);
791
	if($ip == $g['product_website'])
792
		return false;
793

    
794
	$xmlrpc_base_url = isset($config['system']['altpkgrepo']['enable']) ? $config['system']['altpkgrepo']['xmlrpcbaseurl'] : $g['xmlrpcbaseurl'];
795
	$xmlrpc_path = $g['xmlrpcpath'];
796
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
797
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
798
	$resp = $cli->send($msg, $timeout);
799
	if(!$resp) {
800
		log_error("XMLRPC communication error: " . $cli->errstr);
801
		return false;
802
	} elseif($resp->faultCode()) {
803
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
804
		return false;
805
	} else {
806
		return XML_RPC_Decode($resp->value());
807
	}
808
}
809

    
810
/*
811
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
812
 */
813
function check_firmware_version($tocheck = "all", $return_php = true) {
814
	global $g, $config;
815
	$ip = gethostbyname($g['product_website']);
816
	if($ip == $g['product_website'])
817
		return false;
818
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
819
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
820
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
821
		"platform" => trim(file_get_contents('/etc/platform'))
822
		);
823
	if($tocheck == "all") {
824
		$params = $rawparams;
825
	} else {
826
		foreach($tocheck as $check) {
827
			$params['check'] = $rawparams['check'];
828
			$params['platform'] = $rawparams['platform'];
829
		}
830
	}
831
	if($config['system']['firmware']['branch']) {
832
		$params['branch'] = $config['system']['firmware']['branch'];
833
	}
834
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
835
		return false;
836
	} else {
837
		$versions["current"] = $params;
838
	}
839
	return $versions;
840
}
841

    
842
function get_disk_info() {
843
	$diskout = "";
844
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
845
	return explode(' ', $diskout[0]);
846
	// $size, $used, $avail, $cap
847
}
848

    
849
/****f* pfsense-utils/strncpy
850
 * NAME
851
 *   strncpy - copy strings
852
 * INPUTS
853
 *   &$dst, $src, $length
854
 * RESULT
855
 *   none
856
 ******/
857
function strncpy(&$dst, $src, $length) {
858
	if (strlen($src) > $length) {
859
		$dst = substr($src, 0, $length);
860
	} else {
861
		$dst = $src;
862
	}
863
}
864

    
865
/****f* pfsense-utils/reload_interfaces_sync
866
 * NAME
867
 *   reload_interfaces - reload all interfaces
868
 * INPUTS
869
 *   none
870
 * RESULT
871
 *   none
872
 ******/
873
function reload_interfaces_sync() {
874
	global $config, $g;
875

    
876
	/* XXX: Use locks?! */
877
	if (file_exists("{$g['tmp_path']}/reloading_all")) {
878
		log_error("WARNING: Recursive call to interfaces sync!");
879
		return;
880
	}
881
	touch("{$g['tmp_path']}/reloading_all");
882

    
883
	if($g['debug'])
884
		log_error("reload_interfaces_sync() is starting.");
885

    
886
	/* parse config.xml again */
887
	$config = parse_config(true);
888

    
889
	/* enable routing */
890
	system_routing_enable();
891
	if($g['debug'])
892
		log_error("Enabling system routing");
893

    
894
	if($g['debug'])
895
		log_error("Cleaning up Interfaces");
896

    
897
	/* set up interfaces */
898
	interfaces_configure();
899

    
900
	/* remove reloading_all trigger */
901
	if($g['debug'])
902
		log_error("Removing {$g['tmp_path']}/reloading_all");
903

    
904
	/* start devd back up */
905
	mwexec("/bin/rm {$g['tmp_path']}/reload*");
906
}
907

    
908
/****f* pfsense-utils/reload_all
909
 * NAME
910
 *   reload_all - triggers a reload of all settings
911
 *   * INPUTS
912
 *   none
913
 * RESULT
914
 *   none
915
 ******/
916
function reload_all() {
917
	global $g;
918
	touch("{$g['tmp_path']}/reload_all");
919
}
920

    
921
/****f* pfsense-utils/reload_interfaces
922
 * NAME
923
 *   reload_interfaces - triggers a reload of all interfaces
924
 * INPUTS
925
 *   none
926
 * RESULT
927
 *   none
928
 ******/
929
function reload_interfaces() {
930
	global $g;
931
	touch("{$g['tmp_path']}/reload_interfaces");
932
}
933

    
934
/****f* pfsense-utils/reload_all_sync
935
 * NAME
936
 *   reload_all - reload all settings
937
 *   * INPUTS
938
 *   none
939
 * RESULT
940
 *   none
941
 ******/
942
function reload_all_sync() {
943
	global $config, $g;
944

    
945
	$g['booting'] = false;
946

    
947
	/* XXX: Use locks?! */
948
        if (file_exists("{$g['tmp_path']}/reloading_all")) {
949
                log_error("WARNING: Recursive call to reload all sync!");
950
                return;
951
        }
952
	touch("{$g['tmp_path']}/reloading_all");
953

    
954
	/* parse config.xml again */
955
	$config = parse_config(true);
956

    
957
	/* set up our timezone */
958
	system_timezone_configure();
959

    
960
	/* set up our hostname */
961
	system_hostname_configure();
962

    
963
	/* make hosts file */
964
	system_hosts_generate();
965

    
966
	/* generate resolv.conf */
967
	system_resolvconf_generate();
968

    
969
	/* enable routing */
970
	system_routing_enable();
971

    
972
	/* set up interfaces */
973
	interfaces_configure();
974

    
975
	/* start dyndns service */
976
	services_dyndns_configure();
977

    
978
	/* configure cron service */
979
	configure_cron();
980

    
981
	/* start the NTP client */
982
	system_ntp_configure();
983

    
984
	/* sync pw database */
985
	conf_mount_rw();
986
	unlink_if_exists("/etc/spwd.db.tmp");
987
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
988
	conf_mount_ro();
989

    
990
	/* restart sshd */
991
	@touch("{$g['tmp_path']}/start_sshd");
992

    
993
	/* restart webConfigurator if needed */
994
	touch("{$g['tmp_path']}/restart_webgui");
995

    
996
	mwexec("/bin/rm {$g['tmp_path']}/reload*");
997
}
998

    
999
function auto_login($status) {
1000
	$gettytab = file_get_contents("/etc/gettytab");
1001
	$getty_split = split("\n", $gettytab);
1002
	conf_mount_rw();
1003
	$fd = fopen("/etc/gettytab", "w");
1004
	foreach($getty_split as $gs) {
1005
		if(stristr($gs, ":ht:np:sp#115200") ) {
1006
			if($status == true) {
1007
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
1008
			} else {
1009
				fwrite($fd, "	:ht:np:sp#115200:\n");
1010
			}
1011
		} else {
1012
			fwrite($fd, "{$gs}\n");
1013
		}
1014
	}
1015
	fclose($fd);
1016
	conf_mount_ro();
1017
}
1018

    
1019
function setup_serial_port() {
1020
	global $g, $config;
1021
	conf_mount_rw();
1022
	/* serial console - write out /boot.config */
1023
	if(file_exists("/boot.config"))
1024
		$boot_config = file_get_contents("/boot.config");
1025
	else
1026
		$boot_config = "";
1027

    
1028
	if($g['platform'] <> "cdrom") {
1029
		$boot_config_split = split("\n", $boot_config);
1030
		$fd = fopen("/boot.config","w");
1031
		if($fd) {
1032
			foreach($boot_config_split as $bcs) {
1033
				if(stristr($bcs, "-D")) {
1034
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1035
				} else {
1036
					if($bcs <> "")
1037
						fwrite($fd, "{$bcs}\n");
1038
				}
1039
			}
1040
			if(isset($config['system']['enableserial'])) {
1041
				fwrite($fd, "-D");
1042
			}
1043
			fclose($fd);
1044
		}
1045
		/* serial console - write out /boot/loader.conf */
1046
		$boot_config = file_get_contents("/boot/loader.conf");
1047
		$boot_config_split = split("\n", $boot_config);
1048
		$fd = fopen("/boot/loader.conf","w");
1049
		if($fd) {
1050
			foreach($boot_config_split as $bcs) {
1051
				if(stristr($bcs, "console")) {
1052
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1053
				} else {
1054
					if($bcs <> "")
1055
						fwrite($fd, "{$bcs}\n");
1056
				}
1057
			}
1058
			if(isset($config['system']['enableserial'])) {
1059
				fwrite($fd, "console=\"comconsole\"\n");
1060
			}
1061
			fclose($fd);
1062
		}
1063
	}
1064
	$ttys = file_get_contents("/etc/ttys");
1065
	$ttys_split = split("\n", $ttys);
1066
	$fd = fopen("/etc/ttys", "w");
1067
	foreach($ttys_split as $tty) {
1068
		if(stristr($tty, "ttyd0")) {
1069
			if(isset($config['system']['enableserial'])) {
1070
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
1071
			} else {
1072
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
1073
			}
1074
		} else {
1075
			fwrite($fd, $tty . "\n");
1076
		}
1077
	}
1078
	fclose($fd);
1079
	if(isset($config['system']['disableconsolemenu'])) {
1080
		auto_login(false);
1081
	} else {
1082
		auto_login(true);
1083
	}
1084
	conf_mount_ro();
1085
	return;
1086
}
1087

    
1088
function print_value_list($list, $count = 10, $separator = ",") {
1089
	$list = implode($separator, array_slice($list, 0, $count));
1090
	if(count($list) < $count) {
1091
		$list .= ".";
1092
	} else {
1093
		$list .= "...";
1094
	}
1095
	return $list;
1096
}
1097

    
1098
/* DHCP enabled on any interfaces? */
1099
function is_dhcp_server_enabled() 
1100
{
1101
	global $config;
1102

    
1103
	$dhcpdenable = false;
1104
	
1105
	if (!is_array($config['dhcpd']))
1106
		return false;
1107

    
1108
	$Iflist = get_configured_interface_list();
1109

    
1110
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1111
		if (isset($dhcpifconf['enable']) && isset($Iflist[$dhcpif])) {
1112
			$dhcpdenable = true;
1113
			break;
1114
		}
1115
	}
1116

    
1117
	return $dhcpdenable;
1118
}
1119

    
1120
//returns interface information
1121
function get_interface_info($ifdescr) {
1122
	global $config, $linkinfo, $netstatrninfo;
1123

    
1124
	$ifinfo = array();
1125
	/* if list */
1126
	$iflist = get_configured_interface_with_descr(false,true);
1127

    
1128
	$found = false;
1129
    	foreach ($iflist as $if => $ifname) {
1130
    	if ($ifdescr == $if || $ifdescr == $ifname) {
1131
			$ifinfo['hwif'] = $config['interfaces'][$if]['if'];
1132
			if($config['interfaces'][$if]['serialport'])
1133
				$ifinfo['hwif'] =  get_real_interface($if);
1134
			$ifinfo['if'] = get_real_interface($if);
1135
			$found = true;
1136
			break;
1137
		}
1138
	}
1139
	if ($found == false)
1140
		return;
1141

    
1142
	/* run netstat to determine link info */
1143

    
1144
	unset($linkinfo);
1145
	if ($ifinfo['if'] != $ifinfo['hwif'])
1146
		$chkif = $ifinfo['hwif'];
1147
	else
1148
		$chkif = $ifinfo['if'];
1149

    
1150
	exec("/usr/bin/netstat -I {$chkif} -nWb -f link", $linkinfo);
1151

    
1152
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
1153
	if ("{$chkif}*" == $linkinfo[0])
1154
		$ifinfo['status'] = "down";
1155
	else if ($chkif == $linkinfo[0])
1156
		$ifinfo['status'] = "up";
1157
	else
1158
		$ifinfo['status'] = "down";
1159
	
1160
	if (preg_match("/^enc|^tun|^ppp|^pptp|^ovpn/i", $ifinfo['if'])) {
1161
		$ifinfo['inpkts'] = $linkinfo[3];
1162
		$ifinfo['outpkts'] = $linkinfo[6];
1163
	} else {
1164
		$ifinfo['macaddr'] = $linkinfo[3];
1165
		$ifinfo['inerrs'] = $linkinfo[5];
1166
		$ifinfo['outerrs'] = $linkinfo[8];
1167
		$ifinfo['collisions'] = $linkinfo[10];
1168
	}
1169

    
1170
	/* Use pfctl for non wrapping 64 bit counters */
1171
	/* Pass */
1172
	exec("/sbin/pfctl -vvsI -i {$ifinfo['if']}", $pfctlstats);
1173
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1174
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1175
	$in4_pass = $pf_in4_pass[5];
1176
	$out4_pass = $pf_out4_pass[5];
1177
	$in4_pass_packets = $pf_in4_pass[3];
1178
	$out4_pass_packets = $pf_out4_pass[3];
1179
	$ifinfo['inbytespass'] = $in4_pass;
1180
	$ifinfo['outbytespass'] = $out4_pass;
1181
	$ifinfo['inpktspass'] = $in4_pass_packets;
1182
	$ifinfo['outpktspass'] = $out4_pass_packets;
1183

    
1184
	/* Block */
1185
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1186
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1187
	$in4_block = $pf_in4_block[5];
1188
	$out4_block = $pf_out4_block[5];
1189
	$in4_block_packets = $pf_in4_block[3];
1190
	$out4_block_packets = $pf_out4_block[3];
1191
	$ifinfo['inbytesblock'] = $in4_block;
1192
	$ifinfo['outbytesblock'] = $out4_block;
1193
	$ifinfo['inpktsblock'] = $in4_block_packets;
1194
	$ifinfo['outpktsblock'] = $out4_block_packets;
1195

    
1196
	$ifinfo['inbytes'] = $in4_pass + $in4_block;
1197
	$ifinfo['outbytes'] = $out4_pass + $out4_block;
1198
	$ifinfo['inpkts'] = $in4_pass_packets + $in4_block_packets;
1199
	$ifinfo['outpkts'] = $in4_pass_packets + $out4_block_packets;
1200
		
1201
	$ifconfiginfo = "";
1202
	unset($ifconfiginfo, $link0);
1203
	exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1204
	foreach ($ifconfiginfo as $ici) {
1205
		if (preg_match("/inet (\S+)/", $ici, $matches)) {
1206
			$ifinfo['ipaddr'] = $matches[1];
1207
		}
1208
		if (preg_match("/netmask (\S+)/", $ici, $matches)) {
1209
			if (preg_match("/^0x/", $matches[1])) {
1210
				$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
1211
			}
1212
		}
1213
		if (strpos($ici, 'LINK0') !== false) {
1214
			$link0 = "down";
1215
		}
1216
	}
1217

    
1218
	switch ($config['interfaces'][$if]['ipaddr']) {
1219
	/* DHCP? -> see if dhclient is up */
1220
	case "dhcp":
1221
		/* see if dhclient is up */
1222
		if (find_dhclient_process($ifinfo['if']) <> "")
1223
			$ifinfo['dhcplink'] = "up";
1224
		else
1225
			$ifinfo['dhcplink'] = "down";
1226

    
1227
		break;
1228
	case "carpdev-dhcp":
1229
		/* see if dhclient is up */
1230
		if (find_dhclient_process($ifinfo['if']) <> "")
1231
			$ifinfo['dhcplink'] = "up";
1232
		else
1233
			$ifinfo['dhcplink'] = "down";
1234

    
1235
		break;
1236
	/* PPPoE interface? -> get status from virtual interface */
1237
	case "pppoe":
1238
		unset($linkinfo);
1239
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
1240
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
1241
		if ("{$ifinfo['if']}*" == $linkinfo[0])
1242
			$ifinfo['pppoelink'] = "down";
1243
		else if ($ifinfo['if'] == $linkinfo[0] && !isset($link0))
1244
			/* get PPPoE link status for dial on demand */
1245
			$ifinfo['pppoelink'] = "up";
1246
		else
1247
			$ifinfo['pppoelink'] = "down";
1248

    
1249
		break;
1250
	/* PPTP interface? -> get status from virtual interface */
1251
	case "pptp":
1252
		unset($linkinfo);
1253
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
1254
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
1255
		if ("{$ifinfo['if']}*" == $linkinfo[0])
1256
			$ifinfo['pptplink'] = "down";
1257
		else if ($ifinfo['if'] == $linkinfo[0] && !isset($link0))
1258
			/* get PPTP link status for dial on demand */
1259
			$ifinfo['pptplink'] = "up";
1260
		else
1261
			$ifinfo['pptplink'] = "down";
1262

    
1263
		break;
1264
	default:
1265
		break;
1266
	}
1267

    
1268
	if ($ifinfo['status'] == "up") {
1269
		/* try to determine media with ifconfig */
1270
		unset($ifconfiginfo);
1271
		exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1272
		$wifconfiginfo = array();
1273
		if(is_interface_wireless($ifdescr)) {
1274
			exec("/sbin/ifconfig {$ifinfo['if']} list sta", $wifconfiginfo);
1275
			array_shift($wifconfiginfo);
1276
		}
1277
		$matches = "";
1278
		foreach ($ifconfiginfo as $ici) {
1279

    
1280
			/* don't list media/speed for wireless cards, as it always
1281
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1282
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1283
				$ifinfo['media'] = $matches[1];
1284
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1285
				$ifinfo['media'] = $matches[1];
1286
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1287
				$ifinfo['media'] = $matches[1];
1288
			}
1289

    
1290
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
1291
				if ($matches[1] != "active")
1292
					$ifinfo['status'] = $matches[1];
1293
				if($ifinfo['status'] == "running")
1294
					$ifinfo['status'] = "up";
1295
			}
1296
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
1297
				$ifinfo['channel'] = $matches[1];
1298
			}
1299
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
1300
				if ($matches[1][0] == '"')
1301
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
1302
				else
1303
					$ifinfo['ssid'] = $matches[1];
1304
			}
1305
		}
1306
		foreach($wifconfiginfo as $ici) {
1307
			$elements = preg_split("/[ ]+/i", $ici);
1308
			if ($elements[0] != "") {
1309
				$ifinfo['bssid'] = $elements[0];
1310
			}
1311
			if ($elements[3] != "") {
1312
				$ifinfo['rate'] = $elements[3];
1313
			}
1314
			if ($elements[4] != "") {
1315
				$ifinfo['rssi'] = $elements[4];
1316
			}
1317

    
1318
		}
1319
		/* lookup the gateway */
1320
		if (interface_has_gateway($if)) 
1321
			$ifinfo['gateway'] = get_interface_gateway($if);
1322
	}
1323

    
1324
	$bridge = "";
1325
	$bridge = link_interface_to_bridge($ifdescr);
1326
	if($bridge) {
1327
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1328
		if(stristr($bridge_text, "blocking") <> false) {
1329
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
1330
			$ifinfo['bridgeint'] = $bridge;
1331
		} else if(stristr($bridge_text, "learning") <> false) {
1332
			$ifinfo['bridge'] = "learning";
1333
			$ifinfo['bridgeint'] = $bridge;
1334
		} else if(stristr($bridge_text, "forwarding") <> false) {
1335
			$ifinfo['bridge'] = "forwarding";
1336
			$ifinfo['bridgeint'] = $bridge;
1337
		}
1338
	}
1339

    
1340
	return $ifinfo;
1341
}
1342

    
1343
//returns cpu speed of processor. Good for determining capabilities of machine
1344
function get_cpu_speed() {
1345
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
1346
}
1347

    
1348
/* check if the wan interface is up
1349
 * Wait for a maximum of 10 seconds
1350
 * If the interface is up before then continue
1351
 */
1352
function is_wan_interface_up($interface) {
1353
	global $g;
1354
	global $config;
1355
	$i = 0;
1356
	while($i < 10) {
1357
		if(get_interface_gateway($interface)) {
1358
			return true;
1359
		} else {
1360
			sleep(1);
1361
		}
1362
		$i++;
1363
	}
1364
	return false;
1365
}
1366

    
1367
function add_hostname_to_watch($hostname) {
1368
	if(!is_dir("/var/db/dnscache")) {
1369
		mkdir("/var/db/dnscache");
1370
	}
1371
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1372
		$domrecords = array();
1373
		$domips = array();
1374
		exec("host -t A $hostname", $domrecords, $rethost);
1375
		if($rethost == 0) {
1376
			foreach($domrecords as $domr) {
1377
				$doml = explode(" ", $domr);
1378
				$domip = $doml[3];
1379
				/* fill array with domain ip addresses */
1380
				if(is_ipaddr($domip)) {
1381
					$domips[] = $domip;
1382
				}
1383
			}
1384
		}
1385
		sort($domips);
1386
		$contents = "";
1387
		if(! empty($domips)) {
1388
			foreach($domips as $ip) {
1389
				$contents .= "$ip\n";
1390
			}
1391
		}
1392
		file_put_contents("/var/db/dnscache/$hostname", $contents);
1393
	}
1394
}
1395

    
1396
function find_dns_aliases() {
1397
	global $config, $g;
1398
	foreach((array) $config['aliases']['alias'] as $alias) {
1399
		$alias_value = $alias['address'];
1400
		$alias_name = $alias['name'];
1401
		if(stristr($alias_value, " ")) {
1402
			$alias_split = split(" ", $alias_value);
1403
			foreach($alias_split as $as) {
1404
				if(is_fqdn($as)) 
1405
					add_hostname_to_watch($as);			
1406
			}
1407
		} else {
1408
			if(is_fqdn($alias_value)) 
1409
				add_hostname_to_watch($alias_value);
1410
		}
1411
	}
1412
}
1413

    
1414
function is_fqdn($fqdn) {
1415
	$hostname = false;
1416
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1417
		$hostname = true;
1418
	}
1419
	if(preg_match("/\.\./", $fqdn)) {
1420
		$hostname = false;
1421
	}
1422
	if(preg_match("/^\./i", $fqdn)) { 
1423
		$hostname = false;
1424
	}
1425
	if(preg_match("/\//i", $fqdn)) {
1426
		$hostname = false;
1427
	}
1428
	return($hostname);
1429
}
1430

    
1431
function pfsense_default_state_size() {
1432
  /* get system memory amount */
1433
  $memory = get_memory();
1434
  $avail = $memory[0];
1435
  /* Be cautious and only allocate 10% of system memory to the state table */
1436
  $max_states = (int) ($avail/10)*1000;
1437
  return $max_states;
1438
}
1439

    
1440
/* Compare the current hostname DNS to the DNS cache we made
1441
 * if it has changed we return the old records
1442
 * if no change we return true */
1443
function compare_hostname_to_dnscache($hostname) {
1444
	if(!is_dir("/var/db/dnscache")) {
1445
		mkdir("/var/db/dnscache");
1446
	}
1447
	$hostname = trim($hostname);
1448
	if(is_readable("/var/db/dnscache/{$hostname}")) {
1449
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
1450
	} else {
1451
		$oldcontents = "";
1452
	}
1453
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1454
		$domrecords = array();
1455
		$domips = array();
1456
		exec("host -t A $hostname", $domrecords, $rethost);
1457
		if($rethost == 0) {
1458
			foreach($domrecords as $domr) {
1459
				$doml = explode(" ", $domr);
1460
				$domip = $doml[3];
1461
				/* fill array with domain ip addresses */
1462
				if(is_ipaddr($domip)) {
1463
					$domips[] = $domip;
1464
				}
1465
			}
1466
		}
1467
		sort($domips);
1468
		$contents = "";
1469
		if(! empty($domips)) {
1470
			foreach($domips as $ip) {
1471
				$contents .= "$ip\n";
1472
			}
1473
		}
1474
	}
1475

    
1476
	if(trim($oldcontents) != trim($contents)) {
1477
		if($g['debug']) {
1478
			log_error("DNSCACHE: Found old IP {$oldcontents} and new IP {$contents}");
1479
		}
1480
		return ($oldcontents);
1481
	} else {
1482
		return false;
1483
	}
1484
}
1485

    
1486
/*
1487
 * load_glxsb() - Load the glxsb crypto module if enabled in config.
1488
 */
1489
function load_glxsb() {
1490
	global $config, $g;
1491
	$is_loaded = `/sbin/kldstat | /usr/bin/grep -c glxsb`;
1492
	if (isset($config['system']['glxsb_enable']) && ($is_loaded == 0)) {
1493
		mwexec("/sbin/kldload glxsb");
1494
	}
1495
}
1496

    
1497
/****f* pfsense-utils/isvm
1498
 * NAME
1499
 *   isvm
1500
 * INPUTS
1501
 *	 none
1502
 * RESULT
1503
 *   returns true if machine is running under a virtual environment
1504
 ******/
1505
function isvm() {
1506
	$virtualenvs = array("vmware", "parallels", "qemu", "bochs", "plex86");
1507
	$bios_vendor = strtolower(`/bin/kenv | /usr/bin/grep "bios.vendor" | /usr/bin/cut -d"=" -f2`);
1508
	if(in_array($bios_vendor, $virtualenvs)) 
1509
		return true;
1510
	else
1511
		return false;
1512
}
1513

    
1514
function get_freebsd_version() {
1515
	$version = trim(`/usr/bin/uname -r | /usr/bin/cut  -d'.' -f1`);
1516
	return $version;
1517
}
1518

    
1519
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body') {
1520
        global $ch, $fout, $file_size, $downloaded;
1521
        $file_size  = 1;
1522
        $downloaded = 1;
1523
        /* open destination file */
1524
        $fout = fopen($destination_file, "wb");
1525

    
1526
        /*
1527
         *      Originally by Author: Keyvan Minoukadeh
1528
         *      Modified by Scott Ullrich to return Content-Length size
1529
         */
1530

    
1531
        $ch = curl_init();
1532
        curl_setopt($ch, CURLOPT_URL, $url_file);
1533
        curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
1534
        curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
1535
        curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
1536
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, '5');
1537
        curl_setopt($ch, CURLOPT_TIMEOUT, 0);
1538

    
1539
        curl_exec($ch);
1540
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1541
        if($fout)
1542
                fclose($fout);
1543
        curl_close($ch);
1544
        return ($http_code == 200) ? true : $http_code;
1545
}
1546

    
1547
function read_header($ch, $string) {
1548
        global $file_size, $fout;
1549
        $length = strlen($string);
1550
        $regs = "";
1551
        ereg("(Content-Length:) (.*)", $string, $regs);
1552
        if($regs[2] <> "") {
1553
                $file_size = intval($regs[2]);
1554
        }
1555
        ob_flush();
1556
        return $length;
1557
}
1558

    
1559
function read_body($ch, $string) {
1560
        global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen;
1561
        $length = strlen($string);
1562
        $downloaded += intval($length);
1563
        $downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
1564
        $downloadProgress = 100 - $downloadProgress;
1565
        if($lastseen <> $downloadProgress and $downloadProgress < 101) {
1566
                if($sendto == "status") {
1567
                        $tostatus = $static_status . $downloadProgress . "%";
1568
                        update_status($tostatus);
1569
                } else {
1570
                        $tooutput = $static_output . $downloadProgress . "%";
1571
                        update_output_window($tooutput);
1572
                }
1573
                update_progress_bar($downloadProgress);
1574
                $lastseen = $downloadProgress;
1575
        }
1576
        if($fout)
1577
                fwrite($fout, $string);
1578
        ob_flush();
1579
        return $length;
1580
}
1581

    
1582
/*
1583
 *   update_output_window: update bottom textarea dynamically.
1584
 */
1585
function update_output_window($text) {
1586
        global $pkg_interface;
1587
        $log = ereg_replace("\n", "\\n", $text);
1588
        if($pkg_interface == "console") {
1589
                /* too chatty */
1590
        } else {
1591
                echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
1592
        }
1593
        /* ensure that contents are written out */
1594
        ob_flush();
1595
}
1596

    
1597
/*
1598
 *   update_output_window: update top textarea dynamically.
1599
 */
1600
function update_status($status) {
1601
        global $pkg_interface;
1602
        if($pkg_interface == "console") {
1603
                echo $status . "\n";
1604
        } else {
1605
                echo "\n<script type=\"text/javascript\">this.document.forms[0].status.value=\"" . $status . "\";</script>";
1606
        }
1607
        /* ensure that contents are written out */
1608
        ob_flush();
1609
}
1610

    
1611
/*
1612
 * update_progress_bar($percent): updates the javascript driven progress bar.
1613
 */
1614
function update_progress_bar($percent) {
1615
        global $pkg_interface;
1616
        if($percent > 100) $percent = 1;
1617
        if($pkg_interface <> "console") {
1618
                echo "\n<script type=\"text/javascript\" language=\"javascript\">";
1619
                echo "\ndocument.progressbar.style.width='" . $percent . "%';";
1620
                echo "\n</script>";
1621
        } else {
1622
                echo " {$percent}%";
1623
        }
1624
}
1625

    
1626
/* Split() is being DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 6.0.0. Relying on this feature is highly discouraged. */
1627
if(!function_exists("split")) {
1628
	function split($seperator, $haystack, $limit = null) {
1629
		return preg_split($seperator, $haystack, $limit);
1630
	}
1631
}
1632

    
1633
function update_alias_names_upon_change($section, $subsection, $fielda, $fieldb, $new_alias_name, $origname) {
1634
	global $g, $config, $pconfig, $debug;
1635
	if(!$origname) 
1636
		return;
1637

    
1638
	if($debug) $fd = fopen("{$g['tmp_path']}/print_r", "a");
1639
	if($debug) fwrite($fd, print_r($pconfig, true));
1640

    
1641
	if($fieldb) {
1642
		if($debug) fwrite($fd, "fieldb exists\n");
1643
		for ($i = 0; isset($config["$section"]["$subsection"][$i]["$fielda"]); $i++) {
1644
			if($debug) fwrite($fd, "$i\n");
1645
			if($config["$section"]["$subsection"][$i]["$fielda"]["$fieldb"] == $origname) {
1646
				if($debug) fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1647
				$config["$section"]["$subsection"][$i]["$fielda"]["$fieldb"] = $new_alias_name;
1648
			}
1649
		}	
1650
	} else {
1651
		if($debug) fwrite($fd, "fieldb does not exist\n");
1652
		for ($i = 0; isset($config["$section"]["$subsection"][$i]["$fielda"]); $i++) {
1653
			if($config["$section"]["$subsection"][$i]["$fielda"] == $origname) {
1654
				$config["$section"]["$subsection"][$i]["$fielda"] = $new_alias_name;
1655
				if($debug) fwrite($fd, "Setting old alias value $origname to $new_alias_name\n");
1656
			}
1657
		}
1658
	}
1659

    
1660
	if($debug) fclose($fd);
1661

    
1662
}
1663

    
1664
?>
(29-29/50)