📄 driver_ndis.c
字号:
if (b == NULL) return -1; memset(b, 0, blen); len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); if (len < 0) { wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); free(b); return -1; } count = b->NumberOfItems; if (count > max_size) count = max_size; memset(results, 0, max_size * sizeof(struct wpa_scan_result)); pos = (char *) &b->Bssid[0]; for (i = 0; i < count; i++) { NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; memcpy(results[i].bssid, bss->MacAddress, ETH_ALEN); memcpy(results[i].ssid, bss->Ssid.Ssid, bss->Ssid.SsidLength); results[i].ssid_len = bss->Ssid.SsidLength; if (bss->Privacy) results[i].caps |= IEEE80211_CAP_PRIVACY; results[i].level = (int) bss->Rssi; results[i].freq = bss->Configuration.DSConfig / 1000; for (j = 0; j < sizeof(bss->SupportedRates); j++) { if ((bss->SupportedRates[j] & 0x7f) > results[i].maxrate) { results[i].maxrate = bss->SupportedRates[j] & 0x7f; } } wpa_driver_ndis_get_ies(&results[i], bss->IEs, bss->IELength); pos += bss->Length; if (pos > (char *) b + blen) break; } free(b); return count;}static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_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; memset(&rkey, 0, sizeof(rkey)); rkey.Length = sizeof(rkey); rkey.KeyIndex = key_idx; if (pairwise) rkey.KeyIndex |= 1 << 30; memcpy(rkey.BSSID, bssid, ETH_ALEN); res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, sizeof(rkey)); if (!pairwise) { res2 = ndis_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_ndis_add_wep(struct wpa_driver_ndis_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; len = 12 + key_len; wep = malloc(len); if (wep == NULL) return -1; memset(wep, 0, len); wep->Length = len; wep->KeyIndex = key_idx; if (set_tx) wep->KeyIndex |= 1 << 31;#if 0 /* Setting bit30 does not seem to work with some NDIS drivers */ if (pairwise) wep->KeyIndex |= 1 << 30;#endif wep->KeyLength = key_len; memcpy(wep->KeyMaterial, key, key_len); wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_WEP", (char *) wep, len); res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); free(wep); return res;}static int wpa_driver_ndis_set_key(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_ndis_data *drv = priv; size_t len; NDIS_802_11_KEY *nkey; int i, res, pairwise; u8 bssid[ETH_ALEN]; if (addr == NULL || memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) { /* Group Key */ pairwise = 0; wpa_driver_ndis_get_bssid(drv, bssid); } else { /* Pairwise Key */ pairwise = 1; memcpy(bssid, addr, ETH_ALEN); } if (alg == WPA_ALG_NONE || key_len == 0) { return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid, pairwise); } if (alg == WPA_ALG_WEP) { return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx, key, key_len); } len = 12 + 6 + 6 + 8 + key_len; nkey = malloc(len); if (nkey == NULL) return -1; memset(nkey, 0, len); 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; 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) { memcpy(nkey->KeyMaterial, key, 16); memcpy(nkey->KeyMaterial + 16, key + 24, 8); memcpy(nkey->KeyMaterial + 24, key + 16, 8); } else { memcpy(nkey->KeyMaterial, key, key_len); } wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_KEY", (char *) nkey, len); res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); free(nkey); return res;}static intwpa_driver_ndis_associate(void *priv, struct wpa_driver_associate_params *params){ struct wpa_driver_ndis_data *drv = priv; u32 auth_mode, encr, priv_mode, mode; /* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys, * so static WEP keys needs to be set again after this. */ if (params->mode == IEEE80211_MODE_IBSS) mode = Ndis802_11IBSS; else mode = Ndis802_11Infrastructure; if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, (char *) &mode, sizeof(mode)) < 0) { wpa_printf(MSG_DEBUG, "NDIS: 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; priv_mode = Ndis802_11PrivFilterAcceptAll; } else if (params->wpa_ie[0] == RSN_INFO_ELEM) { priv_mode = Ndis802_11PrivFilter8021xWEP; if (params->key_mgmt_suite == KEY_MGMT_PSK) auth_mode = Ndis802_11AuthModeWPA2PSK; else auth_mode = Ndis802_11AuthModeWPA2; } else { priv_mode = Ndis802_11PrivFilter8021xWEP; 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; }; if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER, (char *) &priv_mode, sizeof(priv_mode)) < 0) { wpa_printf(MSG_DEBUG, "NDIS: Failed to set " "OID_802_11_PRIVACY_FILTER (%d)", (int) priv_mode); /* Try to continue anyway */ } ndis_set_auth_mode(drv, auth_mode); ndis_set_encr_status(drv, encr); return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len);}static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv){ int len, count, i, ret; struct ndis_pmkid_entry *entry; NDIS_802_11_PMKID *p; 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 = malloc(len); if (p == NULL) return -1; memset(p, 0, len); p->Length = len; p->BSSIDInfoCount = count; entry = drv->pmkid; for (i = 0; i < count; i++) { memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN); memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16); entry = entry->next; } wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (char *) p, len); ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len); free(p); return ret;}static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid){ struct wpa_driver_ndis_data *drv = priv; struct ndis_pmkid_entry *entry, *prev; if (drv->no_of_pmkid == 0) return 0; prev = NULL; entry = drv->pmkid; while (entry) { if (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. */ memcpy(entry->pmkid, pmkid, 16); if (prev) { prev->next = entry->next; entry->next = drv->pmkid; drv->pmkid = entry; } } else { entry = malloc(sizeof(*entry)); if (entry) { memcpy(entry->bssid, bssid, ETH_ALEN); memcpy(entry->pmkid, pmkid, 16); entry->next = drv->pmkid; drv->pmkid = entry; } } return wpa_driver_ndis_set_pmkid(drv);}static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid){ struct wpa_driver_ndis_data *drv = priv; struct ndis_pmkid_entry *entry, *prev; if (drv->no_of_pmkid == 0) return 0; entry = drv->pmkid; prev = NULL; drv->pmkid = NULL; while (entry) { if (memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && memcmp(entry->pmkid, pmkid, 16) == 0) { if (prev) prev->next = entry->next; else drv->pmkid = entry->next; free(entry); break; } prev = entry; entry = entry->next; } return wpa_driver_ndis_set_pmkid(drv);}static int wpa_driver_ndis_flush_pmkid(void *priv){ struct wpa_driver_ndis_data *drv = priv; NDIS_802_11_PMKID p; struct ndis_pmkid_entry *pmkid, *prev; if (drv->no_of_pmkid == 0) return 0; pmkid = drv->pmkid; drv->pmkid = NULL; while (pmkid) { prev = pmkid; pmkid = pmkid->next; free(prev); } memset(&p, 0, sizeof(p)); p.Length = 8; p.BSSIDInfoCount = 0; wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", (char *) &p, 8); return ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);}static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv){ char buf[512], *pos; NDIS_802_11_ASSOCIATION_INFORMATION *ai; int len, i; union wpa_event_data data; NDIS_802_11_BSSID_LIST_EX *b; size_t blen; len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf, sizeof(buf)); if (len < 0) { wpa_printf(MSG_DEBUG, "NDIS: failed to get association " "information"); return -1; } if (len > sizeof(buf)) { /* Some drivers seem to be producing incorrect length for this * data. Limit the length to the current buffer size to avoid * crashing in hexdump. The data seems to be otherwise valid, * so better try to use it. */ wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association " "information length %d", len); len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf, sizeof(buf)); if (len < -1) { wpa_printf(MSG_DEBUG, "NDIS: re-reading association " "information failed"); return -1; } if (len > sizeof(buf)) { wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association" " information length %d (re-read)", len); len = sizeof(buf); } } wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", buf, len); if (len < sizeof(*ai)) { wpa_printf(MSG_DEBUG, "NDIS: too short association " "information"); return -1; } ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf; wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d " "off_resp=%d len_req=%d len_resp=%d", ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs, (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs, (int) ai->RequestIELength, (int) ai->ResponseIELength); if (ai->OffsetRequestIEs + ai->RequestIELength > len || ai->OffsetResponseIEs + ai->ResponseIELength > len) { wpa_printf(MSG_DEBUG, "NDIS: association information - " "IE overflow"); return -1; } wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", buf + ai->OffsetRequestIEs, ai->RequestIELength); wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", buf + ai->OffsetResponseIEs, ai->ResponseIELength); memset(&data, 0, sizeof(data)); data.assoc_info.req_ies = buf + ai->OffsetRequestIEs; data.assoc_info.req_ies_len = ai->RequestIELength; data.assoc_info.resp_ies = buf + ai->OffsetResponseIEs; data.assoc_info.resp_ies_len = ai->ResponseIELength; blen = 65535; b = malloc(blen); if (b == NULL) goto skip_scan_results; memset(b, 0, blen); len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); if (len < 0) { wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); free(b); b = NULL; goto skip_scan_results; } wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo", (unsigned int) b->NumberOfItems); pos = (char *) &b->Bssid[0]; for (i = 0; i < b->NumberOfItems; i++) { NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; if (memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 && bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) { data.assoc_info.beacon_ies = ((u8 *) bss->IEs) + sizeof(NDIS_802_11_FIXED_IEs); data.assoc_info.beacon_ies_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs", data.assoc_info.beacon_ies, data.assoc_info.beacon_ies_len); break; } pos += bss->Length; if (pos > (char *) b + blen) break; }skip_scan_results: wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); free(b); return 0;}static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx){ struct wpa_driver_ndis_data *drv = eloop_ctx; u8 bssid[ETH_ALEN]; if (drv->wired) return; if (wpa_driver_ndis_get_bssid(drv, bssid)) { /* Disconnected */ if (memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) { memset(drv->bssid, 0, ETH_ALEN); wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); } } else { /* Connected */ if (memcmp(drv->bssid, bssid, ETH_ALEN) != 0) { memcpy(drv->bssid, bssid, ETH_ALEN); wpa_driver_ndis_get_associnfo(drv); wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); } } eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);}static void wpa_driver_ndis_poll(void *priv){ struct wpa_driver_ndis_data *drv = priv; eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); wpa_driver_ndis_poll_timeout(drv, NULL);}/* Called when driver generates Media Connect Event by calling * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv){ wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event"); if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) { wpa_driver_ndis_get_associnfo(drv); wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); }}/* Called when driver generates Media Disconnect Event by calling * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv){ wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event"); memset(drv->bssid, 0, ETH_ALEN); wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);}static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv, const u8 *data, size_t data_len){ NDIS_802_11_AUTHENTICATION_REQUEST *req; int pairwise = 0, group = 0; union wpa_event_data event; if (data_len < sizeof(*req)) { wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -