18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / UNIX domain socket -based control interface 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/un.h> 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/stat.h> 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <grp.h> 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <stddef.h> 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <cutils/sockets.h> 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */ 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/list.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h" 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ctrl_iface.h" 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Per-interface ctrl_iface */ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct wpa_ctrl_dst - Internal data structure of control interface monitors 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This structure is used to store information about registered control 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interface monitors into struct wpa_supplicant. This data is private to 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ctrl_iface_unix.c and should not be touched directly from other files. 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_ctrl_dst { 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct dl_list list; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un addr; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t addrlen; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int debug_level; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int errors; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_priv { 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sock; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct dl_list ctrl_dst; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int level, const char *buf, 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len); 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv, 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un *from, 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen) 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst = os_zalloc(sizeof(*dst)); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst == NULL) 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->addrlen = fromlen; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->debug_level = MSG_INFO; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add(&priv->ctrl_dst, &dst->list); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) from->sun_path, 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen - offsetof(struct sockaddr_un, sun_path)); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv, 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un *from, 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen) 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) { 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fromlen == dst->addrlen && 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(from->sun_path, dst->addr.sun_path, 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen - offsetof(struct sockaddr_un, sun_path)) 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == 0) { 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&dst->list); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) from->sun_path, 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen - 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt offsetof(struct sockaddr_un, sun_path)); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un *from, 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen, 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *level) 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) { 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fromlen == dst->addrlen && 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(from->sun_path, dst->addr.sun_path, 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen - offsetof(struct sockaddr_un, sun_path)) 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == 0) { 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "level", (u8 *) from->sun_path, 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen - 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt offsetof(struct sockaddr_un, sun_path)); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->debug_level = atoi(level); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *sock_ctx) 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_priv *priv = sock_ctx; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[4096]; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un from; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen = sizeof(from); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *reply = NULL; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t reply_len = 0; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int new_attached = 0; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from, &fromlen); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("recvfrom(ctrl_iface)"); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[res] = '\0'; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(buf, "ATTACH") == 0) { 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 1; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_attached = 1; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 2; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strcmp(buf, "DETACH") == 0) { 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 1; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 2; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + 6)) 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 1; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply_len = 2; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf, 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &reply_len); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply) { 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(reply); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (reply_len == 1) { 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (reply_len == 2) { 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (new_attached) 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_ctrl_attached(wpa_s->eapol); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s) 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pbuf, *dir = NULL, *gid_str = NULL; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->conf->ctrl_interface == NULL) 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pbuf = os_strdup(wpa_s->conf->ctrl_interface); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pbuf == NULL) 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(pbuf, "DIR=", 4) == 0) { 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dir = pbuf + 4; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_str = os_strstr(dir, " GROUP="); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gid_str) { 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *gid_str = '\0'; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_str += 7; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dir = pbuf; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(len); 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pbuf); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0 || (size_t) res >= len) { 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pbuf); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __CYGWIN__ 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Windows/WinPcap uses interface names that are not suitable 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * as a file name - convert invalid chars to underscores */ 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos = buf; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos) { 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\\') 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '_'; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __CYGWIN__ */ 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pbuf); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *txt, size_t len) 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_priv * 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_priv *priv; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un addr; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *fname = NULL; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_t gid = 0; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int gid_set = 0; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, *dir = NULL, *gid_str = NULL; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct group *grp; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *endp; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv = os_zalloc(sizeof(*priv)); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv == NULL) 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&priv->ctrl_dst); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->wpa_s = wpa_s; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = -1; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->conf->ctrl_interface == NULL) 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_strdup(wpa_s->conf->ctrl_interface); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", 2840dc7a27a4d3b8328028ced3a71bd331e77981166Irfan Sheriff wpa_s->ifname); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = android_get_control_socket(addr.sun_path); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock >= 0) 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto havesock; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */ 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(buf, "DIR=", 4) == 0) { 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dir = buf + 4; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_str = os_strstr(dir, " GROUP="); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gid_str) { 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *gid_str = '\0'; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_str += 7; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dir = buf; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_str = wpa_s->conf->ctrl_interface_group; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) { 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (errno == EEXIST) { 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Using existing control " 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface directory."); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("mkdir[ctrl_interface]"); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gid_str) { 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt grp = getgrnam(gid_str); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (grp) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid = grp->gr_gid; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_set = 1; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (from group name '%s')", 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) gid, gid_str); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Group name not found - try to parse this as gid */ 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid = strtol(gid_str, &endp, 10); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*gid_str == '\0' || *endp != '\0') { 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: Invalid group " 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "'%s'", gid_str); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_set = 1; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) gid); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gid_set && chown(dir, -1, gid) < 0) { 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("chown[ctrl_interface]"); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Make sure the group can enter and read the directory */ 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gid_set && 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chmod(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) < 0) { 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: chmod[ctrl_interface]: %s", 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strerror(errno)); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >= 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(addr.sun_path)) { 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "ctrl_iface path limit exceeded"); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock < 0) { 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("socket(PF_UNIX)"); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sun_len = sizeof(addr); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __FreeBSD__ */ 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sun_family = AF_UNIX; 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fname = wpa_supplicant_ctrl_iface_path(wpa_s); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fname == NULL) 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strerror(errno)); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (connect(priv->sock, (struct sockaddr *) &addr, 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(addr)) < 0) { 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " allow connections - assuming it was left" 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "over from forced program termination"); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (unlink(fname) < 0) { 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("unlink[ctrl_iface]"); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not unlink " 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "existing ctrl_iface socket '%s'", 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fname); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(addr)) < 0) { 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("bind(PF_UNIX)"); 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ctrl_iface socket '%s'", fname); 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "be in use - cannot override it"); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not used anymore", fname); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(fname); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fname = NULL; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gid_set && chown(fname, -1, gid) < 0) { 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("chown[ctrl_interface/ifname]"); 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("chmod[ctrl_interface/ifname]"); 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(fname); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidthavesock: 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */ 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s, priv); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock >= 0) 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(priv->sock); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fname) { 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unlink(fname); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(fname); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst, *prev; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock > -1) { 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *fname; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, *dir = NULL, *gid_str = NULL; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(priv->sock); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!dl_list_empty(&priv->ctrl_dst)) { 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wait a second before closing the control socket if 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * there are any attached monitors in order to allow 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * them to receive any pending messages. 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "monitors to receive messages"); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_sleep(1, 0); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(priv->sock); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = -1; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fname) { 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unlink(fname); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(fname); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_strdup(priv->wpa_s->conf->ctrl_interface); 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto free_dst; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(buf, "DIR=", 4) == 0) { 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dir = buf + 4; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_str = os_strstr(dir, " GROUP="); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gid_str) { 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *gid_str = '\0'; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gid_str += 7; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dir = buf; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rmdir(dir) < 0) { 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (errno == ENOTEMPTY) { 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Control interface " 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "directory not empty - leaving it " 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "behind"); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("rmdir[ctrl_interface]"); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfree_dst: 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst, 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt list) 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dst); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @level: Priority level of the message 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Message data 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Message length 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send a packet to all monitor programs attached to the control interface. 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int level, const char *buf, 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ctrl_dst *dst, *next; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char levelstr[10]; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx, res; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct msghdr msg; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iovec io[2]; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock < 0 || dl_list_empty(&priv->ctrl_dst)) 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0 || (size_t) res >= sizeof(levelstr)) 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt io[0].iov_base = levelstr; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt io[0].iov_len = os_strlen(levelstr); 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt io[1].iov_base = (char *) buf; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt io[1].iov_len = len; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&msg, 0, sizeof(msg)); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.msg_iov = io; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.msg_iovlen = 2; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx = 0; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(dst, next, &priv->ctrl_dst, struct wpa_ctrl_dst, 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt list) { 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (level >= dst->debug_level) { 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) dst->addr.sun_path, dst->addrlen - 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt offsetof(struct sockaddr_un, sun_path)); 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.msg_name = (void *) &dst->addr; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.msg_namelen = dst->addrlen; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sendmsg(priv->sock, &msg, 0) < 0) { 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int _errno = errno; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d - %s", 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx, errno, strerror(errno)); 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->errors++; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dst->errors > 1000 || 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (_errno != ENOBUFS && dst->errors > 10) || 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _errno == ENOENT) { 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_ctrl_iface_detach( 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv, &dst->addr, 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->addrlen); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dst->errors = 0; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx++; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[256]; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un from; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen = sizeof(from); 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (;;) { 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to " 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attach", priv->wpa_s->ifname); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_wait_for_read_sock(priv->sock); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0, 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from, &fromlen); 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("recvfrom(ctrl_iface)"); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[res] = '\0'; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(buf, "ATTACH") == 0) { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* handle ATTACH signal of first monitor interface */ 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_supplicant_ctrl_iface_attach(priv, &from, 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen)) { 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(priv->sock, "OK\n", 3, 0, 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from, fromlen); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* OK to continue */ 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(priv->sock, "FAIL\n", 5, 0, 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from, fromlen); 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* return FAIL for all other signals */ 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(priv->sock, "FAIL\n", 5, 0, 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from, fromlen); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Global ctrl_iface */ 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_global_priv { 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global *global; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sock; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *sock_ctx) 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_global *global = eloop_ctx; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[256]; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un from; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen = sizeof(from); 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *reply; 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t reply_len; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from, &fromlen); 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("recvfrom(ctrl_iface)"); 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[res] = '\0'; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = wpa_supplicant_global_ctrl_iface_process(global, buf, 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &reply_len); 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply) { 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(reply); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (reply_len) { 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_global_priv * 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ctrl_iface_global_priv *priv; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un addr; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv = os_zalloc(sizeof(*priv)); 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv == NULL) 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->global = global; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = -1; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->params.ctrl_interface == NULL) 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = android_get_control_socket(global->params.ctrl_interface); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock >= 0) 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto havesock; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */ 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Global control interface '%s'", 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->params.ctrl_interface); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock < 0) { 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("socket(PF_UNIX)"); 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sun_len = sizeof(addr); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __FreeBSD__ */ 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sun_family = AF_UNIX; 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(addr.sun_path, global->params.ctrl_interface, 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(addr.sun_path)); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("bind(PF_UNIX)"); 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (connect(priv->sock, (struct sockaddr *) &addr, 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(addr)) < 0) { 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " allow connections - assuming it was left" 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "over from forced program termination"); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (unlink(global->params.ctrl_interface) < 0) { 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("unlink[ctrl_iface]"); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not unlink " 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "existing ctrl_iface socket '%s'", 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->params.ctrl_interface); 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(addr)) < 0) { 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("bind(PF_UNIX)"); 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ctrl_iface socket '%s'", 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->params.ctrl_interface); 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "be in use - cannot override it"); 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not used anymore", 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->params.ctrl_interface); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidthavesock: 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */ 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(priv->sock, 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_global_ctrl_iface_receive, 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global, NULL); 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock >= 0) 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(priv->sock); 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->sock >= 0) { 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(priv->sock); 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(priv->sock); 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv->global->params.ctrl_interface) 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unlink(priv->global->params.ctrl_interface); 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(priv); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 735