Project

General

Profile

Download (36.4 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 /debugging exists, lets set $debugging
61
   so we can output more information */
62
if(file_exists("/debugging"))
63
	$debugging = true;
64

    
65

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

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

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

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

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

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

    
121
					if ($cfgdevice)
122
						break;
123
				}
124
			}
125
		}
126

    
127
		if (!$cfgdevice) {
128
			/* no device found, print an error and die */
129
			echo <<<EOD
130

    
131

    
132
*******************************************************************************
133
* FATAL ERROR                                                                 *
134
* The device that contains the configuration file (config.xml) could not be   *
135
* found. pfSense cannot continue booting.                                     *
136
*******************************************************************************
137

    
138

    
139
EOD;
140

    
141
			mwexec("/sbin/halt");
142
			exit;
143
		}
144

    
145
		/* write device name to a file for rc.firmware */
146
		$fd = fopen("{$g['varetc_path']}/cfdevice", "w");
147
		fwrite($fd, $cfgdevice . "\n");
148
		fclose($fd);
149

    
150
		/* write out an fstab */
151
		$fd = fopen("{$g['etc_path']}/fstab", "w");
152

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

    
156
		fwrite($fd, $fstab);
157
		fclose($fd);
158
	}
159

    
160
	/* mount all filesystems */
161
	mwexec("/sbin/mount -a");
162
}
163

    
164
$config = parse_config();
165

    
166
/****f* config/parse_config
167
 * NAME
168
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
169
 * INPUTS
170
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
171
 * RESULT
172
 *   $config      - array containing all configuration variables
173
 ******/
174
function parse_config($parse = false) {
175
	global $g;
176

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

    
199
/****f* config/generate_config_cache
200
 * NAME
201
 *   generate_config_cache - Write serialized configuration to cache.
202
 * INPUTS
203
 *   $config	- array containing current firewall configuration
204
 * RESULT
205
 *   boolean	- true on completion
206
 ******/
207
function generate_config_cache($config) {
208
	global $g;
209
	conf_mount_rw();
210
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
211
	fwrite($configcache, serialize($config));
212
	fclose($configcache);
213
	conf_mount_ro();
214
	return true;
215
}
216

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

    
250
	parse_config(true);
251
	
252
	if ((float)$config['version'] > (float)$g['latest_config']) {
253
		echo <<<EOD
254

    
255

    
256
*******************************************************************************
257
* WARNING!                                                                    *
258
* The current configuration has been created with a newer version of pfSense  *
259
* than this one! This can lead to serious misbehavior and even security       *
260
* holes! You are urged to either upgrade to a newer version of pfSense or     *
261
* revert to the default configuration immediately!                            *
262
*******************************************************************************
263

    
264

    
265
EOD;
266
		}
267

    
268
	/* make alias table (for faster lookups) */
269
	alias_make_table($config);
270
	config_unlock();
271
}
272

    
273
/****f* config/conf_mount_rw
274
 * NAME
275
 *   conf_mount_rw - Mount filesystems read/write.
276
 * RESULT
277
 *   null
278
 ******/
279
/* mount flash card read/write */
280
function conf_mount_rw() {
281
	global $g;
282

    
283
	/* do not mount on cdrom platform */
284
	if($g['platform'] == "cdrom")
285
		return;
286

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

    
291
	$status = mwexec("/sbin/mount -w -o noatime {$g['cf_path']}");
292
	if($status <> 0) {
293
		mwexec("/sbin/fsck -y {$g['cf_path']}");
294
		$status = mwexec("/sbin/mount -w -o noatime {$g['cf_path']}");
295
	}
296

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

    
313
/****f* config/conf_mount_ro
314
 * NAME         
315
 *   conf_mount_ro - Mount filesystems readonly.
316
 * RESULT
317
 *   null        
318
 ******/
319
function conf_mount_ro() {
320
	global $g;
321

    
322
	if($g['booting'] == true)
323
		return;
324
	
325
	/* do not umount if generating ssh keys */
326
	if(file_exists("/tmp/keys_generating"))
327
		return;
328
	
329
	/* do not umount on cdrom platform */
330
	if($g['platform'] == "cdrom")
331
		return;
332

    
333
	mwexec("/sbin/umount -f {$g['cf_path']}");
334
	mwexec("/sbin/mount -r {$g['cf_path']}");
335
	/*    if the platform is soekris or wrap, lets unmount the
336
	 *    compact flash card.
337
         */
338
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx"
339
	   or $g['platform'] == "embedded") {
340
		mwexec("/sbin/umount -f /");
341
		mwexec("/sbin/mount -f -r /");
342
	}
343
}
344

    
345
/****f* config/convert_config
346
 * NAME         
347
 *   convert_config - Attempt to update config.xml.
348
 * DESCRIPTION
349
 *   convert_config() reads the current global configuration
350
 *   and attempts to convert it to conform to the latest
351
 *   config.xml version. This allows major formatting changes
352
 *   to be made with a minimum of breakage.
353
 * RESULT
354
 *   null        
355
 ******/
356
/* convert configuration, if necessary */
357
function convert_config() {
358
	global $config, $g;
359

    
360
	if ($config['version'] == $g['latest_config'])
361
		return;		/* already at latest version */
362

    
363
	// Save off config version
364
	$prev_version = $config['version'];
365

    
366
	/* convert 1.0 -> 1.1 */
367
	if ($config['version'] == "1.0") {
368
		$opti = 1;
369
		$ifmap = array('lan' => 'lan', 'wan' => 'wan', 'pptp' => 'pptp');
370

    
371
		/* convert DMZ to optional, if necessary */
372
		if (isset($config['interfaces']['dmz'])) {
373

    
374
			$dmzcfg = &$config['interfaces']['dmz'];
375

    
376
			if ($dmzcfg['if']) {
377
				$config['interfaces']['opt' . $opti] = array();
378
				$optcfg = &$config['interfaces']['opt' . $opti];
379

    
380
				$optcfg['enable'] = $dmzcfg['enable'];
381
				$optcfg['descr'] = "DMZ";
382
				$optcfg['if'] = $dmzcfg['if'];
383
				$optcfg['ipaddr'] = $dmzcfg['ipaddr'];
384
				$optcfg['subnet'] = $dmzcfg['subnet'];
385

    
386
				$ifmap['dmz'] = "opt" . $opti;
387
				$opti++;
388
			}
389

    
390
			unset($config['interfaces']['dmz']);
391
		}
392

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

    
396
			if (!$config['interfaces']['wlan' . $i]['if']) {
397
				unset($config['interfaces']['wlan' . $i]);
398
				continue;
399
			}
400

    
401
			$wlancfg = &$config['interfaces']['wlan' . $i];
402
			$config['interfaces']['opt' . $opti] = array();
403
			$optcfg = &$config['interfaces']['opt' . $opti];
404

    
405
			$optcfg['enable'] = $wlancfg['enable'];
406
			$optcfg['descr'] = "WLAN" . $i;
407
			$optcfg['if'] = $wlancfg['if'];
408
			$optcfg['ipaddr'] = $wlancfg['ipaddr'];
409
			$optcfg['subnet'] = $wlancfg['subnet'];
410
			$optcfg['bridge'] = $wlancfg['bridge'];
411

    
412
			$optcfg['wireless'] = array();
413
			$optcfg['wireless']['mode'] = $wlancfg['mode'];
414
			$optcfg['wireless']['ssid'] = $wlancfg['ssid'];
415
			$optcfg['wireless']['channel'] = $wlancfg['channel'];
416
			$optcfg['wireless']['wep'] = $wlancfg['wep'];
417

    
418
			$ifmap['wlan' . $i] = "opt" . $opti;
419

    
420
			unset($config['interfaces']['wlan' . $i]);
421
			$opti++;
422
		}
423

    
424
		/* convert filter rules */
425
		$n = count($config['filter']['rule']);
426
		for ($i = 0; $i < $n; $i++) {
427

    
428
			$fr = &$config['filter']['rule'][$i];
429

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

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

    
454
			/* remap destination network */
455
			if (isset($fr['destination']['network'])) {
456
				if (array_key_exists($fr['destination']['network'], $ifmap))
457
					$fr['destination']['network'] = $ifmap[$fr['destination']['network']];
458
				else {
459
					/* remove the rule */
460
					echo "\nWarning: filter rule removed " .
461
						"(destination network '{$fr['destination']['network']}' does not exist anymore).";
462
					unset($config['filter']['rule'][$i]);
463
					continue;
464
				}
465
			}
466
		}
467

    
468
		/* convert shaper rules */
469
		$n = count($config['pfqueueing']['rule']);
470
		if (is_array($config['pfqueueing']['rule']))
471
			for ($i = 0; $i < $n; $i++) {
472

    
473
			$fr = &$config['pfqueueing']['rule'][$i];
474

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

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

    
499
			/* remap destination network */
500
			if (isset($fr['destination']['network'])) {
501
				if (array_key_exists($fr['destination']['network'], $ifmap))
502
					$fr['destination']['network'] = $ifmap[$fr['destination']['network']];
503
				else {
504
					/* remove the rule */
505
					echo "\nWarning: traffic shaper rule removed " .
506
						"(destination network '{$fr['destination']['network']}' does not exist anymore).";
507
					unset($config['pfqueueing']['rule'][$i]);
508
					continue;
509
				}
510
			}
511
		}
512

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

    
516
	/* convert 1.1 -> 1.2 */
517
	if ($config['version'] == "1.1") {
518
		/* move LAN DHCP server config */
519
		$tmp = $config['dhcpd'];
520
		$config['dhcpd'] = array();
521
		$config['dhcpd']['lan'] = $tmp;
522

    
523
		/* encrypt password */
524
		$config['system']['password'] = crypt($config['system']['password']);
525

    
526
		$config['version'] = "1.2";
527
	}
528

    
529
	/* convert 1.2 -> 1.3 */
530
	if ($config['version'] == "1.2") {
531
		/* convert advanced outbound NAT config */
532
		for ($i = 0; isset($config['nat']['advancedoutbound']['rule'][$i]); $i++) {
533
			$curent = &$config['nat']['advancedoutbound']['rule'][$i];
534
			$src = $curent['source'];
535
			$curent['source'] = array();
536
			$curent['source']['network'] = $src;
537
			$curent['destination'] = array();
538
			$curent['destination']['any'] = true;
539
		}
540

    
541
		/* add an explicit type="pass" to all filter rules to make things consistent */
542
		for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
543
			$config['filter']['rule'][$i]['type'] = "pass";
544
		}
545

    
546
		$config['version'] = "1.3";
547
	}
548

    
549
	/* convert 1.3 -> 1.4 */
550
	if ($config['version'] == "1.3") {
551
		/* convert shaper rules (make pipes) */
552
		if (is_array($config['pfqueueing']['rule'])) {
553
			$config['pfqueueing']['pipe'] = array();
554

    
555
			for ($i = 0; isset($config['pfqueueing']['rule'][$i]); $i++) {
556
				$curent = &$config['pfqueueing']['rule'][$i];
557

    
558
				/* make new pipe and associate with this rule */
559
				$newpipe = array();
560
				$newpipe['descr'] = $curent['descr'];
561
				$newpipe['bandwidth'] = $curent['bandwidth'];
562
				$newpipe['delay'] = $curent['delay'];
563
				$newpipe['mask'] = $curent['mask'];
564
				$config['pfqueueing']['pipe'][$i] = $newpipe;
565

    
566
				$curent['targetpipe'] = $i;
567

    
568
				unset($curent['bandwidth']);
569
				unset($curent['delay']);
570
				unset($curent['mask']);
571
			}
572
		}
573

    
574
		$config['version'] = "1.4";
575
	}
576

    
577
	/* Convert 1.4 -> 1.5 */
578
	if ($config['version'] == "1.4") {
579

    
580
		/* Default route moved */
581
		if (isset($config['interfaces']['wan']['gateway']))
582
			if ($config['interfaces']['wan']['gateway'] <> "")
583
				$config['system']['gateway'] = $config['interfaces']['wan']['gateway'];
584
		unset($config['interfaces']['wan']['gateway']);
585

    
586
                /* Queues are no longer interface specific */
587
                if (isset($config['interfaces']['lan']['schedulertype']))
588
                        unset($config['interfaces']['lan']['schedulertype']);
589
                if (isset($config['interfaces']['wan']['schedulertype']))
590
                        unset($config['interfaces']['wan']['schedulertype']);
591

    
592
                for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
593
                        if(isset($config['interfaces']['opt' . $i]['schedulertype']))
594
                                unset($config['interfaces']['opt' . $i]['schedulertype']);
595
                }
596

    
597
		$config['version'] = "1.5";
598
	}
599

    
600
	/* Convert 1.5 -> 1.6 */
601
	if ($config['version'] == "1.5") {
602
		/* Alternate firmware URL moved */
603
		if (isset($config['system']['firmwareurl']) && isset($config['system']['firmwarename'])) { // Only convert if *both* are defined.
604
			$config['system']['alt_firmware_url'] = array();
605
			$config['system']['alt_firmware_url']['enabled'] = "";
606
			$config['system']['alt_firmware_url']['firmware_base_url'] = $config['system']['firmwareurl'];
607
			$config['system']['alt_firmware_url']['firmware_filename'] = $config['system']['firmwarename'];
608
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
609
		} else {
610
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
611
		}
612

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

    
683
	/* Convert 1.8 -> 1.9 */
684
	if ($config['version'] == "1.8") {
685
		$config['theme']="metallic";
686
		$config['version'] = "1.9";
687
	}
688
	/* Convert 1.9 -> 2.0 */
689
	if ($config['version'] == "1.9") {
690
		if(is_array($config['ipsec']['tunnel'])) {
691
			reset($config['ipsec']['tunnel']);
692
			while (list($index, $tunnel) = each($config['ipsec']['tunnel'])) {
693
				/* Sanity check on required variables */
694
				/* This fixes bogus <tunnel> entries - remnant of bug #393 */
695
				if (!isset($tunnel['local-subnet']) && !isset($tunnel['remote-subnet'])) {
696
					unset($config['ipsec']['tunnel'][$tunnel]);
697
				}
698
			}
699
        	}
700
		$config['version'] = "2.0";
701
	}
702
	/* Convert 2.0 -> 2.1 */
703
	if ($config['version'] == "2.0") {
704
		/* shaper scheduler moved */
705
		if(isset($config['system']['schedulertype'])) {
706
			$config['shaper']['schedulertype'] = $config['system']['schedulertype'];
707
			unset($config['system']['schedulertype']);
708
		}
709
		$config['version'] = "2.1";
710
	}
711

    
712

    
713
	if ($prev_version != $config['version'])
714
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
715
}
716

    
717
/****f* config/write_config
718
 * NAME
719
 *   write_config - Backup and write the firewall configuration.
720
 * DESCRIPTION
721
 *   write_config() handles backing up the current configuration,
722
 *   applying changes, and regenerating the configuration cache.
723
 * INPUTS
724
 *   $desc	- string containing the a description of configuration changes
725
 *   $backup	- boolean: do not back up current configuration if false.
726
 * RESULT
727
 *   null       
728
 ******/
729
/* save the system configuration */
730
function write_config($desc="Unknown", $backup = true) {
731
	global $config, $g;
732

    
733
	if($g['platform'] <> "wrap") {
734
		if($backup) backup_config();
735
	}
736

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

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

    
744
	$config['revision']['description'] = $desc;
745
	$config['revision']['time'] = $changetime;
746
	
747
	config_lock();
748
	conf_mount_rw();
749

    
750
	/* generate configuration XML */
751
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
752

    
753
	/* write new configuration */
754
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
755
	if (!$fd)
756
		die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
757
	fwrite($fd, $xmlconfig);
758
	fclose($fd);
759

    
760
	if($g['booting'] <> true) {
761
		conf_mount_ro();
762
	}
763

    
764
	config_unlock();
765

    
766
	// Always reparse the config after it's written - something is getting lost in serialize().
767
	$config = parse_config(true);
768
	return $config;
769
}
770

    
771
/****f* config/reset_factory_defaults
772
 * NAME
773
 *   reset_factory_defaults - Reset the system to its default configuration.
774
 * RESULT
775
 *   integer	- indicates completion
776
 ******/
