Project

General

Profile

Download (66.6 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-2006 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
function get_tmp_file() {
37
	return "/tmp/tmp-" . time();
38
}
39

    
40
/****f* pfsense-utils/find_number_of_needed_carp_interfaces
41
 * NAME
42
 *   find_number_of_needed_carp_interfaces
43
 * INPUTS
44
 *   null
45
 * RESULT
46
 *   the number of needed carp interfacs
47
 ******/
48
function find_number_of_needed_carp_interfaces() {
49
	global $config, $g;
50
	$carp_counter=0;
51
	foreach($config['virtualip']['vip'] as $vip) {
52
		if($vip['mode'] == "carp")
53
			$carp_counter++;
54
	}
55
	return $carp_counter;
56
}
57

    
58
/****f* pfsense-utils/reset_carp
59
 * NAME
60
 *   reset_carp - resets carp after primary interface changes
61
 * INPUTS
62
 *   null
63
 * RESULT
64
 *   null
65
 ******/
66
function reset_carp() {
67
	$carp_counter=find_number_of_created_carp_interfaces();
68
	$needed_carp_interfaces = find_number_of_needed_carp_interfaces();
69
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
70
	for($x=0; $x<$carp_counter; $x++) {
71
		mwexec("/sbin/ifconfig carp{$x} down");
72
		mwexec("/sbin/ifconfig carp{$x} delete");
73
		log_error("CARP: $needed_carp_interfaces < $carp_counter");
74
		if($needed_carp_interfaces < $carp_counter) {
75
			$needed_carp_interfaces--;
76
			log_error("Destroying carp interface.");
77
			mwexec("/sbin/ifconfig carp{$x} destroy");
78
		}
79
	}
80
	find_number_of_created_carp_interfaces(true);
81
	sleep(1);
82
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
83
	interfaces_carp_configure();
84
	usleep(1000);
85
	interfaces_carp_bring_up_final();
86
}
87

    
88
/****f* pfsense-utils/get_dns_servers
89
 * NAME
90
 *   get_dns_servres - get system dns servers
91
 * INPUTS
92
 *   $dns_servers - an array of the dns servers
93
 * RESULT
94
 *   null
95
 ******/
96
function get_dns_servers() {
97
	$dns_servers = array();
98
	$dns = `cat /etc/resolv.conf`;
99
	$dns_s = split("\n", $dns);
100
	foreach($dns_s as $dns) {
101
		$matches = "";
102
		if (preg_match("/nameserver (.*)/", $dns, $matches))
103
			$dns_servers[] = $matches[1];
104
	}
105
	$dns_server_master = array();
106
	sort($dns_servers);
107
	$lastseen = "";
108
	foreach($dns_servers as $t) {
109
		if($t <> $lastseen)
110
			if($t <> "")
111
				$dns_server_master[] = $t;
112
		$lastseen = $t;
113
	}
114
	return $dns_server_master;
115
}
116

    
117
/****f* pfsense-utils/log_error
118
* NAME
119
*   log_error  - Sends a string to syslog.
120
* INPUTS
121
*   $error     - string containing the syslog message.
122
* RESULT
123
*   null
124
******/
125
function log_error($error) {
126
	$page = $_SERVER['SCRIPT_NAME'];
127
	syslog(LOG_WARNING, "$page: $error");
128
	return;
129
}
130

    
131
/****f* pfsense-utils/get_interface_mac_address
132
 * NAME
133
 *   get_interface_mac_address - Return a interfaces mac address
134
 * INPUTS
135
 *   $interface	- interface to obtain mac address from
136
 * RESULT
137
 *   $mac - the mac address of the interface
138
 ******/
139
function get_interface_mac_address($interface) {
140
	$mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
141
	return trim($mac);
142
}
143

    
144
/****f* pfsense-utils/return_dir_as_array
145
 * NAME
146
 *   return_dir_as_array - Return a directory's contents as an array.
147
 * INPUTS
148
 *   $dir	- string containing the path to the desired directory.
149
 * RESULT
150
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
151
 ******/
152
function return_dir_as_array($dir) {
153
	$dir_array = array();
154
	if (is_dir($dir)) {
155
		if ($dh = opendir($dir)) {
156
			while (($file = readdir($dh)) !== false) {
157
				$canadd = 0;
158
				if($file == ".") $canadd = 1;
159
				if($file == "..") $canadd = 1;
160
				if($canadd == 0)
161
					array_push($dir_array, $file);
162
			}
163
			closedir($dh);
164
		}
165
	}
166
	return $dir_array;
167
}
168

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

    
182
	if(stristr($interface,"lnc"))
183
		return;
184
	if(isset($config['system']['do_not_use_nic_microcode']))
185
		return;
186

    
187
	if($g['booting']) {
188
	/* translate wan, lan, opt -> real interface if needed */
189
	$int = filter_translate_type_to_real_interface($interface);
190
	if($int <> "") $interface = $int;
191
	$int_family = preg_split("/[0-9]+/", $int);
192
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
193
	$supported_ints = array('fxp');
194
	if (in_array($int_family, $supported_ints))
195
		mwexec("/sbin/ifconfig {$interface} link0");
196

    
197
	if(stristr($options, "txcsum") == true)
198
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
199
	if(stristr($options, "rxcsum") == true)
200
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
201
	if(stristr($options, "polling") == true)
202
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
203
	} else {
204
		mwexec("sysctl kern.polling.enable=0");
205
	}
206
	return;
207
}
208

    
209
/****f* pfsense-utils/is_alias_inuse
210
 * NAME
211
 *   checks to see if an alias is currently in use by a rule
212
 * INPUTS
213
 *
214
 * RESULT
215
 *   true or false
216
 * NOTES
217
 *
218
 ******/
219
function is_alias_inuse($alias) {
220
	global $g, $config;
221

    
222
	if($alias == "") return false;
223
	/* loop through firewall rules looking for alias in use */
224
	if(is_array($config['nat']['rule']))
225
		foreach($config['filter']['rule'] as $rule) {
226
			if(is_array($rule['source']['address']))
227
				if($rule['source']['address'] == $alias)
228
					return true;
229
			if(is_array($rule['destination']['address']))
230
				if($rule['destination']['address'] == $alias)
231
					return true;
232
		}
233
	/* loop through nat rules looking for alias in use */
234
	if(is_array($config['nat']['rule']))
235
		foreach($config['nat']['rule'] as $rule) {
236
			if($rule['target'] == $alias)
237
				return true;
238
			if($rule['external-address'] == $alias)
239
				return true;
240
		}
241
	return false;
242
}
243

    
244
/****f* pfsense-utils/setup_polling_defaults
245
 * NAME
246
 *   sets up sysctls for pollingS
247
 * INPUTS
248
 *
249
 * RESULT
250
 *   null
251
 * NOTES
252
 *
253
 ******/
254
function setup_polling_defaults() {
255
	global $g, $config;
256
	if($config['system']['polling_each_burst'])
257
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
258
	if($config['system']['polling_burst_max'])
259
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
260
	if($config['system']['polling_user_frac'])
261
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
262
}
263

    
264
/****f* pfsense-utils/setup_polling
265
 * NAME
266
 *   sets up polling
267
 * INPUTS
268
 *
269
 * RESULT
270
 *   null
271
 * NOTES
272
 *
273
 ******/
274
function setup_polling() {
275
	global $g, $config;
276

    
277
	setup_polling_defaults();
278

    
279
	if(isset($config['system']['polling']))
280
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
281
	else
282
		$supported_ints = array();
283

    
284
	/* build an array of interfaces to work with */
285
	$iflist = array("lan" => "LAN", "wan" => "WAN");
286
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
287
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
288

    
289
	foreach ($iflist as $ifent => $ifname) {
290
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
291
		$supported = false;
292
		foreach($supported_ints as $supported) {
293
			if(stristr($real_interface, $supported)) {
294
				$supported = true;
295
			}
296
		}
297
		if ($supported == true) {
298
			mwexec("/sbin/ifconfig {$real_interface} polling");
299
		} else {
300
			mwexec("/sbin/ifconfig {$real_interface} -polling");
301
		}
302
	}
303
}
304

    
305
/****f* pfsense-utils/setup_microcode
306
 * NAME
307
 *   enumerates all interfaces and calls enable_hardware_offloading which
308
 *   enables a NIC's supported hardware features.
309
 * INPUTS
310
 *
311
 * RESULT
312
 *   null
313
 * NOTES
314
 *   This function only supports the fxp driver's loadable microcode.
315
 ******/
316
function setup_microcode() {
317
	global $config;
318

    
319
	$ifdescrs = array('wan', 'lan');
320
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
321
		$ifdescrs['opt' . $j] = "opt" . $j;
322
	}
323
	foreach($ifdescrs as $if)
324
		enable_hardware_offloading($if);
325
}
326

    
327
/****f* pfsense-utils/return_filename_as_array
328
 * NAME
329
 *   return_filename_as_array - Return a file's contents as an array.
330
 * INPUTS
331
 *   $filename	- string containing the path to the desired file.
332
 *   $strip	- array of characters to strip - default is '#'.
333
 * RESULT
334
 *   $file	- array containing the file's contents.
335
 * NOTES
336
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
337
 ******/
338
function return_filename_as_array($filename, $strip = array('#')) {
339
	if(file_exists($filename)) $file = file($filename);
340
	if(is_array($file)) {
341
		foreach($file as $line) $line = trim($line);
342
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
343
	}
344
	return $file;
345
}
346

    
347
/****f* pfsense-utils/file_put_contents
348
 * NAME
349
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
350
 * RESULT
351
 *   none
352
 ******/
353
if(!function_exists("file_put_contents")) {
354
	function file_put_contents($filename, $data) {
355
		$fd = fopen($filename,"w");
356
		fwrite($fd, $data);
357
		fclose($fd);
358
	}
359
}
360

    
361
/****f* pfsense-utils/get_carp_status
362
 * NAME
363
 *   get_carp_status - Return whether CARP is enabled or disabled.
364
 * RESULT
365
 *   boolean	- true if CARP is enabled, false if otherwise.
366
 ******/
367
function get_carp_status() {
368
    /* grab the current status of carp */
369
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
370
    if(intval($status) == "0") return false;
371
    return true;
372
}
373

    
374
/****f* pfsense-utils/is_carp_defined
375
 * NAME
376
 *   is_carp_defined - Return whether CARP is detected in the kernel.
377
 * RESULT
378
 *   boolean	- true if CARP is detected, false otherwise.
379
 ******/
380
function is_carp_defined() {
381
	/* is carp compiled into the kernel and userland? */
382
	$command = "/sbin/sysctl -a | grep carp";
383
	$fd = popen($command . " 2>&1 ", "r");
384
	if(!$fd) {
385
		log_error("Warning, could not execute command {$command}");
386
		return 0;
387
	}
388
	while(!feof($fd)) {
389
		$tmp .= fread($fd,49);
390
	}
391
	fclose($fd);
392

    
393
	if($tmp == "")
394
		return false;
395
	else
396
		return true;
397
}
398

    
399
/****f* pfsense-utils/get_interface_mtu
400
 * NAME
401
 *   get_interface_mtu - Return the mtu of an interface
402
 * RESULT
403
 *   $tmp	- Returns the mtu of an interface
404
 ******/
405
function get_interface_mtu($interface) {
406
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f4`;
407
	return $mtu;
408
}
409

    
410
/****f* pfsense-utils/is_interface_wireless
411
 * NAME
412
 *   is_interface_wireless - Returns if an interface is wireless
413
 * RESULT
414
 *   $tmp	- Returns if an interface is wireless
415
 ******/
416
function is_interface_wireless($interface) {
417
	global $config, $g;
418
	$interface = convert_real_interface_to_friendly_interface_name($interface);
419
	if(isset($config['interfaces'][$interface]['wireless']))
420
		return true;
421
	else
422
		return false;
423
}
424

    
425
/****f* pfsense-utils/find_number_of_created_carp_interfaces
426
 * NAME
427
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
428
 * RESULT
429
 *   $tmp	- Number of currently created CARP interfaces.
430
 ******/
431
function find_number_of_created_carp_interfaces($flush = false) {
432
	global $carp_interface_count_cache;
433

    
434
	if (!isset($carp_interface_count_cache) or $flush) {
435
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
436
		$fd = popen($command . " 2>&1 ", "r");
437
		if(!$fd) {
438
			log_error("Warning, could not execute command {$command}");
439
			return 0;
440
		}
441
		while(!feof($fd)) {
442
			$tmp .= fread($fd,49);
443
		}
444
		fclose($fd);
445
		$carp_interface_count_cache = intval($tmp);
446
	}
447
	return $carp_interface_count_cache;
448
}
449

    
450
/****f* pfsense-utils/link_int_to_bridge_interface
451
 * NAME
452
 *   link_int_to_bridge_interface - Finds out a bridge group for an interface
453
 * INPUTS
454
 *   $ip
455
 * RESULT
456
 *   bridge[0-99]
457
 ******/
458
function link_int_to_bridge_interface($int) {
459
	global $config, $g;
460
	$real_int = convert_friendly_interface_to_real_interface_name($int);
461
	$num_bridges = find_number_of_created_bridges();
462
	for($x=0; $x<$num_bridges; $x++) {
463
		$matches = "";
464
		$bridge_info = `/sbin/ifconfig bridge{$x}`;
465
		if(stristr($bridge_info, "member: {$real_int}")) {
466
			return "bridge{$x}";
467
		}
468
	}
469
}
470

    
471
/****f* pfsense-utils/link_ip_to_carp_interface
472
 * NAME
473
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
474
 * INPUTS
475
 *   $ip
476
 * RESULT
477
 *   $carp_ints
478
 ******/
479
function link_ip_to_carp_interface($ip) {
480
	global $config;
481
	if($ip == "") return;
482

    
483
	$ifdescrs = array('wan', 'lan');
484
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
485
		$ifdescrs['opt' . $j] = "opt" . $j;
486
	}
487

    
488
	$ft = split("\.", $ip);
489
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
490

    
491
	$carp_ints = "";
492
	$num_carp_ints = find_number_of_created_carp_interfaces();
493
	foreach ($ifdescrs as $ifdescr => $ifname) {
494
		for($x=0; $x<$num_carp_ints; $x++) {
495
			$carp_int = "carp{$x}";
496
			$carp_ip = find_interface_ip($carp_int);
497
			$carp_ft = split("\.", $carp_ip);
498
			$carp_ft_ip = $carp_ft[0] . "." . $carp_ft[1] . "." . $carp_ft[2] . ".";
499
			$result = does_interface_exist($carp_int);
500
			if($result <> true) break;
501
			if($ft_ip == $carp_ft_ip)
502
			if(stristr($carp_ints,$carp_int) == false)
503
			$carp_ints .= " " . $carp_int;
504
		}
505
	}
506
	return $carp_ints;
507
}
508

    
509
/****f* pfsense-utils/exec_command
510
 * NAME
511
 *   exec_command - Execute a command and return a string of the result.
512
 * INPUTS
513
 *   $command	- String of the command to be executed.
514
 * RESULT
515
 *   String containing the command's result.
516
 * NOTES
517
 *   This function returns the command's stdout and stderr.
518
 ******/
519
function exec_command($command) {
520
	$output = array();
521
	exec($command . ' 2>&1 ', $output);
522
	return(implode("\n", $output));
523
}
524

    
525
/****f* interfaces/is_jumbo_capable
526
 * NAME
527
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
528
 * INPUTS
529
 *   $int             - string containing interface name
530
 * RESULT
531
 *   boolean          - true or false
532
 ******/
533
function is_jumbo_capable($int) {
534
	/* Per:
535
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
536
	 * Only the following drivers support large frames
537
         *
538
	 * 'de' chipset purposely left out of this list
539
	 * requires defining BIG_PACKET in the
540
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
541
	 * kernel or module.  The hack works only for the 21041,
542
	 * 21140, and 21140A chips.
543
	 */
544
	global $g;
545

    
546
	$capable = $g['vlan_long_frame'];
547

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

    
550
	if (in_array($int_family[0], $capable))
551
		return true;
552
	else
553
		return false;
554
}
555

    
556
/*
557
 * Return the interface array
558
 */
559
function get_interface_arr($flush = false) {
560
	global $interface_arr_cache;
561

    
562
	/* If the cache doesn't exist, build it */
563
	if (!isset($interface_arr_cache) or $flush)
564
		$interface_arr_cache = exec_command("/sbin/ifconfig -l");
565

    
566
	return $interface_arr_cache;
567
}
568

    
569
/*
570
 * does_interface_exist($interface): return true or false if a interface is
571
 * detected.
572
 */
573
function does_interface_exist($interface) {
574
        $ints = get_interface_arr();
575

    
576
	if(stristr($ints, $interface) !== false)
577
		return true;
578
	else
579
		return false;
580
}
581

    
582
/*
583
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
584
 */
585
function convert_ip_to_network_format($ip, $subnet) {
586
	$ipsplit = split('[.]', $ip);
587
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
588
	return $string;
589
}
590

    
591
/*
592
 * find_interface_ip($interface): return the interface ip (first found)
593
 */
594
function find_interface_ip($interface, $flush = false) {
595
	global $interface_ip_arr_cache;
596
	$interface = str_replace("\n", "", $interface);
597
	if(does_interface_exist($interface) == false) return;
598
	/* Setup IP cache */
599
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
600
		$interface_ip_arr_cache[$interface] = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2");
601
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
602
	}
603

    
604
	return $interface_ip_arr_cache[$interface];
605
}
606

    
607
function guess_interface_from_ip($ipaddress) {
608
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/grep interface | /usr/bin/awk '{ print \$2
609
; };'");
610
	return $ret;
611
}
612

    
613
function filter_opt_interface_to_real($opt) {
614
	global $config;
615
	return $config['interfaces'][$opt]['if'];
616
}
617

    
618
function filter_get_opt_interface_descr($opt) {
619
	global $config;
620
	return $config['interfaces'][$opt]['descr'];
621
}
622

    
623
function get_friendly_interface_list_as_array() {
624
	global $config;
625
	$ints = array();
626
	$ifdescrs = array('wan', 'lan');
627
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
628
		$ifdescrs['opt' . $j] = "opt" . $j;
629
	}
630
	$ifdescrs = get_interface_list();
631
	foreach ($ifdescrs as $ifdescr => $ifname) {
632
		array_push($ints,$ifdescr);
633
	}
634
	return $ints;
635
}
636

    
637
/*
638
 * find_ip_interface($ip): return the interface where an ip is defined
639
 */
640
function find_ip_interface($ip) {
641
	global $config;
642
	$ifdescrs = array('wan', 'lan');
643
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
644
		$ifdescrs['opt' . $j] = "opt" . $j;
645
	}
646
	foreach ($ifdescrs as $ifdescr => $ifname) {
647
		$int = filter_translate_type_to_real_interface($ifname);
648
		$ifconfig = exec_command("/sbin/ifconfig {$int}");
649
	if(stristr($ifconfig,$ip) <> false)
650
		return $int;
651
	}
652
	return false;
653
}
654

    
655
/*
656
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
657
 *                                                       for a friendly interface.  ie: wan
658
 */
659
function filter_translate_type_to_real_interface($interface) {
660
	global $config;
661
	if($config['interfaces'][$interface]['if'] <> "") {
662
		return $config['interfaces'][$interface]['if'];
663
	} else {
664
		return $interface;
665
	}
666
}
667

    
668
/*
669
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
670
 */
671
function get_carp_interface_status($carpinterface) {
672
	/* basically cache the contents of ifconfig statement
673
	to speed up this routine */
674
	global $carp_query;
675
	if($carp_query == "")
676
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
677
	$found_interface = 0;
678
	foreach($carp_query as $int) {
679
		if($found_interface == 1) {
680
			if(stristr($int, "MASTER")) return "MASTER";
681
			if(stristr($int, "BACKUP")) return "BACKUP";
682
			if(stristr($int, "INIT")) return "INIT";
683
			return false;
684
		}
685
		if(stristr($int, $carpinterface) == true)
686
		$found_interface=1;
687
	}
688
	return;
689
}
690

    
691
/*
692
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
693
 */
694
function get_pfsync_interface_status($pfsyncinterface) {
695
    $result = does_interface_exist($pfsyncinterface);
696
    if($result <> true) return;
697
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
698
    return $status;
699
}
700

    
701
/*
702
 * find_carp_interface($ip): return the carp interface where an ip is defined
703
 */
704
function find_carp_interface($ip) {
705
	global $find_carp_ifconfig;
706
	if($find_carp_ifconfig == "") {
707
		$find_carp_ifconfig = array();
708
		$num_carp_ints = find_number_of_created_carp_interfaces();
709
		for($x=0; $x<$num_carp_ints; $x++) {
710
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
711
		}
712
	}
713
	$carps = 0;
714
	foreach($find_carp_ifconfig as $fci) {
715
		if(stristr($fci, $ip) == true)
716
			return "carp{$carps}";
717
		$carps++;
718
	}
719
}
720

    
721
/*
722
 * setup_filter_bridge(): toggle filtering bridge
723
 */
724
function setup_filter_bridge() {
725
	global $config, $g;
726
	if(isset($config['bridge']['filteringbridge'])) {
727
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
728
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
729
	} else {
730
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
731
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
732
	}
733
}
734

    
735
/*
736
 * find_number_of_created_bridges(): returns the number of currently created bridges
737
 */
738
function find_number_of_created_bridges($flush = false) {
739
	global $bridge_interface_count_cache;
740
	if(!isset($bridge_interface_count_cache) or $flush)
741
		$bridge_interface_count_cache = exec_command('/sbin/ifconfig | /usr/bin/grep "bridge[0-999]" | /usr/bin/wc -l');
742

    
743
	return $bridge_interface_count_cache;
744
}
745

    
746
/*
747
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
748
 */
749
function add_rule_to_anchor($anchor, $rule, $label) {
750
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
751
}
752

    
753
/*
754
 * remove_text_from_file
755
 * remove $text from file $file
756
 */
757
function remove_text_from_file($file, $text) {
758
	global $fd_log;
759
	fwrite($fd_log, "Adding needed text items:\n");
760
	$filecontents = exec_command_and_return_text("cat " . $file);
761
	$textTMP = str_replace($text, "", $filecontents);
762
	$text .= $textTMP;
763
	fwrite($fd_log, $text . "\n");
764
	$fd = fopen($file, "w");
765
	fwrite($fd, $text);
766
	fclose($fd);
767
}
768

    
769
/*
770
 * add_text_to_file($file, $text): adds $text to $file.
771
 * replaces the text if it already exists.
772
 */
773
function add_text_to_file($file, $text) {
774
	if(file_exists($file) and is_writable($file)) {
775
		$filecontents = file($file);
776
		$filecontents[] = $text;
777
		$tmpfile = get_tmp_file();
778
		$fout = fopen($tmpfile, "w");
779
		foreach($filecontents as $line) {
780
			fwrite($fout, rtrim($line) . "\n");
781
		}
782
		fclose($fout);
783
		rename($tmpfile, $file);
784
		return true;
785
	} else {
786
		return false;
787
	}
788
}
789

    
790
/*
791
 *   after_sync_bump_adv_skew(): create skew values by 1S
792
 */
793
function after_sync_bump_adv_skew() {
794
	global $config, $g;
795
	$processed_skew = 1;
796
	$a_vip = &$config['virtualip']['vip'];
797
	foreach ($a_vip as $vipent) {
798
		if($vipent['advskew'] <> "") {
799
			$processed_skew = 1;
800
			$vipent['advskew'] = $vipent['advskew']+1;
801
		}
802
	}
803
	if($processed_skew == 1)
804
		write_config("After synch increase advertising skew");
805
}
806

    
807
/*
808
 * get_filename_from_url($url): converts a url to its filename.
809
 */
810
function get_filename_from_url($url) {
811
	return basename($url);
812
}
813

    
814
/*
815
 *   update_output_window: update bottom textarea dynamically.
816
 */
817
function update_output_window($text) {
818
	$log = ereg_replace("\n", "\\n", $text);
819
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
820
	/* ensure that contents are written out */
821
	ob_flush();
822
}
823

    
824
/*
825
 *   get_dir: return an array of $dir
826
 */
827
function get_dir($dir) {
828
	$dir_array = array();
829
	$d = dir($dir);
830
	while (false !== ($entry = $d->read())) {
831
		array_push($dir_array, $entry);
832
	}
833
	$d->close();
834
	return $dir_array;
835
}
836

    
837
/*
838
 *   update_output_window: update top textarea dynamically.
839
 */
840
function update_status($status) {
841
	echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
842
	/* ensure that contents are written out */
843
	ob_flush();
844
}
845

    
846
/*
847
 *   exec_command_and_return_text_array: execute command and return output
848
 */
849
function exec_command_and_return_text_array($command) {
850
	$fd = popen($command . " 2>&1 ", "r");
851
	while(!feof($fd)) {
852
		$tmp .= fread($fd,49);
853
	}
854
	fclose($fd);
855
	$temp_array = split("\n", $tmp);
856
	return $temp_array;
857
}
858

    
859
/*
860
 *   exec_command_and_return_text: execute command and return output
861
 */
862
function exec_command_and_return_text($command) {
863
	return exec_command($command);
864
}
865

    
866
/*
867
 *   exec_command_and_return_text: execute command and update output window dynamically
868
 */
869
function execute_command_return_output($command) {
870
	global $fd_log;
871
	$fd = popen($command . " 2>&1 ", "r");
872
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
873
	$counter = 0;
874
	$counter2 = 0;
875
	while(!feof($fd)) {
876
		$tmp = fread($fd, 50);
877
		$tmp1 = ereg_replace("\n","\\n", $tmp);
878
		$text = ereg_replace("\"","'", $tmp1);
879
		$lasttext = "";
880
		if($lasttext == "..") {
881
			$text = "";
882
			$lasttext = "";
883
			$counter=$counter-2;
884
		} else {
885
			$lasttext .= $text;
886
		}
887
		if($counter > 51) {
888
			$counter = 0;
889
			$extrabreak = "\\n";
890
		} else {
891
	    $extrabreak = "";
892
	    $counter++;
893
		}
894
		if($counter2 > 600) {
895
			echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
896
			$counter2 = 0;
897
		} else
898
			$counter2++;
899
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
900
	}
901
	fclose($fd);
902
}
903

    
904
/*
905
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
906
 */
907
function convert_friendly_interface_to_real_interface_name($interface) {
908
	global $config;
909
	$lc_interface = strtolower($interface);
910
	if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
911
	if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
912
	$ifdescrs = array();
913
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
914
		$ifdescrs['opt' . $j] = "opt" . $j;
915
	foreach ($ifdescrs as $ifdescr => $ifname) {
916
		if(strtolower($ifname) == $lc_interface)
917
	    return $config['interfaces'][$ifname]['if'];
918
		if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
919
			return $config['interfaces'][$ifname]['if'];
920
   }
921
   return $interface;
922
}
923

    
924
/*
925
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
926
 */
927
function convert_real_interface_to_friendly_interface_name($interface) {
928
	global $config;
929
	$ifdescrs = array('wan', 'lan');
930
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
931
		$ifdescrs['opt' . $j] = "opt" . $j;
932
	foreach ($ifdescrs as $ifdescr => $ifname) {
933
		$int = filter_translate_type_to_real_interface($ifname);
934
		if($ifname == $interface) return $ifname;
935
		if($int == $interface) return $ifname;
936
	}
937
	return $interface;
938
}
939

    
940
/*
941
 * update_progress_bar($percent): updates the javascript driven progress bar.
942
 */
943
function update_progress_bar($percent) {
944
	if($percent > 100) $percent = 1;
945
	echo "\n<script type=\"text/javascript\" language=\"javascript\">";
946
	echo "\ndocument.progressbar.style.width='" . $percent . "%';";
947
	echo "\n</script>";
948
}
949

    
950
/****f* pfsense-utils/WakeOnLan
951
 * NAME
952
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
953
 * RESULT
954
 *   true/false - true if the operation was successful
955
 ******/
956
function WakeOnLan($addr, $mac)
957
{
958
	$addr_byte = explode(':', $mac);
959
	$hw_addr = '';
960

    
961
	for ($a=0; $a < 6; $a++)
962
		$hw_addr .= chr(hexdec($addr_byte[$a]));
963

    
964
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
965

    
966
	for ($a = 1; $a <= 16; $a++)
967
		$msg .= $hw_addr;
968

    
969
	// send it to the broadcast address using UDP
970
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
971
	if ($s == false) {
972
		log_error("Error creating socket!");
973
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
974
	} else {
975
		// setting a broadcast option to socket:
976
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
977
		if($opt_ret < 0)
978
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
979
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
980
		socket_close($s);
981
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
982
		return true;
983
	}
984

    
985
	return false;
986
}
987

    
988
/*
989
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
990
 *                             is queuename|qlength|measured_packets
991
 *                             NOTE: this command takes 5 seconds to run
992
 */
993
function gather_altq_queue_stats($dont_return_root_queues) {
994
	mwexec("/usr/bin/killall -9 pfctl");
995
	$stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
996
	$stats_array = split("\n", $stats);
997
	$queue_stats = array();
998
	foreach ($stats_array as $stats_line) {
999
		$match_array = "";
1000
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
1001
			$queue_name = $match_array[1][0];
1002
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
1003
			$speed = $match_array[1][0];
1004
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
1005
			$borrows = $match_array[1][0];
1006
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
1007
			$suspends = $match_array[1][0];
1008
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
1009
			$drops = $match_array[1][0];
1010
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
1011
			$measured = $match_array[1][0];
1012
			if($dont_return_root_queues == true)
1013
				if(stristr($queue_name,"root_") == false)
1014
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
1015
		}
1016
	}
1017
	return $queue_stats;
1018
}
1019

    
1020
/*
1021
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
1022
 *					 Useful for finding paths and stripping file extensions.
1023
 */
1024
function reverse_strrchr($haystack, $needle) {
1025
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
1026
}
1027

    
1028
/*
1029
 *  backup_config_section($section): returns as an xml file string of
1030
 *                                   the configuration section
1031
 */
1032
function backup_config_section($section) {
1033
	global $config;
1034
	$new_section = &$config[$section];
1035
	/* generate configuration XML */
1036
	$xmlconfig = dump_xml_config($new_section, $section);
1037
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
1038
	return $xmlconfig;
1039
}
1040

    
1041
/*
1042
 *  backup_vip_config_section($section): returns as an xml file string of
1043
 *                                   the configuration section
1044
 */
1045
function backup_vip_config_section() {
1046
	global $config;
1047
	$new_section = &$config['virtualip'];
1048
	foreach($new_section['vip'] as $section) {
1049
		if($section['mode'] == "proxyarp") {
1050
			unset($section);
1051
		}
1052
		if($section['advskew'] <> "") {
1053
			$section_val = intval($section['advskew']);
1054
			$section_val=$section_val+100;
1055
			if($section_val > 255)
1056
				$section_val = 255;
1057
			$section['advskew'] = $section_val;
1058
		}
1059
		$temp['vip'][] = $section;
1060
   }
1061
   return $temp;
1062
}
1063

    
1064
/*
1065
 *  restore_config_section($section, new_contents): restore a configuration section,
1066
 *                                                  and write the configuration out
1067
 *                                                  to disk/cf.
1068
 */
1069
function restore_config_section($section, $new_contents) {
1070
	global $config, $g;
1071
	conf_mount_rw();
1072
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
1073
	fwrite($fout, $new_contents);
1074
	fclose($fout);
1075
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
1076
	$config[$section] = &$section_xml;
1077
	unlink($g['tmp_path'] . "/tmpxml");
1078
	write_config("Restored {$section} of config file (maybe from CARP partner)");
1079
	conf_mount_ro();
1080
	return;
1081
}
1082

    
1083
/*
1084
 * http_post($server, $port, $url, $vars): does an http post to a web server
1085
 *                                         posting the vars array.
1086
 * written by nf@bigpond.net.au
1087
 */
1088
function http_post($server, $port, $url, $vars) {
1089
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
1090
	$urlencoded = "";
1091
	while (list($key,$value) = each($vars))
1092
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
1093
	$urlencoded = substr($urlencoded,0,-1);
1094
	$content_length = strlen($urlencoded);
1095
	$headers = "POST $url HTTP/1.1
1096
Accept: */*
1097
Accept-Language: en-au
1098
Content-Type: application/x-www-form-urlencoded
1099
User-Agent: $user_agent
1100
Host: $server
1101
Connection: Keep-Alive
1102
Cache-Control: no-cache
1103
Content-Length: $content_length
1104

    
1105
";
1106

    
1107
	$errno = "";
1108
	$errstr = "";
1109
	$fp = fsockopen($server, $port, $errno, $errstr);
1110
	if (!$fp) {
1111
		return false;
1112
	}
1113

    
1114
	fputs($fp, $headers);
1115
	fputs($fp, $urlencoded);
1116

    
1117
	$ret = "";
1118
	while (!feof($fp))
1119
		$ret.= fgets($fp, 1024);
1120
	fclose($fp);
1121

    
1122
	return $ret;
1123
}
1124

    
1125
/*
1126
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
1127
 */
1128
if (!function_exists('php_check_syntax')){
1129
	function php_check_syntax($code_to_check, &$errormessage){
1130
		return false;
1131
		$fout = fopen("/tmp/codetocheck.php","w");
1132
		$code = $_POST['content'];
1133
		$code = str_replace("<?php", "", $code);
1134
		$code = str_replace("?>", "", $code);
1135
		fwrite($fout, "<?php\n\n");
1136
		fwrite($fout, $code_to_check);
1137
		fwrite($fout, "\n\n?>\n");
1138
		fclose($fout);
1139
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1140
		$output = exec_command($command);
1141
		if (stristr($output, "Errors parsing") == false) {
1142
			echo "false\n";
1143
			$errormessage = '';
1144
			return(false);
1145
		} else {
1146
			$errormessage = $output;
1147
			return(true);
1148
		}
1149
	}
1150
}
1151

    
1152
/*
1153
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1154
 */
1155
if (!function_exists('php_check_syntax')){
1156
	function php_check_syntax($code_to_check, &$errormessage){
1157
		return false;
1158
		$command = "/usr/local/bin/php -l " . $code_to_check;
1159
		$output = exec_command($command);
1160
		if (stristr($output, "Errors parsing") == false) {
1161
			echo "false\n";
1162
			$errormessage = '';
1163
			return(false);
1164
		} else {
1165
			$errormessage = $output;
1166
			return(true);
1167
		}
1168
	}
1169
}
1170

    
1171
/*
1172
 * rmdir_recursive($path,$follow_links=false)
1173
 * Recursively remove a directory tree (rm -rf path)
1174
 * This is for directories _only_
1175
 */
1176
function rmdir_recursive($path,$follow_links=false) {
1177
	$to_do = glob($path);
1178
	if(!is_array($to_do)) $to_do = array($to_do);
1179
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1180
		if(file_exists($workingdir)) {
1181
			if(is_dir($workingdir)) {
1182
				$dir = opendir($workingdir);
1183
				while ($entry = readdir($dir)) {
1184
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1185
						unlink("$workingdir/$entry");
1186
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
1187
						rmdir_recursive("$workingdir/$entry");
1188
				}
1189
				closedir($dir);
1190
				rmdir($workingdir);
1191
			} elseif (is_file($workingdir)) {
1192
				unlink($workingdir);
1193
			}
1194
               	}
1195
	}
1196
	return;
1197
}
1198

    
1199
/*
1200
 *     get_memory()
1201
 *     returns an array listing the amount of
1202
 *     memory installed in the hardware
1203
 *     [0]real and [1]available
1204
 */
1205
function get_memory() {
1206
	if(file_exists("/var/log/dmesg.boot")) {
1207
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1208
		$matches = "";
1209
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1210
			$real = $matches[1];
1211
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1212
			$avail = $matches[1];
1213
		return array($real[0],$avail[0]);
1214
	} else {
1215
		$mem = `dmesg -a`;
1216
		$matches = "";
1217
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1218
			$real = $matches[1];
1219
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1220
			$avail = $matches[1];
1221
		return array($real[0],$avail[0]);
1222
	}
1223
}
1224

    
1225
/*
1226
 *    safe_mkdir($path, $mode = 0755)
1227
 *    create directory if it doesn't already exist and isn't a file!
1228
 */
1229
function safe_mkdir($path, $mode=0755) {
1230
	global $g;
1231

    
1232
	/* cdrom is ro. */
1233
	if($g['platform'] == "cdrom")
1234
		return false;
1235

    
1236
	if (!is_file($path) && !is_dir($path))
1237
		return mkdir($path, $mode);
1238
	else
1239
		return false;
1240
}
1241

    
1242
/*
1243
 * make_dirs($path, $mode = 0755)
1244
 * create directory tree recursively (mkdir -p)
1245
 */
1246
function make_dirs($path, $mode = 0755) {
1247
	$base = '';
1248
	foreach (explode('/', $path) as $dir) {
1249
		$base .= "/$dir";
1250
		if (!is_dir($base)) {
1251
			if (!@mkdir($base, $mode))
1252
				return false;
1253
		}
1254
	}
1255
	return true;
1256
}
1257

    
1258
/*
1259
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
1260
 */
1261
function call_pfsense_method($method, $params, $timeout = 0) {
1262
	$ip = gethostbyname('www.pfsense.com');
1263
	if($ip == "www.pfsense.com")
1264
		return false;
1265
	global $g, $config;
1266
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
1267
	$xmlrpc_path = $g['xmlrpcpath'];
1268
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
1269
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
1270
	$resp = $cli->send($msg, $timeout);
1271
	if(!$resp) {
1272
		log_error("XMLRPC communication error: " . $cli->errstr);
1273
		return false;
1274
	} elseif($resp->faultCode()) {
1275
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
1276
		return false;
1277
	} else {
1278
		return XML_RPC_Decode($resp->value());
1279
	}
1280
}
1281

    
1282
/*
1283
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1284
 */
1285
function check_firmware_version($tocheck = "all", $return_php = true) {
1286
	global $g, $config;
1287
	$ip = gethostbyname('www.pfsense.com');
1288
	if($ip == "www.pfsense.com")
1289
		return false;
1290
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
1291
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
1292
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
1293
		"platform" => trim(file_get_contents('/etc/platform'))
1294
		);
1295
	if($tocheck == "all") {
1296
		$params = $rawparams;
1297
	} else {
1298
		foreach($tocheck as $check) {
1299
			$params['check'] = $rawparams['check'];
1300
			$params['platform'] = $rawparams['platform'];
1301
		}
1302
	}
1303
	if($config['system']['firmware']['branch']) {
1304
		$params['branch'] = $config['system']['firmware']['branch'];
1305
	}
1306
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
1307
		return false;
1308
	} else {
1309
		$versions["current"] = $params;
1310
	}
1311
	return $versions;
1312
}
1313

    
1314
function get_disk_info() {
1315
	$diskout = "";
1316
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
1317
	return explode(' ', $diskout[0]);
1318
	// $size, $used, $avail, $cap
1319
}
1320

    
1321
/****f* pfsense-utils/display_top_tabs
1322
 * NAME
1323
 *   display_top_tabs - display tabs with rounded edges
1324
 * INPUTS
1325
 *   $text	- array of tabs
1326
 * RESULT
1327
 *   null
1328
 ******/
1329
function display_top_tabs($tab_array) {
1330
	echo "<table cellpadding='0' cellspacing='0'>\n";
1331
	echo " <tr height='1'>\n";
1332
	$tabscounter = 0;
1333
	foreach ($tab_array as $ta) {
1334
		if($ta[1] == true) {
1335
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
1336
		} else {
1337
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
1338
		}
1339
		$tabscounter++;
1340
	}
1341
	echo "</tr>\n<tr>\n";
1342
	foreach ($tab_array as $ta) {
1343
		if($ta[1] == true) {
1344
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
1345
			echo "&nbsp;&nbsp;&nbsp;";
1346
			echo "<font size='-12'>&nbsp;</td>\n";
1347
		} else {
1348
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
1349
			echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
1350
			echo "<font size='-12'>&nbsp;</td>\n";
1351
		}
1352
	}
1353
	echo "</tr>\n<tr height='5px'>\n";
1354
	foreach ($tab_array as $ta) {
1355
		if($ta[1] == true) {
1356
			echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1357
		} else {
1358
			echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1359
		}
1360
		$tabscounter++;
1361
	}
1362
	echo " </tr>\n";
1363
	echo "</table>\n";
1364

    
1365
	echo "<script type=\"text/javascript\">";
1366
	echo "NiftyCheck();\n";
1367
	echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1368
	for($x=0; $x<$tabscounter; $x++)
1369
		echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1370
	echo "</script>";
1371
}
1372

    
1373

    
1374
/****f* pfsense-utils/display_topbar
1375
 * NAME
1376
 *   display_topbar - top a table off with rounded edges
1377
 * INPUTS
1378
 *   $text	- (optional) Text to include in bar
1379
 * RESULT
1380
 *   null
1381
 ******/
1382
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
1383
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
1384
	echo "       <tr height='1'>\n";
1385
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
1386
	echo "		<div id='topbar'></div></td>\n";
1387
	echo "       </tr>\n";
1388
	echo "       <tr height='1'>\n";
1389
	if ($text != "")
1390
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
1391
	else
1392
		echo "         <td height='1' class='listtopic'></td>\n";
1393
	echo "       </tr>\n";
1394
	echo "     </table>";
1395
	echo "<script type=\"text/javascript\">";
1396
	echo "NiftyCheck();\n";
1397
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
1398
	echo "</script>";
1399
}
1400

    
1401
/****f* pfsense-utils/generate_random_mac_address
1402
 * NAME
1403
 *   generate_random_mac - generates a random mac address
1404
 * INPUTS
1405
 *   none
1406
 * RESULT
1407
 *   $mac - a random mac address
1408
 ******/
1409
function generate_random_mac_address() {
1410
	$mac = "02";
1411
	for($x=0; $x<5; $x++)
1412
		$mac .= ":" . dechex(rand(16, 255));
1413
	return $mac;
1414
}
1415

    
1416
/****f* pfsense-utils/strncpy
1417
 * NAME
1418
 *   strncpy - copy strings
1419
 * INPUTS
1420
 *   &$dst, $src, $length
1421
 * RESULT
1422
 *   none
1423
 ******/
1424
function strncpy(&$dst, $src, $length) {
1425
	if (strlen($src) > $length) {
1426
		$dst = substr($src, 0, $length);
1427
	} else {
1428
		$dst = $src;
1429
	}
1430
}
1431

    
1432
/****f* pfsense-utils/reload_interfaces_sync
1433
 * NAME
1434
 *   reload_interfaces - reload all interfaces
1435
 * INPUTS
1436
 *   none
1437
 * RESULT
1438
 *   none
1439
 ******/
1440
function reload_interfaces_sync() {
1441
	global $config, $g, $debug;
1442

    
1443
	$shutdown_webgui_needed = false;
1444

    
1445
	touch("{$g['tmp_path']}/reloading_all");
1446

    
1447
	if($debug)
1448
		log_error("reload_interfaces_sync() is starting.");
1449

    
1450
	if(file_exists("{$g['tmp_path']}/config.cache"))
1451
		unlink("{$g['tmp_path']}/config.cache");
1452

    
1453
	/* parse config.xml again */
1454
	$config = parse_config(true);
1455

    
1456
	$wan_if = $config['interfaces']['wan']['if'];
1457
	$lan_if = $config['interfaces']['lan']['if'];
1458

    
1459
	if($debug)
1460
		log_error("Cleaning up Interfaces");
1461

    
1462
	/* build an array of interfaces to work with */
1463
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1464
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1465
		$iflist['opt' . $i] = "opt{$i}";
1466

    
1467
	foreach ($iflist as $ifent => $ifname) {
1468
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1469
		if(stristr($ifname, "lo0") == true)
1470
			continue;
1471
		/* do not process wan interface, its mandatory */
1472
		if(stristr($ifname, "$wan_if") == true)
1473
			continue;
1474
		/* do not process lan interface, its mandatory */
1475
		if(stristr($ifname, "$lan_if") == true)
1476
			continue;
1477
		if($debug)
1478
			log_error("Downing and deleting $ifname_real - $ifname");
1479
		mwexec("/sbin/ifconfig {$ifname_real} down");
1480
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1481
	}
1482

    
1483
	/* set up VLAN virtual interfaces */
1484
	if($debug)
1485
		log_error("Configuring VLANS");
1486
	interfaces_vlan_configure();
1487

    
1488
	/* set up LAN interface */
1489
	if($debug)
1490
		log_error("Configuring LAN");
1491
	interfaces_lan_configure();
1492

    
1493
	/* set up WAN interface */
1494
	if($debug)
1495
		log_error("Configuring WAN");
1496
	interfaces_wan_configure();
1497

    
1498
	/* set up Optional interfaces */
1499
	if($debug)
1500
		log_error("Configuring optional interfaces");
1501
	interfaces_optional_configure();
1502

    
1503
	/* set up static routes */
1504
	if($debug)
1505
		log_error("Configuring system Routing");
1506
	system_routing_configure();
1507

    
1508
	/* enable routing */
1509
	if($debug)
1510
		log_error("Enabling system routing");
1511
	system_routing_enable();
1512

    
1513
	/* setup captive portal if needed */
1514
	if($debug)
1515
		log_error("Configuring Captive portal");
1516
	captiveportal_configure();
1517

    
1518
	/* bring up carp interfaces */
1519
	if($debug)
1520
		log_error("Configuring CARP");
1521
	interfaces_carp_configure();
1522

    
1523
	/* bring up carp interfaces*/
1524
	if($debug)
1525
		log_error("Bringing up CARP interfaces");
1526
	interfaces_carp_bring_up_final();
1527

    
1528
	/* restart webConfigurator if needed */
1529
	if($shutdown_webgui_needed == true)
1530
		touch("/tmp/restart_webgui");
1531

    
1532
	/* start devd back up */
1533
	mwexec("/bin/rm /tmp/reload*");
1534

    
1535
	/* remove reloading_all trigger */
1536
	if($debug)
1537
		log_error("Removing {$g['tmp_path']}/reloading_all");
1538
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1539
}
1540

    
1541
/****f* pfsense-utils/reload_all
1542
 * NAME
1543
 *   reload_all - triggers a reload of all settings
1544
 *   * INPUTS
1545
 *   none
1546
 * RESULT
1547
 *   none
1548
 ******/
1549
function reload_all() {
1550
	touch("/tmp/reload_all");
1551
}
1552

    
1553
/****f* pfsense-utils/reload_interfaces
1554
 * NAME
1555
 *   reload_interfaces - triggers a reload of all interfaces
1556
 * INPUTS
1557
 *   none
1558
 * RESULT
1559
 *   none
1560
 ******/
1561
function reload_interfaces() {
1562
	touch("/tmp/reload_interfaces");
1563
}
1564

    
1565
/****f* pfsense-utils/sync_webgui_passwords
1566
 * NAME
1567
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1568
 * INPUTS
1569
 *   none
1570
 * RESULT
1571
 *   none
1572
 ******/
1573
function sync_webgui_passwords() {
1574
	global $config, $g;
1575
	conf_mount_rw();
1576
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
1577
	if (!$fd) {
1578
		printf("Error: cannot open htpasswd in system_password_configure().\n");
1579
		return 1;
1580
	}
1581
	/* set admin account */
1582
	$username = $config['system']['username'];
1583

    
1584
	/* set defined user account */
1585
	if($username <> "admin") {
1586
		$username = $config['system']['username'];
1587
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1588
	} else {
1589
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1590
	}
1591
	fclose($fd);
1592
	chmod("{$g['varrun_path']}/htpasswd", 0600);
1593
	$crypted_pw = $config['system']['password'];
1594
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1595
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1596
	/* sync root */
1597
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
1598
	fwrite($fd, $crypted_pw);
1599
	pclose($fd);
1600
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
1601
	/* sync admin */
1602
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
1603
	fwrite($fd, $crypted_pw);
1604
	pclose($fd);
1605
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
1606
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1607
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1608
	conf_mount_ro();
1609
}
1610

    
1611
/****f* pfsense-utils/cleanup_opt_interfaces_after_removal
1612
 * NAME
1613
 *   cleanup_opt_interfaces_after_removal - renumber interfaces after removing
1614
 *   * INPUTS
1615
 *   optional interface number
1616
 * RESULT
1617
 *   none
1618
 ******/
1619
function cleanup_opt_interfaces_after_removal($opt_interface_num) {
1620
	global $config;
1621
	config_lock();
1622
	conf_mount_rw();
1623
	unlink_if_exists("/tmp/config.cache");
1624
	$config_file = file_get_contents("/cf/conf/config.xml");
1625
	/* loop through and reassign optional items */
1626
	for ($i = 255; isset($config['interfaces']['opt' . $i]); $i--) {
1627
		if($i < $opt_interface_num)
1628
			break;
1629
		/* replace opt$i with $i -1 */
1630
		str_replace("opt" . $i, "opt" . ($i-1), $config_file);
1631
	}
1632
	conf_mount_rw();
1633
	$fd = fopen("/cf/conf/config.xml", "w");
1634
	fwrite($fd, $config_file);
1635
	fclose($fd);
1636
	$config = parse_config(true);
1637
	conf_mount_ro();
1638
	config_unlock();
1639
	return true;
1640
}
1641

    
1642
/****f* pfsense-utils/get_number_of_wan_netgraph_interfaces_needed
1643
 * NAME
1644
 *   get_number_of_wan_netgraph_interfaces_needed - returns the
1645
 *   		amount of netgraph interfaces needed for system wans
1646
 *   * INPUTS
1647
 *   none
1648
 * RESULT
1649
 *   number of needed netgraph (ng) interfaces
1650
 ******/
1651
function get_number_of_wan_netgraph_interfaces_needed() {
1652
	global $config, $g;
1653
	/* build an array of interfaces to work with */
1654
	$iflist = array("wan" => "WAN");
1655
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1656
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1657
	$ng_interfaces_needed = 0;
1658
	foreach ($iflist as $ifent => $ifname) {
1659
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1660
			$ng_interfaces_needed++;
1661
		}
1662
	}
1663
	return $ng_interfaces_needed;
1664
}
1665

    
1666
function get_netgaph_interface_assignment($friendly_interface) {
1667
	global $config, $g;
1668
	/* build an array of interfaces to work with */
1669
	$iflist = array("wan" => "WAN");
1670
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1671
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1672
		$ng_interfaces_needed = 0;
1673
		$ng_interfaces_number = 0;
1674
		foreach ($iflist as $ifent => $ifname) {
1675
		if($config['interfaces'][$ifname]['ipaddr'] == "pppoe") {
1676
			$ng_interfaces_number++;
1677
		}
1678
		if($friendly_interface == $ifname)
1679
			break;
1680
	}
1681
	return $ng_interfaces_number;
1682
}
1683

    
1684
/****f* pfsense-utils/reload_all_sync
1685
 * NAME
1686
 *   reload_all - reload all settings
1687
 *   * INPUTS
1688
 *   none
1689
 * RESULT
1690
 *   none
1691
 ******/
1692
function reload_all_sync() {
1693
	global $config, $g;
1694

    
1695
	$g['booting'] = false;
1696

    
1697
	touch("{$g['tmp_path']}/reloading_all");
1698

    
1699
	$shutdown_webgui_needed = false;
1700

    
1701
	if(file_exists("{$g['tmp_path']}/config.cache"))
1702
		unlink("{$g['tmp_path']}/config.cache");
1703

    
1704
	/* parse config.xml again */
1705
	$config = parse_config(true);
1706

    
1707
	/* set up our timezone */
1708
	system_timezone_configure();
1709

    
1710
	/* set up our hostname */
1711
	system_hostname_configure();
1712

    
1713
	/* make hosts file */
1714
	system_hosts_generate();
1715

    
1716
	/* generate resolv.conf */
1717
	system_resolvconf_generate();
1718

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

    
1722
	$wan_if = $config['interfaces']['wan']['if'];
1723
	$lan_if = $config['interfaces']['lan']['if'];
1724

    
1725
	/* build an array of interfaces to work with */
1726
	$iflist = array("lan" => "LAN", "wan" => "WAN");
1727
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1728
		$iflist['opt' . $i] = "opt{$i}";
1729

    
1730
	foreach ($iflist as $ifent => $ifname) {
1731
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1732
		if(stristr($ifname, "lo0") == true)
1733
			continue;
1734
		/* do not process wan interface, its mandatory */
1735
		if($wan_if == $ifname_real)
1736
			continue;
1737
		/* do not process lan interface, its mandatory */
1738
		if($lan_if == $ifname_real)
1739
			continue;
1740
		mwexec("/sbin/ifconfig {$ifname_real} down");
1741
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1742
	}
1743

    
1744
	/* set up VLAN virtual interfaces */
1745
	interfaces_vlan_configure();
1746

    
1747
	/* set up LAN interface */
1748
	interfaces_lan_configure();
1749

    
1750
	/* set up WAN interface */
1751
	interfaces_wan_configure();
1752

    
1753
	/* set up Optional interfaces */
1754
	interfaces_optional_configure();
1755

    
1756
	/* bring up carp interfaces */
1757
	interfaces_carp_configure();
1758

    
1759
	/* set up static routes */
1760
	system_routing_configure();
1761

    
1762
	/* enable routing */
1763
	system_routing_enable();
1764

    
1765
	/* ensure passwords are sync'd */
1766
	system_password_configure();
1767

    
1768
	/* start dnsmasq service */
1769
	services_dnsmasq_configure();
1770

    
1771
	/* start dyndns service */
1772
	services_dyndns_configure();
1773

    
1774
	/* start DHCP service */
1775
	services_dhcpd_configure();
1776

    
1777
	/* start the NTP client */
1778
	system_ntp_configure();
1779

    
1780
	/* start ftp proxy helpers if they are enabled */
1781
	system_start_ftp_helpers();
1782

    
1783
	/* start the captive portal */
1784
	captiveportal_configure();
1785

    
1786
        /* reload the filter */
1787
	filter_configure_sync();
1788

    
1789
	/* bring up carp interfaces*/
1790
	interfaces_carp_bring_up_final();
1791

    
1792
	/* sync pw database */
1793
	conf_mount_rw();
1794
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1795
	conf_mount_ro();
1796

    
1797
	/* restart sshd */
1798
	touch("/tmp/start_sshd");
1799

    
1800
	/* restart webConfigurator if needed */
1801
	if($shutdown_webgui_needed == true)
1802
		touch("/tmp/restart_webgui");
1803

    
1804
	mwexec("/bin/rm /tmp/reload*");
1805

    
1806
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1807

    
1808
}
1809

    
1810
function auto_login($status) {
1811
	$gettytab = file_get_contents("/etc/gettytab");
1812
	$getty_split = split("\n", $gettytab);
1813
	conf_mount_rw();
1814
	$fd = fopen("/etc/gettytab", "w");
1815
	foreach($getty_split as $gs) {
1816
		if(stristr($gs, ":ht:np:sp#115200") ) {
1817
			if($status == true) {
1818
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
1819
			} else {
1820
				fwrite($fd, "	:ht:np:sp#115200:\n");
1821
			}
1822
		} else {
1823
			fwrite($fd, "{$gs}\n");
1824
		}
1825
	}
1826
	fclose($fd);
1827
	conf_mount_ro();
1828
}
1829

    
1830
function setup_serial_port() {
1831
	global $g, $config;
1832
	conf_mount_rw();
1833
	/* serial console - write out /boot.config */
1834
	if(file_exists("/boot.config"))
1835
		$boot_config = file_get_contents("/boot.config");
1836
	else
1837
		$boot_config = "";
1838

    
1839
	if($g['platform'] <> "cdrom") {
1840
		$boot_config_split = split("\n", $boot_config);
1841
		$fd = fopen("/boot.config","w");
1842
		if($fd) {
1843
			foreach($boot_config_split as $bcs) {
1844
				if(stristr($bcs, "-D")) {
1845
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1846
				} else {
1847
					if($bcs <> "")
1848
						fwrite($fd, "{$bcs}\n");
1849
				}
1850
			}
1851
			if(isset($config['system']['enableserial'])) {
1852
				fwrite($fd, "-D");
1853
			}
1854
			fclose($fd);
1855
		}
1856
		/* serial console - write out /boot/loader.conf */
1857
		$boot_config = file_get_contents("/boot/loader.conf");
1858
		$boot_config_split = split("\n", $boot_config);
1859
		$fd = fopen("/boot/loader.conf","w");
1860
		if($fd) {
1861
			foreach($boot_config_split as $bcs) {
1862
				if(stristr($bcs, "console")) {
1863
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1864
				} else {
1865
					if($bcs <> "")
1866
						fwrite($fd, "{$bcs}\n");
1867
				}
1868
			}
1869
			if(isset($config['system']['enableserial'])) {
1870
				fwrite($fd, "console=\"comconsole\"\n");
1871
			}
1872
			fclose($fd);
1873
		}
1874
	}
1875
	$ttys = file_get_contents("/etc/ttys");
1876
	$ttys_split = split("\n", $ttys);
1877
	$fd = fopen("/etc/ttys", "w");
1878
	foreach($ttys_split as $tty) {
1879
		if(stristr($tty, "ttyd0")) {
1880
			if(isset($config['system']['enableserial'])) {
1881
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
1882
			} else {
1883
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
1884
			}
1885
		} else {
1886
			fwrite($fd, $tty . "\n");
1887
		}
1888
	}
1889
	fclose($fd);
1890
	if(isset($config['system']['disableconsolemenu'])) {
1891
		auto_login(false);
1892
	} else {
1893
		auto_login(true);
1894
	}
1895
	conf_mount_ro();
1896
	return;
1897
}
1898

    
1899
function print_value_list($list, $count = 10, $separator = ",") {
1900
	$list = implode($separator, array_slice($list, 0, $count));
1901
	if(count($list) < $count) {
1902
		$list .= ".";
1903
	} else {
1904
		$list .= "...";
1905
	}
1906
	return $list;
1907
}
1908

    
1909
function convert_friendly_interface_to_friendly_descr($interface) {
1910
	global $config;
1911
	/* attempt to resolve interface to friendly descr */
1912
	if($config['interfaces'][$interface]['descr'])
1913
		return $config['interfaces'][$interface]['descr'];
1914
	$tmp = convert_real_interface_to_friendly_descr($interface);
1915
	/* could not resolve, return back what was passed */
1916
	return $interface;
1917
}
1918

    
1919
function convert_real_interface_to_friendly_descr($interface) {
1920
	global $config;
1921
	if($interface == $config['interfaces']['wan']['if'])
1922
		return "wan";
1923
	if($interface == $config['interfaces']['lan']['if'])
1924
		return "lan";
1925
	/* attempt to resolve interface to friendly descr */
1926
	$friendly_int = convert_real_interface_to_friendly_interface_name($interface);
1927
	if($config['interfaces'][$friendly_int]['descr'])
1928
		return $config['interfaces'][$friendly_int]['descr'];
1929
	/* could not resolve, return back what was passed */
1930
	return $interface;
1931
}
1932

    
1933
function enable_rrd_graphing()
1934
{
1935
// consider syncing the rrd files to usb storage/xml (cdrom, embbedded)
1936

    
1937
	global $config, $g;
1938

    
1939
    $rrddbpath = "/var/db/rrd/";
1940
    $rrdgraphpath = "/usr/local/www/rrd";
1941
	$rrdtrafficinterval = 60;
1942
	$rrdqualityinterval = 60;
1943
	$rrdqueuesinterval = 60;
1944
	$rrdpacketsinterval = 60;
1945
	$rrdspamdinterval = 60;
1946

    
1947
	$traffic = "-traffic.rrd";
1948
	$packets = "-packets.rrd";
1949
	$quality = "-quality.rrd";
1950
	$queues = "-queues.rrd";
1951
	$spamd = "spamd.rrd";
1952
	$rrdtool = "/usr/local/bin/rrdtool";
1953
	$netstat = "/usr/bin/netstat";
1954
	$awk = "/usr/bin/awk";
1955
	$tar = "/usr/bin/tar";
1956
	$php = "/usr/local/bin/php";
1957
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
1958

    
1959
	$gatewayip = exec("/sbin/route -n get default | /usr/bin/grep gateway | /usr/bin/awk '{print $2}'");
1960
	/* if an alternative gateway is defined, use it. */
1961
	if($config['system']['use_rrd_gateway'])
1962
		$gatewayip = $config['system']['use_rrd_gateway'];
1963
	$numpings = 5;
1964
	$btick = '`';
1965

    
1966
	$trafficvalid = $rrdtrafficinterval*2 ;
1967
	$qualityvalid = $rrdqualityinterval*2 ;
1968
	$queuesvalid = $rrdqueuesinterval*2 ;
1969
	$packetsvalid = $rrdpacketsinterval*2 ;
1970
	$spamdvalid = $rrdspamdinterval*2 ;
1971

    
1972
	/* Asume GigE for now */
1973
	$downstream = 125000000;
1974
	$upstream   = 125000000;
1975

    
1976
	$rrdrestore = "";
1977
	$rrdreturn = "";
1978

    
1979
	$config['rrd']['enable'] = true;
1980

    
1981
	if (isset($config['rrd']['enable'])) {
1982

    
1983
		/* create directory if needed */
1984
		if(!is_dir("$rrddbpath")) {
1985
			mkdir("$rrddbpath", 0755);
1986
		}
1987

    
1988
		if($g['booting']) {
1989
			/* if we are on livecd or embedded use a memoryfs. */
1990
			/* 6MB is enough for everyone. *cough* */
1991
			if($g['platform'] != "pfSense") {
1992
				/* determine highest MD device */
1993
				$mdnr = `mount |grep md | awk -F"md" '{print $2}'|tail -1 |cut -c 1`;
1994
				$mdnr = $mdnr +1;
1995
				system("/sbin/mdmfs -M -s 6m md$mdnr $rrddbpath");
1996

    
1997
				/* we now have something to write "on", restore the databases if we have them */
1998
				if(file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
1999
					exec("cd /;/usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
2000
					if((int)$rrdrestore <> 0) {
2001
						log_error("RRD restore failed exited with $rrdreturn, the
2002
							error is: $rrdrestore[0]\n");
2003
					}
2004
				}
2005
			}
2006

    
2007
		}
2008

    
2009
		/* db update script */
2010
		$rrdupdatesh = "#!/bin/sh\n";
2011
		$rrdupdatesh .= "\n";
2012
		$rrdupdatesh .= "counter=1\n";
2013
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
2014
		$rrdupdatesh .= "do\n";
2015
		$rrdupdatesh .= "";
2016

    
2017
		/* directory index */
2018
		$rrdgraphindexhtml = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">
2019
<HTML>
2020
<HEAD>
2021
    <TITLE>MRTG Index Page</TITLE>
2022
    <META HTTP-EQUIV=\"Refresh\" CONTENT=\"360\">
2023
    <META HTTP-EQUIV=\"Cache-Control\" content=\"no-cache\">
2024
    <META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">
2025
    <META HTTP-EQUIV=\"Expires\" CONTENT=\"Tue, 22 May 2001 09:22:45 GMT\">
2026
</HEAD>
2027
<BODY bgcolor=\"#ffffff\" text=\"#000000\" link=\"#000000\" vlink=\"#000000\" alink=\"#000000\">
2028
<H1>MRTG Index Page</H1>
2029
<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=10>";
2030

    
2031
       		$i = 0;
2032
                $vfaces = array("vlan.?*");
2033
                $ifdescrs = get_interface_list(true, true, $vfaces);
2034
       		foreach ($ifdescrs as $realif => $ifdescr) {
2035
			$ifname = $ifdescr['friendly'];
2036
			$state = $ifdescr['up'];
2037

    
2038
			/* skip interfaces that do not have a friendly name */
2039
			if("$ifname" == "") {
2040
				continue;
2041
			}
2042

    
2043
			/* or are down */
2044
			if(! $state) {
2045
				continue;
2046
			}
2047

    
2048
			/* set up the rrd file */
2049
			if(! file_exists("$rrddbpath$ifname$traffic")) {
2050
				/* create rrd file if it does not exist */
2051
				log_error("Create RRD database $rrddbpath$ifname$traffic");
2052
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval \
2053
					DS:in:COUNTER:$trafficvalid:0:$downstream \
2054
					DS:out:COUNTER:$trafficvalid:0:$upstream \
2055
					RRA:AVERAGE:0.5:1:1000 \
2056
					RRA:AVERAGE:0.5:5:1000 \
2057
					RRA:AVERAGE:0.5:60:1000 \
2058
					RRA:AVERAGE:0.5:360:1000 \
2059
					RRA:MAX:0.5:1:1000 \
2060
					RRA:MAX:0.5:5:1000 \
2061
					RRA:MAX:0.5:60:1000 \
2062
					RRA:MAX:0.5:3600:1000";
2063

    
2064
				$rrdcreateoutput = array();
2065
				$rrdcreatereturn = "";
2066

    
2067
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2068
				if($rrdcreatereturn != 0) {
2069
			                log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2070
				}
2071
			}
2072

    
2073
			if($g['booting']) {
2074
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U");
2075
			}
2076

    
2077
			$rrdupdatesh .= "\n";
2078
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
2079
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
2080
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$7}'`:\\\n";
2081
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$10}'`\n\n";
2082

    
2083
			/* set up the rrd file */
2084
			if(! file_exists("$rrddbpath$ifname$packets")) {
2085
				/* create rrd file if it does not exist */
2086
				log_error("Create RRD database $rrddbpath$ifname$packets");
2087
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval \
2088
					DS:in:COUNTER:$packetsvalid:0:$downstream \
2089
					DS:out:COUNTER:$packetsvalid:0:$upstream \
2090
					RRA:AVERAGE:0.5:1:1000 \
2091
					RRA:AVERAGE:0.5:5:1000 \
2092
					RRA:AVERAGE:0.5:60:1000 \
2093
					RRA:AVERAGE:0.5:360:1000 \
2094
					RRA:MAX:0.5:1:1000 \
2095
					RRA:MAX:0.5:5:1000 \
2096
					RRA:MAX:0.5:60:1000 \
2097
					RRA:MAX:0.5:360:1000";
2098

    
2099
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2100
				if($rrdcreatereturn != 0) {
2101
			                log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput[0]\n");
2102
				}
2103
			}
2104

    
2105
			if($g['booting']) {
2106
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U");
2107
			}
2108

    
2109
			$rrdupdatesh .= "\n";
2110
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
2111
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
2112
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$5}'`:\\\n";
2113
			$rrdupdatesh .= "`$netstat -nbf link -I {$realif} | $awk '{getline 2;print \$8}'`\n\n";
2114

    
2115
			$rrdgraphindexhtml .= "<TR>
2116
<TD><DIV><B>Traffic Analysis for $ifname -- day</B></DIV>
2117
<DIV><IMG BORDER=1 ALT=\"$ifname Traffic Graph\" SRC=\"$ifname-day.png\">
2118
<BR>
2119
</TD>
2120
<TD><DIV><B>Traffic Analysis for $ifname -- week</B></DIV>
2121
<DIV><IMG BORDER=1 ALT=\"$ifname Traffic Graph\" SRC=\"$ifname-week.png\">
2122
<BR>
2123
</TD>
2124
</TR>";
2125

    
2126
			if("$ifname" == "wan") {
2127
				/* create link quality database */
2128
				if(! file_exists("$rrddbpath$ifname$quality")) {
2129
					/* create rrd file if it does not exist */
2130
					log_error("Create RRD database $rrddbpath$ifname$quality");
2131
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$quality --step $rrdqualityinterval \
2132
							DS:loss:GAUGE:$qualityvalid:0:100 \
2133
							DS:roundtrip:GAUGE:$qualityvalid:0:10000 \
2134
							RRA:AVERAGE:0.5:1:1000 \
2135
							RRA:AVERAGE:0.5:5:1000 \
2136
							RRA:AVERAGE:0.5:60:1000 \
2137
							RRA:AVERAGE:0.5:360:1000";
2138

    
2139
					$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2140
					if($rrdcreatereturn != 0) {
2141
				                log_error("RRD create failed exited with $rrdcreatereturn, the
2142
							error is: $rrdcreateoutput[0]\n");
2143
					}
2144
				}
2145

    
2146
				/* the ping test function. We call this on the last line */
2147
				$rrdupdatesh .= "get_ping_stats () {
2148
					packetloss=100
2149
					roundtrip=0
2150
					local out
2151
					out=$btick ping -c $numpings -q $gatewayip $btick
2152
					if [ $? -eq 0 ]; then
2153
						packetloss=$btick echo \$out | cut -f18 -d' ' | cut -c -1 $btick
2154
						roundtrip=$btick echo \$out | cut -f24 -d' ' | cut -f2 -d'/' $btick
2155
					fi
2156
					$rrdtool update $rrddbpath$ifname$quality N:\$packetloss:\$roundtrip
2157
				}\n\n";
2158

    
2159
				$rrdupdatesh .= "get_ping_stats &\n\n";
2160

    
2161
				if (!is_array($config['shaper']['queue'])) {
2162
					$config['shaper']['queue'] = array();
2163
				}
2164
				$a_queues = &$config['shaper']['queue'];
2165

    
2166
				if(isset($config['shaper']['enable'])) {
2167
					if(!file_exists("$rrddbpath$ifname$queues")) {
2168
						/* create rrd file if it does not exist */
2169
						log_error("Create RRD database $rrddbpath$ifname$queues");
2170
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval \\\n";
2171
						/* loop list of shaper queues */
2172
						$q = 0;
2173
						 foreach ($a_queues as $queue) {
2174
							$name = $queue['name'];
2175
							$rrdcreate .= "DS:$name:COUNTER:$queuesvalid:0:$downstream \\\n";
2176
						}
2177

    
2178
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 \
2179
							RRA:AVERAGE:0.5:5:1000 \
2180
							RRA:AVERAGE:0.5:60:1000 \
2181
							RRA:AVERAGE:0.5:360:1000";
2182

    
2183
						$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2184
						if($rrdcreatereturn != 0) {
2185
				        	        log_error("RRD create failed exited with $rrdcreatereturn, the
2186
								error is: $rrdcreateoutput[0]\n");
2187
						}
2188
					}
2189

    
2190
					if($g['booting']) {
2191
						$rrducommand = "$rrdtool update $rrddbpath$ifname$queues N";
2192
						foreach ($a_queues as $queue) {
2193
							$rrducommand .= ":U";
2194
						}
2195
						exec("$rrducommand");
2196
					}
2197

    
2198
				/* awk function to gather shaper data */
2199
				/* yes, it's special */
2200
				$rrdupdatesh .= "` pfctl -vsq | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } \\
2201
					{ \
2202
					if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { \\
2203
					        dsname = dsname \":\" \$2 ; \\
2204
					        q=1; \\
2205
					} \\
2206
					else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { \\
2207
					        dsdata = dsdata \":\" \$5 ; \\
2208
					        q=0; \\
2209
					} \\
2210
					} END { \\
2211
						dsname = substr(dsname,2); \\
2212
						dsdata = substr(dsdata,2); \\
2213
						printf \"-t \" dsname \" N:\" dsdata }' \\
2214
						dsname=\"\" dsdata=\"\"`\n\n";
2215
				}
2216
			}
2217

    
2218
	        }
2219
       		$i++;
2220

    
2221
		$rrdgraphindexhtml .= "</TABLE>
2222
</BODY>
2223
</HTML>";
2224

    
2225
		if(isset($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
2226
			/* set up the spamd rrd file */
2227
			if(! file_exists("$rrddbpath$spamd")) {
2228
				/* create rrd file if it does not exist */
2229
				log_error("Create RRD database $rrddbpath$spamd");
2230
				$rrdcreate = "$rrdtool create $rrddbpath$spamd --step $rrdspamdinterval \
2231
					DS:conn:GAUGE:$trafficvalid:0:10000 \
2232
					DS:time:GAUGE:$trafficvalid:0:86400 \
2233
					RRA:MIN:0.5:1:1000 \
2234
					RRA:MIN:0.5:5:1000 \
2235
					RRA:MIN:0.5:60:1000 \
2236
					RRA:MIN:0.5:360:1000 \
2237
					RRA:AVERAGE:0.5:1:1000 \
2238
					RRA:AVERAGE:0.5:5:1000 \
2239
					RRA:AVERAGE:0.5:60:1000 \
2240
					RRA:AVERAGE:0.5:360:1000 \
2241
					RRA:MAX:0.5:1:1000 \
2242
					RRA:MAX:0.5:5:1000 \
2243
					RRA:MAX:0.5:60:1000 \
2244
					RRA:MAX:0.5:360:1000";
2245

    
2246
				$rrdcreatel = exec("$rrdcreate 2>&1", $rrdcreateoutput, $rrdcreatereturn);
2247
				if($rrdcreatereturn != 0) {
2248
		        	        log_error("RRD create failed exited with $rrdcreatereturn, the
2249
						error is: $rrdcreateoutput[0]\n");
2250
				}
2251
			}
2252

    
2253
			$rrdupdatesh .= "\n";
2254
			$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
2255
			$rrdupdatesh .= "$rrdtool update $rrddbpath$spamd \\\n";
2256
			$rrdupdatesh .= "`$php -q $spamd_gather`\n";
2257

    
2258
		}
2259

    
2260
		$rrdupdatesh .= "sleep 60\n";
2261
		$rrdupdatesh .= "done\n";
2262
		log_error("Creating rrd update script");
2263
		/* write the rrd update script */
2264
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
2265
		$fd = fopen("$updaterrdscript", "w");
2266
		fwrite($fd, "$rrdupdatesh");
2267
		fclose($fd);
2268

    
2269
		log_error("Creating rrd graph index");
2270
		/* write the index.html script */
2271
		$rrdgraphindex = "{$g['vardb_path']}/rrd/index.html";
2272
		$fd = fopen("$rrdgraphindex", "w");
2273
		fwrite($fd, "$rrdgraphindexhtml");
2274
		fclose($fd);
2275

    
2276
		/* kill off traffic collectors */
2277
		kill_traffic_collector();
2278

    
2279
		/* start traffic collector */
2280
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
2281

    
2282
	} else {
2283
		/* unmount and remove */
2284
		system("/sbin/umount $rrddbpath");
2285
		exec("/sbin/mdconfig -d -u 2");
2286
		/* kill off traffic collectors */
2287
		kill_traffic_collector();
2288
	}
2289
}
2290

    
2291
function kill_traffic_collector() {
2292
		mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
2293
}
2294

    
2295
function update_filter_reload_status($text) {
2296
	global $g;
2297
	config_lock();
2298
	$fd = fopen("{$g['varrun_path']}/filter_reload_status", "w");
2299
	fwrite($fd, $text);
2300
	fclose($fd);
2301
	config_unlock();
2302
}
2303

    
2304
function get_interface_gateway($interface) {
2305
	global $config, $g;
2306
	$interface = strtolower($interface);
2307
	/*  if we are dhclient, obtain the gateway from the tmp file, otherwise
2308
	 *  grab the address from the configuration file.
2309
	 */
2310
	$tmpif = convert_real_interface_to_friendly_interface_name($interface);
2311
	if($tmpif <> $interface)
2312
		$interface = $tmpif;
2313
	$realif = $config['interfaces'][$interface]['if'];
2314
	if(file_exists("{$g['tmp_path']}/{$realif}_router")) {
2315
		$gw = file_get_contents("{$g['tmp_path']}/{$realif}_router");
2316
		$gw = rtrim($gw);
2317
	} else {
2318
		$gw = $config['interfaces'][$interface]['gateway'];
2319
	}
2320
	/* if wan is requested, return it */
2321
	if($interface == "wan")
2322
		return str_replace("\n", "", `route -n get default | grep gateway | awk '{ print $2 }'`);
2323
	/* return gateway */
2324
	return $gw;
2325
}
2326

    
2327
function is_dhcp_server_enabled() {
2328
	/* DHCP enabled on any interfaces? */
2329
	global $config, $g;
2330
	$dhcpdcfg = $config['dhcpd'];
2331
	$dhcpdenable = false;
2332
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
2333
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "lan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2334
			$dhcpdenable = true;
2335
		if (isset ($dhcpifconf['enable']) && (($dhcpif == "wan") || (isset ($config['interfaces'][$dhcpif]['enable']) && $config['interfaces'][$dhcpif]['if'] && (!$config['interfaces'][$dhcpif]['bridge']))))
2336
			$dhcpdenable = true;
2337
	}
2338
	return $dhcpdenable;
2339
}
2340

    
2341
?>
(14-14/27)