1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_supplicant/hostapd control interface library 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2007, 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 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UNIX 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sys/un.h> 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UNIX */ 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 232c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 242c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#include <dirent.h> 252c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#include <linux/limits.h> 262c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#include <cutils/sockets.h> 272c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#include <cutils/memory.h> 282c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#include "private/android_filesystem_config.h" 292c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif 302c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_ctrl.h" 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define CTRL_IFACE_SOCKET 372c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 382c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidtstatic const char *local_socket_dir = "/data/misc/wifi/sockets"; 392c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidtstatic const char *local_socket_prefix = "wpa_ctrl_"; 402c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif /* ANDROID */ 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */ 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * struct wpa_ctrl - Internal structure for control interface library 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This structure is used by the wpa_supplicant/hostapd control interface 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * library to store internal data. Programs using the library should not touch 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * this data directly. They can only use the pointer to the data structure as 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * an identifier for the control interface connection and use this as one of 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * the arguments for most of the control interface library functions. 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_ctrl { 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int s; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_in local; 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_in dest; 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *cookie; 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP */ 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UNIX 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int s; 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un local; 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_un dest; 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UNIX */ 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HANDLE pipe; 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UNIX 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl *ctrl; 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt static int counter = 0; 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t res; 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int tries = 0; 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl = os_malloc(sizeof(*ctrl)); 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl == NULL) 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(ctrl, 0, sizeof(*ctrl)); 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl->s < 0) { 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->local.sun_family = AF_UNIX; 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt counter++; 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidttry_again: 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), 962c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 972c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt "%s/%s%d-%d", local_socket_dir, local_socket_prefix, 982c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt getpid(), counter); 992c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#else /* ANDROID */ 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "/tmp/wpa_ctrl_%d-%d", getpid(), counter); 1012c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) { 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(ctrl->s); 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tries++; 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(ctrl->local)) < 0) { 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (errno == EADDRINUSE && tries < 2) { 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * getpid() returns unique identifier for this instance 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * of wpa_ctrl, so the existing socket file must have 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * been left by unclean termination of an earlier run. 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Remove the file and try again. 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unlink(ctrl->local.sun_path); 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto try_again; 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(ctrl->s); 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1252c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 1262c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt chmod(ctrl->local.sun_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); 1272c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI); 1282c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt /* 1292c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt * If the ctrl_path isn't an absolute pathname, assume that 1302c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt * it's the name of a socket in the Android reserved namespace. 1312c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt * Otherwise, it's a normal UNIX domain socket appearing in the 1322c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt * filesystem. 1332c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt */ 1342c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if (ctrl_path != NULL && *ctrl_path != '/') { 1352c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt os_snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "wpa_%s", 1362c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt ctrl_path); 1372c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if (socket_local_client_connect(ctrl->s, 1382c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt ctrl->dest.sun_path, 1392c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt ANDROID_SOCKET_NAMESPACE_RESERVED, 1402c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt SOCK_DGRAM) < 0) { 1412c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt close(ctrl->s); 1422c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt unlink(ctrl->local.sun_path); 1432c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt os_free(ctrl); 1442c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt return NULL; 1452c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt } 1462c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt return ctrl; 1472c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt } 1482c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->dest.sun_family = AF_UNIX; 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(ctrl->dest.sun_path)); 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res >= sizeof(ctrl->dest.sun_path)) { 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(ctrl->s); 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(ctrl->dest)) < 0) { 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(ctrl->s); 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unlink(ctrl->local.sun_path); 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ctrl; 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_ctrl_close(struct wpa_ctrl *ctrl) 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1712c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if (ctrl == NULL) 1722c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt return; 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unlink(ctrl->local.sun_path); 1742c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if (ctrl->s >= 0) 1752c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt close(ctrl->s); 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1792c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 1802c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt/** 1812c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that 1822c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt * may be left over from clients that were previously connected to 1832c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt * wpa_supplicant. This keeps these files from being orphaned in the 1842c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt * event of crashes that prevented them from being removed as part 1852c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt * of the normal orderly shutdown. 1862c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt */ 187087612fdc0806072166a1a68f0f244fe67f644d5Dmitry Shmidtvoid wpa_ctrl_cleanup(void) 1882c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt{ 1892c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt DIR *dir; 1902c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt struct dirent entry; 1912c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt struct dirent *result; 1922c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt size_t dirnamelen; 1932c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt int prefixlen = strlen(local_socket_prefix); 1942c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt size_t maxcopy; 1952c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt char pathname[PATH_MAX]; 1962c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt char *namep; 1972c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt 1982c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if ((dir = opendir(local_socket_dir)) == NULL) 1992c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt return; 2002c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt 2012c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt dirnamelen = (size_t)snprintf(pathname, sizeof(pathname), "%s/", local_socket_dir); 2022c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if (dirnamelen >= sizeof(pathname)) { 2032c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt closedir(dir); 2042c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt return; 2052c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt } 2062c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt namep = pathname + dirnamelen; 2072c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt maxcopy = PATH_MAX-dirnamelen; 2082c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt while (readdir_r(dir, &entry, &result) == 0 && result != NULL) { 2092c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if (strncmp(entry.d_name, local_socket_prefix, prefixlen) == 0) { 2102c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt if (strlcpy(namep, entry.d_name, maxcopy) < maxcopy) { 2112c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt unlink(pathname); 2122c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt } 2132c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt } 2142c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt } 2152c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt closedir(dir); 2162c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt} 2172c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif /* ANDROID */ 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 2192c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#else /* CONFIG_CTRL_IFACE_UNIX */ 2202c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 221087612fdc0806072166a1a68f0f244fe67f644d5Dmitry Shmidtvoid wpa_ctrl_cleanup(void) 2222c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt{ 2232c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt} 2242c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif /* ANDROID */ 2252c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UNIX */ 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl *ctrl; 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char buf[128]; 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl = os_malloc(sizeof(*ctrl)); 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl == NULL) 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(ctrl, 0, sizeof(*ctrl)); 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->s = socket(PF_INET, SOCK_DGRAM, 0); 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl->s < 0) { 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("socket"); 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->local.sin_family = AF_INET; 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1); 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(ctrl->local)) < 0) { 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(ctrl->s); 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->dest.sin_family = AF_INET; 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1); 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT); 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(ctrl->dest)) < 0) { 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("connect"); 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(ctrl->s); 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = sizeof(buf) - 1; 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) { 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[len] = '\0'; 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->cookie = os_strdup(buf); 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ctrl; 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_ctrl_close(struct wpa_ctrl *ctrl) 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(ctrl->s); 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl->cookie); 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP */ 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CTRL_IFACE_SOCKET 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *reply, size_t *reply_len, 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void (*msg_cb)(char *msg, size_t len)) 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct timeval tv; 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int res; 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fd_set rfds; 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const char *_cmd; 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *cmd_buf = NULL; 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t _cmd_len; 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE_UDP 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl->cookie) { 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *pos; 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len; 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cmd_buf = os_malloc(_cmd_len); 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cmd_buf == NULL) 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _cmd = cmd_buf; 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = cmd_buf; 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_strlcpy(pos, ctrl->cookie, _cmd_len); 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += os_strlen(ctrl->cookie); 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = ' '; 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, cmd, cmd_len); 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_UDP */ 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _cmd = cmd; 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _cmd_len = cmd_len; 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) { 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(cmd_buf); 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(cmd_buf); 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (;;) { 3262c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifdef ANDROID 3272c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt tv.tv_sec = 10; 3282c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#else 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tv.tv_sec = 2; 3302c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tv.tv_usec = 0; 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt FD_ZERO(&rfds); 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt FD_SET(ctrl->s, &rfds); 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); 3354d13ed6d3f252ef7a3ae2fd18000fb765b5c2fa1Dmitry Shmidt if (res < 0) 3364d13ed6d3f252ef7a3ae2fd18000fb765b5c2fa1Dmitry Shmidt return res; 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (FD_ISSET(ctrl->s, &rfds)) { 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = recv(ctrl->s, reply, *reply_len, 0); 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return res; 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res > 0 && reply[0] == '<') { 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* This is an unsolicited message from 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_supplicant, not the reply to the 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * request. Use msg_cb to report this to the 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * caller. */ 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg_cb) { 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Make sure the message is nul 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * terminated. */ 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((size_t) res == *reply_len) 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = (*reply_len) - 1; 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reply[res] = '\0'; 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg_cb(reply, res); 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *reply_len = res; 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -2; 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CTRL_IFACE_SOCKET */ 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char buf[10]; 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len = 10; 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf, &len, NULL); 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret < 0) 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0) 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_attach(struct wpa_ctrl *ctrl) 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return wpa_ctrl_attach_helper(ctrl, 1); 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_detach(struct wpa_ctrl *ctrl) 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return wpa_ctrl_attach_helper(ctrl, 0); 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CTRL_IFACE_SOCKET 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int res; 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = recv(ctrl->s, reply, *reply_len, 0); 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return res; 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *reply_len = res; 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_pending(struct wpa_ctrl *ctrl) 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct timeval tv; 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fd_set rfds; 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tv.tv_sec = 0; 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tv.tv_usec = 0; 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt FD_ZERO(&rfds); 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt FD_SET(ctrl->s, &rfds); 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt select(ctrl->s + 1, &rfds, NULL, NULL, &tv); 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return FD_ISSET(ctrl->s, &rfds); 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ctrl->s; 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CTRL_IFACE_SOCKET */ 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef WPA_SUPPLICANT_NAMED_PIPE 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant" 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE) 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_ctrl *ctrl; 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt DWORD mode; 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt TCHAR name[256]; 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int i, ret; 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl = os_malloc(sizeof(*ctrl)); 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl == NULL) 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(ctrl, 0, sizeof(*ctrl)); 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl_path == NULL) 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX); 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl_path); 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* UNICODE */ 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl_path == NULL) 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX); 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl_path); 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* UNICODE */ 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret < 0 || ret >= 256) { 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < 10; i++) { 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt NULL, OPEN_EXISTING, 0, NULL); 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Current named pipe server side in wpa_supplicant is 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * re-opening the pipe for new clients only after the previous 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * one is taken into use. This leaves a small window for race 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * conditions when two connections are being opened at almost 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * the same time. Retry if that was the case. 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl->pipe != INVALID_HANDLE_VALUE || 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt GetLastError() != ERROR_PIPE_BUSY) 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WaitNamedPipe(name, 1000); 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ctrl->pipe == INVALID_HANDLE_VALUE) { 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mode = PIPE_READMODE_MESSAGE; 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) { 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt CloseHandle(ctrl->pipe); 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ctrl; 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid wpa_ctrl_close(struct wpa_ctrl *ctrl) 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt CloseHandle(ctrl->pipe); 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(ctrl); 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *reply, size_t *reply_len, 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void (*msg_cb)(char *msg, size_t len)) 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt DWORD written; 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt DWORD readlen = *reply_len; 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL)) 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL)) 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *reply_len = readlen; 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt DWORD len = *reply_len; 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL)) 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *reply_len = len; 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_pending(struct wpa_ctrl *ctrl) 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt DWORD left; 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL)) 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return left ? 1 : 0; 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 5452c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt return ctrl->pipe; 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE */ 551