Project

General

Profile

Download (39.9 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
	$g['debug'] = true;
65
}
66

    
67
if(file_exists("/cf/conf/config.xml")) {
68
	$config_contents = file_get_contents("/cf/conf/config.xml");
69
	if(stristr($config_contents, "m0n0wall") == true) {
70
		/* user has just upgraded to m0n0wall, replace root xml tags */
71
		echo "Upgrading m0n0wall configuration to pfSense... ";
72
		$config_contents = str_replace("m0n0wall","pfsense", $config_contents);
73
		if (!config_validate($config_contents))
74
			log_error("ERROR!  Could not convert m0n0wall -> pfsense in config.xml");	
75
		$fd = fopen("/cf/conf/config.xml", "w");
76
		fwrite($fd, $config_contents);
77
		fclose($fd);
78
		echo "done.";
79
	}
80
}
81

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

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

    
90
		if (strstr($g['platform'], "cdrom")) {
91
			/* config is on floppy disk for CD-ROM version */
92
			$cfgdevice = $cfgpartition = "fd0";
93
			$dmesg = `dmesg -a`;
94
			if(ereg("da0", $dmesg) == true) {
95
				$cfgdevice = $cfgpartition = "da0" ;
96
				if (mwexec("/sbin/mount -r /dev/{$cfgdevice} /cf")) {
97
					/* could not mount, fallback to floppy */
98
					$cfgdevice = $cfgpartition = "fd0";
99
				}
100
			}
101
			$cfgfstype = "msdos";
102
			echo "CDROM build\n";
103
			echo "   CFG: {$cfgpartition}\n";
104
			echo "  TYPE: {$cfgfstype}\n";
105
		} else {
106
			/* probe kernel known disks until we find one with config.xml */
107
			$disks = explode(" ", trim(preg_replace("/kern.disks: /", "", exec("/sbin/sysctl kern.disks"))));
108
			foreach ($disks as $mountdisk) {
109
				/* skip mfs mounted filesystems */
110
				if (strstr($mountdisk, "md"))
111
					continue;
112
				if (mwexec("/sbin/mount -r /dev/{$mountdisk}a {$g['cf_path']}") == 0) {
113
					if (file_exists("{$g['cf_conf_path']}/config.xml")) {
114
						/* found it */
115
						$cfgdevice = $mountdisk;
116
						$cfgpartition = $cfgdevice . "a";
117
						$cfgfstype = "ufs";
118
						echo "Found configuration on $cfgdevice.\n";
119
					}
120

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

    
123
					if ($cfgdevice)
124
						break;
125
				}
126
				if (mwexec("/sbin/mount -r /dev/{$mountdisk}d {$g['cf_path']}") == 0) {
127
					if (file_exists("{$g['cf_conf_path']}/config.xml")) {
128
						/* found it */
129
						$cfgdevice = $mountdisk;
130
						$cfgpartition = $cfgdevice . "d";
131
						$cfgfstype = "ufs";
132
						echo "Found configuration on $cfgdevice.\n";
133
					}
134

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

    
137
					if ($cfgdevice)
138
						break;
139
				}
140
			}
141
		}
142

    
143
		if (!$cfgdevice) {
144
			/* no device found, print an error and die */
145
			echo <<<EOD
146

    
147

    
148
*******************************************************************************
149
* FATAL ERROR                                                                 *
150
* The device that contains the configuration file (config.xml) could not be   *
151
* found. pfSense cannot continue booting.                                     *
152
*******************************************************************************
153

    
154

    
155
EOD;
156

    
157
			mwexec("/sbin/halt");
158
			exit;
159
		}
160

    
161
		/* write device name to a file for rc.firmware */
162
		$fd = fopen("{$g['varetc_path']}/cfdevice", "w");
163
		fwrite($fd, $cfgdevice . "\n");
164
		fclose($fd);
165

    
166
		/* write out an fstab */
167
		$fd = fopen("{$g['etc_path']}/fstab", "w");
168

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

    
172
		fwrite($fd, $fstab);
173
		fclose($fd);
174
	}
175

    
176
	/* mount all filesystems */
177
	mwexec("/sbin/mount -a");
178
}
179

    
180
$config = parse_config();
181

    
182
/****f* config/parse_config
183
 * NAME
184
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
185
 * INPUTS
186
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
187
 * RESULT
188
 *   $config      - array containing all configuration variables
189
 ******/
190
function parse_config($parse = false) {
191
	global $g;
192

    
193
	config_lock();
194
	if(!$parse) {
195
		if(file_exists($g['tmp_path'] . '/config.cache')) {
196
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
197
			if(is_null($config)) {
198
				config_unlock();
199
				parse_config(true);
200
			}
201
		} else {
202
			config_unlock();
203
			$config = parse_config(true);
204
		}
205
	} else {
206
		$config = parse_xml_config($g['conf_path'] . '/config.xml', $g['xml_rootobj']);
207
		generate_config_cache($config);
208
	}
209
	
210
	alias_make_table($config);
211
	config_unlock();
212

    
213
	/*    override some global configuration parms if they exist
214
	 *    instead of hard coding these checks into the codebase
215
         */	
216
	if($config['pptp']['n_pptp_units'])
217
		$g['n_pptp_units'] = $config['pptp']['n_pptp_units'];
218
	if($config['pptp']['pptp_subnet'])
219
		$g['pptp_subnet'] = $config['pptp']['pptp_subnet'];
220
    
221
	if($config['pppoe']['n_pppoe_units'])
222
		$g['n_pppoe_units'] = $config['pppoe']['n_pppoe_units'];
223
	if($config['pppoe']['pppoe_subnet'])
224
		$g['pppoe_subnet'] = $config['pppoe']['pppoe_subnet'];
225

    
226
	return $config;
227
}
228

    
229
/****f* config/generate_config_cache
230
 * NAME
231
 *   generate_config_cache - Write serialized configuration to cache.
232
 * INPUTS
233
 *   $config	- array containing current firewall configuration
234
 * RESULT
235
 *   boolean	- true on completion
236
 ******/
237
function generate_config_cache($config) {
238
	global $g;
239
	conf_mount_rw();
240
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
241
	fwrite($configcache, serialize($config));
242
	fclose($configcache);
243
	conf_mount_ro();
244
	return true;
245
}
246

    
247
/****f* config/parse_config_bootup
248
 * NAME
249
 *   parse_config_bootup - Bootup-specific configuration checks.
250
 * RESULT
251
 *   null
252
 ******/
253
function parse_config_bootup() {
254
	global $config, $g, $noparseconfig;
255
	if (!$noparseconfig) {
256
		if (!file_exists("{$g['conf_path']}/config.xml")) {
257
			config_lock();
258
			if ($g['booting']) {
259
				if (strstr($g['platform'], "cdrom")) {
260
					/* try copying the default config. to the floppy */
261
					echo "Resetting factory defaults...\n";
262
					reset_factory_defaults();
263
	
264
					echo "No XML configuration file found - using factory defaults.\n";
265
					echo "Make sure that the configuration floppy disk with the conf/config.xml\n";
266
					echo "file is inserted. If it isn't, your configuration changes will be lost\n";
267
					echo "on reboot.\n";
268
				} else {
269
					echo "XML configuration file not found.  pfSense cannot continue booting.\n";
270
					mwexec("/sbin/halt");
271
					exit;
272
				}
273
			} else {
274
				config_unlock();
275
				exit(0);
276
			}
277
		}
278
	}
279

    
280
	parse_config(true);
281
	
282
	if ((float)$config['version'] > (float)$g['latest_config']) {
283
		echo <<<EOD
284

    
285

    
286
*******************************************************************************
287
* WARNING!                                                                    *
288
* The current configuration has been created with a newer version of pfSense  *
289
* than this one! This can lead to serious misbehavior and even security       *
290
* holes! You are urged to either upgrade to a newer version of pfSense or     *
291
* revert to the default configuration immediately!                            *
292
*******************************************************************************
293

    
294

    
295
EOD;
296
		}
297

    
298
	/* make alias table (for faster lookups) */
299
	alias_make_table($config);
300
	config_unlock();
301
}
302

    
303
/****f* config/conf_mount_rw
304
 * NAME
305
 *   conf_mount_rw - Mount filesystems read/write.
306
 * RESULT
307
 *   null
308
 ******/
309
/* mount flash card read/write */
310
function conf_mount_rw() {
311
	global $g;
312

    
313
	/* do not mount on cdrom platform */
314
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
315
		return;
316

    
317
	$status = mwexec("/sbin/umount -f {$g['cf_path']}");
318
	$status = mwexec("/sbin/mount -w {$g['cf_path']}");
319
	if($status <> 0) {
320
		mwexec("/sbin/fsck -y {$g['cf_path']}");
321
		$status = mwexec("/sbin/mount -w {$g['cf_path']}");
322
	}
323

    
324
	/*    if the platform is soekris or wrap or pfSense, lets mount the
325
	 *    compact flash cards root.
326
         */
327
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx"
328
	   or $g['platform'] == "embedded") {
329
		$status = mwexec("/sbin/mount -w /");
330
		/* we could not mount this correctly.  kick off fsck */
331
		if($status <> 0) {
332
			log_error("File system is dirty.  Launching FSCK for /");
333
			mwexec("/sbin/fsck -y");
334
			$status = mwexec("/sbin/mount -w /");
335
		}
336
	}
337
	
338
	usleep(100);
339
	
340
}
341

    
342
/****f* config/conf_mount_ro
343
 * NAME         
344
 *   conf_mount_ro - Mount filesystems readonly.
345
 * RESULT
346
 *   null        
347
 ******/
348
function conf_mount_ro() {
349
	global $g;
350

    
351
	if($g['booting'] == true)
352
		return;
353
	
354
	/* do not umount if generating ssh keys */
355
	if(file_exists("/tmp/keys_generating"))
356
		return;
357
	
358
	/* do not umount on cdrom or pfSense platforms */
359
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
360
		return;
361

    
362
	/* sync data, then force a umount the remount of /cf */
363
	mwexec("/bin/sync");
364
	mwexec("/bin/sync");
365
	mwexec("/sbin/umount -f {$g['cf_path']}");
366
	mwexec("/sbin/mount -r {$g['cf_path']}");
367
	mwexec("/bin/sync");
368
	mwexec("/bin/sync");
369
	mwexec("/sbin/mount -r /");
370
	
371
	usleep(100);
372

    
373
}
374

    
375
/****f* config/convert_config
376
 * NAME         
377
 *   convert_config - Attempt to update config.xml.
378
 * DESCRIPTION
379
 *   convert_config() reads the current global configuration
380
 *   and attempts to convert it to conform to the latest
381
 *   config.xml version. This allows major formatting changes
382
 *   to be made with a minimum of breakage.
383
 * RESULT
384
 *   null        
385
 ******/
386
/* convert configuration, if necessary */
387
function convert_config() {
388
	global $config, $g;
389

    
390
	if ($config['version'] == $g['latest_config'])
391
		return;		/* already at latest version */
392

    
393
	// Save off config version
394
	$prev_version = $config['version'];
395

    
396
	/* convert 1.0 -> 1.1 */
397
	if ($config['version'] == "1.0") {
398
		$opti = 1;
399
		$ifmap = array('lan' => 'lan', 'wan' => 'wan', 'pptp' => 'pptp');
400

    
401
		/* convert DMZ to optional, if necessary */
402
		if (isset($config['interfaces']['dmz'])) {
403

    
404
			$dmzcfg = &$config['interfaces']['dmz'];
405

    
406
			if ($dmzcfg['if']) {
407
				$config['interfaces']['opt' . $opti] = array();
408
				$optcfg = &$config['interfaces']['opt' . $opti];
409

    
410
				$optcfg['enable'] = $dmzcfg['enable'];
411
				$optcfg['descr'] = "DMZ";
412
				$optcfg['if'] = $dmzcfg['if'];
413
				$optcfg['ipaddr'] = $dmzcfg['ipaddr'];
414
				$optcfg['subnet'] = $dmzcfg['subnet'];
415

    
416
				$ifmap['dmz'] = "opt" . $opti;
417
				$opti++;
418
			}
419

    
420
			unset($config['interfaces']['dmz']);
421
		}
422

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

    
426
			if (!$config['interfaces']['wlan' . $i]['if']) {
427
				unset($config['interfaces']['wlan' . $i]);
428
				continue;
429
			}
430

    
431
			$wlancfg = &$config['interfaces']['wlan' . $i];
432
			$config['interfaces']['opt' . $opti] = array();
433
			$optcfg = &$config['interfaces']['opt' . $opti];
434

    
435
			$optcfg['enable'] = $wlancfg['enable'];
436
			$optcfg['descr'] = "WLAN" . $i;
437
			$optcfg['if'] = $wlancfg['if'];
438
			$optcfg['ipaddr'] = $wlancfg['ipaddr'];
439
			$optcfg['subnet'] = $wlancfg['subnet'];
440
			$optcfg['bridge'] = $wlancfg['bridge'];
441

    
442
			$optcfg['wireless'] = array();
443
			$optcfg['wireless']['mode'] = $wlancfg['mode'];
444
			$optcfg['wireless']['ssid'] = $wlancfg['ssid'];
445
			$optcfg['wireless']['channel'] = $wlancfg['channel'];
446
			$optcfg['wireless']['wep'] = $wlancfg['wep'];
447

    
448
			$ifmap['wlan' . $i] = "opt" . $opti;
449

    
450
			unset($config['interfaces']['wlan' . $i]);
451
			$opti++;
452
		}
453

    
454
		/* convert filter rules */
455
		$n = count($config['filter']['rule']);
456
		for ($i = 0; $i < $n; $i++) {
457

    
458
			$fr = &$config['filter']['rule'][$i];
459

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

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

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

    
498
		/* convert shaper rules */
499
		$n = count($config['pfqueueing']['rule']);
500
		if (is_array($config['pfqueueing']['rule']))
501
			for ($i = 0; $i < $n; $i++) {
502

    
503
			$fr = &$config['pfqueueing']['rule'][$i];
504

    
505
			/* remap interface */
506
			if (array_key_exists($fr['interface'], $ifmap))
507
				$fr['interface'] = $ifmap[$fr['interface']];
508
			else {
509
				/* remove the rule */
510
				echo "\nWarning: traffic shaper rule removed " .
511
					"(interface '{$fr['interface']}' does not exist anymore).";
512
				unset($config['pfqueueing']['rule'][$i]);
513
				continue;
514
			}
515

    
516
			/* remap source network */
517
			if (isset($fr['source']['network'])) {
518
				if (array_key_exists($fr['source']['network'], $ifmap))
519
					$fr['source']['network'] = $ifmap[$fr['source']['network']];
520
				else {
521
					/* remove the rule */
522
					echo "\nWarning: traffic shaper rule removed " .
523
						"(source network '{$fr['source']['network']}' does not exist anymore).";
524
					unset($config['pfqueueing']['rule'][$i]);
525
					continue;
526
				}
527
			}
528

    
529
			/* remap destination network */
530
			if (isset($fr['destination']['network'])) {
531
				if (array_key_exists($fr['destination']['network'], $ifmap))
532
					$fr['destination']['network'] = $ifmap[$fr['destination']['network']];
533
				else {
534
					/* remove the rule */
535
					echo "\nWarning: traffic shaper rule removed " .
536
						"(destination network '{$fr['destination']['network']}' does not exist anymore).";
537
					unset($config['pfqueueing']['rule'][$i]);
538
					continue;
539
				}
540
			}
541
		}
542

    
543
		$config['version'] = "1.1";
544
	}
545

    
546
	/* convert 1.1 -> 1.2 */
547
	if ($config['version'] == "1.1") {
548
		/* move LAN DHCP server config */
549
		$tmp = $config['dhcpd'];
550
		$config['dhcpd'] = array();
551
		$config['dhcpd']['lan'] = $tmp;
552

    
553
		/* encrypt password */
554
		$config['system']['password'] = crypt($config['system']['password']);
555

    
556
		$config['version'] = "1.2";
557
	}
558

    
559
	/* convert 1.2 -> 1.3 */
560
	if ($config['version'] == "1.2") {
561
		/* convert advanced outbound NAT config */
562
		for ($i = 0; isset($config['nat']['advancedoutbound']['rule'][$i]); $i++) {
563
			$curent = &$config['nat']['advancedoutbound']['rule'][$i];
564
			$src = $curent['source'];
565
			$curent['source'] = array();
566
			$curent['source']['network'] = $src;
567
			$curent['destination'] = array();
568
			$curent['destination']['any'] = true;
569
		}
570

    
571
		/* add an explicit type="pass" to all filter rules to make things consistent */
572
		for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
573
			$config['filter']['rule'][$i]['type'] = "pass";
574
		}
575

    
576
		$config['version'] = "1.3";
577
	}
578

    
579
	/* convert 1.3 -> 1.4 */
580
	if ($config['version'] == "1.3") {
581
		/* convert shaper rules (make pipes) */
582
		if (is_array($config['pfqueueing']['rule'])) {
583
			$config['pfqueueing']['pipe'] = array();
584

    
585
			for ($i = 0; isset($config['pfqueueing']['rule'][$i]); $i++) {
586
				$curent = &$config['pfqueueing']['rule'][$i];
587

    
588
				/* make new pipe and associate with this rule */
589
				$newpipe = array();
590
				$newpipe['descr'] = $curent['descr'];
591
				$newpipe['bandwidth'] = $curent['bandwidth'];
592
				$newpipe['delay'] = $curent['delay'];
593
				$newpipe['mask'] = $curent['mask'];
594
				$config['pfqueueing']['pipe'][$i] = $newpipe;
595

    
596
				$curent['targetpipe'] = $i;
597

    
598
				unset($curent['bandwidth']);
599
				unset($curent['delay']);
600
				unset($curent['mask']);
601
			}
602
		}
603

    
604
		$config['version'] = "1.4";
605
	}
606

    
607
	/* Convert 1.4 -> 1.5 */
608
	if ($config['version'] == "1.4") {
609

    
610
		/* Default route moved */
611
		if (isset($config['interfaces']['wan']['gateway']))
612
			if ($config['interfaces']['wan']['gateway'] <> "")
613
				$config['interfaces']['wan']['gateway'] = $config['interfaces']['wan']['gateway'];
614
		unset($config['interfaces']['wan']['gateway']);
615

    
616
                /* Queues are no longer interface specific */
617
                if (isset($config['interfaces']['lan']['schedulertype']))
618
                        unset($config['interfaces']['lan']['schedulertype']);
619
                if (isset($config['interfaces']['wan']['schedulertype']))
620
                        unset($config['interfaces']['wan']['schedulertype']);
621

    
622
                for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
623
                        if(isset($config['interfaces']['opt' . $i]['schedulertype']))
624
                                unset($config['interfaces']['opt' . $i]['schedulertype']);
625
                }
626

    
627
		$config['version'] = "1.5";
628
	}
629

    
630
	/* Convert 1.5 -> 1.6 */
631
	if ($config['version'] == "1.5") {
632
		/* Alternate firmware URL moved */
633
		if (isset($config['system']['firmwareurl']) && isset($config['system']['firmwarename'])) { // Only convert if *both* are defined.
634
			$config['system']['alt_firmware_url'] = array();
635
			$config['system']['alt_firmware_url']['enabled'] = "";
636
			$config['system']['alt_firmware_url']['firmware_base_url'] = $config['system']['firmwareurl'];
637
			$config['system']['alt_firmware_url']['firmware_filename'] = $config['system']['firmwarename'];
638
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
639
		} else {
640
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
641
		}
642

    
643
		$config['version'] = "1.6";
644
	}
645
	
646
	/* Convert 1.6 -> 1.7 */
647
	if ($config['version'] == "1.6") {
648
		/* wipe previous shaper configuration */
649
		unset($config['shaper']['queue']);
650
		unset($config['shaper']['rule']);
651
		unset($config['interfaces']['wan']['bandwidth']);
652
		unset($config['interfaces']['wan']['bandwidthtype']);
653
		unset($config['interfaces']['lan']['bandwidth']);
654
		unset($config['interfaces']['lan']['bandwidthtype']);		
655
		$config['shaper']['enable'] = FALSE;
656
		$config['version'] = "1.7";	
657
	}
658
	/* Convert 1.7 -> 1.8 */
659
	if ($config['version'] == "1.7") {
660
		if(isset($config['proxyarp']) && is_array($config['proxyarp']['proxyarpnet'])) {
661
			$proxyarp = &$config['proxyarp']['proxyarpnet'];
662
			foreach($proxyarp as $arpent){
663
				$vip = array();
664
				$vip['mode'] = "proxyarp";
665
				$vip['interface'] = $arpent['interface'];
666
				$vip['descr'] = $arpent['descr'];
667
				if (isset($arpent['range'])) {
668
					$vip['range'] = $arpent['range'];
669
					$vip['type'] = "range";
670
				} else {
671
					$subnet = explode('/', $arpent['network']);
672
					$vip['subnet'] = $subnet[0];
673
					if (isset($subnet[1])) {
674
						$vip['subnet_bits'] = $subnet[1];
675
						$vip['type'] = "network";
676
					} else {
677
						$vip['subnet_bits'] = "32";
678
						$vip['type'] = "single";
679
					}
680
				}
681
				$config['virtualip']['vip'][] = $vip;
682
			}
683
			unset($config['proxyarp']);
684
		}
685
		if(isset($config['installedpackages']) && isset($config['installedpackages']['carp']) && is_array($config['installedpackages']['carp']['config'])) {
686
			$carp = &$config['installedpackages']['carp']['config'];
687
			foreach($carp as $carpent){
688
				$vip = array();
689
				$vip['mode'] = "carp";
690
				$vip['interface'] = "AUTO";
691
				$vip['descr'] = "CARP vhid {$carpent['vhid']}";
692
				$vip['type'] = "single";
693
				$vip['vhid'] = $carpent['vhid'];
694
				$vip['advskew'] = $carpent['advskew'];
695
				$vip['password'] = $carpent['password'];
696
				$vip['subnet'] = $carpent['ipaddress'];
697
				$vip['subnet_bits'] = $carpent['netmask'];
698
				$config['virtualip']['vip'][] = $vip;
699
			}
700
			unset($config['installedpackages']['carp']);
701
		}
702
		/* Server NAT is no longer needed */
703
		unset($config['nat']['servernat']);
704
		
705
		/* enable SSH */
706
		if ($config['version'] == "1.8") {
707
			$config['system']['sshenabled'] = true;
708
		}
709
		
710
		$config['version'] = "1.9";
711
	}
712

    
713
	/* Convert 1.8 -> 1.9 */
714
	if ($config['version'] == "1.8") {
715
		$config['theme']="metallic";
716
		$config['version'] = "1.9";
717
	}
718
	/* Convert 1.9 -> 2.0 */
719
	if ($config['version'] == "1.9") {
720
		if(is_array($config['ipsec']['tunnel'])) {
721
			reset($config['ipsec']['tunnel']);
722
			while (list($index, $tunnel) = each($config['ipsec']['tunnel'])) {
723
				/* Sanity check on required variables */
724
				/* This fixes bogus <tunnel> entries - remnant of bug #393 */
725
				if (!isset($tunnel['local-subnet']) && !isset($tunnel['remote-subnet'])) {
726
					unset($config['ipsec']['tunnel'][$tunnel]);
727
				}
728
			}
729
        	}
730
		$config['version'] = "2.0";
731
	}
732
	/* Convert 2.0 -> 2.1 */
733
	if ($config['version'] == "2.0") {
734
		/* shaper scheduler moved */
735
		if(isset($config['system']['schedulertype'])) {
736
			$config['shaper']['schedulertype'] = $config['system']['schedulertype'];
737
			unset($config['system']['schedulertype']);
738
		}
739
		$config['version'] = "2.1";
740
	}
741
	/* Convert 2.1 -> 2.2 */
742
	if ($config['version'] == "2.1") {
743
		/* move gateway to wan interface */
744
		$config['interfaces']['wan']['gateway'] = $config['system']['gateway'];
745
		$config['version'] = "2.2";
746
	}
747

    
748
	if ($prev_version != $config['version'])
749
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
750
}
751

    
752
/****f* config/write_config
753
 * NAME
754
 *   write_config - Backup and write the firewall configuration.
755
 * DESCRIPTION
756
 *   write_config() handles backing up the current configuration,
757
 *   applying changes, and regenerating the configuration cache.
758
 * INPUTS
759
 *   $desc	- string containing the a description of configuration changes
760
 *   $backup	- boolean: do not back up current configuration if false.
761
 * RESULT
762
 *   null       
763
 ******/
764
/* save the system configuration */
765
function write_config($desc="Unknown", $backup = true) {
766
	global $config, $g;
767

    
768
	if($g['platform'] <> "embedded" and $g['platform'] <> "wrap") 
769
		if($backup) backup_config();
770

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

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

    
778
	$config['revision']['description'] = $desc;
779
	$config['revision']['time'] = $changetime;
780
	
781
	config_lock();
782

    
783
	/* generate configuration XML */
784
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
785

    
786
	conf_mount_rw();
787

    
788
	/* write new configuration */
789
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
790
	if (!$fd)
791
		die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
792
	fwrite($fd, $xmlconfig);
793
	fclose($fd);
794

    
795
	if($g['booting'] <> true) {
796
		conf_mount_ro();
797
	}
798

    
799
	config_unlock();
800

    
801
	// Always reparse the config after it's written - something is getting lost in serialize().
802
	$config = parse_config(true);
803
	return $config;
804
}
805

    
806
/****f* config/reset_factory_defaults
807
 * NAME
808
 *   reset_factory_defaults - Reset the system to its default configuration.
809
 * RESULT
810
 *   integer	- indicates completion
811
 ******/
812
function reset_factory_defaults() {
813
	global $g;
814

    
815
	config_lock();
816
	conf_mount_rw();
817

    
818
	/* create conf directory, if necessary */
819
	safe_mkdir("{$g['cf_conf_path']}");
820

    
821
	/* clear out /conf */
822
	$dh = opendir($g['conf_path']);
823
	while ($filename = readdir($dh)) {
824
		if (($filename != ".") && ($filename != "..")) {
825
			unlink_if_exists($g['conf_path'] . "/" . $filename);
826
		}
827
	}
828
	closedir($dh);
829

    
830
	/* copy default configuration */
831
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
832
	
833
	/* call the wizard */
834
	touch("/conf/trigger_initial_wizard");
835
	
836
	conf_mount_ro();
837
	config_unlock();
838

    
839
	return 0;
840
}
841

    
842
function config_restore($conffile) {
843
	global $config, $g;
844
       
845
        if (!file_exists($conffile))
846
                return 1;
847
        
848
        config_lock();
849
        conf_mount_rw();        
850
        
851
        backup_config();
852
        copy($conffile, "{$g['cf_conf_path']}/config.xml");
853
	$config = parse_config(true);
854
        write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
855
        
856
        conf_mount_ro();
857
        config_unlock();
858

    
859
        return 0;
860
}
861

    
862

    
863

    
864
function config_install($conffile) {
865
        global $config, $g;
866
        
867
        if (!file_exists($conffile))
868
                return 1;
869

    
870
	if (!config_validate($conffile))
871
		return 1;
872

    
873
	if($g['booting'] == true)
874
		echo "Installing configuration...\n";
875
 
876
        config_lock();
877
        conf_mount_rw();
878

    
879
	
880
        copy($conffile, "{$g['conf_path']}/config.xml");
881

    
882
	/* unlink cache file if it exists */
883
	if(file_exists("{$g['tmp_path']}/config.cache"))
884
		unlink("{$g['tmp_path']}/config.cache");
885
  
886
        conf_mount_ro();
887
        config_unlock();
888

    
889
        return 0;
890
}
891

    
892
function config_validate($conffile) {
893

    
894
	global $g, $xmlerr;
895

    
896
	$xml_parser = xml_parser_create();
897
	
898
	if (!($fp = fopen($conffile, "r"))) {
899
		$xmlerr = "XML error: unable to open file";
900
		return false;
901
	}
902
	
903
	while ($data = fread($fp, 4096)) {
904
		if (!xml_parse($xml_parser, $data, feof($fp))) {
905
			$xmlerr = sprintf("%s at line %d",
906
						xml_error_string(xml_get_error_code($xml_parser)),
907
						xml_get_current_line_number($xml_parser));
908
			return false;
909
		}
910
	}
911
	xml_parser_free($xml_parser);
912
	
913
	fclose($fp);
914
	
915
	return true;
916
}
917

    
918
/* lock configuration file, decide that the lock file is stale after
919
   10 seconds */
920
function config_lock() {
921
	global $g, $process_lock;
922

    
923
	/* No need to continue if we're the ones holding the lock */
924
	if ($process_lock)
925
		return;
926

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

    
929
	$n = 0;
930
	while ($n < 10) {
931
		/* open the lock file in append mode to avoid race condition */
932
		if ($fd = @fopen($lockfile, "x")) {
933
			/* succeeded */
934
			$process_lock = true;
935
			fclose($fd);
936
			return;
937
		} else {
938
			/* file locked, wait and try again */
939
			$process_lock = false;
940
			sleep(1);
941
			$n++;
942
		}
943
	}
944
}
945

    
946
/* unlock configuration file */
947
function config_unlock() {
948
	global $g, $process_lock;
949

    
950
	$lockfile = "{$g['varrun_path']}/config.lock";
951
	$process_lock = false;
952

    
953
	unlink_if_exists($lockfile);
954
}
955

    
956
function set_networking_interfaces_ports() {
957
	global $noreboot;
958
	global $config;
959
	global $g;
960
	global $fp;
961

    
962
	$fp = fopen('php://stdin', 'r');
963

    
964
	$iflist = get_interface_list();
965

    
966
	echo <<<EOD
967

    
968
Valid interfaces are:
969

    
970

    
971
EOD;
972

    
973
	if(!is_array($iflist)) {
974
		echo "No interfaces found!\n";
975
	} else {
976
		foreach ($iflist as $iface => $ifa) {
977
			echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
978
				$ifa['up'] ? "   (up)" : "");
979
		}
980
	}
981

    
982
	echo <<<EOD
983

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

    
988
Do you want to set up VLANs now [y|n]?
989
EOD;
990

    
991
	if (strcasecmp(chop(fgets($fp)), "y") == 0)
992
		vlan_setup();
993

    
994
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
995

    
996
		echo "\n\nVLAN interfaces:\n\n";
997
		$i = 0;
998
		foreach ($config['vlans']['vlan'] as $vlan) {
999

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

    
1003
			$iflist['vlan' . $i] = array();
1004
			$i++;
1005
		}
1006
	}
1007

    
1008
	echo <<<EOD
1009

    
1010
*NOTE*  pfSense requires *ATLEAST* 2 assigned interfaces to function.
1011
        If you do not have two interfaces turn off the machine until
1012
	you do.
1013

    
1014
If you do not know the names of your interfaces, you may choose to use
1015
auto-detection... In that case, disconnect all interfaces now before
1016
hitting a.   The system will then prompt you to plug in each nic to
1017
autodetect.
1018

    
1019
EOD;
1020

    
1021
	do {
1022
		echo "\nEnter the LAN interface name or 'a' for auto-detection: ";
1023
		$lanif = chop(fgets($fp));
1024
		if ($lanif === "") {
1025
			return;
1026
		}
1027

    
1028
		if ($lanif === "a")
1029
			$lanif = autodetect_interface("LAN", $fp);
1030
		else if (!array_key_exists($lanif, $iflist)) {
1031
			echo "\nInvalid interface name '{$lanif}'\n";
1032
			unset($lanif);
1033
			continue;
1034
		}
1035
	} while (!$lanif);
1036

    
1037
	do {
1038
		echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
1039
		$wanif = chop(fgets($fp));
1040
		if ($wanif === "") {
1041
			return;
1042
		}
1043
		if ($wanif === "a")
1044
			$wanif = autodetect_interface("WAN", $fp);
1045
		else if (!array_key_exists($wanif, $iflist)) {
1046
			echo "\nInvalid interface name '{$wanif}'\n";
1047
			unset($wanif);
1048
			continue;
1049
		}
1050
	} while (!$wanif);
1051

    
1052
	/* optional interfaces */
1053
	$i = 0;
1054
	$optif = array();
1055

    
1056
	while (1) {
1057
		if ($optif[$i])
1058
			$i++;
1059
		$i1 = $i + 1;
1060
		echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
1061
			"(or nothing if finished): ";
1062
		$optif[$i] = chop(fgets($fp));
1063

    
1064
		if ($optif[$i]) {
1065
			if ($optif[$i] === "a") {
1066
				$ad = autodetect_interface("Optional " . $i1, $fp);
1067
				if ($ad)
1068
					$optif[$i] = $ad;
1069
				else
1070
					unset($optif[$i]);
1071
			} else if (!array_key_exists($optif[$i], $iflist)) {
1072
				echo "\nInvalid interface name '{$optif[$i]}'\n";
1073
				unset($optif[$i]);
1074
				continue;
1075
			}
1076
		} else {
1077
			unset($optif[$i]);
1078
			break;
1079
		}
1080
	}
1081

    
1082
	/* check for double assignments */
1083
	$ifarr = array_merge(array($lanif, $wanif), $optif);
