X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=wpa_supplicant%2Fwpa_priv.c;h=511df4f18148e4d495da9d89859b8028c6d53a50;hp=0cc9fd5f44188a073935078009d5e53983255dff;hb=6013bbe04f138f7d5d750a3e1939732cbde0426a;hpb=c51218372f6ee40c3830b4cb06fa58752e546d06 diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c index 0cc9fd5..511df4f 100644 --- a/wpa_supplicant/wpa_priv.c +++ b/wpa_supplicant/wpa_priv.c @@ -2,14 +2,8 @@ * WPA Supplicant / privileged helper program * Copyright (c) 2007-2009, Jouni Malinen * - * 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" @@ -21,19 +15,11 @@ #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" - -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL 0x888e -#endif - -#ifndef ETH_P_RSN_PREAUTH -#define ETH_P_RSN_PREAUTH 0x88c7 -#endif +#include "common/privsep_commands.h" +#include "common/ieee802_11_defs.h" struct wpa_priv_interface { @@ -43,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; @@ -53,17 +42,23 @@ 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) { if (iface->drv_priv) { wpa_printf(MSG_DEBUG, "Cleaning up forgotten driver instance"); - if (iface->driver->set_wpa) - iface->driver->set_wpa(iface->drv_priv, 0); 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; } @@ -74,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,9 +103,6 @@ static void wpa_priv_cmd_register(struct wpa_priv_interface *iface, iface->driver->set_param(iface->drv_priv, NULL) < 0) { wpa_printf(MSG_ERROR, "Driver interface rejected param"); } - - if (iface->driver->set_wpa) - iface->driver->set_wpa(iface->drv_priv, 1); } @@ -103,36 +110,35 @@ static void wpa_priv_cmd_unregister(struct wpa_priv_interface *iface, struct sockaddr_un *from) { if (iface->drv_priv) { - if (iface->driver->set_wpa) - iface->driver->set_wpa(iface->drv_priv, 0); 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; } } -static void wpa_priv_cmd_set_wpa(struct wpa_priv_interface *iface, - char *buf, size_t len) -{ - if (iface->drv_priv == NULL || len != sizeof(int)) - return; - - if (iface->driver->set_wpa) - iface->driver->set_wpa(iface->drv_priv, *((int *) buf)); -} - - 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(¶ms, 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, ¶ms); } @@ -172,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)); } @@ -288,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(¶ms, 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, ¶ms); + 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) { @@ -323,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; @@ -366,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) @@ -376,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)); @@ -405,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, @@ -428,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; @@ -456,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)); } } @@ -477,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; @@ -564,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) { @@ -599,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; } @@ -621,9 +576,6 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx) case PRIVSEP_CMD_UNREGISTER: wpa_priv_cmd_unregister(iface, &from); break; - case PRIVSEP_CMD_SET_WPA: - wpa_priv_cmd_set_wpa(iface, cmd_buf, cmd_len); - break; case PRIVSEP_CMD_SCAN: wpa_priv_cmd_scan(iface, cmd_buf, cmd_len); break; @@ -657,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)) @@ -667,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; } } @@ -692,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; @@ -711,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, @@ -757,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; } @@ -775,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 " @@ -798,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; } @@ -830,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; } @@ -838,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) { @@ -959,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; @@ -991,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); @@ -1014,72 +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; - - 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 (sendmsg(iface->fd, &msg, 0) < 0) - perror("sendmsg(wpas_socket)"); -} - - -#ifdef CONFIG_CLIENT_MLME -void wpa_supplicant_sta_free_hw_features(struct hostapd_hw_modes *hw_features, - size_t num_hw_features) -{ - size_t i; + struct wpa_priv_global *global = ctx; + struct wpa_priv_interface *iface; - if (hw_features == NULL) + if (event != EVENT_INTERFACE_STATUS) return; - for (i = 0; i < num_hw_features; i++) { - os_free(hw_features[i].channels); - os_free(hw_features[i].rates); + for (iface = global->interfaces; iface; iface = iface->next) { + if (os_strcmp(iface->ifname, data->interface_status.ifname) == + 0) + break; } - - os_free(hw_features); + 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); } -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; @@ -1090,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(); @@ -1125,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 and " + "Copyright (c) 2007-2016, Jouni Malinen and " "contributors\n" "\n" "usage:\n" - " wpa_priv [-Bdd] [-P] " - "[driver:ifname ...]\n"); + " wpa_priv [-Bdd] [-c] [-P] " + " \\\n" + " [driver:ifname ...]\n"); } -extern int wpa_debug_level; - int main(int argc, char *argv[]) { int c, i; @@ -1143,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) @@ -1169,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); @@ -1203,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; @@ -1212,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();