Project

General

Profile

Download (34.5 KB) Statistics
| Branch: | Tag: | Revision:
1 12df7edc Erik
<?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.lib.inc
12
	Ported from config.inc by Erik Kristensen
13
	Copyright (C) 2004-2006 Scott Ullrich
14
	All rights reserved.
15
16
	originally part of m0n0wall (http://m0n0.ch/wall)
17
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
18
	All rights reserved.
19
20
	Redistribution and use in source and binary forms, with or without
21
	modification, are permitted provided that the following conditions are met:
22
23
	1. Redistributions of source code must retain the above copyright notice,
24
	   this list of conditions and the following disclaimer.
25
26
	2. Redistributions in binary form must reproduce the above copyright
27
	   notice, this list of conditions and the following disclaimer in the
28
	   documentation and/or other materials provided with the distribution.
29
30
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
31
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
32
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39
	POSSIBILITY OF SUCH DAMAGE.
40
41
42
	pfSense_BUILDER_BINARIES:	/sbin/mount	/sbin/sysctl	/sbin/umount	/sbin/halt	/sbin/fsck	/bin/sync
43
	pfSense_MODULE:	config
44
*/
45
46
47
/****f* config/encrypted_configxml
48
 * NAME
49
 *   encrypted_configxml - Checks to see if config.xml is encrypted and if so, prompts to unlock.
50
 * INPUTS
51
 *   None
52
 * RESULT
53
 *   $config 	- rewrites config.xml without encryption
54
 ******/
55
function encrypted_configxml() {
56
	global $g, $config;
57
	if(file_exists($g['conf_path'] . "/config.xml")) {
58
		if($g['booting']) {
59
			$configtxt = file_get_contents($g['conf_path'] . "/config.xml");			
60
			if(tagfile_deformat($configtxt, $configtxt, "config.xml")) {
61
				$fp = fopen('php://stdin', 'r');
62
				$data = "";
63
				echo "\n\n*** Encrypted config.xml detected ***\n";
64
				while($data == "") {
65
					echo "\nEnter the password to decrypt config.xml: ";
66
					$decrypt_password = chop(fgets($fp));
67
					$data = decrypt_data($configtxt, $decrypt_password);
68
					if(!strstr($data, "<pfsense>"))
69
						$data = "";
70
					if($data) {
71
						$fd = fopen($g['conf_path'] . "/config.xml", "w");
72
						fwrite($fd, $data);
73
						fclose($fd);
74
						echo "\nConfig.xml unlocked.\n";
75
						fclose($fp);
76
					} else {
77
						echo "\nInvalid password entered.  Please try again.\n";
78
					}
79
				}
80
			}
81
		}
82
	}
83
}
84
85
/****f* config/parse_config
86
 * NAME
87
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
88
 * INPUTS
89
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
90
 * RESULT
91
 *   $config      - array containing all configuration variables
92
 ******/
93
function parse_config($parse = false) {
94
	global $g, $config_parsed;
95
	
96
	$lockkey = lock('config');
97 0af381c2 Scott Ullrich
	$config_parsed = false;
98 12df7edc Erik
	if (!file_exists("{$g['conf_path']}/config.xml") || filesize("{$g['conf_path']}/config.xml") == 0) {
99
		$last_backup = discover_last_backup();
100
		if($last_backup) {
101
			log_error("No config.xml found, attempting last known config restore.");
102
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
103
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
104
		} else {
105
			unlock($lockkey);
106
			die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
107
		}
108
	}
109
	if($g['booting']) echo ".";
110
	// Check for encrypted config.xml
111
	encrypted_configxml();
112
	if(!$parse) {
113
		if(file_exists($g['tmp_path'] . '/config.cache')) {
114
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
115
			if(is_null($config)) {
116
				unlock($lockkey);
117
				parse_config(true);
118
				$lockkey = lock('config');
119
			}
120
		} else {
121
			if(!file_exists($g['conf_path'] . "/config.xml")) {
122
				log_error("No config.xml found, attempting last known config restore.");
123
				file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
124
				$last_backup = discover_last_backup();
125
				if ($last_backup)
126
					restore_backup("/cf/conf/backup/{$last_backup}");
127
				else
128
					log_error("Could not restore config.xml.");
129
			}
130
			unlock($lockkey);
131
			$config = parse_config(true);
132
			$lockkey = lock('config');
133
		}
134
	} else {
135
		if(!file_exists($g['conf_path'] . "/config.xml")) {
136
			if($g['booting']) echo ".";
137
			log_error("No config.xml found, attempting last known config restore.");
138
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
139
			$last_backup = discover_last_backup();
140
			if ($last_backup)
141
				restore_backup("/cf/conf/backup/{$last_backup}");
142
			else
143
				log_error("Could not restore config.xml.");
144
		}
145
		$config = parse_xml_config($g['conf_path'] . '/config.xml', $g['xml_rootobj']);
146
		if($config == "-1") {
147
			$last_backup = discover_last_backup();
148
			if ($last_backup)
149
				restore_backup("/cf/conf/backup/{$last_backup}");
150
			else
151
				log_error(gettext("Could not restore config.xml."));
152
		}
153
		generate_config_cache($config);
154
	}
155
	if($g['booting']) echo ".";
156
	alias_make_table($config);
157
	$config_parsed = true;
158
	unlock($lockkey);
159
160
	return $config;
161
}
162
163
/****f* config/generate_config_cache
164
 * NAME
165
 *   generate_config_cache - Write serialized configuration to cache.
166
 * INPUTS
167
 *   $config	- array containing current firewall configuration
168
 * RESULT
169
 *   boolean	- true on completion
170
 ******/
171
function generate_config_cache($config) {
172
	global $g;
173
174
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
175
	fwrite($configcache, serialize($config));
176
	fclose($configcache);
177
}
178
179
function discover_last_backup() {
180
        $backups = split("\n", `cd /cf/conf/backup && ls -ltr *.xml | awk '{print \$9}'`);
181
	$last_backup = "";
182
        foreach($backups as $backup)
183
        	if($backup)
184
	        	$last_backup = $backup;
185
186
        return $last_backup;
187
}
188
189
function restore_backup($file) {
190
	global $g;
191
192
	if (file_exists($file)) {
193
		conf_mount_rw();
194
		copy("$file","/cf/conf/config.xml");
195
		unlink_if_exists("{$g['tmp_path']}/config.cache");
196
		log_error("{$g['product_name']} is restoring the configuration $file");
197
		file_notice("config.xml", "{$g['product_name']} is restoring the configuration $file", "pfSenseConfigurator", "");
198
		conf_mount_ro();
199
	}
200
}
201
202
/****f* config/parse_config_bootup
203
 * NAME
204
 *   parse_config_bootup - Bootup-specific configuration checks.
205
 * RESULT
206
 *   null
207
 ******/
208
function parse_config_bootup() {
209
	global $config, $g, $noparseconfig;
210
211
	if($g['booting']) echo ".";
212
213
	$lockkey = lock('config');
214
	if (!$noparseconfig) {
215
		if (!file_exists("{$g['conf_path']}/config.xml")) {
216
			if ($g['booting']) {
217
				if (strstr($g['platform'], "cdrom")) {
218
					/* try copying the default config. to the floppy */
219
					echo "Resetting factory defaults...\n";
220
					reset_factory_defaults(true);
221
					if (file_exists("{$g['conf_path']}/config.xml")) {
222
						/* do nothing, we have a file. */
223
					} else {
224
						echo "No XML configuration file found - using factory defaults.\n";
225
						echo "Make sure that the configuration floppy disk with the conf/config.xml\n";
226
						echo "file is inserted. If it isn't, your configuration changes will be lost\n";
227
						echo "on reboot.\n";
228
					}
229
				} else {
230
					$last_backup = discover_last_backup();
231
					if($last_backup) {
232
						log_error("No config.xml found, attempting last known config restore.");
233
						file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
234
						restore_backup("/cf/conf/backup/{$last_backup}");
235
					}
236
					if(!file_exists("{$g['conf_path']}/config.xml")) {
237
						echo "XML configuration file not found.  {$g['product_name']} cannot continue booting.\n";
238
						mwexec("/sbin/halt");
239
						exit;
240
					}
241
					log_error("Last known config found and restored.  Please double check your configuration file for accuracy.");
242
					file_notice("config.xml", "Last known config found and restored.  Please double check your configuration file for accuracy.", "pfSenseConfigurator", "");
243
				}
244
			} else {
245
				unlock($lockkey);
246
				exit(0);
247
			}
248
		}
249
	}
250
	if (filesize("{$g['conf_path']}/config.xml") == 0) {
251
		$last_backup = discover_last_backup();
252
		if($last_backup) {
253
			log_error("No config.xml found, attempting last known config restore.");
254
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
255
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
256
		} else {
257
			unlock($lockkey);
258
			die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
259
		}
260
	}
261
	unlock($lockkey);
262
	parse_config(true);
263
264
	if ((float)$config['version'] > (float)$g['latest_config']) {
265
		echo <<<EOD
266
267
268
*******************************************************************************
269
* WARNING!                                                                    *
270
* The current configuration has been created with a newer version of {$g['product_name']}  *
271
* than this one! This can lead to serious misbehavior and even security       *
272
* holes! You are urged to either upgrade to a newer version of {$g['product_name']} or     *
273
* revert to the default configuration immediately!                            *
274
*******************************************************************************
275
276
277
EOD;
278
		}
279
280
	/* make alias table (for faster lookups) */
281
	alias_make_table($config);
282
}
283
284
/****f* config/conf_mount_rw
285
 * NAME
286
 *   conf_mount_rw - Mount filesystems read/write.
287
 * RESULT
288
 *   null
289
 ******/
290
/* mount flash card read/write */
291
function conf_mount_rw() {
292
	global $g;
293
294
	/* do not mount on cdrom platform */
295
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
296
		return;
297
		
298
	if (is_subsystem_dirty('mount'))
299
		return;
300
301
	$status = mwexec("/sbin/mount -u -w {$g['cf_path']}");
302
	if($status <> 0) {
303
		if($g['booting'])
304
			echo "Disk is dirty.  Running fsck -y\n";
305
		mwexec("/sbin/fsck -y {$g['cf_path']}");
306
		$status = mwexec("/sbin/mount -u -w {$g['cf_path']}");
307
	}
308
309
	/*    if the platform is soekris or wrap or pfSense, lets mount the
310
	 *    compact flash cards root.
311
         */
312
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx"
313
	   or $g['platform'] == "embedded" or $g['platform'] == "nanobsd") {
314
		$status = mwexec("/sbin/mount -u -w /");
315
		/* we could not mount this correctly.  kick off fsck */
316
		if($status <> 0) {
317
			log_error("File system is dirty.  Launching FSCK for /");
318
			mwexec("/sbin/fsck -y /");
319
			$status = mwexec("/sbin/mount -u -w /");
320
		}
321
	}
322
	
323
	mark_subsystem_dirty('mount');
324
}
325
326
/****f* config/conf_mount_ro
327
 * NAME
328
 *   conf_mount_ro - Mount filesystems readonly.
329
 * RESULT
330
 *   null
331
 ******/
332
function conf_mount_ro() {
333
	global $g;
334
335
	if($g['booting'] == true)
336
		return;
337
338
	/* firmare upgrade in progress */
339
	if (is_subsystem_dirty('firmwarelock'))
340
		return;
341
342
	/* do not umount if generating ssh keys */
343
	if (is_subsystem_dirty('sshdkeys'))
344
		return;
345
346
	/* do not umount on cdrom or pfSense platforms */
347
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
348
		return;
349
350
	if (!is_subsystem_dirty('mount'))
351
		return;
352
353
	clear_subsystem_dirty('mount');
354
	/* sync data, then force a remount of /cf */
355
	mwexec("/bin/sync");
356
	mwexec("/bin/sync");
357
	mwexec("/sbin/mount -u -r -f {$g['cf_path']}");
358
	mwexec("/sbin/mount -u -r -f /");
359
}
360
361
/****f* config/convert_config
362
 * NAME
363
 *   convert_config - Attempt to update config.xml.
364
 * DESCRIPTION
365
 *   convert_config() reads the current global configuration
366
 *   and attempts to convert it to conform to the latest
367
 *   config.xml version. This allows major formatting changes
368
 *   to be made with a minimum of breakage.
369
 * RESULT
370
 *   null
371
 ******/
372
/* convert configuration, if necessary */
373
function convert_config() {
374
	global $config, $g;
375
	$now = date("H:i:s");
376
	log_error("Start Configuration upgrade at $now, set execution timeout to 15 minutes");
377
	ini_set("max_execution_time", "900");
378
379
	/* special case upgrades */
380
	/* fix every minute crontab bogons entry */
381
	$cron_item_count = count($config['cron']['item']);
382
	for($x=0; $x<$cron_item_count; $x++) {
383
		if(stristr($config['cron']['item'][$x]['command'], "rc.update_bogons.sh")) {
384
			if($config['cron']['item'][$x]['hour'] == "*" ) {
385
		        $config['cron']['item'][$x]['hour'] = "3";
386
		 		write_config("Updated bogon update frequency to 3am");
387
		 		log_error("Updated bogon update frequency to 3am");
388
		 	}       
389
		}
390
	}
391
	if ($config['version'] == $g['latest_config'])
392
		return;		/* already at latest version */
393
394
	// Save off config version
395
	$prev_version = $config['version'];
396
	
397 b96cad97 Seth Mos
	include_once('auth.inc');
398 12df7edc Erik
	include_once('upgrade_config.inc');
399
	/* Loop and run upgrade_VER_to_VER() until we're at current version */
400
	while ($config['version'] < $g['latest_config']) {
401
		$cur = $config['version'] * 10;
402
		$next = $cur + 1;
403
		$migration_function = sprintf('upgrade_%03d_to_%03d', $cur, $next);
404
		$migration_function();
405
		$config['version'] = sprintf('%.1f', $next / 10);
406 92cf9fcd sullrich
		if($g['booting'])
407
			echo ".";
408 12df7edc Erik
	}
409
410
	$now = date("H:i:s");
411
	log_error("Ended Configuration upgrade at $now");
412
413
	if ($prev_version != $config['version'])
414
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
415 92cf9fcd sullrich
416
	if($g['booting'])
417
		echo "Loading new configuration...";
418 12df7edc Erik
}
419
420
/****f* config/write_config
421
 * NAME
422
 *   write_config - Backup and write the firewall configuration.
423
 * DESCRIPTION
424
 *   write_config() handles backing up the current configuration,
425
 *   applying changes, and regenerating the configuration cache.
426
 * INPUTS
427
 *   $desc	- string containing the a description of configuration changes
428
 *   $backup	- boolean: do not back up current configuration if false.
429
 * RESULT
430
 *   null
431
 ******/
432
/* save the system configuration */
433
function write_config($desc="Unknown", $backup = true) {
434
	global $config, $g;
435
436
	if($g['bootup']) 
437
		log_error("WARNING! Configuration written on bootup.  This can cause stray openvpn and load balancing items in config.xml");
438
439
	if($backup)
440
		backup_config();
441
442
	if (time() > mktime(0, 0, 0, 9, 1, 2004))       /* make sure the clock settings are plausible */
443
		$changetime = time();
444
445
	/* Log the running script so it's not entirely unlogged what changed */
446 42739c1c Ermal Lu?i
	if ($desc == "Unknown")
447 12df7edc Erik
		$desc = "{$_SERVER['SCRIPT_NAME']} made unknown change";
448
449
	$config['revision']['description'] = $desc;
450
	$config['revision']['time'] = $changetime;
451
452
	$lockkey = lock('config');
453
454
	/* generate configuration XML */
455
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
456
457
	conf_mount_rw();
458
459
	/* write new configuration */
460 42739c1c Ermal Lu?i
	$fd = fopen("{$g['conf_path']}/config.xml", "w");
461 12df7edc Erik
        if (!$fd) {
462
                // Unable to open temporary file for writing
463
		log_error("WARNING: Config contents could not be save. Could not open file!");
464
		unlock($lockkey);
465
                return false;
466
        }
467
        if (!fwrite($fd, $xmlconfig)) {
468
                // Unable to write to temporary file
469
		log_error("WARNING: Config contents could not be written on file.");
470
                fclose($fd);
471
		unlock($lockkey);
472
                return false;
473
        }
474
        fclose($fd);
475
476
	if($g['platform'] == "embedded" or $g['platform'] == "nanobsd") {
477
		cleanup_backupcache(5, true);
478
	} else {
479
		cleanup_backupcache(30, true);
480
	}
481
482
	/* re-read configuration */
483
	$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
484
485
	/* write config cache */
486
	$fd = @fopen("{$g['tmp_path']}/config.cache", "wb");
487
	if ($fd) {
488
		fwrite($fd, serialize($config));
489
		fclose($fd);
490
	}
491
492
	/* tell kernel to sync fs data */
493
	if (!$g['booting'])
494
		conf_mount_ro();
495 42739c1c Ermal Lu?i
496 12df7edc Erik
	unlock($lockkey);
497
498
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
499
	/* sync carp entries to other firewalls */
500
        carp_sync_client();
501
502
	if(is_dir("/usr/local/pkg/write_config")) {
503
		/* process packager manager custom rules */
504
		run_plugins("/usr/local/pkg/write_config/");
505
	}
506
507
	return $config;
508
}
509
510
/****f* config/reset_factory_defaults
511
 * NAME
512
 *   reset_factory_defaults - Reset the system to its default configuration.
513
 * RESULT
514
 *   integer	- indicates completion
515
 ******/
516
function reset_factory_defaults($lock = false) {
517
	global $g;
518
519
	if (!$lock)
520
		$lockkey = lock('config');
521
	conf_mount_rw();
522
523
	/* create conf directory, if necessary */
524
	safe_mkdir("{$g['cf_conf_path']}");
525
526
	/* clear out /conf */
527
	$dh = opendir($g['conf_path']);
528
	while ($filename = readdir($dh)) {
529
		if (($filename != ".") && ($filename != "..")) {
530
			unlink_if_exists($g['conf_path'] . "/" . $filename);
531
		}
532
	}
533
	closedir($dh);
534
535
	/* copy default configuration */
536
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
537
538
	/* call the wizard */
539
	touch("/conf/trigger_initial_wizard");
540
	conf_mount_ro();
541
	if (!$lock)
542
		unlock($lockkey);
543
544
	return 0;
545
}
546
547
function config_restore($conffile) {
548
	global $config, $g;
549
550
	if (!file_exists($conffile))
551
		return 1;
552
553
	conf_mount_rw();
554
555
	backup_config();
556
557
	$lockkey = lock('config');
558
559
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
560
	unlink_if_exists("{$g['tmp_path']}/config.cache");
561
562
	unlock($lockkey);
563
564
	$config = parse_config(true);
565
566
	write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
567
568
	conf_mount_ro();
569
570
	return 0;
571
}
572
573
function config_install($conffile) {
574
	global $config, $g;
575
576
	if (!file_exists($conffile))
577
		return 1;
578
579
	if (!config_validate("{$conffile}"))
580
		return 1;
581
582
	if($g['booting'] == true)
583
		echo "Installing configuration...\n";
584
	else
585
		log_error("Installing configuration ....");
586
587
	conf_mount_rw();
588
	$lockkey = lock('config');
589
590
	copy($conffile, "{$g['conf_path']}/config.xml");
591
592
	/* unlink cache file if it exists */
593
	if(file_exists("{$g['tmp_path']}/config.cache"))
594
		unlink("{$g['tmp_path']}/config.cache");
595
596
	unlock($lockkey);
597
	conf_mount_ro();
598
599
    return 0;
600
}
601
602
function config_validate($conffile) {
603
604
	global $g, $xmlerr;
605
606
	$xml_parser = xml_parser_create();
607
608
	if (!($fp = fopen($conffile, "r"))) {
609
		$xmlerr = "XML error: unable to open file";
610
		return false;
611
	}
612
613
	while ($data = fread($fp, 4096)) {
614
		if (!xml_parse($xml_parser, $data, feof($fp))) {
615
			$xmlerr = sprintf("%s at line %d",
616
						xml_error_string(xml_get_error_code($xml_parser)),
617
						xml_get_current_line_number($xml_parser));
618
			return false;
619
		}
620
	}
621
	xml_parser_free($xml_parser);
622
623
	fclose($fp);
624
625
	return true;
626
}
627
628
function set_networking_interfaces_ports() {
629
	global $noreboot;
630
	global $config;
631
	global $g;
632
	global $fp;
633
634
	$fp = fopen('php://stdin', 'r');
635
636
	$memory = get_memory();
637
	$avail = $memory[0];
638
639
	if($avail < $g['minimum_ram_warning']) {
640
		echo "\n\n\n";
641
		echo "DANGER!  WARNING!  ACHTUNG!\n\n";
642
		echo "{$g['product_name']} requires *AT LEAST* {$g['minimum_ram_warning_text']} RAM to function correctly.\n";
643
		echo "Only ({$avail}) MB RAM has been detected.\n";
644
		echo "\nPress ENTER to continue. ";
645
		fgets($fp);
646
		echo "\n";
647
	}
648
649
	$iflist = get_interface_list();
650
651
/* Function flow is based on $key and $auto_assign or the lack thereof */	
652
	$key = null;
653
654
/* Only present auto interface option if running from LiveCD and interface mismatch*/
655
	if ((ereg("cdrom", $g['platform'])) && is_interface_mismatch())
656
		$auto_assign = false;
657
658
	echo <<<EOD
659
660
Valid interfaces are:
661
662
663
EOD;
664
665
	if(!is_array($iflist)) {
666
		echo "No interfaces found!\n";
667
		$iflist = array();
668
	} else {
669
		foreach ($iflist as $iface => $ifa) {
670 cace2dbb sullrich
			echo sprintf("% -6s%s%s\t%s\n", $iface, $ifa['mac'],
671 12df7edc Erik
				$ifa['up'] ? "   (up)" : "   (down)", $ifa['dmesg']);
672
		}
673
	}
674
675
	if ($auto_assign) {
676
		echo <<<EOD
677
		
678
		!!! LiveCD Detected: Auto Interface Option !!!!
679
BEGIN MANUAL CONFIGURATION OR WE WILL PROCEED WITH AUTO CONFIGURATION.
680
681
EOD;
682
	}	
683
	
684
	echo <<<EOD
685
686
Do you want to set up VLANs first? 
687
688
If you are not going to use VLANs, or only for optional interfaces, you should
689
say no here and use the webConfigurator to configure VLANs later, if required.
690
691
Do you want to set up VLANs now [y|n]? 
692
EOD;
693
694
	if ($auto_assign) {
695
		$key = timeout();
696
697
	} else
698
		$key = chop(fgets($fp));
699
700
	if (!isset($key) and $auto_assign) {	// Auto Assign Interfaces
701
		do {
702
			echo <<<EOD
703
704
   !!! Auto Assigning Interfaces !!!
705
706
For installation purposes, you must plug in at least one NIC
707
for the LAN connection. If you plug in a second NIC it will be
708
assigned to WAN. Otherwise, we'll temporarily assign WAN to the
709
next available NIC found regardless of activity. You should
710
assign and configure the WAN interface according to your requirements
711
712
If you haven't plugged in any network cables yet,
713
now is the time to do so.
714
We'll keep trying until you do.
715
716
Searching for active interfaces...
717
 
718
EOD;
719
			unset($wanif, $lanif);
720
721
			$media_iflist = $plugged_in = array();
722
			$media_iflist = get_interface_list("media");
723
			foreach ($media_iflist as $iface => $ifa) {
724
				if ($ifa['up']) 
725
					$plugged_in[] = $iface;
726
				
727
			}
728
729
			$lanif = array_shift($plugged_in);
730
			$wanif = array_shift($plugged_in);
731
732
			if(isset($lanif) && !isset($wanif)) {
733
				foreach ($iflist as $iface => $ifa) {
734
					if ($iface != $lanif) {
735
						$wanif = $iface;
736
						break;
737
					}
738
				}
739
			}
740
741
			echo <<<EOD
742
743
Assigned WAN to : $wanif 
744
Assigned LAN to : $lanif
745
746
If you don't like this assignment,
747
press any key to go back to manual configuration. 
748
749
EOD;
750
			$key = timeout(20);
751
			if(isset($key))
752
				return;
753
		} while (!isset($wanif));
754
755
		$config['system']['enablesshd'] = 'enabled';	
756
		$key = 'y';
757
758
	} else {		//Manually assign interfaces	
759
		if (in_array($key, array('y', 'Y')))
760
			vlan_setup();
761
	
762
		if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
763
	
764
			echo "\n\nVLAN interfaces:\n\n";
765
			foreach ($config['vlans']['vlan'] as $vlan) {
766
	
767
				echo sprintf("% -16s%s\n", "{$vlan['if']}_vlan{$vlan['tag']}",
768
					"VLAN tag {$vlan['tag']}, parent interface {$vlan['if']}");
769
	
770
				$iflist[$vlan['if'] . '_vlan' . $vlan['tag']] = array();
771
			}
772
		}
773
	
774
		echo <<<EOD
775
	
776
*NOTE*  {$g['product_name']} requires {$g['minimum_nic_count_text']} assigned interfaces to function.
777
        If you do not have {$g['minimum_nic_count_text']} interfaces you CANNOT continue. 
778
779
        If you do not have at least {$g['minimum_nic_count']} *REAL* network interface cards
780
        or one interface with multiple VLANs then {$g['product_name']}
781
        *WILL NOT* function correctly.
782
783
If you do not know the names of your interfaces, you may choose to use
784
auto-detection. In that case, disconnect all interfaces now before
785
hitting 'a' to initiate auto detection.
786
	
787
EOD;
788
	
789
		do {
790
			echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
791
			$wanif = chop(fgets($fp));
792
			if ($wanif === "") {
793
				return;
794
			}
795
			if ($wanif === "a")
796
				$wanif = autodetect_interface("WAN", $fp);
797
			else if (!array_key_exists($wanif, $iflist)) {
798
				echo "\nInvalid interface name '{$wanif}'\n";
799
				unset($wanif);
800
				continue;
801
			}
802
		} while (!$wanif);
803
	
804
		do {
805
			echo "\nEnter the LAN interface name or 'a' for auto-detection \n" .
806
			    "NOTE: this enables full Firewalling/NAT mode.\n" .
807
				"(or nothing if finished): ";
808
	
809
			$lanif = chop(fgets($fp));
810
			
811
			if($lanif == "exit") {
812
				exit;
813
			}
814
			
815
			if($lanif == "") {
816
				if($g['minimum_nic_count'] < 2) {
817
					break;	
818
				} else {
819
					fclose($fp);
820
					return;
821
				}
822
			}
823
	
824
			if ($lanif === "a")
825
				$lanif = autodetect_interface("LAN", $fp);
826
			else if (!array_key_exists($lanif, $iflist)) {
827
				echo "\nInvalid interface name '{$lanif}'\n";
828
				unset($lanif);
829
				continue;
830
			}
831
		} while (!$lanif);
832
	
833
		/* optional interfaces */
834
		$i = 0;
835
		$optif = array();
836
	
837
		if($lanif <> "") {
838
			while (1) {
839
				if ($optif[$i])
840
					$i++;
841
				$i1 = $i + 1;
842
		
843
				if($config['interfaces']['opt' . $i1]['descr'])
844
					echo "\nOptional interface {$i1} description found: {$config['interfaces']['opt' . $i1]['descr']}";
845
	
846
				echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
847
					"(or nothing if finished): ";
848
		
849
				$optif[$i] = chop(fgets($fp));
850
		
851
				if ($optif[$i]) {
852
					if ($optif[$i] === "a") {
853
						$ad = autodetect_interface("Optional " . $i1, $fp);
854
						if ($ad)
855
							$optif[$i] = $ad;
856
						else
857
							unset($optif[$i]);
858
					} else if (!array_key_exists($optif[$i], $iflist)) {
859
						echo "\nInvalid interface name '{$optif[$i]}'\n";
860
						unset($optif[$i]);
861
						continue;
862
					}
863
				} else {
864
					unset($optif[$i]);
865
					break;
866
				}
867
			}
868
		}
869
		
870
		/* check for double assignments */
871
		$ifarr = array_merge(array($lanif, $wanif), $optif);
872
		
873
		for ($i = 0; $i < (count($ifarr)-1); $i++) {
874
			for ($j = ($i+1); $j < count($ifarr); $j++) {
875
				if ($ifarr[$i] == $ifarr[$j]) {
876
					echo <<<EOD
877
	
878
Error: you cannot assign the same interface name twice!
879
	
880
EOD;
881
					fclose($fp);
882
					return;
883
				}
884
			}
885
		}
886
	
887
		echo "\nThe interfaces will be assigned as follows: \n\n";
888
	
889
		if ($lanif != "")
890
			echo "LAN  ->" . $lanif . "\n";
891
		echo "WAN  ->" . $wanif . "\n";
892
		for ($i = 0; $i < count($optif); $i++) {
893
			echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
894
		}
895
	
896
		echo <<<EOD
897
	
898
Do you want to proceed [y|n]?
899
EOD;
900
			$key = chop(fgets($fp));		
901
	}
902
903
	if (in_array($key, array('y', 'Y'))) {
904
		if($lanif) {
905
			$config['interfaces']['lan']['if'] = $lanif;
906
		} elseif (!$g['booting'] && !$auto_assign) {
907
908
echo <<<EODD
909
910
You have chosen to remove the LAN interface.
911
912
Would you like to remove the LAN IP address and
913
unload the interface now? [y|n]? 
914
EODD;
915
916
				if (strcasecmp(chop(fgets($fp)), "y") == 0) {
917
					if($config['interfaces']['lan']['if'])
918
						mwexec("/sbin/ifconfig delete " . $config['interfaces']['lan']['if']);
919
				}
920
				if(isset($config['interfaces']['lan']))
921
					unset($config['interfaces']['lan']);
922
				if(isset($config['dhcpd']['lan']))
923
					unset($config['dhcpd']['lan']);
924
				if(isset($config['interfaces']['lan']['if']))
925
					unset($config['interfaces']['lan']['if']);
926
				if(isset($config['interfaces']['wan']['blockpriv']))
927
					unset($config['interfaces']['wan']['blockpriv']);
928
				if(isset($config['shaper']))
929
					unset($config['shaper']);
930
				if(isset($config['ezshaper']))
931
					unset($config['ezshaper']);
932
				if(isset($config['nat']))
933
					unset($config['nat']);				
934
		} else {
935
			if(isset($config['interfaces']['lan']['if']))
936
				mwexec("/sbin/ifconfig delete " . $config['interfaces']['lan']['if']);
937
			if(isset($config['interfaces']['lan']))
938
				unset($config['interfaces']['lan']);
939
			if(isset($config['dhcpd']['lan']))
940
				unset($config['dhcpd']['lan']);
941
			if(isset($config['interfaces']['lan']['if']))
942
				unset($config['interfaces']['lan']['if']);
943
			if(isset($config['interfaces']['wan']['blockpriv']))
944
				unset($config['interfaces']['wan']['blockpriv']);
945
			if(isset($config['shaper']))
946
				unset($config['shaper']);
947
			if(isset($config['ezshaper']))
948
				unset($config['ezshaper']);
949
			if(isset($config['nat']))
950
				unset($config['nat']);				
951
		}
952
		if (preg_match($g['wireless_regex'], $lanif)) {
953
			if (is_array($config['interfaces']['lan']) &&
954
				(!is_array($config['interfaces']['lan']['wireless'])))
955
				$config['interfaces']['lan']['wireless'] = array();
956
		} else {
957
			unset($config['interfaces']['lan']['wireless']);
958
		}
959
960
		$config['interfaces']['wan']['if'] = $wanif;
961
		if (preg_match($g['wireless_regex'], $wanif)) {
962
			if (is_array($config['interfaces']['lan']) &&
963
				(!is_array($config['interfaces']['wan']['wireless'])))
964
				$config['interfaces']['wan']['wireless'] = array();
965
		} else {
966
			unset($config['interfaces']['wan']['wireless']);
967
		}
968
969
		for ($i = 0; $i < count($optif); $i++) {
970
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
971
				$config['interfaces']['opt' . ($i+1)] = array();
972
973
			$config['interfaces']['opt' . ($i+1)]['if'] = $optif[$i];
974
975
			/* wireless interface? */
976
			if (preg_match($g['wireless_regex'], $optif[$i])) {
977
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
978
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
979
			} else {
980
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
981
			}
982
983
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
984
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
985
		}
986
987
		/* remove all other (old) optional interfaces */
988
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
989
			unset($config['interfaces']['opt' . ($i+1)]);
990
991
		echo "\nWriting configuration...";
992
		write_config();
993
		echo "done.\n";
994
995
		echo <<<EOD
996
997
998
999
EOD;
1000
1001
		fclose($fp);
1002
		if($g['booting'])
1003
			return;
1004
1005
		echo "One moment while we reload the settings...";
1006
1007
		$g['booting'] = false;
1008
1009
		/* XXX: ermal - disable it for now this is used during bootup at best so shouldn't be needed.
1010
		 * 		For now just comment it out and later remove it completely.
1011
		 * resync everything 
1012
			reload_all_sync();
1013
		 */
1014
1015
		echo " done!\n";
1016
1017
		touch("{$g['tmp_path']}/assign_complete");
1018
1019
	}
1020
}
1021
1022
function autodetect_interface($ifname, $fp) {
1023
	$iflist_prev = get_interface_list("media");
1024
	echo <<<EOD
1025
1026
Connect the {$ifname} interface now and make sure that the link is up.
1027
Then press ENTER to continue.
1028
1029
EOD;
1030
	fgets($fp);
1031
	$iflist = get_interface_list("media");
1032
1033
	foreach ($iflist_prev as $ifn => $ifa) {
1034
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1035
			echo "Detected link-up on interface {$ifn}.\n";
1036
			return $ifn;
1037
		}
1038
	}
1039
1040
	echo "No link-up detected.\n";
1041
1042
	return null;
1043
}
1044
1045
function vlan_setup() {
1046
	global $iflist, $config, $g, $fp;
1047
1048
	$iflist = get_interface_list();
1049
1050
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1051
1052
	echo <<<EOD
1053
1054
WARNING: all existing VLANs will be cleared if you proceed!
1055
1056
Do you want to proceed [y|n]?
1057
EOD;
1058
1059
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1060
		return;
1061
	}
1062
1063
	$config['vlans']['vlan'] = array();
1064
	echo "\n";
1065
1066
	$vlanif = 0;
1067
1068
	while (1) {
1069
		$vlan = array();
1070
1071
		echo "\n\nVLAN Capable interfaces:\n\n";
1072
		if(!is_array($iflist)) {
1073
			echo "No interfaces found!\n";
1074
		} else {
1075
			$vlan_capable=0;
1076
			foreach ($iflist as $iface => $ifa) {
1077
				if (is_jumbo_capable($iface)) {
1078
					echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
1079
						$ifa['up'] ? "   (up)" : "");
1080
					$vlan_capable++;
1081
				}
1082
			}
1083
		}
1084
1085
		if($vlan_capable == 0) {
1086
			echo "No VLAN capable interfaces detected.\n";
1087
			return;
1088
		}
1089
1090
		echo "\nEnter the parent interface name for the new VLAN (or nothing if finished): ";
1091
		$vlan['if'] = chop(fgets($fp));
1092
1093
		if ($vlan['if']) {
1094
			if (!array_key_exists($vlan['if'], $iflist) or
1095
			    !is_jumbo_capable($vlan['if'])) {
1096
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1097
				continue;
1098
			}
1099
		} else {
1100
			break;
1101
		}
1102
1103
		echo "Enter the VLAN tag (1-4094): ";
1104
		$vlan['tag'] = chop(fgets($fp));
1105
		$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
1106
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1107
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1108
			continue;
1109
		}
1110
		
1111
		$config['vlans']['vlan'][] = $vlan;
1112
		$vlanif++;
1113
	}
1114
}
1115
1116
function cleanup_backupcache($revisions = 30, $lock = false) {
1117
	global $g;
1118
	$i = false;
1119
	
1120
	if (!$lock)
1121
		$lockkey = lock('config');
1122
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1123
		conf_mount_rw();
1124
		$backups = get_backups();
1125
		$newbaks = array();
1126
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1127
		$baktimes = $backups['versions'];
1128
		$tocache = array();
1129
		unset($backups['versions']);
1130
   		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1131
   			if(filesize($backup) == 0) {
1132
   				unlink($backup);
1133
   				continue;
1134
   			}
1135
			$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));
1136
            if(!in_array($tocheck, $baktimes)) {
1137
				$i = true;
1138
				if($g['booting'])
1139
					echo ".";
1140
				$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1141
				if($newxml == "-1") {
1142
					log_error("The backup cache file $backup is corrupted.  Unlinking.");
1143
					unlink($backup);
1144
					log_error("The backup cache file $backup is corrupted.  Unlinking.");
1145
					continue;
1146
				}
1147
				if($newxml['revision']['description'] == "")
1148
					$newxml['revision']['description'] = "Unknown";
1149
				$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1150
			}
1151
    	}
1152
		foreach($backups as $checkbak) {
1153
1154
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1155
				$newbaks[] = $checkbak;
1156
			} else {
1157
				$i = true;
1158
				if($g['booting']) 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)
1165
				$newcache[$sliced] = $tocache[$sliced];
1166
			foreach($tocache as $version => $versioninfo) {
1167
				if(!in_array($version, array_keys($newcache))) {
1168
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1169
					if($g['booting']) print " " . $tocheck . "d";
1170
				}
1171
			}
1172
			$tocache = $newcache;
1173
		}
1174
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1175
        fwrite($bakout, serialize($tocache));
1176
		fclose($bakout);
1177
		conf_mount_ro();
1178
	}
1179
	if($g['booting'] && $i)
1180
		print "done.\n";
1181
	if (!$lock)
1182
		unlock($lockkey);
1183
}
1184
1185
function get_backups() {
1186
	global $g;
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)
1194
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description']);
1195
	} else {
1196
		return false;
1197
	}
1198
	$toreturn['versions'] = $bakvers;
1199
	return $toreturn;
1200
}
1201
1202
function backup_config() {
1203
	global $config, $g;
1204
1205
	if($g['platform'] == "cdrom")
1206
		return;
1207
1208
	conf_mount_rw();
1209
1210
	/* Create backup directory if needed */
1211
	safe_mkdir("{$g['cf_conf_path']}/backup");
1212
1213
    if($config['revision']['time'] == "") {
1214
            $baktime = 0;
1215
    } else {
1216
            $baktime = $config['revision']['time'];
1217
    }
1218
    if($config['revision']['description'] == "") {
1219
            $bakdesc = "Unknown";
1220
    } else {
1221
            $bakdesc = $config['revision']['description'];
1222
    }
1223
    copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1224
    if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1225
            $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1226
    } else {
1227
            $backupcache = array();
1228
    }
1229
    $backupcache[$baktime] = array('description' => $bakdesc);
1230
    $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1231
    fwrite($bakout, serialize($backupcache));
1232
    fclose($bakout);
1233
1234
	conf_mount_ro();
1235
1236
	return true;
1237
}
1238
1239
function set_device_perms() {
1240
	$devices = array(
1241
		'pf'	=> array(	'user'	=> 'proxy',
1242
					'group'	=> 'proxy',
1243
					'mode'	=> 0660),
1244
		);
1245
1246
	foreach ($devices as $name => $attr) {
1247
		$path = "/dev/$name";
1248
		if (file_exists($path)) {
1249
			chown($path, $attr['user']);
1250
			chgrp($path, $attr['group']);
1251
			chmod($path, $attr['mode']);
1252
		}
1253
	}
1254
}
1255
1256 42739c1c Ermal Lu?i
?>