18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / UDP socket -based control interface 3e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ctrl_iface.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define COOKIE_LEN 8 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Per-interface ctrl_iface */ 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct wpa_ctrl_dst - Internal data structure of control interface monitors 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This structure is used to store information about registered control 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interface monitors into struct wpa_supplicant. This data is private to 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ctrl_iface_udp.c and should not be touched directly from other files. 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_ctrl_dst { 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *next; 33f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 34f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sockaddr_in6 addr; 35f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in addr; 37f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t addrlen; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int debug_level; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int errors; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_priv { 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sock; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *ctrl_dst; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 cookie[COOKIE_LEN]; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidtstruct ctrl_iface_global_priv { 5231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt int sock; 5331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt struct wpa_ctrl_dst *ctrl_dst; 5431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt u8 cookie[COOKIE_LEN]; 5531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt}; 5631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, 5931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt const char *ifname, int sock, 6031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt struct wpa_ctrl_dst **head, 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int level, const char *buf, 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidtstatic void wpas_ctrl_iface_free_dst(struct wpa_ctrl_dst *dst) 6631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt{ 6731a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt struct wpa_ctrl_dst *prev; 6831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 6931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt while (dst) { 7031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt prev = dst; 7131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt dst = dst->next; 7231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt os_free(prev); 7331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } 7431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt} 7531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 7631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 7731a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidtstatic int wpa_supplicant_ctrl_iface_attach(struct wpa_ctrl_dst **head, 78f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 79f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sockaddr_in6 *from, 80f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *from, 82f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen) 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst; 86f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 87f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt char addr[INET6_ADDRSTRLEN]; 88f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_UDP_IPV6 */ 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = os_zalloc(sizeof(*dst)); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst == NULL) 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 93f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_memcpy(&dst->addr, from, sizeof(*from)); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->addrlen = fromlen; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->debug_level = MSG_INFO; 9631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt dst->next = *head; 9731a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt *head = dst; 98f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 99f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d", 100f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt inet_ntop(AF_INET6, &from->sin6_addr, addr, sizeof(*from)), 101f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ntohs(from->sin6_port)); 102f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d", 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(from->sin_addr), ntohs(from->sin_port)); 105f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidtstatic int wpa_supplicant_ctrl_iface_detach(struct wpa_ctrl_dst **head, 111f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 112f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sockaddr_in6 *from, 113f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *from, 115f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst, *prev = NULL; 119f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 120f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt char addr[INET6_ADDRSTRLEN]; 121f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt dst = *head; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (dst) { 125f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 126f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (from->sin6_port == dst->addr.sin6_port && 127f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr, 128f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sizeof(from->sin6_addr))) { 129f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s:%d", 130f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt inet_ntop(AF_INET6, &from->sin6_addr, addr, 131f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sizeof(*from)), 132f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ntohs(from->sin6_port)); 133f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from->sin_port == dst->addr.sin_port) { 136b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached " 137b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt "%s:%d", inet_ntoa(from->sin_addr), 138b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt ntohs(from->sin_port)); 139f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev == NULL) 14131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt *head = dst->next; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = dst->next; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = dst; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = dst->next; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, 155f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 156f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sockaddr_in6 *from, 157f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *from, 159f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen, 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *level) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst; 164f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 165f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt char addr[INET6_ADDRSTRLEN]; 166f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = priv->ctrl_dst; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (dst) { 172f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#if CONFIG_CTRL_IFACE_UDP_IPV6 173f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (from->sin6_port == dst->addr.sin6_port && 174f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr, 175f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sizeof(from->sin6_addr))) { 176f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor level %s:%d", 177f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt inet_ntop(AF_INET6, &from->sin6_addr, addr, 178f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sizeof(*from)), 179f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ntohs(from->sin6_port)); 180f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from->sin_port == dst->addr.sin_port) { 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor " 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "level %s:%d", inet_ntoa(from->sin_addr), 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ntohs(from->sin_port)); 186f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->debug_level = atoi(level); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = dst->next; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv, 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *reply_len) 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *reply; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = os_malloc(7 + 2 * COOKIE_LEN + 1); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply == NULL) { 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply_len = 1; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply, "COOKIE=", 7); 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->cookie, COOKIE_LEN); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply_len = 7 + 2 * COOKIE_LEN; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return reply; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *sock_ctx) 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_priv *priv = sock_ctx; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[256], *pos; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 224f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 225f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sockaddr_in6 from; 226f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE 227f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt char addr[INET6_ADDRSTRLEN]; 228f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 229f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in from; 231f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen = sizeof(from); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *reply = NULL; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t reply_len = 0; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int new_attached = 0; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 cookie[COOKIE_LEN]; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from, &fromlen); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 241fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 242fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt strerror(errno)); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE 247f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 248f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from)); 249f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (os_strcmp(addr, "::1")) { 250f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", 251f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt addr); 252f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 253f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The OS networking stack is expected to drop this kind of 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frames since the socket is bound to only localhost address. 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Just in case, drop the frame if it is coming from any other 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * address. 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "source %s", inet_ntoa(from.sin_addr)); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 265f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 26661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 26761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[res] = '\0'; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(buf, "GET_COOKIE") == 0) { 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Require that the client includes a prefix with the 'cookie' value 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * fetched with GET_COOKIE command. This is used to verify that the 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * client has access to a bidirectional link over UDP in order to 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * avoid attacks using forged localhost IP address even if the OS does 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not block such frames from remote destinations. 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(buf, "COOKIE=", 7) != 0) { 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "drop request"); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request - drop request"); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "drop request"); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf + 7 + 2 * COOKIE_LEN; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos == ' ') 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(pos, "ATTACH") == 0) { 30531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, 30631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt &from, fromlen)) 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 1; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_attached = 1; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 2; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strcmp(pos, "DETACH") == 0) { 31331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, 31431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt &from, fromlen)) 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 1; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 2; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strncmp(pos, "LEVEL ", 6) == 0) { 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos + 6)) 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 1; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 2; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos, 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &reply_len); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt done: 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply) { 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(reply); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (reply_len == 1) { 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (reply_len == 2) { 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (new_attached) 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_ctrl_attached(wpa_s->eapol); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3477a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 3487a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt enum wpa_msg_type type, 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *txt, size_t len) 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 35231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 35331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (!wpa_s) 35431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt return; 35531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 35631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (type != WPA_MSG_NO_GLOBAL && wpa_s->global->ctrl_iface) { 35731a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface; 35831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 35931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (priv->ctrl_dst) { 36031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt wpa_supplicant_ctrl_iface_send( 36131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt wpa_s, 36231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt type != WPA_MSG_PER_INTERFACE ? 36331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt NULL : wpa_s->ifname, 36431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt priv->sock, &priv->ctrl_dst, level, txt, len); 36531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } 36631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } 36731a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 36831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (type == WPA_MSG_ONLY_GLOBAL || !wpa_s->ctrl_iface) 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 37031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 37131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock, 37231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt &wpa_s->ctrl_iface->ctrl_dst, 37331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt level, txt, len); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_priv * 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_priv *priv; 381e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt char port_str[40]; 38261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int port = WPA_CTRL_IFACE_PORT; 38331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt char *pos; 384f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 385f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sockaddr_in6 addr; 386f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int domain = PF_INET6; 387f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 388f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sockaddr_in addr; 389f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int domain = PF_INET; 390f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv = os_zalloc(sizeof(*priv)); 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv == NULL) 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->wpa_s = wpa_s; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = -1; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_random(priv->cookie, COOKIE_LEN); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->conf->ctrl_interface == NULL) 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt pos = os_strstr(wpa_s->conf->ctrl_interface, "udp:"); 40331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (pos) { 40431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt pos += 4; 40531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt port = atoi(pos); 40631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (port <= 0) { 40731a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port: %s", 40831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt wpa_s->conf->ctrl_interface); 40931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt goto fail; 41031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } 41131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } 41231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 413f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt priv->sock = socket(domain, SOCK_DGRAM, 0); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock < 0) { 415fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 420f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 421f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt addr.sin6_family = AF_INET6; 422f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 423f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt addr.sin6_addr = in6addr_any; 424f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 425f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt inet_pton(AF_INET6, "::1", &addr.sin6_addr); 426f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 427f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin_family = AF_INET; 42961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 43061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt addr.sin_addr.s_addr = INADDR_ANY; 43161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin_addr.s_addr = htonl((127 << 24) | 1); 43361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 434f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 43561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidttry_again: 436f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 437f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt addr.sin6_port = htons(port); 438f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 43961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt addr.sin_port = htons(port); 440f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 44261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt port--; 443e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if ((WPA_CTRL_IFACE_PORT - port) < WPA_CTRL_IFACE_PORT_LIMIT) 44461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto try_again; 445fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 449e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt /* Update the ctrl_interface value to match the selected port */ 450e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt os_snprintf(port_str, sizeof(port_str), "udp:%d", port); 451e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt os_free(wpa_s->conf->ctrl_interface); 452e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt wpa_s->conf->ctrl_interface = os_strdup(port_str); 453e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (!wpa_s->conf->ctrl_interface) { 454e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt wpa_msg(wpa_s, MSG_ERROR, "Failed to malloc ctrl_interface"); 455e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt goto fail; 456e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } 457e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 45861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 45961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "ctrl_iface_init UDP port: %d", port); 46061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 46161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s, priv); 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock >= 0) 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(priv->sock); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock > -1) { 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(priv->sock); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->ctrl_dst) { 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 482b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt * Wait before closing the control socket if 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * there are any attached monitors in order to allow 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * them to receive any pending messages. 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "monitors to receive messages"); 488b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_sleep(0, 100000); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(priv->sock); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = -1; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt wpas_ctrl_iface_free_dst(priv->ctrl_dst); 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, 50031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt const char *ifname, int sock, 50131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt struct wpa_ctrl_dst **head, 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int level, const char *buf, 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst, *next; 50631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt char levelstr[64]; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *sbuf; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int llen; 510f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 511f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt char addr[INET6_ADDRSTRLEN]; 512f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt dst = *head; 51531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (sock < 0 || dst == NULL) 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (ifname) 51931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt os_snprintf(levelstr, sizeof(levelstr), "IFACE=%s <%d>", 52031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt ifname, level); 52131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt else 52231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt llen = os_strlen(levelstr); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sbuf = os_malloc(llen + len); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sbuf == NULL) 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sbuf, levelstr, llen); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sbuf + llen, buf, len); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx = 0; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (dst) { 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next = dst->next; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (level >= dst->debug_level) { 536f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 537f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", 538f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt inet_ntop(AF_INET6, &dst->addr.sin6_addr, 539f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt addr, sizeof(dst->addr)), 540f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ntohs(dst->addr.sin6_port)); 541f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(dst->addr.sin_addr), 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ntohs(dst->addr.sin_port)); 545f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 54631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (sendto(sock, sbuf, llen + len, 0, 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &dst->addr, 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(dst->addr)) < 0) { 549fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt wpa_printf(MSG_ERROR, 550fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt "sendto(CTRL_IFACE monitor): %s", 551fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt strerror(errno)); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->errors++; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->errors > 10) { 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_ctrl_iface_detach( 55531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt head, &dst->addr, 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->addrlen); 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->errors = 0; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx++; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = next; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sbuf); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor", 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->wpa_s->ifname); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_wait_for_read_sock(priv->sock); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Global ctrl_iface */ 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv, 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *reply_len) 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *reply; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = os_malloc(7 + 2 * COOKIE_LEN + 1); 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply == NULL) { 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply_len = 1; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply, "COOKIE=", 7); 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->cookie, COOKIE_LEN); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply_len = 7 + 2 * COOKIE_LEN; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return reply; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *sock_ctx) 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global *global = eloop_ctx; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_global_priv *priv = sock_ctx; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[256], *pos; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 605e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 606e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt struct sockaddr_in6 from; 607e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in from; 609e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen = sizeof(from); 61131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt char *reply = NULL; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t reply_len; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 cookie[COOKIE_LEN]; 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from, &fromlen); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 618fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 619fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt strerror(errno)); 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 62361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE 624e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#ifndef CONFIG_CTRL_IFACE_UDP_IPV6 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The OS networking stack is expected to drop this kind of 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frames since the socket is bound to only localhost address. 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Just in case, drop the frame if it is coming from any other 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * address. 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "source %s", inet_ntoa(from.sin_addr)); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 636e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 63761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 63861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[res] = '\0'; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(buf, "GET_COOKIE") == 0) { 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = wpa_supplicant_global_get_cookie(priv, &reply_len); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(buf, "COOKIE=", 7) != 0) { 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "drop request"); 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request - drop request"); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "drop request"); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf + 7 + 2 * COOKIE_LEN; 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos == ' ') 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 66831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (os_strcmp(pos, "ATTACH") == 0) { 66931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, 67031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt &from, fromlen)) 67131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt reply_len = 1; 67231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt else 67331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt reply_len = 2; 67431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } else if (os_strcmp(pos, "DETACH") == 0) { 67531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, 67631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt &from, fromlen)) 67731a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt reply_len = 1; 67831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt else 67931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt reply_len = 2; 68031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } else { 68131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt reply = wpa_supplicant_global_ctrl_iface_process(global, pos, 68231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt &reply_len); 68331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt done: 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply) { 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(reply); 69031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } else if (reply_len == 1) { 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 69331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } else if (reply_len == 2) { 69431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 69531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt fromlen); 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_global_priv * 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_global_priv *priv; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in addr; 70531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt char *pos; 70661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int port = WPA_GLOBAL_CTRL_IFACE_PORT; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv = os_zalloc(sizeof(*priv)); 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv == NULL) 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = -1; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_random(priv->cookie, COOKIE_LEN); 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->params.ctrl_interface == NULL) 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Global control interface '%s'", 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->params.ctrl_interface); 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 72031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt pos = os_strstr(global->params.ctrl_interface, "udp:"); 72131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (pos) { 72231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt pos += 4; 72331a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt port = atoi(pos); 72431a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt if (port <= 0) { 72531a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port %s", 72631a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt global->params.ctrl_interface); 72731a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt goto fail; 72831a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } 72931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt } 73031a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = socket(PF_INET, SOCK_DGRAM, 0); 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock < 0) { 733fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin_family = AF_INET; 73961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 74061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt addr.sin_addr.s_addr = INADDR_ANY; 74161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin_addr.s_addr = htonl((127 << 24) | 1); 74361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 74461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidttry_again: 74561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt addr.sin_port = htons(port); 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 74761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt port++; 74861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if ((port - WPA_GLOBAL_CTRL_IFACE_PORT) < 74931a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos) 75061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto try_again; 751fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 75561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 75661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "global_ctrl_iface_init UDP port: %d", port); 75761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 75861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(priv->sock, 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_global_ctrl_iface_receive, 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global, priv); 76231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock >= 0) 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(priv->sock); 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock >= 0) { 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(priv->sock); 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(priv->sock); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 78131a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt 78231a29cc7ed87b62465c7e01f03484f4643d12309Dmitry Shmidt wpas_ctrl_iface_free_dst(priv->ctrl_dst); 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 785