Project

General

Profile

Download (34.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/config
3
 * NAME
4
 *   config.inc - Functions to manipulate config.xml
5
 * DESCRIPTION
6
 *   This include contains various config.xml specific functions.
7
 * HISTORY
8
 * $Id$
9
 ******
10

    
11
	config.inc
12
	Copyright (C) 2004 Scott Ullrich
13
	All rights reserved.
14

    
15
	originally part of m0n0wall (http://m0n0.ch/wall)
16
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
17
	All rights reserved.
18

    
19
	Redistribution and use in source and binary forms, with or without
20
	modification, are permitted provided that the following conditions are met:
21

    
22
	1. Redistributions of source code must retain the above copyright notice,
23
	   this list of conditions and the following disclaimer.
24

    
25
	2. Redistributions in binary form must reproduce the above copyright
26
	   notice, this list of conditions and the following disclaimer in the
27
	   documentation and/or other materials provided with the distribution.
28

    
29
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
30
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
31
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
33
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
	POSSIBILITY OF SUCH DAMAGE.
39
*/
40

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

    
47
/* include globals/utility/XML parser files */
48
require_once("globals.inc");
49
require_once("util.inc");
50
require_once("pfsense-utils.inc");
51
require_once("xmlparse.inc");
52

    
53
/* read platform */
54
if (file_exists("{$g['etc_path']}/platform")) {
55
	$g['platform'] = chop(file_get_contents("{$g['etc_path']}/platform"));
56
} else {
57
	$g['platform'] = "unknown";
58
}
59

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

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

    
68
		if (strstr($g['platform'], "cdrom")) {
69
			/* config is on floppy disk for CD-ROM version */
70
			$cfgdevice = $cfgpartition = "fd0";
71
			$dmesg = `dmesg -a`;
72
			if(ereg("da0", $desg) == true) {
73
				$cfgdevice = $cfgpartition = "da0" ;
74
				if (mwexec("/sbin/mount -r da0 /cf") <> 0) {
75
					/* could not mount, fallback to floppy */
76
					$cfgdevice = $cfgpartition = "fd0";
77
				}
78
			}
79
			$cfgfstype = "msdos";
80
			echo "CDROM build\n";
81
			echo "   CFG: {$cfgpartition}\n";
82
			echo "  TYPE: {$cfgfstype}\n";
83
		} else {
84
			/* probe kernel known disks until we find one with config.xml */
85
			$disks = explode(" ", trim(preg_replace("/kern.disks: /", "", exec("/sbin/sysctl kern.disks"))));
86
			foreach ($disks as $mountdisk) {
87
				/* skip mfs mounted filesystems */
88
				if (strstr($mountdisk, "md"))
89
					continue;
90
				if (mwexec("/sbin/mount -r /dev/{$mountdisk}a {$g['cf_path']}") == 0) {
91
					if (file_exists("{$g['cf_conf_path']}/config.xml")) {
92
						/* found it */
93
						$cfgdevice = $mountdisk;
94
						$cfgpartition = $cfgdevice . "a";
95
						$cfgfstype = "ufs";
96
						echo "Found configuration on $cfgdevice.\n";
97
					}
98

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

    
101
					if ($cfgdevice)
102
						break;
103
				}
104
				if (mwexec("/sbin/mount -r /dev/{$mountdisk}d {$g['cf_path']}") == 0) {
105
					if (file_exists("{$g['cf_conf_path']}/config.xml")) {
106
						/* found it */
107
						$cfgdevice = $mountdisk;
108
						$cfgpartition = $cfgdevice . "d";
109
						$cfgfstype = "ufs";
110
						echo "Found configuration on $cfgdevice.\n";
111
					}
112

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

    
115
					if ($cfgdevice)
116
						break;
117
				}
118
			}
119
		}
120

    
121
		if (!$cfgdevice) {
122
			/* no device found, print an error and die */
123
			echo <<<EOD
124

    
125

    
126
*******************************************************************************
127
* FATAL ERROR                                                                 *
128
* The device that contains the configuration file (config.xml) could not be   *
129
* found. pfSense cannot continue booting.                                     *
130
*******************************************************************************
131

    
132

    
133
EOD;
134

    
135
			mwexec("/sbin/halt");
136
			exit;
137
		}
138

    
139
		/* write device name to a file for rc.firmware */
140
		$fd = fopen("{$g['varetc_path']}/cfdevice", "w");
141
		fwrite($fd, $cfgdevice . "\n");
142
		fclose($fd);
143

    
144
		/* write out an fstab */
145
		$fd = fopen("{$g['etc_path']}/fstab", "w");
146

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

    
150
		fwrite($fd, $fstab);
151
		fclose($fd);
152
	}
153

    
154
	/* mount all filesystems */
155
	mwexec("/sbin/mount -a");
156
}
157

    
158
$config = parse_config();
159

    
160
/****f* config/parse_config
161
 * NAME
162
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
163
 * INPUTS
164
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
165
 * RESULT
166
 *   $config      - array containing all configuration variables
167
 ******/
168
function parse_config($parse = false) {
169
	global $g;
170

    
171
	config_lock();
172
	if(!$parse) {
173
		if(file_exists($g['tmp_path'] . '/config.cache')) {
174
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
175
			if(is_null($config)) {
176
				config_unlock();
177
				parse_config(true);
178
			}
179
		} else {
180
			config_unlock();
181
			$config = parse_config(true);
182
		}
183
	} else {
184
		$config = parse_xml_config($g['conf_path'] . '/config.xml', $g['xml_rootobj']);
185
		generate_config_cache($config);
186
	}
187
	
188
	alias_make_table($config);
189
	config_unlock();
190
	return $config;
191
}
192

    
193
/****f* config/generate_config_cache
194
 * NAME
195
 *   generate_config_cache - Write serialized configuration to cache.
196
 * INPUTS
197
 *   $config	- array containing current firewall configuration
198
 * RESULT
199
 *   boolean	- true on completion
200
 ******/
201
function generate_config_cache($config) {
202
	global $g;
203
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
204
	fwrite($configcache, serialize($config));
205
	fclose($configcache);
206
	return true;
207
}
208

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

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

    
247

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

    
256

    
257
EOD;
258
		}
259

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

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

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

    
279
	/* don't use mount -u anymore
280
	   (doesn't sync the files properly and /bin/sync won't help either) */
281
	mwexec("/sbin/umount -f {$g['cf_path']}");
282
	$status = mwexec("/sbin/mount -w -o noatime {$g['cf_path']}");
283
	while($status == -1) {
284
		mwexec("fsck -y");
285
		$status = mwexec("/sbin/mount -w -o noatime {$g['cf_path']}");
286
	}
287
	/* if the platform is soekris or wrap, lets mount the
288
	   compact flash card. */
289
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx") {
290
		mwexec("/sbin/umount -f {$g['embeddedbootupslice']}");
291
		mwexec("/sbin/mount -w {$g['embeddedbootupslice']}");
292
	}
293
}
294

    
295
/****f* config/conf_mount_ro
296
 * NAME         
297
 *   conf_mount_ro - Mount filesystems readonly.
298
 * RESULT
299
 *   null        
300
 ******/
301
function conf_mount_ro() {
302
	global $g;
303

    
304
	if($g['booting'] == true) return;
305
	
306
	/* do not umount on cdrom platform */
307
	if($g['platform'] == "cdrom")
308
		return;	
309

    
310
	mwexec("/sbin/umount -f {$g['cf_path']}");
311
	mwexec("/sbin/mount -r {$g['cf_path']}");
312
	/* if the platform is soekris or wrap, lets unmount the
313
	   compact flash card. */
314
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx") {
315
		mwexec("/sbin/umount -f {$g['embeddedbootupslice']}");
316
		mwexec("/sbin/mount -r {$g['embeddedbootupslice']}");
317
	}
318
}
319

    
320
/****f* config/convert_config
321
 * NAME         
322
 *   convert_config - Attempt to update config.xml.
323
 * DESCRIPTION
324
 *   convert_config() reads the current global configuration
325
 *   and attempts to convert it to conform to the latest
326
 *   config.xml version. This allows major formatting changes
327
 *   to be made with a minimum of breakage.
328
 * RESULT
329
 *   null        
330
 ******/
331
/* convert configuration, if necessary */
332
function convert_config() {
333
	global $config, $g;
334

    
335
	if ($config['version'] == $g['latest_config'])
336
		return;		/* already at latest version */
337

    
338
	// Save off config version
339
	$prev_version = $config['version'];
340

    
341
	/* convert 1.0 -> 1.1 */
342
	if ($config['version'] == "1.0") {
343
		$opti = 1;
344
		$ifmap = array('lan' => 'lan', 'wan' => 'wan', 'pptp' => 'pptp');
345

    
346
		/* convert DMZ to optional, if necessary */
347
		if (isset($config['interfaces']['dmz'])) {
348

    
349
			$dmzcfg = &$config['interfaces']['dmz'];
350

    
351
			if ($dmzcfg['if']) {
352
				$config['interfaces']['opt' . $opti] = array();
353
				$optcfg = &$config['interfaces']['opt' . $opti];
354

    
355
				$optcfg['enable'] = $dmzcfg['enable'];
356
				$optcfg['descr'] = "DMZ";
357
				$optcfg['if'] = $dmzcfg['if'];
358
				$optcfg['ipaddr'] = $dmzcfg['ipaddr'];
359
				$optcfg['subnet'] = $dmzcfg['subnet'];
360

    
361
				$ifmap['dmz'] = "opt" . $opti;
362
				$opti++;
363
			}
364

    
365
			unset($config['interfaces']['dmz']);
366
		}
367

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

    
371
			if (!$config['interfaces']['wlan' . $i]['if']) {
372
				unset($config['interfaces']['wlan' . $i]);
373
				continue;
374
			}
375

    
376
			$wlancfg = &$config['interfaces']['wlan' . $i];
377
			$config['interfaces']['opt' . $opti] = array();
378
			$optcfg = &$config['interfaces']['opt' . $opti];
379

    
380
			$optcfg['enable'] = $wlancfg['enable'];
381
			$optcfg['descr'] = "WLAN" . $i;
382
			$optcfg['if'] = $wlancfg['if'];
383
			$optcfg['ipaddr'] = $wlancfg['ipaddr'];
384
			$optcfg['subnet'] = $wlancfg['subnet'];
385
			$optcfg['bridge'] = $wlancfg['bridge'];
386

    
387
			$optcfg['wireless'] = array();
388
			$optcfg['wireless']['mode'] = $wlancfg['mode'];
389
			$optcfg['wireless']['ssid'] = $wlancfg['ssid'];
390
			$optcfg['wireless']['channel'] = $wlancfg['channel'];
391
			$optcfg['wireless']['wep'] = $wlancfg['wep'];
392

    
393
			$ifmap['wlan' . $i] = "opt" . $opti;
394

    
395
			unset($config['interfaces']['wlan' . $i]);
396
			$opti++;
397
		}
398

    
399
		/* convert filter rules */
400
		$n = count($config['filter']['rule']);
401
		for ($i = 0; $i < $n; $i++) {
402

    
403
			$fr = &$config['filter']['rule'][$i];
404

    
405
			/* remap interface */
406
			if (array_key_exists($fr['interface'], $ifmap))
407
				$fr['interface'] = $ifmap[$fr['interface']];
408
			else {
409
				/* remove the rule */
410
				echo "\nWarning: filter rule removed " .
411
					"(interface '{$fr['interface']}' does not exist anymore).";
412
				unset($config['filter']['rule'][$i]);
413
				continue;
414
			}
415

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

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

    
443
		/* convert shaper rules */
444
		$n = count($config['pfqueueing']['rule']);
445
		if (is_array($config['pfqueueing']['rule']))
446
			for ($i = 0; $i < $n; $i++) {
447

    
448
			$fr = &$config['pfqueueing']['rule'][$i];
449

    
450
			/* remap interface */
451
			if (array_key_exists($fr['interface'], $ifmap))
452
				$fr['interface'] = $ifmap[$fr['interface']];
453
			else {
454
				/* remove the rule */
455
				echo "\nWarning: traffic shaper rule removed " .
456
					"(interface '{$fr['interface']}' does not exist anymore).";
457
				unset($config['pfqueueing']['rule'][$i]);
458
				continue;
459
			}
460

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

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

    
488
		$config['version'] = "1.1";
489
	}
490

    
491
	/* convert 1.1 -> 1.2 */
492
	if ($config['version'] == "1.1") {
493
		/* move LAN DHCP server config */
494
		$tmp = $config['dhcpd'];
495
		$config['dhcpd'] = array();
496
		$config['dhcpd']['lan'] = $tmp;
497

    
498
		/* encrypt password */
499
		$config['system']['password'] = crypt($config['system']['password']);
500

    
501
		$config['version'] = "1.2";
502
	}
503

    
504
	/* convert 1.2 -> 1.3 */
505
	if ($config['version'] == "1.2") {
506
		/* convert advanced outbound NAT config */
507
		for ($i = 0; isset($config['nat']['advancedoutbound']['rule'][$i]); $i++) {
508
			$curent = &$config['nat']['advancedoutbound']['rule'][$i];
509
			$src = $curent['source'];
510
			$curent['source'] = array();
511
			$curent['source']['network'] = $src;
512
			$curent['destination'] = array();
513
			$curent['destination']['any'] = true;
514
		}
515

    
516
		/* add an explicit type="pass" to all filter rules to make things consistent */
517
		for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
518
			$config['filter']['rule'][$i]['type'] = "pass";
519
		}
520

    
521
		$config['version'] = "1.3";
522
	}
523

    
524
	/* convert 1.3 -> 1.4 */
525
	if ($config['version'] == "1.3") {
526
		/* convert shaper rules (make pipes) */
527
		if (is_array($config['pfqueueing']['rule'])) {
528
			$config['pfqueueing']['pipe'] = array();
529

    
530
			for ($i = 0; isset($config['pfqueueing']['rule'][$i]); $i++) {
531
				$curent = &$config['pfqueueing']['rule'][$i];
532

    
533
				/* make new pipe and associate with this rule */
534
				$newpipe = array();
535
				$newpipe['descr'] = $curent['descr'];
536
				$newpipe['bandwidth'] = $curent['bandwidth'];
537
				$newpipe['delay'] = $curent['delay'];
538
				$newpipe['mask'] = $curent['mask'];
539
				$config['pfqueueing']['pipe'][$i] = $newpipe;
540

    
541
				$curent['targetpipe'] = $i;
542

    
543
				unset($curent['bandwidth']);
544
				unset($curent['delay']);
545
				unset($curent['mask']);
546
			}
547
		}
548

    
549
		$config['version'] = "1.4";
550
	}
551

    
552
	/* Convert 1.4 -> 1.5 */
553
	if ($config['version'] == "1.4") {
554

    
555
		/* Default route moved */
556
		if (isset($config['interfaces']['wan']['gateway']))
557
			if ($config['interfaces']['wan']['gateway'] <> "")
558
				$config['system']['gateway'] = $config['interfaces']['wan']['gateway'];
559
		unset($config['interfaces']['wan']['gateway']);
560

    
561
                /* Queues are no longer interface specific */
562
                if (isset($config['interfaces']['lan']['schedulertype']))
563
                        unset($config['interfaces']['lan']['schedulertype']);
564
                if (isset($config['interfaces']['wan']['schedulertype']))
565
                        unset($config['interfaces']['wan']['schedulertype']);
566

    
567
                for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
568
                        if(isset($config['interfaces']['opt' . $i]['schedulertype']))
569
                                unset($config['interfaces']['opt' . $i]['schedulertype']);
570
                }
571

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

    
575
	/* Convert 1.5 -> 1.6 */
576
	if ($config['version'] == "1.5") {
577
		/* Alternate firmware URL moved */
578
		if (isset($config['system']['firmwareurl']) && isset($config['system']['firmwarename'])) { // Only convert if *both* are defined.
579
			$config['system']['alt_firmware_url'] = array();
580
			$config['system']['alt_firmware_url']['enabled'] = "";
581
			$config['system']['alt_firmware_url']['firmware_base_url'] = $config['system']['firmwareurl'];
582
			$config['system']['alt_firmware_url']['firmware_filename'] = $config['system']['firmwarename'];
583
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
584
		} else {
585
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
586
		}
587

    
588
		$config['version'] = "1.6";
589
	}
590
	
591
	/* Convert 1.6 -> 1.7 */
592
	if ($config['version'] == "1.6") {
593
		/* wipe previous shaper configuration */
594
		unset($config['shaper']['queue']);
595
		unset($config['shaper']['rule']);
596
		unset($config['interfaces']['wan']['bandwidth']);
597
		unset($config['interfaces']['wan']['bandwidthtype']);
598
		unset($config['interfaces']['lan']['bandwidth']);
599
		unset($config['interfaces']['lan']['bandwidthtype']);		
600
		$config['shaper']['enable'] = FALSE;
601
		$config['version'] = "1.7";	
602
	}
603
	/* Convert 1.7 -> 1.8 */
604
	if ($config['version'] == "1.7") {
605
		if(isset($config['proxyarp']) && is_array($config['proxyarp']['proxyarpnet'])) {
606
			$proxyarp = &$config['proxyarp']['proxyarpnet'];
607
			foreach($proxyarp as $arpent){
608
				$vip = array();
609
				$vip['mode'] = "proxyarp";
610
				$vip['interface'] = $arpent['interface'];
611
				$vip['descr'] = $arpent['descr'];
612
				if (isset($arpent['range'])) {
613
					$vip['range'] = $arpent['range'];
614
					$vip['type'] = "range";
615
				} else {
616
					$subnet = explode('/', $arpent['network']);
617
					$vip['subnet'] = $subnet[0];
618
					if (isset($subnet[1])) {
619
						$vip['subnet_bits'] = $subnet[1];
620
						$vip['type'] = "network";
621
					} else {
622
						$vip['subnet_bits'] = "32";
623
						$vip['type'] = "single";
624
					}
625
				}
626
				$config['virtualip']['vip'][] = $vip;
627
			}
628
			unset($config['proxyarp']);
629
		}
630
		if(isset($config['installedpackages']) && isset($config['installedpackages']['carp']) && is_array($config['installedpackages']['carp']['config'])) {
631
			$carp = &$config['installedpackages']['carp']['config'];
632
			foreach($carp as $carpent){
633
				$vip = array();
634
				$vip['mode'] = "carp";
635
				$vip['interface'] = "AUTO";
636
				$vip['descr'] = "CARP vhid {$carpent['vhid']}";
637
				$vip['type'] = "single";
638
				$vip['vhid'] = $carpent['vhid'];
639
				$vip['advskew'] = $carpent['advskew'];
640
				$vip['password'] = $carpent['password'];
641
				$vip['subnet'] = $carpent['ipaddress'];
642
				$vip['subnet_bits'] = $carpent['netmask'];
643
				$config['virtualip']['vip'][] = $vip;
644
			}
645
			unset($config['installedpackages']['carp']);
646
		}
647
		/* Server NAT is no longer needed */
648
		unset($config['nat']['servernat']);
649
		
650
		$config['version'] = "1.8";
651
	}
652
	
653

    
654
	if ($prev_version != $config['version'])
655
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
656
}
657

    
658
/****f* config/write_config
659
 * NAME
660
 *   write_config - Backup and write the firewall configuration.
661
 * DESCRIPTION
662
 *   write_config() handles backing up the current configuration,
663
 *   applying changes, and regenerating the configuration cache.
664
 * INPUTS
665
 *   $desc	- string containing the a description of configuration changes
666
 *   $backup	- boolean: do not back up current configuration if false.
667
 * RESULT
668
 *   null       
669
 ******/
670
/* save the system configuration */
671
function write_config($desc="Unknown", $backup = true) {
672
	global $config, $g;
673

    
674
	if($backup) backup_config();
675

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

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

    
683
	$config['revision']['description'] = $desc;
684
	$config['revision']['time'] = $changetime;
685
	
686
	config_lock();
687
	conf_mount_rw();
688

    
689
	/* generate configuration XML */
690
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
691

    
692
	/* write new configuration */
693
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
694
	if (!$fd)
695
		die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
696
	fwrite($fd, $xmlconfig);
697
	fclose($fd);
698

    
699
	conf_mount_ro();
700
	config_unlock();
701

    
702
	// Always reparse the config after it's written - something is getting lost in serialize().
703
	$config = parse_config(true);
704
	return $config;
705
}
706

    
707
/****f* config/reset_factory_defaults
708
 * NAME
709
 *   reset_factory_defaults - Reset the system to its default configuration.
710
 * RESULT
711
 *   integer	- indicates completion
712
 ******/
713
function reset_factory_defaults() {
714
	global $g;
715

    
716
	config_lock();
717
	conf_mount_rw();
718

    
719
	/* create conf directory, if necessary */
720
	safe_mkdir("{$g['cf_conf_path']}");
721

    
722
	/* clear out /conf */
723
	$dh = opendir($g['conf_path']);
724
	while ($filename = readdir($dh)) {
725
		if (($filename != ".") && ($filename != "..")) {
726
			unlink_if_exists($g['conf_path'] . "/" . $filename);
727
		}
728
	}
729
	closedir($dh);
730

    
731
	/* copy default configuration */
732
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
733

    
734
	conf_mount_ro();
735
	config_unlock();
736

    
737
	return 0;
738
}
739

    
740
function config_restore($conffile) {
741
	global $config, $g;
742
       
743
        if (!file_exists($conffile))
744
                return 1;
745
        
746
        config_lock();
747
        conf_mount_rw();        
748
        
749
        backup_config();
750
        copy($conffile, "{$g['cf_conf_path']}/config.xml");
751
	$config = parse_config(true);
752
        write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
753
        
754
        conf_mount_ro();
755
        config_unlock();
756

    
757
        return 0;
758
}
759

    
760

    
761

    
762
function config_install($conffile) {
763
        global $config, $g;
764
        
765
        if (!file_exists($conffile))
766
                return 1;
767

    
768
	if($g['booting'] == true)
769
		echo "Installing configuration...\n";
770
 
771
        config_lock();
772
        conf_mount_rw();
773
        
774
        copy($conffile, "{$g['conf_path']}/config.xml");
775
                
776
        conf_mount_ro();
777
        config_unlock();
778

    
779
        return 0;
780
}
781

    
782
/* lock configuration file, decide that the lock file is stale after
783
   10 seconds */
784
function config_lock() {
785
	global $g, $process_lock;
786

    
787
	/* No need to continue if we're the ones holding the lock */
788
	if ($process_lock)
789
		return;
790

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

    
793
	$n = 0;
794
	while ($n < 10) {
795
		/* open the lock file in append mode to avoid race condition */
796
		if ($fd = @fopen($lockfile, "x")) {
797
			/* succeeded */
798
			$process_lock = true;
799
			fclose($fd);
800
			return;
801
		} else {
802
			/* file locked, wait and try again */
803
			$process_lock = false;
804
			sleep(1);
805
			$n++;
806
		}
807
	}
808
}
809

    
810
/* unlock configuration file */
811
function config_unlock() {
812
	global $g, $process_lock;
813

    
814
	$lockfile = "{$g['varrun_path']}/config.lock";
815
	$process_lock = false;
816

    
817
	unlink_if_exists($lockfile);
818
}
819

    
820
function set_networking_interfaces_ports() {
821
	global $noreboot;
822
	global $config;
823
	global $g;
824
	global $fp;
825

    
826
	$fp = fopen('php://stdin', 'r');
827

    
828
	$iflist = get_interface_list();
829

    
830
	echo <<<EOD
831

    
832
Valid interfaces are:
833

    
834

    
835
EOD;
836

    
837
	foreach ($iflist as $iface => $ifa) {
838
		echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
839
			$ifa['up'] ? "   (up)" : "");
840
	}
841

    
842
	echo <<<EOD
843

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

    
848
Do you want to set up VLANs now [y|n]?
849
EOD;
850

    
851
	if (strcasecmp(chop(fgets($fp)), "y") == 0)
852
		vlan_setup();
853

    
854
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
855

    
856
		echo "\n\nVLAN interfaces:\n\n";
857
		$i = 0;
858
		foreach ($config['vlans']['vlan'] as $vlan) {
859

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

    
863
			$iflist['vlan' . $i] = array();
864
			$i++;
865
		}
866
	}
867

    
868
	echo <<<EOD
869

    
870
If you do not know the names of your interfaces, you may choose to use
871
auto-detection... In that case, disconnect all interfaces now before
872
hitting a.   The system will then prompt you to plug in each nic to
873
autodetect.
874

    
875
EOD;
876

    
877
	do {
878
		echo "\nEnter the LAN interface name or 'a' for auto-detection: ";
879
		$lanif = chop(fgets($fp));
880
		if ($lanif === "") {
881
			exit(0);
882
		}
883

    
884
		if ($lanif === "a")
885
			$lanif = autodetect_interface("LAN", $fp);
886
		else if (!array_key_exists($lanif, $iflist)) {
887
			echo "\nInvalid interface name '{$lanif}'\n";
888
			unset($lanif);
889
			continue;
890
		}
891
	} while (!$lanif);
892

    
893
	do {
894
		echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
895
		$wanif = chop(fgets($fp));
896
		if ($wanif === "") {
897
			exit(0);
898
		}
899
		if ($wanif === "a")
900
			$wanif = autodetect_interface("WAN", $fp);
901
		else if (!array_key_exists($wanif, $iflist)) {
902
			echo "\nInvalid interface name '{$wanif}'\n";
903
			unset($wanif);
904
			continue;
905
		}
906
	} while (!$wanif);
907

    
908
	/* optional interfaces */
909
	$i = 0;
910
	$optif = array();
911

    
912
	while (1) {
913
		if ($optif[$i])
914
			$i++;
915
		$i1 = $i + 1;
916
		echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
917
			"(or nothing if finished): ";
918
		$optif[$i] = chop(fgets($fp));
919

    
920
		if ($optif[$i]) {
921
			if ($optif[$i] === "a") {
922
				$ad = autodetect_interface("Optional " . $i1, $fp);
923
				if ($ad)
924
					$optif[$i] = $ad;
925
				else
926
					unset($optif[$i]);
927
			} else if (!array_key_exists($optif[$i], $iflist)) {
928
				echo "\nInvalid interface name '{$optif[$i]}'\n";
929
				unset($optif[$i]);
930
				continue;
931
			}
932
		} else {
933
			unset($optif[$i]);
934
			break;
935
		}
936
	}
937

    
938
	/* check for double assignments */
939
	$ifarr = array_merge(array($lanif, $wanif), $optif);
940

    
941
	for ($i = 0; $i < (count($ifarr)-1); $i++) {
942
		for ($j = ($i+1); $j < count($ifarr); $j++) {
943
			if ($ifarr[$i] == $ifarr[$j]) {
944
				echo <<<EOD
945

    
946
Error: you cannot assign the same interface name twice!
947

    
948
EOD;
949

    
950
				exit(0);
951
			}
952
		}
953
	}
954

    
955
	echo <<<EOD
956

    
957
The interfaces will be assigned as follows:
958

    
959
LAN  -> {$lanif}
960
WAN  -> {$wanif}
961

    
962
EOD;
963

    
964
	for ($i = 0; $i < count($optif); $i++) {
965
		echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
966
	}
967

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

    
970
echo <<<EOD
971

    
972
Do you want to proceed [y|n]?
973
EOD;
974

    
975
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
976

    
977
		$config['interfaces']['lan']['if'] = $lanif;
978
		if (preg_match($g['wireless_regex'], $lanif)) {
979
			if (!is_array($config['interfaces']['lan']['wireless']))
980
				$config['interfaces']['lan']['wireless'] = array();
981
		} else {
982
			unset($config['interfaces']['lan']['wireless']);
983
		}
984
		
985
		$config['interfaces']['wan']['if'] = $wanif;
986
		if (preg_match($g['wireless_regex'], $wanif)) {
987
			if (!is_array($config['interfaces']['wan']['wireless']))
988
				$config['interfaces']['wan']['wireless'] = array();
989
		} else {
990
			unset($config['interfaces']['wan']['wireless']);
991
		}
992
		
993
		for ($i = 0; $i < count($optif); $i++) {
994
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
995
				$config['interfaces']['opt' . ($i+1)] = array();
996
			
997
			$config['interfaces']['opt' . ($i+1)]['if'] = $optif[$i];
998
			
999
			/* wireless interface? */
1000
			if (preg_match($g['wireless_regex'], $optif[$i])) {
1001
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
1002
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
1003
			} else {
1004
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
1005
			}
1006
			
1007
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
1008
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
1009
		}
1010
		
1011
		/* remove all other (old) optional interfaces */
1012
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
1013
			unset($config['interfaces']['opt' . ($i+1)]);
1014
		
1015
		write_config();
1016
		
1017
		echo <<<EOD
1018

    
1019

    
1020

    
1021
EOD;
1022

    
1023
		if($noreboot <> true)
1024
			system_reboot_sync();
1025
	}
1026
}
1027

    
1028
function autodetect_interface($ifname, $fp) {
1029
	$iflist_prev = get_interface_list();
1030
	echo <<<EOD
1031

    
1032
Connect the {$ifname} interface now and make sure that the link is up.
1033
Then press ENTER to continue.
1034

    
1035
EOD;
1036
	fgets($fp);
1037
	$iflist = get_interface_list();
1038

    
1039
	foreach ($iflist_prev as $ifn => $ifa) {
1040
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1041
			echo "Detected link-up on interface {$ifn}.\n";
1042
			return $ifn;
1043
		}
1044
	}
1045

    
1046
	echo "No link-up detected.\n";
1047

    
1048
	return null;
1049
}
1050

    
1051
function vlan_setup() {
1052
	global $iflist, $config, $g, $fp;
1053

    
1054
	$iflist = get_interface_list();
1055

    
1056
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1057

    
1058
	echo <<<EOD
1059

    
1060
WARNING: all existing VLANs will be cleared if you proceed!
1061

    
1062
Do you want to proceed [y|n]?
1063
EOD;
1064

    
1065
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1066
		return;
1067
	}
1068

    
1069
	$config['vlans']['vlan'] = array();
1070
	echo "\n";
1071

    
1072
	while (1) {
1073
		$vlan = array();
1074

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

    
1078
		if ($vlan['if']) {
1079
			if (!array_key_exists($vlan['if'], $iflist)) {
1080
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1081
				continue;
1082
			}
1083
		} else {
1084
			break;
1085
		}
1086

    
1087
		echo "Enter the VLAN tag (1-4094): ";
1088
		$vlan['tag'] = chop(fgets($fp));
1089

    
1090
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1091
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1092
			continue;
1093
		}
1094

    
1095
		$config['vlans']['vlan'][] = $vlan;
1096
	}
1097
}
1098

    
1099
function system_start_ftp_helpers() {
1100
	require_once("interfaces.inc");
1101
	global $config, $g;
1102

    
1103
	/* if the ftp proxy is disabled then killall pftpx and return */	
1104
	if($config['system']['disableftpproxy'] <> "") {
1105
		mwexec("/usr/bin/killall pftpx");
1106
		return;
1107
	}
1108
	
1109
	/* grab the current WAN IP address */
1110
	$wanip = get_current_wan_address();
1111
	
1112
	/* kill off pftpx if its already running */
1113
	if(is_process_running("pftpx"))
1114
		mwexec("/usr/bin/killall pftpx");
1115

    
1116
	/* if we do not have a wanip, launch with just the -g flag */	
1117
	if($wanip <> "") {
1118
		$command = "/usr/local/sbin/pftpx -g 8021 {$wanip}";
1119
		mwexec($command);
1120
	} else {
1121
		mwexec("/usr/local/sbin/pftpx -g 8021");
1122
	}
1123

    
1124
	if(!is_process_running("pftpx")) {
1125
		mwexec("/usr/local/sbin/pftpx -g 8021");
1126
		if(!is_process_running("pftpx")) {
1127
			log_error("Could not start PFTPX with command {$command}");
1128
			file_notice("FTP Proxy Startup Error", "PFTPX failed to start.  NOTE: FTP clients may not function correctly.", "", "");
1129
		}
1130
	}	
1131
}
1132

    
1133
function cleanup_backupcache($revisions = 30) {
1134
	global $g;
1135
	$i = false;
1136
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1137
		$backups = get_backups();
1138
		$newbaks = array();
1139
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1140
		$baktimes = $backups['versions'];
1141
		$tocache = array();
1142
		unset($backups['versions']);
1143
       		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1144
			$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));	
1145
                	if(!in_array($tocheck, $baktimes)) {
1146
				$i = true;
1147
				if($bootup) print " " . $tocheck . "a";
1148
				$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1149
				if($newxml['revision']['description'] == "") $newxml['revision']['description'] = "Unknown";
1150
				$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1151
			}
1152
        	}
1153
		foreach($backups as $checkbak) {
1154
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1155
				$newbaks[] = $checkbak;
1156
			} else {
1157
				$i = true;
1158
				if($bootup) print " " . $tocheck . "r";
1159
			}
1160
		}
1161
		foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);	
1162
		if(is_int($revisions) and (count($tocache) > $revisions)) {
1163
			$toslice = array_slice(array_keys($tocache), 0, $revisions);
1164
			foreach($toslice as $sliced) $newcache[$sliced] = $tocache[$sliced];
1165
			foreach($tocache as $version => $versioninfo) {
1166
				if(!in_array($version, array_keys($newcache))) {
1167
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1168
					if($bootup) print " " . $tocheck . "d";
1169
				}
1170
			}
1171
			$tocache = $newcache;
1172
		}
1173
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1174
        	fwrite($bakout, serialize($tocache));
1175
  	        fclose($bakout);
1176
	}
1177
	if($g['booting']) {
1178
		if($i) {
1179
			print "done.\n";
1180
		}
1181
	}
1182
}
1183
  	 
1184
function get_backups() { 	 
1185
	global $g;
1186

    
1187
        if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1188
                $confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1189
		$bakvers = array_keys($confvers);
1190
		$toreturn = array();
1191
		sort($bakvers);
1192
		// $bakvers = array_reverse($bakvers);
1193
		foreach(array_reverse($bakvers) as $bakver) $toreturn[] = array('time' => $bakver,
1194
								 'description' => $confvers[$bakver]['description']
1195
								);
1196
        } else { 	 
1197
                return false; 	 
1198
        }
1199
	$toreturn['versions'] = $bakvers;
1200
        return $toreturn;
1201
}
1202

    
1203
function backup_config() {
1204
	global $config, $g;
1205

    
1206
	/* XXX: temporary */
1207
	if($g['platform'] == "cdrom")
1208
		return;
1209

    
1210
	conf_mount_rw();
1211

    
1212
	/* Create backup directory if needed */
1213
	safe_mkdir("{$g['cf_conf_path']}/backup");
1214

    
1215
        if($config['revision']['time'] == "") {
1216
                $baktime = 0;
1217
        } else {
1218
                $baktime = $config['revision']['time'];
1219
        }
1220
        if($config['revision']['description'] == "") {
1221
                $bakdesc = "Unknown";
1222
        } else {
1223
                $bakdesc = $config['revision']['description'];
1224
        }
1225
        copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1226
        if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1227
                $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1228
        } else {
1229
                $backupcache = array();
1230
        }
1231
        $backupcache[$baktime] = array('description' => $bakdesc);
1232
        $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1233
        fwrite($bakout, serialize($backupcache));
1234
        fclose($bakout);
1235
	
1236
	conf_mount_ro();
1237
	
1238
	return true;
1239
}
1240

    
1241
function mute_kernel_msgs() {
1242
	exec("/sbin/conscontrol mute on");
1243
}
1244

    
1245
function unmute_kernel_msgs() {
1246
	exec("/sbin/conscontrol mute off");
1247
}
1248

    
1249
function start_devd() {
1250
	exec("/sbin/devd");
1251
}
1252

    
1253
?>
(3-3/22)