diff options
Diffstat (limited to 'contrib/wpa/wpa_supplicant/ctrl_iface_unix.c')
-rw-r--r-- | contrib/wpa/wpa_supplicant/ctrl_iface_unix.c | 73 |
1 files changed, 67 insertions, 6 deletions
diff --git a/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c b/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c index 71fe7ed6bef5..639573dae75e 100644 --- a/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c +++ b/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -131,7 +131,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_supplicant *wpa_s = eloop_ctx; struct ctrl_iface_priv *priv = sock_ctx; - char buf[4096]; + char *buf; int res; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); @@ -139,11 +139,20 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, size_t reply_len = 0; int new_attached = 0; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN + 1, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); + return; + } + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); return; } buf[res] = '\0'; @@ -221,6 +230,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, } } os_free(reply_buf); + os_free(buf); if (new_attached) eapol_sm_notify_ctrl_attached(wpa_s->eapol); @@ -790,12 +800,52 @@ static int wpas_ctrl_iface_reinit(struct wpa_supplicant *wpa_s, } -void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) +static void +wpas_global_ctrl_iface_flush_queued_msg(struct wpa_global *global, + struct wpa_supplicant *wpa_s) +{ + struct ctrl_iface_global_priv *gpriv; + struct ctrl_iface_msg *msg, *prev_msg; + unsigned int count = 0; + + if (!global || !global->ctrl_iface) + return; + + gpriv = global->ctrl_iface; + dl_list_for_each_safe(msg, prev_msg, &gpriv->msg_queue, + struct ctrl_iface_msg, list) { + if (msg->wpa_s == wpa_s) { + count++; + dl_list_del(&msg->list); + os_free(msg); + } + } + + if (count) { + wpa_printf(MSG_DEBUG, + "CTRL: Dropped %u pending message(s) for interface that is being removed", + count); + } +} + + +void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s, + struct ctrl_iface_priv *priv) { struct wpa_ctrl_dst *dst, *prev; struct ctrl_iface_msg *msg, *prev_msg; struct ctrl_iface_global_priv *gpriv; + if (!priv) { + /* Control interface has not yet been initialized, so there is + * nothing to deinitialize here. However, there might be a + * pending message for this interface, so get rid of any such + * entry before completing interface removal. */ + wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s); + eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, wpa_s, NULL); + return; + } + if (priv->sock > -1) { char *fname; char *buf, *dir = NULL; @@ -867,6 +917,7 @@ free_dst: } } } + wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s); eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL); os_free(priv); } @@ -1046,18 +1097,27 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_global *global = eloop_ctx; struct ctrl_iface_global_priv *priv = sock_ctx; - char buf[4096]; + char *buf; int res; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); char *reply = NULL, *reply_buf = NULL; size_t reply_len; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN + 1, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); + return; + } + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); return; } buf[res] = '\0'; @@ -1105,6 +1165,7 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, } } os_free(reply_buf); + os_free(buf); } |