Project

General

Profile

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

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

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

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

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

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

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

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

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

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

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

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

    
68
		if (strstr($g['platform'], "cdrom")) {
69
			/* config is on floppy disk for CD-ROM version */
70
			$cfgdevice = $cfgpartition = "fd0";
71
			$dmesg = `dmesg -a`;
72
			if(ereg("da0", $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
	$status = mwexec("/sbin/umount -f {$g['cf_path']}");
282
	while($status < 0) {
283
		mwexec("/sbin/fsck -y");
284
		$status = mwexec("/sbin/umount -f {$g['cf_path']}");
285
	}
286

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

    
293
	/* if the platform is soekris or wrap, lets mount the
294
	   compact flash card. */
295
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx") {
296
		mwexec("/sbin/umount -f {$g['embeddedbootupslice']}");
297
		mwexec("/sbin/mount -w {$g['embeddedbootupslice']}");
298
	}
299
}
300

    
301
/****f* config/conf_mount_ro
302
 * NAME         
303
 *   conf_mount_ro - Mount filesystems readonly.
304
 * RESULT
305
 *   null        
306
 ******/
307
function conf_mount_ro() {
308
	global $g;
309

    
310
	if($g['booting'] == true) return;
311
	
312
	/* do not umount on cdrom platform */
313
	if($g['platform'] == "cdrom")
314
		return;	
315

    
316
	mwexec("/sbin/umount -f {$g['cf_path']}");
317
	mwexec("/sbin/mount -r {$g['cf_path']}");
318
	/* if the platform is soekris or wrap, lets unmount the
319
	   compact flash card. */
320
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx") {
321
		mwexec("/sbin/umount -f {$g['embeddedbootupslice']}");
322
		mwexec("/sbin/mount -r {$g['embeddedbootupslice']}");
323
	}
324
}
325

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

    
341
	if ($config['version'] == $g['latest_config'])
342
		return;		/* already at latest version */
343

    
344
	// Save off config version
345
	$prev_version = $config['version'];
346

    
347
	/* convert 1.0 -> 1.1 */
348
	if ($config['version'] == "1.0") {
349
		$opti = 1;
350
		$ifmap = array('lan' => 'lan', 'wan' => 'wan', 'pptp' => 'pptp');
351

    
352
		/* convert DMZ to optional, if necessary */
353
		if (isset($config['interfaces']['dmz'])) {
354

    
355
			$dmzcfg = &$config['interfaces']['dmz'];
356

    
357
			if ($dmzcfg['if']) {
358
				$config['interfaces']['opt' . $opti] = array();
359
				$optcfg = &$config['interfaces']['opt' . $opti];
360

    
361
				$optcfg['enable'] = $dmzcfg['enable'];
362
				$optcfg['descr'] = "DMZ";
363
				$optcfg['if'] = $dmzcfg['if'];
364
				$optcfg['ipaddr'] = $dmzcfg['ipaddr'];
365
				$optcfg['subnet'] = $dmzcfg['subnet'];
366

    
367
				$ifmap['dmz'] = "opt" . $opti;
368
				$opti++;
369
			}
370

    
371
			unset($config['interfaces']['dmz']);
372
		}
373

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

    
377
			if (!$config['interfaces']['wlan' . $i]['if']) {
378
				unset($config['interfaces']['wlan' . $i]);
379
				continue;
380
			}
381

    
382
			$wlancfg = &$config['interfaces']['wlan' . $i];
383
			$config['interfaces']['opt' . $opti] = array();
384
			$optcfg = &$config['interfaces']['opt' . $opti];
385

    
386
			$optcfg['enable'] = $wlancfg['enable'];
387
			$optcfg['descr'] = "WLAN" . $i;
388
			$optcfg['if'] = $wlancfg['if'];
389
			$optcfg['ipaddr'] = $wlancfg['ipaddr'];
390
			$optcfg['subnet'] = $wlancfg['subnet'];
391
			$optcfg['bridge'] = $wlancfg['bridge'];
392

    
393
			$optcfg['wireless'] = array();
394
			$optcfg['wireless']['mode'] = $wlancfg['mode'];
395
			$optcfg['wireless']['ssid'] = $wlancfg['ssid'];
396
			$optcfg['wireless']['channel'] = $wlancfg['channel'];
397
			$optcfg['wireless']['wep'] = $wlancfg['wep'];
398

    
399
			$ifmap['wlan' . $i] = "opt" . $opti;
400

    
401
			unset($config['interfaces']['wlan' . $i]);
402
			$opti++;
403
		}
404

    
405
		/* convert filter rules */
406
		$n = count($config['filter']['rule']);
407
		for ($i = 0; $i < $n; $i++) {
408

    
409
			$fr = &$config['filter']['rule'][$i];
410

    
411
			/* remap interface */
412
			if (array_key_exists($fr['interface'], $ifmap))
413
				$fr['interface'] = $ifmap[$fr['interface']];
414
			else {
415
				/* remove the rule */
416
				echo "\nWarning: filter rule removed " .
417
					"(interface '{$fr['interface']}' does not exist anymore).";
418
				unset($config['filter']['rule'][$i]);
419
				continue;
420
			}
421

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

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

    
449
		/* convert shaper rules */
450
		$n = count($config['pfqueueing']['rule']);
451
		if (is_array($config['pfqueueing']['rule']))
452
			for ($i = 0; $i < $n; $i++) {
453

    
454
			$fr = &$config['pfqueueing']['rule'][$i];
455

    
456
			/* remap interface */
457
			if (array_key_exists($fr['interface'], $ifmap))
458
				$fr['interface'] = $ifmap[$fr['interface']];
459
			else {
460
				/* remove the rule */
461
				echo "\nWarning: traffic shaper rule removed " .
462
					"(interface '{$fr['interface']}' does not exist anymore).";
463
				unset($config['pfqueueing']['rule'][$i]);
464
				continue;
465
			}
466

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

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

    
494
		$config['version'] = "1.1";
495
	}
496

    
497
	/* convert 1.1 -> 1.2 */
498
	if ($config['version'] == "1.1") {
499
		/* move LAN DHCP server config */
500
		$tmp = $config['dhcpd'];
501
		$config['dhcpd'] = array();
502
		$config['dhcpd']['lan'] = $tmp;
503

    
504
		/* encrypt password */
505
		$config['system']['password'] = crypt($config['system']['password']);
506

    
507
		$config['version'] = "1.2";
508
	}
509

    
510
	/* convert 1.2 -> 1.3 */
511
	if ($config['version'] == "1.2") {
512
		/* convert advanced outbound NAT config */
513
		for ($i = 0; isset($config['nat']['advancedoutbound']['rule'][$i]); $i++) {
514
			$curent = &$config['nat']['advancedoutbound']['rule'][$i];
515
			$src = $curent['source'];
516
			$curent['source'] = array();
517
			$curent['source']['network'] = $src;
518
			$curent['destination'] = array();
519
			$curent['destination']['any'] = true;
520
		}
521

    
522
		/* add an explicit type="pass" to all filter rules to make things consistent */
523
		for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
524
			$config['filter']['rule'][$i]['type'] = "pass";
525
		}
526

    
527
		$config['version'] = "1.3";
528
	}
529

    
530
	/* convert 1.3 -> 1.4 */
