Project

General

Profile

Download (59.2 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/pfsense-utils
3
 * NAME
4
 *   pfsense-utils.inc - Utilities specific to pfSense
5
 * DESCRIPTION
6
 *   This include contains various pfSense specific functions.
7
 * HISTORY
8
 *   $Id$
9
 ******
10
 *
11
 * Copyright (C) 2004-2007 Scott Ullrich (sullrich@gmail.com)
12
 * All rights reserved.
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *
16
 * 1. Redistributions of source code must retain the above copyright notice,
17
 * this list of conditions and the following disclaimer.
18
 *
19
 * 2. Redistributions in binary form must reproduce the above copyright
20
 * notice, this list of conditions and the following disclaimer in the
21
 * documentation and/or other materials provided with the distribution.
22
 *
23
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
27
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
 * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 * POSSIBILITY OF SUCH DAMAGE.
33
 *
34
 */
35

    
36
/****f* pfsense-utils/have_natonetooneruleint_access
37
 * NAME
38
 *   have_natonetooneruleint_access
39
 * INPUTS
40
 *	 none
41
 * RESULT
42
 *   returns true if user has access to edit a specific firewall nat one to one interface
43
 ******/
44
function have_natonetooneruleint_access($if) {
45
	$security_url = "firewall_nat_1to1_edit.php?if=". strtolower($if);
46
	if(isAllowedPage($security_url, $allowed)) 
47
		return true;
48
	return false;
49
}
50

    
51
/****f* pfsense-utils/have_natpfruleint_access
52
 * NAME
53
 *   have_natpfruleint_access
54
 * INPUTS
55
 *	 none
56
 * RESULT
57
 *   returns true if user has access to edit a specific firewall nat port forward interface
58
 ******/
59
function have_natpfruleint_access($if) {
60
	$security_url = "firewall_nat_edit.php?if=". strtolower($if);
61
	if(isAllowedPage($security_url, $allowed)) 
62
		return true;
63
	return false;
64
}
65

    
66
/****f* pfsense-utils/have_ruleint_access
67
 * NAME
68
 *   have_ruleint_access
69
 * INPUTS
70
 *	 none
71
 * RESULT
72
 *   returns true if user has access to edit a specific firewall interface
73
 ******/
74
function have_ruleint_access($if) {
75
	$security_url = "firewall_rules.php?if=". strtolower($if);
76
	if(isAllowedPage($security_url)) 
77
		return true;
78
	return false;
79
}
80

    
81
/****f* pfsense-utils/does_url_exist
82
 * NAME
83
 *   does_url_exist
84
 * INPUTS
85
 *	 none
86
 * RESULT
87
 *   returns true if a url is available
88
 ******/
89
function does_url_exist($url) {
90
	$fd = fopen("$url","r");
91
	if($fd) {
92
		fclose($fd);
93
   		return true;    
94
	} else {
95
        return false;
96
	}
97
}
98

    
99
/****f* pfsense-utils/is_private_ip
100
 * NAME
101
 *   is_private_ip
102
 * INPUTS
103
 *	 none
104
 * RESULT
105
 *   returns true if an ip address is in a private range
106
 ******/
107
function is_private_ip($iptocheck) {
108
        $isprivate = false;
109
        $ip_private_list=array(
110
               "10.0.0.0/8",
111
               "172.16.0.0/12",
112
               "192.168.0.0/16",
113
               "99.0.0.0/8"
114
        );
115
        foreach($ip_private_list as $private) {
116
                if(ip_in_subnet($iptocheck,$private)==true)
117
                        $isprivate = true;
118
        }
119
        return $isprivate;
120
}
121

    
122
/****f* pfsense-utils/get_tmp_file
123
 * NAME
124
 *   get_tmp_file
125
 * INPUTS
126
 *	 none
127
 * RESULT
128
 *   returns a temporary filename
129
 ******/
130
function get_tmp_file() {
131
	return "/tmp/tmp-" . time();
132
}
133

    
134
/****f* pfsense-utils/find_number_of_needed_carp_interfaces
135
 * NAME
136
 *   find_number_of_needed_carp_interfaces
137
 * INPUTS
138
 *   null
139
 * RESULT
140
 *   the number of needed carp interfacs
141
 ******/
142
function find_number_of_needed_carp_interfaces() {
143
	global $config, $g;
144
	$carp_counter=0;
145
	if(!$config['virtualip'])
146
		return 0;
147
	if(!$config['virtualip']['vip'])
148
		return 0;
149
	foreach($config['virtualip']['vip'] as $vip) {
150
		if($vip['mode'] == "carp")
151
			$carp_counter++;
152
	}
153
	return $carp_counter;
154
}
155

    
156
/****f* pfsense-utils/reset_carp
157
 * NAME
158
 *   reset_carp - resets carp after primary interface changes
159
 * INPUTS
160
 *   null
161
 * RESULT
162
 *   null
163
 ******/
164
function reset_carp() {
165
	$carp_counter=find_number_of_created_carp_interfaces();
166
	$needed_carp_interfaces = find_number_of_needed_carp_interfaces();
167
	mwexec("/sbin/sysctl net.inet.carp.allow=0");
168
	for($x=0; $x<$carp_counter; $x++) {
169
		mwexec("/sbin/ifconfig carp{$x} down");
170
		usleep(1000);
171
		mwexec("/sbin/ifconfig carp{$x} delete");
172
		if($needed_carp_interfaces < $carp_counter) {
173
			$needed_carp_interfaces--;
174
			//log_error("Destroying carp interface.");
175
			//mwexec("/sbin/ifconfig carp{$x} destroy");
176
		}
177
	}
178
	find_number_of_created_carp_interfaces(true);
179
	sleep(1);
180
	mwexec("/sbin/sysctl net.inet.carp.allow=1");
181
	interfaces_carp_configure();
182
}
183

    
184
/****f* pfsense-utils/get_dns_servers
185
 * NAME
186
 *   get_dns_servres - get system dns servers
187
 * INPUTS
188
 *   $dns_servers - an array of the dns servers
189
 * RESULT
190
 *   null
191
 ******/
192
function get_dns_servers() {
193
	$dns_servers = array();
194
	$dns = `cat /etc/resolv.conf`;
195
	$dns_s = split("\n", $dns);
196
	foreach($dns_s as $dns) {
197
		$matches = "";
198
		if (preg_match("/nameserver (.*)/", $dns, $matches))
199
			$dns_servers[] = $matches[1];
200
	}
201
	$dns_server_master = array();
202
	$lastseen = "";
203
	foreach($dns_servers as $t) {
204
		if($t <> $lastseen)
205
			if($t <> "")
206
				$dns_server_master[] = $t;
207
		$lastseen = $t;
208
	}
209
	return $dns_server_master;
210
}
211

    
212
/****f* pfsense-utils/enable_hardware_offloading
213
 * NAME
214
 *   enable_hardware_offloading - Enable a NIC's supported hardware features.
215
 * INPUTS
216
 *   $interface	- string containing the physical interface to work on.
217
 * RESULT
218
 *   null
219
 * NOTES
220
 *   This function only supports the fxp driver's loadable microcode.
221
 ******/
222
function enable_hardware_offloading($interface) {
223
	global $g, $config;
224

    
225
	if(stristr($interface,"lnc"))
226
		return;
227

    
228
	/* translate wan, lan, opt -> real interface if needed */
229
	$int = interface_translate_type_to_real($interface);
230
	if($int <> "") $interface = $int;
231
	$int_family = preg_split("/[0-9]+/", $int);
232
	$options = strtolower(`/sbin/ifconfig -m {$interface} | grep capabilities`);
233
	$supported_ints = array('fxp');
234
	if (in_array($int_family, $supported_ints)) {
235
        	if(isset($config['system']['do_not_use_nic_microcode']))
236
                        continue;
237
		mwexec("/sbin/ifconfig {$interface} link0");
238
        }
239

    
240
	/* skip vlans for checksumming and polling */
241
	if(stristr($interface, "vlan")) 
242
		return;
243

    
244
	if($config['system']['disablechecksumoffloading']) {
245
                if(stristr($options, "txcsum") == true)
246
                        mwexec("/sbin/ifconfig {$interface} -txcsum 2>/dev/null");
247
                if(stristr($options, "rxcsum") == true)
248
                        mwexec("/sbin/ifconfig {$interface} -rxcsum 2>/dev/null");
249
	} else {
250
               	if(stristr($options, "txcsum") == true)
251
                        mwexec("/sbin/ifconfig {$interface} txcsum 2>/dev/null");
252
        	if(stristr($options, "rxcsum") == true)
253
                        mwexec("/sbin/ifconfig {$interface} rxcsum 2>/dev/null");
254
        }
255

    
256
	/* if the NIC supports polling *AND* it is enabled in the GUI */
257
	if(interface_supports_polling($interface)) {
258
		$polling = isset($config['system']['polling']);	
259
		if($polling) {
260
			mwexec("sysctl kern.polling.enable=1");
261
                        mwexec("/sbin/ifconfig {$interface} polling 2>/dev/null");
262
		} else {
263
			mwexec("sysctl kern.polling.enable=0");
264
		}
265
	}
266
	return;
267
}
268

    
269
/****f* pfsense-utils/interface_supports_polling
270
 * NAME
271
 *   checks to see if an interface supports polling according to man polling
272
 * INPUTS
273
 *
274
 * RESULT
275
 *   true or false
276
 * NOTES
277
 *
278
 ******/
279
function interface_supports_polling($iface) {
280
	$pattern = '/([a-z].*)[0-9]/';
281
	preg_match($pattern, $iface, $iface2);
282
	$interface=$iface2[1];
283
	$supported_ints = array("bge",
284
		"dc",
285
		"em",
286
		"fwe",
287
		"fwip",
288
		"fxp",
289
		"ixgb",
290
		"nfe",
291
		"vge",
292
		"re",
293
		"rl",
294
		"sf",
295
		"sis",
296
		"ste",
297
		"stge",    
298
		"vge",
299
		"vr",
300
		"xl");
301
	if(in_array($interface, $supported_ints))
302
		return true;
303
	return false;
304
}
305

    
306
/****f* pfsense-utils/is_alias_inuse
307
 * NAME
308
 *   checks to see if an alias is currently in use by a rule
309
 * INPUTS
310
 *
311
 * RESULT
312
 *   true or false
313
 * NOTES
314
 *
315
 ******/
316
function is_alias_inuse($alias) {
317
	global $g, $config;
318

    
319
	if($alias == "") return false;
320
	/* loop through firewall rules looking for alias in use */
321
	if(is_array($config['filter']['rule']))
322
		foreach($config['filter']['rule'] as $rule) {
323
			if($rule['source']['address'])
324
				if($rule['source']['address'] == $alias)
325
					return true;
326
			if($rule['destination']['address'])
327
				if($rule['destination']['address'] == $alias)
328
					return true;
329
		}
330
	/* loop through nat rules looking for alias in use */
331
	if(is_array($config['nat']['rule']))
332
		foreach($config['nat']['rule'] as $rule) {
333
			if($rule['target'] == $alias)
334
				return true;
335
			if($rule['external-address'] == $alias)
336
				return true;
337
		}
338
	return false;
339
}
340

    
341
/****f* pfsense-utils/is_schedule_inuse
342
 * NAME
343
 *   checks to see if a schedule is currently in use by a rule
344
 * INPUTS
345
 *
346
 * RESULT
347
 *   true or false
348
 * NOTES
349
 *
350
 ******/
351
function is_schedule_inuse($schedule) {
352
	global $g, $config;
353

    
354
	if($schedule == "") return false;
355
	/* loop through firewall rules looking for schedule in use */
356
	if(is_array($config['filter']['rule']))
357
		foreach($config['filter']['rule'] as $rule) {
358
			if($rule['sched'] == $schedule)
359
				return true;
360
		}
361
	return false;
362
}
363

    
364
/****f* pfsense-utils/setup_polling_defaults
365
 * NAME
366
 *   sets up sysctls for pollingS
367
 * INPUTS
368
 *
369
 * RESULT
370
 *   null
371
 * NOTES
372
 *
373
 ******/
374
function setup_polling_defaults() {
375
	global $g, $config;
376
	if($config['system']['polling_each_burst'])
377
		mwexec("sysctl kern.polling.each_burst={$config['system']['polling_each_burst']}");
378
	if($config['system']['polling_burst_max'])
379
		mwexec("sysctl kern.polling.burst_max={$config['system']['polling_burst_max']}");
380
	if($config['system']['polling_user_frac'])
381
		mwexec("sysctl kern.polling.user_frac={$config['system']['polling_user_frac']}");
382
}
383

    
384
/****f* pfsense-utils/setup_polling
385
 * NAME
386
 *   sets up polling
387
 * INPUTS
388
 *
389
 * RESULT
390
 *   null
391
 * NOTES
392
 *
393
 ******/
394
function setup_polling() {
395
	global $g, $config;
396

    
397
	setup_polling_defaults();
398

    
399
	$supported_ints = array('bge', 'dc', 'em', 'fwe', 'fwip', 'fxp', 'ixgb', 'ste', 'nge', 're', 'rl', 'sf', 'sis', 'ste', 'vge', 'vr', 'xl');
400

    
401
	/* if list */
402
	$iflist = get_configured_interface_list();
403

    
404
	foreach ($iflist as $ifent => $ifname) {
405
		$real_interface = convert_friendly_interface_to_real_interface_name($ifname);
406
		$ifdevice = substr($real_interface, 0, -1);
407
		if(!in_array($ifdevice, $supported_ints)) {
408
			continue;
409
        }
410
		if(isset($config['system']['polling'])) {
411
			mwexec("/sbin/ifconfig {$real_interface} polling");
412
		} else {
413
			mwexec("/sbin/ifconfig {$real_interface} -polling");
414
		}
415
	}
416
}
417

    
418
/****f* pfsense-utils/setup_microcode
419
 * NAME
420
 *   enumerates all interfaces and calls enable_hardware_offloading which
421
 *   enables a NIC's supported hardware features.
422
 * INPUTS
423
 *
424
 * RESULT
425
 *   null
426
 * NOTES
427
 *   This function only supports the fxp driver's loadable microcode.
428
 ******/
429
function setup_microcode() {
430

    
431
	/* if list */
432
        $ifdescrs = get_configured_interface_list();
433

    
434
	foreach($ifdescrs as $if)
435
		enable_hardware_offloading($if);
436
}
437

    
438
/****f* pfsense-utils/return_filename_as_array
439
 * NAME
440
 *   return_filename_as_array - Return a file's contents as an array.
441
 * INPUTS
442
 *   $filename	- string containing the path to the desired file.
443
 *   $strip	- array of characters to strip - default is '#'.
444
 * RESULT
445
 *   $file	- array containing the file's contents.
446
 * NOTES
447
 *   This function strips lines starting with '#' and leading/trailing whitespace by default.
448
 ******/
449
function return_filename_as_array($filename, $strip = array('#')) {
450
	if(file_exists($filename)) $file = file($filename);
451
	if(is_array($file)) {
452
		foreach($file as $line) $line = trim($line);
453
		foreach($strip as $tostrip) $file = preg_grep("/^{$tostrip}/", $file, PREG_GREP_INVERT);
454
	}
455
	return $file;
456
}
457

    
458
/****f* pfsense-utils/get_carp_status
459
 * NAME
460
 *   get_carp_status - Return whether CARP is enabled or disabled.
461
 * RESULT
462
 *   boolean	- true if CARP is enabled, false if otherwise.
463
 ******/
464
function get_carp_status() {
465
    /* grab the current status of carp */
466
    $status = `/sbin/sysctl net.inet.carp.allow | cut -d" " -f2`;
467
    if(intval($status) == "0") return false;
468
    return true;
469
}
470

    
471
/****f* pfsense-utils/is_carp_defined
472
 * NAME
473
 *   is_carp_defined - Return whether CARP is detected in the kernel.
474
 * RESULT
475
 *   boolean	- true if CARP is detected, false otherwise.
476
 ******/
477
function is_carp_defined() {
478
	/* is carp compiled into the kernel and userland? */
479
	$command = "/sbin/sysctl -a | grep carp";
480
	$fd = popen($command . " 2>&1 ", "r");
481
	if(!$fd) {
482
		log_error("Warning, could not execute command {$command}");
483
		return 0;
484
	}
485
	while(!feof($fd)) {
486
		$tmp .= fread($fd,49);
487
	}
488
	fclose($fd);
489

    
490
	if($tmp == "")
491
		return false;
492
	else
493
		return true;
494
}
495

    
496
/****f* pfsense-utils/find_number_of_created_carp_interfaces
497
 * NAME
498
 *   find_number_of_created_carp_interfaces - Return the number of CARP interfaces.
499
 * RESULT
500
 *   $tmp	- Number of currently created CARP interfaces.
501
 ******/
502
function find_number_of_created_carp_interfaces($flush = false) {
503
	global $carp_interface_count_cache;
504

    
505
	if (!isset($carp_interface_count_cache) or $flush) {
506
		$command = "/sbin/ifconfig | /usr/bin/grep \"carp*:\" | /usr/bin/wc -l";
507
		$fd = popen($command . " 2>&1 ", "r");
508
		if(!$fd) {
509
			log_error("Warning, could not execute command {$command}");
510
			return 0;
511
		}
512
		while(!feof($fd)) {
513
			$tmp .= fread($fd,49);
514
		}
515
		fclose($fd);
516
		$carp_interface_count_cache = intval($tmp);
517
	}
518
	return $carp_interface_count_cache;
519
}
520

    
521
function link_carp_interface_to_parent($interface) {
522
	global $config;
523

    
524
	if ($interface == "")
525
		return;
526

    
527
	$carp_ip = find_interface_ip($interface);
528
	if (!is_ipaddr($carp_ip))
529
		return;
530

    
531
	/* if list */
532
        $ifdescrs = get_configured_interface_list();
533
	foreach ($ifdescrs as $ifdescr => $ifname) {
534
		$interfaceip = get_interface_ip($ifname);
535
		$subnet_bits = get_interface_subnet($ifname);
536
		$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
537
		if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
538
			return $ifname;
539
	}
540

    
541
	return "";
542
}
543

    
544
/****f* pfsense-utils/link_ip_to_carp_interface
545
 * NAME
546
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
547
 * INPUTS
548
 *   $ip
549
 * RESULT
550
 *   $carp_ints
551
 ******/
552
function link_ip_to_carp_interface($ip) {
553
	global $config;
554

    
555
	if (!is_ipaddr($ip))
556
		return;
557

    
558
	$carp_ints = "";
559
	$num_carp_ints = find_number_of_created_carp_interfaces();
560
	for ($x=0; $x<$num_carp_ints; $x++) {
561
		$carp_int = "carp{$x}";
562
		$carp_ip = find_interface_ip($carp_int);
563
		$carp_subnet = find_virtual_ip_netmask($carp_ip);
564
		$starting_ip = gen_subnet("{$carp_ip}", "{$carp_subnet}");
565
		if (ip_in_subnet($ip, "{$starting_ip}/{$carp_subnet}"))
566
			if(!stristr($carp_ints, $carp_int))
567
				$carp_ints .= " " . $carp_int;
568
	}
569
	
570
	return $carp_ints;
571
}
572

    
573
/****f* pfsense-utils/find_virtual_ip_netmask
574
 * NAME
575
 *   find_virtual_ip_netmask - Finds a virtual ip's subnet mask'
576
 * INPUTS
577
 *   $ip - ip address to locate subnet mask of
578
 * RESULT
579
 *   String containing the command's result.
580
 * NOTES
581
 *   This function returns the command's stdout and stderr.
582
 ******/
583
function find_virtual_ip_netmask($ip) {
584
        global $config;
585
        foreach($config['virtualip']['vip'] as $vip) {
586
                if($ip == $vip['subnet'])
587
                        return $vip['subnet_bits'];
588
        }
589
}
590

    
591
/****f* pfsense-utils/exec_command
592
 * NAME
593
 *   exec_command - Execute a command and return a string of the result.
594
 * INPUTS
595
 *   $command	- String of the command to be executed.
596
 * RESULT
597
 *   String containing the command's result.
598
 * NOTES
599
 *   This function returns the command's stdout and stderr.
600
 ******/
601
function exec_command($command) {
602
	$output = array();
603
	exec($command . ' 2>&1 ', $output);
604
	return(implode("\n", $output));
605
}
606

    
607
/*
608
 * convert_ip_to_network_format($ip, $subnet): converts an ip address to network form
609

    
610
 */
611
function convert_ip_to_network_format($ip, $subnet) {
612
	$ipsplit = split('[.]', $ip);
613
	$string = $ipsplit[0] . "." . $ipsplit[1] . "." . $ipsplit[2] . ".0/" . $subnet;
614
	return $string;
615
}
616

    
617
/*
618
 * get_carp_interface_status($carpinterface): returns the status of a carp ip
619
 */
620
function get_carp_interface_status($carpinterface) {
621
	/* basically cache the contents of ifconfig statement
622
	to speed up this routine */
623
	global $carp_query;
624
	if($carp_query == "")
625
	$carp_query = split("\n", `/sbin/ifconfig | /usr/bin/grep carp`);
626
	$found_interface = 0;
627
	foreach($carp_query as $int) {
628
		if($found_interface == 1) {
629
			if(stristr($int, "MASTER")) return "MASTER";
630
			if(stristr($int, "BACKUP")) return "BACKUP";
631
			if(stristr($int, "INIT")) return "INIT";
632
			return false;
633
		}
634
		if(stristr($int, $carpinterface) == true)
635
		$found_interface=1;
636
	}
637
	return;
638
}
639

    
640
/*
641
 * get_pfsync_interface_status($pfsyncinterface): returns the status of a pfsync
642
 */
643
function get_pfsync_interface_status($pfsyncinterface) {
644
    $result = does_interface_exist($pfsyncinterface);
645
    if($result <> true) return;
646
    $status = exec_command("/sbin/ifconfig {$pfsyncinterface} | /usr/bin/grep \"pfsync:\" | /usr/bin/cut -d\" \" -f5");
647
    return $status;
648
}
649

    
650
/*
651
 * find_carp_interface($ip): return the carp interface where an ip is defined
652
 */
653
function find_carp_interface($ip) {
654
	global $find_carp_ifconfig;
655
	if($find_carp_ifconfig == "") {
656
		$find_carp_ifconfig = array();
657
		$num_carp_ints = find_number_of_created_carp_interfaces();
658
		for($x=0; $x<$num_carp_ints; $x++) {
659
			$find_carp_ifconfig[$x] = exec_command("/sbin/ifconfig carp{$x}");
660
		}
661
	}
662
	$carps = 0;
663
	foreach($find_carp_ifconfig as $fci) {
664
		if(stristr($fci, $ip . " ") == true)
665
			return "carp{$carps}";
666
		$carps++;
667
	}
668
}
669

    
670
/*
671
 * add_rule_to_anchor($anchor, $rule): adds the specified rule to an anchor
672
 */
673
function add_rule_to_anchor($anchor, $rule, $label) {
674
	mwexec("echo " . $rule . " | /sbin/pfctl -a " . $anchor . ":" . $label . " -f -");
675
}
676

    
677
/*
678
 * remove_text_from_file
679
 * remove $text from file $file
680
 */
681
function remove_text_from_file($file, $text) {
682
	global $fd_log;
683
	if($fd_log)
684
		fwrite($fd_log, "Adding needed text items:\n");
685
	$filecontents = file_get_contents($file);
686
	$textTMP = str_replace($text, "", $filecontents);
687
	$text = $textTMP;
688
	if($fd_log)
689
		fwrite($fd_log, $text);
690
	$fd = fopen($file, "w");
691
	fwrite($fd, $text);
692
	fclose($fd);
693
}
694

    
695
/*
696
 * add_text_to_file($file, $text): adds $text to $file.
697
 * replaces the text if it already exists.
698
 */
699
function add_text_to_file($file, $text, $replace = false) {
700
	if(file_exists($file) and is_writable($file)) {
701
		$filecontents = file($file);
702
		$fout = fopen($file, "w");
703

    
704
		$filecontents = array_map('rtrim', $filecontents);
705
		array_push($filecontents, $text);
706
		if ($replace)
707
			$filecontents = array_unique($filecontents);
708

    
709
		$file_text = implode("\n", $filecontents);
710

    
711
		fwrite($fout, $file_text);
712
		fclose($fout);
713
		return true;
714
	} else {
715
		return false;
716
	}
717
}
718

    
719
/*
720
 *   after_sync_bump_adv_skew(): create skew values by 1S
721
 */
722
function after_sync_bump_adv_skew() {
723
	global $config, $g;
724
	$processed_skew = 1;
725
	$a_vip = &$config['virtualip']['vip'];
726
	foreach ($a_vip as $vipent) {
727
		if($vipent['advskew'] <> "") {
728
			$processed_skew = 1;
729
			$vipent['advskew'] = $vipent['advskew']+1;
730
		}
731
	}
732
	if($processed_skew == 1)
733
		write_config("After synch increase advertising skew");
734
}
735

    
736
/*
737
 * get_filename_from_url($url): converts a url to its filename.
738
 */
739
function get_filename_from_url($url) {
740
	return basename($url);
741
}
742

    
743
/*
744
 *   update_output_window: update bottom textarea dynamically.
745
 */
746
function update_output_window($text) {
747
	global $pkg_interface;
748
	$log = ereg_replace("\n", "\\n", $text);
749
	if($pkg_interface == "console") {
750
		/* too chatty */
751
	} else {
752
		echo "\n<script language=\"JavaScript\">this.document.forms[0].output.value = \"" . $log . "\";</script>";
753
	}
754
	/* ensure that contents are written out */
755
	ob_flush();
756
}
757

    
758
/*
759
 *   get_dir: return an array of $dir
760
 */
761
function get_dir($dir) {
762
	$dir_array = array();
763
	$d = dir($dir);
764
	while (false !== ($entry = $d->read())) {
765
		array_push($dir_array, $entry);
766
	}
767
	$d->close();
768
	return $dir_array;
769
}
770

    
771
/*
772
 *   update_output_window: update top textarea dynamically.
773
 */
774
function update_status($status) {
775
	global $pkg_interface;
776
	if($pkg_interface == "console") {
777
		echo $status . "\n";
778
	} else {
779
		echo "\n<script type=\"text/javascript\">this.document.forms[0].status.value=\"" . $status . "\";</script>";
780
	}
781
	/* ensure that contents are written out */
782
	ob_flush();
783
}
784

    
785
/*
786
 * update_progress_bar($percent): updates the javascript driven progress bar.
787
 */
788
function update_progress_bar($percent) {
789
	global $pkg_interface;
790
	if($percent > 100) $percent = 1;
791
	if($pkg_interface <> "console") {
792
		echo "\n<script type=\"text/javascript\" language=\"javascript\">";
793
		echo "\ndocument.progressbar.style.width='" . $percent . "%';";
794
		echo "\n</script>";
795
	} else {
796
		echo " {$percent}%";
797
	}
798
}
799

    
800
/****f* pfsense-utils/WakeOnLan
801
 * NAME
802
 *   WakeOnLan - Wake a machine up using the wake on lan format/protocol
803
 * RESULT
804
 *   true/false - true if the operation was successful
805
 ******/
806
function WakeOnLan($addr, $mac)
807
{
808
	$addr_byte = explode(':', $mac);
809
	$hw_addr = '';
810

    
811
	for ($a=0; $a < 6; $a++)
812
		$hw_addr .= chr(hexdec($addr_byte[$a]));
813

    
814
	$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
815

    
816
	for ($a = 1; $a <= 16; $a++)
817
		$msg .= $hw_addr;
818

    
819
	// send it to the broadcast address using UDP
820
	$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
821
	if ($s == false) {
822
		log_error("Error creating socket!");
823
		log_error("Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s)));
824
	} else {
825
		// setting a broadcast option to socket:
826
		$opt_ret =  socket_set_option($s, 1, 6, TRUE);
827
		if($opt_ret < 0)
828
			log_error("setsockopt() failed, error: " . strerror($opt_ret));
829
		$e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
830
		socket_close($s);
831
		log_error("Magic Packet sent ({$e}) to {$addr} MAC={$mac}");
832
		return true;
833
	}
834

    
835
	return false;
836
}
837

    
838
/*
839
 * gather_altq_queue_stats():  gather altq queue stats and return an array that
840
 *                             is queuename|qlength|measured_packets
841
 *                             NOTE: this command takes 5 seconds to run
842
 */
843
function gather_altq_queue_stats($dont_return_root_queues) {
844
	exec("/sbin/pfctl -vvsq", $stats_array);
845
	$queue_stats = array();
846
	foreach ($stats_array as $stats_line) {
847
		$match_array = "";
848
		if (preg_match_all("/queue\s+(\w+)\s+/",$stats_line,$match_array))
849
			$queue_name = $match_array[1][0];
850
		if (preg_match_all("/measured:\s+.*packets\/s\,\s(.*)\s+\]/",$stats_line,$match_array))
851
			$speed = $match_array[1][0];
852
		if (preg_match_all("/borrows:\s+(.*)/",$stats_line,$match_array))
853
			$borrows = $match_array[1][0];
854
		if (preg_match_all("/suspends:\s+(.*)/",$stats_line,$match_array))
855
			$suspends = $match_array[1][0];
856
		if (preg_match_all("/dropped pkts:\s+(.*)/",$stats_line,$match_array))
857
			$drops = $match_array[1][0];
858
		if (preg_match_all("/measured:\s+(.*)packets/",$stats_line,$match_array)) {
859
			$measured = $match_array[1][0];
860
			if($dont_return_root_queues == true)
861
				if(stristr($queue_name,"root_") == false)
862
					array_push($queue_stats, "{$queue_name}|{$speed}|{$measured}|{$borrows}|{$suspends}|{$drops}");
863
		}
864
	}
865
	return $queue_stats;
866
}
867

    
868
/*
869
 * reverse_strrchr($haystack, $needle):  Return everything in $haystack up to the *last* instance of $needle.
870
 *					 Useful for finding paths and stripping file extensions.
871
 */
872
function reverse_strrchr($haystack, $needle) {
873
	return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
874
}
875

    
876
/*
877
 *  backup_config_section($section): returns as an xml file string of
878
 *                                   the configuration section
879
 */
880
function backup_config_section($section) {
881
	global $config;
882
	$new_section = &$config[$section];
883
	/* generate configuration XML */
884
	$xmlconfig = dump_xml_config($new_section, $section);
885
	$xmlconfig = str_replace("<?xml version=\"1.0\"?>", "", $xmlconfig);
886
	return $xmlconfig;
887
}
888

    
889
/*
890
 *  backup_vip_config_section($section): returns as an xml file string of
891
 *                                   the configuration section
892
 */
893
function backup_vip_config_section() {
894
	global $config;
895
	$new_section = &$config['virtualip'];
896
	foreach($new_section['vip'] as $section) {
897
		if($section['mode'] == "proxyarp") {
898
			unset($section);
899
		}
900
		if($section['advskew'] <> "") {
901
			$section_val = intval($section['advskew']);
902
			$section_val=$section_val+100;
903
			if($section_val > 255)
904
				$section_val = 255;
905
			$section['advskew'] = $section_val;
906
		}
907
		$temp['vip'][] = $section;
908
   }
909
   return $temp;
910
}
911

    
912
/*
913
 *  restore_config_section($section, new_contents): restore a configuration section,
914
 *                                                  and write the configuration out
915
 *                                                  to disk/cf.
916
 */
917
function restore_config_section($section, $new_contents) {
918
	global $config, $g;
919
	conf_mount_rw();
920
	$fout = fopen("{$g['tmp_path']}/tmpxml","w");
921
	fwrite($fout, $new_contents);
922
	fclose($fout);
923
	$section_xml = parse_xml_config($g['tmp_path'] . "/tmpxml", $section);
924
	$config[$section] = &$section_xml;
925
	unlink($g['tmp_path'] . "/tmpxml");
926
	write_config("Restored {$section} of config file (maybe from CARP partner)");
927
	conf_mount_ro();
928
	return;
929
}
930

    
931
/*
932
 *  merge_config_section($section, new_contents):   restore a configuration section,
933
 *                                                  and write the configuration out
934
 *                                                  to disk/cf.  But preserve the prior
935
 * 													structure if needed
936
 */
937
function merge_config_section($section, $new_contents) {
938
	global $config;
939
	conf_mount_rw();
940
	$fname = get_tmp_filename();
941
	$fout = fopen($fname, "w");
942
	fwrite($fout, $new_contents);
943
	fclose($fout);
944
	$section_xml = parse_xml_config($fname, $section);
945
	$config[$section] = $section_xml;
946
	unlink($fname);
947
	write_config("Restored {$section} of config file (maybe from CARP partner)");
948
	conf_mount_ro();
949
	return;
950
}
951

    
952
/*
953
 * http_post($server, $port, $url, $vars): does an http post to a web server
954
 *                                         posting the vars array.
955
 * written by nf@bigpond.net.au
956
 */
957
function http_post($server, $port, $url, $vars) {
958
	$user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)";
959
	$urlencoded = "";
960
	while (list($key,$value) = each($vars))
961
		$urlencoded.= urlencode($key) . "=" . urlencode($value) . "&";
962
	$urlencoded = substr($urlencoded,0,-1);
963
	$content_length = strlen($urlencoded);
964
	$headers = "POST $url HTTP/1.1
965
Accept: */*
966
Accept-Language: en-au
967
Content-Type: application/x-www-form-urlencoded
968
User-Agent: $user_agent
969
Host: $server
970
Connection: Keep-Alive
971
Cache-Control: no-cache
972
Content-Length: $content_length
973

    
974
";
975

    
976
	$errno = "";
977
	$errstr = "";
978
	$fp = fsockopen($server, $port, $errno, $errstr);
979
	if (!$fp) {
980
		return false;
981
	}
982

    
983
	fputs($fp, $headers);
984
	fputs($fp, $urlencoded);
985

    
986
	$ret = "";
987
	while (!feof($fp))
988
		$ret.= fgets($fp, 1024);
989
	fclose($fp);
990

    
991
	return $ret;
992
}
993

    
994
/*
995
 *  php_check_syntax($code_tocheck, $errormessage): checks $code_to_check for errors
996
 */
997
if (!function_exists('php_check_syntax')){
998
	function php_check_syntax($code_to_check, &$errormessage){
999
		return false;
1000
		$fout = fopen("/tmp/codetocheck.php","w");
1001
		$code = $_POST['content'];
1002
		$code = str_replace("<?php", "", $code);
1003
		$code = str_replace("?>", "", $code);
1004
		fwrite($fout, "<?php\n\n");
1005
		fwrite($fout, $code_to_check);
1006
		fwrite($fout, "\n\n?>\n");
1007
		fclose($fout);
1008
		$command = "/usr/local/bin/php -l /tmp/codetocheck.php";
1009
		$output = exec_command($command);
1010
		if (stristr($output, "Errors parsing") == false) {
1011
			echo "false\n";
1012
			$errormessage = '';
1013
			return(false);
1014
		} else {
1015
			$errormessage = $output;
1016
			return(true);
1017
		}
1018
	}
1019
}
1020

    
1021
/*
1022
 *  php_check_filename_syntax($filename, $errormessage): checks the file $filename for errors
1023
 */
1024
if (!function_exists('php_check_syntax')){
1025
	function php_check_syntax($code_to_check, &$errormessage){
1026
		return false;
1027
		$command = "/usr/local/bin/php -l " . $code_to_check;
1028
		$output = exec_command($command);
1029
		if (stristr($output, "Errors parsing") == false) {
1030
			echo "false\n";
1031
			$errormessage = '';
1032
			return(false);
1033
		} else {
1034
			$errormessage = $output;
1035
			return(true);
1036
		}
1037
	}
1038
}
1039

    
1040
/*
1041
 * rmdir_recursive($path,$follow_links=false)
1042
 * Recursively remove a directory tree (rm -rf path)
1043
 * This is for directories _only_
1044
 */
1045
function rmdir_recursive($path,$follow_links=false) {
1046
	$to_do = glob($path);
1047
	if(!is_array($to_do)) $to_do = array($to_do);
1048
	foreach($to_do as $workingdir) { // Handle wildcards by foreaching.
1049
		if(file_exists($workingdir)) {
1050
			if(is_dir($workingdir)) {
1051
				$dir = opendir($workingdir);
1052
				while ($entry = readdir($dir)) {
1053
					if (is_file("$workingdir/$entry") || ((!$follow_links) && is_link("$workingdir/$entry")))
1054
						unlink("$workingdir/$entry");
1055
					elseif (is_dir("$workingdir/$entry") && $entry!='.' && $entry!='..')
1056
						rmdir_recursive("$workingdir/$entry");
1057
				}
1058
				closedir($dir);
1059
				rmdir($workingdir);
1060
			} elseif (is_file($workingdir)) {
1061
				unlink($workingdir);
1062
			}
1063
               	}
1064
	}
1065
	return;
1066
}
1067

    
1068
/*
1069
 * call_pfsense_method(): Call a method exposed by the pfsense.com XMLRPC server.
1070
 */
1071
function call_pfsense_method($method, $params, $timeout = 0) {
1072
	global $g, $config;
1073

    
1074
	$ip = gethostbyname($g['product_website']);
1075
	if($ip == $g['product_website'])
1076
		return false;
1077
	global $g, $config;
1078
	$xmlrpc_base_url = $g['xmlrpcbaseurl'];
1079
	$xmlrpc_path = $g['xmlrpcpath'];
1080
	$msg = new XML_RPC_Message($method, array(XML_RPC_Encode($params)));
1081
	$cli = new XML_RPC_Client($xmlrpc_path, $xmlrpc_base_url);
1082
	$resp = $cli->send($msg, $timeout);
1083
	if(!$resp) {
1084
		log_error("XMLRPC communication error: " . $cli->errstr);
1085
		return false;
1086
	} elseif($resp->faultCode()) {
1087
		log_error("XMLRPC request failed with error " . $resp->faultCode() . ": " . $resp->faultString());
1088
		return false;
1089
	} else {
1090
		return XML_RPC_Decode($resp->value());
1091
	}
1092
}
1093

    
1094
/*
1095
 * check_firmware_version(): Check whether the current firmware installed is the most recently released.
1096
 */
1097
function check_firmware_version($tocheck = "all", $return_php = true) {
1098
	global $g, $config;
1099
	$ip = gethostbyname($g['product_website']);
1100
	if($ip == $g['product_website'])
1101
		return false;
1102
	$rawparams = array("firmware" => array("version" => trim(file_get_contents('/etc/version'))),
1103
		"kernel"   => array("version" => trim(file_get_contents('/etc/version_kernel'))),
1104
		"base"     => array("version" => trim(file_get_contents('/etc/version_base'))),
1105
		"platform" => trim(file_get_contents('/etc/platform'))
1106
		);
1107
	if($tocheck == "all") {
1108
		$params = $rawparams;
1109
	} else {
1110
		foreach($tocheck as $check) {
1111
			$params['check'] = $rawparams['check'];
1112
			$params['platform'] = $rawparams['platform'];
1113
		}
1114
	}
1115
	if($config['system']['firmware']['branch']) {
1116
		$params['branch'] = $config['system']['firmware']['branch'];
1117
	}
1118
	if(!$versions = call_pfsense_method('pfsense.get_firmware_version', $params)) {
1119
		return false;
1120
	} else {
1121
		$versions["current"] = $params;
1122
	}
1123
	return $versions;
1124
}
1125

    
1126
function get_disk_info() {
1127
	$diskout = "";
1128
	exec("/bin/df -h | /usr/bin/grep -w '/' | /usr/bin/awk '{ print $2, $3, $4, $5 }'", $diskout);
1129
	return explode(' ', $diskout[0]);
1130
	// $size, $used, $avail, $cap
1131
}
1132

    
1133
/****f* pfsense-utils/display_top_tabs
1134
 * NAME
1135
 *   display_top_tabs - display tabs with rounded edges
1136
 * INPUTS
1137
 *   $text      - array of tabs
1138
 * RESULT
1139
 *   null
1140
 ******/
1141
function display_top_tabs(& $tab_array) {
1142
	global $HTTP_SERVER_VARS;
1143
	global $config;
1144
	global $g;
1145

    
1146
	/*  does the user have access to this tab?
1147
	 *  master user has access to everything.
1148
	 *  if the user does not have access, simply
1149
	 *  unset the tab item.
1150
	 */
1151

    
1152
	$tab_temp = array ();
1153
	foreach ($tab_array as $ta)
1154
		if(isAllowedPage($ta[2]))
1155
			$tab_temp[] = $ta;
1156
	/*
1157
		// FIXME :	if the checks are not good enough
1158
		//			in isAllowedPage, it needs to be
1159
		//			fixed instead of kludging here
1160

    
1161
		// TODO: humm what shall we do with pkg_edit.php and pkg.php?
1162
		if ((strpos($link, "pkg.php")) !== false || (strpos($link, "pkg_edit.php")) !== false) {
1163
			$pos_equal = strpos($link, "=");
1164
			$pos_xmlsuffix = strpos($link, ".xml");
1165
			// do we match an absolute url including ?xml= foo
1166
			if(!isAllowedPage($link, $allowed))
1167
				$link = substr($link, $pos_equal +1, ($pos_xmlsuffix - $pos_equal +3));
1168
		}
1169
		// next check - what if the basename contains a query string?
1170
		if ((strpos($link, "?")) !== false) {
1171
			$pos_qmark = strpos($link, "?");
1172
			$link = substr($link, 0, $pos_qmark);
1173
		}
1174
		$authorized_text = print_r($allowed, true);
1175
		if(is_array($authorized))
1176
			if (in_array(basename($link), $authorized))
1177
	*/
1178

    
1179
	unset ($tab_array);
1180
	$tab_array = & $tab_temp;
1181

    
1182
	$tab_active_bg   = "#EEEEEE";
1183
	$tab_inactive_bg = "#777777";
1184
	$nifty_tabs_corners = "#FFF";
1185
	$font_color = "white";
1186
	
1187
	/* if tabcontrols.php exist for a theme, allow it to be overriden */
1188
	$themename = $config['theme'];
1189
	$filename = "/usr/local/www/themes/{$themename}/tabcontrols.php";
1190
	if(file_exists($filename)) {
1191
		$eval_code = file_get_contents($filename);
1192
		eval($eval_code);
1193
	}
1194
	
1195
	$tabcharcount = 0;
1196
	foreach ($tab_array as $ta) 
1197
		$tabcharcount = $tabcharcount + strlen($ta[0]);
1198

    
1199
	// If the character count of the tab names is > 670
1200
	// then show a select item dropdown menubox.
1201
	if($tabcharcount > 82) {
1202
		echo "Currently viewing: ";
1203
		echo "<select name='TabSelect'>\n";
1204
		foreach ($tab_array as $ta) {
1205
			if($ta[1]=="true")	
1206
				$selected = " SELECTED";
1207
			else 
1208
				$selected = "";
1209
			echo "<option onClick=\"document.location='{$ta[2]}';\"{$selected}>{$ta['0']}</option>\n";
1210
		}
1211
		echo "</select>\n<p/>";
1212
	}  else {
1213
		echo "<table cellpadding='0' cellspacing='0'>\n";
1214
		echo " <tr>\n";
1215
		$tabscounter = 0;
1216
		foreach ($tab_array as $ta) {
1217
			if ($ta[1] == true) {
1218
				echo "  <td bgcolor='{$tab_active_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabactive'></div></td>\n";
1219
			} else {
1220
				echo "  <td bgcolor='{$tab_inactive_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><div id='tabdeactive{$tabscounter}'></div></td>\n";
1221
			}
1222
			$tabscounter++;
1223
		}
1224
		echo "</tr>\n<tr>\n";
1225
		foreach ($tab_array as $ta) {
1226
			if ($ta[1] == true) {
1227
				echo "  <td height=\"15\" valign=\"middle\" bgcolor='{$tab_active_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;{$ta[0]}";
1228
				echo "&nbsp;&nbsp;&nbsp;";
1229
				echo "<font size='-12'>&nbsp;</font></B></td>\n";
1230
			} else {
1231
				echo "  <td height=\"15\" valign=\"middle\" bgcolor='{$tab_inactive_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"><B>&nbsp;&nbsp;&nbsp;<a href='{$ta[2]}'>";
1232
				echo "<font color='{$font_color}'>{$ta[0]}</font></a>&nbsp;&nbsp;&nbsp;";
1233
				echo "<font size='-12'>&nbsp;</font></B></td>\n";
1234
			}
1235
		}
1236
		echo "</tr>\n<tr>\n";
1237
		foreach ($tab_array as $ta) {
1238
			if ($ta[1] == true) {
1239
				echo "  <td bgcolor='{$tab_active_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1240
			} else {
1241
				echo "  <td bgcolor='{$tab_inactive_bg}' onClick=\"document.location='{$ta[2]}'\" style=\"cursor: pointer;\"></td>\n";
1242
			}
1243
			$tabscounter++;
1244
		}
1245
		echo " </tr>\n";
1246
		echo "</table>\n";
1247
		echo "<script type=\"text/javascript\">";
1248
		echo "NiftyCheck();\n";
1249
		echo "Rounded(\"div#tabactive\",\"top\",\"{$nifty_tabs_corners}\",\"{$tab_active_bg}\",\"smooth\");\n";
1250
		for ($x = 0; $x < $tabscounter; $x++)
1251
			echo "Rounded(\"div#tabdeactive{$x}\",\"top\",\"{$nifty_tabs_corners}\",\"{$tab_inactive_bg}\",\"smooth\");\n";
1252
		echo "</script>";
1253
	}
1254
}
1255

    
1256

    
1257
/****f* pfsense-utils/display_topbar
1258
 * NAME
1259
 *   display_topbar - top a table off with rounded edges
1260
 * INPUTS
1261
 *   $text	- (optional) Text to include in bar
1262
 * RESULT
1263
 *   null
1264
 ******/
1265
function display_topbar($text = "", $bg_color="#990000", $replace_color="#FFFFFF", $rounding_style="smooth") {
1266
	echo "     <table width='100%' cellpadding='0' cellspacing='0'>\n";
1267
	echo "       <tr height='1'>\n";
1268
	echo "         <td width='100%' valign='top' color='{$bg_color}' bgcolor='{$bg_color}'>";
1269
	echo "		<div id='topbar'></div></td>\n";
1270
	echo "       </tr>\n";
1271
	echo "       <tr height='1'>\n";
1272
	if ($text != "")
1273
		echo "         <td height='1' class='listtopic'>{$text}</td>\n";
1274
	else
1275
		echo "         <td height='1' class='listtopic'></td>\n";
1276
	echo "       </tr>\n";
1277
	echo "     </table>";
1278
	echo "<script type=\"text/javascript\">";
1279
	echo "NiftyCheck();\n";
1280
	echo "Rounded(\"div#topbar\",\"top\",\"{$replace_color}\",\"{$bg_color}\",\"{$rounding_style}\");\n";
1281
	echo "</script>";
1282
}
1283

    
1284
/****f* pfsense-utils/strncpy
1285
 * NAME
1286
 *   strncpy - copy strings
1287
 * INPUTS
1288
 *   &$dst, $src, $length
1289
 * RESULT
1290
 *   none
1291
 ******/
1292
function strncpy(&$dst, $src, $length) {
1293
	if (strlen($src) > $length) {
1294
		$dst = substr($src, 0, $length);
1295
	} else {
1296
		$dst = $src;
1297
	}
1298
}
1299

    
1300
/****f* pfsense-utils/reload_interfaces_sync
1301
 * NAME
1302
 *   reload_interfaces - reload all interfaces
1303
 * INPUTS
1304
 *   none
1305
 * RESULT
1306
 *   none
1307
 ******/
1308
function reload_interfaces_sync() {
1309
	global $config, $g;
1310

    
1311
	$shutdown_webgui_needed = false;
1312

    
1313
	touch("{$g['tmp_path']}/reloading_all");
1314

    
1315
	if($g['debug'])
1316
		log_error("reload_interfaces_sync() is starting.");
1317

    
1318
	if(file_exists("{$g['tmp_path']}/config.cache"))
1319
		unlink("{$g['tmp_path']}/config.cache");
1320

    
1321
	/* parse config.xml again */
1322
	$config = parse_config(true);
1323

    
1324
	$wan_if = $config['interfaces']['wan']['if'];
1325
	if (isset($config['interfaces']['lan']))
1326
                $lan_if = $config['interfaces']['lan']['if'];
1327
        else
1328
                $lan_if = "";
1329

    
1330
	if($g['debug'])
1331
		log_error("Cleaning up Interfaces");
1332

    
1333
	/* if list */
1334
        $iflist = get_configured_interface_list(true);
1335

    
1336
	foreach ($iflist as $ifent => $ifname) {
1337
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1338

    
1339
		if(stristr($ifname, "lo0") == true)
1340
			continue;
1341
		/* do not process wan interface, its mandatory */
1342
                if(stristr($ifname, "$wan_if") == true)
1343
                        continue;
1344
                /* do not process lan interface, its mandatory */
1345
                if(stristr($ifname, "$lan_if") == true)
1346
                        continue;
1347
		if($g['debug'])
1348
			log_error("Downing and deleting $ifname_real - $ifname");
1349
		mwexec("/sbin/ifconfig {$ifname_real} down");
1350
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1351
	}
1352

    
1353
	/* set up interfaces */
1354
	interfaces_configure();
1355

    
1356
	/* set up static routes */
1357
	if($g['debug'])
1358
		log_error("Configuring system Routing");
1359
	system_routing_configure();
1360

    
1361
	/* enable routing */
1362
	if($g['debug'])
1363
		log_error("Enabling system routing");
1364
	system_routing_enable();
1365

    
1366
	/* setup captive portal if needed */
1367
	if($g['debug'])
1368
		log_error("Configuring Captive portal");
1369
	captiveportal_configure();
1370

    
1371
	/* restart webConfigurator if needed */
1372
	if($shutdown_webgui_needed == true)
1373
		touch("/tmp/restart_webgui");
1374

    
1375
	/* start devd back up */
1376
	mwexec("/bin/rm /tmp/reload*");
1377

    
1378
	/* remove reloading_all trigger */
1379
	if($g['debug'])
1380
		log_error("Removing {$g['tmp_path']}/reloading_all");
1381
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1382
}
1383

    
1384
/****f* pfsense-utils/reload_all
1385
 * NAME
1386
 *   reload_all - triggers a reload of all settings
1387
 *   * INPUTS
1388
 *   none
1389
 * RESULT
1390
 *   none
1391
 ******/
1392
function reload_all() {
1393
	touch("/tmp/reload_all");
1394
}
1395

    
1396
/****f* pfsense-utils/reload_interfaces
1397
 * NAME
1398
 *   reload_interfaces - triggers a reload of all interfaces
1399
 * INPUTS
1400
 *   none
1401
 * RESULT
1402
 *   none
1403
 ******/
1404
function reload_interfaces() {
1405
	touch("/tmp/reload_interfaces");
1406
}
1407

    
1408
/****f* pfsense-utils/reload_all_sync
1409
 * NAME
1410
 *   reload_all - reload all settings
1411
 *   * INPUTS
1412
 *   none
1413
 * RESULT
1414
 *   none
1415
 ******/
1416
function reload_all_sync() {
1417
	global $config, $g;
1418

    
1419
	$g['booting'] = false;
1420

    
1421
	touch("{$g['tmp_path']}/reloading_all");
1422

    
1423
	$shutdown_webgui_needed = false;
1424

    
1425
	if(file_exists("{$g['tmp_path']}/config.cache"))
1426
		unlink("{$g['tmp_path']}/config.cache");
1427

    
1428
	/* parse config.xml again */
1429
	$config = parse_config(true);
1430

    
1431
	/* set up our timezone */
1432
	system_timezone_configure();
1433

    
1434
	/* set up our hostname */
1435
	system_hostname_configure();
1436

    
1437
	/* make hosts file */
1438
	system_hosts_generate();
1439

    
1440
	/* generate resolv.conf */
1441
	system_resolvconf_generate();
1442

    
1443
	/* Set up our loopback interface */
1444
	interfaces_loopback_configure();
1445

    
1446
	$wan_if = $config['interfaces']['wan']['if'];
1447
	if (isset($config['interfaces']['lan']))
1448
		$lan_if = $config['interfaces']['lan']['if'];
1449
	else
1450
		$lan_if = "";
1451

    
1452
	/* if list */
1453
	$iflist = get_configured_interface_list();
1454

    
1455
	foreach ($iflist as $ifent => $ifname) {
1456
		$ifname_real = convert_friendly_interface_to_real_interface_name($ifname);
1457
		if(stristr($ifname, "lo0") == true)
1458
			continue;
1459
		/* do not process wan interface, its mandatory */
1460
		if($wan_if == $ifname_real)
1461
			continue;
1462
		/* do not process lan interface, its mandatory */
1463
		if($lan_if == $ifname_real)
1464
			continue;
1465
		mwexec("/sbin/ifconfig {$ifname_real} down");
1466
		mwexec("/sbin/ifconfig {$ifname_real} delete");
1467
	}
1468

    
1469
	/* set up interfaces */
1470
	interfaces_configure();
1471

    
1472
	/* set up static routes */
1473
	system_routing_configure();
1474

    
1475
	/* enable routing */
1476
	system_routing_enable();
1477

    
1478
	/* ensure passwords are sync'd */
1479
//	system_password_configure();
1480

    
1481
	/* start dnsmasq service */
1482
	services_dnsmasq_configure();
1483

    
1484
	/* start dyndns service */
1485
	services_dyndns_configure();
1486

    
1487
	/* start DHCP service */
1488
	services_dhcpd_configure();
1489

    
1490
	/* configure cron service */
1491
	configure_cron();
1492

    
1493
	/* start the NTP client */
1494
	system_ntp_configure();
1495

    
1496
	/* start the captive portal */
1497
	captiveportal_configure();
1498

    
1499
        /* reload the filter */
1500
	filter_configure_sync();
1501

    
1502
	/* sync pw database */
1503
	conf_mount_rw();
1504
	mwexec("/usr/sbin/pwd_mkdb -d /etc/ /etc/master.passwd");
1505
	conf_mount_ro();
1506

    
1507
	/* restart sshd */
1508
	touch("/tmp/start_sshd");
1509

    
1510
	/* restart webConfigurator if needed */
1511
	if($shutdown_webgui_needed == true)
1512
		touch("/tmp/restart_webgui");
1513

    
1514
	mwexec("/bin/rm /tmp/reload*");
1515

    
1516
	unlink_if_exists("{$g['tmp_path']}/reloading_all");
1517

    
1518
}
1519

    
1520
function auto_login($status) {
1521
	$gettytab = file_get_contents("/etc/gettytab");
1522
	$getty_split = split("\n", $gettytab);
1523
	conf_mount_rw();
1524
	$fd = fopen("/etc/gettytab", "w");
1525
	foreach($getty_split as $gs) {
1526
		if(stristr($gs, ":ht:np:sp#115200") ) {
1527
			if($status == true) {
1528
				fwrite($fd, "	:ht:np:sp#115200:al=root:\n");
1529
			} else {
1530
				fwrite($fd, "	:ht:np:sp#115200:\n");
1531
			}
1532
		} else {
1533
			fwrite($fd, "{$gs}\n");
1534
		}
1535
	}
1536
	fclose($fd);
1537
	conf_mount_ro();
1538
}
1539

    
1540
function setup_serial_port() {
1541
	global $g, $config;
1542
	conf_mount_rw();
1543
	/* serial console - write out /boot.config */
1544
	if(file_exists("/boot.config"))
1545
		$boot_config = file_get_contents("/boot.config");
1546
	else
1547
		$boot_config = "";
1548

    
1549
	if($g['platform'] <> "cdrom") {
1550
		$boot_config_split = split("\n", $boot_config);
1551
		$fd = fopen("/boot.config","w");
1552
		if($fd) {
1553
			foreach($boot_config_split as $bcs) {
1554
				if(stristr($bcs, "-D")) {
1555
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1556
				} else {
1557
					if($bcs <> "")
1558
						fwrite($fd, "{$bcs}\n");
1559
				}
1560
			}
1561
			if(isset($config['system']['enableserial'])) {
1562
				fwrite($fd, "-D");
1563
			}
1564
			fclose($fd);
1565
		}
1566
		/* serial console - write out /boot/loader.conf */
1567
		$boot_config = file_get_contents("/boot/loader.conf");
1568
		$boot_config_split = split("\n", $boot_config);
1569
		$fd = fopen("/boot/loader.conf","w");
1570
		if($fd) {
1571
			foreach($boot_config_split as $bcs) {
1572
				if(stristr($bcs, "console")) {
1573
					/* DONT WRITE OUT, WE'LL DO IT LATER */
1574
				} else {
1575
					if($bcs <> "")
1576
						fwrite($fd, "{$bcs}\n");
1577
				}
1578
			}
1579
			if(isset($config['system']['enableserial'])) {
1580
				fwrite($fd, "console=\"comconsole\"\n");
1581
			}
1582
			fclose($fd);
1583
		}
1584
	}
1585
	$ttys = file_get_contents("/etc/ttys");
1586
	$ttys_split = split("\n", $ttys);
1587
	$fd = fopen("/etc/ttys", "w");
1588
	foreach($ttys_split as $tty) {
1589
		if(stristr($tty, "ttyd0")) {
1590
			if(isset($config['system']['enableserial'])) {
1591
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	on	secure\n");
1592
			} else {
1593
				fwrite($fd, "ttyd0	\"/usr/libexec/getty bootupcli\"	dialup	off	secure\n");
1594
			}
1595
		} else {
1596
			fwrite($fd, $tty . "\n");
1597
		}
1598
	}
1599
	fclose($fd);
1600
	if(isset($config['system']['disableconsolemenu'])) {
1601
		auto_login(false);
1602
	} else {
1603
		auto_login(true);
1604
	}
1605
	conf_mount_ro();
1606
	return;
1607
}
1608

    
1609
function print_value_list($list, $count = 10, $separator = ",") {
1610
	$list = implode($separator, array_slice($list, 0, $count));
1611
	if(count($list) < $count) {
1612
		$list .= ".";
1613
	} else {
1614
		$list .= "...";
1615
	}
1616
	return $list;
1617
}
1618

    
1619
/* DHCP enabled on any interfaces? */
1620
function is_dhcp_server_enabled() 
1621
{
1622
	global $config;
1623

    
1624
	$dhcpdenable = false;
1625
	
1626
	if (!is_array($config['dhcpd']))
1627
		return false;
1628

    
1629
	$Iflist = get_configured_interface_list();
1630

    
1631
	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
1632
		if (isset($dhcpifconf['enable']) && isset($Iflist[$dhcpif])) {
1633
			$dhcpdenable = true;
1634
			break;
1635
		}
1636
	}
1637

    
1638
	return $dhcpdenable;
1639
}
1640

    
1641
/****f* pfsense-utils/isAjax
1642
 * NAME
1643
 *   isAjax - reports if the request is driven from prototype
1644
 * INPUTS
1645
 *   none
1646
 * RESULT
1647
 *   true/false
1648
 ******/
1649
function isAjax() {
1650
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1651
}
1652

    
1653
//returns interface information
1654
function get_interface_info($ifdescr) {
1655
	global $config, $linkinfo, $netstatrninfo;
1656

    
1657
	$ifinfo = array();
1658
	/* if list */
1659
	$iflist = get_configured_interface_with_descr(false,true);
1660
	
1661
	$found = false;
1662
    	foreach ($iflist as $if => $ifname) {
1663
    	if ($ifdescr == $if || $ifdescr == $ifname) {
1664
			$ifinfo['hwif'] = $config['interfaces'][$if]['if'];
1665
			$ifinfo['if'] = get_real_interface($if);
1666
			$found = true;
1667
			break;
1668
		}
1669
	}
1670
	if ($found == false)
1671
		return;
1672

    
1673
	/* run netstat to determine link info */
1674

    
1675
	unset($linkinfo);
1676
	if ($ifinfo['if'] != $ifinfo['hwif'])
1677
		$chkif = $ifinfo['hwif'];
1678
	else
1679
		$chkif = $ifinfo['if'];
1680

    
1681
	exec("/usr/bin/netstat -I {$chkif} -nWb -f link", $linkinfo);
1682

    
1683
	$linkinfo = preg_split("/\s+/", $linkinfo[1]);
1684
	if ("{$chkif}*" == $linkinfo[0])
1685
		$ifinfo['status'] = "down";
1686
	else if ($chkif == $linkinfo[0])
1687
		$ifinfo['status'] = "up";
1688
	else
1689
		$ifinfo['status'] = "down";
1690

    
1691
	if (preg_match("/^enc|^tun|^ppp|^pptp|^ovpn/i", $ifinfo['if'])) {
1692
		$ifinfo['inpkts'] = $linkinfo[3];
1693
		$ifinfo['outpkts'] = $linkinfo[6];
1694
	} else {
1695
		$ifinfo['macaddr'] = $linkinfo[3];
1696
		$ifinfo['inerrs'] = $linkinfo[5];
1697
		$ifinfo['outerrs'] = $linkinfo[8];
1698
		$ifinfo['collisions'] = $linkinfo[10];
1699
	}
1700

    
1701
	/* Use pfctl for non wrapping 64 bit counters */
1702
	/* Pass */
1703
	exec("/sbin/pfctl -vvsI -i {$ifinfo['if']}", $pfctlstats);
1704
	$pf_in4_pass = preg_split("/ +/ ", $pfctlstats[3]);
1705
	$pf_out4_pass = preg_split("/ +/", $pfctlstats[5]);
1706
	$in4_pass = $pf_in4_pass[5];
1707
	$out4_pass = $pf_out4_pass[5];
1708
	$in4_pass_packets = $pf_in4_pass[3];
1709
	$out4_pass_packets = $pf_out4_pass[3];
1710
	$ifinfo['inbytespass'] = $in4_pass;
1711
	$ifinfo['outbytespass'] = $out4_pass;
1712
	$ifinfo['inpktspass'] = $in4_pass_packets;
1713
	$ifinfo['outpktspass'] = $out4_pass_packets;
1714

    
1715
	/* Block */
1716
	$pf_in4_block = preg_split("/ +/", $pfctlstats[4]);
1717
	$pf_out4_block = preg_split("/ +/", $pfctlstats[6]);
1718
	$in4_block = $pf_in4_block[5];
1719
	$out4_block = $pf_out4_block[5];
1720
	$in4_block_packets = $pf_in4_block[3];
1721
	$out4_block_packets = $pf_out4_block[3];
1722
	$ifinfo['inbytesblock'] = $in4_block;
1723
	$ifinfo['outbytesblock'] = $out4_block;
1724
	$ifinfo['inpktsblock'] = $in4_block_packets;
1725
	$ifinfo['outpktsblock'] = $out4_block_packets;
1726

    
1727
	$ifinfo['inbytes'] = $in4_pass + $in4_block;
1728
	$ifinfo['outbytes'] = $out4_pass + $out4_block;
1729
	$ifinfo['inpkts'] = $in4_pass_packets + $in4_block_packets;
1730
	$ifinfo['outpkts'] = $in4_pass_packets + $out4_block_packets;
1731
		
1732
	$ifconfiginfo = "";
1733
	unset($ifconfiginfo, $link0);
1734
	exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo);
1735
	foreach ($ifconfiginfo as $ici) {
1736
		if (preg_match("/inet (\S+)/", $ici, $matches)) {
1737
			$ifinfo['ipaddr'] = $matches[1];
1738
		}
1739
		if (preg_match("/netmask (\S+)/", $ici, $matches)) {
1740
			if (preg_match("/^0x/", $matches[1])) {
1741
				$ifinfo['subnet'] = long2ip(hexdec($matches[1]));
1742
			}
1743
		}
1744
		if (strpos($ici, 'LINK0') !== false) {
1745
			$link0 = "down";
1746
		}
1747
	}
1748

    
1749
	switch ($config['interfaces'][$if]['ipaddr']) {
1750
	/* DHCP? -> see if dhclient is up */
1751
	case "dhcp":
1752
		/* see if dhclient is up */
1753
		if (is_dhcp_running($ifinfo['if']) == true)
1754
			$ifinfo['dhcplink'] = "up";
1755
		else
1756
			$ifinfo['dhcplink'] = "down";
1757

    
1758
		break;
1759
	case "carpdev-dhcp":
1760
		/* see if dhclient is up */
1761
		if (is_dhcp_running($ifinfo['if']) == true)
1762
			$ifinfo['dhcplink'] = "up";
1763
		else
1764
			$ifinfo['dhcplink'] = "down";
1765

    
1766
		break;
1767
	/* PPPoE interface? -> get status from virtual interface */
1768
	case "pppoe":
1769
		unset($linkinfo);
1770
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
1771
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
1772
		if ("{$ifinfo['if']}*" == $linkinfo[0])
1773
			$ifinfo['pppoelink'] = "down";
1774
		else if ($ifinfo['if'] == $linkinfo[0] && !isset($link0))
1775
			/* get PPPoE link status for dial on demand */
1776
			$ifinfo['pppoelink'] = "up";
1777
		else
1778
			$ifinfo['pppoelink'] = "down";
1779

    
1780
		break;
1781
	/* PPTP interface? -> get status from virtual interface */
1782
	case "pptp":
1783
		unset($linkinfo);
1784
		exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo);
1785
		$linkinfo = preg_split("/\s+/", $linkinfo[1]);
1786
		if ("{$ifinfo['if']}*" == $linkinfo[0])
1787
			$ifinfo['pptplink'] = "down";
1788
		else if ($ifinfo['if'] == $linkinfo[0] && !isset($link0))
1789
			/* get PPTP link status for dial on demand */
1790
			$ifinfo['pptplink'] = "up";
1791
		else
1792
			$ifinfo['pptplink'] = "down";
1793

    
1794
		break;
1795
	default:
1796
		break;
1797
	}
