TDLS: Declare tdls_testing as extern in a header file
[mech_eap.git] / wpa_supplicant / wpa_priv.c
index 193c542..511df4f 100644 (file)
@@ -2,14 +2,8 @@
  * WPA Supplicant / privileged helper program
  * 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"
 
 #include "common.h"
 #include "eloop.h"
-#include "version.h"
+#include "common/version.h"
 #include "drivers/driver.h"
 #include "l2_packet/l2_packet.h"
-#include "privsep_commands.h"
-#include "ieee802_11_defs.h"
+#include "common/privsep_commands.h"
+#include "common/ieee802_11_defs.h"
 
 
 struct wpa_priv_interface {
@@ -35,8 +29,11 @@ struct wpa_priv_interface {
        char *sock_name;
        int fd;
 
-       struct wpa_driver_ops *driver;
+       void *ctx;
+
+       const struct wpa_driver_ops *driver;
        void *drv_priv;
+       void *drv_global_priv;
        struct sockaddr_un drv_addr;
        int wpas_registered;
 
@@ -45,6 +42,10 @@ struct wpa_priv_interface {
        struct sockaddr_un l2_addr;
 };
 
+struct wpa_priv_global {
+       struct wpa_priv_interface *interfaces;
+};
+
 
 static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
                                  struct sockaddr_un *from)
@@ -54,6 +55,10 @@ static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
                if (iface->driver->deinit)
                        iface->driver->deinit(iface->drv_priv);
                iface->drv_priv = NULL;
+               if (iface->drv_global_priv) {
+                       iface->driver->global_deinit(iface->drv_global_priv);
+                       iface->drv_global_priv = NULL;
+               }
                iface->wpas_registered = 0;
        }
 
@@ -64,10 +69,25 @@ static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
                iface->l2 = NULL;
        }
 
-       if (iface->driver->init == NULL)
+       if (iface->driver->init2) {
+               if (iface->driver->global_init) {
+                       iface->drv_global_priv =
+                               iface->driver->global_init(iface->ctx);
+                       if (!iface->drv_global_priv) {
+                               wpa_printf(MSG_INFO,
+                                          "Failed to initialize driver global context");
+                               return;
+                       }
+               } else {
+                       iface->drv_global_priv = NULL;
+               }
+               iface->drv_priv = iface->driver->init2(iface, iface->ifname,
+                                                      iface->drv_global_priv);
+       } else if (iface->driver->init) {
+               iface->drv_priv = iface->driver->init(iface, iface->ifname);
+       } else {
                return;
-
-       iface->drv_priv = iface->driver->init(iface, iface->ifname);
+       }
        if (iface->drv_priv == NULL) {
                wpa_printf(MSG_DEBUG, "Failed to initialize driver wrapper");
                return;
@@ -93,6 +113,10 @@ static void wpa_priv_cmd_unregister(struct wpa_priv_interface *iface,
                if (iface->driver->deinit)
                        iface->driver->deinit(iface->drv_priv);
                iface->drv_priv = NULL;
+               if (iface->drv_global_priv) {
+                       iface->driver->global_deinit(iface->drv_global_priv);
+                       iface->drv_global_priv = NULL;
+               }
                iface->wpas_registered = 0;
        }
 }
@@ -101,12 +125,20 @@ static void wpa_priv_cmd_unregister(struct wpa_priv_interface *iface,
 static void wpa_priv_cmd_scan(struct wpa_priv_interface *iface,
                              char *buf, size_t len)
 {
+       struct wpa_driver_scan_params params;
+
        if (iface->drv_priv == NULL)
                return;
 
-       if (iface->driver->scan)
-               iface->driver->scan(iface->drv_priv, len ? (u8 *) buf : NULL,
-                                   len);
+       os_memset(&params, 0, sizeof(params));
+       if (len) {
+               params.ssids[0].ssid = (u8 *) buf;
+               params.ssids[0].ssid_len = len;
+               params.num_ssids = 1;
+       }
+
+       if (iface->driver->scan2)
+               iface->driver->scan2(iface->drv_priv, &params);
 }
 
 
@@ -146,110 +178,12 @@ static void wpa_priv_get_scan_results2(struct wpa_priv_interface *iface,
               sizeof(*from));
 
        os_free(buf);
-       os_free(res);
-       return;
-
-fail:
-       os_free(buf);
-       os_free(res);
-       sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
-}
-
-
-static void wpa_priv_send_old_scan_results(struct wpa_priv_interface *iface,
-                                          struct sockaddr_un *from)
-{
-#define SCAN_AP_LIMIT 128
-       int i, res, val;
-       struct wpa_scan_result *results = NULL;
-       u8 *buf = NULL, *pos, *end;
-       struct wpa_scan_res nres;
-
-       results = os_malloc(SCAN_AP_LIMIT * sizeof(*results));
-       if (results == NULL)
-               goto fail;
-
-       res = iface->driver->get_scan_results(iface->drv_priv, results,
-                                             SCAN_AP_LIMIT);
-       if (res < 0 || res > SCAN_AP_LIMIT)
-               goto fail;
-
-       buf = os_malloc(60000);
-       if (buf == NULL)
-               goto fail;
-       pos = buf;
-       end = buf + 60000;
-       os_memcpy(pos, &res, sizeof(int));
-       pos += sizeof(int);
-
-       os_memset(&nres, 0, sizeof(nres));
-       for (i = 0; i < res; i++) {
-               struct wpa_scan_result *r = &results[i];
-               size_t ie_len;
-
-               ie_len = 2 + r->ssid_len + r->rsn_ie_len + r->wpa_ie_len;
-               if (r->maxrate)
-                       ie_len += 3;
-               if (r->mdie_present)
-                       ie_len += 5;
-
-               val = sizeof(nres) + ie_len;
-               if (end - pos < (int) sizeof(int) + val)
-                       break;
-               os_memcpy(pos, &val, sizeof(int));
-               pos += sizeof(int);
-
-               os_memcpy(nres.bssid, r->bssid, ETH_ALEN);
-               nres.freq = r->freq;
-               nres.caps = r->caps;
-               nres.qual = r->qual;
-               nres.noise = r->noise;
-               nres.level = r->level;
-               nres.tsf = r->tsf;
-               nres.ie_len = ie_len;
-
-               os_memcpy(pos, &nres, sizeof(nres));
-               pos += sizeof(nres);
-
-               /* SSID IE */
-               *pos++ = WLAN_EID_SSID;
-               *pos++ = r->ssid_len;
-               os_memcpy(pos, r->ssid, r->ssid_len);
-               pos += r->ssid_len;
-
-               if (r->maxrate) {
-                       /* Fake Supported Rate IE to include max rate */
-                       *pos++ = WLAN_EID_SUPP_RATES;
-                       *pos++ = 1;
-                       *pos++ = r->maxrate;
-               }
-
-               if (r->rsn_ie_len) {
-                       os_memcpy(pos, r->rsn_ie, r->rsn_ie_len);
-                       pos += r->rsn_ie_len;
-               }
-
-               if (r->mdie_present) {
-                       os_memcpy(pos, r->mdie, 5);
-                       pos += 5;
-               }
-
-               if (r->wpa_ie_len) {
-                       os_memcpy(pos, r->wpa_ie, r->wpa_ie_len);
-                       pos += r->wpa_ie_len;
-               }
-       }
-
-       sendto(iface->fd, buf, pos - buf, 0, (struct sockaddr *) from,
-              sizeof(*from));
-
-       os_free(buf);
-       os_free(results);
+       wpa_scan_results_free(res);
        return;
 
 fail:
        os_free(buf);
-       os_free(results);
+       wpa_scan_results_free(res);
        sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
 }
 
@@ -262,14 +196,64 @@ static void wpa_priv_cmd_get_scan_results(struct wpa_priv_interface *iface,
 
        if (iface->driver->get_scan_results2)
                wpa_priv_get_scan_results2(iface, from);
-       else if (iface->driver->get_scan_results)
-               wpa_priv_send_old_scan_results(iface, from);
        else
                sendto(iface->fd, "", 0, 0, (struct sockaddr *) from,
                       sizeof(*from));
 }
 
 
+static void wpa_priv_cmd_authenticate(struct wpa_priv_interface *iface,
+                                     void *buf, size_t len)
+{
+       struct wpa_driver_auth_params params;
+       struct privsep_cmd_authenticate *auth;
+       int res, i;
+
+       if (iface->drv_priv == NULL || iface->driver->authenticate == NULL)
+               return;
+
+       if (len < sizeof(*auth)) {
+               wpa_printf(MSG_DEBUG, "Invalid authentication request");
+               return;
+       }
+
+       auth = buf;
+       if (sizeof(*auth) + auth->ie_len + auth->sae_data_len > len) {
+               wpa_printf(MSG_DEBUG, "Authentication request overflow");
+               return;
+       }
+
+       os_memset(&params, 0, sizeof(params));
+       params.freq = auth->freq;
+       params.bssid = auth->bssid;
+       params.ssid = auth->ssid;
+       if (auth->ssid_len > SSID_MAX_LEN)
+               return;
+       params.ssid_len = auth->ssid_len;
+       params.auth_alg = auth->auth_alg;
+       for (i = 0; i < 4; i++) {
+               if (auth->wep_key_len[i]) {
+                       params.wep_key[i] = auth->wep_key[i];
+                       params.wep_key_len[i] = auth->wep_key_len[i];
+               }
+       }
+       params.wep_tx_keyidx = auth->wep_tx_keyidx;
+       params.local_state_change = auth->local_state_change;
+       params.p2p = auth->p2p;
+       if (auth->ie_len) {
+               params.ie = (u8 *) (auth + 1);
+               params.ie_len = auth->ie_len;
+       }
+       if (auth->sae_data_len) {
+               params.sae_data = ((u8 *) (auth + 1)) + auth->ie_len;
+               params.sae_data_len = auth->sae_data_len;
+       }
+
+       res = iface->driver->authenticate(iface->drv_priv, &params);
+       wpa_printf(MSG_DEBUG, "drv->authenticate: res=%d", res);
+}
+
+
 static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface,
                                   void *buf, size_t len)
 {
@@ -297,10 +281,12 @@ static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface,
        if (bssid[0] | bssid[1] | bssid[2] | bssid[3] | bssid[4] | bssid[5])
                params.bssid = bssid;
        params.ssid = assoc->ssid;
-       if (assoc->ssid_len > 32)
+       if (assoc->ssid_len > SSID_MAX_LEN)
                return;
        params.ssid_len = assoc->ssid_len;
-       params.freq = assoc->freq;
+       params.freq.mode = assoc->hwmode;
+       params.freq.freq = assoc->freq;
+       params.freq.channel = assoc->channel;
        if (assoc->wpa_ie_len) {
                params.wpa_ie = (u8 *) (assoc + 1);
                params.wpa_ie_len = assoc->wpa_ie_len;
@@ -340,7 +326,7 @@ fail:
 static void wpa_priv_cmd_get_ssid(struct wpa_priv_interface *iface,
                                  struct sockaddr_un *from)
 {
-       u8 ssid[sizeof(int) + 32];
+       u8 ssid[sizeof(int) + SSID_MAX_LEN];
        int res;
 
        if (iface->drv_priv == NULL)
@@ -350,7 +336,7 @@ static void wpa_priv_cmd_get_ssid(struct wpa_priv_interface *iface,
                goto fail;
 
        res = iface->driver->get_ssid(iface->drv_priv, &ssid[sizeof(int)]);
-       if (res < 0 || res > 32)
+       if (res < 0 || res > SSID_MAX_LEN)
                goto fail;
        os_memcpy(ssid, &res, sizeof(int));
 
@@ -379,7 +365,8 @@ static void wpa_priv_cmd_set_key(struct wpa_priv_interface *iface,
 
        params = buf;
 
-       res = iface->driver->set_key(iface->drv_priv, params->alg,
+       res = iface->driver->set_key(iface->ifname, iface->drv_priv,
+                                    params->alg,
                                     params->addr, params->key_idx,
                                     params->set_tx,
                                     params->seq_len ? params->seq : NULL,
@@ -402,6 +389,10 @@ static void wpa_priv_cmd_get_capa(struct wpa_priv_interface *iface,
            iface->driver->get_capa(iface->drv_priv, &capa) < 0)
                goto fail;
 
+       /* For now, no support for passing extended_capa pointers */
+       capa.extended_capa = NULL;
+       capa.extended_capa_mask = NULL;
+       capa.extended_capa_len = 0;
        sendto(iface->fd, &capa, sizeof(capa), 0, (struct sockaddr *) from,
               sizeof(*from));
        return;
@@ -430,7 +421,7 @@ static void wpa_priv_l2_rx(void *ctx, const u8 *src_addr, const u8 *buf,
        msg.msg_namelen = sizeof(iface->l2_addr);
 
        if (sendmsg(iface->fd, &msg, 0) < 0) {
-               perror("sendmsg(l2 rx)");
+               wpa_printf(MSG_ERROR, "sendmsg(l2 rx): %s", strerror(errno));
        }
 }
 
@@ -451,7 +442,8 @@ static void wpa_priv_cmd_l2_register(struct wpa_priv_interface *iface,
        }
 
        proto = reg_cmd[0];
-       if (proto != ETH_P_EAPOL && proto != ETH_P_RSN_PREAUTH) {
+       if (proto != ETH_P_EAPOL && proto != ETH_P_RSN_PREAUTH &&
+           proto != ETH_P_80211_ENCAP) {
                wpa_printf(MSG_DEBUG, "Refused l2_packet connection for "
                           "ethertype 0x%x", proto);
                return;
@@ -538,17 +530,6 @@ static void wpa_priv_cmd_l2_send(struct wpa_priv_interface *iface,
 }
 
 
-static void wpa_priv_cmd_set_mode(struct wpa_priv_interface *iface,
-                                 void *buf, size_t len)
-{
-       if (iface->drv_priv == NULL || iface->driver->set_mode == NULL ||
-           len != sizeof(int))
-               return;
-
-       iface->driver->set_mode(iface->drv_priv, *((int *) buf));
-}
-
-
 static void wpa_priv_cmd_set_country(struct wpa_priv_interface *iface,
                                     char *buf)
 {
@@ -573,7 +554,7 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
        res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &from,
                       &fromlen);
        if (res < 0) {
-               perror("recvfrom");
+               wpa_printf(MSG_ERROR, "recvfrom: %s", strerror(errno));
                return;
        }
 
@@ -628,9 +609,6 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
        case PRIVSEP_CMD_L2_SEND:
                wpa_priv_cmd_l2_send(iface, &from, cmd_buf, cmd_len);
                break;
-       case PRIVSEP_CMD_SET_MODE:
-               wpa_priv_cmd_set_mode(iface, cmd_buf, cmd_len);
-               break;
        case PRIVSEP_CMD_SET_COUNTRY:
                pos = cmd_buf;
                if (pos + cmd_len >= buf + sizeof(buf))
@@ -638,6 +616,9 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
                pos[cmd_len] = '\0';
                wpa_priv_cmd_set_country(iface, pos);
                break;
+       case PRIVSEP_CMD_AUTHENTICATE:
+               wpa_priv_cmd_authenticate(iface, cmd_buf, cmd_len);
+               break;
        }
 }
 
@@ -663,10 +644,8 @@ static void wpa_priv_interface_deinit(struct wpa_priv_interface *iface)
 }
 
 
-extern struct wpa_driver_ops *wpa_drivers[];
-
 static struct wpa_priv_interface *
-wpa_priv_interface_init(const char *dir, const char *params)
+wpa_priv_interface_init(void *ctx, const char *dir, const char *params)
 {
        struct wpa_priv_interface *iface;
        char *pos;
@@ -682,15 +661,14 @@ wpa_priv_interface_init(const char *dir, const char *params)
        if (iface == NULL)
                return NULL;
        iface->fd = -1;
+       iface->ctx = ctx;
 
        len = pos - params;
-       iface->driver_name = os_malloc(len + 1);
+       iface->driver_name = dup_binstr(params, len);
        if (iface->driver_name == NULL) {
                wpa_priv_interface_deinit(iface);
                return NULL;
        }
-       os_memcpy(iface->driver_name, params, len);
-       iface->driver_name[len] = '\0';
 
        for (i = 0; wpa_drivers[i]; i++) {
                if (os_strcmp(iface->driver_name,
@@ -728,7 +706,7 @@ wpa_priv_interface_init(const char *dir, const char *params)
 
        iface->fd = socket(PF_UNIX, SOCK_DGRAM, 0);
        if (iface->fd < 0) {
-               perror("socket(PF_UNIX)");
+               wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
                wpa_priv_interface_deinit(iface);
                return NULL;
        }
@@ -746,15 +724,16 @@ wpa_priv_interface_init(const char *dir, const char *params)
                                   "allow connections - assuming it was "
                                   "leftover from forced program termination");
                        if (unlink(iface->sock_name) < 0) {
-                               perror("unlink[ctrl_iface]");
-                               wpa_printf(MSG_ERROR, "Could not unlink "
-                                          "existing ctrl_iface socket '%s'",
-                                          iface->sock_name);
+                               wpa_printf(MSG_ERROR,
+                                          "Could not unlink existing ctrl_iface socket '%s': %s",
+                                          iface->sock_name, strerror(errno));
                                goto fail;
                        }
                        if (bind(iface->fd, (struct sockaddr *) &addr,
                                 sizeof(addr)) < 0) {
-                               perror("bind(PF_UNIX)");
+                               wpa_printf(MSG_ERROR,
+                                          "wpa-priv-iface-init: bind(PF_UNIX): %s",
+                                          strerror(errno));
                                goto fail;
                        }
                        wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
@@ -769,7 +748,7 @@ wpa_priv_interface_init(const char *dir, const char *params)
        }
 
        if (chmod(iface->sock_name, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
-               perror("chmod");
+               wpa_printf(MSG_ERROR, "chmod: %s", strerror(errno));
                goto fail;
        }
 
@@ -801,7 +780,8 @@ static int wpa_priv_send_event(struct wpa_priv_interface *iface, int event,
        msg.msg_namelen = sizeof(iface->drv_addr);
 
        if (sendmsg(iface->fd, &msg, 0) < 0) {
-               perror("sendmsg(wpas_socket)");
+               wpa_printf(MSG_ERROR, "sendmsg(wpas_socket): %s",
+                          strerror(errno));
                return -1;
        }
 
@@ -809,6 +789,36 @@ static int wpa_priv_send_event(struct wpa_priv_interface *iface, int event,
 }
 
 
+static void wpa_priv_send_auth(struct wpa_priv_interface *iface,
+                              union wpa_event_data *data)
+{
+       size_t buflen = sizeof(struct privsep_event_auth) + data->auth.ies_len;
+       struct privsep_event_auth *auth;
+       u8 *buf, *pos;
+
+       buf = os_malloc(buflen);
+       if (buf == NULL)
+               return;
+
+       auth = (struct privsep_event_auth *) buf;
+       pos = (u8 *) (auth + 1);
+
+       os_memcpy(auth->peer, data->auth.peer, ETH_ALEN);
+       os_memcpy(auth->bssid, data->auth.bssid, ETH_ALEN);
+       auth->auth_type = data->auth.auth_type;
+       auth->auth_transaction = data->auth.auth_transaction;
+       auth->status_code = data->auth.status_code;
+       if (data->auth.ies) {
+               os_memcpy(pos, data->auth.ies, data->auth.ies_len);
+               auth->ies_len = data->auth.ies_len;
+       }
+
+       wpa_priv_send_event(iface, PRIVSEP_EVENT_AUTH, buf, buflen);
+
+       os_free(buf);
+}
+
+
 static void wpa_priv_send_assoc(struct wpa_priv_interface *iface, int event,
                                union wpa_event_data *data)
 {
@@ -930,7 +940,7 @@ static void wpa_priv_send_ft_response(struct wpa_priv_interface *iface,
 }
 
 
-void wpa_supplicant_event(void *ctx, wpa_event_type event,
+void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                          union wpa_event_data *data)
 {
        struct wpa_priv_interface *iface = ctx;
@@ -962,6 +972,10 @@ void wpa_supplicant_event(void *ctx, wpa_event_type event,
                                    &data->michael_mic_failure.unicast,
                                    sizeof(int));
                break;
+       case EVENT_SCAN_STARTED:
+               wpa_priv_send_event(iface, PRIVSEP_EVENT_SCAN_STARTED, NULL,
+                                   0);
+               break;
        case EVENT_SCAN_RESULTS:
                wpa_priv_send_event(iface, PRIVSEP_EVENT_SCAN_RESULTS, NULL,
                                    0);
@@ -985,55 +999,61 @@ void wpa_supplicant_event(void *ctx, wpa_event_type event,
        case EVENT_FT_RESPONSE:
                wpa_priv_send_ft_response(iface, data);
                break;
+       case EVENT_AUTH:
+               wpa_priv_send_auth(iface, data);
+               break;
        default:
-               wpa_printf(MSG_DEBUG, "Unsupported driver event %d - TODO",
-                          event);
+               wpa_printf(MSG_DEBUG, "Unsupported driver event %d (%s) - TODO",
+                          event, event_to_string(event));
                break;
        }
 }
 
 
-void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
-                            const u8 *buf, size_t len)
+void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
+                                union wpa_event_data *data)
 {
-       struct wpa_priv_interface *iface = ctx;
-       struct msghdr msg;
-       struct iovec io[3];
-       int event = PRIVSEP_EVENT_RX_EAPOL;
-
-       wpa_printf(MSG_DEBUG, "RX EAPOL from driver");
-       io[0].iov_base = &event;
-       io[0].iov_len = sizeof(event);
-       io[1].iov_base = (u8 *) src_addr;
-       io[1].iov_len = ETH_ALEN;
-       io[2].iov_base = (u8 *) buf;
-       io[2].iov_len = len;
+       struct wpa_priv_global *global = ctx;
+       struct wpa_priv_interface *iface;
 
-       os_memset(&msg, 0, sizeof(msg));
-       msg.msg_iov = io;
-       msg.msg_iovlen = 3;
-       msg.msg_name = &iface->drv_addr;
-       msg.msg_namelen = sizeof(iface->drv_addr);
+       if (event != EVENT_INTERFACE_STATUS)
+               return;
 
-       if (sendmsg(iface->fd, &msg, 0) < 0)
-               perror("sendmsg(wpas_socket)");
+       for (iface = global->interfaces; iface; iface = iface->next) {
+               if (os_strcmp(iface->ifname, data->interface_status.ifname) ==
+                   0)
+                       break;
+       }
+       if (iface && iface->driver->get_ifindex) {
+               unsigned int ifindex;
+
+               ifindex = iface->driver->get_ifindex(iface->drv_priv);
+               if (ifindex != data->interface_status.ifindex) {
+                       wpa_printf(MSG_DEBUG,
+                                  "%s: interface status ifindex %d mismatch (%d)",
+                                  iface->ifname, ifindex,
+                                  data->interface_status.ifindex);
+                       return;
+               }
+       }
+       if (iface)
+               wpa_supplicant_event(iface, event, data);
 }
 
 
-#ifdef CONFIG_CLIENT_MLME
-void wpa_supplicant_sta_rx(void *ctx, const u8 *buf, size_t len,
-                          struct ieee80211_rx_status *rx_status)
+void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
+                            const u8 *buf, size_t len)
 {
        struct wpa_priv_interface *iface = ctx;
        struct msghdr msg;
        struct iovec io[3];
-       int event = PRIVSEP_EVENT_STA_RX;
+       int event = PRIVSEP_EVENT_RX_EAPOL;
 
-       wpa_printf(MSG_DEBUG, "STA RX from driver");
+       wpa_printf(MSG_DEBUG, "RX EAPOL from driver");
        io[0].iov_base = &event;
        io[0].iov_len = sizeof(event);
-       io[1].iov_base = (u8 *) rx_status;
-       io[1].iov_len = sizeof(*rx_status);
+       io[1].iov_base = (u8 *) src_addr;
+       io[1].iov_len = ETH_ALEN;
        io[2].iov_base = (u8 *) buf;
        io[2].iov_len = len;
 
@@ -1044,12 +1064,12 @@ void wpa_supplicant_sta_rx(void *ctx, const u8 *buf, size_t len,
        msg.msg_namelen = sizeof(iface->drv_addr);
 
        if (sendmsg(iface->fd, &msg, 0) < 0)
-               perror("sendmsg(wpas_socket)");
+               wpa_printf(MSG_ERROR, "sendmsg(wpas_socket): %s",
+                          strerror(errno));
 }
-#endif /* CONFIG_CLIENT_MLME */
 
 
-static void wpa_priv_terminate(int sig, void *eloop_ctx, void *signal_ctx)
+static void wpa_priv_terminate(int sig, void *signal_ctx)
 {
        wpa_printf(MSG_DEBUG, "wpa_priv termination requested");
        eloop_terminate();
@@ -1079,17 +1099,16 @@ static void wpa_priv_fd_workaround(void)
 static void usage(void)
 {
        printf("wpa_priv v" VERSION_STR "\n"
-              "Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi> and "
+              "Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi> and "
               "contributors\n"
               "\n"
               "usage:\n"
-              "  wpa_priv [-Bdd] [-P<pid file>] <driver:ifname> "
-              "[driver:ifname ...]\n");
+              "  wpa_priv [-Bdd] [-c<ctrl dir>] [-P<pid file>] "
+              "<driver:ifname> \\\n"
+              "           [driver:ifname ...]\n");
 }
 
 
-extern int wpa_debug_level;
-
 int main(int argc, char *argv[])
 {
        int c, i;
@@ -1097,13 +1116,17 @@ int main(int argc, char *argv[])
        char *pid_file = NULL;
        int daemonize = 0;
        char *ctrl_dir = "/var/run/wpa_priv";
-       struct wpa_priv_interface *interfaces = NULL, *iface;
+       struct wpa_priv_global global;
+       struct wpa_priv_interface *iface;
 
        if (os_program_init())
                return -1;
 
        wpa_priv_fd_workaround();
 
+       os_memset(&global, 0, sizeof(global));
+       global.interfaces = NULL;
+
        for (;;) {
                c = getopt(argc, argv, "Bc:dP:");
                if (c < 0)
@@ -1123,32 +1146,32 @@ int main(int argc, char *argv[])
                        break;
                default:
                        usage();
-                       goto out;
+                       goto out2;
                }
        }
 
        if (optind >= argc) {
                usage();
-               goto out;
+               goto out2;
        }
 
        wpa_printf(MSG_DEBUG, "wpa_priv control directory: '%s'", ctrl_dir);
 
-       if (eloop_init(NULL)) {
+       if (eloop_init()) {
                wpa_printf(MSG_ERROR, "Failed to initialize event loop");
-               goto out;
+               goto out2;
        }
 
        for (i = optind; i < argc; i++) {
                wpa_printf(MSG_DEBUG, "Adding driver:interface %s", argv[i]);
-               iface = wpa_priv_interface_init(ctrl_dir, argv[i]);
+               iface = wpa_priv_interface_init(&global, ctrl_dir, argv[i]);
                if (iface == NULL)
                        goto out;
-               iface->next = interfaces;
-               interfaces = iface;
+               iface->next = global.interfaces;
+               global.interfaces = iface;
        }
 
-       if (daemonize && os_daemonize(pid_file))
+       if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
                goto out;
 
        eloop_register_signal_terminate(wpa_priv_terminate, NULL);
@@ -1157,7 +1180,7 @@ int main(int argc, char *argv[])
        ret = 0;
 
 out:
-       iface = interfaces;
+       iface = global.interfaces;
        while (iface) {
                struct wpa_priv_interface *prev = iface;
                iface = iface->next;
@@ -1166,7 +1189,9 @@ out:
 
        eloop_destroy();
 
-       os_daemonize_terminate(pid_file);
+out2:
+       if (daemonize)
+               os_daemonize_terminate(pid_file);
        os_free(pid_file);
        os_program_deinit();