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