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 <c_manoha@qca.qualcomm.com>
This commit is contained in:
Sujith Manoharan 2013-07-20 17:41:22 +03:00 committed by Jouni Malinen
parent c8ebeda406
commit 69dd2967db
6 changed files with 55 additions and 12 deletions

View file

@ -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 hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
int val) const u8 *addr, int aid, int val)
{ {
const char *bridge = NULL; const char *bridge = NULL;
if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
return 0; return -1;
if (hapd->conf->wds_bridge[0]) if (hapd->conf->wds_bridge[0])
bridge = hapd->conf->wds_bridge; bridge = hapd->conf->wds_bridge;
else if (hapd->conf->bridge[0]) else if (hapd->conf->bridge[0])
bridge = hapd->conf->bridge; bridge = hapd->conf->bridge;
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val, return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
bridge); bridge, ifname_wds);
} }

View file

@ -31,8 +31,8 @@ int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
int enabled); int enabled);
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname); 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_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 hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
int val); const u8 *addr, int aid, int val);
int hostapd_sta_add(struct hostapd_data *hapd, int hostapd_sta_add(struct hostapd_data *hapd,
const u8 *addr, u16 aid, u16 capability, const u8 *addr, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len, const u8 *supp_rates, size_t supp_rates_len,

View file

@ -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, static void handle_assoc_cb(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, const struct ieee80211_mgmt *mgmt,
size_t len, int reassoc, int ok) size_t len, int reassoc, int ok)
@ -1920,8 +1944,15 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
goto fail; goto fail;
} }
if (sta->flags & WLAN_STA_WDS) if (sta->flags & WLAN_STA_WDS) {
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1); 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) { if (sta->eapol_sm == NULL) {
/* /*
@ -2162,11 +2193,18 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
return; return;
if (wds && !(sta->flags & WLAN_STA_WDS)) { if (wds && !(sta->flags & WLAN_STA_WDS)) {
int ret;
char ifname_wds[IFNAMSIZ + 1];
wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for " wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
"STA " MACSTR " (aid %u)", "STA " MACSTR " (aid %u)",
MAC2STR(sta->addr), sta->aid); MAC2STR(sta->addr), sta->aid);
sta->flags |= WLAN_STA_WDS; 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; return;
} }

View file

@ -129,7 +129,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
ap_sta_set_authorized(hapd, sta, 0); ap_sta_set_authorized(hapd, sta, 0);
if (sta->flags & WLAN_STA_WDS) 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)) if (!(sta->flags & WLAN_STA_PREAUTH))
hostapd_drv_sta_remove(hapd, sta->addr); hostapd_drv_sta_remove(hapd, sta->addr);

View file

@ -2050,10 +2050,12 @@ struct wpa_driver_ops {
* @val: 1 = bind to 4-address WDS; 0 = unbind * @val: 1 = bind to 4-address WDS; 0 = unbind
* @bridge_ifname: Bridge interface to use for the WDS station or %NULL * @bridge_ifname: Bridge interface to use for the WDS station or %NULL
* to indicate that bridge is not to be used * 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 * Returns: 0 on success, -1 on failure
*/ */
int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val, 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 * send_action - Transmit an Action frame

View file

@ -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, 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 i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv; struct wpa_driver_nl80211_data *drv = bss->drv;
char name[IFNAMSIZ + 1]; char name[IFNAMSIZ + 1];
os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid); 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 wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
" aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name); " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
if (val) { if (val) {