Project

General

Profile

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

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

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

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

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

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

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

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

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

    
77
/*
78
 * return_filename_as_array($filename): returns $filename contents as a string
79
 */
80
function return_filename_as_array($filename) {
81
    $file = array();
82
    if(file_exists($filename)) {
83
        $text = return_filename_as_string($filename);
84
        $text_split = split("\n", $text);
85

    
86
        /* Strip out comments */
87
        while (($line = array_shift($text_split)) != NULL) {
88
            if(strpos($line, "#") !== 0)
89
                array_push($file, $line);
90
        }
91
    }
92
    return $file;
93
}
94

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

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

    
128
    if($tmp == "")
129
	return false;
130
    else
131
	return true;
132
}
133

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

    
152
/*
153
 * link_ip_to_carp_interface($ip): finds where a carp interface links to.
154
*/
155
function link_ip_to_carp_interface($ip) {
156
    global $config;
157
    if($ip == "") return;
158
    $i = 0;
159

    
160
    $ifdescrs = array('wan', 'lan');
161
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
162
	$ifdescrs['opt' . $j] = "opt" . $j;
163
    }
164

    
165
    $ft = split("\.", $ip);
166
    $ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
167

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

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

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

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

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

    
231
function guess_interface_from_ip($ipaddress) {
232
    $ints = `/sbin/ifconfig -l`;
233
    $ints_split = split(" ", $ints);
234
    $ip_subnet_split = split("\.", $ipaddress);
235
    $ip_subnet = $ip_subnet_split[0] . "." . $ip_subnet_split[1] . "." . $ip_subnet_split[2] . ".";
236
    foreach($ints_split as $int) {
237
        $ip = find_interface_ip($int);
238
        $ip_split = split("\.", $ip);
239
        $ip_tocheck = $ip_split[0] . "." . $ip_split[1] . "." . $ip_split[2] . ".";
240
        if(stristr($ip_tocheck, $ip_subnet) != false) return $int;
241
    }
242
}
243

    
244
function filter_opt_interface_to_real($opt) {
245
    global $config;
246
    return $config['interfaces'][$opt]['if'];
247
}
248

    
249
function filter_get_opt_interface_descr($opt) {
250
    global $config;
251
    return $config['interfaces'][$opt]['descr'];
252
}
253

    
254
function get_friendly_interface_list_as_array() {
255
    global $config;
256
    $ints = array();
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
    $ifdescrs = get_interface_list();
263
    foreach ($ifdescrs as $ifdescr => $ifname) {
264
	array_push($ints,$ifdescr);
265
    }
266
    return $ints;
267
}
268

    
269
/*
270
 * find_ip_interface($ip): return the interface where an ip is defined
271
 */
272
function find_ip_interface($ip) {
273
    global $config;
274
    $i = 0;
275
    $ifdescrs = array('wan', 'lan');
276
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
277
	$ifdescrs['opt' . $j] = "opt" . $j;
278
    }
279
    foreach ($ifdescrs as $ifdescr => $ifname) {
280
	$int = filter_translate_type_to_real_interface($ifname);
281
	$ifconfig = exec_command("/sbin/ifconfig {$int}");
282
	if(stristr($ifconfig,$ip) <> false)
283
	    return $int;
284
    }
285
    return false;
286
}
287

    
288
/*
289
 *  filter_translate_type_to_real_interface($interface): returns the real interface name
290
 *                                                       for a friendly interface.  ie: wan
291
 */
292
function filter_translate_type_to_real_interface($interface) {
293
    global $config;
294
    return $config['interfaces'][$interface]['if'];
295
}
296

    
297
/*
298
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
299
 */
300
function get_carp_interface_status($carpinterface) {
301
    $result = does_interface_exist($carpinterface);
302
    if($result <> true) return false;
303
    $status = exec_command("/sbin/ifconfig {$carpinterface} | /usr/bin/grep \"carp:\" | /usr/bin/cut -d\" \" -f2");
304
    return $status;
305
}
306

    
307
/*
308
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
309
 */
310
function get_pfsync_interface_status($pfsyncinterface) {
311
    $result = does_interface_exist($pfsyncinterface);
312
    if($result <> true) return;
313
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
314
    return $status;
315
}
316

    
317
/*
318
 * find_carp_interface($ip): return the carp interface where an ip is defined
319
 */
320
function find_carp_interface($ip) {
321
    $num_carp_ints = find_number_of_created_carp_interfaces();
322
    for($x=0; $x<$num_carp_ints; $x++) {
323
        $result = does_interface_exist("carp{$x}");
324
	if($result <> true) return;
325
	$ifconfig = exec_command("/sbin/ifconfig carp{$x}");
326
	if(stristr($ifconfig,$ip))
327
	    return "carp" . $x;
328
    }
329
}
330

    
331
/*
332
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
333
 */
334
function add_rule_to_anchor($anchor, $rule, $label) {
335
    mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
336
}
337

    
338
/*
339
 * remove_text_from_file
340
 * remove $text from file $file
341
 */
342
function remove_text_from_file($file, $text) {
343
    global $fd_log;
344
    fwrite($fd_log, "Adding needed text items:\n");
345
    $filecontents = exec_command_and_return_text("cat " . $file);
346
    $textTMP = str_replace($text, "", $filecontents);
347
    $text .= $textTMP;
348
    fwrite($fd_log, $text . "\n");
349
    $fd = fopen($file, "w");
350
    fwrite($fd, $text);
351
    fclose($fd);
352
}
353

    
354
/*
355
 *  is_package_installed($packagename): returns 1 if a package is installed, 0 otherwise.
356
 */
357
function is_package_installed($packagename) {
358
    global $config;
359
    if($config['installedpackages']['package'] <> "")
360
	foreach ($config['installedpackages']['package'] as $pkg) {
361
	    if($pkg['name'] == $packagename) return 1;
362
	}
363
    return 0;
364
}
365

    
366
/*
367
 * lookup pkg array id#
368
 */
369
function get_pkg_id($pkg_name) {
370
    global $config;
371
    global $pkg_config;
372
    $i=0;
373
    if(is_array($config['installedpackages']['package']))
374
	foreach ($config['installedpackages']['package'] as $pkg) {
375
	    if($pkg['name'] == $pkg_name) return $i;
376
	    $i++;
377
	}
378
    return -1;
379
}
380

    
381
/*
382
 *  get_latest_package_version($pkgname): Get current version of a package. Returns latest package version or false
383
 *  					  if package isn't defined in the currently used pkg_config.xml.
384
 */
385
function get_latest_package_version($pkg_name) {
386
    global $g;
387
    fetch_latest_pkg_config();
388
    $pkg_config = parse_xml_config_pkg("{$g['tmp_path']}/pkg_config.xml", "pfsensepkgs");
389
    foreach($pkg_config['packages']['package'] as $pkg) {
390
	if($pkg['name'] == $pkg_name) {
391
	    return $pkg['version'];
392
	}
393
    }
394
    return false;
395
}
396

    
397
/*
398
 * Lookup pkg_id in pkg_config.xml
399
 */
400
function get_available_pkg_id($pkg_name) {
401
    fetch_latest_pkg_config();
402
    $pkg_config = parse_xml_config_pkg("{$g['tmp_path']}/pkg_config.xml", "pfsensepkgs");
403
    $id = 0;
404
    foreach($pkg_config as $pkg) {
405
	if($pkg_config['name'] == $pkg_name) {
406
	    return $id;
407
	}
408
	$id++;
409
    }
410
    return;
411
}
412

    
413
/*
414
 * fetch_latest_pkg_config: download the latest pkg_config.xml to /tmp/ directory
415
 */
