WPS 2.0: Provide (Re)Association Response WPS IE to driver
[libeap.git] / src / drivers / driver_atheros.c
index ce9f983..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 "../hostapd/hostapd.h"
-#include "../hostapd/config.h"
-#include "../hostapd/sta_flags.h"
 #include "driver.h"
 #include "eloop.h"
 #include "priv_netlink.h"
 #include "l2_packet/l2_packet.h"
 #include "common/ieee802_11_defs.h"
+#include "netlink.h"
+#include "linux_ioctl.h"
 
 
 struct madwifi_driver_data {
@@ -76,7 +64,7 @@ struct madwifi_driver_data {
        struct l2_packet_data *sock_xmit;       /* raw packet xmit socket */
        struct l2_packet_data *sock_recv;       /* raw packet recv socket */
        int     ioctl_sock;                     /* socket for ioctl() use */
-       int     wext_sock;                      /* socket for wireless events */
+       struct netlink_data *netlink;
        int     we_version;
        u8      acct_mac[ETH_ALEN];
        struct hostap_sta_driver_data acct_data;
@@ -86,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)
@@ -116,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;
@@ -167,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;
@@ -192,13 +255,12 @@ ether_sprintf(const u8 *addr)
  * Configure WPA parameters.
  */
 static int
-madwifi_configure_wpa(struct madwifi_driver_data *drv)
+madwifi_configure_wpa(struct madwifi_driver_data *drv,
+                     struct wpa_bss_params *params)
 {
-       struct hostapd_data *hapd = drv->hapd;
-       struct hostapd_bss_config *conf = hapd->conf;
        int v;
 
-       switch (conf->wpa_group) {
+       switch (params->wpa_group) {
        case WPA_CIPHER_CCMP:
                v = IEEE80211_CIPHER_AES_CCM;
                break;
@@ -216,7 +278,7 @@ madwifi_configure_wpa(struct madwifi_driver_data *drv)
                break;
        default:
                wpa_printf(MSG_ERROR, "Unknown group key cipher %u",
-                          conf->wpa_group);
+                          params->wpa_group);
                return -1;
        }
        wpa_printf(MSG_DEBUG, "%s: group key cipher=%d", __func__, v);
@@ -226,7 +288,7 @@ madwifi_configure_wpa(struct madwifi_driver_data *drv)
        }
        if (v == IEEE80211_CIPHER_WEP) {
                /* key length is done only for specific ciphers */
-               v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
+               v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
                if (set80211param(drv, IEEE80211_PARAM_MCASTKEYLEN, v)) {
                        printf("Unable to set group key length to %u\n", v);
                        return -1;
@@ -234,11 +296,11 @@ madwifi_configure_wpa(struct madwifi_driver_data *drv)
        }
 
        v = 0;
-       if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
+       if (params->wpa_pairwise & WPA_CIPHER_CCMP)
                v |= 1<<IEEE80211_CIPHER_AES_CCM;
-       if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
+       if (params->wpa_pairwise & WPA_CIPHER_TKIP)
                v |= 1<<IEEE80211_CIPHER_TKIP;
-       if (conf->wpa_pairwise & WPA_CIPHER_NONE)
+       if (params->wpa_pairwise & WPA_CIPHER_NONE)
                v |= 1<<IEEE80211_CIPHER_NONE;
        wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v);
        if (set80211param(drv, IEEE80211_PARAM_UCASTCIPHERS, v)) {
@@ -247,61 +309,29 @@ madwifi_configure_wpa(struct madwifi_driver_data *drv)
        }
 
        wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x",
-                  __func__, conf->wpa_key_mgmt);
-       if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS, conf->wpa_key_mgmt)) {
+                  __func__, params->wpa_key_mgmt);
+       if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS,
+                         params->wpa_key_mgmt)) {
                printf("Unable to set key management algorithms to 0x%x\n",
-                       conf->wpa_key_mgmt);
+                       params->wpa_key_mgmt);
                return -1;
        }
 
        v = 0;
-       if (conf->rsn_preauth)
+       if (params->rsn_preauth)
                v |= BIT(0);
        wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
-                  __func__, conf->rsn_preauth);
+                  __func__, params->rsn_preauth);
        if (set80211param(drv, IEEE80211_PARAM_RSNCAPS, v)) {
                printf("Unable to set RSN capabilities to 0x%x\n", v);
                return -1;
        }
 
-       wpa_printf(MSG_DEBUG, "%s: enable WPA=0x%x", __func__, conf->wpa);
-       if (set80211param(drv, IEEE80211_PARAM_WPA, conf->wpa)) {
-               printf("Unable to set WPA to %u\n", conf->wpa);
-               return -1;
-       }
-       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]");
+       wpa_printf(MSG_DEBUG, "%s: enable WPA=0x%x", __func__, params->wpa);
+       if (set80211param(drv, IEEE80211_PARAM_WPA, params->wpa)) {
+               printf("Unable to set WPA to %u\n", params->wpa);
                return -1;
        }
-
        return 0;
 }
 
@@ -309,30 +339,30 @@ static int
 madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params)
 {
        struct madwifi_driver_data *drv = priv;
-       struct hostapd_data *hapd = drv->hapd;
-       struct hostapd_bss_config *conf = hapd->conf;
-       int enabled = params->enabled;
 
-       wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
+       wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled);
 
-       if (!enabled) {
+       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 (!conf->wpa && !conf->ieee802_1x) {
-               hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
+       if (!params->wpa && !params->ieee802_1x) {
+               hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
                        HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
                return -1;
        }
-       if (conf->wpa && madwifi_configure_wpa(drv) != 0) {
-               hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
+       if (params->wpa && madwifi_configure_wpa(drv, params) != 0) {
+               hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
                        HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
                return -1;
        }
        if (set80211param(priv, IEEE80211_PARAM_AUTHMODE,
-               (conf->wpa ?  IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
-               hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
+               (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
+               hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
                        HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!");
                return -1;
        }
@@ -341,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;
 
@@ -376,13 +406,13 @@ 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 & WLAN_STA_AUTHORIZED)
+       if (flags_or & WPA_STA_AUTHORIZED)
                return madwifi_set_sta_authorized(priv, addr, 1);
-       if (!(flags_and & WLAN_STA_AUTHORIZED))
+       if (!(flags_and & WPA_STA_AUTHORIZED))
                return madwifi_set_sta_authorized(priv, addr, 0);
        return 0;
 }
@@ -416,9 +446,9 @@ madwifi_del_key(void *priv, const u8 *addr, int key_idx)
 }
 
 static int
-madwifi_set_key(const char *ifname, void *priv, wpa_alg alg, const u8 *addr,
-               int key_idx, int set_tx, const u8 *seq, size_t seq_len,
-               const u8 *key, size_t key_len)
+madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
+               const u8 *addr, int key_idx, int set_tx, const u8 *seq,
+               size_t seq_len, const u8 *key, size_t key_len)
 {
        struct madwifi_driver_data *drv = priv;
        struct ieee80211req_key wk;
@@ -510,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++) {
@@ -591,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
@@ -654,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 */
 
@@ -669,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 */
 
@@ -704,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__,
@@ -720,30 +753,32 @@ madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
 }
 
 static int
-madwifi_set_wps_beacon_ie(const char *ifname, void *priv, const u8 *ie,
-                         size_t len)
+madwifi_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
+                     const struct wpabuf *proberesp,
+                     const struct wpabuf *assocresp)
 {
-       return madwifi_set_wps_ie(priv, ie, len, IEEE80211_APPIE_FRAME_BEACON);
-}
-
-static int
-madwifi_set_wps_probe_resp_ie(const char *ifname, void *priv, const u8 *ie,
-                             size_t len)
-{
-       return madwifi_set_wps_ie(priv, ie, len,
+       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))
+               return -1;
+       return madwifi_set_wps_ie(priv,
+                                 proberesp ? wpabuf_head(proberesp) : NULL,
+                                 proberesp ? wpabuf_len(proberesp): 0,
                                  IEEE80211_APPIE_FRAME_PROBE_RESP);
 }
 #else /* CONFIG_WPS */
-#define madwifi_set_wps_beacon_ie NULL
-#define madwifi_set_wps_probe_resp_ie NULL
+#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;
 
        /*
@@ -784,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
@@ -813,7 +846,12 @@ madwifi_wireless_event_wireless_custom(struct madwifi_driver_data *drv,
                }
                pos += 5;
                if (hwaddr_aton(pos, addr) == 0) {
-                       hostapd_michael_mic_failure(drv->hapd, addr);
+                       union wpa_event_data data;
+                       os_memset(&data, 0, sizeof(data));
+                       data.michael_mic_failure.unicast = 1;
+                       data.michael_mic_failure.src = addr;
+                       wpa_supplicant_event(drv->hapd,
+                                            EVENT_MICHAEL_MIC_FAILURE, &data);
                } else {
                        wpa_printf(MSG_DEBUG,
                                   "MLME-MICHAELMICFAILURE.indication "
@@ -848,7 +886,7 @@ madwifi_wireless_event_wireless_custom(struct madwifi_driver_data *drv,
                /* PROBLEM! this event is received for ALL BSSs ...
                 * so all are enabled for WPS... ugh.
                 */
