[PATCH v2 5/6] nl80211: Make processing rtm link event per bss

Alexander Savchenko oleksandr.savchenko at celeno.com
Tue Sep 6 09:14:09 PDT 2022


In virtual AP mode, driver nl80211 doesn't handle
RTM link event for non-first bss.
It leads to the situation when non-first bss does not become
into DOWN/UP/LOWER_UP state when netlink reports it
and iface leaves in NO-CARRIER state.
This commit also fixes ifindex updating for non-first bss when it
changed, for example, after device_reprobe() at the kernel.

Signed-off-by: Alexander Savchenko <oleksandr.savchenko at celeno.com>
---
 src/drivers/driver_nl80211.c | 203 +++++++++++++++++++----------------
 src/drivers/driver_nl80211.h |  13 +--
 2 files changed, 115 insertions(+), 101 deletions(-)

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 69d5f3d2f..427c5bd49 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -162,8 +162,8 @@ static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
 					    struct hostapd_freq_params *freq);
 
 static int
-wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
-				   const u8 *set_addr, int first,
+wpa_driver_nl80211_finish_drv_init(struct i802_bss *bss,
+				   const u8 *set_addr,
 				   const char *driver_params);
 static int nl80211_send_frame_cmd(struct i802_bss *bss,
 				  unsigned int freq, unsigned int wait,
@@ -1020,22 +1020,22 @@ static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
 
 
 static void wpa_driver_nl80211_event_newlink(
-	struct nl80211_global *global, struct wpa_driver_nl80211_data *drv,
+	struct nl80211_global *global, struct i802_bss *bss,
 	int ifindex, const char *ifname)
 {
 	union wpa_event_data event;
 
-	if (drv && os_strcmp(drv->first_bss->ifname, ifname) == 0) {
-		if (if_nametoindex(drv->first_bss->ifname) == 0) {
+	if (bss && os_strcmp(bss->ifname, ifname) == 0) {
+		if (if_nametoindex(bss->ifname) == 0) {
 			wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
-				   drv->first_bss->ifname);
+				   bss->ifname);
 			return;
 		}
-		if (!drv->if_removed)
+		if (!bss->if_removed)
 			return;
 		wpa_printf(MSG_DEBUG, "nl80211: Mark if_removed=0 for %s based on RTM_NEWLINK event",
-			   drv->first_bss->ifname);
-		drv->if_removed = 0;
+			   bss->ifname);
+		bss->if_removed = 0;
 	}
 
 	os_memset(&event, 0, sizeof(event));
@@ -1043,8 +1043,8 @@ static void wpa_driver_nl80211_event_newlink(
 	os_strlcpy(event.interface_status.ifname, ifname,
 		   sizeof(event.interface_status.ifname));
 	event.interface_status.ievent = EVENT_INTERFACE_ADDED;
-	if (drv)
-		wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+	if (bss)
+		wpa_supplicant_event(bss->ctx, EVENT_INTERFACE_STATUS, &event);
 	else
 		wpa_supplicant_event_global(global->ctx, EVENT_INTERFACE_STATUS,
 					    &event);
@@ -1052,20 +1052,20 @@ static void wpa_driver_nl80211_event_newlink(
 
 
 static void wpa_driver_nl80211_event_dellink(
-	struct nl80211_global *global, struct wpa_driver_nl80211_data *drv,
+	struct nl80211_global *global, struct i802_bss *bss,
 	int ifindex, const char *ifname)
 {
 	union wpa_event_data event;
 
-	if (drv && os_strcmp(drv->first_bss->ifname, ifname) == 0) {
-		if (drv->if_removed) {
+	if (bss && os_strcmp(bss->ifname, ifname) == 0) {
+		if (bss->if_removed) {
 			wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
 				   ifname);
 			return;
 		}
 		wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed - mark if_removed=1",
 			   ifname);
-		drv->if_removed = 1;
+		bss->if_removed = 1;
 	} else {
 		wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed",
 			   ifname);
@@ -1076,15 +1076,15 @@ static void wpa_driver_nl80211_event_dellink(
 	os_strlcpy(event.interface_status.ifname, ifname,
 		   sizeof(event.interface_status.ifname));
 	event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
-	if (drv)
-		wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+	if (bss)
+		wpa_supplicant_event(bss->ctx, EVENT_INTERFACE_STATUS, &event);
 	else
 		wpa_supplicant_event_global(global->ctx, EVENT_INTERFACE_STATUS,
 					    &event);
 }
 
 
-static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
+static int wpa_driver_nl80211_own_ifname(const char *ifname,
 					 u8 *buf, size_t len)
 {
 	int attrlen, rta_len;
@@ -1096,8 +1096,7 @@ static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
 	while (RTA_OK(attr, attrlen)) {
 		if (attr->rta_type == IFLA_IFNAME) {
-			if (os_strcmp(((char *) attr) + rta_len,
-				      drv->first_bss->ifname) == 0)
+			if (os_strcmp(((char *) attr) + rta_len, ifname) == 0)
 				return 1;
 			else
 				break;
@@ -1109,18 +1108,22 @@ static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
 }
 
 
-static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
+static int wpa_driver_nl80211_own_ifindex(struct i802_bss *bss,
 					  int ifindex, u8 *buf, size_t len)
 {
-	if (drv->ifindex == ifindex)
+	if (bss->ifindex == ifindex)
 		return 1;
 
-	if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
-		nl80211_check_global(drv->global);
+	if (bss->if_removed && wpa_driver_nl80211_own_ifname(bss->ifname, buf, len)) {
+		struct wpa_driver_nl80211_data *drv = bss->drv;
+
+		if (drv->first_bss == bss)
+			nl80211_check_global(drv->global);
+
 		wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
 			   "interface");
-		del_ifidx(drv, drv->ifindex, IFIDX_ANY);
-		if (wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL) < 0)
+		del_ifidx(drv, bss->ifindex, IFIDX_ANY);
+		if (wpa_driver_nl80211_finish_drv_init(bss, NULL, NULL) < 0)
 			return -1;
 		return 1;
 	}
@@ -1129,8 +1132,8 @@ static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
 }
 
 
-static struct wpa_driver_nl80211_data *
-nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len,
+static struct i802_bss *
+nl80211_find_bss(struct nl80211_global *global, int idx, u8 *buf, size_t len,
 		 int *init_failed)
 {
 	struct wpa_driver_nl80211_data *drv;
@@ -1140,16 +1143,20 @@ nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len,
 		*init_failed = 0;
 	dl_list_for_each(drv, &global->interfaces,
 			 struct wpa_driver_nl80211_data, list) {
-		res = wpa_driver_nl80211_own_ifindex(drv, idx, buf, len);
-		if (res < 0) {
-			wpa_printf(MSG_DEBUG,
-				   "nl80211: Found matching own interface, but failed to complete reinitialization");
-			if (init_failed)
-				*init_failed = 1;
-			return drv;
+		struct i802_bss *bss;
+
+		for (bss = drv->first_bss; bss; bss = bss->next) {
+			res = wpa_driver_nl80211_own_ifindex(bss, idx, buf, len);
+			if (res < 0) {
+				wpa_printf(MSG_DEBUG,
+					   "nl80211: Found matching own interface, but failed to complete reinitialization");
+				if (init_failed)
+					*init_failed = 1;
+				return bss;
+			}
+			if (res > 0)
+				return bss;
 		}
-		if (res > 0 || have_ifidx(drv, idx, IFIDX_ANY))
-			return drv;
 	}
 	return NULL;
 }
@@ -1187,7 +1194,8 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 						 u8 *buf, size_t len)
 {
 	struct nl80211_global *global = ctx;
-	struct wpa_driver_nl80211_data *drv;
+	struct wpa_driver_nl80211_data *drv = NULL;
+	struct i802_bss *bss = NULL;
 	int attrlen;
 	struct rtattr *attr;
 	u32 brid = 0;
@@ -1239,32 +1247,34 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 		   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
 		   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
 
-	drv = nl80211_find_drv(global, ifi->ifi_index, buf, len, &init_failed);
-	if (!drv)
+	bss = nl80211_find_bss(global, ifi->ifi_index, buf, len, &init_failed);
+	if (!bss)
 		goto event_newlink;
 	if (init_failed)
 		return; /* do not update interface state */
 
-	if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
+	drv = bss->drv;
+
+	if (!bss->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
 		namebuf[0] = '\0';
 		if (if_indextoname(ifi->ifi_index, namebuf) &&
 		    linux_iface_up(drv->global->ioctl_sock, namebuf) > 0) {
 			wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
 				   "event since interface %s is up", namebuf);
-			drv->ignore_if_down_event = 0;
+			bss->ignore_if_down_event = 0;
 			/* Re-read MAC address as it may have changed */
 			nl80211_refresh_mac(drv, ifi->ifi_index, 1);
 			return;
 		}
 		wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
 			   namebuf, ifname);
-		if (drv->ignore_if_down_event) {
+		if (bss->ignore_if_down_event) {
 			wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
 				   "event generated by mode change");
-			drv->ignore_if_down_event = 0;
+			bss->ignore_if_down_event = 0;
 		} else {
-			drv->if_disabled = 1;
-			wpa_supplicant_event(drv->ctx,
+			bss->if_disabled = 1;
+			wpa_supplicant_event(bss->ctx,
 					     EVENT_INTERFACE_DISABLED, NULL);
 
 			/*
@@ -1272,14 +1282,16 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 			 * part of the EVENT_INTERFACE_DISABLED handling for
 			 * dynamic interfaces
 			 */
-			drv = nl80211_find_drv(global, ifi->ifi_index,
-					       buf, len, NULL);
-			if (!drv)
+			drv = NULL;
+			bss = nl80211_find_bss(global, ifi->ifi_index, buf, len, &init_failed);
+			if (!bss)
 				return;
+
+			drv = bss->drv;
 		}
 	}
 
-	if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
+	if (bss->if_disabled && (ifi->ifi_flags & IFF_UP)) {
 		namebuf[0] = '\0';
 		if (if_indextoname(ifi->ifi_index, namebuf) &&
 		    linux_iface_up(drv->global->ioctl_sock, namebuf) == 0) {
@@ -1291,20 +1303,20 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 		wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)",
 				namebuf, ifname);
 
-		if (if_nametoindex(drv->first_bss->ifname) == 0) {
+		if (if_nametoindex(bss->ifname) == 0) {
 			wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
 				   "event since interface %s does not exist",
-				   drv->first_bss->ifname);
-		} else if (drv->if_removed) {
+				   bss->ifname);
+		} else if (bss->if_removed) {
 			wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
 				   "event since interface %s is marked "
-				   "removed", drv->first_bss->ifname);
+				   "removed", bss->ifname);
 		} else {
 			/* Re-read MAC address as it may have changed */
 			nl80211_refresh_mac(drv, ifi->ifi_index, 0);
 
-			drv->if_disabled = 0;
-			wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
+			bss->if_disabled = 0;
+			wpa_supplicant_event(bss->ctx, EVENT_INTERFACE_ENABLED,
 					     NULL);
 		}
 	}
@@ -1315,22 +1327,20 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 	 * fails. This will hit us when wpa_supplicant does not need to do
 	 * IEEE 802.1X authentication
 	 */
-	if (drv->operstate == 1 &&
+	if (bss->operstate == 1 &&
 	    (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
 	    !(ifi->ifi_flags & IFF_RUNNING)) {
 		wpa_printf(MSG_DEBUG, "nl80211: Set IF_OPER_UP again based on ifi_flags and expected operstate");
-		netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
+		netlink_send_oper_ifla(drv->global->netlink, bss->ifindex,
 				       -1, IF_OPER_UP);
 	}
 
 event_newlink:
 	if (ifname[0])
-		wpa_driver_nl80211_event_newlink(global, drv, ifi->ifi_index,
+		wpa_driver_nl80211_event_newlink(global, bss, ifi->ifi_index,
 						 ifname);
 
-	if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
-		struct i802_bss *bss;
-
+	if (ifi->ifi_family == AF_BRIDGE && brid && drv && bss) {
 		/* device has been added to bridge */
 		if (!if_indextoname(brid, namebuf)) {
 			wpa_printf(MSG_DEBUG,
@@ -1342,12 +1352,8 @@ event_newlink:
 			   brid, namebuf);
 		add_ifidx(drv, brid, ifi->ifi_index);
 
-		for (bss = drv->first_bss; bss; bss = bss->next) {
-			if (os_strcmp(ifname, bss->ifname) == 0) {
-				os_strlcpy(bss->brname, namebuf, IFNAMSIZ);
-				break;
-			}
-		}
+		if (os_strcmp(ifname, bss->ifname) == 0)
+			os_strlcpy(bss->brname, namebuf, IFNAMSIZ);
 	}
 }
 
@@ -1357,7 +1363,8 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
 						 u8 *buf, size_t len)
 {
 	struct nl80211_global *global = ctx;
-	struct wpa_driver_nl80211_data *drv;
+	struct wpa_driver_nl80211_data *drv = NULL;
+	struct i802_bss *bss = NULL;
 	int attrlen;
 	struct rtattr *attr;
 	u32 brid = 0;
@@ -1404,7 +1411,9 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
 		   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
 		   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
 
-	drv = nl80211_find_drv(global, ifi->ifi_index, buf, len, NULL);
+	bss = nl80211_find_bss(global, ifi->ifi_index, buf, len, NULL);
+	if (bss)
+		drv = bss->drv;
 
 	if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
 		/* device has been removed from bridge */
@@ -1423,7 +1432,7 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
 	}
 
 	if (ifi->ifi_family != AF_BRIDGE || !brid)
-		wpa_driver_nl80211_event_dellink(global, drv, ifi->ifi_index,
+		wpa_driver_nl80211_event_dellink(global, bss, ifi->ifi_index,
 						 ifname);
 }
 
@@ -2224,7 +2233,7 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
 	if (nl80211_init_bss(bss))
 		goto failed;
 
-	if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params))
+	if (wpa_driver_nl80211_finish_drv_init(bss, set_addr, driver_params))
 		goto failed;
 
 	if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS) {
@@ -2823,22 +2832,25 @@ static void qca_vendor_test(struct wpa_driver_nl80211_data *drv)
 
 
 static int
-wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
-				   const u8 *set_addr, int first,
+wpa_driver_nl80211_finish_drv_init(struct i802_bss *bss,
+				   const u8 *set_addr,
 				   const char *driver_params)
 {
-	struct i802_bss *bss = drv->first_bss;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int send_rfkill_event = 0;
 	enum nl80211_iftype nlmode;
+	int first = drv->first_bss == bss;
 
-	drv->ifindex = if_nametoindex(bss->ifname);
-	bss->ifindex = drv->ifindex;
+	bss->ifindex = if_nametoindex(bss->ifname);
+	if (first)
+		drv->ifindex = bss->ifindex;
 	bss->wdev_id = drv->global->if_add_wdevid;
 	bss->wdev_id_set = drv->global->if_add_wdevid_set;
 
 	bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex;
 	bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;
-	drv->global->if_add_wdevid_set = 0;
+	if (first)
+		drv->global->if_add_wdevid_set = 0;
 
 	if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
 		bss->static_ap = 1;
@@ -2846,9 +2858,9 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
 	if (first &&
 	    nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
 	    linux_iface_up(drv->global->ioctl_sock, bss->ifname) > 0)
-		drv->start_iface_up = 1;
+		bss->start_iface_up = 1;
 
-	if (wpa_driver_nl80211_capa(drv))
+	if (first & wpa_driver_nl80211_capa(drv))
 		return -1;
 
 	if (driver_params && nl80211_set_param(bss, driver_params) < 0)
@@ -2874,7 +2886,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
 	else
 		nlmode = NL80211_IFTYPE_STATION;
 
-	if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
+	if (first && wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
 		wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode");
 		return -1;
 	}
@@ -2902,25 +2914,26 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
 		wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
 			   "interface '%s' due to rfkill", bss->ifname);
 		if (nlmode != NL80211_IFTYPE_P2P_DEVICE)
-			drv->if_disabled = 1;
+			bss->if_disabled = 1;
 
 		send_rfkill_event = 1;
 	}
 
 	if (!drv->hostapd && nlmode != NL80211_IFTYPE_P2P_DEVICE)
-		netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
+		netlink_send_oper_ifla(drv->global->netlink, bss->ifindex,
 				       1, IF_OPER_DORMANT);
 
 	if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
 		if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
 				       bss->addr))
 			return -1;
-		os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);
+		if (first)
+			os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);
 	}
 
 	if (send_rfkill_event) {
 		eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
-				       drv, drv->ctx);
+				       drv, bss->ctx);
 	}
 
 	if (drv->vendor_cmd_test_avail)
@@ -2936,11 +2949,11 @@ static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss)
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
-		   drv->ifindex);
+		   bss->ifindex);
 	bss->beacon_set = 0;
 	bss->freq = 0;
 	nl80211_put_wiphy_data_ap(bss);
-	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON);
+	msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_BEACON);
 	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 }
 
@@ -3007,14 +3020,14 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
 	if (drv->disabled_11b_rates)
 		nl80211_disable_11b_rates(drv, drv->ifindex, 0);
 
-	netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
+	netlink_send_oper_ifla(drv->global->netlink, bss->ifindex, 0,
 			       IF_OPER_UP);
 	eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
 	rfkill_deinit(drv->rfkill);
 
 	eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
 
-	if (!drv->start_iface_up)
+	if (!bss->start_iface_up)
 		(void) i802_set_iface_flags(bss, 0);
 
 	if (drv->addr_changed) {
@@ -6780,7 +6793,7 @@ static int wpa_driver_nl80211_set_mode_impl(
 		wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
 			   "interface is down");
 		drv->nlmode = nlmode;
-		drv->ignore_if_down_event = 1;
+		bss->ignore_if_down_event = 1;
 	}
 
 	/* Bring the interface back up */
@@ -6899,10 +6912,10 @@ static int wpa_driver_nl80211_set_operstate(void *priv, int state)
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Set %s operstate %d->%d (%s)",
-		   bss->ifname, drv->operstate, state,
+		   bss->ifname, bss->operstate, state,
 		   state ? "UP" : "DORMANT");
-	drv->operstate = state;
-	return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
+	bss->operstate = state;
+	return netlink_send_oper_ifla(drv->global->netlink, bss->ifindex, -1,
 				      state ? IF_OPER_UP : IF_OPER_DORMANT);
 }
 
@@ -9758,7 +9771,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
 			  drv->phyname,
 			  MAC2STR(drv->perm_addr),
 			  drv->ifindex,
-			  drv->operstate,
+			  bss->operstate,
 			  scan_state_str(drv->scan_state),
 			  MAC2STR(drv->auth_bssid),
 			  MAC2STR(drv->auth_attempt_bssid),
@@ -9771,7 +9784,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
 			  drv->monitor_refcount,
 			  drv->last_mgmt_freq,
 			  drv->eapol_tx_sock,
-			  drv->ignore_if_down_event ?
+			  bss->ignore_if_down_event ?
 			  "ignore_if_down_event=1\n" : "",
 			  drv->scan_complete_events ?
 			  "scan_complete_events=1\n" : "",
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 9a9faf698..ce0794a3a 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -53,7 +53,10 @@ struct i802_bss {
 	struct wpa_driver_nl80211_data *drv;
 	struct i802_bss *next;
 	int ifindex;
+	int ignore_if_down_event;
 	int br_ifindex;
+	int if_removed;
+	int if_disabled;
 	u64 wdev_id;
 	char ifname[IFNAMSIZ + 1];
 	char brname[IFNAMSIZ];
@@ -73,6 +76,8 @@ struct i802_bss {
 	int bandwidth;
 	int if_dynamic;
 
+	int operstate;
+
 	void *ctx;
 	struct nl_sock *nl_preq, *nl_mgmt, *nl_connect;
 	struct nl_cb *nl_cb;
@@ -80,6 +85,8 @@ struct i802_bss {
 	struct nl80211_wiphy_data *wiphy_data;
 	struct dl_list wiphy_list;
 	u8 rand_addr[ETH_ALEN];
+
+	unsigned int start_iface_up:1;
 };
 
 struct drv_nl80211_if_info {
@@ -97,9 +104,6 @@ struct wpa_driver_nl80211_data {
 	u8 perm_addr[ETH_ALEN];
 	void *ctx;
 	int ifindex;
-	int if_removed;
-	int if_disabled;
-	int ignore_if_down_event;
 	struct rfkill_data *rfkill;
 	struct wpa_driver_capa capa;
 	u8 *extended_capa, *extended_capa_mask;
@@ -114,8 +118,6 @@ struct wpa_driver_nl80211_data {
 	int has_capability;
 	int has_driver_key_mgmt;
 
-	int operstate;
-
 	int scan_complete_events;
 	enum scan_states {
 		NO_SCAN, SCAN_REQUESTED, SCAN_STARTED, SCAN_COMPLETED,
@@ -151,7 +153,6 @@ struct wpa_driver_nl80211_data {
 	unsigned int ignore_next_local_deauth:1;
 	unsigned int hostapd:1;
 	unsigned int start_mode_sta:1;
-	unsigned int start_iface_up:1;
 	unsigned int test_use_roc_tx:1;
 	unsigned int ignore_deauth_event:1;
 	unsigned int vendor_cmd_test_avail:1;
-- 
2.25.0




More information about the Hostap mailing list