📄 iw_ndis.c
字号:
if (res) return -ENOTSUPP; wrqu->frag.value = frag_threshold; return 0;}static int iw_set_frag_threshold(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); ndis_rts_threshold threshold; NDIS_STATUS res; ENTER2(""); threshold = wrqu->frag.value; res = mp_set(wnd, OID_802_11_FRAGMENTATION_THRESHOLD, &threshold, sizeof(threshold)); if (res == NDIS_STATUS_INVALID_DATA) return -EINVAL; if (res) return -EOPNOTSUPP; return 0;}int get_ap_address(struct wrap_ndis_device *wnd, mac_address ap_addr){ NDIS_STATUS res; res = mp_query(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN); TRACE2(MACSTRSEP, MAC2STR(ap_addr)); if (res) { TRACE2("res: %08X", res); memset(ap_addr, 0x0, ETH_ALEN); EXIT2(return -EOPNOTSUPP); } EXIT2(return 0);}static int iw_get_ap_address(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); mac_address ap_addr; ENTER2(""); get_ap_address(wnd, ap_addr); memcpy(wrqu->ap_addr.sa_data, ap_addr, ETH_ALEN); wrqu->ap_addr.sa_family = ARPHRD_ETHER; EXIT2(return 0);}static int iw_set_ap_address(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; mac_address ap_addr; ENTER2(""); memcpy(ap_addr, wrqu->ap_addr.sa_data, ETH_ALEN); TRACE2(MACSTRSEP, MAC2STR(ap_addr)); res = mp_set(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN); /* user apps may set ap's mac address, which is not required; * they may fail to work if this function fails, so return * success */ if (res) WARNING("setting AP mac address failed (%08X)", res); EXIT2(return 0);}int set_iw_auth_mode(struct wrap_ndis_device *wnd, int wpa_version, int auth_80211_alg){ NDIS_STATUS res; ULONG auth_mode; ENTER2("%d, %d", wpa_version, auth_80211_alg); if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) { if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X) auth_mode = Ndis802_11AuthModeWPA2; else auth_mode = Ndis802_11AuthModeWPA2PSK; } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) { if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X) auth_mode = Ndis802_11AuthModeWPA; else if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_PSK) auth_mode = Ndis802_11AuthModeWPAPSK; else auth_mode = Ndis802_11AuthModeWPANone; } else if (auth_80211_alg & IW_AUTH_ALG_SHARED_KEY) { if (auth_80211_alg & IW_AUTH_ALG_OPEN_SYSTEM) auth_mode = Ndis802_11AuthModeAutoSwitch; else auth_mode = Ndis802_11AuthModeShared; } else auth_mode = Ndis802_11AuthModeOpen; res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode); if (res) { WARNING("setting auth mode to %u failed (%08X)", auth_mode, res); if (res == NDIS_STATUS_INVALID_DATA) EXIT2(return -EINVAL); return -EOPNOTSUPP; } wnd->iw_auth_wpa_version = wpa_version; wnd->iw_auth_80211_alg = auth_80211_alg; EXIT2(return 0);}int set_ndis_auth_mode(struct wrap_ndis_device *wnd, ULONG auth_mode){ NDIS_STATUS res; ENTER2("%d", auth_mode); res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode); if (res) { WARNING("setting auth mode to %u failed (%08X)", auth_mode, res); if (res == NDIS_STATUS_INVALID_DATA) EXIT2(return -EINVAL); return -EOPNOTSUPP; } switch (auth_mode) { case Ndis802_11AuthModeWPA: wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA; wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X; break; case Ndis802_11AuthModeWPAPSK: wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA; wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK; case Ndis802_11AuthModeWPANone: wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK; break; case Ndis802_11AuthModeWPA2: wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2; wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X; break; case Ndis802_11AuthModeWPA2PSK: wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2; wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK; break; case Ndis802_11AuthModeOpen: wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; wnd->iw_auth_80211_alg = IW_AUTH_ALG_OPEN_SYSTEM; break; case Ndis802_11AuthModeShared: wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY; break; case Ndis802_11AuthModeAutoSwitch: wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY; wnd->iw_auth_80211_alg |= IW_AUTH_ALG_OPEN_SYSTEM; break; default: WARNING("invalid authentication algorithm: %d", auth_mode); break; } EXIT2(return 0);}int set_auth_mode(struct wrap_ndis_device *wnd){ return set_iw_auth_mode(wnd, wnd->iw_auth_wpa_version, wnd->iw_auth_80211_alg);}int get_ndis_auth_mode(struct wrap_ndis_device *wnd){ ULONG mode; NDIS_STATUS res; res = mp_query_int(wnd, OID_802_11_AUTHENTICATION_MODE, &mode); if (res) { WARNING("getting authentication mode failed (%08X)", res); EXIT2(return -EOPNOTSUPP); } TRACE2("%d", mode); return mode;}int set_iw_encr_mode(struct wrap_ndis_device *wnd, int cipher_pairwise, int cipher_groupwise){ NDIS_STATUS res; ULONG ndis_mode; ENTER2("%d, %d", cipher_pairwise, cipher_groupwise); if (cipher_pairwise & IW_AUTH_CIPHER_CCMP) ndis_mode = Ndis802_11Encryption3Enabled; else if (cipher_pairwise & IW_AUTH_CIPHER_TKIP) ndis_mode = Ndis802_11Encryption2Enabled; else if (cipher_pairwise & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) ndis_mode = Ndis802_11Encryption1Enabled; else if (cipher_groupwise & IW_AUTH_CIPHER_CCMP) ndis_mode = Ndis802_11Encryption3Enabled; else if (cipher_groupwise & IW_AUTH_CIPHER_TKIP) ndis_mode = Ndis802_11Encryption2Enabled; else ndis_mode = Ndis802_11EncryptionDisabled; res = mp_set_int(wnd, OID_802_11_ENCRYPTION_STATUS, ndis_mode); if (res) { WARNING("setting encryption mode to %u failed (%08X)", ndis_mode, res); if (res == NDIS_STATUS_INVALID_DATA) EXIT2(return -EINVAL); return -EOPNOTSUPP; } wnd->iw_auth_cipher_pairwise = cipher_pairwise; wnd->iw_auth_cipher_group = cipher_groupwise; EXIT2(return 0);}int set_encr_mode(struct wrap_ndis_device *wnd){ return set_iw_encr_mode(wnd, wnd->iw_auth_cipher_pairwise, wnd->iw_auth_cipher_group);}int get_ndis_encr_mode(struct wrap_ndis_device *wnd){ ULONG mode; NDIS_STATUS res; ENTER2(""); res = mp_query_int(wnd, OID_802_11_ENCRYPTION_STATUS, &mode); if (res) { WARNING("getting encryption status failed (%08X)", res); EXIT2(return -EOPNOTSUPP); } else EXIT2(return mode);}static int iw_get_encr(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); int index, mode; struct encr_info *encr_info = &wnd->encr_info; ENTER2("wnd = %p", wnd); wrqu->data.length = 0; extra[0] = 0; index = (wrqu->encoding.flags & IW_ENCODE_INDEX); TRACE2("index = %u", index); if (index > 0) index--; else index = encr_info->tx_key_index; if (index < 0 || index >= MAX_ENCR_KEYS) { WARNING("encryption index out of range (%u)", index); EXIT2(return -EINVAL); } if (index != encr_info->tx_key_index) { if (encr_info->keys[index].length > 0) { wrqu->data.flags |= IW_ENCODE_ENABLED; wrqu->data.length = encr_info->keys[index].length; memcpy(extra, encr_info->keys[index].key, encr_info->keys[index].length); } else wrqu->data.flags |= IW_ENCODE_DISABLED; EXIT2(return 0); } /* transmit key */ mode = get_ndis_encr_mode(wnd); if (mode < 0) EXIT2(return -EOPNOTSUPP); if (mode == Ndis802_11EncryptionDisabled || mode == Ndis802_11EncryptionNotSupported) wrqu->data.flags |= IW_ENCODE_DISABLED; else { if (mode == Ndis802_11Encryption1KeyAbsent || mode == Ndis802_11Encryption2KeyAbsent || mode == Ndis802_11Encryption3KeyAbsent) wrqu->data.flags |= IW_ENCODE_NOKEY; else { wrqu->data.flags |= IW_ENCODE_ENABLED; wrqu->encoding.flags |= index+1; wrqu->data.length = encr_info->keys[index].length; memcpy(extra, encr_info->keys[index].key, encr_info->keys[index].length); } } mode = get_ndis_auth_mode(wnd); if (mode < 0) EXIT2(return -EOPNOTSUPP); if (mode == Ndis802_11AuthModeOpen) wrqu->data.flags |= IW_ENCODE_OPEN; else if (mode == Ndis802_11AuthModeAutoSwitch) wrqu->data.flags |= IW_ENCODE_RESTRICTED; else // Ndis802_11AuthModeAutoSwitch, Ndis802_11AuthModeWPA etc. wrqu->data.flags |= IW_ENCODE_RESTRICTED; EXIT2(return 0);}/* index must be 0 - N, as per NDIS */int add_wep_key(struct wrap_ndis_device *wnd, char *key, int key_len, int index){ struct ndis_encr_key ndis_key; NDIS_STATUS res; ENTER2("key index: %d, length: %d", index, key_len); if (key_len <= 0 || key_len > NDIS_ENCODING_TOKEN_MAX) { WARNING("invalid key length (%d)", key_len); EXIT2(return -EINVAL); } if (index < 0 || index >= MAX_ENCR_KEYS) { WARNING("invalid key index (%d)", index); EXIT2(return -EINVAL); } ndis_key.struct_size = sizeof(ndis_key); ndis_key.length = key_len; memcpy(&ndis_key.key, key, key_len); ndis_key.index = index; if (index == wnd->encr_info.tx_key_index) { ndis_key.index |= (1 << 31); res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104, IW_AUTH_CIPHER_NONE); if (res) WARNING("encryption couldn't be enabled (%08X)", res); } TRACE2("key %d: " MACSTRSEP, index, MAC2STR(key)); res = mp_set(wnd, OID_802_11_ADD_WEP, &ndis_key, sizeof(ndis_key)); if (res) { WARNING("adding encryption key %d failed (%08X)", index+1, res); EXIT2(return -EINVAL); } /* Atheros driver messes up ndis_key during ADD_WEP, so * don't rely on that; instead use info in key and key_len */ wnd->encr_info.keys[index].length = key_len; memcpy(&wnd->encr_info.keys[index].key, key, key_len); EXIT2(return 0);}/* remove_key is for both wep and wpa */static int remove_key(struct wrap_ndis_device *wnd, int index, mac_address bssid){ NDIS_STATUS res; if (wnd->encr_info.keys[index].length == 0) EXIT2(return 0); wnd->encr_info.keys[index].length = 0; memset(&wnd->encr_info.keys[index].key, 0, sizeof(wnd->encr_info.keys[index].length)); if (wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_TKIP || wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_CCMP || wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_TKIP || wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_CCMP) { struct ndis_remove_key remove_key; remove_key.struct_size = sizeof(remove_key); remove_key.index = index; if (bssid) { /* pairwise key */ if (memcmp(bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) remove_key.index |= (1 << 30); memcpy(remove_key.bssid, bssid, sizeof(remove_key.bssid)); } else memset(remove_key.bssid, 0xff, sizeof(remove_key.bssid)); if (mp_set(wnd, OID_802_11_REMOVE_KEY, &remove_key, sizeof(remove_key))) EXIT2(return -EINVAL); } else { ndis_key_index keyindex = index; res = mp_set_int(wnd, OID_802_11_REMOVE_WEP, keyindex); if (res) { WARNING("removing encryption key %d failed (%08X)", keyindex, res); EXIT2(return -EINVAL); } } /* if it is transmit key, disable encryption */ if (index == wnd->encr_info.tx_key_index) { res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE); if (res) WARNING("changing encr status failed (%08X)", res); } TRACE2("key %d removed", index); EXIT2(return 0);}static int iw_set_wep(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; unsigned int index, key_len; struct encr_info *encr_info = &wnd->encr_info; unsigned char *key; ENTER2(""); index = (wrqu->encoding.flags & IW_ENCODE_INDEX); TRACE2("index = %u", index); /* iwconfig gives index as 1 - N */ if (index > 0) index--; else index = encr_info->tx_key_index; if (index < 0 || index >= MAX_ENCR_KEYS) { WARNING("encryption index out of range (%u)", index); EXIT2(return -EINVAL); } /* remove key if disabled */ if (wrqu->data.flags & IW_ENCODE_DISABLED) { if (remove_key(wnd, index, NULL)) EXIT2(return -EINVAL); else EXIT2(return 0); } /* global encryption state (for all keys) */ if (wrqu->data.flags & IW_ENCODE_OPEN) res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeOpen); else // if (wrqu->data.flags & IW_ENCODE_RESTRICTED) res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeShared); if (res) { WARNING("setting authentication mode failed (%08X)", res); EXIT2(return -EINVAL); } TRACE2("key length: %d", wrqu->data.length); if (wrqu->data.length > 0) { key_len = wrqu->data.length; key = extra; } else { // must be set as tx key if (encr_info->keys[index].length == 0) { WARNING("key %d is not set", index+1); EXIT2(return -EINVAL); } key_len = encr_info->keys[index].length; key = encr_info->keys[index].key; encr_info->tx_key_index = index; } if (add_wep_key(wnd, key, key_len, index)) EXIT2(return -EINVAL); if (index == encr_info->tx_key_index) { /* if transmit key is at index other than 0, some * drivers, at least Atheros and TI, want another * (global) non-transmit key to be set; don't know why */ if (index != 0) { int i; for (i = 0; i < MAX_ENCR_KEYS; i++) if (i != index && encr_info->keys[i].length != 0) break; if (i == MAX_ENCR_KEYS) { if (index == 0) i = index + 1; else i = index - 1; if (add_wep_key(wnd, key, key_len, i)) WARNING("couldn't add broadcast key" " at %d", i); } } /* ndis drivers want essid to be set after setting encr */ set_essid(wnd, wnd->essid.essid, wnd->essid.length); } EXIT2(return 0);}static int iw_set_nick(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); if (wrqu->data.length > IW_ESSID_MAX_SIZE || wrqu->data.length <= 0) return -EINVAL; memset(wnd->nick, 0, sizeof(wnd->nick)); memcpy(wnd->nick, extra, wrqu->data.length); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -