Project

General

Profile

Download (36.2 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
	conf_mount_rw();
204
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
205
	fwrite($configcache, serialize($config));
206
	fclose($configcache);
207
	conf_mount_ro();
208
	return true;
209
}
210

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

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

    
249

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

    
258

    
259
EOD;
260
		}
261

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

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

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

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

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

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

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

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

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

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

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

    
352
	// Save off config version
353
	$prev_version = $config['version'];
354

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

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

    
363
			$dmzcfg = &$config['interfaces']['dmz'];
364

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

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

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

    
379
			unset($config['interfaces']['dmz']);
380
		}
381

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

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

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

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

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

    
407
			$ifmap['wlan' . $i] = "opt" . $opti;
408

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

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

    
417
			$fr = &$config['filter']['rule'][$i];
418

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

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

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

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

    
462
			$fr = &$config['pfqueueing']['rule'][$i];
463

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

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

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

    
502
		$config['version'] = "1.1";
503
	}
504

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

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

    
515
		$config['version'] = "1.2";
516
	}
517

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

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

    
535
		$config['version'] = "1.3";
536
	}
537

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

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

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

    
555
				$curent['targetpipe'] = $i;
556

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

    
563
		$config['version'] = "1.4";
564
	}
565

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

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

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

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

    
586
		$config['version'] = "1.5";
587
	}
588

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

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

    
672
	/* Convert 1.8 -> 1.9 */
673
	if ($config['version'] == "1.8") {
674
		$config['theme']="metallic";
675
		$config['version'] = "1.9";
676
	}
677
	/* Convert 1.9 -> 2.0 */
678
	if ($config['version'] == "1.9") {
679
		if(is_array($config['ipsec']['tunnel'])) {
680
			reset($config['ipsec']['tunnel']);
681
			while (list($index, $tunnel) = each($config['ipsec']['tunnel'])) {
682
				/* Sanity check on required variables */
683
				/* This fixes bogus <tunnel> entries - remnant of bug #393 */
684
				if (!isset($tunnel['local-subnet']) && !isset($tunnel['remote-subnet'])) {
685
					unset($config['ipsec']['tunnel'][$tunnel]);
686
				}
687
			}
688
        	}
689
		$config['version'] = "2.0";
690
	}
691
	/* Convert 2.0 -> 2.1 */
692
	if ($config['version'] == "2.0") {
693
		/* shaper scheduler moved */
694
		if(isset($config['system']['schedulertype'])) {
695
			$config['shaper']['schedulertype'] = $config['system']['schedulertype'];
696
			unset($config['system']['schedulertype']);
697
		}
698
		$config['version'] = "2.1";
699
	}
700

    
701

    
702
	if ($prev_version != $config['version'])
703
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
704
}
705

    
706
/****f* config/write_config
707
 * NAME
708
 *   write_config - Backup and write the firewall configuration.
709
 * DESCRIPTION
710
 *   write_config() handles backing up the current configuration,
711
 *   applying changes, and regenerating the configuration cache.
712
 * INPUTS
713
 *   $desc	- string containing the a description of configuration changes
714
 *   $backup	- boolean: do not back up current configuration if false.
715
 * RESULT
716
 *   null       
717
 ******/
718
/* save the system configuration */
719
function write_config($desc="Unknown", $backup = true) {
720
	global $config, $g;
721

    
722
	if($g['platform'] <> "wrap") {
723
		if($backup) backup_config();
724
	}
725

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

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

    
733
	$config['revision']['description'] = $desc;
734
	$config['revision']['time'] = $changetime;
735
	
736
	config_lock();
737
	conf_mount_rw();
738

    
739
	/* generate configuration XML */
740
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
741

    
742
	/* write new configuration */
743
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
744
	if (!$fd)
745
		die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
746
	fwrite($fd, $xmlconfig);
747
	fclose($fd);
748

    
749
	if($g['booting'] <> true) {
750
		conf_mount_ro();
751
	}
752

    
753
	config_unlock();
754

    
755
	// Always reparse the config after it's written - something is getting lost in serialize().
756
	$config = parse_config(true);
757
	return $config;
758
}
759

    
760
/****f* config/reset_factory_defaults
761
 * NAME
762
 *   reset_factory_defaults - Reset the system to its default configuration.
763
 * RESULT
764
 *   integer	- indicates completion
765
 ******/
766
function reset_factory_defaults() {
767
	global $g;
768

    
769
	config_lock();
770
	conf_mount_rw();
771

    
772
	/* create conf directory, if necessary */
773
	safe_mkdir("{$g['cf_conf_path']}");
774

    
775
	/* clear out /conf */
776
	$dh = opendir($g['conf_path']);
777
	while ($filename = readdir($dh)) {
778
		if (($filename != ".") && ($filename != "..")) {
779
			unlink_if_exists($g['conf_path'] . "/" . $filename);
780
		}
781
	}
782
	closedir($dh);
783

    
784
	/* copy default configuration */
785
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
786
	
787
	/* call the wizard */
788
	touch("/trigger_initial_wizard");
789
	
790
	conf_mount_ro();
791
	config_unlock();
792

    
793
	return 0;
794
}
795

    
796
function config_restore($conffile) {
797
	global $config, $g;
798
       
799
        if (!file_exists($conffile))
800
                return 1;
801
        
802
        config_lock();
803
        conf_mount_rw();        
804
        
805
        backup_config();
806
        copy($conffile, "{$g['cf_conf_path']}/config.xml");
807
	$config = parse_config(true);
808
        write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
809
        
810
        conf_mount_ro();
811
        config_unlock();
812

    
813
        return 0;
814
}
815

    
816

    
817

    
818
function config_install($conffile) {
819
        global $config, $g;
820
        
821
        if (!file_exists($conffile))
822
                return 1;
823

    
824
	if($g['booting'] == true)
825
		echo "Installing configuration...\n";
826
 
827
        config_lock();
828
        conf_mount_rw();
829
        
830
        copy($conffile, "{$g['conf_path']}/config.xml");
831
                
832
        conf_mount_ro();
833
        config_unlock();
834

    
835
        return 0;
836
}
837

    
838
/* lock configuration file, decide that the lock file is stale after
839
   10 seconds */
840
function config_lock() {
841
	global $g, $process_lock;
842

    
843
	/* No need to continue if we're the ones holding the lock */
844
	if ($process_lock)
845
		return;
846

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

    
849
	$n = 0;
850
	while ($n < 10) {
851
		/* open the lock file in append mode to avoid race condition */
852
		if ($fd = @fopen($lockfile, "x")) {
853
			/* succeeded */
854
			$process_lock = true;
855
			fclose($fd);
856
			return;
857
		} else {
858
			/* file locked, wait and try again */
859
			$process_lock = false;
860
			sleep(1);
861
			$n++;
862
		}
863
	}
864
}
865

    
866
/* unlock configuration file */
867
function config_unlock() {
868
	global $g, $process_lock;
869

    
870
	$lockfile = "{$g['varrun_path']}/config.lock";
871
	$process_lock = false;
872

    
873
	unlink_if_exists($lockfile);
874
}
875

    
876
function set_networking_interfaces_ports() {
877
	global $noreboot;
878
	global $config;
879
	global $g;
880
	global $fp;
881

    
882
	$fp = fopen('php://stdin', 'r');
883

    
884
	$iflist = get_interface_list();
885

    
886
	echo <<<EOD
887

    
888
Valid interfaces are:
889

    
890

    
891
EOD;
892

    
893
	foreach ($iflist as $iface => $ifa) {
894
		echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
895
			$ifa['up'] ? "   (up)" : "");
896
	}
897

    
898
	echo <<<EOD
899

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

    
904
Do you want to set up VLANs now [y|n]?
905
EOD;
906

    
907
	if (strcasecmp(chop(fgets($fp)), "y") == 0)
908
		vlan_setup();
909

    
910
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
911

    
912
		echo "\n\nVLAN interfaces:\n\n";
913
		$i = 0;
914
		foreach ($config['vlans']['vlan'] as $vlan) {
915

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

    
919
			$iflist['vlan' . $i] = array();
920
			$i++;
921
		}
922
	}
923

    
924
	echo <<<EOD
925

    
926
*NOTE*  pfSense requires *ATLEAST* 2 assigned interfaces to function.
927
        If you do not have two interfaces turn off the machine until
928
	you do.
929

    
930
If you do not know the names of your interfaces, you may choose to use
931
auto-detection... In that case, disconnect all interfaces now before
932
hitting a.   The system will then prompt you to plug in each nic to
933
autodetect.
934

    
935
EOD;
936

    
937
	do {
938
		echo "\nEnter the LAN interface name or 'a' for auto-detection: ";
939
		$lanif = chop(fgets($fp));
940
		if ($lanif === "") {
941
			exit(0);
942
		}
943

    
944
		if ($lanif === "a")
945
			$lanif = autodetect_interface("LAN", $fp);
946
		else if (!array_key_exists($lanif, $iflist)) {
947
			echo "\nInvalid interface name '{$lanif}'\n";
948
			unset($lanif);
949
			continue;
950
		}
951
	} while (!$lanif);
952

    
953
	do {
954
		echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
955
		$wanif = chop(fgets($fp));
956
		if ($wanif === "") {
957
			exit(0);
958
		}
959
		if ($wanif === "a")
960
			$wanif = autodetect_interface("WAN", $fp);
961
		else if (!array_key_exists($wanif, $iflist)) {
962
			echo "\nInvalid interface name '{$wanif}'\n";
963
			unset($wanif);
964
			continue;
965
		}
966
	} while (!$wanif);
967

    
968
	/* optional interfaces */
969
	$i = 0;
970
	$optif = array();
971

    
972
	while (1) {
973
		if ($optif[$i])
974
			$i++;
975
		$i1 = $i + 1;
976
		echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
977
			"(or nothing if finished): ";
978
		$optif[$i] = chop(fgets($fp));
979

    
980
		if ($optif[$i]) {
981
			if ($optif[$i] === "a") {
982
				$ad = autodetect_interface("Optional " . $i1, $fp);
983
				if ($ad)
984
					$optif[$i] = $ad;
985
				else
986
					unset($optif[$i]);
987
			} else if (!array_key_exists($optif[$i], $iflist)) {
988
				echo "\nInvalid interface name '{$optif[$i]}'\n";
989
				unset($optif[$i]);
990
				continue;
991
			}
992
		} else {
993
			unset($optif[$i]);
994
			break;
995
		}
996
	}
997

    
998
	/* check for double assignments */
999
	$ifarr = array_merge(array($lanif, $wanif), $optif);
1000

    
1001
	for ($i = 0; $i < (count($ifarr)-1); $i++) {
1002
		for ($j = ($i+1); $j < count($ifarr); $j++) {
1003
			if ($ifarr[$i] == $ifarr[$j]) {
1004
				echo <<<EOD
1005

    
1006
Error: you cannot assign the same interface name twice!
1007

    
1008
EOD;
1009

    
1010
				exit(0);
1011
			}
1012
		}
1013
	}
1014

    
1015
	echo <<<EOD
1016

    
1017
The interfaces will be assigned as follows:
1018

    
1019
LAN  -> {$lanif}
1020
WAN  -> {$wanif}
1021

    
1022
EOD;
1023

    
1024
	for ($i = 0; $i < count($optif); $i++) {
1025
		echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
1026
	}
1027

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

    
1030
echo <<<EOD
1031

    
1032
Do you want to proceed [y|n]?
1033
EOD;
1034

    
1035
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
1036

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

    
1084

    
1085

    
1086
EOD;
1087

    
1088
		if($noreboot <> true)
1089
			system_reboot_sync();
1090
	}
1091
}
1092

    
1093
function autodetect_interface($ifname, $fp) {
1094
	$iflist_prev = get_interface_list("media");
1095
	echo <<<EOD
1096

    
1097
Connect the {$ifname} interface now and make sure that the link is up.
1098
Then press ENTER to continue.
1099

    
1100
EOD;
1101
	fgets($fp);
1102
	$iflist = get_interface_list("media");
1103

    
1104
	foreach ($iflist_prev as $ifn => $ifa) {
1105
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1106
			echo "Detected link-up on interface {$ifn}.\n";
1107
			return $ifn;
1108
		}
1109
	}
1110

    
1111
	echo "No link-up detected.\n";
1112

    
1113
	return null;
1114
}
1115

    
1116
function vlan_setup() {
1117
	global $iflist, $config, $g, $fp;
1118

    
1119
	$iflist = get_interface_list();
1120

    
1121
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1122

    
1123
	echo <<<EOD
1124

    
1125
WARNING: all existing VLANs will be cleared if you proceed!
1126

    
1127
Do you want to proceed [y|n]?
1128
EOD;
1129

    
1130
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1131
		return;
1132
	}
1133

    
1134
	$config['vlans']['vlan'] = array();
1135
	echo "\n";
1136

    
1137
	while (1) {
1138
		$vlan = array();
1139

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

    
1143
		if ($vlan['if']) {
1144
			if (!array_key_exists($vlan['if'], $iflist)) {
1145
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1146
				continue;
1147
			}
1148
		} else {
1149
			break;
1150
		}
1151

    
1152
		echo "Enter the VLAN tag (1-4094): ";
1153
		$vlan['tag'] = chop(fgets($fp));
1154

    
1155
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1156
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1157
			continue;
1158
		}
1159

    
1160
		$config['vlans']['vlan'][] = $vlan;
1161
	}
1162
}
1163

    
1164
function system_start_ftp_helpers() {
1165
	require_once("interfaces.inc");
1166
	global $config, $g;
1167

    
1168
	/* if the ftp proxy is disabled then killall pftpx and return */	
1169
	if($config['system']['disableftpproxy'] <> "") {
1170
		mwexec("/usr/bin/killall pftpx");
1171
		return;
1172
	}
1173
	
1174
	/* grab the current WAN IP address */
1175
	$wanip = get_current_wan_address();
1176
	
1177
	/* kill off pftpx if its already running */
1178
	if(is_process_running("pftpx"))
1179
		mwexec("/usr/bin/killall pftpx 2>/dev/null");
1180

    
1181
	/* if we do not have a wanip, launch with just the -g flag */	
1182
	if($wanip <> "") {
1183
		$command = "/usr/local/sbin/pftpx -g 8021 {$wanip}";
1184
		mwexec($command);
1185
	} else {
1186
		mwexec("/usr/local/sbin/pftpx -g 8021");
1187
	}
1188
}
1189

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

    
1246
        if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1247
                $confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1248
		$bakvers = array_keys($confvers);
1249
		$toreturn = array();
1250
		sort($bakvers);
1251
		// $bakvers = array_reverse($bakvers);
1252
		foreach(array_reverse($bakvers) as $bakver) $toreturn[] = array('time' => $bakver,
1253
								 'description' => $confvers[$bakver]['description']
1254
								);
1255
        } else { 	 
1256
                return false; 	 
1257
        }
1258
	$toreturn['versions'] = $bakvers;
1259
        return $toreturn;
1260
}
1261

    
1262
function backup_config() {
1263
	global $config, $g;
1264

    
1265
	if($g['platform'] == "cdrom")
1266
		return;
1267

    
1268
	conf_mount_rw();
1269

    
1270
	/* Create backup directory if needed */
1271
	safe_mkdir("{$g['cf_conf_path']}/backup");
1272

    
1273
        if($config['revision']['time'] == "") {
1274
                $baktime = 0;
1275
        } else {
1276
                $baktime = $config['revision']['time'];
1277
        }
1278
        if($config['revision']['description'] == "") {
1279
                $bakdesc = "Unknown";
1280
        } else {
1281
                $bakdesc = $config['revision']['description'];
1282
        }
1283
        copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1284
        if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1285
                $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1286
        } else {
1287
                $backupcache = array();
1288
        }
1289
        $backupcache[$baktime] = array('description' => $bakdesc);
1290
        $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1291
        fwrite($bakout, serialize($backupcache));
1292
        fclose($bakout);
1293
	
1294
	conf_mount_ro();
1295
	
1296
	return true;
1297
}
1298

    
1299
function mute_kernel_msgs() {
1300
	exec("/sbin/conscontrol mute on");
1301
}
1302

    
1303
function unmute_kernel_msgs() {
1304
	exec("/sbin/conscontrol mute off");
1305
}
1306

    
1307
function start_devd() {
1308
	exec("/sbin/devd");
1309
}
1310

    
1311
?>
(3-3/23)