Project

General

Profile

Download (44.1 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
if($g['booting']) echo ".";
42

    
43
/* do not load this file twice. */
44
if($config_inc_loaded == true)
45
	return;
46
else
47
	$config_inc_loaded = true;
48

    
49
/* include globals/utility/XML parser files */
50
require_once("globals.inc");
51
if($g['booting']) echo ".";
52
require_once("util.inc");
53
if($g['booting']) echo ".";
54
require_once("pfsense-utils.inc");
55
if($g['booting']) echo ".";
56
require_once("xmlparse.inc");
57

    
58
/* read platform */
59
if($g['booting']) echo ".";
60
if (file_exists("{$g['etc_path']}/platform")) {
61
	$g['platform'] = chop(file_get_contents("{$g['etc_path']}/platform"));
62
} else {
63
	$g['platform'] = "unknown";
64
}
65

    
66
/* if /debugging exists, lets set $debugging
67
   so we can output more information */
68
if(file_exists("/debugging")) {
69
	$debugging = true;
70
	$g['debug'] = true;
71
}
72

    
73
if($g['booting']) echo ".";
74
if(file_exists("/cf/conf/config.xml")) {
75
	$config_contents = file_get_contents("/cf/conf/config.xml");
76
	if(stristr($config_contents, "<m0n0wall>") == true) {
77
		if($g['booting']) echo ".";
78
		/* user has just upgraded to m0n0wall, replace root xml tags */
79
		log_error("Upgrading m0n0wall configuration to pfSense... ");
80
		$config_contents = str_replace("m0n0wall","pfsense", $config_contents);
81
		if (!config_validate("{$g['conf_path']}/config.xml"))
82
			log_error("ERROR!  Could not convert m0n0wall -> pfsense in config.xml");
83
		conf_mount_rw();
84
		$fd = fopen("/cf/conf/config.xml", "w");
85
		fwrite($fd, $config_contents);
86
		fclose($fd);
87
		conf_mount_ro();
88
	}
89
}
90

    
91
/* if our config file exists bail out, we're already set. */
92
if ($g['booting'] and !file_exists($g['cf_conf_path'] . "/config.xml")  ) {
93
	if($g['booting']) echo ".";
94
	/* find the device where config.xml resides and write out an fstab */
95
	unset($cfgdevice);
96
	if($g['booting']) echo ".";
97
	/* check if there's already an fstab (NFS booting?) */
98
	if (!file_exists("{$g['etc_path']}/fstab")) {
99
		if($g['booting']) echo ".";
100
		if (strstr($g['platform'], "cdrom")) {
101
			/* config is on floppy disk for CD-ROM version */
102
			$cfgdevice = $cfgpartition = "fd0";
103
			$dmesg = `dmesg -a`;
104
			if(ereg("da0", $dmesg) == true) {
105
				$cfgdevice = $cfgpartition = "da0" ;
106
				if (mwexec("/sbin/mount -r /dev/{$cfgdevice} /cf")) {
107
					/* could not mount, fallback to floppy */
108
					$cfgdevice = $cfgpartition = "fd0";
109
				}
110
			}
111
			$cfgfstype = "msdos";
112
			echo "CDROM build\n";
113
			echo "   CFG: {$cfgpartition}\n";
114
			echo "  TYPE: {$cfgfstype}\n";
115
		} else {
116
			if($g['booting']) echo ".";
117
			/* probe kernel known disks until we find one with config.xml */
118
			$disks = explode(" ", trim(preg_replace("/kern.disks: /", "", exec("/sbin/sysctl kern.disks"))));
119
			foreach ($disks as $mountdisk) {
120
				/* skip mfs mounted filesystems */
121
				if (strstr($mountdisk, "md"))
122
					continue;
123
				if (mwexec("/sbin/mount -r /dev/{$mountdisk}a {$g['cf_path']}") == 0) {
124
					if (file_exists("{$g['cf_conf_path']}/config.xml")) {
125
						/* found it */
126
						$cfgdevice = $mountdisk;
127
						$cfgpartition = $cfgdevice . "a";
128
						$cfgfstype = "ufs";
129
						echo "Found configuration on $cfgdevice.\n";
130
					}
131

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

    
134
					if ($cfgdevice)
135
						break;
136
				}
137
				if (mwexec("/sbin/mount -r /dev/{$mountdisk}d {$g['cf_path']}") == 0) {
138
					if($g['booting']) echo ".";
139
					if (file_exists("{$g['cf_conf_path']}/config.xml")) {
140
						/* found it */
141
						$cfgdevice = $mountdisk;
142
						$cfgpartition = $cfgdevice . "d";
143
						$cfgfstype = "ufs";
144
						echo "Found configuration on $cfgdevice.\n";
145
					}
146

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

    
149
					if ($cfgdevice)
150
						break;
151
				}
152
			}
153
		}
154
		if($g['booting']) echo ".";
155
		if (!$cfgdevice) {
156
			$last_backup = discover_last_backup();
157
			if($last_backup) {
158
				log_error("No config.xml found, attempting last known config restore.");
159
				restore_backup("/cf/conf/backup/{$last_backup}");
160
			} else {
161
				/* no device found, print an error and die */
162
				echo <<<EOD
163

    
164
*******************************************************************************
165
* FATAL ERROR                                                                 *
166
* The device that contains the configuration file (config.xml) could not be   *
167
* found. pfSense cannot continue booting.                                     *
168
*******************************************************************************
169

    
170

    
171
EOD;
172

    
173
				mwexec("/sbin/halt");
174
				exit;
175
			}
176
		}
177

    
178
		/* write device name to a file for rc.firmware */
179
		$fd = fopen("{$g['varetc_path']}/cfdevice", "w");
180
		fwrite($fd, $cfgdevice . "\n");
181
		fclose($fd);
182

    
183
		/* write out an fstab */
184
		$fd = fopen("{$g['etc_path']}/fstab", "w");
185

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

    
189
		fwrite($fd, $fstab);
190
		fclose($fd);
191
	}
192
	if($g['booting']) echo ".";
193
	/* mount all filesystems */
194
	mwexec("/sbin/mount -a");
195
}
196

    
197
/****f* config/parse_config
198
 * NAME
199
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
200
 * INPUTS
201
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
202
 * RESULT
203
 *   $config      - array containing all configuration variables
204
 ******/
205
function parse_config($parse = false) {
206
	global $g;
207
	if($g['booting']) echo ".";
208
	config_lock();
209
	if(!$parse) {
210
		if(file_exists($g['tmp_path'] . '/config.cache')) {
211
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
212
			if(is_null($config)) {
213
				config_unlock();
214
				parse_config(true);
215
			}
216
		} else {
217
			config_unlock();
218
			if(!file_exists($g['conf_path'] . "/config.xml")) {
219
				log_error("No config.xml found, attempting last known config restore.");
220
				$last_backup = discover_last_backup();
221
				if ($last_backup)
222
					restore_backup("/cf/conf/backup/{$last_backup}");
223
				else
224
					log_error("Could not restore config.xml.");
225
			}
226
			$config = parse_config(true);
227
		}
228
	} else {
229
		if(!file_exists($g['conf_path'] . "/config.xml")) {
230
			if($g['booting']) echo ".";
231
			log_error("No config.xml found, attempting last known config restore.");
232
			$last_backup = discover_last_backup();
233
			if ($last_backup)
234
				restore_backup("/cf/conf/backup/{$last_backup}");
235
			else
236
				log_error("Could not restore config.xml.");
237
		}
238
		$config = parse_xml_config($g['conf_path'] . '/config.xml', $g['xml_rootobj']);
239
		generate_config_cache($config);
240
	}
241
	if($g['booting']) echo ".";
242
	alias_make_table($config);
243
	config_unlock();
244

    
245
	/*    override some global configuration parms if they exist
246
	 *    instead of hard coding these checks into the codebase
247
     */
248
	if($config['pptp']['n_pptp_units'])
249
		$g['n_pptp_units'] = $config['pptp']['n_pptp_units'];
250
	if($config['pptp']['pptp_subnet'])
251
		$g['pptp_subnet'] = $config['pptp']['pptp_subnet'];
252

    
253
	if($config['pppoe']['n_pppoe_units'])
254
		$g['n_pppoe_units'] = $config['pppoe']['n_pppoe_units'];
255
	if($config['pppoe']['pppoe_subnet'])
256
		$g['pppoe_subnet'] = $config['pppoe']['pppoe_subnet'];
257

    
258
	return $config;
259
}
260

    
261
/****f* config/generate_config_cache
262
 * NAME
263
 *   generate_config_cache - Write serialized configuration to cache.
264
 * INPUTS
265
 *   $config	- array containing current firewall configuration
266
 * RESULT
267
 *   boolean	- true on completion
268
 ******/
269
function generate_config_cache($config) {
270
	global $g;
271
	conf_mount_rw();
272
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
273
	fwrite($configcache, serialize($config));
274
	fclose($configcache);
275
	conf_mount_ro();
276
	return true;
277
}
278

    
279
function discover_last_backup() {
280
        $backups = split("\n", `cd /cf/conf/backup && ls -ltr *.xml | awk '{print \$9}'`);
281
		$last_backup = "";
282
        foreach($backups as $backup)
283
        	if($backup)
284
	        	$last_backup = $backup;
285
        return $last_backup;
286
}
287

    
288
function restore_backup($file) {
289
	if(file_exists($file)) {
290
		conf_mount_rw();
291
		system("cp $file /cf/conf/config.xml");
292
	}
293
}
294

    
295
/****f* config/parse_config_bootup
296
 * NAME
297
 *   parse_config_bootup - Bootup-specific configuration checks.
298
 * RESULT
299
 *   null
300
 ******/
301
function parse_config_bootup() {
302
	global $config, $g, $noparseconfig;
303
	if($g['booting']) echo ".";
304
	if (!$noparseconfig) {
305
		if (!file_exists("{$g['conf_path']}/config.xml")) {
306
			config_lock();
307
			if ($g['booting']) {
308
				if (strstr($g['platform'], "cdrom")) {
309
					/* try copying the default config. to the floppy */
310
					echo "Resetting factory defaults...\n";
311
					reset_factory_defaults();
312
					if (file_exists("{$g['conf_path']}/config.xml")) {
313
						/* do nothing, we have a file. */
314
					} else {
315
						echo "No XML configuration file found - using factory defaults.\n";
316
						echo "Make sure that the configuration floppy disk with the conf/config.xml\n";
317
						echo "file is inserted. If it isn't, your configuration changes will be lost\n";
318
						echo "on reboot.\n";
319
					}
320
				} else {
321
					$last_backup = discover_last_backup();
322
					if($last_backup) {
323
						log_error("No config.xml found, attempting last known config restore.");
324
						restore_backup("/cf/conf/backup/{$last_backup}");
325
					}
326
					if(!file_exists("{$g['conf_path']}/config.xml")) {
327
						echo "XML configuration file not found.  pfSense cannot continue booting.\n";
328
						mwexec("/sbin/halt");
329
						exit;
330
					}
331
					log_error("Last known config found and restored.  Please double check your configuration file for accuracy.");
332
				}
333
			} else {
334
				config_unlock();
335
				exit(0);
336
			}
337
		}
338
	}
339

    
340
	parse_config(true);
341

    
342
	if ((float)$config['version'] > (float)$g['latest_config']) {
343
		echo <<<EOD
344

    
345

    
346
*******************************************************************************
347
* WARNING!                                                                    *
348
* The current configuration has been created with a newer version of pfSense  *
349
* than this one! This can lead to serious misbehavior and even security       *
350
* holes! You are urged to either upgrade to a newer version of pfSense or     *
351
* revert to the default configuration immediately!                            *
352
*******************************************************************************
353

    
354

    
355
EOD;
356
		}
357

    
358
	/* make alias table (for faster lookups) */
359
	alias_make_table($config);
360
	config_unlock();
361
}
362

    
363
/****f* config/conf_mount_rw
364
 * NAME
365
 *   conf_mount_rw - Mount filesystems read/write.
366
 * RESULT
367
 *   null
368
 ******/
369
/* mount flash card read/write */
370
function conf_mount_rw() {
371
	global $g;
372

    
373
	/* do not mount on cdrom platform */
374
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
375
		return;
376

    
377
	$status = mwexec("/sbin/mount -u -w {$g['cf_path']}");
378
	if($status <> 0) {
379
		if($g['booting'])
380
			echo "Disk is dirty.  Running fsck -y\n";
381
		mwexec("/sbin/fsck -y {$g['cf_path']}");
382
		$status = mwexec("/sbin/mount -u -w {$g['cf_path']}");
383
	}
384

    
385
	/*    if the platform is soekris or wrap or pfSense, lets mount the
386
	 *    compact flash cards root.
387
         */
388
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx"
389
	   or $g['platform'] == "embedded") {
390
		$status = mwexec("/sbin/mount -u -w /");
391
		/* we could not mount this correctly.  kick off fsck */
392
		if($status <> 0) {
393
			log_error("File system is dirty.  Launching FSCK for /");
394
			mwexec("/sbin/fsck -y /");
395
			$status = mwexec("/sbin/mount -u -w /");
396
		}
397
	}
398
}
399

    
400
/****f* config/conf_mount_ro
401
 * NAME
402
 *   conf_mount_ro - Mount filesystems readonly.
403
 * RESULT
404
 *   null
405
 ******/
406
function conf_mount_ro() {
407
	global $g;
408

    
409
	if($g['booting'] == true)
410
		return;
411

    
412
	/* firmare upgrade in progress */
413
	if(file_exists($g['varrun_path'] . "/fwup.enabled"))
414
		return;
415

    
416
	/* do not umount if generating ssh keys */
417
	if(file_exists("/tmp/keys_generating"))
418
		return;
419

    
420
	/* do not umount on cdrom or pfSense platforms */
421
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
422
		return;
423

    
424
	/* sync data, then force a remount of /cf */
425
	mwexec("/bin/sync");
426
	mwexec("/sbin/mount -u -r -f {$g['cf_path']}");
427
	mwexec("/sbin/mount -u -r -f /");
428
}
429

    
430
/****f* config/convert_config
431
 * NAME
432
 *   convert_config - Attempt to update config.xml.
433
 * DESCRIPTION
434
 *   convert_config() reads the current global configuration
435
 *   and attempts to convert it to conform to the latest
436
 *   config.xml version. This allows major formatting changes
437
 *   to be made with a minimum of breakage.
438
 * RESULT
439
 *   null
440
 ******/
441
/* convert configuration, if necessary */
442
function convert_config() {
443
	global $config, $g;
444

    
445
	if ($config['version'] == $g['latest_config'])
446
		return;		/* already at latest version */
447

    
448
	// Save off config version
449
	$prev_version = $config['version'];
450

    
451
	/* convert 1.0 -> 1.1 */
452
	if ($config['version'] == "1.0") {
453
		$opti = 1;
454
		$ifmap = array('lan' => 'lan', 'wan' => 'wan', 'pptp' => 'pptp');
455

    
456
		/* convert DMZ to optional, if necessary */
457
		if (isset($config['interfaces']['dmz'])) {
458

    
459
			$dmzcfg = &$config['interfaces']['dmz'];
460

    
461
			if ($dmzcfg['if']) {
462
				$config['interfaces']['opt' . $opti] = array();
463
				$optcfg = &$config['interfaces']['opt' . $opti];
464

    
465
				$optcfg['enable'] = $dmzcfg['enable'];
466
				$optcfg['descr'] = "DMZ";
467
				$optcfg['if'] = $dmzcfg['if'];
468
				$optcfg['ipaddr'] = $dmzcfg['ipaddr'];
469
				$optcfg['subnet'] = $dmzcfg['subnet'];
470

    
471
				$ifmap['dmz'] = "opt" . $opti;
472
				$opti++;
473
			}
474

    
475
			unset($config['interfaces']['dmz']);
476
		}
477

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

    
481
			if (!$config['interfaces']['wlan' . $i]['if']) {
482
				unset($config['interfaces']['wlan' . $i]);
483
				continue;
484
			}
485

    
486
			$wlancfg = &$config['interfaces']['wlan' . $i];
487
			$config['interfaces']['opt' . $opti] = array();
488
			$optcfg = &$config['interfaces']['opt' . $opti];
489

    
490
			$optcfg['enable'] = $wlancfg['enable'];
491
			$optcfg['descr'] = "WLAN" . $i;
492
			$optcfg['if'] = $wlancfg['if'];
493
			$optcfg['ipaddr'] = $wlancfg['ipaddr'];
494
			$optcfg['subnet'] = $wlancfg['subnet'];
495
			$optcfg['bridge'] = $wlancfg['bridge'];
496

    
497
			$optcfg['wireless'] = array();
498
			$optcfg['wireless']['mode'] = $wlancfg['mode'];
499
			$optcfg['wireless']['ssid'] = $wlancfg['ssid'];
500
			$optcfg['wireless']['channel'] = $wlancfg['channel'];
501
			$optcfg['wireless']['wep'] = $wlancfg['wep'];
502

    
503
			$ifmap['wlan' . $i] = "opt" . $opti;
504

    
505
			unset($config['interfaces']['wlan' . $i]);
506
			$opti++;
507
		}
508

    
509
		/* convert filter rules */
510
		$n = count($config['filter']['rule']);
511
		for ($i = 0; $i < $n; $i++) {
512

    
513
			$fr = &$config['filter']['rule'][$i];
514

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

    
526
			/* remap source network */
527
			if (isset($fr['source']['network'])) {
528
				if (array_key_exists($fr['source']['network'], $ifmap))
529
					$fr['source']['network'] = $ifmap[$fr['source']['network']];
530
				else {
531
					/* remove the rule */
532
					echo "\nWarning: filter rule removed " .
533
						"(source network '{$fr['source']['network']}' does not exist anymore).";
534
					unset($config['filter']['rule'][$i]);
535
					continue;
536
				}
537
			}
538

    
539
			/* remap destination network */
540
			if (isset($fr['destination']['network'])) {
541
				if (array_key_exists($fr['destination']['network'], $ifmap))
542
					$fr['destination']['network'] = $ifmap[$fr['destination']['network']];
543
				else {
544
					/* remove the rule */
545
					echo "\nWarning: filter rule removed " .
546
						"(destination network '{$fr['destination']['network']}' does not exist anymore).";
547
					unset($config['filter']['rule'][$i]);
548
					continue;
549
				}
550
			}
551
		}
552

    
553
		/* convert shaper rules */
554
		$n = count($config['pfqueueing']['rule']);
555
		if (is_array($config['pfqueueing']['rule']))
556
			for ($i = 0; $i < $n; $i++) {
557

    
558
			$fr = &$config['pfqueueing']['rule'][$i];
559

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

    
571
			/* remap source network */
572
			if (isset($fr['source']['network'])) {
573
				if (array_key_exists($fr['source']['network'], $ifmap))
574
					$fr['source']['network'] = $ifmap[$fr['source']['network']];
575
				else {
576
					/* remove the rule */
577
					echo "\nWarning: traffic shaper rule removed " .
578
						"(source network '{$fr['source']['network']}' does not exist anymore).";
579
					unset($config['pfqueueing']['rule'][$i]);
580
					continue;
581
				}
582
			}
583

    
584
			/* remap destination network */
585
			if (isset($fr['destination']['network'])) {
586
				if (array_key_exists($fr['destination']['network'], $ifmap))
587
					$fr['destination']['network'] = $ifmap[$fr['destination']['network']];
588
				else {
589
					/* remove the rule */
590
					echo "\nWarning: traffic shaper rule removed " .
591
						"(destination network '{$fr['destination']['network']}' does not exist anymore).";
592
					unset($config['pfqueueing']['rule'][$i]);
593
					continue;
594
				}
595
			}
596
		}
597

    
598
		$config['version'] = "1.1";
599
	}
600

    
601
	/* convert 1.1 -> 1.2 */
602
	if ($config['version'] == "1.1") {
603
		/* move LAN DHCP server config */
604
		$tmp = $config['dhcpd'];
605
		$config['dhcpd'] = array();
606
		$config['dhcpd']['lan'] = $tmp;
607

    
608
		/* encrypt password */
609
		$config['system']['password'] = crypt($config['system']['password']);
610

    
611
		$config['version'] = "1.2";
612
	}
613

    
614
	/* convert 1.2 -> 1.3 */
615
	if ($config['version'] == "1.2") {
616
		/* convert advanced outbound NAT config */
617
		for ($i = 0; isset($config['nat']['advancedoutbound']['rule'][$i]); $i++) {
618
			$curent = &$config['nat']['advancedoutbound']['rule'][$i];
619
			$src = $curent['source'];
620
			$curent['source'] = array();
621
			$curent['source']['network'] = $src;
622
			$curent['destination'] = array();
623
			$curent['destination']['any'] = true;
624
		}
625

    
626
		/* add an explicit type="pass" to all filter rules to make things consistent */
627
		for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
628
			$config['filter']['rule'][$i]['type'] = "pass";
629
		}
630

    
631
		$config['version'] = "1.3";
632
	}
633

    
634
	/* convert 1.3 -> 1.4 */
635
	if ($config['version'] == "1.3") {
636
		/* convert shaper rules (make pipes) */
637
		if (is_array($config['pfqueueing']['rule'])) {
638
			$config['pfqueueing']['pipe'] = array();
639

    
640
			for ($i = 0; isset($config['pfqueueing']['rule'][$i]); $i++) {
641
				$curent = &$config['pfqueueing']['rule'][$i];
642

    
643
				/* make new pipe and associate with this rule */
644
				$newpipe = array();
645
				$newpipe['descr'] = $curent['descr'];
646
				$newpipe['bandwidth'] = $curent['bandwidth'];
647
				$newpipe['delay'] = $curent['delay'];
648
				$newpipe['mask'] = $curent['mask'];
649
				$config['pfqueueing']['pipe'][$i] = $newpipe;
650

    
651
				$curent['targetpipe'] = $i;
652

    
653
				unset($curent['bandwidth']);
654
				unset($curent['delay']);
655
				unset($curent['mask']);
656
			}
657
		}
658

    
659
		$config['version'] = "1.4";
660
	}
661

    
662
	/* Convert 1.4 -> 1.5 */
663
	if ($config['version'] == "1.4") {
664

    
665
		/* Default route moved */
666
		if (isset($config['interfaces']['wan']['gateway']))
667
			if ($config['interfaces']['wan']['gateway'] <> "")
668
				$config['interfaces']['wan']['gateway'] = $config['interfaces']['wan']['gateway'];
669
		unset($config['interfaces']['wan']['gateway']);
670

    
671
                /* Queues are no longer interface specific */
672
                if (isset($config['interfaces']['lan']['schedulertype']))
673
                        unset($config['interfaces']['lan']['schedulertype']);
674
                if (isset($config['interfaces']['wan']['schedulertype']))
675
                        unset($config['interfaces']['wan']['schedulertype']);
676

    
677
                for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
678
                        if(isset($config['interfaces']['opt' . $i]['schedulertype']))
679
                                unset($config['interfaces']['opt' . $i]['schedulertype']);
680
                }
681

    
682
		$config['version'] = "1.5";
683
	}
684

    
685
	/* Convert 1.5 -> 1.6 */
686
	if ($config['version'] == "1.5") {
687
		/* Alternate firmware URL moved */
688
		if (isset($config['system']['firmwareurl']) && isset($config['system']['firmwarename'])) { // Only convert if *both* are defined.
689
			$config['system']['alt_firmware_url'] = array();
690
			$config['system']['alt_firmware_url']['enabled'] = "";
691
			$config['system']['alt_firmware_url']['firmware_base_url'] = $config['system']['firmwareurl'];
692
			$config['system']['alt_firmware_url']['firmware_filename'] = $config['system']['firmwarename'];
693
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
694
		} else {
695
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
696
		}
697

    
698
		$config['version'] = "1.6";
699
	}
700

    
701
	/* Convert 1.6 -> 1.7 */
702
	if ($config['version'] == "1.6") {
703
		/* wipe previous shaper configuration */
704
		unset($config['shaper']['queue']);
705
		unset($config['shaper']['rule']);
706
		unset($config['interfaces']['wan']['bandwidth']);
707
		unset($config['interfaces']['wan']['bandwidthtype']);
708
		unset($config['interfaces']['lan']['bandwidth']);
709
		unset($config['interfaces']['lan']['bandwidthtype']);
710
		$config['shaper']['enable'] = FALSE;
711
		$config['version'] = "1.7";
712
	}
713
	/* Convert 1.7 -> 1.8 */
714
	if ($config['version'] == "1.7") {
715
		if(isset($config['proxyarp']) && is_array($config['proxyarp']['proxyarpnet'])) {
716
			$proxyarp = &$config['proxyarp']['proxyarpnet'];
717
			foreach($proxyarp as $arpent){
718
				$vip = array();
719
				$vip['mode'] = "proxyarp";
720
				$vip['interface'] = $arpent['interface'];
721
				$vip['descr'] = $arpent['descr'];
722
				if (isset($arpent['range'])) {
723
					$vip['range'] = $arpent['range'];
724
					$vip['type'] = "range";
725
				} else {
726
					$subnet = explode('/', $arpent['network']);
727
					$vip['subnet'] = $subnet[0];
728
					if (isset($subnet[1])) {
729
						$vip['subnet_bits'] = $subnet[1];
730
						$vip['type'] = "network";
731
					} else {
732
						$vip['subnet_bits'] = "32";
733
						$vip['type'] = "single";
734
					}
735
				}
736
				$config['virtualip']['vip'][] = $vip;
737
			}
738
			unset($config['proxyarp']);
739
		}
740
		if(isset($config['installedpackages']) && isset($config['installedpackages']['carp']) && is_array($config['installedpackages']['carp']['config'])) {
741
			$carp = &$config['installedpackages']['carp']['config'];
742
			foreach($carp as $carpent){
743
				$vip = array();
744
				$vip['mode'] = "carp";
745
				$vip['interface'] = "AUTO";
746
				$vip['descr'] = "CARP vhid {$carpent['vhid']}";
747
				$vip['type'] = "single";
748
				$vip['vhid'] = $carpent['vhid'];
749
				$vip['advskew'] = $carpent['advskew'];
750
				$vip['password'] = $carpent['password'];
751
				$vip['subnet'] = $carpent['ipaddress'];
752
				$vip['subnet_bits'] = $carpent['netmask'];
753
				$config['virtualip']['vip'][] = $vip;
754
			}
755
			unset($config['installedpackages']['carp']);
756
		}
757
		/* Server NAT is no longer needed */
758
		unset($config['nat']['servernat']);
759

    
760
		/* enable SSH */
761
		if ($config['version'] == "1.8") {
762
			$config['system']['sshenabled'] = true;
763
		}
764

    
765
		$config['version'] = "1.9";
766
	}
767

    
768
	/* Convert 1.8 -> 1.9 */
769
	if ($config['version'] == "1.8") {
770
		$config['theme']="metallic";
771
		$config['version'] = "1.9";
772
	}
773
	/* Convert 1.9 -> 2.0 */
774
	if ($config['version'] == "1.9") {
775
		if(is_array($config['ipsec']['tunnel'])) {
776
			reset($config['ipsec']['tunnel']);
777
			while (list($index, $tunnel) = each($config['ipsec']['tunnel'])) {
778
				/* Sanity check on required variables */
779
				/* This fixes bogus <tunnel> entries - remnant of bug #393 */
780
				if (!isset($tunnel['local-subnet']) && !isset($tunnel['remote-subnet'])) {
781
					unset($config['ipsec']['tunnel'][$tunnel]);
782
				}
783
			}
784
        	}
785
		$config['version'] = "2.0";
786
	}
787
	/* Convert 2.0 -> 2.1 */
788
	if ($config['version'] == "2.0") {
789
		/* shaper scheduler moved */
790
		if(isset($config['system']['schedulertype'])) {
791
			$config['shaper']['schedulertype'] = $config['system']['schedulertype'];
792
			unset($config['system']['schedulertype']);
793
		}
794
		$config['version'] = "2.1";
795
	}
796
	/* Convert 2.1 -> 2.2 */
797
	if ($config['version'] == "2.1") {
798
		/* move gateway to wan interface */
799
		$config['interfaces']['wan']['gateway'] = $config['system']['gateway'];
800
		$config['version'] = "2.2";
801
	}
802
	/* Convert 2.2 -> 2.3 */
803
	if ($config['version'] == "2.2") {
804
		if(isset($config['shaper'])) {
805
			/* wipe previous shaper configuration */
806
			unset($config['shaper']);
807
		}
808
		$config['version'] = "2.3";
809
	}
810

    
811
	/* Convert 2.4 -> 2.5 */
812
	if ($config['version'] == "2.4") {
813
		$config['interfaces']['wan']['use_rrd_gateway'] = $config['system']['use_rrd_gateway'];
814
		unset($config['system']['use_rrd_gateway']);
815
 		$config['version'] = "2.5";
816
	}
817

    
818
	if ($prev_version != $config['version'])
819
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
820
}
821

    
822
/****f* config/write_config
823
 * NAME
824
 *   write_config - Backup and write the firewall configuration.
825
 * DESCRIPTION
826
 *   write_config() handles backing up the current configuration,
827
 *   applying changes, and regenerating the configuration cache.
828
 * INPUTS
829
 *   $desc	- string containing the a description of configuration changes
830
 *   $backup	- boolean: do not back up current configuration if false.
831
 * RESULT
832
 *   null
833
 ******/
834
/* save the system configuration */
835
function write_config($desc="Unknown", $backup = true) {
836
	global $config, $g;
837

    
838
	if($backup)
839
		backup_config();
840

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

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

    
848
	$config['revision']['description'] = $desc;
849
	$config['revision']['time'] = $changetime;
850

    
851
	config_lock();
852

    
853
	/* generate configuration XML */
854
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
855

    
856
	conf_mount_rw();
857

    
858
	/* write new configuration */
859
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
860
	if (!$fd)
861
		die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
862
	fwrite($fd, $xmlconfig);
863
	fclose($fd);
864

    
865
	if($g['platform'] == "embedded") {
866
		/*   backup last config.xml and remove all others to avoid
867
		 *   filling up the compact flash dedicated config partition
868
		 */
869
		$last_backup = discover_last_backup();
870
		mwexec("/bin/mv /cf/conf/backup/{$last_backup} /tmp/lastconfig.xml");
871
		mwexec("/bin/rm /cf/conf/backup/*");
872
		mwexec("/bin/mv /tmp/lastconfig.xml /cf/conf/backup/{$last_backup}");
873
	}
874

    
875
	if($g['booting'] <> true) {
876
		conf_mount_ro();
877
	}
878

    
879
	/* re-read configuration */
880
	$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
881

    
882
	/* write config cache */
883
	$fd = @fopen("{$g['tmp_path']}/config.cache", "wb");
884
	if ($fd) {
885
		fwrite($fd, serialize($config));
886
		fclose($fd);
887
	}
888

    
889
	config_unlock();
890

    
891
	/* tell kernel to sync fs data */
892
	mwexec("/bin/sync");
893

    
894
	return $config;
895
}
896

    
897
/****f* config/reset_factory_defaults
898
 * NAME
899
 *   reset_factory_defaults - Reset the system to its default configuration.
900
 * RESULT
901
 *   integer	- indicates completion
902
 ******/
903
function reset_factory_defaults() {
904
	global $g;
905

    
906
	config_lock();
907
	conf_mount_rw();
908

    
909
	/* create conf directory, if necessary */
910
	safe_mkdir("{$g['cf_conf_path']}");
911

    
912
	/* clear out /conf */
913
	$dh = opendir($g['conf_path']);
914
	while ($filename = readdir($dh)) {
915
		if (($filename != ".") && ($filename != "..")) {
916
			unlink_if_exists($g['conf_path'] . "/" . $filename);
917
		}
918
	}
919
	closedir($dh);
920

    
921
	/* copy default configuration */
922
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
923

    
924
	/* call the wizard */
925
	touch("/conf/trigger_initial_wizard");
926

    
927
	conf_mount_ro();
928
	config_unlock();
929

    
930
	return 0;
931
}
932

    
933
function config_restore($conffile) {
934
	global $config, $g;
935

    
936
	if (!file_exists($conffile))
937
		return 1;
938

    
939
    config_lock();
940
    conf_mount_rw();
941

    
942
    backup_config();
943
    copy($conffile, "{$g['cf_conf_path']}/config.xml");
944
	$config = parse_config(true);
945
    write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
946

    
947
    conf_mount_ro();
948
    config_unlock();
949

    
950
    return 0;
951
}
952

    
953
function config_install($conffile) {
954
	global $config, $g;
955

    
956
	if (!file_exists($conffile))
957
		return 1;
958

    
959
	if (!config_validate("{$g['conf_path']}/config.xml"))
960
		return 1;
961

    
962
	if($g['booting'] == true)
963
		echo "Installing configuration...\n";
964

    
965
    config_lock();
966
    conf_mount_rw();
967

    
968
    copy($conffile, "{$g['conf_path']}/config.xml");
969

    
970
	/* unlink cache file if it exists */
971
	if(file_exists("{$g['tmp_path']}/config.cache"))
972
		unlink("{$g['tmp_path']}/config.cache");
973

    
974
    conf_mount_ro();
975
    config_unlock();
976

    
977
    return 0;
978
}
979

    
980
function config_validate($conffile) {
981

    
982
	global $g, $xmlerr;
983

    
984
	$xml_parser = xml_parser_create();
985

    
986
	if (!($fp = fopen($conffile, "r"))) {
987
		$xmlerr = "XML error: unable to open file";
988
		return false;
989
	}
990

    
991
	while ($data = fread($fp, 4096)) {
992
		if (!xml_parse($xml_parser, $data, feof($fp))) {
993
			$xmlerr = sprintf("%s at line %d",
994
						xml_error_string(xml_get_error_code($xml_parser)),
995
						xml_get_current_line_number($xml_parser));
996
			return false;
997
		}
998
	}
999
	xml_parser_free($xml_parser);
1000

    
1001
	fclose($fp);
1002

    
1003
	return true;
1004
}
1005

    
1006
/*   lock configuration file, decide that the lock file
1007
 *   is stale after 10 seconds
1008
 */
1009
function config_lock() {
1010
	global $g, $process_lock;
1011

    
1012
	/* No need to continue if we're the ones holding the lock */
1013
	if ($process_lock)
1014
		return;
1015

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

    
1018
	$n = 0;
1019
	while ($n < 10) {
1020
		/* open the lock file in append mode to avoid race condition */
1021
		if ($fd = @fopen($lockfile, "x")) {
1022
			/* succeeded */
1023
			$process_lock = true;
1024
			fclose($fd);
1025
			return;
1026
		} else {
1027
			/* file locked, wait and try again */
1028
			$process_lock = false;
1029
			sleep(1);
1030
			$n++;
1031
		}
1032
	}
1033
}
1034

    
1035
/* unlock configuration file */
1036
function config_unlock() {
1037
	global $g, $process_lock;
1038

    
1039
	$lockfile = "{$g['varrun_path']}/config.lock";
1040
	$process_lock = false;
1041

    
1042
	unlink_if_exists($lockfile);
1043
}
1044

    
1045
function set_networking_interfaces_ports() {
1046
	global $noreboot;
1047
	global $config;
1048
	global $g;
1049
	global $fp;
1050

    
1051
	$fp = fopen('php://stdin', 'r');
1052

    
1053
	$memory = get_memory();
1054
	$avail = $memory[0];
1055

    
1056
	if($avail < 115) {
1057
		echo "\n\n\n";
1058
		echo "DANGER!  WARNING!\n\n";
1059
		echo "pfSense requires *ATLEAST* 128 megs of ram to function correctly.\n";
1060
		echo "Only ($avail) megs of ram has been detected.\n";
1061
		echo "\nPress ENTER to continue.";
1062
		fgets($fp);
1063
		echo "\n";
1064
	}
1065

    
1066
	$iflist = get_interface_list();
1067

    
1068
	echo <<<EOD
1069

    
1070
Valid interfaces are:
1071

    
1072

    
1073
EOD;
1074

    
1075
	if(!is_array($iflist)) {
1076
		echo "No interfaces found!\n";
1077
	} else {
1078
		foreach ($iflist as $iface => $ifa) {
1079
			echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
1080
				$ifa['up'] ? "   (up)" : "");
1081
		}
1082
	}
1083

    
1084
	echo <<<EOD
1085

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

    
1090
Do you want to set up VLANs now [y|n]?
1091
EOD;
1092

    
1093
	if (strcasecmp(chop(fgets($fp)), "y") == 0)
1094
		vlan_setup();
1095

    
1096
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1097

    
1098
		echo "\n\nVLAN interfaces:\n\n";
1099
		$i = 0;
1100
		foreach ($config['vlans']['vlan'] as $vlan) {
1101

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

    
1105
			$iflist['vlan' . $i] = array();
1106
			$i++;
1107
		}
1108
	}
1109

    
1110
	echo <<<EOD
1111

    
1112
*NOTE*  pfSense requires *ATLEAST* 2 assigned interfaces to function.
1113
        If you do not have two interfaces turn off the machine until
1114
	    you do.
1115

    
1116
	    And now in ENGLISH.  If you do not have atleast two *REAL*
1117
	    network interface cards or one nic with multiple VLANS then
1118
	    pfSense *WILL NOT* run correctly.
1119

    
1120
If you do not know the names of your interfaces, you may choose to use
1121
auto-detection... In that case, disconnect all interfaces now before
1122
hitting a.   The system will then prompt you to plug in each nic to
1123
autodetect.
1124

    
1125
EOD;
1126

    
1127
	do {
1128
		echo "\nEnter the LAN interface name or 'a' for auto-detection: ";
1129
		$lanif = chop(fgets($fp));
1130
		if ($lanif === "") {
1131
			return;
1132
		}
1133

    
1134
		if ($lanif === "a")
1135
			$lanif = autodetect_interface("LAN", $fp);
1136
		else if (!array_key_exists($lanif, $iflist)) {
1137
			echo "\nInvalid interface name '{$lanif}'\n";
1138
			unset($lanif);
1139
			continue;
1140
		}
1141
	} while (!$lanif);
1142

    
1143
	do {
1144
		echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
1145
		$wanif = chop(fgets($fp));
1146
		if ($wanif === "") {
1147
			return;
1148
		}
1149
		if ($wanif === "a")
1150
			$wanif = autodetect_interface("WAN", $fp);
1151
		else if (!array_key_exists($wanif, $iflist)) {
1152
			echo "\nInvalid interface name '{$wanif}'\n";
1153
			unset($wanif);
1154
			continue;
1155
		}
1156
	} while (!$wanif);
1157

    
1158
	/* optional interfaces */
1159
	$i = 0;
1160
	$optif = array();
1161

    
1162
	while (1) {
1163
		if ($optif[$i])
1164
			$i++;
1165
		$i1 = $i + 1;
1166

    
1167
		if($config['interfaces']['opt' . $i1]['descr'])
1168
			echo "\nOptional interface {$i1} description found: {$config['interfaces']['opt' . $i1]['descr']}";
1169

    
1170
		echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
1171
			"(or nothing if finished): ";
1172

    
1173
		$optif[$i] = chop(fgets($fp));
1174

    
1175
		if ($optif[$i]) {
1176
			if ($optif[$i] === "a") {
1177
				$ad = autodetect_interface("Optional " . $i1, $fp);
1178
				if ($ad)
1179
					$optif[$i] = $ad;
1180
				else
1181
					unset($optif[$i]);
1182
			} else if (!array_key_exists($optif[$i], $iflist)) {
1183
				echo "\nInvalid interface name '{$optif[$i]}'\n";
1184
				unset($optif[$i]);
1185
				continue;
1186
			}
1187
		} else {
1188
			unset($optif[$i]);
1189
			break;
1190
		}
1191
	}
1192

    
1193
	/* check for double assignments */
1194
	$ifarr = array_merge(array($lanif, $wanif), $optif);
1195

    
1196
	for ($i = 0; $i < (count($ifarr)-1); $i++) {
1197
		for ($j = ($i+1); $j < count($ifarr); $j++) {
1198
			if ($ifarr[$i] == $ifarr[$j]) {
1199
				echo <<<EOD
1200

    
1201
Error: you cannot assign the same interface name twice!
1202

    
1203
EOD;
1204

    
1205
				return;
1206
			}
1207
		}
1208
	}
1209

    
1210
	echo <<<EOD
1211

    
1212
The interfaces will be assigned as follows:
1213

    
1214
LAN  -> {$lanif}
1215
WAN  -> {$wanif}
1216

    
1217
EOD;
1218

    
1219
	for ($i = 0; $i < count($optif); $i++) {
1220
		echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
1221
	}
1222

    
1223
echo <<<EOD
1224

    
1225
Do you want to proceed [y|n]?
1226
EOD;
1227

    
1228
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
1229

    
1230
		$config['interfaces']['lan']['if'] = $lanif;
1231
		if (preg_match($g['wireless_regex'], $lanif)) {
1232
			if (!is_array($config['interfaces']['lan']['wireless']))
1233
				$config['interfaces']['lan']['wireless'] = array();
1234
		} else {
1235
			unset($config['interfaces']['lan']['wireless']);
1236
		}
1237

    
1238
		$config['interfaces']['wan']['if'] = $wanif;
1239
		if (preg_match($g['wireless_regex'], $wanif)) {
1240
			if (!is_array($config['interfaces']['wan']['wireless']))
1241
				$config['interfaces']['wan']['wireless'] = array();
1242
		} else {
1243
			unset($config['interfaces']['wan']['wireless']);
1244
		}
1245

    
1246
		for ($i = 0; $i < count($optif); $i++) {
1247
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
1248
				$config['interfaces']['opt' . ($i+1)] = array();
1249

    
1250
			$config['interfaces']['opt' . ($i+1)]['if'] = $optif[$i];
1251

    
1252
			/* wireless interface? */
1253
			if (preg_match($g['wireless_regex'], $optif[$i])) {
1254
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
1255
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
1256
			} else {
1257
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
1258
			}
1259

    
1260
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
1261
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
1262
		}
1263

    
1264
		/* remove all other (old) optional interfaces */
1265
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
1266
			unset($config['interfaces']['opt' . ($i+1)]);
1267

    
1268
		write_config();
1269

    
1270
		echo <<<EOD
1271

    
1272

    
1273

    
1274
EOD;
1275

    
1276
		if($g['booting'])
1277
			return;
1278

    
1279
		echo "One moment while we reload the settings...";
1280

    
1281
		$g['booting'] = false;
1282

    
1283
		/* resync everything */
1284
		reload_all_sync();
1285

    
1286
		echo " done!\n";
1287

    
1288
		touch("{$g['tmp_path']}/assign_complete");
1289

    
1290
	}
1291
}
1292

    
1293
function autodetect_interface($ifname, $fp) {
1294
	$iflist_prev = get_interface_list("media");
1295
	echo <<<EOD
1296

    
1297
Connect the {$ifname} interface now and make sure that the link is up.
1298
Then press ENTER to continue.
1299

    
1300
EOD;
1301
	fgets($fp);
1302
	$iflist = get_interface_list("media");
1303

    
1304
	foreach ($iflist_prev as $ifn => $ifa) {
1305
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1306
			echo "Detected link-up on interface {$ifn}.\n";
1307
			return $ifn;
1308
		}
1309
	}
1310

    
1311
	echo "No link-up detected.\n";
1312

    
1313
	return null;
1314
}
1315

    
1316
function vlan_setup() {
1317
	global $iflist, $config, $g, $fp;
1318

    
1319
	$iflist = get_interface_list();
1320

    
1321
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1322

    
1323
	echo <<<EOD
1324

    
1325
WARNING: all existing VLANs will be cleared if you proceed!
1326

    
1327
Do you want to proceed [y|n]?
1328
EOD;
1329

    
1330
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1331
		return;
1332
	}
1333

    
1334
	$config['vlans']['vlan'] = array();
1335
	echo "\n";
1336

    
1337
	while (1) {
1338
		$vlan = array();
1339

    
1340
		echo "\n\nVLAN Capable interfaces:\n\n";
1341
		if(!is_array($iflist)) {
1342
			echo "No interfaces found!\n";
1343
		} else {
1344
			$vlan_capable=0;
1345
			foreach ($iflist as $iface => $ifa) {
1346
				if (is_jumbo_capable($iface)) {
1347
					echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
1348
						$ifa['up'] ? "   (up)" : "");
1349
					$vlan_capable++;
1350
				}
1351
			}
1352
		}
1353

    
1354
		if($vlan_capable == 0) {
1355
			echo "No VLAN capable interfaces detected.\n";
1356
			return;
1357
		}
1358

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

    
1362
		if ($vlan['if']) {
1363
			if (!array_key_exists($vlan['if'], $iflist) or
1364
			    !is_jumbo_capable($vlan['if'])) {
1365
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1366
				continue;
1367
			}
1368
		} else {
1369
			break;
1370
		}
1371

    
1372
		echo "Enter the VLAN tag (1-4094): ";
1373
		$vlan['tag'] = chop(fgets($fp));
1374

    
1375
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1376
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1377
			continue;
1378
		}
1379

    
1380
		$config['vlans']['vlan'][] = $vlan;
1381
	}
1382
}
1383

    
1384
function system_start_ftp_helpers() {
1385
	require_once("interfaces.inc");
1386
	global $config, $g;
1387

    
1388
	mwexec("/usr/bin/killall ftpsesame");
1389

    
1390
	/* build an array of interfaces to work with */
1391
	$iflist = array("lan" => "LAN");
1392
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1393
		$iflist['opt' . $i] = "opt{$i}";
1394

    
1395
	/* loop through all interfaces and handle pftpx */
1396
	$interface_counter = 0;
1397
	foreach ($iflist as $ifent => $ifname) {
1398
		/*    if the ftp proxy is disabled for this interface then kill pftpx
1399
		 *    instance and continue. note that the helpers for port forwards are
1400
		 *    launched in a  different sequence so we are filtering them out
1401
         *    here by not including -c {$port} -g 8021 first.
1402
		 */
1403
		 /* only install a ftp helper for enabled interfaces. wan and lan are always enabled. */
1404
		if(stristr($ifname, "opt") <> false)
1405
			if(!isset($config['interfaces'][strtolower($ifname)]['enable']))
1406
				continue;
1407
		$port = 8021 + $interface_counter;
1408
		if(isset($config['interfaces'][$ifname]['disableftpproxy'])) {
1409
			/*    item is disabled.  lets ++ the interface counter and
1410
			 *    keep processing interfaces. kill pftpx if already
1411
			 *    running for this instance.
1412
			 */
1413
			$helpers = exec("/bin/ps awux | grep \"/usr/local/sbin/pftpx -c {$port}\" | grep -v grep | sed \"s/  */ /g\" | cut -f2 -d\" \"");
1414
			if($helpers)
1415
				mwexec("/bin/kill {$helpers}");
1416
			$interface_counter++;
1417
		} else {
1418
			/* grab the current interface IP address */
1419
			$int = convert_friendly_interface_to_real_interface_name($ifname);
1420
			$ip = find_interface_ip($int);
1421
			/* if pftpx is already running then do not launch it again */
1422
			$helpers = exec("/bin/ps awux | grep \"/usr/local/sbin/pftpx -c {$port}\" | grep -v grep | sed \"s/  */ /g\"");
1423
			if(!$helpers && $ip)
1424
 				mwexec("/usr/local/sbin/pftpx -c {$port} -g 8021 {$ip}");
1425
			if(!$ip)
1426
				mwexec("/usr/local/sbin/ftpsesame -i $int");
1427
			$interface_counter++;
1428
		}
1429
	}
1430
	/* support bridged interfaces.  even they need ftp mojo */
1431
	$num_bridges = find_number_of_created_bridges();
1432
	$num_bridges++;
1433
	for($x=0; $x<$num_bridges; $x++) {
1434
		mwexec("/usr/local/sbin/ftpsesame -i bridge{$x}");
1435
	}
1436
}
1437

    
1438
function cleanup_backupcache($revisions = 30) {
1439
	global $g;
1440
	$i = false;
1441
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1442
		conf_mount_rw();
1443
		$backups = get_backups();
1444
		$newbaks = array();
1445
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1446
		$baktimes = $backups['versions'];
1447
		$tocache = array();
1448
		unset($backups['versions']);
1449
       		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1450
				$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));
1451
                if(!in_array($tocheck, $baktimes)) {
1452
					$i = true;
1453
					if($g['booting'])
1454
						print " " . $tocheck . "a";
1455
					$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1456
					if($newxml['revision']['description'] == "")
1457
						$newxml['revision']['description'] = "Unknown";
1458
					$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1459
				}
1460
        	}
1461
		foreach($backups as $checkbak) {
1462
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1463
				$newbaks[] = $checkbak;
1464
			} else {
1465
				$i = true;
1466
				if($g['booting']) print " " . $tocheck . "r";
1467
			}
1468
		}
1469
		foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);
1470
		if(is_int($revisions) and (count($tocache) > $revisions)) {
1471
			$toslice = array_slice(array_keys($tocache), 0, $revisions);
1472
			foreach($toslice as $sliced)
1473
				$newcache[$sliced] = $tocache[$sliced];
1474
			foreach($tocache as $version => $versioninfo) {
1475
				if(!in_array($version, array_keys($newcache))) {
1476
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1477
					if($g['booting']) print " " . $tocheck . "d";
1478
				}
1479
			}
1480
			$tocache = $newcache;
1481
		}
1482
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1483
        fwrite($bakout, serialize($tocache));
1484
		fclose($bakout);
1485
		conf_mount_ro();
1486
	}
1487
	if($g['booting']) {
1488
		if($i) {
1489
			print "done.\n";
1490
		}
1491
	}
1492
}
1493

    
1494
function get_backups() {
1495
	global $g;
1496
	if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1497
		$confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1498
		$bakvers = array_keys($confvers);
1499
		$toreturn = array();
1500
		sort($bakvers);
1501
		// 	$bakvers = array_reverse($bakvers);
1502
		foreach(array_reverse($bakvers) as $bakver)
1503
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description']);
1504
	} else {
1505
		return false;
1506
	}
1507
	$toreturn['versions'] = $bakvers;
1508
	return $toreturn;
1509
}
1510

    
1511
function backup_config() {
1512
	global $config, $g;
1513

    
1514
	if($g['platform'] == "cdrom")
1515
		return;
1516

    
1517
	conf_mount_rw();
1518

    
1519
	/* Create backup directory if needed */
1520
	safe_mkdir("{$g['cf_conf_path']}/backup");
1521

    
1522
    if($config['revision']['time'] == "") {
1523
            $baktime = 0;
1524
    } else {
1525
            $baktime = $config['revision']['time'];
1526
    }
1527
    if($config['revision']['description'] == "") {
1528
            $bakdesc = "Unknown";
1529
    } else {
1530
            $bakdesc = $config['revision']['description'];
1531
    }
1532
    copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1533
    if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1534
            $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1535
    } else {
1536
            $backupcache = array();
1537
    }
1538
    $backupcache[$baktime] = array('description' => $bakdesc);
1539
    $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1540
    fwrite($bakout, serialize($backupcache));
1541
    fclose($bakout);
1542

    
1543
	conf_mount_ro();
1544

    
1545
	return true;
1546
}
1547

    
1548
function mute_kernel_msgs() {
1549
	exec("/sbin/conscontrol mute on");
1550
}
1551

    
1552
function unmute_kernel_msgs() {
1553
	exec("/sbin/conscontrol mute off");
1554
}
1555

    
1556
function start_devd() {
1557
	exec("/sbin/devd");
1558
	sleep(1);
1559
	if(file_exists("/tmp/rc.linkup"))
1560
		unlink("/tmp/rc.linkup");
1561
}
1562

    
1563
function set_device_perms() {
1564
	$devices = array(
1565
		'pf'	=> array(	'user'	=> 'proxy',
1566
					'group'	=> 'proxy',
1567
					'mode'	=> 0660),
1568
		);
1569

    
1570
	foreach ($devices as $name => $attr) {
1571
		$path = "/dev/$name";
1572
		if (file_exists($path)) {
1573
			chown($path, $attr['user']);
1574
			chgrp($path, $attr['group']);
1575
			chmod($path, $attr['mode']);
1576
		}
1577
	}
1578
}
1579

    
1580
if($g['booting']) echo ".";
1581
$config = parse_config();
1582

    
1583
?>
(5-5/27)