1 /* 2 * WPA Supplicant - driver interaction with BSD net80211 layer 3 * Copyright (c) 2004, Sam Leffler <sam (at) errno.com> 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/ioctl.h> 17 18 #include "common.h" 19 #include "driver.h" 20 #include "eloop.h" 21 #include "ieee802_11_defs.h" 22 23 #include <net/if.h> 24 25 #ifdef __NetBSD__ 26 #include <net/if_ether.h> 27 #define COMPAT_FREEBSD_NET80211 28 #else 29 #include <net/ethernet.h> 30 #endif 31 32 #include <net80211/ieee80211.h> 33 #include <net80211/ieee80211_crypto.h> 34 #include <net80211/ieee80211_ioctl.h> 35 36 struct wpa_driver_bsd_data { 37 int sock; /* open socket for 802.11 ioctls */ 38 int route; /* routing socket for events */ 39 char ifname[IFNAMSIZ+1]; /* interface name */ 40 unsigned int ifindex; /* interface index */ 41 void *ctx; 42 int prev_roaming; /* roaming state to restore on deinit */ 43 int prev_privacy; /* privacy state to restore on deinit */ 44 int prev_wpa; /* wpa state to restore on deinit */ 45 }; 46 47 static int 48 set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len) 49 { 50 struct ieee80211req ireq; 51 52 os_memset(&ireq, 0, sizeof(ireq)); 53 os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ); 54 ireq.i_type = op; 55 ireq.i_len = arg_len; 56 ireq.i_data = (void *) arg; 57 58 if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) { 59 fprintf(stderr, "ioctl[SIOCS80211, op %u, len %u]: %s\n", 60 op, arg_len, strerror(errno)); 61 return -1; 62 } 63 return 0; 64 } 65 66 static int 67 get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len) 68 { 69 struct ieee80211req ireq; 70 71 os_memset(&ireq, 0, sizeof(ireq)); 72 os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ); 73 ireq.i_type = op; 74 ireq.i_len = arg_len; 75 ireq.i_data = arg; 76 77 if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) { 78 fprintf(stderr, "ioctl[SIOCG80211, op %u, len %u]: %s\n", 79 op, arg_len, strerror(errno)); 80 return -1; 81 } 82 return ireq.i_len; 83 } 84 85 static int 86 set80211param(struct wpa_driver_bsd_data *drv, int op, int arg) 87 { 88 struct ieee80211req ireq; 89 90 os_memset(&ireq, 0, sizeof(ireq)); 91 os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ); 92 ireq.i_type = op; 93 ireq.i_val = arg; 94 95 if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) { 96 fprintf(stderr, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n", 97 op, arg, strerror(errno)); 98 return -1; 99 } 100 return 0; 101 } 102 103 static int 104 get80211param(struct wpa_driver_bsd_data *drv, int op) 105 { 106 struct ieee80211req ireq; 107 108 os_memset(&ireq, 0, sizeof(ireq)); 109 os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ); 110 ireq.i_type = op; 111 112 if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) { 113 fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n", 114 op, strerror(errno)); 115 return -1; 116 } 117 return ireq.i_val; 118 } 119 120 static int 121 getifflags(struct wpa_driver_bsd_data *drv, int *flags) 122 { 123 struct ifreq ifr; 124 125 os_memset(&ifr, 0, sizeof(ifr)); 126 os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 127 if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 128 perror("SIOCGIFFLAGS"); 129 return errno; 130 } 131 *flags = ifr.ifr_flags & 0xffff; 132 return 0; 133 } 134 135 static int 136 setifflags(struct wpa_driver_bsd_data *drv, int flags) 137 { 138 struct ifreq ifr; 139 140 os_memset(&ifr, 0, sizeof(ifr)); 141 os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 142 ifr.ifr_flags = flags & 0xffff; 143 if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { 144 perror("SIOCSIFFLAGS"); 145 return errno; 146 } 147 return 0; 148 } 149 150 static int 151 wpa_driver_bsd_get_bssid(void *priv, u8 *bssid) 152 { 153 struct wpa_driver_bsd_data *drv = priv; 154 155 return get80211var(drv, IEEE80211_IOC_BSSID, 156 bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0; 157 } 158 159 #if 0 160 static int 161 wpa_driver_bsd_set_bssid(void *priv, const char *bssid) 162 { 163 struct wpa_driver_bsd_data *drv = priv; 164 165 return set80211var(drv, IEEE80211_IOC_BSSID, 166 bssid, IEEE80211_ADDR_LEN); 167 } 168 #endif 169 170 static int 171 wpa_driver_bsd_get_ssid(void *priv, u8 *ssid) 172 { 173 struct wpa_driver_bsd_data *drv = priv; 174 175 return get80211var(drv, IEEE80211_IOC_SSID, 176 ssid, IEEE80211_NWID_LEN); 177 } 178 179 static int 180 wpa_driver_bsd_set_ssid(void *priv, const u8 *ssid, 181 size_t ssid_len) 182 { 183 struct wpa_driver_bsd_data *drv = priv; 184 185 return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); 186 } 187 188 static int 189 wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv, 190 const u8 *wpa_ie, size_t wpa_ie_len) 191 { 192 return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len); 193 } 194 195 static int 196 wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy) 197 { 198 struct wpa_driver_bsd_data *drv = priv; 199 int ret = 0; 200 201 wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d", 202 __FUNCTION__, wpa, privacy); 203 204 if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0) 205 ret = -1; 206 if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) 207 ret = -1; 208 if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0) 209 ret = -1; 210 211 return ret; 212 } 213 214 static int 215 wpa_driver_bsd_set_wpa(void *priv, int enabled) 216 { 217 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); 218 219 return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled); 220 } 221 222 static int 223 wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx, 224 const unsigned char *addr) 225 { 226 struct ieee80211req_del_key wk; 227 228 os_memset(&wk, 0, sizeof(wk)); 229 if (addr != NULL && 230 bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) != 0) { 231 struct ether_addr ea; 232 233 os_memcpy(&ea, addr, IEEE80211_ADDR_LEN); 234 wpa_printf(MSG_DEBUG, "%s: addr=%s keyidx=%d", 235 __func__, ether_ntoa(&ea), key_idx); 236 os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); 237 wk.idk_keyix = (uint8_t) IEEE80211_KEYIX_NONE; 238 } else { 239 wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __func__, key_idx); 240 wk.idk_keyix = key_idx; 241 } 242 return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); 243 } 244 245 static int 246 wpa_driver_bsd_set_key(void *priv, wpa_alg alg, 247 const unsigned char *addr, int key_idx, int set_tx, 248 const u8 *seq, size_t seq_len, 249 const u8 *key, size_t key_len) 250 { 251 struct wpa_driver_bsd_data *drv = priv; 252 struct ieee80211req_key wk; 253 struct ether_addr ea; 254 char *alg_name; 255 u_int8_t cipher; 256 257 if (alg == WPA_ALG_NONE) 258 return wpa_driver_bsd_del_key(drv, key_idx, addr); 259 260 switch (alg) { 261 case WPA_ALG_WEP: 262 alg_name = "WEP"; 263 cipher = IEEE80211_CIPHER_WEP; 264 break; 265 case WPA_ALG_TKIP: 266 alg_name = "TKIP"; 267 cipher = IEEE80211_CIPHER_TKIP; 268 break; 269 case WPA_ALG_CCMP: 270 alg_name = "CCMP"; 271 cipher = IEEE80211_CIPHER_AES_CCM; 272 break; 273 default: 274 wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d", 275 __func__, alg); 276 return -1; 277 } 278 279 os_memcpy(&ea, addr, IEEE80211_ADDR_LEN); 280 wpa_printf(MSG_DEBUG, 281 "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu", 282 __func__, alg_name, ether_ntoa(&ea), key_idx, set_tx, 283 seq_len, key_len); 284 285 if (seq_len > sizeof(u_int64_t)) { 286 wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big", 287 __func__, seq_len); 288 return -2; 289 } 290 if (key_len > sizeof(wk.ik_keydata)) { 291 wpa_printf(MSG_DEBUG, "%s: key length %zu too big", 292 __func__, key_len); 293 return -3; 294 } 295 296 os_memset(&wk, 0, sizeof(wk)); 297 wk.ik_type = cipher; 298 wk.ik_flags = IEEE80211_KEY_RECV; 299 if (set_tx) 300 wk.ik_flags |= IEEE80211_KEY_XMIT; 301 os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); 302 /* 303 * Deduce whether group/global or unicast key by checking 304 * the address (yech). Note also that we can only mark global 305 * keys default; doing this for a unicast key is an error. 306 */ 307 if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) { 308 wk.ik_flags |= IEEE80211_KEY_GROUP; 309 wk.ik_keyix = key_idx; 310 } else { 311 wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx); 312 } 313 if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) 314 wk.ik_flags |= IEEE80211_KEY_DEFAULT; 315 wk.ik_keylen = key_len; 316 os_memcpy(&wk.ik_keyrsc, seq, seq_len); 317 os_memcpy(wk.ik_keydata, key, key_len); 318 319 return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); 320 } 321 322 static int 323 wpa_driver_bsd_set_countermeasures(void *priv, int enabled) 324 { 325 struct wpa_driver_bsd_data *drv = priv; 326 327 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 328 return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled); 329 } 330 331 332 static int 333 wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled) 334 { 335 struct wpa_driver_bsd_data *drv = priv; 336 337 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 338 return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled); 339 } 340 341 static int 342 wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code) 343 { 344 struct wpa_driver_bsd_data *drv = priv; 345 struct ieee80211req_mlme mlme; 346 347 wpa_printf(MSG_DEBUG, "%s", __func__); 348 os_memset(&mlme, 0, sizeof(mlme)); 349 mlme.im_op = IEEE80211_MLME_DEAUTH; 350 mlme.im_reason = reason_code; 351 os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 352 return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); 353 } 354 355 static int 356 wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code) 357 { 358 struct wpa_driver_bsd_data *drv = priv; 359 struct ieee80211req_mlme mlme; 360 361 wpa_printf(MSG_DEBUG, "%s", __func__); 362 os_memset(&mlme, 0, sizeof(mlme)); 363 mlme.im_op = IEEE80211_MLME_DISASSOC; 364 mlme.im_reason = reason_code; 365 os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 366 return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); 367 } 368 369 static int 370 wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) 371 { 372 struct wpa_driver_bsd_data *drv = priv; 373 struct ieee80211req_mlme mlme; 374 int privacy; 375 376 wpa_printf(MSG_DEBUG, 377 "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" 378 , __func__ 379 , params->ssid_len, params->ssid 380 , params->wpa_ie_len 381 , params->pairwise_suite 382 , params->group_suite 383 , params->key_mgmt_suite 384 ); 385 386 /* XXX error handling is wrong but unclear what to do... */ 387 if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) 388 return -1; 389 390 privacy = !(params->pairwise_suite == CIPHER_NONE && 391 params->group_suite == CIPHER_NONE && 392 params->key_mgmt_suite == KEY_MGMT_NONE && 393 params->wpa_ie_len == 0); 394 wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); 395 396 if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) 397 return -1; 398 399 if (params->wpa_ie_len && 400 set80211param(drv, IEEE80211_IOC_WPA, 401 params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0) 402 return -1; 403 404 os_memset(&mlme, 0, sizeof(mlme)); 405 mlme.im_op = IEEE80211_MLME_ASSOC; 406 if (params->ssid != NULL) 407 os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len); 408 mlme.im_ssid_len = params->ssid_len; 409 if (params->bssid != NULL) 410 os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); 411 if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0) 412 return -1; 413 return 0; 414 } 415 416 static int 417 wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg) 418 { 419 struct wpa_driver_bsd_data *drv = priv; 420 int authmode; 421 422 if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) && 423 (auth_alg & AUTH_ALG_SHARED_KEY)) 424 authmode = IEEE80211_AUTH_AUTO; 425 else if (auth_alg & AUTH_ALG_SHARED_KEY) 426 authmode = IEEE80211_AUTH_SHARED; 427 else 428 authmode = IEEE80211_AUTH_OPEN; 429 430 return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode); 431 } 432 433 static int 434 wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len) 435 { 436 struct wpa_driver_bsd_data *drv = priv; 437 int flags; 438 439 /* NB: interface must be marked UP to do a scan */ 440 if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0) 441 return -1; 442 443 /* set desired ssid before scan */ 444 if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0) 445 return -1; 446 447 /* NB: net80211 delivers a scan complete event so no need to poll */ 448 return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0); 449 } 450 451 #include <net/route.h> 452 #if __FreeBSD__ 453 #include <net80211/ieee80211_freebsd.h> 454 #endif 455 #if __NetBSD__ 456 #include <net80211/ieee80211_netbsd.h> 457 #endif 458 459 static void 460 wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) 461 { 462 struct wpa_driver_bsd_data *drv = sock_ctx; 463 char buf[2048]; 464 struct if_announcemsghdr *ifan; 465 struct if_msghdr *ifm; 466 struct rt_msghdr *rtm; 467 union wpa_event_data event; 468 struct ieee80211_michael_event *mic; 469 int n; 470 471 n = read(sock, buf, sizeof(buf)); 472 if (n < 0) { 473 if (errno != EINTR && errno != EAGAIN) 474 perror("read(PF_ROUTE)"); 475 return; 476 } 477 478 rtm = (struct rt_msghdr *) buf; 479 if (rtm->rtm_version != RTM_VERSION) { 480 wpa_printf(MSG_DEBUG, "Routing message version %d not " 481 "understood\n", rtm->rtm_version); 482 return; 483 } 484 os_memset(&event, 0, sizeof(event)); 485 switch (rtm->rtm_type) { 486 case RTM_IFANNOUNCE: 487 ifan = (struct if_announcemsghdr *) rtm; 488 if (ifan->ifan_index != drv->ifindex) 489 break; 490 strlcpy(event.interface_status.ifname, drv->ifname, 491 sizeof(event.interface_status.ifname)); 492 switch (ifan->ifan_what) { 493 case IFAN_DEPARTURE: 494 event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 495 default: 496 return; 497 } 498 wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s", 499 event.interface_status.ifname, 500 ifan->ifan_what == IFAN_DEPARTURE ? 501 "removed" : "added"); 502 wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); 503 break; 504 case RTM_IEEE80211: 505 ifan = (struct if_announcemsghdr *) rtm; 506 if (ifan->ifan_index != drv->ifindex) 507 break; 508 switch (ifan->ifan_what) { 509 case RTM_IEEE80211_ASSOC: 510 case RTM_IEEE80211_REASSOC: 511 wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); 512 break; 513 case RTM_IEEE80211_DISASSOC: 514 wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); 515 break; 516 case RTM_IEEE80211_SCAN: 517 wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL); 518 break; 519 case RTM_IEEE80211_REPLAY: 520 /* ignore */ 521 break; 522 case RTM_IEEE80211_MICHAEL: 523 mic = (struct ieee80211_michael_event *) &ifan[1]; 524 wpa_printf(MSG_DEBUG, 525 "Michael MIC failure wireless event: " 526 "keyix=%u src_addr=" MACSTR, mic->iev_keyix, 527 MAC2STR(mic->iev_src)); 528 529 os_memset(&event, 0, sizeof(event)); 530 event.michael_mic_failure.unicast = 531 !IEEE80211_IS_MULTICAST(mic->iev_dst); 532 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, 533 &event); 534 break; 535 } 536 break; 537 case RTM_IFINFO: 538 ifm = (struct if_msghdr *) rtm; 539 if (ifm->ifm_index != drv->ifindex) 540 break; 541 if ((rtm->rtm_flags & RTF_UP) == 0) { 542 strlcpy(event.interface_status.ifname, drv->ifname, 543 sizeof(event.interface_status.ifname)); 544 event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 545 wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", 546 event.interface_status.ifname); 547 wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); 548 } 549 break; 550 } 551 } 552 553 /* Compare function for sorting scan results. Return >0 if @b is consider 554 * better. */ 555 static int 556 wpa_scan_result_compar(const void *a, const void *b) 557 { 558 const struct wpa_scan_result *wa = a; 559 const struct wpa_scan_result *wb = b; 560 561 /* WPA/WPA2 support preferred */ 562 if ((wb->wpa_ie_len || wb->rsn_ie_len) && 563 !(wa->wpa_ie_len || wa->rsn_ie_len)) 564 return 1; 565 if (!(wb->wpa_ie_len || wb->rsn_ie_len) && 566 (wa->wpa_ie_len || wa->rsn_ie_len)) 567 return -1; 568 569 /* privacy support preferred */ 570 if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) && 571 (wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0) 572 return 1; 573 if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 && 574 (wb->caps & IEEE80211_CAPINFO_PRIVACY)) 575 return -1; 576 577 /* best/max rate preferred if signal level close enough XXX */ 578 if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5) 579 return wb->maxrate - wa->maxrate; 580 581 /* use freq for channel preference */ 582 583 /* all things being equal, use signal level */ 584 return wb->level - wa->level; 585 } 586 587 static int 588 getmaxrate(uint8_t rates[15], uint8_t nrates) 589 { 590 int i, maxrate = -1; 591 592 for (i = 0; i < nrates; i++) { 593 int rate = rates[i] & IEEE80211_RATE_VAL; 594 if (rate > maxrate) 595 rate = maxrate; 596 } 597 return maxrate; 598 } 599 600 /* unalligned little endian access */ 601 #define LE_READ_4(p) \ 602 ((u_int32_t) \ 603 ((((const u_int8_t *)(p))[0] ) | \ 604 (((const u_int8_t *)(p))[1] << 8) | \ 605 (((const u_int8_t *)(p))[2] << 16) | \ 606 (((const u_int8_t *)(p))[3] << 24))) 607 608 static int __inline 609 iswpaoui(const u_int8_t *frm) 610 { 611 return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI); 612 } 613 614 static int 615 wpa_driver_bsd_get_scan_results(void *priv, 616 struct wpa_scan_result *results, 617 size_t max_size) 618 { 619 #define min(a,b) ((a)>(b)?(b):(a)) 620 struct wpa_driver_bsd_data *drv = priv; 621 uint8_t buf[24*1024]; 622 uint8_t *cp, *vp; 623 struct ieee80211req_scan_result *sr; 624 struct wpa_scan_result *wsr; 625 int len, ielen; 626 627 os_memset(results, 0, max_size * sizeof(struct wpa_scan_result)); 628 629 len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf)); 630 if (len < 0) 631 return -1; 632 cp = buf; 633 wsr = results; 634 while (len >= sizeof(struct ieee80211req_scan_result)) { 635 sr = (struct ieee80211req_scan_result *) cp; 636 os_memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN); 637 wsr->ssid_len = sr->isr_ssid_len; 638 wsr->freq = sr->isr_freq; 639 wsr->noise = sr->isr_noise; 640 wsr->qual = sr->isr_rssi; 641 wsr->level = 0; /* XXX? */ 642 wsr->caps = sr->isr_capinfo; 643 wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates); 644 vp = (u_int8_t *)(sr+1); 645 os_memcpy(wsr->ssid, vp, sr->isr_ssid_len); 646 if (sr->isr_ie_len > 0) { 647 vp += sr->isr_ssid_len; 648 ielen = sr->isr_ie_len; 649 while (ielen > 0) { 650 switch (vp[0]) { 651 case IEEE80211_ELEMID_VENDOR: 652 if (!iswpaoui(vp)) 653 break; 654 wsr->wpa_ie_len = 655 min(2+vp[1], SSID_MAX_WPA_IE_LEN); 656 os_memcpy(wsr->wpa_ie, vp, 657 wsr->wpa_ie_len); 658 break; 659 case IEEE80211_ELEMID_RSN: 660 wsr->rsn_ie_len = 661 min(2+vp[1], SSID_MAX_WPA_IE_LEN); 662 os_memcpy(wsr->rsn_ie, vp, 663 wsr->rsn_ie_len); 664 break; 665 } 666 ielen -= 2+vp[1]; 667 vp += 2+vp[1]; 668 } 669 } 670 671 cp += sr->isr_len, len -= sr->isr_len; 672 wsr++; 673 } 674 qsort(results, wsr - results, sizeof(struct wpa_scan_result), 675 wpa_scan_result_compar); 676 677 wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)", 678 len, wsr - results); 679 680 return wsr - results; 681 #undef min 682 } 683 684 static void * 685 wpa_driver_bsd_init(void *ctx, const char *ifname) 686 { 687 #define GETPARAM(drv, param, v) \ 688 (((v) = get80211param(drv, param)) != -1) 689 struct wpa_driver_bsd_data *drv; 690 691 drv = os_zalloc(sizeof(*drv)); 692 if (drv == NULL) 693 return NULL; 694 /* 695 * NB: We require the interface name be mappable to an index. 696 * This implies we do not support having wpa_supplicant 697 * wait for an interface to appear. This seems ok; that 698 * doesn't belong here; it's really the job of devd. 699 */ 700 drv->ifindex = if_nametoindex(ifname); 701 if (drv->ifindex == 0) { 702 wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", 703 __func__, ifname); 704 goto fail1; 705 } 706 drv->sock = socket(PF_INET, SOCK_DGRAM, 0); 707 if (drv->sock < 0) 708 goto fail1; 709 drv->route = socket(PF_ROUTE, SOCK_RAW, 0); 710 if (drv->route < 0) 711 goto fail; 712 eloop_register_read_sock(drv->route, 713 wpa_driver_bsd_event_receive, ctx, drv); 714 715 drv->ctx = ctx; 716 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 717 718 if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { 719 wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", 720 __func__, strerror(errno)); 721 goto fail; 722 } 723 if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) { 724 wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s", 725 __func__, strerror(errno)); 726 goto fail; 727 } 728 if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) { 729 wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s", 730 __func__, strerror(errno)); 731 goto fail; 732 } 733 if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) { 734 wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based " 735 "roaming: %s", __func__, strerror(errno)); 736 goto fail; 737 } 738 739 if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) { 740 wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s", 741 __func__, strerror(errno)); 742 goto fail; 743 } 744 745 return drv; 746 fail: 747 close(drv->sock); 748 fail1: 749 os_free(drv); 750 return NULL; 751 #undef GETPARAM 752 } 753 754 static void 755 wpa_driver_bsd_deinit(void *priv) 756 { 757 struct wpa_driver_bsd_data *drv = priv; 758 int flags; 759 760 eloop_unregister_read_sock(drv->route); 761 762 /* NB: mark interface down */ 763 if (getifflags(drv, &flags) == 0) 764 (void) setifflags(drv, flags &~ IFF_UP); 765 766 wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy); 767 if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0) 768 wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state", 769 __func__); 770 771 (void) close(drv->route); /* ioctl socket */ 772 (void) close(drv->sock); /* event socket */ 773 os_free(drv); 774 } 775 776 777 const struct wpa_driver_ops wpa_driver_bsd_ops = { 778 .name = "bsd", 779 .desc = "BSD 802.11 support (Atheros, etc.)", 780 .init = wpa_driver_bsd_init, 781 .deinit = wpa_driver_bsd_deinit, 782 .get_bssid = wpa_driver_bsd_get_bssid, 783 .get_ssid = wpa_driver_bsd_get_ssid, 784 .set_wpa = wpa_driver_bsd_set_wpa, 785 .set_key = wpa_driver_bsd_set_key, 786 .set_countermeasures = wpa_driver_bsd_set_countermeasures, 787 .set_drop_unencrypted = wpa_driver_bsd_set_drop_unencrypted, 788 .scan = wpa_driver_bsd_scan, 789 .get_scan_results = wpa_driver_bsd_get_scan_results, 790 .deauthenticate = wpa_driver_bsd_deauthenticate, 791 .disassociate = wpa_driver_bsd_disassociate, 792 .associate = wpa_driver_bsd_associate, 793 .set_auth_alg = wpa_driver_bsd_set_auth_alg, 794 }; 795