ctrl_iface_unix.c revision 189251
1126261Smlaier/* 2130639Smlaier * WPA Supplicant / UNIX domain socket -based control interface 3126258Smlaier * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> 4126258Smlaier * 5126258Smlaier * This program is free software; you can redistribute it and/or modify 6130613Smlaier * it under the terms of the GNU General Public License version 2 as 7126258Smlaier * published by the Free Software Foundation. 8126258Smlaier * 9126258Smlaier * Alternatively, this software may be distributed under the terms of BSD 10126258Smlaier * license. 11126258Smlaier * 12126258Smlaier * See README and COPYING for more details. 13126258Smlaier */ 14126258Smlaier 15126258Smlaier#include "includes.h" 16126258Smlaier#include <sys/un.h> 17126258Smlaier#include <sys/stat.h> 18126258Smlaier#include <grp.h> 19126258Smlaier 20126258Smlaier#include "common.h" 21126258Smlaier#include "eloop.h" 22126258Smlaier#include "config.h" 23126258Smlaier#include "eapol_supp/eapol_supp_sm.h" 24126258Smlaier#include "wpa_supplicant_i.h" 25126258Smlaier#include "ctrl_iface.h" 26126258Smlaier 27126258Smlaier/* Per-interface ctrl_iface */ 28126258Smlaier 29126258Smlaier/** 30126258Smlaier * struct wpa_ctrl_dst - Internal data structure of control interface monitors 31126258Smlaier * 32126258Smlaier * This structure is used to store information about registered control 33126258Smlaier * interface monitors into struct wpa_supplicant. This data is private to 34126258Smlaier * ctrl_iface_unix.c and should not be touched directly from other files. 35126258Smlaier */ 36126258Smlaierstruct wpa_ctrl_dst { 37126258Smlaier struct wpa_ctrl_dst *next; 38126258Smlaier struct sockaddr_un addr; 39127145Smlaier socklen_t addrlen; 40126261Smlaier int debug_level; 41126261Smlaier int errors; 42126261Smlaier}; 43126261Smlaier 44127145Smlaier 45126261Smlaierstruct ctrl_iface_priv { 46126261Smlaier struct wpa_supplicant *wpa_s; 47127145Smlaier int sock; 48127145Smlaier struct wpa_ctrl_dst *ctrl_dst; 49127145Smlaier}; 50126261Smlaier 51126258Smlaier 52126258Smlaierstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 53126258Smlaier int level, const char *buf, 54126261Smlaier size_t len); 55126258Smlaier 56126258Smlaier 57126258Smlaierstatic int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv, 58126258Smlaier struct sockaddr_un *from, 59126258Smlaier socklen_t fromlen) 60126258Smlaier{ 61126258Smlaier struct wpa_ctrl_dst *dst; 62126258Smlaier 63126258Smlaier dst = os_zalloc(sizeof(*dst)); 64127145Smlaier if (dst == NULL) 65126261Smlaier return -1; 66130613Smlaier os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 67126261Smlaier dst->addrlen = fromlen; 68126258Smlaier dst->debug_level = MSG_INFO; 69126261Smlaier dst->next = priv->ctrl_dst; 70126258Smlaier priv->ctrl_dst = dst; 71126258Smlaier wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", 72126258Smlaier (u8 *) from->sun_path, fromlen - sizeof(from->sun_family)); 73126258Smlaier return 0; 74126258Smlaier} 75126258Smlaier 76126258Smlaier 77126258Smlaierstatic int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv, 78126258Smlaier struct sockaddr_un *from, 79126258Smlaier socklen_t fromlen) 80126258Smlaier{ 81126258Smlaier struct wpa_ctrl_dst *dst, *prev = NULL; 82126258Smlaier 83126258Smlaier dst = priv->ctrl_dst; 84126258Smlaier while (dst) { 85126258Smlaier if (fromlen == dst->addrlen && 86126258Smlaier os_memcmp(from->sun_path, dst->addr.sun_path, 87126258Smlaier fromlen - sizeof(from->sun_family)) == 0) { 88126258Smlaier if (prev == NULL) 89126258Smlaier priv->ctrl_dst = dst->next; 90126258Smlaier else 91127145Smlaier prev->next = dst->next; 92126258Smlaier os_free(dst); 93126261Smlaier wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", 94126258Smlaier (u8 *) from->sun_path, 95126258Smlaier fromlen - sizeof(from->sun_family)); 96130613Smlaier return 0; 97130613Smlaier } 98126258Smlaier prev = dst; 99130613Smlaier dst = dst->next; 100126258Smlaier } 101126258Smlaier return -1; 102126258Smlaier} 103126258Smlaier 104126258Smlaier 105126258Smlaierstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, 106127145Smlaier struct sockaddr_un *from, 107126261Smlaier socklen_t fromlen, 108126261Smlaier char *level) 109126261Smlaier{ 110126258Smlaier struct wpa_ctrl_dst *dst; 111126258Smlaier 112127145Smlaier wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 113126261Smlaier 114126261Smlaier dst = priv->ctrl_dst; 115126261Smlaier while (dst) { 116126258Smlaier if (fromlen == dst->addrlen && 117126261Smlaier os_memcmp(from->sun_path, dst->addr.sun_path, 118126261Smlaier fromlen - sizeof(from->sun_family)) == 0) { 119126261Smlaier wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " 120126258Smlaier "level", (u8 *) from->sun_path, 121126258Smlaier fromlen - sizeof(from->sun_family)); 122126258Smlaier dst->debug_level = atoi(level); 123126258Smlaier return 0; 124126258Smlaier } 125126258Smlaier dst = dst->next; 126126258Smlaier } 127126258Smlaier 128126258Smlaier return -1; 129126258Smlaier} 130126258Smlaier 131126258Smlaier 132126258Smlaierstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, 133126258Smlaier void *sock_ctx) 134126258Smlaier{ 135126258Smlaier struct wpa_supplicant *wpa_s = eloop_ctx; 136130613Smlaier struct ctrl_iface_priv *priv = sock_ctx; 137126258Smlaier char buf[256]; 138126258Smlaier int res; 139127145Smlaier struct sockaddr_un from; 140126261Smlaier socklen_t fromlen = sizeof(from); 141126261Smlaier char *reply = NULL; 142126258Smlaier size_t reply_len = 0; 143126261Smlaier int new_attached = 0; 144126258Smlaier 145126261Smlaier res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 146127145Smlaier (struct sockaddr *) &from, &fromlen); 147130613Smlaier if (res < 0) { 148126261Smlaier perror("recvfrom(ctrl_iface)"); 149126261Smlaier return; 150130613Smlaier } 151126258Smlaier buf[res] = '\0'; 152126261Smlaier 153126258Smlaier if (os_strcmp(buf, "ATTACH") == 0) { 154126258Smlaier if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) 155126258Smlaier reply_len = 1; 156126258Smlaier else { 157126258Smlaier new_attached = 1; 158126258Smlaier reply_len = 2; 159126258Smlaier } 160126258Smlaier } else if (os_strcmp(buf, "DETACH") == 0) { 161126258Smlaier if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) 162126258Smlaier reply_len = 1; 163126258Smlaier else 164126258Smlaier reply_len = 2; 165126258Smlaier } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 166126258Smlaier if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 167126258Smlaier buf + 6)) 168126258Smlaier reply_len = 1; 169126258Smlaier else 170126258Smlaier reply_len = 2; 171126258Smlaier } else { 172126258Smlaier reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf, 173126258Smlaier &reply_len); 174126258Smlaier } 175126258Smlaier 176126258Smlaier if (reply) { 177126258Smlaier sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 178130613Smlaier fromlen); 179126258Smlaier os_free(reply); 180126258Smlaier } else if (reply_len == 1) { 181126258Smlaier sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 182130613Smlaier fromlen); 183126258Smlaier } else if (reply_len == 2) { 184126258Smlaier sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 185126258Smlaier fromlen); 186126258Smlaier } 187130613Smlaier 188126258Smlaier if (new_attached) 189126258Smlaier eapol_sm_notify_ctrl_attached(wpa_s->eapol); 190126258Smlaier} 191130613Smlaier 192126258Smlaier 193126258Smlaierstatic char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s) 194126258Smlaier{ 195130613Smlaier char *buf; 196126258Smlaier size_t len; 197126258Smlaier char *pbuf, *dir = NULL, *gid_str = NULL; 198126258Smlaier int res; 199130613Smlaier 200126258Smlaier if (wpa_s->conf->ctrl_interface == NULL) 201126258Smlaier return NULL; 202126258Smlaier 203130613Smlaier pbuf = os_strdup(wpa_s->conf->ctrl_interface); 204126258Smlaier if (pbuf == NULL) 205126258Smlaier return NULL; 206126258Smlaier if (os_strncmp(pbuf, "DIR=", 4) == 0) { 207130613Smlaier dir = pbuf + 4; 208126258Smlaier gid_str = os_strstr(dir, " GROUP="); 209126258Smlaier if (gid_str) { 210130613Smlaier *gid_str = '\0'; 211126258Smlaier gid_str += 7; 212126258Smlaier } 213130613Smlaier } else 214126258Smlaier dir = pbuf; 215126258Smlaier 216130613Smlaier len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2; 217126258Smlaier buf = os_malloc(len); 218126258Smlaier if (buf == NULL) { 219130613Smlaier os_free(pbuf); 220126258Smlaier return NULL; 221126258Smlaier } 222130613Smlaier 223126258Smlaier res = os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname); 224130613Smlaier if (res < 0 || (size_t) res >= len) { 225130613Smlaier os_free(pbuf); 226126258Smlaier os_free(buf); 227130613Smlaier return NULL; 228130613Smlaier } 229126258Smlaier#ifdef __CYGWIN__ 230126258Smlaier { 231126258Smlaier /* Windows/WinPcap uses interface names that are not suitable 232126258Smlaier * as a file name - convert invalid chars to underscores */ 233130613Smlaier char *pos = buf; 234126258Smlaier while (*pos) { 235126258Smlaier if (*pos == '\\') 236126258Smlaier *pos = '_'; 237126258Smlaier pos++; 238126258Smlaier } 239126258Smlaier } 240126258Smlaier#endif /* __CYGWIN__ */ 241126258Smlaier os_free(pbuf); 242126258Smlaier return buf; 243126258Smlaier} 244126258Smlaier 245126258Smlaier 246126258Smlaierstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 247130613Smlaier const char *txt, size_t len) 248130613Smlaier{ 249130613Smlaier struct wpa_supplicant *wpa_s = ctx; 250126258Smlaier if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) 251127145Smlaier return; 252126261Smlaier wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); 253126258Smlaier} 254126261Smlaier 255126261Smlaier 256130613Smlaierstruct ctrl_iface_priv * 257130613Smlaierwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 258130613Smlaier{ 259130613Smlaier struct ctrl_iface_priv *priv; 260130613Smlaier struct sockaddr_un addr; 261126261Smlaier char *fname = NULL; 262126258Smlaier gid_t gid = 0; 263126258Smlaier int gid_set = 0; 264126258Smlaier char *buf, *dir = NULL, *gid_str = NULL; 265126258Smlaier struct group *grp; 266130613Smlaier char *endp; 267130613Smlaier 268126258Smlaier priv = os_zalloc(sizeof(*priv)); 269130613Smlaier if (priv == NULL) 270130613Smlaier return NULL; 271126258Smlaier priv->wpa_s = wpa_s; 272126258Smlaier priv->sock = -1; 273126258Smlaier 274126258Smlaier if (wpa_s->conf->ctrl_interface == NULL) 275126258Smlaier return priv; 276126258Smlaier 277126258Smlaier buf = os_strdup(wpa_s->conf->ctrl_interface); 278130613Smlaier if (buf == NULL) 279130613Smlaier goto fail; 280126258Smlaier if (os_strncmp(buf, "DIR=", 4) == 0) { 281126258Smlaier dir = buf + 4; 282126258Smlaier gid_str = os_strstr(dir, " GROUP="); 283126258Smlaier if (gid_str) { 284126258Smlaier *gid_str = '\0'; 285126258Smlaier gid_str += 7; 286126258Smlaier } 287126258Smlaier } else { 288126258Smlaier dir = buf; 289126258Smlaier gid_str = wpa_s->conf->ctrl_interface_group; 290126258Smlaier } 291130613Smlaier 292130613Smlaier if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) { 293130613Smlaier if (errno == EEXIST) { 294126258Smlaier wpa_printf(MSG_DEBUG, "Using existing control " 295130613Smlaier "interface directory."); 296130613Smlaier } else { 297130613Smlaier perror("mkdir[ctrl_interface]"); 298130613Smlaier goto fail; 299130613Smlaier } 300130613Smlaier } 301130613Smlaier 302126258Smlaier if (gid_str) { 303130613Smlaier grp = getgrnam(gid_str); 304130613Smlaier if (grp) { 305130613Smlaier gid = grp->gr_gid; 306130613Smlaier gid_set = 1; 307130613Smlaier wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" 308130613Smlaier " (from group name '%s')", 309130613Smlaier (int) gid, gid_str); 310130613Smlaier } else { 311130613Smlaier /* Group name not found - try to parse this as gid */ 312130613Smlaier gid = strtol(gid_str, &endp, 10); 313130613Smlaier if (*gid_str == '\0' || *endp != '\0') { 314130613Smlaier wpa_printf(MSG_ERROR, "CTRL: Invalid group " 315130613Smlaier "'%s'", gid_str); 316127145Smlaier goto fail; 317126409Smlaier } 318126409Smlaier gid_set = 1; 319126258Smlaier wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", 320126409Smlaier (int) gid); 321130613Smlaier } 322126258Smlaier } 323126258Smlaier 324126258Smlaier if (gid_set && chown(dir, -1, gid) < 0) { 325130613Smlaier perror("chown[ctrl_interface]"); 326130613Smlaier goto fail; 327130613Smlaier } 328130613Smlaier 329130613Smlaier if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >= 330130613Smlaier sizeof(addr.sun_path)) { 331130613Smlaier wpa_printf(MSG_ERROR, "ctrl_iface path limit exceeded"); 332130613Smlaier goto fail; 333130613Smlaier } 334130613Smlaier 335130613Smlaier priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 336130613Smlaier if (priv->sock < 0) { 337130613Smlaier perror("socket(PF_UNIX)"); 338130613Smlaier goto fail; 339130613Smlaier } 340130613Smlaier 341130613Smlaier os_memset(&addr, 0, sizeof(addr)); 342130613Smlaier addr.sun_family = AF_UNIX; 343130613Smlaier fname = wpa_supplicant_ctrl_iface_path(wpa_s); 344130613Smlaier if (fname == NULL) 345130613Smlaier goto fail; 346130613Smlaier os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 347130613Smlaier if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 348130613Smlaier wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 349130613Smlaier strerror(errno)); 350130613Smlaier if (connect(priv->sock, (struct sockaddr *) &addr, 351130613Smlaier sizeof(addr)) < 0) { 352130613Smlaier wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 353130613Smlaier " allow connections - assuming it was left" 354130613Smlaier "over from forced program termination"); 355130613Smlaier if (unlink(fname) < 0) { 356130613Smlaier perror("unlink[ctrl_iface]"); 357130613Smlaier wpa_printf(MSG_ERROR, "Could not unlink " 358130613Smlaier "existing ctrl_iface socket '%s'", 359130613Smlaier fname); 360130613Smlaier goto fail; 361130613Smlaier } 362130613Smlaier if (bind(priv->sock, (struct sockaddr *) &addr, 363130613Smlaier sizeof(addr)) < 0) { 364130613Smlaier perror("bind(PF_UNIX)"); 365130613Smlaier goto fail; 366130613Smlaier } 367130613Smlaier wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 368130613Smlaier "ctrl_iface socket '%s'", fname); 369130613Smlaier } else { 370130613Smlaier wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 371130613Smlaier "be in use - cannot override it"); 372130613Smlaier wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 373126258Smlaier "not used anymore", fname); 374126258Smlaier os_free(fname); 375126258Smlaier fname = NULL; 376126258Smlaier goto fail; 377126258Smlaier } 378126258Smlaier } 379126258Smlaier 380130613Smlaier if (gid_set && chown(fname, -1, gid) < 0) { 381126258Smlaier perror("chown[ctrl_interface/ifname]"); 382130613Smlaier goto fail; 383126258Smlaier } 384130613Smlaier 385126258Smlaier if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 386130613Smlaier perror("chmod[ctrl_interface/ifname]"); 387126258Smlaier goto fail; 388126258Smlaier } 389126258Smlaier os_free(fname); 390126258Smlaier 391126258Smlaier eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 392130613Smlaier wpa_s, priv); 393126258Smlaier wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 394130613Smlaier 395126258Smlaier os_free(buf); 396130613Smlaier return priv; 397126258Smlaier 398130613Smlaierfail: 399126258Smlaier if (priv->sock >= 0) 400130613Smlaier close(priv->sock); 401126258Smlaier os_free(priv); 402130613Smlaier if (fname) { 403126258Smlaier unlink(fname); 404130613Smlaier os_free(fname); 405126258Smlaier } 406130613Smlaier os_free(buf); 407126258Smlaier return NULL; 408130613Smlaier} 409126258Smlaier 410130613Smlaier 411126258Smlaiervoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 412130613Smlaier{ 413126258Smlaier struct wpa_ctrl_dst *dst, *prev; 414130613Smlaier 415126258Smlaier if (priv->sock > -1) { 416130613Smlaier char *fname; 417126258Smlaier char *buf, *dir = NULL, *gid_str = NULL; 418130613Smlaier eloop_unregister_read_sock(priv->sock); 419126258Smlaier if (priv->ctrl_dst) { 420130613Smlaier /* 421126258Smlaier * Wait a second before closing the control socket if 422130613Smlaier * there are any attached monitors in order to allow 423126258Smlaier * them to receive any pending messages. 424126258Smlaier */ 425126258Smlaier wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 426126258Smlaier "monitors to receive messages"); 427126258Smlaier os_sleep(1, 0); 428130613Smlaier } 429126258Smlaier close(priv->sock); 430130613Smlaier priv->sock = -1; 431126258Smlaier fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s); 432126258Smlaier if (fname) { 433126258Smlaier unlink(fname); 434126258Smlaier os_free(fname); 435126258Smlaier } 436130613Smlaier 437130613Smlaier buf = os_strdup(priv->wpa_s->conf->ctrl_interface); 438130613Smlaier if (buf == NULL) 439130613Smlaier goto free_dst; 440130613Smlaier if (os_strncmp(buf, "DIR=", 4) == 0) { 441130613Smlaier dir = buf + 4; 442130613Smlaier gid_str = os_strstr(dir, " GROUP="); 443130613Smlaier if (gid_str) { 444130613Smlaier *gid_str = '\0'; 445130613Smlaier gid_str += 7; 446130613Smlaier } 447130613Smlaier } else 448130613Smlaier dir = buf; 449130613Smlaier 450130613Smlaier if (rmdir(dir) < 0) { 451130613Smlaier if (errno == ENOTEMPTY) { 452130613Smlaier wpa_printf(MSG_DEBUG, "Control interface " 453130613Smlaier "directory not empty - leaving it " 454130613Smlaier "behind"); 455130613Smlaier } else { 456130613Smlaier perror("rmdir[ctrl_interface]"); 457130613Smlaier } 458130613Smlaier } 459130613Smlaier os_free(buf); 460130613Smlaier } 461130613Smlaier 462126258Smlaierfree_dst: 463130613Smlaier dst = priv->ctrl_dst; 464130613Smlaier while (dst) { 465130613Smlaier prev = dst; 466130613Smlaier dst = dst->next; 467130613Smlaier os_free(prev); 468130613Smlaier } 469130613Smlaier os_free(priv); 470130613Smlaier} 471130613Smlaier 472130613Smlaier 473130613Smlaier/** 474130613Smlaier * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors 475130613Smlaier * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() 476130613Smlaier * @level: Priority level of the message 477130613Smlaier * @buf: Message data 478130613Smlaier * @len: Message length 479130613Smlaier * 480130613Smlaier * Send a packet to all monitor programs attached to the control interface. 481130613Smlaier */ 482130613Smlaierstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 483130613Smlaier int level, const char *buf, 484130613Smlaier size_t len) 485130613Smlaier{ 486130613Smlaier struct wpa_ctrl_dst *dst, *next; 487130613Smlaier char levelstr[10]; 488130613Smlaier int idx, res; 489130613Smlaier struct msghdr msg; 490130613Smlaier struct iovec io[2]; 491130613Smlaier 492130613Smlaier dst = priv->ctrl_dst; 493130613Smlaier if (priv->sock < 0 || dst == NULL) 494130613Smlaier return; 495130613Smlaier 496130613Smlaier res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 497130613Smlaier if (res < 0 || (size_t) res >= sizeof(levelstr)) 498130613Smlaier return; 499130613Smlaier io[0].iov_base = levelstr; 500130613Smlaier io[0].iov_len = os_strlen(levelstr); 501130613Smlaier io[1].iov_base = (char *) buf; 502130613Smlaier io[1].iov_len = len; 503130613Smlaier os_memset(&msg, 0, sizeof(msg)); 504130613Smlaier msg.msg_iov = io; 505130613Smlaier msg.msg_iovlen = 2; 506130613Smlaier 507130613Smlaier idx = 0; 508130613Smlaier while (dst) { 509130613Smlaier next = dst->next; 510130613Smlaier if (level >= dst->debug_level) { 511130613Smlaier wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 512130613Smlaier (u8 *) dst->addr.sun_path, dst->addrlen - 513130613Smlaier sizeof(dst->addr.sun_family)); 514130613Smlaier msg.msg_name = (void *) &dst->addr; 515130613Smlaier msg.msg_namelen = dst->addrlen; 516130613Smlaier if (sendmsg(priv->sock, &msg, 0) < 0) { 517130613Smlaier perror("sendmsg(CTRL_IFACE monitor)"); 518130613Smlaier dst->errors++; 519130613Smlaier if (dst->errors > 10) { 520130613Smlaier wpa_supplicant_ctrl_iface_detach( 521130613Smlaier priv, &dst->addr, 522130613Smlaier dst->addrlen); 523130613Smlaier } 524130613Smlaier } else 525130613Smlaier dst->errors = 0; 526130613Smlaier } 527130613Smlaier idx++; 528126258Smlaier dst = next; 529126258Smlaier } 530126258Smlaier} 531126258Smlaier 532126258Smlaier 533126258Smlaiervoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 534126258Smlaier{ 535126258Smlaier char buf[256]; 536126258Smlaier int res; 537126258Smlaier struct sockaddr_un from; 538126258Smlaier socklen_t fromlen = sizeof(from); 539126258Smlaier 540126258Smlaier for (;;) { 541126258Smlaier wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to " 542126258Smlaier "attach", priv->wpa_s->ifname); 543126258Smlaier eloop_wait_for_read_sock(priv->sock); 544126258Smlaier 545126258Smlaier res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0, 546126258Smlaier (struct sockaddr *) &from, &fromlen); 547126258Smlaier if (res < 0) { 548130613Smlaier perror("recvfrom(ctrl_iface)"); 549126258Smlaier continue; 550130613Smlaier } 551130613Smlaier buf[res] = '\0'; 552130613Smlaier 553126258Smlaier if (os_strcmp(buf, "ATTACH") == 0) { 554130613Smlaier /* handle ATTACH signal of first monitor interface */ 555130613Smlaier if (!wpa_supplicant_ctrl_iface_attach(priv, &from, 556130613Smlaier fromlen)) { 557130613Smlaier sendto(priv->sock, "OK\n", 3, 0, 558130613Smlaier (struct sockaddr *) &from, fromlen); 559126258Smlaier /* OK to continue */ 560130613Smlaier return; 561130613Smlaier } else { 562130613Smlaier sendto(priv->sock, "FAIL\n", 5, 0, 563130613Smlaier (struct sockaddr *) &from, fromlen); 564130613Smlaier } 565130613Smlaier } else { 566130613Smlaier /* return FAIL for all other signals */ 567130613Smlaier sendto(priv->sock, "FAIL\n", 5, 0, 568130613Smlaier (struct sockaddr *) &from, fromlen); 569126258Smlaier } 570130613Smlaier } 571130613Smlaier} 572130613Smlaier 573130613Smlaier 574130613Smlaier/* Global ctrl_iface */ 575130613Smlaier 576130613Smlaierstruct ctrl_iface_global_priv { 577130613Smlaier struct wpa_global *global; 578130613Smlaier int sock; 579130613Smlaier}; 580130613Smlaier 581126258Smlaier 582126258Smlaierstatic void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 583130613Smlaier void *sock_ctx) 584130613Smlaier{ 585130613Smlaier struct wpa_global *global = eloop_ctx; 586130613Smlaier char buf[256]; 587130613Smlaier int res; 588130613Smlaier struct sockaddr_un from; 589130613Smlaier socklen_t fromlen = sizeof(from); 590130613Smlaier char *reply; 591130613Smlaier size_t reply_len; 592130613Smlaier 593130613Smlaier res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 594130613Smlaier (struct sockaddr *) &from, &fromlen); 595130613Smlaier if (res < 0) { 596130613Smlaier perror("recvfrom(ctrl_iface)"); 597130613Smlaier return; 598130613Smlaier } 599130613Smlaier buf[res] = '\0'; 600130613Smlaier 601130613Smlaier reply = wpa_supplicant_global_ctrl_iface_process(global, buf, 602130613Smlaier &reply_len); 603130613Smlaier 604130613Smlaier if (reply) { 605130613Smlaier sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 606130613Smlaier fromlen); 607130613Smlaier os_free(reply); 608130613Smlaier } else if (reply_len) { 609130613Smlaier sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 610130613Smlaier fromlen); 611130613Smlaier } 612130613Smlaier} 613130613Smlaier 614130613Smlaier 615130613Smlaierstruct ctrl_iface_global_priv * 616130613Smlaierwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 617130613Smlaier{ 618130613Smlaier struct ctrl_iface_global_priv *priv; 619130613Smlaier struct sockaddr_un addr; 620130613Smlaier 621126258Smlaier priv = os_zalloc(sizeof(*priv)); 622130613Smlaier if (priv == NULL) 623130613Smlaier return NULL; 624126258Smlaier priv->global = global; 625130613Smlaier priv->sock = -1; 626126258Smlaier 627130613Smlaier if (global->params.ctrl_interface == NULL) 628130613Smlaier return priv; 629130613Smlaier 630130613Smlaier wpa_printf(MSG_DEBUG, "Global control interface '%s'", 631130613Smlaier global->params.ctrl_interface); 632130613Smlaier 633130613Smlaier priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 634130613Smlaier if (priv->sock < 0) { 635130613Smlaier perror("socket(PF_UNIX)"); 636130613Smlaier goto fail; 637130613Smlaier } 638130613Smlaier 639130613Smlaier os_memset(&addr, 0, sizeof(addr)); 640130613Smlaier addr.sun_family = AF_UNIX; 641130613Smlaier os_strlcpy(addr.sun_path, global->params.ctrl_interface, 642130613Smlaier sizeof(addr.sun_path)); 643130613Smlaier if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 644130613Smlaier perror("bind(PF_UNIX)"); 645130613Smlaier if (connect(priv->sock, (struct sockaddr *) &addr, 646130613Smlaier sizeof(addr)) < 0) { 647130613Smlaier wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 648130613Smlaier " allow connections - assuming it was left" 649130613Smlaier "over from forced program termination"); 650130613Smlaier if (unlink(global->params.ctrl_interface) < 0) { 651130613Smlaier perror("unlink[ctrl_iface]"); 652130613Smlaier wpa_printf(MSG_ERROR, "Could not unlink " 653130613Smlaier "existing ctrl_iface socket '%s'", 654130613Smlaier global->params.ctrl_interface); 655130613Smlaier goto fail; 656130613Smlaier } 657130613Smlaier if (bind(priv->sock, (struct sockaddr *) &addr, 658130613Smlaier sizeof(addr)) < 0) { 659130613Smlaier perror("bind(PF_UNIX)"); 660130613Smlaier goto fail; 661130613Smlaier } 662130613Smlaier wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 663130613Smlaier "ctrl_iface socket '%s'", 664130613Smlaier global->params.ctrl_interface); 665130613Smlaier } else { 666130613Smlaier wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 667130613Smlaier "be in use - cannot override it"); 668130613Smlaier wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 669130613Smlaier "not used anymore", 670130613Smlaier global->params.ctrl_interface); 671130613Smlaier goto fail; 672130613Smlaier } 673130613Smlaier } 674130613Smlaier 675130613Smlaier eloop_register_read_sock(priv->sock, 676130613Smlaier wpa_supplicant_global_ctrl_iface_receive, 677130613Smlaier global, NULL); 678130613Smlaier 679126258Smlaier return priv; 680130613Smlaier 681130613Smlaierfail: 682130613Smlaier if (priv->sock >= 0) 683126258Smlaier close(priv->sock); 684130613Smlaier os_free(priv); 685130613Smlaier return NULL; 686126258Smlaier} 687126258Smlaier 688126258Smlaier 689126258Smlaiervoid 690126258Smlaierwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 691126258Smlaier{ 692126258Smlaier if (priv->sock >= 0) { 693126258Smlaier eloop_unregister_read_sock(priv->sock); 694126258Smlaier close(priv->sock); 695126258Smlaier } 696126258Smlaier if (priv->global->params.ctrl_interface) 697130613Smlaier unlink(priv->global->params.ctrl_interface); 698130613Smlaier os_free(priv); 699126258Smlaier} 700126258Smlaier