1/* 2 * Driver interaction with generic Linux Wireless Extensions 3 * Copyright (c) 2003-2010, 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 * This file implements a driver interface for the Linux Wireless Extensions. 9 * When used with WE-18 or newer, this interface can be used as-is with number 10 * of drivers. In addition to this, some of the common functions in this file 11 * can be used by other driver interface implementations that use generic WE 12 * ioctls, but require private ioctls for some of the functionality. 13 */ 14 15#include "includes.h" 16#include <sys/ioctl.h> 17#include <sys/types.h> 18#include <sys/stat.h> 19#include <fcntl.h> 20#include <net/if_arp.h> 21 22#include "linux_wext.h" 23#include "common.h" 24#include "eloop.h" 25#include "common/ieee802_11_defs.h" 26#include "common/wpa_common.h" 27#include "priv_netlink.h" 28#include "netlink.h" 29#include "linux_ioctl.h" 30#include "rfkill.h" 31#include "driver.h" 32#include "driver_wext.h" 33 34#ifdef ANDROID 35#include "android_drv.h" 36#endif /* ANDROID */ 37 38static int wpa_driver_wext_flush_pmkid(void *priv); 39static int wpa_driver_wext_get_range(void *priv); 40static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv); 41static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv); 42static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg); 43 44 45int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, 46 int idx, u32 value) 47{ 48 struct iwreq iwr; 49 int ret = 0; 50 51 os_memset(&iwr, 0, sizeof(iwr)); 52 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 53 iwr.u.param.flags = idx & IW_AUTH_INDEX; 54 iwr.u.param.value = value; 55 56 if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) { 57 if (errno != EOPNOTSUPP) { 58 wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d " 59 "value 0x%x) failed: %s)", 60 idx, value, strerror(errno)); 61 } 62 ret = errno == EOPNOTSUPP ? -2 : -1; 63 } 64 65 return ret; 66} 67 68 69/** 70 * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP 71 * @priv: Pointer to private wext data from wpa_driver_wext_init() 72 * @bssid: Buffer for BSSID 73 * Returns: 0 on success, -1 on failure 74 */ 75int wpa_driver_wext_get_bssid(void *priv, u8 *bssid) 76{ 77 struct wpa_driver_wext_data *drv = priv; 78 struct iwreq iwr; 79 int ret = 0; 80 81 os_memset(&iwr, 0, sizeof(iwr)); 82 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 83 84 if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) { 85 perror("ioctl[SIOCGIWAP]"); 86 ret = -1; 87 } 88 os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN); 89 90 return ret; 91} 92 93 94/** 95 * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP 96 * @priv: Pointer to private wext data from wpa_driver_wext_init() 97 * @bssid: BSSID 98 * Returns: 0 on success, -1 on failure 99 */ 100int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid) 101{ 102 struct wpa_driver_wext_data *drv = priv; 103 struct iwreq iwr; 104 int ret = 0; 105 106 os_memset(&iwr, 0, sizeof(iwr)); 107 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 108 iwr.u.ap_addr.sa_family = ARPHRD_ETHER; 109 if (bssid) 110 os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN); 111 else 112 os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN); 113 114 if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) { 115 perror("ioctl[SIOCSIWAP]"); 116 ret = -1; 117 } 118 119 return ret; 120} 121 122 123/** 124 * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID 125 * @priv: Pointer to private wext data from wpa_driver_wext_init() 126 * @ssid: Buffer for the SSID; must be at least 32 bytes long 127 * Returns: SSID length on success, -1 on failure 128 */ 129int wpa_driver_wext_get_ssid(void *priv, u8 *ssid) 130{ 131 struct wpa_driver_wext_data *drv = priv; 132 struct iwreq iwr; 133 int ret = 0; 134 135 os_memset(&iwr, 0, sizeof(iwr)); 136 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 137 iwr.u.essid.pointer = (caddr_t) ssid; 138 iwr.u.essid.length = 32; 139 140 if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { 141 perror("ioctl[SIOCGIWESSID]"); 142 ret = -1; 143 } else { 144 ret = iwr.u.essid.length; 145 if (ret > 32) 146 ret = 32; 147 /* Some drivers include nul termination in the SSID, so let's 148 * remove it here before further processing. WE-21 changes this 149 * to explicitly require the length _not_ to include nul 150 * termination. */ 151 if (ret > 0 && ssid[ret - 1] == '\0' && 152 drv->we_version_compiled < 21) 153 ret--; 154 } 155 156 return ret; 157} 158 159 160/** 161 * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID 162 * @priv: Pointer to private wext data from wpa_driver_wext_init() 163 * @ssid: SSID 164 * @ssid_len: Length of SSID (0..32) 165 * Returns: 0 on success, -1 on failure 166 */ 167int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len) 168{ 169 struct wpa_driver_wext_data *drv = priv; 170 struct iwreq iwr; 171 int ret = 0; 172 char buf[33]; 173 174 if (ssid_len > 32) 175 return -1; 176 177 os_memset(&iwr, 0, sizeof(iwr)); 178 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 179 /* flags: 1 = ESSID is active, 0 = not (promiscuous) */ 180 iwr.u.essid.flags = (ssid_len != 0); 181 os_memset(buf, 0, sizeof(buf)); 182 os_memcpy(buf, ssid, ssid_len); 183 iwr.u.essid.pointer = (caddr_t) buf; 184 if (drv->we_version_compiled < 21) { 185 /* For historic reasons, set SSID length to include one extra 186 * character, C string nul termination, even though SSID is 187 * really an octet string that should not be presented as a C 188 * string. Some Linux drivers decrement the length by one and 189 * can thus end up missing the last octet of the SSID if the 190 * length is not incremented here. WE-21 changes this to 191 * explicitly require the length _not_ to include nul 192 * termination. */ 193 if (ssid_len) 194 ssid_len++; 195 } 196 iwr.u.essid.length = ssid_len; 197 198 if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { 199 perror("ioctl[SIOCSIWESSID]"); 200 ret = -1; 201 } 202 203 return ret; 204} 205 206 207/** 208 * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ 209 * @priv: Pointer to private wext data from wpa_driver_wext_init() 210 * @freq: Frequency in MHz 211 * Returns: 0 on success, -1 on failure 212 */ 213int wpa_driver_wext_set_freq(void *priv, int freq) 214{ 215 struct wpa_driver_wext_data *drv = priv; 216 struct iwreq iwr; 217 int ret = 0; 218 219 os_memset(&iwr, 0, sizeof(iwr)); 220 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 221 iwr.u.freq.m = freq * 100000; 222 iwr.u.freq.e = 1; 223 224 if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) { 225 perror("ioctl[SIOCSIWFREQ]"); 226 ret = -1; 227 } 228 229 return ret; 230} 231 232 233static void 234wpa_driver_wext_event_wireless_custom(void *ctx, char *custom) 235{ 236 union wpa_event_data data; 237 238 wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'", 239 custom); 240 241 os_memset(&data, 0, sizeof(data)); 242 /* Host AP driver */ 243 if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { 244 data.michael_mic_failure.unicast = 245 os_strstr(custom, " unicast ") != NULL; 246 /* TODO: parse parameters(?) */ 247 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); 248 } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) { 249 char *spos; 250 int bytes; 251 u8 *req_ies = NULL, *resp_ies = NULL; 252 253 spos = custom + 17; 254 255 bytes = strspn(spos, "0123456789abcdefABCDEF"); 256 if (!bytes || (bytes & 1)) 257 return; 258 bytes /= 2; 259 260 req_ies = os_malloc(bytes); 261 if (req_ies == NULL || 262 hexstr2bin(spos, req_ies, bytes) < 0) 263 goto done; 264 data.assoc_info.req_ies = req_ies; 265 data.assoc_info.req_ies_len = bytes; 266 267 spos += bytes * 2; 268 269 data.assoc_info.resp_ies = NULL; 270 data.assoc_info.resp_ies_len = 0; 271 272 if (os_strncmp(spos, " RespIEs=", 9) == 0) { 273 spos += 9; 274 275 bytes = strspn(spos, "0123456789abcdefABCDEF"); 276 if (!bytes || (bytes & 1)) 277 goto done; 278 bytes /= 2; 279 280 resp_ies = os_malloc(bytes); 281 if (resp_ies == NULL || 282 hexstr2bin(spos, resp_ies, bytes) < 0) 283 goto done; 284 data.assoc_info.resp_ies = resp_ies; 285 data.assoc_info.resp_ies_len = bytes; 286 } 287 288 wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); 289 290 done: 291 os_free(resp_ies); 292 os_free(req_ies); 293#ifdef CONFIG_PEERKEY 294 } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) { 295 if (hwaddr_aton(custom + 17, data.stkstart.peer)) { 296 wpa_printf(MSG_DEBUG, "WEXT: unrecognized " 297 "STKSTART.request '%s'", custom + 17); 298 return; 299 } 300 wpa_supplicant_event(ctx, EVENT_STKSTART, &data); 301#endif /* CONFIG_PEERKEY */ 302#ifdef ANDROID 303 } else if (os_strncmp(custom, "STOP", 4) == 0) { 304 wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); 305 } else if (os_strncmp(custom, "START", 5) == 0) { 306 wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); 307 } else if (os_strncmp(custom, "HANG", 4) == 0) { 308 wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); 309#endif /* ANDROID */ 310 } 311} 312 313 314static int wpa_driver_wext_event_wireless_michaelmicfailure( 315 void *ctx, const char *ev, size_t len) 316{ 317 const struct iw_michaelmicfailure *mic; 318 union wpa_event_data data; 319 320 if (len < sizeof(*mic)) 321 return -1; 322 323 mic = (const struct iw_michaelmicfailure *) ev; 324 325 wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: " 326 "flags=0x%x src_addr=" MACSTR, mic->flags, 327 MAC2STR(mic->src_addr.sa_data)); 328 329 os_memset(&data, 0, sizeof(data)); 330 data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP); 331 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); 332 333 return 0; 334} 335 336 337static int wpa_driver_wext_event_wireless_pmkidcand( 338 struct wpa_driver_wext_data *drv, const char *ev, size_t len) 339{ 340 const struct iw_pmkid_cand *cand; 341 union wpa_event_data data; 342 const u8 *addr; 343 344 if (len < sizeof(*cand)) 345 return -1; 346 347 cand = (const struct iw_pmkid_cand *) ev; 348 addr = (const u8 *) cand->bssid.sa_data; 349 350 wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: " 351 "flags=0x%x index=%d bssid=" MACSTR, cand->flags, 352 cand->index, MAC2STR(addr)); 353 354 os_memset(&data, 0, sizeof(data)); 355 os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN); 356 data.pmkid_candidate.index = cand->index; 357 data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH; 358 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data); 359 360 return 0; 361} 362 363 364static int wpa_driver_wext_event_wireless_assocreqie( 365 struct wpa_driver_wext_data *drv, const char *ev, int len) 366{ 367 if (len < 0) 368 return -1; 369 370 wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev, 371 len); 372 os_free(drv->assoc_req_ies); 373 drv->assoc_req_ies = os_malloc(len); 374 if (drv->assoc_req_ies == NULL) { 375 drv->assoc_req_ies_len = 0; 376 return -1; 377 } 378 os_memcpy(drv->assoc_req_ies, ev, len); 379 drv->assoc_req_ies_len = len; 380 381 return 0; 382} 383 384 385static int wpa_driver_wext_event_wireless_assocrespie( 386 struct wpa_driver_wext_data *drv, const char *ev, int len) 387{ 388 if (len < 0) 389 return -1; 390 391 wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev, 392 len); 393 os_free(drv->assoc_resp_ies); 394 drv->assoc_resp_ies = os_malloc(len); 395 if (drv->assoc_resp_ies == NULL) { 396 drv->assoc_resp_ies_len = 0; 397 return -1; 398 } 399 os_memcpy(drv->assoc_resp_ies, ev, len); 400 drv->assoc_resp_ies_len = len; 401 402 return 0; 403} 404 405 406static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv) 407{ 408 union wpa_event_data data; 409 410 if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL) 411 return; 412 413 os_memset(&data, 0, sizeof(data)); 414 if (drv->assoc_req_ies) { 415 data.assoc_info.req_ies = drv->assoc_req_ies; 416 data.assoc_info.req_ies_len = drv->assoc_req_ies_len; 417 } 418 if (drv->assoc_resp_ies) { 419 data.assoc_info.resp_ies = drv->assoc_resp_ies; 420 data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len; 421 } 422 423 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); 424 425 os_free(drv->assoc_req_ies); 426 drv->assoc_req_ies = NULL; 427 os_free(drv->assoc_resp_ies); 428 drv->assoc_resp_ies = NULL; 429} 430 431 432static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv, 433 char *data, int len) 434{ 435 struct iw_event iwe_buf, *iwe = &iwe_buf; 436 char *pos, *end, *custom, *buf; 437 438 pos = data; 439 end = data + len; 440 441 while (pos + IW_EV_LCP_LEN <= end) { 442 /* Event data may be unaligned, so make a local, aligned copy 443 * before processing. */ 444 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); 445 wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", 446 iwe->cmd, iwe->len); 447 if (iwe->len <= IW_EV_LCP_LEN) 448 return; 449 450 custom = pos + IW_EV_POINT_LEN; 451 if (drv->we_version_compiled > 18 && 452 (iwe->cmd == IWEVMICHAELMICFAILURE || 453 iwe->cmd == IWEVCUSTOM || 454 iwe->cmd == IWEVASSOCREQIE || 455 iwe->cmd == IWEVASSOCRESPIE || 456 iwe->cmd == IWEVPMKIDCAND)) { 457 /* WE-19 removed the pointer from struct iw_point */ 458 char *dpos = (char *) &iwe_buf.u.data.length; 459 int dlen = dpos - (char *) &iwe_buf; 460 os_memcpy(dpos, pos + IW_EV_LCP_LEN, 461 sizeof(struct iw_event) - dlen); 462 } else { 463 os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); 464 custom += IW_EV_POINT_OFF; 465 } 466 467 switch (iwe->cmd) { 468 case SIOCGIWAP: 469 wpa_printf(MSG_DEBUG, "Wireless event: new AP: " 470 MACSTR, 471 MAC2STR((u8 *) iwe->u.ap_addr.sa_data)); 472 if (is_zero_ether_addr( 473 (const u8 *) iwe->u.ap_addr.sa_data) || 474 os_memcmp(iwe->u.ap_addr.sa_data, 475 "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 476 0) { 477 os_free(drv->assoc_req_ies); 478 drv->assoc_req_ies = NULL; 479 os_free(drv->assoc_resp_ies); 480 drv->assoc_resp_ies = NULL; 481 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, 482 NULL); 483 484 } else { 485 wpa_driver_wext_event_assoc_ies(drv); 486 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, 487 NULL); 488 } 489 break; 490 case IWEVMICHAELMICFAILURE: 491 if (custom + iwe->u.data.length > end) { 492 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 493 "IWEVMICHAELMICFAILURE length"); 494 return; 495 } 496 wpa_driver_wext_event_wireless_michaelmicfailure( 497 drv->ctx, custom, iwe->u.data.length); 498 break; 499 case IWEVCUSTOM: 500 if (custom + iwe->u.data.length > end) { 501 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 502 "IWEVCUSTOM length"); 503 return; 504 } 505 buf = dup_binstr(custom, iwe->u.data.length); 506 if (buf == NULL) 507 return; 508 wpa_driver_wext_event_wireless_custom(drv->ctx, buf); 509 os_free(buf); 510 break; 511 case SIOCGIWSCAN: 512 drv->scan_complete_events = 1; 513 eloop_cancel_timeout(wpa_driver_wext_scan_timeout, 514 drv, drv->ctx); 515 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, 516 NULL); 517 break; 518 case IWEVASSOCREQIE: 519 if (custom + iwe->u.data.length > end) { 520 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 521 "IWEVASSOCREQIE length"); 522 return; 523 } 524 wpa_driver_wext_event_wireless_assocreqie( 525 drv, custom, iwe->u.data.length); 526 break; 527 case IWEVASSOCRESPIE: 528 if (custom + iwe->u.data.length > end) { 529 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 530 "IWEVASSOCRESPIE length"); 531 return; 532 } 533 wpa_driver_wext_event_wireless_assocrespie( 534 drv, custom, iwe->u.data.length); 535 break; 536 case IWEVPMKIDCAND: 537 if (custom + iwe->u.data.length > end) { 538 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 539 "IWEVPMKIDCAND length"); 540 return; 541 } 542 wpa_driver_wext_event_wireless_pmkidcand( 543 drv, custom, iwe->u.data.length); 544 break; 545 } 546 547 pos += iwe->len; 548 } 549} 550 551 552static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv, 553 char *buf, size_t len, int del) 554{ 555 union wpa_event_data event; 556 557 os_memset(&event, 0, sizeof(event)); 558 if (len > sizeof(event.interface_status.ifname)) 559 len = sizeof(event.interface_status.ifname) - 1; 560 os_memcpy(event.interface_status.ifname, buf, len); 561 event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED : 562 EVENT_INTERFACE_ADDED; 563 564 wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s", 565 del ? "DEL" : "NEW", 566 event.interface_status.ifname, 567 del ? "removed" : "added"); 568 569 if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { 570 if (del) { 571 if (drv->if_removed) { 572 wpa_printf(MSG_DEBUG, "WEXT: if_removed " 573 "already set - ignore event"); 574 return; 575 } 576 drv->if_removed = 1; 577 } else { 578 if (if_nametoindex(drv->ifname) == 0) { 579 wpa_printf(MSG_DEBUG, "WEXT: Interface %s " 580 "does not exist - ignore " 581 "RTM_NEWLINK", 582 drv->ifname); 583 return; 584 } 585 if (!drv->if_removed) { 586 wpa_printf(MSG_DEBUG, "WEXT: if_removed " 587 "already cleared - ignore event"); 588 return; 589 } 590 drv->if_removed = 0; 591 } 592 } 593 594 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 595} 596 597 598static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv, 599 u8 *buf, size_t len) 600{ 601 int attrlen, rta_len; 602 struct rtattr *attr; 603 604 attrlen = len; 605 attr = (struct rtattr *) buf; 606 607 rta_len = RTA_ALIGN(sizeof(struct rtattr)); 608 while (RTA_OK(attr, attrlen)) { 609 if (attr->rta_type == IFLA_IFNAME) { 610 if (os_strcmp(((char *) attr) + rta_len, drv->ifname) 611 == 0) 612 return 1; 613 else 614 break; 615 } 616 attr = RTA_NEXT(attr, attrlen); 617 } 618 619 return 0; 620} 621 622 623static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv, 624 int ifindex, u8 *buf, size_t len) 625{ 626 if (drv->ifindex == ifindex || drv->ifindex2 == ifindex) 627 return 1; 628 629 if (drv->if_removed && wpa_driver_wext_own_ifname(drv, buf, len)) { 630 drv->ifindex = if_nametoindex(drv->ifname); 631 wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed " 632 "interface"); 633 wpa_driver_wext_finish_drv_init(drv); 634 return 1; 635 } 636 637 return 0; 638} 639 640 641static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, 642 u8 *buf, size_t len) 643{ 644 struct wpa_driver_wext_data *drv = ctx; 645 int attrlen, rta_len; 646 struct rtattr *attr; 647 char namebuf[IFNAMSIZ]; 648 649 if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) { 650 wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", 651 ifi->ifi_index); 652 return; 653 } 654 655 wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x " 656 "(%s%s%s%s)", 657 drv->operstate, ifi->ifi_flags, 658 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", 659 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", 660 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", 661 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); 662 663 if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) { 664 wpa_printf(MSG_DEBUG, "WEXT: Interface down"); 665 drv->if_disabled = 1; 666 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL); 667 } 668 669 if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) { 670 if (if_indextoname(ifi->ifi_index, namebuf) && 671 linux_iface_up(drv->ioctl_sock, drv->ifname) == 0) { 672 wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up " 673 "event since interface %s is down", 674 namebuf); 675 } else if (if_nametoindex(drv->ifname) == 0) { 676 wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up " 677 "event since interface %s does not exist", 678 drv->ifname); 679 } else if (drv->if_removed) { 680 wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up " 681 "event since interface %s is marked " 682 "removed", drv->ifname); 683 } else { 684 wpa_printf(MSG_DEBUG, "WEXT: Interface up"); 685 drv->if_disabled = 0; 686 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, 687 NULL); 688 } 689 } 690 691 /* 692 * Some drivers send the association event before the operup event--in 693 * this case, lifting operstate in wpa_driver_wext_set_operstate() 694 * fails. This will hit us when wpa_supplicant does not need to do 695 * IEEE 802.1X authentication 696 */ 697 if (drv->operstate == 1 && 698 (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && 699 !(ifi->ifi_flags & IFF_RUNNING)) 700 netlink_send_oper_ifla(drv->netlink, drv->ifindex, 701 -1, IF_OPER_UP); 702 703 attrlen = len; 704 attr = (struct rtattr *) buf; 705 706 rta_len = RTA_ALIGN(sizeof(struct rtattr)); 707 while (RTA_OK(attr, attrlen)) { 708 if (attr->rta_type == IFLA_WIRELESS) { 709 wpa_driver_wext_event_wireless( 710 drv, ((char *) attr) + rta_len, 711 attr->rta_len - rta_len); 712 } else if (attr->rta_type == IFLA_IFNAME) { 713 wpa_driver_wext_event_link(drv, 714 ((char *) attr) + rta_len, 715 attr->rta_len - rta_len, 0); 716 } 717 attr = RTA_NEXT(attr, attrlen); 718 } 719} 720 721 722static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi, 723 u8 *buf, size_t len) 724{ 725 struct wpa_driver_wext_data *drv = ctx; 726 int attrlen, rta_len; 727 struct rtattr *attr; 728 729 attrlen = len; 730 attr = (struct rtattr *) buf; 731 732 rta_len = RTA_ALIGN(sizeof(struct rtattr)); 733 while (RTA_OK(attr, attrlen)) { 734 if (attr->rta_type == IFLA_IFNAME) { 735 wpa_driver_wext_event_link(drv, 736 ((char *) attr) + rta_len, 737 attr->rta_len - rta_len, 1); 738 } 739 attr = RTA_NEXT(attr, attrlen); 740 } 741} 742 743 744static void wpa_driver_wext_rfkill_blocked(void *ctx) 745{ 746 wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked"); 747 /* 748 * This may be for any interface; use ifdown event to disable 749 * interface. 750 */ 751} 752 753 754static void wpa_driver_wext_rfkill_unblocked(void *ctx) 755{ 756 struct wpa_driver_wext_data *drv = ctx; 757 wpa_printf(MSG_DEBUG, "WEXT: RFKILL unblocked"); 758 if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) { 759 wpa_printf(MSG_DEBUG, "WEXT: Could not set interface UP " 760 "after rfkill unblock"); 761 return; 762 } 763 /* rtnetlink ifup handler will report interface as enabled */ 764} 765 766 767static void wext_get_phy_name(struct wpa_driver_wext_data *drv) 768{ 769 /* Find phy (radio) to which this interface belongs */ 770 char buf[90], *pos; 771 int f, rv; 772 773 drv->phyname[0] = '\0'; 774 snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name", 775 drv->ifname); 776 f = open(buf, O_RDONLY); 777 if (f < 0) { 778 wpa_printf(MSG_DEBUG, "Could not open file %s: %s", 779 buf, strerror(errno)); 780 return; 781 } 782 783 rv = read(f, drv->phyname, sizeof(drv->phyname) - 1); 784 close(f); 785 if (rv < 0) { 786 wpa_printf(MSG_DEBUG, "Could not read file %s: %s", 787 buf, strerror(errno)); 788 return; 789 } 790 791 drv->phyname[rv] = '\0'; 792 pos = os_strchr(drv->phyname, '\n'); 793 if (pos) 794 *pos = '\0'; 795 wpa_printf(MSG_DEBUG, "wext: interface %s phy: %s", 796 drv->ifname, drv->phyname); 797} 798 799 800/** 801 * wpa_driver_wext_init - Initialize WE driver interface 802 * @ctx: context to be used when calling wpa_supplicant functions, 803 * e.g., wpa_supplicant_event() 804 * @ifname: interface name, e.g., wlan0 805 * Returns: Pointer to private data, %NULL on failure 806 */ 807void * wpa_driver_wext_init(void *ctx, const char *ifname) 808{ 809 struct wpa_driver_wext_data *drv; 810 struct netlink_config *cfg; 811 struct rfkill_config *rcfg; 812 char path[128]; 813 struct stat buf; 814 815 drv = os_zalloc(sizeof(*drv)); 816 if (drv == NULL) 817 return NULL; 818 drv->ctx = ctx; 819 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 820 821 os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname); 822 if (stat(path, &buf) == 0) { 823 wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected"); 824 drv->cfg80211 = 1; 825 wext_get_phy_name(drv); 826 } 827 828 drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); 829 if (drv->ioctl_sock < 0) { 830 perror("socket(PF_INET,SOCK_DGRAM)"); 831 goto err1; 832 } 833 834 cfg = os_zalloc(sizeof(*cfg)); 835 if (cfg == NULL) 836 goto err1; 837 cfg->ctx = drv; 838 cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink; 839 cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink; 840 drv->netlink = netlink_init(cfg); 841 if (drv->netlink == NULL) { 842 os_free(cfg); 843 goto err2; 844 } 845 846 rcfg = os_zalloc(sizeof(*rcfg)); 847 if (rcfg == NULL) 848 goto err3; 849 rcfg->ctx = drv; 850 os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname)); 851 rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked; 852 rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked; 853 drv->rfkill = rfkill_init(rcfg); 854 if (drv->rfkill == NULL) { 855 wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available"); 856 os_free(rcfg); 857 } 858 859 drv->mlme_sock = -1; 860 861#ifdef ANDROID 862 drv->errors = 0; 863 drv->driver_is_started = TRUE; 864 drv->bgscan_enabled = 0; 865#endif /* ANDROID */ 866 867 if (wpa_driver_wext_finish_drv_init(drv) < 0) 868 goto err3; 869 870 wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1); 871 872 return drv; 873 874err3: 875 rfkill_deinit(drv->rfkill); 876 netlink_deinit(drv->netlink); 877err2: 878 close(drv->ioctl_sock); 879err1: 880 os_free(drv); 881 return NULL; 882} 883 884 885static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx) 886{ 887 wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL); 888} 889 890 891static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) 892{ 893 int send_rfkill_event = 0; 894 895 if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) { 896 if (rfkill_is_blocked(drv->rfkill)) { 897 wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable " 898 "interface '%s' due to rfkill", 899 drv->ifname); 900 drv->if_disabled = 1; 901 send_rfkill_event = 1; 902 } else { 903 wpa_printf(MSG_ERROR, "WEXT: Could not set " 904 "interface '%s' UP", drv->ifname); 905 return -1; 906 } 907 } 908 909 /* 910 * Make sure that the driver does not have any obsolete PMKID entries. 911 */ 912 wpa_driver_wext_flush_pmkid(drv); 913 914 if (wpa_driver_wext_set_mode(drv, 0) < 0) { 915 wpa_printf(MSG_DEBUG, "Could not configure driver to use " 916 "managed mode"); 917 /* Try to use it anyway */ 918 } 919 920 wpa_driver_wext_get_range(drv); 921 922 /* 923 * Unlock the driver's BSSID and force to a random SSID to clear any 924 * previous association the driver might have when the supplicant 925 * starts up. 926 */ 927 wpa_driver_wext_disconnect(drv); 928 929 drv->ifindex = if_nametoindex(drv->ifname); 930 931 if (os_strncmp(drv->ifname, "wlan", 4) == 0) { 932 /* 933 * Host AP driver may use both wlan# and wifi# interface in 934 * wireless events. Since some of the versions included WE-18 935 * support, let's add the alternative ifindex also from 936 * driver_wext.c for the time being. This may be removed at 937 * some point once it is believed that old versions of the 938 * driver are not in use anymore. 939 */ 940 char ifname2[IFNAMSIZ + 1]; 941 os_strlcpy(ifname2, drv->ifname, sizeof(ifname2)); 942 os_memcpy(ifname2, "wifi", 4); 943 wpa_driver_wext_alternative_ifindex(drv, ifname2); 944 } 945 946 netlink_send_oper_ifla(drv->netlink, drv->ifindex, 947 1, IF_OPER_DORMANT); 948 949 if (send_rfkill_event) { 950 eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill, 951 drv, drv->ctx); 952 } 953 954 return 0; 955} 956 957 958/** 959 * wpa_driver_wext_deinit - Deinitialize WE driver interface 960 * @priv: Pointer to private wext data from wpa_driver_wext_init() 961 * 962 * Shut down driver interface and processing of driver events. Free 963 * private data buffer if one was allocated in wpa_driver_wext_init(). 964 */ 965void wpa_driver_wext_deinit(void *priv) 966{ 967 struct wpa_driver_wext_data *drv = priv; 968 969 wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 0); 970 971 eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); 972 973 /* 974 * Clear possibly configured driver parameters in order to make it 975 * easier to use the driver after wpa_supplicant has been terminated. 976 */ 977 wpa_driver_wext_disconnect(drv); 978 979 netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP); 980 netlink_deinit(drv->netlink); 981 rfkill_deinit(drv->rfkill); 982 983 if (drv->mlme_sock >= 0) 984 eloop_unregister_read_sock(drv->mlme_sock); 985 986 (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); 987 988 close(drv->ioctl_sock); 989 if (drv->mlme_sock >= 0) 990 close(drv->mlme_sock); 991 os_free(drv->assoc_req_ies); 992 os_free(drv->assoc_resp_ies); 993 os_free(drv); 994} 995 996 997/** 998 * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion 999 * @eloop_ctx: Unused 1000 * @timeout_ctx: ctx argument given to wpa_driver_wext_init() 1001 * 1002 * This function can be used as registered timeout when starting a scan to 1003 * generate a scan completed event if the driver does not report this. 1004 */ 1005void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx) 1006{ 1007 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); 1008 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 1009} 1010 1011 1012/** 1013 * wpa_driver_wext_scan - Request the driver to initiate scan 1014 * @priv: Pointer to private wext data from wpa_driver_wext_init() 1015 * @param: Scan parameters (specific SSID to scan for (ProbeReq), etc.) 1016 * Returns: 0 on success, -1 on failure 1017 */ 1018int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params) 1019{ 1020 struct wpa_driver_wext_data *drv = priv; 1021 struct iwreq iwr; 1022 int ret = 0, timeout; 1023 struct iw_scan_req req; 1024 const u8 *ssid = params->ssids[0].ssid; 1025 size_t ssid_len = params->ssids[0].ssid_len; 1026 1027 if (ssid_len > IW_ESSID_MAX_SIZE) { 1028 wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", 1029 __FUNCTION__, (unsigned long) ssid_len); 1030 return -1; 1031 } 1032 1033 os_memset(&iwr, 0, sizeof(iwr)); 1034 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1035 1036 if (ssid && ssid_len) { 1037 os_memset(&req, 0, sizeof(req)); 1038 req.essid_len = ssid_len; 1039 req.bssid.sa_family = ARPHRD_ETHER; 1040 os_memset(req.bssid.sa_data, 0xff, ETH_ALEN); 1041 os_memcpy(req.essid, ssid, ssid_len); 1042 iwr.u.data.pointer = (caddr_t) &req; 1043 iwr.u.data.length = sizeof(req); 1044 iwr.u.data.flags = IW_SCAN_THIS_ESSID; 1045 } 1046 1047 if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) { 1048 perror("ioctl[SIOCSIWSCAN]"); 1049 ret = -1; 1050 } 1051 1052 /* Not all drivers generate "scan completed" wireless event, so try to 1053 * read results after a timeout. */ 1054 timeout = 10; 1055 if (drv->scan_complete_events) { 1056 /* 1057 * The driver seems to deliver SIOCGIWSCAN events to notify 1058 * when scan is complete, so use longer timeout to avoid race 1059 * conditions with scanning and following association request. 1060 */ 1061 timeout = 30; 1062 } 1063 wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " 1064 "seconds", ret, timeout); 1065 eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); 1066 eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv, 1067 drv->ctx); 1068 1069 return ret; 1070} 1071 1072 1073static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv, 1074 size_t *len) 1075{ 1076 struct iwreq iwr; 1077 u8 *res_buf; 1078 size_t res_buf_len; 1079 1080 res_buf_len = IW_SCAN_MAX_DATA; 1081 for (;;) { 1082 res_buf = os_malloc(res_buf_len); 1083 if (res_buf == NULL) 1084 return NULL; 1085 os_memset(&iwr, 0, sizeof(iwr)); 1086 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1087 iwr.u.data.pointer = res_buf; 1088 iwr.u.data.length = res_buf_len; 1089 1090 if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0) 1091 break; 1092 1093 if (errno == E2BIG && res_buf_len < 65535) { 1094 os_free(res_buf); 1095 res_buf = NULL; 1096 res_buf_len *= 2; 1097 if (res_buf_len > 65535) 1098 res_buf_len = 65535; /* 16-bit length field */ 1099 wpa_printf(MSG_DEBUG, "Scan results did not fit - " 1100 "trying larger buffer (%lu bytes)", 1101 (unsigned long) res_buf_len); 1102 } else { 1103 perror("ioctl[SIOCGIWSCAN]"); 1104 os_free(res_buf); 1105 return NULL; 1106 } 1107 } 1108 1109 if (iwr.u.data.length > res_buf_len) { 1110 os_free(res_buf); 1111 return NULL; 1112 } 1113 *len = iwr.u.data.length; 1114 1115 return res_buf; 1116} 1117 1118 1119/* 1120 * Data structure for collecting WEXT scan results. This is needed to allow 1121 * the various methods of reporting IEs to be combined into a single IE buffer. 1122 */ 1123struct wext_scan_data { 1124 struct wpa_scan_res res; 1125 u8 *ie; 1126 size_t ie_len; 1127 u8 ssid[32]; 1128 size_t ssid_len; 1129 int maxrate; 1130}; 1131 1132 1133static void wext_get_scan_mode(struct iw_event *iwe, 1134 struct wext_scan_data *res) 1135{ 1136 if (iwe->u.mode == IW_MODE_ADHOC) 1137 res->res.caps |= IEEE80211_CAP_IBSS; 1138 else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA) 1139 res->res.caps |= IEEE80211_CAP_ESS; 1140} 1141 1142 1143static void wext_get_scan_ssid(struct iw_event *iwe, 1144 struct wext_scan_data *res, char *custom, 1145 char *end) 1146{ 1147 int ssid_len = iwe->u.essid.length; 1148 if (custom + ssid_len > end) 1149 return; 1150 if (iwe->u.essid.flags && 1151 ssid_len > 0 && 1152 ssid_len <= IW_ESSID_MAX_SIZE) { 1153 os_memcpy(res->ssid, custom, ssid_len); 1154 res->ssid_len = ssid_len; 1155 } 1156} 1157 1158 1159static void wext_get_scan_freq(struct iw_event *iwe, 1160 struct wext_scan_data *res) 1161{ 1162 int divi = 1000000, i; 1163 1164 if (iwe->u.freq.e == 0) { 1165 /* 1166 * Some drivers do not report frequency, but a channel. 1167 * Try to map this to frequency by assuming they are using 1168 * IEEE 802.11b/g. But don't overwrite a previously parsed 1169 * frequency if the driver sends both frequency and channel, 1170 * since the driver may be sending an A-band channel that we 1171 * don't handle here. 1172 */ 1173 1174 if (res->res.freq) 1175 return; 1176 1177 if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) { 1178 res->res.freq = 2407 + 5 * iwe->u.freq.m; 1179 return; 1180 } else if (iwe->u.freq.m == 14) { 1181 res->res.freq = 2484; 1182 return; 1183 } 1184 } 1185 1186 if (iwe->u.freq.e > 6) { 1187 wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID=" 1188 MACSTR " m=%d e=%d)", 1189 MAC2STR(res->res.bssid), iwe->u.freq.m, 1190 iwe->u.freq.e); 1191 return; 1192 } 1193 1194 for (i = 0; i < iwe->u.freq.e; i++) 1195 divi /= 10; 1196 res->res.freq = iwe->u.freq.m / divi; 1197} 1198 1199 1200static void wext_get_scan_qual(struct wpa_driver_wext_data *drv, 1201 struct iw_event *iwe, 1202 struct wext_scan_data *res) 1203{ 1204 res->res.qual = iwe->u.qual.qual; 1205 res->res.noise = iwe->u.qual.noise; 1206 res->res.level = iwe->u.qual.level; 1207 if (iwe->u.qual.updated & IW_QUAL_QUAL_INVALID) 1208 res->res.flags |= WPA_SCAN_QUAL_INVALID; 1209 if (iwe->u.qual.updated & IW_QUAL_LEVEL_INVALID) 1210 res->res.flags |= WPA_SCAN_LEVEL_INVALID; 1211 if (iwe->u.qual.updated & IW_QUAL_NOISE_INVALID) 1212 res->res.flags |= WPA_SCAN_NOISE_INVALID; 1213 if (iwe->u.qual.updated & IW_QUAL_DBM) 1214 res->res.flags |= WPA_SCAN_LEVEL_DBM; 1215 if ((iwe->u.qual.updated & IW_QUAL_DBM) || 1216 ((iwe->u.qual.level != 0) && 1217 (iwe->u.qual.level > drv->max_level))) { 1218 if (iwe->u.qual.level >= 64) 1219 res->res.level -= 0x100; 1220 if (iwe->u.qual.noise >= 64) 1221 res->res.noise -= 0x100; 1222 } 1223} 1224 1225 1226static void wext_get_scan_encode(struct iw_event *iwe, 1227 struct wext_scan_data *res) 1228{ 1229 if (!(iwe->u.data.flags & IW_ENCODE_DISABLED)) 1230 res->res.caps |= IEEE80211_CAP_PRIVACY; 1231} 1232 1233 1234static void wext_get_scan_rate(struct iw_event *iwe, 1235 struct wext_scan_data *res, char *pos, 1236 char *end) 1237{ 1238 int maxrate; 1239 char *custom = pos + IW_EV_LCP_LEN; 1240 struct iw_param p; 1241 size_t clen; 1242 1243 clen = iwe->len; 1244 if (custom + clen > end) 1245 return; 1246 maxrate = 0; 1247 while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) { 1248 /* Note: may be misaligned, make a local, aligned copy */ 1249 os_memcpy(&p, custom, sizeof(struct iw_param)); 1250 if (p.value > maxrate) 1251 maxrate = p.value; 1252 clen -= sizeof(struct iw_param); 1253 custom += sizeof(struct iw_param); 1254 } 1255 1256 /* Convert the maxrate from WE-style (b/s units) to 1257 * 802.11 rates (500000 b/s units). 1258 */ 1259 res->maxrate = maxrate / 500000; 1260} 1261 1262 1263static void wext_get_scan_iwevgenie(struct iw_event *iwe, 1264 struct wext_scan_data *res, char *custom, 1265 char *end) 1266{ 1267 char *genie, *gpos, *gend; 1268 u8 *tmp; 1269 1270 if (iwe->u.data.length == 0) 1271 return; 1272 1273 gpos = genie = custom; 1274 gend = genie + iwe->u.data.length; 1275 if (gend > end) { 1276 wpa_printf(MSG_INFO, "IWEVGENIE overflow"); 1277 return; 1278 } 1279 1280 tmp = os_realloc(res->ie, res->ie_len + gend - gpos); 1281 if (tmp == NULL) 1282 return; 1283 os_memcpy(tmp + res->ie_len, gpos, gend - gpos); 1284 res->ie = tmp; 1285 res->ie_len += gend - gpos; 1286} 1287 1288 1289static void wext_get_scan_custom(struct iw_event *iwe, 1290 struct wext_scan_data *res, char *custom, 1291 char *end) 1292{ 1293 size_t clen; 1294 u8 *tmp; 1295 1296 clen = iwe->u.data.length; 1297 if (custom + clen > end) 1298 return; 1299 1300 if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) { 1301 char *spos; 1302 int bytes; 1303 spos = custom + 7; 1304 bytes = custom + clen - spos; 1305 if (bytes & 1 || bytes == 0) 1306 return; 1307 bytes /= 2; 1308 tmp = os_realloc(res->ie, res->ie_len + bytes); 1309 if (tmp == NULL) 1310 return; 1311 res->ie = tmp; 1312 if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0) 1313 return; 1314 res->ie_len += bytes; 1315 } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) { 1316 char *spos; 1317 int bytes; 1318 spos = custom + 7; 1319 bytes = custom + clen - spos; 1320 if (bytes & 1 || bytes == 0) 1321 return; 1322 bytes /= 2; 1323 tmp = os_realloc(res->ie, res->ie_len + bytes); 1324 if (tmp == NULL) 1325 return; 1326 res->ie = tmp; 1327 if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0) 1328 return; 1329 res->ie_len += bytes; 1330 } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) { 1331 char *spos; 1332 int bytes; 1333 u8 bin[8]; 1334 spos = custom + 4; 1335 bytes = custom + clen - spos; 1336 if (bytes != 16) { 1337 wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes); 1338 return; 1339 } 1340 bytes /= 2; 1341 if (hexstr2bin(spos, bin, bytes) < 0) { 1342 wpa_printf(MSG_DEBUG, "WEXT: Invalid TSF value"); 1343 return; 1344 } 1345 res->res.tsf += WPA_GET_BE64(bin); 1346 } 1347} 1348 1349 1350static int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd) 1351{ 1352 return drv->we_version_compiled > 18 && 1353 (cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE || 1354 cmd == IWEVGENIE || cmd == IWEVCUSTOM); 1355} 1356 1357 1358static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res, 1359 struct wext_scan_data *data) 1360{ 1361 struct wpa_scan_res **tmp; 1362 struct wpa_scan_res *r; 1363 size_t extra_len; 1364 u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL; 1365 1366 /* Figure out whether we need to fake any IEs */ 1367 pos = data->ie; 1368 end = pos + data->ie_len; 1369 while (pos && pos + 1 < end) { 1370 if (pos + 2 + pos[1] > end) 1371 break; 1372 if (pos[0] == WLAN_EID_SSID) 1373 ssid_ie = pos; 1374 else if (pos[0] == WLAN_EID_SUPP_RATES) 1375 rate_ie = pos; 1376 else if (pos[0] == WLAN_EID_EXT_SUPP_RATES) 1377 rate_ie = pos; 1378 pos += 2 + pos[1]; 1379 } 1380 1381 extra_len = 0; 1382 if (ssid_ie == NULL) 1383 extra_len += 2 + data->ssid_len; 1384 if (rate_ie == NULL && data->maxrate) 1385 extra_len += 3; 1386 1387 r = os_zalloc(sizeof(*r) + extra_len + data->ie_len); 1388 if (r == NULL) 1389 return; 1390 os_memcpy(r, &data->res, sizeof(*r)); 1391 r->ie_len = extra_len + data->ie_len; 1392 pos = (u8 *) (r + 1); 1393 if (ssid_ie == NULL) { 1394 /* 1395 * Generate a fake SSID IE since the driver did not report 1396 * a full IE list. 1397 */ 1398 *pos++ = WLAN_EID_SSID; 1399 *pos++ = data->ssid_len; 1400 os_memcpy(pos, data->ssid, data->ssid_len); 1401 pos += data->ssid_len; 1402 } 1403 if (rate_ie == NULL && data->maxrate) { 1404 /* 1405 * Generate a fake Supported Rates IE since the driver did not 1406 * report a full IE list. 1407 */ 1408 *pos++ = WLAN_EID_SUPP_RATES; 1409 *pos++ = 1; 1410 *pos++ = data->maxrate; 1411 } 1412 if (data->ie) 1413 os_memcpy(pos, data->ie, data->ie_len); 1414 1415 tmp = os_realloc_array(res->res, res->num + 1, 1416 sizeof(struct wpa_scan_res *)); 1417 if (tmp == NULL) { 1418 os_free(r); 1419 return; 1420 } 1421 tmp[res->num++] = r; 1422 res->res = tmp; 1423} 1424 1425 1426/** 1427 * wpa_driver_wext_get_scan_results - Fetch the latest scan results 1428 * @priv: Pointer to private wext data from wpa_driver_wext_init() 1429 * Returns: Scan results on success, -1 on failure 1430 */ 1431struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv) 1432{ 1433 struct wpa_driver_wext_data *drv = priv; 1434 size_t len; 1435 int first; 1436 u8 *res_buf; 1437 struct iw_event iwe_buf, *iwe = &iwe_buf; 1438 char *pos, *end, *custom; 1439 struct wpa_scan_results *res; 1440 struct wext_scan_data data; 1441 1442 res_buf = wpa_driver_wext_giwscan(drv, &len); 1443 if (res_buf == NULL) 1444 return NULL; 1445 1446 first = 1; 1447 1448 res = os_zalloc(sizeof(*res)); 1449 if (res == NULL) { 1450 os_free(res_buf); 1451 return NULL; 1452 } 1453 1454 pos = (char *) res_buf; 1455 end = (char *) res_buf + len; 1456 os_memset(&data, 0, sizeof(data)); 1457 1458 while (pos + IW_EV_LCP_LEN <= end) { 1459 /* Event data may be unaligned, so make a local, aligned copy 1460 * before processing. */ 1461 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); 1462 if (iwe->len <= IW_EV_LCP_LEN) 1463 break; 1464 1465 custom = pos + IW_EV_POINT_LEN; 1466 if (wext_19_iw_point(drv, iwe->cmd)) { 1467 /* WE-19 removed the pointer from struct iw_point */ 1468 char *dpos = (char *) &iwe_buf.u.data.length; 1469 int dlen = dpos - (char *) &iwe_buf; 1470 os_memcpy(dpos, pos + IW_EV_LCP_LEN, 1471 sizeof(struct iw_event) - dlen); 1472 } else { 1473 os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); 1474 custom += IW_EV_POINT_OFF; 1475 } 1476 1477 switch (iwe->cmd) { 1478 case SIOCGIWAP: 1479 if (!first) 1480 wpa_driver_wext_add_scan_entry(res, &data); 1481 first = 0; 1482 os_free(data.ie); 1483 os_memset(&data, 0, sizeof(data)); 1484 os_memcpy(data.res.bssid, 1485 iwe->u.ap_addr.sa_data, ETH_ALEN); 1486 break; 1487 case SIOCGIWMODE: 1488 wext_get_scan_mode(iwe, &data); 1489 break; 1490 case SIOCGIWESSID: 1491 wext_get_scan_ssid(iwe, &data, custom, end); 1492 break; 1493 case SIOCGIWFREQ: 1494 wext_get_scan_freq(iwe, &data); 1495 break; 1496 case IWEVQUAL: 1497 wext_get_scan_qual(drv, iwe, &data); 1498 break; 1499 case SIOCGIWENCODE: 1500 wext_get_scan_encode(iwe, &data); 1501 break; 1502 case SIOCGIWRATE: 1503 wext_get_scan_rate(iwe, &data, pos, end); 1504 break; 1505 case IWEVGENIE: 1506 wext_get_scan_iwevgenie(iwe, &data, custom, end); 1507 break; 1508 case IWEVCUSTOM: 1509 wext_get_scan_custom(iwe, &data, custom, end); 1510 break; 1511 } 1512 1513 pos += iwe->len; 1514 } 1515 os_free(res_buf); 1516 res_buf = NULL; 1517 if (!first) 1518 wpa_driver_wext_add_scan_entry(res, &data); 1519 os_free(data.ie); 1520 1521 wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)", 1522 (unsigned long) len, (unsigned long) res->num); 1523 1524 return res; 1525} 1526 1527 1528static int wpa_driver_wext_get_range(void *priv) 1529{ 1530 struct wpa_driver_wext_data *drv = priv; 1531 struct iw_range *range; 1532 struct iwreq iwr; 1533 int minlen; 1534 size_t buflen; 1535 1536 /* 1537 * Use larger buffer than struct iw_range in order to allow the 1538 * structure to grow in the future. 1539 */ 1540 buflen = sizeof(struct iw_range) + 500; 1541 range = os_zalloc(buflen); 1542 if (range == NULL) 1543 return -1; 1544 1545 os_memset(&iwr, 0, sizeof(iwr)); 1546 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1547 iwr.u.data.pointer = (caddr_t) range; 1548 iwr.u.data.length = buflen; 1549 1550 minlen = ((char *) &range->enc_capa) - (char *) range + 1551 sizeof(range->enc_capa); 1552 1553 if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { 1554 perror("ioctl[SIOCGIWRANGE]"); 1555 os_free(range); 1556 return -1; 1557 } else if (iwr.u.data.length >= minlen && 1558 range->we_version_compiled >= 18) { 1559 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " 1560 "WE(source)=%d enc_capa=0x%x", 1561 range->we_version_compiled, 1562 range->we_version_source, 1563 range->enc_capa); 1564 drv->has_capability = 1; 1565 drv->we_version_compiled = range->we_version_compiled; 1566 if (range->enc_capa & IW_ENC_CAPA_WPA) { 1567 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1568 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 1569 } 1570 if (range->enc_capa & IW_ENC_CAPA_WPA2) { 1571 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1572 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 1573 } 1574 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 1575 WPA_DRIVER_CAPA_ENC_WEP104; 1576 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP128; 1577 if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) 1578 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 1579 if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) 1580 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 1581 if (range->enc_capa & IW_ENC_CAPA_4WAY_HANDSHAKE) 1582 drv->capa.flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; 1583 drv->capa.auth = WPA_DRIVER_AUTH_OPEN | 1584 WPA_DRIVER_AUTH_SHARED | 1585 WPA_DRIVER_AUTH_LEAP; 1586 drv->capa.max_scan_ssids = 1; 1587 1588 wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x " 1589 "flags 0x%x", 1590 drv->capa.key_mgmt, drv->capa.enc, drv->capa.flags); 1591 } else { 1592 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - " 1593 "assuming WPA is not supported"); 1594 } 1595 1596 drv->max_level = range->max_qual.level; 1597 1598 os_free(range); 1599 return 0; 1600} 1601 1602 1603static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv, 1604 const u8 *psk) 1605{ 1606 struct iw_encode_ext *ext; 1607 struct iwreq iwr; 1608 int ret; 1609 1610 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 1611 1612 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) 1613 return 0; 1614 1615 if (!psk) 1616 return 0; 1617 1618 os_memset(&iwr, 0, sizeof(iwr)); 1619 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1620 1621 ext = os_zalloc(sizeof(*ext) + PMK_LEN); 1622 if (ext == NULL) 1623 return -1; 1624 1625 iwr.u.encoding.pointer = (caddr_t) ext; 1626 iwr.u.encoding.length = sizeof(*ext) + PMK_LEN; 1627 ext->key_len = PMK_LEN; 1628 os_memcpy(&ext->key, psk, ext->key_len); 1629 ext->alg = IW_ENCODE_ALG_PMK; 1630 1631 ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr); 1632 if (ret < 0) 1633 perror("ioctl[SIOCSIWENCODEEXT] PMK"); 1634 os_free(ext); 1635 1636 return ret; 1637} 1638 1639 1640static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg, 1641 const u8 *addr, int key_idx, 1642 int set_tx, const u8 *seq, 1643 size_t seq_len, 1644 const u8 *key, size_t key_len) 1645{ 1646 struct wpa_driver_wext_data *drv = priv; 1647 struct iwreq iwr; 1648 int ret = 0; 1649 struct iw_encode_ext *ext; 1650 1651 if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) { 1652 wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu", 1653 __FUNCTION__, (unsigned long) seq_len); 1654 return -1; 1655 } 1656 1657 ext = os_zalloc(sizeof(*ext) + key_len); 1658 if (ext == NULL) 1659 return -1; 1660 os_memset(&iwr, 0, sizeof(iwr)); 1661 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1662 iwr.u.encoding.flags = key_idx + 1; 1663 iwr.u.encoding.flags |= IW_ENCODE_TEMP; 1664 if (alg == WPA_ALG_NONE) 1665 iwr.u.encoding.flags |= IW_ENCODE_DISABLED; 1666 iwr.u.encoding.pointer = (caddr_t) ext; 1667 iwr.u.encoding.length = sizeof(*ext) + key_len; 1668 1669 if (addr == NULL || is_broadcast_ether_addr(addr)) 1670 ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY; 1671 if (set_tx) 1672 ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY; 1673 1674 ext->addr.sa_family = ARPHRD_ETHER; 1675 if (addr) 1676 os_memcpy(ext->addr.sa_data, addr, ETH_ALEN); 1677 else 1678 os_memset(ext->addr.sa_data, 0xff, ETH_ALEN); 1679 if (key && key_len) { 1680 os_memcpy(ext + 1, key, key_len); 1681 ext->key_len = key_len; 1682 } 1683 switch (alg) { 1684 case WPA_ALG_NONE: 1685 ext->alg = IW_ENCODE_ALG_NONE; 1686 break; 1687 case WPA_ALG_WEP: 1688 ext->alg = IW_ENCODE_ALG_WEP; 1689 break; 1690 case WPA_ALG_TKIP: 1691 ext->alg = IW_ENCODE_ALG_TKIP; 1692 break; 1693 case WPA_ALG_CCMP: 1694 ext->alg = IW_ENCODE_ALG_CCMP; 1695 break; 1696 case WPA_ALG_PMK: 1697 ext->alg = IW_ENCODE_ALG_PMK; 1698 break; 1699#ifdef CONFIG_IEEE80211W 1700 case WPA_ALG_IGTK: 1701 ext->alg = IW_ENCODE_ALG_AES_CMAC; 1702 break; 1703#endif /* CONFIG_IEEE80211W */ 1704 default: 1705 wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d", 1706 __FUNCTION__, alg); 1707 os_free(ext); 1708 return -1; 1709 } 1710 1711 if (seq && seq_len) { 1712 ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID; 1713 os_memcpy(ext->rx_seq, seq, seq_len); 1714 } 1715 1716 if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) { 1717 ret = errno == EOPNOTSUPP ? -2 : -1; 1718 if (errno == ENODEV) { 1719 /* 1720 * ndiswrapper seems to be returning incorrect error 1721 * code.. */ 1722 ret = -2; 1723 } 1724 1725 perror("ioctl[SIOCSIWENCODEEXT]"); 1726 } 1727 1728 os_free(ext); 1729 return ret; 1730} 1731 1732 1733/** 1734 * wpa_driver_wext_set_key - Configure encryption key 1735 * @priv: Pointer to private wext data from wpa_driver_wext_init() 1736 * @priv: Private driver interface data 1737 * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, 1738 * %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key. 1739 * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for 1740 * broadcast/default keys 1741 * @key_idx: key index (0..3), usually 0 for unicast keys 1742 * @set_tx: Configure this key as the default Tx key (only used when 1743 * driver does not support separate unicast/individual key 1744 * @seq: Sequence number/packet number, seq_len octets, the next 1745 * packet number to be used for in replay protection; configured 1746 * for Rx keys (in most cases, this is only used with broadcast 1747 * keys and set to zero for unicast keys) 1748 * @seq_len: Length of the seq, depends on the algorithm: 1749 * TKIP: 6 octets, CCMP: 6 octets 1750 * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, 1751 * 8-byte Rx Mic Key 1752 * @key_len: Length of the key buffer in octets (WEP: 5 or 13, 1753 * TKIP: 32, CCMP: 16) 1754 * Returns: 0 on success, -1 on failure 1755 * 1756 * This function uses SIOCSIWENCODEEXT by default, but tries to use 1757 * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key. 1758 */ 1759int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg, 1760 const u8 *addr, int key_idx, 1761 int set_tx, const u8 *seq, size_t seq_len, 1762 const u8 *key, size_t key_len) 1763{ 1764 struct wpa_driver_wext_data *drv = priv; 1765 struct iwreq iwr; 1766 int ret = 0; 1767 1768 wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu " 1769 "key_len=%lu", 1770 __FUNCTION__, alg, key_idx, set_tx, 1771 (unsigned long) seq_len, (unsigned long) key_len); 1772 1773 ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx, 1774 seq, seq_len, key, key_len); 1775 if (ret == 0) 1776 return 0; 1777 1778 if (ret == -2 && 1779 (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) { 1780 wpa_printf(MSG_DEBUG, "Driver did not support " 1781 "SIOCSIWENCODEEXT, trying SIOCSIWENCODE"); 1782 ret = 0; 1783 } else { 1784 wpa_printf(MSG_DEBUG, "Driver did not support " 1785 "SIOCSIWENCODEEXT"); 1786 return ret; 1787 } 1788 1789 os_memset(&iwr, 0, sizeof(iwr)); 1790 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1791 iwr.u.encoding.flags = key_idx + 1; 1792 iwr.u.encoding.flags |= IW_ENCODE_TEMP; 1793 if (alg == WPA_ALG_NONE) 1794 iwr.u.encoding.flags |= IW_ENCODE_DISABLED; 1795 iwr.u.encoding.pointer = (caddr_t) key; 1796 iwr.u.encoding.length = key_len; 1797 1798 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 1799 perror("ioctl[SIOCSIWENCODE]"); 1800 ret = -1; 1801 } 1802 1803 if (set_tx && alg != WPA_ALG_NONE) { 1804 os_memset(&iwr, 0, sizeof(iwr)); 1805 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1806 iwr.u.encoding.flags = key_idx + 1; 1807 iwr.u.encoding.flags |= IW_ENCODE_TEMP; 1808 iwr.u.encoding.pointer = (caddr_t) NULL; 1809 iwr.u.encoding.length = 0; 1810 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 1811 perror("ioctl[SIOCSIWENCODE] (set_tx)"); 1812 ret = -1; 1813 } 1814 } 1815 1816 return ret; 1817} 1818 1819 1820static int wpa_driver_wext_set_countermeasures(void *priv, 1821 int enabled) 1822{ 1823 struct wpa_driver_wext_data *drv = priv; 1824 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 1825 return wpa_driver_wext_set_auth_param(drv, 1826 IW_AUTH_TKIP_COUNTERMEASURES, 1827 enabled); 1828} 1829 1830 1831static int wpa_driver_wext_set_drop_unencrypted(void *priv, 1832 int enabled) 1833{ 1834 struct wpa_driver_wext_data *drv = priv; 1835 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 1836 drv->use_crypt = enabled; 1837 return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED, 1838 enabled); 1839} 1840 1841 1842static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv, 1843 const u8 *addr, int cmd, int reason_code) 1844{ 1845 struct iwreq iwr; 1846 struct iw_mlme mlme; 1847 int ret = 0; 1848 1849 os_memset(&iwr, 0, sizeof(iwr)); 1850 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1851 os_memset(&mlme, 0, sizeof(mlme)); 1852 mlme.cmd = cmd; 1853 mlme.reason_code = reason_code; 1854 mlme.addr.sa_family = ARPHRD_ETHER; 1855 os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN); 1856 iwr.u.data.pointer = (caddr_t) &mlme; 1857 iwr.u.data.length = sizeof(mlme); 1858 1859 if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) { 1860 perror("ioctl[SIOCSIWMLME]"); 1861 ret = -1; 1862 } 1863 1864 return ret; 1865} 1866 1867 1868static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv) 1869{ 1870 struct iwreq iwr; 1871 const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; 1872#ifndef ANDROID 1873 u8 ssid[32]; 1874 int i; 1875#endif /* ANDROID */ 1876 1877 /* 1878 * Only force-disconnect when the card is in infrastructure mode, 1879 * otherwise the driver might interpret the cleared BSSID and random 1880 * SSID as an attempt to create a new ad-hoc network. 1881 */ 1882 os_memset(&iwr, 0, sizeof(iwr)); 1883 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1884 if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { 1885 perror("ioctl[SIOCGIWMODE]"); 1886 iwr.u.mode = IW_MODE_INFRA; 1887 } 1888 1889 if (iwr.u.mode == IW_MODE_INFRA) { 1890 /* Clear the BSSID selection */ 1891 if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0) { 1892 wpa_printf(MSG_DEBUG, "WEXT: Failed to clear BSSID " 1893 "selection on disconnect"); 1894 } 1895 1896#ifndef ANDROID 1897 if (drv->cfg80211) { 1898 /* 1899 * cfg80211 supports SIOCSIWMLME commands, so there is 1900 * no need for the random SSID hack, but clear the 1901 * SSID. 1902 */ 1903 if (wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) { 1904 wpa_printf(MSG_DEBUG, "WEXT: Failed to clear " 1905 "SSID on disconnect"); 1906 } 1907 return; 1908 } 1909 1910 /* 1911 * Set a random SSID to make sure the driver will not be trying 1912 * to associate with something even if it does not understand 1913 * SIOCSIWMLME commands (or tries to associate automatically 1914 * after deauth/disassoc). 1915 */ 1916 for (i = 0; i < 32; i++) 1917 ssid[i] = rand() & 0xFF; 1918 if (wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) { 1919 wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus " 1920 "SSID to disconnect"); 1921 } 1922#endif /* ANDROID */ 1923 } 1924} 1925 1926 1927static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr, 1928 int reason_code) 1929{ 1930 struct wpa_driver_wext_data *drv = priv; 1931 int ret; 1932 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 1933 ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code); 1934 wpa_driver_wext_disconnect(drv); 1935 return ret; 1936} 1937 1938 1939static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie, 1940 size_t ie_len) 1941{ 1942 struct wpa_driver_wext_data *drv = priv; 1943 struct iwreq iwr; 1944 int ret = 0; 1945 1946 os_memset(&iwr, 0, sizeof(iwr)); 1947 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1948 iwr.u.data.pointer = (caddr_t) ie; 1949 iwr.u.data.length = ie_len; 1950 1951 if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { 1952 perror("ioctl[SIOCSIWGENIE]"); 1953 ret = -1; 1954 } 1955 1956 return ret; 1957} 1958 1959 1960int wpa_driver_wext_cipher2wext(int cipher) 1961{ 1962 switch (cipher) { 1963 case CIPHER_NONE: 1964 return IW_AUTH_CIPHER_NONE; 1965 case CIPHER_WEP40: 1966 return IW_AUTH_CIPHER_WEP40; 1967 case CIPHER_TKIP: 1968 return IW_AUTH_CIPHER_TKIP; 1969 case CIPHER_CCMP: 1970 return IW_AUTH_CIPHER_CCMP; 1971 case CIPHER_WEP104: 1972 return IW_AUTH_CIPHER_WEP104; 1973 default: 1974 return 0; 1975 } 1976} 1977 1978 1979int wpa_driver_wext_keymgmt2wext(int keymgmt) 1980{ 1981 switch (keymgmt) { 1982 case KEY_MGMT_802_1X: 1983 case KEY_MGMT_802_1X_NO_WPA: 1984 return IW_AUTH_KEY_MGMT_802_1X; 1985 case KEY_MGMT_PSK: 1986 return IW_AUTH_KEY_MGMT_PSK; 1987 default: 1988 return 0; 1989 } 1990} 1991 1992 1993static int 1994wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv, 1995 struct wpa_driver_associate_params *params) 1996{ 1997 struct iwreq iwr; 1998 int ret = 0; 1999 2000 wpa_printf(MSG_DEBUG, "WEXT: Driver did not support " 2001 "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE"); 2002 2003 os_memset(&iwr, 0, sizeof(iwr)); 2004 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 2005 /* Just changing mode, not actual keys */ 2006 iwr.u.encoding.flags = 0; 2007 iwr.u.encoding.pointer = (caddr_t) NULL; 2008 iwr.u.encoding.length = 0; 2009 2010 /* 2011 * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two 2012 * different things. Here they are used to indicate Open System vs. 2013 * Shared Key authentication algorithm. However, some drivers may use 2014 * them to select between open/restricted WEP encrypted (open = allow 2015 * both unencrypted and encrypted frames; restricted = only allow 2016 * encrypted frames). 2017 */ 2018 2019 if (!drv->use_crypt) { 2020 iwr.u.encoding.flags |= IW_ENCODE_DISABLED; 2021 } else { 2022 if (params->auth_alg & WPA_AUTH_ALG_OPEN) 2023 iwr.u.encoding.flags |= IW_ENCODE_OPEN; 2024 if (params->auth_alg & WPA_AUTH_ALG_SHARED) 2025 iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED; 2026 } 2027 2028 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 2029 perror("ioctl[SIOCSIWENCODE]"); 2030 ret = -1; 2031 } 2032 2033 return ret; 2034} 2035 2036 2037int wpa_driver_wext_associate(void *priv, 2038 struct wpa_driver_associate_params *params) 2039{ 2040 struct wpa_driver_wext_data *drv = priv; 2041 int ret = 0; 2042 int allow_unencrypted_eapol; 2043 int value; 2044 2045 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 2046 2047 if (drv->cfg80211) { 2048 /* 2049 * Stop cfg80211 from trying to associate before we are done 2050 * with all parameters. 2051 */ 2052 wpa_driver_wext_set_ssid(drv, (u8 *) "", 0); 2053 } 2054 2055 if (wpa_driver_wext_set_drop_unencrypted(drv, params->drop_unencrypted) 2056 < 0) 2057 ret = -1; 2058 if (wpa_driver_wext_set_auth_alg(drv, params->auth_alg) < 0) 2059 ret = -1; 2060 if (wpa_driver_wext_set_mode(drv, params->mode) < 0) 2061 ret = -1; 2062 2063 /* 2064 * If the driver did not support SIOCSIWAUTH, fallback to 2065 * SIOCSIWENCODE here. 2066 */ 2067 if (drv->auth_alg_fallback && 2068 wpa_driver_wext_auth_alg_fallback(drv, params) < 0) 2069 ret = -1; 2070 2071 if (!params->bssid && 2072 wpa_driver_wext_set_bssid(drv, NULL) < 0) 2073 ret = -1; 2074 2075 /* TODO: should consider getting wpa version and cipher/key_mgmt suites 2076 * from configuration, not from here, where only the selected suite is 2077 * available */ 2078 if (wpa_driver_wext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len) 2079 < 0) 2080 ret = -1; 2081 if (params->wpa_ie == NULL || params->wpa_ie_len == 0) 2082 value = IW_AUTH_WPA_VERSION_DISABLED; 2083 else if (params->wpa_ie[0] == WLAN_EID_RSN) 2084 value = IW_AUTH_WPA_VERSION_WPA2; 2085 else 2086 value = IW_AUTH_WPA_VERSION_WPA; 2087 if (wpa_driver_wext_set_auth_param(drv, 2088 IW_AUTH_WPA_VERSION, value) < 0) 2089 ret = -1; 2090 value = wpa_driver_wext_cipher2wext(params->pairwise_suite); 2091 if (wpa_driver_wext_set_auth_param(drv, 2092 IW_AUTH_CIPHER_PAIRWISE, value) < 0) 2093 ret = -1; 2094 value = wpa_driver_wext_cipher2wext(params->group_suite); 2095 if (wpa_driver_wext_set_auth_param(drv, 2096 IW_AUTH_CIPHER_GROUP, value) < 0) 2097 ret = -1; 2098 value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); 2099 if (wpa_driver_wext_set_auth_param(drv, 2100 IW_AUTH_KEY_MGMT, value) < 0) 2101 ret = -1; 2102 value = params->key_mgmt_suite != KEY_MGMT_NONE || 2103 params->pairwise_suite != CIPHER_NONE || 2104 params->group_suite != CIPHER_NONE || 2105 params->wpa_ie_len; 2106 if (wpa_driver_wext_set_auth_param(drv, 2107 IW_AUTH_PRIVACY_INVOKED, value) < 0) 2108 ret = -1; 2109 2110 /* Allow unencrypted EAPOL messages even if pairwise keys are set when 2111 * not using WPA. IEEE 802.1X specifies that these frames are not 2112 * encrypted, but WPA encrypts them when pairwise keys are in use. */ 2113 if (params->key_mgmt_suite == KEY_MGMT_802_1X || 2114 params->key_mgmt_suite == KEY_MGMT_PSK) 2115 allow_unencrypted_eapol = 0; 2116 else 2117 allow_unencrypted_eapol = 1; 2118 2119 if (wpa_driver_wext_set_psk(drv, params->psk) < 0) 2120 ret = -1; 2121 if (wpa_driver_wext_set_auth_param(drv, 2122 IW_AUTH_RX_UNENCRYPTED_EAPOL, 2123 allow_unencrypted_eapol) < 0) 2124 ret = -1; 2125#ifdef CONFIG_IEEE80211W 2126 switch (params->mgmt_frame_protection) { 2127 case NO_MGMT_FRAME_PROTECTION: 2128 value = IW_AUTH_MFP_DISABLED; 2129 break; 2130 case MGMT_FRAME_PROTECTION_OPTIONAL: 2131 value = IW_AUTH_MFP_OPTIONAL; 2132 break; 2133 case MGMT_FRAME_PROTECTION_REQUIRED: 2134 value = IW_AUTH_MFP_REQUIRED; 2135 break; 2136 }; 2137 if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0) 2138 ret = -1; 2139#endif /* CONFIG_IEEE80211W */ 2140 if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0) 2141 ret = -1; 2142 if (!drv->cfg80211 && 2143 wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) 2144 ret = -1; 2145 if (params->bssid && 2146 wpa_driver_wext_set_bssid(drv, params->bssid) < 0) 2147 ret = -1; 2148 if (drv->cfg80211 && 2149 wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) 2150 ret = -1; 2151 2152 return ret; 2153} 2154 2155 2156static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg) 2157{ 2158 struct wpa_driver_wext_data *drv = priv; 2159 int algs = 0, res; 2160 2161 if (auth_alg & WPA_AUTH_ALG_OPEN) 2162 algs |= IW_AUTH_ALG_OPEN_SYSTEM; 2163 if (auth_alg & WPA_AUTH_ALG_SHARED) 2164 algs |= IW_AUTH_ALG_SHARED_KEY; 2165 if (auth_alg & WPA_AUTH_ALG_LEAP) 2166 algs |= IW_AUTH_ALG_LEAP; 2167 if (algs == 0) { 2168 /* at least one algorithm should be set */ 2169 algs = IW_AUTH_ALG_OPEN_SYSTEM; 2170 } 2171 2172 res = wpa_driver_wext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG, 2173 algs); 2174 drv->auth_alg_fallback = res == -2; 2175 return res; 2176} 2177 2178 2179/** 2180 * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE 2181 * @priv: Pointer to private wext data from wpa_driver_wext_init() 2182 * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS 2183 * Returns: 0 on success, -1 on failure 2184 */ 2185int wpa_driver_wext_set_mode(void *priv, int mode) 2186{ 2187 struct wpa_driver_wext_data *drv = priv; 2188 struct iwreq iwr; 2189 int ret = -1; 2190 unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA; 2191 2192 os_memset(&iwr, 0, sizeof(iwr)); 2193 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 2194 iwr.u.mode = new_mode; 2195 if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) { 2196 ret = 0; 2197 goto done; 2198 } 2199 2200 if (errno != EBUSY) { 2201 perror("ioctl[SIOCSIWMODE]"); 2202 goto done; 2203 } 2204 2205 /* mac80211 doesn't allow mode changes while the device is up, so if 2206 * the device isn't in the mode we're about to change to, take device 2207 * down, try to set the mode again, and bring it back up. 2208 */ 2209 if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { 2210 perror("ioctl[SIOCGIWMODE]"); 2211 goto done; 2212 } 2213 2214 if (iwr.u.mode == new_mode) { 2215 ret = 0; 2216 goto done; 2217 } 2218 2219 if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0) == 0) { 2220 /* Try to set the mode again while the interface is down */ 2221 iwr.u.mode = new_mode; 2222 if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) 2223 perror("ioctl[SIOCSIWMODE]"); 2224 else 2225 ret = 0; 2226 2227 (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1); 2228 } 2229 2230done: 2231 return ret; 2232} 2233 2234 2235static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv, 2236 u32 cmd, const u8 *bssid, const u8 *pmkid) 2237{ 2238 struct iwreq iwr; 2239 struct iw_pmksa pmksa; 2240 int ret = 0; 2241 2242 os_memset(&iwr, 0, sizeof(iwr)); 2243 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 2244 os_memset(&pmksa, 0, sizeof(pmksa)); 2245 pmksa.cmd = cmd; 2246 pmksa.bssid.sa_family = ARPHRD_ETHER; 2247 if (bssid) 2248 os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN); 2249 if (pmkid) 2250 os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN); 2251 iwr.u.data.pointer = (caddr_t) &pmksa; 2252 iwr.u.data.length = sizeof(pmksa); 2253 2254 if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) { 2255 if (errno != EOPNOTSUPP) 2256 perror("ioctl[SIOCSIWPMKSA]"); 2257 ret = -1; 2258 } 2259 2260 return ret; 2261} 2262 2263 2264static int wpa_driver_wext_add_pmkid(void *priv, const u8 *bssid, 2265 const u8 *pmkid) 2266{ 2267 struct wpa_driver_wext_data *drv = priv; 2268 return wpa_driver_wext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid); 2269} 2270 2271 2272static int wpa_driver_wext_remove_pmkid(void *priv, const u8 *bssid, 2273 const u8 *pmkid) 2274{ 2275 struct wpa_driver_wext_data *drv = priv; 2276 return wpa_driver_wext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid); 2277} 2278 2279 2280static int wpa_driver_wext_flush_pmkid(void *priv) 2281{ 2282 struct wpa_driver_wext_data *drv = priv; 2283 return wpa_driver_wext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL); 2284} 2285 2286 2287int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa) 2288{ 2289 struct wpa_driver_wext_data *drv = priv; 2290 if (!drv->has_capability) 2291 return -1; 2292 os_memcpy(capa, &drv->capa, sizeof(*capa)); 2293 return 0; 2294} 2295 2296 2297int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv, 2298 const char *ifname) 2299{ 2300 if (ifname == NULL) { 2301 drv->ifindex2 = -1; 2302 return 0; 2303 } 2304 2305 drv->ifindex2 = if_nametoindex(ifname); 2306 if (drv->ifindex2 <= 0) 2307 return -1; 2308 2309 wpa_printf(MSG_DEBUG, "Added alternative ifindex %d (%s) for " 2310 "wireless events", drv->ifindex2, ifname); 2311 2312 return 0; 2313} 2314 2315 2316int wpa_driver_wext_set_operstate(void *priv, int state) 2317{ 2318 struct wpa_driver_wext_data *drv = priv; 2319 2320 wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", 2321 __func__, drv->operstate, state, state ? "UP" : "DORMANT"); 2322 drv->operstate = state; 2323 return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1, 2324 state ? IF_OPER_UP : IF_OPER_DORMANT); 2325} 2326 2327 2328int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv) 2329{ 2330 return drv->we_version_compiled; 2331} 2332 2333 2334static const char * wext_get_radio_name(void *priv) 2335{ 2336 struct wpa_driver_wext_data *drv = priv; 2337 return drv->phyname; 2338} 2339 2340 2341#ifdef ANDROID 2342 2343static int android_wext_cmd(struct wpa_driver_wext_data *drv, const char *cmd) 2344{ 2345 struct iwreq iwr; 2346 char buf[MAX_DRV_CMD_SIZE]; 2347 int ret; 2348 2349 os_memset(&iwr, 0, sizeof(iwr)); 2350 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 2351 2352 os_memset(buf, 0, sizeof(buf)); 2353 os_strlcpy(buf, cmd, sizeof(buf)); 2354 2355 iwr.u.data.pointer = buf; 2356 iwr.u.data.length = sizeof(buf); 2357 2358 ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr); 2359 2360 if (ret < 0) { 2361 wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret, 2362 cmd); 2363 drv->errors++; 2364 if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { 2365 drv->errors = 0; 2366 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE 2367 "HANGED"); 2368 } 2369 return ret; 2370 } 2371 2372 drv->errors = 0; 2373 return 0; 2374} 2375 2376 2377static int wext_sched_scan(void *priv, struct wpa_driver_scan_params *params, 2378 u32 interval) 2379{ 2380 struct wpa_driver_wext_data *drv = priv; 2381 struct iwreq iwr; 2382 int ret = 0, i = 0, bp; 2383 char buf[WEXT_PNO_MAX_COMMAND_SIZE]; 2384 2385 bp = WEXT_PNOSETUP_HEADER_SIZE; 2386 os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp); 2387 buf[bp++] = WEXT_PNO_TLV_PREFIX; 2388 buf[bp++] = WEXT_PNO_TLV_VERSION; 2389 buf[bp++] = WEXT_PNO_TLV_SUBVERSION; 2390 buf[bp++] = WEXT_PNO_TLV_RESERVED; 2391 2392 while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) { 2393 /* 2394 * Check that there is enough space needed for 1 more SSID, the 2395 * other sections and null termination. 2396 */ 2397 if ((bp + WEXT_PNO_SSID_HEADER_SIZE + IW_ESSID_MAX_SIZE + 2398 WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf)) 2399 break; 2400 2401 wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan", 2402 params->ssids[i].ssid, 2403 params->ssids[i].ssid_len); 2404 buf[bp++] = WEXT_PNO_SSID_SECTION; 2405 buf[bp++] = params->ssids[i].ssid_len; 2406 os_memcpy(&buf[bp], params->ssids[i].ssid, 2407 params->ssids[i].ssid_len); 2408 bp += params->ssids[i].ssid_len; 2409 i++; 2410 } 2411 2412 buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION; 2413 /* TODO: consider using interval parameter (interval in msec) instead 2414 * of hardcoded value here */ 2415 os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", 2416 WEXT_PNO_SCAN_INTERVAL); 2417 bp += WEXT_PNO_SCAN_INTERVAL_LENGTH; 2418 2419 buf[bp++] = WEXT_PNO_REPEAT_SECTION; 2420 os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", 2421 WEXT_PNO_REPEAT); 2422 bp += WEXT_PNO_REPEAT_LENGTH; 2423 2424 buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION; 2425 os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", 2426 WEXT_PNO_MAX_REPEAT); 2427 bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1; 2428 2429 os_memset(&iwr, 0, sizeof(iwr)); 2430 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 2431 iwr.u.data.pointer = buf; 2432 iwr.u.data.length = bp; 2433 2434 ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr); 2435 if (ret < 0) { 2436 wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", 2437 ret); 2438 drv->errors++; 2439 if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { 2440 drv->errors = 0; 2441 wpa_msg(drv->ctx, MSG_INFO, 2442 WPA_EVENT_DRIVER_STATE "HANGED"); 2443 } 2444 return ret; 2445 } 2446 2447 drv->errors = 0; 2448 drv->bgscan_enabled = 1; 2449 2450 return android_wext_cmd(drv, "PNOFORCE 1"); 2451} 2452 2453 2454static int wext_stop_sched_scan(void *priv) 2455{ 2456 struct wpa_driver_wext_data *drv = priv; 2457 drv->bgscan_enabled = 0; 2458 return android_wext_cmd(drv, "PNOFORCE 0"); 2459} 2460 2461#endif /* ANDROID */ 2462 2463 2464const struct wpa_driver_ops wpa_driver_wext_ops = { 2465 .name = "wext", 2466 .desc = "Linux wireless extensions (generic)", 2467 .get_bssid = wpa_driver_wext_get_bssid, 2468 .get_ssid = wpa_driver_wext_get_ssid, 2469 .set_key = wpa_driver_wext_set_key, 2470 .set_countermeasures = wpa_driver_wext_set_countermeasures, 2471 .scan2 = wpa_driver_wext_scan, 2472 .get_scan_results2 = wpa_driver_wext_get_scan_results, 2473 .deauthenticate = wpa_driver_wext_deauthenticate, 2474 .associate = wpa_driver_wext_associate, 2475 .init = wpa_driver_wext_init, 2476 .deinit = wpa_driver_wext_deinit, 2477 .add_pmkid = wpa_driver_wext_add_pmkid, 2478 .remove_pmkid = wpa_driver_wext_remove_pmkid, 2479 .flush_pmkid = wpa_driver_wext_flush_pmkid, 2480 .get_capa = wpa_driver_wext_get_capa, 2481 .set_operstate = wpa_driver_wext_set_operstate, 2482 .get_radio_name = wext_get_radio_name, 2483#ifdef ANDROID 2484 .sched_scan = wext_sched_scan, 2485 .stop_sched_scan = wext_stop_sched_scan, 2486#endif /* ANDROID */ 2487}; 2488