Project

General

Profile

Download (41.6 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-2006 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
		log_error("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
		conf_mount_rw();	
76
		$fd = fopen("/cf/conf/config.xml", "w");
77
		fwrite($fd, $config_contents);
78
		fclose($fd);
79
		conf_mount_ro();
80
		echo "done.";
81
	}
82
}
83

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

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

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

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

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

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

    
139
					if ($cfgdevice)
140
						break;
141
				}
142
			}
143
		}
144

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

    
149

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

    
156

    
157
EOD;
158

    
159
			mwexec("/sbin/halt");
160
			exit;
161
		}
162

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

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

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

    
174
		fwrite($fd, $fstab);
175
		fclose($fd);
176
	}
177

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

    
182
$config = parse_config();
183

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

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

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

    
228
	return $config;
229
}
230

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

    
249
function discover_last_backup() {
250
        $backups = split("\n", `cd /cf/conf/backup && ls -lat | awk '{print \$9}' | grep -v "\\.\\."`);
251
		$last_backup = "";
252
        foreach($backups as $backup)
253
                if($backup)
254
                        $last_backup = $backup;
255
        return $last_backup;
256
}
257

    
258
function restore_backup($file) {
259
	if(file_exists($file)) {
260
		conf_mount_rw();
261
		system("mv $file /cf/conf/config.xml");
262
	}
263
}
264

    
265
/****f* config/parse_config_bootup
266
 * NAME
267
 *   parse_config_bootup - Bootup-specific configuration checks.
268
 * RESULT
269
 *   null
270
 ******/
271
function parse_config_bootup() {
272
	global $config, $g, $noparseconfig;
273
	if (!$noparseconfig) {
274
		if (!file_exists("{$g['conf_path']}/config.xml")) {
275
			config_lock();
276
			if ($g['booting']) {
277
				if (strstr($g['platform'], "cdrom")) {
278
					/* try copying the default config. to the floppy */
279
					echo "Resetting factory defaults...\n";
280
					reset_factory_defaults();
281
					if (file_exists("{$g['conf_path']}/config.xml")) {
282
						/* do nothing, we have a file. */
283
					} else {
284
						echo "No XML configuration file found - using factory defaults.\n";
285
						echo "Make sure that the configuration floppy disk with the conf/config.xml\n";
286
						echo "file is inserted. If it isn't, your configuration changes will be lost\n";
287
						echo "on reboot.\n";
288
					}
289
				} else {
290
					$last_backup = discover_last_backup();
291
					if($last_backup) {
292
						log_error("No config.xml found, attempting last known config restore.");
293
						restore_backup("/cf/conf/backup/{$last_backup}");
294
					}
295
					if(!file_exists("{$g['conf_path']}/config.xml")) {
296
						echo "XML configuration file not found.  pfSense cannot continue booting.\n";
297
						mwexec("/sbin/halt");
298
						exit;
299
					}
300
					log_error("Last known config found and restored.  Please double check your configuration file for accuracy.");
301
				}
302
			} else {
303
				config_unlock();
304
				exit(0);
305
			}
306
		}
307
	}
308
	
309
	parse_config(true);
310
	
311
	if ((float)$config['version'] > (float)$g['latest_config']) {
312
		echo <<<EOD
313

    
314

    
315
*******************************************************************************
316
* WARNING!                                                                    *
317
* The current configuration has been created with a newer version of pfSense  *
318
* than this one! This can lead to serious misbehavior and even security       *
319
* holes! You are urged to either upgrade to a newer version of pfSense or     *
320
* revert to the default configuration immediately!                            *
321
*******************************************************************************
322

    
323

    
324
EOD;
325
		}
326

    
327
	/* make alias table (for faster lookups) */
328
	alias_make_table($config);
329
	config_unlock();
330
}
331

    
332
/****f* config/conf_mount_rw
333
 * NAME
334
 *   conf_mount_rw - Mount filesystems read/write.
335
 * RESULT
336
 *   null
337
 ******/
338
/* mount flash card read/write */
339
function conf_mount_rw() {
340
	global $g;
341

    
342
	/* do not mount on cdrom platform */
343
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
344
		return;
345

    
346
	$status = mwexec("/sbin/umount -f {$g['cf_path']}");
347
	$status = mwexec("/sbin/mount -w {$g['cf_path']}");
348
	if($status <> 0) {
349
		mwexec("/sbin/fsck -y {$g['cf_path']}");
350
		$status = mwexec("/sbin/mount -w {$g['cf_path']}");
351
	}
352

    
353
	/*    if the platform is soekris or wrap or pfSense, lets mount the
354
	 *    compact flash cards root.
355
         */
356
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx"
357
	   or $g['platform'] == "embedded") {
358
		$status = mwexec("/sbin/mount -w /");
359
		/* we could not mount this correctly.  kick off fsck */
360
		if($status <> 0) {
361
			log_error("File system is dirty.  Launching FSCK for /");
362
			mwexec("/sbin/fsck -y");
363
			$status = mwexec("/sbin/mount -w /");
364
		}
365
	}
366
	
367
	usleep(100);
368
	
369
}
370

    
371
/****f* config/conf_mount_ro
372
 * NAME         
373
 *   conf_mount_ro - Mount filesystems readonly.
374
 * RESULT
375
 *   null        
376
 ******/
377
function conf_mount_ro() {
378
	global $g;
379

    
380
	if($g['booting'] == true)
381
		return;
382
	
383
	/* do not umount if generating ssh keys */
384
	if(file_exists("/tmp/keys_generating"))
385
		return;
386
	
387
	/* do not umount on cdrom or pfSense platforms */
388
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
389
		return;
390

    
391
	/* sync data, then force a umount the remount of /cf */
392
	mwexec("/bin/sync");
393
	mwexec("/bin/sync");
394
	mwexec("/sbin/umount -f {$g['cf_path']}");
395
	mwexec("/sbin/mount -r {$g['cf_path']}");
396
	mwexec("/bin/sync");
397
	mwexec("/bin/sync");
398
	mwexec("/sbin/mount -r /");
399
	
400
	usleep(100);
401

    
402
}
403

    
404
/****f* config/convert_config
405
 * NAME         
406
 *   convert_config - Attempt to update config.xml.
407
 * DESCRIPTION
408
 *   convert_config() reads the current global configuration
409
 *   and attempts to convert it to conform to the latest
410
 *   config.xml version. This allows major formatting changes
411
 *   to be made with a minimum of breakage.
412
 * RESULT
413
 *   null        
414
 ******/
415
/* convert configuration, if necessary */
416
function convert_config() {
417
	global $config, $g;
418

    
419
	if ($config['version'] == $g['latest_config'])
420
		return;		/* already at latest version */
421

    
422
	// Save off config version
423
	$prev_version = $config['version'];
424

    
425
	/* convert 1.0 -> 1.1 */
426
	if ($config['version'] == "1.0") {
427
		$opti = 1;
428
		$ifmap = array('lan' => 'lan', 'wan' => 'wan', 'pptp' => 'pptp');
429

    
430
		/* convert DMZ to optional, if necessary */
431
		if (isset($config['interfaces']['dmz'])) {
432

    
433
			$dmzcfg = &$config['interfaces']['dmz'];
434

    
435
			if ($dmzcfg['if']) {
436
				$config['interfaces']['opt' . $opti] = array();
437
				$optcfg = &$config['interfaces']['opt' . $opti];
438

    
439
				$optcfg['enable'] = $dmzcfg['enable'];
440
				$optcfg['descr'] = "DMZ";
441
				$optcfg['if'] = $dmzcfg['if'];
442
				$optcfg['ipaddr'] = $dmzcfg['ipaddr'];
443
				$optcfg['subnet'] = $dmzcfg['subnet'];
444

    
445
				$ifmap['dmz'] = "opt" . $opti;
446
				$opti++;
447
			}
448

    
449
			unset($config['interfaces']['dmz']);
450
		}
451

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

    
455
			if (!$config['interfaces']['wlan' . $i]['if']) {
456
				unset($config['interfaces']['wlan' . $i]);
457
				continue;
458
			}
459

    
460
			$wlancfg = &$config['interfaces']['wlan' . $i];
461
			$config['interfaces']['opt' . $opti] = array();
462
			$optcfg = &$config['interfaces']['opt' . $opti];
463

    
464
			$optcfg['enable'] = $wlancfg['enable'];
465
			$optcfg['descr'] = "WLAN" . $i;
466
			$optcfg['if'] = $wlancfg['if'];
467
			$optcfg['ipaddr'] = $wlancfg['ipaddr'];
468
			$optcfg['subnet'] = $wlancfg['subnet'];
469
			$optcfg['bridge'] = $wlancfg['bridge'];
470

    
471
			$optcfg['wireless'] = array();
472
			$optcfg['wireless']['mode'] = $wlancfg['mode'];
473
			$optcfg['wireless']['ssid'] = $wlancfg['ssid'];
474
			$optcfg['wireless']['channel'] = $wlancfg['channel'];
475
			$optcfg['wireless']['wep'] = $wlancfg['wep'];
476

    
477
			$ifmap['wlan' . $i] = "opt" . $opti;
478

    
479
			unset($config['interfaces']['wlan' . $i]);
480
			$opti++;
481
		}
482

    
483
		/* convert filter rules */
484
		$n = count($config['filter']['rule']);
485
		for ($i = 0; $i < $n; $i++) {
486

    
487
			$fr = &$config['filter']['rule'][$i];
488

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

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

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

    
527
		/* convert shaper rules */
528
		$n = count($config['pfqueueing']['rule']);
529
		if (is_array($config['pfqueueing']['rule']))
530
			for ($i = 0; $i < $n; $i++) {
531

    
532
			$fr = &$config['pfqueueing']['rule'][$i];
533

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

    
545
			/* remap source network */
546
			if (isset($fr['source']['network'])) {
547
				if (array_key_exists($fr['source']['network'], $ifmap))
548
					$fr['source']['network'] = $ifmap[$fr['source']['network']];
549
				else {
550
					/* remove the rule */
551
					echo "\nWarning: traffic shaper rule removed " .
552
						"(source network '{$fr['source']['network']}' does not exist anymore).";
553
					unset($config['pfqueueing']['rule'][$i]);
554
					continue;
555
				}
556
			}
557

    
558
			/* remap destination network */
559
			if (isset($fr['destination']['network'])) {
560
				if (array_key_exists($fr['destination']['network'], $ifmap))
561
					$fr['destination']['network'] = $ifmap[$fr['destination']['network']];
562
				else {
563
					/* remove the rule */
564
					echo "\nWarning: traffic shaper rule removed " .
565
						"(destination network '{$fr['destination']['network']}' does not exist anymore).";
566
					unset($config['pfqueueing']['rule'][$i]);
567
					continue;
568
				}
569
			}
570
		}
571

    
572
		$config['version'] = "1.1";
573
	}
574

    
575
	/* convert 1.1 -> 1.2 */
576
	if ($config['version'] == "1.1") {
577
		/* move LAN DHCP server config */
578
		$tmp = $config['dhcpd'];
579
		$config['dhcpd'] = array();
580
		$config['dhcpd']['lan'] = $tmp;
581

    
582
		/* encrypt password */
583
		$config['system']['password'] = crypt($config['system']['password']);
584

    
585
		$config['version'] = "1.2";
586
	}
587

    
588
	/* convert 1.2 -> 1.3 */
589
	if ($config['version'] == "1.2") {
590
		/* convert advanced outbound NAT config */
591
		for ($i = 0; isset($config['nat']['advancedoutbound']['rule'][$i]); $i++) {
592
			$curent = &$config['nat']['advancedoutbound']['rule'][$i];
593
			$src = $curent['source'];
594
			$curent['source'] = array();
595
			$curent['source']['network'] = $src;
596
			$curent['destination'] = array();
597
			$curent['destination']['any'] = true;
598
		}
599

    
600
		/* add an explicit type="pass" to all filter rules to make things consistent */
601
		for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
602
			$config['filter']['rule'][$i]['type'] = "pass";
603
		}
604

    
605
		$config['version'] = "1.3";
606
	}
607

    
608
	/* convert 1.3 -> 1.4 */
609
	if ($config['version'] == "1.3") {
610
		/* convert shaper rules (make pipes) */
611
		if (is_array($config['pfqueueing']['rule'])) {
612
			$config['pfqueueing']['pipe'] = array();
613

    
614
			for ($i = 0; isset($config['pfqueueing']['rule'][$i]); $i++) {
615
				$curent = &$config['pfqueueing']['rule'][$i];
616

    
617
				/* make new pipe and associate with this rule */
618
				$newpipe = array();
619
				$newpipe['descr'] = $curent['descr'];
620
				$newpipe['bandwidth'] = $curent['bandwidth'];
621
				$newpipe['delay'] = $curent['delay'];
622
				$newpipe['mask'] = $curent['mask'];
623
				$config['pfqueueing']['pipe'][$i] = $newpipe;
624

    
625
				$curent['targetpipe'] = $i;
626

    
627
				unset($curent['bandwidth']);
628
				unset($curent['delay']);
629
				unset($curent['mask']);
630
			}
631
		}
632

    
633
		$config['version'] = "1.4";
634
	}
635

    
636
	/* Convert 1.4 -> 1.5 */
637
	if ($config['version'] == "1.4") {
638

    
639
		/* Default route moved */
640
		if (isset($config['interfaces']['wan']['gateway']))
641
			if ($config['interfaces']['wan']['gateway'] <> "")
642
				$config['interfaces']['wan']['gateway'] = $config['interfaces']['wan']['gateway'];
643
		unset($config['interfaces']['wan']['gateway']);
644

    
645
                /* Queues are no longer interface specific */
646
                if (isset($config['interfaces']['lan']['schedulertype']))
647
                        unset($config['interfaces']['lan']['schedulertype']);
648
                if (isset($config['interfaces']['wan']['schedulertype']))
649
                        unset($config['interfaces']['wan']['schedulertype']);
650

    
651
                for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
652
                        if(isset($config['interfaces']['opt' . $i]['schedulertype']))
653
                                unset($config['interfaces']['opt' . $i]['schedulertype']);
654
                }
655

    
656
		$config['version'] = "1.5";
657
	}
658

    
659
	/* Convert 1.5 -> 1.6 */
660
	if ($config['version'] == "1.5") {
661
		/* Alternate firmware URL moved */
662
		if (isset($config['system']['firmwareurl']) && isset($config['system']['firmwarename'])) { // Only convert if *both* are defined.
663
			$config['system']['alt_firmware_url'] = array();
664
			$config['system']['alt_firmware_url']['enabled'] = "";
665
			$config['system']['alt_firmware_url']['firmware_base_url'] = $config['system']['firmwareurl'];
666
			$config['system']['alt_firmware_url']['firmware_filename'] = $config['system']['firmwarename'];
667
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
668
		} else {
669
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
670
		}
671

    
672
		$config['version'] = "1.6";
673
	}
674
	
675
	/* Convert 1.6 -> 1.7 */
676
	if ($config['version'] == "1.6") {
677
		/* wipe previous shaper configuration */
678
		unset($config['shaper']['queue']);
679
		unset($config['shaper']['rule']);
680
		unset($config['interfaces']['wan']['bandwidth']);
681
		unset($config['interfaces']['wan']['bandwidthtype']);
682
		unset($config['interfaces']['lan']['bandwidth']);
683
		unset($config['interfaces']['lan']['bandwidthtype']);		
684
		$config['shaper']['enable'] = FALSE;
685
		$config['version'] = "1.7";	
686
	}
687
	/* Convert 1.7 -> 1.8 */
688
	if ($config['version'] == "1.7") {
689
		if(isset($config['proxyarp']) && is_array($config['proxyarp']['proxyarpnet'])) {
690
			$proxyarp = &$config['proxyarp']['proxyarpnet'];
691
			foreach($proxyarp as $arpent){
692
				$vip = array();
693
				$vip['mode'] = "proxyarp";
694
				$vip['interface'] = $arpent['interface'];
695
				$vip['descr'] = $arpent['descr'];
696
				if (isset($arpent['range'])) {
697
					$vip['range'] = $arpent['range'];
698
					$vip['type'] = "range";
699
				} else {
700
					$subnet = explode('/', $arpent['network']);
701
					$vip['subnet'] = $subnet[0];
702
					if (isset($subnet[1])) {
703
						$vip['subnet_bits'] = $subnet[1];
704
						$vip['type'] = "network";
705
					} else {
706
						$vip['subnet_bits'] = "32";
707
						$vip['type'] = "single";
708
					}
709
				}
710
				$config['virtualip']['vip'][] = $vip;
711
			}
712
			unset($config['proxyarp']);
713
		}
714
		if(isset($config['installedpackages']) && isset($config['installedpackages']['carp']) && is_array($config['installedpackages']['carp']['config'])) {
715
			$carp = &$config['installedpackages']['carp']['config'];
716
			foreach($carp as $carpent){
717
				$vip = array();
718
				$vip['mode'] = "carp";
719
				$vip['interface'] = "AUTO";
720
				$vip['descr'] = "CARP vhid {$carpent['vhid']}";
721
				$vip['type'] = "single";
722
				$vip['vhid'] = $carpent['vhid'];
723
				$vip['advskew'] = $carpent['advskew'];
724
				$vip['password'] = $carpent['password'];
725
				$vip['subnet'] = $carpent['ipaddress'];
726
				$vip['subnet_bits'] = $carpent['netmask'];
727
				$config['virtualip']['vip'][] = $vip;
728
			}
729
			unset($config['installedpackages']['carp']);
730
		}
731
		/* Server NAT is no longer needed */
732
		unset($config['nat']['servernat']);
733
		
734
		/* enable SSH */
735
		if ($config['version'] == "1.8") {
736
			$config['system']['sshenabled'] = true;
737
		}
738
		
739
		$config['version'] = "1.9";
740
	}
741

    
742
	/* Convert 1.8 -> 1.9 */
743
	if ($config['version'] == "1.8") {
744
		$config['theme']="metallic";
745
		$config['version'] = "1.9";
746
	}
747
	/* Convert 1.9 -> 2.0 */
748
	if ($config['version'] == "1.9") {
749
		if(is_array($config['ipsec']['tunnel'])) {
750
			reset($config['ipsec']['tunnel']);
751
			while (list($index, $tunnel) = each($config['ipsec']['tunnel'])) {
752
				/* Sanity check on required variables */
753
				/* This fixes bogus <tunnel> entries - remnant of bug #393 */
754
				if (!isset($tunnel['local-subnet']) && !isset($tunnel['remote-subnet'])) {
755
					unset($config['ipsec']['tunnel'][$tunnel]);
756
				}
757
			}
758
        	}
759
		$config['version'] = "2.0";
760
	}
761
	/* Convert 2.0 -> 2.1 */
762
	if ($config['version'] == "2.0") {
763
		/* shaper scheduler moved */
764
		if(isset($config['system']['schedulertype'])) {
765
			$config['shaper']['schedulertype'] = $config['system']['schedulertype'];
766
			unset($config['system']['schedulertype']);
767
		}
768
		$config['version'] = "2.1";
769
	}
770
	/* Convert 2.1 -> 2.2 */
771
	if ($config['version'] == "2.1") {
772
		/* move gateway to wan interface */
773
		$config['interfaces']['wan']['gateway'] = $config['system']['gateway'];
774
		$config['version'] = "2.2";
775
	}
776
	/* Convert 2.2 -> 2.3 */
777
	if ($config['version'] == "2.2") {
778
		if(isset($config['shaper'])) {
779
			/* wipe previous shaper configuration */
780
			unset($config['shaper']);
781
		}
782
		$config['version'] = "2.3";
783
	}
784

    
785
	if ($prev_version != $config['version'])
786
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
787
}
788

    
789
/****f* config/write_config
790
 * NAME
791
 *   write_config - Backup and write the firewall configuration.
792
 * DESCRIPTION
793
 *   write_config() handles backing up the current configuration,
794
 *   applying changes, and regenerating the configuration cache.
795
 * INPUTS
796
 *   $desc	- string containing the a description of configuration changes
797
 *   $backup	- boolean: do not back up current configuration if false.
798
 * RESULT
799
 *   null       
800
 ******/
801
/* save the system configuration */
802
function write_config($desc="Unknown", $backup = true) {
803
	global $config, $g;
804

    
805
	if($backup) 
806
		backup_config();
807

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

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

    
815
	$config['revision']['description'] = $desc;
816
	$config['revision']['time'] = $changetime;
817
	
818
	config_lock();
819

    
820
	/* generate configuration XML */
821
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
822

    
823
	conf_mount_rw();
824

    
825
	/* write new configuration */
826
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
827
	if (!$fd)
828
		die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
829
	fwrite($fd, $xmlconfig);
830
	fclose($fd);
831

    
832
	if($g['platform'] == "embedded") {
833
		/*   backup last config.xml and remove all others to avoid
834
		 *   filling up the compact flash dedicated config partition
835
		 */
836
		$last_backup = discover_last_backup();
837
		mwexec("/bin/mv /cf/conf/backup/{$last_backup} /tmp/lastconfig.xml");
838
		mwexec("/bin/rm /cf/conf/backup/*");
839
		mwexec("/bin/mv /tmp/lastconfig.xml /cf/conf/backup/{$last_backup}");
840
	}
841

    
842
	if($g['booting'] <> true) {
843
		conf_mount_ro();
844
	}
845

    
846
	config_unlock();
847

    
848
	// Always reparse the config after it's written - something is getting lost in serialize().
849
	$config = parse_config(true);
850
	return $config;
851
}
852

    
853
/****f* config/reset_factory_defaults
854
 * NAME
855
 *   reset_factory_defaults - Reset the system to its default configuration.
856
 * RESULT
857
 *   integer	- indicates completion
858
 ******/
859
function reset_factory_defaults() {
860
	global $g;
861

    
862
	config_lock();
863
	conf_mount_rw();
864

    
865
	/* create conf directory, if necessary */
866
	safe_mkdir("{$g['cf_conf_path']}");
867

    
868
	/* clear out /conf */
869
	$dh = opendir($g['conf_path']);
870
	while ($filename = readdir($dh)) {
871
		if (($filename != ".") && ($filename != "..")) {
872
			unlink_if_exists($g['conf_path'] . "/" . $filename);
873
		}
874
	}
875
	closedir($dh);
876

    
877
	/* copy default configuration */
878
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
879
	
880
	/* call the wizard */
881
	touch("/conf/trigger_initial_wizard");
882
	
883
	conf_mount_ro();
884
	config_unlock();
885

    
886
	return 0;
887
}
888

    
889
function config_restore($conffile) {
890
	global $config, $g;
891
       
892
	if (!file_exists($conffile))
893
		return 1;
894
        
895
    config_lock();
896
    conf_mount_rw();        
897
    
898
    backup_config();
899
    copy($conffile, "{$g['cf_conf_path']}/config.xml");
900
	$config = parse_config(true);
901
    write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
902
    
903
    conf_mount_ro();
904
    config_unlock();
905

    
906
    return 0;
907
}
908

    
909
function config_install($conffile) {
910
	global $config, $g;
911
        
912
	if (!file_exists($conffile))
913
		return 1;
914

    
915
	if (!config_validate($conffile))
916
		return 1;
917

    
918
	if($g['booting'] == true)
919
		echo "Installing configuration...\n";
920
 
921
    config_lock();
922
    conf_mount_rw();
923
	
924
    copy($conffile, "{$g['conf_path']}/config.xml");
925

    
926
	/* unlink cache file if it exists */
927
	if(file_exists("{$g['tmp_path']}/config.cache"))
928
		unlink("{$g['tmp_path']}/config.cache");
929
  
930
    conf_mount_ro();
931
    config_unlock();
932

    
933
    return 0;
934
}
935

    
936
function config_validate($conffile) {
937

    
938
	global $g, $xmlerr;
939

    
940
	$xml_parser = xml_parser_create();
941
	
942
	if (!($fp = fopen($conffile, "r"))) {
943
		$xmlerr = "XML error: unable to open file";
944
		return false;
945
	}
946
	
947
	while ($data = fread($fp, 4096)) {
948
		if (!xml_parse($xml_parser, $data, feof($fp))) {
949
			$xmlerr = sprintf("%s at line %d",
950
						xml_error_string(xml_get_error_code($xml_parser)),
951
						xml_get_current_line_number($xml_parser));
952
			return false;
953
		}
954
	}
955
	xml_parser_free($xml_parser);
956
	
957
	fclose($fp);
958
	
959
	return true;
960
}
961

    
962
/*   lock configuration file, decide that the lock file 
963
 *   is stale after 10 seconds 
964
 */
965
function config_lock() {
966
	global $g, $process_lock;
967

    
968
	/* No need to continue if we're the ones holding the lock */
969
	if ($process_lock)
970
		return;
971

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

    
974
	$n = 0;
975
	while ($n < 10) {
976
		/* open the lock file in append mode to avoid race condition */
977
		if ($fd = @fopen($lockfile, "x")) {
978
			/* succeeded */
979
			$process_lock = true;
980
			fclose($fd);
981
			return;
982
		} else {
983
			/* file locked, wait and try again */
984
			$process_lock = false;
985
			sleep(1);
986
			$n++;
987
		}
988
	}
989
}
990

    
991
/* unlock configuration file */
992
function config_unlock() {
993
	global $g, $process_lock;
994

    
995
	$lockfile = "{$g['varrun_path']}/config.lock";
996
	$process_lock = false;
997

    
998
	unlink_if_exists($lockfile);
999
}
1000

    
1001
function set_networking_interfaces_ports() {
1002
	global $noreboot;
1003
	global $config;
1004
	global $g;
1005
	global $fp;
1006

    
1007
	$fp = fopen('php://stdin', 'r');
1008

    
1009
	$iflist = get_interface_list();
1010

    
1011
	echo <<<EOD
1012

    
1013
Valid interfaces are:
1014

    
1015

    
1016
EOD;
1017

    
1018
	if(!is_array($iflist)) {
1019
		echo "No interfaces found!\n";
1020
	} else {
1021
		foreach ($iflist as $iface => $ifa) {
1022
			echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
1023
				$ifa['up'] ? "   (up)" : "");
1024
		}
1025
	}
1026

    
1027
	echo <<<EOD
1028

    
1029
Do you want to set up VLANs first?
1030
If you are not going to use VLANs, or only for optional interfaces, you should 
1031
say no here and use the webConfigurator to configure VLANs later, if required.
1032

    
1033
Do you want to set up VLANs now [y|n]?
1034
EOD;
1035

    
1036
	if (strcasecmp(chop(fgets($fp)), "y") == 0)
1037
		vlan_setup();
1038

    
1039
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1040

    
1041
		echo "\n\nVLAN interfaces:\n\n";
1042
		$i = 0;
1043
		foreach ($config['vlans']['vlan'] as $vlan) {
1044

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

    
1048
			$iflist['vlan' . $i] = array();
1049
			$i++;
1050
		}
1051
	}
1052

    
1053
	echo <<<EOD
1054

    
1055
*NOTE*  pfSense requires *ATLEAST* 2 assigned interfaces to function.
1056
        If you do not have two interfaces turn off the machine until
1057
	you do.
1058

    
1059
If you do not know the names of your interfaces, you may choose to use
1060
auto-detection... In that case, disconnect all interfaces now before
1061
hitting a.   The system will then prompt you to plug in each nic to
1062
autodetect.
1063

    
1064
EOD;
1065

    
1066
	do {
1067
		echo "\nEnter the LAN interface name or 'a' for auto-detection: ";
1068
		$lanif = chop(fgets($fp));
1069
		if ($lanif === "") {
1070
			return;
1071
		}
1072

    
1073
		if ($lanif === "a")
1074
			$lanif = autodetect_interface("LAN", $fp);
1075
		else if (!array_key_exists($lanif, $iflist)) {
1076
			echo "\nInvalid interface name '{$lanif}'\n";
1077
			unset($lanif);
1078
			continue;
1079
		}
1080
	} while (!$lanif);
1081

    
1082
	do {
1083
		echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
1084
		$wanif = chop(fgets($fp));
1085
		if ($wanif === "") {
1086
			return;
1087
		}
1088
		if ($wanif === "a")
1089
			$wanif = autodetect_interface("WAN", $fp);
1090
		else if (!array_key_exists($wanif, $iflist)) {
1091
			echo "\nInvalid interface name '{$wanif}'\n";
1092
			unset($wanif);
1093
			continue;
1094
		}
1095
	} while (!$wanif);
1096

    
1097
	/* optional interfaces */
1098
	$i = 0;
1099
	$optif = array();
1100

    
1101
	while (1) {
1102
		if ($optif[$i])
1103
			$i++;
1104
		$i1 = $i + 1;
1105
		
1106
		if($config['interfaces']['opt' . $i1]['descr']) 
1107
			echo "\nOptional interface {$i1} description found: {$config['interfaces']['opt' . $i1]['descr']}";
1108
		
1109
		echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
1110
			"(or nothing if finished): ";
1111
		
1112
		$optif[$i] = chop(fgets($fp));
1113

    
1114
		if ($optif[$i]) {
1115
			if ($optif[$i] === "a") {
1116
				$ad = autodetect_interface("Optional " . $i1, $fp);
1117
				if ($ad)
1118
					$optif[$i] = $ad;
1119
				else
1120
					unset($optif[$i]);
1121
			} else if (!array_key_exists($optif[$i], $iflist)) {
1122
				echo "\nInvalid interface name '{$optif[$i]}'\n";
1123
				unset($optif[$i]);
1124
				continue;
1125
			}
1126
		} else {
1127
			unset($optif[$i]);
1128
			break;
1129
		}
1130
	}
1131

    
1132
	/* check for double assignments */
1133
	$ifarr = array_merge(array($lanif, $wanif), $optif);
1134

    
1135
	for ($i = 0; $i < (count($ifarr)-1); $i++) {
1136
		for ($j = ($i+1); $j < count($ifarr); $j++) {
1137
			if ($ifarr[$i] == $ifarr[$j]) {
1138
				echo <<<EOD
1139

    
1140
Error: you cannot assign the same interface name twice!
1141

    
1142
EOD;
1143

    
1144
				return;
1145
			}
1146
		}
1147
	}
1148

    
1149
	echo <<<EOD
1150

    
1151
The interfaces will be assigned as follows:
1152

    
1153
LAN  -> {$lanif}
1154
WAN  -> {$wanif}
1155

    
1156
EOD;
1157

    
1158
	for ($i = 0; $i < count($optif); $i++) {
1159
		echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
1160
	}
1161

    
1162
echo <<<EOD
1163

    
1164
Do you want to proceed [y|n]?
1165
EOD;
1166

    
1167
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
1168

    
1169
		$config['interfaces']['lan']['if'] = $lanif;
1170
		if (preg_match($g['wireless_regex'], $lanif)) {
1171
			if (!is_array($config['interfaces']['lan']['wireless']))
1172
				$config['interfaces']['lan']['wireless'] = array();
1173
		} else {
1174
			unset($config['interfaces']['lan']['wireless']);
1175
		}
1176
		
1177
		$config['interfaces']['wan']['if'] = $wanif;
1178
		if (preg_match($g['wireless_regex'], $wanif)) {
1179
			if (!is_array($config['interfaces']['wan']['wireless']))
1180
				$config['interfaces']['wan']['wireless'] = array();
1181
		} else {
1182
			unset($config['interfaces']['wan']['wireless']);
1183
		}
1184
		
1185
		for ($i = 0; $i < count($optif); $i++) {
1186
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
1187
				$config['interfaces']['opt' . ($i+1)] = array();
1188
			
1189
			$config['interfaces']['opt' . ($i+1)]['if'] = $optif[$i];
1190
			
1191
			/* wireless interface? */
1192
			if (preg_match($g['wireless_regex'], $optif[$i])) {
1193
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
1194
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
1195
			} else {
1196
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
1197
			}
1198
			
1199
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
1200
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
1201
		}
1202
		
1203
		/* remove all other (old) optional interfaces */
1204
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
1205
			unset($config['interfaces']['opt' . ($i+1)]);
1206
		
1207
		write_config();
1208
		
1209
		echo <<<EOD
1210

    
1211

    
1212

    
1213
EOD;
1214

    
1215
		if($g['booting'])
1216
			return;
1217

    
1218
		echo "One moment while we reload the settings...";
1219

    
1220
		$g['booting'] = false;
1221

    
1222
		/* resync everything */
1223
		reload_all_sync();
1224
		
1225
		echo " done!\n";
1226
		
1227
		touch("{$g['tmp_path']}/assign_complete");
1228

    
1229
	}
1230
}
1231

    
1232
function autodetect_interface($ifname, $fp) {
1233
	$iflist_prev = get_interface_list("media");
1234
	echo <<<EOD
1235

    
1236
Connect the {$ifname} interface now and make sure that the link is up.
1237
Then press ENTER to continue.
1238

    
1239
EOD;
1240
	fgets($fp);
1241
	$iflist = get_interface_list("media");
1242

    
1243
	foreach ($iflist_prev as $ifn => $ifa) {
1244
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1245
			echo "Detected link-up on interface {$ifn}.\n";
1246
			return $ifn;
1247
		}
1248
	}
1249

    
1250
	echo "No link-up detected.\n";
1251

    
1252
	return null;
1253
}
1254

    
1255
function vlan_setup() {
1256
	global $iflist, $config, $g, $fp;
1257

    
1258
	$iflist = get_interface_list();
1259

    
1260
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1261

    
1262
	echo <<<EOD
1263

    
1264
WARNING: all existing VLANs will be cleared if you proceed!
1265

    
1266
Do you want to proceed [y|n]?
1267
EOD;
1268

    
1269
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1270
		return;
1271
	}
1272

    
1273
	$config['vlans']['vlan'] = array();
1274
	echo "\n";
1275

    
1276
	while (1) {
1277
		$vlan = array();
1278

    
1279
		echo "\n\nVLAN Capable interfaces:\n\n";
1280
		if(!is_array($iflist)) {
1281
			echo "No interfaces found!\n";
1282
		} else {
1283
			$vlan_capable=0;
1284
			foreach ($iflist as $iface => $ifa) {
1285
				if (is_jumbo_capable($iface)) {
1286
					echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
1287
						$ifa['up'] ? "   (up)" : "");
1288
					$vlan_capable++;
1289
				}
1290
			}
1291
		}
1292

    
1293
		if($vlan_capable == 0) {
1294
			echo "No VLAN capable interfaces detected.\n";
1295
			return;
1296
		}
1297

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

    
1301
		if ($vlan['if']) {
1302
			if (!array_key_exists($vlan['if'], $iflist) or
1303
			    !is_jumbo_capable($vlan['if'])) {
1304
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1305
				continue;
1306
			}
1307
		} else {
1308
			break;
1309
		}
1310

    
1311
		echo "Enter the VLAN tag (1-4094): ";
1312
		$vlan['tag'] = chop(fgets($fp));
1313

    
1314
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1315
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1316
			continue;
1317
		}
1318

    
1319
		$config['vlans']['vlan'][] = $vlan;
1320
	}
1321
}
1322

    
1323
function system_start_ftp_helpers() {
1324
	require_once("interfaces.inc");
1325
	global $config, $g;
1326
	
1327
	mwexec("/usr/bin/killall ftpsesame");
1328

    
1329
	/* build an array of interfaces to work with */
1330
	$iflist = array("lan" => "LAN");
1331
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
1332
		$iflist['opt' . $i] = "opt{$i}";
1333

    
1334
	/* loop through all interfaces and handle pftpx */
1335
	$interface_counter = 0;
1336
	foreach ($iflist as $ifent => $ifname) {
1337
		/*    if the ftp proxy is disabled for this interface then kill pftpx 
1338
		 *    instance and continue. note that the helpers for port forwards are 
1339
		 *    launched in a  different sequence so we are filtering them out 
1340
         *    here by not including -c {$port} -g 8021 first.
1341
		 */
1342
		$port = 8021 + $interface_counter;
1343
		if(isset($config['interfaces'][$ifname]['disableftpproxy'])) {
1344
			/*    item is disabled.  lets ++ the interface counter and
1345
			 *    keep processing interfaces. kill pftpx if already
1346
			 *    running for this instance.
1347
			 */
1348
			$helpers = exec("/bin/ps awux | grep \"/usr/local/sbin/pftpx -c {$port}\" | grep -v grep | sed \"s/  */ /g\" | cut -f2 -d\" \"");
1349
			if($helpers)
1350
				mwexec("/bin/kill {$helpers}");
1351
			$interface_counter++;
1352
		} else {
1353
			/* grab the current interface IP address */
1354
			$int = convert_friendly_interface_to_real_interface_name($ifname);
1355
			$ip = find_interface_ip($int);
1356
			/* if pftpx is already running then do not launch it again */
1357
			$helpers = exec("/bin/ps awux | grep \"/usr/local/sbin/pftpx -c {$port}\" | grep -v grep | sed \"s/  */ /g\"");
1358
			if(!$helpers && $ip)
1359
 				mwexec("/usr/local/sbin/pftpx -c {$port} -g 8021 {$ip}");
1360
			if(!$ip)
1361
				mwexec("/usr/local/sbin/ftpsesame -i $int");				
1362
			$interface_counter++;
1363
		}
1364
	}
1365
	/* support bridged interfaces.  even they need ftp mojo */
1366
	$num_bridges = find_number_of_created_bridges();
1367
	$num_bridges++;
1368
	for($x=0; $x<$num_bridges; $x++) {
1369
		mwexec("/usr/local/sbin/ftpsesame -i bridge{$x}");
1370
	}	
1371
}
1372

    
1373
function cleanup_backupcache($revisions = 30) {
1374
	global $g;
1375
	$i = false;
1376
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1377
		conf_mount_rw();
1378
		$backups = get_backups();
1379
		$newbaks = array();
1380
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1381
		$baktimes = $backups['versions'];
1382
		$tocache = array();
1383
		unset($backups['versions']);
1384
       		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1385
				$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));	
1386
                if(!in_array($tocheck, $baktimes)) {
1387
					$i = true;
1388
					if($g['booting']) 
1389
						print " " . $tocheck . "a";
1390
					$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1391
					if($newxml['revision']['description'] == "") 
1392
						$newxml['revision']['description'] = "Unknown";
1393
					$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1394
				}
1395
        	}
1396
		foreach($backups as $checkbak) {
1397
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1398
				$newbaks[] = $checkbak;
1399
			} else {
1400
				$i = true;
1401
				if($g['booting']) print " " . $tocheck . "r";
1402
			}
1403
		}
1404
		foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);	
1405
		if(is_int($revisions) and (count($tocache) > $revisions)) {
1406
			$toslice = array_slice(array_keys($tocache), 0, $revisions);
1407
			foreach($toslice as $sliced) 
1408
				$newcache[$sliced] = $tocache[$sliced];
1409
			foreach($tocache as $version => $versioninfo) {
1410
				if(!in_array($version, array_keys($newcache))) {
1411
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1412
					if($g['booting']) print " " . $tocheck . "d";
1413
				}
1414
			}
1415
			$tocache = $newcache;
1416
		}
1417
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1418
        fwrite($bakout, serialize($tocache));
1419
		fclose($bakout);
1420
		conf_mount_ro();
1421
	}
1422
	if($g['booting']) {
1423
		if($i) {
1424
			print "done.\n";
1425
		}
1426
	}
1427
}
1428
  	 
1429
function get_backups() { 	 
1430
	global $g;
1431
	if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1432
		$confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1433
		$bakvers = array_keys($confvers);
1434
		$toreturn = array();
1435
		sort($bakvers);
1436
		// 	$bakvers = array_reverse($bakvers);
1437
		foreach(array_reverse($bakvers) as $bakver) 
1438
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description']);
1439
	} else { 	 
1440
		return false; 	 
1441
	}
1442
	$toreturn['versions'] = $bakvers;
1443
	return $toreturn;
1444
}
1445

    
1446
function backup_config() {
1447
	global $config, $g;
1448

    
1449
	if($g['platform'] == "cdrom")
1450
		return;
1451

    
1452
	conf_mount_rw();
1453

    
1454
	/* Create backup directory if needed */
1455
	safe_mkdir("{$g['cf_conf_path']}/backup");
1456

    
1457
    if($config['revision']['time'] == "") {
1458
            $baktime = 0;
1459
    } else {
1460
            $baktime = $config['revision']['time'];
1461
    }
1462
    if($config['revision']['description'] == "") {
1463
            $bakdesc = "Unknown";
1464
    } else {
1465
            $bakdesc = $config['revision']['description'];
1466
    }
1467
    copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1468
    if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1469
            $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1470
    } else {
1471
            $backupcache = array();
1472
    }
1473
    $backupcache[$baktime] = array('description' => $bakdesc);
1474
    $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1475
    fwrite($bakout, serialize($backupcache));
1476
    fclose($bakout);
1477
	
1478
	conf_mount_ro();
1479
	
1480
	return true;
1481
}
1482

    
1483
function mute_kernel_msgs() {
1484
	exec("/sbin/conscontrol mute on");
1485
}
1486

    
1487
function unmute_kernel_msgs() {
1488
	exec("/sbin/conscontrol mute off");
1489
}
1490

    
1491
function start_devd() {
1492
	exec("/sbin/devd");
1493
	sleep(1);
1494
	if(file_exists("/tmp/rc.linkup"))
1495
		unlink("/tmp/rc.linkup");	
1496
}
1497

    
1498
?>
(5-5/27)