Project

General

Profile

Download (42.4 KB) Statistics
| Branch: | Tag: | Revision:
1 7b2274cb Scott Ullrich
<?php
2 d884b49c Colin Smith
/****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 3a508fe2 Colin Smith
 *
23 d884b49c Colin Smith
 * 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 b63f20c3 Colin Smith
function get_tmp_file() {
37
	return "/tmp/tmp-" . time();
38
}
39
40 ab8caecc Scott Ullrich
/****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 767a716e Scott Ullrich
	$lastseen = "";
50
	$matches = "";
51 ab8caecc Scott Ullrich
	$dns_servers = array();
52
	$dns = `cat /etc/resolv.conf`;
53
	$dns_s = split("\n", $dns);
54
	foreach($dns_s as $dns) {
55
		if (preg_match("/nameserver (.*)/", $dns, $matches))
56
			$dns_servers[] = $matches[1];		
57
	}
58 d9fadeaa Scott Ullrich
	$dns_server_master = array();
59 05d3c4ad Scott Ullrich
	sort($dns_servers);
60 d9fadeaa Scott Ullrich
	foreach($dns_servers as $t) {
61
		if($t <> $lastseen)
62
			if($t <> "")
63
				$dns_server_master[] = $t;
64
		$lastseen = $t;
65
	}
66
	return $dns_server_master;
67 ab8caecc Scott Ullrich
}
68
69 2265659b Colin Smith
/****f* pfsense-utils/log_error
70 a7a594d1 Scott Ullrich
* NAME
71
*   log_error  - Sends a string to syslog.
72
* INPUTS
73
*   $error     - string containing the syslog message.
74
* RESULT
75
*   null
76
******/
77 7b2274cb Scott Ullrich
function log_error($error) {
78 a7a594d1 Scott Ullrich
    $page = $_SERVER['PHP_SELF'];
79
    syslog(LOG_WARNING, "$page: $error");
80 7b2274cb Scott Ullrich
    return;
81
}
82
83 94e8082f Scott Ullrich
/****f* pfsense-utils/get_interface_mac_address
84
 * NAME
85
 *   get_interface_mac_address - Return a interfaces mac address
86
 * INPUTS
87
 *   $interface	- interface to obtain mac address from
88
 * RESULT
89
 *   $mac - the mac address of the interface
90
 ******/
91
function get_interface_mac_address($interface) {
92 4d027492 Colin Smith
    $mac = exec("ifconfig {$interface} | awk '/ether/ {print $2}'");
93
    return trim($mac);
94 94e8082f Scott Ullrich
}
95
96 25192408 Colin Smith
/****f* pfsense-utils/return_dir_as_array
97
 * NAME
98
 *   return_dir_as_array - Return a directory's contents as an array.
99
 * INPUTS
100
 *   $dir	- string containing the path to the desired directory.
101
 * RESULT
102 775433e7 Colin Smith
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
103 8e362784 Colin Smith
 ******/
104 622fa35a Scott Ullrich
function return_dir_as_array($dir) {
105 174861fd Scott Ullrich
    $dir_array = array();
106 622fa35a Scott Ullrich
    if (is_dir($dir)) {
107 775433e7 Colin Smith
	if ($dh = opendir($dir)) {
108 622fa35a Scott Ullrich
	    while (($file = readdir($dh)) !== false) {
109 174861fd Scott Ullrich
		$canadd = 0;
110
		if($file == ".") $canadd = 1;
111
		if($file == "..") $canadd = 1;
112
		if($canadd == 0)
113
		    array_push($dir_array, $file);
114 622fa35a Scott Ullrich
	    }
115
	    closedir($dh);
116
	}
117
    }
118
    return $dir_array;
119
}
120 7b2274cb Scott Ullrich
121 775433e7 Colin Smith
/****f* pfsense-utils/enable_hardware_offloading
122
 * NAME
123
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
124
 * INPUTS
125
 *   $interface	- string containing the physical interface to work on.
126
 * RESULT
127
 *   null
128
 * NOTES
129
 *   This function only supports the fxp driver's loadable microcode.
130
 ******/
131 ed059571 Scott Ullrich
function enable_hardware_offloading($interface) {
132 d22669ef Scott Ullrich
    global $g, $config;
133 0c03a1eb Scott Ullrich
    if(isset($config['system']['do_not_use_nic_microcode']))
134 d22669ef Scott Ullrich
	return;
135 31a82233 Scott Ullrich
    if($g['booting']) {
136 af67c4ab Scott Ullrich
	/* translate wan, lan, opt -> real interface if needed */
137
	$int = filter_translate_type_to_real_interface($interface);
138 d641b292 Scott Ullrich
	if(stristr($int,"lnc"))
139
		return;    	
140 8d36fd1d Scott Ullrich
	if($int <> "") $interface = $int;
141 562fca6d Scott Ullrich
        $int_family = preg_split("/[0-9]+/", $int);
142 cc42f645 Scott Ullrich
	$options = strtolower(`/sbin/ifconfig {$interface} | grep options`);
143 7c748413 Scott Ullrich
	echo $interface . " ";
144 027aaef0 Scott Ullrich
	$supported_ints = array('fxp');
145 562fca6d Scott Ullrich
	if (in_array($int_family, $supported_ints))
146
		mwexec("/sbin/ifconfig {$interface} link0");
147 ad7ca08a Scott Ullrich
	if(stristr($options, "txcsum") == true)
148
	    mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
149
	if(stristr($options, "rxcsum") == true)    
150
	    mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");    
151
	if(stristr($options, "polling") == true)
152
	    mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
153 c9b4da10 Scott Ullrich
    }
154 775433e7 Colin Smith
    return;
155 ed059571 Scott Ullrich
}
156
157 a18b6b97 Scott Ullrich
/****f* pfsense-utils/is_alias_inuse
158
 * NAME
159
 *   checks to see if an alias is currently in use by a rule
160
 * INPUTS
161
 *   
162
 * RESULT
163
 *   true or false
164
 * NOTES
165
 *   
166
 ******/
167
function is_alias_inuse($alias) {
168
    global $g, $config;
169 fde34eb9 Scott Ullrich
    if($alias == "") return false;
170 a18b6b97 Scott Ullrich
    /* loop through firewall rules looking for alias in use */
171 69c30754 Scott Ullrich
    if(is_array($config['nat']['rule']))
172
	    foreach($config['filter']['rule'] as $rule) {
173
			if(is_array($rule['source']['address']))
174 3dad45ad Scott Ullrich
				if($rule['source']['address'] == $alias)
175
					return true;
176 69c30754 Scott Ullrich
			if(is_array($rule['destination']['address']))
177 3dad45ad Scott Ullrich
				if($rule['destination']['address'] == $alias)
178
					return true;
179 69c30754 Scott Ullrich
	    }
180 a18b6b97 Scott Ullrich
    /* loop through nat rules looking for alias in use */
181 69c30754 Scott Ullrich
    if(is_array($config['nat']['rule']))
182
	    foreach($config['nat']['rule'] as $rule) {
183
			if($rule['target'] == $alias)
184 3dad45ad Scott Ullrich
				return true;
185 69c30754 Scott Ullrich
			if($rule['external-address'] == $alias)
186
				return true;	
187
	    }
188 a18b6b97 Scott Ullrich
    return false;
189
}
190
191 562fca6d Scott Ullrich
/****f* pfsense-utils/setup_polling_defaults
192
 * NAME
193
 *   sets up sysctls for pollingS
194
 * INPUTS
195
 *   
196
 * RESULT
197
 *   null
198
 * NOTES
199
 *   
200
 ******/
201
function setup_polling_defaults() {
202
	global $g, $config;
203
	if($config['system']['polling_each_burst'])
204
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
205
	if($config['system']['polling_burst_max'])
206
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
207
	if($config['system']['polling_user_frac'])
208
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");		
209
}
210
211
/****f* pfsense-utils/setup_polling
212
 * NAME
213
 *   sets up polling
214
 * INPUTS
215
 *   
216
 * RESULT
217
 *   null
218
 * NOTES
219
 *   
220
 ******/
221
function setup_polling() {
222
	setup_polling_defaults();
223
	global $g, $config;
224
	/* build an array of interfaces to work with */
225
	$iflist = array("lan" => "LAN", "wan" => "WAN");
226
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
227
	$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];		
228
	/*    activate polling for interface if it supports it
229
	 *    man polling on a freebsd box for the following list
230
	 */
231
	/* loop through all interfaces and handle pftpx redirections */
232
	foreach ($iflist as $ifent => $ifname) {	
233
		$supported_ints = array('dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste',
234
			'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
235 767a716e Scott Ullrich
		if (in_array($ifname, $supported_ints) and isset($config['system']['polling'])) {
236 562fca6d Scott Ullrich
			mwexec("/sbin/ifconfig {$interface} polling");
237
		} else {
238
			mwexec("/sbin/ifconfig {$interface} -polling");
239
		}
240
	}
241
}
242
243 9f6b1429 Scott Ullrich
/****f* pfsense-utils/setup_microcode
244
 * NAME
245
 *   enumerates all interfaces and calls enable_hardware_offloading which
246
 *   enables a NIC's supported hardware features.
247
 * INPUTS
248
 *   
249
 * RESULT
250
 *   null
251
 * NOTES
252
 *   This function only supports the fxp driver's loadable microcode.
253
 ******/
254
function setup_microcode() {
255
   global $config;
256
    $ifdescrs = array('wan', 'lan');
257
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
258
	$ifdescrs['opt' . $j] = "opt" . $j;
259
    }
260
    foreach($ifdescrs as $if)
261
	enable_hardware_offloading($if);
262
}
263
264 775433e7 Colin Smith
/****f* pfsense-utils/return_filename_as_array
265
 * NAME
266
 *   return_filename_as_array - Return a file's contents as an array.
267
 * INPUTS
268 158dd870 Colin Smith
 *   $filename	- string containing the path to the desired file.
269
 *   $strip	- array of characters to strip - default is '#'.
270 775433e7 Colin Smith
 * RESULT
271 158dd870 Colin Smith
 *   $file	- array containing the file's contents.
272 775433e7 Colin Smith
 * NOTES
273
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
274
 ******/
275
function return_filename_as_array($filename, $strip = array('#')) {
276
    if(file_exists($filename)) $file = file($filename);
277
    if(is_array($file)) {
278 b99a7892 Scott Ullrich
	foreach($file as $line) $line = trim($line);
279 775433e7 Colin Smith
        foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
280 98b77940 Scott Ullrich
    }
281 0dd62c88 Bill Marquette
    return $file;
282 3ff9d424 Scott Ullrich
}
283
284 e7f2ea12 Scott Ullrich
/****f* pfsense-utils/file_put_contents
285
 * NAME
286
 *   file_put_contents - Wrapper for file_put_contents if it doesn't exist
287
 * RESULT
288
 *   none
289
 ******/
290 5563a2c0 Scott Ullrich
if(!function_exists("file_put_contents")) {
291
    function file_put_contents($filename, $data) {
292
	$fd = fopen($filename,"w");
293
	fwrite($fd, $data);
294
	fclose($fd);
295
    }
296
}
297
298 158dd870 Colin Smith
/****f* pfsense-utils/get_carp_status
299
 * NAME
300
 *   get_carp_status - Return whether CARP is enabled or disabled.
301
 * RESULT
302
 *   boolean	- true if CARP is enabled, false if otherwise.
303
 ******/
304 b1174d02 Scott Ullrich
function get_carp_status() {
305
    /* grab the current status of carp */
306 1a97d17c Scott Ullrich
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
307
    if(intval($status) == "0") return false;
308 b1174d02 Scott Ullrich
    return true;
309
}
310
311 158dd870 Colin Smith
/****f* pfsense-utils/is_carp_defined
312
 * NAME
313
 *   is_carp_defined - Return whether CARP is detected in the kernel.
314
 * RESULT
315
 *   boolean	- true if CARP is detected, false otherwise.
316
 ******/
317 a8ac6c98 Scott Ullrich
function is_carp_defined() {
318 0f66804f Scott Ullrich
    /* is carp compiled into the kernel and userland? */
319
    $command = "/sbin/sysctl -a | grep carp";
320
    $fd = popen($command . " 2>&1 ", "r");
321
    if(!$fd) {
322 ef4550f8 Scott Ullrich
	log_error("Warning, could not execute command {$command}");
323
	return 0;
324 0f66804f Scott Ullrich
    }
325
    while(!feof($fd)) {
326 ef4550f8 Scott Ullrich
	$tmp .= fread($fd,49);
327 0f66804f Scott Ullrich
    }
328
    fclose($fd);
329 a8ac6c98 Scott Ullrich
330 0f66804f Scott Ullrich
    if($tmp == "")
331 ef4550f8 Scott Ullrich
	return false;
332 0f66804f Scott Ullrich
    else
333 ef4550f8 Scott Ullrich
	return true;
334 a8ac6c98 Scott Ullrich
}
335
336 ffb4b005 Scott Ullrich
/****f* pfsense-utils/get_interface_mtu
337
 * NAME
338
 *   get_interface_mtu - Return the mtu of an interface
339
 * RESULT
340
 *   $tmp	- Returns the mtu of an interface
341
 ******/
342
function get_interface_mtu($interface) {
343
	$mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f4`;
344 62739c1c Scott Ullrich
	return $mtu;
345 ffb4b005 Scott Ullrich
}
346
347 df792110 Scott Ullrich
/****f* pfsense-utils/is_interface_wireless
348
 * NAME
349
 *   is_interface_wireless - Returns if an interface is wireless
350
 * RESULT
351
 *   $tmp	- Returns if an interface is wireless
352
 ******/
353
function is_interface_wireless($interface) {
354
	global $config, $g;
355 b5af44a1 Scott Ullrich
	$interface = convert_real_interface_to_friendly_interface_name($interface);
356 df792110 Scott Ullrich
	if(isset($config['interfaces'][$interface]['wireless']))
357
		return true;
358
	else
359
		return false;
360
}
361
362 158dd870 Colin Smith
/****f* pfsense-utils/find_number_of_created_carp_interfaces
363
 * NAME
364
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
365
 * RESULT
366
 *   $tmp	- Number of currently created CARP interfaces.
367
 ******/
368 ed059571 Scott Ullrich
function find_number_of_created_carp_interfaces() {
369 0f66804f Scott Ullrich
    $command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
370
    $fd = popen($command . " 2>&1 ", "r");
371
    if(!$fd) {
372 ef4550f8 Scott Ullrich
	log_error("Warning, could not execute command {$command}");
373
	return 0;
374 0f66804f Scott Ullrich
    }
375
    while(!feof($fd)) {
376 ef4550f8 Scott Ullrich
	$tmp .= fread($fd,49);
377 0f66804f Scott Ullrich
    }
378
    fclose($fd);
379
    $tmp = intval($tmp);
380
    return $tmp;
381 ed059571 Scott Ullrich
}
382
383 158dd870 Colin Smith
/****f* pfsense-utils/link_ip_to_carp_interface
384
 * NAME
385
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
386
 * INPUTS
387
 *   $ip
388
 * RESULT
389
 *   $carp_ints
390 0c84aff0 Colin Smith
 ******/
391 fa65a62b Scott Ullrich
function link_ip_to_carp_interface($ip) {
392 669e1adb Bill Marquette
	global $config;
393
	if($ip == "") return;
394 fa65a62b Scott Ullrich
395 669e1adb Bill Marquette
	$ifdescrs = array('wan', 'lan');
396
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
397
		$ifdescrs['opt' . $j] = "opt" . $j;
398
	}
399 fa65a62b Scott Ullrich
400 669e1adb Bill Marquette
	$ft = split("\.", $ip);
401
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
402 0f66804f Scott Ullrich
403 669e1adb Bill Marquette
	$carp_ints = "";
404
	$num_carp_ints = find_number_of_created_carp_interfaces();
405
	foreach ($ifdescrs as $ifdescr => $ifname) {
406
		for($x=0; $x<$num_carp_ints; $x++) {
407
			$carp_int = "carp{$x}";
408
			$carp_ip = find_interface_ip($carp_int);
409
			$carp_ft = split("\.", $carp_ip);
410
			$carp_ft_ip = $carp_ft[0] . "." . $carp_ft[1] . "." . $carp_ft[2] . ".";
411
			$result = does_interface_exist($carp_int);
412
			if($result <> true) break;
413
			if($ft_ip == $carp_ft_ip)
414
			if(stristr($carp_ints,$carp_int) == false)
415
			$carp_ints .= " " . $carp_int;
416
		}
417 ef4550f8 Scott Ullrich
	}
418 669e1adb Bill Marquette
	return $carp_ints;
419 fa65a62b Scott Ullrich
}
420
421 158dd870 Colin Smith
/****f* pfsense-utils/exec_command
422
 * NAME
423
 *   exec_command - Execute a command and return a string of the result.
424
 * INPUTS
425
 *   $command	- String of the command to be executed.
426
 * RESULT
427
 *   String containing the command's result.
428
 * NOTES
429
 *   This function returns the command's stdout and stderr.
430
 ******/
431 5ccfea33 Scott Ullrich
function exec_command($command) {
432 158dd870 Colin Smith
    $output = array();
433
    exec($command . ' 2>&1 ', $output);
434
    return(implode("\n", $output));
435 5ccfea33 Scott Ullrich
}
436
437 dc19bcf8 Scott Ullrich
/****f* interfaces/is_jumbo_capable
438 ff02a977 Scott Ullrich
 * NAME
439 dc19bcf8 Scott Ullrich
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
440 ff02a977 Scott Ullrich
 * INPUTS
441 dc19bcf8 Scott Ullrich
 *   $int             - string containing interface name
442 ff02a977 Scott Ullrich
 * RESULT
443 dc19bcf8 Scott Ullrich
 *   boolean          - true or false
444 ff02a977 Scott Ullrich
 ******/
445 dc19bcf8 Scott Ullrich
function is_jumbo_capable($int) {
446
	/* Per:
447 784c2947 Scott Ullrich
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-RELEASE&format=html
448 dc19bcf8 Scott Ullrich
	 * Only the following drivers support large frames
449
	 */
450 a52609a5 Scott Ullrich
	/* 'de' chipset purposely left out of this list
451
	 * requires defining BIG_PACKET in the
452
	 * /usr/src/sys/pci/if_de.c source file and rebuilding the
453
	 * kernel or module.  The hack works only for the 21041,
454
	 * 21140, and 21140A chips.
455
	 */
456
	$capable = array("bfe", "bge", "dc", "em", "fxp", "gem", "hme", 
457 784c2947 Scott Ullrich
		"ixgb", "nge", "re", "rl", "sis", "ste", "ti", "tl", "tx",
458 42080a5a Scott Ullrich
		"txp", "xl", "sk");
459 dc19bcf8 Scott Ullrich
	
460
	$int_family = preg_split("/[0-9]+/", $int);
461
462
	if (in_array($int_family[0], $capable))
463
		return true;
464
	else
465
		return false;
466 ff02a977 Scott Ullrich
}
467
468 fa65a62b Scott Ullrich
/*
469
 * does_interface_exist($interface): return true or false if a interface is detected.
470
 */
471
function does_interface_exist($interface) {
472
    $ints = exec_command("/sbin/ifconfig -l");
473 83661f77 Scott Ullrich
    if(stristr($ints, $interface) !== false)
474 fa65a62b Scott Ullrich
	return true;
475
    else
476
	return false;
477
}
478
479 5ccfea33 Scott Ullrich
/*
480
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
481
 */
482
function convert_ip_to_network_format($ip, $subnet) {
483
    $ipsplit = split('[.]', $ip);
484
    $string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
485
    return $string;
486
}
487
488 b04a6ca4 Scott Ullrich
/*
489
 * find_interface_ip($interface): return the interface ip (first found)
490
 */
491
function find_interface_ip($interface) {
492 4983ed8c Scott Ullrich
    if(does_interface_exist($interface) == false) return;
493 e3939e20 Scott Ullrich
    $ip = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2");
494 e67f187a Scott Ullrich
    $ip = str_replace("\n","",$ip);
495 b04a6ca4 Scott Ullrich
    return $ip;
496
}
497
498 3314bb92 Scott Ullrich
function guess_interface_from_ip($ipaddress) {
499
    $ints = `/sbin/ifconfig -l`;
500
    $ints_split = split(" ", $ints);
501
    $ip_subnet_split = split("\.", $ipaddress);
502
    $ip_subnet = $ip_subnet_split[0] . "." . $ip_subnet_split[1] . "." . $ip_subnet_split[2] . ".";
503
    foreach($ints_split as $int) {
504
        $ip = find_interface_ip($int);
505
        $ip_split = split("\.", $ip);
506
        $ip_tocheck = $ip_split[0] . "." . $ip_split[1] . "." . $ip_split[2] . ".";
507
        if(stristr($ip_tocheck, $ip_subnet) != false) return $int;
508
    }
509
}
510
511 fa65a62b Scott Ullrich
function filter_opt_interface_to_real($opt) {
512 0f66804f Scott Ullrich
    global $config;
513
    return $config['interfaces'][$opt]['if'];
514 fa65a62b Scott Ullrich
}
515
516
function filter_get_opt_interface_descr($opt) {
517 0f66804f Scott Ullrich
    global $config;
518
    return $config['interfaces'][$opt]['descr'];
519 fa65a62b Scott Ullrich
}
520
521 b73cc056 Scott Ullrich
function get_friendly_interface_list_as_array() {
522 0f66804f Scott Ullrich
    global $config;
523
    $ints = array();
524
    $ifdescrs = array('wan', 'lan');
525
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
526 669e1adb Bill Marquette
		$ifdescrs['opt' . $j] = "opt" . $j;
527 0f66804f Scott Ullrich
    }
528
    $ifdescrs = get_interface_list();
529
    foreach ($ifdescrs as $ifdescr => $ifname) {
530 669e1adb Bill Marquette
		array_push($ints,$ifdescr);
531 0f66804f Scott Ullrich
    }
532
    return $ints;
533 b73cc056 Scott Ullrich
}
534
535 5ccfea33 Scott Ullrich
/*
536
 * find_ip_interface($ip): return the interface where an ip is defined
537
 */
538
function find_ip_interface($ip) {
539 0f66804f Scott Ullrich
    global $config;
540
    $ifdescrs = array('wan', 'lan');
541
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
542 ef4550f8 Scott Ullrich
	$ifdescrs['opt' . $j] = "opt" . $j;
543 0f66804f Scott Ullrich
    }
544
    foreach ($ifdescrs as $ifdescr => $ifname) {
545
	$int = filter_translate_type_to_real_interface($ifname);
546
	$ifconfig = exec_command("/sbin/ifconfig {$int}");
547
	if(stristr($ifconfig,$ip) <> false)
548
	    return $int;
549
    }
550
    return false;
551 5ccfea33 Scott Ullrich
}
552
553 bc5d2a26 Scott Ullrich
/*
554
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
555
 *                                                       for a friendly interface.  ie: wan
556
 */
557
function filter_translate_type_to_real_interface($interface) {
558 ef4550f8 Scott Ullrich
    global $config;
559 b46dbd5e Scott Ullrich
    if($config['interfaces'][$interface]['if'] <> "") {
560
	return $config['interfaces'][$interface]['if'];
561
    } else {
562
	return $interface;
563
    }
564 bc5d2a26 Scott Ullrich
}
565
566 591afdfd Scott Ullrich
/*
567
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
568
 */
569
function get_carp_interface_status($carpinterface) {
570 669e1adb Bill Marquette
	/* basically cache the contents of ifconfig statement
571
	to speed up this routine */
572
	global $carp_query;
573
	if($carp_query == "")
574 10655b3c Scott Ullrich
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
575 669e1adb Bill Marquette
	$found_interface = 0;
576
	foreach($carp_query as $int) {
577
		if($found_interface == 1) {
578
			if(stristr($int, "MASTER") == true) return "MASTER";
579
			if(stristr($int, "BACKUP") == true) return "BACKUP";
580
			if(stristr($int, "INIT") == true) return "INIT";
581
			return false;
582
		}
583
		if(stristr($int, $carpinterface) == true)
584
		$found_interface=1;
585 10655b3c Scott Ullrich
	}
586 669e1adb Bill Marquette
	return;
587 591afdfd Scott Ullrich
}
588
589 167bcf84 Scott Ullrich
/*
590
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
591
 */
592
function get_pfsync_interface_status($pfsyncinterface) {
593 962f7d25 Scott Ullrich
    $result = does_interface_exist($pfsyncinterface);
594 4983ed8c Scott Ullrich
    if($result <> true) return;
595 e3939e20 Scott Ullrich
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
596 167bcf84 Scott Ullrich
    return $status;
597
}
598
599 5ccfea33 Scott Ullrich
/*
600
 * find_carp_interface($ip): return the carp interface where an ip is defined
601
 */
602
function find_carp_interface($ip) {
603 d6caad17 Scott Ullrich
    global $find_carp_ifconfig;
604
    if($find_carp_ifconfig == "") {
605
	$find_carp_ifconfig = array();
606
	$num_carp_ints = find_number_of_created_carp_interfaces();
607
	for($x=0; $x<$num_carp_ints; $x++) {
608
	    $find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
609
	}
610
    }
611
    $carps = 0;
612
    foreach($find_carp_ifconfig as $fci) {
613
	if(stristr($fci, $ip) == true)
614
	    return "carp{$carps}";
615
	$carps++;
616 5ccfea33 Scott Ullrich
    }
617
}
618
619 3962b070 Scott Ullrich
/*
620
 * setup_filter_bridge(): toggle filtering bridge
621
 */
622
function setup_filter_bridge() {
623
	global $config, $g;
624
	if(isset($config['bridge']['filteringbridge'])) {
625 3f82e64d Scott Ullrich
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=1");
626
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=1");
627 3962b070 Scott Ullrich
	} else {		
628 3f82e64d Scott Ullrich
		mwexec("/sbin/sysctl net.link.bridge.pfil_member=0");
629
		mwexec("/sbin/sysctl net.link.bridge.pfil_bridge=0");
630 3962b070 Scott Ullrich
	}
631
}
632
633 335978db Scott Ullrich
/*
634
 * find_number_of_created_bridges(): returns the number of currently created bridges
635
 */
636
function find_number_of_created_bridges() {
637
    return `/sbin/ifconfig | grep \"bridge[0-999]\:" | wc -l`;
638
}
639
640 5ccfea33 Scott Ullrich
/*
641
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
642
 */
643 a35f1242 Scott Ullrich
function add_rule_to_anchor($anchor, $rule, $label) {
644 8c8e6792 Scott Ullrich
    mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
645 5ccfea33 Scott Ullrich
}
646
647 06e2627e Scott Ullrich
/*
648
 * remove_text_from_file
649
 * remove $text from file $file
650
 */
651
function remove_text_from_file($file, $text) {
652
    global $fd_log;
653
    fwrite($fd_log, "Adding needed text items:\n");
654
    $filecontents = exec_command_and_return_text("cat " . $file);
655
    $textTMP = str_replace($text, "", $filecontents);
656
    $text .= $textTMP;
657
    fwrite($fd_log, $text . "\n");
658
    $fd = fopen($file, "w");
659
    fwrite($fd, $text);
660
    fclose($fd);
661
}
662
663
/*
664
 * add_text_to_file($file, $text): adds $text to $file.
665
 * replaces the text if it already exists.
666
 */
667
function add_text_to_file($file, $text) {
668 b63f20c3 Colin Smith
	if(file_exists($file) and is_writable($file)) {
669
		$filecontents = file($file);
670 ee3a5827 Colin Smith
		$filecontents[] = $text;
671 b63f20c3 Colin Smith
		$tmpfile = get_tmp_file();
672
		$fout = fopen($tmpfile, "w");
673
		foreach($filecontents as $line) {
674 ee3a5827 Colin Smith
			fwrite($fout, rtrim($line) . "\n");
675 b63f20c3 Colin Smith
		}
676 ee3a5827 Colin Smith
		fclose($fout);
677 b63f20c3 Colin Smith
		rename($tmpfile, $file);
678
		return true;
679
	} else {
680
		return false;
681
	}
682 06e2627e Scott Ullrich
}
683
684 b9716104 Scott Ullrich
/*
685
 *   after_sync_bump_adv_skew(): create skew values by 1S
686
 */
687
function after_sync_bump_adv_skew() {
688
	global $config, $g;
689
	$processed_skew = 1;
690
	$a_vip = &$config['virtualip']['vip'];
691
	foreach ($a_vip as $vipent) {
692
		if($vipent['advskew'] <> "") {
693
			$processed_skew = 1;
694
			$vipent['advskew'] = $vipent['advskew']+1;
695
		}
696
	}
697
	if($processed_skew == 1)
698
		write_config("After synch increase advertising skew");
699
}
700
701 06e2627e Scott Ullrich
/*
702
 * get_filename_from_url($url): converts a url to its filename.
703
 */
704
function get_filename_from_url($url) {
705 8072f087 Colin Smith
	return basename($url);
706 06e2627e Scott Ullrich
}
707
708
/*
709
 *   update_output_window: update bottom textarea dynamically.
710
 */
711
function update_output_window($text) {
712 0f66804f Scott Ullrich
    $log = ereg_replace("\n", "\\n", $text);
713
    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
714 1efaae23 Scott Ullrich
    /* ensure that contents are written out */
715
    ob_flush();    
716 06e2627e Scott Ullrich
}
717
718
/*
719
 *   get_dir: return an array of $dir
720
 */
721
function get_dir($dir) {
722 0f66804f Scott Ullrich
    $dir_array = array();
723
    $d = dir($dir);
724
    while (false !== ($entry = $d->read())) {
725 ef4550f8 Scott Ullrich
	array_push($dir_array, $entry);
726 0f66804f Scott Ullrich
    }
727
    $d->close();
728
    return $dir_array;
729 06e2627e Scott Ullrich
}
730
731
/*
732
 *   update_output_window: update top textarea dynamically.
733
 */
734
function update_status($status) {
735 ef4550f8 Scott Ullrich
    echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
736 1efaae23 Scott Ullrich
    /* ensure that contents are written out */
737
    ob_flush();    
738 06e2627e Scott Ullrich
}
739
740
/*
741
 *   exec_command_and_return_text_array: execute command and return output
742
 */
743
function exec_command_and_return_text_array($command) {
744 669e1adb Bill Marquette
	$fd = popen($command . " 2>&1 ", "r");
745
	while(!feof($fd)) {
746
		$tmp .= fread($fd,49);
747
	}
748
	fclose($fd);
749
	$temp_array = split("\n", $tmp);
750
	return $temp_array;
751 06e2627e Scott Ullrich
}
752
753
/*
754
 *   exec_command_and_return_text: execute command and return output
755
 */
756
function exec_command_and_return_text($command) {
757 ef4550f8 Scott Ullrich
    return exec_command($command);
758 06e2627e Scott Ullrich
}
759
760
/*
761
 *   exec_command_and_return_text: execute command and update output window dynamically
762
 */
763
function execute_command_return_output($command) {
764
    global $fd_log;
765 767a716e Scott Ullrich
    $lasttext = "";
766 06e2627e Scott Ullrich
    $fd = popen($command . " 2>&1 ", "r");
767
    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
768
    $counter = 0;
769
    $counter2 = 0;
770
    while(!feof($fd)) {
771
	$tmp = fread($fd, 50);
772
	$tmp1 = ereg_replace("\n","\\n", $tmp);
773
	$text = ereg_replace("\"","'", $tmp1);
774
	if($lasttext == "..") {
775
	    $text = "";
776
	    $lasttext = "";
777
	    $counter=$counter-2;
778
	} else {
779
	    $lasttext .= $text;
780
	}
781
	if($counter > 51) {
782
	    $counter = 0;
783
	    $extrabreak = "\\n";
784
	} else {
785
	    $extrabreak = "";
786
	    $counter++;
787
	}
788
	if($counter2 > 600) {
789
	    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
790
	    $counter2 = 0;
791
	} else
792
	    $counter2++;
793
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
794
    }
795
    fclose($fd);
796
}
797
798 55be70e6 Scott Ullrich
/*
799
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
800
 */
801
function convert_friendly_interface_to_real_interface_name($interface) {
802 54f4caed Scott Ullrich
    global $config;
803 a7f5febb Scott Ullrich
    $lc_interface = strtolower($interface);
804 303831c6 Scott Ullrich
    if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
805
    if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
806
    $ifdescrs = array();
807
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
808
	$ifdescrs['opt' . $j] = "opt" . $j;
809 401e59a9 Scott Ullrich
    foreach ($ifdescrs as $ifdescr => $ifname) {
810 303831c6 Scott Ullrich
	if(strtolower($ifname) == $lc_interface)
811
	    return $config['interfaces'][$ifname]['if'];
812
	if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
813 401e59a9 Scott Ullrich
	    return $config['interfaces'][$ifname]['if'];
814
    }
815
    return $interface;
816 55be70e6 Scott Ullrich
}
817
818 cc869478 Scott Ullrich
/*
819
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
820
 */
821
function convert_real_interface_to_friendly_interface_name($interface) {
822 0f66804f Scott Ullrich
    global $config;
823
    $ifdescrs = array('wan', 'lan');
824
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
825
	$ifdescrs['opt' . $j] = "opt" . $j;
826
    foreach ($ifdescrs as $ifdescr => $ifname) {
827
	$int = filter_translate_type_to_real_interface($ifname);
828
	if($ifname == $interface) return $ifname;
829
	if($int == $interface) return $ifname;
830
    }
831
    return $interface;
832 cc869478 Scott Ullrich
}
833
834 06e2627e Scott Ullrich
/*
835
 * update_progress_bar($percent): updates the javascript driven progress bar.
836
 */
837
function update_progress_bar($percent) {
838 0f66804f Scott Ullrich
    if($percent > 100) $percent = 1;
839
    echo "\n<script type=\"text/javascript\" language=\"javascript\">";
840
    echo "\ndocument.progressbar.style.width='" . $percent . "%';";
841
    echo "\n</script>";
842 06e2627e Scott Ullrich
}
843
844 b45ea709 Scott Ullrich
/*
845 76177335 Scott Ullrich
 * gather_altq_queue_stats():  gather alq queue stats and return an array that
846 b45ea709 Scott Ullrich
 *                             is queuename|qlength|measured_packets
847 fbc24b62 Colin Smith
 *                             NOTE: this command takes 5 seconds to run
848 b45ea709 Scott Ullrich
 */
849 6a153733 Scott Ullrich
function gather_altq_queue_stats($dont_return_root_queues) {
850 e90bc39f Scott Ullrich
    mwexec("/usr/bin/killall -9 pfctl");
851 9c0ad35c Scott Ullrich
    $stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
852 b45ea709 Scott Ullrich
    $stats_array = split("\n", $stats);
853
    $queue_stats = array();
854 767a716e Scott Ullrich
    $match_array = "";
855 b45ea709 Scott Ullrich
    foreach ($stats_array as $stats_line) {
856
        if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
857
            $queue_name = $match_array[1][0];
858 fccb044c Scott Ullrich
        if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
859
            $speed = $match_array[1][0];
860 e90bc39f Scott Ullrich
        if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
861
            $borrows = $match_array[1][0];
862 4bed294c Bill Marquette
        if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
863
            $suspends = $match_array[1][0];
864 04e6e7b7 Bill Marquette
        if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
865
            $drops = $match_array[1][0];
866 b45ea709 Scott Ullrich
        if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
867
            $measured = $match_array[1][0];
868 6a153733 Scott Ullrich
	    if($dont_return_root_queues == true)
869
		if(stristr($queue_name,"root_") == false)
870 122a9c39 Scott Ullrich
		    array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
871 b45ea709 Scott Ullrich
        }
872
    }
873
    return $queue_stats;
874
}
875 fa35df12 Scott Ullrich
876 fbc24b62 Colin Smith
/*
877 0ad0f98c Scott Ullrich
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
878 fbc24b62 Colin Smith
 *					 Useful for finding paths and stripping file extensions.
879
 */
880 29c3c942 Colin Smith
function reverse_strrchr($haystack, $needle)
881
{
882
               return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
883 fbc24b62 Colin Smith
}
884
885 f8891a0f Scott Ullrich
/*
886 832f1b83 Scott Ullrich
 *  backup_config_section($section): returns as an xml file string of
887
 *                                   the configuration section
888 f8891a0f Scott Ullrich
 */
889
function backup_config_section($section) {
890
    global $config;
891 6d501961 Scott Ullrich
    $new_section = &$config[$section];
892 832f1b83 Scott Ullrich
    /* generate configuration XML */
893 5ea0509e Colin Smith
    $xmlconfig = dump_xml_config($new_section, $section);
894
    $xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
895
    return $xmlconfig;
896
}
897
898 7c4990af Scott Ullrich
/*
899
 *  backup_config_section($section): returns as an xml file string of
900
 *                                   the configuration section
901
 */
902 20091784 Scott Ullrich
function backup_vip_config_section() {
903 7c4990af Scott Ullrich
    global $config;
904
    $new_section = &$config['virtualip'];
905 dd7f4560 Scott Ullrich
    foreach($new_section['vip'] as $section) {
906
	if($section['mode'] == "proxyarp") {
907 7c4990af Scott Ullrich
		unset($section);		
908
	}
909 dd7f4560 Scott Ullrich
	if($section['advskew'] <> "") {
910 afb3b079 Scott Ullrich
		$section_val = intval($section['advskew']);
911 ec2a000e Scott Ullrich
		$section_val=$section_val+100;
912 afb3b079 Scott Ullrich
		if($section_val > 255)
913
			$section_val = 255;
914
		$section['advskew'] = $section_val;
915 02ed6c8f Scott Ullrich
	}
916 dd7f4560 Scott Ullrich
	$temp['vip'][] = $section;
917 7c4990af Scott Ullrich
    }
918 1a94ea6c Scott Ullrich
    return $temp;
919 7c4990af Scott Ullrich
}
920
921 f8891a0f Scott Ullrich
/*
922
 *  restore_config_section($section, new_contents): restore a configuration section,
923
 *                                                  and write the configuration out
924
 *                                                  to disk/cf.
925
 */
926
function restore_config_section($section, $new_contents) {
927 767a716e Scott Ullrich
    global $config, $g;
928 ee096757 Scott Ullrich
    conf_mount_rw();
929 832f1b83 Scott Ullrich
    $fout = fopen("{$g['tmp_path']}/tmpxml","w");
930 014beac3 Scott Ullrich
    fwrite($fout, $new_contents);
931 832f1b83 Scott Ullrich
    fclose($fout);
932 bb4f8f8a Colin Smith
    $section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
933 832f1b83 Scott Ullrich
    $config[$section] = &$section_xml;
934
    unlink($g['tmp_path'] . "/tmpxml");
935 782c32a7 Bill Marquette
    write_config("Restored {$section} of config file (maybe from CARP partner)");
936 ee096757 Scott Ullrich
    conf_mount_ro();
937 46624b94 Scott Ullrich
    return;
938 f8891a0f Scott Ullrich
}
939
940 e99d11e3 Scott Ullrich
/*
941 c70c4e8a Colin Smith
 * http_post($server, $port, $url, $vars): does an http post to a web server
942
 *                                         posting the vars array.
943 e99d11e3 Scott Ullrich
 * written by nf@bigpond.net.au
944
 */
945
function http_post($server, $port, $url, $vars) {
946 767a716e Scott Ullrich
	global $errstr;
947 0f66804f Scott Ullrich
    $user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
948
    $urlencoded = "";
949
    while (list($key,$value) = each($vars))
950 ef4550f8 Scott Ullrich
	$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
951 0f66804f Scott Ullrich
    $urlencoded = substr($urlencoded,0,-1);
952 e99d11e3 Scott Ullrich
953 0f66804f Scott Ullrich
    $content_length = strlen($urlencoded);
954 e99d11e3 Scott Ullrich
955 0f66804f Scott Ullrich
    $headers = "POST $url HTTP/1.1
956 e99d11e3 Scott Ullrich
Accept: */*
957
Accept-Language: en-au
958
Content-Type: application/x-www-form-urlencoded
959
User-Agent: $user_agent
960
Host: $server
961
Connection: Keep-Alive
962
Cache-Control: no-cache
963
Content-Length: $content_length
964
965
";
966
967 767a716e Scott Ullrich
	$errno = "";
968 0f66804f Scott Ullrich
    $fp = fsockopen($server, $port, $errno, $errstr);
969
    if (!$fp) {
970 ef4550f8 Scott Ullrich
	return false;
971 0f66804f Scott Ullrich
    }
972 e99d11e3 Scott Ullrich
973 0f66804f Scott Ullrich
    fputs($fp, $headers);
974
    fputs($fp, $urlencoded);
975 e99d11e3 Scott Ullrich
976 0f66804f Scott Ullrich
    $ret = "";
977
    while (!feof($fp))
978 ef4550f8 Scott Ullrich
	$ret.= fgets($fp, 1024);
979 e99d11e3 Scott Ullrich
980 0f66804f Scott Ullrich
    fclose($fp);
981 e99d11e3 Scott Ullrich
982 0f66804f Scott Ullrich
    return $ret;
983 e99d11e3 Scott Ullrich
984
}
985 f8891a0f Scott Ullrich
986 ee8f4a58 Scott Ullrich
/*
987
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
988
 */
989
if (!function_exists('php_check_syntax')){
990
   function php_check_syntax($code_to_check, &$errormessage){
991 c177d6ad Scott Ullrich
	return false;
992 7197df7d Scott Ullrich
        $fout = fopen("/tmp/codetocheck.php","w");
993
        $code = $_POST['content'];
994
        $code = str_replace("<?php", "", $code);
995
        $code = str_replace("?>", "", $code);
996
        fwrite($fout, "<?php\n\n");
997 669e1adb Bill Marquette
        fwrite($fout, $code_to_check);
998 7197df7d Scott Ullrich
        fwrite($fout, "\n\n?>\n");
999
        fclose($fout);
1000
        $command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1001
        $output = exec_command($command);
1002
        if (stristr($output, "Errors parsing") == false) {
1003
            echo "false\n";
1004
            $errormessage = '';
1005
            return(false);
1006
        } else {
1007
            $errormessage = $output;
1008
            return(true);
1009
        }
1010 ee8f4a58 Scott Ullrich
    }
1011
}
1012
1013
/*
1014
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1015
 */
1016 7197df7d Scott Ullrich
if (!function_exists('php_check_syntax')){
1017
   function php_check_syntax($code_to_check, &$errormessage){
1018 c177d6ad Scott Ullrich
	return false;
1019 7197df7d Scott Ullrich
        $command = "/usr/local/bin/php -l " . $code_to_check;
1020
        $output = exec_command($command);
1021
        if (stristr($output, "Errors parsing") == false) {
1022
            echo "false\n";
1023
            $errormessage = '';
1024
            return(false);
1025
        } else {
1026
            $errormessage = $output;
1027
            return(true);
1028
        }
1029
    }
1030 ee8f4a58 Scott Ullrich
}
1031
1032 bebb9d4d Bill Marquette
/*
1033 7eb2e498 Colin Smith
 * rmdir_recursive($path,$follow_links=false)
1034 6f2e9d7f Bill Marquette
 * Recursively remove a directory tree (rm -rf path)
1035
 * This is for directories _only_
1036
 */
1037
function rmdir_recursive($path,$follow_links=false) {
1038 7eb2e498 Colin Smith
	$to_do = glob($path);
1039 ed919b11 Colin Smith
	if(!is_array($to_do)) $to_do = array($to_do);
1040
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1041
		if(file_exists($workingdir)) {
1042
			if(is_dir($workingdir)) {
1043 0fdf1eaa Colin Smith
				$dir = opendir($workingdir);
1044
				while ($entry = readdir($dir)) {
1045
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1046 ed919b11 Colin Smith
						unlink("$workingdir/$entry");
1047 0fdf1eaa Colin Smith
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
1048 ed919b11 Colin Smith
						rmdir_recursive("$workingdir/$entry");
1049 0fdf1eaa Colin Smith
				}
1050
				closedir($dir);
1051
				rmdir($workingdir);
1052 ed919b11 Colin Smith
			} elseif (is_file($workingdir)) {
1053
				unlink($workingdir);
1054
			}
1055
               	}
1056 6f2e9d7f Bill Marquette
	}
1057 0a44a421 Colin Smith
	return;
1058 6f2e9d7f Bill Marquette
}
1059
1060 1682dc1e Bill Marquette
/*
1061 27f58699 Scott Ullrich
 *     get_memory()
1062
 *     returns an array listing the amount of
1063
 *     memory installed in the hardware
1064
 *     [0]real and [1]available
1065
 */
1066
function get_memory() {
1067 b84d1b32 Scott Ullrich
	if(file_exists("/var/log/dmesg.boot")) {
1068 767a716e Scott Ullrich
		$matches = "";
1069 6562edb8 Scott Ullrich
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1070
		if (preg_match_all("/real memory  = .* \((.*) MB/", $mem, $matches))
1071
			$real = $matches[1];
1072
		if (preg_match_all("/avail memory = .* \((.*) MB/", $mem, $matches))
1073
			$avail = $matches[1];
1074
		return array($real[0],$avail[0]);
1075
	}
1076
	return array("64","64");
1077 27f58699 Scott Ullrich
}
1078
1079
1080
/*
1081
 *    safe_mkdir($path, $mode = 0755)
1082
 *    create directory if it doesn't already exist and isn't a file!
1083 1682dc1e Bill Marquette
 */
1084
function safe_mkdir($path, $mode=0755) {
1085 aaea2643 Scott Ullrich
	global $g;
1086 29f9dd52 Scott Ullrich
1087
	/* cdrom is ro. */
1088 7316a702 Colin Smith
	if($g['platform'] == "cdrom")
1089 3fb1a788 Scott Ullrich
		return false;
1090 27273870 Colin Smith
	
1091
	if (!is_file($path) && !is_dir($path))
1092
		return mkdir($path, $mode);
1093
	else
1094
		return false;
1095 1682dc1e Bill Marquette
}
1096
1097
/*
1098
 * make_dirs($path, $mode = 0755)
1099
 * create directory tree recursively (mkdir -p)
1100
 */
1101 3fb1a788 Scott Ullrich
function make_dirs($path, $mode = 0755) {
1102 cc5ae6bc Scott Ullrich
	/* is dir already created? */
1103
	if(is_dir($path)) return;
1104
	/* create directory in question */
1105 27273870 Colin Smith
	$to_create = explode("/", $path);
1106 29f9dd52 Scott Ullrich
	foreach($to_create as $tc) 
1107
	    if(!is_dir($tc))
1108 27273870 Colin Smith
		safe_mkdir($path, $mode);
1109 1682dc1e Bill Marquette
}
1110
1111 c7934653 Colin Smith
/*
1112
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1113
 */
1114 bd21e2b7 Colin Smith
function check_firmware_version($tocheck = "all", $return_php = true) {
1115 335c7b2a Colin Smith
        global $g, $config;
1116 bb4f8f8a Colin Smith
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
1117
        $xmlrpc_path = $g['xmlrpcpath'];
1118 bd21e2b7 Colin Smith
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
1119 79020a5e Colin Smith
			"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
1120
			"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
1121
			"platform" => trim(file_get_contents('/etc/platform'))
1122
		);
1123 39a7c0c3 Bill Marquette
	if($tocheck == "all") {
1124 bd21e2b7 Colin Smith
		$params = $rawparams;
1125
	} else {
1126
		foreach($tocheck as $check) {
1127
			$params['check'] = $rawparams['check'];
1128
			$params['platform'] = $rawparams['platform'];
1129
		}
1130
	}
1131 335c7b2a Colin Smith
	if($config['system']['firmware']['branch']) {
1132
		$params['branch'] = $config['system']['firmware']['branch'];
1133 52621d32 Colin Smith
	}
1134 79020a5e Colin Smith
	$xmlparams = php_value_to_xmlrpc($params);
1135
        $msg = new XML_RPC_Message('pfsense.get_firmware_version', array($xmlparams));
1136 bb4f8f8a Colin Smith
        $cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
1137 335c7b2a Colin Smith
	//$cli->setDebug(1);
1138 8ac0a4de Colin Smith
	$resp = $cli->send($msg, 10);
1139
	if(!$resp or $resp->faultCode()) {
1140
		$raw_versions = false;
1141
	} else {
1142 d1779cc4 Colin Smith
		$raw_versions = XML_RPC_decode($resp->value());
1143 8ac0a4de Colin Smith
		$raw_versions["current"] = $params;
1144
	}
1145 79020a5e Colin Smith
	return $raw_versions;
1146 c7934653 Colin Smith
}
1147
1148 12eb7056 Colin Smith
function get_disk_info() {
1149 767a716e Scott Ullrich
		$diskout = "";
1150 12eb7056 Colin Smith
        exec("df -h | grep -w '/' | awk '{ print $2, $3, $4, $5 }'", $diskout);
1151
        return explode(' ', $diskout[0]);
1152
        // $size, $used, $avail, $cap
1153 64092c34 Scott Ullrich
}
1154
1155 90fd355f Bill Marquette
/****f* pfsense-utils/display_top_tabs
1156
 * NAME
1157
 *   display_top_tabs - display tabs with rounded edges
1158
 * INPUTS
1159
 *   $text	- array of tabs
1160
 * RESULT
1161
 *   null
1162
 ******/
1163 a8726a3d Scott Ullrich
    function display_top_tabs($tab_array) {
1164
	    echo "<table cellpadding='0' cellspacing='0'>\n";
1165
	    echo " <tr height='1'>\n";
1166
	    $tabscounter = 0;
1167
	    foreach ($tab_array as $ta) {
1168
		    if($ta[1] == true) {
1169 6948fa96 Bill Marquette
			    echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\"><div id='tabactive'></div></td>\n";
1170 a8726a3d Scott Ullrich
		    } else {
1171 6948fa96 Bill Marquette
			    echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
1172 a8726a3d Scott Ullrich
		    }
1173
		    $tabscounter++;
1174
	    }
1175 0366b748 Scott Ullrich
	    echo "</tr>\n<tr>\n";
1176 a8726a3d Scott Ullrich
	    foreach ($tab_array as $ta) {
1177
		    if($ta[1] == true) {
1178 6948fa96 Bill Marquette
			    echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
1179 63586b79 Scott Ullrich
			    echo "&nbsp;&nbsp;&nbsp;";
1180 2f4809ea Bill Marquette
			    echo "<font size='-12'>&nbsp;</td>\n";
1181 a8726a3d Scott Ullrich
		    } else {
1182 6948fa96 Bill Marquette
			    echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
1183 63586b79 Scott Ullrich
			    echo "<font color='white'>{$ta[0]}</a>&nbsp;&nbsp;&nbsp;";
1184 2f4809ea Bill Marquette
			    echo "<font size='-12'>&nbsp;</td>\n";
1185 a8726a3d Scott Ullrich
		    }
1186
	    }
1187 2f4809ea Bill Marquette
	    echo "</tr>\n<tr height='5px'>\n";
1188
	    foreach ($tab_array as $ta) {
1189
		    if($ta[1] == true) {
1190
			    echo "  <td bgcolor='#EEEEEE' onClick=\"document.location='{$ta[2]}'\"></td>\n";
1191
		    } else {
1192
			    echo "  <td bgcolor='#777777' onClick=\"document.location='{$ta[2]}'\"></td>\n";
1193
		    }
1194
		    $tabscounter++;
1195
	    }
1196 a8726a3d Scott Ullrich
	    echo " </tr>\n";
1197
	    echo "</table>\n";
1198
	    
1199
	    echo "<script type=\"text/javascript\">";
1200
	    echo "NiftyCheck();\n";
1201 0366b748 Scott Ullrich
	    echo "Rounded(\"div#tabactive\",\"top\",\"#FFF\",\"#EEEEEE\",\"smooth\");\n";
1202 a8726a3d Scott Ullrich
	    for($x=0; $x<$tabscounter; $x++) 
1203 0366b748 Scott Ullrich
		    echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"#FFF\",\"#777777\",\"smooth\");\n";
1204 a8726a3d Scott Ullrich
	    echo "</script>";
1205
    }
1206 305eae3c Bill Marquette
1207
1208 90fd355f Bill Marquette
/****f* pfsense-utils/display_topbar
1209
 * NAME
1210
 *   display_topbar - top a table off with rounded edges
1211
 * INPUTS
1212
 *   $text	- (optional) Text to include in bar
1213
 * RESULT
1214
 *   null
1215
 ******/
1216 411528e9 Scott Ullrich
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {	    
1217 305eae3c Bill Marquette
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
1218
	echo "       <tr height='1'>\n";
1219 411528e9 Scott Ullrich
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
1220
	echo "		<div id='topbar'></div></td>\n";
1221 305eae3c Bill Marquette
	echo "       </tr>\n";
1222
	echo "       <tr height='1'>\n";
1223
	if ($text != "")
1224
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
1225
	else
1226
		echo "         <td height='1' class='listtopic'></td>\n";
1227
	echo "       </tr>\n";
1228
	echo "     </table>";
1229
	echo "<script type=\"text/javascript\">";
1230
	echo "NiftyCheck();\n";
1231 411528e9 Scott Ullrich
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
1232 305eae3c Bill Marquette
	echo "</script>";
1233
}
1234 730768f7 Colin Smith
1235 c615128d Scott Ullrich
/****f* pfsense-utils/generate_random_mac_address
1236 94e8082f Scott Ullrich
 * NAME
1237
 *   generate_random_mac - generates a random mac address
1238
 * INPUTS
1239
 *   none
1240
 * RESULT
1241
 *   $mac - a random mac address
1242
 ******/
1243 c615128d Scott Ullrich
function generate_random_mac_address() {
1244 e8dd289e Scott Ullrich
	$mac = "00:a0:8e";
1245
	for($x=0; $x<3; $x++) 
1246 a57a45cb Colin Smith
	    $mac .= ":" . dechex(rand(16, 255));
1247 ac1bb69d Scott Ullrich
1248 730768f7 Colin Smith
	return $mac;
1249
}
1250 94e8082f Scott Ullrich
1251 d6fbd4ca Bill Marquette
/****f* pfsense-utils/strncpy
1252
 * NAME
1253
 *   strncpy - copy strings
1254
 * INPUTS
1255
 *   &$dst, $src, $length
1256
 * RESULT
1257
 *   none
1258
 ******/
1259
function strncpy(&$dst, $src, $length) {
1260
	if (strlen($src) > $length) {
1261
		$dst = substr($src, 0, $length);
1262
	} else {
1263
		$dst = $src;
1264
	}
1265
}
1266
1267 39a85258 Scott Ullrich
/****f* pfsense-utils/reload_interfaces_sync
1268 182c30de Scott Ullrich
 * NAME
1269
 *   reload_interfaces - reload all interfaces
1270
 * INPUTS
1271
 *   none
1272
 * RESULT
1273
 *   none
1274
 ******/
1275 39a85258 Scott Ullrich
function reload_interfaces_sync() {
1276 4f1252d5 Scott Ullrich
	global $config, $g;
1277
	
1278
	if(file_exists("{$g['tmp_path']}/config.cache"))
1279
		unlink("{$g['tmp_path']}/config.cache");
1280
	
1281
	/* parse config.xml again */
1282 12886b41 Scott Ullrich
	$config = parse_config(true);
1283 a5489081 Scott Ullrich
1284 e4b6977d Scott Ullrich
	/* delete all old interface information */
1285
	$iflist = split(" ", str_replace("\n", "", `/sbin/ifconfig -l`));
1286 a5489081 Scott Ullrich
	foreach ($iflist as $ifent => $ifname) {
1287
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1288
		mwexec("/sbin/ifconfig {$ifname_real} down");
1289 01ea39c8 Scott Ullrich
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1290 a5489081 Scott Ullrich
	}
1291
1292 898f9144 Scott Ullrich
	/* set up VLAN virtual interfaces */
1293
	interfaces_vlan_configure();
1294
1295 182c30de Scott Ullrich
	/* set up LAN interface */
1296
	interfaces_lan_configure();
1297
1298
	/* set up WAN interface */
1299
	interfaces_wan_configure();
1300
1301
	/* set up Optional interfaces */
1302
	interfaces_optional_configure();
1303
        
1304
	/* set up static routes */
1305
	system_routing_configure();
1306 835c9f4a Scott Ullrich
	
1307 182c30de Scott Ullrich
	/* enable routing */
1308
	system_routing_enable();
1309 d7be682d Scott Ullrich
	
1310
	/* setup captive portal if needed */
1311 3674284c Scott Ullrich
	captiveportal_configure();
1312
	
1313
	/* bring up carp interfaces */
1314
	interfaces_carp_configure();
1315
	
1316
	/* bring up carp interfaces*/
1317
	interfaces_carp_bring_up_final();	
1318 182c30de Scott Ullrich
}
1319
1320
/****f* pfsense-utils/reload_all
1321
 * NAME
1322 39a85258 Scott Ullrich
 *   reload_all - triggers a reload of all settings
1323 182c30de Scott Ullrich
 *   * INPUTS
1324
 *   none
1325
 * RESULT
1326
 *   none
1327
 ******/
1328
function reload_all() {
1329 39a85258 Scott Ullrich
	touch("/tmp/reload_all");
1330
}
1331
1332
/****f* pfsense-utils/reload_interfaces
1333
 * NAME
1334
 *   reload_interfaces - triggers a reload of all interfaces
1335
 * INPUTS
1336
 *   none
1337
 * RESULT
1338
 *   none
1339
 ******/
1340
function reload_interfaces() {
1341
	touch("/tmp/reload_interfaces");
1342
}
1343
1344 7872051e Scott Ullrich
/****f* pfsense-utils/sync_webgui_passwords
1345
 * NAME
1346
 *   sync_webgui_passwords - syncs webgui and ssh passwords
1347
 * INPUTS
1348
 *   none
1349
 * RESULT
1350
 *   none
1351
 ******/
1352
function sync_webgui_passwords() {
1353 f7594142 Scott Ullrich
	global $config, $g;
1354 12f23f46 Scott Ullrich
	conf_mount_rw();
1355 f7594142 Scott Ullrich
	$fd = fopen("{$g['varrun_path']}/htpasswd", "w");
1356
	if (!$fd) {
1357
		printf("Error: cannot open htpasswd in system_password_configure().\n");
1358
		return 1;
1359
	}
1360
	/* set admin account */
1361 9604ac1f Scott Ullrich
	$username = $config['system']['username'];
1362 5bfc9fdf Scott Ullrich
	
1363 f7594142 Scott Ullrich
	/* set defined user account */
1364
	if($username <> "admin") {
1365
		$username = $config['system']['username'];
1366
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");
1367 5bfc9fdf Scott Ullrich
	} else {
1368
		fwrite($fd, $username . ":" . $config['system']['password'] . "\n");	
1369
	}	
1370 f7594142 Scott Ullrich
	fclose($fd);
1371
	chmod("{$g['varrun_path']}/htpasswd", 0600);	
1372 caa72e06 Scott Ullrich
	$crypted_pw = $config['system']['password'];
1373 71bee409 Scott Ullrich
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1374
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1375 f53c7cd0 Scott Ullrich
	/* sync root */
1376
	$fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
1377 72183413 Scott Ullrich
	fwrite($fd, $crypted_pw);
1378
	pclose($fd);
1379 ac21b329 Scott Ullrich
	mwexec("/usr/sbin/pw usermod -n root -s /bin/sh");
1380 72183413 Scott Ullrich
	/* sync admin */
1381
	$fd = popen("/usr/sbin/pw usermod -n admin -H 0", "w");
1382
	fwrite($fd, $crypted_pw);
1383 2c24977e Scott Ullrich
	pclose($fd);
1384 b3a88dd6 Scott Ullrich
	mwexec("/usr/sbin/pw usermod -n admin -s /etc/rc.initial");
1385 71bee409 Scott Ullrich
	mwexec("/usr/sbin/pwd_mkdb -d /etc -p /etc/master.passwd");
1386
	mwexec("/usr/sbin/pwd_mkdb -p /etc/master.passwd");
1387 12f23f46 Scott Ullrich
	conf_mount_ro();
1388 7872051e Scott Ullrich
}
1389
1390 39a85258 Scott Ullrich
/****f* pfsense-utils/reload_all_sync
1391
 * NAME
1392
 *   reload_all - reload all settings
1393
 *   * INPUTS
1394
 *   none
1395
 * RESULT
1396
 *   none
1397
 ******/
1398
function reload_all_sync() {
1399 4f1252d5 Scott Ullrich
	global $config, $g;
1400
	
1401
	if(file_exists("{$g['tmp_path']}/config.cache"))
1402
		unlink("{$g['tmp_path']}/config.cache");
1403
	
1404
	/* parse config.xml again */
1405 12886b41 Scott Ullrich
	$config = parse_config(true);
1406
1407 182c30de Scott Ullrich
	/* set up our timezone */
1408
	system_timezone_configure();
1409
1410
	/* set up our hostname */
1411
	system_hostname_configure();
1412
1413
	/* make hosts file */
1414
	system_hosts_generate();
1415
1416
	/* generate resolv.conf */
1417
	system_resolvconf_generate();
1418
1419 e4b6977d Scott Ullrich
	/* delete all old interface information */
1420
	$iflist = split(" ", str_replace("\n", "", `/sbin/ifconfig -l`));
1421 a5489081 Scott Ullrich
	foreach ($iflist as $ifent => $ifname) {
1422
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1423 653480c5 Scott Ullrich
		if($ifname_real == "lo0")
1424
		    continue;		
1425 a5489081 Scott Ullrich
		mwexec("/sbin/ifconfig {$ifname_real} down");
1426 1120ff57 Scott Ullrich
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1427 a5489081 Scott Ullrich
	}
1428
1429 898f9144 Scott Ullrich
	/* set up VLAN virtual interfaces */
1430
	interfaces_vlan_configure();
1431
1432 182c30de Scott Ullrich
	/* set up LAN interface */
1433
	interfaces_lan_configure();
1434
1435
	/* set up WAN interface */
1436
	interfaces_wan_configure();
1437
1438
	/* set up Optional interfaces */
1439
	interfaces_optional_configure();
1440
        
1441
	/* bring up carp interfaces */
1442 835c9f4a Scott Ullrich
	interfaces_carp_configure();
1443 182c30de Scott Ullrich
	
1444
	/* set up static routes */
1445
	system_routing_configure();
1446
1447
	/* enable routing */
1448
	system_routing_enable();
1449
	
1450
	/* ensure passwords are sync'd */
1451
	system_password_configure();
1452
1453
	/* start dnsmasq service */
1454
	services_dnsmasq_configure();
1455
1456
	/* start dyndns service */
1457
	services_dyndns_configure();
1458
1459
	/* start DHCP service */
1460
	services_dhcpd_configure();
1461
1462
	/* start the NTP client */
1463
	system_ntp_configure();
1464
1465
	/* start ftp proxy helpers if they are enabled */
1466
	system_start_ftp_helpers();
1467 375f907e Scott Ullrich
	
1468 a64f14a2 Scott Ullrich
	/* start the captive portal */
1469
	captiveportal_configure();
1470 721a2c10 Scott Ullrich
1471
        /* reload the filter */
1472 c7c7be3f Scott Ullrich
	filter_configure_sync();
1473 933e1032 Scott Ullrich
1474
	/* bring up carp interfaces*/
1475
	interfaces_carp_bring_up_final();
1476
1477 375f907e Scott Ullrich
	/* sync pw database */
1478
	conf_mount_rw();
1479
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1480
	conf_mount_ro();
1481 ef4a2962 Scott Ullrich
1482
	/* restart sshd */
1483
	touch("/tmp/start_sshd");
1484 375f907e Scott Ullrich
	
1485 182c30de Scott Ullrich
}
1486
1487 71bee409 Scott Ullrich
?>