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
    $pos = strrpos($haystack, $needle);
665
    if($post === false) {
666
	return $haystack;
667
    }
668
    return substr($haystack, 0, $post + 1);
669
}
670

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

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

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

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

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

    
795
    $content_length = strlen($urlencoded);
796

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

    
807
";
808

    
809
    $fp = fsockopen($server, $port, $errno, $errstr);
810
    if (!$fp) {
811
	return false;
812
    }
813

    
814
    fputs($fp, $headers);
815
    fputs($fp, $urlencoded);
816

    
817
    $ret = "";
818
    while (!feof($fp))
819
	$ret.= fgets($fp, 1024);
820

    
821
    fclose($fp);
822

    
823
    return $ret;
824

    
825
}
826

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

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

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

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

    
925
/*
926
 * rmdir_recursive($path,$follow_links=false)
927
 * Recursively remove a directory tree (rm -rf path)
928
 * This is for directories _only_
929
 */
930
function rmdir_recursive($path,$follow_links=false) {
931
	$to_do = glob($path);
932
	if(!is_array($to_do)) {
933
		$dir = opendir($path);
934
		while ($entry = readdir($dir)) {
935
			if (is_file("$path/$entry") || ((!$follow_links) && is_link("$path/$entry")))
936
				unlink("$path/$entry");
937
       			elseif (is_dir("$path/$entry") && $entry!='.' && $entry!='..')
938
				rmdir_recursive("$path/$entry");
939
		}
940
		closedir($dir);
941
		rmdir($path);
942
		return;
943
	} else {
944
		foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
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
		return;
956
	}
957
	return;
958
}
959

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

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

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

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

    
1036
?>
(10-10/17)