$search
00001 /* 00002 * Driver interaction with generic Linux Wireless Extensions 00003 * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 * 00014 * This file implements a driver interface for the Linux Wireless Extensions. 00015 * When used with WE-18 or newer, this interface can be used as-is with number 00016 * of drivers. In addition to this, some of the common functions in this file 00017 * can be used by other driver interface implementations that use generic WE 00018 * ioctls, but require private ioctls for some of the functionality. 00019 */ 00020 00021 #include "includes.h" 00022 #include <sys/ioctl.h> 00023 #include <sys/stat.h> 00024 #include <net/if_arp.h> 00025 00026 #include "wireless_copy.h" 00027 #include "common.h" 00028 #include "eloop.h" 00029 #include "common/ieee802_11_defs.h" 00030 #include "common/wpa_common.h" 00031 #include "priv_netlink.h" 00032 #include "netlink.h" 00033 #include "linux_ioctl.h" 00034 #include "driver.h" 00035 #include "driver_wext.h" 00036 00037 00038 static int wpa_driver_wext_flush_pmkid(void *priv); 00039 static int wpa_driver_wext_get_range(void *priv); 00040 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv); 00041 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv); 00042 static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg); 00043 00044 00045 int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, 00046 int idx, u32 value) 00047 { 00048 struct iwreq iwr; 00049 int ret = 0; 00050 00051 os_memset(&iwr, 0, sizeof(iwr)); 00052 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 00053 iwr.u.param.flags = idx & IW_AUTH_INDEX; 00054 iwr.u.param.value = value; 00055 00056 if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) { 00057 if (errno != EOPNOTSUPP) { 00058 wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d " 00059 "value 0x%x) failed: %s)", 00060 idx, value, strerror(errno)); 00061 } 00062 ret = errno == EOPNOTSUPP ? -2 : -1; 00063 } 00064 00065 return ret; 00066 } 00067 00068 00075 int wpa_driver_wext_get_bssid(void *priv, u8 *bssid) 00076 { 00077 struct wpa_driver_wext_data *drv = priv; 00078 struct iwreq iwr; 00079 int ret = 0; 00080 00081 os_memset(&iwr, 0, sizeof(iwr)); 00082 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 00083 00084 if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) { 00085 perror("ioctl[SIOCGIWAP]"); 00086 ret = -1; 00087 } 00088 os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN); 00089 00090 return ret; 00091 } 00092 00093 00100 int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid) 00101 { 00102 struct wpa_driver_wext_data *drv = priv; 00103 struct iwreq iwr; 00104 int ret = 0; 00105 00106 os_memset(&iwr, 0, sizeof(iwr)); 00107 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 00108 iwr.u.ap_addr.sa_family = ARPHRD_ETHER; 00109 if (bssid) 00110 os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN); 00111 else 00112 os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN); 00113 00114 if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) { 00115 perror("ioctl[SIOCSIWAP]"); 00116 ret = -1; 00117 } 00118 00119 return ret; 00120 } 00121 00122 00129 int wpa_driver_wext_get_ssid(void *priv, u8 *ssid) 00130 { 00131 struct wpa_driver_wext_data *drv = priv; 00132 struct iwreq iwr; 00133 int ret = 0; 00134 00135 os_memset(&iwr, 0, sizeof(iwr)); 00136 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 00137 iwr.u.essid.pointer = (caddr_t) ssid; 00138 iwr.u.essid.length = 32; 00139 00140 if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { 00141 perror("ioctl[SIOCGIWESSID]"); 00142 ret = -1; 00143 } else { 00144 ret = iwr.u.essid.length; 00145 if (ret > 32) 00146 ret = 32; 00147 /* Some drivers include nul termination in the SSID, so let's 00148 * remove it here before further processing. WE-21 changes this 00149 * to explicitly require the length _not_ to include nul 00150 * termination. */ 00151 if (ret > 0 && ssid[ret - 1] == '\0' && 00152 drv->we_version_compiled < 21) 00153 ret--; 00154 } 00155 00156 return ret; 00157 } 00158 00159 00167 int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len) 00168 { 00169 struct wpa_driver_wext_data *drv = priv; 00170 struct iwreq iwr; 00171 int ret = 0; 00172 char buf[33]; 00173 00174 if (ssid_len > 32) 00175 return -1; 00176 00177 os_memset(&iwr, 0, sizeof(iwr)); 00178 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 00179 /* flags: 1 = ESSID is active, 0 = not (promiscuous) */ 00180 iwr.u.essid.flags = (ssid_len != 0); 00181 os_memset(buf, 0, sizeof(buf)); 00182 os_memcpy(buf, ssid, ssid_len); 00183 iwr.u.essid.pointer = (caddr_t) buf; 00184 if (drv->we_version_compiled < 21) { 00185 /* For historic reasons, set SSID length to include one extra 00186 * character, C string nul termination, even though SSID is 00187 * really an octet string that should not be presented as a C 00188 * string. Some Linux drivers decrement the length by one and 00189 * can thus end up missing the last octet of the SSID if the 00190 * length is not incremented here. WE-21 changes this to 00191 * explicitly require the length _not_ to include nul 00192 * termination. */ 00193 if (ssid_len) 00194 ssid_len++; 00195 } 00196 iwr.u.essid.length = ssid_len; 00197 00198 if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { 00199 perror("ioctl[SIOCSIWESSID]"); 00200 ret = -1; 00201 } 00202 00203 return ret; 00204 } 00205 00206 00213 int wpa_driver_wext_set_freq(void *priv, int freq) 00214 { 00215 struct wpa_driver_wext_data *drv = priv; 00216 struct iwreq iwr; 00217 int ret = 0; 00218 00219 os_memset(&iwr, 0, sizeof(iwr)); 00220 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 00221 iwr.u.freq.m = freq * 100000; 00222 iwr.u.freq.e = 1; 00223 00224 if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) { 00225 perror("ioctl[SIOCSIWFREQ]"); 00226 ret = -1; 00227 } 00228 00229 return ret; 00230 } 00231 00232 00233 static void 00234 wpa_driver_wext_event_wireless_custom(void *ctx, char *custom) 00235 { 00236 union wpa_event_data data; 00237 00238 wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'", 00239 custom); 00240 00241 os_memset(&data, 0, sizeof(data)); 00242 /* Host AP driver */ 00243 if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { 00244 data.michael_mic_failure.unicast = 00245 os_strstr(custom, " unicast ") != NULL; 00246 /* TODO: parse parameters(?) */ 00247 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); 00248 } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) { 00249 char *spos; 00250 int bytes; 00251 u8 *req_ies = NULL, *resp_ies = NULL; 00252 00253 spos = custom + 17; 00254 00255 bytes = strspn(spos, "0123456789abcdefABCDEF"); 00256 if (!bytes || (bytes & 1)) 00257 return; 00258 bytes /= 2; 00259 00260 req_ies = os_malloc(bytes); 00261 if (req_ies == NULL || 00262 hexstr2bin(spos, req_ies, bytes) < 0) 00263 goto done; 00264 data.assoc_info.req_ies = req_ies; 00265 data.assoc_info.req_ies_len = bytes; 00266 00267 spos += bytes * 2; 00268 00269 data.assoc_info.resp_ies = NULL; 00270 data.assoc_info.resp_ies_len = 0; 00271 00272 if (os_strncmp(spos, " RespIEs=", 9) == 0) { 00273 spos += 9; 00274 00275 bytes = strspn(spos, "0123456789abcdefABCDEF"); 00276 if (!bytes || (bytes & 1)) 00277 goto done; 00278 bytes /= 2; 00279 00280 resp_ies = os_malloc(bytes); 00281 if (resp_ies == NULL || 00282 hexstr2bin(spos, resp_ies, bytes) < 0) 00283 goto done; 00284 data.assoc_info.resp_ies = resp_ies; 00285 data.assoc_info.resp_ies_len = bytes; 00286 } 00287 00288 wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); 00289 00290 done: 00291 os_free(resp_ies); 00292 os_free(req_ies); 00293 #ifdef CONFIG_PEERKEY 00294 } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) { 00295 if (hwaddr_aton(custom + 17, data.stkstart.peer)) { 00296 wpa_printf(MSG_DEBUG, "WEXT: unrecognized " 00297 "STKSTART.request '%s'", custom + 17); 00298 return; 00299 } 00300 wpa_supplicant_event(ctx, EVENT_STKSTART, &data); 00301 #endif /* CONFIG_PEERKEY */ 00302 } 00303 } 00304 00305 00306 static int wpa_driver_wext_event_wireless_michaelmicfailure( 00307 void *ctx, const char *ev, size_t len) 00308 { 00309 const struct iw_michaelmicfailure *mic; 00310 union wpa_event_data data; 00311 00312 if (len < sizeof(*mic)) 00313 return -1; 00314 00315 mic = (const struct iw_michaelmicfailure *) ev; 00316 00317 wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: " 00318 "flags=0x%x src_addr=" MACSTR, mic->flags, 00319 MAC2STR(mic->src_addr.sa_data)); 00320 00321 os_memset(&data, 0, sizeof(data)); 00322 data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP); 00323 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); 00324 00325 return 0; 00326 } 00327 00328 00329 static int wpa_driver_wext_event_wireless_pmkidcand( 00330 struct wpa_driver_wext_data *drv, const char *ev, size_t len) 00331 { 00332 const struct iw_pmkid_cand *cand; 00333 union wpa_event_data data; 00334 const u8 *addr; 00335 00336 if (len < sizeof(*cand)) 00337 return -1; 00338 00339 cand = (const struct iw_pmkid_cand *) ev; 00340 addr = (const u8 *) cand->bssid.sa_data; 00341 00342 wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: " 00343 "flags=0x%x index=%d bssid=" MACSTR, cand->flags, 00344 cand->index, MAC2STR(addr)); 00345 00346 os_memset(&data, 0, sizeof(data)); 00347 os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN); 00348 data.pmkid_candidate.index = cand->index; 00349 data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH; 00350 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data); 00351 00352 return 0; 00353 } 00354 00355 00356 static int wpa_driver_wext_event_wireless_assocreqie( 00357 struct wpa_driver_wext_data *drv, const char *ev, int len) 00358 { 00359 if (len < 0) 00360 return -1; 00361 00362 wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev, 00363 len); 00364 os_free(drv->assoc_req_ies); 00365 drv->assoc_req_ies = os_malloc(len); 00366 if (drv->assoc_req_ies == NULL) { 00367 drv->assoc_req_ies_len = 0; 00368 return -1; 00369 } 00370 os_memcpy(drv->assoc_req_ies, ev, len); 00371 drv->assoc_req_ies_len = len; 00372 00373 return 0; 00374 } 00375 00376 00377 static int wpa_driver_wext_event_wireless_assocrespie( 00378 struct wpa_driver_wext_data *drv, const char *ev, int len) 00379 { 00380 if (len < 0) 00381 return -1; 00382 00383 wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev, 00384 len); 00385 os_free(drv->assoc_resp_ies); 00386 drv->assoc_resp_ies = os_malloc(len); 00387 if (drv->assoc_resp_ies == NULL) { 00388 drv->assoc_resp_ies_len = 0; 00389 return -1; 00390 } 00391 os_memcpy(drv->assoc_resp_ies, ev, len); 00392 drv->assoc_resp_ies_len = len; 00393 00394 return 0; 00395 } 00396 00397 00398 static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv) 00399 { 00400 union wpa_event_data data; 00401 00402 if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL) 00403 return; 00404 00405 os_memset(&data, 0, sizeof(data)); 00406 if (drv->assoc_req_ies) { 00407 data.assoc_info.req_ies = drv->assoc_req_ies; 00408 data.assoc_info.req_ies_len = drv->assoc_req_ies_len; 00409 } 00410 if (drv->assoc_resp_ies) { 00411 data.assoc_info.resp_ies = drv->assoc_resp_ies; 00412 data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len; 00413 } 00414 00415 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); 00416 00417 os_free(drv->assoc_req_ies); 00418 drv->assoc_req_ies = NULL; 00419 os_free(drv->assoc_resp_ies); 00420 drv->assoc_resp_ies = NULL; 00421 } 00422 00423 00424 static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv, 00425 char *data, int len) 00426 { 00427 struct iw_event iwe_buf, *iwe = &iwe_buf; 00428 char *pos, *end, *custom, *buf; 00429 00430 pos = data; 00431 end = data + len; 00432 00433 while (pos + IW_EV_LCP_LEN <= end) { 00434 /* Event data may be unaligned, so make a local, aligned copy 00435 * before processing. */ 00436 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); 00437 wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", 00438 iwe->cmd, iwe->len); 00439 if (iwe->len <= IW_EV_LCP_LEN) 00440 return; 00441 00442 custom = pos + IW_EV_POINT_LEN; 00443 if (drv->we_version_compiled > 18 && 00444 (iwe->cmd == IWEVMICHAELMICFAILURE || 00445 iwe->cmd == IWEVCUSTOM || 00446 iwe->cmd == IWEVASSOCREQIE || 00447 iwe->cmd == IWEVASSOCRESPIE || 00448 iwe->cmd == IWEVPMKIDCAND)) { 00449 /* WE-19 removed the pointer from struct iw_point */ 00450 char *dpos = (char *) &iwe_buf.u.data.length; 00451 int dlen = dpos - (char *) &iwe_buf; 00452 os_memcpy(dpos, pos + IW_EV_LCP_LEN, 00453 sizeof(struct iw_event) - dlen); 00454 } else { 00455 os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); 00456 custom += IW_EV_POINT_OFF; 00457 } 00458 00459 switch (iwe->cmd) { 00460 case SIOCGIWAP: 00461 wpa_printf(MSG_DEBUG, "Wireless event: new AP: " 00462 MACSTR, 00463 MAC2STR((u8 *) iwe->u.ap_addr.sa_data)); 00464 if (is_zero_ether_addr( 00465 (const u8 *) iwe->u.ap_addr.sa_data) || 00466 os_memcmp(iwe->u.ap_addr.sa_data, 00467 "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 00468 0) { 00469 os_free(drv->assoc_req_ies); 00470 drv->assoc_req_ies = NULL; 00471 os_free(drv->assoc_resp_ies); 00472 drv->assoc_resp_ies = NULL; 00473 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, 00474 NULL); 00475 00476 } else { 00477 wpa_driver_wext_event_assoc_ies(drv); 00478 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, 00479 NULL); 00480 } 00481 break; 00482 case IWEVMICHAELMICFAILURE: 00483 if (custom + iwe->u.data.length > end) { 00484 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 00485 "IWEVMICHAELMICFAILURE length"); 00486 return; 00487 } 00488 wpa_driver_wext_event_wireless_michaelmicfailure( 00489 drv->ctx, custom, iwe->u.data.length); 00490 break; 00491 case IWEVCUSTOM: 00492 if (custom + iwe->u.data.length > end) { 00493 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 00494 "IWEVCUSTOM length"); 00495 return; 00496 } 00497 buf = os_malloc(iwe->u.data.length + 1); 00498 if (buf == NULL) 00499 return; 00500 os_memcpy(buf, custom, iwe->u.data.length); 00501 buf[iwe->u.data.length] = '\0'; 00502 wpa_driver_wext_event_wireless_custom(drv->ctx, buf); 00503 os_free(buf); 00504 break; 00505 case SIOCGIWSCAN: 00506 drv->scan_complete_events = 1; 00507 eloop_cancel_timeout(wpa_driver_wext_scan_timeout, 00508 drv, drv->ctx); 00509 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, 00510 NULL); 00511 break; 00512 case IWEVASSOCREQIE: 00513 if (custom + iwe->u.data.length > end) { 00514 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 00515 "IWEVASSOCREQIE length"); 00516 return; 00517 } 00518 wpa_driver_wext_event_wireless_assocreqie( 00519 drv, custom, iwe->u.data.length); 00520 break; 00521 case IWEVASSOCRESPIE: 00522 if (custom + iwe->u.data.length > end) { 00523 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 00524 "IWEVASSOCRESPIE length"); 00525 return; 00526 } 00527 wpa_driver_wext_event_wireless_assocrespie( 00528 drv, custom, iwe->u.data.length); 00529 break; 00530 case IWEVPMKIDCAND: 00531 if (custom + iwe->u.data.length > end) { 00532 wpa_printf(MSG_DEBUG, "WEXT: Invalid " 00533 "IWEVPMKIDCAND length"); 00534 return; 00535 } 00536 wpa_driver_wext_event_wireless_pmkidcand( 00537 drv, custom, iwe->u.data.length); 00538 break; 00539 } 00540 00541 pos += iwe->len; 00542 } 00543 } 00544 00545 00546 static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv, 00547 char *buf, size_t len, int del) 00548 { 00549 union wpa_event_data event; 00550 00551 os_memset(&event, 0, sizeof(event)); 00552 if (len > sizeof(event.interface_status.ifname)) 00553 len = sizeof(event.interface_status.ifname) - 1; 00554 os_memcpy(event.interface_status.ifname, buf, len); 00555 event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED : 00556 EVENT_INTERFACE_ADDED; 00557 00558 wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s", 00559 del ? "DEL" : "NEW", 00560 event.interface_status.ifname, 00561 del ? "removed" : "added"); 00562 00563 if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { 00564 if (del) 00565 drv->if_removed = 1; 00566 else 00567 drv->if_removed = 0; 00568 } 00569 00570 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 00571 } 00572 00573 00574 static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv, 00575 u8 *buf, size_t len) 00576 { 00577 int attrlen, rta_len; 00578 struct rtattr *attr; 00579 00580 attrlen = len; 00581 attr = (struct rtattr *) buf; 00582 00583 rta_len = RTA_ALIGN(sizeof(struct rtattr)); 00584 while (RTA_OK(attr, attrlen)) { 00585 if (attr->rta_type == IFLA_IFNAME) { 00586 if (os_strcmp(((char *) attr) + rta_len, drv->ifname) 00587 == 0) 00588 return 1; 00589 else 00590 break; 00591 } 00592 attr = RTA_NEXT(attr, attrlen); 00593 } 00594 00595 return 0; 00596 } 00597 00598 00599 static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv, 00600 int ifindex, u8 *buf, size_t len) 00601 { 00602 if (drv->ifindex == ifindex || drv->ifindex2 == ifindex) 00603 return 1; 00604 00605 if (drv->if_removed && wpa_driver_wext_own_ifname(drv, buf, len)) { 00606 drv->ifindex = if_nametoindex(drv->ifname); 00607 wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed " 00608 "interface"); 00609 wpa_driver_wext_finish_drv_init(drv); 00610 return 1; 00611 } 00612 00613 return 0; 00614 } 00615 00616 00617 static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, 00618 u8 *buf, size_t len) 00619 { 00620 struct wpa_driver_wext_data *drv = ctx; 00621 int attrlen, rta_len; 00622 struct rtattr *attr; 00623 00624 if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) { 00625 wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", 00626 ifi->ifi_index); 00627 return; 00628 } 00629 00630 wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x " 00631 "(%s%s%s%s)", 00632 drv->operstate, ifi->ifi_flags, 00633 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", 00634 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", 00635 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", 00636 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); 00637 /* 00638 * Some drivers send the association event before the operup event--in 00639 * this case, lifting operstate in wpa_driver_wext_set_operstate() 00640 * fails. This will hit us when wpa_supplicant does not need to do 00641 * IEEE 802.1X authentication 00642 */ 00643 if (drv->operstate == 1 && 00644 (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && 00645 !(ifi->ifi_flags & IFF_RUNNING)) 00646 netlink_send_oper_ifla(drv->netlink, drv->ifindex, 00647 -1, IF_OPER_UP); 00648 00649 attrlen = len; 00650 attr = (struct rtattr *) buf; 00651 00652 rta_len = RTA_ALIGN(sizeof(struct rtattr)); 00653 while (RTA_OK(attr, attrlen)) { 00654 if (attr->rta_type == IFLA_WIRELESS) { 00655 wpa_driver_wext_event_wireless( 00656 drv, ((char *) attr) + rta_len, 00657 attr->rta_len - rta_len); 00658 } else if (attr->rta_type == IFLA_IFNAME) { 00659 wpa_driver_wext_event_link(drv, 00660 ((char *) attr) + rta_len, 00661 attr->rta_len - rta_len, 0); 00662 } 00663 attr = RTA_NEXT(attr, attrlen); 00664 } 00665 } 00666 00667 00668 static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi, 00669 u8 *buf, size_t len) 00670 { 00671 struct wpa_driver_wext_data *drv = ctx; 00672 int attrlen, rta_len; 00673 struct rtattr *attr; 00674 00675 attrlen = len; 00676 attr = (struct rtattr *) buf; 00677 00678 rta_len = RTA_ALIGN(sizeof(struct rtattr)); 00679 while (RTA_OK(attr, attrlen)) { 00680 if (attr->rta_type == IFLA_IFNAME) { 00681 wpa_driver_wext_event_link(drv, 00682 ((char *) attr) + rta_len, 00683 attr->rta_len - rta_len, 1); 00684 } 00685 attr = RTA_NEXT(attr, attrlen); 00686 } 00687 } 00688 00689 00697 void * wpa_driver_wext_init(void *ctx, const char *ifname) 00698 { 00699 struct wpa_driver_wext_data *drv; 00700 struct netlink_config *cfg; 00701 char path[128]; 00702 struct stat buf; 00703 00704 drv = os_zalloc(sizeof(*drv)); 00705 if (drv == NULL) 00706 return NULL; 00707 drv->ctx = ctx; 00708 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 00709 00710 os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname); 00711 if (stat(path, &buf) == 0) { 00712 wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected"); 00713 drv->cfg80211 = 1; 00714 } 00715 00716 drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); 00717 if (drv->ioctl_sock < 0) { 00718 perror("socket(PF_INET,SOCK_DGRAM)"); 00719 goto err1; 00720 } 00721 00722 cfg = os_zalloc(sizeof(*cfg)); 00723 if (cfg == NULL) 00724 goto err1; 00725 cfg->ctx = drv; 00726 cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink; 00727 cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink; 00728 drv->netlink = netlink_init(cfg); 00729 if (drv->netlink == NULL) { 00730 os_free(cfg); 00731 goto err2; 00732 } 00733 00734 drv->mlme_sock = -1; 00735 00736 if (wpa_driver_wext_finish_drv_init(drv) < 0) 00737 goto err3; 00738 00739 wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1); 00740 00741 return drv; 00742 00743 err3: 00744 netlink_deinit(drv->netlink); 00745 err2: 00746 close(drv->ioctl_sock); 00747 err1: 00748 os_free(drv); 00749 return NULL; 00750 } 00751 00752 00753 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) 00754 { 00755 if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) 00756 return -1; 00757 00758 /* 00759 * Make sure that the driver does not have any obsolete PMKID entries. 00760 */ 00761 wpa_driver_wext_flush_pmkid(drv); 00762 00763 if (wpa_driver_wext_set_mode(drv, 0) < 0) { 00764 wpa_printf(MSG_DEBUG, "Could not configure driver to use " 00765 "managed mode"); 00766 /* Try to use it anyway */ 00767 } 00768 00769 wpa_driver_wext_get_range(drv); 00770 00771 /* 00772 * Unlock the driver's BSSID and force to a random SSID to clear any 00773 * previous association the driver might have when the supplicant 00774 * starts up. 00775 */ 00776 wpa_driver_wext_disconnect(drv); 00777 00778 drv->ifindex = if_nametoindex(drv->ifname); 00779 00780 if (os_strncmp(drv->ifname, "wlan", 4) == 0) { 00781 /* 00782 * Host AP driver may use both wlan# and wifi# interface in 00783 * wireless events. Since some of the versions included WE-18 00784 * support, let's add the alternative ifindex also from 00785 * driver_wext.c for the time being. This may be removed at 00786 * some point once it is believed that old versions of the 00787 * driver are not in use anymore. 00788 */ 00789 char ifname2[IFNAMSIZ + 1]; 00790 os_strlcpy(ifname2, drv->ifname, sizeof(ifname2)); 00791 os_memcpy(ifname2, "wifi", 4); 00792 wpa_driver_wext_alternative_ifindex(drv, ifname2); 00793 } 00794 00795 netlink_send_oper_ifla(drv->netlink, drv->ifindex, 00796 1, IF_OPER_DORMANT); 00797 00798 return 0; 00799 } 00800 00801 00809 void wpa_driver_wext_deinit(void *priv) 00810 { 00811 struct wpa_driver_wext_data *drv = priv; 00812 00813 wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 0); 00814 00815 eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); 00816 00817 /* 00818 * Clear possibly configured driver parameters in order to make it 00819 * easier to use the driver after wpa_supplicant has been terminated. 00820 */ 00821 wpa_driver_wext_disconnect(drv); 00822 00823 netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP); 00824 netlink_deinit(drv->netlink); 00825 00826 if (drv->mlme_sock >= 0) 00827 eloop_unregister_read_sock(drv->mlme_sock); 00828 00829 (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); 00830 00831 close(drv->ioctl_sock); 00832 if (drv->mlme_sock >= 0) 00833 close(drv->mlme_sock); 00834 os_free(drv->assoc_req_ies); 00835 os_free(drv->assoc_resp_ies); 00836 os_free(drv); 00837 } 00838 00839 00848 void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx) 00849 { 00850 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); 00851 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 00852 } 00853 00854 00861 int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params) 00862 { 00863 struct wpa_driver_wext_data *drv = priv; 00864 struct iwreq iwr; 00865 int ret = 0, timeout; 00866 struct iw_scan_req req; 00867 const u8 *ssid = params->ssids[0].ssid; 00868 size_t ssid_len = params->ssids[0].ssid_len; 00869 00870 if (ssid_len > IW_ESSID_MAX_SIZE) { 00871 wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", 00872 __FUNCTION__, (unsigned long) ssid_len); 00873 return -1; 00874 } 00875 00876 os_memset(&iwr, 0, sizeof(iwr)); 00877 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 00878 00879 if (ssid && ssid_len) { 00880 os_memset(&req, 0, sizeof(req)); 00881 req.essid_len = ssid_len; 00882 req.bssid.sa_family = ARPHRD_ETHER; 00883 os_memset(req.bssid.sa_data, 0xff, ETH_ALEN); 00884 os_memcpy(req.essid, ssid, ssid_len); 00885 iwr.u.data.pointer = (caddr_t) &req; 00886 iwr.u.data.length = sizeof(req); 00887 iwr.u.data.flags = IW_SCAN_THIS_ESSID; 00888 } 00889 00890 if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) { 00891 perror("ioctl[SIOCSIWSCAN]"); 00892 ret = -1; 00893 } 00894 00895 /* Not all drivers generate "scan completed" wireless event, so try to 00896 * read results after a timeout. */ 00897 timeout = 5; 00898 if (drv->scan_complete_events) { 00899 /* 00900 * The driver seems to deliver SIOCGIWSCAN events to notify 00901 * when scan is complete, so use longer timeout to avoid race 00902 * conditions with scanning and following association request. 00903 */ 00904 timeout = 30; 00905 } 00906 wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " 00907 "seconds", ret, timeout); 00908 eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); 00909 eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv, 00910 drv->ctx); 00911 00912 return ret; 00913 } 00914 00915 00916 static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv, 00917 size_t *len) 00918 { 00919 struct iwreq iwr; 00920 u8 *res_buf; 00921 size_t res_buf_len; 00922 00923 res_buf_len = IW_SCAN_MAX_DATA; 00924 for (;;) { 00925 res_buf = os_malloc(res_buf_len); 00926 if (res_buf == NULL) 00927 return NULL; 00928 os_memset(&iwr, 0, sizeof(iwr)); 00929 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 00930 iwr.u.data.pointer = res_buf; 00931 iwr.u.data.length = res_buf_len; 00932 00933 if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0) 00934 break; 00935 00936 if (errno == E2BIG && res_buf_len < 65535) { 00937 os_free(res_buf); 00938 res_buf = NULL; 00939 res_buf_len *= 2; 00940 if (res_buf_len > 65535) 00941 res_buf_len = 65535; /* 16-bit length field */ 00942 wpa_printf(MSG_DEBUG, "Scan results did not fit - " 00943 "trying larger buffer (%lu bytes)", 00944 (unsigned long) res_buf_len); 00945 } else { 00946 perror("ioctl[SIOCGIWSCAN]"); 00947 os_free(res_buf); 00948 return NULL; 00949 } 00950 } 00951 00952 if (iwr.u.data.length > res_buf_len) { 00953 os_free(res_buf); 00954 return NULL; 00955 } 00956 *len = iwr.u.data.length; 00957 00958 return res_buf; 00959 } 00960 00961 00962 /* 00963 * Data structure for collecting WEXT scan results. This is needed to allow 00964 * the various methods of reporting IEs to be combined into a single IE buffer. 00965 */ 00966 struct wext_scan_data { 00967 struct wpa_scan_res res; 00968 u8 *ie; 00969 size_t ie_len; 00970 u8 ssid[32]; 00971 size_t ssid_len; 00972 int maxrate; 00973 }; 00974 00975 00976 static void wext_get_scan_mode(struct iw_event *iwe, 00977 struct wext_scan_data *res) 00978 { 00979 if (iwe->u.mode == IW_MODE_ADHOC) 00980 res->res.caps |= IEEE80211_CAP_IBSS; 00981 else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA) 00982 res->res.caps |= IEEE80211_CAP_ESS; 00983 } 00984 00985 00986 static void wext_get_scan_ssid(struct iw_event *iwe, 00987 struct wext_scan_data *res, char *custom, 00988 char *end) 00989 { 00990 int ssid_len = iwe->u.essid.length; 00991 if (custom + ssid_len > end) 00992 return; 00993 if (iwe->u.essid.flags && 00994 ssid_len > 0 && 00995 ssid_len <= IW_ESSID_MAX_SIZE) { 00996 os_memcpy(res->ssid, custom, ssid_len); 00997 res->ssid_len = ssid_len; 00998 } 00999 } 01000 01001 01002 static void wext_get_scan_freq(struct iw_event *iwe, 01003 struct wext_scan_data *res) 01004 { 01005 int divi = 1000000, i; 01006 01007 if (iwe->u.freq.e == 0) { 01008 /* 01009 * Some drivers do not report frequency, but a channel. 01010 * Try to map this to frequency by assuming they are using 01011 * IEEE 802.11b/g. But don't overwrite a previously parsed 01012 * frequency if the driver sends both frequency and channel, 01013 * since the driver may be sending an A-band channel that we 01014 * don't handle here. 01015 */ 01016 01017 if (res->res.freq) 01018 return; 01019 01020 if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) { 01021 res->res.freq = 2407 + 5 * iwe->u.freq.m; 01022 return; 01023 } else if (iwe->u.freq.m == 14) { 01024 res->res.freq = 2484; 01025 return; 01026 } 01027 } 01028 01029 if (iwe->u.freq.e > 6) { 01030 wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID=" 01031 MACSTR " m=%d e=%d)", 01032 MAC2STR(res->res.bssid), iwe->u.freq.m, 01033 iwe->u.freq.e); 01034 return; 01035 } 01036 01037 for (i = 0; i < iwe->u.freq.e; i++) 01038 divi /= 10; 01039 res->res.freq = iwe->u.freq.m / divi; 01040 } 01041 01042 01043 static void wext_get_scan_qual(struct iw_event *iwe, 01044 struct wext_scan_data *res) 01045 { 01046 res->res.qual = iwe->u.qual.qual; 01047 res->res.noise = iwe->u.qual.noise; 01048 res->res.level = iwe->u.qual.level; 01049 if (iwe->u.qual.updated & IW_QUAL_QUAL_INVALID) 01050 res->res.flags |= WPA_SCAN_QUAL_INVALID; 01051 if (iwe->u.qual.updated & IW_QUAL_LEVEL_INVALID) 01052 res->res.flags |= WPA_SCAN_LEVEL_INVALID; 01053 if (iwe->u.qual.updated & IW_QUAL_NOISE_INVALID) 01054 res->res.flags |= WPA_SCAN_NOISE_INVALID; 01055 if (iwe->u.qual.updated & IW_QUAL_DBM) 01056 res->res.flags |= WPA_SCAN_LEVEL_DBM; 01057 } 01058 01059 01060 static void wext_get_scan_encode(struct iw_event *iwe, 01061 struct wext_scan_data *res) 01062 { 01063 if (!(iwe->u.data.flags & IW_ENCODE_DISABLED)) 01064 res->res.caps |= IEEE80211_CAP_PRIVACY; 01065 } 01066 01067 01068 static void wext_get_scan_rate(struct iw_event *iwe, 01069 struct wext_scan_data *res, char *pos, 01070 char *end) 01071 { 01072 int maxrate; 01073 char *custom = pos + IW_EV_LCP_LEN; 01074 struct iw_param p; 01075 size_t clen; 01076 01077 clen = iwe->len; 01078 if (custom + clen > end) 01079 return; 01080 maxrate = 0; 01081 while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) { 01082 /* Note: may be misaligned, make a local, aligned copy */ 01083 os_memcpy(&p, custom, sizeof(struct iw_param)); 01084 if (p.value > maxrate) 01085 maxrate = p.value; 01086 clen -= sizeof(struct iw_param); 01087 custom += sizeof(struct iw_param); 01088 } 01089 01090 /* Convert the maxrate from WE-style (b/s units) to 01091 * 802.11 rates (500000 b/s units). 01092 */ 01093 res->maxrate = maxrate / 500000; 01094 } 01095 01096 01097 static void wext_get_scan_iwevgenie(struct iw_event *iwe, 01098 struct wext_scan_data *res, char *custom, 01099 char *end) 01100 { 01101 char *genie, *gpos, *gend; 01102 u8 *tmp; 01103 01104 if (iwe->u.data.length == 0) 01105 return; 01106 01107 gpos = genie = custom; 01108 gend = genie + iwe->u.data.length; 01109 if (gend > end) { 01110 wpa_printf(MSG_INFO, "IWEVGENIE overflow"); 01111 return; 01112 } 01113 01114 tmp = os_realloc(res->ie, res->ie_len + gend - gpos); 01115 if (tmp == NULL) 01116 return; 01117 os_memcpy(tmp + res->ie_len, gpos, gend - gpos); 01118 res->ie = tmp; 01119 res->ie_len += gend - gpos; 01120 } 01121 01122 01123 static void wext_get_scan_custom(struct iw_event *iwe, 01124 struct wext_scan_data *res, char *custom, 01125 char *end) 01126 { 01127 size_t clen; 01128 u8 *tmp; 01129 01130 clen = iwe->u.data.length; 01131 if (custom + clen > end) 01132 return; 01133 01134 if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) { 01135 char *spos; 01136 int bytes; 01137 spos = custom + 7; 01138 bytes = custom + clen - spos; 01139 if (bytes & 1 || bytes == 0) 01140 return; 01141 bytes /= 2; 01142 tmp = os_realloc(res->ie, res->ie_len + bytes); 01143 if (tmp == NULL) 01144 return; 01145 res->ie = tmp; 01146 if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0) 01147 return; 01148 res->ie_len += bytes; 01149 } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) { 01150 char *spos; 01151 int bytes; 01152 spos = custom + 7; 01153 bytes = custom + clen - spos; 01154 if (bytes & 1 || bytes == 0) 01155 return; 01156 bytes /= 2; 01157 tmp = os_realloc(res->ie, res->ie_len + bytes); 01158 if (tmp == NULL) 01159 return; 01160 res->ie = tmp; 01161 if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0) 01162 return; 01163 res->ie_len += bytes; 01164 } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) { 01165 char *spos; 01166 int bytes; 01167 u8 bin[8]; 01168 spos = custom + 4; 01169 bytes = custom + clen - spos; 01170 if (bytes != 16) { 01171 wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes); 01172 return; 01173 } 01174 bytes /= 2; 01175 if (hexstr2bin(spos, bin, bytes) < 0) { 01176 wpa_printf(MSG_DEBUG, "WEXT: Invalid TSF value"); 01177 return; 01178 } 01179 res->res.tsf += WPA_GET_BE64(bin); 01180 } 01181 } 01182 01183 01184 static int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd) 01185 { 01186 return drv->we_version_compiled > 18 && 01187 (cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE || 01188 cmd == IWEVGENIE || cmd == IWEVCUSTOM); 01189 } 01190 01191 01192 static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res, 01193 struct wext_scan_data *data) 01194 { 01195 struct wpa_scan_res **tmp; 01196 struct wpa_scan_res *r; 01197 size_t extra_len; 01198 u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL; 01199 01200 /* Figure out whether we need to fake any IEs */ 01201 pos = data->ie; 01202 end = pos + data->ie_len; 01203 while (pos && pos + 1 < end) { 01204 if (pos + 2 + pos[1] > end) 01205 break; 01206 if (pos[0] == WLAN_EID_SSID) 01207 ssid_ie = pos; 01208 else if (pos[0] == WLAN_EID_SUPP_RATES) 01209 rate_ie = pos; 01210 else if (pos[0] == WLAN_EID_EXT_SUPP_RATES) 01211 rate_ie = pos; 01212 pos += 2 + pos[1]; 01213 } 01214 01215 extra_len = 0; 01216 if (ssid_ie == NULL) 01217 extra_len += 2 + data->ssid_len; 01218 if (rate_ie == NULL && data->maxrate) 01219 extra_len += 3; 01220 01221 r = os_zalloc(sizeof(*r) + extra_len + data->ie_len); 01222 if (r == NULL) 01223 return; 01224 os_memcpy(r, &data->res, sizeof(*r)); 01225 r->ie_len = extra_len + data->ie_len; 01226 pos = (u8 *) (r + 1); 01227 if (ssid_ie == NULL) { 01228 /* 01229 * Generate a fake SSID IE since the driver did not report 01230 * a full IE list. 01231 */ 01232 *pos++ = WLAN_EID_SSID; 01233 *pos++ = data->ssid_len; 01234 os_memcpy(pos, data->ssid, data->ssid_len); 01235 pos += data->ssid_len; 01236 } 01237 if (rate_ie == NULL && data->maxrate) { 01238 /* 01239 * Generate a fake Supported Rates IE since the driver did not 01240 * report a full IE list. 01241 */ 01242 *pos++ = WLAN_EID_SUPP_RATES; 01243 *pos++ = 1; 01244 *pos++ = data->maxrate; 01245 } 01246 if (data->ie) 01247 os_memcpy(pos, data->ie, data->ie_len); 01248 01249 tmp = os_realloc(res->res, 01250 (res->num + 1) * sizeof(struct wpa_scan_res *)); 01251 if (tmp == NULL) { 01252 os_free(r); 01253 return; 01254 } 01255 tmp[res->num++] = r; 01256 res->res = tmp; 01257 } 01258 01259 01265 struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv) 01266 { 01267 struct wpa_driver_wext_data *drv = priv; 01268 size_t ap_num = 0, len; 01269 int first; 01270 u8 *res_buf; 01271 struct iw_event iwe_buf, *iwe = &iwe_buf; 01272 char *pos, *end, *custom; 01273 struct wpa_scan_results *res; 01274 struct wext_scan_data data; 01275 01276 res_buf = wpa_driver_wext_giwscan(drv, &len); 01277 if (res_buf == NULL) 01278 return NULL; 01279 01280 ap_num = 0; 01281 first = 1; 01282 01283 res = os_zalloc(sizeof(*res)); 01284 if (res == NULL) { 01285 os_free(res_buf); 01286 return NULL; 01287 } 01288 01289 pos = (char *) res_buf; 01290 end = (char *) res_buf + len; 01291 os_memset(&data, 0, sizeof(data)); 01292 01293 while (pos + IW_EV_LCP_LEN <= end) { 01294 /* Event data may be unaligned, so make a local, aligned copy 01295 * before processing. */ 01296 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); 01297 if (iwe->len <= IW_EV_LCP_LEN) 01298 break; 01299 01300 custom = pos + IW_EV_POINT_LEN; 01301 if (wext_19_iw_point(drv, iwe->cmd)) { 01302 /* WE-19 removed the pointer from struct iw_point */ 01303 char *dpos = (char *) &iwe_buf.u.data.length; 01304 int dlen = dpos - (char *) &iwe_buf; 01305 os_memcpy(dpos, pos + IW_EV_LCP_LEN, 01306 sizeof(struct iw_event) - dlen); 01307 } else { 01308 os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); 01309 custom += IW_EV_POINT_OFF; 01310 } 01311 01312 switch (iwe->cmd) { 01313 case SIOCGIWAP: 01314 if (!first) 01315 wpa_driver_wext_add_scan_entry(res, &data); 01316 first = 0; 01317 os_free(data.ie); 01318 os_memset(&data, 0, sizeof(data)); 01319 os_memcpy(data.res.bssid, 01320 iwe->u.ap_addr.sa_data, ETH_ALEN); 01321 break; 01322 case SIOCGIWMODE: 01323 wext_get_scan_mode(iwe, &data); 01324 break; 01325 case SIOCGIWESSID: 01326 wext_get_scan_ssid(iwe, &data, custom, end); 01327 break; 01328 case SIOCGIWFREQ: 01329 wext_get_scan_freq(iwe, &data); 01330 break; 01331 case IWEVQUAL: 01332 wext_get_scan_qual(iwe, &data); 01333 break; 01334 case SIOCGIWENCODE: 01335 wext_get_scan_encode(iwe, &data); 01336 break; 01337 case SIOCGIWRATE: 01338 wext_get_scan_rate(iwe, &data, pos, end); 01339 break; 01340 case IWEVGENIE: 01341 wext_get_scan_iwevgenie(iwe, &data, custom, end); 01342 break; 01343 case IWEVCUSTOM: 01344 wext_get_scan_custom(iwe, &data, custom, end); 01345 break; 01346 } 01347 01348 pos += iwe->len; 01349 } 01350 os_free(res_buf); 01351 res_buf = NULL; 01352 if (!first) 01353 wpa_driver_wext_add_scan_entry(res, &data); 01354 os_free(data.ie); 01355 01356 wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)", 01357 (unsigned long) len, (unsigned long) res->num); 01358 01359 return res; 01360 } 01361 01362 01363 static int wpa_driver_wext_get_range(void *priv) 01364 { 01365 struct wpa_driver_wext_data *drv = priv; 01366 struct iw_range *range; 01367 struct iwreq iwr; 01368 int minlen; 01369 size_t buflen; 01370 01371 /* 01372 * Use larger buffer than struct iw_range in order to allow the 01373 * structure to grow in the future. 01374 */ 01375 buflen = sizeof(struct iw_range) + 500; 01376 range = os_zalloc(buflen); 01377 if (range == NULL) 01378 return -1; 01379 01380 os_memset(&iwr, 0, sizeof(iwr)); 01381 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 01382 iwr.u.data.pointer = (caddr_t) range; 01383 iwr.u.data.length = buflen; 01384 01385 minlen = ((char *) &range->enc_capa) - (char *) range + 01386 sizeof(range->enc_capa); 01387 01388 if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { 01389 perror("ioctl[SIOCGIWRANGE]"); 01390 os_free(range); 01391 return -1; 01392 } else if (iwr.u.data.length >= minlen && 01393 range->we_version_compiled >= 18) { 01394 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " 01395 "WE(source)=%d enc_capa=0x%x", 01396 range->we_version_compiled, 01397 range->we_version_source, 01398 range->enc_capa); 01399 drv->has_capability = 1; 01400 drv->we_version_compiled = range->we_version_compiled; 01401 if (range->enc_capa & IW_ENC_CAPA_WPA) { 01402 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | 01403 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 01404 } 01405 if (range->enc_capa & IW_ENC_CAPA_WPA2) { 01406 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 01407 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 01408 } 01409 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 01410 WPA_DRIVER_CAPA_ENC_WEP104; 01411 if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) 01412 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 01413 if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) 01414 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 01415 if (range->enc_capa & IW_ENC_CAPA_4WAY_HANDSHAKE) 01416 drv->capa.flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; 01417 drv->capa.auth = WPA_DRIVER_AUTH_OPEN | 01418 WPA_DRIVER_AUTH_SHARED | 01419 WPA_DRIVER_AUTH_LEAP; 01420 drv->capa.max_scan_ssids = 1; 01421 01422 wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x " 01423 "flags 0x%x", 01424 drv->capa.key_mgmt, drv->capa.enc, drv->capa.flags); 01425 } else { 01426 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - " 01427 "assuming WPA is not supported"); 01428 } 01429 01430 os_free(range); 01431 return 0; 01432 } 01433 01434 01435 static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv, 01436 const u8 *psk) 01437 { 01438 struct iw_encode_ext *ext; 01439 struct iwreq iwr; 01440 int ret; 01441 01442 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 01443 01444 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) 01445 return 0; 01446 01447 if (!psk) 01448 return 0; 01449 01450 os_memset(&iwr, 0, sizeof(iwr)); 01451 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 01452 01453 ext = os_zalloc(sizeof(*ext) + PMK_LEN); 01454 if (ext == NULL) 01455 return -1; 01456 01457 iwr.u.encoding.pointer = (caddr_t) ext; 01458 iwr.u.encoding.length = sizeof(*ext) + PMK_LEN; 01459 ext->key_len = PMK_LEN; 01460 os_memcpy(&ext->key, psk, ext->key_len); 01461 ext->alg = IW_ENCODE_ALG_PMK; 01462 01463 ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr); 01464 if (ret < 0) 01465 perror("ioctl[SIOCSIWENCODEEXT] PMK"); 01466 os_free(ext); 01467 01468 return ret; 01469 } 01470 01471 01472 static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg, 01473 const u8 *addr, int key_idx, 01474 int set_tx, const u8 *seq, 01475 size_t seq_len, 01476 const u8 *key, size_t key_len) 01477 { 01478 struct wpa_driver_wext_data *drv = priv; 01479 struct iwreq iwr; 01480 int ret = 0; 01481 struct iw_encode_ext *ext; 01482 01483 if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) { 01484 wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu", 01485 __FUNCTION__, (unsigned long) seq_len); 01486 return -1; 01487 } 01488 01489 ext = os_zalloc(sizeof(*ext) + key_len); 01490 if (ext == NULL) 01491 return -1; 01492 os_memset(&iwr, 0, sizeof(iwr)); 01493 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 01494 iwr.u.encoding.flags = key_idx + 1; 01495 iwr.u.encoding.flags |= IW_ENCODE_TEMP; 01496 if (alg == WPA_ALG_NONE) 01497 iwr.u.encoding.flags |= IW_ENCODE_DISABLED; 01498 iwr.u.encoding.pointer = (caddr_t) ext; 01499 iwr.u.encoding.length = sizeof(*ext) + key_len; 01500 01501 if (addr == NULL || 01502 os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) 01503 ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY; 01504 if (set_tx) 01505 ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY; 01506 01507 ext->addr.sa_family = ARPHRD_ETHER; 01508 if (addr) 01509 os_memcpy(ext->addr.sa_data, addr, ETH_ALEN); 01510 else 01511 os_memset(ext->addr.sa_data, 0xff, ETH_ALEN); 01512 if (key && key_len) { 01513 os_memcpy(ext + 1, key, key_len); 01514 ext->key_len = key_len; 01515 } 01516 switch (alg) { 01517 case WPA_ALG_NONE: 01518 ext->alg = IW_ENCODE_ALG_NONE; 01519 break; 01520 case WPA_ALG_WEP: 01521 ext->alg = IW_ENCODE_ALG_WEP; 01522 break; 01523 case WPA_ALG_TKIP: 01524 ext->alg = IW_ENCODE_ALG_TKIP; 01525 break; 01526 case WPA_ALG_CCMP: 01527 ext->alg = IW_ENCODE_ALG_CCMP; 01528 break; 01529 case WPA_ALG_PMK: 01530 ext->alg = IW_ENCODE_ALG_PMK; 01531 break; 01532 #ifdef CONFIG_IEEE80211W 01533 case WPA_ALG_IGTK: 01534 ext->alg = IW_ENCODE_ALG_AES_CMAC; 01535 break; 01536 #endif /* CONFIG_IEEE80211W */ 01537 default: 01538 wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d", 01539 __FUNCTION__, alg); 01540 os_free(ext); 01541 return -1; 01542 } 01543 01544 if (seq && seq_len) { 01545 ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID; 01546 os_memcpy(ext->rx_seq, seq, seq_len); 01547 } 01548 01549 if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) { 01550 ret = errno == EOPNOTSUPP ? -2 : -1; 01551 if (errno == ENODEV) { 01552 /* 01553 * ndiswrapper seems to be returning incorrect error 01554 * code.. */ 01555 ret = -2; 01556 } 01557 01558 perror("ioctl[SIOCSIWENCODEEXT]"); 01559 } 01560 01561 os_free(ext); 01562 return ret; 01563 } 01564 01565 01592 int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg, 01593 const u8 *addr, int key_idx, 01594 int set_tx, const u8 *seq, size_t seq_len, 01595 const u8 *key, size_t key_len) 01596 { 01597 struct wpa_driver_wext_data *drv = priv; 01598 struct iwreq iwr; 01599 int ret = 0; 01600 01601 wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu " 01602 "key_len=%lu", 01603 __FUNCTION__, alg, key_idx, set_tx, 01604 (unsigned long) seq_len, (unsigned long) key_len); 01605 01606 ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx, 01607 seq, seq_len, key, key_len); 01608 if (ret == 0) 01609 return 0; 01610 01611 if (ret == -2 && 01612 (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) { 01613 wpa_printf(MSG_DEBUG, "Driver did not support " 01614 "SIOCSIWENCODEEXT, trying SIOCSIWENCODE"); 01615 ret = 0; 01616 } else { 01617 wpa_printf(MSG_DEBUG, "Driver did not support " 01618 "SIOCSIWENCODEEXT"); 01619 return ret; 01620 } 01621 01622 os_memset(&iwr, 0, sizeof(iwr)); 01623 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 01624 iwr.u.encoding.flags = key_idx + 1; 01625 iwr.u.encoding.flags |= IW_ENCODE_TEMP; 01626 if (alg == WPA_ALG_NONE) 01627 iwr.u.encoding.flags |= IW_ENCODE_DISABLED; 01628 iwr.u.encoding.pointer = (caddr_t) key; 01629 iwr.u.encoding.length = key_len; 01630 01631 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 01632 perror("ioctl[SIOCSIWENCODE]"); 01633 ret = -1; 01634 } 01635 01636 if (set_tx && alg != WPA_ALG_NONE) { 01637 os_memset(&iwr, 0, sizeof(iwr)); 01638 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 01639 iwr.u.encoding.flags = key_idx + 1; 01640 iwr.u.encoding.flags |= IW_ENCODE_TEMP; 01641 iwr.u.encoding.pointer = (caddr_t) NULL; 01642 iwr.u.encoding.length = 0; 01643 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 01644 perror("ioctl[SIOCSIWENCODE] (set_tx)"); 01645 ret = -1; 01646 } 01647 } 01648 01649 return ret; 01650 } 01651 01652 01653 static int wpa_driver_wext_set_countermeasures(void *priv, 01654 int enabled) 01655 { 01656 struct wpa_driver_wext_data *drv = priv; 01657 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 01658 return wpa_driver_wext_set_auth_param(drv, 01659 IW_AUTH_TKIP_COUNTERMEASURES, 01660 enabled); 01661 } 01662 01663 01664 static int wpa_driver_wext_set_drop_unencrypted(void *priv, 01665 int enabled) 01666 { 01667 struct wpa_driver_wext_data *drv = priv; 01668 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 01669 drv->use_crypt = enabled; 01670 return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED, 01671 enabled); 01672 } 01673 01674 01675 static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv, 01676 const u8 *addr, int cmd, int reason_code) 01677 { 01678 struct iwreq iwr; 01679 struct iw_mlme mlme; 01680 int ret = 0; 01681 01682 os_memset(&iwr, 0, sizeof(iwr)); 01683 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 01684 os_memset(&mlme, 0, sizeof(mlme)); 01685 mlme.cmd = cmd; 01686 mlme.reason_code = reason_code; 01687 mlme.addr.sa_family = ARPHRD_ETHER; 01688 os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN); 01689 iwr.u.data.pointer = (caddr_t) &mlme; 01690 iwr.u.data.length = sizeof(mlme); 01691 01692 if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) { 01693 perror("ioctl[SIOCSIWMLME]"); 01694 ret = -1; 01695 } 01696 01697 return ret; 01698 } 01699 01700 01701 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv) 01702 { 01703 struct iwreq iwr; 01704 const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; 01705 u8 ssid[32]; 01706 int i; 01707 01708 /* 01709 * Only force-disconnect when the card is in infrastructure mode, 01710 * otherwise the driver might interpret the cleared BSSID and random 01711 * SSID as an attempt to create a new ad-hoc network. 01712 */ 01713 os_memset(&iwr, 0, sizeof(iwr)); 01714 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 01715 if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { 01716 perror("ioctl[SIOCGIWMODE]"); 01717 iwr.u.mode = IW_MODE_INFRA; 01718 } 01719 01720 if (iwr.u.mode == IW_MODE_INFRA) { 01721 if (drv->cfg80211) { 01722 /* 01723 * cfg80211 supports SIOCSIWMLME commands, so there is 01724 * no need for the random SSID hack, but clear the 01725 * BSSID and SSID. 01726 */ 01727 if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 || 01728 wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) { 01729 wpa_printf(MSG_DEBUG, "WEXT: Failed to clear " 01730 "to disconnect"); 01731 } 01732 return; 01733 } 01734 /* 01735 * Clear the BSSID selection and set a random SSID to make sure 01736 * the driver will not be trying to associate with something 01737 * even if it does not understand SIOCSIWMLME commands (or 01738 * tries to associate automatically after deauth/disassoc). 01739 */ 01740 for (i = 0; i < 32; i++) 01741 ssid[i] = rand() & 0xFF; 01742 if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 || 01743 wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) { 01744 wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus " 01745 "BSSID/SSID to disconnect"); 01746 } 01747 } 01748 } 01749 01750 01751 static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr, 01752 int reason_code) 01753 { 01754 struct wpa_driver_wext_data *drv = priv; 01755 int ret; 01756 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 01757 ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code); 01758 wpa_driver_wext_disconnect(drv); 01759 return ret; 01760 } 01761 01762 01763 static int wpa_driver_wext_disassociate(void *priv, const u8 *addr, 01764 int reason_code) 01765 { 01766 struct wpa_driver_wext_data *drv = priv; 01767 int ret; 01768 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 01769 ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DISASSOC, reason_code); 01770 wpa_driver_wext_disconnect(drv); 01771 return ret; 01772 } 01773 01774 01775 static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie, 01776 size_t ie_len) 01777 { 01778 struct wpa_driver_wext_data *drv = priv; 01779 struct iwreq iwr; 01780 int ret = 0; 01781 01782 os_memset(&iwr, 0, sizeof(iwr)); 01783 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 01784 iwr.u.data.pointer = (caddr_t) ie; 01785 iwr.u.data.length = ie_len; 01786 01787 if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { 01788 perror("ioctl[SIOCSIWGENIE]"); 01789 ret = -1; 01790 } 01791 01792 return ret; 01793 } 01794 01795 01796 int wpa_driver_wext_cipher2wext(int cipher) 01797 { 01798 switch (cipher) { 01799 case CIPHER_NONE: 01800 return IW_AUTH_CIPHER_NONE; 01801 case CIPHER_WEP40: 01802 return IW_AUTH_CIPHER_WEP40; 01803 case CIPHER_TKIP: 01804 return IW_AUTH_CIPHER_TKIP; 01805 case CIPHER_CCMP: 01806 return IW_AUTH_CIPHER_CCMP; 01807 case CIPHER_WEP104: 01808 return IW_AUTH_CIPHER_WEP104; 01809 default: 01810 return 0; 01811 } 01812 } 01813 01814 01815 int wpa_driver_wext_keymgmt2wext(int keymgmt) 01816 { 01817 switch (keymgmt) { 01818 case KEY_MGMT_802_1X: 01819 case KEY_MGMT_802_1X_NO_WPA: 01820 return IW_AUTH_KEY_MGMT_802_1X; 01821 case KEY_MGMT_PSK: 01822 return IW_AUTH_KEY_MGMT_PSK; 01823 default: 01824 return 0; 01825 } 01826 } 01827 01828 01829 static int 01830 wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv, 01831 struct wpa_driver_associate_params *params) 01832 { 01833 struct iwreq iwr; 01834 int ret = 0; 01835 01836 wpa_printf(MSG_DEBUG, "WEXT: Driver did not support " 01837 "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE"); 01838 01839 os_memset(&iwr, 0, sizeof(iwr)); 01840 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 01841 /* Just changing mode, not actual keys */ 01842 iwr.u.encoding.flags = 0; 01843 iwr.u.encoding.pointer = (caddr_t) NULL; 01844 iwr.u.encoding.length = 0; 01845 01846 /* 01847 * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two 01848 * different things. Here they are used to indicate Open System vs. 01849 * Shared Key authentication algorithm. However, some drivers may use 01850 * them to select between open/restricted WEP encrypted (open = allow 01851 * both unencrypted and encrypted frames; restricted = only allow 01852 * encrypted frames). 01853 */ 01854 01855 if (!drv->use_crypt) { 01856 iwr.u.encoding.flags |= IW_ENCODE_DISABLED; 01857 } else { 01858 if (params->auth_alg & WPA_AUTH_ALG_OPEN) 01859 iwr.u.encoding.flags |= IW_ENCODE_OPEN; 01860 if (params->auth_alg & WPA_AUTH_ALG_SHARED) 01861 iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED; 01862 } 01863 01864 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 01865 perror("ioctl[SIOCSIWENCODE]"); 01866 ret = -1; 01867 } 01868 01869 return ret; 01870 } 01871 01872 01873 int wpa_driver_wext_associate(void *priv, 01874 struct wpa_driver_associate_params *params) 01875 { 01876 struct wpa_driver_wext_data *drv = priv; 01877 int ret = 0; 01878 int allow_unencrypted_eapol; 01879 int value; 01880 01881 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 01882 01883 if (drv->cfg80211) { 01884 /* 01885 * Stop cfg80211 from trying to associate before we are done 01886 * with all parameters. 01887 */ 01888 wpa_driver_wext_set_ssid(drv, (u8 *) "", 0); 01889 } 01890 01891 if (wpa_driver_wext_set_drop_unencrypted(drv, params->drop_unencrypted) 01892 < 0) 01893 ret = -1; 01894 if (wpa_driver_wext_set_auth_alg(drv, params->auth_alg) < 0) 01895 ret = -1; 01896 if (wpa_driver_wext_set_mode(drv, params->mode) < 0) 01897 ret = -1; 01898 01899 /* 01900 * If the driver did not support SIOCSIWAUTH, fallback to 01901 * SIOCSIWENCODE here. 01902 */ 01903 if (drv->auth_alg_fallback && 01904 wpa_driver_wext_auth_alg_fallback(drv, params) < 0) 01905 ret = -1; 01906 01907 if (!params->bssid && 01908 wpa_driver_wext_set_bssid(drv, NULL) < 0) 01909 ret = -1; 01910 01911 /* TODO: should consider getting wpa version and cipher/key_mgmt suites 01912 * from configuration, not from here, where only the selected suite is 01913 * available */ 01914 if (wpa_driver_wext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len) 01915 < 0) 01916 ret = -1; 01917 if (params->wpa_ie == NULL || params->wpa_ie_len == 0) 01918 value = IW_AUTH_WPA_VERSION_DISABLED; 01919 else if (params->wpa_ie[0] == WLAN_EID_RSN) 01920 value = IW_AUTH_WPA_VERSION_WPA2; 01921 else 01922 value = IW_AUTH_WPA_VERSION_WPA; 01923 if (wpa_driver_wext_set_auth_param(drv, 01924 IW_AUTH_WPA_VERSION, value) < 0) 01925 ret = -1; 01926 value = wpa_driver_wext_cipher2wext(params->pairwise_suite); 01927 if (wpa_driver_wext_set_auth_param(drv, 01928 IW_AUTH_CIPHER_PAIRWISE, value) < 0) 01929 ret = -1; 01930 value = wpa_driver_wext_cipher2wext(params->group_suite); 01931 if (wpa_driver_wext_set_auth_param(drv, 01932 IW_AUTH_CIPHER_GROUP, value) < 0) 01933 ret = -1; 01934 value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); 01935 if (wpa_driver_wext_set_auth_param(drv, 01936 IW_AUTH_KEY_MGMT, value) < 0) 01937 ret = -1; 01938 value = params->key_mgmt_suite != KEY_MGMT_NONE || 01939 params->pairwise_suite != CIPHER_NONE || 01940 params->group_suite != CIPHER_NONE || 01941 params->wpa_ie_len; 01942 if (wpa_driver_wext_set_auth_param(drv, 01943 IW_AUTH_PRIVACY_INVOKED, value) < 0) 01944 ret = -1; 01945 01946 /* Allow unencrypted EAPOL messages even if pairwise keys are set when 01947 * not using WPA. IEEE 802.1X specifies that these frames are not 01948 * encrypted, but WPA encrypts them when pairwise keys are in use. */ 01949 if (params->key_mgmt_suite == KEY_MGMT_802_1X || 01950 params->key_mgmt_suite == KEY_MGMT_PSK) 01951 allow_unencrypted_eapol = 0; 01952 else 01953 allow_unencrypted_eapol = 1; 01954 01955 if (wpa_driver_wext_set_psk(drv, params->psk) < 0) 01956 ret = -1; 01957 if (wpa_driver_wext_set_auth_param(drv, 01958 IW_AUTH_RX_UNENCRYPTED_EAPOL, 01959 allow_unencrypted_eapol) < 0) 01960 ret = -1; 01961 #ifdef CONFIG_IEEE80211W 01962 switch (params->mgmt_frame_protection) { 01963 case NO_MGMT_FRAME_PROTECTION: 01964 value = IW_AUTH_MFP_DISABLED; 01965 break; 01966 case MGMT_FRAME_PROTECTION_OPTIONAL: 01967 value = IW_AUTH_MFP_OPTIONAL; 01968 break; 01969 case MGMT_FRAME_PROTECTION_REQUIRED: 01970 value = IW_AUTH_MFP_REQUIRED; 01971 break; 01972 }; 01973 if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0) 01974 ret = -1; 01975 #endif /* CONFIG_IEEE80211W */ 01976 if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0) 01977 ret = -1; 01978 if (!drv->cfg80211 && 01979 wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) 01980 ret = -1; 01981 if (params->bssid && 01982 wpa_driver_wext_set_bssid(drv, params->bssid) < 0) 01983 ret = -1; 01984 if (drv->cfg80211 && 01985 wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) 01986 ret = -1; 01987 01988 return ret; 01989 } 01990 01991 01992 static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg) 01993 { 01994 struct wpa_driver_wext_data *drv = priv; 01995 int algs = 0, res; 01996 01997 if (auth_alg & WPA_AUTH_ALG_OPEN) 01998 algs |= IW_AUTH_ALG_OPEN_SYSTEM; 01999 if (auth_alg & WPA_AUTH_ALG_SHARED) 02000 algs |= IW_AUTH_ALG_SHARED_KEY; 02001 if (auth_alg & WPA_AUTH_ALG_LEAP) 02002 algs |= IW_AUTH_ALG_LEAP; 02003 if (algs == 0) { 02004 /* at least one algorithm should be set */ 02005 algs = IW_AUTH_ALG_OPEN_SYSTEM; 02006 } 02007 02008 res = wpa_driver_wext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG, 02009 algs); 02010 drv->auth_alg_fallback = res == -2; 02011 return res; 02012 } 02013 02014 02021 int wpa_driver_wext_set_mode(void *priv, int mode) 02022 { 02023 struct wpa_driver_wext_data *drv = priv; 02024 struct iwreq iwr; 02025 int ret = -1; 02026 unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA; 02027 02028 os_memset(&iwr, 0, sizeof(iwr)); 02029 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 02030 iwr.u.mode = new_mode; 02031 if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) { 02032 ret = 0; 02033 goto done; 02034 } 02035 02036 if (errno != EBUSY) { 02037 perror("ioctl[SIOCSIWMODE]"); 02038 goto done; 02039 } 02040 02041 /* mac80211 doesn't allow mode changes while the device is up, so if 02042 * the device isn't in the mode we're about to change to, take device 02043 * down, try to set the mode again, and bring it back up. 02044 */ 02045 if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { 02046 perror("ioctl[SIOCGIWMODE]"); 02047 goto done; 02048 } 02049 02050 if (iwr.u.mode == new_mode) { 02051 ret = 0; 02052 goto done; 02053 } 02054 02055 if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0) == 0) { 02056 /* Try to set the mode again while the interface is down */ 02057 iwr.u.mode = new_mode; 02058 if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) 02059 perror("ioctl[SIOCSIWMODE]"); 02060 else 02061 ret = 0; 02062 02063 (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1); 02064 } 02065 02066 done: 02067 return ret; 02068 } 02069 02070 02071 static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv, 02072 u32 cmd, const u8 *bssid, const u8 *pmkid) 02073 { 02074 struct iwreq iwr; 02075 struct iw_pmksa pmksa; 02076 int ret = 0; 02077 02078 os_memset(&iwr, 0, sizeof(iwr)); 02079 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 02080 os_memset(&pmksa, 0, sizeof(pmksa)); 02081 pmksa.cmd = cmd; 02082 pmksa.bssid.sa_family = ARPHRD_ETHER; 02083 if (bssid) 02084 os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN); 02085 if (pmkid) 02086 os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN); 02087 iwr.u.data.pointer = (caddr_t) &pmksa; 02088 iwr.u.data.length = sizeof(pmksa); 02089 02090 if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) { 02091 if (errno != EOPNOTSUPP) 02092 perror("ioctl[SIOCSIWPMKSA]"); 02093 ret = -1; 02094 } 02095 02096 return ret; 02097 } 02098 02099 02100 static int wpa_driver_wext_add_pmkid(void *priv, const u8 *bssid, 02101 const u8 *pmkid) 02102 { 02103 struct wpa_driver_wext_data *drv = priv; 02104 return wpa_driver_wext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid); 02105 } 02106 02107 02108 static int wpa_driver_wext_remove_pmkid(void *priv, const u8 *bssid, 02109 const u8 *pmkid) 02110 { 02111 struct wpa_driver_wext_data *drv = priv; 02112 return wpa_driver_wext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid); 02113 } 02114 02115 02116 static int wpa_driver_wext_flush_pmkid(void *priv) 02117 { 02118 struct wpa_driver_wext_data *drv = priv; 02119 return wpa_driver_wext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL); 02120 } 02121 02122 02123 int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa) 02124 { 02125 struct wpa_driver_wext_data *drv = priv; 02126 if (!drv->has_capability) 02127 return -1; 02128 os_memcpy(capa, &drv->capa, sizeof(*capa)); 02129 return 0; 02130 } 02131 02132 02133 int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv, 02134 const char *ifname) 02135 { 02136 if (ifname == NULL) { 02137 drv->ifindex2 = -1; 02138 return 0; 02139 } 02140 02141 drv->ifindex2 = if_nametoindex(ifname); 02142 if (drv->ifindex2 <= 0) 02143 return -1; 02144 02145 wpa_printf(MSG_DEBUG, "Added alternative ifindex %d (%s) for " 02146 "wireless events", drv->ifindex2, ifname); 02147 02148 return 0; 02149 } 02150 02151 02152 int wpa_driver_wext_set_operstate(void *priv, int state) 02153 { 02154 struct wpa_driver_wext_data *drv = priv; 02155 02156 wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", 02157 __func__, drv->operstate, state, state ? "UP" : "DORMANT"); 02158 drv->operstate = state; 02159 return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1, 02160 state ? IF_OPER_UP : IF_OPER_DORMANT); 02161 } 02162 02163 02164 int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv) 02165 { 02166 return drv->we_version_compiled; 02167 } 02168 02169 02170 const struct wpa_driver_ops wpa_driver_wext_ops = { 02171 .name = "wext", 02172 .desc = "Linux wireless extensions (generic)", 02173 .get_bssid = wpa_driver_wext_get_bssid, 02174 .get_ssid = wpa_driver_wext_get_ssid, 02175 .set_key = wpa_driver_wext_set_key, 02176 .set_countermeasures = wpa_driver_wext_set_countermeasures, 02177 .scan2 = wpa_driver_wext_scan, 02178 .get_scan_results2 = wpa_driver_wext_get_scan_results, 02179 .deauthenticate = wpa_driver_wext_deauthenticate, 02180 .disassociate = wpa_driver_wext_disassociate, 02181 .associate = wpa_driver_wext_associate, 02182 .init = wpa_driver_wext_init, 02183 .deinit = wpa_driver_wext_deinit, 02184 .add_pmkid = wpa_driver_wext_add_pmkid, 02185 .remove_pmkid = wpa_driver_wext_remove_pmkid, 02186 .flush_pmkid = wpa_driver_wext_flush_pmkid, 02187 .get_capa = wpa_driver_wext_get_capa, 02188 .set_operstate = wpa_driver_wext_set_operstate, 02189 };