1845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/* 2845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * WPA Supplicant / UDP socket -based control interface 3845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> 4845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 5845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This program is free software; you can redistribute it and/or modify 6845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * it under the terms of the GNU General Public License version 2 as 7845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * published by the Free Software Foundation. 8845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 9845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Alternatively, this software may be distributed under the terms of BSD 10845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * license. 11845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 12845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * See README and COPYING for more details. 13845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 14845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 15845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "includes.h" 16845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 17845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "common.h" 18845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "eloop.h" 19845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "config.h" 20845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "eapol_sm.h" 21845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "wpa_supplicant_i.h" 22845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "ctrl_iface.h" 23845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "wpa_ctrl.h" 24845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 25845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 26845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#define COOKIE_LEN 8 27845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 28845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/* Per-interface ctrl_iface */ 29845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 30845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 31845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * struct wpa_ctrl_dst - Internal data structure of control interface monitors 32845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 33845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This structure is used to store information about registered control 34845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * interface monitors into struct wpa_supplicant. This data is private to 35845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * ctrl_iface_udp.c and should not be touched directly from other files. 36845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 37845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct wpa_ctrl_dst { 38845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_ctrl_dst *next; 39845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct sockaddr_in addr; 40845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project socklen_t addrlen; 41845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int debug_level; 42845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int errors; 43845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}; 44845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 45845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 46845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct ctrl_iface_priv { 47845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_supplicant *wpa_s; 48845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int sock; 49845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_ctrl_dst *ctrl_dst; 50845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project u8 cookie[COOKIE_LEN]; 51845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}; 52845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 53845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 54845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 55845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int level, const char *buf, 56845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t len); 57845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 58845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 59845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv, 60845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct sockaddr_in *from, 61845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project socklen_t fromlen) 62845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 63845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_ctrl_dst *dst; 64845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 65845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst = os_zalloc(sizeof(*dst)); 66845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (dst == NULL) 67845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 68845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcpy(&dst->addr, from, sizeof(struct sockaddr_in)); 69845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst->addrlen = fromlen; 70845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst->debug_level = MSG_INFO; 71845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst->next = priv->ctrl_dst; 72845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->ctrl_dst = dst; 73845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d", 74845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project inet_ntoa(from->sin_addr), ntohs(from->sin_port)); 75845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 76845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 77845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 78845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 79845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv, 80845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct sockaddr_in *from, 81845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project socklen_t fromlen) 82845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 83845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_ctrl_dst *dst, *prev = NULL; 84845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 85845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst = priv->ctrl_dst; 86845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (dst) { 87845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && 88845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project from->sin_port == dst->addr.sin_port) { 89845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (prev == NULL) 90845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->ctrl_dst = dst->next; 91845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project else 92845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project prev->next = dst->next; 93845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(dst); 94845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached " 95845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "%s:%d", inet_ntoa(from->sin_addr), 96845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ntohs(from->sin_port)); 97845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 98845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 99845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project prev = dst; 100845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst = dst->next; 101845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 102845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 103845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 104845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 105845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 106845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, 107845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct sockaddr_in *from, 108845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project socklen_t fromlen, 109845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char *level) 110845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 111845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_ctrl_dst *dst; 112845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 113845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 114845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 115845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst = priv->ctrl_dst; 116845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (dst) { 117845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && 118845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project from->sin_port == dst->addr.sin_port) { 119845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor " 120845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "level %s:%d", inet_ntoa(from->sin_addr), 121845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ntohs(from->sin_port)); 122845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst->debug_level = atoi(level); 123845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 124845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 125845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst = dst->next; 126845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 127845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 128845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 129845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 130845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 131845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 132845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic char * 133845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv, 134845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t *reply_len) 135845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 136845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char *reply; 137845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply = os_malloc(7 + 2 * COOKIE_LEN + 1); 138845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (reply == NULL) { 139845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reply_len = 1; 140845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 141845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 142845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 143845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcpy(reply, "COOKIE=", 7); 144845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 145845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->cookie, COOKIE_LEN); 146845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 147845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reply_len = 7 + 2 * COOKIE_LEN; 148845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return reply; 149845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 150845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 151845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 152845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, 153845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project void *sock_ctx) 154845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 155845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_supplicant *wpa_s = eloop_ctx; 156845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct ctrl_iface_priv *priv = sock_ctx; 157845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char buf[256], *pos; 158845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int res; 159845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct sockaddr_in from; 160845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project socklen_t fromlen = sizeof(from); 161845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char *reply = NULL; 162845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t reply_len = 0; 163845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int new_attached = 0; 164845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project u8 cookie[COOKIE_LEN]; 165845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 166845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 167845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (struct sockaddr *) &from, &fromlen); 168845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res < 0) { 169845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project perror("recvfrom(ctrl_iface)"); 170845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 171845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 172845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 173845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 174845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * The OS networking stack is expected to drop this kind of 175845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * frames since the socket is bound to only localhost address. 176845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Just in case, drop the frame if it is coming from any other 177845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * address. 178845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 179845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 180845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "source %s", inet_ntoa(from.sin_addr)); 181845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 182845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 183845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project buf[res] = '\0'; 184845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 185845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (os_strcmp(buf, "GET_COOKIE") == 0) { 186845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len); 187845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto done; 188845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 189845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 190845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 191845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Require that the client includes a prefix with the 'cookie' value 192845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * fetched with GET_COOKIE command. This is used to verify that the 193845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * client has access to a bidirectional link over UDP in order to 194845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * avoid attacks using forged localhost IP address even if the OS does 195845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * not block such frames from remote destinations. 196845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 197845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (os_strncmp(buf, "COOKIE=", 7) != 0) { 198845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 199845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "drop request"); 200845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 201845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 202845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 203845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 204845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 205845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "request - drop request"); 206845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 207845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 208845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 209845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 210845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 211845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "drop request"); 212845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 213845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 214845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 215845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = buf + 7 + 2 * COOKIE_LEN; 216845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (*pos == ' ') 217845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos++; 218845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 219845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (os_strcmp(pos, "ATTACH") == 0) { 220845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) 221845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply_len = 1; 222845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project else { 223845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project new_attached = 1; 224845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply_len = 2; 225845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 226845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } else if (os_strcmp(pos, "DETACH") == 0) { 227845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) 228845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply_len = 1; 229845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project else 230845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply_len = 2; 231845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } else if (os_strncmp(pos, "LEVEL ", 6) == 0) { 232845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 233845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos + 6)) 234845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply_len = 1; 235845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project else 236845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply_len = 2; 237845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } else { 238845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos, 239845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &reply_len); 240845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 241845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 242845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project done: 243845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (reply) { 244845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 245845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fromlen); 246845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(reply); 247845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } else if (reply_len == 1) { 248845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 249845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fromlen); 250845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } else if (reply_len == 2) { 251845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 252845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fromlen); 253845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 254845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 255845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (new_attached) 256845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project eapol_sm_notify_ctrl_attached(wpa_s->eapol); 257845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 258845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 259845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 260845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 261845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const char *txt, size_t len) 262845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 263845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_supplicant *wpa_s = ctx; 264845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) 265845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 266845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); 267845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 268845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 269845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 270845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct ctrl_iface_priv * 271845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 272845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 273845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct ctrl_iface_priv *priv; 274845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct sockaddr_in addr; 275845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 276845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv = os_zalloc(sizeof(*priv)); 277845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv == NULL) 278845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 279845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->wpa_s = wpa_s; 280845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->sock = -1; 281845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_get_random(priv->cookie, COOKIE_LEN); 282845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 283845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (wpa_s->conf->ctrl_interface == NULL) 284845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return priv; 285845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 286845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->sock = socket(PF_INET, SOCK_DGRAM, 0); 287845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv->sock < 0) { 288845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project perror("socket(PF_INET)"); 289845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto fail; 290845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 291845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 292845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memset(&addr, 0, sizeof(addr)); 293845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project addr.sin_family = AF_INET; 294845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project addr.sin_addr.s_addr = htonl((127 << 24) | 1); 295845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project addr.sin_port = htons(WPA_CTRL_IFACE_PORT); 296845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 297845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project perror("bind(AF_INET)"); 298845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto fail; 299845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 300845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 301845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 302845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_s, priv); 303845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 304845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 305845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return priv; 306845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 307845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectfail: 308845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv->sock >= 0) 309845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project close(priv->sock); 310845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(priv); 311845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 312845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 313845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 314845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 315845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 316845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 317845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_ctrl_dst *dst, *prev; 318845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 319845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv->sock > -1) { 320845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project eloop_unregister_read_sock(priv->sock); 321845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv->ctrl_dst) { 322845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 323845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Wait a second before closing the control socket if 324845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * there are any attached monitors in order to allow 325845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * them to receive any pending messages. 326845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 327845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 328845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "monitors to receive messages"); 329845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_sleep(1, 0); 330845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 331845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project close(priv->sock); 332845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->sock = -1; 333845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 334845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 335845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst = priv->ctrl_dst; 336845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (dst) { 337845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project prev = dst; 338845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst = dst->next; 339845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(prev); 340845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 341845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(priv); 342845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 343845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 344845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 345845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 346845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int level, const char *buf, 347845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t len) 348845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 349845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_ctrl_dst *dst, *next; 350845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char levelstr[10]; 351845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int idx; 352845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char *sbuf; 353845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int llen; 354845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 355845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst = priv->ctrl_dst; 356845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv->sock < 0 || dst == NULL) 357845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 358845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 359845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 360845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 361845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project llen = os_strlen(levelstr); 362845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project sbuf = os_malloc(llen + len); 363845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (sbuf == NULL) 364845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 365845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 366845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcpy(sbuf, levelstr, llen); 367845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcpy(sbuf + llen, buf, len); 368845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 369845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project idx = 0; 370845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (dst) { 371845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project next = dst->next; 372845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (level >= dst->debug_level) { 373845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", 374845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project inet_ntoa(dst->addr.sin_addr), 375845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ntohs(dst->addr.sin_port)); 376845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (sendto(priv->sock, sbuf, llen + len, 0, 377845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (struct sockaddr *) &dst->addr, 378845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project sizeof(dst->addr)) < 0) { 379845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project perror("sendto(CTRL_IFACE monitor)"); 380845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst->errors++; 381845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (dst->errors > 10) { 382845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_supplicant_ctrl_iface_detach( 383845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv, &dst->addr, 384845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst->addrlen); 385845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 386845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } else 387845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst->errors = 0; 388845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 389845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project idx++; 390845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project dst = next; 391845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 392845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(sbuf); 393845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 394845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 395845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 396845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 397845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 398845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor", 399845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->wpa_s->ifname); 400845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project eloop_wait_for_read_sock(priv->sock); 401845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 402845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 403845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 404845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/* Global ctrl_iface */ 405845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 406845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct ctrl_iface_global_priv { 407845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int sock; 408845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project u8 cookie[COOKIE_LEN]; 409845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}; 410845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 411845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 412845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic char * 413845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv, 414845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t *reply_len) 415845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 416845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char *reply; 417845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply = os_malloc(7 + 2 * COOKIE_LEN + 1); 418845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (reply == NULL) { 419845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reply_len = 1; 420845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 421845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 422845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 423845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcpy(reply, "COOKIE=", 7); 424845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 425845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->cookie, COOKIE_LEN); 426845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 427845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reply_len = 7 + 2 * COOKIE_LEN; 428845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return reply; 429845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 430845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 431845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 432845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 433845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project void *sock_ctx) 434845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 435845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct wpa_global *global = eloop_ctx; 436845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct ctrl_iface_global_priv *priv = sock_ctx; 437845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char buf[256], *pos; 438845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int res; 439845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct sockaddr_in from; 440845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project socklen_t fromlen = sizeof(from); 441845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char *reply; 442845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t reply_len; 443845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project u8 cookie[COOKIE_LEN]; 444845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 445845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 446845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (struct sockaddr *) &from, &fromlen); 447845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res < 0) { 448845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project perror("recvfrom(ctrl_iface)"); 449845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 450845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 451845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 452845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 453845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * The OS networking stack is expected to drop this kind of 454845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * frames since the socket is bound to only localhost address. 455845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Just in case, drop the frame if it is coming from any other 456845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * address. 457845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 458845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 459845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "source %s", inet_ntoa(from.sin_addr)); 460845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 461845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 462845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project buf[res] = '\0'; 463845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 464845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (os_strcmp(buf, "GET_COOKIE") == 0) { 465845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply = wpa_supplicant_global_get_cookie(priv, &reply_len); 466845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto done; 467845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 468845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 469845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (os_strncmp(buf, "COOKIE=", 7) != 0) { 470845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 471845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "drop request"); 472845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 473845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 474845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 475845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 476845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 477845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "request - drop request"); 478845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 479845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 480845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 481845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 482845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 483845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "drop request"); 484845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 485845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 486845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 487845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = buf + 7 + 2 * COOKIE_LEN; 488845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (*pos == ' ') 489845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos++; 490845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 491845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project reply = wpa_supplicant_global_ctrl_iface_process(global, pos, 492845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &reply_len); 493845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 494845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project done: 495845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (reply) { 496845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 497845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fromlen); 498845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(reply); 499845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } else if (reply_len) { 500845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 501845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fromlen); 502845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 503845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 504845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 505845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 506845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct ctrl_iface_global_priv * 507845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 508845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 509845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct ctrl_iface_global_priv *priv; 510845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct sockaddr_in addr; 511845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 512845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv = os_zalloc(sizeof(*priv)); 513845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv == NULL) 514845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 515845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->sock = -1; 516845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_get_random(priv->cookie, COOKIE_LEN); 517845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 518845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (global->params.ctrl_interface == NULL) 519845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return priv; 520845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 521845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "Global control interface '%s'", 522845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project global->params.ctrl_interface); 523845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 524845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project priv->sock = socket(PF_INET, SOCK_DGRAM, 0); 525845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv->sock < 0) { 526845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project perror("socket(PF_INET)"); 527845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto fail; 528845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 529845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 530845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memset(&addr, 0, sizeof(addr)); 531845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project addr.sin_family = AF_INET; 532845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project addr.sin_addr.s_addr = htonl((127 << 24) | 1); 533845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project addr.sin_port = htons(WPA_GLOBAL_CTRL_IFACE_PORT); 534845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 535845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project perror("bind(AF_INET)"); 536845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto fail; 537845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 538845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 539845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project eloop_register_read_sock(priv->sock, 540845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_supplicant_global_ctrl_iface_receive, 541845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project global, priv); 542845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 543845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return priv; 544845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 545845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectfail: 546845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv->sock >= 0) 547845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project close(priv->sock); 548845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(priv); 549845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 550845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 551845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 552845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 553845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid 554845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 555845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 556845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (priv->sock >= 0) { 557845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project eloop_unregister_read_sock(priv->sock); 558845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project close(priv->sock); 559845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 560845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(priv); 561845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 562