📄 driver_ndis.c
字号:
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; drv->mode = params->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; /* Need to make sure that BSSID polling is enabled for * IBSS mode. */ eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL); } 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->key_mgmt_suite == KEY_MGMT_NONE || params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) { /* Re-set WEP keys if static WEP configuration is used. */ u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; int i; for (i = 0; i < 4; i++) { if (!params->wep_key[i]) continue; wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP " "key %d", i); wpa_driver_ndis_set_key(drv, WPA_ALG_WEP, bcast, i, i == params->wep_tx_keyidx, NULL, 0, params->wep_key[i], params->wep_key_len[i]); } } 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] == WLAN_EID_RSN) { priv_mode = Ndis802_11PrivFilter8021xWEP; if (params->key_mgmt_suite == KEY_MGMT_PSK) auth_mode = Ndis802_11AuthModeWPA2PSK; else auth_mode = Ndis802_11AuthModeWPA2;#ifdef CONFIG_WPS } else if (params->key_mgmt_suite == KEY_MGMT_WPS) { auth_mode = Ndis802_11AuthModeOpen; priv_mode = Ndis802_11PrivFilterAcceptAll;#endif /* CONFIG_WPS */ } 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); if (params->bssid) { ndis_set_oid(drv, OID_802_11_BSSID, (char *) params->bssid, ETH_ALEN); drv->oid_bssid_set = 1; } else if (drv->oid_bssid_set) { ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff", ETH_ALEN); drv->oid_bssid_set = 0; } 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 = 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", (u8 *) p, len); ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len); os_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 (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_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; 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_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; int prev_authmode, ret; if (drv->no_of_pmkid == 0) return 0; pmkid = drv->pmkid; drv->pmkid = NULL; while (pmkid) { prev = pmkid; pmkid = pmkid->next; os_free(prev); } /* * Some drivers may refuse OID_802_11_PMKID if authMode is not set to * WPA2, so change authMode temporarily, if needed. */ prev_authmode = ndis_get_auth_mode(drv); if (prev_authmode != Ndis802_11AuthModeWPA2) ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2); os_memset(&p, 0, sizeof(p)); p.Length = 8; p.BSSIDInfoCount = 0; wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", (u8 *) &p, 8); ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); if (prev_authmode != Ndis802_11AuthModeWPA2) ndis_set_auth_mode(drv, prev_authmode); return ret;}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; union wpa_event_data data; NDIS_802_11_BSSID_LIST_EX *b; size_t blen, i; 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", (u8 *) 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 > (unsigned) len || ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) { wpa_printf(MSG_DEBUG, "NDIS: association information - " "IE overflow"); return -1; } wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength); wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength); os_memset(&data, 0, sizeof(data)); data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs; data.assoc_info.req_ies_len = ai->RequestIELength; data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs; data.assoc_info.resp_ies_len = ai->ResponseIELength; blen = 65535; b = os_zalloc(blen); if (b == NULL) goto skip_scan_results; 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"); os_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 (os_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); os_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]; int poll; if (drv->wired) return; if (wpa_driver_ndis_get_bssid(drv, bssid)) { /* Disconnected */ if (!is_zero_ether_addr(drv->bssid)) { os_memset(drv->bssid, 0, ETH_ALEN); wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); } } else { /* Connected */ if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) { os_memcpy(drv->bssid, bssid, ETH_ALEN); wpa_driver_ndis_get_associnfo(drv); wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); } } /* When using integrated NDIS event receiver, we can skip BSSID * polling when using infrastructure network. However, when using * IBSS mode, many driver do not seem to generate connection event, * so we need to enable BSSID polling to figure out when IBSS network * has been formed. */ poll = drv->mode == IEEE80211_MODE_IBSS;#ifndef CONFIG_NDIS_EVENTS_INTEGRATED#ifndef _WIN32_WCE poll = 1;#endif /* _WIN32_WCE */#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ if (poll) { 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"); os_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 " "Event (len=%d)", data_len); return; } req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data; wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: " "Bssid " MACSTR " Flags 0x%x", MAC2STR(req->Bssid), (int) req->Flags); if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) == NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) pairwise = 1; else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) == NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) group = 1; if (pairwise || group) { os_memset(&event, 0, sizeof(event)); event.michael_mic_failure.unicast = pairwise; wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, &event); }}static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -