Cumulative patch from commit 3b208346ec56342fda736e62601df485ed002493

3b20834 ctrl_iface: BSS command to skip info items if parsing fails
a9c52e8 HS 2.0R2: No longer use HTTP_RAW_POST_DATA
04c18fa curl: Don't free memory for subjectAltName before calling callback
5a8e48f mesh: Use MESH_CAP_* macros for mesh capability
d70a8ab mesh: Ignore crowded peer
a151b0e mesh: Select pairwise and group cipher based on network profile
3b6deac mesh: Avoid use of hardcoded cipher
f868d56 mesh: Clean up AMPE element encoding and parsing
4367eec mesh: Do not use RX MGTK as RX IGTK
a4eec3c mesh: Use variable length MGTK for RX
fccba2c mesh: Generate a separate TX IGTK if PMF is enabled
696f792 mesh: Support variable length TX MGTK
b02f4d0 mesh: Add variable length MTK support
846201d mesh: Coding style cleanup for MTK derivation
0f76d82 mesh: Fix MTK derivation to use AKM suite selector
f5ba692 mesh: Coding style cleanup for AEK derivation
a59c5e9 mesh: Fix AEK derivation to use AKM suite selector
18aca1a mesh: Use ieee80211w profile parameter
b8b499e mesh: Use WPA_NONCE_LEN macro
bb4e19e hostapd: Skip hostapd ACL check for drivers supporting ACL offload
00ec535 WPS: Fix memory leak with wps_ie in wpa_bss_is_wps_candidate()
d1296da Reserve QCA vendor specific nl80211 command 121
fae7b37 WPS: Do not expire probable BSSes for WPS connection
52a6c9c Add a QCA vendor command to configure AP parameters
31d3692 hostapd: Add comment about '-i' parameter in hostapd.conf
40f6282 hostapd: Accept interface names as a command line parameter
cc27c8e hostapd: Fix early init failure path
976dfb3 FST: Make fst_global_deinit() more robust
7a69fad mesh: Sync max peer links with kernel
f7cb6e9 Update PKCS#11 references in template wpa_supplicant.conf
c3d7fb7 OpenSSL: Initialise PKCS#11 engine even if found with ENGINE_by_id()
fdc1188 nl80211: Fix use-after-free in qca_nl80211_get_features()
8359472 hostapd Make GAS Address3 field selection behavior configurable
6996ff7 hostapd: Fix Public Action frame TX status processing for wildcard BSSID
78a3632 hostapd: Fix Public Action frame addressing (BSSID field)
c86bef2 wpa_supplicant: Make GAS Address3 field selection behavior configurable
a5a187b nl80211: Add TEST_FAIL() to command generation and set_mode
ee854ff mesh: Remove extra newline from the end of an error message
331f077 mesh: Allow 160 MHz channel to be configured
92a515b nl80211: Update drv->assoc_freq on mesh join
d2cc8bb mesh: Remove unreachable code
cc9a257 nl80211: Use extended capabilities per interface type
c6edea0 Sync with mac80211-next.git include/uapi/linux/nl80211.h
9a5160f Report connection timeouts in CTRL-EVENT-ASSOC-REJECT
dad0129 mesh: Support simple SAE group negotiation case
b4c738e mesh: Fix error path handling for RSN (MGTK init)
f4b4ddf D-Bus: Remove unused wpas_dbus_signal_p2p_group_started() parameter
4fe50bb D-Bus: Indicate whether created group is persistent or not
62fc8e6 mesh: Fix MESH_INTERFACE_ADD error path cleanup
9c10be3 mesh: Fix error path handling in init OOM cases
7012e25 Remove dead code from wpas_sched_scan_plans_set()
8e909fa Improve reattach scan OOM failure handling
f37d8a4 Indicate scan failure event on parameter cloning failure
9356823 wpaspy: Fix potentially referencing non existing attribute

Change-Id: I656be560523c206195a5bf8649e73d8aa70bd8f9
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/main.c b/hostapd/main.c
index 1d9e63e..2c8dbd3 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -217,11 +217,20 @@
 		iface->drv_flags = capa.flags;
 		iface->smps_modes = capa.smps_modes;
 		iface->probe_resp_offloads = capa.probe_resp_offloads;
+		/*
+		 * Use default extended capa values from per-radio information
+		 */
 		iface->extended_capa = capa.extended_capa;
 		iface->extended_capa_mask = capa.extended_capa_mask;
 		iface->extended_capa_len = capa.extended_capa_len;
 		iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
 
+		/*
+		 * Override extended capa with per-interface type (AP), if
+		 * available from the driver.
+		 */
+		hostapd_get_ext_capa(iface);
+
 		triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
 		if (triggs && hapd->driver->set_wowlan) {
 			if (hapd->driver->set_wowlan(hapd->drv_priv, triggs))
@@ -242,7 +251,7 @@
  * interfaces. No actiual driver operations are started.
  */
 static struct hostapd_iface *
-hostapd_interface_init(struct hapd_interfaces *interfaces,
+hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name,
 		       const char *config_fname, int debug)
 {
 	struct hostapd_iface *iface;
@@ -252,6 +261,12 @@
 	iface = hostapd_init(interfaces, config_fname);
 	if (!iface)
 		return NULL;
+
+	if (if_name) {
+		os_strlcpy(iface->conf->bss[0]->iface, if_name,
+			   sizeof(iface->conf->bss[0]->iface));
+	}
+
 	iface->interfaces = interfaces;
 
 	for (k = 0; k < debug; k++) {
@@ -261,7 +276,8 @@
 
 	if (iface->conf->bss[0]->iface[0] == '\0' &&
 	    !hostapd_drv_none(iface->bss[0])) {
-		wpa_printf(MSG_ERROR, "Interface name not specified in %s",
+		wpa_printf(MSG_ERROR,
+			   "Interface name not specified in %s, nor by '-i' parameter",
 			   config_fname);
 		hostapd_interface_deinit_free(iface);
 		return NULL;
@@ -330,6 +346,7 @@
 		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
 		return -1;
 	}
+	interfaces->eloop_initialized = 1;
 
 	random_init(entropy_file);
 
@@ -357,7 +374,7 @@
 }
 
 
-static void hostapd_global_deinit(const char *pid_file)
+static void hostapd_global_deinit(const char *pid_file, int eloop_initialized)
 {
 	int i;
 
@@ -375,7 +392,8 @@
 
 	random_deinit();
 
-	eloop_destroy();
+	if (eloop_initialized)
+		eloop_destroy();
 
 #ifndef CONFIG_NATIVE_WINDOWS
 	closelog();
@@ -445,7 +463,8 @@
 		"\n"
 		"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
 		"\\\n"
-		"         [-g <global ctrl_iface>] [-G <group>] \\\n"
+		"         [-g <global ctrl_iface>] [-G <group>]\\\n"
+		"         [-i <comma-separated list of interface names>]\\\n"
 		"         <configuration file(s)>\n"
 		"\n"
 		"options:\n"
@@ -464,6 +483,7 @@
 		"   -T = record to Linux tracing in addition to logging\n"
 		"        (records all messages regardless of debug verbosity)\n"
 #endif /* CONFIG_DEBUG_LINUX_TRACING */
+		"   -i   list of interface names to use\n"
 		"   -S   start all the interfaces synchronously\n"
 		"   -t   include timestamps in some debug messages\n"
 		"   -v   show hostapd version\n");
@@ -527,6 +547,43 @@
 }
 
 
+static int hostapd_get_interface_names(char ***if_names,
+				       size_t *if_names_size,
+				       char *optarg)
+{
+	char *if_name, *tmp, **nnames;
+	size_t i;
+
+	if (!optarg)
+		return -1;
+	if_name = strtok_r(optarg, ",", &tmp);
+
+	while (if_name) {
+		nnames = os_realloc_array(*if_names, 1 + *if_names_size,
+					  sizeof(char *));
+		if (!nnames)
+			goto fail;
+		*if_names = nnames;
+
+		(*if_names)[*if_names_size] = os_strdup(if_name);
+		if (!(*if_names)[*if_names_size])
+			goto fail;
+		(*if_names_size)++;
+		if_name = strtok_r(NULL, ",", &tmp);
+	}
+
+	return 0;
+
+fail:
+	for (i = 0; i < *if_names_size; i++)
+		os_free((*if_names)[i]);
+	os_free(*if_names);
+	*if_names = NULL;
+	*if_names_size = 0;
+	return -1;
+}
+
+
 #ifdef CONFIG_WPS
 static int gen_uuid(const char *txt_addr)
 {
@@ -585,6 +642,8 @@
 	int enable_trace_dbg = 0;
 #endif /* CONFIG_DEBUG_LINUX_TRACING */
 	int start_ifaces_in_sync = 0;
+	char **if_names = NULL;
+	size_t if_names_size = 0;
 
 	if (os_program_init())
 		return -1;
@@ -602,7 +661,7 @@
 	dl_list_init(&interfaces.global_ctrl_dst);
 
 	for (;;) {
-		c = getopt(argc, argv, "b:Bde:f:hKP:STtu:vg:G:");
+		c = getopt(argc, argv, "b:Bde:f:hi:KP:STtu:vg:G:");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -666,6 +725,11 @@
 		case 'u':
 			return gen_uuid(optarg);
 #endif /* CONFIG_WPS */
+		case 'i':
+			if (hostapd_get_interface_names(&if_names,
+							&if_names_size, optarg))
+				goto out;
+			break;
 		default:
 			usage();
 			break;
@@ -723,7 +787,13 @@
 
 	/* Allocate and parse configuration for full interface files */
 	for (i = 0; i < interfaces.count; i++) {
+		char *if_name = NULL;
+
+		if (i < if_names_size)
+			if_name = if_names[i];
+
 		interfaces.iface[i] = hostapd_interface_init(&interfaces,
+							     if_name,
 							     argv[optind + i],
 							     debug);
 		if (!interfaces.iface[i]) {
@@ -807,8 +877,9 @@
 	}
 	os_free(interfaces.iface);
 
-	eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
-	hostapd_global_deinit(pid_file);
+	if (interfaces.eloop_initialized)
+		eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
+	hostapd_global_deinit(pid_file, interfaces.eloop_initialized);
 	os_free(pid_file);
 
 	if (log_file)
@@ -817,6 +888,10 @@
 
 	os_free(bss_config);
 
+	for (i = 0; i < if_names_size; i++)
+		os_free(if_names[i]);
+	os_free(if_names);
+
 	fst_global_deinit();
 
 	os_program_deinit();