WPS 2.0: Provide (Re)Association Response WPS IE to driver
[libeap.git] / src / drivers / driver_atheros.c
index 0c2f81c..c0dd731 100644 (file)
 #endif
 #endif /* _BYTE_ORDER */
 
-#include <net80211/ieee80211.h>
-#include <net80211/_ieee80211.h>
-#include <net80211/ieee80211_crypto.h>
-
 /*
  * Note, the ATH_WPS_IE setting must match with the driver build.. If the
  * driver does not include this, the IEEE80211_IOCTL_GETWPAIE ioctl will fail.
  */
 #define ATH_WPS_IE
-#include <net80211/ieee80211_ioctl.h>
+
+#include "os/linux/include/ieee80211_external.h"
+
 
 #ifdef CONFIG_WPS
-#ifdef IEEE80211_IOCTL_FILTERFRAME
 #include <netpacket/packet.h>
 
 #ifndef ETH_P_80211_RAW
 #define ETH_P_80211_RAW 0x0019
 #endif
-#endif /* IEEE80211_IOCTL_FILTERFRAME */
 #endif /* CONFIG_WPS */
 
-/*
- * Avoid conflicts with hostapd definitions by undefining couple of defines
- * from madwifi header files.
- */
-#undef WPA_OUI_TYPE
-#undef WME_OUI_TYPE
-
 #include "wireless_copy.h"
 
 #include "driver.h"
@@ -64,6 +53,7 @@
 #include "l2_packet/l2_packet.h"
 #include "common/ieee802_11_defs.h"
 #include "netlink.h"
+#include "linux_ioctl.h"
 
 
 struct madwifi_driver_data {
@@ -84,6 +74,109 @@ struct madwifi_driver_data {
 
 static int madwifi_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
                              int reason_code);
+static int madwifi_set_privacy(void *priv, int enabled);
+
+static const char * athr_get_ioctl_name(int op)
+{
+       switch (op) {
+       case IEEE80211_IOCTL_SETPARAM:
+               return "SETPARAM";
+       case IEEE80211_IOCTL_GETPARAM:
+               return "GETPARAM";
+       case IEEE80211_IOCTL_SETKEY:
+               return "SETKEY";
+       case IEEE80211_IOCTL_SETWMMPARAMS:
+               return "SETWMMPARAMS";
+       case IEEE80211_IOCTL_DELKEY:
+               return "DELKEY";
+       case IEEE80211_IOCTL_GETWMMPARAMS:
+               return "GETWMMPARAMS";
+       case IEEE80211_IOCTL_SETMLME:
+               return "SETMLME";
+       case IEEE80211_IOCTL_GETCHANINFO:
+               return "GETCHANINFO";
+       case IEEE80211_IOCTL_SETOPTIE:
+               return "SETOPTIE";
+       case IEEE80211_IOCTL_GETOPTIE:
+               return "GETOPTIE";
+       case IEEE80211_IOCTL_ADDMAC:
+               return "ADDMAC";
+       case IEEE80211_IOCTL_DELMAC:
+               return "DELMAC";
+       case IEEE80211_IOCTL_GETCHANLIST:
+               return "GETCHANLIST";
+       case IEEE80211_IOCTL_SETCHANLIST:
+               return "SETCHANLIST";
+       case IEEE80211_IOCTL_KICKMAC:
+               return "KICKMAC";
+       case IEEE80211_IOCTL_CHANSWITCH:
+               return "CHANSWITCH";
+       case IEEE80211_IOCTL_GETMODE:
+               return "GETMODE";
+       case IEEE80211_IOCTL_SETMODE:
+               return "SETMODE";
+       case IEEE80211_IOCTL_GET_APPIEBUF:
+               return "GET_APPIEBUF";
+       case IEEE80211_IOCTL_SET_APPIEBUF:
+               return "SET_APPIEBUF";
+       case IEEE80211_IOCTL_SET_ACPARAMS:
+               return "SET_ACPARAMS";
+       case IEEE80211_IOCTL_FILTERFRAME:
+               return "FILTERFRAME";
+       case IEEE80211_IOCTL_SET_RTPARAMS:
+               return "SET_RTPARAMS";
+       case IEEE80211_IOCTL_SENDADDBA:
+               return "SENDADDBA";
+       case IEEE80211_IOCTL_GETADDBASTATUS:
+               return "GETADDBASTATUS";
+       case IEEE80211_IOCTL_SENDDELBA:
+               return "SENDDELBA";
+       case IEEE80211_IOCTL_SET_MEDENYENTRY:
+               return "SET_MEDENYENTRY";
+       case IEEE80211_IOCTL_SET_ADDBARESP:
+               return "SET_ADDBARESP";
+       case IEEE80211_IOCTL_GET_MACADDR:
+               return "GET_MACADDR";
+       case IEEE80211_IOCTL_SET_HBRPARAMS:
+               return "SET_HBRPARAMS";
+       case IEEE80211_IOCTL_SET_RXTIMEOUT:
+               return "SET_RXTIMEOUT";
+       case IEEE80211_IOCTL_STA_STATS:
+               return "STA_STATS";
+       case IEEE80211_IOCTL_GETWPAIE:
+               return "GETWPAIE";
+       default:
+               return "??";
+       }
+}
+
+
+static const char * athr_get_param_name(int op)
+{
+       switch (op) {
+       case IEEE80211_IOC_MCASTCIPHER:
+               return "MCASTCIPHER";
+       case IEEE80211_PARAM_MCASTKEYLEN:
+               return "MCASTKEYLEN";
+       case IEEE80211_PARAM_UCASTCIPHERS:
+               return "UCASTCIPHERS";
+       case IEEE80211_PARAM_KEYMGTALGS:
+               return "KEYMGTALGS";
+       case IEEE80211_PARAM_RSNCAPS:
+               return "RSNCAPS";
+       case IEEE80211_PARAM_WPA:
+               return "WPA";
+       case IEEE80211_PARAM_AUTHMODE:
+               return "AUTHMODE";
+       case IEEE80211_PARAM_PRIVACY:
+               return "PRIVACY";
+       case IEEE80211_PARAM_COUNTERMEASURES:
+               return "COUNTERMEASURES";
+       default:
+               return "??";
+       }
+}
+
 
 static int
 set80211priv(struct madwifi_driver_data *drv, int op, void *data, int len)
@@ -114,40 +207,11 @@ set80211priv(struct madwifi_driver_data *drv, int op, void *data, int len)
        }
 
        if (ioctl(drv->ioctl_sock, op, &iwr) < 0) {
-               int first = IEEE80211_IOCTL_SETPARAM;
-               static const char *opnames[] = {
-                       "ioctl[IEEE80211_IOCTL_SETPARAM]",
-                       "ioctl[IEEE80211_IOCTL_GETPARAM]",
-                       "ioctl[IEEE80211_IOCTL_SETKEY]",
-                       "ioctl[IEEE80211_IOCTL_SETWMMPARAMS]",
-                       "ioctl[IEEE80211_IOCTL_DELKEY]",
-                       "ioctl[IEEE80211_IOCTL_GETWMMPARAMS]",
-                       "ioctl[IEEE80211_IOCTL_SETMLME]",
-                       "ioctl[IEEE80211_IOCTL_GETCHANINFO]",
-                       "ioctl[IEEE80211_IOCTL_SETOPTIE]",
-                       "ioctl[IEEE80211_IOCTL_GETOPTIE]",
-                       "ioctl[IEEE80211_IOCTL_ADDMAC]",
-                       "ioctl[IEEE80211_IOCTL_DELMAC]",
-                       "ioctl[IEEE80211_IOCTL_GETCHANLIST]",
-                       "ioctl[IEEE80211_IOCTL_SETCHANLIST]",
-                       "ioctl[IEEE80211_IOCTL_KICKMAC]",
-                       "ioctl[IEEE80211_IOCTL_CHANSWITCH]",
-                       "ioctl[IEEE80211_IOCTL_GETMODE]",
-                       "ioctl[IEEE80211_IOCTL_SETMODE]",
-                       "ioctl[IEEE80211_IOCTL_GET_APPIEBUF]",
-                       "ioctl[IEEE80211_IOCTL_SET_APPIEBUF]",
-                       NULL,
-                       "ioctl[IEEE80211_IOCTL_FILTERFRAME]",
-               };
-               int idx = op - first;
-               if (first <= op &&
-                   idx < (int) (sizeof(opnames) / sizeof(opnames[0])) &&
-                   opnames[idx])
-                       perror(opnames[idx]);
-               else {
-                       perror("ioctl[unknown???]");
-                       wpa_printf(MSG_DEBUG, "Failed ioctl: 0x%x", op);
-               }
+               wpa_printf(MSG_DEBUG, "atheros: %s: %s: ioctl op=0x%x "
+                          "(%s) len=%d failed: %d (%s)",
+                          __func__, drv->iface, op,
+                          athr_get_ioctl_name(op),
+                          len, errno, strerror(errno));
                return -1;
        }
        return 0;
@@ -165,8 +229,9 @@ set80211param(struct madwifi_driver_data *drv, int op, int arg)
 
        if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
                perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
-               wpa_printf(MSG_DEBUG, "%s: Failed to set parameter (op %d "
-                          "arg %d)", __func__, op, arg);
+               wpa_printf(MSG_DEBUG, "%s: %s: Failed to set parameter (op %d "
+                          "(%s) arg %d)", __func__, drv->iface, op,
+                          athr_get_param_name(op), arg);
                return -1;
        }
        return 0;
@@ -270,39 +335,6 @@ madwifi_configure_wpa(struct madwifi_driver_data *drv,
        return 0;
 }
 
-
-static int
-madwifi_set_iface_flags(void *priv, int dev_up)
-{
-       struct madwifi_driver_data *drv = priv;
-       struct ifreq ifr;
-
-       wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up);
-
-       if (drv->ioctl_sock < 0)
-               return -1;
-
-       memset(&ifr, 0, sizeof(ifr));
-       os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
-
-       if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
-               perror("ioctl[SIOCGIFFLAGS]");
-               return -1;
-       }
-
-       if (dev_up)
-               ifr.ifr_flags |= IFF_UP;
-       else
-               ifr.ifr_flags &= ~IFF_UP;
-
-       if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
-               perror("ioctl[SIOCSIFFLAGS]");
-               return -1;
-       }
-
-       return 0;
-}
-
 static int
 madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params)
 {
@@ -312,8 +344,11 @@ madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params)
 
        if (!params->enabled) {
                /* XXX restore state */
-               return set80211param(priv, IEEE80211_PARAM_AUTHMODE,
-                       IEEE80211_AUTH_AUTO);
+               if (set80211param(priv, IEEE80211_PARAM_AUTHMODE,
+                                 IEEE80211_AUTH_AUTO) < 0)
+                       return -1;
+               /* IEEE80211_AUTH_AUTO ends up enabling Privacy; clear that */
+               return madwifi_set_privacy(drv, 0);
        }
        if (!params->wpa && !params->ieee802_1x) {
                hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
@@ -336,7 +371,7 @@ madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params)
 }
 
 static int
-madwifi_set_privacy(const char *ifname, void *priv, int enabled)
+madwifi_set_privacy(void *priv, int enabled)
 {
        struct madwifi_driver_data *drv = priv;
 
@@ -371,8 +406,8 @@ madwifi_set_sta_authorized(void *priv, const u8 *addr, int authorized)
 }
 
 static int
-madwifi_sta_set_flags(void *priv, const u8 *addr, int total_flags,
-                     int flags_or, int flags_and)
+madwifi_sta_set_flags(void *priv, const u8 *addr,
+                     int total_flags, int flags_or, int flags_and)
 {
        /* For now, only support setting Authorized flag */
        if (flags_or & WPA_STA_AUTHORIZED)
@@ -505,6 +540,9 @@ madwifi_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
                 * swap it to match with the byte order used in WPA.
                 */
                int i;
+#ifndef WPA_KEY_RSC_LEN
+#define WPA_KEY_RSC_LEN 8
+#endif
                u8 tmp[WPA_KEY_RSC_LEN];
                memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
                for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
@@ -586,7 +624,7 @@ madwifi_sta_clear_stats(void *priv, const u8 *addr)
 
 
 static int
-madwifi_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len)
+madwifi_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
 {
        /*
         * Do nothing; we setup parameters at startup that define the
@@ -649,9 +687,8 @@ static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
 {
        struct madwifi_driver_data *drv = ctx;
        const struct ieee80211_mgmt *mgmt;
-       const u8 *end, *ie;
        u16 fc;
-       size_t ie_len;
+       union wpa_event_data event;
 
        /* Send Probe Request information to WPS processing */
 
@@ -664,11 +701,12 @@ static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
            WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_PROBE_REQ)
                return;
 
-       end = buf + len;
-       ie = mgmt->u.probe_req.variable;
-       ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
-
-       hostapd_probe_req_rx(drv->hapd, mgmt->sa, ie, ie_len);
+       os_memset(&event, 0, sizeof(event));
+       event.rx_probe_req.sa = mgmt->sa;
+       event.rx_probe_req.ie = mgmt->u.probe_req.variable;
+       event.rx_probe_req.ie_len =
+               len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
+       wpa_supplicant_event(drv->hapd, EVENT_RX_PROBE_REQ, &event);
 }
 #endif /* CONFIG_WPS */
 
@@ -699,7 +737,7 @@ static int
 madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
 {
        struct madwifi_driver_data *drv = priv;
-       u8 buf[256];
+       u8 buf[500];
        struct ieee80211req_getset_appiebuf *beac_ie;
 
        wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__,
@@ -715,10 +753,13 @@ madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
 }
 
 static int
-madwifi_set_ap_wps_ie(const char *ifname, void *priv,
-                     const struct wpabuf *beacon,
-                     const struct wpabuf *proberesp)
+madwifi_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
+                     const struct wpabuf *proberesp,
+                     const struct wpabuf *assocresp)
 {
+       madwifi_set_wps_ie(priv, assocresp ? wpabuf_head(assocresp) : NULL,
+                          assocresp ? wpabuf_len(assocresp) : 0,
+                          IEEE80211_APPIE_FRAME_ASSOC_RESP);
        if (madwifi_set_wps_ie(priv, beacon ? wpabuf_head(beacon) : NULL,
                               beacon ? wpabuf_len(beacon) : 0,
                               IEEE80211_APPIE_FRAME_BEACON))
@@ -732,12 +773,12 @@ madwifi_set_ap_wps_ie(const char *ifname, void *priv,
 #define madwifi_set_ap_wps_ie NULL
 #endif /* CONFIG_WPS */
 
-static int
+static void
 madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
 {
        struct hostapd_data *hapd = drv->hapd;
        struct ieee80211req_wpaie ie;
-       int ielen = 0, res;
+       int ielen = 0;
        u8 *iebuf = NULL;
 
        /*
@@ -778,15 +819,13 @@ madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
                ielen += 2;
 
 no_ie:
-       res = hostapd_notif_assoc(hapd, addr, iebuf, ielen);
+       drv_event_assoc(hapd, addr, iebuf, ielen);
 
        if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
                /* Cached accounting data is not valid anymore. */
                memset(drv->acct_mac, 0, ETH_ALEN);
                memset(&drv->acct_data, 0, sizeof(drv->acct_data));
        }
-
-       return res;
 }
 
 static void
@@ -904,8 +943,8 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
 
                switch (iwe->cmd) {
                case IWEVEXPIRED:
-                       hostapd_notif_disassoc(drv->hapd,
-                                              (u8 *) iwe->u.addr.sa_data);
+                       drv_event_disassoc(drv->hapd,
+                                          (u8 *) iwe->u.addr.sa_data);
                        break;
                case IWEVREGISTERED:
                        madwifi_new_sta(drv, (u8 *) iwe->u.addr.sa_data);
@@ -1073,9 +1112,8 @@ static void
 handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
 {
        struct madwifi_driver_data *drv = ctx;
-       hostapd_eapol_receive(drv->hapd, src_addr,
-                             buf + sizeof(struct l2_ethhdr),
-                             len - sizeof(struct l2_ethhdr));
+       drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr),
+                          len - sizeof(struct l2_ethhdr));
 }
 
 static void *
