1 /* 2 * WPA Supplicant / UDP socket -based control interface 3 * Copyright (c) 2004-2005, 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 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 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