From: Michael Braun <michael-dev@xxxxxxxxxxxxx> 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@xxxxxxxxxxxxx> --- 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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap