Project

General

Profile

Download (19.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	pfSense-utils.inc
4
	Utilities specific to pfSense
5
	part of pfSense (www.pfSense.com)
6

    
7
	Copyright (C) 2005 Scott Ullrich (sullrich@gmail.com)
8
	All rights reserved.
9

    
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12

    
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15

    
16
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19

    
20
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31

    
32
/*
33
 * log_error: send string to syslog
34
 */
35
function log_error($error) {
36
    syslog(LOG_WARNING, $error);
37
    return;
38
}
39

    
40
/*
41
 * return_dir_as_array($dir): returns $dir contents as an array
42
 */
43
function return_dir_as_array($dir) {
44
    $dir_array = array();
45
    if (is_dir($dir)) {
46
	if ($dh = opendir($dir)) {
47
	    while (($file = readdir($dh)) !== false) {
48
		$canadd = 0;
49
		if($file == ".") $canadd = 1;
50
		if($file == "..") $canadd = 1;
51
		if($canadd == 0)
52
		    array_push($dir_array, $file);
53
	    }
54
	    closedir($dh);
55
	}
56
    }
57
    return $dir_array;
58
}
59

    
60
/*
61
 * enable_hardware_offloading() enables hardware features of nics if they are supported
62
 */
63
function enable_hardware_offloading($interface) {
64
    $supported_ints = array('fxp');
65
    foreach($supported_ints as $int) {
66
	if(stristr($interface,$int) != false) {
67
	    mwexec("/sbin/ifconfig $interface link0");
68
	}
69
    }
70
}
71

    
72
/*
73
 * return_filename_as_array($filename): returns $filename contents as a string
74
 */
75
function return_filename_as_array($filename) {
76
    $file = array();
77
    if(file_exists($filename)) {
78
        $text = return_filename_as_string($filename);
79
        $text_split = split("\n", $text);
80

    
81
        /* Strip out comments */
82
        while (($line = array_shift($text_split)) != NULL) {
83
            if(strpos($line, "#") !== 0)
84
                array_push($file, $line);
85
        }
86
    }
87
    return $file;
88
}
89

    
90
/*
91
 * return_dir_as_array($filename): returns $filename contents as a string
92
 */
93
function return_filename_as_string($filename) {
94
    $tmp = "";
95
    $fd = fopen($filename, "r");
96
    if(!$fd) {
97
	log_error("Could not open {$filename}");
98
	return;
99
    }
100
    while(!feof($fd)) {
101
	$tmp .= fread($fd,49);
102
    }
103
    fclose($fd);
104
    return $tmp;
105
}
106

    
107
/*
108
 * is_carp_defined: returns true if carp is detected in kernel
109
 */
110
function is_carp_defined() {
111
	/* is carp compiled into the kernel and userland? */
112
	$command = "/sbin/sysctl -a | grep carp";
113
	$fd = popen($command . " 2>&1 ", "r");
114
	if(!$fd) {
115
		log_error("Warning, could not execute command {$command}");
116
		return 0;
117
	}
118
	while(!feof($fd)) {
119
		    $tmp .= fread($fd,49);
120
	}
121
	fclose($fd);
122

    
123
	if($tmp == "")
124
		return false;
125
	else
126
		return true;
127
}
128

    
129
/*
130
 * find_number_of_created_carp_interfaces() returns the number of currently created carp interfaces
131
 */
132
function find_number_of_created_carp_interfaces() {
133
	$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
134
	$fd = popen($command . " 2>&1 ", "r");
135
	if(!$fd) {
136
		log_error("Warning, could not execute command {$command}");
137
		return 0;
138
	}
139
	while(!feof($fd)) {
140
		    $tmp .= fread($fd,49);
141
	}
142
	fclose($fd);
143
	$tmp = intval($tmp);
144
	return $tmp;
145
}
146

    
147
/*
148
 * link_ip_to_carp_interface($ip): finds where a carp interface links to.
149
*/
150
function link_ip_to_carp_interface($ip) {
151
	global $config;
152
	if($ip == "") return;
153
        $i = 0;
154

    
155
        $ifdescrs = array('wan', 'lan');
156
        for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
157
                $ifdescrs['opt' . $j] = "opt" . $j;
158
        }
159

    
160
	$ft = split("\.", $ip);
161
	$ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
162

    
163
	$carp_ints = "";
164
	$num_carp_ints = find_number_of_created_carp_interfaces();
165
        foreach ($ifdescrs as $ifdescr => $ifname) {
166
                for($x=0; $x<$num_carp_ints; $x++) {
167
                        $carp_int = "carp{$x}";
168
			$carp_ip = find_interface_ip($carp_int);
169
			$carp_ft = split("\.", $carp_ip);
170
			$carp_ft_ip = $carp_ft[0] . "." . $carp_ft[1] . "." . $carp_ft[2] . ".";
171
                        $result = does_interface_exist($carp_int);
172
                        if($result <> true) break;
173
                        $interface = filter_opt_interface_to_real($ifname);
174
			if($ft_ip == $carp_ft_ip)
175
			    if(stristr($carp_ints,$carp_int) == false)
176
				$carp_ints .= " " . $carp_int;
177
                }
178
        }
179
	return $carp_ints;
180
}
181

    
182

    
183
/*
184
 * exec_command($command): execute command return string of result
185
 */
186
function exec_command($command) {
187
            $counter = 0;
188
            $tmp = "";
189
            $fd = popen($command . " 2>&1 ", "r");
190
            while(!feof($fd)) {
191
                        $tmp .= fread($fd,49);
192
            }
193
            fclose($fd);
194
            return $tmp;
195
}
196

    
197
/*
198
 * does_interface_exist($interface): return true or false if a interface is detected.
199
 */
200
function does_interface_exist($interface) {
201
    $ints = exec_command("/sbin/ifconfig -l");
202
    if(stristr($ints, $interface) !== false)
203
	return true;
204
    else
205
	return false;
206
}
207

    
208
/*
209
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
210
 */
211
function convert_ip_to_network_format($ip, $subnet) {
212
    $ipsplit = split('[.]', $ip);
213
    $string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
214
    return $string;
215
}
216

    
217
/*
218
 * find_interface_ip($interface): return the interface ip (first found)
219
 */
220
function find_interface_ip($interface) {
221
    if(does_interface_exist($interface) == false) return;
222
    $ip = exec_command("/sbin/ifconfig {$interface} | /usr/bin/grep -w \"inet\" | /usr/bin/cut -d\" \" -f 2");
223
    $ip = str_replace("\n","",$ip);
224
    return $ip;
225
}
226

    
227
function filter_opt_interface_to_real($opt) {
228
	global $config;
229
	return $config['interfaces'][$opt]['if'];
230
}
231

    
232
function filter_get_opt_interface_descr($opt) {
233
	global $config;
234
	return $config['interfaces'][$opt]['descr'];
235
}
236

    
237
function get_friendly_interface_list_as_array() {
238
	global $config;
239
	$ints = array();
240
	$i = 0;
241
	$ifdescrs = array('wan', 'lan');
242
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
243
		$ifdescrs['opt' . $j] = "opt" . $j;
244
	}
245
	$ifdescrs = get_interface_list();
246
	foreach ($ifdescrs as $ifdescr => $ifname) {
247
	    array_push($ints,$ifdescr);
248
	}
249
	return $ints;
250
}
251

    
252
/*
253
 * find_ip_interface($ip): return the interface where an ip is defined
254
 */
255
function find_ip_interface($ip) {
256
	global $config;
257
	$i = 0;
258
	$ifdescrs = array('wan', 'lan');
259
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
260
		$ifdescrs['opt' . $j] = "opt" . $j;
261
	}
262
	foreach ($ifdescrs as $ifdescr => $ifname) {
263
	    $int = filter_translate_type_to_real_interface($ifname);
264
	    $ifconfig = exec_command("/sbin/ifconfig {$int}");
265
	    if(stristr($ifconfig,$ip) <> false)
266
		return $int;
267
	}
268
	return false;
269
}
270

    
271
/*
272
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
273
 */
274
function get_carp_interface_status($carpinterface) {
275
    $result = does_interface_exist($carpinterface);
276
    if($result <> true) return false;
277
    $status = exec_command("/sbin/ifconfig {$carpinterface} | /usr/bin/grep \"carp:\" | /usr/bin/cut -d\" \" -f2");
278
    return $status;
279
}
280

    
281
/*
282
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
283
 */
284
function get_pfsync_interface_status($pfsyncinterface) {
285
    $result = does_interface_exist($pfsyncinterface);
286
    if($result <> true) return;
287
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
288
    return $status;
289
}
290

    
291
/*
292
 * find_carp_interface($ip): return the carp interface where an ip is defined
293
 */
294
function find_carp_interface($ip) {
295
    $num_carp_ints = find_number_of_created_carp_interfaces();
296
    for($x=0; $x<$num_carp_ints; $x++) {
297
        $result = does_interface_exist("carp{$x}");
298
	if($result <> true) return;
299
	$ifconfig = exec_command("/sbin/ifconfig carp{$x}");
300
	if(stristr($ifconfig,$ip))
301
	    return "carp" . $x;
302
    }
303
}
304

    
305
/*
306
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
307
 */
308
function add_rule_to_anchor($anchor, $rule, $label) {
309
    mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
310
}
311

    
312
/*
313
 * remove_text_from_file
314
 * remove $text from file $file
315
 */
316
function remove_text_from_file($file, $text) {
317
    global $fd_log;
318
    fwrite($fd_log, "Adding needed text items:\n");
319
    $filecontents = exec_command_and_return_text("cat " . $file);
320
    $textTMP = str_replace($text, "", $filecontents);
321
    $text .= $textTMP;
322
    fwrite($fd_log, $text . "\n");
323
    $fd = fopen($file, "w");
324
    fwrite($fd, $text);
325
    fclose($fd);
326
}
327

    
328
/*
329
 * lookup pkg array id#
330
 */
331
function get_pkg_id($pkg_name) {
332
            global $config;
333
            global $pkg_config;
334
            $i=0;
335
            foreach ($config['installedpackages']['package'] as $pkg) {
336
                        if($pkg['name'] == $pkg_name) return $i;
337
                        $i++;
338
            }
339
            return -1;
340
}
341

    
342
/*
343
 *  get_latest_package_version($pkgname): get current version of a package.
344
 *  returns latest package version
345
 */
346
function get_latest_package_version($pkg_name) {
347
    global $g;
348
    fetch_latest_pkg_config();
349
    $pkg_config = parse_xml_config_pkg("{$g['tmp_path']}/pkg_config.xml", "pfsensepkgs");
350
    foreach($pkg_config['packages']['package'] as $pkg) {
351
	if($pkg['name'] == $pkg_name) {
352
	    return $pkg['version'];
353
	}
354
    }
355
    return;
356
}
357

    
358
/*
359
 * Lookup pkg_id in pkg_config.xml
360
 */
361
function get_available_pkg_id($pkg_name) {
362
    fetch_latest_pkg_config();
363
    $pkg_config = parse_xml_config_pkg("{$g['tmp_path']}/pkg_config.xml", "pfsensepkgs");
364
    $id = 0;
365
    foreach($pkg_config as $pkg) {
366
	if($pkg_config['name'] == $pkg_name) {
367
	    return $id;
368
	}
369
	$id++;
370
    }
371
    return;
372
}
373

    
374
/*
375
 * fetch_latest_pkg_config: download the latest pkg_config.xml to /tmp/ directory
376
 */
377
function fetch_latest_pkg_config() {
378
    global $g;
379
    if(!file_exists("{$g['tmp_path']}/pkg_config.xml")) {
380
	mwexec("/usr/bin/fetch -o {$g['tmp_path']}/pkg_config.xml {$g['pkg_config_location']}");
381
	if(!file_exists("{$g['tmp_path']}/pkg_config.xml")) {
382
	    print_info_box_np("Could not download pkg_config.xml from pfSense.com.  Check your DNS settings.");
383
	    die;
384
	}
385
    }
386
    return;
387
}
388

    
389
/*
390
 * add_text_to_file($file, $text): adds $text to $file.
391
 * replaces the text if it already exists.
392
 */
393
function add_text_to_file($file, $text) {
394
    global $fd_log;
395
    fwrite($fd_log, "Adding needed text items:\n");
396
    $filecontents = exec_command_and_return_text("cat " . $file);
397
    $filecontents = str_replace($text, "", $filecontents);
398
    $text = $filecontents . $text;
399
    fwrite($fd_log, $text . "\n");
400
    $fd = fopen($file, "w");
401
    fwrite($fd, $text . "\n");
402
    fclose($fd);
403
}
404

    
405
/*
406
 * get_filename_from_url($url): converts a url to its filename.
407
 */
408
function get_filename_from_url($url) {
409
            $filenamesplit = split("/", $url);
410
            foreach($filenamesplit as $fn) $filename = $fn;
411
            return $filename;
412
}
413

    
414
/*
415
 *   update_output_window: update bottom textarea dynamically.
416
 */
417
function update_output_window($text) {
418
            $log = ereg_replace("\n", "\\n", $text);
419
            echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
420
}
421

    
422
/*
423
 *   get_dir: return an array of $dir
424
 */
425
function get_dir($dir) {
426
            $dir_array = array();
427
            $d = dir($dir);
428
            while (false !== ($entry = $d->read())) {
429
                        array_push($dir_array, $entry);
430
            }
431
            $d->close();
432
            return $dir_array;
433
}
434

    
435
/*
436
 *   update_output_window: update top textarea dynamically.
437
 */
438
function update_status($status) {
439
            echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
440
}
441

    
442
/*
443
 *   exec_command_and_return_text_array: execute command and return output
444
 */
445
function exec_command_and_return_text_array($command) {
446
            $counter = 0;
447
            $fd = popen($command . " 2>&1 ", "r");
448
            while(!feof($fd)) {
449
                        $tmp .= fread($fd,49);
450
            }
451
            fclose($fd);
452
            $temp_array = split("\n", $tmp);
453
            return $tmp_array;
454
}
455

    
456
/*
457
 *   exec_command_and_return_text: execute command and return output
458
 */
459
function exec_command_and_return_text($command) {
460
	    return exec_command($command);
461
}
462

    
463
/*
464
 *   exec_command_and_return_text: execute command and update output window dynamically
465
 */
466
function execute_command_return_output($command) {
467
    global $fd_log;
468
    $fd = popen($command . " 2>&1 ", "r");
469
    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
470
    $counter = 0;
471
    $counter2 = 0;
472
    while(!feof($fd)) {
473
	$tmp = fread($fd, 50);
474
	$tmp1 = ereg_replace("\n","\\n", $tmp);
475
	$text = ereg_replace("\"","'", $tmp1);
476
	if($lasttext == "..") {
477
	    $text = "";
478
	    $lasttext = "";
479
	    $counter=$counter-2;
480
	} else {
481
	    $lasttext .= $text;
482
	}
483
	if($counter > 51) {
484
	    $counter = 0;
485
	    $extrabreak = "\\n";
486
	} else {
487
	    $extrabreak = "";
488
	    $counter++;
489
	}
490
	if($counter2 > 600) {
491
	    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
492
	    $counter2 = 0;
493
	} else
494
	    $counter2++;
495
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
496
    }
497
    fclose($fd);
498
}
499

    
500
/*
501
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
502
 */
503
function convert_friendly_interface_to_real_interface_name($interface) {
504
    return $config['interfaces'][$interface]['if'];
505
}
506

    
507
/*
508
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
509
 */
510
function convert_real_interface_to_friendly_interface_name($interface) {
511
	global $config;
512
	$i = 0;
513
	$ifdescrs = array('wan', 'lan');
514
	for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
515
		$ifdescrs['opt' . $j] = "opt" . $j;
516
	}
517
	foreach ($ifdescrs as $ifdescr => $ifname) {
518
	    $int = filter_translate_type_to_real_interface($ifname);
519
	    if($int == $interface) return $ifname;
520
	}
521
	return $interface;
522
}
523

    
524
/*
525
 * update_progress_bar($percent): updates the javascript driven progress bar.
526
 */
527
function update_progress_bar($percent) {
528
            if($percent > 100) $percent = 1;
529
            echo "\n<script type=\"text/javascript\" language=\"javascript\">";
530
            echo "\ndocument.progressbar.style.width='" . $percent . "%';";
531
            echo "\n</script>";
532
}
533

    
534
/*
535
 * resync_all_package_configs_bootup() Force packages to setup their configuration and rc.d files at bootup.
536
 * This function also prints output to the terminal indicating progress.
537
 */
