wpa_supplicant: Add option -I for additional config file

This option can be used only for global parameters that is not going
to be changed from settings.

Change-Id: I4f18aa0a8503cf8cc3a847ac9fcc15419291edf0
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c
index eb7f5f2..10b9e0d 100644
--- a/src/utils/os_unix.c
+++ b/src/utils/os_unix.c
@@ -213,6 +213,9 @@
 	size_t len = 128, cwd_len, rel_len, ret_len;
 	int last_errno;
 
+	if (!rel_path)
+		return NULL;
+
 	if (rel_path[0] == '/')
 		return os_strdup(rel_path);
 
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 1315e7b..f83499c 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -912,6 +912,7 @@
  * wpa_config_read - Read and parse configuration database
  * @name: Name of the configuration (e.g., path and file name for the
  * configuration file)
+ * @cfgp: Pointer to previousely allocated configuration data
  * Returns: Pointer to allocated configuration data or %NULL on failure
  *
  * This function reads configuration data, parses its contents, and allocates
@@ -920,7 +921,7 @@
  *
  * Each configuration backend needs to implement this function.
  */
-struct wpa_config * wpa_config_read(const char *name);
+struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp);
 
 /**
  * wpa_config_write - Write or update configuration data
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 5ca6bf2..8604ae8 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -345,7 +345,7 @@
 #endif /* CONFIG_NO_CONFIG_BLOBS */
 
 
-struct wpa_config * wpa_config_read(const char *name)
+struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
 {
 	FILE *f;
 	char buf[512], *pos;
@@ -356,12 +356,19 @@
 	int id = 0;
 	int cred_id = 0;
 
-	config = wpa_config_alloc_empty(NULL, NULL);
+	if (name == NULL)
+		return NULL;
+	if (cfgp)
+		config = cfgp;
+	else
+		config = wpa_config_alloc_empty(NULL, NULL);
 	if (config == NULL) {
 		wpa_printf(MSG_ERROR, "Failed to allocate config file "
 			   "structure");
 		return NULL;
 	}
+	head = config->ssid;
+	cred_head = config->cred;
 
 	wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
 	f = fopen(name, "r");
diff --git a/wpa_supplicant/config_none.c b/wpa_supplicant/config_none.c
index 589ea36..2aac28f 100644
--- a/wpa_supplicant/config_none.c
+++ b/wpa_supplicant/config_none.c
@@ -17,11 +17,16 @@
 #include "base64.h"
 
 
-struct wpa_config * wpa_config_read(const char *name)
+struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
 {
 	struct wpa_config *config;
 
-	config = wpa_config_alloc_empty(NULL, NULL);
+	if (name == NULL)
+		return NULL;
+	if (cfgp)
+		config = cfgp;
+	else
+		config = wpa_config_alloc_empty(NULL, NULL);
 	if (config == NULL)
 		return NULL;
 	/* TODO: fill in configuration data */
diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c
index 2750b63..3cf3a91 100644
--- a/wpa_supplicant/config_winreg.c
+++ b/wpa_supplicant/config_winreg.c
@@ -434,7 +434,7 @@
 }
 
 
-struct wpa_config * wpa_config_read(const char *name)
+struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
 {
 	TCHAR buf[256];
 	int errors = 0;
@@ -442,7 +442,12 @@
 	HKEY hk;
 	LONG ret;
 
-	config = wpa_config_alloc_empty(NULL, NULL);
+	if (name == NULL)
+		return NULL;
+	if (cfgp)
+		config = cfgp;
+	else
+		config = wpa_config_alloc_empty(NULL, NULL);
 	if (config == NULL)
 		return NULL;
 	wpa_printf(MSG_DEBUG, "Reading configuration profile '%s'", name);
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index 87e399c..dad2765 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -1232,7 +1232,7 @@
 
 	os_memset(&wpa_s, 0, sizeof(wpa_s));
 	eapol_test.wpa_s = &wpa_s;
-	wpa_s.conf = wpa_config_read(conf);
+	wpa_s.conf = wpa_config_read(conf, NULL);
 	if (wpa_s.conf == NULL) {
 		printf("Failed to parse configuration file '%s'.\n", conf);
 		return -1;
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index 19f7ce6..c3ecbb3 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -32,7 +32,7 @@
 	       "        [-o<override driver>] [-O<override ctrl>] \\\n"
 	       "        [-N -i<ifname> -c<conf> [-C<ctrl>] "
 	       "[-D<driver>] \\\n"
-	       "        [-p<driver_param>] [-b<br_ifname>] ...]\n"
+	       "        [-p<driver_param>] [-b<br_ifname>] [-I<config file>]\n"
 	       "\n"
 	       "drivers:\n",
 	       wpa_supplicant_version, wpa_supplicant_license);
@@ -50,6 +50,7 @@
 	       "  -c = Configuration file\n"
 	       "  -C = ctrl_interface parameter (only used if -c is not)\n"
 	       "  -i = interface name\n"
+	       "  -I = additional Configuration file\n"
 	       "  -d = increase debugging verbosity (-dd even more)\n"
 	       "  -D = driver name (can be multiple drivers: nl80211,wext)\n"
 	       "  -e = entropy file\n");
@@ -155,7 +156,7 @@
 
 	for (;;) {
 		c = getopt(argc, argv,
-			   "b:Bc:C:D:de:f:g:hi:KLNo:O:p:P:qsTtuvW");
+			   "b:Bc:C:D:de:f:g:hi:I:KLNo:O:p:P:qsTtuvW");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -202,6 +203,9 @@
 		case 'i':
 			iface->ifname = optarg;
 			break;
+		case 'I':
+			iface->confanother = optarg;
+			break;
 		case 'K':
 			params.wpa_debug_show_keys++;
 			break;
diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c
index 3503e65..ff2ae74 100644
--- a/wpa_supplicant/preauth_test.c
+++ b/wpa_supplicant/preauth_test.c
@@ -309,7 +309,7 @@
 	}
 
 	os_memset(&wpa_s, 0, sizeof(wpa_s));
-	wpa_s.conf = wpa_config_read(argv[1]);
+	wpa_s.conf = wpa_config_read(argv[1], NULL);
 	if (wpa_s.conf == NULL) {
 		printf("Failed to parse configuration file '%s'.\n", argv[1]);
 		return -1;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index a6478b6..398fca1 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -766,12 +766,14 @@
 
 	if (wpa_s->confname == NULL)
 		return -1;
-	conf = wpa_config_read(wpa_s->confname);
+	conf = wpa_config_read(wpa_s->confname, NULL);
 	if (conf == NULL) {
 		wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
 			"file '%s' - exiting", wpa_s->confname);
 		return -1;
 	}
+	wpa_config_read(wpa_s->confanother, conf);
+
 	conf->changed_parameters = (unsigned int) -1;
 
 	reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
@@ -2822,12 +2824,14 @@
 #else /* CONFIG_BACKEND_FILE */
 		wpa_s->confname = os_strdup(iface->confname);
 #endif /* CONFIG_BACKEND_FILE */
-		wpa_s->conf = wpa_config_read(wpa_s->confname);
+		wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
 		if (wpa_s->conf == NULL) {
 			wpa_printf(MSG_ERROR, "Failed to read or parse "
 				   "configuration '%s'.", wpa_s->confname);
 			return -1;
 		}
+		wpa_s->confanother = os_rel2abs_path(iface->confanother);
+		wpa_config_read(wpa_s->confanother, wpa_s->conf);
 
 		/*
 		 * Override ctrl_interface and driver_param if set on command
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 0308806..b47c11b 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -56,6 +56,13 @@
 	const char *confname;
 
 	/**
+	 * confanother - Additional Configuration name (file or profile) name
+	 *
+	 * This can also be %NULL when a configuration file is not used.
+	 */
+	const char *confanother;
+
+	/**
 	 * ctrl_interface - Control interface parameter
 	 *
 	 * If a configuration file is not used, this variable can be used to
@@ -307,6 +314,7 @@
 	char bridge_ifname[16];
 
 	char *confname;
+	char *confanother;
 	struct wpa_config *conf;
 	int countermeasures;
 	os_time_t last_michael_mic_error;