1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant / UNIX domain socket -based control interface 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sys/un.h> 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sys/stat.h> 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <grp.h> 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <stddef.h> 202c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 212c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#include <cutils/sockets.h> 222c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h" 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "config.h" 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_supplicant_i.h" 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "ctrl_iface.h" 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* Per-interface ctrl_iface */ 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * struct wpa_ctrl_dst - Internal data structure of control interface monitors 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This structure is used to store information about registered control 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * interface monitors into struct wpa_supplicant. This data is private to 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * ctrl_iface_unix.c and should not be touched directly from other files. 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_ctrl_dst { 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl_dst *next; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un addr; 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t addrlen; 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int debug_level; 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int errors; 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_priv { 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_supplicant *wpa_s; 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int sock; 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl_dst *ctrl_dst; 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int level, const char *buf, 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len); 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv, 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un *from, 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t fromlen) 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl_dst *dst; 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst = os_zalloc(sizeof(*dst)); 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (dst == NULL) 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst->addrlen = fromlen; 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst->debug_level = MSG_INFO; 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst->next = priv->ctrl_dst; 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv->ctrl_dst = dst; 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) from->sun_path, 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen - offsetof(struct sockaddr_un, sun_path)); 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv, 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un *from, 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t fromlen) 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl_dst *dst, *prev = NULL; 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst = priv->ctrl_dst; 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (dst) { 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (fromlen == dst->addrlen && 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(from->sun_path, dst->addr.sun_path, 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen - offsetof(struct sockaddr_un, sun_path)) 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt == 0) { 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prev == NULL) 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv->ctrl_dst = dst->next; 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev->next = dst->next; 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(dst); 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) from->sun_path, 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen - 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt offsetof(struct sockaddr_un, sun_path)); 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = dst; 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst = dst->next; 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un *from, 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t fromlen, 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *level) 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl_dst *dst; 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst = priv->ctrl_dst; 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (dst) { 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (fromlen == dst->addrlen && 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(from->sun_path, dst->addr.sun_path, 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen - offsetof(struct sockaddr_un, sun_path)) 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt == 0) { 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "level", (u8 *) from->sun_path, 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen - 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt offsetof(struct sockaddr_un, sun_path)); 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst->debug_level = atoi(level); 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst = dst->next; 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *sock_ctx) 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ctrl_iface_priv *priv = sock_ctx; 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char buf[256]; 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int res; 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un from; 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t fromlen = sizeof(from); 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *reply = NULL; 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t reply_len = 0; 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int new_attached = 0; 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) &from, &fromlen); 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) { 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("recvfrom(ctrl_iface)"); 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[res] = '\0'; 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_strcmp(buf, "ATTACH") == 0) { 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply_len = 1; 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else { 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt new_attached = 1; 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply_len = 2; 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (os_strcmp(buf, "DETACH") == 0) { 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply_len = 1; 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply_len = 2; 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf + 6)) 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply_len = 1; 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply_len = 2; 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf, 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &reply_len); 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (reply) { 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen); 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(reply); 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (reply_len == 1) { 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen); 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (reply_len == 2) { 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen); 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (new_attached) 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eapol_sm_notify_ctrl_attached(wpa_s->eapol); 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s) 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *buf; 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *pbuf, *dir = NULL, *gid_str = NULL; 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int res; 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_s->conf->ctrl_interface == NULL) 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pbuf = os_strdup(wpa_s->conf->ctrl_interface); 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pbuf == NULL) 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_strncmp(pbuf, "DIR=", 4) == 0) { 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dir = pbuf + 4; 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_str = os_strstr(dir, " GROUP="); 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (gid_str) { 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *gid_str = '\0'; 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_str += 7; 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dir = pbuf; 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2; 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(len); 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) { 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pbuf); 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname); 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0 || (size_t) res >= len) { 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pbuf); 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef __CYGWIN__ 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Windows/WinPcap uses interface names that are not suitable 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * as a file name - convert invalid chars to underscores */ 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *pos = buf; 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (*pos) { 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (*pos == '\\') 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos = '_'; 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* __CYGWIN__ */ 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pbuf); 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return buf; 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const char *txt, size_t len) 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_priv * 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ctrl_iface_priv *priv; 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un addr; 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *fname = NULL; 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_t gid = 0; 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int gid_set = 0; 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *buf, *dir = NULL, *gid_str = NULL; 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct group *grp; 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *endp; 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv = os_zalloc(sizeof(*priv)); 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv == NULL) 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv->wpa_s = wpa_s; 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv->sock = -1; 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_s->conf->ctrl_interface == NULL) 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return priv; 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_strdup(wpa_s->conf->ctrl_interface); 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 2892c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 2902c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", 2912c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt wpa_s->conf->ctrl_interface); 2922c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt priv->sock = android_get_control_socket(addr.sun_path); 2932c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if (priv->sock >= 0) 2942c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt goto havesock; 2952c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_strncmp(buf, "DIR=", 4) == 0) { 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dir = buf + 4; 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_str = os_strstr(dir, " GROUP="); 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (gid_str) { 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *gid_str = '\0'; 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_str += 7; 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dir = buf; 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_str = wpa_s->conf->ctrl_interface_group; 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) { 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (errno == EEXIST) { 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "Using existing control " 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "interface directory."); 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("mkdir[ctrl_interface]"); 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (gid_str) { 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt grp = getgrnam(gid_str); 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (grp) { 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid = grp->gr_gid; 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_set = 1; 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " (from group name '%s')", 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (int) gid, gid_str); 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Group name not found - try to parse this as gid */ 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid = strtol(gid_str, &endp, 10); 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (*gid_str == '\0' || *endp != '\0') { 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: Invalid group " 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "'%s'", gid_str); 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_set = 1; 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (int) gid); 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (gid_set && chown(dir, -1, gid) < 0) { 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("chown[ctrl_interface]"); 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 345dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt /* Make sure the group can enter and read the directory */ 346dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (gid_set && 347dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt chmod(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) < 0) { 348dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpa_printf(MSG_ERROR, "CTRL: chmod[ctrl_interface]: %s", 349dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt strerror(errno)); 350dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt goto fail; 351dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt } 352dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >= 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(addr.sun_path)) { 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "ctrl_iface path limit exceeded"); 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv->sock < 0) { 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("socket(PF_UNIX)"); 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef __FreeBSD__ 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr.sun_len = sizeof(addr); 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* __FreeBSD__ */ 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr.sun_family = AF_UNIX; 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fname = wpa_supplicant_ctrl_iface_path(wpa_s); 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (fname == NULL) 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt strerror(errno)); 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (connect(priv->sock, (struct sockaddr *) &addr, 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(addr)) < 0) { 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " allow connections - assuming it was left" 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "over from forced program termination"); 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (unlink(fname) < 0) { 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("unlink[ctrl_iface]"); 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "Could not unlink " 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "existing ctrl_iface socket '%s'", 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fname); 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(addr)) < 0) { 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("bind(PF_UNIX)"); 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "ctrl_iface socket '%s'", fname); 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "be in use - cannot override it"); 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "not used anymore", fname); 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(fname); 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fname = NULL; 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (gid_set && chown(fname, -1, gid) < 0) { 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("chown[ctrl_interface/ifname]"); 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("chmod[ctrl_interface/ifname]"); 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(fname); 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 4182c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidthavesock: 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_s, priv); 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return priv; 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtfail: 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv->sock >= 0) 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(priv->sock); 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(priv); 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (fname) { 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unlink(fname); 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(fname); 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl_dst *dst, *prev; 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv->sock > -1) { 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *fname; 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *buf, *dir = NULL, *gid_str = NULL; 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_unregister_read_sock(priv->sock); 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv->ctrl_dst) { 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Wait a second before closing the control socket if 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * there are any attached monitors in order to allow 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * them to receive any pending messages. 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "monitors to receive messages"); 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_sleep(1, 0); 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(priv->sock); 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv->sock = -1; 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s); 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (fname) { 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unlink(fname); 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(fname); 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_strdup(priv->wpa_s->conf->ctrl_interface); 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto free_dst; 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_strncmp(buf, "DIR=", 4) == 0) { 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dir = buf + 4; 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_str = os_strstr(dir, " GROUP="); 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (gid_str) { 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *gid_str = '\0'; 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt gid_str += 7; 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dir = buf; 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (rmdir(dir) < 0) { 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (errno == ENOTEMPTY) { 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "Control interface " 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "directory not empty - leaving it " 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "behind"); 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("rmdir[ctrl_interface]"); 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtfree_dst: 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst = priv->ctrl_dst; 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (dst) { 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = dst; 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst = dst->next; 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(prev); 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(priv); 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @level: Priority level of the message 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @buf: Message data 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @len: Message length 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Send a packet to all monitor programs attached to the control interface. 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int level, const char *buf, 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len) 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl_dst *dst, *next; 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char levelstr[10]; 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int idx, res; 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct msghdr msg; 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct iovec io[2]; 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst = priv->ctrl_dst; 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv->sock < 0 || dst == NULL) 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0 || (size_t) res >= sizeof(levelstr)) 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt io[0].iov_base = levelstr; 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt io[0].iov_len = os_strlen(levelstr); 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt io[1].iov_base = (char *) buf; 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt io[1].iov_len = len; 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&msg, 0, sizeof(msg)); 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg.msg_iov = io; 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg.msg_iovlen = 2; 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt idx = 0; 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (dst) { 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next = dst->next; 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (level >= dst->debug_level) { 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) dst->addr.sun_path, dst->addrlen - 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt offsetof(struct sockaddr_un, sun_path)); 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg.msg_name = (void *) &dst->addr; 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg.msg_namelen = dst->addrlen; 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sendmsg(priv->sock, &msg, 0) < 0) { 545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int _errno = errno; 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%d - %s", 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt idx, errno, strerror(errno)); 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst->errors++; 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (dst->errors > 10 || _errno == ENOENT) { 551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_ctrl_iface_detach( 552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv, &dst->addr, 553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst->addrlen); 554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst->errors = 0; 557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt idx++; 559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt dst = next; 560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char buf[256]; 567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int res; 568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un from; 569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t fromlen = sizeof(from); 570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (;;) { 572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to " 573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "attach", priv->wpa_s->ifname); 574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_wait_for_read_sock(priv->sock); 575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0, 577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) &from, &fromlen); 578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) { 579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("recvfrom(ctrl_iface)"); 580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[res] = '\0'; 583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_strcmp(buf, "ATTACH") == 0) { 585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* handle ATTACH signal of first monitor interface */ 586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!wpa_supplicant_ctrl_iface_attach(priv, &from, 587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen)) { 588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sendto(priv->sock, "OK\n", 3, 0, 589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) &from, fromlen); 590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* OK to continue */ 591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sendto(priv->sock, "FAIL\n", 5, 0, 594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) &from, fromlen); 595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* return FAIL for all other signals */ 598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sendto(priv->sock, "FAIL\n", 5, 0, 599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) &from, fromlen); 600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* Global ctrl_iface */ 606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_global_priv { 608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_global *global; 609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int sock; 610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *sock_ctx) 615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_global *global = eloop_ctx; 617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char buf[256]; 618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int res; 619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un from; 620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t fromlen = sizeof(from); 621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *reply; 622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t reply_len; 623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (struct sockaddr *) &from, &fromlen); 626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) { 627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("recvfrom(ctrl_iface)"); 628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[res] = '\0'; 631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply = wpa_supplicant_global_ctrl_iface_process(global, buf, 633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &reply_len); 634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (reply) { 636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen); 638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(reply); 639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (reply_len) { 640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fromlen); 642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ctrl_iface_global_priv * 647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ctrl_iface_global_priv *priv; 650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un addr; 651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv = os_zalloc(sizeof(*priv)); 653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv == NULL) 654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv->global = global; 656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv->sock = -1; 657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (global->params.ctrl_interface == NULL) 659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return priv; 660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 6612c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 6622c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt priv->sock = android_get_control_socket(global->params.ctrl_interface); 6632c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if (priv->sock >= 0) 6642c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt goto havesock; 6652c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif 6662c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt 667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "Global control interface '%s'", 668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt global->params.ctrl_interface); 669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv->sock < 0) { 672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("socket(PF_UNIX)"); 673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef __FreeBSD__ 678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr.sun_len = sizeof(addr); 679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* __FreeBSD__ */ 680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr.sun_family = AF_UNIX; 681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_strlcpy(addr.sun_path, global->params.ctrl_interface, 682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(addr.sun_path)); 683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("bind(PF_UNIX)"); 685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (connect(priv->sock, (struct sockaddr *) &addr, 686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(addr)) < 0) { 687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " allow connections - assuming it was left" 689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "over from forced program termination"); 690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (unlink(global->params.ctrl_interface) < 0) { 691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("unlink[ctrl_iface]"); 692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "Could not unlink " 693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "existing ctrl_iface socket '%s'", 694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt global->params.ctrl_interface); 695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (bind(priv->sock, (struct sockaddr *) &addr, 698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(addr)) < 0) { 699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("bind(PF_UNIX)"); 700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "ctrl_iface socket '%s'", 704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt global->params.ctrl_interface); 705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "be in use - cannot override it"); 708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "not used anymore", 710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt global->params.ctrl_interface); 711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 7152c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidthavesock: 716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_read_sock(priv->sock, 717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_supplicant_global_ctrl_iface_receive, 718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt global, NULL); 719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return priv; 721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtfail: 723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv->sock >= 0) 724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(priv->sock); 725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(priv); 726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid 731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv->sock >= 0) { 734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_unregister_read_sock(priv->sock); 735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(priv->sock); 736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv->global->params.ctrl_interface) 738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unlink(priv->global->params.ctrl_interface); 739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(priv); 740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 741