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($g['platform'] <> "wrap") {
712
		if($backup) backup_config();
713
	}
714

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

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

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

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

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

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

    
742
	config_unlock();
743

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

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

    
758
	config_lock();
759
	conf_mount_rw();
760

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

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

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

    
782
	return 0;
783
}
784

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

    
802
        return 0;
803
}
804

    
805

    
806

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

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

    
824
        return 0;
825
}
826

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

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

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

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

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

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

    
862
	unlink_if_exists($lockfile);
863
}
864

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

    
871
	$fp = fopen('php://stdin', 'r');
872

    
873
	$iflist = get_interface_list();
874

    
875
	echo <<<EOD
876

    
877
Valid interfaces are:
878

    
879

    
880
EOD;
881

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

    
887
	echo <<<EOD
888

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

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

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

    
899
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
900

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

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

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

    
913
	echo <<<EOD
914

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

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

    
924
EOD;
925

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

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

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

    
957
	/* optional interfaces */
958
	$i = 0;
959
	$optif = array();
960

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

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

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

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

    
995
Error: you cannot assign the same interface name twice!
996

    
997
EOD;
998

    
999
				exit(0);
1000
			}
1001
		}
1002
	}
1003

    
1004
	echo <<<EOD
1005

    
1006
The interfaces will be assigned as follows:
1007

    
1008
LAN  -> {$lanif}
1009
WAN  -> {$wanif}
1010

    
1011
EOD;
1012

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

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

    
1019
echo <<<EOD
1020

    
1021
Do you want to proceed [y|n]?
1022
EOD;
1023

    
1024
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
1025

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

    
1073

    
1074

    
1075
EOD;
1076

    
1077
		if($noreboot <> true)
1078
			system_reboot_sync();
1079
	}
1080
}
1081

    
1082
function autodetect_interface($ifname, $fp) {
1083
	$iflist_prev = get_interface_list("media");
1084
	echo <<<EOD
1085

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

    
1089
EOD;
1090
	fgets($fp);
1091
	$iflist = get_interface_list("media");
1092

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

    
1100
	echo "No link-up detected.\n";
1101

    
1102
	return null;
1103
}
1104

    
1105
function vlan_setup() {
1106
	global $iflist, $config, $g, $fp;
1107

    
1108
	$iflist = get_interface_list();
1109

    
1110
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1111

    
1112
	echo <<<EOD
1113

    
1114
WARNING: all existing VLANs will be cleared if you proceed!
1115

    
1116
Do you want to proceed [y|n]?
1117
EOD;
1118

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

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

    
1126
	while (1) {
1127
		$vlan = array();
1128

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

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

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

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

    
1149
		$config['vlans']['vlan'][] = $vlan;
1150
	}
1151
}
1152

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

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

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

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

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

    
1251
function backup_config() {
1252
	global $config, $g;
1253

    
1254
	if($g['platform'] == "cdrom")
1255
		return;
1256

    
1257
	conf_mount_rw();
1258

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

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

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

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

    
1296
function start_devd() {
1297
	exec("/sbin/devd");
1298
}
1299

    
1300
?>
(3-3/23)