📄 driver_ndis.c
字号:
const char *data, size_t len){#ifdef CONFIG_USE_NDISUIO NDISUIO_SET_OID *o; size_t buflen, reallen; DWORD written; char txt[50]; os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); buflen = sizeof(*o) + len; reallen = buflen - sizeof(o->Data); o = os_zalloc(buflen); if (o == NULL) return -1; o->Oid = oid;#ifdef _WIN32_WCE o->ptcDeviceName = drv->adapter_name;#endif /* _WIN32_WCE */ if (data) os_memcpy(o->Data, data, len); if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_SET_OID_VALUE, o, reallen, NULL, 0, &written, NULL)) { wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_SET_OID_VALUE " "(oid=%08x) failed: %d", oid, (int) GetLastError()); os_free(o); return -1; } os_free(o); return 0;#else /* CONFIG_USE_NDISUIO */ char *buf; PACKET_OID_DATA *o; char txt[50]; os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); buf = os_zalloc(sizeof(*o) + len); if (buf == NULL) return -1; o = (PACKET_OID_DATA *) buf; o->Oid = oid; o->Length = len; if (data) os_memcpy(o->Data, data, len); if (!PacketRequest(drv->adapter, TRUE, o)) { wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", __func__, oid, len); os_free(buf); return -1; } os_free(buf); return 0;#endif /* CONFIG_USE_NDISUIO */}static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode){ u32 auth_mode = mode; if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE, (char *) &auth_mode, sizeof(auth_mode)) < 0) { wpa_printf(MSG_DEBUG, "NDIS: Failed to set " "OID_802_11_AUTHENTICATION_MODE (%d)", (int) auth_mode); return -1; } return 0;}static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv){ u32 auth_mode; int res; res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE, (char *) &auth_mode, sizeof(auth_mode)); if (res != sizeof(auth_mode)) { wpa_printf(MSG_DEBUG, "NDIS: Failed to get " "OID_802_11_AUTHENTICATION_MODE"); return -1; } return auth_mode;}static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr){ u32 encr_status = encr; if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS, (char *) &encr_status, sizeof(encr_status)) < 0) { wpa_printf(MSG_DEBUG, "NDIS: Failed to set " "OID_802_11_ENCRYPTION_STATUS (%d)", encr); return -1; } return 0;}static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv){ u32 encr; int res; res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS, (char *) &encr, sizeof(encr)); if (res != sizeof(encr)) { wpa_printf(MSG_DEBUG, "NDIS: Failed to get " "OID_802_11_ENCRYPTION_STATUS"); return -1; } return encr;}static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid){ struct wpa_driver_ndis_data *drv = priv; if (drv->wired) { /* * Report PAE group address as the "BSSID" for wired * connection. */ os_memcpy(bssid, pae_group_addr, ETH_ALEN); return 0; } return ndis_get_oid(drv, OID_802_11_BSSID, (char *) bssid, ETH_ALEN) < 0 ? -1 : 0;}static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid){ struct wpa_driver_ndis_data *drv = priv; NDIS_802_11_SSID buf; int res; res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); if (res < 4) { wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID"); if (drv->wired) { wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure " "with a wired interface"); return 0; } return -1; } os_memcpy(ssid, buf.Ssid, buf.SsidLength); return buf.SsidLength;}static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv, const u8 *ssid, size_t ssid_len){ NDIS_802_11_SSID buf; os_memset(&buf, 0, sizeof(buf)); buf.SsidLength = ssid_len; os_memcpy(buf.Ssid, ssid, ssid_len); /* * Make sure radio is marked enabled here so that scan request will not * force SSID to be changed to a random one in order to enable radio at * that point. */ drv->radio_enabled = 1; return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));}/* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off. */static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv){ drv->radio_enabled = 0; return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4);}/* Disconnect by setting SSID to random (i.e., likely not used). */static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv){ char ssid[32]; int i; for (i = 0; i < 32; i++) ssid[i] = rand() & 0xff; return wpa_driver_ndis_set_ssid(drv, (u8 *) ssid, 32);}static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr, int reason_code){ struct wpa_driver_ndis_data *drv = priv; return wpa_driver_ndis_disconnect(drv);}static int wpa_driver_ndis_disassociate(void *priv, const u8 *addr, int reason_code){ struct wpa_driver_ndis_data *drv = priv; return wpa_driver_ndis_disconnect(drv);}static int wpa_driver_ndis_set_wpa(void *priv, int enabled){ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); return 0;}static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx){ wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);}static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len){ struct wpa_driver_ndis_data *drv = priv; int res; if (!drv->radio_enabled) { wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first" " scan"); if (wpa_driver_ndis_disconnect(drv) < 0) { wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio"); } drv->radio_enabled = 1; } res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, " ", 4); eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, drv->ctx); return res;}static struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid( struct wpa_scan_res *r, NDIS_802_11_SSID *ssid){ struct wpa_scan_res *nr; u8 *pos; if (wpa_scan_get_ie(r, WLAN_EID_SSID)) return r; /* SSID IE already present */ if (ssid->SsidLength == 0 || ssid->SsidLength > 32) return r; /* No valid SSID inside scan data */ nr = os_realloc(r, sizeof(*r) + r->ie_len + 2 + ssid->SsidLength); if (nr == NULL) return r; pos = ((u8 *) (nr + 1)) + nr->ie_len; *pos++ = WLAN_EID_SSID; *pos++ = ssid->SsidLength; os_memcpy(pos, ssid->Ssid, ssid->SsidLength); nr->ie_len += 2 + ssid->SsidLength; return nr;}static struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv){ struct wpa_driver_ndis_data *drv = priv; NDIS_802_11_BSSID_LIST_EX *b; size_t blen, count, i; int len; char *pos; struct wpa_scan_results *results; struct wpa_scan_res *r; blen = 65535; b = os_zalloc(blen); if (b == NULL) return NULL; 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); return NULL; } count = b->NumberOfItems; results = os_zalloc(sizeof(*results)); if (results == NULL) { os_free(b); return NULL; } results->res = os_zalloc(count * sizeof(struct wpa_scan_res *)); if (results->res == NULL) { os_free(results); os_free(b); return NULL; } pos = (char *) &b->Bssid[0]; for (i = 0; i < count; i++) { NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; NDIS_802_11_FIXED_IEs *fixed; if (bss->IELength < sizeof(NDIS_802_11_FIXED_IEs)) { wpa_printf(MSG_DEBUG, "NDIS: too small IELength=%d", (int) bss->IELength); break; } if (((char *) bss->IEs) + bss->IELength > (char *) b + blen) { /* * Some NDIS drivers have been reported to include an * entry with an invalid IELength in scan results and * this has crashed wpa_supplicant, so validate the * returned value before using it. */ wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan " "result IE (BSSID=" MACSTR ") IELength=%d", MAC2STR(bss->MacAddress), (int) bss->IELength); break; } r = os_zalloc(sizeof(*r) + bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)); if (r == NULL) break; os_memcpy(r->bssid, bss->MacAddress, ETH_ALEN); r->level = (int) bss->Rssi; r->freq = bss->Configuration.DSConfig / 1000; fixed = (NDIS_802_11_FIXED_IEs *) bss->IEs; r->beacon_int = WPA_GET_LE16((u8 *) &fixed->BeaconInterval); r->caps = WPA_GET_LE16((u8 *) &fixed->Capabilities); r->tsf = WPA_GET_LE64(fixed->Timestamp); os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs), bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)); r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); r = wpa_driver_ndis_add_scan_ssid(r, &bss->Ssid); results->res[results->num++] = r; pos += bss->Length; if (pos > (char *) b + blen) break; } os_free(b); return results;}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; 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 = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, sizeof(rkey)); if (!pairwise) { index = key_idx; res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP, (char *) &index, sizeof(index)); } else res2 = 0; if (res < 0 && res2 < 0) return -1; 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 = os_zalloc(len); if (wep == NULL) return -1; 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; os_memcpy(wep->KeyMaterial, key, key_len); wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP", (u8 *) wep, len); res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); os_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, i; NDIS_802_11_KEY *nkey; int res, pairwise; u8 bssid[ETH_ALEN]; if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) { /* Group Key */ pairwise = 0; if (wpa_driver_ndis_get_bssid(drv, bssid) < 0) os_memset(bssid, 0xff, ETH_ALEN); } else { /* Pairwise Key */ pairwise = 1; os_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 = 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 |= (ULONGLONG) 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_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY", (u8 *) nkey, len); res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); os_free(nkey);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -