00001
00022 #include "includes.h"
00023 #include <sys/ioctl.h>
00024 #include <net/if_arp.h>
00025
00026 #include "wireless_copy.h"
00027 #include "common.h"
00028 #include "driver.h"
00029 #include "l2_packet.h"
00030 #include "eloop.h"
00031 #include "wpa_supplicant.h"
00032 #include "priv_netlink.h"
00033 #include "driver_wext.h"
00034 #include "wpa.h"
00035
00036 #ifdef CONFIG_CLIENT_MLME
00037 #include <netpacket/packet.h>
00038 #include <hostapd_ioctl.h>
00039 #include <net/d80211_common.h>
00040 #include <net/d80211_shared.h>
00041 #include "mlme.h"
00042
00043 #ifndef ETH_P_ALL
00044 #define ETH_P_ALL 0x0003
00045 #endif
00046 #endif
00047
00048
00049 struct wpa_driver_wext_data {
00050 void *ctx;
00051 int event_sock;
00052 int ioctl_sock;
00053 int mlme_sock;
00054 char ifname[IFNAMSIZ + 1];
00055 int ifindex;
00056 int ifindex2;
00057 u8 *assoc_req_ies;
00058 size_t assoc_req_ies_len;
00059 u8 *assoc_resp_ies;
00060 size_t assoc_resp_ies_len;
00061 struct wpa_driver_capa capa;
00062 int has_capability;
00063 int we_version_compiled;
00064
00065
00066 int use_crypt;
00067 int auth_alg_fallback;
00068
00069 int operstate;
00070
00071 char mlmedev[IFNAMSIZ + 1];
00072 };
00073
00074
00075 static int wpa_driver_wext_flush_pmkid(void *priv);
00076 static int wpa_driver_wext_get_range(void *priv);
00077
00078 static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv,
00079 int linkmode, int operstate)
00080 {
00081 struct {
00082 struct nlmsghdr hdr;
00083 struct ifinfomsg ifinfo;
00084 char opts[16];
00085 } req;
00086 struct rtattr *rta;
00087 static int nl_seq;
00088 ssize_t ret;
00089
00090 req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
00091 req.hdr.nlmsg_type = RTM_SETLINK;
00092 req.hdr.nlmsg_flags = NLM_F_REQUEST;
00093 req.hdr.nlmsg_seq = ++nl_seq;
00094 req.hdr.nlmsg_pid = 0;
00095
00096 req.ifinfo.ifi_family = AF_UNSPEC;
00097 req.ifinfo.ifi_type = 0;
00098 req.ifinfo.ifi_index = drv->ifindex;
00099 req.ifinfo.ifi_flags = 0;
00100 req.ifinfo.ifi_change = 0;
00101
00102 if (linkmode != -1) {
00103 rta = (struct rtattr *)
00104 ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len));
00105 rta->rta_type = IFLA_LINKMODE;
00106 rta->rta_len = RTA_LENGTH(sizeof(char));
00107 *((char *) RTA_DATA(rta)) = linkmode;
00108 req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +
00109 RTA_LENGTH(sizeof(char));
00110 }
00111 if (operstate != -1) {
00112 rta = (struct rtattr *)
00113 ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len));
00114 rta->rta_type = IFLA_OPERSTATE;
00115 rta->rta_len = RTA_LENGTH(sizeof(char));
00116 *((char *) RTA_DATA(rta)) = operstate;
00117 req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +
00118 RTA_LENGTH(sizeof(char));
00119 }
00120
00121 wpa_printf(MSG_DEBUG, "WEXT: Operstate: linkmode=%d, operstate=%d",
00122 linkmode, operstate);
00123
00124 ret = send(drv->event_sock, &req, req.hdr.nlmsg_len, 0);
00125 if (ret < 0) {
00126 wpa_printf(MSG_DEBUG, "WEXT: Sending operstate IFLA failed: "
00127 "%s (assume operstate is not supported)",
00128 strerror(errno));
00129 }
00130
00131 return ret < 0 ? -1 : 0;
00132 }
00133
00134
00135 static int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
00136 int idx, u32 value)
00137 {
00138 struct iwreq iwr;
00139 int ret = 0;
00140
00141 os_memset(&iwr, 0, sizeof(iwr));
00142 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
00143 iwr.u.param.flags = idx & IW_AUTH_INDEX;
00144 iwr.u.param.value = value;
00145
00146 if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) {
00147 perror("ioctl[SIOCSIWAUTH]");
00148 fprintf(stderr, "WEXT auth param %d value 0x%x - ",
00149 idx, value);
00150 ret = errno == EOPNOTSUPP ? -2 : -1;
00151 }
00152
00153 return ret;
00154 }
00155
00156
00164 int wpa_driver_wext_get_bssid(void *priv, u8 *bssid)
00165 {
00166 struct wpa_driver_wext_data *drv = priv;
00167 struct iwreq iwr;
00168 int ret = 0;
00169
00170 os_memset(&iwr, 0, sizeof(iwr));
00171 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
00172
00173 if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
00174 perror("ioctl[SIOCGIWAP]");
00175 ret = -1;
00176 }
00177 os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
00178
00179 return ret;
00180 }
00181
00182
00190 int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid)
00191 {
00192 struct wpa_driver_wext_data *drv = priv;
00193 struct iwreq iwr;
00194 int ret = 0;
00195
00196 os_memset(&iwr, 0, sizeof(iwr));
00197 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
00198 iwr.u.ap_addr.sa_family = ARPHRD_ETHER;
00199 if (bssid)
00200 os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN);
00201 else
00202 os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN);
00203
00204 if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) {
00205 perror("ioctl[SIOCSIWAP]");
00206 ret = -1;
00207 }
00208
00209 return ret;
00210 }
00211
00212
00220 int wpa_driver_wext_get_ssid(void *priv, u8 *ssid)
00221 {
00222 struct wpa_driver_wext_data *drv = priv;
00223 struct iwreq iwr;
00224 int ret = 0;
00225
00226 os_memset(&iwr, 0, sizeof(iwr));
00227 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
00228 iwr.u.essid.pointer = (caddr_t) ssid;
00229 iwr.u.essid.length = 32;
00230
00231 if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
00232 perror("ioctl[SIOCGIWESSID]");
00233 ret = -1;
00234 } else {
00235 ret = iwr.u.essid.length;
00236 if (ret > 32)
00237 ret = 32;
00238
00239
00240
00241
00242 if (ret > 0 && ssid[ret - 1] == '\0' &&
00243 drv->we_version_compiled < 21)
00244 ret--;
00245 }
00246
00247 return ret;
00248 }
00249
00250
00259 int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len)
00260 {
00261 struct wpa_driver_wext_data *drv = priv;
00262 struct iwreq iwr;
00263 int ret = 0;
00264 char buf[33];
00265
00266 if (ssid_len > 32)
00267 return -1;
00268
00269 os_memset(&iwr, 0, sizeof(iwr));
00270 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
00271
00272 iwr.u.essid.flags = (ssid_len != 0);
00273 os_memset(buf, 0, sizeof(buf));
00274 os_memcpy(buf, ssid, ssid_len);
00275 iwr.u.essid.pointer = (caddr_t) buf;
00276 if (drv->we_version_compiled < 21) {
00277
00278
00279
00280
00281
00282
00283
00284
00285 if (ssid_len)
00286 ssid_len++;
00287 }
00288 iwr.u.essid.length = ssid_len;
00289
00290 if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
00291 perror("ioctl[SIOCSIWESSID]");
00292 ret = -1;
00293 }
00294
00295 return ret;
00296 }
00297
00298
00306 int wpa_driver_wext_set_freq(void *priv, int freq)
00307 {
00308 struct wpa_driver_wext_data *drv = priv;
00309 struct iwreq iwr;
00310 int ret = 0;
00311
00312 os_memset(&iwr, 0, sizeof(iwr));
00313 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
00314 iwr.u.freq.m = freq * 100000;
00315 iwr.u.freq.e = 1;
00316
00317 if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
00318 perror("ioctl[SIOCSIWFREQ]");
00319 ret = -1;
00320 }
00321
00322 return ret;
00323 }
00324
00325
00326 static void
00327 wpa_driver_wext_event_wireless_custom(void *ctx, char *custom)
00328 {
00329 union wpa_event_data data;
00330
00331 wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'",
00332 custom);
00333
00334 os_memset(&data, 0, sizeof(data));
00335
00336 if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
00337 data.michael_mic_failure.unicast =
00338 os_strstr(custom, " unicast ") != NULL;
00339
00340 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
00341 } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) {
00342 char *spos;
00343 int bytes;
00344
00345 spos = custom + 17;
00346
00347 bytes = strspn(spos, "0123456789abcdefABCDEF");
00348 if (!bytes || (bytes & 1))
00349 return;
00350 bytes /= 2;
00351
00352 data.assoc_info.req_ies = os_malloc(bytes);
00353 if (data.assoc_info.req_ies == NULL)
00354 return;
00355
00356 data.assoc_info.req_ies_len = bytes;
00357 hexstr2bin(spos, data.assoc_info.req_ies, bytes);
00358
00359 spos += bytes * 2;
00360
00361 data.assoc_info.resp_ies = NULL;
00362 data.assoc_info.resp_ies_len = 0;
00363
00364 if (os_strncmp(spos, " RespIEs=", 9) == 0) {
00365 spos += 9;
00366
00367 bytes = strspn(spos, "0123456789abcdefABCDEF");
00368 if (!bytes || (bytes & 1))
00369 goto done;
00370 bytes /= 2;
00371
00372 data.assoc_info.resp_ies = os_malloc(bytes);
00373 if (data.assoc_info.resp_ies == NULL)
00374 goto done;
00375
00376 data.assoc_info.resp_ies_len = bytes;
00377 hexstr2bin(spos, data.assoc_info.resp_ies, bytes);
00378 }
00379
00380 wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
00381
00382 done:
00383 os_free(data.assoc_info.resp_ies);
00384 os_free(data.assoc_info.req_ies);
00385 #ifdef CONFIG_PEERKEY
00386 } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) {
00387 if (hwaddr_aton(custom + 17, data.stkstart.peer)) {
00388 wpa_printf(MSG_DEBUG, "WEXT: unrecognized "
00389 "STKSTART.request '%s'", custom + 17);
00390 return;
00391 }
00392 wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
00393 #endif
00394 }
00395 }
00396
00397
00398 static int wpa_driver_wext_event_wireless_michaelmicfailure(
00399 void *ctx, const char *ev, size_t len)
00400 {
00401 const struct iw_michaelmicfailure *mic;
00402 union wpa_event_data data;
00403
00404 if (len < sizeof(*mic))
00405 return -1;
00406
00407 mic = (const struct iw_michaelmicfailure *) ev;
00408
00409 wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: "
00410 "flags=0x%x src_addr=" MACSTR, mic->flags,
00411 MAC2STR(mic->src_addr.sa_data));
00412
00413 os_memset(&data, 0, sizeof(data));
00414 data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP);
00415 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
00416
00417 return 0;
00418 }
00419
00420
00421 static int wpa_driver_wext_event_wireless_pmkidcand(
00422 struct wpa_driver_wext_data *drv, const char *ev, size_t len)
00423 {
00424 const struct iw_pmkid_cand *cand;
00425 union wpa_event_data data;
00426 const u8 *addr;
00427
00428 if (len < sizeof(*cand))
00429 return -1;
00430
00431 cand = (const struct iw_pmkid_cand *) ev;
00432 addr = (const u8 *) cand->bssid.sa_data;
00433
00434 wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: "
00435 "flags=0x%x index=%d bssid=" MACSTR, cand->flags,
00436 cand->index, MAC2STR(addr));
00437
00438 os_memset(&data, 0, sizeof(data));
00439 os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN);
00440 data.pmkid_candidate.index = cand->index;
00441 data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH;
00442 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
00443
00444 return 0;
00445 }
00446
00447
00448 static int wpa_driver_wext_event_wireless_assocreqie(
00449 struct wpa_driver_wext_data *drv, const char *ev, int len)
00450 {
00451 if (len < 0)
00452 return -1;
00453
00454 wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev,
00455 len);
00456 os_free(drv->assoc_req_ies);
00457 drv->assoc_req_ies = os_malloc(len);
00458 if (drv->assoc_req_ies == NULL) {
00459 drv->assoc_req_ies_len = 0;
00460 return -1;
00461 }
00462 os_memcpy(drv->assoc_req_ies, ev, len);
00463 drv->assoc_req_ies_len = len;
00464
00465 return 0;
00466 }
00467
00468
00469 static int wpa_driver_wext_event_wireless_assocrespie(
00470 struct wpa_driver_wext_data *drv, const char *ev, int len)
00471 {
00472 if (len < 0)
00473 return -1;
00474
00475 wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev,
00476 len);
00477 os_free(drv->assoc_resp_ies);
00478 drv->assoc_resp_ies = os_malloc(len);
00479 if (drv->assoc_resp_ies == NULL) {
00480 drv->assoc_resp_ies_len = 0;
00481 return -1;
00482 }
00483 os_memcpy(drv->assoc_resp_ies, ev, len);
00484 drv->assoc_resp_ies_len = len;
00485
00486 return 0;
00487 }
00488
00489
00490 static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv)
00491 {
00492 union wpa_event_data data;
00493
00494 if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL)
00495 return;
00496
00497 os_memset(&data, 0, sizeof(data));
00498 if (drv->assoc_req_ies) {
00499 data.assoc_info.req_ies = drv->assoc_req_ies;
00500 drv->assoc_req_ies = NULL;
00501 data.assoc_info.req_ies_len = drv->assoc_req_ies_len;
00502 }
00503 if (drv->assoc_resp_ies) {
00504 data.assoc_info.resp_ies = drv->assoc_resp_ies;
00505 drv->assoc_resp_ies = NULL;
00506 data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len;
00507 }
00508
00509 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
00510
00511 os_free(data.assoc_info.req_ies);
00512 os_free(data.assoc_info.resp_ies);
00513 }
00514
00515
00516 static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv,
00517 void *ctx, char *data, int len)
00518 {
00519 struct iw_event iwe_buf, *iwe = &iwe_buf;
00520 char *pos, *end, *custom, *buf;
00521
00522 pos = data;
00523 end = data + len;
00524
00525 while (pos + IW_EV_LCP_LEN <= end) {
00526
00527
00528 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
00529 wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
00530 iwe->cmd, iwe->len);
00531 if (iwe->len <= IW_EV_LCP_LEN)
00532 return;
00533
00534 custom = pos + IW_EV_POINT_LEN;
00535 if (drv->we_version_compiled > 18 &&
00536 (iwe->cmd == IWEVMICHAELMICFAILURE ||
00537 iwe->cmd == IWEVCUSTOM ||
00538 iwe->cmd == IWEVASSOCREQIE ||
00539 iwe->cmd == IWEVASSOCRESPIE ||
00540 iwe->cmd == IWEVPMKIDCAND)) {
00541
00542 char *dpos = (char *) &iwe_buf.u.data.length;
00543 int dlen = dpos - (char *) &iwe_buf;
00544 os_memcpy(dpos, pos + IW_EV_LCP_LEN,
00545 sizeof(struct iw_event) - dlen);
00546 } else {
00547 os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
00548 custom += IW_EV_POINT_OFF;
00549 }
00550
00551 switch (iwe->cmd) {
00552 case SIOCGIWAP:
00553 wpa_printf(MSG_DEBUG, "Wireless event: new AP: "
00554 MACSTR,
00555 MAC2STR((u8 *) iwe->u.ap_addr.sa_data));
00556 if (os_memcmp(iwe->u.ap_addr.sa_data,
00557 "\x00\x00\x00\x00\x00\x00", ETH_ALEN) ==
00558 0 ||
00559 os_memcmp(iwe->u.ap_addr.sa_data,
00560 "\x44\x44\x44\x44\x44\x44", ETH_ALEN) ==
00561 0) {
00562 os_free(drv->assoc_req_ies);
00563 drv->assoc_req_ies = NULL;
00564 os_free(drv->assoc_resp_ies);
00565 drv->assoc_resp_ies = NULL;
00566 wpa_supplicant_event(ctx, EVENT_DISASSOC,
00567 NULL);
00568
00569 } else {
00570 wpa_driver_wext_event_assoc_ies(drv);
00571 wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
00572 }
00573 break;
00574 case IWEVMICHAELMICFAILURE:
00575 wpa_driver_wext_event_wireless_michaelmicfailure(
00576 ctx, custom, iwe->u.data.length);
00577 break;
00578 case IWEVCUSTOM:
00579 if (custom + iwe->u.data.length > end)
00580 return;
00581 buf = os_malloc(iwe->u.data.length + 1);
00582 if (buf == NULL)
00583 return;
00584 os_memcpy(buf, custom, iwe->u.data.length);
00585 buf[iwe->u.data.length] = '\0';
00586 wpa_driver_wext_event_wireless_custom(ctx, buf);
00587 os_free(buf);
00588 break;
00589 case SIOCGIWSCAN:
00590 eloop_cancel_timeout(wpa_driver_wext_scan_timeout,
00591 drv, ctx);
00592 wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
00593 break;
00594 case IWEVASSOCREQIE:
00595 wpa_driver_wext_event_wireless_assocreqie(
00596 drv, custom, iwe->u.data.length);
00597 break;
00598 case IWEVASSOCRESPIE:
00599 wpa_driver_wext_event_wireless_assocrespie(
00600 drv, custom, iwe->u.data.length);
00601 break;
00602 case IWEVPMKIDCAND:
00603 wpa_driver_wext_event_wireless_pmkidcand(
00604 drv, custom, iwe->u.data.length);
00605 break;
00606 }
00607
00608 pos += iwe->len;
00609 }
00610 }
00611
00612
00613 static void wpa_driver_wext_event_link(void *ctx, char *buf, size_t len,
00614 int del)
00615 {
00616 union wpa_event_data event;
00617
00618 os_memset(&event, 0, sizeof(event));
00619 if (len > sizeof(event.interface_status.ifname))
00620 len = sizeof(event.interface_status.ifname) - 1;
00621 os_memcpy(event.interface_status.ifname, buf, len);
00622 event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :
00623 EVENT_INTERFACE_ADDED;
00624
00625 wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
00626 del ? "DEL" : "NEW",
00627 event.interface_status.ifname,
00628 del ? "removed" : "added");
00629
00630 wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
00631 }
00632
00633
00634 static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv,
00635 void *ctx, struct nlmsghdr *h,
00636 size_t len)
00637 {
00638 struct ifinfomsg *ifi;
00639 int attrlen, nlmsg_len, rta_len;
00640 struct rtattr * attr;
00641
00642 if (len < sizeof(*ifi))
00643 return;
00644
00645 ifi = NLMSG_DATA(h);
00646
00647 if (drv->ifindex != ifi->ifi_index && drv->ifindex2 != ifi->ifi_index)
00648 {
00649 wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d",
00650 ifi->ifi_index);
00651 return;
00652 }
00653
00654 wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
00655 "(%s%s%s%s)",
00656 drv->operstate, ifi->ifi_flags,
00657 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
00658 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
00659 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
00660 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT" : "");
00661
00662
00663
00664
00665
00666
00667 if (drv->operstate == 1 &&
00668 (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
00669 !(ifi->ifi_flags & IFF_RUNNING))
00670 wpa_driver_wext_send_oper_ifla(drv, -1, IF_OPER_UP);
00671
00672 nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
00673
00674 attrlen = h->nlmsg_len - nlmsg_len;
00675 if (attrlen < 0)
00676 return;
00677
00678 attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
00679
00680 rta_len = RTA_ALIGN(sizeof(struct rtattr));
00681 while (RTA_OK(attr, attrlen)) {
00682 if (attr->rta_type == IFLA_WIRELESS) {
00683 wpa_driver_wext_event_wireless(
00684 drv, ctx, ((char *) attr) + rta_len,
00685 attr->rta_len - rta_len);
00686 } else if (attr->rta_type == IFLA_IFNAME) {
00687 wpa_driver_wext_event_link(ctx,
00688 ((char *) attr) + rta_len,
00689 attr->rta_len - rta_len, 0);
00690 }
00691 attr = RTA_NEXT(attr, attrlen);
00692 }
00693 }
00694
00695
00696 static void wpa_driver_wext_event_rtm_dellink(struct wpa_driver_wext_data *drv,
00697 void *ctx, struct nlmsghdr *h,
00698 size_t len)
00699 {
00700 struct ifinfomsg *ifi;
00701 int attrlen, nlmsg_len, rta_len;
00702 struct rtattr * attr;
00703
00704 if (len < sizeof(*ifi))
00705 return;
00706
00707 ifi = NLMSG_DATA(h);
00708
00709 nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
00710
00711 attrlen = h->nlmsg_len - nlmsg_len;
00712 if (attrlen < 0)
00713 return;
00714
00715 attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
00716
00717 rta_len = RTA_ALIGN(sizeof(struct rtattr));
00718 while (RTA_OK(attr, attrlen)) {
00719 if (attr->rta_type == IFLA_IFNAME) {
00720 wpa_driver_wext_event_link(ctx,
00721 ((char *) attr) + rta_len,
00722 attr->rta_len - rta_len, 1);
00723 }
00724 attr = RTA_NEXT(attr, attrlen);
00725 }
00726 }
00727
00728
00729 static void wpa_driver_wext_event_receive(int sock, void *eloop_ctx,
00730 void *sock_ctx)
00731 {
00732 char buf[8192];
00733 int left;
00734 struct sockaddr_nl from;
00735 socklen_t fromlen;
00736 struct nlmsghdr *h;
00737 int max_events = 10;
00738
00739 try_again:
00740 fromlen = sizeof(from);
00741 left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
00742 (struct sockaddr *) &from, &fromlen);
00743 if (left < 0) {
00744 if (errno != EINTR && errno != EAGAIN)
00745 perror("recvfrom(netlink)");
00746 return;
00747 }
00748
00749 h = (struct nlmsghdr *) buf;
00750 while (left >= (int) sizeof(*h)) {
00751 int len, plen;
00752
00753 len = h->nlmsg_len;
00754 plen = len - sizeof(*h);
00755 if (len > left || plen < 0) {
00756 wpa_printf(MSG_DEBUG, "Malformed netlink message: "
00757 "len=%d left=%d plen=%d",
00758 len, left, plen);
00759 break;
00760 }
00761
00762 switch (h->nlmsg_type) {
00763 case RTM_NEWLINK:
00764 wpa_driver_wext_event_rtm_newlink(eloop_ctx, sock_ctx,
00765 h, plen);
00766 break;
00767 case RTM_DELLINK:
00768 wpa_driver_wext_event_rtm_dellink(eloop_ctx, sock_ctx,
00769 h, plen);
00770 break;
00771 }
00772
00773 len = NLMSG_ALIGN(len);
00774 left -= len;
00775 h = (struct nlmsghdr *) ((char *) h + len);
00776 }
00777
00778 if (left > 0) {
00779 wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink "
00780 "message", left);
00781 }
00782
00783 if (--max_events > 0) {
00784
00785
00786
00787
00788
00789
00790
00791 goto try_again;
00792 }
00793 }
00794
00795
00796 static int wpa_driver_wext_get_ifflags_ifname(struct wpa_driver_wext_data *drv,
00797 const char *ifname, int *flags)
00798 {
00799 struct ifreq ifr;
00800
00801 os_memset(&ifr, 0, sizeof(ifr));
00802 os_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
00803 if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
00804 perror("ioctl[SIOCGIFFLAGS]");
00805 return -1;
00806 }
00807 *flags = ifr.ifr_flags & 0xffff;
00808 return 0;
00809 }
00810
00811
00819 int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags)
00820 {
00821 return wpa_driver_wext_get_ifflags_ifname(drv, drv->ifname, flags);
00822 }
00823
00824
00825 static int wpa_driver_wext_set_ifflags_ifname(struct wpa_driver_wext_data *drv,
00826 const char *ifname, int flags)
00827 {
00828 struct ifreq ifr;
00829
00830 os_memset(&ifr, 0, sizeof(ifr));
00831 os_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
00832 ifr.ifr_flags = flags & 0xffff;
00833 if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
00834 perror("SIOCSIFFLAGS");
00835 return -1;
00836 }
00837 return 0;
00838 }
00839
00840
00848 int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags)
00849 {
00850 return wpa_driver_wext_set_ifflags_ifname(drv, drv->ifname, flags);
00851 }
00852
00853
00862 void * wpa_driver_wext_init(void *ctx, const char *ifname)
00863 {
00864 int s, flags;
00865 struct sockaddr_nl local;
00866 struct wpa_driver_wext_data *drv;
00867
00868 drv = os_zalloc(sizeof(*drv));
00869 if (drv == NULL)
00870 return NULL;
00871 drv->ctx = ctx;
00872 os_strncpy(drv->ifname, ifname, sizeof(drv->ifname));
00873
00874 drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
00875 if (drv->ioctl_sock < 0) {
00876 perror("socket(PF_INET,SOCK_DGRAM)");
00877 os_free(drv);
00878 return NULL;
00879 }
00880
00881 s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
00882 if (s < 0) {
00883 perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
00884 close(drv->ioctl_sock);
00885 os_free(drv);
00886 return NULL;
00887 }
00888
00889 os_memset(&local, 0, sizeof(local));
00890 local.nl_family = AF_NETLINK;
00891 local.nl_groups = RTMGRP_LINK;
00892 if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
00893 perror("bind(netlink)");
00894 close(s);
00895 close(drv->ioctl_sock);
00896 os_free(drv);
00897 return NULL;
00898 }
00899
00900 eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx);
00901 drv->event_sock = s;
00902
00903 drv->mlme_sock = -1;
00904
00905
00906
00907
00908 wpa_driver_wext_flush_pmkid(drv);
00909
00910 if (wpa_driver_wext_set_mode(drv, 0) < 0) {
00911 printf("Could not configure driver to use managed mode\n");
00912 }
00913
00914 if (wpa_driver_wext_get_ifflags(drv, &flags) != 0 ||
00915 wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) {
00916 printf("Could not set interface '%s' UP\n", drv->ifname);
00917 }
00918
00919 wpa_driver_wext_get_range(drv);
00920
00921 drv->ifindex = if_nametoindex(drv->ifname);
00922
00923 if (os_strncmp(ifname, "wlan", 4) == 0) {
00924
00925
00926
00927
00928
00929
00930
00931
00932 char ifname2[IFNAMSIZ + 1];
00933 os_strncpy(ifname2, ifname, sizeof(ifname2));
00934 os_memcpy(ifname2, "wifi", 4);
00935 wpa_driver_wext_alternative_ifindex(drv, ifname2);
00936 }
00937
00938 wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT);
00939
00940 return drv;
00941 }
00942
00943
00952 void wpa_driver_wext_deinit(void *priv)
00953 {
00954 struct wpa_driver_wext_data *drv = priv;
00955 int flags;
00956
00957 eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
00958
00959
00960
00961
00962
00963 wpa_driver_wext_set_bssid(drv, (u8 *) "\x00\x00\x00\x00\x00\x00");
00964
00965 wpa_driver_wext_send_oper_ifla(priv, 0, IF_OPER_UP);
00966
00967 eloop_unregister_read_sock(drv->event_sock);
00968 if (drv->mlme_sock >= 0)
00969 eloop_unregister_read_sock(drv->mlme_sock);
00970
00971 if (wpa_driver_wext_get_ifflags(drv, &flags) == 0)
00972 (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
00973
00974 #ifdef CONFIG_CLIENT_MLME
00975 if (drv->mlmedev[0] &&
00976 wpa_driver_wext_get_ifflags_ifname(drv, drv->mlmedev, &flags) == 0)
00977 (void) wpa_driver_wext_set_ifflags_ifname(drv, drv->mlmedev,
00978 flags & ~IFF_UP);
00979 #endif
00980
00981 close(drv->event_sock);
00982 close(drv->ioctl_sock);
00983 if (drv->mlme_sock >= 0)
00984 close(drv->mlme_sock);
00985 os_free(drv->assoc_req_ies);
00986 os_free(drv->assoc_resp_ies);
00987 os_free(drv);
00988 }
00989
00990
01000 void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
01001 {
01002 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
01003 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
01004 }
01005
01006
01017 int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len)
01018 {
01019 struct wpa_driver_wext_data *drv = priv;
01020 struct iwreq iwr;
01021 int ret = 0;
01022 struct iw_scan_req req;
01023
01024 if (ssid_len > IW_ESSID_MAX_SIZE) {
01025 wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
01026 __FUNCTION__, (unsigned long) ssid_len);
01027 return -1;
01028 }
01029
01030 os_memset(&iwr, 0, sizeof(iwr));
01031 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01032
01033 if (ssid && ssid_len) {
01034 os_memset(&req, 0, sizeof(req));
01035 req.essid_len = ssid_len;
01036 req.bssid.sa_family = ARPHRD_ETHER;
01037 os_memset(req.bssid.sa_data, 0xff, ETH_ALEN);
01038 os_memcpy(req.essid, ssid, ssid_len);
01039 iwr.u.data.pointer = (caddr_t) &req;
01040 iwr.u.data.length = sizeof(req);
01041 iwr.u.data.flags = IW_SCAN_THIS_ESSID;
01042 }
01043
01044 if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
01045 perror("ioctl[SIOCSIWSCAN]");
01046 ret = -1;
01047 }
01048
01049
01050
01051 eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv,
01052 drv->ctx);
01053
01054 return ret;
01055 }
01056
01057
01058
01059
01060 static int wpa_scan_result_compar(const void *a, const void *b)
01061 {
01062 const struct wpa_scan_result *wa = a;
01063 const struct wpa_scan_result *wb = b;
01064
01065
01066 if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
01067 !(wa->wpa_ie_len || wa->rsn_ie_len))
01068 return 1;
01069 if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
01070 (wa->wpa_ie_len || wa->rsn_ie_len))
01071 return -1;
01072
01073
01074 if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
01075 (wb->caps & IEEE80211_CAP_PRIVACY))
01076 return 1;
01077 if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
01078 (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
01079 return -1;
01080
01081
01082 if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
01083 return wb->maxrate - wa->maxrate;
01084
01085
01086
01087
01088
01089
01090 if (wb->level == wa->level)
01091 return wb->qual - wa->qual;
01092 return wb->level - wa->level;
01093 }
01094
01095
01109 int wpa_driver_wext_get_scan_results(void *priv,
01110 struct wpa_scan_result *results,
01111 size_t max_size)
01112 {
01113 struct wpa_driver_wext_data *drv = priv;
01114 struct iwreq iwr;
01115 size_t ap_num = 0;
01116 int first, maxrate;
01117 u8 *res_buf;
01118 struct iw_event iwe_buf, *iwe = &iwe_buf;
01119 char *pos, *end, *custom, *genie, *gpos, *gend;
01120 struct iw_param p;
01121 size_t len, clen, res_buf_len;
01122
01123 os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
01124
01125 res_buf_len = IW_SCAN_MAX_DATA;
01126 for (;;) {
01127 res_buf = os_malloc(res_buf_len);
01128 if (res_buf == NULL)
01129 return -1;
01130 os_memset(&iwr, 0, sizeof(iwr));
01131 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01132 iwr.u.data.pointer = res_buf;
01133 iwr.u.data.length = res_buf_len;
01134
01135 if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0)
01136 break;
01137
01138 if (errno == E2BIG && res_buf_len < 100000) {
01139 os_free(res_buf);
01140 res_buf = NULL;
01141 res_buf_len *= 2;
01142 wpa_printf(MSG_DEBUG, "Scan results did not fit - "
01143 "trying larger buffer (%lu bytes)",
01144 (unsigned long) res_buf_len);
01145 } else {
01146 perror("ioctl[SIOCGIWSCAN]");
01147 os_free(res_buf);
01148 return -1;
01149 }
01150 }
01151
01152 len = iwr.u.data.length;
01153 ap_num = 0;
01154 first = 1;
01155
01156 pos = (char *) res_buf;
01157 end = (char *) res_buf + len;
01158
01159 while (pos + IW_EV_LCP_LEN <= end) {
01160 int ssid_len;
01161
01162
01163 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
01164 if (iwe->len <= IW_EV_LCP_LEN)
01165 break;
01166
01167 custom = pos + IW_EV_POINT_LEN;
01168 if (drv->we_version_compiled > 18 &&
01169 (iwe->cmd == SIOCGIWESSID ||
01170 iwe->cmd == SIOCGIWENCODE ||
01171 iwe->cmd == IWEVGENIE ||
01172 iwe->cmd == IWEVCUSTOM)) {
01173
01174 char *dpos = (char *) &iwe_buf.u.data.length;
01175 int dlen = dpos - (char *) &iwe_buf;
01176 os_memcpy(dpos, pos + IW_EV_LCP_LEN,
01177 sizeof(struct iw_event) - dlen);
01178 } else {
01179 os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
01180 custom += IW_EV_POINT_OFF;
01181 }
01182
01183 switch (iwe->cmd) {
01184 case SIOCGIWAP:
01185 if (!first)
01186 ap_num++;
01187 first = 0;
01188 if (ap_num < max_size) {
01189 os_memcpy(results[ap_num].bssid,
01190 iwe->u.ap_addr.sa_data, ETH_ALEN);
01191 }
01192 break;
01193 case SIOCGIWMODE:
01194 if (ap_num >= max_size)
01195 break;
01196 if (iwe->u.mode == IW_MODE_ADHOC)
01197 results[ap_num].caps |= IEEE80211_CAP_IBSS;
01198 else if (iwe->u.mode == IW_MODE_MASTER ||
01199 iwe->u.mode == IW_MODE_INFRA)
01200 results[ap_num].caps |= IEEE80211_CAP_ESS;
01201 break;
01202 case SIOCGIWESSID:
01203 ssid_len = iwe->u.essid.length;
01204 if (custom + ssid_len > end)
01205 break;
01206 if (iwe->u.essid.flags &&
01207 ssid_len > 0 &&
01208 ssid_len <= IW_ESSID_MAX_SIZE) {
01209 if (ap_num < max_size) {
01210 os_memcpy(results[ap_num].ssid, custom,
01211 ssid_len);
01212 results[ap_num].ssid_len = ssid_len;
01213 }
01214 }
01215 break;
01216 case SIOCGIWFREQ:
01217 if (ap_num < max_size) {
01218 int divi = 1000000, i;
01219 if (iwe->u.freq.e == 0) {
01220
01221
01222
01223
01224
01225
01226 if (iwe->u.freq.m >= 1 &&
01227 iwe->u.freq.m <= 13) {
01228 results[ap_num].freq =
01229 2407 +
01230 5 * iwe->u.freq.m;
01231 break;
01232 } else if (iwe->u.freq.m == 14) {
01233 results[ap_num].freq = 2484;
01234 break;
01235 }
01236 }
01237 if (iwe->u.freq.e > 6) {
01238 wpa_printf(
01239 MSG_DEBUG, "Invalid freq "
01240 "in scan results (BSSID="
01241 MACSTR ": m=%d e=%d\n",
01242 MAC2STR(results[ap_num].bssid),
01243 iwe->u.freq.m, iwe->u.freq.e);
01244 break;
01245 }
01246 for (i = 0; i < iwe->u.freq.e; i++)
01247 divi /= 10;
01248 results[ap_num].freq = iwe->u.freq.m / divi;
01249 }
01250 break;
01251 case IWEVQUAL:
01252 if (ap_num < max_size) {
01253 results[ap_num].qual = iwe->u.qual.qual;
01254 results[ap_num].noise = iwe->u.qual.noise;
01255 results[ap_num].level = iwe->u.qual.level;
01256 }
01257 break;
01258 case SIOCGIWENCODE:
01259 if (ap_num < max_size &&
01260 !(iwe->u.data.flags & IW_ENCODE_DISABLED))
01261 results[ap_num].caps |= IEEE80211_CAP_PRIVACY;
01262 break;
01263 case SIOCGIWRATE:
01264 custom = pos + IW_EV_LCP_LEN;
01265 clen = iwe->len;
01266 if (custom + clen > end)
01267 break;
01268 maxrate = 0;
01269 while (((ssize_t) clen) >=
01270 (ssize_t) sizeof(struct iw_param)) {
01271
01272
01273 os_memcpy(&p, custom, sizeof(struct iw_param));
01274 if (p.value > maxrate)
01275 maxrate = p.value;
01276 clen -= sizeof(struct iw_param);
01277 custom += sizeof(struct iw_param);
01278 }
01279 if (ap_num < max_size)
01280 results[ap_num].maxrate = maxrate;
01281 break;
01282 case IWEVGENIE:
01283 if (ap_num >= max_size)
01284 break;
01285 gpos = genie = custom;
01286 gend = genie + iwe->u.data.length;
01287 if (gend > end) {
01288 wpa_printf(MSG_INFO, "IWEVGENIE overflow");
01289 break;
01290 }
01291 while (gpos + 1 < gend &&
01292 gpos + 2 + (u8) gpos[1] <= gend) {
01293 u8 ie = gpos[0], ielen = gpos[1] + 2;
01294 if (ielen > SSID_MAX_WPA_IE_LEN) {
01295 gpos += ielen;
01296 continue;
01297 }
01298 switch (ie) {
01299 case GENERIC_INFO_ELEM:
01300 if (ielen < 2 + 4 ||
01301 os_memcmp(&gpos[2],
01302 "\x00\x50\xf2\x01", 4) !=
01303 0)
01304 break;
01305 os_memcpy(results[ap_num].wpa_ie, gpos,
01306 ielen);
01307 results[ap_num].wpa_ie_len = ielen;
01308 break;
01309 case RSN_INFO_ELEM:
01310 os_memcpy(results[ap_num].rsn_ie, gpos,
01311 ielen);
01312 results[ap_num].rsn_ie_len = ielen;
01313 break;
01314 }
01315 gpos += ielen;
01316 }
01317 break;
01318 case IWEVCUSTOM:
01319 clen = iwe->u.data.length;
01320 if (custom + clen > end)
01321 break;
01322 if (clen > 7 &&
01323 os_strncmp(custom, "wpa_ie=", 7) == 0 &&
01324 ap_num < max_size) {
01325 char *spos;
01326 int bytes;
01327 spos = custom + 7;
01328 bytes = custom + clen - spos;
01329 if (bytes & 1)
01330 break;
01331 bytes /= 2;
01332 if (bytes > SSID_MAX_WPA_IE_LEN) {
01333 wpa_printf(MSG_INFO, "Too long WPA IE "
01334 "(%d)", bytes);
01335 break;
01336 }
01337 hexstr2bin(spos, results[ap_num].wpa_ie,
01338 bytes);
01339 results[ap_num].wpa_ie_len = bytes;
01340 } else if (clen > 7 &&
01341 os_strncmp(custom, "rsn_ie=", 7) == 0 &&
01342 ap_num < max_size) {
01343 char *spos;
01344 int bytes;
01345 spos = custom + 7;
01346 bytes = custom + clen - spos;
01347 if (bytes & 1)
01348 break;
01349 bytes /= 2;
01350 if (bytes > SSID_MAX_WPA_IE_LEN) {
01351 wpa_printf(MSG_INFO, "Too long RSN IE "
01352 "(%d)", bytes);
01353 break;
01354 }
01355 hexstr2bin(spos, results[ap_num].rsn_ie,
01356 bytes);
01357 results[ap_num].rsn_ie_len = bytes;
01358 }
01359 break;
01360 }
01361
01362 pos += iwe->len;
01363 }
01364 os_free(res_buf);
01365 res_buf = NULL;
01366 if (!first)
01367 ap_num++;
01368 if (ap_num > max_size) {
01369 wpa_printf(MSG_DEBUG, "Too small scan result buffer - "
01370 "%lu BSSes but room only for %lu",
01371 (unsigned long) ap_num,
01372 (unsigned long) max_size);
01373 ap_num = max_size;
01374 }
01375 qsort(results, ap_num, sizeof(struct wpa_scan_result),
01376 wpa_scan_result_compar);
01377
01378 wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)",
01379 (unsigned long) len, (unsigned long) ap_num);
01380
01381 return ap_num;
01382 }
01383
01384
01385 static int wpa_driver_wext_get_range(void *priv)
01386 {
01387 struct wpa_driver_wext_data *drv = priv;
01388 struct iw_range *range;
01389 struct iwreq iwr;
01390 int minlen;
01391 size_t buflen;
01392
01393
01394
01395
01396
01397 buflen = sizeof(struct iw_range) + 500;
01398 range = os_zalloc(buflen);
01399 if (range == NULL)
01400 return -1;
01401
01402 os_memset(&iwr, 0, sizeof(iwr));
01403 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01404 iwr.u.data.pointer = (caddr_t) range;
01405 iwr.u.data.length = buflen;
01406
01407 minlen = ((char *) &range->enc_capa) - (char *) range +
01408 sizeof(range->enc_capa);
01409
01410 if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
01411 perror("ioctl[SIOCGIWRANGE]");
01412 os_free(range);
01413 return -1;
01414 } else if (iwr.u.data.length >= minlen &&
01415 range->we_version_compiled >= 18) {
01416 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
01417 "WE(source)=%d enc_capa=0x%x",
01418 range->we_version_compiled,
01419 range->we_version_source,
01420 range->enc_capa);
01421 drv->has_capability = 1;
01422 drv->we_version_compiled = range->we_version_compiled;
01423 if (range->enc_capa & IW_ENC_CAPA_WPA) {
01424 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
01425 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
01426 }
01427 if (range->enc_capa & IW_ENC_CAPA_WPA2) {
01428 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
01429 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
01430 }
01431 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
01432 WPA_DRIVER_CAPA_ENC_WEP104;
01433 if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP)
01434 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
01435 if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP)
01436 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
01437 wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x",
01438 drv->capa.key_mgmt, drv->capa.enc);
01439 } else {
01440 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - "
01441 "assuming WPA is not supported");
01442 }
01443
01444 os_free(range);
01445 return 0;
01446 }
01447
01448
01449 static int wpa_driver_wext_set_wpa(void *priv, int enabled)
01450 {
01451 struct wpa_driver_wext_data *drv = priv;
01452 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
01453
01454 return wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED,
01455 enabled);
01456 }
01457
01458
01459 static int wpa_driver_wext_set_key_ext(void *priv, wpa_alg alg,
01460 const u8 *addr, int key_idx,
01461 int set_tx, const u8 *seq,
01462 size_t seq_len,
01463 const u8 *key, size_t key_len)
01464 {
01465 struct wpa_driver_wext_data *drv = priv;
01466 struct iwreq iwr;
01467 int ret = 0;
01468 struct iw_encode_ext *ext;
01469
01470 if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) {
01471 wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu",
01472 __FUNCTION__, (unsigned long) seq_len);
01473 return -1;
01474 }
01475
01476 ext = os_zalloc(sizeof(*ext) + key_len);
01477 if (ext == NULL)
01478 return -1;
01479 os_memset(&iwr, 0, sizeof(iwr));
01480 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01481 iwr.u.encoding.flags = key_idx + 1;
01482 if (alg == WPA_ALG_NONE)
01483 iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
01484 iwr.u.encoding.pointer = (caddr_t) ext;
01485 iwr.u.encoding.length = sizeof(*ext) + key_len;
01486
01487 if (addr == NULL ||
01488 os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
01489 ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
01490 if (set_tx)
01491 ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;
01492
01493 ext->addr.sa_family = ARPHRD_ETHER;
01494 if (addr)
01495 os_memcpy(ext->addr.sa_data, addr, ETH_ALEN);
01496 else
01497 os_memset(ext->addr.sa_data, 0xff, ETH_ALEN);
01498 if (key && key_len) {
01499 os_memcpy(ext + 1, key, key_len);
01500 ext->key_len = key_len;
01501 }
01502 switch (alg) {
01503 case WPA_ALG_NONE:
01504 ext->alg = IW_ENCODE_ALG_NONE;
01505 break;
01506 case WPA_ALG_WEP:
01507 ext->alg = IW_ENCODE_ALG_WEP;
01508 break;
01509 case WPA_ALG_TKIP:
01510 ext->alg = IW_ENCODE_ALG_TKIP;
01511 break;
01512 case WPA_ALG_CCMP:
01513 ext->alg = IW_ENCODE_ALG_CCMP;
01514 break;
01515 default:
01516 wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d",
01517 __FUNCTION__, alg);
01518 os_free(ext);
01519 return -1;
01520 }
01521
01522 if (seq && seq_len) {
01523 ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID;
01524 os_memcpy(ext->rx_seq, seq, seq_len);
01525 }
01526
01527 if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) {
01528 ret = errno == EOPNOTSUPP ? -2 : -1;
01529 if (errno == ENODEV) {
01530
01531
01532
01533 ret = -2;
01534 }
01535
01536 perror("ioctl[SIOCSIWENCODEEXT]");
01537 }
01538
01539 os_free(ext);
01540 return ret;
01541 }
01542
01543
01571 int wpa_driver_wext_set_key(void *priv, wpa_alg alg,
01572 const u8 *addr, int key_idx,
01573 int set_tx, const u8 *seq, size_t seq_len,
01574 const u8 *key, size_t key_len)
01575 {
01576 struct wpa_driver_wext_data *drv = priv;
01577 struct iwreq iwr;
01578 int ret = 0;
01579
01580 wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
01581 "key_len=%lu",
01582 __FUNCTION__, alg, key_idx, set_tx,
01583 (unsigned long) seq_len, (unsigned long) key_len);
01584
01585 ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx,
01586 seq, seq_len, key, key_len);
01587 if (ret == 0)
01588 return 0;
01589
01590 if (ret == -2 &&
01591 (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) {
01592 wpa_printf(MSG_DEBUG, "Driver did not support "
01593 "SIOCSIWENCODEEXT, trying SIOCSIWENCODE");
01594 ret = 0;
01595 } else {
01596 wpa_printf(MSG_DEBUG, "Driver did not support "
01597 "SIOCSIWENCODEEXT");
01598 return ret;
01599 }
01600
01601 os_memset(&iwr, 0, sizeof(iwr));
01602 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01603 iwr.u.encoding.flags = key_idx + 1;
01604 if (alg == WPA_ALG_NONE)
01605 iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
01606 iwr.u.encoding.pointer = (caddr_t) key;
01607 iwr.u.encoding.length = key_len;
01608
01609 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
01610 perror("ioctl[SIOCSIWENCODE]");
01611 ret = -1;
01612 }
01613
01614 if (set_tx && alg != WPA_ALG_NONE) {
01615 os_memset(&iwr, 0, sizeof(iwr));
01616 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01617 iwr.u.encoding.flags = key_idx + 1;
01618 iwr.u.encoding.pointer = (caddr_t) key;
01619 iwr.u.encoding.length = 0;
01620 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
01621 perror("ioctl[SIOCSIWENCODE] (set_tx)");
01622 ret = -1;
01623 }
01624 }
01625
01626 return ret;
01627 }
01628
01629
01630 static int wpa_driver_wext_set_countermeasures(void *priv,
01631 int enabled)
01632 {
01633 struct wpa_driver_wext_data *drv = priv;
01634 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
01635 return wpa_driver_wext_set_auth_param(drv,
01636 IW_AUTH_TKIP_COUNTERMEASURES,
01637 enabled);
01638 }
01639
01640
01641 static int wpa_driver_wext_set_drop_unencrypted(void *priv,
01642 int enabled)
01643 {
01644 struct wpa_driver_wext_data *drv = priv;
01645 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
01646 drv->use_crypt = enabled;
01647 return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED,
01648 enabled);
01649 }
01650
01651
01652 static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv,
01653 const u8 *addr, int cmd, int reason_code)
01654 {
01655 struct iwreq iwr;
01656 struct iw_mlme mlme;
01657 int ret = 0;
01658
01659 os_memset(&iwr, 0, sizeof(iwr));
01660 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01661 os_memset(&mlme, 0, sizeof(mlme));
01662 mlme.cmd = cmd;
01663 mlme.reason_code = reason_code;
01664 mlme.addr.sa_family = ARPHRD_ETHER;
01665 os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN);
01666 iwr.u.data.pointer = (caddr_t) &mlme;
01667 iwr.u.data.length = sizeof(mlme);
01668
01669 if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) {
01670 perror("ioctl[SIOCSIWMLME]");
01671 ret = -1;
01672 }
01673
01674 return ret;
01675 }
01676
01677
01678 static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr,
01679 int reason_code)
01680 {
01681 struct wpa_driver_wext_data *drv = priv;
01682 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
01683 return wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code);
01684 }
01685
01686
01687 static int wpa_driver_wext_disassociate(void *priv, const u8 *addr,
01688 int reason_code)
01689 {
01690 struct wpa_driver_wext_data *drv = priv;
01691 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
01692 return wpa_driver_wext_mlme(drv, addr, IW_MLME_DISASSOC,
01693 reason_code);
01694 }
01695
01696
01697 static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie,
01698 size_t ie_len)
01699 {
01700 struct wpa_driver_wext_data *drv = priv;
01701 struct iwreq iwr;
01702 int ret = 0;
01703
01704 os_memset(&iwr, 0, sizeof(iwr));
01705 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01706 iwr.u.data.pointer = (caddr_t) ie;
01707 iwr.u.data.length = ie_len;
01708
01709 if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) {
01710 perror("ioctl[SIOCSIWGENIE]");
01711 ret = -1;
01712 }
01713
01714 return ret;
01715 }
01716
01717
01718 static int wpa_driver_wext_cipher2wext(int cipher)
01719 {
01720 switch (cipher) {
01721 case CIPHER_NONE:
01722 return IW_AUTH_CIPHER_NONE;
01723 case CIPHER_WEP40:
01724 return IW_AUTH_CIPHER_WEP40;
01725 case CIPHER_TKIP:
01726 return IW_AUTH_CIPHER_TKIP;
01727 case CIPHER_CCMP:
01728 return IW_AUTH_CIPHER_CCMP;
01729 case CIPHER_WEP104:
01730 return IW_AUTH_CIPHER_WEP104;
01731 default:
01732 return 0;
01733 }
01734 }
01735
01736
01737 static int wpa_driver_wext_keymgmt2wext(int keymgmt)
01738 {
01739 switch (keymgmt) {
01740 case KEY_MGMT_802_1X:
01741 return IW_AUTH_KEY_MGMT_802_1X;
01742 case KEY_MGMT_PSK:
01743 return IW_AUTH_KEY_MGMT_PSK;
01744 default:
01745 return 0;
01746 }
01747 }
01748
01749
01750 static int
01751 wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv,
01752 struct wpa_driver_associate_params *params)
01753 {
01754 struct iwreq iwr;
01755 int ret = 0;
01756
01757 wpa_printf(MSG_DEBUG, "WEXT: Driver did not support "
01758 "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE");
01759
01760 os_memset(&iwr, 0, sizeof(iwr));
01761 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01762
01763 iwr.u.encoding.flags = 0;
01764 iwr.u.encoding.pointer = (caddr_t) NULL;
01765 iwr.u.encoding.length = 0;
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776 if (!drv->use_crypt) {
01777 iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
01778 } else {
01779 if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
01780 iwr.u.encoding.flags |= IW_ENCODE_OPEN;
01781 if (params->auth_alg & AUTH_ALG_SHARED_KEY)
01782 iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED;
01783 }
01784
01785 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
01786 perror("ioctl[SIOCSIWENCODE]");
01787 ret = -1;
01788 }
01789
01790 return ret;
01791 }
01792
01793
01794 static int
01795 wpa_driver_wext_associate(void *priv,
01796 struct wpa_driver_associate_params *params)
01797 {
01798 struct wpa_driver_wext_data *drv = priv;
01799 int ret = 0;
01800 int allow_unencrypted_eapol;
01801 int value;
01802
01803 wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
01804
01805
01806
01807
01808
01809 if (drv->auth_alg_fallback &&
01810 wpa_driver_wext_auth_alg_fallback(drv, params) < 0)
01811 ret = -1;
01812
01813 if (!params->bssid &&
01814 wpa_driver_wext_set_bssid(drv, NULL) < 0)
01815 ret = -1;
01816
01817 if (wpa_driver_wext_set_mode(drv, params->mode) < 0)
01818 ret = -1;
01819
01820
01821
01822 if (wpa_driver_wext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len)
01823 < 0)
01824 ret = -1;
01825 if (params->wpa_ie == NULL || params->wpa_ie_len == 0)
01826 value = IW_AUTH_WPA_VERSION_DISABLED;
01827 else if (params->wpa_ie[0] == RSN_INFO_ELEM)
01828 value = IW_AUTH_WPA_VERSION_WPA2;
01829 else
01830 value = IW_AUTH_WPA_VERSION_WPA;
01831 if (wpa_driver_wext_set_auth_param(drv,
01832 IW_AUTH_WPA_VERSION, value) < 0)
01833 ret = -1;
01834 value = wpa_driver_wext_cipher2wext(params->pairwise_suite);
01835 if (wpa_driver_wext_set_auth_param(drv,
01836 IW_AUTH_CIPHER_PAIRWISE, value) < 0)
01837 ret = -1;
01838 value = wpa_driver_wext_cipher2wext(params->group_suite);
01839 if (wpa_driver_wext_set_auth_param(drv,
01840 IW_AUTH_CIPHER_GROUP, value) < 0)
01841 ret = -1;
01842 value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite);
01843 if (wpa_driver_wext_set_auth_param(drv,
01844 IW_AUTH_KEY_MGMT, value) < 0)
01845 ret = -1;
01846 value = params->key_mgmt_suite != KEY_MGMT_NONE ||
01847 params->pairwise_suite != CIPHER_NONE ||
01848 params->group_suite != CIPHER_NONE ||
01849 params->wpa_ie_len;
01850 if (wpa_driver_wext_set_auth_param(drv,
01851 IW_AUTH_PRIVACY_INVOKED, value) < 0)
01852 ret = -1;
01853
01854
01855
01856
01857 if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
01858 params->key_mgmt_suite == KEY_MGMT_PSK)
01859 allow_unencrypted_eapol = 0;
01860 else
01861 allow_unencrypted_eapol = 1;
01862
01863 if (wpa_driver_wext_set_auth_param(drv,
01864 IW_AUTH_RX_UNENCRYPTED_EAPOL,
01865 allow_unencrypted_eapol) < 0)
01866 ret = -1;
01867 if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0)
01868 ret = -1;
01869 if (wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
01870 ret = -1;
01871 if (params->bssid &&
01872 wpa_driver_wext_set_bssid(drv, params->bssid) < 0)
01873 ret = -1;
01874
01875 return ret;
01876 }
01877
01878
01879 static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg)
01880 {
01881 struct wpa_driver_wext_data *drv = priv;
01882 int algs = 0, res;
01883
01884 if (auth_alg & AUTH_ALG_OPEN_SYSTEM)
01885 algs |= IW_AUTH_ALG_OPEN_SYSTEM;
01886 if (auth_alg & AUTH_ALG_SHARED_KEY)
01887 algs |= IW_AUTH_ALG_SHARED_KEY;
01888 if (auth_alg & AUTH_ALG_LEAP)
01889 algs |= IW_AUTH_ALG_LEAP;
01890 if (algs == 0) {
01891
01892 algs = IW_AUTH_ALG_OPEN_SYSTEM;
01893 }
01894
01895 res = wpa_driver_wext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG,
01896 algs);
01897 drv->auth_alg_fallback = res == -2;
01898 return res;
01899 }
01900
01901
01909 int wpa_driver_wext_set_mode(void *priv, int mode)
01910 {
01911 struct wpa_driver_wext_data *drv = priv;
01912 struct iwreq iwr;
01913 int ret = 0;
01914
01915 os_memset(&iwr, 0, sizeof(iwr));
01916 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01917 iwr.u.mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
01918
01919 if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
01920 perror("ioctl[SIOCSIWMODE]");
01921 ret = -1;
01922 }
01923
01924 return ret;
01925 }
01926
01927
01928 static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv,
01929 u32 cmd, const u8 *bssid, const u8 *pmkid)
01930 {
01931 struct iwreq iwr;
01932 struct iw_pmksa pmksa;
01933 int ret = 0;
01934
01935 os_memset(&iwr, 0, sizeof(iwr));
01936 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
01937 os_memset(&pmksa, 0, sizeof(pmksa));
01938 pmksa.cmd = cmd;
01939 pmksa.bssid.sa_family = ARPHRD_ETHER;
01940 if (bssid)
01941 os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN);
01942 if (pmkid)
01943 os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN);
01944 iwr.u.data.pointer = (caddr_t) &pmksa;
01945 iwr.u.data.length = sizeof(pmksa);
01946
01947 if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) {
01948 if (errno != EOPNOTSUPP)
01949 perror("ioctl[SIOCSIWPMKSA]");
01950 ret = -1;
01951 }
01952
01953 return ret;
01954 }
01955
01956
01957 static int wpa_driver_wext_add_pmkid(void *priv, const u8 *bssid,
01958 const u8 *pmkid)
01959 {
01960 struct wpa_driver_wext_data *drv = priv;
01961 return wpa_driver_wext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid);
01962 }
01963
01964
01965 static int wpa_driver_wext_remove_pmkid(void *priv, const u8 *bssid,
01966 const u8 *pmkid)
01967 {
01968 struct wpa_driver_wext_data *drv = priv;
01969 return wpa_driver_wext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid);
01970 }
01971
01972
01973 static int wpa_driver_wext_flush_pmkid(void *priv)
01974 {
01975 struct wpa_driver_wext_data *drv = priv;
01976 return wpa_driver_wext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL);
01977 }
01978
01979
01980 static int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa)
01981 {
01982 struct wpa_driver_wext_data *drv = priv;
01983 if (!drv->has_capability)
01984 return -1;
01985 os_memcpy(capa, &drv->capa, sizeof(*capa));
01986 return 0;
01987 }
01988
01989
01990 int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv,
01991 const char *ifname)
01992 {
01993 if (ifname == NULL) {
01994 drv->ifindex2 = -1;
01995 return 0;
01996 }
01997
01998 drv->ifindex2 = if_nametoindex(ifname);
01999 if (drv->ifindex2 <= 0)
02000 return -1;
02001
02002 wpa_printf(MSG_DEBUG, "Added alternative ifindex %d (%s) for "
02003 "wireless events", drv->ifindex2, ifname);
02004
02005 return 0;
02006 }
02007
02008
02009 int wpa_driver_wext_set_operstate(void *priv, int state)
02010 {
02011 struct wpa_driver_wext_data *drv = priv;
02012
02013 wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
02014 __func__, drv->operstate, state, state ? "UP" : "DORMANT");
02015 drv->operstate = state;
02016 return wpa_driver_wext_send_oper_ifla(
02017 drv, -1, state ? IF_OPER_UP : IF_OPER_DORMANT);
02018 }
02019
02020
02021 #ifdef CONFIG_CLIENT_MLME
02022 static int hostapd_ioctl(struct wpa_driver_wext_data *drv,
02023 struct prism2_hostapd_param *param, int len)
02024 {
02025 struct iwreq iwr;
02026
02027 os_memset(&iwr, 0, sizeof(iwr));
02028 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
02029 iwr.u.data.pointer = (caddr_t) param;
02030 iwr.u.data.length = len;
02031
02032 if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
02033 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
02034 return -1;
02035 }
02036
02037 return 0;
02038 }
02039
02040
02041 static struct wpa_hw_modes *
02042 wpa_driver_wext_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
02043 {
02044 struct wpa_driver_wext_data *drv = priv;
02045 struct prism2_hostapd_param *param;
02046 u8 *pos, *end;
02047 struct wpa_hw_modes *modes = NULL;
02048 int i;
02049
02050 param = os_zalloc(PRISM2_HOSTAPD_MAX_BUF_SIZE);
02051 if (param == NULL)
02052 return NULL;
02053 param->cmd = PRISM2_HOSTAPD_GET_HW_FEATURES;
02054
02055 if (hostapd_ioctl(drv, param, PRISM2_HOSTAPD_MAX_BUF_SIZE) < 0) {
02056 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
02057 goto out;
02058 }
02059
02060 *num_modes = param->u.hw_features.num_modes;
02061 *flags = param->u.hw_features.flags;
02062
02063 pos = param->u.hw_features.data;
02064 end = pos + PRISM2_HOSTAPD_MAX_BUF_SIZE -
02065 (param->u.hw_features.data - (u8 *) param);
02066
02067 modes = os_zalloc(*num_modes * sizeof(struct wpa_hw_modes));
02068 if (modes == NULL)
02069 goto out;
02070
02071 for (i = 0; i < *num_modes; i++) {
02072 struct hostapd_ioctl_hw_modes_hdr *hdr;
02073 struct wpa_hw_modes *feature;
02074 int clen, rlen;
02075
02076 hdr = (struct hostapd_ioctl_hw_modes_hdr *) pos;
02077 pos = (u8 *) (hdr + 1);
02078 clen = hdr->num_channels * sizeof(struct wpa_channel_data);
02079 rlen = hdr->num_rates * sizeof(struct wpa_rate_data);
02080
02081 feature = &modes[i];
02082 switch (hdr->mode) {
02083 case MODE_IEEE80211A:
02084 feature->mode = WPA_MODE_IEEE80211A;
02085 break;
02086 case MODE_IEEE80211B:
02087 feature->mode = WPA_MODE_IEEE80211B;
02088 break;
02089 case MODE_IEEE80211G:
02090 feature->mode = WPA_MODE_IEEE80211G;
02091 break;
02092 case MODE_ATHEROS_TURBO:
02093 case MODE_ATHEROS_TURBOG:
02094 wpa_printf(MSG_ERROR, "Skip unsupported hw_mode=%d in "
02095 "get_hw_features data", hdr->mode);
02096 pos += clen + rlen;
02097 continue;
02098 default:
02099 wpa_printf(MSG_ERROR, "Unknown hw_mode=%d in "
02100 "get_hw_features data", hdr->mode);
02101 ieee80211_sta_free_hw_features(modes, *num_modes);
02102 modes = NULL;
02103 break;
02104 }
02105 feature->num_channels = hdr->num_channels;
02106 feature->num_rates = hdr->num_rates;
02107
02108 feature->channels = os_malloc(clen);
02109 feature->rates = os_malloc(rlen);
02110 if (!feature->channels || !feature->rates) {
02111 ieee80211_sta_free_hw_features(modes, *num_modes);
02112 modes = NULL;
02113 break;
02114 }
02115
02116 os_memcpy(feature->channels, pos, clen);
02117 pos += clen;
02118 os_memcpy(feature->rates, pos, rlen);
02119 pos += rlen;
02120 }
02121
02122 out:
02123 os_free(param);
02124 return modes;
02125 }
02126
02127
02128 int wpa_driver_wext_set_channel(void *priv, wpa_hw_mode phymode, int chan,
02129 int freq)
02130 {
02131 return wpa_driver_wext_set_freq(priv, freq);
02132 }
02133
02134
02135 static void wpa_driver_wext_mlme_read(int sock, void *eloop_ctx,
02136 void *sock_ctx)
02137 {
02138 struct wpa_driver_wext_data *drv = eloop_ctx;
02139 int len;
02140 unsigned char buf[3000];
02141 struct ieee80211_frame_info *fi;
02142 struct ieee80211_rx_status rx_status;
02143
02144 len = recv(sock, buf, sizeof(buf), 0);
02145 if (len < 0) {
02146 perror("recv[MLME]");
02147 return;
02148 }
02149
02150 if (len < (int) sizeof(struct ieee80211_frame_info)) {
02151 wpa_printf(MSG_DEBUG, "WEXT: Too short MLME frame (len=%d)",
02152 len);
02153 return;
02154 }
02155
02156 fi = (struct ieee80211_frame_info *) buf;
02157 if (ntohl(fi->version) != IEEE80211_FI_VERSION) {
02158 wpa_printf(MSG_DEBUG, "WEXT: Invalid MLME frame info version "
02159 "0x%x", ntohl(fi->version));
02160 return;
02161 }
02162
02163 os_memset(&rx_status, 0, sizeof(rx_status));
02164 rx_status.ssi = ntohl(fi->ssi_signal);
02165 rx_status.channel = ntohl(fi->channel);
02166
02167 ieee80211_sta_rx(drv->ctx, buf + sizeof(struct ieee80211_frame_info),
02168 len - sizeof(struct ieee80211_frame_info),
02169 &rx_status);
02170 }
02171
02172
02173 static int wpa_driver_wext_open_mlme(struct wpa_driver_wext_data *drv)
02174 {
02175 int flags, ifindex, s, *i;
02176 struct sockaddr_ll addr;
02177 struct iwreq iwr;
02178
02179 os_memset(&iwr, 0, sizeof(iwr));
02180 os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
02181 i = (int *) iwr.u.name;
02182 *i++ = PRISM2_PARAM_USER_SPACE_MLME;
02183 *i++ = 1;
02184
02185 if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {
02186 wpa_printf(MSG_ERROR, "WEXT: Failed to configure driver to "
02187 "use user space MLME");
02188 return -1;
02189 }
02190
02191 ifindex = if_nametoindex(drv->mlmedev);
02192 if (ifindex == 0) {
02193 wpa_printf(MSG_ERROR, "WEXT: mlmedev='%s' not found",
02194 drv->mlmedev);
02195 return -1;
02196 }
02197
02198 if (wpa_driver_wext_get_ifflags_ifname(drv, drv->mlmedev, &flags) != 0
02199 || wpa_driver_wext_set_ifflags_ifname(drv, drv->mlmedev,
02200 flags | IFF_UP) != 0) {
02201 wpa_printf(MSG_ERROR, "WEXT: Could not set interface "
02202 "'%s' UP", drv->mlmedev);
02203 return -1;
02204 }
02205
02206 s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
02207 if (s < 0) {
02208 perror("socket[PF_PACKET,SOCK_RAW]");
02209 return -1;
02210 }
02211
02212 os_memset(&addr, 0, sizeof(addr));
02213 addr.sll_family = AF_PACKET;
02214 addr.sll_ifindex = ifindex;
02215
02216 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
02217 perror("bind(MLME)");
02218 return -1;
02219 }
02220
02221 if (eloop_register_read_sock(s, wpa_driver_wext_mlme_read, drv, NULL))
02222 {
02223 wpa_printf(MSG_ERROR, "WEXT: Could not register MLME read "
02224 "socket");
02225 close(s);
02226 return -1;
02227 }
02228
02229 return s;
02230 }
02231
02232
02233 static int wpa_driver_wext_send_mlme(void *priv, const u8 *data,
02234 size_t data_len)
02235 {
02236 struct wpa_driver_wext_data *drv = priv;
02237 int ret;
02238
02239 ret = send(drv->mlme_sock, data, data_len, 0);
02240 if (ret < 0) {
02241 perror("send[MLME]");
02242 return -1;
02243 }
02244
02245 return 0;
02246 }
02247
02248
02249 static int wpa_driver_wext_mlme_add_sta(void *priv, const u8 *addr,
02250 const u8 *supp_rates,
02251 size_t supp_rates_len)
02252 {
02253 struct wpa_driver_wext_data *drv = priv;
02254 struct prism2_hostapd_param param;
02255 size_t len;
02256
02257 os_memset(¶m, 0, sizeof(param));
02258 param.cmd = PRISM2_HOSTAPD_ADD_STA;
02259 os_memcpy(param.sta_addr, addr, ETH_ALEN);
02260 len = supp_rates_len;
02261 if (len > sizeof(param.u.add_sta.supp_rates))
02262 len = sizeof(param.u.add_sta.supp_rates);
02263 os_memcpy(param.u.add_sta.supp_rates, supp_rates, len);
02264 return hostapd_ioctl(drv, ¶m, sizeof(param));
02265 }
02266
02267
02268 static int wpa_driver_wext_mlme_remove_sta(void *priv, const u8 *addr)
02269 {
02270 struct wpa_driver_wext_data *drv = priv;
02271 struct prism2_hostapd_param param;
02272
02273 os_memset(¶m, 0, sizeof(param));
02274 param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
02275 os_memcpy(param.sta_addr, addr, ETH_ALEN);
02276 return hostapd_ioctl(drv, ¶m, sizeof(param));
02277 }
02278
02279 #endif
02280
02281
02282 static int wpa_driver_wext_set_param(void *priv, const char *param)
02283 {
02284 #ifdef CONFIG_CLIENT_MLME
02285 struct wpa_driver_wext_data *drv = priv;
02286 const char *pos, *pos2;
02287 size_t len;
02288
02289 if (param == NULL)
02290 return 0;
02291
02292 wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
02293
02294 pos = os_strstr(param, "mlmedev=");
02295 if (pos) {
02296 pos += 8;
02297 pos2 = os_strchr(pos, ' ');
02298 if (pos2)
02299 len = pos2 - pos;
02300 else
02301 len = os_strlen(pos);
02302 if (len + 1 > sizeof(drv->mlmedev))
02303 return -1;
02304 os_memcpy(drv->mlmedev, pos, len);
02305 drv->mlmedev[len] = '\0';
02306 wpa_printf(MSG_DEBUG, "WEXT: Using user space MLME with "
02307 "mlmedev='%s'", drv->mlmedev);
02308 drv->capa.flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME;
02309
02310 drv->mlme_sock = wpa_driver_wext_open_mlme(drv);
02311 if (drv->mlme_sock < 0)
02312 return -1;
02313 }
02314 #endif
02315
02316 return 0;
02317 }
02318
02319
02320 int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv)
02321 {
02322 return drv->we_version_compiled;
02323 }
02324
02325
02326 const struct wpa_driver_ops wpa_driver_wext_ops = {
02327 .name = "wext",
02328 .desc = "Linux wireless extensions (generic)",
02329 .get_bssid = wpa_driver_wext_get_bssid,
02330 .get_ssid = wpa_driver_wext_get_ssid,
02331 .set_wpa = wpa_driver_wext_set_wpa,
02332 .set_key = wpa_driver_wext_set_key,
02333 .set_countermeasures = wpa_driver_wext_set_countermeasures,
02334 .set_drop_unencrypted = wpa_driver_wext_set_drop_unencrypted,
02335 .scan = wpa_driver_wext_scan,
02336 .get_scan_results = wpa_driver_wext_get_scan_results,
02337 .deauthenticate = wpa_driver_wext_deauthenticate,
02338 .disassociate = wpa_driver_wext_disassociate,
02339 .associate = wpa_driver_wext_associate,
02340 .set_auth_alg = wpa_driver_wext_set_auth_alg,
02341 .init = wpa_driver_wext_init,
02342 .deinit = wpa_driver_wext_deinit,
02343 .set_param = wpa_driver_wext_set_param,
02344 .add_pmkid = wpa_driver_wext_add_pmkid,
02345 .remove_pmkid = wpa_driver_wext_remove_pmkid,
02346 .flush_pmkid = wpa_driver_wext_flush_pmkid,
02347 .get_capa = wpa_driver_wext_get_capa,
02348 .set_operstate = wpa_driver_wext_set_operstate,
02349 #ifdef CONFIG_CLIENT_MLME
02350 .get_hw_feature_data = wpa_driver_wext_get_hw_feature_data,
02351 .set_channel = wpa_driver_wext_set_channel,
02352 .set_ssid = wpa_driver_wext_set_ssid,
02353 .set_bssid = wpa_driver_wext_set_bssid,
02354 .send_mlme = wpa_driver_wext_send_mlme,
02355 .mlme_add_sta = wpa_driver_wext_mlme_add_sta,
02356 .mlme_remove_sta = wpa_driver_wext_mlme_remove_sta,
02357 #endif
02358 };
02359