-               hostapd_button_pushed(drv->hapd);
+               wpa_supplicant_event(drv->hapd, EVENT_WPS_BUTTON_PUSHED, NULL);
        } else if (strncmp(custom, "Manage.prob_req ", 16) == 0) {
                /*
                 * Atheros driver uses a hack to pass Probe Request frames as a
@@ -905,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);
@@ -936,28 +974,18 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
 
 
 static void
-madwifi_wireless_event_rtm_newlink(struct madwifi_driver_data *drv,
-                                              struct nlmsghdr *h, int len)
+madwifi_wireless_event_rtm_newlink(void *ctx,
+                                  struct ifinfomsg *ifi, u8 *buf, size_t len)
 {
-       struct ifinfomsg *ifi;
-       int attrlen, nlmsg_len, rta_len;
-       struct rtattr * attr;
-
-       if (len < (int) sizeof(*ifi))
-               return;
-
-       ifi = NLMSG_DATA(h);
+       struct madwifi_driver_data *drv = ctx;
+       int attrlen, rta_len;
+       struct rtattr *attr;
 
        if (ifi->ifi_index != drv->ifindex)
                return;
 
-       nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
-       attrlen = h->nlmsg_len - nlmsg_len;
-       if (attrlen < 0)
-               return;
-
-       attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+       attrlen = len;
+       attr = (struct rtattr *) buf;
 
        rta_len = RTA_ALIGN(sizeof(struct rtattr));
        while (RTA_OK(attr, attrlen)) {
@@ -971,55 +999,6 @@ madwifi_wireless_event_rtm_newlink(struct madwifi_driver_data *drv,
 }
 
 
-static void
-madwifi_wireless_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
-{
-       char buf[256];
-       int left;
-       struct sockaddr_nl from;
-       socklen_t fromlen;
-       struct nlmsghdr *h;
-       struct madwifi_driver_data *drv = eloop_ctx;
-
-       fromlen = sizeof(from);
-       left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
-                       (struct sockaddr *) &from, &fromlen);
-       if (left < 0) {
-               if (errno != EINTR && errno != EAGAIN)
-                       perror("recvfrom(netlink)");
-               return;
-       }
-
-       h = (struct nlmsghdr *) buf;
-       while (left >= (int) sizeof(*h)) {
-               int len, plen;
-
-               len = h->nlmsg_len;
-               plen = len - sizeof(*h);
-               if (len > left || plen < 0) {
-                       printf("Malformed netlink message: "
-                              "len=%d left=%d plen=%d\n",
-                              len, left, plen);
-                       break;
-               }
-
-               switch (h->nlmsg_type) {
-               case RTM_NEWLINK:
-                       madwifi_wireless_event_rtm_newlink(drv, h, plen);
-                       break;
-               }
-
-               len = NLMSG_ALIGN(len);
-               left -= len;
-               h = (struct nlmsghdr *) ((char *) h + len);
-       }
-
-       if (left > 0) {
-               printf("%d extra bytes in the end of netlink message\n", left);
-       }
-}
-
-
 static int
 madwifi_get_we_version(struct madwifi_driver_data *drv)
 {
@@ -1069,45 +1048,25 @@ madwifi_get_we_version(struct madwifi_driver_data *drv)
 static int
 madwifi_wireless_event_init(struct madwifi_driver_data *drv)
 {
-       int s;
-       struct sockaddr_nl local;
+       struct netlink_config *cfg;
 
        madwifi_get_we_version(drv);
 
-       drv->wext_sock = -1;
-
-       s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-       if (s < 0) {
-               perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
+       cfg = os_zalloc(sizeof(*cfg));
+       if (cfg == NULL)
                return -1;
-       }
-
-       memset(&local, 0, sizeof(local));
-       local.nl_family = AF_NETLINK;
-       local.nl_groups = RTMGRP_LINK;
-       if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
-               perror("bind(netlink)");
-               close(s);
+       cfg->ctx = drv;
+       cfg->newlink_cb = madwifi_wireless_event_rtm_newlink;
+       drv->netlink = netlink_init(cfg);
+       if (drv->netlink == NULL) {
+               os_free(cfg);
                return -1;
        }
 
-       eloop_register_read_sock(s, madwifi_wireless_event_receive, drv, NULL);
-       drv->wext_sock = s;
-
        return 0;
 }
 
 
-static void
-madwifi_wireless_event_deinit(struct madwifi_driver_data *drv)
-{
-       if (drv->wext_sock < 0)
-               return;
-       eloop_unregister_read_sock(drv->wext_sock);
-       close(drv->wext_sock);
-}
-
-
 static int
 madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
                   int encrypt, const u8 *own_addr)
@@ -1153,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 *
@@ -1164,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) {
@@ -1201,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;
 
@@ -1215,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);
 
@@ -1225,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)
@@ -1240,8 +1209,8 @@ madwifi_deinit(void *priv)
 {
        struct madwifi_driver_data *drv = priv;
 
-       madwifi_wireless_event_deinit(drv);
-       (void) madwifi_set_iface_flags(drv, 0);
+       netlink_deinit(drv->netlink);
+       (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)
@@ -1254,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;
@@ -1274,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;
@@ -1305,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,
@@ -1328,6 +1298,5 @@ const struct wpa_driver_ops wpa_driver_atheros_ops = {
        .set_countermeasures    = madwifi_set_countermeasures,
        .sta_clear_stats        = madwifi_sta_clear_stats,
        .commit                 = madwifi_commit,
-       .set_wps_beacon_ie      = madwifi_set_wps_beacon_ie,
-       .set_wps_probe_resp_ie  = madwifi_set_wps_probe_resp_ie,
+       .set_ap_wps_ie          = madwifi_set_ap_wps_ie,
 };