1798

    
1799
	if ($ifinfo['status'] == "up") {
1800
		/* try to determine media with ifconfig */
1801
		unset($ifconfiginfo);
1802
		exec("/sbin/ifconfig " . $ifinfo['hwif'], $ifconfiginfo);
1803
		$matches = "";
1804
		foreach ($ifconfiginfo as $ici) {
1805

    
1806
			/* don't list media/speed for wireless cards, as it always
1807
			   displays 2 Mbps even though clients can connect at 11 Mbps */
1808
			if (preg_match("/media: .*? \((.*?)\)/", $ici, $matches)) {
1809
				$ifinfo['media'] = $matches[1];
1810
			} else if (preg_match("/media: Ethernet (.*)/", $ici, $matches)) {
1811
				$ifinfo['media'] = $matches[1];
1812
			} else if (preg_match("/media: IEEE 802.11 Wireless Ethernet (.*)/", $ici, $matches)) {
1813
				$ifinfo['media'] = $matches[1];
1814
			}
1815

    
1816
			if (preg_match("/status: (.*)$/", $ici, $matches)) {
1817
				if ($matches[1] != "active")
1818
					$ifinfo['status'] = $matches[1];
1819
			}
1820
			if (preg_match("/channel (\S*)/", $ici, $matches)) {
1821
				$ifinfo['channel'] = $matches[1];
1822
			}
1823
			if (preg_match("/ssid (\".*?\"|\S*)/", $ici, $matches)) {
1824
				if ($matches[1][0] == '"')
1825
					$ifinfo['ssid'] = substr($matches[1], 1, -1);
1826
				else
1827
					$ifinfo['ssid'] = $matches[1];
1828
			}
1829
		}
1830
		/* lookup the gateway */
1831
		if (interface_has_gateway($if)) 
1832
			$ifinfo['gateway'] = get_interface_gateway($if);
1833
	}