531
	if ($config['version'] == "1.3") {
532
		/* convert shaper rules (make pipes) */
533
		if (is_array($config['pfqueueing']['rule'])) {
534
			$config['pfqueueing']['pipe'] = array();
535

    
536
			for ($i = 0; isset($config['pfqueueing']['rule'][$i]); $i++) {
537
				$curent = &$config['pfqueueing']['rule'][$i];
538

    
539
				/* make new pipe and associate with this rule */
540
				$newpipe = array();
541
				$newpipe['descr'] = $curent['descr'];
542
				$newpipe['bandwidth'] = $curent['bandwidth'];
543
				$newpipe['delay'] = $curent['delay'];
544
				$newpipe['mask'] = $curent['mask'];
545
				$config['pfqueueing']['pipe'][$i] = $newpipe;
546

    
547
				$curent['targetpipe'] = $i;
548

    
549
				unset($curent['bandwidth']);
550
				unset($curent['delay']);
551
				unset($curent['mask']);
552
			}
553
		}
554

    
555
		$config['version'] = "1.4";
556
	}
557

    
558
	/* Convert 1.4 -> 1.5 */
559
	if ($config['version'] == "1.4") {
560

    
561
		/* Default route moved */
562
		if (isset($config['interfaces']['wan']['gateway']))
563
			if ($config['interfaces']['wan']['gateway'] <> "")
564
				$config['system']['gateway'] = $config['interfaces']['wan']['gateway'];
565
		unset($config['interfaces']['wan']['gateway']);
566

    
567
                /* Queues are no longer interface specific */
568
                if (isset($config['interfaces']['lan']['schedulertype']))
569
                        unset($config['interfaces']['lan']['schedulertype']);
570
                if (isset($config['interfaces']['wan']['schedulertype']))
571
                        unset($config['interfaces']['wan']['schedulertype']);
572

    
573
                for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
574
                        if(isset($config['interfaces']['opt' . $i]['schedulertype']))
575
                                unset($config['interfaces']['opt' . $i]['schedulertype']);
576
                }
577

    
578
		$config['version'] = "1.5";
579
	}
580

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

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

    
664
	/* Convert 1.8 -> 1.9 */
665
	if ($config['version'] == "1.8") {
666
		$config['theme']="metallic";
667
		$config['version'] = "1.9";
668
	}
669

    
670
	if ($prev_version != $config['version'])
671
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
672
}
673

    
674
/****f* config/write_config
675
 * NAME
676
 *   write_config - Backup and write the firewall configuration.
677
 * DESCRIPTION
678
 *   write_config() handles backing up the current configuration,
679
 *   applying changes, and regenerating the configuration cache.
680
 * INPUTS
681
 *   $desc	- string containing the a description of configuration changes
682
 *   $backup	- boolean: do not back up current configuration if false.
683
 * RESULT
684
 *   null       
685
 ******/
686
/* save the system configuration */
687
function write_config($desc="Unknown", $backup = true) {
688
	global $config, $g;
689

    
690
	if($backup) backup_config();
691

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

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

    
699
	$config['revision']['description'] = $desc;
700
	$config['revision']['time'] = $changetime;
701
	
702
	config_lock();
703
	conf_mount_rw();
704

    
705
	/* generate configuration XML */
706
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
707

    
708
	/* write new configuration */
709
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
710
	if (!$fd)
711
		die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
712
	fwrite($fd, $xmlconfig);
713
	fclose($fd);
714

    
715
	if($g['booting'] <> true) {
716
		conf_mount_ro();
717
	}
718

    
719
	config_unlock();
720

    
721
	// Always reparse the config after it's written - something is getting lost in serialize().
722
	$config = parse_config(true);
723
	return $config;
724
}
725

    
726
/****f* config/reset_factory_defaults
727
 * NAME
728
 *   reset_factory_defaults - Reset the system to its default configuration.
729
 * RESULT
730
 *   integer	- indicates completion
731
 ******/
732
function reset_factory_defaults() {
733
	global $g;
734

    
735
	config_lock();
736
	conf_mount_rw();
737

    
738
	/* create conf directory, if necessary */
739
	safe_mkdir("{$g['cf_conf_path']}");
740

    
741
	/* clear out /conf */
742
	$dh = opendir($g['conf_path']);
743
	while ($filename = readdir($dh)) {
744
		if (($filename != ".") && ($filename != "..")) {
745
			unlink_if_exists($g['conf_path'] . "/" . $filename);
746
		}
747
	}
748
	closedir($dh);
749

    
750
	/* copy default configuration */
751
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
752
	
753
	/* call the wizard */
754
	touch("/trigger_initial_wizard");
755
	
756
	conf_mount_ro();
757
	config_unlock();
758

    
759
	return 0;
760
}
761

    
762
function config_restore($conffile) {
763
	global $config, $g;
764
       
765
        if (!file_exists($conffile))
766
                return 1;
767
        
768
        config_lock();
769
        conf_mount_rw();        
770
        
771
        backup_config();
772
        copy($conffile, "{$g['cf_conf_path']}/config.xml");
773
	$config = parse_config(true);
774
        write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
775
        
776
        conf_mount_ro();
777
        config_unlock();
778

    
779
        return 0;
780
}
781

    
782

    
783

    
784
function config_install($conffile) {
785
        global $config, $g;
786
        
787
        if (!file_exists($conffile))
788
                return 1;
789

    
790
	if($g['booting'] == true)
791
		echo "Installing configuration...\n";
792
 
793
        config_lock();
794
        conf_mount_rw();
795
        
796
        copy($conffile, "{$g['conf_path']}/config.xml");
797
                
798
        conf_mount_ro();
799
        config_unlock();
800

    
801
        return 0;
802
}
803

    
804
/* lock configuration file, decide that the lock file is stale after
805
   10 seconds */
806
function config_lock() {
807
	global $g, $process_lock;
808

    
809
	/* No need to continue if we're the ones holding the lock */
810
	if ($process_lock)
811
		return;
812

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

    
815
	$n = 0;
816
	while ($n < 10) {
817
		/* open the lock file in append mode to avoid race condition */
818
		if ($fd = @fopen($lockfile, "x")) {
819
			/* succeeded */
820
			$process_lock = true;
821
			fclose($fd);
822
			return;
823
		} else {
824
			/* file locked, wait and try again */
825
			$process_lock = false;
826
			sleep(1);
827
			$n++;
828
		}
829
	}
830
}
831

    
832
/* unlock configuration file */
833
function config_unlock() {
834
	global $g, $process_lock;
835

    
836
	$lockfile = "{$g['varrun_path']}/config.lock";
837
	$process_lock = false;
838

    
839
	unlink_if_exists($lockfile);
840
}
841

    
842
function set_networking_interfaces_ports() {
843
	global $noreboot;
844
	global $config;
845
	global $g;
846
	global $fp;
847

    
848
	$fp = fopen('php://stdin', 'r');
849

    
850
	$iflist = get_interface_list();
851

    
852
	echo <<<EOD
853

    
854
Valid interfaces are:
855

    
856

    
857
EOD;
858

    
859
	foreach ($iflist as $iface => $ifa) {
860
		echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
861
			$ifa['up'] ? "   (up)" : "");
862
	}
863

    
864
	echo <<<EOD
865

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

    
870
Do you want to set up VLANs now [y|n]?
871
EOD;
872

    
873
	if (strcasecmp(chop(fgets($fp)), "y") == 0)
874
		vlan_setup();
875

    
876
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
877

    
878
		echo "\n\nVLAN interfaces:\n\n";
879
		$i = 0;
880
		foreach ($config['vlans']['vlan'] as $vlan) {
881

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

    
885
			$iflist['vlan' . $i] = array();
886
			$i++;
887
		}
888
	}
889

    
890
	echo <<<EOD
891

    
892
If you do not know the names of your interfaces, you may choose to use
893
auto-detection... In that case, disconnect all interfaces now before
894
hitting a.   The system will then prompt you to plug in each nic to
895
autodetect.
896

    
897
EOD;
898

    
899
	do {
900
		echo "\nEnter the LAN interface name or 'a' for auto-detection: ";
901
		$lanif = chop(fgets($fp));
902
		if ($lanif === "") {
903
			exit(0);
904
		}
905

    
906
		if ($lanif === "a")
907
			$lanif = autodetect_interface("LAN", $fp);
908
		else if (!array_key_exists($lanif, $iflist)) {
909
			echo "\nInvalid interface name '{$lanif}'\n";
910
			unset($lanif);
911
			continue;
912
		}
913
	} while (!$lanif);
914

    
915
	do {
916
		echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
917
		$wanif = chop(fgets($fp));
918
		if ($wanif === "") {
919
			exit(0);
920
		}
921
		if ($wanif === "a")
922
			$wanif = autodetect_interface("WAN", $fp);
923
		else if (!array_key_exists($wanif, $iflist)) {
924
			echo "\nInvalid interface name '{$wanif}'\n";
925
			unset($wanif);
926
			continue;
927
		}
928
	} while (!$wanif);
929

    
930
	/* optional interfaces */
931
	$i = 0;
932
	$optif = array();
933

    
934
	while (1) {
935
		if ($optif[$i])
936
			$i++;
937
		$i1 = $i + 1;
938
		echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
939
			"(or nothing if finished): ";
940
		$optif[$i] = chop(fgets($fp));
941

    
942
		if ($optif[$i]) {
943
			if ($optif[$i] === "a") {
944
				$ad = autodetect_interface("Optional " . $i1, $fp);
945
				if ($ad)
946
					$optif[$i] = $ad;
947
				else
948
					unset($optif[$i]);
949
			} else if (!array_key_exists($optif[$i], $iflist)) {
950
				echo "\nInvalid interface name '{$optif[$i]}'\n";
951
				unset($optif[$i]);
952
				continue;
953
			}
954
		} else {
955
			unset($optif[$i]);
956
			break;
957
		}
958
	}
959

    
960
	/* check for double assignments */
961
	$ifarr = array_merge(array($lanif, $wanif), $optif);
962

    
963
	for ($i = 0; $i < (count($ifarr)-1); $i++) {
964
		for ($j = ($i+1); $j < count($ifarr); $j++) {
965
			if ($ifarr[$i] == $ifarr[$j]) {
966
				echo <<<EOD
967

    
968
Error: you cannot assign the same interface name twice!
969

    
970
EOD;
971

    
972
				exit(0);
973
			}
974
		}
975
	}
976

    
977
	echo <<<EOD
978

    
979
The interfaces will be assigned as follows:
980

    
981
LAN  -> {$lanif}
982
WAN  -> {$wanif}
983

    
984
EOD;
985

    
986
	for ($i = 0; $i < count($optif); $i++) {
987
		echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
988
	}
989

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

    
992
echo <<<EOD
993

    
994
Do you want to proceed [y|n]?
995
EOD;
996

    
997
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
998

    
999
		$config['interfaces']['lan']['if'] = $lanif;
1000
		if (preg_match($g['wireless_regex'], $lanif)) {
1001
			if (!is_array($config['interfaces']['lan']['wireless']))
1002
				$config['interfaces']['lan']['wireless'] = array();
1003
		} else {
1004
			unset($config['interfaces']['lan']['wireless']);
1005
		}
1006
		
1007
		$config['interfaces']['wan']['if'] = $wanif;
1008
		if (preg_match($g['wireless_regex'], $wanif)) {
1009
			if (!is_array($config['interfaces']['wan']['wireless']))
1010
				$config['interfaces']['wan']['wireless'] = array();
1011
		} else {
1012
			unset($config['interfaces']['wan']['wireless']);
1013
		}
1014
		
1015
		for ($i = 0; $i < count($optif); $i++) {
1016
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
1017
				$config['interfaces']['opt' . ($i+1)] = array();
1018
			
1019
			$config['interfaces']['opt' . ($i+1)]['if'] = $optif[$i];
1020
			
1021
			/* wireless interface? */
1022
			if (preg_match($g['wireless_regex'], $optif[$i])) {
1023
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
1024
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
1025
			} else {
1026
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
1027
			}
1028
			
1029
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
1030
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
1031
		}
1032
		
1033
		/* remove all other (old) optional interfaces */
1034
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
1035
			unset($config['interfaces']['opt' . ($i+1)]);
1036
		
1037
		conf_mount_rw();
1038
		
1039
		/* call the wizard */
1040
		touch("/trigger_initial_wizard");
1041
		
1042
		write_config();
1043
		
1044
		echo <<<EOD
1045

    
1046

    
1047

    
1048
EOD;
1049

    
1050
		if($noreboot <> true)
1051
			system_reboot_sync();
1052
	}
1053
}
1054

    
1055
function autodetect_interface($ifname, $fp) {
1056
	$iflist_prev = get_interface_list();
1057
	echo <<<EOD
1058

    
1059
Connect the {$ifname} interface now and make sure that the link is up.
1060
Then press ENTER to continue.
1061

    
1062
EOD;
1063
	fgets($fp);
1064
	$iflist = get_interface_list();
1065

    
1066
	foreach ($iflist_prev as $ifn => $ifa) {
1067
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1068
			echo "Detected link-up on interface {$ifn}.\n";
1069
			return $ifn;
1070
		}
1071
	}
1072

    
1073
	echo "No link-up detected.\n";
1074

    
1075
	return null;
1076
}
1077

    
1078
function vlan_setup() {
1079
	global $iflist, $config, $g, $fp;
1080

    
1081
	$iflist = get_interface_list();
1082

    
1083
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1084

    
1085
	echo <<<EOD
1086

    
1087
WARNING: all existing VLANs will be cleared if you proceed!
1088

    
1089
Do you want to proceed [y|n]?
1090
EOD;
1091

    
1092
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1093
		return;
1094
	}
1095

    
1096
	$config['vlans']['vlan'] = array();
1097
	echo "\n";
1098

    
1099
	while (1) {
1100
		$vlan = array();
1101

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

    
1105
		if ($vlan['if']) {
1106
			if (!array_key_exists($vlan['if'], $iflist)) {
1107
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1108
				continue;
1109
			}
1110
		} else {
1111
			break;
1112
		}
1113

    
1114
		echo "Enter the VLAN tag (1-4094): ";
1115
		$vlan['tag'] = chop(fgets($fp));
1116

    
1117
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1118
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1119
			continue;
1120
		}
1121

    
1122
		$config['vlans']['vlan'][] = $vlan;
1123
	}
1124
}
1125

    
1126
function system_start_ftp_helpers() {
1127
	require_once("interfaces.inc");
1128
	global $config, $g;
1129

    
1130
	/* if the ftp proxy is disabled then killall pftpx and return */	
1131
	if($config['system']['disableftpproxy'] <> "") {
1132
		mwexec("/usr/bin/killall pftpx");
1133
		return;
1134
	}
1135
	
1136
	/* grab the current WAN IP address */
1137
	$wanip = get_current_wan_address();
1138
	
1139
	/* kill off pftpx if its already running */
1140
	if(is_process_running("pftpx"))
1141
		mwexec("/usr/bin/killall pftpx");
1142

    
1143
	/* if we do not have a wanip, launch with just the -g flag */	
1144
	if($wanip <> "") {
1145
		$command = "/usr/local/sbin/pftpx -g 8021 {$wanip}";
1146
		mwexec($command);
1147
	} else {
1148
		mwexec("/usr/local/sbin/pftpx -g 8021");
1149
	}
1150

    
1151
	if(!is_process_running("pftpx")) {
1152
		mwexec("/usr/local/sbin/pftpx -g 8021");
1153
		if(!is_process_running("pftpx")) {
1154
			log_error("Could not start PFTPX with command {$command}");
1155
			file_notice("FTP Proxy Startup Error", "PFTPX failed to start.  NOTE: FTP clients may not function correctly.", "", "");
1156
		}
1157
	}	
1158
}
1159

    
1160
function cleanup_backupcache($revisions = 30) {
1161
	global $g;
1162
	$i = false;
1163
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1164
		$backups = get_backups();
1165
		$newbaks = array();
1166
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1167
		$baktimes = $backups['versions'];
1168
		$tocache = array();
1169
		unset($backups['versions']);
1170
       		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1171
			$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));	
1172
                	if(!in_array($tocheck, $baktimes)) {
1173
				$i = true;
1174
				if($bootup) print " " . $tocheck . "a";
1175
				$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1176
				if($newxml['revision']['description'] == "") $newxml['revision']['description'] = "Unknown";
1177
				$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1178
			}
1179
        	}
1180
		foreach($backups as $checkbak) {
1181
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1182
				$newbaks[] = $checkbak;
1183
			} else {
1184
				$i = true;
1185
				if($bootup) print " " . $tocheck . "r";
1186
			}
1187
		}
1188
		foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);	
1189
		if(is_int($revisions) and (count($tocache) > $revisions)) {
1190
			$toslice = array_slice(array_keys($tocache), 0, $revisions);
1191
			foreach($toslice as $sliced) $newcache[$sliced] = $tocache[$sliced];
1192
			foreach($tocache as $version => $versioninfo) {
1193
				if(!in_array($version, array_keys($newcache))) {
1194
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1195
					if($bootup) print " " . $tocheck . "d";
1196
				}
1197
			}
1198
			$tocache = $newcache;
1199
		}
1200
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1201
        	fwrite($bakout, serialize($tocache));
1202
  	        fclose($bakout);
1203
	}
1204
	if($g['booting']) {
1205
		if($i) {
1206
			print "done.\n";
1207
		}
1208
	}
1209
}
1210
  	 
1211
function get_backups() { 	 
1212
	global $g;
1213

    
1214
        if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1215
                $confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1216
		$bakvers = array_keys($confvers);
1217
		$toreturn = array();
1218
		sort($bakvers);
1219
		// $bakvers = array_reverse($bakvers);
1220
		foreach(array_reverse($bakvers) as $bakver) $toreturn[] = array('time' => $bakver,
1221
								 'description' => $confvers[$bakver]['description']
1222
								);
1223
        } else { 	 
1224
                return false; 	 
1225
        }
1226
	$toreturn['versions'] = $bakvers;
1227
        return $toreturn;
1228
}
1229

    
1230
function backup_config() {
1231
	global $config, $g;
1232

    
1233
	if($g['platform'] == "cdrom")
1234
		return;
1235

    
1236
	conf_mount_rw();
1237

    
1238
	/* Create backup directory if needed */
1239
	safe_mkdir("{$g['cf_conf_path']}/backup");
1240

    
1241
        if($config['revision']['time'] == "") {
1242
                $baktime = 0;
1243
        } else {
1244
                $baktime = $config['revision']['time'];
1245
        }
1246
        if($config['revision']['description'] == "") {
1247
                $bakdesc = "Unknown";
1248
        } else {
1249
                $bakdesc = $config['revision']['description'];
1250
        }
1251
        copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1252
        if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1253
                $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1254
        } else {
1255
                $backupcache = array();
1256
        }
1257
        $backupcache[$baktime] = array('description' => $bakdesc);
1258
        $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1259
        fwrite($bakout, serialize($backupcache));
1260
        fclose($bakout);
1261
	
1262
	conf_mount_ro();
1263
	
1264
	return true;
1265
}
1266

    
1267
function mute_kernel_msgs() {
1268
	exec("/sbin/conscontrol mute on");
1269
}
1270

    
1271
function unmute_kernel_msgs() {
1272
	exec("/sbin/conscontrol mute off");
1273
}
1274

    
1275
function start_devd() {
1276
	exec("/sbin/devd");
1277
}
1278

    
1279
?>
(3-3/22)