1084

    
1085
	for ($i = 0; $i < (count($ifarr)-1); $i++) {
1086
		for ($j = ($i+1); $j < count($ifarr); $j++) {
1087
			if ($ifarr[$i] == $ifarr[$j]) {
1088
				echo <<<EOD
1089

    
1090
Error: you cannot assign the same interface name twice!
1091

    
1092
EOD;
1093

    
1094
				return;
1095
			}
1096
		}
1097
	}
1098

    
1099
	echo <<<EOD
1100

    
1101
The interfaces will be assigned as follows:
1102

    
1103
LAN  -> {$lanif}
1104
WAN  -> {$wanif}
1105

    
1106
EOD;
1107

    
1108
	for ($i = 0; $i < count($optif); $i++) {
1109
		echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
1110
	}
1111

    
1112
echo <<<EOD
1113

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

    
1117
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
1118

    
1119
		$config['interfaces']['lan']['if'] = $lanif;
1120
		if (preg_match($g['wireless_regex'], $lanif)) {
1121
			if (!is_array($config['interfaces']['lan']['wireless']))
1122
				$config['interfaces']['lan']['wireless'] = array();
1123
		} else {
1124
			unset($config['interfaces']['lan']['wireless']);
1125
		}
1126
		
1127
		$config['interfaces']['wan']['if'] = $wanif;
1128
		if (preg_match($g['wireless_regex'], $wanif)) {
1129
			if (!is_array($config['interfaces']['wan']['wireless']))
1130
				$config['interfaces']['wan']['wireless'] = array();
1131
		} else {
1132
			unset($config['interfaces']['wan']['wireless']);
1133
		}
1134
		
1135
		for ($i = 0; $i < count($optif); $i++) {
1136
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
1137
				$config['interfaces']['opt' . ($i+1)] = array();
1138
			
1139
			$config['interfaces']['opt' . ($i+1)]['if'] = $optif[$i];
1140
			
1141
			/* wireless interface? */
1142
			if (preg_match($g['wireless_regex'], $optif[$i])) {
1143
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
1144
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
1145
			} else {
1146
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
1147
			}
1148
			
1149
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
1150
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
1151
		}
1152
		
1153
		/* remove all other (old) optional interfaces */
1154
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
1155
			unset($config['interfaces']['opt' . ($i+1)]);
1156
		
1157
		conf_mount_rw();
1158
		
1159
		/* call the wizard */
1160
		touch("/conf/trigger_initial_wizard");
1161
		
1162
		write_config();
1163
		
1164
		echo <<<EOD
1165

    
1166

    
1167

    
1168
EOD;
1169

    
1170
		if($g['booting'])
1171
			return;
1172

    
1173
		echo "One moment while we reload the settings...";
1174

    
1175
		/* resync everything */
1176
		reload_all_sync();
1177
		
1178
		echo " done!\n";
1179
		
1180
		touch("{$g['tmp_path']}/assign_complete");
1181

    
1182
	}
1183
}
1184

    
1185
function autodetect_interface($ifname, $fp) {
1186
	$iflist_prev = get_interface_list("media");
1187
	echo <<<EOD
1188

    
1189
Connect the {$ifname} interface now and make sure that the link is up.
1190
Then press ENTER to continue.
1191

    
1192
EOD;
1193
	fgets($fp);
1194
	$iflist = get_interface_list("media");
1195

    
1196
	foreach ($iflist_prev as $ifn => $ifa) {
1197
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1198
			echo "Detected link-up on interface {$ifn}.\n";
1199
			return $ifn;
1200
		}
1201
	}
1202

    
1203
	echo "No link-up detected.\n";
1204

    
1205
	return null;
1206
}
1207

    
1208
function vlan_setup() {
1209
	global $iflist, $config, $g, $fp;
1210

    
1211
	$iflist = get_interface_list();
1212

    
1213
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1214

    
1215
	echo <<<EOD
1216

    
1217
WARNING: all existing VLANs will be cleared if you proceed!
1218

    
1219
Do you want to proceed [y|n]?
1220
EOD;
1221

    
1222
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1223
		return;
1224
	}
1225

    
1226
	$config['vlans']['vlan'] = array();
1227
	echo "\n";
1228

    
1229
	while (1) {
1230
		$vlan = array();
1231

    
1232
		echo "\n\nVLAN Capable interfaces:\n\n";
1233
		if(!is_array($iflist)) {
1234
			echo "No interfaces found!\n";
1235
		} else {
1236
			$vlan_capable=0;
1237
			foreach ($iflist as $iface => $ifa) {
1238
				if (is_jumbo_capable($iface)) {
1239
					echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
1240
						$ifa['up'] ? "   (up)" : "");
1241
					$vlan_capable++;
1242
				}
1243
			}
1244
		}
1245

    
1246
		if($vlan_capable == 0) {
1247
			echo "No VLAN capable interfaces detected.\n";
1248
			return;
1249
		}
1250

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

    
1254
		if ($vlan['if']) {
1255
			if (!array_key_exists($vlan['if'], $iflist) or
1256
			    !is_jumbo_capable($vlan['if'])) {
1257
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1258
				continue;
1259
			}
1260
		} else {
1261
			break;
1262
		}
1263

    
1264
		echo "Enter the VLAN tag (1-4094): ";
1265
		$vlan['tag'] = chop(fgets($fp));
1266

    
1267
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1268
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1269
			continue;
1270
		}
1271

    
1272
		$config['vlans']['vlan'][] = $vlan;
1273
	}
1274
}
1275

    
1276
function system_start_ftp_helpers() {
1277
	require_once("interfaces.inc");
1278
	global $config, $g;
1279

    
1280
	/* build an array of interfaces to work with */
1281
	$iflist = array("lan" => "LAN");
1282
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1283
		$iflist['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
1284

    
1285
	/* loop through all interfaces and handle pftpx */
1286
	$interface_counter = 0;
1287
	foreach ($iflist as $ifent => $ifname) {
1288
		/*    if the ftp proxy is disabled for this interface then kill pftpx 
1289
		 *    instance and continue. note that the helpers for port forwards are 
1290
		 *    launched in a  different sequence so we are filtering them out 
1291
                 *    here by not including -c {$port} -g 8021 first.
1292
		 */
1293
		$port = 8021 + $interface_counter;
1294
		if(isset($config['interfaces'][strtolower($ifname)]['disableftpproxy'])) {
1295
			/*    item is disabled.  lets ++ the interface counter and
1296
			 *    keep processing interfaces. kill pftpx if already
1297
                         *    running for this instance.
1298
                         */
1299
			$helpers = exec("ps awux | grep \"/usr/local/sbin/pftpx -c {$port}\" | grep -v grep | sed \"s/  */ /g\" | cut -f2 -d\" \"");
1300
			if($helpers)
1301
				mwexec("/bin/kill {$helpers}");
1302
			$interface_counter++;
1303
		} else {
1304
			/* grab the current interface IP address */
1305
			$int = convert_friendly_interface_to_real_interface_name($ifname);
1306
			$ip = find_interface_ip($int);
1307
			/* if pftpx is already running then do not launch it again */
1308
			$helpers = exec("/bin/ps awux | grep \"/usr/local/sbin/pftpx -c {$port}\" | grep -v grep | sed \"s/  */ /g\"");
1309
			if(!$helpers && $ip)
1310
 				mwexec("/usr/local/sbin/pftpx -c {$port} -g 8021 {$ip}");
1311
			$interface_counter++;
1312
		}
1313
	}
1314
}
1315

    
1316
function cleanup_backupcache($revisions = 30) {
1317
	global $g;
1318
	$i = false;
1319
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1320
		conf_mount_rw();
1321
		$backups = get_backups();
1322
		$newbaks = array();
1323
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1324
		$baktimes = $backups['versions'];
1325
		$tocache = array();
1326
		unset($backups['versions']);
1327
       		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1328
			$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));	
1329
                	if(!in_array($tocheck, $baktimes)) {
1330
				$i = true;
1331
				if($g['booting']) print " " . $tocheck . "a";
1332
				$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1333
				if($newxml['revision']['description'] == "") $newxml['revision']['description'] = "Unknown";
1334
				$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1335
			}
1336
        	}
1337
		foreach($backups as $checkbak) {
1338
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1339
				$newbaks[] = $checkbak;
1340
			} else {
1341
				$i = true;
1342
				if($g['booting']) print " " . $tocheck . "r";
1343
			}
1344
		}
1345
		foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);	
1346
		if(is_int($revisions) and (count($tocache) > $revisions)) {
1347
			$toslice = array_slice(array_keys($tocache), 0, $revisions);
1348
			foreach($toslice as $sliced) $newcache[$sliced] = $tocache[$sliced];
1349
			foreach($tocache as $version => $versioninfo) {
1350
				if(!in_array($version, array_keys($newcache))) {
1351
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1352
					if($g['booting']) print " " . $tocheck . "d";
1353
				}
1354
			}
1355
			$tocache = $newcache;
1356
		}
1357
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1358
        	fwrite($bakout, serialize($tocache));
1359
  	        fclose($bakout);
1360
		conf_mount_ro();
1361
	}
1362
	if($g['booting']) {
1363
		if($i) {
1364
			print "done.\n";
1365
		}
1366
	}
1367
}
1368
  	 
1369
function get_backups() { 	 
1370
	global $g;
1371

    
1372
        if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1373
                $confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1374
		$bakvers = array_keys($confvers);
1375
		$toreturn = array();
1376
		sort($bakvers);
1377
		// $bakvers = array_reverse($bakvers);
1378
		foreach(array_reverse($bakvers) as $bakver) $toreturn[] = array('time' => $bakver,
1379
								 'description' => $confvers[$bakver]['description']
1380
								);
1381
        } else { 	 
1382
                return false; 	 
1383
        }
1384
	$toreturn['versions'] = $bakvers;
1385
        return $toreturn;
1386
}
1387

    
1388
function backup_config() {
1389
	global $config, $g;
1390

    
1391
	if($g['platform'] == "cdrom")
1392
		return;
1393

    
1394
	conf_mount_rw();
1395

    
1396
	/* Create backup directory if needed */
1397
	safe_mkdir("{$g['cf_conf_path']}/backup");
1398

    
1399
        if($config['revision']['time'] == "") {
1400
                $baktime = 0;
1401
        } else {
1402
                $baktime = $config['revision']['time'];
1403
        }
1404
        if($config['revision']['description'] == "") {
1405
                $bakdesc = "Unknown";
1406
        } else {
1407
                $bakdesc = $config['revision']['description'];
1408
        }
1409
        copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1410
        if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1411
                $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1412
        } else {
1413
                $backupcache = array();
1414
        }
1415
        $backupcache[$baktime] = array('description' => $bakdesc);
1416
        $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1417
        fwrite($bakout, serialize($backupcache));
1418
        fclose($bakout);
1419
	
1420
	conf_mount_ro();
1421
	
1422
	return true;
1423
}
1424

    
1425
function mute_kernel_msgs() {
1426
	exec("/sbin/conscontrol mute on");
1427
}
1428

    
1429
function unmute_kernel_msgs() {
1430
	exec("/sbin/conscontrol mute off");
1431
}
1432

    
1433
function start_devd() {
1434
	exec("/sbin/devd");
1435
}
1436

    
1437
?>
(5-5/27)