00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00148
00149
00150
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
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
00186
00187
00188
00189
00190
00191
00192
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
00243 if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
00244 data.michael_mic_failure.unicast =
00245 os_strstr(custom, " unicast ") != NULL;
00246
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
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
00435
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
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
00639
00640
00641
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
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
00767 }
00768
00769 wpa_driver_wext_get_range(drv);
00770
00771
00772
00773
00774
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
00783
00784
00785
00786
00787
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
00819
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
00896
00897 timeout = 5;
00898 if (drv->scan_complete_events) {
00899
00900
00901
00902
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;
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
00964
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
01010
01011
01012
01013
01014
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
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
01091
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
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
01230
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
01240
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
01295
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
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
01373
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
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
01554
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
01710
01711
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
01724
01725
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
01736
01737
01738
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
01842 iwr.u.encoding.flags = 0;
01843 iwr.u.encoding.pointer = (caddr_t) NULL;
01844 iwr.u.encoding.length = 0;
01845
01846
01847
01848
01849
01850
01851
01852
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
01886
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
01901
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
01912
01913
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
01947
01948
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
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
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
02042
02043
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
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 };