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