@@ -1084,6 +1122,7 @@ madwifi_init(struct hostapd_data *hapd, struct wpa_init_params *params)
        struct madwifi_driver_data *drv;
        struct ifreq ifr;
        struct iwreq iwr;
+       char brname[IFNAMSIZ];
 
        drv = os_zalloc(sizeof(struct madwifi_driver_data));
        if (drv == NULL) {
@@ -1121,6 +1160,13 @@ madwifi_init(struct hostapd_data *hapd, struct wpa_init_params *params)
                                                1);
                if (drv->sock_recv == NULL)
                        goto bad;
+       } else if (linux_br_get(brname, drv->iface) == 0) {
+               wpa_printf(MSG_DEBUG, "Interface in bridge %s; configure for "
+                          "EAPOL receive", brname);
+               drv->sock_recv = l2_packet_init(brname, NULL, ETH_P_EAPOL,
+                                               handle_read, drv, 1);
+               if (drv->sock_recv == NULL)
+                       goto bad;
        } else
                drv->sock_recv = drv->sock_xmit;
 
@@ -1135,8 +1181,9 @@ madwifi_init(struct hostapd_data *hapd, struct wpa_init_params *params)
                goto bad;
        }
 
-       madwifi_set_iface_flags(drv, 0);        /* mark down during setup */
-       madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */
+       /* mark down during setup */
+       linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0);
+       madwifi_set_privacy(drv, 0); /* default to no privacy */
 
        madwifi_receive_probe_req(drv);
 
@@ -1145,6 +1192,8 @@ madwifi_init(struct hostapd_data *hapd, struct wpa_init_params *params)
 
        return drv;
 bad:
+       if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit)
+               l2_packet_deinit(drv->sock_recv);
        if (drv->sock_xmit != NULL)
                l2_packet_deinit(drv->sock_xmit);
        if (drv->ioctl_sock >= 0)
@@ -1161,7 +1210,7 @@ madwifi_deinit(void *priv)
        struct madwifi_driver_data *drv = priv;
 
        netlink_deinit(drv->netlink);
-       (void) madwifi_set_iface_flags(drv, 0);
+       (void) linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0);
        if (drv->ioctl_sock >= 0)
                close(drv->ioctl_sock);
        if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit)
@@ -1174,7 +1223,7 @@ madwifi_deinit(void *priv)
 }
 
 static int
-madwifi_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
+madwifi_set_ssid(void *priv, const u8 *buf, int len)
 {
        struct madwifi_driver_data *drv = priv;
        struct iwreq iwr;
@@ -1194,7 +1243,7 @@ madwifi_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
 }
 
 static int
-madwifi_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
+madwifi_get_ssid(void *priv, u8 *buf, int len)
 {
        struct madwifi_driver_data *drv = priv;
        struct iwreq iwr;
@@ -1225,13 +1274,14 @@ madwifi_set_countermeasures(void *priv, int enabled)
 static int
 madwifi_commit(void *priv)
 {
-       return madwifi_set_iface_flags(priv, 1);
+       struct madwifi_driver_data *drv = priv;
+       return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);
 }
 
 const struct wpa_driver_ops wpa_driver_atheros_ops = {
        .name                   = "atheros",
        .hapd_init              = madwifi_init,
-       .deinit                 = madwifi_deinit,
+       .hapd_deinit            = madwifi_deinit,
        .set_ieee8021x          = madwifi_set_ieee8021x,
        .set_privacy            = madwifi_set_privacy,
        .set_key                = madwifi_set_key,