Project

General

Profile

Download (31.5 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
/* include globals/utility/XML parser files */
42
require_once("globals.inc");
43
require_once("util.inc");
44
require_once("pfsense-utils.inc");
45
require_once("xmlparse.inc");
46

    
47
/* read platform */
48
if (file_exists("{$g['etc_path']}/platform")) {
49
	$g['platform'] = chop(file_get_contents("{$g['etc_path']}/platform"));
50
} else {
51
	$g['platform'] = "unknown";
52
}
53

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

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

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

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

    
92
					if ($cfgdevice)
93
						break;
94
				}
95
				if (mwexec("/sbin/mount -r /dev/{$mountdisk}d {$g['cf_path']}") == 0) {
96
					if (file_exists("{$g['cf_conf_path']}/config.xml")) {
97
						/* found it */
98
						$cfgdevice = $mountdisk;
99
						$cfgpartition = $cfgdevice . "d";
100
						$cfgfstype = "ufs";
101
						echo "Found configuration on $cfgdevice.\n";
102
					}
103

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

    
106
					if ($cfgdevice)
107
						break;
108
				}
109
			}
110
		}
111

    
112
		if (!$cfgdevice) {
113
			/* no device found, print an error and die */
114
			echo <<<EOD
115

    
116

    
117
*******************************************************************************
118
* FATAL ERROR                                                                 *
119
* The device that contains the configuration file (config.xml) could not be   *
120
* found. pfSense cannot continue booting.                                     *
121
*******************************************************************************
122

    
123

    
124
EOD;
125

    
126
			mwexec("/sbin/halt");
127
			exit;
128
		}
129

    
130
		/* write device name to a file for rc.firmware */
131
		$fd = fopen("{$g['varetc_path']}/cfdevice", "w");
132
		fwrite($fd, $cfgdevice . "\n");
133
		fclose($fd);
134

    
135
		/* write out an fstab */
136
		$fd = fopen("{$g['etc_path']}/fstab", "w");
137

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

    
141
		fwrite($fd, $fstab);
142
		fclose($fd);
143
	}
144

    
145
	/* mount all filesystems */
146
	mwexec("/sbin/mount -a");
147
}
148

    
149
$config = parse_config();
150

    
151
/****f* config/parse_config
152
 * NAME
153
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
154
 * INPUTS
155
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
156
 * RESULT
157
 *   $config      - array containing all configuration variables
158
 ******/
159
function parse_config($parse = false) {
160
	global $g;
161

    
162
	config_lock();
163
	if(!$parse) {
164
		if(file_exists($g['tmp_path'] . '/config.cache')) {
165
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
166
			if(is_null($config)) {
167
				config_unlock();
168
				parse_config(true);
169
			}
170
		} else {
171
			config_unlock();
172
			$config = parse_config(true);
173
		}
174
	} else {
175
		$config = parse_xml_config($g['conf_path'] . '/config.xml', $g['xml_rootobj']);
176
		generate_config_cache($config);
177
	}
178
	
179
	/* ugly hack!  config.cache is really borked.  don't use until its fixed. */
180
	//$config = parse_xml_config($g['conf_path'] . '/config.xml', $g['xml_rootobj']);
181

    
182
	alias_make_table($config);
183
	config_unlock();
184
	return $config;
185
}
186

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

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

    
235
	parse_config(true);
236
	
237
	if ((float)$config['version'] > (float)$g['latest_config']) {
238
		echo <<<EOD
239

    
240

    
241
*******************************************************************************
242
* WARNING!                                                                    *
243
* The current configuration has been created with a newer version of pfSense  *
244
* than this one! This can lead to serious misbehavior and even security       *
245
* holes! You are urged to either upgrade to a newer version of pfSense or     *
246
* revert to the default configuration immediately!                            *
247
*******************************************************************************
248

    
249

    
250
EOD;
251
		}
252

    
253
	/* make alias table (for faster lookups) */
254
	alias_make_table($config);
255
	config_unlock();
256
}
257

    
258
/****f* config/conf_mount_rw
259
 * NAME
260
 *   conf_mount_rw - Mount filesystems read/write.
261
 * RESULT
262
 *   null
263
 ******/
264
/* mount flash card read/write */
265
function conf_mount_rw() {
266
	global $g;
267

    
268
	/* don't use mount -u anymore
269
	   (doesn't sync the files properly and /bin/sync won't help either) */
270
	mwexec("/sbin/umount -f {$g['cf_path']}");
271
	$status = mwexec("/sbin/mount -w -o noatime {$g['cf_path']}");
272
	while($status == -1) {
273
		mwexec("fsck -y");
274
		$status = mwexec("/sbin/mount -w -o noatime {$g['cf_path']}");
275
	}
276
	/* if the platform is soekris or wrap, lets mount the
277
	   compact flash card. */
278
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx") {
279
		mwexec("/sbin/umount -f {$g['embeddedbootupslice']}");
280
		mwexec("/sbin/mount -w {$g['embeddedbootupslice']}");
281
	}
282
}
283

    
284
/****f* config/conf_mount_ro
285
 * NAME         
286
 *   conf_mount_ro - Mount filesystems readonly.
287
 * RESULT
288
 *   null        
289
 ******/
290
function conf_mount_ro() {
291
	global $g, $do_not_mount_ro;
292

    
293
	if($g['booting'] == true) return;
294

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

    
305
/****f* config/convert_config
306
 * NAME         
307
 *   convert_config - Attempt to update config.xml.
308
 * DESCRIPTION
309
 *   convert_config() reads the current global configuration
310
 *   and attempts to convert it to conform to the latest
311
 *   config.xml version. This allows major formatting changes
312
 *   to be made with a minimum of breakage.
313
 * RESULT
314
 *   null        
315
 ******/
316
/* convert configuration, if necessary */
317
function convert_config() {
318
	global $config, $pkg_config, $g;
319

    
320
	if ($config['version'] == $g['latest_config'])
321
		return;		/* already at latest version */
322

    
323
	// Save off config version
324
	$prev_version = $config['version'];
325

    
326
	/* convert 1.0 -> 1.1 */
327
	if ($config['version'] == "1.0") {
328
		$opti = 1;
329
		$ifmap = array('lan' => 'lan', 'wan' => 'wan', 'pptp' => 'pptp');
330

    
331
		/* convert DMZ to optional, if necessary */
332
		if (isset($config['interfaces']['dmz'])) {
333

    
334
			$dmzcfg = &$config['interfaces']['dmz'];
335

    
336
			if ($dmzcfg['if']) {
337
				$config['interfaces']['opt' . $opti] = array();
338
				$optcfg = &$config['interfaces']['opt' . $opti];
339

    
340
				$optcfg['enable'] = $dmzcfg['enable'];
341
				$optcfg['descr'] = "DMZ";
342
				$optcfg['if'] = $dmzcfg['if'];
343
				$optcfg['ipaddr'] = $dmzcfg['ipaddr'];
344
				$optcfg['subnet'] = $dmzcfg['subnet'];
345

    
346
				$ifmap['dmz'] = "opt" . $opti;
347
				$opti++;
348
			}
349

    
350
			unset($config['interfaces']['dmz']);
351
		}
352

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

    
356
			if (!$config['interfaces']['wlan' . $i]['if']) {
357
				unset($config['interfaces']['wlan' . $i]);
358
				continue;
359
			}
360

    
361
			$wlancfg = &$config['interfaces']['wlan' . $i];
362
			$config['interfaces']['opt' . $opti] = array();
363
			$optcfg = &$config['interfaces']['opt' . $opti];
364

    
365
			$optcfg['enable'] = $wlancfg['enable'];
366
			$optcfg['descr'] = "WLAN" . $i;
367
			$optcfg['if'] = $wlancfg['if'];
368
			$optcfg['ipaddr'] = $wlancfg['ipaddr'];
369
			$optcfg['subnet'] = $wlancfg['subnet'];
370
			$optcfg['bridge'] = $wlancfg['bridge'];
371

    
372
			$optcfg['wireless'] = array();
373
			$optcfg['wireless']['mode'] = $wlancfg['mode'];
374
			$optcfg['wireless']['ssid'] = $wlancfg['ssid'];
375
			$optcfg['wireless']['channel'] = $wlancfg['channel'];
376
			$optcfg['wireless']['wep'] = $wlancfg['wep'];
377

    
378
			$ifmap['wlan' . $i] = "opt" . $opti;
379

    
380
			unset($config['interfaces']['wlan' . $i]);
381
			$opti++;
382
		}
383

    
384
		/* convert filter rules */
385
		$n = count($config['filter']['rule']);
386
		for ($i = 0; $i < $n; $i++) {
387

    
388
			$fr = &$config['filter']['rule'][$i];
389

    
390
			/* remap interface */
391
			if (array_key_exists($fr['interface'], $ifmap))
392
				$fr['interface'] = $ifmap[$fr['interface']];
393
			else {
394
				/* remove the rule */
395
				echo "\nWarning: filter rule removed " .
396
					"(interface '{$fr['interface']}' does not exist anymore).";
397
				unset($config['filter']['rule'][$i]);
398
				continue;
399
			}
400

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

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

    
428
		/* convert shaper rules */
429
		$n = count($config['pfqueueing']['rule']);
430
		if (is_array($config['pfqueueing']['rule']))
431
			for ($i = 0; $i < $n; $i++) {
432

    
433
			$fr = &$config['pfqueueing']['rule'][$i];
434

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

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

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

    
473
		$config['version'] = "1.1";
474
	}
475

    
476
	/* convert 1.1 -> 1.2 */
477
	if ($config['version'] == "1.1") {
478
		/* move LAN DHCP server config */
479
		$tmp = $config['dhcpd'];
480
		$config['dhcpd'] = array();
481
		$config['dhcpd']['lan'] = $tmp;
482

    
483
		/* encrypt password */
484
		$config['system']['password'] = crypt($config['system']['password']);
485

    
486
		$config['version'] = "1.2";
487
	}
488

    
489
	/* convert 1.2 -> 1.3 */
490
	if ($config['version'] == "1.2") {
491
		/* convert advanced outbound NAT config */
492
		for ($i = 0; isset($config['nat']['advancedoutbound']['rule'][$i]); $i++) {
493
			$curent = &$config['nat']['advancedoutbound']['rule'][$i];
494
			$src = $curent['source'];
495
			$curent['source'] = array();
496
			$curent['source']['network'] = $src;
497
			$curent['destination'] = array();
498
			$curent['destination']['any'] = true;
499
		}
500

    
501
		/* add an explicit type="pass" to all filter rules to make things consistent */
502
		for ($i = 0; isset($config['filter']['rule'][$i]); $i++) {
503
			$config['filter']['rule'][$i]['type'] = "pass";
504
		}
505

    
506
		$config['version'] = "1.3";
507
	}
508

    
509
	/* convert 1.3 -> 1.4 */
510
	if ($config['version'] == "1.3") {
511
		/* convert shaper rules (make pipes) */
512
		if (is_array($config['pfqueueing']['rule'])) {
513
			$config['pfqueueing']['pipe'] = array();
514

    
515
			for ($i = 0; isset($config['pfqueueing']['rule'][$i]); $i++) {
516
				$curent = &$config['pfqueueing']['rule'][$i];
517

    
518
				/* make new pipe and associate with this rule */
519
				$newpipe = array();
520
				$newpipe['descr'] = $curent['descr'];
521
				$newpipe['bandwidth'] = $curent['bandwidth'];
522
				$newpipe['delay'] = $curent['delay'];
523
				$newpipe['mask'] = $curent['mask'];
524
				$config['pfqueueing']['pipe'][$i] = $newpipe;
525

    
526
				$curent['targetpipe'] = $i;
527

    
528
				unset($curent['bandwidth']);
529
				unset($curent['delay']);
530
				unset($curent['mask']);
531
			}
532
		}
533

    
534
		$config['version'] = "1.4";
535
	}
536

    
537
	/* Convert 1.4 -> 1.5 */
538
	if ($config['version'] == "1.4") {
539

    
540
		/* Default route moved */
541
		if (isset($config['interfaces']['wan']['gateway']))
542
			if ($config['interfaces']['wan']['gateway'] <> "")
543
				$config['system']['gateway'] = $config['interfaces']['wan']['gateway'];
544
		unset($config['interfaces']['wan']['gateway']);
545

    
546
                /* Queues are no longer interface specific */
547
                if (isset($config['interfaces']['lan']['schedulertype']))
548
                        unset($config['interfaces']['lan']['schedulertype']);
549
                if (isset($config['interfaces']['wan']['schedulertype']))
550
                        unset($config['interfaces']['wan']['schedulertype']);
551

    
552
                for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
553
                        if(isset($config['interfaces']['opt' . $i]['schedulertype']))
554
                                unset($config['interfaces']['opt' . $i]['schedulertype']);
555
                }
556

    
557
		$config['version'] = "1.5";
558
	}
559

    
560
	/* Convert 1.5 -> 1.6 */
561
	if ($config['version'] == "1.5") {
562
		/* Alternate firmware URL moved */
563
		if (isset($config['system']['firmwareurl']) && isset($config['system']['firmwarename'])) { // Only convert if *both* are defined.
564
			$config['system']['alt_firmware_url'] = array();
565
			$config['system']['alt_firmware_url']['enabled'] = "";
566
			$config['system']['alt_firmware_url']['firmware_base_url'] = $config['system']['firmwareurl'];
567
			$config['system']['alt_firmware_url']['firmware_filename'] = $config['system']['firmwarename'];
568
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
569
		} else {
570
			unset($config['system']['firmwareurl'], $config['system']['firmwarename']);
571
		}
572

    
573
		$config['version'] = "1.6";
574
	}
575

    
576
	if ($prev_version != $config['version'])
577
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
578
}
579

    
580
/****f* config/write_config
581
 * NAME
582
 *   write_config - Backup and write the firewall configuration.
583
 * DESCRIPTION
584
 *   write_config() handles backing up the current configuration,
585
 *   applying changes, and regenerating the configuration cache.
586
 * INPUTS
587
 *   $desc	- string containing the a description of configuration changes
588
 *   $backup	- boolean: do not back up current configuration if false.
589
 * RESULT
590
 *   null       
591
 ******/
592
/* save the system configuration */
593
function write_config($desc="Unknown", $backup = true) {
594
	global $config, $g;
595

    
596
	if($backup) backup_config();
597

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

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

    
605
	$config['revision']['description'] = $desc;
606
	$config['revision']['time'] = $changetime;
607
	
608
	config_lock();
609
	conf_mount_rw();
610

    
611
	/* generate configuration XML */
612
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
613

    
614
	/* write new configuration */
615
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
616
	if (!$fd)
617
		die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
618
	fwrite($fd, $xmlconfig);
619
	fclose($fd);
620

    
621
	conf_mount_ro();
622
	config_unlock();
623

    
624
	// Always reparse the config after it's written - something is getting lost in serialize().
625
	$config = parse_config(true);
626
	return $config;
627
}
628

    
629
/****f* config/reset_factory_defaults
630
 * NAME
631
 *   reset_factory_defaults - Reset the system to its default configuration.
632
 * RESULT
633
 *   integer	- indicates completion
634
 ******/
635
function reset_factory_defaults() {
636
	global $g;
637

    
638
	config_lock();
639
	conf_mount_rw();
640

    
641
	/* create conf directory, if necessary */
642
	safe_mkdir("{$g['cf_conf_path']}");
643

    
644
	/* clear out /conf */
645
	$dh = opendir($g['conf_path']);
646
	while ($filename = readdir($dh)) {
647
		if (($filename != ".") && ($filename != "..")) {
648
			unlink_if_exists($g['conf_path'] . "/" . $filename);
649
		}
650
	}
651
	closedir($dh);
652

    
653
	/* copy default configuration */
654
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
655

    
656
	conf_mount_ro();
657
	config_unlock();
658

    
659
	return 0;
660
}
661

    
662
function config_restore($conffile) {
663
	global $config, $g;
664
       
665
        if (!file_exists($conffile))
666
                return 1;
667
        
668
        config_lock();
669
        conf_mount_rw();        
670
        
671
        backup_config();
672
        copy($conffile, "{$g['cf_conf_path']}/config.xml");
673
	$config = parse_config(true);
674
        write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
675
        
676
        conf_mount_ro();
677
        config_unlock();
678

    
679
        return 0;
680
}
681

    
682

    
683

    
684
function config_install($conffile) {
685
        global $config, $g;
686
        
687
        if (!file_exists($conffile))
688
                return 1;
689
 
690
        config_lock();
691
        conf_mount_rw();
692
        
693
        copy($conffile, "{$g['conf_path']}/config.xml");
694
                
695
        conf_mount_ro();
696
        config_unlock();
697

    
698
        return 0;
699
}
700

    
701
/* lock configuration file, decide that the lock file is stale after
702
   10 seconds */
703
function config_lock() {
704
	global $g, $process_lock;
705

    
706
	/* No need to continue if we're the ones holding the lock */
707
	if ($process_lock)
708
		return;
709

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

    
712
	$n = 0;
713
	while ($n < 10) {
714
		/* open the lock file in append mode to avoid race condition */
715
		if ($fd = @fopen($lockfile, "x")) {
716
			/* succeeded */
717
			$process_lock = true;
718
			fclose($fd);
719
			return;
720
		} else {
721
			/* file locked, wait and try again */
722
			$process_lock = false;
723
			sleep(1);
724
			$n++;
725
		}
726
	}
727
}
728

    
729
/* unlock configuration file */
730
function config_unlock() {
731
	global $g, $process_lock;
732

    
733
	$lockfile = "{$g['varrun_path']}/config.lock";
734
	$process_lock = false;
735

    
736
	unlink_if_exists($lockfile);
737
}
738

    
739
function set_networking_interfaces_ports() {
740
	global $noreboot;
741
	global $config;
742
	global $g;
743
	global $fp;
744

    
745
	$fp = fopen('php://stdin', 'r');
746

    
747
	$iflist = get_interface_list();
748

    
749
	echo <<<EOD
750

    
751
Valid interfaces are:
752

    
753

    
754
EOD;
755

    
756
	foreach ($iflist as $iface => $ifa) {
757
		echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
758
			$ifa['up'] ? "   (up)" : "");
759
	}
760

    
761
	echo <<<EOD
762

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

    
767
Do you want to set up VLANs now [y|n]?
768
EOD;
769

    
770
	if (strcasecmp(chop(fgets($fp)), "y") == 0)
771
		vlan_setup();
772

    
773
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
774

    
775
		echo "\n\nVLAN interfaces:\n\n";
776
		$i = 0;
777
		foreach ($config['vlans']['vlan'] as $vlan) {
778

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

    
782
			$iflist['vlan' . $i] = array();
783
			$i++;
784
		}
785
	}
786

    
787
	echo <<<EOD
788

    
789
If you do not know the names of your interfaces, you may choose to use
790
auto-detection. In that case, disconnect all interfaces before you begin,
791
and reconnect each one when prompted to do so.
792

    
793
EOD;
794

    
795
	do {
796
		echo "\nEnter the LAN interface name or 'a' for auto-detection: ";
797
		$lanif = chop(fgets($fp));
798
		if ($lanif === "") {
799
			exit(0);
800
		}
801

    
802
		if ($lanif === "a")
803
			$lanif = autodetect_interface("LAN", $fp);
804
		else if (!array_key_exists($lanif, $iflist)) {
805
			echo "\nInvalid interface name '{$lanif}'\n";
806
			unset($lanif);
807
			continue;
808
		}
809
	} while (!$lanif);
810

    
811
	do {
812
		echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
813
		$wanif = chop(fgets($fp));
814
		if ($wanif === "") {
815
			exit(0);
816
		}
817
		if ($wanif === "a")
818
			$wanif = autodetect_interface("WAN", $fp);
819
		else if (!array_key_exists($wanif, $iflist)) {
820
			echo "\nInvalid interface name '{$wanif}'\n";
821
			unset($wanif);
822
			continue;
823
		}
824
	} while (!$wanif);
825

    
826
	/* optional interfaces */
827
	$i = 0;
828
	$optif = array();
829

    
830
	while (1) {
831
		if ($optif[$i])
832
			$i++;
833
		$i1 = $i + 1;
834
		echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
835
			"(or nothing if finished): ";
836
		$optif[$i] = chop(fgets($fp));
837

    
838
		if ($optif[$i]) {
839
			if ($optif[$i] === "a") {
840
				$ad = autodetect_interface("Optional " . $i1, $fp);
841
				if ($ad)
842
					$optif[$i] = $ad;
843
				else
844
					unset($optif[$i]);
845
			} else if (!array_key_exists($optif[$i], $iflist)) {
846
				echo "\nInvalid interface name '{$optif[$i]}'\n";
847
				unset($optif[$i]);
848
				continue;
849
			}
850
		} else {
851
			unset($optif[$i]);
852
			break;
853
		}
854
	}
855

    
856
	/* check for double assignments */
857
	$ifarr = array_merge(array($lanif, $wanif), $optif);
858

    
859
	for ($i = 0; $i < (count($ifarr)-1); $i++) {
860
		for ($j = ($i+1); $j < count($ifarr); $j++) {
861
			if ($ifarr[$i] == $ifarr[$j]) {
862
				echo <<<EOD
863

    
864
Error: you cannot assign the same interface name twice!
865

    
866
EOD;
867

    
868
				exit(0);
869
			}
870
		}
871
	}
872

    
873
	echo <<<EOD
874

    
875
The interfaces will be assigned as follows:
876

    
877
LAN  -> {$lanif}
878
WAN  -> {$wanif}
879

    
880
EOD;
881

    
882
	for ($i = 0; $i < count($optif); $i++) {
883
		echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
884
	}
885

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

    
888
echo <<<EOD
889

    
890
Do you want to proceed [y|n]?
891
EOD;
892

    
893
	if (strcasecmp(chop(fgets($fp)), "y") == 0) {
894

    
895
		$config['interfaces']['lan']['if'] = $lanif;
896
		if (preg_match($g['wireless_regex'], $lanif)) {
897
			if (!is_array($config['interfaces']['lan']['wireless']))
898
				$config['interfaces']['lan']['wireless'] = array();
899
		} else {
900
			unset($config['interfaces']['lan']['wireless']);
901
		}
902
		
903
		$config['interfaces']['wan']['if'] = $wanif;
904
		if (preg_match($g['wireless_regex'], $wanif)) {
905
			if (!is_array($config['interfaces']['wan']['wireless']))
906
				$config['interfaces']['wan']['wireless'] = array();
907
		} else {
908
			unset($config['interfaces']['wan']['wireless']);
909
		}
910
		
911
		for ($i = 0; $i < count($optif); $i++) {
912
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
913
				$config['interfaces']['opt' . ($i+1)] = array();
914
			
915
			$config['interfaces']['opt' . ($i+1)]['if'] = $optif[$i];
916
			
917
			/* wireless interface? */
918
			if (preg_match($g['wireless_regex'], $optif[$i])) {
919
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
920
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
921
			} else {
922
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
923
			}
924
			
925
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
926
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
927
		}
928
		
929
		/* remove all other (old) optional interfaces */
930
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
931
			unset($config['interfaces']['opt' . ($i+1)]);
932
		
933
		write_config();
934
		
935
		echo <<<EOD
936

    
937

    
938

    
939
EOD;
940

    
941
		if($noreboot <> true)
942
			system_reboot_sync();
943
	}
944
}
945

    
946
function autodetect_interface($ifname, $fp) {
947
	$iflist_prev = get_interface_list();
948
	echo <<<EOD
949

    
950
Connect the {$ifname} interface now and make sure that the link is up.
951
Then press ENTER to continue.
952

    
953
EOD;
954
	fgets($fp);
955
	$iflist = get_interface_list();
956

    
957
	foreach ($iflist_prev as $ifn => $ifa) {
958
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
959
			echo "Detected link-up on interface {$ifn}.\n";
960
			return $ifn;
961
		}
962
	}
963

    
964
	echo "No link-up detected.\n";
965

    
966
	return null;
967
}
968

    
969
function vlan_setup() {
970
	global $iflist, $config, $g, $fp;
971

    
972
	$iflist = get_interface_list();
973

    
974
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
975

    
976
	echo <<<EOD
977

    
978
WARNING: all existing VLANs will be cleared if you proceed!
979

    
980
Do you want to proceed [y|n]?
981
EOD;
982

    
983
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
984
		return;
985
	}
986

    
987
	$config['vlans']['vlan'] = array();
988
	echo "\n";
989

    
990
	while (1) {
991
		$vlan = array();
992

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

    
996
		if ($vlan['if']) {
997
			if (!array_key_exists($vlan['if'], $iflist)) {
998
				echo "\nInvalid interface name '{$vlan['if']}'\n";
999
				continue;
1000
			}
1001
		} else {
1002
			break;
1003
		}
1004

    
1005
		echo "Enter the VLAN tag (1-4094): ";
1006
		$vlan['tag'] = chop(fgets($fp));
1007

    
1008
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1009
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1010
			continue;
1011
		}
1012

    
1013
		$config['vlans']['vlan'][] = $vlan;
1014
	}
1015
}
1016

    
1017
function system_start_ftp_helpers() {
1018
	global $config, $g;
1019
	if($config['system']['disableftpproxy'] <> "") return;
1020
	$wanif = get_real_wan_interface();
1021
	$ip = find_interface_ip($wanif);
1022
	mwexec("/sbin/killall pftpx");
1023
	mwexec("/usr/local/sbin/pftpx -g 8021 -p {$ip}");
1024
}
1025

    
1026
function cleanup_backupcache($revisions = 30) {
1027
	global $g;
1028
	$i = false;
1029
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1030
		$backups = get_backups();
1031
		$newbaks = array();
1032
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1033
		$baktimes = $backups['versions'];
1034
		$tocache = array();
1035
		unset($backups['versions']);
1036
       		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1037
			$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));	
1038
                	if(!in_array($tocheck, $baktimes)) {
1039
				$i = true;
1040
				if($bootup) print " " . $tocheck . "a";
1041
				$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1042
				if($newxml['revision']['description'] == "") $newxml['revision']['description'] = "Unknown";
1043
				$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1044
			}
1045
        	}
1046
		foreach($backups as $checkbak) {
1047
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1048
				$newbaks[] = $checkbak;
1049
			} else {
1050
				$i = true;
1051
				if($bootup) print " " . $tocheck . "r";
1052
			}
1053
		}
1054
		foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);	
1055
		if(is_int($revisions) and (count($tocache) > $revisions)) {
1056
			$toslice = array_slice(array_keys($tocache), 0, $revisions);
1057
			foreach($toslice as $sliced) $newcache[$sliced] = $tocache[$sliced];
1058
			foreach($tocache as $version => $versioninfo) {
1059
				if(!in_array($version, array_keys($newcache))) {
1060
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1061
					if($bootup) print " " . $tocheck . "d";
1062
				}
1063
			}
1064
			$tocache = $newcache;
1065
		}
1066
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1067
        	fwrite($bakout, serialize($tocache));
1068
  	        fclose($bakout);
1069
	}
1070
	if($g['booting']) {
1071
		if($i) {
1072
			print "done.\n";
1073
		}
1074
	}
1075
}
1076
  	 
1077
function get_backups() { 	 
1078
	global $g;
1079

    
1080
        if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1081
                $confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1082
		$bakvers = array_keys($confvers);
1083
		$toreturn = array();
1084
		sort($bakvers);
1085
		// $bakvers = array_reverse($bakvers);
1086
		foreach(array_reverse($bakvers) as $bakver) $toreturn[] = array('time' => $bakver,
1087
								 'description' => $confvers[$bakver]['description']
1088
								);
1089
        } else { 	 
1090
                return false; 	 
1091
        }
1092
	$toreturn['versions'] = $bakvers;
1093
        return $toreturn;
1094
}
1095

    
1096
function backup_config() {
1097
	global $config, $g;
1098

    
1099
	conf_mount_rw();
1100

    
1101
	/* Create backup directory if needed */
1102
	safe_mkdir("{$g['cf_conf_path']}/backup");
1103

    
1104
        if($config['revision']['time'] == "") {
1105
                $baktime = 0;
1106
        } else {
1107
                $baktime = $config['revision']['time'];
1108
        }
1109
        if($config['revision']['description'] == "") {
1110
                $bakdesc = "Unknown";
1111
        } else {
1112
                $bakdesc = $config['revision']['description'];
1113
        }
1114
        copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1115
        if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1116
                $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1117
        } else {
1118
                $backupcache = array();
1119
        }
1120
        $backupcache[$baktime] = array('description' => $bakdesc);
1121
        $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1122
        fwrite($bakout, serialize($backupcache));
1123
        fclose($bakout);
1124
	
1125
	conf_mount_ro();
1126
	
1127
	return true;
1128
}
1129

    
1130
function mute_kernel_msgs() {
1131
	exec("/sbin/conscontrol mute on");
1132
}
1133

    
1134
function unmute_kernel_msgs() {
1135
	exec("/sbin/conscontrol mute off");
1136
}
1137

    
1138
?>
(3-3/19)