WDS: Fix WEP usage with nl80211 wds_sta=1
authorSujith Manoharan <c_manoha@qca.qualcomm.com>
Sat, 20 Jul 2013 14:41:22 +0000 (17:41 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 20 Jul 2013 14:41:22 +0000 (17:41 +0300)
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>

src/ap/ap_drv_ops.c
src/ap/ap_drv_ops.h
src/ap/ieee802_11.c
src/ap/sta_info.c
src/drivers/driver.h
src/drivers/driver_nl80211.c

index 8205d13..3072562 100644 (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 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);
 }
 
 
index 70fab55..cfc30ce 100644 (file)
@@ -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,
index 5503af1..35282af 100644 (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,
                            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;
        }
index 833f1b2..21235f2 100644 (file)
@@ -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);
index 4b7bf80..980f913 100644 (file)
@@ -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
index 4c0c24d..4b15ff6 100644 (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,
-                            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) {