Project

General

Profile

Download (36.2 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) 2005 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/get_dns_servers
41
 * NAME
42
 *   get_dns_servres - get system dns servers
43
 * INPUTS
44
 *   $dns_servers - an array of the dns servers
45
 * RESULT
46
 *   null
47
 ******/
48
function get_dns_servers() {
49
	$dns_servers = array();
50
	$dns = `cat /etc/resolv.conf`;
51
	$dns_s = split("\n", $dns);
52
	foreach($dns_s as $dns) {
53
		if (preg_match("/nameserver (.*)/", $dns, $matches))
54
			$dns_servers[] = $matches[1];		
55
	}
56
	return $dns_servers;
57
}
58

    
59
 	
60
/****f* pfsense-utils/log_error
61
* NAME
62
*   log_error  - Sends a string to syslog.
63
* INPUTS
64
*   $error     - string containing the syslog message.
65
* RESULT
66
*   null
67
******/
68
function log_error($error) {
69
    $page = $_SERVER['PHP_SELF'];
70
    syslog(LOG_WARNING, "$page: $error");
71
    return;
72
}
73

    
74
/****f* pfsense-utils/get_interface_mac_address
75
 * NAME
76
 *   get_interface_mac_address - Return a interfaces mac address
77
 * INPUTS
78
 *   $interface	- interface to obtain mac address from
79
 * RESULT
80
 *   $mac - the mac address of the interface
81
 ******/
82
function get_interface_mac_address($interface) {
83
    $mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
84
    return trim($mac);
85
}
86

    
87
/****f* pfsense-utils/return_dir_as_array
88
 * NAME
89
 *   return_dir_as_array - Return a directory's contents as an array.
90
 * INPUTS
91
 *   $dir	- string containing the path to the desired directory.
92
 * RESULT
93
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
94
 ******/
95
function return_dir_as_array($dir) {
96
    $dir_array = array();
97
    if (is_dir($dir)) {
98
	if ($dh = opendir($dir)) {
99
	    while (($file = readdir($dh)) !== false) {
100
		$canadd = 0;
101
		if($file == ".") $canadd = 1;
102
		if($file == "..") $canadd = 1;
103
		if($canadd == 0)
104
		    array_push($dir_array, $file);
105
	    }
106
	    closedir($dh);
107
	}
108
    }
109
    return $dir_array;
110
}
111

    
112
/****f* pfsense-utils/enable_hardware_offloading
113
 * NAME
114
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
115
 * INPUTS
116
 *   $interface	- string containing the physical interface to work on.
117
 * RESULT
118
 *   null
119
 * NOTES
120
 *   This function only supports the fxp driver's loadable microcode.
121
 ******/
122
function enable_hardware_offloading($interface) {
123
    global $g;
124
    if($g['booting']) {
125
	/* translate wan, lan, opt -> real interface if needed */
126
	$int = filter_translate_type_to_real_interface($interface);
127
	if($int <> "") $interface = $int;
128
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
129
	$supported_ints = array('fxp');
130
	foreach($supported_ints as $int) {
131
		if(stristr($interface,$int) != false) {
132
			mwexec("/sbin/ifconfig {$interface} link0");
133
		}
134
	}
135
	if(stristr($options, "txcsum") == true)
136
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
137
	if(stristr($options, "rxcsum") == true)    
138
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");    
139
	if(stristr($options, "polling") == true)
140
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
141
    }
142
    return;
143
}
144

    
145
/****f* pfsense-utils/setup_microcode
146
 * NAME
147
 *   enumerates all interfaces and calls enable_hardware_offloading which
148
 *   enables a NIC's supported hardware features.
149
 * INPUTS
150
 *   
151
 * RESULT
152
 *   null
153
 * NOTES
154
 *   This function only supports the fxp driver's loadable microcode.
155
 ******/
156
function setup_microcode() {
157
   global $config;
158
    $ifdescrs = array('wan', 'lan');
159
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
160
	$ifdescrs['opt' . $j] = "opt" . $j;
161
    }
162
    foreach($ifdescrs as $if)
163
	enable_hardware_offloading($if);
164
}
165

    
166
/****f* pfsense-utils/return_filename_as_array
167
 * NAME
168
 *   return_filename_as_array - Return a file's contents as an array.
169
 * INPUTS
170
 *   $filename	- string containing the path to the desired file.
171
 *   $strip	- array of characters to strip - default is '#'.
172
 * RESULT
173
 *   $file	- array containing the file's contents.
174
 * NOTES
175
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
176
 ******/
177
function return_filename_as_array($filename, $strip = array('#')) {
178
    if(file_exists($filename)) $file = file($filename);
179
    if(is_array($file)) {
180
	foreach($file as $line) $line = trim($line);
181
        foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
182
    }
183
    return $file;
184
}
185

    
186
/****f* pfsense-utils/file_put_contents
187
 * NAME
188
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
189
 * RESULT
190
 *   none
191
 ******/
192
if(!function_exists("file_put_contents")) {
193
    function file_put_contents($filename, $data) {
194
	$fd = fopen($filename,"w");
195
	fwrite($fd, $data);
196
	fclose($fd);
197
    }
198
}
199

    
200
/****f* pfsense-utils/get_carp_status
201
 * NAME
202
 *   get_carp_status - Return whether CARP is enabled or disabled.
203
 * RESULT
204
 *   boolean	- true if CARP is enabled, false if otherwise.
205
 ******/
206
function get_carp_status() {
207
    /* grab the current status of carp */
208
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
209
    if(intval($status) == "0") return false;
210
    return true;
211
}
212

    
213
/****f* pfsense-utils/is_carp_defined
214
 * NAME
215
 *   is_carp_defined - Return whether CARP is detected in the kernel.
216
 * RESULT
217
 *   boolean	- true if CARP is detected, false otherwise.
218
 ******/
219
function is_carp_defined() {
220
    /* is carp compiled into the kernel and userland? */
221
    $command = "/sbin/sysctl -a | grep carp";
222
    $fd = popen($command . " 2>&1 ", "r");
223
    if(!$fd) {
224
	log_error("Warning, could not execute command {$command}");
225
	return 0;
226
    }
227
    while(!feof($fd)) {
228
	$tmp .= fread($fd,49);
229
    }
230
    fclose($fd);
231

    
232
    if($tmp == "")
233
	return false;
234
    else
235
	return true;
236
}
237

    
238
/****f* pfsense-utils/find_number_of_created_carp_interfaces
239
 * NAME
240
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
241
 * RESULT
242
 *   $tmp	- Number of currently created CARP interfaces.
243
 ******/
244
function find_number_of_created_carp_interfaces() {
245
    $command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
246
    $fd = popen($command . " 2>&1 ", "r");
247
    if(!$fd) {
248
	log_error("Warning, could not execute command {$command}");
249
	return 0;
250
    }
251
    while(!feof($fd)) {
252
	$tmp .= fread($fd,49);
253
    }
254
    fclose($fd);
255
    $tmp = intval($tmp);
256
    return $tmp;
257
}
258

    
259
/****f* pfsense-utils/link_ip_to_carp_interface
260
 * NAME
261
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
262
 * INPUTS
263
 *   $ip
264
 * RESULT
265
 *   $carp_ints
266
 ******/
267
function link_ip_to_carp_interface($ip) {
268
	global $config;
269
	if($ip == "") return;
270

    
271
	$ifdescrs = array('wan', 'lan');
272
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
273
		$ifdescrs['opt' . $j] = "opt" . $j;
274
	}
275

    
276
	$ft = split("\.", $ip);
277
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
278

    
279
	$carp_ints = "";
280
	$num_carp_ints = find_number_of_created_carp_interfaces();
281
	foreach ($ifdescrs as $ifdescr => $ifname) {
282
		for($x=0; $x<$num_carp_ints; $x++) {
283
			$carp_int = "carp{$x}";
284
			$carp_ip = find_interface_ip($carp_int);
285
			$carp_ft = split("\.", $carp_ip);
286
			$carp_ft_ip = $carp_ft[0] . "." . $carp_ft[1] . "." . $carp_ft[2] . ".";
287
			$result = does_interface_exist($carp_int);
288
			if($result <> true) break;
289
			if($ft_ip == $carp_ft_ip)
290
			if(stristr($carp_ints,$carp_int) == false)
291
			$carp_ints .= " " . $carp_int;
292
		}
293
	}
294
	return $carp_ints;
295
}
296

    
297
/****f* pfsense-utils/exec_command
298
 * NAME
299
 *   exec_command - Execute a command and return a string of the result.
300
 * INPUTS
301
 *   $command	- String of the command to be executed.
302
 * RESULT
303
 *   String containing the command's result.
304
 * NOTES
305
 *   This function returns the command's stdout and stderr.
306
 ******/
307
function exec_command($command) {
308
    $output = array();
309
    exec($command . ' 2>&1 ', $output);
310
    return(implode("\n", $output));
311
}
312

    
313
/****f* interfaces/is_jumbo_capable
314
 * NAME
315
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
316
 * INPUTS
317
 *   $int             - string containing interface name
318
 * RESULT
319
 *   boolean          - true or false
320
 ******/
321
function is_jumbo_capable($int) {
322
	/* Per:
323
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-current&format=html
324
	 * Only the following drivers support large frames
325
	 */
326
	$capable = array("bfe", "dc", "de", "fxp", "hme", "rl", "sis", "ste",
327
		"tl", "tx", "xl", "em");
328
	
329
	$int_family = preg_split("/[0-9]+/", $int);
330

    
331
	if (in_array($int_family[0], $capable))
332
		return true;
333
	else
334
		return false;
335
}
336

    
337
/*
338
 * does_interface_exist($interface): return true or false if a interface is detected.
339
 */
340
function does_interface_exist($interface) {
341
    $ints = exec_command("/sbin/ifconfig -l");
342
    if(stristr($ints, $interface) !== false)
343
	return true;
344
    else
345
	return false;
346
}
347

    
348
/*
349
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
350
 */
351
function convert_ip_to_network_format($ip, $subnet) {
352
    $ipsplit = split('[.]', $ip);
353
    $string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
354
    return $string;
355
}
356

    
357
/*
358
 * find_interface_ip($interface): return the interface ip (first found)
359
 */
360
function find_interface_ip($interface) {
361
    if(does_interface_exist($interface) == false) return;
362
    $ip = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2");
363
    $ip = str_replace("\n","",$ip);
364
    return $ip;
365
}
366

    
367
function guess_interface_from_ip($ipaddress) {
368
    $ints = `/sbin/ifconfig -l`;
369
    $ints_split = split(" ", $ints);
370
    $ip_subnet_split = split("\.", $ipaddress);
371
    $ip_subnet = $ip_subnet_split[0] . "." . $ip_subnet_split[1] . "." . $ip_subnet_split[2] . ".";
372
    foreach($ints_split as $int) {
373
        $ip = find_interface_ip($int);
374
        $ip_split = split("\.", $ip);
375
        $ip_tocheck = $ip_split[0] . "." . $ip_split[1] . "." . $ip_split[2] . ".";
376
        if(stristr($ip_tocheck, $ip_subnet) != false) return $int;
377
    }
378
}
379

    
380
function filter_opt_interface_to_real($opt) {
381
    global $config;
382
    return $config['interfaces'][$opt]['if'];
383
}
384

    
385
function filter_get_opt_interface_descr($opt) {
386
    global $config;
387
    return $config['interfaces'][$opt]['descr'];
388
}
389

    
390
function get_friendly_interface_list_as_array() {
391
    global $config;
392
    $ints = array();
393
    $ifdescrs = array('wan', 'lan');
394
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
395
		$ifdescrs['opt' . $j] = "opt" . $j;
396
    }
397
    $ifdescrs = get_interface_list();
398
    foreach ($ifdescrs as $ifdescr => $ifname) {
399
		array_push($ints,$ifdescr);
400
    }
401
    return $ints;
402
}
403

    
404
/*
405
 * find_ip_interface($ip): return the interface where an ip is defined
406
 */
407
function find_ip_interface($ip) {
408
    global $config;
409
    $ifdescrs = array('wan', 'lan');
410
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
411
	$ifdescrs['opt' . $j] = "opt" . $j;
412
    }
413
    foreach ($ifdescrs as $ifdescr => $ifname) {
414
	$int = filter_translate_type_to_real_interface($ifname);
415
	$ifconfig = exec_command("/sbin/ifconfig {$int}");
416
	if(stristr($ifconfig,$ip) <> false)
417
	    return $int;
418
    }
419
    return false;
420
}
421

    
422
/*
423
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
424
 *                                                       for a friendly interface.  ie: wan
425
 */
426
function filter_translate_type_to_real_interface($interface) {
427
    global $config;
428
    return $config['interfaces'][$interface]['if'];
429
}
430

    
431
/*
432
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
433
 */
434
function get_carp_interface_status($carpinterface) {
435
	/* basically cache the contents of ifconfig statement
436
	to speed up this routine */
437
	global $carp_query;
438
	if($carp_query == "")
439
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
440
	$found_interface = 0;
441
	foreach($carp_query as $int) {
442
		if($found_interface == 1) {
443
			if(stristr($int, "MASTER") == true) return "MASTER";
444
			if(stristr($int, "BACKUP") == true) return "BACKUP";
445
			if(stristr($int, "INIT") == true) return "INIT";
446
			return false;
447
		}
448
		if(stristr($int, $carpinterface) == true)
449
		$found_interface=1;
450
	}
451
	return;
452
}
453

    
454
/*
455
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
456
 */
457
function get_pfsync_interface_status($pfsyncinterface) {
458
    $result = does_interface_exist($pfsyncinterface);
459
    if($result <> true) return;
460
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
461
    return $status;
462
}
463

    
464
/*
465
 * find_carp_interface($ip): return the carp interface where an ip is defined
466
 */
467
function find_carp_interface($ip) {
468
    global $find_carp_ifconfig;
469
    if($find_carp_ifconfig == "") {
470
	$find_carp_ifconfig = array();
471
	$num_carp_ints = find_number_of_created_carp_interfaces();
472
	for($x=0; $x<$num_carp_ints; $x++) {
473
	    $find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
474
	}
475
    }
476
    $carps = 0;
477
    foreach($find_carp_ifconfig as $fci) {
478
	if(stristr($fci, $ip) == true)
479
	    return "carp{$carps}";
480
	$carps++;
481
    }
482
}
483

    
484
/*
485
 * find_number_of_created_bridges(): returns the number of currently created bridges
486
 */
487
function find_number_of_created_bridges() {
488
    return `/sbin/ifconfig | grep \"bridge[0-999]\:" | wc -l`;
489
}
490

    
491
/*
492
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
493
 */
494
function add_rule_to_anchor($anchor, $rule, $label) {
495
    mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
496
}
497

    
498
/*
499
 * remove_text_from_file
500
 * remove $text from file $file
501
 */
502
function remove_text_from_file($file, $text) {
503
    global $fd_log;
504
    fwrite($fd_log, "Adding needed text items:\n");
505
    $filecontents = exec_command_and_return_text("cat " . $file);
506
    $textTMP = str_replace($text, "", $filecontents);
507
    $text .= $textTMP;
508
    fwrite($fd_log, $text . "\n");
509
    $fd = fopen($file, "w");
510
    fwrite($fd, $text);
511
    fclose($fd);
512
}
513

    
514
/*
515
 * add_text_to_file($file, $text): adds $text to $file.
516
 * replaces the text if it already exists.
517
 */
518
function add_text_to_file($file, $text) {
519
	if(file_exists($file) and is_writable($file)) {
520
		$filecontents = file($file);
521
		$filecontents[] = $text;
522
		$tmpfile = get_tmp_file();
523
		$fout = fopen($tmpfile, "w");
524
		foreach($filecontents as $line) {
525
			fwrite($fout, rtrim($line) . "\n");
526
		}
527
		fclose($fout);
528
		rename($tmpfile, $file);
529
		return true;
530
	} else {
531
		return false;
532
	}
533
}
534

    
535
/*
536
 *   after_sync_bump_adv_skew(): create skew values by 1S
537
 */
538
function after_sync_bump_adv_skew() {
539
	global $config, $g;
540
	$processed_skew = 1;
541
	$a_vip = &$config['virtualip']['vip'];
542
	foreach ($a_vip as $vipent) {
543
		if($vipent['advskew'] <> "") {
544
			$processed_skew = 1;
545
			$vipent['advskew'] = $vipent['advskew']+1;
546
		}
547
	}
548
	if($processed_skew == 1)
549
		write_config("After synch increase advertising skew");
550
}
551

    
552
/*
553
 * get_filename_from_url($url): converts a url to its filename.
554
 */
555
function get_filename_from_url($url) {
556
	return basename($url);
557
}
558

    
559
/*
560
 *   update_output_window: update bottom textarea dynamically.
561
 */
562
function update_output_window($text) {
563
    $log = ereg_replace("\n", "\\n", $text);
564
    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
565
}
566

    
567
/*
568
 *   get_dir: return an array of $dir
569
 */
570
function get_dir($dir) {
571
    $dir_array = array();
572
    $d = dir($dir);
573
    while (false !== ($entry = $d->read())) {
574
	array_push($dir_array, $entry);
575
    }
576
    $d->close();
577
    return $dir_array;
578
}
579

    
580
/*
581
 *   update_output_window: update top textarea dynamically.
582
 */
583
function update_status($status) {
584
    echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
585
}
586

    
587
/*
588
 *   exec_command_and_return_text_array: execute command and return output
589
 */
590
function exec_command_and_return_text_array($command) {
591
	$fd = popen($command . " 2>&1 ", "r");
592
	while(!feof($fd)) {
593
		$tmp .= fread($fd,49);
594
	}
595
	fclose($fd);
596
	$temp_array = split("\n", $tmp);
597
	return $temp_array;
598
}
599

    
600
/*
601
 *   exec_command_and_return_text: execute command and return output
602
 */
603
function exec_command_and_return_text($command) {
604
    return exec_command($command);
605
}
606

    
607
/*
608
 *   exec_command_and_return_text: execute command and update output window dynamically
609
 */
610
function execute_command_return_output($command) {
611
    global $fd_log;
612
    $fd = popen($command . " 2>&1 ", "r");
613
    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
614
    $counter = 0;
615
    $counter2 = 0;
616
    while(!feof($fd)) {
617
	$tmp = fread($fd, 50);
618
	$tmp1 = ereg_replace("\n","\\n", $tmp);
619
	$text = ereg_replace("\"","'", $tmp1);
620
	if($lasttext == "..") {
621
	    $text = "";
622
	    $lasttext = "";
623
	    $counter=$counter-2;
624
	} else {
625
	    $lasttext .= $text;
626
	}
627
	if($counter > 51) {
628
	    $counter = 0;
629
	    $extrabreak = "\\n";
630
	} else {
631
	    $extrabreak = "";
632
	    $counter++;
633
	}
634
	if($counter2 > 600) {
635
	    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
636
	    $counter2 = 0;
637
	} else
638
	    $counter2++;
639
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
640
    }
641
    fclose($fd);
642
}
643

    
644
/*
645
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
646
 */
647
function convert_friendly_interface_to_real_interface_name($interface) {
648
    global $config;
649
    $lc_interface = strtolower($interface);
650
    if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
651
    if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
652
    $ifdescrs = array();
653
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
654
	$ifdescrs['opt' . $j] = "opt" . $j;
655
    foreach ($ifdescrs as $ifdescr => $ifname) {
656
	if(strtolower($ifname) == $lc_interface)
657
	    return $config['interfaces'][$ifname]['if'];
658
	if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
659
	    return $config['interfaces'][$ifname]['if'];
660
    }
661
    return $interface;
662
}
663

    
664
/*
665
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
666
 */
