diff options
Diffstat (limited to 'src/drivers/driver_ralink.c')
-rw-r--r-- | src/drivers/driver_ralink.c | 654 |
1 files changed, 324 insertions, 330 deletions
diff --git a/src/drivers/driver_ralink.c b/src/drivers/driver_ralink.c index e9313cb..09d1ef5 100644 --- a/src/drivers/driver_ralink.c +++ b/src/drivers/driver_ralink.c @@ -22,8 +22,10 @@ #include "driver.h" #include "l2_packet/l2_packet.h" #include "eloop.h" -#include "ieee802_11_defs.h" +#include "common/ieee802_11_defs.h" #include "priv_netlink.h" +#include "netlink.h" +#include "linux_ioctl.h" #include "driver_ralink.h" static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx); @@ -33,7 +35,7 @@ static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx); struct wpa_driver_ralink_data { void *ctx; int ioctl_sock; - int event_sock; + struct netlink_data *netlink; char ifname[IFNAMSIZ + 1]; u8 *assoc_req_ies; size_t assoc_req_ies_len; @@ -45,6 +47,7 @@ struct wpa_driver_ralink_data { int ap_scan; int scanning_done; u8 g_driver_down; + BOOLEAN bAddWepKey; }; static int ralink_set_oid(struct wpa_driver_ralink_data *drv, @@ -450,6 +453,7 @@ wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv, void *ctx, char *custom) { union wpa_event_data data; + u8 *req_ies = NULL, *resp_ies = NULL; wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); @@ -478,12 +482,12 @@ wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv, */ bytes = drv->assoc_req_ies_len; - data.assoc_info.req_ies = os_malloc(bytes); - if (data.assoc_info.req_ies == NULL) + req_ies = os_malloc(bytes); + if (req_ies == NULL) return; - + os_memcpy(req_ies, spos, bytes); + data.assoc_info.req_ies = req_ies; data.assoc_info.req_ies_len = bytes; - os_memcpy(data.assoc_info.req_ies, spos, bytes); /* skip the '\0' byte */ spos += bytes + 1; @@ -499,21 +503,48 @@ wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv, if (!bytes) goto done; - - data.assoc_info.resp_ies = os_malloc(bytes); - if (data.assoc_info.resp_ies == NULL) + resp_ies = os_malloc(bytes); + if (resp_ies == NULL) goto done; - + os_memcpy(resp_ies, spos, bytes); + data.assoc_info.resp_ies = resp_ies; data.assoc_info.resp_ies_len = bytes; - os_memcpy(data.assoc_info.resp_ies, spos, bytes); } wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); - /* free allocated memory */ done: - os_free(data.assoc_info.resp_ies); - os_free(data.assoc_info.req_ies); + /* free allocated memory */ + os_free(resp_ies); + os_free(req_ies); + } +} + +static void ralink_interface_up(struct wpa_driver_ralink_data *drv) +{ + union wpa_event_data event; + int enable_wpa_supplicant = 0; + drv->g_driver_down = 0; + os_memset(&event, 0, sizeof(event)); + os_snprintf(event.interface_status.ifname, + sizeof(event.interface_status.ifname), "%s", drv->ifname); + + event.interface_status.ievent = EVENT_INTERFACE_ADDED; + wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); + + if (drv->ap_scan == 1) + enable_wpa_supplicant = 1; + else + enable_wpa_supplicant = 2; + /* trigger driver support wpa_supplicant */ + if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, + (PCHAR) &enable_wpa_supplicant, sizeof(UCHAR)) < 0) + { + wpa_printf(MSG_INFO, "RALINK: Failed to set " + "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)", + (int) enable_wpa_supplicant); + wpa_printf(MSG_ERROR, "ralink. Driver does not support " + "wpa_supplicant"); } } @@ -580,33 +611,9 @@ wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv, } if (iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) { + wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); wpa_printf(MSG_DEBUG, "Custom wireless event: " "receive ASSOCIATED_EVENT !!!"); - /* determine whether the dynamic-WEP is used or - * not */ -#if 0 - if (wpa_s && wpa_s->current_ssid && - wpa_s->current_ssid->key_mgmt == - WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if ((wpa_s->current_ssid->eapol_flags & - (EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) { - //wpa_printf(MSG_DEBUG, "The current ssid - (%s), eapol_flag = %d.\n", - // wpa_ssid_txt(wpa_s->current_ssid->ssid, wpa_s->current_ssid->ssid_len),wpa_s->current_ssid->eapol_flags); - ieee8021x_required_key = TRUE; - } - - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, (char *) &ieee8021x_required_key, sizeof(BOOLEAN)) < 0) - { - wpa_printf(MSG_DEBUG, "ERROR: Failed to set OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", - (int) ieee8021x_required_key); - } - - wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s and eapol_flag(%d).\n", ieee8021x_required_key ? "TRUE" : "FALSE", - wpa_s->current_ssid->eapol_flags); - } -#endif - - wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); } else if (iwe->u.data.flags == RT_REQIE_EVENT_FLAG) { wpa_printf(MSG_DEBUG, "Custom wireless event: " "receive ReqIEs !!!"); @@ -689,51 +696,8 @@ wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv, } else if (iwe->u.data.flags == RT_INTERFACE_DOWN) { drv->g_driver_down = 1; eloop_terminate(); - } else if (iwe->u.data.flags == RT_REPORT_AP_INFO) { - if (drv->ap_scan != 1) { - typedef struct PACKED { - UCHAR bssid[MAC_ADDR_LEN]; - UCHAR ssid[MAX_LEN_OF_SSID]; - INT ssid_len; - UCHAR wpa_ie[40]; - INT wpa_ie_len; - UCHAR rsn_ie[40]; - INT rsn_ie_len; - INT freq; - USHORT caps; - } *PAPINFO; - - wpa_printf(MSG_DEBUG, "Custom wireless" - " event: receive " - "RT_REPORT_AP_INFO !!!"); - //printf("iwe->u.data.length = %d\n", iwe->u.data.length); - //wpa_hexdump(MSG_DEBUG, "AP_Info: ", buf, iwe->u.data.length); -#if 0 - wpa_s->num_scan_results = 1; - if (wpa_s->scan_results) - os_free(wpa_s->scan_results); - wpa_s->scan_results = os_malloc(sizeof(struct wpa_scan_result) + 1); - if (wpa_s->scan_results) { - PAPINFO pApInfo = (PAPINFO)buf; - os_memcpy(wpa_s->scan_results[0].bssid, pApInfo->bssid, ETH_ALEN); - os_memcpy(wpa_s->scan_results[0].ssid, pApInfo->ssid, pApInfo->ssid_len); - wpa_s->scan_results[0].ssid_len = pApInfo->ssid_len; - if (pApInfo->wpa_ie_len > 0) { - os_memcpy(wpa_s->scan_results[0].wpa_ie, pApInfo->wpa_ie, pApInfo->wpa_ie_len); - wpa_s->scan_results[0].wpa_ie_len = pApInfo->wpa_ie_len; - } else if (pApInfo->rsn_ie_len > 0) { - os_memcpy(wpa_s->scan_results[0].rsn_ie, pApInfo->rsn_ie, pApInfo->rsn_ie_len); - wpa_s->scan_results[0].rsn_ie_len = pApInfo->rsn_ie_len; - } - wpa_s->scan_results[0].caps = pApInfo->caps; - wpa_s->scan_results[0].freq = pApInfo->freq; - } else { - wpa_printf("wpa_s->scan_" - "results fail to " - "os_malloc!!\n"); - } -#endif - } + } else if (iwe->u.data.flags == RT_INTERFACE_UP) { + ralink_interface_up(drv); } else { wpa_driver_ralink_event_wireless_custom( drv, ctx, buf); @@ -747,29 +711,20 @@ wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv, } static void -wpa_driver_ralink_event_rtm_newlink(struct wpa_driver_ralink_data *drv, - void *ctx, struct nlmsghdr *h, int len) +wpa_driver_ralink_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, + u8 *buf, size_t len) { - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr * attr; + struct wpa_driver_ralink_data *drv = ctx; + int attrlen, rta_len; + struct rtattr *attr; wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - if (len < (int) sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); wpa_hexdump(MSG_DEBUG, "ifi: ", (u8 *) ifi, sizeof(struct ifinfomsg)); - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; + attrlen = len; wpa_printf(MSG_DEBUG, "attrlen=%d", attrlen); - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); + attr = (struct rtattr *) buf; wpa_hexdump(MSG_DEBUG, "attr1: ", (u8 *) attr, sizeof(struct rtattr)); rta_len = RTA_ALIGN(sizeof(struct rtattr)); wpa_hexdump(MSG_DEBUG, "attr2: ", (u8 *)attr,rta_len); @@ -787,60 +742,6 @@ wpa_driver_ralink_event_rtm_newlink(struct wpa_driver_ralink_data *drv, } } -static void wpa_driver_ralink_event_receive(int sock, void *ctx, - void *sock_ctx) -{ - char buf[8192]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - wpa_hexdump(MSG_DEBUG, "h: ", (u8 *)h, h->nlmsg_len); - - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - wpa_printf(MSG_DEBUG, "Malformed netlink message: " - "len=%d left=%d plen=%d", len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - wpa_driver_ralink_event_rtm_newlink(ctx, sock_ctx, h, - plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink " - "message", left); - } - -} - static int ralink_get_we_version_compiled(struct wpa_driver_ralink_data *drv) { @@ -862,45 +763,13 @@ ralink_get_we_version_compiled(struct wpa_driver_ralink_data *drv) return 0; } -static int -ralink_set_iface_flags(void *priv, int dev_up) -{ - struct wpa_driver_ralink_data *drv = priv; - struct ifreq ifr; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->ioctl_sock < 0) - return -1; - - os_memset(&ifr, 0, sizeof(ifr)); - os_snprintf(ifr.ifr_name, IFNAMSIZ, "%s", drv->ifname); - - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - return 0; -} - static void * wpa_driver_ralink_init(void *ctx, const char *ifname) { int s; struct wpa_driver_ralink_data *drv; struct ifreq ifr; - struct sockaddr_nl local; UCHAR enable_wpa_supplicant = 0; + struct netlink_config *cfg; wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); @@ -928,31 +797,25 @@ static void * wpa_driver_ralink_init(void *ctx, const char *ifname) drv->ioctl_sock = s; drv->g_driver_down = 0; - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); + cfg = os_zalloc(sizeof(*cfg)); + if (cfg == NULL) { close(drv->ioctl_sock); os_free(drv); return NULL; } - - os_memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); + cfg->ctx = drv; + cfg->newlink_cb = wpa_driver_ralink_event_rtm_newlink; + drv->netlink = netlink_init(cfg); + if (drv->netlink == NULL) { + os_free(cfg); close(drv->ioctl_sock); os_free(drv); return NULL; } - eloop_register_read_sock(s, wpa_driver_ralink_event_receive, drv, ctx); - drv->event_sock = s; drv->no_of_pmkid = 4; /* Number of PMKID saved supported */ - ralink_set_iface_flags(drv, 1); /* mark up during setup */ + linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1); ralink_get_we_version_compiled(drv); wpa_driver_ralink_flush_pmkid(drv); @@ -1003,12 +866,11 @@ static void wpa_driver_ralink_deinit(void *priv) wpa_driver_ralink_flush_pmkid(drv); sleep(1); - ralink_set_iface_flags(drv, 0); + /* linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); */ } eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx); - eloop_unregister_read_sock(drv->event_sock); - close(drv->event_sock); + netlink_deinit(drv->netlink); close(drv->ioctl_sock); os_free(drv); } @@ -1026,7 +888,8 @@ static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx) } -static int wpa_driver_ralink_scan(void *priv, const u8 *ssid, size_t ssid_len) +static int wpa_driver_ralink_scan(void *priv, + struct wpa_driver_scan_params *params) { struct wpa_driver_ralink_data *drv = priv; struct iwreq iwr; @@ -1037,6 +900,7 @@ static int wpa_driver_ralink_scan(void *priv, const u8 *ssid, size_t ssid_len) wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); +#if 0 if (ssid_len > IW_ESSID_MAX_SIZE) { wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", __FUNCTION__, (unsigned long) ssid_len); @@ -1044,6 +908,14 @@ static int wpa_driver_ralink_scan(void *priv, const u8 *ssid, size_t ssid_len) } /* wpa_driver_ralink_set_ssid(drv, ssid, ssid_len); */ +#endif + + if (ralink_set_oid(drv, RT_OID_WPS_PROBE_REQ_IE, + (char *) params->extra_ies, params->extra_ies_len) < + 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "RT_OID_WPS_PROBE_REQ_IE"); + } os_memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); @@ -1064,96 +936,124 @@ static int wpa_driver_ralink_scan(void *priv, const u8 *ssid, size_t ssid_len) return ret; } -static int -wpa_driver_ralink_get_scan_results(void *priv, - struct wpa_scan_result *results, - size_t max_size) +static struct wpa_scan_results * +wpa_driver_ralink_get_scan_results(void *priv) { struct wpa_driver_ralink_data *drv = priv; UCHAR *buf = NULL; + size_t buf_len; NDIS_802_11_BSSID_LIST_EX *wsr; NDIS_WLAN_BSSID_EX *wbi; struct iwreq iwr; - int rv = 0; size_t ap_num; - u8 *pos, *end; + u8 *pos; + struct wpa_scan_results *res; if (drv->g_driver_down == 1) - return -1; + return NULL; wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - if (drv->we_version_compiled >= 17) { - buf = os_zalloc(8192); - iwr.u.data.length = 8192; - } else { - buf = os_zalloc(4096); - iwr.u.data.length = 4096; - } - if (buf == NULL) - return -1; + if (drv->we_version_compiled >= 17) + buf_len = 8192; + else + buf_len = 4096; - wsr = (NDIS_802_11_BSSID_LIST_EX *) buf; + for (;;) { + buf = os_zalloc(buf_len); + iwr.u.data.length = buf_len; + if (buf == NULL) + return NULL; - wsr->NumberOfItems = 0; - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (void *) buf; - iwr.u.data.flags = OID_802_11_BSSID_LIST; + wsr = (NDIS_802_11_BSSID_LIST_EX *) buf; - if ((rv = ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr)) < 0) { - wpa_printf(MSG_DEBUG, "ioctl fail: rv = %d", rv); + wsr->NumberOfItems = 0; + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + iwr.u.data.pointer = (void *) buf; + iwr.u.data.flags = OID_802_11_BSSID_LIST; + + if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) == 0) + break; + + if (errno == E2BIG && buf_len < 65535) { + os_free(buf); + buf = NULL; + buf_len *= 2; + if (buf_len > 65535) + buf_len = 65535; /* 16-bit length field */ + wpa_printf(MSG_DEBUG, "Scan results did not fit - " + "trying larger buffer (%lu bytes)", + (unsigned long) buf_len); + } else { + perror("ioctl[RT_PRIV_IOCTL]"); + os_free(buf); + return NULL; + } + } + + res = os_zalloc(sizeof(*res)); + if (res == NULL) { os_free(buf); - return -1; + return NULL; } - os_memset(results, 0, max_size * sizeof(struct wpa_scan_result)); + res->res = os_zalloc(wsr->NumberOfItems * + sizeof(struct wpa_scan_res *)); + if (res->res == NULL) { + os_free(res); + os_free(buf); + return NULL; + } for (ap_num = 0, wbi = wsr->Bssid; ap_num < wsr->NumberOfItems; ++ap_num) { - os_memcpy(results[ap_num].bssid, &wbi->MacAddress, ETH_ALEN); - os_memcpy(results[ap_num].ssid, wbi->Ssid.Ssid, - wbi->Ssid.SsidLength); - results[ap_num].ssid_len = wbi->Ssid.SsidLength; - results[ap_num].freq = (wbi->Configuration.DSConfig / 1000); + struct wpa_scan_res *r = NULL; + size_t extra_len = 0, var_ie_len = 0; + u8 *pos2; + + /* SSID data element */ + extra_len += 2 + wbi->Ssid.SsidLength; + var_ie_len = wbi->IELength - sizeof(NDIS_802_11_FIXED_IEs); + r = os_zalloc(sizeof(*r) + extra_len + var_ie_len); + if (r == NULL) + break; + res->res[res->num++] = r; + wpa_printf(MSG_DEBUG, "SSID - %s", wbi->Ssid.Ssid); /* get ie's */ wpa_hexdump(MSG_DEBUG, "RALINK: AP IEs", - (u8 *) wbi + sizeof(*wbi) - 1, wbi->IELength); + (u8 *) &wbi->IEs[0], wbi->IELength); - pos = (u8 *) wbi + sizeof(*wbi) - 1; - end = (u8 *) wbi + sizeof(*wbi) + wbi->IELength; + os_memcpy(r->bssid, wbi->MacAddress, ETH_ALEN); - if (wbi->IELength < sizeof(NDIS_802_11_FIXED_IEs)) - break; + extra_len += (2 + wbi->Ssid.SsidLength); + r->ie_len = extra_len + var_ie_len; + pos2 = (u8 *) (r + 1); - pos += sizeof(NDIS_802_11_FIXED_IEs) - 2; - os_memcpy(&results[ap_num].caps, pos, 2); - pos += 2; + /* + * Generate a fake SSID IE since the driver did not report + * a full IE list. + */ + *pos2++ = WLAN_EID_SSID; + *pos2++ = wbi->Ssid.SsidLength; + os_memcpy(pos2, wbi->Ssid.Ssid, wbi->Ssid.SsidLength); + pos2 += wbi->Ssid.SsidLength; - while (pos + 1 < end && pos + 2 + pos[1] <= end) { - u8 ielen = 2 + pos[1]; + r->freq = (wbi->Configuration.DSConfig / 1000); - if (ielen > SSID_MAX_WPA_IE_LEN) { - pos += ielen; - continue; - } + pos = (u8 *) wbi + sizeof(*wbi) - 1; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && - pos[1] >= 4 && - os_memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) { - os_memcpy(results[ap_num].wpa_ie, pos, ielen); - results[ap_num].wpa_ie_len = ielen; - } else if (pos[0] == WLAN_EID_RSN) { - os_memcpy(results[ap_num].rsn_ie, pos, ielen); - results[ap_num].rsn_ie_len = ielen; - } - pos += ielen; - } + pos += sizeof(NDIS_802_11_FIXED_IEs) - 2; + os_memcpy(&(r->caps), pos, 2); + pos += 2; + + if (wbi->IELength > sizeof(NDIS_802_11_FIXED_IEs)) + os_memcpy(pos2, pos, var_ie_len); wbi = (NDIS_WLAN_BSSID_EX *) ((u8 *) wbi + wbi->Length); } os_free(buf); - return ap_num; + return res; } static int ralink_set_auth_mode(struct wpa_driver_ralink_data *drv, @@ -1173,6 +1073,24 @@ static int ralink_set_auth_mode(struct wpa_driver_ralink_data *drv, return 0; } +static int ralink_set_encr_type(struct wpa_driver_ralink_data *drv, + NDIS_802_11_WEP_STATUS encr_type) +{ + NDIS_802_11_WEP_STATUS wep_status = encr_type; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (ralink_set_oid(drv, OID_802_11_WEP_STATUS, + (char *) &wep_status, sizeof(wep_status)) < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "OID_802_11_WEP_STATUS (%d)", + (int) wep_status); + return -1; + } + return 0; +} + + static int wpa_driver_ralink_remove_key(struct wpa_driver_ralink_data *drv, int key_idx, const u8 *addr, const u8 *bssid, int pairwise) @@ -1241,7 +1159,8 @@ static int wpa_driver_ralink_add_wep(struct wpa_driver_ralink_data *drv, return res; } -static int wpa_driver_ralink_set_key(void *priv, wpa_alg alg, const u8 *addr, +static int wpa_driver_ralink_set_key(const char *ifname, void *priv, + enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) @@ -1257,6 +1176,8 @@ static int wpa_driver_ralink_set_key(void *priv, wpa_alg alg, const u8 *addr, wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + drv->bAddWepKey = FALSE; + if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) { /* Group Key */ @@ -1274,6 +1195,7 @@ static int wpa_driver_ralink_set_key(void *priv, wpa_alg alg, const u8 *addr, } if (alg == WPA_ALG_WEP) { + drv->bAddWepKey = TRUE; return wpa_driver_ralink_add_wep(drv, pairwise, key_idx, set_tx, key, key_len); } @@ -1363,6 +1285,29 @@ static int wpa_driver_ralink_deauthenticate(void *priv, const u8 *addr, } } +static int wpa_driver_ralink_set_gen_ie(void *priv, const u8 *ie, + size_t ie_len) +{ + struct wpa_driver_ralink_data *drv = priv; + struct iwreq iwr; + int ret = 0; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) ie; + iwr.u.data.length = ie_len; + + wpa_hexdump(MSG_DEBUG, "wpa_driver_ralink_set_gen_ie: ", + (u8 *) ie, ie_len); + + if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { + perror("ioctl[SIOCSIWGENIE]"); + ret = -1; + } + + return ret; +} + static int wpa_driver_ralink_associate(void *priv, struct wpa_driver_associate_params *params) @@ -1373,6 +1318,7 @@ wpa_driver_ralink_associate(void *priv, NDIS_802_11_AUTHENTICATION_MODE auth_mode; NDIS_802_11_WEP_STATUS encr; BOOLEAN ieee8021xMode; + BOOLEAN ieee8021x_required_key = TRUE; if (drv->g_driver_down == 1) return -1; @@ -1391,83 +1337,131 @@ wpa_driver_ralink_associate(void *priv, /* Try to continue anyway */ } - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { - if (params->auth_alg & AUTH_ALG_SHARED_KEY) { - if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM) - auth_mode = Ndis802_11AuthModeAutoSwitch; - else - auth_mode = Ndis802_11AuthModeShared; - } else - auth_mode = Ndis802_11AuthModeOpen; - } else if (params->wpa_ie[0] == WLAN_EID_RSN) { - if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPA2PSK; - else - auth_mode = Ndis802_11AuthModeWPA2; + if (params->key_mgmt_suite == KEY_MGMT_WPS) { + UCHAR enable_wps = 0x80; + /* trigger driver support wpa_supplicant */ + if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, + (PCHAR) &enable_wps, sizeof(UCHAR)) < 0) { + wpa_printf(MSG_INFO, "RALINK: Failed to set " + "RT_OID_WPA_SUPPLICANT_SUPPORT (%d)", + (int) enable_wps); + } + + wpa_driver_ralink_set_gen_ie(priv, params->wpa_ie, + params->wpa_ie_len); + + ralink_set_auth_mode(drv, Ndis802_11AuthModeOpen); + + ralink_set_encr_type(drv, Ndis802_11EncryptionDisabled); } else { - if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE) - auth_mode = Ndis802_11AuthModeWPANone; - else if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPAPSK; +#ifdef CONFIG_WPS + UCHAR enable_wpa_supplicant; + + if (drv->ap_scan == 1) + enable_wpa_supplicant = 0x01; else - auth_mode = Ndis802_11AuthModeWPA; - } + enable_wpa_supplicant = 0x02; - switch (params->pairwise_suite) { - case CIPHER_CCMP: - encr = Ndis802_11Encryption3Enabled; - break; - case CIPHER_TKIP: - encr = Ndis802_11Encryption2Enabled; - break; - case CIPHER_WEP40: - case CIPHER_WEP104: - encr = Ndis802_11Encryption1Enabled; - break; - case CIPHER_NONE: - if (params->group_suite == CIPHER_CCMP) + /* trigger driver support wpa_supplicant */ + if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, + (PCHAR) &enable_wpa_supplicant, + sizeof(UCHAR)) < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "RT_OID_WPA_SUPPLICANT_SUPPORT (%d)", + (int) enable_wpa_supplicant); + } + + wpa_driver_ralink_set_gen_ie(priv, (u8 *) "", 0); +#endif /* CONFIG_WPS */ + + if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { + if (params->auth_alg & WPA_AUTH_ALG_SHARED) { + if (params->auth_alg & WPA_AUTH_ALG_OPEN) + auth_mode = Ndis802_11AuthModeAutoSwitch; + else + auth_mode = Ndis802_11AuthModeShared; + } else + auth_mode = Ndis802_11AuthModeOpen; + } else if (params->wpa_ie[0] == WLAN_EID_RSN) { + if (params->key_mgmt_suite == KEY_MGMT_PSK) + auth_mode = Ndis802_11AuthModeWPA2PSK; + else + auth_mode = Ndis802_11AuthModeWPA2; + } else { + if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE) + auth_mode = Ndis802_11AuthModeWPANone; + else if (params->key_mgmt_suite == KEY_MGMT_PSK) + auth_mode = Ndis802_11AuthModeWPAPSK; + else + auth_mode = Ndis802_11AuthModeWPA; + } + + switch (params->pairwise_suite) { + case CIPHER_CCMP: encr = Ndis802_11Encryption3Enabled; - else if (params->group_suite == CIPHER_TKIP) + break; + case CIPHER_TKIP: encr = Ndis802_11Encryption2Enabled; - else + break; + case CIPHER_WEP40: + case CIPHER_WEP104: + encr = Ndis802_11Encryption1Enabled; + break; + case CIPHER_NONE: + if (params->group_suite == CIPHER_CCMP) + encr = Ndis802_11Encryption3Enabled; + else if (params->group_suite == CIPHER_TKIP) + encr = Ndis802_11Encryption2Enabled; + else + encr = Ndis802_11EncryptionDisabled; + break; + default: encr = Ndis802_11EncryptionDisabled; - break; - default: - encr = Ndis802_11EncryptionDisabled; - break; - } - - ralink_set_auth_mode(drv, auth_mode); + break; + } - /* notify driver that IEEE8021x mode is enabled */ - if (params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) - ieee8021xMode = TRUE; - else - ieee8021xMode = FALSE; + ralink_set_auth_mode(drv, auth_mode); - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, - (char *) &ieee8021xMode, sizeof(BOOLEAN)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_SET_IEEE8021X(%d)", - (int) ieee8021xMode); - } + /* notify driver that IEEE8021x mode is enabled */ + if (params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) { + ieee8021xMode = TRUE; + if (drv->bAddWepKey) + ieee8021x_required_key = FALSE; + } else + ieee8021xMode = FALSE; - if (ralink_set_oid(drv, OID_802_11_WEP_STATUS, - (char *) &encr, sizeof(encr)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_WEP_STATUS(%d)", - (int) encr); - } + if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, + (char *) &ieee8021x_required_key, + sizeof(BOOLEAN)) < 0) { + wpa_printf(MSG_DEBUG, "ERROR: Failed to set " + "OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", + (int) ieee8021x_required_key); + } else { + wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s", + ieee8021x_required_key ? "TRUE" : "FALSE"); + } - if ((ieee8021xMode == FALSE) && - (encr == Ndis802_11Encryption1Enabled)) { - /* static WEP */ - int enabled = 0; - if (ralink_set_oid(drv, OID_802_11_DROP_UNENCRYPTED, - (char *) &enabled, sizeof(enabled)) < 0) { + if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, + (char *) &ieee8021xMode, sizeof(BOOLEAN)) < + 0) { wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_DROP_UNENCRYPTED(%d)", - (int) encr); + "OID_802_11_SET_IEEE8021X(%d)", + (int) ieee8021xMode); + } + + ralink_set_encr_type(drv, encr); + + if ((ieee8021xMode == FALSE) && + (encr == Ndis802_11Encryption1Enabled)) { + /* static WEP */ + int enabled = 0; + if (ralink_set_oid(drv, OID_802_11_DROP_UNENCRYPTED, + (char *) &enabled, sizeof(enabled)) + < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "OID_802_11_DROP_UNENCRYPTED(%d)", + (int) encr); + } } } @@ -1494,8 +1488,8 @@ const struct wpa_driver_ops wpa_driver_ralink_ops = { .init = wpa_driver_ralink_init, .deinit = wpa_driver_ralink_deinit, .set_countermeasures = wpa_driver_ralink_set_countermeasures, - .scan = wpa_driver_ralink_scan, - .get_scan_results = wpa_driver_ralink_get_scan_results, + .scan2 = wpa_driver_ralink_scan, + .get_scan_results2 = wpa_driver_ralink_get_scan_results, .deauthenticate = wpa_driver_ralink_deauthenticate, .disassociate = wpa_driver_ralink_disassociate, .associate = wpa_driver_ralink_associate, |