416
function fetch_latest_pkg_config() {
417
    global $g;
418
    global $config;
419
    if(!file_exists("{$g['tmp_path']}/pkg_config.xml")) {
420
	$pkg_config_location = $g['pkg_config_location'];
421
	$pkg_config_base_url = $g['pkg_config_base_url'];
422
	if(isset($config['system']['alt_pkgconfig_url']['enabled'])) {
423
	    $pkg_config_location = $config['system']['alt_pkgconfig_url']['pkgconfig_base_url'] . $config['system']['alt_pkgconfig_url']['pkgconfig_filename'];
424
	    $pkg_config_base_url = $config['system']['alt_pkgconfig_url']['pkgconfig_base_url'];
425
	}
426
	mwexec("/usr/bin/fetch -o {$g['tmp_path']}/pkg_config.xml {$pkg_config_location}");
427
	if(!file_exists("{$g['tmp_path']}/pkg_config.xml")) {
428
	    print_info_box_np("Could not download pkg_config.xml from " . $pkg_config_base_url . ". Check your DNS settings.");
429
	    die;
430
    	}
431
    }
432
    return;
433
}
434

    
435
/*
436
 * add_text_to_file($file, $text): adds $text to $file.
437
 * replaces the text if it already exists.
438
 */
439
function add_text_to_file($file, $text) {
440
    global $fd_log;
441
    fwrite($fd_log, "Adding needed text items:\n");
442
    $filecontents = exec_command_and_return_text("cat " . $file);
443
    $filecontents = str_replace($text, "", $filecontents);
444
    $text = $filecontents . $text;
445
    fwrite($fd_log, $text . "\n");
446
    $fd = fopen($file, "w");
447
    fwrite($fd, $text . "\n");
448
    fclose($fd);
449
}
450

    
451
/*
452
 * get_filename_from_url($url): converts a url to its filename.
453
 */
454
function get_filename_from_url($url) {
455
    $filenamesplit = split("/", $url);
456
    foreach($filenamesplit as $fn) $filename = $fn;
457
    return $filename;
458
}
459

    
460
/*
461
 *   update_output_window: update bottom textarea dynamically.
462
 */
463
function update_output_window($text) {
464
    $log = ereg_replace("\n", "\\n", $text);
465
    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
466
}
467

    
468
/*
469
 *   get_dir: return an array of $dir
470
 */
471
function get_dir($dir) {
472
    $dir_array = array();
473
    $d = dir($dir);
474
    while (false !== ($entry = $d->read())) {
475
	array_push($dir_array, $entry);
476
    }
477
    $d->close();
478
    return $dir_array;
479
}
480

    
481
/*
482
 *   update_output_window: update top textarea dynamically.
483
 */
484
function update_status($status) {
485
    echo "\n<script language=\"JavaScript\">document.forms[0].status.value=\"" . $status . "\";</script>";
486
}
487

    
488
/*
489
 *   exec_command_and_return_text_array: execute command and return output
490
 */
491
function exec_command_and_return_text_array($command) {
492
    $counter = 0;
493
    $fd = popen($command . " 2>&1 ", "r");
494
    while(!feof($fd)) {
495
	$tmp .= fread($fd,49);
496
    }
497
    fclose($fd);
498
    $temp_array = split("\n", $tmp);
499
    return $tmp_array;
500
}
501

    
502
/*
503
 *   exec_command_and_return_text: execute command and return output
504
 */
505
function exec_command_and_return_text($command) {
506
    return exec_command($command);
507
}
508

    
509
/*
510
 *   exec_command_and_return_text: execute command and update output window dynamically
511
 */
512
function execute_command_return_output($command) {
513
    global $fd_log;
514
    $fd = popen($command . " 2>&1 ", "r");
515
    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
516
    $counter = 0;
517
    $counter2 = 0;
518
    while(!feof($fd)) {
519
	$tmp = fread($fd, 50);
520
	$tmp1 = ereg_replace("\n","\\n", $tmp);
521
	$text = ereg_replace("\"","'", $tmp1);
522
	if($lasttext == "..") {
523
	    $text = "";
524
	    $lasttext = "";
525
	    $counter=$counter-2;
526
	} else {
527
	    $lasttext .= $text;
528
	}
529
	if($counter > 51) {
530
	    $counter = 0;
531
	    $extrabreak = "\\n";
532
	} else {
533
	    $extrabreak = "";
534
	    $counter++;
535
	}
536
	if($counter2 > 600) {
537
	    echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"\";</script>";
538
	    $counter2 = 0;
539
	} else
540
	    $counter2++;
541
	echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = this.document.forms[0].output.value + \"" . $text . $extrabreak .  "\"; f('output'); </script>";
542
    }
543
    fclose($fd);
544
}
545

    
546
/*
547
 * convert_friendly_interface_to_real_interface_name($interface): convert WAN to FXP0
548
 */
549
function convert_friendly_interface_to_real_interface_name($interface) {
550
    global $config;
551
    $lc_interface = strtolower($interface);
552
    if($lc_interface == "lan") return $config['interfaces']['lan']['if'];
553
    if($lc_interface == "wan") return $config['interfaces']['wan']['if'];
554
    $i = 0;
555
    $ifdescrs = array();
556
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
557
	$ifdescrs['opt' . $j] = "opt" . $j;
558
    foreach ($ifdescrs as $ifdescr => $ifname) {
559
	if(strtolower($ifname) == $lc_interface)
560
	    return $config['interfaces'][$ifname]['if'];
561
	if(strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface)
562
	    return $config['interfaces'][$ifname]['if'];
563
    }
564
    return $interface;
565
}
566

    
567
/*
568
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
569
 */
570
function convert_real_interface_to_friendly_interface_name($interface) {
571
    global $config;
572
    $i = 0;
573
    $ifdescrs = array('wan', 'lan');
574
    for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++)
575
	$ifdescrs['opt' . $j] = "opt" . $j;
576
    foreach ($ifdescrs as $ifdescr => $ifname) {
577
	$int = filter_translate_type_to_real_interface($ifname);
578
	if($ifname == $interface) return $ifname;
579
	if($int == $interface) return $ifname;
580
    }
581
    return $interface;
582
}
583

    
584
/*
585
 * update_progress_bar($percent): updates the javascript driven progress bar.
586
 */
587
function update_progress_bar($percent) {
588
    if($percent > 100) $percent = 1;
589
    echo "\n<script type=\"text/javascript\" language=\"javascript\">";
590
    echo "\ndocument.progressbar.style.width='" . $percent . "%';";
591
    echo "\n</script>";
592
}
593

    
594
/*
595
 * resync_all_package_configs() Force packages to setup their configuration and rc.d files.
596
 * This function may also print output to the terminal indicating progress.
597
 */
598
function resync_all_package_configs($show_message = false) {
599
    global $config;
600
    $i = 0;
601
    log_error("Resyncing configuration for all packages.");
602
    if(!$config['installedpackages']['package']) return;
603
    if($show_message == true) print "Syncing packages:";
604
    foreach($config['installedpackages']['package'] as $package) {
605
	if($show_message == true) print " " . $package['name'];
606
	sync_package($i, true, true);
607
	$i++;
608
    }
609
    if($show_message == true) print ".\n";
610
}
611

    
612
/*
613
 * sweep_package_processes(): Periodically kill a package's unnecessary processes
614
 *			      that may still be running (a server that does not automatically timeout, for example)
615
 */
616
function sweep_package_processes() {
617
    global $config;
618
    if(!$config['installedpackages']['package']) return;
619
    foreach($config['installedpackages']['package'] as $package) {
620
        $pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
621
        if($pkg_config['swept_processes'] <> "") {
622
            mwexec("/usr/bin/killall " . $pkg_config['swept_processes']);
623
            log_error("Killed " . $package['name'] . "'s unnecessary processes.");
624
        }
625
    }
626
}
627

    
628
/*
629
 * gather_altq_queue_stats():  gather alq queue stats and return an array that
630
 *                             is queuename|qlength|measured_packets
631
 *                             NOTE: this command takes 5 seconds to run
632
 */
633
function gather_altq_queue_stats($dont_return_root_queues) {
634
    mwexec("/usr/bin/killall -9 pfctl");
635
    $stats = `/sbin/pfctl -vvsq & /bin/sleep 5;/usr/bin/killall pfctl 2>/dev/null`;
636
    $stats_array = split("\n", $stats);
637
    $queue_stats = array();
638
    foreach ($stats_array as $stats_line) {
639
        if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
640
            $queue_name = $match_array[1][0];
641
        if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
642
            $speed = $match_array[1][0];
643
        if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
644
            $borrows = $match_array[1][0];
645
        if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
646
            $suspends = $match_array[1][0];
647
        if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
648
            $drops = $match_array[1][0];
649
        if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
650
            $measured = $match_array[1][0];
651
	    if($dont_return_root_queues == true)
652
		if(stristr($queue_name,"root_") == false)
653
		    array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
654
        }
655
    }
656
    return $queue_stats;
657
}
658

    
659
/*
660
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
661
 *					 Useful for finding paths and stripping file extensions.
662
 */
663
function reverse_strrchr($haystack, $needle)
664
{
665
               return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
666
}
667

    
668
/*
669
 * get_pkg_depends($pkg_name, $filetype = ".xml", $format = "files", return_nosync = 1):  Return a package's dependencies.
670
 *
671
 * $filetype = "all" || ".xml", ".tgz", etc.
672
 * $format = "files" (full filenames) || "names" (stripped / parsed depend names)
673
 * $return_nosync = 1 (return depends that have nosync set) | 0 (ignore packages with nosync)
674
 *
675
 */
676
function get_pkg_depends($pkg_name, $filetype = ".xml", $format = "files", $return_nosync = 1) {
677
    global $config;
678
    if(!is_numeric($pkg_name)) {
679
	$pkg_name = get_pkg_id($pkg_name);
680
	if($pkg_id == -1) return -1; // This package doesn't really exist - exit the function.
681
    } else {
682
	if(!isset($config['installedpackages']['package'][$pkg_id])) return; // No package belongs to the pkg_id passed to this function.
683
    }
684
    $package = $config['installedpackages']['package'][$pkg_id];
685
    print '$package done.';
686
    if(!file_exists("/usr/local/pkg/" . $package['configurationfile'])) { // If the package's config file doesn't exist, log an error and fetch it.
687
	log_error("Fetching missing configuration XML for " . $package['name']);
688
	mwexec("/usr/bin/fetch -o /usr/local/pkg/" . $package['configurationfile'] . " http://www.pfsense.com/packages/config/" . $package['configurationfile']);
689
    }
690
    $pkg_xml = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
691
    if($pkg_xml['additional_files_needed'] != "") {
692
	foreach($pkg_xml['additional_files_needed'] as $item) {
693
	    if (($return_nosync == 0) && (isset($item['nosync']))) continue; // Do not return depends with nosync set if not required.
694
	    $depend_file = substr(strrchr($item['item']['0'], '/'),1); // Strip URLs down to filenames.
695
	    $depend_name = substr(substr($depend_file,0,strpos($depend_file,".")+1),0,-1); // Strip filename down to dependency name.
696
	    if (($filetype != "all") && (!preg_match("/${filetype}/i", $depend_file))) continue;
697
	    if ($item['prefix'] != "") {
698
		$prefix = $item['prefix'];
699
	    } else {
700
		$prefix = "/usr/local/pkg/";
701
	    }
702
	    if(!file_exists($prefix . $pkg_name)) {
703
		log_error("Fetching missing dependency (" . $depend_name . ") for " . $pkg_name);
704
		mwexec("/usr/local/bin/fetch -o " . $prefix . $depend_file . " " . $item['name']['0']);
705
		if($item['chmod'] != "")
706
		    chmod($prefix . $depend_file, $item['chmod']); // Handle chmods.
707
	    }
708
	    switch ($format) {
709
	    case "files":
710
		$depends[] = $depend_file;
711
		break;
712
	    case "names":
713
		switch ($filetype) {
714
		case "all":
715
		    if(preg_match("/\.xml/i", $depend_file)) {
716
			$depend_xml = parse_xml_config_pkg("/usr/local/pkg/" . $depend_file, "packagegui");
717
			$depends[] = $depend_xml['name'];
718
			break;
719
		    } else {
720
			$depends[] = $depend_name; // If this dependency isn't package XML, use the stripped filename.
721
			break;
722
		    }
723
		case ".xml":
724
		    $depend_xml = parse_xml_config_pkg("/usr/local/pkg/" . $depend_file, "packagegui");
725
		    $depends[] = $depend_xml['name'];
726
		    break;
727
		default:
728
		    $depends[] = $depend_name; // If we aren't looking for XML, use the stripped filename (it's all we have).
729
		    break;
730
		}
731
	    }
732
	}
733
	return $depends;
734
    }
735
}
736

    
737
/*
738
 * is_service_running($service_name): checks to see if a service is running.
739
 *                                    if the service is running returns 1.
740
 */
741
function is_service_running($service_name) {
742
    $status = `/bin/ps ax | grep {$service_name} | grep -v grep`;
743
    $status_split = split("\n", $service_name);
744
    $counter = 0;
745
    foreach ($status_split as $ss) $counter++;
746
    if($counter > 0) return 1;
747
    return 0;
748
}
749

    
750
/*
751
 *  backup_config_section($section): returns as an xml file string of
752
 *                                   the configuration section
753
 */
754
function backup_config_section($section) {
755
    global $config;
756
    $new_section = &$config[$section];
757
    /* generate configuration XML */
758
    $xmlconfig = dump_xml_config($new_section, $section);
759
    $xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
760
    return $xmlconfig;
761
}
762

    
763
/*
764
 *  restore_config_section($section, new_contents): restore a configuration section,
765
 *                                                  and write the configuration out
766
 *                                                  to disk/cf.
767
 */
768
function restore_config_section($section, $new_contents) {
769
    global $config;
770
    $fout = fopen("{$g['tmp_path']}/tmpxml","w");
771
    fwrite($fout, $new_contents);
772
    fclose($fout);
773
    $section_xml = parse_xml_config_pkg($g['tmp_path'] . "/tmpxml", $section);
774
    $config[$section] = &$section_xml;
775
    unlink($g['tmp_path'] . "/tmpxml");
776
    write_config("Restored {$section} of config file (maybe from CARP partner)");
777
    return;
778
}
779

    
780
/*
781
 * http_post($server, $port, $url, $vars): does an http post to a web server
782
 *                                         posting the vars array.
783
 * written by nf@bigpond.net.au
784
 */
785
function http_post($server, $port, $url, $vars) {
786
    $user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
787
    $urlencoded = "";
788
    while (list($key,$value) = each($vars))
789
	$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
790
    $urlencoded = substr($urlencoded,0,-1);
791

    
792
    $content_length = strlen($urlencoded);
793

    
794
    $headers = "POST $url HTTP/1.1
795
Accept: */*
796
Accept-Language: en-au
797
Content-Type: application/x-www-form-urlencoded
798
User-Agent: $user_agent
799
Host: $server
800
Connection: Keep-Alive
801
Cache-Control: no-cache
802
Content-Length: $content_length
803

    
804
";
805

    
806
    $fp = fsockopen($server, $port, $errno, $errstr);
807
    if (!$fp) {
808
	return false;
809
    }
810

    
811
    fputs($fp, $headers);
812
    fputs($fp, $urlencoded);
813

    
814
    $ret = "";
815
    while (!feof($fp))
816
	$ret.= fgets($fp, 1024);
817

    
818
    fclose($fp);
819

    
820
    return $ret;
821

    
822
}
823

    
824
/*
825
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
826
 */
827
if (!function_exists('php_check_syntax')){
828
   function php_check_syntax($code_to_check, &$errormessage){
829
	return false;
830
        $fout = fopen("/tmp/codetocheck.php","w");
831
        $code = $_POST['content'];
832
        $code = str_replace("<?php", "", $code);
833
        $code = str_replace("?>", "", $code);
834
        fwrite($fout, "<?php\n\n");
835
        fwrite($fout, $code);
836
        fwrite($fout, "\n\n?>\n");
837
        fclose($fout);
838
        $command = "/usr/local/bin/php -l /tmp/codetocheck.php";
839
        $output = exec_command($command);
840
        if (stristr($output, "Errors parsing") == false) {
841
            echo "false\n";
842
            $errormessage = '';
843
            return(false);
844
        } else {
845
            $errormessage = $output;
846
            return(true);
847
        }
848
    }
849
}
850

    
851
/*
852
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
853
 */
854
if (!function_exists('php_check_syntax')){
855
   function php_check_syntax($code_to_check, &$errormessage){
856
	return false;
857
        $command = "/usr/local/bin/php -l " . $code_to_check;
858
        $output = exec_command($command);
859
        if (stristr($output, "Errors parsing") == false) {
860
            echo "false\n";
861
            $errormessage = '';
862
            return(false);
863
        } else {
864
            $errormessage = $output;
865
            return(true);
866
        }
867
    }
868
}
869

    
870
/*
871
 * sync_package($pkg_name, $sync_depends = true, $show_message = false) Force a package to setup its configuration and rc.d files.
872
 */
873
function sync_package($pkg_name, $sync_depends = true, $show_message = false) {
874
    global $config;
875

    
876
    if(!file_exists("/usr/local/pkg")) mwexec("/bin/mkdir -p /usr/local/pkg/pf");
877
    if(!$config['installedpackages']['package']) return;
878
    if(!is_numeric($pkg_name)) {
879
	$pkg_id = get_pkg_id($pkg_name);
880
	if($pkg_id == -1) return -1; // This package doesn't really exist - exit the function.
881
    } else {
882
	$pkg_id = $pkg_name;
883
	if(!isset($config['installedpackages']['package'][$pkg_id]))
884
	    return;  // No package belongs to the pkg_id passed to this function.
885
    }
886
    $package = $config['installedpackages']['package'][$pkg_id];
887
    if(!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
888
	//if($show_message == true) print "(f)"; Don't mess with this until the package system has settled.
889
	log_error("Fetching missing configuration XML for " . $package['name']);
890
	mwexec("/usr/bin/fetch -o /usr/local/pkg/" . $package['configurationfile'] . " http://www.pfsense.com/packages/config/" . $package['configurationfile']);
891
    }
892
    $pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
893
    if(isset($pkg_config['nosync'])) continue;
894
    //if($show_message == true) print "Syncing " . $pkg_name;
895
    if($pkg['custom_php_global_functions'] <> "")
896
        eval($pkg['custom_php_global_functions']);
897
    if($pkg_config['custom_php_command_before_form'] <> "")
898
	eval($pkg_config['custom_php_command_before_form']);
899
    if($pkg_config['custom_php_resync_config_command'] <> "")
900
	eval($pkg_config['custom_php_resync_config_command']);
901
    if($sync_depends == true) {
902
	$depends = get_pkg_depends($pkg_name, ".xml", "files", 1); // Call dependency handler and do a little more error checking.
903
	if(is_array($depends)) {
904
	    foreach($depends as $item) {
905
		$item_config = parse_xml_config_pkg("/usr/local/pkg/" . $item, "packagegui");
906
		if(isset($item_config['nosync'])) continue;
907
		if($item_config['custom_php_command_before_form'] <> "") {
908
		    eval($item_config['custom_php_command_before_form']);
909
		    print "Evaled dependency.";
910
		}
911
		if($item_config['custom_php_resync_config_command'] <> "") {
912
		    eval($item_config['custom_php_resync_config_command']);
913
		    print "Evaled dependency.";
914
		}
915
		if($show_message == true) print " " . $item_config['name'];
916
	    }
917
	}
918
    }
919
    // if($show_message == true) print ".";
920
}
921

    
922
/*
923
 * rmdir_recursive($path,$follow_links=false)
924
 * Recursively remove a directory tree (rm -rf path)
925
 * This is for directories _only_
926
 */
927
function rmdir_recursive($path,$follow_links=false) {
928
	$to_do = glob($path);
929
	if(!is_array($to_do)) {
930
		if(file_exists($to_do)) {
931
			$dir = opendir($path);
932
			while ($entry = readdir($dir)) {
933
				if (is_file("$path/$entry") || ((!$follow_links) && is_link("$path/$entry")))
934
					unlink("$path/$entry");
935
      	 			elseif (is_dir("$path/$entry") && $entry!='.' && $entry!='..')
936
					rmdir_recursive("$path/$entry");
937
			}
938
			closedir($dir);
939
			rmdir($path);
940
			return;
941
		}
942
	} else {
943
		foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
944
			if(file_exists($workingdir)) {
945
				$dir = opendir($workingdir);
946
				while ($entry = readdir($dir)) {
947
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
948
					unlink("$workingdir/$entry");
949
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
950
					rmdir_recursive("$workingdir/$entry");
951
				}
952
				closedir($dir);
953
				rmdir($workingdir);
954
                	}
955
		}
956
		return;
957
	}
958
	return;
959
}
960

    
961
/*
962
 * safe_mkdir($path, $mode = 0755)
963
 * create directory if it doesn't already exist and isn't a file!
964
 */
965
function safe_mkdir($path, $mode=0755) {
966
	if (!is_file($path) && !is_dir($path))
967
		return mkdir($path, $mode);
968
	else
969
		return false;
970
}
971

    
972
/*
973
 * make_dirs($path, $mode = 0755)
974
 * create directory tree recursively (mkdir -p)
975
 */
976
function make_dirs($path, $mode = 0755)
977
{
978
	return is_dir($path) || (make_dirs(dirname($path), $mode) && safe_mkdir($path, $mode));
979
}
980

    
981
/*
982
 * auto_upgrade(): Upgrade pfSense to the latest firmware version.
983
 */
984
function auto_upgrade() {
985
        global $config, $g;
986
	if (isset($config['system']['alt_firmware_url']['enabled'])) {
987
                $firmwareurl=$config['system']['alt_firmware_url']['firmware_base_url'];
988
                $firmwarepath=$config['system']['alt_firmware_url']['firmware_filename'];
989
        } else {
990
                $firmwareurl=$g['firmwarebaseurl'];
991
                $firmwarepath=$g['firmwarefilename'];
992
        }
993
        if($config['system']['proxy_auth_username'] <> "")
994
	    $http_auth_username = $config['system']['proxy_auth_username'];
995
        if($config['system']['proxy_auth_password'] <> "")
996
	    $http_auth_password = $config['system']['proxy_auth_password'];
997
        if (isset($config['system']['alt_firmware_url']['enabled'])) {
998
                $firmwareurl=$config['system']['alt_firmware_url']['firmware_base_url'];
999
                $firmwarename=$config['system']['alt_firmware_url']['firmware_filename'];
1000
        } else {
1001
                $firmwareurl=$g['firmwarebaseurl'];
1002
                $firmwarename=$g['firmwarefilename'];
1003
        }
1004
        exec_rc_script_async("/etc/rc.firmware_auto {$firmwareurl} {$firmwarename} {$http_auth_username} {$http_auth_password}");
1005
	return;
1006
}
1007

    
1008
/*
1009
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1010
 */
1011
function check_firmware_version($return_php = true) {
1012
        global $g;
1013
	$versioncheck_base_url = $g['versioncheckbaseurl'];
1014
        $versioncheck_path = $g['versioncheckpath'];
1015
        if(isset($config['system']['alt_firmware_url']['enabled']) and isset($config['system']['alt_firmware_url']['versioncheck_base_url'])) {
1016
                $versioncheck_base_url = $config['system']['alt_firmware_url']['versioncheck_base_url'];
1017
	}
1018
        $params = array(new XML_RPC_Value(trim(file_get_contents('/etc/platform')), 'string'),
1019
                        new XML_RPC_Value(trim(file_get_contents('/etc/version')), 'string'),
1020
                        new XML_RPC_Value(trim(file_get_contents('/etc/version_kernel')), 'string'),
1021
                        new XML_RPC_Value(trim(file_get_contents('/etc/version_base')), 'string'));
1022
        $msg = new XML_RPC_Message('pfsense.get_firmware_version', $params);
1023
        $cli = new XML_RPC_Client($versioncheck_path, $versioncheck_base_url);
1024
        $resp = $cli->send($msg);
1025
	if(!$resp) return -1;
1026
	if($resp->faultCode()) return -1;
1027
        if($return_php == false) return $resp->serialize();
1028
	$raw_versions = $resp->value();
1029
	$toreturn = array();
1030
	for($i = 0; $i < $raw_versions->arraysize(); $i++) {
1031
		$arrayval = $raw_versions->arraymem($i);
1032
		$toreturn[] = $arrayval->scalarval();
1033
	}
1034
	return $toreturn;
1035
}
1036

    
1037
?>
(10-10/18)