hostapd: Fix WDS/WEP usage
authorFelix Fietkau <nbd@openwrt.org>
Tue, 6 Aug 2013 17:59:12 +0000 (17:59 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 6 Aug 2013 17:59:12 +0000 (17:59 +0000)
WEP in WDS is currently broken in hostapd. Add a patch
to fix the issue.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
SVN-Revision: 37733

package/network/services/hostapd/patches/710-wds-wep-fix.patch [new file with mode: 0644]

diff --git a/package/network/services/hostapd/patches/710-wds-wep-fix.patch b/package/network/services/hostapd/patches/710-wds-wep-fix.patch
new file mode 100644 (file)
index 0000000..1411d1f
--- /dev/null
@@ -0,0 +1,156 @@
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -296,19 +296,19 @@ int hostapd_vlan_if_remove(struct hostap
+ }
+-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);
+ }
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -31,8 +31,8 @@ int hostapd_set_drv_ieee8021x(struct hos
+                             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,
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -1846,6 +1846,29 @@ static void handle_auth_cb(struct hostap
+       }
+ }
++static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
++                                     struct sta_info *sta,
++                                     char *ifname_wds)
++{
++      int i, idx;
++      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,
+@@ -1949,8 +1972,15 @@ static void handle_assoc_cb(struct hosta
+               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) {
+               /*
+@@ -2191,11 +2221,18 @@ void ieee802_11_rx_from_unknown(struct h
+                       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;
+       }
+--- a/src/ap/sta_info.c
++++ b/src/ap/sta_info.c
+@@ -129,7 +129,7 @@ void ap_free_sta(struct hostapd_data *ha
+       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);
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -2057,10 +2057,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.
+        * 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
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -8744,13 +8744,16 @@ static int have_ifidx(struct wpa_driver_
+ 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) {