📄 iw_ndis.c
字号:
static int deauthenticate(struct wrap_ndis_device *wnd){ int ret; ENTER2(""); ret = disassociate(wnd, 1); set_default_iw_params(wnd); EXIT2(return ret);}NDIS_STATUS disassociate(struct wrap_ndis_device *wnd, int reset_ssid){ NDIS_STATUS res; u8 buf[NDIS_ESSID_MAX_SIZE]; int i; TRACE2(""); res = mp_set(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;}ULONG ndis_priv_mode(struct wrap_ndis_device *wnd){ if (wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2 || wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA) return Ndis802_11PrivFilter8021xWEP; else return Ndis802_11PrivFilterAcceptAll;}int set_priv_filter(struct wrap_ndis_device *wnd){ NDIS_STATUS res; ULONG flags; flags = ndis_priv_mode(wnd); ENTER2("filter: %d", flags); res = mp_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); 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_alg = wrqu->param.value; break; case IW_AUTH_WPA_ENABLED: if (wrqu->param.value) deauthenticate(wnd); break; 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: %d", wrqu->param.flags & IW_AUTH_INDEX, wrqu->param.value); 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_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 iw_encode_ext *)extra; struct wrap_ndis_device *wnd = netdev_priv(dev); struct ndis_add_key ndis_key; int i, keyidx; NDIS_STATUS res; u8 *addr; keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; ENTER2("%d", keyidx); if (keyidx) keyidx--; else keyidx = wnd->encr_info.tx_key_index; if (keyidx < 0 || keyidx >= MAX_ENCR_KEYS) return -EINVAL; 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, ext->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 = 0; i < 6 ; i++) ndis_key.rsc |= (ext->rx_seq[i] << (i * 8)); TRACE2("0x%Lx", ndis_key.rsc); ndis_key.index |= 1 << 29; } addr = ext->addr.sa_data; if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { /* 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(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, ext->key, 16); memcpy(ndis_key.key + 16, ext->key + 24, 8); memcpy(ndis_key.key + 24, ext->key + 16, 8); } else memcpy(ndis_key.key, ext->key, ext->key_len); res = mp_set(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("%d", pmksa->cmd); if ((pmksa->cmd == IW_PMKSA_ADD || pmksa->cmd == IW_PMKSA_REMOVE) && (!(wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2))) EXIT2(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 = sizeof(pmkid); res = mp_set(wnd, OID_802_11_PMKID, &pmkid, pmkid.length); if (res == NDIS_STATUS_FAILURE) EXIT2(return -EOPNOTSUPP); TRACE2("OID_802_11_PMKID -> %d", res); if (res) return -EINVAL; return 0;}#endif /* WIRELESS_EXT > 17 */#define WEXT(id) [id - SIOCIWFIRST]static const iw_handler ndis_handler[] = { WEXT(SIOCGIWNAME) = iw_get_network_type, WEXT(SIOCSIWESSID) = iw_set_essid, WEXT(SIOCGIWESSID) = iw_get_essid, WEXT(SIOCSIWMODE) = iw_set_infra_mode, WEXT(SIOCGIWMODE) = iw_get_infra_mode, WEXT(SIOCGIWFREQ) = iw_get_freq, WEXT(SIOCSIWFREQ) = iw_set_freq, WEXT(SIOCGIWTXPOW) = iw_get_tx_power, WEXT(SIOCSIWTXPOW) = iw_set_tx_power, WEXT(SIOCGIWRATE) = iw_get_bitrate, WEXT(SIOCSIWRATE) = iw_set_bitrate, WEXT(SIOCGIWRTS) = iw_get_rts_threshold, WEXT(SIOCSIWRTS) = iw_set_rts_threshold, WEXT(SIOCGIWFRAG) = iw_get_frag_threshold, WEXT(SIOCSIWFRAG) = iw_set_frag_threshold, WEXT(SIOCGIWAP) = iw_get_ap_address, WEXT(SIOCSIWAP) = iw_set_ap_address, WEXT(SIOCSIWENCODE) = iw_set_wep, WEXT(SIOCGIWENCODE) = iw_get_encr, WEXT(SIOCSIWSCAN) = iw_set_scan, WEXT(SIOCGIWSCAN) = iw_get_scan, WEXT(SIOCGIWPOWER) = iw_get_power_mode, WEXT(SIOCSIWPOWER) = iw_set_power_mode, WEXT(SIOCGIWRANGE) = iw_get_range, WEXT(SIOCGIWSTATS) = iw_get_ndis_stats, WEXT(SIOCGIWSENS) = iw_get_sensitivity, WEXT(SIOCSIWSENS) = iw_set_sensitivity, WEXT(SIOCGIWNICKN) = iw_get_nick, WEXT(SIOCSIWNICKN) = iw_set_nick, WEXT(SIOCSIWCOMMIT) = iw_set_dummy,#if WIRELESS_EXT > 17 WEXT(SIOCSIWMLME) = iw_set_mlme, WEXT(SIOCSIWGENIE) = iw_set_genie, WEXT(SIOCSIWAUTH) = iw_set_auth, WEXT(SIOCGIWAUTH) = iw_get_auth, WEXT(SIOCSIWENCODEEXT) = iw_set_encodeext, WEXT(SIOCGIWENCODEEXT) = iw_get_encodeext, WEXT(SIOCSIWPMKSA) = 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 = mp_reset(netdev_priv(dev)); if (res) { WARNING("reset failed: %08X", res); return -EOPNOTSUPP; } return 0;}static int priv_deauthenticate(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ int res; ENTER2(""); res = deauthenticate(netdev_priv(dev)); return res;}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 *mp; ULONG profile_inf; ENTER2(""); mp = &wnd->wd->driver->ndis_driver->mp; if (!mp->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(mp->pnp_event_notify, wnd->nmb->mp_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){ struct wrap_ndis_device *wnd = netdev_priv(dev); enum network_type network_type; NDIS_STATUS res; char type; ENTER2(""); type = wrqu->param.value; if (type == 'f') network_type = Ndis802_11FH; else if (type == 'b') network_type = Ndis802_11DS; else if (type == 'a') network_type = Ndis802_11OFDM5; else if (type == 'g' || type == 'n') network_type = Ndis802_11OFDM24; else network_type = Ndis802_11Automode; res = mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, network_type); if (res) { WARNING("setting network type to %d failed (%08X)", network_type, res); EXIT2(return -EINVAL); } EXIT2(return 0);}static int priv_media_stream_mode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); NDIS_STATUS res; int mode; ENTER2(""); if (wrqu->param.value > 0) mode = Ndis802_11MediaStreamOn; else mode = Ndis802_11MediaStreamOff; res = mp_set_int(wnd, OID_802_11_MEDIA_STREAM_MODE, mode); if (res) { WARNING("oid failed (%08X)", res); EXIT2(return -EINVAL); } EXIT2(return 0);}static int priv_reload_defaults(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); int res; ENTER2(""); res = mp_set_int(wnd, OID_802_11_RELOAD_DEFAULTS, Ndis802_11ReloadWEPKeys); if (res) { WARNING("reloading defaults failed: %08X", res); return -EOPNOTSUPP; } return 0;}static const struct iw_priv_args priv_args[] = { {PRIV_RESET, 0, 0, "ndis_reset"}, {PRIV_POWER_PROFILE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "power_profile"}, {PRIV_DEAUTHENTICATE, 0, 0, "deauthenticate"}, {PRIV_NETWORK_TYPE, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "network_type"}, {PRIV_MEDIA_STREAM_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "media_stream"}, {PRIV_RELOAD_DEFAULTS, 0, 0, "reload_defaults"},};#define WEPRIV(id) [id - SIOCIWFIRSTPRIV]static const iw_handler priv_handler[] = { WEPRIV(PRIV_RESET) = priv_reset, WEPRIV(PRIV_POWER_PROFILE) = priv_power_profile, WEPRIV(PRIV_DEAUTHENTICATE) = priv_deauthenticate, WEPRIV(PRIV_NETWORK_TYPE) = priv_network_type, WEPRIV(PRIV_MEDIA_STREAM_MODE) = priv_media_stream_mode, WEPRIV(PRIV_RELOAD_DEFAULTS) = priv_reload_defaults,};const struct iw_handler_def ndis_handler_def = { .num_standard = sizeof(ndis_handler) / sizeof(ndis_handler[0]), .num_private = sizeof(priv_handler) / sizeof(priv_handler[0]), .num_private_args = sizeof(priv_args) / sizeof(priv_args[0]), .standard = (iw_handler *)ndis_handler, .private = (iw_handler *)priv_handler, .private_args = (struct iw_priv_args *)priv_args,#if WIRELESS_EXT >= 19 .get_wireless_stats = get_iw_stats,#endif};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -