1189251Ssam/* 2189251Ssam * WPA Supplicant / UDP socket -based control interface 3189251Ssam * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> 4189251Ssam * 5189251Ssam * This program is free software; you can redistribute it and/or modify 6189251Ssam * it under the terms of the GNU General Public License version 2 as 7189251Ssam * published by the Free Software Foundation. 8189251Ssam * 9189251Ssam * Alternatively, this software may be distributed under the terms of BSD 10189251Ssam * license. 11189251Ssam * 12189251Ssam * See README and COPYING for more details. 13189251Ssam */ 14189251Ssam 15189251Ssam#include "includes.h" 16189251Ssam 17189251Ssam#include "common.h" 18189251Ssam#include "eloop.h" 19189251Ssam#include "config.h" 20189251Ssam#include "eapol_supp/eapol_supp_sm.h" 21189251Ssam#include "wpa_supplicant_i.h" 22189251Ssam#include "ctrl_iface.h" 23214734Srpaulo#include "common/wpa_ctrl.h" 24189251Ssam 25189251Ssam 26189251Ssam#define COOKIE_LEN 8 27189251Ssam 28189251Ssam/* Per-interface ctrl_iface */ 29189251Ssam 30189251Ssam/** 31189251Ssam * struct wpa_ctrl_dst - Internal data structure of control interface monitors 32189251Ssam * 33189251Ssam * This structure is used to store information about registered control 34189251Ssam * interface monitors into struct wpa_supplicant. This data is private to 35189251Ssam * ctrl_iface_udp.c and should not be touched directly from other files. 36189251Ssam */ 37189251Ssamstruct wpa_ctrl_dst { 38189251Ssam struct wpa_ctrl_dst *next; 39189251Ssam struct sockaddr_in addr; 40189251Ssam socklen_t addrlen; 41189251Ssam int debug_level; 42189251Ssam int errors; 43189251Ssam}; 44189251Ssam 45189251Ssam 46189251Ssamstruct ctrl_iface_priv { 47189251Ssam struct wpa_supplicant *wpa_s; 48189251Ssam int sock; 49189251Ssam struct wpa_ctrl_dst *ctrl_dst; 50189251Ssam u8 cookie[COOKIE_LEN]; 51189251Ssam}; 52189251Ssam 53189251Ssam 54189251Ssamstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 55189251Ssam int level, const char *buf, 56189251Ssam size_t len); 57189251Ssam 58189251Ssam 59189251Ssamstatic int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv, 60189251Ssam struct sockaddr_in *from, 61189251Ssam socklen_t fromlen) 62189251Ssam{ 63189251Ssam struct wpa_ctrl_dst *dst; 64189251Ssam 65189251Ssam dst = os_zalloc(sizeof(*dst)); 66189251Ssam if (dst == NULL) 67189251Ssam return -1; 68189251Ssam os_memcpy(&dst->addr, from, sizeof(struct sockaddr_in)); 69189251Ssam dst->addrlen = fromlen; 70189251Ssam dst->debug_level = MSG_INFO; 71189251Ssam dst->next = priv->ctrl_dst; 72189251Ssam priv->ctrl_dst = dst; 73189251Ssam wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d", 74189251Ssam inet_ntoa(from->sin_addr), ntohs(from->sin_port)); 75189251Ssam return 0; 76189251Ssam} 77189251Ssam 78189251Ssam 79189251Ssamstatic int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv, 80189251Ssam struct sockaddr_in *from, 81189251Ssam socklen_t fromlen) 82189251Ssam{ 83189251Ssam struct wpa_ctrl_dst *dst, *prev = NULL; 84189251Ssam 85189251Ssam dst = priv->ctrl_dst; 86189251Ssam while (dst) { 87189251Ssam if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && 88189251Ssam from->sin_port == dst->addr.sin_port) { 89189251Ssam if (prev == NULL) 90189251Ssam priv->ctrl_dst = dst->next; 91189251Ssam else 92189251Ssam prev->next = dst->next; 93189251Ssam os_free(dst); 94189251Ssam wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached " 95189251Ssam "%s:%d", inet_ntoa(from->sin_addr), 96189251Ssam ntohs(from->sin_port)); 97189251Ssam return 0; 98189251Ssam } 99189251Ssam prev = dst; 100189251Ssam dst = dst->next; 101189251Ssam } 102189251Ssam return -1; 103189251Ssam} 104189251Ssam 105189251Ssam 106189251Ssamstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, 107189251Ssam struct sockaddr_in *from, 108189251Ssam socklen_t fromlen, 109189251Ssam char *level) 110189251Ssam{ 111189251Ssam struct wpa_ctrl_dst *dst; 112189251Ssam 113189251Ssam wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 114189251Ssam 115189251Ssam dst = priv->ctrl_dst; 116189251Ssam while (dst) { 117189251Ssam if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && 118189251Ssam from->sin_port == dst->addr.sin_port) { 119189251Ssam wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor " 120189251Ssam "level %s:%d", inet_ntoa(from->sin_addr), 121189251Ssam ntohs(from->sin_port)); 122189251Ssam dst->debug_level = atoi(level); 123189251Ssam return 0; 124189251Ssam } 125189251Ssam dst = dst->next; 126189251Ssam } 127189251Ssam 128189251Ssam return -1; 129189251Ssam} 130189251Ssam 131189251Ssam 132189251Ssamstatic char * 133189251Ssamwpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv, 134189251Ssam size_t *reply_len) 135189251Ssam{ 136189251Ssam char *reply; 137189251Ssam reply = os_malloc(7 + 2 * COOKIE_LEN + 1); 138189251Ssam if (reply == NULL) { 139189251Ssam *reply_len = 1; 140189251Ssam return NULL; 141189251Ssam } 142189251Ssam 143189251Ssam os_memcpy(reply, "COOKIE=", 7); 144189251Ssam wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 145189251Ssam priv->cookie, COOKIE_LEN); 146189251Ssam 147189251Ssam *reply_len = 7 + 2 * COOKIE_LEN; 148189251Ssam return reply; 149189251Ssam} 150189251Ssam 151189251Ssam 152189251Ssamstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, 153189251Ssam void *sock_ctx) 154189251Ssam{ 155189251Ssam struct wpa_supplicant *wpa_s = eloop_ctx; 156189251Ssam struct ctrl_iface_priv *priv = sock_ctx; 157189251Ssam char buf[256], *pos; 158189251Ssam int res; 159189251Ssam struct sockaddr_in from; 160189251Ssam socklen_t fromlen = sizeof(from); 161189251Ssam char *reply = NULL; 162189251Ssam size_t reply_len = 0; 163189251Ssam int new_attached = 0; 164189251Ssam u8 cookie[COOKIE_LEN]; 165189251Ssam 166189251Ssam res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 167189251Ssam (struct sockaddr *) &from, &fromlen); 168189251Ssam if (res < 0) { 169189251Ssam perror("recvfrom(ctrl_iface)"); 170189251Ssam return; 171189251Ssam } 172189251Ssam if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 173189251Ssam /* 174189251Ssam * The OS networking stack is expected to drop this kind of 175189251Ssam * frames since the socket is bound to only localhost address. 176189251Ssam * Just in case, drop the frame if it is coming from any other 177189251Ssam * address. 178189251Ssam */ 179189251Ssam wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 180189251Ssam "source %s", inet_ntoa(from.sin_addr)); 181189251Ssam return; 182189251Ssam } 183189251Ssam buf[res] = '\0'; 184189251Ssam 185189251Ssam if (os_strcmp(buf, "GET_COOKIE") == 0) { 186189251Ssam reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len); 187189251Ssam goto done; 188189251Ssam } 189189251Ssam 190189251Ssam /* 191189251Ssam * Require that the client includes a prefix with the 'cookie' value 192189251Ssam * fetched with GET_COOKIE command. This is used to verify that the 193189251Ssam * client has access to a bidirectional link over UDP in order to 194189251Ssam * avoid attacks using forged localhost IP address even if the OS does 195189251Ssam * not block such frames from remote destinations. 196189251Ssam */ 197189251Ssam if (os_strncmp(buf, "COOKIE=", 7) != 0) { 198189251Ssam wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 199189251Ssam "drop request"); 200189251Ssam return; 201189251Ssam } 202189251Ssam 203189251Ssam if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 204189251Ssam wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 205189251Ssam "request - drop request"); 206189251Ssam return; 207189251Ssam } 208189251Ssam 209189251Ssam if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 210189251Ssam wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 211189251Ssam "drop request"); 212189251Ssam return; 213189251Ssam } 214189251Ssam 215189251Ssam pos = buf + 7 + 2 * COOKIE_LEN; 216189251Ssam while (*pos == ' ') 217189251Ssam pos++; 218189251Ssam 219189251Ssam if (os_strcmp(pos, "ATTACH") == 0) { 220189251Ssam if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) 221189251Ssam reply_len = 1; 222189251Ssam else { 223189251Ssam new_attached = 1; 224189251Ssam reply_len = 2; 225189251Ssam } 226189251Ssam } else if (os_strcmp(pos, "DETACH") == 0) { 227189251Ssam if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) 228189251Ssam reply_len = 1; 229189251Ssam else 230189251Ssam reply_len = 2; 231189251Ssam } else if (os_strncmp(pos, "LEVEL ", 6) == 0) { 232189251Ssam if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 233189251Ssam pos + 6)) 234189251Ssam reply_len = 1; 235189251Ssam else 236189251Ssam reply_len = 2; 237189251Ssam } else { 238189251Ssam reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos, 239189251Ssam &reply_len); 240189251Ssam } 241189251Ssam 242189251Ssam done: 243189251Ssam if (reply) { 244189251Ssam sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 245189251Ssam fromlen); 246189251Ssam os_free(reply); 247189251Ssam } else if (reply_len == 1) { 248189251Ssam sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 249189251Ssam fromlen); 250189251Ssam } else if (reply_len == 2) { 251189251Ssam sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 252189251Ssam fromlen); 253189251Ssam } 254189251Ssam 255189251Ssam if (new_attached) 256189251Ssam eapol_sm_notify_ctrl_attached(wpa_s->eapol); 257189251Ssam} 258189251Ssam 259189251Ssam 260189251Ssamstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 261189251Ssam const char *txt, size_t len) 262189251Ssam{ 263189251Ssam struct wpa_supplicant *wpa_s = ctx; 264189251Ssam if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) 265189251Ssam return; 266189251Ssam wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); 267189251Ssam} 268189251Ssam 269189251Ssam 270189251Ssamstruct ctrl_iface_priv * 271189251Ssamwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 272189251Ssam{ 273189251Ssam struct ctrl_iface_priv *priv; 274189251Ssam struct sockaddr_in addr; 275189251Ssam 276189251Ssam priv = os_zalloc(sizeof(*priv)); 277189251Ssam if (priv == NULL) 278189251Ssam return NULL; 279189251Ssam priv->wpa_s = wpa_s; 280189251Ssam priv->sock = -1; 281189251Ssam os_get_random(priv->cookie, COOKIE_LEN); 282189251Ssam 283189251Ssam if (wpa_s->conf->ctrl_interface == NULL) 284189251Ssam return priv; 285189251Ssam 286189251Ssam priv->sock = socket(PF_INET, SOCK_DGRAM, 0); 287189251Ssam if (priv->sock < 0) { 288189251Ssam perror("socket(PF_INET)"); 289189251Ssam goto fail; 290189251Ssam } 291189251Ssam 292189251Ssam os_memset(&addr, 0, sizeof(addr)); 293189251Ssam addr.sin_family = AF_INET; 294189251Ssam addr.sin_addr.s_addr = htonl((127 << 24) | 1); 295189251Ssam addr.sin_port = htons(WPA_CTRL_IFACE_PORT); 296189251Ssam if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 297189251Ssam perror("bind(AF_INET)"); 298189251Ssam goto fail; 299189251Ssam } 300189251Ssam 301189251Ssam eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 302189251Ssam wpa_s, priv); 303189251Ssam wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 304189251Ssam 305189251Ssam return priv; 306189251Ssam 307189251Ssamfail: 308189251Ssam if (priv->sock >= 0) 309189251Ssam close(priv->sock); 310189251Ssam os_free(priv); 311189251Ssam return NULL; 312189251Ssam} 313189251Ssam 314189251Ssam 315189251Ssamvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 316189251Ssam{ 317189251Ssam struct wpa_ctrl_dst *dst, *prev; 318189251Ssam 319189251Ssam if (priv->sock > -1) { 320189251Ssam eloop_unregister_read_sock(priv->sock); 321189251Ssam if (priv->ctrl_dst) { 322189251Ssam /* 323189251Ssam * Wait a second before closing the control socket if 324189251Ssam * there are any attached monitors in order to allow 325189251Ssam * them to receive any pending messages. 326189251Ssam */ 327189251Ssam wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 328189251Ssam "monitors to receive messages"); 329189251Ssam os_sleep(1, 0); 330189251Ssam } 331189251Ssam close(priv->sock); 332189251Ssam priv->sock = -1; 333189251Ssam } 334189251Ssam 335189251Ssam dst = priv->ctrl_dst; 336189251Ssam while (dst) { 337189251Ssam prev = dst; 338189251Ssam dst = dst->next; 339189251Ssam os_free(prev); 340189251Ssam } 341189251Ssam os_free(priv); 342189251Ssam} 343189251Ssam 344189251Ssam 345189251Ssamstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 346189251Ssam int level, const char *buf, 347189251Ssam size_t len) 348189251Ssam{ 349189251Ssam struct wpa_ctrl_dst *dst, *next; 350189251Ssam char levelstr[10]; 351189251Ssam int idx; 352189251Ssam char *sbuf; 353189251Ssam int llen; 354189251Ssam 355189251Ssam dst = priv->ctrl_dst; 356189251Ssam if (priv->sock < 0 || dst == NULL) 357189251Ssam return; 358189251Ssam 359189251Ssam os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 360189251Ssam 361189251Ssam llen = os_strlen(levelstr); 362189251Ssam sbuf = os_malloc(llen + len); 363189251Ssam if (sbuf == NULL) 364189251Ssam return; 365189251Ssam 366189251Ssam os_memcpy(sbuf, levelstr, llen); 367189251Ssam os_memcpy(sbuf + llen, buf, len); 368189251Ssam 369189251Ssam idx = 0; 370189251Ssam while (dst) { 371189251Ssam next = dst->next; 372189251Ssam if (level >= dst->debug_level) { 373189251Ssam wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", 374189251Ssam inet_ntoa(dst->addr.sin_addr), 375189251Ssam ntohs(dst->addr.sin_port)); 376189251Ssam if (sendto(priv->sock, sbuf, llen + len, 0, 377189251Ssam (struct sockaddr *) &dst->addr, 378189251Ssam sizeof(dst->addr)) < 0) { 379189251Ssam perror("sendto(CTRL_IFACE monitor)"); 380189251Ssam dst->errors++; 381189251Ssam if (dst->errors > 10) { 382189251Ssam wpa_supplicant_ctrl_iface_detach( 383189251Ssam priv, &dst->addr, 384189251Ssam dst->addrlen); 385189251Ssam } 386189251Ssam } else 387189251Ssam dst->errors = 0; 388189251Ssam } 389189251Ssam idx++; 390189251Ssam dst = next; 391189251Ssam } 392189251Ssam os_free(sbuf); 393189251Ssam} 394189251Ssam 395189251Ssam 396189251Ssamvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 397189251Ssam{ 398189251Ssam wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor", 399189251Ssam priv->wpa_s->ifname); 400189251Ssam eloop_wait_for_read_sock(priv->sock); 401189251Ssam} 402189251Ssam 403189251Ssam 404189251Ssam/* Global ctrl_iface */ 405189251Ssam 406189251Ssamstruct ctrl_iface_global_priv { 407189251Ssam int sock; 408189251Ssam u8 cookie[COOKIE_LEN]; 409189251Ssam}; 410189251Ssam 411189251Ssam 412189251Ssamstatic char * 413189251Ssamwpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv, 414189251Ssam size_t *reply_len) 415189251Ssam{ 416189251Ssam char *reply; 417189251Ssam reply = os_malloc(7 + 2 * COOKIE_LEN + 1); 418189251Ssam if (reply == NULL) { 419189251Ssam *reply_len = 1; 420189251Ssam return NULL; 421189251Ssam } 422189251Ssam 423189251Ssam os_memcpy(reply, "COOKIE=", 7); 424189251Ssam wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 425189251Ssam priv->cookie, COOKIE_LEN); 426189251Ssam 427189251Ssam *reply_len = 7 + 2 * COOKIE_LEN; 428189251Ssam return reply; 429189251Ssam} 430189251Ssam 431189251Ssam 432189251Ssamstatic void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 433189251Ssam void *sock_ctx) 434189251Ssam{ 435189251Ssam struct wpa_global *global = eloop_ctx; 436189251Ssam struct ctrl_iface_global_priv *priv = sock_ctx; 437189251Ssam char buf[256], *pos; 438189251Ssam int res; 439189251Ssam struct sockaddr_in from; 440189251Ssam socklen_t fromlen = sizeof(from); 441189251Ssam char *reply; 442189251Ssam size_t reply_len; 443189251Ssam u8 cookie[COOKIE_LEN]; 444189251Ssam 445189251Ssam res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 446189251Ssam (struct sockaddr *) &from, &fromlen); 447189251Ssam if (res < 0) { 448189251Ssam perror("recvfrom(ctrl_iface)"); 449189251Ssam return; 450189251Ssam } 451189251Ssam if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 452189251Ssam /* 453189251Ssam * The OS networking stack is expected to drop this kind of 454189251Ssam * frames since the socket is bound to only localhost address. 455189251Ssam * Just in case, drop the frame if it is coming from any other 456189251Ssam * address. 457189251Ssam */ 458189251Ssam wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 459189251Ssam "source %s", inet_ntoa(from.sin_addr)); 460189251Ssam return; 461189251Ssam } 462189251Ssam buf[res] = '\0'; 463189251Ssam 464189251Ssam if (os_strcmp(buf, "GET_COOKIE") == 0) { 465189251Ssam reply = wpa_supplicant_global_get_cookie(priv, &reply_len); 466189251Ssam goto done; 467189251Ssam } 468189251Ssam 469189251Ssam if (os_strncmp(buf, "COOKIE=", 7) != 0) { 470189251Ssam wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 471189251Ssam "drop request"); 472189251Ssam return; 473189251Ssam } 474189251Ssam 475189251Ssam if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 476189251Ssam wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 477189251Ssam "request - drop request"); 478189251Ssam return; 479189251Ssam } 480189251Ssam 481189251Ssam if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 482189251Ssam wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 483189251Ssam "drop request"); 484189251Ssam return; 485189251Ssam } 486189251Ssam 487189251Ssam pos = buf + 7 + 2 * COOKIE_LEN; 488189251Ssam while (*pos == ' ') 489189251Ssam pos++; 490189251Ssam 491189251Ssam reply = wpa_supplicant_global_ctrl_iface_process(global, pos, 492189251Ssam &reply_len); 493189251Ssam 494189251Ssam done: 495189251Ssam if (reply) { 496189251Ssam sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 497189251Ssam fromlen); 498189251Ssam os_free(reply); 499189251Ssam } else if (reply_len) { 500189251Ssam sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 501189251Ssam fromlen); 502189251Ssam } 503189251Ssam} 504189251Ssam 505189251Ssam 506189251Ssamstruct ctrl_iface_global_priv * 507189251Ssamwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 508189251Ssam{ 509189251Ssam struct ctrl_iface_global_priv *priv; 510189251Ssam struct sockaddr_in addr; 511189251Ssam 512189251Ssam priv = os_zalloc(sizeof(*priv)); 513189251Ssam if (priv == NULL) 514189251Ssam return NULL; 515189251Ssam priv->sock = -1; 516189251Ssam os_get_random(priv->cookie, COOKIE_LEN); 517189251Ssam 518189251Ssam if (global->params.ctrl_interface == NULL) 519189251Ssam return priv; 520189251Ssam 521189251Ssam wpa_printf(MSG_DEBUG, "Global control interface '%s'", 522189251Ssam global->params.ctrl_interface); 523189251Ssam 524189251Ssam priv->sock = socket(PF_INET, SOCK_DGRAM, 0); 525189251Ssam if (priv->sock < 0) { 526189251Ssam perror("socket(PF_INET)"); 527189251Ssam goto fail; 528189251Ssam } 529189251Ssam 530189251Ssam os_memset(&addr, 0, sizeof(addr)); 531189251Ssam addr.sin_family = AF_INET; 532189251Ssam addr.sin_addr.s_addr = htonl((127 << 24) | 1); 533189251Ssam addr.sin_port = htons(WPA_GLOBAL_CTRL_IFACE_PORT); 534189251Ssam if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 535189251Ssam perror("bind(AF_INET)"); 536189251Ssam goto fail; 537189251Ssam } 538189251Ssam 539189251Ssam eloop_register_read_sock(priv->sock, 540189251Ssam wpa_supplicant_global_ctrl_iface_receive, 541189251Ssam global, priv); 542189251Ssam 543189251Ssam return priv; 544189251Ssam 545189251Ssamfail: 546189251Ssam if (priv->sock >= 0) 547189251Ssam close(priv->sock); 548189251Ssam os_free(priv); 549189251Ssam return NULL; 550189251Ssam} 551189251Ssam 552189251Ssam 553189251Ssamvoid 554189251Ssamwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 555189251Ssam{ 556189251Ssam if (priv->sock >= 0) { 557189251Ssam eloop_unregister_read_sock(priv->sock); 558189251Ssam close(priv->sock); 559189251Ssam } 560189251Ssam os_free(priv); 561189251Ssam} 562