Project

General

Profile

Download (35.8 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/config
3
 * NAME
4
 *   config.inc - Functions to manipulate config.xml
5
 * DESCRIPTION
6
 *   This include contains various config.xml specific functions.
7
 * HISTORY
8
 * $Id$
9
 ******
10

    
11
	config.inc
12
	Copyright (C) 2004 Scott Ullrich
13
	All rights reserved.
14

    
15
	originally part of m0n0wall (http://m0n0.ch/wall)
16
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
17
	All rights reserved.
18

    
19
	Redistribution and use in source and binary forms, with or without
20
	modification, are permitted provided that the following conditions are met:
21

    
22
	1. Redistributions of source code must retain the above copyright notice,
23
	   this list of conditions and the following disclaimer.
24

    
25
	2. Redistributions in binary form must reproduce the above copyright
26
	   notice, this list of conditions and the following disclaimer in the
27
	   documentation and/or other materials provided with the distribution.
28

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

    
41
/* do not load this file twice. */
42
if($config_inc_loaded == true)
43
	return;
44
else
45
	$config_inc_loaded = true;
46

    
47
/* include globals/utility/XML parser files */
48
require_once("globals.inc");
49
require_once("util.inc");
50
require_once("pfsense-utils.inc");
51
require_once("xmlparse.inc");
52

    
53
/* read platform */
54
if (file_exists("{$g['etc_path']}/platform")) {
55
	$g['platform'] = chop(file_get_contents("{$g['etc_path']}/platform"));
56
} else {
57
	$g['platform'] = "unknown";
58
}
59

    
60
/* if our config file exists bail out, we're already set. */
61
if ($g['booting'] and !file_exists($g['cf_conf_path'] . "/config.xml")  ) {
62
	/* find the device where config.xml resides and write out an fstab */
63
	unset($cfgdevice);
64

    
65
	/* check if there's already an fstab (NFS booting?) */
66
	if (!file_exists("{$g['etc_path']}/fstab")) {
67

    
68
		if (strstr($g['platform'], "cdrom")) {
69
			/* config is on floppy disk for CD-ROM version */
70
			$cfgdevice = $cfgpartition = "fd0";
71
			$dmesg = `dmesg -a`;
72
			if(ereg("da0", $dmesg) == true) {
73
				$cfgdevice = $cfgpartition = "da0" ;
74
				if (mwexec("/sbin/mount -r /dev/{$cfgdevice} /cf")) {
75
					/* could not mount, fallback to floppy */
76
					$cfgdevice = $cfgpartition = "fd0";
77
				}
78
			}
79
			$cfgfstype = "msdos";
80
			echo "CDROM build\n";
81
			echo "   CFG: {$cfgpartition}\n";
82
			echo "  TYPE: {$cfgfstype}\n";
83
		} else {
84
			/* probe kernel known disks until we find one with config.xml */
85
			$disks = explode(" ", trim(preg_replace("/kern.disks: /", "", exec("/sbin/sysctl kern.disks"))));
86
			foreach ($disks as $mountdisk) {
87
				/* skip mfs mounted filesystems */
88
				if (strstr($mountdisk, "md"))
89
					continue;
90
				if (mwexec("/sbin/mount -r /dev/{$mountdisk}a {$g['cf_path']}") == 0) {
91
					if (file_exists("{$g['cf_conf_path']}/config.xml")) {
92
						/* found it */
93
						$cfgdevice = $mountdisk;
94
						$cfgpartition = $cfgdevice . "a";
95
						$cfgfstype = "ufs";
96
						echo "Found configuration on $cfgdevice.\n";
97
					}
98

    
99
					mwexec("/sbin/umount -f {$g['cf_path']}");
100

    
101
					if ($cfgdevice)
102
						break;
103
				}
104
				if (mwexec("/sbin/mount -r /dev/{$mountdisk}d {$g['cf_path']}") == 0) {
105
					if (file_exists("{$g['cf_conf_path']}/config.xml")) {
106
						/* found it */
107
						$cfgdevice = $mountdisk;
108
						$cfgpartition = $cfgdevice . "d";
109
						$cfgfstype = "ufs";
110
						echo "Found configuration on $cfgdevice.\n";
111
					}
112

    
113
					mwexec("/sbin/umount -f {$g['cf_path']}");
114

    
115
					if ($cfgdevice)
116
						break;
117
				}
118
			}
119
		}
120

    
121
		if (!$cfgdevice) {
122
			/* no device found, print an error and die */
123
			echo <<<EOD
124

    
125

    
126
*******************************************************************************
127
* FATAL ERROR                                                                 *
128
* The device that contains the configuration file (config.xml) could not be   *
129
* found. pfSense cannot continue booting.                                     *
130
*******************************************************************************
131

    
132

    
133
EOD;
134

    
135
			mwexec("/sbin/halt");
136
			exit;
137
		}
138

    
139
		/* write device name to a file for rc.firmware */
140
		$fd = fopen("{$g['varetc_path']}/cfdevice", "w");
141
		fwrite($fd, $cfgdevice . "\n");
142
		fclose($fd);
143

    
144
		/* write out an fstab */
145
		$fd = fopen("{$g['etc_path']}/fstab", "w");
146

    
147
		$fstab = "/dev/{$cfgpartition} {$g['cf_path']} {$cfgfstype} ro 1 1\n";
148
		$fstab .= "proc /proc procfs rw 0 0\n";
149

    
150
		fwrite($fd, $fstab);
151
		fclose($fd);
152
	}
153

    
154
	/* mount all filesystems */
155
	mwexec("/sbin/mount -a");
156
}
157

    
158
$config = parse_config();
159

    
160
/****f* config/parse_config
161
 * NAME
162
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
163
 * INPUTS
164
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
165
 * RESULT
166
 *   $config      - array containing all configuration variables
167
 ******/
168
function parse_config($parse = false) {
169
	global $g;
170

    
171
	config_lock();
172
	if(!$parse) {
173
		if(file_exists($g['tmp_path'] . '/config.cache')) {
174
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
175
			if(is_null($config)) {
176
				config_unlock();
177
				parse_config(true);
178
			}
179
		} else {
180
			config_unlock();
181
			$config = parse_config(true);
182
		}
183
	} else {
184
		$config = parse_xml_config($g['conf_path'] . '/config.xml', $g['xml_rootobj']);
185
		generate_config_cache($config);
186
	}
187
	
188
	alias_make_table($config);
189
	config_unlock();
190
	return $config;
191
}
192

    
193
/****f* config/generate_config_cache
194
 * NAME
195
 *   generate_config_cache - Write serialized configuration to cache.
196
 * INPUTS
197
 *   $config	- array containing current firewall configuration
198
 * RESULT
199
 *   boolean	- true on completion
200
 ******/
201
function generate_config_cache($config) {
202
	global $g;
203
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
204
	fwrite($configcache, serialize($config));
205
	fclose($configcache);
206
	return true;
207
}
208

    
209
/****f* config/parse_config_bootup
210
 * NAME
211
 *   parse_config_bootup - Bootup-specific configuration checks.
212
 * RESULT
213
 *   null
214
 ******/
215
function parse_config_bootup() {
216
	global $config, $g;
217
	if (!$noparseconfig) {
218
		if (!file_exists("{$g['conf_path']}/config.xml")) {
219
			config_lock();
220
			if ($g['booting']) {
221
				if (strstr($g['platform'], "cdrom")) {
222
					/* try copying the default config. to the floppy */
223
					echo "Resetting factory defaults...\n";
224
					reset_factory_defaults();
225
	
226
					echo "No XML configuration file found - using factory defaults.\n";
227
					echo "Make sure that the configuration floppy disk with the conf/config.xml\n";
228
					echo "file is inserted. If it isn't, your configuration changes will be lost\n";
229
					echo "on reboot.\n";
230
				} else {
231
					echo "XML configuration file not found.  pfSense cannot continue booting.\n";
232
					mwexec("/sbin/halt");
233
					exit;
234
				}
235
			} else {
236
				config_unlock();
237
				exit(0);
238
			}
239
		}
240
	}
241

    
242
	parse_config(true);
243
	
244
	if ((float)$config['version'] > (float)$g['latest_config']) {
245
		echo <<<EOD
246

    
247

    
248
*******************************************************************************
249
* WARNING!                                                                    *
250
* The current configuration has been created with a newer version of pfSense  *
251
* than this one! This can lead to serious misbehavior and even security       *
252
* holes! You are urged to either upgrade to a newer version of pfSense or     *
253
* revert to the default configuration immediately!                            *
254
*******************************************************************************
255

    
256

    
257
EOD;
258
		}
259

    
260
	/* make alias table (for faster lookups) */
261
	alias_make_table($config);
262
	config_unlock();
263
}
264

    
265
/****f* config/conf_mount_rw
266
 * NAME
267
 *   conf_mount_rw - Mount filesystems read/write.
268
 * RESULT
269
 *   null
270
 ******/
271
/* mount flash card read/write */
272
function conf_mount_rw() {
273
	global $g;
274

    
275
	/* do not mount on cdrom platform */
276
	if($g['platform'] == "cdrom")
277
		return;
278

    
279
	/* don't use mount -u anymore
280
	   (doesn't sync the files properly and /bin/sync won't help either) */
281
	$status = mwexec("/sbin/umount -f {$g['cf_path']}");
282

    
283
	$status = mwexec("/sbin/mount -w -o noatime {$g['cf_path']}");
284
	if($status <> 0) {
285
		mwexec("/sbin/fsck -y {$g['cf_path']}");
286
		$status = mwexec("/sbin/mount -w -o noatime {$g['cf_path']}");
287
	}
288

    
289
	/*    if the platform is soekris or wrap or pfSense, lets mount the
290
	 *    compact flash cards root.
291
         */
292
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx"
293
	   or $g['platform'] == "embedded") {
294
		mwexec("/sbin/umount -f /");
295
		$status = mwexec("/sbin/mount -w /");
296
		/* we could not mount this correctly.  kick off fsck */
297
		if($status <> 0) {
298
			log_error("File system is dirty.  Launching FSCK for /");
299
			mwexec("/sbin/fsck -y");
300
			$status = mwexec("/sbin/mount -w /");
301
		}
302
	}
303
}
304

    
305
/****f* config/conf_mount_ro
306
 * NAME         
307
 *   conf_mount_ro - Mount filesystems readonly.
308
 * RESULT
309
 *   null        
310
 ******/
311
function conf_mount_ro() {
312
	global $g;
313

    
314
	if($g['booting'] == true) return;
315
	
316
	/* do not umount on cdrom platform */
317
	if($g['platform'] == "cdrom")
318
		return;
319

    
320
	mwexec("/sbin/umount -f {$g['cf_path']}");
321
	mwexec("/sbin/mount -r {$g['cf_path']}");
322
	/*    if the platform is soekris or wrap, lets unmount the
323
	 *    compact flash card.
324
         */
325
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx"
326
	   or $g['platform'] == "embedded") {
327
		mwexec("/sbin/umount -f /");
328
		mwexec("/sbin/mount -f -r /");
329
	}
330
}
331

    
332
/****f* config/convert_config
333
 * NAME         
334
 *   convert_config - Attempt to update config.xml.
335
 * DESCRIPTION
336
 *   convert_config() reads the current global configuration
337
 *   and attempts to convert it to conform to the latest
338
 *   config.xml version. This allows major formatting changes
339
 *   to be made with a minimum of breakage.
340
 * RESULT
341
 *   null        
342
 ******/
