Fix UNIX domain socket address handling to be more portable
[wpasupplicant] / hostapd / driver_madwifi.c
index 9ddd033..a532ee2 100644 (file)
 #include <net80211/ieee80211_crypto.h>
 #include <net80211/ieee80211_ioctl.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.
 
 #include "hostapd.h"
 #include "driver.h"
-#include "ieee802_1x.h"
 #include "eloop.h"
 #include "priv_netlink.h"
-#include "sta_info.h"
 #include "l2_packet/l2_packet.h"
 
-#include "wpa.h"
-#include "radius/radius.h"
-#include "ieee802_11.h"
-#include "accounting.h"
 #include "common.h"
+#include "wps_hostapd.h"
+#include "ieee802_11_defs.h"
 
 
 struct madwifi_driver_data {
@@ -91,6 +97,8 @@ set80211priv(struct madwifi_driver_data *drv, int op, void *data, int len)
        if (op == IEEE80211_IOCTL_FILTERFRAME)
                do_inline = 0;
 #endif /* IEEE80211_IOCTL_FILTERFRAME */
+       if (op == IEEE80211_IOCTL_SET_APPIEBUF)
+               do_inline = 0;
        if (do_inline) {
                /*
                 * Argument data fits inline; put it there.
@@ -197,6 +205,7 @@ set80211param(struct madwifi_driver_data *drv, int op, int arg)
        return 0;
 }
 
+#ifndef CONFIG_NO_STDOUT_DEBUG
 static const char *
 ether_sprintf(const u8 *addr)
 {
@@ -208,6 +217,7 @@ ether_sprintf(const u8 *addr)
                snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
        return buf;
 }
+#endif /* CONFIG_NO_STDOUT_DEBUG */
 
 /*
  * Configure WPA parameters.
@@ -729,44 +739,117 @@ madwifi_sta_disassoc(void *priv, const u8 *addr, int reason_code)
        return ret;
 }
 
+#ifdef CONFIG_WPS
+#ifdef IEEE80211_IOCTL_FILTERFRAME
+static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
+                               size_t len)
+{
+       struct madwifi_driver_data *drv = ctx;
+       const struct ieee80211_mgmt *mgmt;
+       const u8 *end, *ie;
+       u16 fc;
+       size_t ie_len;
+
+       /* Send Probe Request information to WPS processing */
+
+       if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
+               return;
+       mgmt = (const struct ieee80211_mgmt *) buf;
+
+       fc = le_to_host16(mgmt->frame_control);
+       if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT ||
+           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_wps_probe_req_rx(drv->hapd, mgmt->sa, ie, ie_len);
+}
+#endif /* IEEE80211_IOCTL_FILTERFRAME */
+#endif /* CONFIG_WPS */
+
+static int madwifi_receive_probe_req(struct madwifi_driver_data *drv)
+{
+       int ret = 0;
+#ifdef CONFIG_WPS
+#ifdef IEEE80211_IOCTL_FILTERFRAME
+       struct ieee80211req_set_filter filt;
+
+       wpa_printf(MSG_DEBUG, "%s Enter", __func__);
+       filt.app_filterype = IEEE80211_FILTER_TYPE_PROBE_REQ;
+
+       ret = set80211priv(drv, IEEE80211_IOCTL_FILTERFRAME, &filt,
+                          sizeof(struct ieee80211req_set_filter));
+       if (ret)
+               return ret;
+
+       drv->sock_raw = l2_packet_init(drv->iface, NULL, ETH_P_80211_RAW,
+                                      madwifi_raw_receive, drv, 1);
+       if (drv->sock_raw == NULL)
+               return -1;
+#endif /* IEEE80211_IOCTL_FILTERFRAME */
+#endif /* CONFIG_WPS */
+       return ret;
+}
+
+#ifdef CONFIG_WPS
 static int
-madwifi_del_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
+madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
 {
-       struct hostapd_data *hapd = drv->hapd;
-       struct sta_info *sta;
-
-       hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
-               HOSTAPD_LEVEL_INFO, "disassociated");
-
-       sta = ap_get_sta(hapd, addr);
-       if (sta != NULL) {
-               sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
-               wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
-               sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
-               ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
-               ap_free_sta(hapd, sta);
-       }
-       return 0;
+       struct madwifi_driver_data *drv = priv;
+       u8 buf[256];
+       struct ieee80211req_getset_appiebuf *beac_ie;
+
+       wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__,
+                  (unsigned long) len);
+
+       beac_ie = (struct ieee80211req_getset_appiebuf *) buf;
+       beac_ie->app_frmtype = frametype;
+       beac_ie->app_buflen = len;
+       memcpy(&(beac_ie->app_buf[0]), ie, len);
+
+       return set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, beac_ie,
+                           sizeof(struct ieee80211req_getset_appiebuf) + len);
+}
+
+static int
+madwifi_set_wps_beacon_ie(const char *ifname, void *priv, const u8 *ie,
+                         size_t len)
+{
+       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,
+                                 IEEE80211_APPIE_FRAME_PROBE_RESP);
 }
+#else /* CONFIG_WPS */
+#define madwifi_set_wps_beacon_ie NULL
+#define madwifi_set_wps_probe_resp_ie NULL
+#endif /* CONFIG_WPS */
 
 static int
-madwifi_process_wpa_ie(struct madwifi_driver_data *drv, struct sta_info *sta)
+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, res;
-       u8 *iebuf;
+       int ielen = 0, res;
+       u8 *iebuf = NULL;
 
        /*
         * Fetch negotiated WPA/RSN parameters from the system.
         */
        memset(&ie, 0, sizeof(ie));
-       memcpy(ie.wpa_macaddr, sta->addr, IEEE80211_ADDR_LEN);
+       memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
        if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) {
-               wpa_printf(MSG_ERROR, "%s: Failed to get WPA/RSN IE",
+               wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE",
                           __func__);
-               printf("Failed to get WPA/RSN information element.\n");
-               return -1;              /* XXX not right */
+               goto no_ie;
        }
        wpa_hexdump(MSG_MSGDUMP, "madwifi req WPA IE",
                    ie.wpa_ie, IEEE80211_MAX_OPT_IE);
@@ -786,68 +869,23 @@ madwifi_process_wpa_ie(struct madwifi_driver_data *drv, struct sta_info *sta)
                        iebuf[1] = 0;
        }
 #endif /* MADWIFI_NG */
-       ielen = iebuf[1];
-       if (ielen == 0) {
-               printf("No WPA/RSN information element for station!?\n");
-               return -1;              /* XXX not right */
-       }
-       ielen += 2;
-       if (sta->wpa_sm == NULL)
-               sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr);
-       if (sta->wpa_sm == NULL) {
-               printf("Failed to initialize WPA state machine\n");
-               return -1;
-       }
-       res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
-                                 iebuf, ielen, NULL, 0);
-       if (res != WPA_IE_OK) {
-               printf("WPA/RSN information element rejected? (res %u)\n", res);
-               return -1;
-       }
-       return 0;
-}
 
-static int
-madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
-{
-       struct hostapd_data *hapd = drv->hapd;
-       struct sta_info *sta;
-       int new_assoc;
+       ielen = iebuf[1];
+       if (ielen == 0)
+               iebuf = NULL;
+       else
+               ielen += 2;
 
-       hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
-               HOSTAPD_LEVEL_INFO, "associated");
-
-       sta = ap_get_sta(hapd, addr);
-       if (sta) {
-               accounting_sta_stop(hapd, sta);
-       } else {
-               sta = ap_sta_add(hapd, addr);
-               if (sta == NULL)
-                       return -1;
-       }
+no_ie:
+       res = hostapd_notif_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));
        }
-       accounting_sta_get_id(hapd, sta);
-
-       if (hapd->conf->wpa) {
-               if (madwifi_process_wpa_ie(drv, sta))
-                       return -1;
-       }
 
-       /*
-        * Now that the internal station state is setup
-        * kick the authenticator into action.
-        */
-       new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
-       sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
-       wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
-       hostapd_new_assoc_sta(hapd, sta, !new_assoc);
-       ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
-       return 0;
+       return res;
 }
 
 static void
@@ -868,7 +906,7 @@ madwifi_wireless_event_wireless_custom(struct madwifi_driver_data *drv,
                }
                pos += 5;
                if (hwaddr_aton(pos, addr) == 0) {
-                       ieee80211_michael_mic_failure(drv->hapd, addr, 1);
+                       hostapd_michael_mic_failure(drv->hapd, addr);
                } else {
                        wpa_printf(MSG_DEBUG,
                                   "MLME-MICHAELMICFAILURE.indication "
@@ -935,7 +973,8 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
 
                switch (iwe->cmd) {
                case IWEVEXPIRED:
-                       madwifi_del_sta(drv, (u8 *) iwe->u.addr.sa_data);
+                       hostapd_notif_disassoc(drv->hapd,
+                                              (u8 *) iwe->u.addr.sa_data);
                        break;
                case IWEVREGISTERED:
                        madwifi_new_sta(drv, (u8 *) iwe->u.addr.sa_data);
@@ -1165,7 +1204,7 @@ madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
        eth = (struct l2_ethhdr *) bp;
        memcpy(eth->h_dest, addr, ETH_ALEN);
        memcpy(eth->h_source, own_addr, ETH_ALEN);
-       eth->h_proto = htons(ETH_P_EAPOL);
+       eth->h_proto = host_to_be16(ETH_P_EAPOL);
        memcpy(eth+1, data, data_len);
 
        wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
@@ -1181,18 +1220,9 @@ static void
 handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
 {
        struct madwifi_driver_data *drv = ctx;
-       struct hostapd_data *hapd = drv->hapd;
-       struct sta_info *sta;
-
-       sta = ap_get_sta(hapd, src_addr);
-       if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
-               printf("Data frame from not associated STA %s\n",
-                      ether_sprintf(src_addr));
-               /* XXX cannot happen */
-               return;
-       }
-       ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr),
-                          len - sizeof(struct l2_ethhdr));
+       hostapd_eapol_receive(drv->hapd, src_addr,
+                             buf + sizeof(struct l2_ethhdr),
+                             len - sizeof(struct l2_ethhdr));
 }
 
 static void *
@@ -1255,6 +1285,8 @@ madwifi_init(struct hostapd_data *hapd)
        madwifi_set_iface_flags(drv, 0);        /* mark down during setup */
        madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */
 
+       madwifi_receive_probe_req(drv);
+
        return drv;
 bad:
        if (drv->sock_xmit != NULL)
@@ -1361,4 +1393,6 @@ const struct wpa_driver_ops wpa_driver_madwifi_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,
 };