538
function resync_all_package_configs_bootup($show_message) {
539
    global $config;
540
    log_error("Resyncing configuration for all packages.");
541
    if(!$config['installedpackages']['package']) return;
542
    foreach($config['installedpackages']['package'] as $package) {
543
	if($show_message == true) print "Syncing " . $package['name'] . ".\n";
544
        if(!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
545
	    if($show_message == true) print "Fetching " . $package['configurationfile'] . ".\n";
546
	    log_error("Fetching missing configuration XML for " . $package['name']);
547
	    system("/usr/bin/fetch -o /usr/local/pkg/" . $package['configurationfile'] . " http://www.pfsense.com/packages/config/" . $package['configurationfile']);
548
        }
549
	$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
550
        if($pkg_config['custom_php_command_before_form'] <> "") eval($pkg_config['custom_php_command_before_form']);
551
	if($pkg_config['custom_php_resync_config_command'] <> "") eval($pkg_config['custom_php_resync_config_command']);
552
	if($show_message == true) print "Synced " . $package['name'] . ".\n";
553
	if($pkg_config['additional_files_needed'] != "") {
554
		foreach($pkg_config['additional_files_needed']['item'] as $item) {
555
			$pkg_name = strrchr($item, "/");
556
			if(!preg_match("/.xml/i", $pkg_name)) break;
557
			if(!file_exists("/usr/local/pkg/" . $pkg_name)) {
558
				if($show_message == true) print "Fetching " . $pkg_name . ".\n";
559
				log_error("Fetching missing configuration XML for " . $pkg_name);
560
				system("/usr/bin/fetch -o /usr/local/pkg/" . $pkg_name . " " . $item);
561
			}
562
			$item_config = parse_xml_config_pkg("/usr/local/pkg" . $pkg_name, "packagegui");
563
			if($show_message == true) print "Syncing " . $item_config['name'] . ".\n";
564
			if($item_config['custom_php_command_before_form'] <> "") eval($item_config['custom_php_command_before_form']);
565
			if($item_config['custom_php_resync_config_command'] <> "") eval($item_config['custom_php_resync_config_command']);
566
			if($show_message == true) print "Synced " . $item_config['name'] . ".\n";
567
		}
568
	}
569
    }
570
}
571

    
572
/*
573
 * sweep_package_processes() Periodically kill a package's unnecessary processes that may still be running (a server that does not automatically timeout, for example)
574
 */
575
function sweep_package_processes() {
576
    global $config;
577
    if(!$config['installedpackages']['package']) return;
578
    foreach($config['installedpackages']['package'] as $package) {
579
        $pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
580
        if($pkg_config['swept_processes'] <> "") {
581
                mwexec("killall" . $pkg_config['swept_processes']);
582
                log_error("Killed " . $package['name'] . "'s unnecessary processes.");
583
        }           
584
    }
585
} 
586

    
587
/*
588
 * gather_altq_queue_stats():  gather alq queue stats and return an array that
589
 *                             is queuename|qlength|measured_packets
590
 *                             NOTE: this commandt takes 5 seconds to run
591
 */
592
function gather_altq_queue_stats($dont_return_root_queues) {
593
    mwexec("/usr/bin/killall -9 pfctl");
594
    $stats = `/sbin/pfctl -vvsq & sleep 5;killall pfctl 2>/dev/null`;
595
    $stats_array = split("\n", $stats);
596
    $queue_stats = array();
597
    foreach ($stats_array as $stats_line) {
598
        if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
599
            $queue_name = $match_array[1][0];
600
        if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
601
            $speed = $match_array[1][0];
602
        if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
603
            $borrows = $match_array[1][0];
604
        if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
605
            $suspends = $match_array[1][0];
606
        if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
607
            $drops = $match_array[1][0];
608
        if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
609
            $measured = $match_array[1][0];
610
	    if($dont_return_root_queues == true)
611
		if(stristr($queue_name,"root_") == false)
612
		    array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|${drops}");
613
        }
614
    }
615
    return $queue_stats;
616
}
617
?>
(9-9/14)