667
function convert_real_interface_to_friendly_interface_name($interface) {
668
    global $config;
669
    $ifdescrs = array('wan', 'lan');
670
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
671
	$ifdescrs['opt' . $j] = "opt" . $j;
672
    foreach ($ifdescrs as $ifdescr => $ifname) {
673
	$int = filter_translate_type_to_real_interface($ifname);
674
	if($ifname == $interface) return $ifname;
675
	if($int == $interface) return $ifname;
676
    }
677
    return $interface;
678
}
679

    
680
/*
681
 * update_progress_bar($percent): updates the javascript driven progress bar.
682
 */
683
function update_progress_bar($percent) {
684
    if($percent > 100) $percent = 1;
685
    echo "\n<script type=\"text/javascript\" language=\"javascript\">";
686
    echo "\ndocument.progressbar.style.width='" . $percent . "%';";
687
    echo "\n</script>";
688
}
689

    
690
/*
691
 * gather_altq_queue_stats():  gather alq queue stats and return an array that
692
 *                             is queuename|qlength|measured_packets
693
 *                             NOTE: this command takes 5 seconds to run
694
 */
695
function gather_altq_queue_stats($dont_return_root_queues) {
696
    mwexec("/usr/bin/killall -9 pfctl");
697
    $stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
698
    $stats_array = split("\n", $stats);
699
    $queue_stats = array();
700
    foreach ($stats_array as $stats_line) {
701
        if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
702
            $queue_name = $match_array[1][0];
703
        if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
704
            $speed = $match_array[1][0];
705
        if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
706
            $borrows = $match_array[1][0];
707
        if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
708
            $suspends = $match_array[1][0];
709
        if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
710
            $drops = $match_array[1][0];
711
        if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
712
            $measured = $match_array[1][0];
713
	    if($dont_return_root_queues == true)
714
		if(stristr($queue_name,"root_") == false)
715
		    array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
716
        }
717
    }
718
    return $queue_stats;
719
}
720

    
721
/*
722
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
723
 *					 Useful for finding paths and stripping file extensions.
724
 */
725
function reverse_strrchr($haystack, $needle)
726
{
727
               return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
728
}
729

    
730
/*
731
 *  backup_config_section($section): returns as an xml file string of
732
 *                                   the configuration section
733
 */
734
function backup_config_section($section) {
735
    global $config;
736
    $new_section = &$config[$section];
737
    /* generate configuration XML */
738
    $xmlconfig = dump_xml_config($new_section, $section);
739
    $xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
740
    return $xmlconfig;
741
}
742

    
743
/*
744
 *  backup_config_ts_scheduler(): returns the traffic shaper scheduler for backup
745
 */
746
function backup_config_ts_scheduler() {
747
    global $config;
748
    $new_section = &$config['syste']['schedulertype'];
749
    /* generate configuration XML */
750
    $xmlconfig = dump_xml_config($new_section, $section);
751
    $xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
752
    return $xmlconfig;
753
}
754

    
755
/*
756
 *  backup_config_section($section): returns as an xml file string of
757
 *                                   the configuration section
758
 */
759
function backup_vip_config_section() {
760
    global $config;
761
    $new_section = &$config['virtualip'];
762
    foreach($new_section['vip'] as $section) {
763
	if($section['mode'] == "proxyarp") {
764
		unset($section);		
765
	}
766
	if($section['advskew'] <> "") {
767
		$section['advskew']++;
768
	}
769
	$temp['vip'][] = $section;
770
    }
771
    
772
    /* generate configuration XML */
773
    $xmlconfig = dump_xml_config($temp, "virtualip");
774
    $xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
775
    return $xmlconfig;
776
}
777

    
778
/*
779
 *  restore_config_section($section, new_contents): restore a configuration section,
780
 *                                                  and write the configuration out
781
 *                                                  to disk/cf.
782
 */
783
function restore_config_section($section, $new_contents) {
784
    global $config;
785
    conf_mount_rw();
786
    $fout = fopen("{$g['tmp_path']}/tmpxml","w");
787
    fwrite($fout, $new_contents);
788
    fclose($fout);
789
    $section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
790
    $config[$section] = &$section_xml;
791
    unlink($g['tmp_path'] . "/tmpxml");
792
    write_config("Restored {$section} of config file (maybe from CARP partner)");
793
    conf_mount_ro();
794
    return;
795
}
796

    
797
/*
798
 * http_post($server, $port, $url, $vars): does an http post to a web server
799
 *                                         posting the vars array.
800
 * written by nf@bigpond.net.au
801
 */
802
function http_post($server, $port, $url, $vars) {
803
    $user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
804
    $urlencoded = "";
805
    while (list($key,$value) = each($vars))
806
	$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
807
    $urlencoded = substr($urlencoded,0,-1);
808

    
809
    $content_length = strlen($urlencoded);
810

    
811
    $headers = "POST $url HTTP/1.1
812
Accept: */*
813
Accept-Language: en-au
814
Content-Type: application/x-www-form-urlencoded
815
User-Agent: $user_agent
816
Host: $server
817
Connection: Keep-Alive
818
Cache-Control: no-cache
819
Content-Length: $content_length
820

    
821
";
822

    
823
    $fp = fsockopen($server, $port, $errno, $errstr);
824
    if (!$fp) {
825
	return false;
826
    }
827

    
828
    fputs($fp, $headers);
829
    fputs($fp, $urlencoded);
830

    
831
    $ret = "";
832
    while (!feof($fp))
833
	$ret.= fgets($fp, 1024);
834

    
835
    fclose($fp);
836

    
837
    return $ret;
838

    
839
}
840

    
841
/*
842
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
843
 */
844
if (!function_exists('php_check_syntax')){
845
   function php_check_syntax($code_to_check, &$errormessage){
846
	return false;
847
        $fout = fopen("/tmp/codetocheck.php","w");
848
        $code = $_POST['content'];
849
        $code = str_replace("<?php", "", $code);
850
        $code = str_replace("?>", "", $code);
851
        fwrite($fout, "<?php\n\n");
852
        fwrite($fout, $code_to_check);
853
        fwrite($fout, "\n\n?>\n");
854
        fclose($fout);
855
        $command = "/usr/local/bin/php -l /tmp/codetocheck.php";
856
        $output = exec_command($command);
857
        if (stristr($output, "Errors parsing") == false) {
858
            echo "false\n";
859
            $errormessage = '';
860
            return(false);
861
        } else {
862
            $errormessage = $output;
863
            return(true);
864
        }
865
    }
866
}
867

    
868
/*
869
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
870
 */
871
if (!function_exists('php_check_syntax')){
872
   function php_check_syntax($code_to_check, &$errormessage){
873
	return false;
874
        $command = "/usr/local/bin/php -l " . $code_to_check;
875
        $output = exec_command($command);
876
        if (stristr($output, "Errors parsing") == false) {
877
            echo "false\n";
878
            $errormessage = '';
879
            return(false);
880
        } else {
881
            $errormessage = $output;
882
            return(true);
883
        }
884
    }
885
}
886

    
887
/*
888
 * rmdir_recursive($path,$follow_links=false)
889
 * Recursively remove a directory tree (rm -rf path)
890
 * This is for directories _only_
891
 */
892
function rmdir_recursive($path,$follow_links=false) {
893
	$to_do = glob($path);
894
	if(!is_array($to_do)) $to_do = array($to_do);
895
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
896
		if(file_exists($workingdir)) {
897
			if(is_dir($workingdir)) {
898
				$dir = opendir($workingdir);
899
				while ($entry = readdir($dir)) {
900
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
901
						unlink("$workingdir/$entry");
902
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
903
						rmdir_recursive("$workingdir/$entry");
904
				}
905
				closedir($dir);
906
				rmdir($workingdir);
907
			} elseif (is_file($workingdir)) {
908
				unlink($workingdir);
909
			}
910
               	}
911
	}
912
	return;
913
}
914

    
915
/*
916
 *     get_memory()
917
 *     returns an array listing the amount of
918
 *     memory installed in the hardware
919
 *     [0]real and [1]available
920
 */
921
function get_memory() {
922
        $mem = `cat /var/log/dmesg.boot | grep memory`;
923
        if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
924
                $real = $matches[1];
925
        if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
926
                $avail = $matches[1];
927
        return array($real[0],$avail[0]);
928
}
929

    
930

    
931
/*
932
 *    safe_mkdir($path, $mode = 0755)
933
 *    create directory if it doesn't already exist and isn't a file!
934
 */
935
function safe_mkdir($path, $mode=0755) {
936
	global $g;
937

    
938
	/* cdrom is ro. */
939
	if($g['platform'] == "cdrom")
940
		return false;
941
	
942
	if (!is_file($path) && !is_dir($path))
943
		return mkdir($path, $mode);
944
	else
945
		return false;
946
}
947

    
948
/*
949
 * make_dirs($path, $mode = 0755)
950
 * create directory tree recursively (mkdir -p)
951
 */
952
function make_dirs($path, $mode = 0755) {
953
	/* is dir already created? */
954
	if(is_dir($path)) return;
955
	/* create directory in question */
956
	$to_create = explode("/", $path);
957
	foreach($to_create as $tc) 
958
	    if(!is_dir($tc))
959
		safe_mkdir($path, $mode);
960
}
961

    
962
/*
963
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
964
 */
965
function check_firmware_version($tocheck = "all", $return_php = true) {
966
        global $g, $config;
967
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
968
        $xmlrpc_path = $g['xmlrpcpath'];
969
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
970
			"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
971
			"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
972
			"platform" => trim(file_get_contents('/etc/platform'))
973
		);