1834

    
1835
	$bridge = "";
1836
	$bridge = link_interface_to_bridge($ifdescr);
1837
	if($bridge) {
1838
		$bridge_text = `/sbin/ifconfig {$bridge}`;
1839
		if(stristr($bridge_text, "blocking") <> false) {
1840
			$ifinfo['bridge'] = "<b><font color='red'>blocking</font></b> - check for ethernet loops";
1841
			$ifinfo['bridgeint'] = $bridge;
1842
		} else if(stristr($bridge_text, "learning") <> false) {
1843
			$ifinfo['bridge'] = "learning";
1844
			$ifinfo['bridgeint'] = $bridge;
1845
		} else if(stristr($bridge_text, "forwarding") <> false) {
1846
			$ifinfo['bridge'] = "forwarding";
1847
			$ifinfo['bridgeint'] = $bridge;
1848
		}
1849
	}
1850

    
1851
	return $ifinfo;
1852
}
1853

    
1854
//returns cpu speed of processor. Good for determining capabilities of machine
1855
function get_cpu_speed() {
1856
	 return exec("sysctl hw.clockrate | awk '{ print $2 }'");
1857
}
1858

    
1859
/* check if the wan interface is up
1860
 * Wait for a maximum of 10 seconds
1861
 * If the interface is up before then continue
1862
 */
1863
function is_wan_interface_up($interface) {
1864
	global $g;
1865
	global $config;
1866
	$i = 0;
1867
	while($i < 10) {
1868
		if(get_interface_gateway($interface)) {
1869
			return true;
1870
		} else {
1871
			sleep(1);
1872
		}
1873
		$i++;
1874
	}
1875
	return false;
1876
}
1877

    
1878
function add_hostname_to_watch($hostname) {
1879
	if(!is_dir("/var/db/dnscache")) {
1880
		mkdir("/var/db/dnscache");
1881
	}
1882
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
1883
		$domrecords = array();
1884
		$domips = array();
1885
		exec("host -t A $hostname", $domrecords, $rethost);
1886
		if($rethost == 0) {
1887
			foreach($domrecords as $domr) {
1888
				$doml = explode(" ", $domr);
1889
				$domip = $doml[3];
1890
				/* fill array with domain ip addresses */
1891
				if(is_ipaddr($domip)) {
1892
					$domips[] = $domip;
1893
				}
1894
			}
1895
		}
1896
		sort($domips);
1897
		$contents = "";
1898
		if(! empty($domips)) {
1899
			foreach($domips as $ip) {
1900
				$contents .= "$ip\n";
1901
			}
1902
		}
1903
		file_put_contents("/var/db/dnscache/$hostname", $contents);
1904
	}
1905
}
1906

    
1907
function find_dns_aliases() {
1908
	global $config, $g;
1909
	foreach((array) $config['aliases']['alias'] as $alias) {
1910
		$alias_value = $alias['address'];
1911
		$alias_name = $alias['name'];
1912
		if(stristr($alias_value, " ")) {
1913
			$alias_split = split(" ", $alias_value);
1914
			foreach($alias_split as $as) {
1915
				if(is_fqdn($as)) 
1916
					add_hostname_to_watch($as);			
1917
			}
1918
		} else {
1919
			if(is_fqdn($alias_value)) 
1920
				add_hostname_to_watch($alias_value);
1921
		}
1922
	}
1923
}
1924

    
1925
function is_fqdn($fqdn) {
1926
	$hostname = false;
1927
	if(preg_match("/[-A-Z0-9\.]+\.[-A-Z0-9\.]+/i", $fqdn)) {
1928
		$hostname = true;
1929
	}
1930
	if(preg_match("/\.\./", $fqdn)) {
1931
		$hostname = false;
1932
	}
1933
	if(preg_match("/^\./i", $fqdn)) { 
1934
		$hostname = false;
1935
	}
1936
	if(preg_match("/\//i", $fqdn)) {
1937
		$hostname = false;
1938
	}
1939
	return($hostname);
1940
}
1941

    
1942
function pfsense_default_state_size() {
1943
  /* get system memory amount */
1944
  $memory = get_memory();
1945
  $avail = $memory[0];
1946
  /* Be cautious and only allocate 10% of system memory to the state table */
1947
  $max_states = (int) ($avail/10)*1000;
1948
  return $max_states;
1949
}
1950

    
1951
/****f* pfsense-utils/safe_write_file
1952
 * NAME
1953
 *   safe_write_file - Write a file out atomically
1954
 * DESCRIPTION
1955
 *   safe_write_file() Writes a file out atomically by first writing to a
1956
 *   temporary file of the same name but ending with the pid of the current
1957
 *   process, them renaming the temporary file over the original.
1958
 * INPUTS
1959
 *   $filename  - string containing the filename of the file to write
1960
 *   $content   - string containing the file content to write to file
1961
 *   $force_binary      - boolean denoting whether we should force binary
1962
 *   mode writing.
1963
 * RESULT
1964
 *   boolean - true if successful, false if not
1965
 ******/
