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 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 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 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 222 strerror(errno)); 223 return; 224 } 225 226 #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE 227 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 228 inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from)); 229 if (os_strcmp(addr, "::1")) { 230 wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", 231 addr); 232 } 233 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 234 if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 235 /* 236 * The OS networking stack is expected to drop this kind of 237 * frames since the socket is bound to only localhost address. 238 * Just in case, drop the frame if it is coming from any other 239 * address. 240 */ 241 wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 242 "source %s", inet_ntoa(from.sin_addr)); 243 return; 244 } 245 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 246 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 247 248 buf[res] = '\0'; 249 250 if (os_strcmp(buf, "GET_COOKIE") == 0) { 251 reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len); 252 goto done; 253 } 254 255 /* 256 * Require that the client includes a prefix with the 'cookie' value 257 * fetched with GET_COOKIE command. This is used to verify that the 258 * client has access to a bidirectional link over UDP in order to 259 * avoid attacks using forged localhost IP address even if the OS does 260 * not block such frames from remote destinations. 261 */ 262 if (os_strncmp(buf, "COOKIE=", 7) != 0) { 263 wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 264 "drop request"); 265 return; 266 } 267 268 if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 269 wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 270 "request - drop request"); 271 return; 272 } 273 274 if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 275 wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 276 "drop request"); 277 return; 278 } 279 280 pos = buf + 7 + 2 * COOKIE_LEN; 281 while (*pos == ' ') 282 pos++; 283 284 if (os_strcmp(pos, "ATTACH") == 0) { 285 if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) 286 reply_len = 1; 287 else { 288 new_attached = 1; 289 reply_len = 2; 290 } 291 } else if (os_strcmp(pos, "DETACH") == 0) { 292 if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) 293 reply_len = 1; 294 else 295 reply_len = 2; 296 } else if (os_strncmp(pos, "LEVEL ", 6) == 0) { 297 if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 298 pos + 6)) 299 reply_len = 1; 300 else 301 reply_len = 2; 302 } else { 303 reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos, 304 &reply_len); 305 } 306 307 done: 308 if (reply) { 309 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 310 fromlen); 311 os_free(reply); 312 } else if (reply_len == 1) { 313 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 314 fromlen); 315 } else if (reply_len == 2) { 316 sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 317 fromlen); 318 } 319 320 if (new_attached) 321 eapol_sm_notify_ctrl_attached(wpa_s->eapol); 322 } 323 324 325 static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, int global, 326 const char *txt, size_t len) 327 { 328 struct wpa_supplicant *wpa_s = ctx; 329 if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) 330 return; 331 wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); 332 } 333 334 335 struct ctrl_iface_priv * 336 wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 337 { 338 struct ctrl_iface_priv *priv; 339 int port = WPA_CTRL_IFACE_PORT; 340 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 341 struct sockaddr_in6 addr; 342 int domain = PF_INET6; 343 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 344 struct sockaddr_in addr; 345 int domain = PF_INET; 346 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 347 348 priv = os_zalloc(sizeof(*priv)); 349 if (priv == NULL) 350 return NULL; 351 priv->wpa_s = wpa_s; 352 priv->sock = -1; 353 os_get_random(priv->cookie, COOKIE_LEN); 354 355 if (wpa_s->conf->ctrl_interface == NULL) 356 return priv; 357 358 priv->sock = socket(domain, SOCK_DGRAM, 0); 359 if (priv->sock < 0) { 360 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 361 goto fail; 362 } 363 364 os_memset(&addr, 0, sizeof(addr)); 365 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 366 addr.sin6_family = AF_INET6; 367 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 368 addr.sin6_addr = in6addr_any; 369 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 370 inet_pton(AF_INET6, "::1", &addr.sin6_addr); 371 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 372 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 373 addr.sin_family = AF_INET; 374 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 375 addr.sin_addr.s_addr = INADDR_ANY; 376 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 377 addr.sin_addr.s_addr = htonl((127 << 24) | 1); 378 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 379 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 380 try_again: 381 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 382 addr.sin6_port = htons(port); 383 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 384 addr.sin_port = htons(port); 385 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 386 if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 387 port--; 388 if ((WPA_CTRL_IFACE_PORT - port) < WPA_CTRL_IFACE_PORT_LIMIT) 389 goto try_again; 390 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 391 goto fail; 392 } 393 394 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 395 wpa_msg(wpa_s, MSG_DEBUG, "ctrl_iface_init UDP port: %d", port); 396 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 397 398 eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 399 wpa_s, priv); 400 wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 401 402 return priv; 403 404 fail: 405 if (priv->sock >= 0) 406 close(priv->sock); 407 os_free(priv); 408 return NULL; 409 } 410 411 412 void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 413 { 414 struct wpa_ctrl_dst *dst, *prev; 415 416 if (priv->sock > -1) { 417 eloop_unregister_read_sock(priv->sock); 418 if (priv->ctrl_dst) { 419 /* 420 * Wait before closing the control socket if 421 * there are any attached monitors in order to allow 422 * them to receive any pending messages. 423 */ 424 wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 425 "monitors to receive messages"); 426 os_sleep(0, 100000); 427 } 428 close(priv->sock); 429 priv->sock = -1; 430 } 431 432 dst = priv->ctrl_dst; 433 while (dst) { 434 prev = dst; 435 dst = dst->next; 436 os_free(prev); 437 } 438 os_free(priv); 439 } 440 441 442 static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 443 int level, const char *buf, 444 size_t len) 445 { 446 struct wpa_ctrl_dst *dst, *next; 447 char levelstr[10]; 448 int idx; 449 char *sbuf; 450 int llen; 451 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 452 char addr[INET6_ADDRSTRLEN]; 453 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 454 455 dst = priv->ctrl_dst; 456 if (priv->sock < 0 || dst == NULL) 457 return; 458 459 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 460 461 llen = os_strlen(levelstr); 462 sbuf = os_malloc(llen + len); 463 if (sbuf == NULL) 464 return; 465 466 os_memcpy(sbuf, levelstr, llen); 467 os_memcpy(sbuf + llen, buf, len); 468 469 idx = 0; 470 while (dst) { 471 next = dst->next; 472 if (level >= dst->debug_level) { 473 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 474 wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", 475 inet_ntop(AF_INET6, &dst->addr.sin6_addr, 476 addr, sizeof(dst->addr)), 477 ntohs(dst->addr.sin6_port)); 478 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 479 wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", 480 inet_ntoa(dst->addr.sin_addr), 481 ntohs(dst->addr.sin_port)); 482 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 483 if (sendto(priv->sock, sbuf, llen + len, 0, 484 (struct sockaddr *) &dst->addr, 485 sizeof(dst->addr)) < 0) { 486 wpa_printf(MSG_ERROR, 487 "sendto(CTRL_IFACE monitor): %s", 488 strerror(errno)); 489 dst->errors++; 490 if (dst->errors > 10) { 491 wpa_supplicant_ctrl_iface_detach( 492 priv, &dst->addr, 493 dst->addrlen); 494 } 495 } else 496 dst->errors = 0; 497 } 498 idx++; 499 dst = next; 500 } 501 os_free(sbuf); 502 } 503 504 505 void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 506 { 507 wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor", 508 priv->wpa_s->ifname); 509 eloop_wait_for_read_sock(priv->sock); 510 } 511 512 513 /* Global ctrl_iface */ 514 515 struct ctrl_iface_global_priv { 516 int sock; 517 u8 cookie[COOKIE_LEN]; 518 }; 519 520 521 static char * 522 wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv, 523 size_t *reply_len) 524 { 525 char *reply; 526 reply = os_malloc(7 + 2 * COOKIE_LEN + 1); 527 if (reply == NULL) { 528 *reply_len = 1; 529 return NULL; 530 } 531 532 os_memcpy(reply, "COOKIE=", 7); 533 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 534 priv->cookie, COOKIE_LEN); 535 536 *reply_len = 7 + 2 * COOKIE_LEN; 537 return reply; 538 } 539 540 541 static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 542 void *sock_ctx) 543 { 544 struct wpa_global *global = eloop_ctx; 545 struct ctrl_iface_global_priv *priv = sock_ctx; 546 char buf[256], *pos; 547 int res; 548 struct sockaddr_in from; 549 socklen_t fromlen = sizeof(from); 550 char *reply; 551 size_t reply_len; 552 u8 cookie[COOKIE_LEN]; 553 554 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 555 (struct sockaddr *) &from, &fromlen); 556 if (res < 0) { 557 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 558 strerror(errno)); 559 return; 560 } 561 562 #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE 563 if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 564 /* 565 * The OS networking stack is expected to drop this kind of 566 * frames since the socket is bound to only localhost address. 567 * Just in case, drop the frame if it is coming from any other 568 * address. 569 */ 570 wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 571 "source %s", inet_ntoa(from.sin_addr)); 572 return; 573 } 574 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 575 576 buf[res] = '\0'; 577 578 if (os_strcmp(buf, "GET_COOKIE") == 0) { 579 reply = wpa_supplicant_global_get_cookie(priv, &reply_len); 580 goto done; 581 } 582 583 if (os_strncmp(buf, "COOKIE=", 7) != 0) { 584 wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 585 "drop request"); 586 return; 587 } 588 589 if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 590 wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 591 "request - drop request"); 592 return; 593 } 594 595 if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 596 wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 597 "drop request"); 598 return; 599 } 600 601 pos = buf + 7 + 2 * COOKIE_LEN; 602 while (*pos == ' ') 603 pos++; 604 605 reply = wpa_supplicant_global_ctrl_iface_process(global, pos, 606 &reply_len); 607 608 done: 609 if (reply) { 610 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 611 fromlen); 612 os_free(reply); 613 } else if (reply_len) { 614 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 615 fromlen); 616 } 617 } 618 619 620 struct ctrl_iface_global_priv * 621 wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 622 { 623 struct ctrl_iface_global_priv *priv; 624 struct sockaddr_in addr; 625 int port = WPA_GLOBAL_CTRL_IFACE_PORT; 626 627 priv = os_zalloc(sizeof(*priv)); 628 if (priv == NULL) 629 return NULL; 630 priv->sock = -1; 631 os_get_random(priv->cookie, COOKIE_LEN); 632 633 if (global->params.ctrl_interface == NULL) 634 return priv; 635 636 wpa_printf(MSG_DEBUG, "Global control interface '%s'", 637 global->params.ctrl_interface); 638 639 priv->sock = socket(PF_INET, SOCK_DGRAM, 0); 640 if (priv->sock < 0) { 641 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 642 goto fail; 643 } 644 645 os_memset(&addr, 0, sizeof(addr)); 646 addr.sin_family = AF_INET; 647 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 648 addr.sin_addr.s_addr = INADDR_ANY; 649 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 650 addr.sin_addr.s_addr = htonl((127 << 24) | 1); 651 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 652 try_again: 653 addr.sin_port = htons(port); 654 if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 655 port++; 656 if ((port - WPA_GLOBAL_CTRL_IFACE_PORT) < 657 WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT) 658 goto try_again; 659 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 660 goto fail; 661 } 662 663 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 664 wpa_printf(MSG_DEBUG, "global_ctrl_iface_init UDP port: %d", port); 665 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 666 667 eloop_register_read_sock(priv->sock, 668 wpa_supplicant_global_ctrl_iface_receive, 669 global, priv); 670 671 return priv; 672 673 fail: 674 if (priv->sock >= 0) 675 close(priv->sock); 676 os_free(priv); 677 return NULL; 678 } 679 680 681 void 682 wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 683 { 684 if (priv->sock >= 0) { 685 eloop_unregister_read_sock(priv->sock); 686 close(priv->sock); 687 } 688 os_free(priv); 689 } 690