343
/* convert configuration, if necessary */
344
function convert_config() {
345
	global $config, $g;
346

    
347
	if ($config['version'] == $g['latest_config'])
348
		return;		/* already at latest version */
349

    
350
	// Save off config version
351
	$prev_version = $config['version'];
352

    
353
	/* convert 1.0 -> 1.1 */
354
	if ($config['version'] == "1.0") {
355
		$opti = 1;
356
		$ifmap = array('lan' => 'lan', 'wan' => 'wan', 'pptp' => 'pptp');
357

    
358
		/* convert DMZ to optional, if necessary */
359
		if (isset($config['interfaces']['dmz'])) {
360

    
361
			$dmzcfg = &$config['interfaces']['dmz'];
362

    
363
			if ($dmzcfg['if']) {
364
				$config['interfaces']['opt' . $opti] = array();
365
				$optcfg = &$config['interfaces']['opt' . $opti];
366

    
367
				$optcfg['enable'] = $dmzcfg['enable'];
368
				$optcfg['descr'] = "DMZ";
369
				$optcfg['if'] = $dmzcfg['if'];
370
				$optcfg['ipaddr'] = $dmzcfg['ipaddr'];
371
				$optcfg['subnet'] = $dmzcfg['subnet'];
372

    
373
				$ifmap['dmz'] = "opt" . $opti;
374
				$opti++;
375
			}
376

    
377
			unset($config['interfaces']['dmz']);
378
		}
379

    
380
		/* convert WLAN1/2 to optional, if necessary */
381
		for ($i = 1; isset($config['interfaces']['wlan' . $i]); $i++) {
382

    
383
			if (!$config['interfaces']['wlan' . $i]['if']) {
384
				unset($config['interfaces']['wlan' . $i]);
385
				continue;
386
			}
387

    
388
			$wlancfg = &$config['interfaces']['wlan' . $i];
389
			$config['interfaces']['opt' . $opti] = array();
390
			$optcfg = &$config['interfaces']['opt' . $opti];
391

    
392
			$optcfg['enable'] = $wlancfg['enable'];
393
			$optcfg['descr'] = "WLAN" . $i;
394
			$optcfg['if'] = $wlancfg['if'];
395
			$optcfg['ipaddr'] = $wlancfg['ipaddr'];
396
			$optcfg['subnet'] = $wlancfg['subnet'];
397
			$optcfg['bridge'] = $wlancfg['bridge'];
398

    
399
			$optcfg['wireless'] = array();
400
			$optcfg['wireless']['mode'] = $wlancfg['mode'];
401
			$optcfg['wireless']['ssid'] = $wlancfg['ssid'];
402
			$optcfg['wireless']['channel'] = $wlancfg['channel'];
403
			$optcfg['wireless']['wep'] = $wlancfg['wep'];
404

    
405
			$ifmap['wlan' . $i] = "opt" . $opti;
406

    
407
			unset($config['interfaces']['wlan' . $i]);
408
			$opti++;
409
		}
410

    
411
		/* convert filter rules */
412
		$n = count($config['filter']['rule']);
413
		for ($i = 0; $i < $n; $i++) {
414

    
415
			$fr = &$config['filter']['rule'][$i];
416

    
417
			/* remap interface */
418
			if (array_key_exists($fr['interface'], $ifmap))
419
				$fr['interface'] = $ifmap[$fr['interface']];
420
			else {
421
				/* remove the rule */
422
				echo "\nWarning: filter rule removed " .
423
					"(interface '{$fr['interface']}' does not exist anymore).";
424
				unset($config['filter']['rule'][$i]);
425
				continue;
426
			}
427

    
428
			/* remap source network */
429
			if (isset($fr['source']['network'])) {
430
				if (array_key_exists($fr['source']['network'], $ifmap))
431
					$fr['source']['network'] = $ifmap[$fr['source']['network']];
432
				else {
433
					/* remove the rule */
434
					echo "\nWarning: filter rule removed " .
435
						"(source network '{$fr['source']['network']}' does not exist anymore).";
436
					unset($config['filter']['rule'][$i]);
437
					continue;
438
				}
439
			}
440

    
441
			/* remap destination network */
442
			if (isset($fr['destination']['network'])) {
443
				if (array_key_exists($fr['destination']['network'], $ifmap))
444
					$fr['destination']['network'] = $ifmap[$fr['destination']['network']];
445
				else {
446
					/* remove the rule */
447
					echo "\nWarning: filter rule removed " .
448
						"(destination network '{$fr['destination']['network']}' does not exist anymore).";
449
					unset($config['filter']['rule'][$i]);
450
					continue;
451
				}
452
			}
453
		}
454

    
455
		/* convert shaper rules */
456
		$n = count($config['pfqueueing']['rule']);
457
		if (is_array($config['pfqueueing']['rule']))
458
			for ($i = 0; $i < $n; $i++) {
459

    
460
			$fr = &$config['pfqueueing']['rule'][$i];
461

    
462
			/* remap interface */
463
			if (array_key_exists($fr['interface'], $ifmap))
464
				$fr['interface'] = $ifmap[$fr['interface']];
465
			else {
466
				/* remove the rule */
467
				echo "\nWarning: traffic shaper rule removed " .
468
					"(interface '{$fr['interface']}' does not exist anymore).";
469
				unset($config['pfqueueing']['rule'][$i]);
470
				continue;
471
			}
472

    
473
			/* remap source network */
474
			if (isset($fr['source']['network'])) {
475
				if (array_key_exists($fr['source']['network'], $ifmap))
476
					$fr['source']['network'] = $ifmap[$fr['source']['network']];
477
				else {
478
					/* remove the rule */
479
					echo "\nWarning: traffic shaper rule removed " .
480
						"(source network '{$fr['source']['network']}' does not exist anymore).";
481
					unset($config['pfqueueing']['rule'][$i]);
482
					continue;
483
				}
484
			}
485

    
486
			/* remap destination network */
487
			if (isset($fr['destination']['network'])) {
488
				if (array_key_exists($fr['destination']['network'], $ifmap))
489
					$fr['destination']['network'] = $ifmap[$fr['destination']['network']];
490
				else {
491
					/* remove the rule */
492
					echo "\nWarning: traffic shaper rule removed " .
493
						"(destination network '{$fr['destination']['network']}' does not exist anymore).";
494
					unset($config['pfqueueing']['rule'][$i]);
495
					continue;
496
				}
497
			}
498
		}
499

    
500
		$config['version'] = "1.1";
501
	}
502

    
503
	/* convert 1.1 -> 1.2 */
504
	if ($config['version'] == "1.1") {
505
		/* move LAN DHCP server config */
506
		$tmp = $config['dhcpd'];
507
		$config['dhcpd'] = array();
508
		$config['dhcpd']['lan'] = $tmp;
509

    
510
		/* encrypt password */
511
		$config['system']['password'] = crypt($config['system']['password']);
512

    
513
		$config['version'] = "1.2";
514
	}
515

    
516
	/* convert 1.2 -> 1.3 */
517
	if ($config['version'] == "1.2") {
518
		/* convert advanced outbound NAT config */
519
		for ($i = 0; isset($config['nat']['advancedoutbound']['rule'][$i]); $i++) {
520
			$curent = &$config['nat']['advancedoutbound']['rule'][$i];
521
			$src = $curent['source'];
522
			$curent['source'] = array();
523
			$curent['source']['network'] = $src;
524
			$curent['destination'] = array();
525
			$curent['destination']['any'] = true;
526
		}
527

    
528
		/* add an explicit type="pass" to all filter rules to make things consistent */
529
		for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
530
			$config['filter']['rule'][$i]['type'] = "pass";
531
		}
532

    
533
		$config['version'] = "1.3";
534
	}
535

    
536
	/* convert 1.3 -> 1.4 */
537
	if ($config['version'] == "1.3") {
538
		/* convert shaper rules (make pipes) */
539
		if (is_array($config['pfqueueing']['rule'])) {
540
			$config['pfqueueing']['pipe'] = array();
541

    
542
			for ($i = 0; isset($config['pfqueueing']['rule'][$i]); $i++) {
543
				$curent = &$config['pfqueueing']['rule'][$i];
544

    
545
				/* make new pipe and associate with this rule */
546
				$newpipe = array();
547
				$newpipe['descr'] = $curent['descr'];
548
				$newpipe['bandwidth'] = $curent['bandwidth'];
549
				$newpipe['delay'] = $curent['delay'];
550
				$newpipe['mask'] = $curent['mask'];
551
				$config['pfqueueing']['pipe'][$i] = $newpipe;
552

    
553
				$curent['targetpipe'] = $i;
554

    
555
				unset($curent['bandwidth']);
556
				unset($curent['delay']);
557
				unset($curent['mask']);
558
			}
559
		}
560

    
561
		$config['version'] = "1.4";
562
	}
563

    
564
	/* Convert 1.4 -> 1.5 */
565
	if ($config['version'] == "1.4") {
566

    
567
		/* Default route moved */
568
		if (isset($config['interfaces']['wan']['gateway']))
569
			if ($config['interfaces']['wan']['gateway'] <> "")
570
				$config['system']['gateway'] = $config['interfaces']['wan']['gateway'];
571
		unset($config['interfaces']['wan']['gateway']);
572

    
573
                /* Queues are no longer interface specific */
574
                if (isset($config['interfaces']['lan']['schedulertype']))
575
                        unset($config['interfaces']['lan']['schedulertype']);
576
                if (isset($config['interfaces']['wan']['schedulertype']))
577
                        unset($config['interfaces']['wan']['schedulertype']);
578

    
579
                for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
580
                        if(isset($config['interfaces']['opt' . $i]['schedulertype']))
581
                                unset($config['interfaces']['opt' . $i]['schedulertype']);
582
                }
583

    
584
		$config['version'] = "1.5";
585
	}
586

    
587
	/* Convert 1.5 -> 1.6 */
588
	if ($config['version'] == "1.5") {
589
		/* Alternate firmware URL moved */
590
		if (isset($config['system']['firmwareurl']) && isset($config['system']['firmwarename'])) { // Only convert if *both* are defined.
591
			$config['system']['alt_firmware_url'] = array();
592
			$config['system']['alt_firmware_url']['enabled'] = "";
593
			$config['system']['alt_firmware_url']['firmware_base_url'] = $config['system']['firmwareurl'];
594
			$config['system']['alt_firmware_url']['firmware_filename'] = $config['system']['firmwarename'];
595
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
596
		} else {
597
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
598
		}
599

    
600
		$config['version'] = "1.6";
601
	}
602
	
603
	/* Convert 1.6 -> 1.7 */
604
	if ($config['version'] == "1.6") {
605
		/* wipe previous shaper configuration */
606
		unset($config['shaper']['queue']);
607
		unset($config['shaper']['rule']);
608
		unset($config['interfaces']['wan']['bandwidth']);
609
		unset($config['interfaces']['wan']['bandwidthtype']);
610
		unset($config['interfaces']['lan']['bandwidth']);
611
		unset($config['interfaces']['lan']['bandwidthtype']);		
612
		$config['shaper']['enable'] = FALSE;
613
		$config['version'] = "1.7";	
614
	}
615
	/* Convert 1.7 -> 1.8 */
616
	if ($config['version'] == "1.7") {
617
		if(isset($config['proxyarp']) && is_array($config['proxyarp']['proxyarpnet'])) {
618
			$proxyarp = &$config['proxyarp']['proxyarpnet'];
619
			foreach($proxyarp as $arpent){
620
				$vip = array();
621
				$vip['mode'] = "proxyarp";
622
				$vip['interface'] = $arpent['interface'];
623
				$vip['descr'] = $arpent['descr'];
624
				if (isset($arpent['range'])) {
625
					$vip['range'] = $arpent['range'];
626
					$vip['type'] = "range";
627
				} else {
628
					$subnet = explode('/', $arpent['network']);
629
					$vip['subnet'] = $subnet[0];
630
					if (isset($subnet[1])) {
631
						$vip['subnet_bits'] = $subnet[1];
632
						$vip['type'] = "network";
633
					} else {
634
						$vip['subnet_bits'] = "32";
635
						$vip['type'] = "single";
636
					}
637
				}
638
				$config['virtualip']['vip'][] = $vip;
639
			}
640
			unset($config['proxyarp']);
641
		}
642
		if(isset($config['installedpackages']) && isset($config['installedpackages']['carp']) && is_array($config['installedpackages']['carp']['config'])) {
643
			$carp = &$config['installedpackages']['carp']['config'];
644
			foreach($carp as $carpent){
645
				$vip = array();
646
				$vip['mode'] = "carp";
647
				$vip['interface'] = "AUTO";
648
				$vip['descr'] = "CARP vhid {$carpent['vhid']}";
649
				$vip['type'] = "single";
650
				$vip['vhid'] = $carpent['vhid'];
651
				$vip['advskew'] = $carpent['advskew'];
652
				$vip['password'] = $carpent['password'];
653
				$vip['subnet'] = $carpent['ipaddress'];
654
				$vip['subnet_bits'] = $carpent['netmask'];
655
				$config['virtualip']['vip'][] = $vip;
656
			}
657
			unset($config['installedpackages']['carp']);
658
		}
659
		/* Server NAT is no longer needed */
660
		unset($config['nat']['servernat']);
661
		
662
		/* enable SSH */
663
		if ($config['version'] == "1.8") {
664
			$config['system']['sshenabled'] = true;
665
		}
666
		
667
		$config['version'] = "1.9";
668
	}
669

    
670
	/* Convert 1.8 -> 1.9 */
671
	if ($config['version'] == "1.8") {
672
		$config['theme']="metallic";
673
		$config['version'] = "1.9";
674
	}
675
	/* Convert 1.9 -> 2.0 */
676
	if ($config['version'] == "1.9") {
677
		if(is_array($config['ipsec']['tunnel'])) {
678
			reset($config['ipsec']['tunnel']);
679
			while (list($index, $tunnel) = each($config['ipsec']['tunnel'])) {
680
				/* Sanity check on required variables */
681
				/* This fixes bogus <tunnel> entries - remnant of bug #393 */
682
				if (!isset($tunnel['local-subnet']) && !isset($tunnel['remote-subnet'])) {
683
					unset($config['ipsec']['tunnel'][$tunnel]);
684
				}
685
			}
686
        	}
687
		$config['version'] = "2.0";
688
	}
689

    
690

    
691
	if ($prev_version != $config['version'])
692
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
693
}
694

    
695
/****f* config/write_config
696
 * NAME
697
 *   write_config - Backup and write the firewall configuration.
698
 * DESCRIPTION
699
 *   write_config() handles backing up the current configuration,
700
 *   applying changes, and regenerating the configuration cache.
701
 * INPUTS
702
 *   $desc	- string containing the a description of configuration changes
703
 *   $backup	- boolean: do not back up current configuration if false.
704
 * RESULT
705
 *   null       
706
 ******/
707
/* save the system configuration */
708
function write_config($desc="Unknown", $backup = true) {
709
	global $config, $g;
710

    
711
	if($backup) backup_config();
712

    
713
	if (time() > mktime(0, 0, 0, 9, 1, 2004))       /* make sure the clock settings are plausible */
714
                $changetime = time();
715

    
716
	/* Log the running script so it's not entirely unlogged what changed */ 
717
        if ($desc == "Unknown") 
718
        	$desc = "{$_SERVER['SCRIPT_NAME']} made unknown change";  
719

    
720
	$config['revision']['description'] = $desc;
721
	$config['revision']['time'] = $changetime;
722
	
723
	config_lock();
724
	conf_mount_rw();
725

    
726
	/* generate configuration XML */
727
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
728

    
729
	/* write new configuration */
730
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
731
	if (!$fd)
732
		die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
733
	fwrite($fd, $xmlconfig);
734
	fclose($fd);
735

    
736
	if($g['booting'] <> true) {
737
		conf_mount_ro();
738
	}
739

    
740
	config_unlock();
741

    
742
	// Always reparse the config after it's written - something is getting lost in serialize().
743
	$config = parse_config(true);
744
	return $config;
745
}
746

    
747
/****f* config/reset_factory_defaults
748
 * NAME
749
 *   reset_factory_defaults - Reset the system to its default configuration.
750
 * RESULT
751
 *   integer	- indicates completion
752
 ******/
753
function reset_factory_defaults() {
754
	global $g;
755

    
756
	config_lock();
757
	conf_mount_rw();
758

    
759
	/* create conf directory, if necessary */
760
	safe_mkdir("{$g['cf_conf_path']}");
761

    
762
	/* clear out /conf */
763
	$dh = opendir($g['conf_path']);
764
	while ($filename = readdir($dh)) {
765
		if (($filename != ".") && ($filename != "..")) {
766
			unlink_if_exists($g['conf_path'] . "/" . $filename);
767
		}
768
	}
769
	closedir($dh);
770

    
771
	/* copy default configuration */
772
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
773
	
774
	/* call the wizard */
775
	touch("/trigger_initial_wizard");
776
	
777
	conf_mount_ro();
778
	config_unlock();
779

    
780
	return 0;
781
}
782

    
783
function config_restore($conffile) {
784
	global $config, $g;
785
       
786
        if (!file_exists($conffile))
787
                return 1;
788
        
789
        config_lock();
790
        conf_mount_rw();        
791
        
792
        backup_config();
793
        copy($conffile, "{$g['cf_conf_path']}/config.xml");
794
	$config = parse_config(true);
795
        write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
796
        
797
        conf_mount_ro();
798
        config_unlock();
799

    
800
        return 0;
801
}
802

    
803

    
804

    
805
function config_install($conffile) {
806
        global $config, $g;
807
        
808
        if (!file_exists($conffile))
809
                return 1;
810

    
811
	if($g['booting'] == true)
812
		echo "Installing configuration...\n";
813
 
814
        config_lock();
815
        conf_mount_rw();
816
        
817
        copy($conffile, "{$g['conf_path']}/config.xml");
818
                
819
        conf_mount_ro();
820
        config_unlock();
821

    
822
        return 0;
823
}
824

    
825
/* lock configuration file, decide that the lock file is stale after
826
   10 seconds */
827
function config_lock() {
828
	global $g, $process_lock;
829

    
830
	/* No need to continue if we're the ones holding the lock */
831
	if ($process_lock)
832
		return;
833

    
834
	$lockfile = "{$g['varrun_path']}/config.lock";
835

    
836
	$n = 0;
837
	while ($n < 10) {
838
		/* open the lock file in append mode to avoid race condition */
839
		if ($fd = @fopen($lockfile, "x")) {
840
			/* succeeded */
841
			$process_lock = true;
842
			fclose($fd);
843
			return;
844
		} else {
845
			/* file locked, wait and try again */
846
			$process_lock = false;
847
			sleep(1);
848
			$n++;
849
		}
850
	}
851
}
852

    
853
/* unlock configuration file */
854
function config_unlock() {
855
	global $g, $process_lock;
856

    
857
	$lockfile = "{$g['varrun_path']}/config.lock";
858
	$process_lock = false;
859

    
860
	unlink_if_exists($lockfile);
861
}
862

    
863
function set_networking_interfaces_ports() {
864
	global $noreboot;
865
	global $config;
866
	global $g;
867
	global $fp;
868

    
869
	$fp = fopen('php://stdin', 'r');
870

    
871
	$iflist = get_interface_list();
872

    
873
	echo <<<EOD
874

    
875
Valid interfaces are:
876

    
877

    
878
EOD;
879

    
880
	foreach ($iflist as $iface => $ifa) {
881
		echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
882
			$ifa['up'] ? "   (up)" : "");
883
	}
884

    
885
	echo <<<EOD
886

    
887
Do you want to set up VLANs first?
888
If you are not going to use VLANs, or only for optional interfaces, you
889
should say no here and use the webGUI to configure VLANs later, if required.
890

    
891
Do you want to set up VLANs now [y|n]?
892
EOD;
893

    
894
	if (strcasecmp(chop(fgets($fp)), "y") == 0)
895
		vlan_setup();
896

    
897
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
898

    
899
		echo "\n\nVLAN interfaces:\n\n";
900
		$i = 0;
901
		foreach ($config['vlans']['vlan'] as $vlan) {
902

    
903
			echo sprintf("% -8s%s\n", "vlan{$i}",
904
				"VLAN tag {$vlan['tag']}, interface {$vlan['if']}");
905

    
906
			$iflist['vlan' . $i] = array();
907
			$i++;
908
		}
909
	}
910

    
911
	echo <<<EOD
912

    
913
*NOTE*  pfSense requires *ATLEAST* 2 assigned interfaces to function.
914
        If you do not have two interfaces turn off the machine until
915
	you do.
916

    
917
If you do not know the names of your interfaces, you may choose to use
918
auto-detection... In that case, disconnect all interfaces now before
919
hitting a.   The system will then prompt you to plug in each nic to
920
autodetect.
921

    
922
EOD;
923

    
924
	do {
925
		echo "\nEnter the LAN interface name or 'a' for auto-detection: ";
926
		$lanif = chop(fgets($fp));
927
		if ($lanif === "") {
928
			exit(0);
929
		}
930

    
931
		if ($lanif === "a")
932
			$lanif = autodetect_interface("LAN", $fp);
933
		else if (!array_key_exists($lanif, $iflist)) {
934
			echo "\nInvalid interface name '{$lanif}'\n";
935
			unset($lanif);
936
			continue;
937
		}
938
	} while (!$lanif);
