Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * WPA Supplicant / UDP socket -based control interface
      3  * Copyright (c) 2004-2016, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "eloop.h"
     13 #include "config.h"
     14 #include "eapol_supp/eapol_supp_sm.h"
     15 #include "wpa_supplicant_i.h"
     16 #include "ctrl_iface.h"
     17 #include "common/wpa_ctrl.h"
     18 
     19 
     20 #define COOKIE_LEN 8
     21 
     22 /* Per-interface ctrl_iface */
     23 
     24 /**
     25  * struct wpa_ctrl_dst - Internal data structure of control interface monitors
     26  *
     27  * This structure is used to store information about registered control
     28  * interface monitors into struct wpa_supplicant. This data is private to
     29  * ctrl_iface_udp.c and should not be touched directly from other files.
     30  */
     31 struct wpa_ctrl_dst {
     32 	struct wpa_ctrl_dst *next;
     33 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
     34 	struct sockaddr_in6 addr;
     35 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
     36 	struct sockaddr_in addr;
     37 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
     38 	socklen_t addrlen;
     39 	int debug_level;
     40 	int errors;
     41 };
     42 
     43 
     44 struct ctrl_iface_priv {
     45 	struct wpa_supplicant *wpa_s;
     46 	int sock;
     47 	struct wpa_ctrl_dst *ctrl_dst;
     48 	u8 cookie[COOKIE_LEN];
     49 };
     50 
     51 struct ctrl_iface_global_priv {
     52 	int sock;
     53 	struct wpa_ctrl_dst *ctrl_dst;
     54 	u8 cookie[COOKIE_LEN];
     55 };
     56 
     57 
     58 static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
     59 					   const char *ifname, int sock,
     60 					   struct wpa_ctrl_dst **head,
     61 					   int level, const char *buf,
     62 					   size_t len);
     63 
     64 
     65 static void wpas_ctrl_iface_free_dst(struct wpa_ctrl_dst *dst)
     66 {
     67 	struct wpa_ctrl_dst *prev;
     68 
     69 	while (dst) {
     70 		prev = dst;
     71 		dst = dst->next;
     72 		os_free(prev);
     73 	}
     74 }
     75 
     76 
     77 static int wpa_supplicant_ctrl_iface_attach(struct wpa_ctrl_dst **head,
     78 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
     79 					    struct sockaddr_in6 *from,
     80 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
     81 					    struct sockaddr_in *from,
     82 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
     83 					    socklen_t fromlen)
     84 {
     85 	struct wpa_ctrl_dst *dst;
     86 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
     87 	char addr[INET6_ADDRSTRLEN];
     88 #endif /* CONFIG_UDP_IPV6 */
     89 
     90 	dst = os_zalloc(sizeof(*dst));
     91 	if (dst == NULL)
     92 		return -1;
     93 	os_memcpy(&dst->addr, from, sizeof(*from));
     94 	dst->addrlen = fromlen;
     95 	dst->debug_level = MSG_INFO;
     96 	dst->next = *head;
     97 	*head = dst;
     98 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
     99 	wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
    100 		   inet_ntop(AF_INET6, &from->sin6_addr, addr, sizeof(*from)),
    101 		   ntohs(from->sin6_port));
    102 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    103 	wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
    104 		   inet_ntoa(from->sin_addr), ntohs(from->sin_port));
    105 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    106 	return 0;
    107 }
    108 
    109 
    110 static int wpa_supplicant_ctrl_iface_detach(struct wpa_ctrl_dst **head,
    111 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    112 					    struct sockaddr_in6 *from,
    113 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    114 					    struct sockaddr_in *from,
    115 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    116 					    socklen_t fromlen)
    117 {
    118 	struct wpa_ctrl_dst *dst, *prev = NULL;
    119 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    120 	char addr[INET6_ADDRSTRLEN];
    121 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    122 
    123 	dst = *head;
    124 	while (dst) {
    125 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    126 		if (from->sin6_port == dst->addr.sin6_port &&
    127 		    !os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr,
    128 			       sizeof(from->sin6_addr))) {
    129 			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s:%d",
    130 				   inet_ntop(AF_INET6, &from->sin6_addr, addr,
    131 					     sizeof(*from)),
    132 				   ntohs(from->sin6_port));
    133 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    134 		if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
    135 		    from->sin_port == dst->addr.sin_port) {
    136 			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
    137 				   "%s:%d", inet_ntoa(from->sin_addr),
    138 				   ntohs(from->sin_port));
    139 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    140 			if (prev == NULL)
    141 				*head = dst->next;
    142 			else
    143 				prev->next = dst->next;
    144 			os_free(dst);
    145 			return 0;
    146 		}
    147 		prev = dst;
    148 		dst = dst->next;
    149 	}
    150 	return -1;
    151 }
    152 
    153 
    154 static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
    155 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    156 					   struct sockaddr_in6 *from,
    157 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    158 					   struct sockaddr_in *from,
    159 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    160 					   socklen_t fromlen,
    161 					   char *level)
    162 {
    163 	struct wpa_ctrl_dst *dst;
    164 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    165 	char addr[INET6_ADDRSTRLEN];
    166 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    167 
    168 	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
    169 
    170 	dst = priv->ctrl_dst;
    171 	while (dst) {
    172 #if CONFIG_CTRL_IFACE_UDP_IPV6
    173 		if (from->sin6_port == dst->addr.sin6_port &&
    174 		    !os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr,
    175 			       sizeof(from->sin6_addr))) {
    176 			wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor level %s:%d",
    177 				   inet_ntop(AF_INET6, &from->sin6_addr, addr,
    178 					     sizeof(*from)),
    179 				   ntohs(from->sin6_port));
    180 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    181 		if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
    182 		    from->sin_port == dst->addr.sin_port) {
    183 			wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
    184 				   "level %s:%d", inet_ntoa(from->sin_addr),
    185 				   ntohs(from->sin_port));
    186 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    187 			dst->debug_level = atoi(level);
    188 			return 0;
    189 		}
    190 		dst = dst->next;
    191 	}
    192 
    193 	return -1;
    194 }
    195 
    196 
    197 static char *
    198 wpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv,
    199 				     size_t *reply_len)
    200 {
    201 	char *reply;
    202 	reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
    203 	if (reply == NULL) {
    204 		*reply_len = 1;
    205 		return NULL;
    206 	}
    207 
    208 	os_memcpy(reply, "COOKIE=", 7);
    209 	wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
    210 			 priv->cookie, COOKIE_LEN);
    211 
    212 	*reply_len = 7 + 2 * COOKIE_LEN;
    213 	return reply;
    214 }
    215 
    216 
    217 static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
    218 					      void *sock_ctx)
    219 {
    220 	struct wpa_supplicant *wpa_s = eloop_ctx;
    221 	struct ctrl_iface_priv *priv = sock_ctx;
    222 	char buf[256], *pos;
    223 	int res;
    224 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    225 	struct sockaddr_in6 from;
    226 #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
    227 	char addr[INET6_ADDRSTRLEN];
    228 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    229 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    230 	struct sockaddr_in from;
    231 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    232 	socklen_t fromlen = sizeof(from);
    233 	char *reply = NULL;
    234 	size_t reply_len = 0;
    235 	int new_attached = 0;
    236 	u8 cookie[COOKIE_LEN];
    237 
    238 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    239 		       (struct sockaddr *) &from, &fromlen);
    240 	if (res < 0) {
    241 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
    242 			   strerror(errno));
    243 		return;
    244 	}
    245 
    246 #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
    247 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    248 	inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from));
    249 	if (os_strcmp(addr, "::1")) {
    250 		wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s",
    251 			   addr);
    252 	}
    253 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    254 	if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
    255 		/*
    256 		 * The OS networking stack is expected to drop this kind of
    257 		 * frames since the socket is bound to only localhost address.
    258 		 * Just in case, drop the frame if it is coming from any other
    259 		 * address.
    260 		 */
    261 		wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
    262 			   "source %s", inet_ntoa(from.sin_addr));
    263 		return;
    264 	}
    265 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    266 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    267 
    268 	buf[res] = '\0';
    269 
    270 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
    271 		reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len);
    272 		goto done;
    273 	}
    274 
    275 	/*
    276 	 * Require that the client includes a prefix with the 'cookie' value
    277 	 * fetched with GET_COOKIE command. This is used to verify that the
    278 	 * client has access to a bidirectional link over UDP in order to
    279 	 * avoid attacks using forged localhost IP address even if the OS does
    280 	 * not block such frames from remote destinations.
    281 	 */
    282 	if (os_strncmp(buf, "COOKIE=", 7) != 0) {
    283 		wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
    284 			   "drop request");
    285 		return;
    286 	}
    287 
    288 	if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
    289 		wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
    290 			   "request - drop request");
    291 		return;
    292 	}
    293 
    294 	if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
    295 		wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
    296 			   "drop request");
    297 		return;
    298 	}
    299 
    300 	pos = buf + 7 + 2 * COOKIE_LEN;
    301 	while (*pos == ' ')
    302 		pos++;
    303 
    304 	if (os_strcmp(pos, "ATTACH") == 0) {
    305 		if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
    306 						     &from, fromlen))
    307 			reply_len = 1;
    308 		else {
    309 			new_attached = 1;
    310 			reply_len = 2;
    311 		}
    312 	} else if (os_strcmp(pos, "DETACH") == 0) {
    313 		if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst,
    314 						     &from, fromlen))
    315 			reply_len = 1;
    316 		else
    317 			reply_len = 2;
    318 	} else if (os_strncmp(pos, "LEVEL ", 6) == 0) {
    319 		if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
    320 						    pos + 6))
    321 			reply_len = 1;
    322 		else
    323 			reply_len = 2;
    324 	} else {
    325 		reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos,
    326 							  &reply_len);
    327 	}
    328 
    329  done:
    330 	if (reply) {
    331 		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
    332 		       fromlen);
    333 		os_free(reply);
    334 	} else if (reply_len == 1) {
    335 		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
    336 		       fromlen);
    337 	} else if (reply_len == 2) {
    338 		sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
    339 		       fromlen);
    340 	}
    341 
    342 	if (new_attached)
    343 		eapol_sm_notify_ctrl_attached(wpa_s->eapol);
    344 }
    345 
    346 
    347 static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
    348 					     enum wpa_msg_type type,
    349 					     const char *txt, size_t len)
    350 {
    351 	struct wpa_supplicant *wpa_s = ctx;
    352 
    353 	if (!wpa_s)
    354 		return;
    355 
    356 	if (type != WPA_MSG_NO_GLOBAL && wpa_s->global->ctrl_iface) {
    357 		struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
    358 
    359 		if (priv->ctrl_dst) {
    360 			wpa_supplicant_ctrl_iface_send(
    361 				wpa_s,
    362 				type != WPA_MSG_PER_INTERFACE ?
    363 				NULL : wpa_s->ifname,
    364 				priv->sock, &priv->ctrl_dst, level, txt, len);
    365 		}
    366 	}
    367 
    368 	if (type == WPA_MSG_ONLY_GLOBAL || !wpa_s->ctrl_iface)
    369 		return;
    370 
    371 	wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock,
    372 				       &wpa_s->ctrl_iface->ctrl_dst,
    373 				       level, txt, len);
    374 }
    375 
    376 
    377 struct ctrl_iface_priv *
    378 wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
    379 {
    380 	struct ctrl_iface_priv *priv;
    381 	char port_str[40];
    382 	int port = WPA_CTRL_IFACE_PORT;
    383 	char *pos;
    384 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    385 	struct sockaddr_in6 addr;
    386 	int domain = PF_INET6;
    387 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    388 	struct sockaddr_in addr;
    389 	int domain = PF_INET;
    390 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    391 
    392 	priv = os_zalloc(sizeof(*priv));
    393 	if (priv == NULL)
    394 		return NULL;
    395 	priv->wpa_s = wpa_s;
    396 	priv->sock = -1;
    397 	os_get_random(priv->cookie, COOKIE_LEN);
    398 
    399 	if (wpa_s->conf->ctrl_interface == NULL)
    400 		return priv;
    401 
    402 	pos = os_strstr(wpa_s->conf->ctrl_interface, "udp:");
    403 	if (pos) {
    404 		pos += 4;
    405 		port = atoi(pos);
    406 		if (port <= 0) {
    407 			wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port: %s",
    408 				   wpa_s->conf->ctrl_interface);
    409 			goto fail;
    410 		}
    411 	}
    412 
    413 	priv->sock = socket(domain, SOCK_DGRAM, 0);
    414 	if (priv->sock < 0) {
    415 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
    416 		goto fail;
    417 	}
    418 
    419 	os_memset(&addr, 0, sizeof(addr));
    420 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    421 	addr.sin6_family = AF_INET6;
    422 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
    423 	addr.sin6_addr = in6addr_any;
    424 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    425 	inet_pton(AF_INET6, "::1", &addr.sin6_addr);
    426 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    427 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    428 	addr.sin_family = AF_INET;
    429 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
    430 	addr.sin_addr.s_addr = INADDR_ANY;
    431 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    432 	addr.sin_addr.s_addr = htonl((127 << 24) | 1);
    433 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    434 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    435 try_again:
    436 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    437 	addr.sin6_port = htons(port);
    438 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    439 	addr.sin_port = htons(port);
    440 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    441 	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    442 		port--;
    443 		if ((WPA_CTRL_IFACE_PORT - port) < WPA_CTRL_IFACE_PORT_LIMIT)
    444 			goto try_again;
    445 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
    446 		goto fail;
    447 	}
    448 
    449 	/* Update the ctrl_interface value to match the selected port */
    450 	os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
    451 	os_free(wpa_s->conf->ctrl_interface);
    452 	wpa_s->conf->ctrl_interface = os_strdup(port_str);
    453 	if (!wpa_s->conf->ctrl_interface) {
    454 		wpa_msg(wpa_s, MSG_ERROR, "Failed to malloc ctrl_interface");
    455 		goto fail;
    456 	}
    457 
    458 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
    459 	wpa_msg(wpa_s, MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
    460 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    461 
    462 	eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
    463 				 wpa_s, priv);
    464 	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
    465 
    466 	return priv;
    467 
    468 fail:
    469 	if (priv->sock >= 0)
    470 		close(priv->sock);
    471 	os_free(priv);
    472 	return NULL;
    473 }
    474 
    475 
    476 void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
    477 {
    478 	if (priv->sock > -1) {
    479 		eloop_unregister_read_sock(priv->sock);
    480 		if (priv->ctrl_dst) {
    481 			/*
    482 			 * Wait before closing the control socket if
    483 			 * there are any attached monitors in order to allow
    484 			 * them to receive any pending messages.
    485 			 */
    486 			wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
    487 				   "monitors to receive messages");
    488 			os_sleep(0, 100000);
    489 		}
    490 		close(priv->sock);
    491 		priv->sock = -1;
    492 	}
    493 
    494 	wpas_ctrl_iface_free_dst(priv->ctrl_dst);
    495 	os_free(priv);
    496 }
    497 
    498 
    499 static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
    500 					   const char *ifname, int sock,
    501 					   struct wpa_ctrl_dst **head,
    502 					   int level, const char *buf,
    503 					   size_t len)
    504 {
    505 	struct wpa_ctrl_dst *dst, *next;
    506 	char levelstr[64];
    507 	int idx;
    508 	char *sbuf;
    509 	int llen;
    510 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    511 	char addr[INET6_ADDRSTRLEN];
    512 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    513 
    514 	dst = *head;
    515 	if (sock < 0 || dst == NULL)
    516 		return;
    517 
    518 	if (ifname)
    519 		os_snprintf(levelstr, sizeof(levelstr), "IFACE=%s <%d>",
    520 			    ifname, level);
    521 	else
    522 		os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
    523 
    524 	llen = os_strlen(levelstr);
    525 	sbuf = os_malloc(llen + len);
    526 	if (sbuf == NULL)
    527 		return;
    528 
    529 	os_memcpy(sbuf, levelstr, llen);
    530 	os_memcpy(sbuf + llen, buf, len);
    531 
    532 	idx = 0;
    533 	while (dst) {
    534 		next = dst->next;
    535 		if (level >= dst->debug_level) {
    536 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    537 			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
    538 				   inet_ntop(AF_INET6, &dst->addr.sin6_addr,
    539 					     addr, sizeof(dst->addr)),
    540 				   ntohs(dst->addr.sin6_port));
    541 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    542 			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
    543 				   inet_ntoa(dst->addr.sin_addr),
    544 				   ntohs(dst->addr.sin_port));
    545 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    546 			if (sendto(sock, sbuf, llen + len, 0,
    547 				   (struct sockaddr *) &dst->addr,
    548 				   sizeof(dst->addr)) < 0) {
    549 				wpa_printf(MSG_ERROR,
    550 					   "sendto(CTRL_IFACE monitor): %s",
    551 					   strerror(errno));
    552 				dst->errors++;
    553 				if (dst->errors > 10) {
    554 					wpa_supplicant_ctrl_iface_detach(
    555 						head, &dst->addr,
    556 						dst->addrlen);
    557 				}
    558 			} else
    559 				dst->errors = 0;
    560 		}
    561 		idx++;
    562 		dst = next;
    563 	}
    564 	os_free(sbuf);
    565 }
    566 
    567 
    568 void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
    569 {
    570 	wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
    571 		   priv->wpa_s->ifname);
    572 	eloop_wait_for_read_sock(priv->sock);
    573 }
    574 
    575 
    576 /* Global ctrl_iface */
    577 
    578 static char *
    579 wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv,
    580 				 size_t *reply_len)
    581 {
    582 	char *reply;
    583 	reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
    584 	if (reply == NULL) {
    585 		*reply_len = 1;
    586 		return NULL;
    587 	}
    588 
    589 	os_memcpy(reply, "COOKIE=", 7);
    590 	wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
    591 			 priv->cookie, COOKIE_LEN);
    592 
    593 	*reply_len = 7 + 2 * COOKIE_LEN;
    594 	return reply;
    595 }
    596 
    597 
    598 static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
    599 						     void *sock_ctx)
    600 {
    601 	struct wpa_global *global = eloop_ctx;
    602 	struct ctrl_iface_global_priv *priv = sock_ctx;
    603 	char buf[256], *pos;
    604 	int res;
    605 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
    606 	struct sockaddr_in6 from;
    607 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    608 	struct sockaddr_in from;
    609 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    610 	socklen_t fromlen = sizeof(from);
    611 	char *reply = NULL;
    612 	size_t reply_len;
    613 	u8 cookie[COOKIE_LEN];
    614 
    615 	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
    616 		       (struct sockaddr *) &from, &fromlen);
    617 	if (res < 0) {
    618 		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
    619 			   strerror(errno));
    620 		return;
    621 	}
    622 
    623 #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
    624 #ifndef CONFIG_CTRL_IFACE_UDP_IPV6
    625 	if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
    626 		/*
    627 		 * The OS networking stack is expected to drop this kind of
    628 		 * frames since the socket is bound to only localhost address.
    629 		 * Just in case, drop the frame if it is coming from any other
    630 		 * address.
    631 		 */
    632 		wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
    633 			   "source %s", inet_ntoa(from.sin_addr));
    634 		return;
    635 	}
    636 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
    637 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    638 
    639 	buf[res] = '\0';
    640 
    641 	if (os_strcmp(buf, "GET_COOKIE") == 0) {
    642 		reply = wpa_supplicant_global_get_cookie(priv, &reply_len);
    643 		goto done;
    644 	}
    645 
    646 	if (os_strncmp(buf, "COOKIE=", 7) != 0) {
    647 		wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
    648 			   "drop request");
    649 		return;
    650 	}
    651 
    652 	if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
    653 		wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
    654 			   "request - drop request");
    655 		return;
    656 	}
    657 
    658 	if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
    659 		wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
    660 			   "drop request");
    661 		return;
    662 	}
    663 
    664 	pos = buf + 7 + 2 * COOKIE_LEN;
    665 	while (*pos == ' ')
    666 		pos++;
    667 
    668 	if (os_strcmp(pos, "ATTACH") == 0) {
    669 		if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
    670 						     &from, fromlen))
    671 			reply_len = 1;
    672 		else
    673 			reply_len = 2;
    674 	} else if (os_strcmp(pos, "DETACH") == 0) {
    675 		if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst,
    676 						     &from, fromlen))
    677 			reply_len = 1;
    678 		else
    679 			reply_len = 2;
    680 	} else {
    681 		reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
    682 								 &reply_len);
    683 	}
    684 
    685  done:
    686 	if (reply) {
    687 		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
    688 		       fromlen);
    689 		os_free(reply);
    690 	} else if (reply_len == 1) {
    691 		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
    692 		       fromlen);
    693 	} else if (reply_len == 2) {
    694 		sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
    695 		       fromlen);
    696 	}
    697 }
    698 
    699 
    700 struct ctrl_iface_global_priv *
    701 wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
    702 {
    703 	struct ctrl_iface_global_priv *priv;
    704 	struct sockaddr_in addr;
    705 	char *pos;
    706 	int port = WPA_GLOBAL_CTRL_IFACE_PORT;
    707 
    708 	priv = os_zalloc(sizeof(*priv));
    709 	if (priv == NULL)
    710 		return NULL;
    711 	priv->sock = -1;
    712 	os_get_random(priv->cookie, COOKIE_LEN);
    713 
    714 	if (global->params.ctrl_interface == NULL)
    715 		return priv;
    716 
    717 	wpa_printf(MSG_DEBUG, "Global control interface '%s'",
    718 		   global->params.ctrl_interface);
    719 
    720 	pos = os_strstr(global->params.ctrl_interface, "udp:");
    721 	if (pos) {
    722 		pos += 4;
    723 		port = atoi(pos);
    724 		if (port <= 0) {
    725 			wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port %s",
    726 				   global->params.ctrl_interface);
    727 			goto fail;
    728 		}
    729 	}
    730 
    731 	priv->sock = socket(PF_INET, SOCK_DGRAM, 0);
    732 	if (priv->sock < 0) {
    733 		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
    734 		goto fail;
    735 	}
    736 
    737 	os_memset(&addr, 0, sizeof(addr));
    738 	addr.sin_family = AF_INET;
    739 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
    740 	addr.sin_addr.s_addr = INADDR_ANY;
    741 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    742 	addr.sin_addr.s_addr = htonl((127 << 24) | 1);
    743 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    744 try_again:
    745 	addr.sin_port = htons(port);
    746 	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    747 		port++;
    748 		if ((port - WPA_GLOBAL_CTRL_IFACE_PORT) <
    749 		    WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
    750 			goto try_again;
    751 		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
    752 		goto fail;
    753 	}
    754 
    755 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
    756 	wpa_printf(MSG_DEBUG, "global_ctrl_iface_init UDP port: %d", port);
    757 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
    758 
    759 	eloop_register_read_sock(priv->sock,
    760 				 wpa_supplicant_global_ctrl_iface_receive,
    761 				 global, priv);
    762 	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
    763 
    764 	return priv;
    765 
    766 fail:
    767 	if (priv->sock >= 0)
    768 		close(priv->sock);
    769 	os_free(priv);
    770 	return NULL;
    771 }
    772 
    773 
    774 void
    775 wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
    776 {
    777 	if (priv->sock >= 0) {
    778 		eloop_unregister_read_sock(priv->sock);
    779 		close(priv->sock);
    780 	}
    781 
    782 	wpas_ctrl_iface_free_dst(priv->ctrl_dst);
    783 	os_free(priv);
    784 }
    785