974
	if($tocheck == "all") {
975
		$params = $rawparams;
976
	} else {
977
		foreach($tocheck as $check) {
978
			$params['check'] = $rawparams['check'];
979
			$params['platform'] = $rawparams['platform'];
980
		}
981
	}
982
	if($config['system']['firmware']['branch']) {
983
		$params['branch'] = $config['system']['firmware']['branch'];
984
	}
985
	$xmlparams = php_value_to_xmlrpc($params);
986
        $msg = new XML_RPC_Message('pfsense.get_firmware_version', array($xmlparams));
987
        $cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
988
	//$cli->setDebug(1);
989
	$resp = $cli->send($msg, 10);
990
	if(!$resp or $resp->faultCode()) {
991
		$raw_versions = false;
992
	} else {
993
		$raw_versions = XML_RPC_decode($resp->value());
994
		$raw_versions["current"] = $params;
995
	}
996
	return $raw_versions;
997
}
998

    
999
function get_disk_info() {
1000
        exec("df -h | grep -w '/' | awk '{ print $2, $3, $4, $5 }'", $diskout);
1001
        return explode(' ', $diskout[0]);
1002
        // $size, $used, $avail, $cap
1003
}
1004

    
1005
/****f* pfsense-utils/display_top_tabs
1006
 * NAME
1007
 *   display_top_tabs - display tabs with rounded edges
1008
 * INPUTS
1009
 *   $text	- array of tabs
1010
 * RESULT
1011
 *   null
1012
 ******/
1013
    function display_top_tabs($tab_array) {
1014
	    echo "<table cellpadding='0' cellspacing='0'>\n";
1015
	    echo " <tr height='1'>\n";
1016
	    $tabscounter = 0;
1017
	    foreach ($tab_array as $ta) {
1018
		    if($ta[1] == true) {
1019
			    echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\"><div id='tabactive'></div></td>\n";
1020
		    } else {
1021
			    echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
1022
		    }
1023
		    $tabscounter++;
1024
	    }
1025
	    echo "</tr>\n<tr>\n";
1026
	    foreach ($tab_array as $ta) {
1027
		    if($ta[1] == true) {
1028
			    echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
1029
			    echo "&nbsp;&nbsp;&nbsp;";
1030
			    echo "<font size='-12'>&nbsp;</td>\n";
1031
		    } else {
1032
			    echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
1033
			    echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
1034
			    echo "<font size='-12'>&nbsp;</td>\n";
1035
		    }
1036
	    }
1037
	    echo "</tr>\n<tr height='5px'>\n";
1038
	    foreach ($tab_array as $ta) {
1039
		    if($ta[1] == true) {
1040
			    echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\"></td>\n";
1041
		    } else {
1042
			    echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\"></td>\n";
1043
		    }
1044
		    $tabscounter++;
1045
	    }
1046
	    echo " </tr>\n";
1047
	    echo "</table>\n";
1048
	    
1049
	    echo "<script type=\"text/javascript\">";
1050
	    echo "NiftyCheck();\n";
1051
	    echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1052
	    for($x=0; $x<$tabscounter; $x++) 
1053
		    echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1054
	    echo "</script>";
1055
    }
1056

    
1057

    
1058
/****f* pfsense-utils/display_topbar
1059
 * NAME
1060
 *   display_topbar - top a table off with rounded edges
1061
 * INPUTS
1062
 *   $text	- (optional) Text to include in bar
1063
 * RESULT
1064
 *   null
1065
 ******/
1066
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {	    
1067
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
1068
	echo "       <tr height='1'>\n";
1069
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
1070
	echo "		<div id='topbar'></div></td>\n";
1071
	echo "       </tr>\n";
1072
	echo "       <tr height='1'>\n";
1073
	if ($text != "")
1074
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
1075
	else
1076
		echo "         <td height='1' class='listtopic'></td>\n";
1077
	echo "       </tr>\n";
1078
	echo "     </table>";
1079
	echo "<script type=\"text/javascript\">";
1080
	echo "NiftyCheck();\n";
1081
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
1082
	echo "</script>";
1083
}
1084

    
1085
/****f* pfsense-utils/generate_random_mac_address
1086
 * NAME
1087
 *   generate_random_mac - generates a random mac address
1088
 * INPUTS
1089
 *   none
1090
 * RESULT
1091
 *   $mac - a random mac address
1092
 ******/
1093
function generate_random_mac_address() {
1094
	$mac = "00:a0:8e";
1095
	for($x=0; $x<3; $x++) 
1096
	    $mac .= ":" . dechex(rand(16, 255));
1097

    
1098
	return $mac;
1099
}
1100

    
1101
/****f* pfsense-utils/strncpy
1102
 * NAME
1103
 *   strncpy - copy strings
1104
 * INPUTS
1105
 *   &$dst, $src, $length
1106
 * RESULT
1107
 *   none
1108
 ******/
1109
function strncpy(&$dst, $src, $length) {
1110
	if (strlen($src) > $length) {
1111
		$dst = substr($src, 0, $length);
1112
	} else {
1113
		$dst = $src;
1114
	}
1115
}
1116

    
1117
/****f* pfsense-utils/reload_interfaces_sync
1118
 * NAME
1119
 *   reload_interfaces - reload all interfaces
1120
 * INPUTS
1121
 *   none
1122
 * RESULT
1123
 *   none
1124
 ******/
1125
function reload_interfaces_sync() {
1126
	global $config, $g;
1127
	
1128
	if(file_exists("{$g['tmp_path']}/config.cache"))
1129
		unlink("{$g['tmp_path']}/config.cache");
1130
	
1131
	/* parse config.xml again */
1132
	$config = parse_config(true);
1133
	
1134
	/* set up LAN interface */
1135
	interfaces_lan_configure();
1136

    
1137
	/* set up WAN interface */
1138
	interfaces_wan_configure();
1139

    
1140
	/* set up Optional interfaces */
1141
	interfaces_optional_configure();
1142
        
1143
	/* set up static routes */
1144
	system_routing_configure();
1145
	
1146
	/* bring up carp interfaces */
1147
	interfaces_carp_bringup();
1148

    
1149
	/* enable routing */
1150
	system_routing_enable();
1151
}
1152

    
1153
/****f* pfsense-utils/reload_all
1154
 * NAME
1155
 *   reload_all - triggers a reload of all settings
1156
 *   * INPUTS
1157
 *   none
1158
 * RESULT
1159
 *   none
1160
 ******/
1161
function reload_all() {
1162
	touch("/tmp/reload_all");
1163
}
1164

    
1165
/****f* pfsense-utils/reload_interfaces
1166
 * NAME
1167
 *   reload_interfaces - triggers a reload of all interfaces
1168
 * INPUTS
1169
 *   none
1170
 * RESULT
1171
 *   none
1172
 ******/
1173
function reload_interfaces() {
1174
	touch("/tmp/reload_interfaces");
1175
}
1176

    
1177
/****f* pfsense-utils/sync_webgui_passwords
1178
 * NAME
1179
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1180
 * INPUTS
1181
 *   none
1182
 * RESULT
1183
 *   none
1184
 ******/
1185
function sync_webgui_passwords() {
1186
	conf_mount_rw();
1187
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1188
	mwexec("/usr/sbin/pwd_mkdb /etc/master.passwd");
1189
	conf_mount_ro();
1190
}
1191

    
1192
/****f* pfsense-utils/reload_all_sync
1193
 * NAME
1194
 *   reload_all - reload all settings
1195
 *   * INPUTS
1196
 *   none
1197
 * RESULT
1198
 *   none
1199
 ******/
1200
function reload_all_sync() {
1201
	global $config, $g;
1202
	
1203
	if(file_exists("{$g['tmp_path']}/config.cache"))
1204
		unlink("{$g['tmp_path']}/config.cache");
1205
	
1206
	/* parse config.xml again */
1207
	$config = parse_config(true);
1208

    
1209
	/* set up our timezone */
1210
	system_timezone_configure();
1211

    
1212
	/* set up our hostname */
1213
	system_hostname_configure();
1214

    
1215
	/* make hosts file */
1216
	system_hosts_generate();
1217

    
1218
	/* generate resolv.conf */
1219
	system_resolvconf_generate();
1220

    
1221
	/* set up LAN interface */
1222
	interfaces_lan_configure();
1223

    
1224
	/* set up WAN interface */
1225
	interfaces_wan_configure();
1226

    
1227
	/* set up Optional interfaces */
1228
	interfaces_optional_configure();
1229
        
1230
	/* bring up carp interfaces */
1231
	interfaces_carp_configure();
1232
	
1233
	/* set up static routes */
1234
	system_routing_configure();
1235

    
1236
	/* enable routing */
1237
	system_routing_enable();
1238
	
1239
	/* ensure passwords are sync'd */
1240
	system_password_configure();
1241

    
1242
	/* start dnsmasq service */
1243
	services_dnsmasq_configure();
1244

    
1245
	/* start dyndns service */
1246
	services_dyndns_configure();
1247

    
1248
	/* start DHCP service */
1249
	services_dhcpd_configure();
1250

    
1251
	/* start the NTP client */
1252
	system_ntp_configure();
1253

    
1254
	/* start ftp proxy helpers if they are enabled */
1255
	system_start_ftp_helpers();
1256

    
1257
	/* bring up carp interfaces */
1258
	interfaces_carp_bringup();
1259

    
1260
        /* reload the filter */
1261
	filter_configure();
1262
	
1263
	/* sync pw database */
1264
	conf_mount_rw();
1265
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1266
	mwexec("/usr/sbin/pwd_mkdb /etc/master.passwd");
1267
	conf_mount_ro();
1268
	
1269
}
1270

    
1271
?>
(12-12/23)