]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/drivers/driver_privsep.c
Replace int status/reason_code with u16 variable
[thirdparty/hostap.git] / src / drivers / driver_privsep.c
index abe4303ebbfc768a569dc2145d7741f08f8326c9..55cf61885741936dbf2e9a19f17e53f515cf4f79 100644 (file)
@@ -2,14 +2,8 @@
  * WPA Supplicant - privilege separated driver interface
  * Copyright (c) 2007-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
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "includes.h"
@@ -18,7 +12,7 @@
 #include "common.h"
 #include "driver.h"
 #include "eloop.h"
-#include "privsep_commands.h"
+#include "common/privsep_commands.h"
 
 
 struct wpa_driver_privsep_data {
@@ -41,7 +35,7 @@ static int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd)
                     (struct sockaddr *) &drv->priv_addr,
                     sizeof(drv->priv_addr));
        if (res < 0)
-               perror("sendto");
+               wpa_printf(MSG_ERROR, "sendto: %s", strerror(errno));
        return res < 0 ? -1 : 0;
 }
 
@@ -65,7 +59,8 @@ static int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd,
        msg.msg_namelen = sizeof(drv->priv_addr);
 
        if (sendmsg(drv->cmd_socket, &msg, 0) < 0) {
-               perror("sendmsg(cmd_socket)");
+               wpa_printf(MSG_ERROR, "sendmsg(cmd_socket): %s",
+                          strerror(errno));
                return -1;
        }
 
@@ -80,14 +75,15 @@ static int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd,
                tv.tv_usec = 0;
                res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv);
                if (res < 0 && errno != EINTR) {
-                       perror("select");
+                       wpa_printf(MSG_ERROR, "select: %s", strerror(errno));
                        return -1;
                }
 
                if (FD_ISSET(drv->cmd_socket, &rfds)) {
                        res = recv(drv->cmd_socket, reply, *reply_len, 0);
                        if (res < 0) {
-                               perror("recv");
+                               wpa_printf(MSG_ERROR, "recv: %s",
+                                          strerror(errno));
                                return -1;
                        }
                        *reply_len = res;
@@ -101,21 +97,31 @@ static int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd,
        return 0;
 }
 
-                            
-static int wpa_driver_privsep_set_wpa(void *priv, int enabled)
-{
-       struct wpa_driver_privsep_data *drv = priv;
-       wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
-       return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_WPA, &enabled,
-                           sizeof(enabled), NULL, NULL);
-}
 
-
-static int wpa_driver_privsep_scan(void *priv, const u8 *ssid, size_t ssid_len)
+static int wpa_driver_privsep_scan(void *priv,
+                                  struct wpa_driver_scan_params *params)
 {
        struct wpa_driver_privsep_data *drv = priv;
+       struct privsep_cmd_scan scan;
+       size_t i;
+
        wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
-       return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, ssid, ssid_len,
+       os_memset(&scan, 0, sizeof(scan));
+       scan.num_ssids = params->num_ssids;
+       for (i = 0; i < params->num_ssids; i++) {
+               if (!params->ssids[i].ssid)
+                       continue;
+               scan.ssid_lens[i] = params->ssids[i].ssid_len;
+               os_memcpy(scan.ssids[i], params->ssids[i].ssid,
+                         scan.ssid_lens[i]);
+       }
+
+       for (i = 0; i < PRIVSEP_MAX_SCAN_FREQS &&
+                    params->freqs && params->freqs[i]; i++)
+               scan.freqs[i] = params->freqs[i];
+       scan.num_freqs = i;
+
+       return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, &scan, sizeof(scan),
                            NULL, NULL);
 }
 
@@ -164,26 +170,29 @@ wpa_driver_privsep_get_scan_results2(void *priv)
                return NULL;
        }
 
-       results->res = os_zalloc(num * sizeof(struct wpa_scan_res *));
+       results->res = os_calloc(num, sizeof(struct wpa_scan_res *));
        if (results->res == NULL) {
                os_free(results);
                os_free(buf);
                return NULL;
        }
 
-       while (results->num < (size_t) num && pos + sizeof(int) < end) {
+       while (results->num < (size_t) num && end - pos > (int) sizeof(int)) {
                int len;
                os_memcpy(&len, pos, sizeof(int));
                pos += sizeof(int);
-               if (len < 0 || len > 10000 || pos + len > end)
+               if (len < 0 || len > 10000 || len > end - pos)
                        break;
 
-               r = os_malloc(len);
+               r = os_memdup(pos, len);
                if (r == NULL)
                        break;
-               os_memcpy(r, pos, len);
                pos += len;
-               if (sizeof(*r) + r->ie_len > (size_t) len) {
+               if (sizeof(*r) + r->ie_len + r->beacon_ie_len > (size_t) len) {
+                       wpa_printf(MSG_ERROR,
+                                  "privsep: Invalid scan result len (%d + %d + %d > %d)",
+                                  (int) sizeof(*r), (int) r->ie_len,
+                                  (int) r->beacon_ie_len, len);
                        os_free(r);
                        break;
                }
@@ -196,10 +205,11 @@ wpa_driver_privsep_get_scan_results2(void *priv)
 }
 
 
-static int wpa_driver_privsep_set_key(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)
+static int wpa_driver_privsep_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 wpa_driver_privsep_data *drv = priv;
        struct privsep_cmd_set_key cmd;
@@ -229,6 +239,56 @@ static int wpa_driver_privsep_set_key(void *priv, wpa_alg alg, const u8 *addr,
 }
 
 
+static int wpa_driver_privsep_authenticate(
+       void *priv, struct wpa_driver_auth_params *params)
+{
+       struct wpa_driver_privsep_data *drv = priv;
+       struct privsep_cmd_authenticate *data;
+       int i, res;
+       size_t buflen;
+       u8 *pos;
+
+       wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d bssid=" MACSTR
+                  " auth_alg=%d local_state_change=%d p2p=%d",
+                  __func__, priv, params->freq, MAC2STR(params->bssid),
+                  params->auth_alg, params->local_state_change, params->p2p);
+
+       buflen = sizeof(*data) + params->ie_len + params->auth_data_len;
+       data = os_zalloc(buflen);
+       if (data == NULL)
+               return -1;
+
+       data->freq = params->freq;
+       os_memcpy(data->bssid, params->bssid, ETH_ALEN);
+       os_memcpy(data->ssid, params->ssid, params->ssid_len);
+       data->ssid_len = params->ssid_len;
+       data->auth_alg = params->auth_alg;
+       data->ie_len = params->ie_len;
+       for (i = 0; i < 4; i++) {
+               if (params->wep_key[i])
+                       os_memcpy(data->wep_key[i], params->wep_key[i],
+                                 params->wep_key_len[i]);
+               data->wep_key_len[i] = params->wep_key_len[i];
+       }
+       data->wep_tx_keyidx = params->wep_tx_keyidx;
+       data->local_state_change = params->local_state_change;
+       data->p2p = params->p2p;
+       pos = (u8 *) (data + 1);
+       if (params->ie_len) {
+               os_memcpy(pos, params->ie, params->ie_len);
+               pos += params->ie_len;
+       }
+       if (params->auth_data_len)
+               os_memcpy(pos, params->auth_data, params->auth_data_len);
+
+       res = wpa_priv_cmd(drv, PRIVSEP_CMD_AUTHENTICATE, data, buflen,
+                          NULL, NULL);
+       os_free(data);
+
+       return res;
+}
+
+
 static int wpa_driver_privsep_associate(
        void *priv, struct wpa_driver_associate_params *params)
 {
@@ -239,7 +299,7 @@ static int wpa_driver_privsep_associate(
 
        wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
                   "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
-                  __func__, priv, params->freq, params->pairwise_suite,
+                  __func__, priv, params->freq.freq, params->pairwise_suite,
                   params->group_suite, params->key_mgmt_suite,
                   params->auth_alg, params->mode);
 
@@ -252,7 +312,9 @@ static int wpa_driver_privsep_associate(
                os_memcpy(data->bssid, params->bssid, ETH_ALEN);
        os_memcpy(data->ssid, params->ssid, params->ssid_len);
        data->ssid_len = params->ssid_len;
-       data->freq = params->freq;
+       data->hwmode = params->freq.mode;
+       data->freq = params->freq.freq;
+       data->channel = params->freq.channel;
        data->pairwise_suite = params->pairwise_suite;
        data->group_suite = params->group_suite;
        data->key_mgmt_suite = params->key_mgmt_suite;
@@ -288,14 +350,15 @@ static int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid)
 {
        struct wpa_driver_privsep_data *drv = priv;
        int res, ssid_len;
-       u8 reply[sizeof(int) + 32];
+       u8 reply[sizeof(int) + SSID_MAX_LEN];
        size_t len = sizeof(reply);
 
        res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len);
        if (res < 0 || len < sizeof(int))
                return -1;
        os_memcpy(&ssid_len, reply, sizeof(int));
-       if (ssid_len < 0 || ssid_len > 32 || sizeof(int) + ssid_len > len) {
+       if (ssid_len < 0 || ssid_len > SSID_MAX_LEN ||
+           sizeof(int) + ssid_len > len) {
                wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply");
                return -1;
        }
@@ -305,7 +368,7 @@ static int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid)
 
 
 static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
-                                         int reason_code)
+                                            u16 reason_code)
 {
        //struct wpa_driver_privsep_data *drv = priv;
        wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
@@ -315,18 +378,34 @@ static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
 }
 
 
-static int wpa_driver_privsep_disassociate(void *priv, const u8 *addr,
-                                       int reason_code)
+static void wpa_driver_privsep_event_auth(void *ctx, u8 *buf, size_t len)
 {
-       //struct wpa_driver_privsep_data *drv = priv;
-       wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
-                  __func__, MAC2STR(addr), reason_code);
-       wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
-       return 0;
+       union wpa_event_data data;
+       struct privsep_event_auth *auth;
+
+       os_memset(&data, 0, sizeof(data));
+       if (len < sizeof(*auth))
+               return;
+       auth = (struct privsep_event_auth *) buf;
+       if (len < sizeof(*auth) + auth->ies_len)
+               return;
+
+       os_memcpy(data.auth.peer, auth->peer, ETH_ALEN);
+       os_memcpy(data.auth.bssid, auth->bssid, ETH_ALEN);
+       data.auth.auth_type = auth->auth_type;
+       data.auth.auth_transaction = auth->auth_transaction;
+       data.auth.status_code = auth->status_code;
+       if (auth->ies_len) {
+               data.auth.ies = (u8 *) (auth + 1);
+               data.auth.ies_len = auth->ies_len;
+       }
+
+       wpa_supplicant_event(ctx, EVENT_AUTH, &data);
 }
 
 
-static void wpa_driver_privsep_event_assoc(void *ctx, wpa_event_type event,
+static void wpa_driver_privsep_event_assoc(void *ctx,
+                                          enum wpa_event_type event,
                                           u8 *buf, size_t len)
 {
        union wpa_event_data data;
@@ -404,19 +483,6 @@ static void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf,
 }
 
 
-static void wpa_driver_privsep_event_stkstart(void *ctx, u8 *buf, size_t len)
-{
-       union wpa_event_data data;
-
-       if (len != ETH_ALEN)
-               return;
-
-       os_memset(&data, 0, sizeof(data));
-       os_memcpy(data.stkstart.peer, buf, ETH_ALEN);
-       wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
-}
-
-
 static void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf,
                                                 size_t len)
 {
@@ -438,24 +504,7 @@ static void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len)
 {
        if (len < ETH_ALEN)
                return;
-
-       wpa_supplicant_rx_eapol(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN);
-}
-
-
-static void wpa_driver_privsep_event_sta_rx(void *ctx, u8 *buf, size_t len)
-{
-#ifdef CONFIG_CLIENT_MLME
-       struct ieee80211_rx_status *rx_status;
-
-       if (len < sizeof(*rx_status))
-               return;
-       rx_status = (struct ieee80211_rx_status *) buf;
-       buf += sizeof(*rx_status);
-       len -= sizeof(*rx_status);
-
-       wpa_supplicant_sta_rx(ctx, buf, len, rx_status);
-#endif /* CONFIG_CLIENT_MLME */
+       drv_event_eapol_rx(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN);
 }
 
 
@@ -477,7 +526,8 @@ static void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
        res = recvfrom(sock, buf, buflen, 0,
                       (struct sockaddr *) &from, &fromlen);
        if (res < 0) {
-               perror("recvfrom(priv_socket)");
+               wpa_printf(MSG_ERROR, "recvfrom(priv_socket): %s",
+                          strerror(errno));
                os_free(buf);
                return;
        }
@@ -500,6 +550,9 @@ static void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
        case PRIVSEP_EVENT_SCAN_RESULTS:
                wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL);
                break;
+       case PRIVSEP_EVENT_SCAN_STARTED:
+               wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
+               break;
        case PRIVSEP_EVENT_ASSOC:
                wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC,
                                               event_buf, event_len);
@@ -523,10 +576,6 @@ static void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
                wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf,
                                                         event_len);
                break;
-       case PRIVSEP_EVENT_STKSTART:
-               wpa_driver_privsep_event_stkstart(drv->ctx, event_buf,
-                                                 event_len);
-               break;
        case PRIVSEP_EVENT_FT_RESPONSE:
                wpa_driver_privsep_event_ft_response(drv->ctx, event_buf,
                                                     event_len);
@@ -535,9 +584,8 @@ static void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
                wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
                                                  event_len);
                break;
-       case PRIVSEP_EVENT_STA_RX:
-               wpa_driver_privsep_event_sta_rx(drv->ctx, event_buf,
-                                               event_len);
+       case PRIVSEP_EVENT_AUTH:
+               wpa_driver_privsep_event_auth(drv->ctx, event_buf, event_len);
                break;
        }
 
@@ -671,7 +719,7 @@ static int wpa_driver_privsep_set_param(void *priv, const char *param)
 
        drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
        if (drv->priv_socket < 0) {
-               perror("socket(PF_UNIX)");
+               wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
                os_free(drv->own_socket_path);
                drv->own_socket_path = NULL;
                return -1;
@@ -682,7 +730,9 @@ static int wpa_driver_privsep_set_param(void *priv, const char *param)
        os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
        if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) <
            0) {
-               perror("bind(PF_UNIX)");
+               wpa_printf(MSG_ERROR,
+                          "privsep-set-params priv-sock: bind(PF_UNIX): %s",
+                          strerror(errno));
                close(drv->priv_socket);
                drv->priv_socket = -1;
                unlink(drv->own_socket_path);
@@ -696,7 +746,7 @@ static int wpa_driver_privsep_set_param(void *priv, const char *param)
 
        drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
        if (drv->cmd_socket < 0) {
-               perror("socket(PF_UNIX)");
+               wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
                os_free(drv->own_cmd_path);
                drv->own_cmd_path = NULL;
                return -1;
@@ -707,7 +757,9 @@ static int wpa_driver_privsep_set_param(void *priv, const char *param)
        os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path));
        if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0)
        {
-               perror("bind(PF_UNIX)");
+               wpa_printf(MSG_ERROR,
+                          "privsep-set-params cmd-sock: bind(PF_UNIX): %s",
+                          strerror(errno));
                close(drv->cmd_socket);
                drv->cmd_socket = -1;
                unlink(drv->own_cmd_path);
@@ -735,6 +787,10 @@ static int wpa_driver_privsep_get_capa(void *priv,
        res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len);
        if (res < 0 || len != sizeof(*capa))
                return -1;
+       /* For now, no support for passing extended_capa pointers */
+       capa->extended_capa = NULL;
+       capa->extended_capa_mask = NULL;
+       capa->extended_capa_len = 0;
        return 0;
 }
 
@@ -747,65 +803,36 @@ static const u8 * wpa_driver_privsep_get_mac_addr(void *priv)
 }
 
 
-static int wpa_driver_privsep_set_mode(void *priv, int mode)
+static int wpa_driver_privsep_set_country(void *priv, const char *alpha2)
 {
        struct wpa_driver_privsep_data *drv = priv;
-       wpa_printf(MSG_DEBUG, "%s mode=%d", __func__, mode);
-       return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_MODE, &mode, sizeof(mode),
-                           NULL, NULL);
+       wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2);
+       return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2,
+                           os_strlen(alpha2), NULL, NULL);
 }
 
 
 struct wpa_driver_ops wpa_driver_privsep_ops = {
        "privsep",
        "wpa_supplicant privilege separated driver",
-       wpa_driver_privsep_get_bssid,
-       wpa_driver_privsep_get_ssid,
-       wpa_driver_privsep_set_wpa,
-       wpa_driver_privsep_set_key,
-       wpa_driver_privsep_init,
-       wpa_driver_privsep_deinit,
-       wpa_driver_privsep_set_param,
-       NULL /* set_countermeasures */,
-       NULL /* set_drop_unencrypted */,
-       wpa_driver_privsep_scan,
-       NULL /*  get_scan_results */,
-       wpa_driver_privsep_deauthenticate,
-       wpa_driver_privsep_disassociate,
-       wpa_driver_privsep_associate,
-       NULL /* set_auth_alg */,
-       NULL /* add_pmkid */,
-       NULL /* remove_pmkid */,
-       NULL /* flush_pmkid */,
-       wpa_driver_privsep_get_capa,
-       NULL /* poll */,
-       NULL /* get_ifname */,
-       wpa_driver_privsep_get_mac_addr,
-       NULL /* send_eapol */,
-       NULL /* set_operstate */,
-       NULL /* mlme_setprotection */,
-       NULL /* get_hw_feature_data */,
-       NULL /* set_channel */,
-       NULL /* set_ssid */,
-       NULL /* set_bssid */,
-       NULL /* send_mlme */,
-       NULL /* mlme_add_sta */,
-       NULL /* mlme_remove_sta */,
-       NULL /* update_ft_ies */,
-       NULL /* send_ft_action */,
-       wpa_driver_privsep_get_scan_results2,
-       NULL /* set_probe_req_ie */,
-       wpa_driver_privsep_set_mode,
-       NULL /* set_country */,
-       NULL /* global_init */,
-       NULL /* global_deinit */,
-       NULL /* init2 */,
-       NULL /* get_interfaces */,
-       NULL /* scan2 */
+       .get_bssid = wpa_driver_privsep_get_bssid,
+       .get_ssid = wpa_driver_privsep_get_ssid,
+       .set_key = wpa_driver_privsep_set_key,
+       .init = wpa_driver_privsep_init,
+       .deinit = wpa_driver_privsep_deinit,
+       .set_param = wpa_driver_privsep_set_param,
+       .scan2 = wpa_driver_privsep_scan,
+       .deauthenticate = wpa_driver_privsep_deauthenticate,
+       .authenticate = wpa_driver_privsep_authenticate,
+       .associate = wpa_driver_privsep_associate,
+       .get_capa = wpa_driver_privsep_get_capa,
+       .get_mac_addr = wpa_driver_privsep_get_mac_addr,
+       .get_scan_results2 = wpa_driver_privsep_get_scan_results2,
+       .set_country = wpa_driver_privsep_set_country,
 };
 
 
-struct wpa_driver_ops *wpa_supplicant_drivers[] =
+const struct wpa_driver_ops *const wpa_drivers[] =
 {
        &wpa_driver_privsep_ops,
        NULL