[PATCH 08/44] nl80211: fix CMD_FRAME used with VLANs

michael-dev at fami-braun.de michael-dev at fami-braun.de
Wed Feb 24 03:53:14 PST 2016


From: Michael Braun <michael-dev at fami-braun.de>

This is required for 802.11r with VLANs used in combination with over_ds,
or the action reply frame won't get out on WiFi.

This is because kernel mac80211 CMD_FRAME uses get_sta instead of
get_sta_bss, so the ifidx given needs to be the of the AP_VLAN iface.

Signed-off-by: Michael Braun <michael-dev at fami-braun.de>
---
 src/ap/ap_config.c           | 27 ++++++++++++++++++++++
 src/ap/ap_config.h           |  4 ++++
 src/ap/ap_drv_ops.c          | 15 +++++++++++--
 src/ap/ap_drv_ops.h          |  3 +++
 src/ap/wpa_auth_glue.c       |  5 ++++-
 src/drivers/driver.h         |  3 ++-
 src/drivers/driver_atheros.c |  3 ++-
 src/drivers/driver_hostap.c  | 10 ++++-----
 src/drivers/driver_nl80211.c | 53 ++++++++++++++++++++++++++------------------
 wpa_supplicant/driver_i.h    |  2 +-
 10 files changed, 93 insertions(+), 32 deletions(-)

diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 477ea5b..ce96ed5 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -18,6 +18,8 @@
 #include "wpa_auth.h"
 #include "sta_info.h"
 #include "ap_config.h"
+#include "hostapd.h"
+#include <net/if.h>
 
 
 static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
@@ -708,6 +710,31 @@ const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
 }
 
 
+int hostapd_get_vlan_id_ifidx(struct hostapd_vlan *vlan, int vlan_id)
+{
+	const char *ifname = hostapd_get_vlan_id_ifname(vlan, vlan_id);
+
+	if (!ifname)
+		return 0;
+	return if_nametoindex(ifname);
+}
+
+
+int hostapd_get_sta_ifidx(struct hostapd_data *hapd, const u8 *addr)
+{
+	struct sta_info *sta;
+
+	if (!hapd)
+		return 0;
+	sta = ap_get_sta(hapd, addr);
+	if (!sta)
+		return 0;
+	if (!sta->vlan_id_bound)
+		return 0;
+	return hostapd_get_vlan_id_ifidx(hapd->conf->vlan, sta->vlan_id_bound);
+}
+
+
 const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
 			   const u8 *addr, const u8 *p2p_dev_addr,
 			   const u8 *prev_psk)
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 9afca48..4b039b4 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -687,6 +687,8 @@ struct hostapd_config {
 #endif /* CONFIG_ACS */
 };
 
+struct hostapd_data;
+
 
 int hostapd_mac_comp(const void *a, const void *b);
 int hostapd_mac_comp_empty(const void *a);
@@ -707,6 +709,8 @@ int hostapd_vlan_valid(struct hostapd_vlan *vlan,
 		       struct vlan_description *vlan_desc);
 const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
 					int vlan_id);
+int hostapd_get_vlan_id_ifidx(struct hostapd_vlan *vlan, int vlan_id);
+int hostapd_get_sta_ifidx(struct hostapd_data *hapd, const u8 *addr);
 struct hostapd_radius_attr *
 hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type);
 int hostapd_config_check(struct hostapd_config *conf, int full_config);
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index b89f60e..a20d2fd 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -623,7 +623,7 @@ int hostapd_drv_send_mlme(struct hostapd_data *hapd,
 	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
 		return 0;
 	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
-				       NULL, 0);
+				       NULL, 0, 0);
 }
 
 
@@ -634,7 +634,18 @@ int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
 	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
 		return 0;
 	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
-				       csa_offs, csa_offs_len);
+				       csa_offs, csa_offs_len, 0);
+}
+
+
+int hostapd_drv_send_mlme_ifidx(struct hostapd_data *hapd,
+				const void *msg, size_t len, int noack,
+				int ifidx)
+{
+	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
+		return 0;
+	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
+				       NULL, 0, ifidx);
 }
 
 
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 757a706..3b3ca90 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -91,6 +91,9 @@ int hostapd_drv_send_mlme(struct hostapd_data *hapd,
 int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
 			      const void *msg, size_t len, int noack,
 			      const u16 *csa_offs, size_t csa_offs_len);
+int hostapd_drv_send_mlme_ifidx(struct hostapd_data *hapd,
+				const void *msg, size_t len, int noack,
+				int ifidx);
 int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
 			   const u8 *addr, int reason);
 int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 8dbc2c4..e7042ef 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -503,6 +503,7 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
 	struct ieee80211_mgmt *m;
 	size_t mlen;
 	struct sta_info *sta;
+	int ifidx;
 
 	sta = ap_get_sta(hapd, dst);
 	if (sta == NULL || sta->wpa_sm == NULL)
@@ -519,7 +520,9 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
 	os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
 	os_memcpy(&m->u, data, data_len);
 
-	res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0);
+	ifidx = hostapd_get_sta_ifidx(hapd, dst);
+
+	res = hostapd_drv_send_mlme_ifidx(hapd, (u8 *) m, mlen, 0, ifidx);
 	os_free(m);
 	return res;
 }
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2315226..6b925d0 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2028,11 +2028,12 @@ struct wpa_driver_ops {
 	 * driver decide
 	 * @csa_offs: Array of CSA offsets or %NULL
 	 * @csa_offs_len: Number of elements in csa_offs
+	 * @ifidx: Interface index to send this out (AP_VLAN)
 	 * Returns: 0 on success, -1 on failure
 	 */
 	int (*send_mlme)(void *priv, const u8 *data, size_t data_len,
 			 int noack, unsigned int freq, const u16 *csa_offs,
-			 size_t csa_offs_len);
+			 size_t csa_offs_len, int ifidx);
 
 	/**
 	 * update_ft_ies - Update FT (IEEE 802.11r) IEs
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index a5a379e..bcf5ef9 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -1849,7 +1849,8 @@ static int atheros_set_ap(void *priv, struct wpa_driver_ap_params *params)
 
 static int atheros_send_mgmt(void *priv, const u8 *frm, size_t data_len,
 			     int noack, unsigned int freq,
-			     const u16 *csa_offs, size_t csa_offs_len)
+			     const u16 *csa_offs, size_t csa_offs_len,
+			     int ifidx)
 {
 	struct atheros_driver_data *drv = priv;
 	u8 buf[1510];
diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c
index 517a3bb..b5026c5 100644
--- a/src/drivers/driver_hostap.c
+++ b/src/drivers/driver_hostap.c
@@ -259,7 +259,7 @@ static int hostap_init_sockets(struct hostap_driver_data *drv, u8 *own_addr)
 
 static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack,
 			    unsigned int freq,
-			    const u16 *csa_offs, size_t csa_offs_len)
+			    const u16 *csa_offs, size_t csa_offs_len, int ifidx)
 {
 	struct hostap_driver_data *drv = priv;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg;
@@ -308,7 +308,7 @@ static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data,
 	pos += 2;
 	memcpy(pos, data, data_len);
 
-	res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0, NULL, 0);
+	res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0, NULL, 0, 0);
 	if (res < 0) {
 		wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - "
 			   "failed: %d (%s)",
@@ -1046,7 +1046,7 @@ static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
 	memcpy(mgmt.bssid, own_addr, ETH_ALEN);
 	mgmt.u.deauth.reason_code = host_to_le16(reason);
 	return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
-				sizeof(mgmt.u.deauth), 0, 0, NULL, 0);
+				sizeof(mgmt.u.deauth), 0, 0, NULL, 0, 0);
 }
 
 
@@ -1084,7 +1084,7 @@ static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
 	memcpy(mgmt.bssid, own_addr, ETH_ALEN);
 	mgmt.u.disassoc.reason_code = host_to_le16(reason);
 	return  hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
-				 sizeof(mgmt.u.disassoc), 0, 0, NULL, 0);
+				 sizeof(mgmt.u.disassoc), 0, 0, NULL, 0, 0);
 }
 
 
@@ -1162,7 +1162,7 @@ static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr,
 	os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
 	os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
 
-	hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0, 0, NULL, 0);
+	hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0, 0, NULL, 0, 0);
 }
 
 
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5fec430..3e6ee3b 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -177,7 +177,8 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
 				  unsigned int freq, unsigned int wait,
 				  const u8 *buf, size_t buf_len, u64 *cookie,
 				  int no_cck, int no_ack, int offchanok,
-				  const u16 *csa_offs, size_t csa_offs_len);
+				  const u16 *csa_offs, size_t csa_offs_len,
+				  int ifidx);
 static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
 					       int report);
 
@@ -445,15 +446,19 @@ void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
 }
 
 
-static int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss)
+static int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss,
+				int ifidx)
 {
+	if (ifidx)
+		return nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifidx);
 	if (bss->wdev_id_set)
 		return nla_put_u64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
 	return nla_put_u32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
 }
 
 
-struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
+struct nl_msg * nl80211_cmd_msg_ifidx(struct i802_bss *bss, int flags,
+				      uint8_t cmd, int ifidx)
 {
 	struct nl_msg *msg;
 
@@ -462,7 +467,7 @@ struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
 		return NULL;
 
 	if (!nl80211_cmd(bss->drv, msg, flags, cmd) ||
-	    nl80211_set_iface_id(msg, bss) < 0) {
+	    nl80211_set_iface_id(msg, bss, ifidx) < 0) {
 		nlmsg_free(msg);
 		return NULL;
 	}
@@ -471,6 +476,11 @@ struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
 }
 
 
+struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
+{
+	return nl80211_cmd_msg_ifidx(bss, flags, cmd, 0);
+}
+
 static struct nl_msg *
 nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
 		    int flags, uint8_t cmd)
@@ -3160,7 +3170,7 @@ static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
 					 unsigned int freq, int no_cck,
 					 int offchanok, unsigned int wait_time,
 					 const u16 *csa_offs,
-					 size_t csa_offs_len)
+					 size_t csa_offs_len, int ifidx)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	u64 cookie;
@@ -3187,7 +3197,7 @@ static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
 	wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
 	res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
 				     &cookie, no_cck, noack, offchanok,
-				     csa_offs, csa_offs_len);
+				     csa_offs, csa_offs_len, ifidx);
 	if (res == 0 && !noack) {
 		const struct ieee80211_mgmt *mgmt;
 		u16 fc;
@@ -3215,7 +3225,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
 					int offchanok,
 					unsigned int wait_time,
 					const u16 *csa_offs,
-					size_t csa_offs_len)
+					size_t csa_offs_len, int ifidx)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct ieee80211_mgmt *mgmt;
@@ -3245,7 +3255,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
 		}
 		return nl80211_send_frame_cmd(bss, freq, 0,
 					      data, data_len, NULL, 1, noack,
-					      1, csa_offs, csa_offs_len);
+					      1, csa_offs, csa_offs_len, ifidx);
 	}
 
 	if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
@@ -3260,7 +3270,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
 					      data, data_len,
 					      &drv->send_action_cookie,
 					      no_cck, noack, offchanok,
-					      csa_offs, csa_offs_len);
+					      csa_offs, csa_offs_len, ifidx);
 	}
 
 	if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
@@ -3281,7 +3291,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
 	return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
 					     noack, freq, no_cck, offchanok,
 					     wait_time, csa_offs,
-					     csa_offs_len);
+					     csa_offs_len, ifidx);
 }
 
 
@@ -4380,7 +4390,7 @@ static int wpa_driver_nl80211_hapd_send_eapol(
 	memcpy(pos, data, data_len);
 
 	res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
-					    0, 0, 0, 0, NULL, 0);
+					    0, 0, 0, 0, NULL, 0, 0);
 	if (res < 0) {
 		wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
 			   "failed: %d (%s)",
@@ -5593,7 +5603,7 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
 	return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
 					    IEEE80211_HDRLEN +
 					    sizeof(mgmt.u.deauth), 0, 0, 0, 0,
-					    0, NULL, 0);
+					    0, NULL, 0, 0);
 }
 
 
@@ -5620,7 +5630,7 @@ static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
 	return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
 					    IEEE80211_HDRLEN +
 					    sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
-					    0, NULL, 0);
+					    0, NULL, 0, 0);
 }
 
 
@@ -6281,7 +6291,7 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
 				  const u8 *buf, size_t buf_len,
 				  u64 *cookie_out, int no_cck, int no_ack,
 				  int offchanok, const u16 *csa_offs,
-				  size_t csa_offs_len)
+				  size_t csa_offs_len, int ifidx)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
@@ -6293,7 +6303,7 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
 		   freq, wait, no_cck, no_ack, offchanok);
 	wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
 
-	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) ||
+	if (!(msg = nl80211_cmd_msg_ifidx(bss, 0, NL80211_CMD_FRAME, ifidx)) ||
 	    (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
 	    (wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) ||
 	    (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
@@ -6376,12 +6386,12 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
 	     !drv->use_monitor))
 		ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
 						   0, freq, no_cck, 1,
-						   wait_time, NULL, 0);
+						   wait_time, NULL, 0, 0);
 	else
 		ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
 					     24 + data_len,
 					     &drv->send_action_cookie,
-					     no_cck, 0, 1, NULL, 0);
+					     no_cck, 0, 1, NULL, 0, 0);
 
 	os_free(buf);
 	return ret;
@@ -6754,7 +6764,7 @@ static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
 {
 	struct i802_bss *bss = priv;
 	return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
-					     0, 0, 0, 0, NULL, 0);
+					     0, 0, 0, 0, NULL, 0, 0);
 }
 
 
@@ -7163,7 +7173,7 @@ static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
 	os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
 
 	if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
-					 0, 0, NULL, 0) < 0)
+					 0, 0, NULL, 0, 0) < 0)
 		wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
 			   "send poll frame");
 }
@@ -7484,12 +7494,13 @@ static int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type,
 static int driver_nl80211_send_mlme(void *priv, const u8 *data,
 				    size_t data_len, int noack,
 				    unsigned int freq,
-				    const u16 *csa_offs, size_t csa_offs_len)
+				    const u16 *csa_offs, size_t csa_offs_len,
+				    int ifidx)
 {
 	struct i802_bss *bss = priv;
 	return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
 					    freq, 0, 0, 0, csa_offs,
-					    csa_offs_len);
+					    csa_offs_len, ifidx);
 }
 
 
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 699fd4f..a7613b9 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -290,7 +290,7 @@ static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s,
 	if (wpa_s->driver->send_mlme)
 		return wpa_s->driver->send_mlme(wpa_s->drv_priv,
 						data, data_len, noack,
-						freq, NULL, 0);
+						freq, NULL, 0, 0);
 	return -1;
 }
 
-- 
1.9.1




More information about the Hostap mailing list