📄 iw_ndis.c
字号:
struct wrap_ndis_device *wnd = netdev_priv(dev); int i, n; NDIS_STATUS res; ndis_rates_ex rates_ex; ENTER2(""); if (wrqu->bitrate.fixed == 0) EXIT2(return 0); res = miniport_query_info(wnd, OID_802_11_SUPPORTED_RATES, &rates_ex, sizeof(ndis_rates_ex)); if (res) { res = miniport_query_info(wnd, OID_802_11_SUPPORTED_RATES, &rates_ex, sizeof(ndis_rates)); n = NDIS_MAX_RATES; } else n = NDIS_MAX_RATES_EX; if (res) { WARNING("getting bit rate failed (%08X)", res); EXIT2(return 0); } for (i = 0 ; i < n ; i++) { if (rates_ex[i] & 0x80) continue; if ((rates_ex[i] & 0x7f) * 500000 > wrqu->bitrate.value) { TRACE2("setting rate %d to 0", (rates_ex[i] & 0x7f) * 500000); rates_ex[i] = 0; } } if (n == NDIS_MAX_RATES_EX) res = miniport_set_info(wnd, OID_802_11_DESIRED_RATES, &rates_ex, sizeof(ndis_rates_ex)); else res = miniport_set_info(wnd, OID_802_11_DESIRED_RATES, &rates_ex, sizeof(ndis_rates)); if (res) { WARNING("setting bit rate failed (%08X)", res); EXIT2(return 0); } return 0;}static int iw_set_dummy(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ /* Do nothing. Used for ioctls that are not implemented. */ return 0;}static int iw_get_rts_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(""); res = miniport_query_info(wnd, OID_802_11_RTS_THRESHOLD, &threshold, sizeof(threshold)); if (res) return -EOPNOTSUPP; wrqu->rts.value = threshold; return 0;}static int iw_set_rts_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->rts.value; res = miniport_set_info(wnd, OID_802_11_RTS_THRESHOLD, &threshold, sizeof(threshold)); if (res == NDIS_STATUS_INVALID_DATA) return -EINVAL; if (res) return -EOPNOTSUPP; return 0;}static int iw_get_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_fragmentation_threshold frag_threshold; NDIS_STATUS res; ENTER2(""); res = miniport_query_info(wnd, OID_802_11_FRAGMENTATION_THRESHOLD, &frag_threshold, sizeof(frag_threshold)); 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 = miniport_set_info(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 = NDIS_STATUS_ADAPTER_NOT_READY; /* this OID is valid only when associated */ if (netif_carrier_ok(wnd->net_dev)) res = miniport_query_info(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 = miniport_set_info(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_auth_mode(struct wrap_ndis_device *wnd, ULONG auth_mode){ NDIS_STATUS res; ENTER2("%d", auth_mode); res = miniport_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->auth_mode = auth_mode; EXIT2(return 0);}int get_auth_mode(struct wrap_ndis_device *wnd){ ULONG mode; NDIS_STATUS res; res = miniport_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_encr_mode(struct wrap_ndis_device *wnd, ULONG encr_mode){ NDIS_STATUS res; ENTER2("%d", encr_mode); res = miniport_set_int(wnd, OID_802_11_ENCRYPTION_STATUS, encr_mode); if (res) { WARNING("setting encryption mode to %u failed (%08X)", encr_mode, res); if (res == NDIS_STATUS_INVALID_DATA) EXIT2(return -EINVAL); return -EOPNOTSUPP; } wnd->encr_mode = encr_mode; EXIT2(return 0);}int get_encr_mode(struct wrap_ndis_device *wnd){ ULONG mode; NDIS_STATUS res; ENTER2(""); res = miniport_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_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_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_encr_mode(wnd, Ndis802_11Encryption1Enabled); if (res) WARNING("encryption couldn't be enabled (%08X)", res); } TRACE2("key %d: " MACSTRSEP, index, MAC2STR(key)); res = miniport_set_info(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->encr_mode == Ndis802_11Encryption2Enabled || wnd->encr_mode == Ndis802_11Encryption3Enabled) { 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 (miniport_set_info(wnd, OID_802_11_REMOVE_KEY, (char *)&remove_key, sizeof(remove_key))) EXIT2(return -EINVAL); } else { ndis_key_index keyindex = index; res = miniport_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_encr_mode(wnd, Ndis802_11EncryptionDisabled); 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_auth_mode(wnd, Ndis802_11AuthModeOpen); else // if (wrqu->data.flags & IW_ENCODE_RESTRICTED) res = set_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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -