Project

General

Profile

« Previous | Next » 

Revision 12df7edc

Added by Erik Augustsson over 15 years ago

remove functional code from config.inc and place it in a library file config.lib.inc

View differences:

etc/inc/config.inc
45 45
 * XXX: Hack around the cvs syntax checks. 
46 46
 * DISABLE_PHP_LINT_CHECKING
47 47
 */
48
 
49 48

  
50 49
if($g['booting']) echo ".";
51 50

  
......
61 60
ini_set("memory_limit","128M");
62 61

  
63 62
/* include globals from notices.inc /utility/XML parser files */
63
require_once('config.lib.inc');
64
if($g['booting']) echo ".";
64 65
require_once("notices.inc");
65 66
if($g['booting']) echo ".";
66 67
require_once("util.inc");
......
197 198
	mwexec("/sbin/mount -a");
198 199
}
199 200

  
200
/****f* config/encrypted_configxml
201
 * NAME
202
 *   encrypted_configxml - Checks to see if config.xml is encrypted and if so, prompts to unlock.
203
 * INPUTS
204
 *   None
205
 * RESULT
206
 *   $config 	- rewrites config.xml without encryption
207
 ******/
208
function encrypted_configxml() {
209
	global $g, $config;
210
	if(file_exists($g['conf_path'] . "/config.xml")) {
211
		if($g['booting']) {
212
			$configtxt = file_get_contents($g['conf_path'] . "/config.xml");			
213
			if(tagfile_deformat($configtxt, $configtxt, "config.xml")) {
214
				$fp = fopen('php://stdin', 'r');
215
				$data = "";
216
				echo "\n\n*** Encrypted config.xml detected ***\n";
217
				while($data == "") {
218
					echo "\nEnter the password to decrypt config.xml: ";
219
					$decrypt_password = chop(fgets($fp));
220
					$data = decrypt_data($configtxt, $decrypt_password);
221
					if(!strstr($data, "<pfsense>"))
222
						$data = "";
223
					if($data) {
224
						$fd = fopen($g['conf_path'] . "/config.xml", "w");
225
						fwrite($fd, $data);
226
						fclose($fd);
227
						echo "\nConfig.xml unlocked.\n";
228
						fclose($fp);
229
					} else {
230
						echo "\nInvalid password entered.  Please try again.\n";
231
					}
232
				}
233
			}
234
		}
235
	}
236
}
237

  
238
/****f* config/parse_config
239
 * NAME
240
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
241
 * INPUTS
242
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
243
 * RESULT
244
 *   $config      - array containing all configuration variables
245
 ******/
246
function parse_config($parse = false) {
247
	global $g, $config_parsed;
248
	
249
	$lockkey = lock('config');
250
	$config_parsed == false;
251
	if (!file_exists("{$g['conf_path']}/config.xml") || filesize("{$g['conf_path']}/config.xml") == 0) {
252
		$last_backup = discover_last_backup();
253
		if($last_backup) {
254
			log_error("No config.xml found, attempting last known config restore.");
255
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
256
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
257
		} else {
258
			unlock($lockkey);
259
			die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
260
		}
261
	}
262
	if($g['booting']) echo ".";
263
	// Check for encrypted config.xml
264
	encrypted_configxml();
265
	if(!$parse) {
266
		if(file_exists($g['tmp_path'] . '/config.cache')) {
267
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
268
			if(is_null($config)) {
269
				unlock($lockkey);
270
				parse_config(true);
271
				$lockkey = lock('config');
272
			}
273
		} else {
274
			if(!file_exists($g['conf_path'] . "/config.xml")) {
275
				log_error("No config.xml found, attempting last known config restore.");
276
				file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
277
				$last_backup = discover_last_backup();
278
				if ($last_backup)
279
					restore_backup("/cf/conf/backup/{$last_backup}");
280
				else
281
					log_error("Could not restore config.xml.");
282
			}
283
			unlock($lockkey);
284
			$config = parse_config(true);
285
			$lockkey = lock('config');
286
		}
287
	} else {
288
		if(!file_exists($g['conf_path'] . "/config.xml")) {
289
			if($g['booting']) echo ".";
290
			log_error("No config.xml found, attempting last known config restore.");
291
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
292
			$last_backup = discover_last_backup();
293
			if ($last_backup)
294
				restore_backup("/cf/conf/backup/{$last_backup}");
295
			else
296
				log_error("Could not restore config.xml.");
297
		}
298
		$config = parse_xml_config($g['conf_path'] . '/config.xml', $g['xml_rootobj']);
299
		if($config == "-1") {
300
			$last_backup = discover_last_backup();
301
			if ($last_backup)
302
				restore_backup("/cf/conf/backup/{$last_backup}");
303
			else
304
				log_error(gettext("Could not restore config.xml."));
305
		}
306
		generate_config_cache($config);
307
	}
308
	if($g['booting']) echo ".";
309
	alias_make_table($config);
310
	$config_parsed = true;
311
	unlock($lockkey);
312

  
313

  
314
	return $config;
315
}
316

  
317
/****f* config/generate_config_cache
318
 * NAME
319
 *   generate_config_cache - Write serialized configuration to cache.
320
 * INPUTS
321
 *   $config	- array containing current firewall configuration
322
 * RESULT
323
 *   boolean	- true on completion
324
 ******/
325
function generate_config_cache($config) {
326
	global $g;
327

  
328
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
329
	fwrite($configcache, serialize($config));
330
	fclose($configcache);
331
}
332

  
333
function discover_last_backup() {
334
        $backups = split("\n", `cd /cf/conf/backup && ls -ltr *.xml | awk '{print \$9}'`);
335
	$last_backup = "";
336
        foreach($backups as $backup)
337
        	if($backup)
338
	        	$last_backup = $backup;
339

  
340
        return $last_backup;
341
}
342

  
343
function restore_backup($file) {
344
	global $g;
345

  
346
	if (file_exists($file)) {
347
		conf_mount_rw();
348
		copy("$file","/cf/conf/config.xml");
349
		unlink_if_exists("{$g['tmp_path']}/config.cache");
350
		log_error("{$g['product_name']} is restoring the configuration $file");
351
		file_notice("config.xml", "{$g['product_name']} is restoring the configuration $file", "pfSenseConfigurator", "");
352
		conf_mount_ro();
353
	}
354
}
355

  
356
/****f* config/parse_config_bootup
357
 * NAME
358
 *   parse_config_bootup - Bootup-specific configuration checks.
359
 * RESULT
360
 *   null
361
 ******/
362
function parse_config_bootup() {
363
	global $config, $g, $noparseconfig;
364

  
365
	if($g['booting']) echo ".";
366

  
367
	$lockkey = lock('config');
368
	if (!$noparseconfig) {
369
		if (!file_exists("{$g['conf_path']}/config.xml")) {
370
			if ($g['booting']) {
371
				if (strstr($g['platform'], "cdrom")) {
372
					/* try copying the default config. to the floppy */
373
					echo "Resetting factory defaults...\n";
374
					reset_factory_defaults(true);
375
					if (file_exists("{$g['conf_path']}/config.xml")) {
376
						/* do nothing, we have a file. */
377
					} else {
378
						echo "No XML configuration file found - using factory defaults.\n";
379
						echo "Make sure that the configuration floppy disk with the conf/config.xml\n";
380
						echo "file is inserted. If it isn't, your configuration changes will be lost\n";
381
						echo "on reboot.\n";
382
					}
383
				} else {
384
					$last_backup = discover_last_backup();
385
					if($last_backup) {
386
						log_error("No config.xml found, attempting last known config restore.");
387
						file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
388
						restore_backup("/cf/conf/backup/{$last_backup}");
389
					}
390
					if(!file_exists("{$g['conf_path']}/config.xml")) {
391
						echo "XML configuration file not found.  {$g['product_name']} cannot continue booting.\n";
392
						mwexec("/sbin/halt");
393
						exit;
394
					}
395
					log_error("Last known config found and restored.  Please double check your configuration file for accuracy.");
396
					file_notice("config.xml", "Last known config found and restored.  Please double check your configuration file for accuracy.", "pfSenseConfigurator", "");
397
				}
398
			} else {
399
				unlock($lockkey);
400
				exit(0);
401
			}
402
		}
403
	}
404
	if (filesize("{$g['conf_path']}/config.xml") == 0) {
405
		$last_backup = discover_last_backup();
406
		if($last_backup) {
407
			log_error("No config.xml found, attempting last known config restore.");
408
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
409
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
410
		} else {
411
			unlock($lockkey);
412
			die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
413
		}
414
	}
415
	unlock($lockkey);
416
	parse_config(true);
417

  
418
	if ((float)$config['version'] > (float)$g['latest_config']) {
419
		echo <<<EOD
420

  
421

  
422
*******************************************************************************
423
* WARNING!                                                                    *
424
* The current configuration has been created with a newer version of {$g['product_name']}  *
425
* than this one! This can lead to serious misbehavior and even security       *
426
* holes! You are urged to either upgrade to a newer version of {$g['product_name']} or     *
427
* revert to the default configuration immediately!                            *
428
*******************************************************************************
429

  
430

  
431
EOD;
432
		}
433

  
434
	/* make alias table (for faster lookups) */
435
	alias_make_table($config);
436
}
437

  
438
/****f* config/conf_mount_rw
439
 * NAME
440
 *   conf_mount_rw - Mount filesystems read/write.
441
 * RESULT
442
 *   null
443
 ******/
444
/* mount flash card read/write */
445
function conf_mount_rw() {
446
	global $g;
447

  
448
	/* do not mount on cdrom platform */
449
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
450
		return;
451
		
452
	if (is_subsystem_dirty('mount'))
453
		return;
454

  
455
	$status = mwexec("/sbin/mount -u -w {$g['cf_path']}");
456
	if($status <> 0) {
457
		if($g['booting'])
458
			echo "Disk is dirty.  Running fsck -y\n";
459
		mwexec("/sbin/fsck -y {$g['cf_path']}");
460
		$status = mwexec("/sbin/mount -u -w {$g['cf_path']}");
461
	}
462

  
463
	/*    if the platform is soekris or wrap or pfSense, lets mount the
464
	 *    compact flash cards root.
465
         */
466
	if($g['platform'] == "wrap" or $g['platform'] == "net45xx"
467
	   or $g['platform'] == "embedded" or $g['platform'] == "nanobsd") {
468
		$status = mwexec("/sbin/mount -u -w /");
469
		/* we could not mount this correctly.  kick off fsck */
470
		if($status <> 0) {
471
			log_error("File system is dirty.  Launching FSCK for /");
472
			mwexec("/sbin/fsck -y /");
473
			$status = mwexec("/sbin/mount -u -w /");
474
		}
475
	}
476
	
477
	mark_subsystem_dirty('mount');
478
}
479

  
480
/****f* config/conf_mount_ro
481
 * NAME
482
 *   conf_mount_ro - Mount filesystems readonly.
483
 * RESULT
484
 *   null
485
 ******/
486
function conf_mount_ro() {
487
	global $g;
488

  
489
	if($g['booting'] == true)
490
		return;
491

  
492
	/* firmare upgrade in progress */
493
	if (is_subsystem_dirty('firmwarelock'))
494
		return;
495

  
496
	/* do not umount if generating ssh keys */
497
	if (is_subsystem_dirty('sshdkeys'))
498
		return;
499

  
500
	/* do not umount on cdrom or pfSense platforms */
501
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
502
		return;
503

  
504
	if (!is_subsystem_dirty('mount'))
505
		return;
506

  
507
	clear_subsystem_dirty('mount');
508
	/* sync data, then force a remount of /cf */
509
	mwexec("/bin/sync");
510
	mwexec("/bin/sync");
511
	mwexec("/sbin/mount -u -r -f {$g['cf_path']}");
512
	mwexec("/sbin/mount -u -r -f /");
513
}
514

  
515
/****f* config/convert_config
516
 * NAME
517
 *   convert_config - Attempt to update config.xml.
518
 * DESCRIPTION
519
 *   convert_config() reads the current global configuration
520
 *   and attempts to convert it to conform to the latest
521
 *   config.xml version. This allows major formatting changes
522
 *   to be made with a minimum of breakage.
523
 * RESULT
524
 *   null
525
 ******/
526
/* convert configuration, if necessary */
527
function convert_config() {
528
	global $config, $g;
529
	$now = date("H:i:s");
530
	log_error("Start Configuration upgrade at $now, set execution timeout to 15 minutes");
531
	ini_set("max_execution_time", "900");
532

  
533
	/* special case upgrades */
534
	/* fix every minute crontab bogons entry */
535
	$cron_item_count = count($config['cron']['item']);
536
	for($x=0; $x<$cron_item_count; $x++) {
537
		if(stristr($config['cron']['item'][$x]['command'], "rc.update_bogons.sh")) {
538
			if($config['cron']['item'][$x]['hour'] == "*" ) {
539
		        $config['cron']['item'][$x]['hour'] = "3";
540
		 		write_config("Updated bogon update frequency to 3am");
541
		 		log_error("Updated bogon update frequency to 3am");
542
		 	}       
543
		}
544
	}
545
	if ($config['version'] == $g['latest_config'])
546
		return;		/* already at latest version */
547

  
548
	// Save off config version
549
	$prev_version = $config['version'];
550
	
551
	include_once('upgrade_config.inc');
552
	/* Loop and run upgrade_VER_to_VER() until we're at current version */
553
	while ($config['version'] < $g['latest_config']) {
554
		$cur = $config['version'] * 10;
555
		$next = $cur + 1;
556
		$migration_function = sprintf('upgrade_%03d_to_%03d', $cur, $next);
557
		$migration_function();
558
		$config['version'] = sprintf('%.1f', $next / 10);
559
		echo ".";
560
	}
561

  
562
	$now = date("H:i:s");
563
	log_error("Ended Configuration upgrade at $now");
564

  
565
	if ($prev_version != $config['version'])
566
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
567
}
568

  
569
/****f* config/write_config
570
 * NAME
571
 *   write_config - Backup and write the firewall configuration.
572
 * DESCRIPTION
573
 *   write_config() handles backing up the current configuration,
574
 *   applying changes, and regenerating the configuration cache.
575
 * INPUTS
576
 *   $desc	- string containing the a description of configuration changes
577
 *   $backup	- boolean: do not back up current configuration if false.
578
 * RESULT
579
 *   null
580
 ******/
581
/* save the system configuration */
582
function write_config($desc="Unknown", $backup = true) {
583
	global $config, $g;
584

  
585
	if($g['bootup']) 
586
		log_error("WARNING! Configuration written on bootup.  This can cause stray openvpn and load balancing items in config.xml");
587

  
588
	if($backup)
589
		backup_config();
590

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

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

  
598
	$config['revision']['description'] = $desc;
599
	$config['revision']['time'] = $changetime;
600

  
601
	$lockkey = lock('config');
602

  
603
	/* generate configuration XML */
604
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
605

  
606
	conf_mount_rw();
607

  
608
	/* write new configuration */
609
	$fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
610
        if (!$fd) {
611
                // Unable to open temporary file for writing
612
		log_error("WARNING: Config contents could not be save. Could not open file!");
613
		unlock($lockkey);
614
                return false;
615
        }
616
        if (!fwrite($fd, $xmlconfig)) {
617
                // Unable to write to temporary file
618
		log_error("WARNING: Config contents could not be written on file.");
619
                fclose($fd);
620
		unlock($lockkey);
621
                return false;
622
        }
623
        fclose($fd);
624

  
625
	if($g['platform'] == "embedded" or $g['platform'] == "nanobsd") {
626
		cleanup_backupcache(5, true);
627
	} else {
628
		cleanup_backupcache(30, true);
629
	}
630

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

  
634
	/* write config cache */
635
	$fd = @fopen("{$g['tmp_path']}/config.cache", "wb");
636
	if ($fd) {
637
		fwrite($fd, serialize($config));
638
		fclose($fd);
639
	}
640

  
641
	/* tell kernel to sync fs data */
642
	if (!$g['booting'])
643
		conf_mount_ro();
644
	unlock($lockkey);
645

  
646
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
647
	/* sync carp entries to other firewalls */
648
        carp_sync_client();
649

  
650
	if(is_dir("/usr/local/pkg/write_config")) {
651
		/* process packager manager custom rules */
652
		run_plugins("/usr/local/pkg/write_config/");
653
	}
654

  
655
	return $config;
656
}
657

  
658
/****f* config/reset_factory_defaults
659
 * NAME
660
 *   reset_factory_defaults - Reset the system to its default configuration.
661
 * RESULT
662
 *   integer	- indicates completion
663
 ******/
664
function reset_factory_defaults($lock = false) {
665
	global $g;
666

  
667
	if (!$lock)
668
		$lockkey = lock('config');
669
	conf_mount_rw();
670

  
671
	/* create conf directory, if necessary */
672
	safe_mkdir("{$g['cf_conf_path']}");
673

  
674
	/* clear out /conf */
675
	$dh = opendir($g['conf_path']);
676
	while ($filename = readdir($dh)) {
677
		if (($filename != ".") && ($filename != "..")) {
678
			unlink_if_exists($g['conf_path'] . "/" . $filename);
679
		}
680
	}
681
	closedir($dh);
682

  
683
	/* copy default configuration */
684
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
685

  
686
	/* call the wizard */
687
	touch("/conf/trigger_initial_wizard");
688
	conf_mount_ro();
689
	if (!$lock)
690
		unlock($lockkey);
691

  
692
	return 0;
693
}
694

  
695
function config_restore($conffile) {
696
	global $config, $g;
697

  
698
	if (!file_exists($conffile))
699
		return 1;
700

  
701
	conf_mount_rw();
702

  
703
	backup_config();
704

  
705
	$lockkey = lock('config');
706

  
707
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
708
	unlink_if_exists("{$g['tmp_path']}/config.cache");
709

  
710
	unlock($lockkey);
711

  
712
	$config = parse_config(true);
713

  
714
	write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
715

  
716
	conf_mount_ro();
717

  
718
	return 0;
719
}
720

  
721
function config_install($conffile) {
722
	global $config, $g;
723

  
724
	if (!file_exists($conffile))
725
		return 1;
726

  
727
	if (!config_validate("{$conffile}"))
728
		return 1;
729

  
730
	if($g['booting'] == true)
731
		echo "Installing configuration...\n";
732
	else
733
		log_error("Installing configuration ....");
734

  
735
	conf_mount_rw();
736
	$lockkey = lock('config');
737

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

  
740
	/* unlink cache file if it exists */
741
	if(file_exists("{$g['tmp_path']}/config.cache"))
742
		unlink("{$g['tmp_path']}/config.cache");
743

  
744
	unlock($lockkey);
745
	conf_mount_ro();
746

  
747
    return 0;
748
}
749

  
750
function config_validate($conffile) {
751

  
752
	global $g, $xmlerr;
753

  
754
	$xml_parser = xml_parser_create();
755

  
756
	if (!($fp = fopen($conffile, "r"))) {
757
		$xmlerr = "XML error: unable to open file";
758
		return false;
759
	}
760

  
761
	while ($data = fread($fp, 4096)) {
762
		if (!xml_parse($xml_parser, $data, feof($fp))) {
763
			$xmlerr = sprintf("%s at line %d",
764
						xml_error_string(xml_get_error_code($xml_parser)),
765
						xml_get_current_line_number($xml_parser));
766
			return false;
767
		}
768
	}
769
	xml_parser_free($xml_parser);
770

  
771
	fclose($fp);
772

  
773
	return true;
774
}
775

  
776
function set_networking_interfaces_ports() {
777
	global $noreboot;
778
	global $config;
779
	global $g;
780
	global $fp;
781

  
782
	$fp = fopen('php://stdin', 'r');
783

  
784
	$memory = get_memory();
785
	$avail = $memory[0];
786

  
787
	if($avail < $g['minimum_ram_warning']) {
788
		echo "\n\n\n";
789
		echo "DANGER!  WARNING!  ACHTUNG!\n\n";
790
		echo "{$g['product_name']} requires *AT LEAST* {$g['minimum_ram_warning_text']} RAM to function correctly.\n";
791
		echo "Only ({$avail}) MB RAM has been detected.\n";
792
		echo "\nPress ENTER to continue. ";
793
		fgets($fp);
794
		echo "\n";
795
	}
796

  
797
	$iflist = get_interface_list();
798

  
799
/* Function flow is based on $key and $auto_assign or the lack thereof */	
800
	$key = null;
801

  
802
/* Only present auto interface option if running from LiveCD and interface mismatch*/
803
	if ((ereg("cdrom", $g['platform'])) && is_interface_mismatch())
804
		$auto_assign = false;
805

  
806
	echo <<<EOD
807

  
808
Valid interfaces are:
809

  
810

  
811
EOD;
812

  
813
	if(!is_array($iflist)) {
814
		echo "No interfaces found!\n";
815
		$iflist = array();
816
	} else {
817
		foreach ($iflist as $iface => $ifa) {
818
			echo sprintf("% -16s%s%s\t%s\n", $iface, $ifa['mac'],
819
				$ifa['up'] ? "   (up)" : "   (down)", $ifa['dmesg']);
820
		}
821
	}
822

  
823
	if ($auto_assign) {
824
		echo <<<EOD
825
		
826
		!!! LiveCD Detected: Auto Interface Option !!!!
827
BEGIN MANUAL CONFIGURATION OR WE WILL PROCEED WITH AUTO CONFIGURATION.
828

  
829
EOD;
830
	}	
831
	
832
	echo <<<EOD
833

  
834
Do you want to set up VLANs first? 
835

  
836
If you are not going to use VLANs, or only for optional interfaces, you should
837
say no here and use the webConfigurator to configure VLANs later, if required.
838

  
839
Do you want to set up VLANs now [y|n]? 
840
EOD;
841

  
842
	if ($auto_assign) {
843
		$key = timeout();
844

  
845
	} else
846
		$key = chop(fgets($fp));
847

  
848
	if (!isset($key) and $auto_assign) {	// Auto Assign Interfaces
849
		do {
850
			echo <<<EOD
851

  
852
   !!! Auto Assigning Interfaces !!!
853

  
854
For installation purposes, you must plug in at least one NIC
855
for the LAN connection. If you plug in a second NIC it will be
856
assigned to WAN. Otherwise, we'll temporarily assign WAN to the
857
next available NIC found regardless of activity. You should
858
assign and configure the WAN interface according to your requirements
859

  
860
If you haven't plugged in any network cables yet,
861
now is the time to do so.
862
We'll keep trying until you do.
863

  
864
Searching for active interfaces...
865
 
866
EOD;
867
			unset($wanif, $lanif);
868

  
869
			$media_iflist = $plugged_in = array();
870
			$media_iflist = get_interface_list("media");
871
			foreach ($media_iflist as $iface => $ifa) {
872
				if ($ifa['up']) 
873
					$plugged_in[] = $iface;
874
				
875
			}
876

  
877
			$lanif = array_shift($plugged_in);
878
			$wanif = array_shift($plugged_in);
879

  
880
			if(isset($lanif) && !isset($wanif)) {
881
				foreach ($iflist as $iface => $ifa) {
882
					if ($iface != $lanif) {
883
						$wanif = $iface;
884
						break;
885
					}
886
				}
887
			}
888

  
889
			echo <<<EOD
890

  
891
Assigned WAN to : $wanif 
892
Assigned LAN to : $lanif
893

  
894
If you don't like this assignment,
895
press any key to go back to manual configuration. 
896

  
897
EOD;
898
			$key = timeout(20);
899
			if(isset($key))
900
				return;
901
		} while (!isset($wanif));
902

  
903
		$config['system']['enablesshd'] = 'enabled';	
904
		$key = 'y';
905

  
906
	} else {		//Manually assign interfaces	
907
		if (in_array($key, array('y', 'Y')))
908
			vlan_setup();
909
	
910
		if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
911
	
912
			echo "\n\nVLAN interfaces:\n\n";
913
			foreach ($config['vlans']['vlan'] as $vlan) {
914
	
915
				echo sprintf("% -16s%s\n", "{$vlan['if']}_vlan{$vlan['tag']}",
916
					"VLAN tag {$vlan['tag']}, parent interface {$vlan['if']}");
917
	
918
				$iflist[$vlan['if'] . '_vlan' . $vlan['tag']] = array();
919
			}
920
		}
921
	
922
		echo <<<EOD
923
	
924
*NOTE*  {$g['product_name']} requires {$g['minimum_nic_count_text']} assigned interfaces to function.
925
        If you do not have {$g['minimum_nic_count_text']} interfaces you CANNOT continue. 
926

  
927
        If you do not have at least {$g['minimum_nic_count']} *REAL* network interface cards
928
        or one interface with multiple VLANs then {$g['product_name']}
929
        *WILL NOT* function correctly.
930

  
931
If you do not know the names of your interfaces, you may choose to use
932
auto-detection. In that case, disconnect all interfaces now before
933
hitting 'a' to initiate auto detection.
934
	
935
EOD;
936
	
937
		do {
938
			echo "\nEnter the WAN interface name or 'a' for auto-detection: ";
939
			$wanif = chop(fgets($fp));
940
			if ($wanif === "") {
941
				return;
942
			}
943
			if ($wanif === "a")
944
				$wanif = autodetect_interface("WAN", $fp);
945
			else if (!array_key_exists($wanif, $iflist)) {
946
				echo "\nInvalid interface name '{$wanif}'\n";
947
				unset($wanif);
948
				continue;
949
			}
950
		} while (!$wanif);
951
	
952
		do {
953
			echo "\nEnter the LAN interface name or 'a' for auto-detection \n" .
954
			    "NOTE: this enables full Firewalling/NAT mode.\n" .
955
				"(or nothing if finished): ";
956
	
957
			$lanif = chop(fgets($fp));
958
			
959
			if($lanif == "exit") {
960
				exit;
961
			}
962
			
963
			if($lanif == "") {
964
				if($g['minimum_nic_count'] < 2) {
965
					break;	
966
				} else {
967
					fclose($fp);
968
					return;
969
				}
970
			}
971
	
972
			if ($lanif === "a")
973
				$lanif = autodetect_interface("LAN", $fp);
974
			else if (!array_key_exists($lanif, $iflist)) {
975
				echo "\nInvalid interface name '{$lanif}'\n";
976
				unset($lanif);
977
				continue;
978
			}
979
		} while (!$lanif);
980
	
981
		/* optional interfaces */
982
		$i = 0;
983
		$optif = array();
984
	
985
		if($lanif <> "") {
986
			while (1) {
987
				if ($optif[$i])
988
					$i++;
989
				$i1 = $i + 1;
990
		
991
				if($config['interfaces']['opt' . $i1]['descr'])
992
					echo "\nOptional interface {$i1} description found: {$config['interfaces']['opt' . $i1]['descr']}";
993
	
994
				echo "\nEnter the Optional {$i1} interface name or 'a' for auto-detection\n" .
995
					"(or nothing if finished): ";
996
		
997
				$optif[$i] = chop(fgets($fp));
998
		
999
				if ($optif[$i]) {
1000
					if ($optif[$i] === "a") {
1001
						$ad = autodetect_interface("Optional " . $i1, $fp);
1002
						if ($ad)
1003
							$optif[$i] = $ad;
1004
						else
1005
							unset($optif[$i]);
1006
					} else if (!array_key_exists($optif[$i], $iflist)) {
1007
						echo "\nInvalid interface name '{$optif[$i]}'\n";
1008
						unset($optif[$i]);
1009
						continue;
1010
					}
1011
				} else {
1012
					unset($optif[$i]);
1013
					break;
1014
				}
1015
			}
1016
		}
1017
		
1018
		/* check for double assignments */
1019
		$ifarr = array_merge(array($lanif, $wanif), $optif);
1020
		
1021
		for ($i = 0; $i < (count($ifarr)-1); $i++) {
1022
			for ($j = ($i+1); $j < count($ifarr); $j++) {
1023
				if ($ifarr[$i] == $ifarr[$j]) {
1024
					echo <<<EOD
1025
	
1026
Error: you cannot assign the same interface name twice!
1027
	
1028
EOD;
1029
					fclose($fp);
1030
					return;
1031
				}
1032
			}
1033
		}
1034
	
1035
		echo "\nThe interfaces will be assigned as follows: \n\n";
1036
	
1037
		if ($lanif != "")
1038
			echo "LAN  ->" . $lanif . "\n";
1039
		echo "WAN  ->" . $wanif . "\n";
1040
		for ($i = 0; $i < count($optif); $i++) {
1041
			echo "OPT" . ($i+1) . " -> " . $optif[$i] . "\n";
1042
		}
1043
	
1044
		echo <<<EOD
1045
	
1046
Do you want to proceed [y|n]?
1047
EOD;
1048
			$key = chop(fgets($fp));		
1049
	}
1050

  
1051
	if (in_array($key, array('y', 'Y'))) {
1052
		if($lanif) {
1053
			$config['interfaces']['lan']['if'] = $lanif;
1054
		} elseif (!$g['booting'] && !$auto_assign) {
1055

  
1056
echo <<<EODD
1057

  
1058
You have chosen to remove the LAN interface.
1059

  
1060
Would you like to remove the LAN IP address and
1061
unload the interface now? [y|n]? 
1062
EODD;
1063

  
1064
				if (strcasecmp(chop(fgets($fp)), "y") == 0) {
1065
					if($config['interfaces']['lan']['if'])
1066
						mwexec("/sbin/ifconfig delete " . $config['interfaces']['lan']['if']);
1067
				}
1068
				if(isset($config['interfaces']['lan']))
1069
					unset($config['interfaces']['lan']);
1070
				if(isset($config['dhcpd']['lan']))
1071
					unset($config['dhcpd']['lan']);
1072
				if(isset($config['interfaces']['lan']['if']))
1073
					unset($config['interfaces']['lan']['if']);
1074
				if(isset($config['interfaces']['wan']['blockpriv']))
1075
					unset($config['interfaces']['wan']['blockpriv']);
1076
				if(isset($config['shaper']))
1077
					unset($config['shaper']);
1078
				if(isset($config['ezshaper']))
1079
					unset($config['ezshaper']);
1080
				if(isset($config['nat']))
1081
					unset($config['nat']);				
1082
		} else {
1083
			if(isset($config['interfaces']['lan']['if']))
1084
				mwexec("/sbin/ifconfig delete " . $config['interfaces']['lan']['if']);
1085
			if(isset($config['interfaces']['lan']))
1086
				unset($config['interfaces']['lan']);
1087
			if(isset($config['dhcpd']['lan']))
1088
				unset($config['dhcpd']['lan']);
1089
			if(isset($config['interfaces']['lan']['if']))
1090
				unset($config['interfaces']['lan']['if']);
1091
			if(isset($config['interfaces']['wan']['blockpriv']))
1092
				unset($config['interfaces']['wan']['blockpriv']);
1093
			if(isset($config['shaper']))
1094
				unset($config['shaper']);
1095
			if(isset($config['ezshaper']))
1096
				unset($config['ezshaper']);
1097
			if(isset($config['nat']))
1098
				unset($config['nat']);				
1099
		}
1100
		if (preg_match($g['wireless_regex'], $lanif)) {
1101
			if (is_array($config['interfaces']['lan']) &&
1102
				(!is_array($config['interfaces']['lan']['wireless'])))
1103
				$config['interfaces']['lan']['wireless'] = array();
1104
		} else {
1105
			unset($config['interfaces']['lan']['wireless']);
1106
		}
1107

  
1108
		$config['interfaces']['wan']['if'] = $wanif;
1109
		if (preg_match($g['wireless_regex'], $wanif)) {
1110
			if (is_array($config['interfaces']['lan']) &&
1111
				(!is_array($config['interfaces']['wan']['wireless'])))
1112
				$config['interfaces']['wan']['wireless'] = array();
1113
		} else {
1114
			unset($config['interfaces']['wan']['wireless']);
1115
		}
1116

  
1117
		for ($i = 0; $i < count($optif); $i++) {
1118
			if (!is_array($config['interfaces']['opt' . ($i+1)]))
1119
				$config['interfaces']['opt' . ($i+1)] = array();
1120

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

  
1123
			/* wireless interface? */
1124
			if (preg_match($g['wireless_regex'], $optif[$i])) {
1125
				if (!is_array($config['interfaces']['opt' . ($i+1)]['wireless']))
1126
					$config['interfaces']['opt' . ($i+1)]['wireless'] = array();
1127
			} else {
1128
				unset($config['interfaces']['opt' . ($i+1)]['wireless']);
1129
			}
1130

  
1131
			unset($config['interfaces']['opt' . ($i+1)]['enable']);
1132
			$config['interfaces']['opt' . ($i+1)]['descr'] = "OPT" . ($i+1);
1133
		}
1134

  
1135
		/* remove all other (old) optional interfaces */
1136
		for (; isset($config['interfaces']['opt' . ($i+1)]); $i++)
1137
			unset($config['interfaces']['opt' . ($i+1)]);
1138

  
1139
		echo "\nWriting configuration...";
1140
		write_config();
1141
		echo "done.\n";
1142

  
1143
		echo <<<EOD
1144

  
1145

  
1146

  
1147
EOD;
1148

  
1149
		fclose($fp);
1150
		if($g['booting'])
1151
			return;
1152

  
1153
		echo "One moment while we reload the settings...";
1154

  
1155
		$g['booting'] = false;
1156

  
1157
		/* XXX: ermal - disable it for now this is used during bootup at best so shouldn't be needed.
1158
		 * 		For now just comment it out and later remove it completely.
1159
		 * resync everything 
1160
			reload_all_sync();
1161
		 */
1162

  
1163
		echo " done!\n";
1164

  
1165
		touch("{$g['tmp_path']}/assign_complete");
1166

  
1167
	}
1168
}
1169

  
1170
function autodetect_interface($ifname, $fp) {
1171
	$iflist_prev = get_interface_list("media");
1172
	echo <<<EOD
1173

  
1174
Connect the {$ifname} interface now and make sure that the link is up.
1175
Then press ENTER to continue.
1176

  
1177
EOD;
1178
	fgets($fp);
1179
	$iflist = get_interface_list("media");
1180

  
1181
	foreach ($iflist_prev as $ifn => $ifa) {
1182
		if (!$ifa['up'] && $iflist[$ifn]['up']) {
1183
			echo "Detected link-up on interface {$ifn}.\n";
1184
			return $ifn;
1185
		}
1186
	}
1187

  
1188
	echo "No link-up detected.\n";
1189

  
1190
	return null;
1191
}
1192

  
1193
function vlan_setup() {
1194
	global $iflist, $config, $g, $fp;
1195

  
1196
	$iflist = get_interface_list();
1197

  
1198
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
1199

  
1200
	echo <<<EOD
1201

  
1202
WARNING: all existing VLANs will be cleared if you proceed!
1203

  
1204
Do you want to proceed [y|n]?
1205
EOD;
1206

  
1207
	if (strcasecmp(chop(fgets($fp)), "y") != 0)
1208
		return;
1209
	}
1210

  
1211
	$config['vlans']['vlan'] = array();
1212
	echo "\n";
1213

  
1214
	$vlanif = 0;
1215

  
1216
	while (1) {
1217
		$vlan = array();
1218

  
1219
		echo "\n\nVLAN Capable interfaces:\n\n";
1220
		if(!is_array($iflist)) {
1221
			echo "No interfaces found!\n";
1222
		} else {
1223
			$vlan_capable=0;
1224
			foreach ($iflist as $iface => $ifa) {
1225
				if (is_jumbo_capable($iface)) {
1226
					echo sprintf("% -8s%s%s\n", $iface, $ifa['mac'],
1227
						$ifa['up'] ? "   (up)" : "");
1228
					$vlan_capable++;
1229
				}
1230
			}
1231
		}
1232

  
1233
		if($vlan_capable == 0) {
1234
			echo "No VLAN capable interfaces detected.\n";
1235
			return;
1236
		}
1237

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

  
1241
		if ($vlan['if']) {
1242
			if (!array_key_exists($vlan['if'], $iflist) or
1243
			    !is_jumbo_capable($vlan['if'])) {
1244
				echo "\nInvalid interface name '{$vlan['if']}'\n";
1245
				continue;
1246
			}
1247
		} else {
1248
			break;
1249
		}
1250

  
1251
		echo "Enter the VLAN tag (1-4094): ";
1252
		$vlan['tag'] = chop(fgets($fp));
1253
		$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
1254
		if (!is_numericint($vlan['tag']) || ($vlan['tag'] < 1) || ($vlan['tag'] > 4094)) {
1255
			echo "\nInvalid VLAN tag '{$vlan['tag']}'\n";
1256
			continue;
1257
		}
1258
		
1259
		$config['vlans']['vlan'][] = $vlan;
1260
		$vlanif++;
1261
	}
1262
}
1263

  
1264
function cleanup_backupcache($revisions = 30, $lock = false) {
1265
	global $g;
1266
	$i = false;
1267
	
1268
	if (!$lock)
1269
		$lockkey = lock('config');
1270
	if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1271
		conf_mount_rw();
1272
		$backups = get_backups();
1273
		$newbaks = array();
1274
		$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
1275
		$baktimes = $backups['versions'];
1276
		$tocache = array();
1277
		unset($backups['versions']);
1278
   		foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
1279
   			if(filesize($backup) == 0) {
1280
   				unlink($backup);
1281
   				continue;
1282
   			}
1283
			$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));
1284
            if(!in_array($tocheck, $baktimes)) {
1285
				$i = true;
1286
				if($g['booting'])
1287
					echo ".";
1288
				$newxml = parse_xml_config($backup, $g['xml_rootobj']);
1289
				if($newxml == "-1") {
1290
					log_error("The backup cache file $backup is corrupted.  Unlinking.");
1291
					unlink($backup);
1292
					log_error("The backup cache file $backup is corrupted.  Unlinking.");
1293
					continue;
1294
				}
1295
				if($newxml['revision']['description'] == "")
1296
					$newxml['revision']['description'] = "Unknown";
1297
				$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
1298
			}
1299
    	}
1300
		foreach($backups as $checkbak) {
1301 201

  
1302
			if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
1303
				$newbaks[] = $checkbak;
1304
			} else {
1305
				$i = true;
1306
				if($g['booting']) print " " . $tocheck . "r";
1307
			}
1308
		}
1309
		foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);
1310
		if(is_int($revisions) and (count($tocache) > $revisions)) {
1311
			$toslice = array_slice(array_keys($tocache), 0, $revisions);
1312
			foreach($toslice as $sliced)
1313
				$newcache[$sliced] = $tocache[$sliced];
1314
			foreach($tocache as $version => $versioninfo) {
1315
				if(!in_array($version, array_keys($newcache))) {
1316
					unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
1317
					if($g['booting']) print " " . $tocheck . "d";
1318
				}
1319
			}
1320
			$tocache = $newcache;
1321
		}
1322
		$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1323
        fwrite($bakout, serialize($tocache));
1324
		fclose($bakout);
1325
		conf_mount_ro();
1326
	}
1327
	if($g['booting'] && $i)
1328
		print "done.\n";
1329
	if (!$lock)
1330
		unlock($lockkey);
1331
}
1332

  
1333
function get_backups() {
1334
	global $g;
1335
	if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1336
		$confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1337
		$bakvers = array_keys($confvers);
1338
		$toreturn = array();
1339
		sort($bakvers);
1340
		// 	$bakvers = array_reverse($bakvers);
1341
		foreach(array_reverse($bakvers) as $bakver)
1342
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description']);
1343
	} else {
1344
		return false;
1345
	}
1346
	$toreturn['versions'] = $bakvers;
1347
	return $toreturn;
1348
}
1349

  
1350
function backup_config() {
1351
	global $config, $g;
1352

  
1353
	if($g['platform'] == "cdrom")
1354
		return;
1355

  
1356
	conf_mount_rw();
1357

  
1358
	/* Create backup directory if needed */
1359
	safe_mkdir("{$g['cf_conf_path']}/backup");
1360

  
1361
    if($config['revision']['time'] == "") {
1362
            $baktime = 0;
1363
    } else {
1364
            $baktime = $config['revision']['time'];
1365
    }
1366
    if($config['revision']['description'] == "") {
1367
            $bakdesc = "Unknown";
1368
    } else {
1369
            $bakdesc = $config['revision']['description'];
1370
    }
1371
    copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
1372
    if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
1373
            $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
1374
    } else {
1375
            $backupcache = array();
1376
    }
1377
    $backupcache[$baktime] = array('description' => $bakdesc);
1378
    $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
1379
    fwrite($bakout, serialize($backupcache));
1380
    fclose($bakout);
1381

  
1382
	conf_mount_ro();
1383

  
1384
	return true;
1385
}
1386

  
1387
function set_device_perms() {
1388
	$devices = array(
1389
		'pf'	=> array(	'user'	=> 'proxy',
1390
					'group'	=> 'proxy',
1391
					'mode'	=> 0660),
1392
		);
1393

  
1394
	foreach ($devices as $name => $attr) {
1395
		$path = "/dev/$name";
1396
		if (file_exists($path)) {
1397
			chown($path, $attr['user']);
1398
			chgrp($path, $attr['group']);
1399
			chmod($path, $attr['mode']);
1400
		}
1401
	}
1402
}
1403 202

  
1404 203
if($g['booting']) echo ".";
1405 204
$config = parse_config();

Also available in: Unified diff