📄 iw_ndis.c
字号:
} if (res) WARNING("getting bit rates failed: %08X", res); else { for (i = 0; i < n && range->num_bitrates < IW_MAX_BITRATES; i++) if (rates_ex[i] & 0x80) continue; else if (rates_ex[i] & 0x7f) { range->bitrate[range->num_bitrates] = (rates_ex[i] & 0x7f) * 500000; range->num_bitrates++; } } range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0])); for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) && i < IW_MAX_FREQUENCIES; i++) { range->freq[i].i = i + 1; range->freq[i].m = freq_chan[i] * 100000; range->freq[i].e = 1; } range->num_frequency = i; range->min_rts = 0; range->max_rts = 2347; range->min_frag = 256; range->max_frag = 2346;#if WIRELESS_EXT > 16 /* Event capability (kernel + driver) */ range->event_capa[0] = (IW_EVENT_CAPA_K_0 | IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | IW_EVENT_CAPA_MASK(SIOCGIWAP) | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); range->event_capa[1] = IW_EVENT_CAPA_K_1; range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) | IW_EVENT_CAPA_MASK(IWEVCUSTOM) | IW_EVENT_CAPA_MASK(IWEVREGISTERED) | IW_EVENT_CAPA_MASK(IWEVEXPIRED));#endif /* WIRELESS_EXT > 16 */#if WIRELESS_EXT > 17 range->enc_capa = 0; if (test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr)) range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP; if (test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr)) range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP; if (test_bit(Ndis802_11AuthModeWPA, &wnd->capa.auth) || test_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth)) range->enc_capa |= IW_ENC_CAPA_WPA; if (test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) || test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth)) range->enc_capa |= IW_ENC_CAPA_WPA2;#endif /* WIRELESS_EXT > 17 */ return 0;}NDIS_STATUS disassociate(struct wrap_ndis_device *wnd, int reset_ssid){ NDIS_STATUS res; u8 buf[NDIS_ESSID_MAX_SIZE]; int i; TRACE2(""); res = miniport_set_info(wnd, OID_802_11_DISASSOCIATE, NULL, 0); /* disassociate causes radio to be turned off; if reset_ssid * is given, set ssid to random to enable radio */ if (reset_ssid) { get_random_bytes(buf, sizeof(buf)); for (i = 0; i < sizeof(buf); i++) buf[i] = 'a' + (buf[i] % 26); set_essid(wnd, buf, sizeof(buf)); } return res;}static int deauthenticate(struct wrap_ndis_device *wnd){ int ret; ENTER2(""); ret = disassociate(wnd, 1); set_priv_filter(wnd, Ndis802_11PrivFilterAcceptAll); set_auth_mode(wnd, Ndis802_11AuthModeOpen); set_encr_mode(wnd, Ndis802_11EncryptionDisabled); EXIT2(return ret);}int set_priv_filter(struct wrap_ndis_device *wnd, int flags){ NDIS_STATUS res; ENTER2("filter: %d", flags); res = miniport_set_int(wnd, OID_802_11_PRIVACY_FILTER, flags); if (res) TRACE2("setting privacy filter to %d failed (%08X)", flags, res); EXIT2(return 0);}#if WIRELESS_EXT > 17static int iw_set_mlme(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); struct iw_mlme *mlme = (struct iw_mlme *)extra; ENTER2(""); switch (mlme->cmd) { case IW_MLME_DEAUTH: return deauthenticate(wnd); case IW_MLME_DISASSOC: TRACE2("cmd=%d reason_code=%d", mlme->cmd, mlme->reason_code); return disassociate(wnd, 1); default: return -EOPNOTSUPP; } return 0;}static int iw_set_genie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ /* * NDIS drivers do not allow IEs to be configured; this is * done by the driver based on other configuration. Return 0 * to avoid causing issues with user space programs that * expect this function to succeed. */ return 0;}static int iw_set_auth(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); TRACE2("index=%d value=%d", wrqu->param.flags & IW_AUTH_INDEX, wrqu->param.value); wnd->iw_auth_set = 1; switch (wrqu->param.flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: wnd->iw_auth_wpa_version = wrqu->param.value; break; case IW_AUTH_CIPHER_PAIRWISE: wnd->iw_auth_cipher_pairwise = wrqu->param.value; break; case IW_AUTH_CIPHER_GROUP: wnd->iw_auth_cipher_group = wrqu->param.value; break; case IW_AUTH_KEY_MGMT: wnd->iw_auth_key_mgmt = wrqu->param.value; break; case IW_AUTH_80211_AUTH_ALG: wnd->iw_auth_80211_auth_alg = wrqu->param.value; break; case IW_AUTH_WPA_ENABLED: case IW_AUTH_TKIP_COUNTERMEASURES: case IW_AUTH_DROP_UNENCRYPTED: case IW_AUTH_RX_UNENCRYPTED_EAPOL: case IW_AUTH_PRIVACY_INVOKED: TRACE2("%d not implemented", wrqu->param.flags & IW_AUTH_INDEX); /* TODO */ break; default: WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX); return -EOPNOTSUPP; } return 0;}static int iw_get_auth(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); ENTER2("index=%d", wrqu->param.flags & IW_AUTH_INDEX); switch (wrqu->param.flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: wrqu->param.value = wnd->iw_auth_wpa_version; break; case IW_AUTH_CIPHER_PAIRWISE: wrqu->param.value = wnd->iw_auth_cipher_pairwise; break; case IW_AUTH_CIPHER_GROUP: wrqu->param.value = wnd->iw_auth_cipher_group; break; case IW_AUTH_KEY_MGMT: wrqu->param.value = wnd->iw_auth_key_mgmt; break; case IW_AUTH_80211_AUTH_ALG: wrqu->param.value = wnd->iw_auth_80211_auth_alg; break; default: WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX); return -EOPNOTSUPP; } return 0;}static int iw_set_encodeext(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct iw_encode_ext ext; struct wrap_ndis_device *wnd = netdev_priv(dev); struct ndis_add_key ndis_key; int i, keyidx; NDIS_STATUS res; u8 *addr; u8 key[IW_ENCODING_TOKEN_MAX]; ENTER2(""); keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; if (keyidx > 0) keyidx--; else keyidx = wnd->encr_info.tx_key_index; if (keyidx < 0 || keyidx >= MAX_ENCR_KEYS) return -EINVAL; if (copy_from_user(&ext, wrqu->encoding.pointer, sizeof(ext))) EXIT2(return -EFAULT); if (copy_from_user(key, wrqu->encoding.pointer + sizeof(ext), ext.key_len)) EXIT2(return -EFAULT); if (ext.alg == WPA_ALG_WEP) { if (!test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr)) EXIT2(return -1); if (ext.ext_flags & IW_ENCODE_EXT_SET_TX_KEY) wnd->encr_info.tx_key_index = keyidx; if (add_wep_key(wnd, key, ext.key_len, keyidx)) EXIT2(return -1); else EXIT2(return 0); } if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) || ext.alg == IW_ENCODE_ALG_NONE || ext.key_len == 0) EXIT2(return remove_key(wnd, keyidx, ndis_key.bssid)); if (ext.key_len > sizeof(ndis_key.key)) { TRACE2("incorrect key length (%u)", ext.key_len); EXIT2(return -1); } memset(&ndis_key, 0, sizeof(ndis_key)); ndis_key.struct_size = sizeof(ndis_key) - sizeof(ndis_key.key) + ext.key_len; ndis_key.length = ext.key_len; ndis_key.index = keyidx; if (ext.ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { for (i = ndis_key.rsc = 0 ; i < 6 ; i++) ndis_key.rsc |= (ext.rx_seq[i] << (i * 8)); ndis_key.index |= 1 << 29; } addr = ext.addr.sa_data; TRACE2("infra_mode = %d, addr = " MACSTRSEP, wnd->infrastructure_mode, MAC2STR(addr)); if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) { /* group key */ if (wnd->infrastructure_mode == Ndis802_11IBSS) memset(ndis_key.bssid, 0xff, ETH_ALEN); else get_ap_address(wnd, ndis_key.bssid); } else { /* pairwise key */ ndis_key.index |= (1 << 30); memcpy(&ndis_key.bssid, addr, ETH_ALEN); } TRACE2("bssid " MACSTRSEP, MAC2STR(ndis_key.bssid)); if (ext.ext_flags & IW_ENCODE_EXT_SET_TX_KEY) ndis_key.index |= (1 << 31); if (ext.alg == IW_ENCODE_ALG_TKIP && ext.key_len == 32) { /* wpa_supplicant gives us the Michael MIC RX/TX keys in * different order than NDIS spec, so swap the order here. */ memcpy(ndis_key.key, key, 16); memcpy(ndis_key.key + 16, key + 24, 8); memcpy(ndis_key.key + 24, key + 16, 8); } else memcpy(ndis_key.key, key, ext.key_len); res = miniport_set_info(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size); if (res) { TRACE2("adding key failed (%08X), %u", res, ndis_key.struct_size); EXIT2(return -1); } wnd->encr_info.keys[keyidx].length = ext.key_len; memcpy(&wnd->encr_info.keys[keyidx].key, &ndis_key.key, ext.key_len); if (ext.ext_flags & IW_ENCODE_EXT_SET_TX_KEY) wnd->encr_info.tx_key_index = keyidx; TRACE2("key %d added", keyidx); EXIT2(return 0);}static int iw_get_encodeext(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ /* struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; */ /* TODO */ ENTER2(""); return 0;}static int iw_set_pmksa(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct iw_pmksa *pmksa = (struct iw_pmksa *) extra; struct ndis_pmkid pmkid; NDIS_STATUS res; struct wrap_ndis_device *wnd = netdev_priv(dev); /* TODO: must keep local list of PMKIDs since NDIS drivers * expect that all PMKID entries are included whenever a new * one is added. */ ENTER2(""); if (wnd->auth_mode != Ndis802_11AuthModeWPA2) return -EOPNOTSUPP; memset(&pmkid, 0, sizeof(pmkid)); if (pmksa->cmd == IW_PMKSA_ADD) { pmkid.bssid_info_count = 1; memcpy(pmkid.bssid_info[0].bssid, pmksa->bssid.sa_data, ETH_ALEN); memcpy(pmkid.bssid_info[0].pmkid, pmksa->pmkid, IW_PMKID_LEN); } pmkid.length = 8 + pmkid.bssid_info_count * sizeof(struct ndis_bssid_info); res = miniport_set_info(wnd, OID_802_11_PMKID, &pmkid, sizeof(pmkid)); if (res == NDIS_STATUS_FAILURE) return -EOPNOTSUPP; TRACE2("OID_802_11_PMKID -> %d", res); if (res) return -EINVAL; return 0;}#endif /* WIRELESS_EXT > 17 */static const iw_handler ndis_handler[] = { [SIOCGIWNAME - SIOCIWFIRST] = iw_get_network_type, [SIOCSIWESSID - SIOCIWFIRST] = iw_set_essid, [SIOCGIWESSID - SIOCIWFIRST] = iw_get_essid, [SIOCSIWMODE - SIOCIWFIRST] = iw_set_infra_mode, [SIOCGIWMODE - SIOCIWFIRST] = iw_get_infra_mode, [SIOCGIWFREQ - SIOCIWFIRST] = iw_get_freq, [SIOCSIWFREQ - SIOCIWFIRST] = iw_set_freq, [SIOCGIWTXPOW - SIOCIWFIRST] = iw_get_tx_power, [SIOCSIWTXPOW - SIOCIWFIRST] = iw_set_tx_power, [SIOCGIWRATE - SIOCIWFIRST] = iw_get_bitrate, [SIOCSIWRATE - SIOCIWFIRST] = iw_set_bitrate, [SIOCGIWRTS - SIOCIWFIRST] = iw_get_rts_threshold, [SIOCSIWRTS - SIOCIWFIRST] = iw_set_rts_threshold, [SIOCGIWFRAG - SIOCIWFIRST] = iw_get_frag_threshold, [SIOCSIWFRAG - SIOCIWFIRST] = iw_set_frag_threshold, [SIOCGIWAP - SIOCIWFIRST] = iw_get_ap_address, [SIOCSIWAP - SIOCIWFIRST] = iw_set_ap_address, [SIOCSIWENCODE - SIOCIWFIRST] = iw_set_wep, [SIOCGIWENCODE - SIOCIWFIRST] = iw_get_encr, [SIOCSIWSCAN - SIOCIWFIRST] = iw_set_scan, [SIOCGIWSCAN - SIOCIWFIRST] = iw_get_scan, [SIOCGIWPOWER - SIOCIWFIRST] = iw_get_power_mode, [SIOCSIWPOWER - SIOCIWFIRST] = iw_set_power_mode, [SIOCGIWRANGE - SIOCIWFIRST] = iw_get_range, [SIOCGIWSTATS - SIOCIWFIRST] = iw_get_ndis_stats, [SIOCGIWSENS - SIOCIWFIRST] = iw_get_sensitivity, [SIOCSIWSENS - SIOCIWFIRST] = iw_set_sensitivity, [SIOCGIWNICKN - SIOCIWFIRST] = iw_get_nick, [SIOCSIWNICKN - SIOCIWFIRST] = iw_set_nick, [SIOCSIWCOMMIT - SIOCIWFIRST] = iw_set_dummy,#if WIRELESS_EXT > 17 [SIOCSIWMLME - SIOCIWFIRST] = iw_set_mlme, [SIOCSIWGENIE - SIOCIWFIRST] = iw_set_genie, [SIOCSIWAUTH - SIOCIWFIRST] = iw_set_auth, [SIOCGIWAUTH - SIOCIWFIRST] = iw_get_auth, [SIOCSIWENCODEEXT - SIOCIWFIRST] = iw_set_encodeext, [SIOCGIWENCODEEXT - SIOCIWFIRST] = iw_get_encodeext, [SIOCSIWPMKSA - SIOCIWFIRST] = iw_set_pmksa,#endif /* WIRELESS_EXT > 17 */};/* private ioctl's */static int priv_reset(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ int res; ENTER2(""); res = miniport_reset(netdev_priv(dev)); if (res) { WARNING("reset failed: %08X", res); return -EOPNOTSUPP; } return 0;}static int priv_usb_reset(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ int res; struct wrap_ndis_device *wnd; ENTER2(""); wnd = netdev_priv(dev); res = 0;#if defined(CONFIG_USB) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) res = usb_reset_configuration(wnd->wd->usb.udev); if (res) { WARNING("reset failed: %08X", res); return -EOPNOTSUPP; }#endif return 0;}static int priv_power_profile(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); struct miniport_char *miniport; ULONG profile_inf; ENTER2(""); miniport = &wnd->wd->driver->ndis_driver->miniport; if (!miniport->pnp_event_notify) EXIT2(return -EOPNOTSUPP); /* 1 for AC and 0 for Battery */ if (wrqu->param.value) profile_inf = NdisPowerProfileAcOnLine; else profile_inf = NdisPowerProfileBattery; LIN2WIN4(miniport->pnp_event_notify, wnd->nmb->adapter_ctx, NdisDevicePnPEventPowerProfileChanged, &profile_inf, sizeof(profile_inf)); EXIT2(return 0);}static int priv_network_type(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -