?? driver_ralink.c
字號(hào):
/* * 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 "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 32struct 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 intralink_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: %d: " MACSTR " Flags 0x%x", 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 voidwpa_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);
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -