Fix couple of forgotten wpa_hw_modes -> hostapd_hw_modes
[wpasupplicant] / hostapd / driver_hostap.c
index de8e23c..1d4bef1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd / Kernel driver communication with Linux Host AP driver
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #endif /* USE_KERNEL_HEADERS */
 
 #include "hostapd.h"
+#include "config.h"
 #include "driver.h"
-#include "ieee802_1x.h"
 #include "eloop.h"
 #include "priv_netlink.h"
-#include "ieee802_11.h"
-#include "sta_info.h"
 #include "hostap_common.h"
 #include "hw_features.h"
+#include "ieee802_11_defs.h"
 
+static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 
 struct hostap_driver_data {
        struct hostapd_data *hapd;
@@ -55,21 +55,24 @@ struct hostap_driver_data {
 
        u8 *generic_ie;
        size_t generic_ie_len;
+       u8 *wps_ie;
+       size_t wps_ie_len;
 };
 
 
 static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
                         int len);
 static int hostap_set_iface_flags(void *priv, int dev_up);
+static int hostap_sta_disassoc(void *priv, const u8 *addr, int reason);
+static int hostap_sta_deauth(void *priv, const u8 *addr, int reason);
 
-static void handle_data(struct hostapd_data *hapd, u8 *buf, size_t len,
+static void handle_data(struct hostap_driver_data *drv, u8 *buf, size_t len,
                        u16 stype)
 {
        struct ieee80211_hdr *hdr;
        u16 fc, ethertype;
        u8 *pos, *sa;
        size_t left;
-       struct sta_info *sta;
 
        if (len < sizeof(struct ieee80211_hdr))
                return;
@@ -83,20 +86,7 @@ static void handle_data(struct hostapd_data *hapd, u8 *buf, size_t len,
        }
 
        sa = hdr->addr2;
-       sta = ap_get_sta(hapd, sa);
-       if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
-               printf("Data frame from not associated STA " MACSTR "\n",
-                      MAC2STR(sa));
-               if (sta && (sta->flags & WLAN_STA_AUTH))
-                       hostapd_sta_disassoc(
-                               hapd, sa,
-                               WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
-               else
-                       hostapd_sta_deauth(
-                               hapd, sa,
-                               WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
-               return;
-       }
+       hostapd_rx_from_unknown_sta(drv->hapd, sa);
 
        pos = (u8 *) (hdr + 1);
        left = len - sizeof(*hdr);
@@ -123,7 +113,7 @@ static void handle_data(struct hostapd_data *hapd, u8 *buf, size_t len,
        left -= 2;
        switch (ethertype) {
        case ETH_P_PAE:
-               ieee802_1x_receive(hapd, sa, pos, left);
+               hostapd_eapol_receive(drv->hapd, sa, pos, left);
                break;
 
        default:
@@ -133,12 +123,11 @@ static void handle_data(struct hostapd_data *hapd, u8 *buf, size_t len,
 }
 
 
-static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
-                              int ok)
+static void handle_tx_callback(struct hostap_driver_data *drv, u8 *buf,
+                              size_t len, int ok)
 {
        struct ieee80211_hdr *hdr;
        u16 fc, type, stype;
-       struct sta_info *sta;
 
        hdr = (struct ieee80211_hdr *) buf;
        fc = le_to_host16(hdr->frame_control);
@@ -150,7 +139,7 @@ static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
        case WLAN_FC_TYPE_MGMT:
                wpa_printf(MSG_DEBUG, "MGMT (TX callback) %s",
                           ok ? "ACK" : "fail");
-               ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
+               hostapd_mgmt_tx_cb(drv->hapd, buf, len, stype, ok);
                break;
        case WLAN_FC_TYPE_CTRL:
                wpa_printf(MSG_DEBUG, "CTRL (TX callback) %s",
@@ -159,17 +148,7 @@ static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
        case WLAN_FC_TYPE_DATA:
                wpa_printf(MSG_DEBUG, "DATA (TX callback) %s",
                           ok ? "ACK" : "fail");
-               sta = ap_get_sta(hapd, hdr->addr1);
-               if (sta && sta->flags & WLAN_STA_PENDING_POLL) {
-                       wpa_printf(MSG_DEBUG, "STA " MACSTR
-                                  " %s pending activity poll",
-                                  MAC2STR(sta->addr),
-                                  ok ? "ACKed" : "did not ACK");
-                       if (ok)
-                               sta->flags &= ~WLAN_STA_PENDING_POLL;
-               }
-               if (sta)
-                       ieee802_1x_tx_status(hapd, sta, buf, len, ok);
+               hostapd_tx_status(drv->hapd, hdr->addr1, buf, len, ok);
                break;
        default:
                printf("unknown TX callback frame type %d\n", type);
@@ -178,7 +157,7 @@ static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
 }
 
 
-static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len)
+static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len)
 {
        struct ieee80211_hdr *hdr;
        u16 fc, extra_len, type, stype;
@@ -220,7 +199,7 @@ static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len)
                len -= extra_len + 2;
                extra = buf + len;
        } else if (ver == 1 || ver == 2) {
-               handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0);
+               handle_tx_callback(drv, buf, data_len, ver == 2 ? 1 : 0);
                return;
        } else if (ver != 0) {
                printf("unknown protocol version %d\n", ver);
@@ -231,14 +210,14 @@ static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len)
        case WLAN_FC_TYPE_MGMT:
                if (stype != WLAN_FC_STYPE_BEACON)
                        wpa_printf(MSG_MSGDUMP, "MGMT");
-               ieee802_11_mgmt(hapd, buf, data_len, stype, NULL);
+               hostapd_mgmt_rx(drv->hapd, buf, data_len, stype, NULL);
                break;
        case WLAN_FC_TYPE_CTRL:
                wpa_printf(MSG_DEBUG, "CTRL");
                break;
        case WLAN_FC_TYPE_DATA:
                wpa_printf(MSG_DEBUG, "DATA");
-               handle_data(hapd, buf, data_len, stype);
+               handle_data(drv, buf, data_len, stype);
                break;
        default:
                wpa_printf(MSG_DEBUG, "unknown frame type %d", type);
@@ -249,7 +228,7 @@ static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len)
 
 static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
 {
-       struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
+       struct hostap_driver_data *drv = eloop_ctx;
        int len;
        unsigned char buf[3000];
 
@@ -259,7 +238,7 @@ static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
                return;
        }
 
-       handle_frame(hapd, buf, len);
+       handle_frame(drv, buf, len);
 }
 
 
@@ -274,8 +253,7 @@ static int hostap_init_sockets(struct hostap_driver_data *drv)
                return -1;
        }
 
-       if (eloop_register_read_sock(drv->sock, handle_read, drv->hapd, NULL))
-       {
+       if (eloop_register_read_sock(drv->sock, handle_read, drv, NULL)) {
                printf("Could not register read socket\n");
                return -1;
        }
@@ -458,10 +436,10 @@ static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
 }
 
 
-static int hostap_set_encryption(const char *ifname, void *priv,
-                                const char *alg, const u8 *addr,
-                                int idx, const u8 *key, size_t key_len,
-                                int txkey)
+static int hostap_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)
 {
        struct hostap_driver_data *drv = priv;
        struct prism2_hostapd_param *param;
@@ -480,10 +458,29 @@ static int hostap_set_encryption(const char *ifname, void *priv,
                memset(param->sta_addr, 0xff, ETH_ALEN);
        else
                memcpy(param->sta_addr, addr, ETH_ALEN);
-       os_strlcpy((char *) param->u.crypt.alg, alg,
-                  HOSTAP_CRYPT_ALG_NAME_LEN);
-       param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
-       param->u.crypt.idx = idx;
+       switch (alg) {
+       case WPA_ALG_NONE:
+               os_strlcpy((char *) param->u.crypt.alg, "NONE",
+                          HOSTAP_CRYPT_ALG_NAME_LEN);
+               break;
+       case WPA_ALG_WEP:
+               os_strlcpy((char *) param->u.crypt.alg, "WEP",
+                          HOSTAP_CRYPT_ALG_NAME_LEN);
+               break;
+       case WPA_ALG_TKIP:
+               os_strlcpy((char *) param->u.crypt.alg, "TKIP",
+                          HOSTAP_CRYPT_ALG_NAME_LEN);
+               break;
+       case WPA_ALG_CCMP:
+               os_strlcpy((char *) param->u.crypt.alg, "CCMP",
+                          HOSTAP_CRYPT_ALG_NAME_LEN);
+               break;
+       default:
+               os_free(buf);
+               return -1;
+       }
+       param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
+       param->u.crypt.idx = key_idx;
        param->u.crypt.key_len = key_len;
        memcpy((u8 *) (param + 1), key, key_len);
 
@@ -663,10 +660,8 @@ static int hostap_read_sta_data(void *priv,
 }
 
 
-static int hostap_sta_add(const char *ifname, void *priv, const u8 *addr,
-                         u16 aid, u16 capability, u8 *supp_rates,
-                         size_t supp_rates_len, int flags,
-                         u16 listen_interval)
+static int hostap_sta_add(const char *ifname, void *priv,
+                         struct hostapd_sta_add_params *params)
 {
        struct hostap_driver_data *drv = priv;
        struct prism2_hostapd_param param;
@@ -678,22 +673,22 @@ static int hostap_sta_add(const char *ifname, void *priv, const u8 *addr,
 #define WLAN_RATE_5M5 BIT(2)
 #define WLAN_RATE_11M BIT(3)
 
-       for (i = 0; i < supp_rates_len; i++) {
-               if ((supp_rates[i] & 0x7f) == 2)
+       for (i = 0; i < params->supp_rates_len; i++) {
+               if ((params->supp_rates[i] & 0x7f) == 2)
                        tx_supp_rates |= WLAN_RATE_1M;
-               if ((supp_rates[i] & 0x7f) == 4)
+               if ((params->supp_rates[i] & 0x7f) == 4)
                        tx_supp_rates |= WLAN_RATE_2M;
-               if ((supp_rates[i] & 0x7f) == 11)
+               if ((params->supp_rates[i] & 0x7f) == 11)
                        tx_supp_rates |= WLAN_RATE_5M5;
-               if ((supp_rates[i] & 0x7f) == 22)
+               if ((params->supp_rates[i] & 0x7f) == 22)
                        tx_supp_rates |= WLAN_RATE_11M;
        }
 
        memset(&param, 0, sizeof(param));
        param.cmd = PRISM2_HOSTAPD_ADD_STA;
-       memcpy(param.sta_addr, addr, ETH_ALEN);
-       param.u.add_sta.aid = aid;
-       param.u.add_sta.capability = capability;
+       memcpy(param.sta_addr, params->addr, ETH_ALEN);
+       param.u.add_sta.aid = params->aid;
+       param.u.add_sta.capability = params->capability;
        param.u.add_sta.tx_supp_rates = tx_supp_rates;
        return hostapd_ioctl(drv, &param, sizeof(param));
 }
@@ -749,28 +744,13 @@ static int hostap_sta_clear_stats(void *priv, const u8 *addr)
 }
 
 
-static int hostap_set_assoc_ap(void *priv, const u8 *addr)
-{
-       struct hostap_driver_data *drv = priv;
-       struct prism2_hostapd_param param;
-
-       memset(&param, 0, sizeof(param));
-       param.cmd = PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR;
-       memcpy(param.sta_addr, addr, ETH_ALEN);
-       if (hostapd_ioctl(drv, &param, sizeof(param)))
-               return -1;
-
-       return 0;
-}
-
-
 static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv)
 {
        struct prism2_hostapd_param *param;
        int res;
        size_t blen, elem_len;
 
-       elem_len = drv->generic_ie_len;
+       elem_len = drv->generic_ie_len + drv->wps_ie_len;
        blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len;
        if (blen < sizeof(*param))
                blen = sizeof(*param);
@@ -785,6 +765,10 @@ static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv)
                os_memcpy(param->u.generic_elem.data, drv->generic_ie,
                          drv->generic_ie_len);
        }
+       if (drv->wps_ie) {
+               os_memcpy(&param->u.generic_elem.data[drv->generic_ie_len],
+                         drv->wps_ie, drv->wps_ie_len);
+       }
        wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE",
                    param->u.generic_elem.data, elem_len);
        res = hostapd_ioctl(drv, param, blen);
@@ -815,6 +799,36 @@ static int hostap_set_generic_elem(const char *ifname, void *priv,
 }
 
 
+static int hostap_set_wps_beacon_ie(const char *ifname, void *priv,
+                                   const u8 *ie, size_t len)
+{
+       /* Host AP driver supports only one set of extra IEs, so we need to
+        * use the ProbeResp IEs also for Beacon frames since they include more
+        * information. */
+       return 0;
+}
+
+
+static int hostap_set_wps_probe_resp_ie(const char *ifname, void *priv,
+                                       const u8 *ie, size_t len)
+{
+       struct hostap_driver_data *drv = priv;
+
+       os_free(drv->wps_ie);
+       drv->wps_ie = NULL;
+       drv->wps_ie_len = 0;
+       if (ie) {
+               drv->wps_ie = os_malloc(len);
+               if (drv->wps_ie == NULL)
+                       return -1;
+               os_memcpy(drv->wps_ie, ie, len);
+               drv->wps_ie_len = len;
+       }
+
+       return hostapd_ioctl_set_generic_elem(drv);
+}
+
+
 static void
 hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv,
                                       char *custom)
@@ -833,7 +847,7 @@ hostapd_wireless_event_wireless_custom(struct hostap_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 "
@@ -1023,9 +1037,8 @@ static int hostap_get_we_version(struct hostap_driver_data *drv)
 }
 
 
-static int hostap_wireless_event_init(void *priv)
+static int hostap_wireless_event_init(struct hostap_driver_data *drv)
 {
-       struct hostap_driver_data *drv = priv;
        int s;
        struct sockaddr_nl local;
 
@@ -1056,9 +1069,8 @@ static int hostap_wireless_event_init(void *priv)
 }
 
 
-static void hostap_wireless_event_deinit(void *priv)
+static void hostap_wireless_event_deinit(struct hostap_driver_data *drv)
 {
-       struct hostap_driver_data *drv = priv;
        if (drv->wext_sock < 0)
                return;
        eloop_unregister_read_sock(drv->wext_sock);
@@ -1095,16 +1107,7 @@ static void * hostap_init(struct hostapd_data *hapd)
                return NULL;
        }
 
-       if (hapd->conf->assoc_ap &&
-           hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 1)) {
-               printf("Could not enable hostapd STA mode for interface %s\n",
-                      drv->iface);
-               close(drv->ioctl_sock);
-               free(drv);
-               return NULL;
-       }
-
-       if (hostap_init_sockets(drv)) {
+       if (hostap_init_sockets(drv) || hostap_wireless_event_init(drv)) {
                close(drv->ioctl_sock);
                free(drv);
                return NULL;
@@ -1118,6 +1121,7 @@ static void hostap_driver_deinit(void *priv)
 {
        struct hostap_driver_data *drv = priv;
 
+       hostap_wireless_event_deinit(drv);
        (void) hostap_set_iface_flags(drv, 0);
        (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0);
        (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0);
@@ -1129,6 +1133,7 @@ static void hostap_driver_deinit(void *priv)
                close(drv->sock);
 
        os_free(drv->generic_ie);
+       os_free(drv->wps_ie);
 
        free(drv);
 }
@@ -1221,15 +1226,13 @@ static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv,
 }
 
 
-const struct wpa_driver_ops wpa_driver_hostap_ops = {
+const struct hapd_driver_ops wpa_driver_hostap_ops = {
        .name = "hostap",
        .init = hostap_init,
        .deinit = hostap_driver_deinit,
-       .wireless_event_init = hostap_wireless_event_init,
-       .wireless_event_deinit = hostap_wireless_event_deinit,
        .set_ieee8021x = hostap_set_ieee8021x,
        .set_privacy = hostap_set_privacy,
-       .set_encryption = hostap_set_encryption,
+       .set_key = hostap_set_key,
        .get_seqnum = hostap_get_seqnum,
        .flush = hostap_flush,
        .set_generic_elem = hostap_set_generic_elem,
@@ -1241,9 +1244,10 @@ const struct wpa_driver_ops wpa_driver_hostap_ops = {
        .sta_remove = hostap_sta_remove,
        .set_ssid = hostap_set_ssid,
        .send_mgmt_frame = hostap_send_mgmt_frame,
-       .set_assoc_ap = hostap_set_assoc_ap,
        .sta_add = hostap_sta_add,
        .get_inact_sec = hostap_get_inact_sec,
        .sta_clear_stats = hostap_sta_clear_stats,
        .get_hw_feature_data = hostap_get_hw_feature_data,
+       .set_wps_beacon_ie = hostap_set_wps_beacon_ie,
+       .set_wps_probe_resp_ie = hostap_set_wps_probe_resp_ie,
 };