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