📄 wrapndis.c
字号:
struct wrap_ndis_device *wnd = netdev_priv(dev); disable_irq(dev->irq); ndis_isr(wnd->mp_interrupt->kinterrupt, wnd->mp_interrupt); enable_irq(dev->irq);}#endif/* called from BH context */static struct net_device_stats *ndis_get_stats(struct net_device *dev){ struct wrap_ndis_device *wnd = netdev_priv(dev); return &wnd->net_stats;}/* called from BH context */static void ndis_set_multicast_list(struct net_device *dev){ struct wrap_ndis_device *wnd = netdev_priv(dev); set_bit(SET_MULTICAST_LIST, &wnd->wrap_ndis_pending_work); schedule_wrapndis_work(&wnd->wrap_ndis_work);}/* called from BH context */struct iw_statistics *get_iw_stats(struct net_device *dev){ struct wrap_ndis_device *wnd = netdev_priv(dev); return &wnd->iw_stats;}static void update_iw_stats(struct wrap_ndis_device *wnd){ struct iw_statistics *iw_stats = &wnd->iw_stats; struct ndis_wireless_stats ndis_stats; NDIS_STATUS res; ndis_rssi rssi; int qual; ENTER2("%p", wnd); if (wnd->iw_stats_enabled == FALSE || !netif_carrier_ok(wnd->net_dev)) { memset(iw_stats, 0, sizeof(*iw_stats)); EXIT2(return); } res = mp_query(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi)); if (res == NDIS_STATUS_SUCCESS) iw_stats->qual.level = rssi; qual = 100 * (rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE); if (qual < 0) qual = 0; else if (qual > 100) qual = 100; iw_stats->qual.noise = WL_NOISE; iw_stats->qual.qual = qual; res = mp_query(wnd, OID_802_11_STATISTICS, &ndis_stats, sizeof(ndis_stats)); if (res != NDIS_STATUS_SUCCESS) EXIT2(return); iw_stats->discard.retries = (unsigned long)ndis_stats.retry + (unsigned long)ndis_stats.multi_retry; iw_stats->discard.misc = (unsigned long)ndis_stats.fcs_err + (unsigned long)ndis_stats.rtss_fail + (unsigned long)ndis_stats.ack_fail + (unsigned long)ndis_stats.frame_dup; EXIT2(return);}static void set_multicast_list(struct wrap_ndis_device *wnd){ struct net_device *net_dev; ULONG packet_filter; NDIS_STATUS res; net_dev = wnd->net_dev; packet_filter = wnd->packet_filter; TRACE2("0x%08x", packet_filter); if (net_dev->flags & IFF_PROMISC) { packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS | NDIS_PACKET_TYPE_ALL_LOCAL; } else if (net_dev->flags & IFF_ALLMULTI || net_dev->mc_count > wnd->multicast_size) { packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; TRACE2("0x%08x", packet_filter); } else if (net_dev->mc_count > 0) { int i, size; char *buf; struct dev_mc_list *mclist; size = min(wnd->multicast_size, net_dev->mc_count); TRACE2("%d, %d", wnd->multicast_size, net_dev->mc_count); buf = kmalloc(size * ETH_ALEN, GFP_KERNEL); if (!buf) { WARNING("couldn't allocate memory"); EXIT2(return); } mclist = net_dev->mc_list; for (i = 0; i < size && mclist; mclist = mclist->next) { if (mclist->dmi_addrlen != ETH_ALEN) continue; memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN); TRACE2(MACSTRSEP, MAC2STR(mclist->dmi_addr)); i++; } res = mp_set(wnd, OID_802_3_MULTICAST_LIST, buf, i * ETH_ALEN); if (res == NDIS_STATUS_SUCCESS && i > 0) packet_filter |= NDIS_PACKET_TYPE_MULTICAST; else packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; kfree(buf); } TRACE2("0x%08x", packet_filter); res = set_packet_filter(wnd, packet_filter); if (res) TRACE1("couldn't set packet filter (%08X)", res); EXIT2(return);}static void link_status_off(struct wrap_ndis_device *wnd){ union iwreq_data wrqu; memset(&wrqu, 0, sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL); EXIT2(return);}static void link_status_on(struct wrap_ndis_device *wnd){#ifdef CONFIG_WIRELESS_EXT struct ndis_assoc_info *ndis_assoc_info; union iwreq_data wrqu; NDIS_STATUS res; const int assoc_size = sizeof(*ndis_assoc_info) + IW_CUSTOM_MAX + 32;#endif ENTER2("");#ifdef CONFIG_WIRELESS_EXT memset(&wrqu, 0, sizeof(wrqu)); ndis_assoc_info = kzalloc(assoc_size, GFP_KERNEL); if (!ndis_assoc_info) { ERROR("couldn't allocate memory"); goto send_assoc_event; } res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION, ndis_assoc_info, assoc_size); if (res) { TRACE2("query assoc_info failed (%08X)", res); kfree(ndis_assoc_info); goto send_assoc_event; } TRACE2("%u, 0x%x, %u, 0x%x, %u", ndis_assoc_info->length, ndis_assoc_info->req_ies, ndis_assoc_info->req_ie_length, ndis_assoc_info->resp_ies, ndis_assoc_info->resp_ie_length);#if WIRELESS_EXT > 17 if (ndis_assoc_info->req_ie_length > 0) { wrqu.data.length = ndis_assoc_info->req_ie_length; wireless_send_event(wnd->net_dev, IWEVASSOCREQIE, &wrqu, ((char *)ndis_assoc_info) + ndis_assoc_info->offset_req_ies); } if (ndis_assoc_info->resp_ie_length > 0) { wrqu.data.length = ndis_assoc_info->resp_ie_length; wireless_send_event(wnd->net_dev, IWEVASSOCRESPIE, &wrqu, ((char *)ndis_assoc_info) + ndis_assoc_info->offset_resp_ies); }#endif kfree(ndis_assoc_info);send_assoc_event: get_ap_address(wnd, wrqu.ap_addr.sa_data); wrqu.ap_addr.sa_family = ARPHRD_ETHER; TRACE2(MACSTRSEP, MAC2STR(wrqu.ap_addr.sa_data)); wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL);#endif EXIT2(return);}static void iw_stats_timer_proc(unsigned long data){ struct wrap_ndis_device *wnd = (struct wrap_ndis_device *)data; ENTER2("%d", wnd->iw_stats_interval); if (wnd->iw_stats_interval > 0) { set_bit(COLLECT_IW_STATS, &wnd->wrap_ndis_pending_work); schedule_wrapndis_work(&wnd->wrap_ndis_work); } mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval);}static void add_iw_stats_timer(struct wrap_ndis_device *wnd){ if (wnd->physical_medium != NdisPhysicalMediumWirelessLan) return; if (wnd->iw_stats_interval < 0) wnd->iw_stats_interval *= -1; wnd->iw_stats_timer.data = (unsigned long)wnd; wnd->iw_stats_timer.function = iw_stats_timer_proc; mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval);}static void del_iw_stats_timer(struct wrap_ndis_device *wnd){ ENTER2("%d", wnd->iw_stats_interval); wnd->iw_stats_interval *= -1; del_timer_sync(&wnd->iw_stats_timer); EXIT2(return);}static void hangcheck_proc(unsigned long data){ struct wrap_ndis_device *wnd = (struct wrap_ndis_device *)data; ENTER3("%d", wnd->hangcheck_interval); if (wnd->hangcheck_interval > 0) { set_bit(HANGCHECK, &wnd->wrap_ndis_pending_work); schedule_wrapndis_work(&wnd->wrap_ndis_work); } mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval); EXIT3(return);}void hangcheck_add(struct wrap_ndis_device *wnd){ if (!wnd->wd->driver->ndis_driver->mp.hangcheck || hangcheck_interval < 0) EXIT2(return); if (hangcheck_interval > 0) wnd->hangcheck_interval = hangcheck_interval * HZ; if (wnd->hangcheck_interval < 0) wnd->hangcheck_interval *= -1; wnd->hangcheck_timer.data = (unsigned long)wnd; wnd->hangcheck_timer.function = hangcheck_proc; mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval); EXIT2(return);}void hangcheck_del(struct wrap_ndis_device *wnd){ ENTER2("%d", wnd->hangcheck_interval); if (wnd->hangcheck_interval > 0) wnd->hangcheck_interval *= -1; del_timer_sync(&wnd->hangcheck_timer); EXIT2(return);}/* worker procedure to take care of setting/checking various states */static void wrap_ndis_worker(worker_param_t param){ struct wrap_ndis_device *wnd; wnd = worker_param_data(param, struct wrap_ndis_device, wrap_ndis_work); WORKTRACE("0x%lx", wnd->wrap_ndis_pending_work); if (test_and_clear_bit(NETIF_WAKEQ, &wnd->wrap_ndis_pending_work)) { netif_tx_lock_bh(wnd->net_dev); netif_wake_queue(wnd->net_dev); netif_tx_unlock_bh(wnd->net_dev); } if (test_and_clear_bit(LINK_STATUS_OFF, &wnd->wrap_ndis_pending_work)) link_status_off(wnd); if (test_and_clear_bit(LINK_STATUS_ON, &wnd->wrap_ndis_pending_work)) link_status_on(wnd); if (test_and_clear_bit(COLLECT_IW_STATS, &wnd->wrap_ndis_pending_work)) update_iw_stats(wnd); if (test_and_clear_bit(SET_MULTICAST_LIST, &wnd->wrap_ndis_pending_work)) set_multicast_list(wnd); if (test_and_clear_bit(HANGCHECK, &wnd->wrap_ndis_pending_work)) { struct miniport *mp; BOOLEAN reset; KIRQL irql; mp = &wnd->wd->driver->ndis_driver->mp; irql = serialize_lock_irql(wnd); reset = LIN2WIN1(mp->hangcheck, wnd->nmb->mp_ctx); serialize_unlock_irql(wnd, irql); if (reset) { TRACE2("%s needs reset", wnd->net_dev->name); mp_reset(wnd); } } WORKEXIT(return);}NDIS_STATUS ndis_reinit(struct wrap_ndis_device *wnd){ NDIS_STATUS status; wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; status = mp_set_power_state(wnd, NdisDeviceStateD3); if (status != NDIS_STATUS_SUCCESS) { ERROR("halting device %s failed: %08X", wnd->net_dev->name, status); return status; } status = mp_set_power_state(wnd, NdisDeviceStateD0); if (status != NDIS_STATUS_SUCCESS) ERROR("starting device %s failed: %08X", wnd->net_dev->name, status); return status;}static void get_encryption_capa(struct wrap_ndis_device *wnd, char *buf, const int buf_len){ int i, mode; NDIS_STATUS res; struct ndis_assoc_info ndis_assoc_info; struct ndis_add_key ndis_key; struct ndis_capability *c; ENTER1("%p", wnd); /* set network type to g, b, or a, in that order */ res = mp_query(wnd, OID_802_11_NETWORK_TYPES_SUPPORTED, buf, buf_len); if (res == NDIS_STATUS_SUCCESS) { struct network_type_list *net_types; unsigned long types = 0; net_types = (typeof(net_types))buf; for (i = 0; i < net_types->num; i++) { TRACE2("%d", net_types->types[i]); set_bit(net_types->types[i], &types); } if (types & Ndis802_11OFDM24) mode = Ndis802_11OFDM24; else if (types & Ndis802_11DS) mode = Ndis802_11DS; else if (types & Ndis802_11OFDM5) mode = Ndis802_11OFDM5; else mode = Ndis802_11DS; mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, mode); } /* check if WEP is supported */ if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104, IW_AUTH_CIPHER_NONE) == 0 && get_ndis_encr_mode(wnd) == Ndis802_11Encryption1KeyAbsent) set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr); /* check if WPA is supported */ if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPA) == 0 && get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPA) set_bit(Ndis802_11AuthModeWPA, &wnd->capa.encr); else EXIT1(return); if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPAPSK) == 0 && get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPAPSK) set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.encr); /* check for highest encryption */ mode = 0; if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_CCMP, IW_AUTH_CIPHER_NONE) == 0 && (i = get_ndis_encr_mode(wnd)) > 0 && (i == Ndis802_11Encryption3KeyAbsent || i == Ndis802_11Encryption3Enabled)) mode = Ndis802_11Encryption3Enabled; else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_TKIP, IW_AUTH_CIPHER_NONE) == 0 && (i = get_ndis_encr_mode(wnd)) > 0 && (i == Ndis802_11Encryption2KeyAbsent || i == Ndis802_11Encryption2Enabled)) mode = Ndis802_11Encryption2Enabled; else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104, IW_AUTH_CIPHER_NONE) == 0 && (i = get_ndis_encr_mode(wnd)) > 0 && (i == Ndis802_11Encryption1KeyAbsent || i == Ndis802_11Encryption1Enabled)) mode = Ndis802_11Encryption1Enabled; TRACE1("mode: %d", mode); if (mode == 0) EXIT1(return); set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr); if (mode == Ndis802_11Encryption1Enabled) EXIT1(return); ndis_key.length = 32; ndis_key.index = 0xC0000001; ndis_key.struct_size = sizeof(ndis_key); res = mp_set(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size); TRACE2("%08X, %lu", res, (unsigned long)sizeof(ndis_key)); if (res && res != NDIS_STATUS_INVALID_DATA) EXIT1(return); res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION, &ndis_assoc_info, sizeof(ndis_assoc_info)); TRACE1("%08X", res); if (res == NDIS_STATUS_NOT_SUPPORTED) EXIT1(return); set_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr); if (mode == Ndis802_11Encryption3Enabled) set_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr); /* not all drivers support OID_802_11_CAPABILITY, so we don't * know for sure if driver support WPA or WPAPSK; assume * WPAPSK */ set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth); wnd->max_pmkids = 1; memset(buf, 0, buf_len); c = (struct ndis_capability *)buf; res = mp_query(wnd, OID_802_11_CAPABILITY, buf, buf_len); if (!(res == NDIS_STATUS_SUCCESS && c->version == 2)) EXIT1(return); wnd->max_pmkids = c->num_PMKIDs; for (i = 0; i < c->num_auth_encr_pair; i++) { struct ndis_auth_encr_pair *ae;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -