1 /* 2 * WPA Supplicant / UNIX domain socket -based control interface 3 * Copyright (c) 2004-2005, Jouni Malinen <j (at) w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 #include <sys/un.h> 17 #include <sys/stat.h> 18 #include <grp.h> 19 #ifdef ANDROID 20 #include <cutils/sockets.h> 21 #endif 22 23 #include "common.h" 24 #include "eloop.h" 25 #include "config.h" 26 #include "eapol_sm.h" 27 #include "wpa_supplicant_i.h" 28 #include "ctrl_iface.h" 29 30 /* Per-interface ctrl_iface */ 31 32 /** 33 * struct wpa_ctrl_dst - Internal data structure of control interface monitors 34 * 35 * This structure is used to store information about registered control 36 * interface monitors into struct wpa_supplicant. This data is private to 37 * ctrl_iface_unix.c and should not be touched directly from other files. 38 */ 39 struct wpa_ctrl_dst { 40 struct wpa_ctrl_dst *next; 41 struct sockaddr_un addr; 42 socklen_t addrlen; 43 int debug_level; 44 int errors; 45 }; 46 47 48 struct ctrl_iface_priv { 49 struct wpa_supplicant *wpa_s; 50 int sock; 51 struct wpa_ctrl_dst *ctrl_dst; 52 }; 53 54 55 static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 56 int level, const char *buf, 57 size_t len); 58 59 60 static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv, 61 struct sockaddr_un *from, 62 socklen_t fromlen) 63 { 64 struct wpa_ctrl_dst *dst; 65 66 dst = os_zalloc(sizeof(*dst)); 67 if (dst == NULL) 68 return -1; 69 os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 70 dst->addrlen = fromlen; 71 dst->debug_level = MSG_INFO; 72 dst->next = priv->ctrl_dst; 73 priv->ctrl_dst = dst; 74 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", 75 (u8 *) from->sun_path, fromlen - sizeof(from->sun_family)); 76 return 0; 77 } 78 79 80 static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv, 81 struct sockaddr_un *from, 82 socklen_t fromlen) 83 { 84 struct wpa_ctrl_dst *dst, *prev = NULL; 85 86 dst = priv->ctrl_dst; 87 while (dst) { 88 if (fromlen == dst->addrlen && 89 os_memcmp(from->sun_path, dst->addr.sun_path, 90 fromlen - sizeof(from->sun_family)) == 0) { 91 if (prev == NULL) 92 priv->ctrl_dst = dst->next; 93 else 94 prev->next = dst->next; 95 os_free(dst); 96 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", 97 (u8 *) from->sun_path, 98 fromlen - sizeof(from->sun_family)); 99 return 0; 100 } 101 prev = dst; 102 dst = dst->next; 103 } 104 return -1; 105 } 106 107 108 static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, 109 struct sockaddr_un *from, 110 socklen_t fromlen, 111 char *level) 112 { 113 struct wpa_ctrl_dst *dst; 114 115 wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 116 117 dst = priv->ctrl_dst; 118 while (dst) { 119 if (fromlen == dst->addrlen && 120 os_memcmp(from->sun_path, dst->addr.sun_path, 121 fromlen - sizeof(from->sun_family)) == 0) { 122 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " 123 "level", (u8 *) from->sun_path, 124 fromlen - sizeof(from->sun_family)); 125 dst->debug_level = atoi(level); 126 return 0; 127 } 128 dst = dst->next; 129 } 130 131 return -1; 132 } 133 134 135 static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, 136 void *sock_ctx) 137 { 138 struct wpa_supplicant *wpa_s = eloop_ctx; 139 struct ctrl_iface_priv *priv = sock_ctx; 140 char buf[256]; 141 int res; 142 struct sockaddr_un from; 143 socklen_t fromlen = sizeof(from); 144 char *reply = NULL; 145 size_t reply_len = 0; 146 int new_attached = 0; 147 148 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 149 (struct sockaddr *) &from, &fromlen); 150 if (res < 0) { 151 perror("recvfrom(ctrl_iface)"); 152 return; 153 } 154 buf[res] = '\0'; 155 156 if (os_strcmp(buf, "ATTACH") == 0) { 157 if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) 158 reply_len = 1; 159 else { 160 new_attached = 1; 161 reply_len = 2; 162 } 163 } else if (os_strcmp(buf, "DETACH") == 0) { 164 if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) 165 reply_len = 1; 166 else 167 reply_len = 2; 168 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 169 if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, 170 buf + 6)) 171 reply_len = 1; 172 else 173 reply_len = 2; 174 } else { 175 reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf, 176 &reply_len); 177 } 178 179 if (reply) { 180 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 181 fromlen); 182 os_free(reply); 183 } else if (reply_len == 1) { 184 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 185 fromlen); 186 } else if (reply_len == 2) { 187 sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, 188 fromlen); 189 } 190 191 if (new_attached) 192 eapol_sm_notify_ctrl_attached(wpa_s->eapol); 193 } 194 195 196 static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s) 197 { 198 char *buf; 199 size_t len; 200 char *pbuf, *dir = NULL, *gid_str = NULL; 201 202 if (wpa_s->conf->ctrl_interface == NULL) 203 return NULL; 204 205 pbuf = os_strdup(wpa_s->conf->ctrl_interface); 206 if (pbuf == NULL) 207 return NULL; 208 if (os_strncmp(pbuf, "DIR=", 4) == 0) { 209 dir = pbuf + 4; 210 gid_str = os_strstr(dir, " GROUP="); 211 if (gid_str) { 212 *gid_str = '\0'; 213 gid_str += 7; 214 } 215 } else 216 dir = pbuf; 217 218 len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2; 219 buf = os_malloc(len); 220 if (buf == NULL) { 221 os_free(pbuf); 222 return NULL; 223 } 224 225 os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname); 226 #ifdef __CYGWIN__ 227 { 228 /* Windows/WinPcap uses interface names that are not suitable 229 * as a file name - convert invalid chars to underscores */ 230 char *pos = buf; 231 while (*pos) { 232 if (*pos == '\\') 233 *pos = '_'; 234 pos++; 235 } 236 } 237 #endif /* __CYGWIN__ */ 238 os_free(pbuf); 239 return buf; 240 } 241 242 243 static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, 244 const char *txt, size_t len) 245 { 246 struct wpa_supplicant *wpa_s = ctx; 247 if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) 248 return; 249 wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); 250 } 251 252 253 struct ctrl_iface_priv * 254 wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) 255 { 256 struct ctrl_iface_priv *priv; 257 struct sockaddr_un addr; 258 char *fname = NULL; 259 gid_t gid = 0; 260 int gid_set = 0; 261 char *buf, *dir = NULL, *gid_str = NULL; 262 struct group *grp; 263 char *endp; 264 265 priv = os_zalloc(sizeof(*priv)); 266 if (priv == NULL) 267 return NULL; 268 priv->wpa_s = wpa_s; 269 priv->sock = -1; 270 271 if (wpa_s->conf->ctrl_interface == NULL) 272 return priv; 273 274 buf = os_strdup(wpa_s->conf->ctrl_interface); 275 if (buf == NULL) 276 goto fail; 277 #ifdef ANDROID 278 os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", 279 wpa_s->conf->ctrl_interface); 280 priv->sock = android_get_control_socket(addr.sun_path); 281 if (priv->sock >= 0) 282 goto havesock; 283 #endif 284 if (os_strncmp(buf, "DIR=", 4) == 0) { 285 dir = buf + 4; 286 gid_str = os_strstr(dir, " GROUP="); 287 if (gid_str) { 288 *gid_str = '\0'; 289 gid_str += 7; 290 } 291 } else { 292 dir = buf; 293 gid_str = wpa_s->conf->ctrl_interface_group; 294 } 295 296 if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) { 297 if (errno == EEXIST) { 298 wpa_printf(MSG_DEBUG, "Using existing control " 299 "interface directory."); 300 } else { 301 perror("mkdir[ctrl_interface]"); 302 goto fail; 303 } 304 } 305 306 if (gid_str) { 307 grp = getgrnam(gid_str); 308 if (grp) { 309 gid = grp->gr_gid; 310 gid_set = 1; 311 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" 312 " (from group name '%s')", 313 (int) gid, gid_str); 314 } else { 315 /* Group name not found - try to parse this as gid */ 316 gid = strtol(gid_str, &endp, 10); 317 if (*gid_str == '\0' || *endp != '\0') { 318 wpa_printf(MSG_ERROR, "CTRL: Invalid group " 319 "'%s'", gid_str); 320 goto fail; 321 } 322 gid_set = 1; 323 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", 324 (int) gid); 325 } 326 } 327 328 if (gid_set && chown(dir, -1, gid) < 0) { 329 perror("chown[ctrl_interface]"); 330 goto fail; 331 } 332 333 if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >= 334 sizeof(addr.sun_path)) 335 goto fail; 336 337 priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 338 if (priv->sock < 0) { 339 perror("socket(PF_UNIX)"); 340 goto fail; 341 } 342 343 os_memset(&addr, 0, sizeof(addr)); 344 addr.sun_family = AF_UNIX; 345 fname = wpa_supplicant_ctrl_iface_path(wpa_s); 346 if (fname == NULL) 347 goto fail; 348 os_strncpy(addr.sun_path, fname, sizeof(addr.sun_path)); 349 if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 350 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 351 strerror(errno)); 352 if (connect(priv->sock, (struct sockaddr *) &addr, 353 sizeof(addr)) < 0) { 354 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 355 " allow connections - assuming it was left" 356 "over from forced program termination"); 357 if (unlink(fname) < 0) { 358 perror("unlink[ctrl_iface]"); 359 wpa_printf(MSG_ERROR, "Could not unlink " 360 "existing ctrl_iface socket '%s'", 361 fname); 362 goto fail; 363 } 364 if (bind(priv->sock, (struct sockaddr *) &addr, 365 sizeof(addr)) < 0) { 366 perror("bind(PF_UNIX)"); 367 goto fail; 368 } 369 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 370 "ctrl_iface socket '%s'", fname); 371 } else { 372 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 373 "be in use - cannot override it"); 374 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 375 "not used anymore", fname); 376 os_free(fname); 377 fname = NULL; 378 goto fail; 379 } 380 } 381 382 if (gid_set && chown(fname, -1, gid) < 0) { 383 perror("chown[ctrl_interface/ifname]"); 384 goto fail; 385 } 386 387 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 388 perror("chmod[ctrl_interface/ifname]"); 389 goto fail; 390 } 391 os_free(fname); 392 393 havesock: 394 eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, 395 wpa_s, priv); 396 wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); 397 398 os_free(buf); 399 return priv; 400 401 fail: 402 if (priv->sock >= 0) 403 close(priv->sock); 404 os_free(priv); 405 if (fname) { 406 unlink(fname); 407 os_free(fname); 408 } 409 os_free(buf); 410 return NULL; 411 } 412 413 414 void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) 415 { 416 struct wpa_ctrl_dst *dst, *prev; 417 418 if (priv->sock > -1) { 419 char *fname; 420 char *buf, *dir = NULL, *gid_str = NULL; 421 eloop_unregister_read_sock(priv->sock); 422 if (priv->ctrl_dst) { 423 /* 424 * Wait a second before closing the control socket if 425 * there are any attached monitors in order to allow 426 * them to receive any pending messages. 427 */ 428 wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " 429 "monitors to receive messages"); 430 os_sleep(1, 0); 431 } 432 close(priv->sock); 433 priv->sock = -1; 434 fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s); 435 if (fname) { 436 unlink(fname); 437 os_free(fname); 438 } 439 440 buf = os_strdup(priv->wpa_s->conf->ctrl_interface); 441 if (buf == NULL) 442 goto free_dst; 443 if (os_strncmp(buf, "DIR=", 4) == 0) { 444 dir = buf + 4; 445 gid_str = os_strstr(dir, " GROUP="); 446 if (gid_str) { 447 *gid_str = '\0'; 448 gid_str += 7; 449 } 450 } else 451 dir = buf; 452 453 if (rmdir(dir) < 0) { 454 if (errno == ENOTEMPTY) { 455 wpa_printf(MSG_DEBUG, "Control interface " 456 "directory not empty - leaving it " 457 "behind"); 458 } else { 459 perror("rmdir[ctrl_interface]"); 460 } 461 } 462 os_free(buf); 463 } 464 465 free_dst: 466 dst = priv->ctrl_dst; 467 while (dst) { 468 prev = dst; 469 dst = dst->next; 470 os_free(prev); 471 } 472 os_free(priv); 473 } 474 475 476 /** 477 * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors 478 * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() 479 * @level: Priority level of the message 480 * @buf: Message data 481 * @len: Message length 482 * 483 * Send a packet to all monitor programs attached to the control interface. 484 */ 485 static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, 486 int level, const char *buf, 487 size_t len) 488 { 489 struct wpa_ctrl_dst *dst, *next; 490 char levelstr[10]; 491 int idx; 492 struct msghdr msg; 493 struct iovec io[2]; 494 495 dst = priv->ctrl_dst; 496 if (priv->sock < 0 || dst == NULL) 497 return; 498 499 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 500 io[0].iov_base = levelstr; 501 io[0].iov_len = os_strlen(levelstr); 502 io[1].iov_base = (char *) buf; 503 io[1].iov_len = len; 504 os_memset(&msg, 0, sizeof(msg)); 505 msg.msg_iov = io; 506 msg.msg_iovlen = 2; 507 508 idx = 0; 509 while (dst) { 510 next = dst->next; 511 if (level >= dst->debug_level) { 512 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 513 (u8 *) dst->addr.sun_path, dst->addrlen - 514 sizeof(dst->addr.sun_family)); 515 msg.msg_name = (void *) &dst->addr; 516 msg.msg_namelen = dst->addrlen; 517 if (sendmsg(priv->sock, &msg, 0) < 0) { 518 perror("sendmsg(CTRL_IFACE monitor)"); 519 dst->errors++; 520 if (dst->errors > 10) { 521 wpa_supplicant_ctrl_iface_detach( 522 priv, &dst->addr, 523 dst->addrlen); 524 } 525 } else 526 dst->errors = 0; 527 } 528 idx++; 529 dst = next; 530 } 531 } 532 533 534 void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) 535 { 536 char buf[256]; 537 int res; 538 struct sockaddr_un from; 539 socklen_t fromlen = sizeof(from); 540 541 for (;;) { 542 wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to " 543 "attach", priv->wpa_s->ifname); 544 eloop_wait_for_read_sock(priv->sock); 545 546 res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0, 547 (struct sockaddr *) &from, &fromlen); 548 if (res < 0) { 549 perror("recvfrom(ctrl_iface)"); 550 continue; 551 } 552 buf[res] = '\0'; 553 554 if (os_strcmp(buf, "ATTACH") == 0) { 555 /* handle ATTACH signal of first monitor interface */ 556 if (!wpa_supplicant_ctrl_iface_attach(priv, &from, 557 fromlen)) { 558 sendto(priv->sock, "OK\n", 3, 0, 559 (struct sockaddr *) &from, fromlen); 560 /* OK to continue */ 561 return; 562 } else { 563 sendto(priv->sock, "FAIL\n", 5, 0, 564 (struct sockaddr *) &from, fromlen); 565 } 566 } else { 567 /* return FAIL for all other signals */ 568 sendto(priv->sock, "FAIL\n", 5, 0, 569 (struct sockaddr *) &from, fromlen); 570 } 571 } 572 } 573 574 575 /* Global ctrl_iface */ 576 577 struct ctrl_iface_global_priv { 578 struct wpa_global *global; 579 int sock; 580 }; 581 582 583 static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, 584 void *sock_ctx) 585 { 586 struct wpa_global *global = eloop_ctx; 587 char buf[256]; 588 int res; 589 struct sockaddr_un from; 590 socklen_t fromlen = sizeof(from); 591 char *reply; 592 size_t reply_len; 593 594 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 595 (struct sockaddr *) &from, &fromlen); 596 if (res < 0) { 597 perror("recvfrom(ctrl_iface)"); 598 return; 599 } 600 buf[res] = '\0'; 601 602 reply = wpa_supplicant_global_ctrl_iface_process(global, buf, 603 &reply_len); 604 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_un addr; 621 622 priv = os_zalloc(sizeof(*priv)); 623 if (priv == NULL) 624 return NULL; 625 priv->global = global; 626 priv->sock = -1; 627 628 if (global->params.ctrl_interface == NULL) 629 return priv; 630 631 #ifdef ANDROID 632 priv->sock = android_get_control_socket(global->params.ctrl_interface); 633 if (priv->sock >= 0) 634 goto havesock; 635 #endif 636 wpa_printf(MSG_DEBUG, "Global control interface '%s'", 637 global->params.ctrl_interface); 638 639 priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 640 if (priv->sock < 0) { 641 perror("socket(PF_UNIX)"); 642 goto fail; 643 } 644 645 os_memset(&addr, 0, sizeof(addr)); 646 addr.sun_family = AF_UNIX; 647 os_strncpy(addr.sun_path, global->params.ctrl_interface, 648 sizeof(addr.sun_path)); 649 if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 650 perror("bind(PF_UNIX)"); 651 if (connect(priv->sock, (struct sockaddr *) &addr, 652 sizeof(addr)) < 0) { 653 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 654 " allow connections - assuming it was left" 655 "over from forced program termination"); 656 if (unlink(global->params.ctrl_interface) < 0) { 657 perror("unlink[ctrl_iface]"); 658 wpa_printf(MSG_ERROR, "Could not unlink " 659 "existing ctrl_iface socket '%s'", 660 global->params.ctrl_interface); 661 goto fail; 662 } 663 if (bind(priv->sock, (struct sockaddr *) &addr, 664 sizeof(addr)) < 0) { 665 perror("bind(PF_UNIX)"); 666 goto fail; 667 } 668 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 669 "ctrl_iface socket '%s'", 670 global->params.ctrl_interface); 671 } else { 672 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 673 "be in use - cannot override it"); 674 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 675 "not used anymore", 676 global->params.ctrl_interface); 677 goto fail; 678 } 679 } 680 havesock: 681 eloop_register_read_sock(priv->sock, 682 wpa_supplicant_global_ctrl_iface_receive, 683 global, NULL); 684 685 return priv; 686 687 fail: 688 if (priv->sock >= 0) 689 close(priv->sock); 690 os_free(priv); 691 return NULL; 692 } 693 694 695 void 696 wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) 697 { 698 if (priv->sock >= 0) { 699 eloop_unregister_read_sock(priv->sock); 700 close(priv->sock); 701 } 702 if (priv->global->params.ctrl_interface) 703 unlink(priv->global->params.ctrl_interface); 704 os_free(priv); 705 } 706