1966
function safe_write_file($file, $content, $force_binary) {
1967
        $tmp_file = $file . "." . getmypid();
1968
        $write_mode = $force_binary ? "wb" : "w";
1969

    
1970
        $fd = fopen($tmp_file, $write_mode);
1971
        if (!$fd) {
1972
                // Unable to open temporary file for writing
1973
                return false;
1974
        }
1975
        if (!fwrite($fd, $content)) {
1976
                // Unable to write to temporary file
1977
                fclose($fd);
1978
                return false;
1979
        }
1980
        fclose($fd);
1981

    
1982
        if (!rename($tmp_file, $file)) {
1983
                // Unable to move temporary file to original
1984
                unlink($tmp_file);
1985
                return false;
1986
        }
1987
        return true;
1988
}
1989

    
1990
function rule_popup($src,$srcport,$dst,$dstport){
1991
global $config;
1992
$aliases_array = array();
1993
if($config['aliases']['alias'] <> "" and is_array($config['aliases']['alias']))
1994
{
1995
$span_begin = "";
1996
		$alias_src_span_begin = "";
1997
		$alias_src_span_end = "";
1998
		$alias_src_port_span_begin = "";
1999
		$alias_src_port_span_end = "";
2000
		$alias_dst_span_begin = "";
2001
		$alias_dst_span_end = "";
2002
		$alias_dst_port_span_begin = "";
2003
		$alias_dst_port_span_end = "";
2004
		$alias_content_text = "";
2005
	foreach($config['aliases']['alias'] as $alias_name) 
2006
	{	
2007
	 	$alias_addresses = explode (" ", $alias_name['address']);
2008
	 	$alias_details = explode ("||", $alias_name['detail']);
2009
	 	$alias_objects_with_details = "";
2010
	 	$counter = 0;
2011
	 	foreach($alias_addresses as $alias_ports_address)
2012
	 	{
2013
			$alias_objects_with_details .= $alias_addresses[$counter];
2014
			$alias_detail_default = strpos ($alias_details[$counter],"Entry added");
2015
			if ($alias_details[$counter] != "" && $alias_detail_default === False){
2016
				$alias_objects_with_details .=" - " . $alias_details[$counter];
2017
			}  
2018
			$alias_objects_with_details .= "<br>";
2019
			$counter++;
2020
		}			
2021
		//max character length for caption field
2022
		$maxlength = 60;
2023
		
2024
		$alias_descr_substr = $alias_name['descr'];
2025
		$alias_content_text = htmlspecialchars($alias_objects_with_details);
2026
		$alias_caption = htmlspecialchars($alias_descr_substr . ":");
2027
		$strlength = strlen ($alias_caption);
2028
		if ($strlength >= $maxlength) 
2029
			$alias_caption = substr($alias_caption, 0, $maxlength) . "...";		
2030
						
2031
		$span_begin = "<span style=\"cursor: help;\" onmouseover=\"domTT_activate(this, event, 'content', '<h1>$alias_caption</h1><p>$alias_content_text</p>', 'trail', true, 'delay', 0, 'fade', 'both', 'fadeMax', 93, 'styleClass', 'niceTitle');\" onmouseout=\"this.style.color = ''; domTT_mouseout(this, event);\"><U>";
2032
		
2033
		
2034
		if ($alias_name['name'] == $src)
2035
	 	{										
2036
			$alias_src_span_begin = $span_begin;
2037
		}
2038
	 	if ($alias_name['name'] == $srcport)
2039
	 	{									
2040
			$alias_src_port_span_begin = $span_begin;					
2041
		}
2042
		if ($alias_name['name'] == $dst)
2043
	 	{										
2044
			$alias_dst_span_begin = $span_begin;									
2045
		}
2046
		if ($alias_name['name'] == $dstport)
2047
	 	{											
2048
			$alias_dst_port_span_begin = $span_begin;											
2049
		}										
2050
		
2051
	}
2052
	$descriptions = array ();
2053
	$descriptions['src'] = $alias_src_span_begin;
2054
	$descriptions['srcport'] = $alias_src_port_span_begin;
2055
	$descriptions['dst'] = $alias_dst_span_begin;
2056
	$descriptions['dstport'] = $alias_dst_port_span_begin;
2057
	return $descriptions; 
2058
  }
2059
}
2060
function download_file_with_progress_bar($url_file, $destination_file, $readbody = 'read_body') {
2061
	global $ch, $fout, $file_size, $downloaded;
2062
	$file_size  = 1;
2063
	$downloaded = 1;
2064
	/* open destination file */
2065
	$fout = fopen($destination_file, "wb");
2066

    
2067
	/*
2068
	 *	Originally by Author: Keyvan Minoukadeh
2069
	 *	Modified by Scott Ullrich to return Content-Length size
2070
         */
2071

    
2072
	$ch = curl_init();
2073
	curl_setopt($ch, CURLOPT_URL, $url_file);
2074
	curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
2075
	curl_setopt($ch, CURLOPT_WRITEFUNCTION, $readbody);
2076
	curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
2077
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, '5');
2078
	curl_setopt($ch, CURLOPT_TIMEOUT, 0);
2079
	
2080
	curl_exec($ch);
2081
	$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
2082
	if($fout)
2083
		fclose($fout);
2084
	curl_close($ch);
2085
	return ($http_code == 200) ? true : $http_code;
2086
}
2087

    
2088
function read_header($ch, $string) {
2089
	global $file_size, $fout;
2090
	$length = strlen($string);
2091
	$regs = "";
2092
	ereg("(Content-Length:) (.*)", $string, $regs);
2093
	if($regs[2] <> "") {
2094
		$file_size = intval($regs[2]);
2095
	}
2096
	ob_flush();
2097
	return $length;
2098
}
2099

    
2100
function read_body($ch, $string) {
2101
	global $fout, $file_size, $downloaded, $sendto, $static_status, $static_output, $lastseen;
2102
	$length = strlen($string);
2103
	$downloaded += intval($length);
2104
	$downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
2105
	$downloadProgress = 100 - $downloadProgress;
2106
	if($lastseen <> $downloadProgress and $downloadProgress < 101) {
2107
		if($sendto == "status") {
2108
			$tostatus = $static_status . $downloadProgress . "%";
2109
			update_status($tostatus);
2110
		} else {
2111
			$tooutput = $static_output . $downloadProgress . "%";
2112
			update_output_window($tooutput);
2113
		}
2114
		update_progress_bar($downloadProgress);
2115
		$lastseen = $downloadProgress;
2116
	}
2117
	if($fout)
2118
		fwrite($fout, $string);
2119
	ob_flush();
2120
	return $length;
2121
}
2122

    
2123
/* Compare the current hostname DNS to the DNS cache we made
2124
 * if it has changed we return the old records
2125
 * if no change we return true */
2126
function compare_hostname_to_dnscache($hostname) {
2127
	if(!is_dir("/var/db/dnscache")) {
2128
		mkdir("/var/db/dnscache");
2129
	}
2130
	$hostname = trim($hostname);
2131
	if(is_readable("/var/db/dnscache/{$hostname}")) {
2132
		$oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
2133
	} else {
2134
		$oldcontents = "";
2135
	}
2136
	if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
2137
		$domrecords = array();
2138
		$domips = array();
2139
		exec("host -t A $hostname", $domrecords, $rethost);
2140
		if($rethost == 0) {
2141
			foreach($domrecords as $domr) {
2142
				$doml = explode(" ", $domr);
2143
				$domip = $doml[3];
2144
				/* fill array with domain ip addresses */
2145
				if(is_ipaddr($domip)) {
2146
					$domips[] = $domip;
2147
				}
2148
			}
2149
		}
2150
		sort($domips);
2151
		$contents = "";
2152
		if(! empty($domips)) {
2153
			foreach($domips as $ip) {
2154
				$contents .= "$ip\n";
2155
			}
2156
		}
2157
	}
2158

    
2159
	if(trim($oldcontents) != trim($contents)) {
2160
		log_error("DNSCACHE: Found old IP {$oldcontents} and new IP {$contents}");
2161
		return ($oldcontents);
2162
	} else {
2163
		return false;
2164
	}
2165
}
2166

    
2167
?>
(22-22/40)