📄 iw_ndis.c
字号:
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; memcpy(wnd->nick, extra, wrqu->data.length); wnd->nick[wrqu->data.length-1] = 0; return 0;}static int iw_get_nick(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); wrqu->data.length = strlen(wnd->nick); memcpy(extra, wnd->nick, wrqu->data.length); return 0;}static char *ndis_translate_scan(struct net_device *dev, char *event, char *end_buf, void *item){ struct iw_event iwe; char *current_val; int i, nrates; unsigned char buf[MAX_WPA_IE_LEN * 2 + 30]; struct ndis_wlan_bssid *bssid; struct ndis_wlan_bssid_ex *bssid_ex; ENTER2("%p, %p", event, item); bssid = item; bssid_ex = item; /* add mac address */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; iwe.len = IW_EV_ADDR_LEN; memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN); event = iwe_stream_add_event(event, end_buf, &iwe, IW_EV_ADDR_LEN); /* add essid */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWESSID; iwe.u.data.length = bssid->ssid.length; if (iwe.u.data.length > IW_ESSID_MAX_SIZE) iwe.u.data.length = IW_ESSID_MAX_SIZE; iwe.u.data.flags = 1; iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; event = iwe_stream_add_point(event, end_buf, &iwe, bssid->ssid.essid); /* add protocol name */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWNAME; strncpy(iwe.u.name, network_type_to_name(bssid->net_type), IFNAMSIZ); event = iwe_stream_add_event(event, end_buf, &iwe, IW_EV_CHAR_LEN); /* add mode */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWMODE; if (bssid->mode == Ndis802_11IBSS) iwe.u.mode = IW_MODE_ADHOC; else if (bssid->mode == Ndis802_11Infrastructure) iwe.u.mode = IW_MODE_INFRA; else // if (bssid->mode == Ndis802_11AutoUnknown) iwe.u.mode = IW_MODE_AUTO; event = iwe_stream_add_event(event, end_buf, &iwe, IW_EV_UINT_LEN); /* add freq */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = bssid->config.ds_config; if (bssid->config.ds_config > 1000000) { iwe.u.freq.m = bssid->config.ds_config / 10; iwe.u.freq.e = 1; } else iwe.u.freq.m = bssid->config.ds_config; /* convert from kHz to Hz */ iwe.u.freq.e += 3; iwe.len = IW_EV_FREQ_LEN; event = iwe_stream_add_event(event, end_buf, &iwe, IW_EV_FREQ_LEN); /* add qual */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVQUAL; i = 100 * (bssid->rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE); if (i < 0) i = 0; else if (i > 100) i = 100; iwe.u.qual.level = bssid->rssi; iwe.u.qual.noise = WL_NOISE; iwe.u.qual.qual = i; iwe.len = IW_EV_QUAL_LEN; event = iwe_stream_add_event(event, end_buf, &iwe, IW_EV_QUAL_LEN); /* add key info */ memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWENCODE; if (bssid->privacy == Ndis802_11PrivFilterAcceptAll) iwe.u.data.flags = IW_ENCODE_DISABLED; else iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; iwe.u.data.length = 0; iwe.len = IW_EV_POINT_LEN; event = iwe_stream_add_point(event, end_buf, &iwe, bssid->ssid.essid); /* add rate */ memset(&iwe, 0, sizeof(iwe)); current_val = event + IW_EV_LCP_LEN; iwe.cmd = SIOCGIWRATE; if (bssid->length > sizeof(*bssid)) nrates = NDIS_MAX_RATES_EX; else nrates = NDIS_MAX_RATES; for (i = 0 ; i < nrates ; i++) { if (bssid->rates[i] & 0x7f) { iwe.u.bitrate.value = ((bssid->rates[i] & 0x7f) * 500000); current_val = iwe_stream_add_value(event, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } } if ((current_val - event) > IW_EV_LCP_LEN) event = current_val; memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVCUSTOM; sprintf(buf, "bcn_int=%d", bssid->config.beacon_period); iwe.u.data.length = strlen(buf); event = iwe_stream_add_point(event, end_buf, &iwe, buf); memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVCUSTOM; sprintf(buf, "atim=%u", bssid->config.atim_window); iwe.u.data.length = strlen(buf); event = iwe_stream_add_point(event, end_buf, &iwe, buf); TRACE2("%d, %u", bssid->length, (unsigned int)sizeof(*bssid)); if (bssid->length > sizeof(*bssid)) { unsigned char *iep = (unsigned char *)bssid_ex->ies + sizeof(struct ndis_fixed_ies); no_warn_unused unsigned char *end = iep + bssid_ex->ie_length; while (iep + 1 < end && iep + 2 + iep[1] <= end) { unsigned char ielen = 2 + iep[1]; if (ielen > SSID_MAX_WPA_IE_LEN) { iep += ielen; continue; }#if WIRELESS_EXT > 17 if ((iep[0] == WLAN_EID_GENERIC && iep[1] >= 4 && memcmp(iep + 2, "\x00\x50\xf2\x01", 4) == 0) || iep[0] == RSN_INFO_ELEM) { memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVGENIE; iwe.u.data.length = ielen; event = iwe_stream_add_point(event, end_buf, &iwe, iep); }#else if (iep[0] == WLAN_EID_GENERIC && iep[1] >= 4 && memcmp(iep + 2, "\x00\x50\xf2\x01", 4) == 0) { unsigned char *p = buf; p += sprintf(p, "wpa_ie="); for (i = 0; i < ielen; i++) p += sprintf(p, "%02x", iep[i]); TRACE2("adding wpa_ie :%lu", (unsigned long)strlen(buf)); memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVCUSTOM; iwe.u.data.length = strlen(buf); event = iwe_stream_add_point(event, end_buf, &iwe, buf); } else if (iep[0] == RSN_INFO_ELEM) { unsigned char *p = buf; p += sprintf(p, "rsn_ie="); for (i = 0; i < ielen; i++) p += sprintf(p, "%02x", iep[i]); TRACE2("adding rsn_ie :%lu", (unsigned long)strlen(buf)); memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVCUSTOM; iwe.u.data.length = strlen(buf); event = iwe_stream_add_point(event, end_buf, &iwe, buf); }#endif iep += ielen; } } TRACE2("event = %p, current_val = %p", event, current_val); EXIT2(return event);}int set_scan(struct wrap_ndis_device *wnd){ NDIS_STATUS res; ENTER2(""); res = miniport_set_info(wnd, OID_802_11_BSSID_LIST_SCAN, NULL, 0); if (res) { WARNING("scanning failed (%08X)", res); EXIT2(return -EOPNOTSUPP); } wnd->scan_timestamp = jiffies; EXIT2(return 0);}static int iw_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); return set_scan(wnd);}static int iw_get_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct wrap_ndis_device *wnd = netdev_priv(dev); unsigned int i, list_len, needed; NDIS_STATUS res; struct ndis_bssid_list *bssid_list = NULL; char *event = extra; struct ndis_wlan_bssid *cur_item ; ENTER2(""); if (time_before(jiffies, wnd->scan_timestamp + 3 * HZ)) return -EAGAIN; /* try with space for a few scan items */ list_len = sizeof(ULONG) + sizeof(struct ndis_wlan_bssid_ex) * 8; bssid_list = kmalloc(list_len, GFP_KERNEL); if (!bssid_list) { ERROR("couldn't allocate memory"); return -ENOMEM; } /* some drivers don't set bssid_list->num_items to 0 if OID_802_11_BSSID_LIST returns no items (prism54 driver, e.g.,) */ memset(bssid_list, 0, list_len); needed = 0; res = miniport_query_info_needed(wnd, OID_802_11_BSSID_LIST, bssid_list, list_len, &needed); if (res == NDIS_STATUS_INVALID_LENGTH || res == NDIS_STATUS_BUFFER_TOO_SHORT) { /* now try with required space */ kfree(bssid_list); list_len = needed; bssid_list = kmalloc(list_len, GFP_KERNEL); if (!bssid_list) { ERROR("couldn't allocate memory"); return -ENOMEM; } memset(bssid_list, 0, list_len); res = miniport_query_info(wnd, OID_802_11_BSSID_LIST, bssid_list, list_len); } if (res) { WARNING("getting BSSID list failed (%08X)", res); kfree(bssid_list); EXIT2(return -EOPNOTSUPP); } TRACE2("%d", bssid_list->num_items); cur_item = &bssid_list->bssid[0]; for (i = 0; i < bssid_list->num_items; i++) { event = ndis_translate_scan(dev, event, extra + IW_SCAN_MAX_DATA, cur_item); cur_item = (struct ndis_wlan_bssid *)((char *)cur_item + cur_item->length); } wrqu->data.length = event - extra; wrqu->data.flags = 0; kfree(bssid_list); EXIT2(return 0);}static int iw_set_power_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; ULONG power_mode; ENTER2(""); if (wrqu->power.disabled == 1) power_mode = NDIS_POWER_OFF; else if (wrqu->power.flags & IW_POWER_MIN) power_mode = NDIS_POWER_MIN; else // if (wrqu->power.flags & IW_POWER_MAX) power_mode = NDIS_POWER_MAX; res = miniport_set_info(wnd, OID_802_11_POWER_MODE, &power_mode, sizeof(power_mode)); if (res) WARNING("setting power mode failed (%08X)", res); return 0;}static int iw_get_power_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; ULONG power_mode; ENTER2(""); res = miniport_query_info(wnd, OID_802_11_POWER_MODE, &power_mode, sizeof(power_mode)); if (res) return -ENOTSUPP; if (power_mode == NDIS_POWER_OFF) wrqu->power.disabled = 1; else { if (wrqu->power.flags != 0) return 0; wrqu->power.flags |= IW_POWER_ALL_R; wrqu->power.flags |= IW_POWER_TIMEOUT; wrqu->power.value = 0; wrqu->power.disabled = 0; if (power_mode == NDIS_POWER_MIN) wrqu->power.flags |= IW_POWER_MIN; else // if (power_mode == NDIS_POWER_MAX) wrqu->power.flags |= IW_POWER_MAX; } return 0;}static int iw_get_sensitivity(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; ndis_rssi rssi_trigger; ENTER2(""); res = miniport_query_info(wnd, OID_802_11_RSSI_TRIGGER, &rssi_trigger, sizeof(rssi_trigger)); if (res) return -EOPNOTSUPP; wrqu->param.value = rssi_trigger; wrqu->param.disabled = (rssi_trigger == 0); wrqu->param.fixed = 1; return 0;}static int iw_set_sensitivity(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; ndis_rssi rssi_trigger; ENTER2(""); if (wrqu->param.disabled) rssi_trigger = 0; else rssi_trigger = wrqu->param.value; res = miniport_set_info(wnd, OID_802_11_RSSI_TRIGGER, &rssi_trigger, sizeof(rssi_trigger)); if (res == NDIS_STATUS_INVALID_DATA) return -EINVAL; if (res) return -EOPNOTSUPP; return 0;}static int iw_get_ndis_stats(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_statistics *stats = &wnd->iw_stats; memcpy(&wrqu->qual, &stats->qual, sizeof(stats->qual)); return 0;}static int iw_get_range(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra){ struct iw_range *range = (struct iw_range *)extra; struct iw_point *data = &wrqu->data; struct wrap_ndis_device *wnd = netdev_priv(dev); unsigned int i, n; NDIS_STATUS res; ndis_rates_ex rates_ex; ndis_tx_power_level tx_power; ENTER2(""); data->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); range->txpower_capa = IW_TXPOW_MWATT; range->num_txpower = 0; res = miniport_query_info(wnd, OID_802_11_TX_POWER_LEVEL, &tx_power, sizeof(tx_power)); if (!res) { range->num_txpower = 1; range->txpower[0] = tx_power; } range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 18; range->retry_capa = IW_RETRY_LIMIT; range->retry_flags = IW_RETRY_LIMIT; range->min_retry = 0; range->max_retry = 255; range->num_channels = 1; range->max_qual.qual = 100; range->max_qual.level = 154; range->max_qual.noise = 154; range->sensitivity = 3; range->max_encoding_tokens = 4; range->num_encoding_sizes = 2; range->encoding_size[0] = 5; range->encoding_size[1] = 13; range->num_bitrates = 0; n = NDIS_MAX_RATES_EX; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -