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:
parent
c8ebeda406
commit
69dd2967db
6 changed files with 55 additions and 12 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue