1 /* $OpenBSD: hostapd.c,v 1.35 2015/01/16 06:40:17 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org> 5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/ioctl.h> 21 #include <sys/types.h> 22 #include <sys/signal.h> 23 #include <sys/socket.h> 24 #include <sys/time.h> 25 #include <sys/queue.h> 26 #include <sys/stat.h> 27 28 #include <net/if.h> 29 #include <net/if_dl.h> 30 #include <net/if_media.h> 31 #include <net/if_arp.h> 32 #include <net/if_llc.h> 33 #include <net/bpf.h> 34 35 #include <netinet/in.h> 36 #include <netinet/if_ether.h> 37 #include <arpa/inet.h> 38 39 #include <errno.h> 40 #include <event.h> 41 #include <fcntl.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <stdarg.h> 45 #include <string.h> 46 #include <unistd.h> 47 #include <limits.h> 48 #include <err.h> 49 50 #include "hostapd.h" 51 #include "iapp.h" 52 53 void hostapd_usage(void); 54 void hostapd_udp_init(struct hostapd_config *); 55 void hostapd_sig_handler(int, short, void *); 56 static __inline int 57 hostapd_entry_cmp(struct hostapd_entry *, struct hostapd_entry *); 58 59 struct hostapd_config hostapd_cfg; 60 61 extern char *__progname; 62 char printbuf[BUFSIZ]; 63 64 void 65 hostapd_usage(void) 66 { 67 fprintf(stderr, "usage: %s [-dv] [-D macro=value] [-f file]\n", 68 __progname); 69 exit(EXIT_FAILURE); 70 } 71 72 void 73 hostapd_log(u_int level, const char *fmt, ...) 74 { 75 char *nfmt = NULL; 76 va_list ap; 77 78 if (level > hostapd_cfg.c_verbose) 79 return; 80 81 va_start(ap, fmt); 82 if (hostapd_cfg.c_debug) { 83 if (asprintf(&nfmt, "%s\n", fmt) != -1) 84 vfprintf(stderr, nfmt, ap); 85 else { 86 vfprintf(stderr, fmt, ap); 87 fprintf(stderr, "\n"); 88 } 89 fflush(stderr); 90 } else 91 vsyslog(LOG_INFO, fmt, ap); 92 va_end(ap); 93 94 if (nfmt != NULL) 95 free(nfmt); 96 } 97 98 void 99 hostapd_printf(const char *fmt, ...) 100 { 101 char newfmt[BUFSIZ]; 102 va_list ap; 103 size_t n; 104 105 if (fmt == NULL) 106 goto flush; 107 108 va_start(ap, fmt); 109 bzero(newfmt, sizeof(newfmt)); 110 if ((n = strlcpy(newfmt, printbuf, sizeof(newfmt))) >= sizeof(newfmt)) 111 goto va_flush; 112 if (strlcpy(newfmt + n, fmt, sizeof(newfmt) - n) >= sizeof(newfmt) - n) 113 goto va_flush; 114 if (vsnprintf(printbuf, sizeof(printbuf), newfmt, ap) == -1) 115 goto va_flush; 116 va_end(ap); 117 118 return; 119 120 va_flush: 121 va_end(ap); 122 flush: 123 if (strlen(printbuf)) 124 hostapd_log(HOSTAPD_LOG, "%s", printbuf); 125 bzero(printbuf, sizeof(printbuf)); 126 } 127 128 void 129 hostapd_fatal(const char *fmt, ...) 130 { 131 va_list ap; 132 133 va_start(ap, fmt); 134 if (hostapd_cfg.c_debug) { 135 vfprintf(stderr, fmt, ap); 136 fflush(stderr); 137 } else 138 vsyslog(LOG_ERR, fmt, ap); 139 va_end(ap); 140 141 hostapd_cleanup(&hostapd_cfg); 142 exit(EXIT_FAILURE); 143 } 144 145 int 146 hostapd_check_file_secrecy(int fd, const char *fname) 147 { 148 struct stat st; 149 150 if (fstat(fd, &st)) { 151 hostapd_log(HOSTAPD_LOG, 152 "cannot stat %s", fname); 153 return (-1); 154 } 155 156 if (st.st_uid != 0 && st.st_uid != getuid()) { 157 hostapd_log(HOSTAPD_LOG, 158 "%s: owner not root or current user", fname); 159 return (-1); 160 } 161 162 if (st.st_mode & (S_IRWXG | S_IRWXO)) { 163 hostapd_log(HOSTAPD_LOG, 164 "%s: group/world readable/writeable", fname); 165 return (-1); 166 } 167 168 return (0); 169 } 170 171 int 172 hostapd_bpf_open(u_int flags) 173 { 174 u_int i; 175 int fd = -1; 176 char *dev; 177 struct bpf_version bpv; 178 179 /* 180 * Try to open the next available BPF device 181 */ 182 for (i = 0; i < 255; i++) { 183 if (asprintf(&dev, "/dev/bpf%u", i) == -1) 184 hostapd_fatal("failed to allocate buffer\n"); 185 186 if ((fd = open(dev, flags)) != -1) { 187 free(dev); 188 break; 189 } 190 191 free(dev); 192 } 193 194 if (fd == -1) 195 hostapd_fatal("unable to open BPF device\n"); 196 197 /* 198 * Get and validate the BPF version 199 */ 200 201 if (ioctl(fd, BIOCVERSION, &bpv) == -1) 202 hostapd_fatal("failed to get BPF version: %s\n", 203 strerror(errno)); 204 205 if (bpv.bv_major != BPF_MAJOR_VERSION || 206 bpv.bv_minor < BPF_MINOR_VERSION) 207 hostapd_fatal("invalid BPF version\n"); 208 209 return (fd); 210 } 211 212 void 213 hostapd_udp_init(struct hostapd_config *cfg) 214 { 215 struct hostapd_iapp *iapp = &cfg->c_iapp; 216 struct ifreq ifr; 217 struct sockaddr_in *addr, baddr; 218 struct ip_mreq mreq; 219 int brd = 1; 220 221 bzero(&ifr, sizeof(ifr)); 222 223 /* 224 * Open a listening UDP socket 225 */ 226 227 if ((iapp->i_udp = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 228 hostapd_fatal("unable to open udp socket\n"); 229 230 cfg->c_flags |= HOSTAPD_CFG_F_UDP; 231 232 (void)strlcpy(ifr.ifr_name, iapp->i_iface, sizeof(ifr.ifr_name)); 233 234 if (ioctl(iapp->i_udp, SIOCGIFADDR, &ifr) == -1) 235 hostapd_fatal("UDP ioctl %s on \"%s\" failed: %s\n", 236 "SIOCGIFADDR", ifr.ifr_name, strerror(errno)); 237 238 addr = (struct sockaddr_in *)&ifr.ifr_addr; 239 iapp->i_addr.sin_family = AF_INET; 240 iapp->i_addr.sin_addr.s_addr = addr->sin_addr.s_addr; 241 if (iapp->i_addr.sin_port == 0) 242 iapp->i_addr.sin_port = htons(IAPP_PORT); 243 244 if (ioctl(iapp->i_udp, SIOCGIFBRDADDR, &ifr) == -1) 245 hostapd_fatal("UDP ioctl %s on \"%s\" failed: %s\n", 246 "SIOCGIFBRDADDR", ifr.ifr_name, strerror(errno)); 247 248 addr = (struct sockaddr_in *)&ifr.ifr_addr; 249 iapp->i_broadcast.sin_family = AF_INET; 250 iapp->i_broadcast.sin_addr.s_addr = addr->sin_addr.s_addr; 251 iapp->i_broadcast.sin_port = iapp->i_addr.sin_port; 252 253 baddr.sin_family = AF_INET; 254 baddr.sin_addr.s_addr = htonl(INADDR_ANY); 255 baddr.sin_port = iapp->i_addr.sin_port; 256 257 if (bind(iapp->i_udp, (struct sockaddr *)&baddr, 258 sizeof(baddr)) == -1) 259 hostapd_fatal("failed to bind UDP socket: %s\n", 260 strerror(errno)); 261 262 /* 263 * The revised 802.11F standard requires IAPP messages to be 264 * sent via multicast to the default group 224.0.1.178. 265 * Nevertheless, some implementations still use broadcasts 266 * for IAPP messages. 267 */ 268 if (cfg->c_flags & HOSTAPD_CFG_F_BRDCAST) { 269 /* 270 * Enable broadcast 271 */ 272 if (setsockopt(iapp->i_udp, SOL_SOCKET, SO_BROADCAST, 273 &brd, sizeof(brd)) == -1) 274 hostapd_fatal("failed to enable broadcast on socket\n"); 275 276 hostapd_log(HOSTAPD_LOG_DEBUG, "%s: using broadcast mode " 277 "(address %s)", iapp->i_iface, inet_ntoa(addr->sin_addr)); 278 } else { 279 /* 280 * Enable multicast 281 */ 282 bzero(&mreq, sizeof(mreq)); 283 284 iapp->i_multicast.sin_family = AF_INET; 285 if (iapp->i_multicast.sin_addr.s_addr == INADDR_ANY) 286 iapp->i_multicast.sin_addr.s_addr = 287 inet_addr(IAPP_MCASTADDR); 288 iapp->i_multicast.sin_port = iapp->i_addr.sin_port; 289 290 mreq.imr_multiaddr.s_addr = 291 iapp->i_multicast.sin_addr.s_addr; 292 mreq.imr_interface.s_addr = 293 iapp->i_addr.sin_addr.s_addr; 294 295 if (setsockopt(iapp->i_udp, IPPROTO_IP, 296 IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) 297 hostapd_fatal("failed to add multicast membership to " 298 "%s: %s\n", IAPP_MCASTADDR, strerror(errno)); 299 300 if (setsockopt(iapp->i_udp, IPPROTO_IP, IP_MULTICAST_TTL, 301 &iapp->i_ttl, sizeof(iapp->i_ttl)) < 0) 302 hostapd_fatal("failed to set multicast ttl to " 303 "%u: %s\n", iapp->i_ttl, strerror(errno)); 304 305 hostapd_log(HOSTAPD_LOG_DEBUG, "%s: using multicast mode " 306 "(ttl %u, group %s)", iapp->i_iface, iapp->i_ttl, 307 inet_ntoa(iapp->i_multicast.sin_addr)); 308 } 309 } 310 311 /* ARGSUSED */ 312 void 313 hostapd_sig_handler(int sig, short event, void *arg) 314 { 315 switch (sig) { 316 case SIGALRM: 317 case SIGTERM: 318 case SIGQUIT: 319 case SIGINT: 320 (void)event_loopexit(NULL); 321 } 322 } 323 324 void 325 hostapd_cleanup(struct hostapd_config *cfg) 326 { 327 struct hostapd_iapp *iapp = &cfg->c_iapp; 328 struct ip_mreq mreq; 329 struct hostapd_apme *apme; 330 struct hostapd_table *table; 331 struct hostapd_entry *entry; 332 333 /* Release all Host APs */ 334 if (cfg->c_flags & HOSTAPD_CFG_F_APME) { 335 while ((apme = TAILQ_FIRST(&cfg->c_apmes)) != NULL) 336 hostapd_apme_term(apme); 337 } 338 339 if (cfg->c_flags & HOSTAPD_CFG_F_PRIV && 340 (cfg->c_flags & HOSTAPD_CFG_F_BRDCAST) == 0) { 341 /* 342 * Disable multicast and let the kernel unsubscribe 343 * from the multicast group. 344 */ 345 346 bzero(&mreq, sizeof(mreq)); 347 348 mreq.imr_multiaddr.s_addr = 349 inet_addr(IAPP_MCASTADDR); 350 mreq.imr_interface.s_addr = 351 iapp->i_addr.sin_addr.s_addr; 352 353 if (setsockopt(iapp->i_udp, IPPROTO_IP, 354 IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) 355 hostapd_log(HOSTAPD_LOG, "failed to remove multicast" 356 " membership to %s: %s", 357 IAPP_MCASTADDR, strerror(errno)); 358 } 359 360 if ((cfg->c_flags & HOSTAPD_CFG_F_PRIV) == 0 && 361 cfg->c_flags & HOSTAPD_CFG_F_APME) { 362 /* Shutdown the Host AP protocol handler */ 363 hostapd_iapp_term(&hostapd_cfg); 364 } 365 366 /* Cleanup tables */ 367 while ((table = TAILQ_FIRST(&cfg->c_tables)) != NULL) { 368 while ((entry = RB_MIN(hostapd_tree, &table->t_tree)) != NULL) { 369 RB_REMOVE(hostapd_tree, &table->t_tree, entry); 370 free(entry); 371 } 372 while ((entry = TAILQ_FIRST(&table->t_mask_head)) != NULL) { 373 TAILQ_REMOVE(&table->t_mask_head, entry, e_entries); 374 free(entry); 375 } 376 TAILQ_REMOVE(&cfg->c_tables, table, t_entries); 377 free(table); 378 } 379 380 hostapd_log(HOSTAPD_LOG_VERBOSE, "bye!"); 381 } 382 383 int 384 main(int argc, char *argv[]) 385 { 386 struct event ev_sigalrm; 387 struct event ev_sigterm; 388 struct event ev_sigquit; 389 struct event ev_sigint; 390 struct hostapd_config *cfg = &hostapd_cfg; 391 struct hostapd_iapp *iapp; 392 struct hostapd_apme *apme; 393 char *config = NULL; 394 u_int debug = 0, ret; 395 int ch; 396 397 /* Set startup logging */ 398 cfg->c_debug = 1; 399 400 /* 401 * Get and parse command line options 402 */ 403 while ((ch = getopt(argc, argv, "f:D:dv")) != -1) { 404 switch (ch) { 405 case 'f': 406 config = optarg; 407 break; 408 case 'D': 409 if (hostapd_parse_symset(optarg) < 0) 410 hostapd_fatal("could not parse macro " 411 "definition %s\n", optarg); 412 break; 413 case 'd': 414 debug++; 415 break; 416 case 'v': 417 cfg->c_verbose++; 418 break; 419 default: 420 hostapd_usage(); 421 } 422 } 423 424 argc -= optind; 425 argv += optind; 426 if (argc > 0) 427 hostapd_usage(); 428 429 if (config == NULL) 430 ret = strlcpy(cfg->c_config, HOSTAPD_CONFIG, sizeof(cfg->c_config)); 431 else 432 ret = strlcpy(cfg->c_config, config, sizeof(cfg->c_config)); 433 if (ret >= sizeof(cfg->c_config)) 434 hostapd_fatal("invalid configuration file\n"); 435 436 if (geteuid()) 437 hostapd_fatal("need root privileges\n"); 438 439 /* Parse the configuration file */ 440 if (hostapd_parse_file(cfg) != 0) 441 hostapd_fatal("invalid configuration in %s\n", cfg->c_config); 442 443 iapp = &cfg->c_iapp; 444 445 if ((cfg->c_flags & HOSTAPD_CFG_F_IAPP) == 0) 446 hostapd_fatal("IAPP interface not specified\n"); 447 448 if (cfg->c_apme_dlt == 0) 449 cfg->c_apme_dlt = HOSTAPD_DLT; 450 451 /* 452 * Setup the hostapd handlers 453 */ 454 hostapd_udp_init(cfg); 455 hostapd_llc_init(cfg); 456 457 /* 458 * Set runtime logging and detach as daemon 459 */ 460 if ((cfg->c_debug = debug) == 0) { 461 openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); 462 tzset(); 463 if (daemon(0, 0) == -1) 464 hostapd_fatal("failed to daemonize\n"); 465 } 466 467 if (cfg->c_flags & HOSTAPD_CFG_F_APME) { 468 TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) 469 hostapd_apme_init(apme); 470 } else 471 hostapd_log(HOSTAPD_LOG, "%s: running without a Host AP", 472 iapp->i_iface); 473 474 /* Drop all privileges in an unprivileged child process */ 475 hostapd_priv_init(cfg); 476 477 if (cfg->c_flags & HOSTAPD_CFG_F_APME) 478 setproctitle("IAPP: %s, Host AP", iapp->i_iface); 479 else 480 setproctitle("IAPP: %s", iapp->i_iface); 481 482 /* 483 * Unprivileged child process 484 */ 485 486 (void)event_init(); 487 488 /* 489 * Set signal handlers 490 */ 491 signal_set(&ev_sigalrm, SIGALRM, hostapd_sig_handler, NULL); 492 signal_set(&ev_sigterm, SIGTERM, hostapd_sig_handler, NULL); 493 signal_set(&ev_sigquit, SIGQUIT, hostapd_sig_handler, NULL); 494 signal_set(&ev_sigint, SIGINT, hostapd_sig_handler, NULL); 495 signal_add(&ev_sigalrm, NULL); 496 signal_add(&ev_sigterm, NULL); 497 signal_add(&ev_sigquit, NULL); 498 signal_add(&ev_sigint, NULL); 499 signal(SIGHUP, SIG_IGN); 500 signal(SIGCHLD, SIG_IGN); 501 502 /* Initialize the IAPP protocol handler */ 503 hostapd_iapp_init(cfg); 504 505 /* 506 * Schedule the Host AP listener 507 */ 508 if (cfg->c_flags & HOSTAPD_CFG_F_APME) { 509 TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) { 510 event_set(&apme->a_ev, apme->a_raw, 511 EV_READ | EV_PERSIST, hostapd_apme_input, apme); 512 if (event_add(&apme->a_ev, NULL) == -1) 513 hostapd_fatal("failed to add APME event"); 514 } 515 } 516 517 /* 518 * Schedule the IAPP listener 519 */ 520 event_set(&iapp->i_udp_ev, iapp->i_udp, EV_READ | EV_PERSIST, 521 hostapd_iapp_input, cfg); 522 if (event_add(&iapp->i_udp_ev, NULL) == -1) 523 hostapd_fatal("failed to add IAPP event"); 524 525 hostapd_log(HOSTAPD_LOG, "starting hostapd with pid %u", 526 getpid()); 527 528 /* Run event loop */ 529 if (event_dispatch() == -1) 530 hostapd_fatal("failed to dispatch hostapd"); 531 532 /* Executed after the event loop has been terminated */ 533 hostapd_cleanup(cfg); 534 return (EXIT_SUCCESS); 535 } 536 537 void 538 hostapd_randval(u_int8_t *buf, const u_int len) 539 { 540 u_int32_t data = 0; 541 u_int i; 542 543 for (i = 0; i < len; i++) { 544 if ((i % sizeof(data)) == 0) 545 data = arc4random(); 546 buf[i] = data & 0xff; 547 data >>= 8; 548 } 549 } 550 551 struct hostapd_table * 552 hostapd_table_add(struct hostapd_config *cfg, const char *name) 553 { 554 struct hostapd_table *table; 555 556 if (hostapd_table_lookup(cfg, name) != NULL) 557 return (NULL); 558 if ((table = (struct hostapd_table *) 559 calloc(1, sizeof(struct hostapd_table))) == NULL) 560 return (NULL); 561 if (strlcpy(table->t_name, name, sizeof(table->t_name)) >= 562 sizeof(table->t_name)) { 563 free(table); 564 return (NULL); 565 } 566 RB_INIT(&table->t_tree); 567 TAILQ_INIT(&table->t_mask_head); 568 TAILQ_INSERT_TAIL(&cfg->c_tables, table, t_entries); 569 570 return (table); 571 } 572 573 struct hostapd_table * 574 hostapd_table_lookup(struct hostapd_config *cfg, const char *name) 575 { 576 struct hostapd_table *table; 577 578 TAILQ_FOREACH(table, &cfg->c_tables, t_entries) { 579 if (strcmp(name, table->t_name) == 0) 580 return (table); 581 } 582 583 return (NULL); 584 } 585 586 struct hostapd_entry * 587 hostapd_entry_add(struct hostapd_table *table, u_int8_t *lladdr) 588 { 589 struct hostapd_entry *entry; 590 591 if (hostapd_entry_lookup(table, lladdr) != NULL) 592 return (NULL); 593 594 if ((entry = (struct hostapd_entry *) 595 calloc(1, sizeof(struct hostapd_entry))) == NULL) 596 return (NULL); 597 598 bcopy(lladdr, entry->e_lladdr, IEEE80211_ADDR_LEN); 599 RB_INSERT(hostapd_tree, &table->t_tree, entry); 600 601 return (entry); 602 } 603 604 struct hostapd_entry * 605 hostapd_entry_lookup(struct hostapd_table *table, u_int8_t *lladdr) 606 { 607 struct hostapd_entry *entry, key; 608 609 bcopy(lladdr, key.e_lladdr, IEEE80211_ADDR_LEN); 610 if ((entry = RB_FIND(hostapd_tree, &table->t_tree, &key)) != NULL) 611 return (entry); 612 613 /* Masked entries can't be handled by the red-black tree */ 614 TAILQ_FOREACH(entry, &table->t_mask_head, e_entries) { 615 if (HOSTAPD_ENTRY_MASK_MATCH(entry, lladdr)) 616 return (entry); 617 } 618 619 return (NULL); 620 } 621 622 void 623 hostapd_entry_update(struct hostapd_table *table, struct hostapd_entry *entry) 624 { 625 RB_REMOVE(hostapd_tree, &table->t_tree, entry); 626 627 /* Apply mask to entry */ 628 if (entry->e_flags & HOSTAPD_ENTRY_F_MASK) { 629 HOSTAPD_ENTRY_MASK_ADD(entry->e_lladdr, entry->e_mask); 630 TAILQ_INSERT_TAIL(&table->t_mask_head, entry, e_entries); 631 } else { 632 RB_INSERT(hostapd_tree, &table->t_tree, entry); 633 } 634 } 635 636 static __inline int 637 hostapd_entry_cmp(struct hostapd_entry *a, struct hostapd_entry *b) 638 { 639 return (memcmp(a->e_lladdr, b->e_lladdr, IEEE80211_ADDR_LEN)); 640 } 641 642 RB_GENERATE(hostapd_tree, hostapd_entry, e_nodes, hostapd_entry_cmp); 643