777
function reset_factory_defaults() {
778
	global $g;
779

    
780
	config_lock();
781
	conf_mount_rw();
782

    
783
	/* create conf directory, if necessary */
784
	safe_mkdir("{$g['cf_conf_path']}");
785

    
786
	/* clear out /conf */
787
	$dh = opendir($g['conf_path']);
788
	while ($filename = readdir($dh)) {
789
		if (($filename != ".") && ($filename != "..")) {
790
			unlink_if_exists($g['conf_path'] . "/" . $filename);
791
		}
792
	}
793
	closedir($dh);
794

    
795
	/* copy default configuration */
796
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
797
	
798
	/* call the wizard */
799
	touch("/trigger_initial_wizard");
800
	
801
	conf_mount_ro();
802
	config_unlock();
803

    
804
	return 0;
805
}
806

    
807
function config_restore($conffile) {
808
	global $config, $g;
809
       
810
        if (!file_exists($conffile))
811
                return 1;
812
        
813
        config_lock();
814
        conf_mount_rw();        
815
        
816
        backup_config();
817
        copy($conffile, "{$g['cf_conf_path']}/config.xml");
818
	$config = parse_config(true);
819
        write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
820
        
821
        conf_mount_ro();
822
        config_unlock();
823

    
824
        return 0;
825
}
826

    
827

    
828

    
829
function config_install($conffile) {
830
        global $config, $g;
831
        
832
        if (!file_exists($conffile))
833
                return 1;
834

    
835
	if($g['booting'] == true)
836
		echo "Installing configuration...\n";
837
 
838
        config_lock();
839
        conf_mount_rw();
840
        
841
        copy($conffile, "{$g['conf_path']}/config.xml");
842
                
843
        conf_mount_ro();
844
        config_unlock();
845

    
846
        return 0;
847
}
848

    
849
/* lock configuration file, decide that the lock file is stale after
850
   10 seconds */
851
function config_lock() {
852
	global $g, $process_lock;
853

    
854
	/* No need to continue if we're the ones holding the lock */
855
	if ($process_lock)
856
		return;
857

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

    
860
	$n = 0;
861
	while ($n < 10) {
862
		/* open the lock file in append mode to avoid race condition */
863
		if ($fd = @fopen($lockfile, "x")) {
864
			/* succeeded */
865
			$process_lock = true;
866
			fclose($fd);
867
			return;
868
		} else {
869
			/* file locked, wait and try again */
870
			$process_lock = false;
871
			sleep(1);
872
			$n++;
873
		}
874
	}
875
}
876

    
877
/* unlock configuration file */
878
function config_unlock() {
879
	global $g, $process_lock;
880

    
881
	$lockfile = "{$g['varrun_path']}/config.lock";
882
	$process_lock = false;
883

    
884
	unlink_if_exists($lockfile);
885
}
886

    
887
function set_networking_interfaces_ports() {
888
	global $noreboot;
889
	global $config;
890
	global $g;
891
	global $fp;
892

    
893
	$fp = fopen('php://stdin', 'r');
894

    
895
	$iflist = get_interface_list();
896

    
897
	echo <<<EOD
898

    
899
Valid interfaces are:
900

    
901

    
902
EOD;
903

    
904
	foreach ($iflist as $iface => $ifa) {
905
		echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
906
			$ifa['up'] ? "   (up)" : "");
907
	}
908

    
909
	echo <<<EOD
910

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

    
915
Do you want to set up VLANs now [y|n]?
916
EOD;
917

    
918
	if (strcasecmp(chop(fgets($fp)), "y") == 0)
919
		vlan_setup();
920

    
921
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
922

    
923
		echo "\n\nVLAN interfaces:\n\n";
924
		$i = 0;
925
		foreach ($config['vlans']['vlan'] as $vlan) {
926

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

    
930
			$iflist['vlan' . $i] = array();
931
			$i++;
932
		}
933
	}
934

    
935
	echo <<<EOD
936

    
937
*NOTE*  pfSense requires *ATLEAST* 2 assigned interfaces to function.
938
        If you do not have two interfaces turn off the machine until
939
	you do.
940

    
941
If you do not know the names of your interfaces, you may choose to use
942
auto-detection... In that case, disconnect all interfaces now before
943
hitting a.   The system will then prompt you to plug in each nic to
944
autodetect.
945

    
946
EOD;
947

    
948
	do {
949
		echo "\nEnter the LAN interface name or 'a' for auto-detection: ";
950
		$lanif = chop(fgets($fp));
951
		if ($lanif === "") {
952
			exit(0);
953
		}
954

    
955
		if ($lanif === "a")
956
			$lanif = autodetect_interface("LAN", $fp);
957
		else if (!array_key_exists($lanif, $iflist)) {
958
			echo "\nInvalid interface name '{$lanif}'\n";
959
			unset($lanif);
960
			continue;
961
		}
962
	} while (!$lanif);
963

    
964
	do {
965
		echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
966
		$wanif = chop(fgets($fp));
967
		if ($wanif === "") {
968
			exit(0);
969
		}
970
		if ($wanif === "a")
971
			$wanif = autodetect_interface("WAN", $fp);
972
		else if (!array_key_exists($wanif, $iflist)) {
973
			echo "\nInvalid interface name '{$wanif}'\n";
974
			unset($wanif);
975
			continue;
976
		}
977
	} while (!$wanif);
978

    
979
	/* optional interfaces */
980
	$i = 0;
981
	$optif = array();
982

    
983
	while (1) {
984
		if ($optif[$i])
985
			$i++;
986
		$i1 = $i + 1;
987
		echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
988
			"(or nothing if finished): ";
989
		$optif[$i] = chop(fgets($fp));
990

    
991
		if ($optif[$i]) {
992
			if ($optif[$i] === "a") {
993
				$ad = autodetect_interface("Optional " . $i1, $fp);
994
				if ($ad)
995
					$optif[$i] = $ad;
996
				else
997
					unset($optif[$i]);
998
			} else if (!array_key_exists($optif[$i], $iflist)) {
999
				echo "\nInvalid interface name '{$optif[$i]}'\n";
1000
				unset($optif[$i]);
1001
				continue;
1002
			}
1003
		} else {
1004
			unset($optif[$i]);
1005
			break;
1006
		}
1007
	}
1008

    
1009
	/* check for double assignments */
1010
	$ifarr = array_merge(array($lanif, $wanif), $optif);
1011

    
1012
	for ($i = 0; $i < (count($ifarr)-1); $i++) {
1013
		for ($j = ($i+1); $j < count($ifarr); $j++) {
1014
			if ($ifarr[$i] == $ifarr[$j]) {
1015
				echo <<<EOD
1016

    
1017
Error: you cannot assign the same interface name twice!
1018

    
1019
EOD;
1020

    
1021
				exit(0);
1022
			}
1023
		}
1024
	}
1025

    
1026
	echo <<<EOD
1027

    
1028
The interfaces will be assigned as follows:
1029

    
1030
LAN  -> {$lanif}
1031
WAN  -> {$wanif}
1032

    
1033
EOD;
1034

    
1035
	for ($i = 0; $i < count($optif); $i++) {
1036
		echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
1037
	}
1038

    
1039
echo <<<EOD
1040

    
1041
Do you want to proceed [y|n]?
1042
EOD;
1043

    
1044
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
1045

    
1046
		$config['interfaces']['lan']['if'] = $lanif;
1047
		if (preg_match($g['wireless_regex'], $lanif)) {
1048
			if (!is_array($config['interfaces']['lan']['wireless']))
1049
				$config['interfaces']['lan']['wireless'] = array();
1050
		} else {
1051
			unset($config['interfaces']['lan']['wireless']);
1052
		}
1053
		
1054
		$config['interfaces']['wan']['if'] = $wanif;
1055
		if (preg_match($g['wireless_regex'], $wanif)) {
1056
			if (!is_array($config['interfaces']['wan']['wireless']))
1057
				$config['interfaces']['wan']['wireless'] = array();
1058
		} else {
1059
			unset($config['interfaces']['wan']['wireless']);
1060
		}
1061
		
1062
		for ($i = 0; $i < count($optif); $i++) {
1063
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
1064
				$config['interfaces']['opt' . ($i+1)] = array();
1065
			
1066
			$config['interfaces']['opt' . ($i+1)]['if'] = $optif[$i];
1067
			
1068
			/* wireless interface? */
1069
			if (preg_match($g['wireless_regex'], $optif[$i])) {
1070
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
1071
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
1072
			} else {
1073
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
1074
			}
1075
			
1076
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
1077
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
1078
		}
1079
		
1080
		/* remove all other (old) optional interfaces */
1081
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
1082
			unset($config['interfaces']['opt' . ($i+1)]);
1083
		
1084
		conf_mount_rw();
1085
		
1086
		/* call the wizard */
1087
		touch("/trigger_initial_wizard");
1088
		
1089
		write_config();
1090
		
1091
		echo <<<EOD
1092

    
1093

    
1094

    
1095
EOD;
1096

    
1097
		if($g['booting'])
1098
			return;
1099

    
1100
		/* resync everything */
1101
		reload_all_sync();
1102

    
1103
	}
1104
}
1105

    
1106
function autodetect_interface($ifname, $fp) {
1107
	$iflist_prev = get_interface_list("media");
1108
	echo <<<EOD
1109

    
1110
Connect the {$ifname} interface now and make sure that the link is up.
1111
Then press ENTER to continue.
1112

    
1113
EOD;
1114
	fgets($fp);
1115
	$iflist = get_interface_list("media");
1116

    
1117
	foreach ($iflist_prev as $ifn => $ifa) {
1118
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1119
			echo "Detected link-up on interface {$ifn}.\n";
1120
			return $ifn;
1121
		}
1122
	}
1123

    
1124
	echo "No link-up detected.\n";
1125

    
1126
	return null;
1127
}
1128

    
1129
function vlan_setup() {
1130
	global $iflist, $config, $g, $fp;
1131

    
1132
	$iflist = get_interface_list();
1133

    
1134
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1135

    
1136
	echo <<<EOD
1137

    
1138
WARNING: all existing VLANs will be cleared if you proceed!
1139

    
1140
Do you want to proceed [y|n]?
1141
EOD;
1142

    
1143
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1144
		return;
1145
	}
1146

    
1147
	$config['vlans']['vlan'] = array();
1148
	echo "\n";
1149

    
1150
	while (1) {
1151
		$vlan = array();
1152

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

    
1156
		if ($vlan['if']) {
1157
			if (!array_key_exists($vlan['if'], $iflist) or
1158
			    !is_jumbo_capable($vlan['if'])) {
1159
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1160
				continue;
1161
			}
1162
		} else {
1163
			break;
1164
		}
1165

    
1166
		echo "Enter the VLAN tag (1-4094): ";
1167
		$vlan['tag'] = chop(fgets($fp));
1168

    
1169
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1170
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1171
			continue;
1172
		}
1173

    
1174
		$config['vlans']['vlan'][] = $vlan;
1175
	}
1176
}
1177

    
1178
function system_start_ftp_helpers() {
1179
	require_once("interfaces.inc");
1180
	global $config, $g;
1181

    
1182
	/* if the ftp proxy is disabled then killall pftpx and return */	
1183
	if($config['system']['disableftpproxy'] <> "") {
1184
		mwexec("/usr/bin/killall pftpx");
1185
		return;
1186
	}
1187
	
1188
	/* grab the current WAN IP address */
1189
	$wanip = get_current_wan_address();
1190
	
1191
	/* kill off pftpx if its already running */
1192
	if(is_process_running("pftpx"))
1193
		mwexec("/usr/bin/killall pftpx 2>/dev/null");
1194

    
1195
	/* if we do not have a wanip, launch with just the -g flag */	
1196
	if($wanip <> "") {
1197
		$command = "/usr/local/sbin/pftpx -g 8021 {$wanip}";
1198
		mwexec($command);
1199
	} else {
1200
		mwexec("/usr/local/sbin/pftpx -g 8021");
1201
	}
1202
}
1203

    
1204
function cleanup_backupcache($revisions = 30) {
1205
	global $g;
1206
	$i = false;
1207
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1208
		conf_mount_rw();
1209
		$backups = get_backups();
1210
		$newbaks = array();
1211
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1212
		$baktimes = $backups['versions'];
1213
		$tocache = array();
1214
		unset($backups['versions']);
1215
       		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1216
			$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));	
1217
                	if(!in_array($tocheck, $baktimes)) {
1218
				$i = true;
1219
				if($bootup) print " " . $tocheck . "a";
1220
				$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1221
				if($newxml['revision']['description'] == "") $newxml['revision']['description'] = "Unknown";
1222
				$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1223
			}
1224
        	}
1225
		foreach($backups as $checkbak) {
1226
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1227
				$newbaks[] = $checkbak;
1228
			} else {
1229
				$i = true;
1230
				if($bootup) print " " . $tocheck . "r";
1231
			}
1232
		}
1233
		foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);	
1234
		if(is_int($revisions) and (count($tocache) > $revisions)) {
1235
			$toslice = array_slice(array_keys($tocache), 0, $revisions);
1236
			foreach($toslice as $sliced) $newcache[$sliced] = $tocache[$sliced];
1237
			foreach($tocache as $version => $versioninfo) {
1238
				if(!in_array($version, array_keys($newcache))) {
1239
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1240
					if($bootup) print " " . $tocheck . "d";
1241
				}
1242
			}
1243
			$tocache = $newcache;
1244
		}
1245
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1246
        	fwrite($bakout, serialize($tocache));
1247
  	        fclose($bakout);
1248
		conf_mount_ro();
1249
	}
1250
	if($g['booting']) {
1251
		if($i) {
1252
			print "done.\n";
1253
		}
1254
	}
1255
}
1256
  	 
1257
function get_backups() { 	 
1258
	global $g;
1259

    
1260
        if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1261
                $confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1262
		$bakvers = array_keys($confvers);
1263
		$toreturn = array();
1264
		sort($bakvers);
1265
		// $bakvers = array_reverse($bakvers);
1266
		foreach(array_reverse($bakvers) as $bakver) $toreturn[] = array('time' => $bakver,
1267
								 'description' => $confvers[$bakver]['description']
1268
								);
1269
        } else { 	 
1270
                return false; 	 
1271
        }
1272
	$toreturn['versions'] = $bakvers;
1273
        return $toreturn;
1274
}
1275

    
1276
function backup_config() {
1277
	global $config, $g;
1278

    
1279
	if($g['platform'] == "cdrom")
1280
		return;
1281

    
1282
	conf_mount_rw();
1283

    
1284
	/* Create backup directory if needed */
1285
	safe_mkdir("{$g['cf_conf_path']}/backup");
1286

    
1287
        if($config['revision']['time'] == "") {
1288
                $baktime = 0;
1289
        } else {
1290
                $baktime = $config['revision']['time'];
1291
        }
1292
        if($config['revision']['description'] == "") {
1293
                $bakdesc = "Unknown";
1294
        } else {
1295
                $bakdesc = $config['revision']['description'];
1296
        }
1297
        copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1298
        if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1299
                $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1300
        } else {
1301
                $backupcache = array();
1302
        }
1303
        $backupcache[$baktime] = array('description' => $bakdesc);
1304
        $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1305
        fwrite($bakout, serialize($backupcache));
1306
        fclose($bakout);
1307
	
1308
	conf_mount_ro();
1309
	
1310
	return true;
1311
}
1312

    
1313
function mute_kernel_msgs() {
1314
	exec("/sbin/conscontrol mute on");
1315
}
1316

    
1317
function unmute_kernel_msgs() {
1318
	exec("/sbin/conscontrol mute off");
1319
}
1320

    
1321
function start_devd() {
1322
	exec("/sbin/devd");
1323
}
1324

    
1325
?>
(3-3/24)