939

    
940
	do {
941
		echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
942
		$wanif = chop(fgets($fp));
943
		if ($wanif === "") {
944
			exit(0);
945
		}
946
		if ($wanif === "a")
947
			$wanif = autodetect_interface("WAN", $fp);
948
		else if (!array_key_exists($wanif, $iflist)) {
949
			echo "\nInvalid interface name '{$wanif}'\n";
950
			unset($wanif);
951
			continue;
952
		}
953
	} while (!$wanif);
954

    
955
	/* optional interfaces */
956
	$i = 0;
957
	$optif = array();
958

    
959
	while (1) {
960
		if ($optif[$i])
961
			$i++;
962
		$i1 = $i + 1;
963
		echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
964
			"(or nothing if finished): ";
965
		$optif[$i] = chop(fgets($fp));
966

    
967
		if ($optif[$i]) {
968
			if ($optif[$i] === "a") {
969
				$ad = autodetect_interface("Optional " . $i1, $fp);
970
				if ($ad)
971
					$optif[$i] = $ad;
972
				else
973
					unset($optif[$i]);
974
			} else if (!array_key_exists($optif[$i], $iflist)) {
975
				echo "\nInvalid interface name '{$optif[$i]}'\n";
976
				unset($optif[$i]);
977
				continue;
978
			}
979
		} else {
980
			unset($optif[$i]);
981
			break;
982
		}
983
	}
984

    
985
	/* check for double assignments */
986
	$ifarr = array_merge(array($lanif, $wanif), $optif);
987

    
988
	for ($i = 0; $i < (count($ifarr)-1); $i++) {
989
		for ($j = ($i+1); $j < count($ifarr); $j++) {
990
			if ($ifarr[$i] == $ifarr[$j]) {
991
				echo <<<EOD
992

    
993
Error: you cannot assign the same interface name twice!
994

    
995
EOD;
996

    
997
				exit(0);
998
			}
999
		}
1000
	}
1001

    
1002
	echo <<<EOD
1003

    
1004
The interfaces will be assigned as follows:
1005

    
1006
LAN  -> {$lanif}
1007
WAN  -> {$wanif}
1008

    
1009
EOD;
1010

    
1011
	for ($i = 0; $i < count($optif); $i++) {
1012
		echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
1013
	}
1014

    
1015
	if(!$noreboot) echo "\npfSense will reboot after saving the changes.\n";
1016

    
1017
echo <<<EOD
1018

    
1019
Do you want to proceed [y|n]?
1020
EOD;
1021

    
1022
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
1023

    
1024
		$config['interfaces']['lan']['if'] = $lanif;
1025
		if (preg_match($g['wireless_regex'], $lanif)) {
1026
			if (!is_array($config['interfaces']['lan']['wireless']))
1027
				$config['interfaces']['lan']['wireless'] = array();
1028
		} else {
1029
			unset($config['interfaces']['lan']['wireless']);
1030
		}
1031
		
1032
		$config['interfaces']['wan']['if'] = $wanif;
1033
		if (preg_match($g['wireless_regex'], $wanif)) {
1034
			if (!is_array($config['interfaces']['wan']['wireless']))
1035
				$config['interfaces']['wan']['wireless'] = array();
1036
		} else {
1037
			unset($config['interfaces']['wan']['wireless']);
1038
		}
1039
		
1040
		for ($i = 0; $i < count($optif); $i++) {
1041
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
1042
				$config['interfaces']['opt' . ($i+1)] = array();
1043
			
1044
			$config['interfaces']['opt' . ($i+1)]['if'] = $optif[$i];
1045
			
1046
			/* wireless interface? */
1047
			if (preg_match($g['wireless_regex'], $optif[$i])) {
1048
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
1049
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
1050
			} else {
1051
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
1052
			}
1053
			
1054
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
1055
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
1056
		}
1057
		
1058
		/* remove all other (old) optional interfaces */
1059
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
1060
			unset($config['interfaces']['opt' . ($i+1)]);
1061
		
1062
		conf_mount_rw();
1063
		
1064
		/* call the wizard */
1065
		touch("/trigger_initial_wizard");
1066
		
1067
		write_config();
1068
		
1069
		echo <<<EOD
1070

    
1071

    
1072

    
1073
EOD;
1074

    
1075
		if($noreboot <> true)
1076
			system_reboot_sync();
1077
	}
1078
}
1079

    
1080
function autodetect_interface($ifname, $fp) {
1081
	$iflist_prev = get_interface_list();
1082
	echo <<<EOD
1083

    
1084
Connect the {$ifname} interface now and make sure that the link is up.
1085
Then press ENTER to continue.
1086

    
1087
EOD;
1088
	fgets($fp);
1089
	$iflist = get_interface_list();
1090

    
1091
	foreach ($iflist_prev as $ifn => $ifa) {
1092
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1093
			echo "Detected link-up on interface {$ifn}.\n";
1094
			return $ifn;
1095
		}
1096
	}
1097

    
1098
	echo "No link-up detected.\n";
1099

    
1100
	return null;
1101
}
1102

    
1103
function vlan_setup() {
1104
	global $iflist, $config, $g, $fp;
1105

    
1106
	$iflist = get_interface_list();
1107

    
1108
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1109

    
1110
	echo <<<EOD
1111

    
1112
WARNING: all existing VLANs will be cleared if you proceed!
1113

    
1114
Do you want to proceed [y|n]?
1115
EOD;
1116

    
1117
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1118
		return;
1119
	}
1120

    
1121
	$config['vlans']['vlan'] = array();
1122
	echo "\n";
1123

    
1124
	while (1) {
1125
		$vlan = array();
1126

    
1127
		echo "\nEnter the parent interface name for the new VLAN (or nothing if finished): ";
1128
		$vlan['if'] = chop(fgets($fp));
1129

    
1130
		if ($vlan['if']) {
1131
			if (!array_key_exists($vlan['if'], $iflist)) {
1132
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1133
				continue;
1134
			}
1135
		} else {
1136
			break;
1137
		}
1138

    
1139
		echo "Enter the VLAN tag (1-4094): ";
1140
		$vlan['tag'] = chop(fgets($fp));
1141

    
1142
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1143
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1144
			continue;
1145
		}
1146

    
1147
		$config['vlans']['vlan'][] = $vlan;
1148
	}
1149
}
1150

    
1151
function system_start_ftp_helpers() {
1152
	require_once("interfaces.inc");
1153
	global $config, $g;
1154

    
1155
	/* if the ftp proxy is disabled then killall pftpx and return */	
1156
	if($config['system']['disableftpproxy'] <> "") {
1157
		mwexec("/usr/bin/killall pftpx");
1158
		return;
1159
	}
1160
	
1161
	/* grab the current WAN IP address */
1162
	$wanip = get_current_wan_address();
1163
	
1164
	/* kill off pftpx if its already running */
1165
	if(is_process_running("pftpx"))
1166
		mwexec("/usr/bin/killall pftpx 2>/dev/null");
1167

    
1168
	/* if we do not have a wanip, launch with just the -g flag */	
1169
	if($wanip <> "") {
1170
		$command = "/usr/local/sbin/pftpx -g 8021 {$wanip}";
1171
		mwexec($command);
1172
	} else {
1173
		mwexec("/usr/local/sbin/pftpx -g 8021");
1174
	}
1175
}
1176

    
1177
function cleanup_backupcache($revisions = 30) {
1178
	global $g;
1179
	$i = false;
1180
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1181
		conf_mount_rw();
1182
		$backups = get_backups();
1183
		$newbaks = array();
1184
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1185
		$baktimes = $backups['versions'];
1186
		$tocache = array();
1187
		unset($backups['versions']);
1188
       		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1189
			$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));	
1190
                	if(!in_array($tocheck, $baktimes)) {
1191
				$i = true;
1192
				if($bootup) print " " . $tocheck . "a";
1193
				$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1194
				if($newxml['revision']['description'] == "") $newxml['revision']['description'] = "Unknown";
1195
				$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1196
			}
1197
        	}
1198
		foreach($backups as $checkbak) {
1199
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1200
				$newbaks[] = $checkbak;
1201
			} else {
1202
				$i = true;
1203
				if($bootup) print " " . $tocheck . "r";
1204
			}
1205
		}
1206
		foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);	
1207
		if(is_int($revisions) and (count($tocache) > $revisions)) {
1208
			$toslice = array_slice(array_keys($tocache), 0, $revisions);
1209
			foreach($toslice as $sliced) $newcache[$sliced] = $tocache[$sliced];
1210
			foreach($tocache as $version => $versioninfo) {
1211
				if(!in_array($version, array_keys($newcache))) {
1212
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1213
					if($bootup) print " " . $tocheck . "d";
1214
				}
1215
			}
1216
			$tocache = $newcache;
1217
		}
1218
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1219
        	fwrite($bakout, serialize($tocache));
1220
  	        fclose($bakout);
1221
		conf_mount_ro();
1222
	}
1223
	if($g['booting']) {
1224
		if($i) {
1225
			print "done.\n";
1226
		}
1227
	}
1228
}
1229
  	 
1230
function get_backups() { 	 
1231
	global $g;
1232

    
1233
        if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1234
                $confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1235
		$bakvers = array_keys($confvers);
1236
		$toreturn = array();
1237
		sort($bakvers);
1238
		// $bakvers = array_reverse($bakvers);
1239
		foreach(array_reverse($bakvers) as $bakver) $toreturn[] = array('time' => $bakver,
1240
								 'description' => $confvers[$bakver]['description']
1241
								);
1242
        } else { 	 
1243
                return false; 	 
1244
        }
1245
	$toreturn['versions'] = $bakvers;
1246
        return $toreturn;
1247
}
1248

    
1249
function backup_config() {
1250
	global $config, $g;
1251

    
1252
	if($g['platform'] == "cdrom")
1253
		return;
1254

    
1255
	conf_mount_rw();
1256

    
1257
	/* Create backup directory if needed */
1258
	safe_mkdir("{$g['cf_conf_path']}/backup");
1259

    
1260
        if($config['revision']['time'] == "") {
1261
                $baktime = 0;
1262
        } else {
1263
                $baktime = $config['revision']['time'];
1264
        }
1265
        if($config['revision']['description'] == "") {
1266
                $bakdesc = "Unknown";
1267
        } else {
1268
                $bakdesc = $config['revision']['description'];
1269
        }
1270
        copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1271
        if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1272
                $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1273
        } else {
1274
                $backupcache = array();
1275
        }
1276
        $backupcache[$baktime] = array('description' => $bakdesc);
1277
        $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1278
        fwrite($bakout, serialize($backupcache));
1279
        fclose($bakout);
1280
	
1281
	conf_mount_ro();
1282
	
1283
	return true;
1284
}
1285

    
1286
function mute_kernel_msgs() {
1287
	exec("/sbin/conscontrol mute on");
1288
}
1289

    
1290
function unmute_kernel_msgs() {
1291
	exec("/sbin/conscontrol mute off");
1292
}
1293

    
1294
function start_devd() {
1295
	exec("/sbin/devd");
1296
}
1297

    
1298
?>
(3-3/23)