1 /* 2 * WPA Supplicant / UDP socket -based control interface 3 * Copyright (c) 2004-2020, 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 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, *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 buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); 239 if (!buf) 240 return; 241 res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, 242 (struct sockaddr *) &from, &fromlen); 243 if (res < 0) { 244 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 245 strerror(errno)); 246 os_free(buf); 247 return; 248 } 249 250 #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE 251 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 252 inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from)); 253 if (os_strcmp(addr, "::1")) { 254 wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", 255 addr); 256 os_free(buf); 257 return; 258 } 259 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 260 if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 261 /* 262 * The OS networking stack is expected to drop this kind of 263 * frames since the socket is bound to only localhost address. 264 * Just in case, drop the frame if it is coming from any other 265 * address. 266 */ 267 wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 268 "source %s", inet_ntoa(from.sin_addr)); 269 os_free(buf); 270 return; 271 } 272 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 273 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 274 275 if ((size_t) res > CTRL_IFACE_MAX_LEN) { 276 wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); 277 os_free(buf); 278 return; 279 } 280 buf[res] = '\0'; 281 282 if (os_strcmp(buf, "GET_COOKIE") == 0) { 283 reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len); 284 goto done; 285 } 286 287 /* 288 * Require that the client includes a prefix with the 'cookie' value 289 * fetched with GET_COOKIE command. This is used to verify that the 290 * client has access to a bidirectional link over UDP in order to 291 * avoid attacks using forged localhost IP address even if the OS does 292 * not block such frames from remote destinations. 293 */ 294 if (os_strncmp(buf, "COOKIE=", 7) != 0) { 295 wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 296 "drop request"); 297 os_free(buf); 298 return; 299 } 300 301 if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 302 wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 303 "request - drop request"); 304 os_free(buf); 305 return; 306 } 307 308 if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 309 wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 310 "drop request"); 311 os_free(buf); 312 return; 313 } 314 315 pos = buf + 7 + 2 * COOKIE_LEN; 316 while (*pos == ' ') 317 pos++; 318 319 if (os_strcmp(pos, "ATTACH") == 0) { 320 if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, 321 &from, fromlen)) 322 reply_len = 1; 323 else { 324 new_attached = 1; 325 reply_len = 2; 326 } 327 } else if (os_strcmp(pos, "DETACH") == 0) { 328 if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, 329 &from, fromlen)) 330 reply_len = 1; 331 else 332 reply_len = 2; 333 } else if (os_strncmp(pos, "LEVEL ", 6) == 0) { 334 if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 335 pos + 6)) 336 reply_len = 1; 337 else 338 reply_len = 2; 339 } else { 340 reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos, 341 &reply_len); 342 } 343 344 done: 345 if (reply) { 346 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 347 fromlen); 348 os_free(reply); 349 } else if (reply_len == 1) { 350 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 351 fromlen); 352 } else if (reply_len == 2) { 353 sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 354 fromlen); 355 } 356 357 os_free(buf); 358 359 if (new_attached) 360 eapol_sm_notify_ctrl_attached(wpa_s->eapol); 361 } 362 363 364 static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 365 enum wpa_msg_type type, 366 const char *txt, size_t len) 367 { 368 struct wpa_supplicant *wpa_s = ctx; 369 370 if (!wpa_s) 371 return; 372 373 if (type != WPA_MSG_NO_GLOBAL && wpa_s->global->ctrl_iface) { 374 struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface; 375 376 if (priv->ctrl_dst) { 377 wpa_supplicant_ctrl_iface_send( 378 wpa_s, 379 type != WPA_MSG_PER_INTERFACE ? 380 NULL : wpa_s->ifname, 381 priv->sock, &priv->ctrl_dst, level, txt, len); 382 } 383 } 384 385 if (type == WPA_MSG_ONLY_GLOBAL || !wpa_s->ctrl_iface) 386 return; 387 388 wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock, 389 &wpa_s->ctrl_iface->ctrl_dst, 390 level, txt, len); 391 } 392 393 394 struct ctrl_iface_priv * 395 wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 396 { 397 struct ctrl_iface_priv *priv; 398 char port_str[40]; 399 int port = WPA_CTRL_IFACE_PORT; 400 char *pos; 401 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 402 struct sockaddr_in6 addr; 403 int domain = PF_INET6; 404 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 405 struct sockaddr_in addr; 406 int domain = PF_INET; 407 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 408 409 priv = os_zalloc(sizeof(*priv)); 410 if (priv == NULL) 411 return NULL; 412 priv->wpa_s = wpa_s; 413 priv->sock = -1; 414 os_get_random(priv->cookie, COOKIE_LEN); 415 416 if (wpa_s->conf->ctrl_interface == NULL) 417 return priv; 418 419 pos = os_strstr(wpa_s->conf->ctrl_interface, "udp:"); 420 if (pos) { 421 pos += 4; 422 port = atoi(pos); 423 if (port <= 0) { 424 wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port: %s", 425 wpa_s->conf->ctrl_interface); 426 goto fail; 427 } 428 } 429 430 priv->sock = socket(domain, SOCK_DGRAM, 0); 431 if (priv->sock < 0) { 432 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 433 goto fail; 434 } 435 436 os_memset(&addr, 0, sizeof(addr)); 437 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 438 addr.sin6_family = AF_INET6; 439 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 440 addr.sin6_addr = in6addr_any; 441 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 442 inet_pton(AF_INET6, "::1", &addr.sin6_addr); 443 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 444 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 445 addr.sin_family = AF_INET; 446 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 447 addr.sin_addr.s_addr = INADDR_ANY; 448 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 449 addr.sin_addr.s_addr = htonl((127 << 24) | 1); 450 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 451 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 452 try_again: 453 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 454 addr.sin6_port = htons(port); 455 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 456 addr.sin_port = htons(port); 457 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 458 if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 459 port--; 460 if ((WPA_CTRL_IFACE_PORT - port) < WPA_CTRL_IFACE_PORT_LIMIT) 461 goto try_again; 462 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 463 goto fail; 464 } 465 466 /* Update the ctrl_interface value to match the selected port */ 467 os_snprintf(port_str, sizeof(port_str), "udp:%d", port); 468 os_free(wpa_s->conf->ctrl_interface); 469 wpa_s->conf->ctrl_interface = os_strdup(port_str); 470 if (!wpa_s->conf->ctrl_interface) { 471 wpa_msg(wpa_s, MSG_ERROR, "Failed to malloc ctrl_interface"); 472 goto fail; 473 } 474 475 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 476 wpa_msg(wpa_s, MSG_DEBUG, "ctrl_iface_init UDP port: %d", port); 477 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 478 479 eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 480 wpa_s, priv); 481 wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 482 483 return priv; 484 485 fail: 486 if (priv->sock >= 0) 487 close(priv->sock); 488 os_free(priv); 489 return NULL; 490 } 491 492 493 void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s, 494 struct ctrl_iface_priv *priv) 495 { 496 if (!priv) 497 return; 498 499 if (priv->sock > -1) { 500 eloop_unregister_read_sock(priv->sock); 501 if (priv->ctrl_dst) { 502 /* 503 * Wait before closing the control socket if 504 * there are any attached monitors in order to allow 505 * them to receive any pending messages. 506 */ 507 wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 508 "monitors to receive messages"); 509 os_sleep(0, 100000); 510 } 511 close(priv->sock); 512 priv->sock = -1; 513 } 514 515 wpas_ctrl_iface_free_dst(priv->ctrl_dst); 516 os_free(priv); 517 } 518 519 520 static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, 521 const char *ifname, int sock, 522 struct wpa_ctrl_dst **head, 523 int level, const char *buf, 524 size_t len) 525 { 526 struct wpa_ctrl_dst *dst, *next; 527 char levelstr[64]; 528 int idx; 529 char *sbuf; 530 int llen; 531 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 532 char addr[INET6_ADDRSTRLEN]; 533 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 534 535 dst = *head; 536 if (sock < 0 || dst == NULL) 537 return; 538 539 if (ifname) 540 os_snprintf(levelstr, sizeof(levelstr), "IFNAME=%s <%d>", 541 ifname, level); 542 else 543 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 544 545 llen = os_strlen(levelstr); 546 sbuf = os_malloc(llen + len); 547 if (sbuf == NULL) 548 return; 549 550 os_memcpy(sbuf, levelstr, llen); 551 os_memcpy(sbuf + llen, buf, len); 552 553 idx = 0; 554 while (dst) { 555 next = dst->next; 556 if (level >= dst->debug_level) { 557 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 558 wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", 559 inet_ntop(AF_INET6, &dst->addr.sin6_addr, 560 addr, sizeof(dst->addr)), 561 ntohs(dst->addr.sin6_port)); 562 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 563 wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", 564 inet_ntoa(dst->addr.sin_addr), 565 ntohs(dst->addr.sin_port)); 566 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 567 if (sendto(sock, sbuf, llen + len, 0, 568 (struct sockaddr *) &dst->addr, 569 sizeof(dst->addr)) < 0) { 570 wpa_printf(MSG_ERROR, 571 "sendto(CTRL_IFACE monitor): %s", 572 strerror(errno)); 573 dst->errors++; 574 if (dst->errors > 10) { 575 wpa_supplicant_ctrl_iface_detach( 576 head, &dst->addr, 577 dst->addrlen); 578 } 579 } else 580 dst->errors = 0; 581 } 582 idx++; 583 dst = next; 584 } 585 os_free(sbuf); 586 } 587 588 589 void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 590 { 591 wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor", 592 priv->wpa_s->ifname); 593 eloop_wait_for_read_sock(priv->sock); 594 } 595 596 597 /* Global ctrl_iface */ 598 599 static char * 600 wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv, 601 size_t *reply_len) 602 { 603 char *reply; 604 reply = os_malloc(7 + 2 * COOKIE_LEN + 1); 605 if (reply == NULL) { 606 *reply_len = 1; 607 return NULL; 608 } 609 610 os_memcpy(reply, "COOKIE=", 7); 611 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 612 priv->cookie, COOKIE_LEN); 613 614 *reply_len = 7 + 2 * COOKIE_LEN; 615 return reply; 616 } 617 618 619 static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 620 void *sock_ctx) 621 { 622 struct wpa_global *global = eloop_ctx; 623 struct ctrl_iface_global_priv *priv = sock_ctx; 624 char *buf, *pos; 625 int res; 626 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 627 struct sockaddr_in6 from; 628 #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE 629 char addr[INET6_ADDRSTRLEN]; 630 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 631 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 632 struct sockaddr_in from; 633 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 634 socklen_t fromlen = sizeof(from); 635 char *reply = NULL; 636 size_t reply_len; 637 u8 cookie[COOKIE_LEN]; 638 639 buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); 640 if (!buf) 641 return; 642 res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, 643 (struct sockaddr *) &from, &fromlen); 644 if (res < 0) { 645 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 646 strerror(errno)); 647 os_free(buf); 648 return; 649 } 650 651 #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE 652 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 653 inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from)); 654 if (os_strcmp(addr, "::1")) { 655 wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", 656 addr); 657 os_free(buf); 658 return; 659 } 660 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 661 if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { 662 /* 663 * The OS networking stack is expected to drop this kind of 664 * frames since the socket is bound to only localhost address. 665 * Just in case, drop the frame if it is coming from any other 666 * address. 667 */ 668 wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " 669 "source %s", inet_ntoa(from.sin_addr)); 670 os_free(buf); 671 return; 672 } 673 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 674 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 675 676 if ((size_t) res > CTRL_IFACE_MAX_LEN) { 677 wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); 678 os_free(buf); 679 return; 680 } 681 buf[res] = '\0'; 682 683 if (os_strcmp(buf, "GET_COOKIE") == 0) { 684 reply = wpa_supplicant_global_get_cookie(priv, &reply_len); 685 goto done; 686 } 687 688 if (os_strncmp(buf, "COOKIE=", 7) != 0) { 689 wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " 690 "drop request"); 691 os_free(buf); 692 return; 693 } 694 695 if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { 696 wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " 697 "request - drop request"); 698 os_free(buf); 699 return; 700 } 701 702 if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { 703 wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " 704 "drop request"); 705 os_free(buf); 706 return; 707 } 708 709 pos = buf + 7 + 2 * COOKIE_LEN; 710 while (*pos == ' ') 711 pos++; 712 713 if (os_strcmp(pos, "ATTACH") == 0) { 714 if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, 715 &from, fromlen)) 716 reply_len = 1; 717 else 718 reply_len = 2; 719 } else if (os_strcmp(pos, "DETACH") == 0) { 720 if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, 721 &from, fromlen)) 722 reply_len = 1; 723 else 724 reply_len = 2; 725 } else { 726 reply = wpa_supplicant_global_ctrl_iface_process(global, pos, 727 &reply_len); 728 } 729 730 done: 731 if (reply) { 732 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 733 fromlen); 734 os_free(reply); 735 } else if (reply_len == 1) { 736 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 737 fromlen); 738 } else if (reply_len == 2) { 739 sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 740 fromlen); 741 } 742 743 os_free(buf); 744 } 745 746 747 struct ctrl_iface_global_priv * 748 wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) 749 { 750 struct ctrl_iface_global_priv *priv; 751 struct sockaddr_in addr; 752 char *pos; 753 int port = WPA_GLOBAL_CTRL_IFACE_PORT; 754 755 priv = os_zalloc(sizeof(*priv)); 756 if (priv == NULL) 757 return NULL; 758 priv->sock = -1; 759 os_get_random(priv->cookie, COOKIE_LEN); 760 761 if (global->params.ctrl_interface == NULL) 762 return priv; 763 764 wpa_printf(MSG_DEBUG, "Global control interface '%s'", 765 global->params.ctrl_interface); 766 767 pos = os_strstr(global->params.ctrl_interface, "udp:"); 768 if (pos) { 769 pos += 4; 770 port = atoi(pos); 771 if (port <= 0) { 772 wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port %s", 773 global->params.ctrl_interface); 774 goto fail; 775 } 776 } 777 778 priv->sock = socket(PF_INET, SOCK_DGRAM, 0); 779 if (priv->sock < 0) { 780 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 781 goto fail; 782 } 783 784 os_memset(&addr, 0, sizeof(addr)); 785 addr.sin_family = AF_INET; 786 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 787 addr.sin_addr.s_addr = INADDR_ANY; 788 #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 789 addr.sin_addr.s_addr = htonl((127 << 24) | 1); 790 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 791 try_again: 792 addr.sin_port = htons(port); 793 if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 794 port++; 795 if ((port - WPA_GLOBAL_CTRL_IFACE_PORT) < 796 WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos) 797 goto try_again; 798 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 799 goto fail; 800 } 801 802 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 803 wpa_printf(MSG_DEBUG, "global_ctrl_iface_init UDP port: %d", port); 804 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 805 806 eloop_register_read_sock(priv->sock, 807 wpa_supplicant_global_ctrl_iface_receive, 808 global, priv); 809 wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 810 811 return priv; 812 813 fail: 814 if (priv->sock >= 0) 815 close(priv->sock); 816 os_free(priv); 817 return NULL; 818 } 819 820 821 void 822 wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 823 { 824 if (priv->sock >= 0) { 825 eloop_unregister_read_sock(priv->sock); 826 close(priv->sock); 827 } 828 829 wpas_ctrl_iface_free_dst(priv->ctrl_dst); 830 os_free(priv); 831 } 832