mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-26 09:18:24 -05:00
90973fb2fd
This makes it clearer which files are including header from src/common. Some of these cases should probably be cleaned up in the future not to do that. In addition, src/common/nl80211_copy.h and wireless_copy.h were moved into src/drivers since they are only used by driver wrappers and do not need to live in src/common.
1503 lines
38 KiB
C
1503 lines
38 KiB
C
/*
|
|
* WPA Supplicant - driver interaction with Ralink Wireless Client
|
|
* Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
|
|
* Copyright (c) 2007, Snowpin Lee <snowpin_lee@ralinktech.com.tw>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* Alternatively, this software may be distributed under the terms of BSD
|
|
* license.
|
|
*
|
|
* See README and COPYING for more details.
|
|
*
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include <sys/ioctl.h>
|
|
|
|
#include "wireless_copy.h"
|
|
#include "common.h"
|
|
#include "driver.h"
|
|
#include "l2_packet/l2_packet.h"
|
|
#include "eloop.h"
|
|
#include "common/ieee802_11_defs.h"
|
|
#include "priv_netlink.h"
|
|
#include "driver_ralink.h"
|
|
|
|
static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx);
|
|
|
|
#define MAX_SSID_LEN 32
|
|
|
|
struct wpa_driver_ralink_data {
|
|
void *ctx;
|
|
int ioctl_sock;
|
|
int event_sock;
|
|
char ifname[IFNAMSIZ + 1];
|
|
u8 *assoc_req_ies;
|
|
size_t assoc_req_ies_len;
|
|
u8 *assoc_resp_ies;
|
|
size_t assoc_resp_ies_len;
|
|
int no_of_pmkid;
|
|
struct ndis_pmkid_entry *pmkid;
|
|
int we_version_compiled;
|
|
int ap_scan;
|
|
int scanning_done;
|
|
u8 g_driver_down;
|
|
};
|
|
|
|
static int ralink_set_oid(struct wpa_driver_ralink_data *drv,
|
|
unsigned short oid, char *data, int len)
|
|
{
|
|
char *buf;
|
|
struct iwreq iwr;
|
|
|
|
buf = os_zalloc(len);
|
|
if (buf == NULL)
|
|
return -1;
|
|
os_memset(&iwr, 0, sizeof(iwr));
|
|
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
|
|
iwr.u.data.flags = oid;
|
|
iwr.u.data.flags |= OID_GET_SET_TOGGLE;
|
|
|
|
if (data)
|
|
os_memcpy(buf, data, len);
|
|
|
|
iwr.u.data.pointer = (caddr_t) buf;
|
|
iwr.u.data.length = len;
|
|
|
|
if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
|
|
wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
|
|
__func__, oid, len);
|
|
os_free(buf);
|
|
return -1;
|
|
}
|
|
os_free(buf);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ralink_get_new_driver_flag(struct wpa_driver_ralink_data *drv)
|
|
{
|
|
struct iwreq iwr;
|
|
UCHAR enabled = 0;
|
|
|
|
os_memset(&iwr, 0, sizeof(iwr));
|
|
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
|
|
iwr.u.data.pointer = (UCHAR*) &enabled;
|
|
iwr.u.data.flags = RT_OID_NEW_DRIVER;
|
|
|
|
if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
|
|
wpa_printf(MSG_DEBUG, "%s: failed", __func__);
|
|
return 0;
|
|
}
|
|
|
|
return (enabled == 1) ? 1 : 0;
|
|
}
|
|
|
|
static int wpa_driver_ralink_get_bssid(void *priv, u8 *bssid)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
struct iwreq iwr;
|
|
int ret = 0;
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
os_memset(&iwr, 0, sizeof(iwr));
|
|
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
|
|
|
|
if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
|
|
perror("ioctl[SIOCGIWAP]");
|
|
ret = -1;
|
|
}
|
|
os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int wpa_driver_ralink_get_ssid(void *priv, u8 *ssid)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
#if 0
|
|
struct wpa_supplicant *wpa_s = drv->ctx;
|
|
struct wpa_ssid *entry;
|
|
#endif
|
|
int ssid_len;
|
|
u8 bssid[ETH_ALEN];
|
|
u8 ssid_str[MAX_SSID_LEN];
|
|
struct iwreq iwr;
|
|
#if 0
|
|
int result = 0;
|
|
#endif
|
|
int ret = 0;
|
|
#if 0
|
|
BOOLEAN ieee8021x_mode = FALSE;
|
|
BOOLEAN ieee8021x_required_key = FALSE;
|
|
#endif
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
os_memset(&iwr, 0, sizeof(iwr));
|
|
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
|
|
iwr.u.essid.pointer = (caddr_t) ssid;
|
|
iwr.u.essid.length = 32;
|
|
|
|
if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
|
|
perror("ioctl[SIOCGIWESSID]");
|
|
ret = -1;
|
|
} else
|
|
ret = iwr.u.essid.length;
|
|
|
|
if (ret <= 0)
|
|
return ret;
|
|
|
|
ssid_len = ret;
|
|
os_memset(ssid_str, 0, MAX_SSID_LEN);
|
|
os_memcpy(ssid_str, ssid, ssid_len);
|
|
|
|
if (drv->ap_scan == 0) {
|
|
/* Read BSSID form driver */
|
|
if (wpa_driver_ralink_get_bssid(priv, bssid) < 0) {
|
|
wpa_printf(MSG_WARNING, "Could not read BSSID from "
|
|
"driver.");
|
|
return ret;
|
|
}
|
|
|
|
#if 0
|
|
entry = wpa_s->conf->ssid;
|
|
while (entry) {
|
|
if (!entry->disabled && ssid_len == entry->ssid_len &&
|
|
os_memcmp(ssid_str, entry->ssid, ssid_len) == 0 &&
|
|
(!entry->bssid_set ||
|
|
os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) {
|
|
/* match the config of driver */
|
|
result = 1;
|
|
break;
|
|
}
|
|
entry = entry->next;
|
|
}
|
|
|
|
if (result) {
|
|
wpa_printf(MSG_DEBUG, "Ready to set 802.1x mode and "
|
|
"ieee_required_keys parameters to driver");
|
|
|
|
/* set 802.1x mode and ieee_required_keys parameter */
|
|
if (entry->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
|
|
if ((entry->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST)))
|
|
ieee8021x_required_key = TRUE;
|
|
ieee8021x_mode = TRUE;
|
|
}
|
|
|
|
if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, (char *) &ieee8021x_mode, sizeof(BOOLEAN)) < 0)
|
|
{
|
|
wpa_printf(MSG_DEBUG, "RALINK: Failed to set OID_802_11_SET_IEEE8021X(%d)", (int) ieee8021x_mode);
|
|
}
|
|
else
|
|
{
|
|
wpa_printf(MSG_DEBUG, "ieee8021x_mode is %s", ieee8021x_mode ? "TRUE" : "FALSE");
|
|
}
|
|
|
|
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 and eapol_flag(%d)", ieee8021x_required_key ? "TRUE" : "FALSE",
|
|
entry->eapol_flags);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int wpa_driver_ralink_set_ssid(struct wpa_driver_ralink_data *drv,
|
|
const u8 *ssid, size_t ssid_len)
|
|
{
|
|
NDIS_802_11_SSID *buf;
|
|
int ret = 0;
|
|
struct iwreq iwr;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
buf = os_zalloc(sizeof(NDIS_802_11_SSID));
|
|
if (buf == NULL)
|
|
return -1;
|
|
os_memset(buf, 0, sizeof(buf));
|
|
buf->SsidLength = ssid_len;
|
|
os_memcpy(buf->Ssid, ssid, ssid_len);
|
|
os_memset(&iwr, 0, sizeof(iwr));
|
|
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
|
|
|
|
iwr.u.data.flags = OID_802_11_SSID;
|
|
iwr.u.data.flags |= OID_GET_SET_TOGGLE;
|
|
iwr.u.data.pointer = (caddr_t) buf;
|
|
iwr.u.data.length = sizeof(NDIS_802_11_SSID);
|
|
|
|
if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
|
|
perror("ioctl[RT_PRIV_IOCTL] -- OID_802_11_SSID");
|
|
ret = -1;
|
|
}
|
|
os_free(buf);
|
|
return ret;
|
|
}
|
|
|
|
static void wpa_driver_ralink_event_pmkid(struct wpa_driver_ralink_data *drv,
|
|
const u8 *data, size_t data_len)
|
|
{
|
|
NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
|
|
size_t i;
|
|
union wpa_event_data event;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
if (data_len < 8) {
|
|
wpa_printf(MSG_DEBUG, "RALINK: Too short PMKID Candidate List "
|
|
"Event (len=%lu)", (unsigned long) data_len);
|
|
return;
|
|
}
|
|
pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data;
|
|
wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List Event - Version %d"
|
|
" NumCandidates %d",
|
|
(int) pmkid->Version, (int) pmkid->NumCandidates);
|
|
|
|
if (pmkid->Version != 1) {
|
|
wpa_printf(MSG_DEBUG, "RALINK: Unsupported PMKID Candidate "
|
|
"List Version %d", (int) pmkid->Version);
|
|
return;
|
|
}
|
|
|
|
if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) {
|
|
wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List "
|
|
"underflow");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
os_memset(&event, 0, sizeof(event));
|
|
for (i = 0; i < pmkid->NumCandidates; i++) {
|
|
PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
|
|
wpa_printf(MSG_DEBUG, "RALINK: %lu: " MACSTR " Flags 0x%x",
|
|
(unsigned long) i, MAC2STR(p->BSSID),
|
|
(int) p->Flags);
|
|
os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
|
|
event.pmkid_candidate.index = i;
|
|
event.pmkid_candidate.preauth =
|
|
p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
|
|
wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE,
|
|
&event);
|
|
}
|
|
}
|
|
|
|
static int wpa_driver_ralink_set_pmkid(struct wpa_driver_ralink_data *drv)
|
|
{
|
|
int len, count, i, ret;
|
|
struct ndis_pmkid_entry *entry;
|
|
NDIS_802_11_PMKID *p;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
count = 0;
|
|
entry = drv->pmkid;
|
|
while (entry) {
|
|
count++;
|
|
if (count >= drv->no_of_pmkid)
|
|
break;
|
|
entry = entry->next;
|
|
}
|
|
len = 8 + count * sizeof(BSSID_INFO);
|
|
p = os_zalloc(len);
|
|
if (p == NULL)
|
|
return -1;
|
|
p->Length = len;
|
|
p->BSSIDInfoCount = count;
|
|
entry = drv->pmkid;
|
|
for (i = 0; i < count; i++) {
|
|
os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
|
|
os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
|
|
entry = entry->next;
|
|
}
|
|
wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID",
|
|
(const u8 *) p, len);
|
|
ret = ralink_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
|
|
os_free(p);
|
|
return ret;
|
|
}
|
|
|
|
static int wpa_driver_ralink_add_pmkid(void *priv, const u8 *bssid,
|
|
const u8 *pmkid)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
struct ndis_pmkid_entry *entry, *prev;
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
if (drv->no_of_pmkid == 0)
|
|
return 0;
|
|
|
|
prev = NULL;
|
|
entry = drv->pmkid;
|
|
while (entry) {
|
|
if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
|
|
break;
|
|
prev = entry;
|
|
entry = entry->next;
|
|
}
|
|
|
|
if (entry) {
|
|
/* Replace existing entry for this BSSID and move it into the
|
|
* beginning of the list. */
|
|
os_memcpy(entry->pmkid, pmkid, 16);
|
|
if (prev) {
|
|
prev->next = entry->next;
|
|
entry->next = drv->pmkid;
|
|
drv->pmkid = entry;
|
|
}
|
|
} else {
|
|
entry = os_malloc(sizeof(*entry));
|
|
if (entry) {
|
|
os_memcpy(entry->bssid, bssid, ETH_ALEN);
|
|
os_memcpy(entry->pmkid, pmkid, 16);
|
|
entry->next = drv->pmkid;
|
|
drv->pmkid = entry;
|
|
}
|
|
}
|
|
|
|
return wpa_driver_ralink_set_pmkid(drv);
|
|
}
|
|
|
|
|
|
static int wpa_driver_ralink_remove_pmkid(void *priv, const u8 *bssid,
|
|
const u8 *pmkid)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
struct ndis_pmkid_entry *entry, *prev;
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
if (drv->no_of_pmkid == 0)
|
|
return 0;
|
|
|
|
entry = drv->pmkid;
|
|
prev = NULL;
|
|
drv->pmkid = NULL;
|
|
while (entry) {
|
|
if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
|
|
os_memcmp(entry->pmkid, pmkid, 16) == 0) {
|
|
if (prev)
|
|
prev->next = entry->next;
|
|
else
|
|
drv->pmkid = entry->next;
|
|
os_free(entry);
|
|
break;
|
|
}
|
|
prev = entry;
|
|
entry = entry->next;
|
|
}
|
|
return wpa_driver_ralink_set_pmkid(drv);
|
|
}
|
|
|
|
|
|
static int wpa_driver_ralink_flush_pmkid(void *priv)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
NDIS_802_11_PMKID p;
|
|
struct ndis_pmkid_entry *pmkid, *prev;
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
if (drv->no_of_pmkid == 0)
|
|
return 0;
|
|
|
|
pmkid = drv->pmkid;
|
|
drv->pmkid = NULL;
|
|
while (pmkid) {
|
|
prev = pmkid;
|
|
pmkid = pmkid->next;
|
|
os_free(prev);
|
|
}
|
|
|
|
os_memset(&p, 0, sizeof(p));
|
|
p.Length = 8;
|
|
p.BSSIDInfoCount = 0;
|
|
wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
|
|
(const u8 *) &p, 8);
|
|
return ralink_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
|
|
}
|
|
|
|
static void
|
|
wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv,
|
|
void *ctx, char *custom)
|
|
{
|
|
union wpa_event_data data;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
|
|
|
|
os_memset(&data, 0, sizeof(data));
|
|
/* Host AP driver */
|
|
if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
|
|
/* receive a MICFAILURE report */
|
|
data.michael_mic_failure.unicast =
|
|
os_strstr(custom, " unicast") != NULL;
|
|
/* TODO: parse parameters(?) */
|
|
wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
|
|
} else if (os_strncmp(custom, "ASSOCINFO_ReqIEs=", 17) == 0) {
|
|
/* receive assoc. req. IEs */
|
|
char *spos;
|
|
int bytes;
|
|
|
|
spos = custom + 17;
|
|
/*get IE's length */
|
|
/*
|
|
* bytes = strlen(spos); ==> bug, bytes may less than original
|
|
* size by using this way to get size. snowpin 20070312
|
|
* if (!bytes)
|
|
* return;
|
|
*/
|
|
bytes = drv->assoc_req_ies_len;
|
|
|
|
data.assoc_info.req_ies = os_malloc(bytes);
|
|
if (data.assoc_info.req_ies == NULL)
|
|
return;
|
|
|
|
data.assoc_info.req_ies_len = bytes;
|
|
os_memcpy(data.assoc_info.req_ies, spos, bytes);
|
|
|
|
/* skip the '\0' byte */
|
|
spos += bytes + 1;
|
|
|
|
data.assoc_info.resp_ies = NULL;
|
|
data.assoc_info.resp_ies_len = 0;
|
|
|
|
if (os_strncmp(spos, " RespIEs=", 9) == 0) {
|
|
/* receive assoc. resp. IEs */
|
|
spos += 9;
|
|
/* get IE's length */
|
|
bytes = os_strlen(spos);
|
|
if (!bytes)
|
|
goto done;
|
|
|
|
|
|
data.assoc_info.resp_ies = os_malloc(bytes);
|
|
if (data.assoc_info.resp_ies == NULL)
|
|
goto done;
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
static void
|
|
wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv,
|
|
void *ctx, char *data, int len)
|
|
{
|
|
struct iw_event iwe_buf, *iwe = &iwe_buf;
|
|
char *pos, *end, *custom, *buf, *assoc_info_buf, *info_pos;
|
|
#if 0
|
|
BOOLEAN ieee8021x_required_key = FALSE;
|
|
#endif
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
assoc_info_buf = info_pos = NULL;
|
|
pos = data;
|
|
end = data + len;
|
|
|
|
while (pos + IW_EV_LCP_LEN <= end) {
|
|
/* Event data may be unaligned, so make a local, aligned copy
|
|
* before processing. */
|
|
os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
|
|
wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
|
|
iwe->cmd, iwe->len);
|
|
if (iwe->len <= IW_EV_LCP_LEN)
|
|
return;
|
|
|
|
custom = pos + IW_EV_POINT_LEN;
|
|
|
|
if (drv->we_version_compiled > 18 && iwe->cmd == IWEVCUSTOM) {
|
|
/* WE-19 removed the pointer from struct iw_point */
|
|
char *dpos = (char *) &iwe_buf.u.data.length;
|
|
int dlen = dpos - (char *) &iwe_buf;
|
|
os_memcpy(dpos, pos + IW_EV_LCP_LEN,
|
|
sizeof(struct iw_event) - dlen);
|
|
} else {
|
|
os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
|
|
custom += IW_EV_POINT_OFF;
|
|
}
|
|
|
|
switch (iwe->cmd) {
|
|
case IWEVCUSTOM:
|
|
if (custom + iwe->u.data.length > end)
|
|
return;
|
|
buf = os_malloc(iwe->u.data.length + 1);
|
|
if (buf == NULL)
|
|
return;
|
|
os_memcpy(buf, custom, iwe->u.data.length);
|
|
buf[iwe->u.data.length] = '\0';
|
|
|
|
if (drv->ap_scan == 1) {
|
|
if ((iwe->u.data.flags == RT_ASSOC_EVENT_FLAG)
|
|
|| (iwe->u.data.flags ==
|
|
RT_REQIE_EVENT_FLAG) ||
|
|
(iwe->u.data.flags == RT_RESPIE_EVENT_FLAG)
|
|
|| (iwe->u.data.flags ==
|
|
RT_ASSOCINFO_EVENT_FLAG)) {
|
|
if (drv->scanning_done == 0) {
|
|
os_free(buf);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) {
|
|
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 !!!");
|
|
drv->assoc_req_ies =
|
|
os_malloc(iwe->u.data.length);
|
|
if (drv->assoc_req_ies == NULL) {
|
|
os_free(buf);
|
|
return;
|
|
}
|
|
|
|
drv->assoc_req_ies_len = iwe->u.data.length;
|
|
os_memcpy(drv->assoc_req_ies, custom,
|
|
iwe->u.data.length);
|
|
} else if (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG) {
|
|
wpa_printf(MSG_DEBUG, "Custom wireless event: "
|
|
"receive RespIEs !!!");
|
|
drv->assoc_resp_ies =
|
|
os_malloc(iwe->u.data.length);
|
|
if (drv->assoc_resp_ies == NULL) {
|
|
os_free(drv->assoc_req_ies);
|
|
drv->assoc_req_ies = NULL;
|
|
os_free(buf);
|
|
return;
|
|
}
|
|
|
|
drv->assoc_resp_ies_len = iwe->u.data.length;
|
|
os_memcpy(drv->assoc_resp_ies, custom,
|
|
iwe->u.data.length);
|
|
} else if (iwe->u.data.flags ==
|
|
RT_ASSOCINFO_EVENT_FLAG) {
|
|
wpa_printf(MSG_DEBUG, "Custom wireless event: "
|
|
"receive ASSOCINFO_EVENT !!!");
|
|
|
|
assoc_info_buf =
|
|
os_zalloc(drv->assoc_req_ies_len +
|
|
drv->assoc_resp_ies_len + 1);
|
|
|
|
if (assoc_info_buf == NULL) {
|
|
os_free(drv->assoc_req_ies);
|
|
drv->assoc_req_ies = NULL;
|
|
os_free(drv->assoc_resp_ies);
|
|
drv->assoc_resp_ies = NULL;
|
|
os_free(buf);
|
|
return;
|
|
}
|
|
|
|
if (drv->assoc_req_ies) {
|
|
os_memcpy(assoc_info_buf,
|
|
drv->assoc_req_ies,
|
|
drv->assoc_req_ies_len);
|
|
}
|
|
info_pos = assoc_info_buf +
|
|
drv->assoc_req_ies_len;
|
|
if (drv->assoc_resp_ies) {
|
|
os_memcpy(info_pos,
|
|
drv->assoc_resp_ies,
|
|
drv->assoc_resp_ies_len);
|
|
}
|
|
assoc_info_buf[drv->assoc_req_ies_len +
|
|
drv->assoc_resp_ies_len] = '\0';
|
|
wpa_driver_ralink_event_wireless_custom(
|
|
drv, ctx, assoc_info_buf);
|
|
os_free(drv->assoc_req_ies);
|
|
drv->assoc_req_ies = NULL;
|
|
os_free(drv->assoc_resp_ies);
|
|
drv->assoc_resp_ies = NULL;
|
|
os_free(assoc_info_buf);
|
|
} else if (iwe->u.data.flags == RT_DISASSOC_EVENT_FLAG)
|
|
{
|
|
wpa_printf(MSG_DEBUG, "Custom wireless event: "
|
|
"receive DISASSOCIATED_EVENT !!!");
|
|
wpa_supplicant_event(ctx, EVENT_DISASSOC,
|
|
NULL);
|
|
} else if (iwe->u.data.flags == RT_PMKIDCAND_FLAG) {
|
|
wpa_printf(MSG_DEBUG, "Custom wireless event: "
|
|
"receive PMKIDCAND_EVENT !!!");
|
|
wpa_driver_ralink_event_pmkid(
|
|
drv, (const u8 *) custom,
|
|
iwe->u.data.length);
|
|
} 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 {
|
|
wpa_driver_ralink_event_wireless_custom(
|
|
drv, ctx, buf);
|
|
}
|
|
os_free(buf);
|
|
break;
|
|
}
|
|
|
|
pos += iwe->len;
|
|
}
|
|
}
|
|
|
|
static void
|
|
wpa_driver_ralink_event_rtm_newlink(struct wpa_driver_ralink_data *drv,
|
|
void *ctx, struct nlmsghdr *h, int len)
|
|
{
|
|
struct ifinfomsg *ifi;
|
|
int attrlen, nlmsg_len, 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;
|
|
wpa_printf(MSG_DEBUG, "attrlen=%d", attrlen);
|
|
if (attrlen < 0)
|
|
return;
|
|
|
|
attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
|
|
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);
|
|
while (RTA_OK(attr, attrlen)) {
|
|
wpa_printf(MSG_DEBUG, "rta_type=%02x\n", attr->rta_type);
|
|
if (attr->rta_type == IFLA_WIRELESS) {
|
|
wpa_driver_ralink_event_wireless(
|
|
drv, ctx,
|
|
((char *) attr) + rta_len,
|
|
attr->rta_len - rta_len);
|
|
}
|
|
attr = RTA_NEXT(attr, attrlen);
|
|
wpa_hexdump(MSG_DEBUG, "attr3: ",
|
|
(u8 *) attr, sizeof(struct rtattr));
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
struct iwreq iwr;
|
|
UINT we_version_compiled = 0;
|
|
|
|
os_memset(&iwr, 0, sizeof(iwr));
|
|
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
|
|
iwr.u.data.pointer = (caddr_t) &we_version_compiled;
|
|
iwr.u.data.flags = RT_OID_WE_VERSION_COMPILED;
|
|
|
|
if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
|
|
wpa_printf(MSG_DEBUG, "%s: failed", __func__);
|
|
return -1;
|
|
}
|
|
|
|
drv->we_version_compiled = we_version_compiled;
|
|
|
|
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;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
/* open socket to kernel */
|
|
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
|
perror("socket");
|
|
return NULL;
|
|
}
|
|
/* do it */
|
|
os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
|
|
|
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
|
perror(ifr.ifr_name);
|
|
return NULL;
|
|
}
|
|
|
|
drv = os_zalloc(sizeof(*drv));
|
|
if (drv == NULL)
|
|
return NULL;
|
|
|
|
drv->scanning_done = 1;
|
|
drv->ap_scan = 1; /* for now - let's assume ap_scan=1 is used */
|
|
drv->ctx = ctx;
|
|
os_strlcpy(drv->ifname, ifname, sizeof(drv->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)");
|
|
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);
|
|
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 */
|
|
ralink_get_we_version_compiled(drv);
|
|
wpa_driver_ralink_flush_pmkid(drv);
|
|
|
|
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_DEBUG, "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");
|
|
close(s);
|
|
close(drv->ioctl_sock);
|
|
os_free(drv);
|
|
return NULL;
|
|
}
|
|
|
|
if (drv->ap_scan == 1)
|
|
drv->scanning_done = 0;
|
|
|
|
return drv;
|
|
}
|
|
|
|
static void wpa_driver_ralink_deinit(void *priv)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
UCHAR enable_wpa_supplicant;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
enable_wpa_supplicant = 0;
|
|
|
|
if (drv->g_driver_down == 0) {
|
|
/* trigger driver disable wpa_supplicant support */
|
|
if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT,
|
|
(char *) &enable_wpa_supplicant,
|
|
sizeof(BOOLEAN)) < 0) {
|
|
wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
|
|
"RT_OID_WPA_SUPPLICANT_SUPPORT(%d)",
|
|
(int) enable_wpa_supplicant);
|
|
}
|
|
|
|
wpa_driver_ralink_flush_pmkid(drv);
|
|
|
|
sleep(1);
|
|
ralink_set_iface_flags(drv, 0);
|
|
}
|
|
|
|
eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx);
|
|
eloop_unregister_read_sock(drv->event_sock);
|
|
close(drv->event_sock);
|
|
close(drv->ioctl_sock);
|
|
os_free(drv);
|
|
}
|
|
|
|
static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = eloop_ctx;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
|
|
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
|
|
|
drv->scanning_done = 1;
|
|
|
|
}
|
|
|
|
static int wpa_driver_ralink_scan(void *priv,
|
|
struct wpa_driver_scan_params *params)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
struct iwreq iwr;
|
|
int ret = 0;
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
|
|
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);
|
|
return -1;
|
|
}
|
|
|
|
/* wpa_driver_ralink_set_ssid(drv, ssid, ssid_len); */
|
|
#endif
|
|
|
|
os_memset(&iwr, 0, sizeof(iwr));
|
|
os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
|
|
|
|
if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
|
|
perror("ioctl[SIOCSIWSCAN]");
|
|
ret = -1;
|
|
}
|
|
|
|
/* Not all drivers generate "scan completed" wireless event, so try to
|
|
* read results after a timeout. */
|
|
eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx);
|
|
eloop_register_timeout(4, 0, wpa_driver_ralink_scan_timeout, drv,
|
|
drv->ctx);
|
|
|
|
drv->scanning_done = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static struct wpa_scan_results *
|
|
wpa_driver_ralink_get_scan_results(void *priv)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
UCHAR *buf = NULL;
|
|
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;
|
|
struct wpa_scan_results *res;
|
|
|
|
if (drv->g_driver_down == 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 NULL;
|
|
|
|
wsr = (NDIS_802_11_BSSID_LIST_EX *) buf;
|
|
|
|
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 ((rv = ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr)) < 0) {
|
|
wpa_printf(MSG_DEBUG, "ioctl fail: rv = %d", rv);
|
|
os_free(buf);
|
|
return NULL;
|
|
}
|
|
|
|
res = os_zalloc(sizeof(*res));
|
|
if (res == NULL) {
|
|
os_free(buf);
|
|
return NULL;
|
|
}
|
|
|
|
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) {
|
|
struct wpa_scan_res *r;
|
|
r = os_malloc(sizeof(*r) + wbi->IELength);
|
|
if (r == NULL)
|
|
break;
|
|
res->res[res->num++] = r;
|
|
|
|
os_memcpy(r->bssid, &wbi->MacAddress, ETH_ALEN);
|
|
r->freq = (wbi->Configuration.DSConfig / 1000);
|
|
|
|
pos = (u8 *) wbi + sizeof(*wbi) - 1;
|
|
end = (u8 *) wbi + sizeof(*wbi) + wbi->IELength;
|
|
|
|
if (wbi->IELength < sizeof(NDIS_802_11_FIXED_IEs))
|
|
break;
|
|
|
|
pos += sizeof(NDIS_802_11_FIXED_IEs) - 2;
|
|
r->caps = WPA_GET_LE16(pos);
|
|
pos += 2;
|
|
|
|
os_memcpy(r + 1, pos, end - pos);
|
|
r->ie_len = end - pos;
|
|
|
|
wbi = (NDIS_WLAN_BSSID_EX *) ((u8 *) wbi + wbi->Length);
|
|
}
|
|
|
|
os_free(buf);
|
|
return res;
|
|
}
|
|
|
|
static int ralink_set_auth_mode(struct wpa_driver_ralink_data *drv,
|
|
NDIS_802_11_AUTHENTICATION_MODE mode)
|
|
{
|
|
NDIS_802_11_AUTHENTICATION_MODE auth_mode = mode;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
if (ralink_set_oid(drv, OID_802_11_AUTHENTICATION_MODE,
|
|
(char *) &auth_mode, sizeof(auth_mode)) < 0) {
|
|
wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
|
|
"OID_802_11_AUTHENTICATION_MODE (%d)",
|
|
(int) auth_mode);
|
|
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)
|
|
{
|
|
NDIS_802_11_REMOVE_KEY rkey;
|
|
NDIS_802_11_KEY_INDEX _index;
|
|
int res, res2;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
os_memset(&rkey, 0, sizeof(rkey));
|
|
|
|
rkey.Length = sizeof(rkey);
|
|
rkey.KeyIndex = key_idx;
|
|
|
|
if (pairwise)
|
|
rkey.KeyIndex |= 1 << 30;
|
|
|
|
os_memcpy(rkey.BSSID, bssid, ETH_ALEN);
|
|
|
|
res = ralink_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
|
|
sizeof(rkey));
|
|
|
|
/* AlbertY@20060210 removed it */
|
|
if (0 /* !pairwise */) {
|
|
res2 = ralink_set_oid(drv, OID_802_11_REMOVE_WEP,
|
|
(char *) &_index, sizeof(_index));
|
|
} else
|
|
res2 = 0;
|
|
|
|
if (res < 0 && res2 < 0)
|
|
return res;
|
|
return 0;
|
|
}
|
|
|
|
static int wpa_driver_ralink_add_wep(struct wpa_driver_ralink_data *drv,
|
|
int pairwise, int key_idx, int set_tx,
|
|
const u8 *key, size_t key_len)
|
|
{
|
|
NDIS_802_11_WEP *wep;
|
|
size_t len;
|
|
int res;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
len = 12 + key_len;
|
|
wep = os_zalloc(len);
|
|
if (wep == NULL)
|
|
return -1;
|
|
|
|
wep->Length = len;
|
|
wep->KeyIndex = key_idx;
|
|
|
|
if (set_tx)
|
|
wep->KeyIndex |= 0x80000000;
|
|
|
|
wep->KeyLength = key_len;
|
|
os_memcpy(wep->KeyMaterial, key, key_len);
|
|
|
|
wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_WEP",
|
|
(const u8 *) wep, len);
|
|
res = ralink_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
|
|
|
|
os_free(wep);
|
|
|
|
return res;
|
|
}
|
|
|
|
static int wpa_driver_ralink_set_key(const char *ifname, void *priv,
|
|
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)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
size_t len, i;
|
|
NDIS_802_11_KEY *nkey;
|
|
int res, pairwise;
|
|
u8 bssid[ETH_ALEN];
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
|
|
ETH_ALEN) == 0) {
|
|
/* Group Key */
|
|
pairwise = 0;
|
|
wpa_driver_ralink_get_bssid(drv, bssid);
|
|
} else {
|
|
/* Pairwise Key */
|
|
pairwise = 1;
|
|
os_memcpy(bssid, addr, ETH_ALEN);
|
|
}
|
|
|
|
if (alg == WPA_ALG_NONE || key_len == 0) {
|
|
return wpa_driver_ralink_remove_key(drv, key_idx, addr, bssid,
|
|
pairwise);
|
|
}
|
|
|
|
if (alg == WPA_ALG_WEP) {
|
|
return wpa_driver_ralink_add_wep(drv, pairwise, key_idx,
|
|
set_tx, key, key_len);
|
|
}
|
|
|
|
len = 12 + 6 + 6 + 8 + key_len;
|
|
|
|
nkey = os_zalloc(len);
|
|
if (nkey == NULL)
|
|
return -1;
|
|
|
|
nkey->Length = len;
|
|
nkey->KeyIndex = key_idx;
|
|
|
|
if (set_tx)
|
|
nkey->KeyIndex |= 1 << 31;
|
|
|
|
if (pairwise)
|
|
nkey->KeyIndex |= 1 << 30;
|
|
|
|
if (seq && seq_len)
|
|
nkey->KeyIndex |= 1 << 29;
|
|
|
|
nkey->KeyLength = key_len;
|
|
os_memcpy(nkey->BSSID, bssid, ETH_ALEN);
|
|
|
|
if (seq && seq_len) {
|
|
for (i = 0; i < seq_len; i++)
|
|
nkey->KeyRSC |= seq[i] << (i * 8);
|
|
}
|
|
if (alg == WPA_ALG_TKIP && key_len == 32) {
|
|
os_memcpy(nkey->KeyMaterial, key, 16);
|
|
os_memcpy(nkey->KeyMaterial + 16, key + 24, 8);
|
|
os_memcpy(nkey->KeyMaterial + 24, key + 16, 8);
|
|
} else {
|
|
os_memcpy(nkey->KeyMaterial, key, key_len);
|
|
}
|
|
|
|
wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
|
|
"key_len=%lu", __FUNCTION__, alg, key_idx, set_tx,
|
|
(unsigned long) seq_len, (unsigned long) key_len);
|
|
|
|
wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_KEY",
|
|
(const u8 *) nkey, len);
|
|
res = ralink_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
|
|
os_free(nkey);
|
|
|
|
return res;
|
|
}
|
|
|
|
static int wpa_driver_ralink_disassociate(void *priv, const u8 *addr,
|
|
int reason_code)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
if (ralink_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4) < 0) {
|
|
wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
|
|
"OID_802_11_DISASSOCIATE");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int wpa_driver_ralink_deauthenticate(void *priv, const u8 *addr,
|
|
int reason_code)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
|
|
wpa_printf(MSG_DEBUG, "g_driver_down = %d", drv->g_driver_down);
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
if (ralink_get_new_driver_flag(drv) == 0) {
|
|
return wpa_driver_ralink_disassociate(priv, addr, reason_code);
|
|
} else {
|
|
MLME_DEAUTH_REQ_STRUCT mlme;
|
|
os_memset(&mlme, 0, sizeof(MLME_DEAUTH_REQ_STRUCT));
|
|
mlme.Reason = reason_code;
|
|
os_memcpy(mlme.Addr, addr, MAC_ADDR_LEN);
|
|
return ralink_set_oid(drv, OID_802_11_DEAUTHENTICATION,
|
|
(char *) &mlme,
|
|
sizeof(MLME_DEAUTH_REQ_STRUCT));
|
|
}
|
|
}
|
|
|
|
static int
|
|
wpa_driver_ralink_associate(void *priv,
|
|
struct wpa_driver_associate_params *params)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
|
|
NDIS_802_11_NETWORK_INFRASTRUCTURE mode;
|
|
NDIS_802_11_AUTHENTICATION_MODE auth_mode;
|
|
NDIS_802_11_WEP_STATUS encr;
|
|
BOOLEAN ieee8021xMode;
|
|
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
|
|
|
if (params->mode == IEEE80211_MODE_IBSS)
|
|
mode = Ndis802_11IBSS;
|
|
else
|
|
mode = Ndis802_11Infrastructure;
|
|
|
|
if (ralink_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
|
|
(char *) &mode, sizeof(mode)) < 0) {
|
|
wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
|
|
"OID_802_11_INFRASTRUCTURE_MODE (%d)",
|
|
(int) mode);
|
|
/* 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;
|
|
} 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;
|
|
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)
|
|
encr = Ndis802_11Encryption3Enabled;
|
|
else if (params->group_suite == CIPHER_TKIP)
|
|
encr = Ndis802_11Encryption2Enabled;
|
|
else
|
|
encr = Ndis802_11EncryptionDisabled;
|
|
break;
|
|
default:
|
|
encr = Ndis802_11EncryptionDisabled;
|
|
break;
|
|
}
|
|
|
|
ralink_set_auth_mode(drv, auth_mode);
|
|
|
|
/* notify driver that IEEE8021x mode is enabled */
|
|
if (params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA)
|
|
ieee8021xMode = TRUE;
|
|
else
|
|
ieee8021xMode = FALSE;
|
|
|
|
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);
|
|
}
|
|
|
|
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 ((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);
|
|
}
|
|
}
|
|
|
|
return wpa_driver_ralink_set_ssid(drv, params->ssid, params->ssid_len);
|
|
}
|
|
|
|
static int
|
|
wpa_driver_ralink_set_countermeasures(void *priv, int enabled)
|
|
{
|
|
struct wpa_driver_ralink_data *drv = priv;
|
|
if (drv->g_driver_down == 1)
|
|
return -1;
|
|
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
|
|
return ralink_set_oid(drv, OID_SET_COUNTERMEASURES, (char *) &enabled,
|
|
sizeof(int));
|
|
}
|
|
|
|
const struct wpa_driver_ops wpa_driver_ralink_ops = {
|
|
.name = "ralink",
|
|
.desc = "Ralink Wireless Client driver",
|
|
.get_bssid = wpa_driver_ralink_get_bssid,
|
|
.get_ssid = wpa_driver_ralink_get_ssid,
|
|
.set_key = wpa_driver_ralink_set_key,
|
|
.init = wpa_driver_ralink_init,
|
|
.deinit = wpa_driver_ralink_deinit,
|
|
.set_countermeasures = wpa_driver_ralink_set_countermeasures,
|
|
.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,
|
|
.add_pmkid = wpa_driver_ralink_add_pmkid,
|
|
.remove_pmkid = wpa_driver_ralink_remove_pmkid,
|
|
.flush_pmkid = wpa_driver_ralink_flush_pmkid,
|
|
};
|