From 69dd2967db680a2dafc6f86feedb4730dc93a015 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sat, 20 Jul 2013 17:41:22 +0300 Subject: [PATCH] WDS: Fix WEP usage with nl80211 wds_sta=1 The static WEP keys have to be configured for the new VLAN interface that is created for a 4addr WDS peer, not doing so breaks WEP functionality in nl80211/4addr based WDS links. Signed-hostap: Sujith Manoharan --- src/ap/ap_drv_ops.c | 8 +++---- src/ap/ap_drv_ops.h | 4 ++-- src/ap/ieee802_11.c | 44 +++++++++++++++++++++++++++++++++--- src/ap/sta_info.c | 2 +- src/drivers/driver.h | 4 +++- src/drivers/driver_nl80211.c | 5 +++- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 8205d132a..3072562e3 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -296,19 +296,19 @@ int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname) } -int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid, - int val) +int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds, + const u8 *addr, int aid, int val) { const char *bridge = NULL; if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) - return 0; + return -1; if (hapd->conf->wds_bridge[0]) bridge = hapd->conf->wds_bridge; else if (hapd->conf->bridge[0]) bridge = hapd->conf->bridge; return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val, - bridge); + bridge, ifname_wds); } diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 70fab5537..cfc30ce44 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -31,8 +31,8 @@ int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, int enabled); int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname); int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname); -int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid, - int val); +int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds, + const u8 *addr, int aid, int val); int hostapd_sta_add(struct hostapd_data *hapd, const u8 *addr, u16 aid, u16 capability, const u8 *supp_rates, size_t supp_rates_len, diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 5503af157..35282af0e 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1818,6 +1818,30 @@ static void handle_auth_cb(struct hostapd_data *hapd, } +static void hostapd_set_wds_encryption(struct hostapd_data *hapd, + struct sta_info *sta, + char *ifname_wds) +{ + int i; + struct hostapd_ssid *ssid = sta->ssid; + + if (hapd->conf->ieee802_1x || hapd->conf->wpa) + return; + + for (i = 0; i < 4; i++) { + if (ssid->wep.key[i] && + hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i, + i == ssid->wep.idx, NULL, 0, + ssid->wep.key[i], ssid->wep.len[i])) { + wpa_printf(MSG_WARNING, + "Could not set WEP keys for WDS interface; %s", + ifname_wds); + break; + } + } +} + + static void handle_assoc_cb(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len, int reassoc, int ok) @@ -1920,8 +1944,15 @@ static void handle_assoc_cb(struct hostapd_data *hapd, goto fail; } - if (sta->flags & WLAN_STA_WDS) - hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1); + if (sta->flags & WLAN_STA_WDS) { + int ret; + char ifname_wds[IFNAMSIZ + 1]; + + ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr, + sta->aid, 1); + if (!ret) + hostapd_set_wds_encryption(hapd, sta, ifname_wds); + } if (sta->eapol_sm == NULL) { /* @@ -2162,11 +2193,18 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, return; if (wds && !(sta->flags & WLAN_STA_WDS)) { + int ret; + char ifname_wds[IFNAMSIZ + 1]; + wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for " "STA " MACSTR " (aid %u)", MAC2STR(sta->addr), sta->aid); sta->flags |= WLAN_STA_WDS; - hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1); + ret = hostapd_set_wds_sta(hapd, ifname_wds, + sta->addr, sta->aid, 1); + if (!ret) + hostapd_set_wds_encryption(hapd, sta, + ifname_wds); } return; } diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 833f1b23a..21235f259 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -129,7 +129,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) ap_sta_set_authorized(hapd, sta, 0); if (sta->flags & WLAN_STA_WDS) - hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0); + hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0); if (!(sta->flags & WLAN_STA_PREAUTH)) hostapd_drv_sta_remove(hapd, sta->addr); diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 4b7bf8035..980f913ed 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2050,10 +2050,12 @@ struct wpa_driver_ops { * @val: 1 = bind to 4-address WDS; 0 = unbind * @bridge_ifname: Bridge interface to use for the WDS station or %NULL * to indicate that bridge is not to be used + * @ifname_wds: Buffer to return the interface name for the new WDS + * station or %NULL to indicate name is not returned. * Returns: 0 on success, -1 on failure */ int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val, - const char *bridge_ifname); + const char *bridge_ifname, char *ifname_wds); /** * send_action - Transmit an Action frame diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 4c0c24d0f..4b15ff60a 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -8672,13 +8672,16 @@ static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val, - const char *bridge_ifname) + const char *bridge_ifname, char *ifname_wds) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; char name[IFNAMSIZ + 1]; os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid); + if (ifname_wds) + os_strlcpy(ifname_wds, name, IFNAMSIZ + 1); + wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name); if (val) {