📄 wrapndis.c
字号:
#ifdef CONFIG_NET_POLL_CONTROLLERstatic void ndis_poll_controller(struct net_device *dev){ struct wrap_ndis_device *wnd = netdev_priv(dev); disable_irq(dev->irq); ndis_isr(dev->irq, wnd ISR_PT_REGS_ARG); 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_wrap_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 = miniport_query_info(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 = miniport_query_info(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 = miniport_set_info(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_handler(struct wrap_ndis_device *wnd){ 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; int i;#if WIRELESS_EXT <= 17 unsigned char *wpa_assoc_info, *ies; unsigned char *p;#endif ENTER2("link: %d", netif_carrier_ok(wnd->net_dev)); if (wnd->physical_medium != NdisPhysicalMediumWirelessLan) EXIT2(return);#ifndef CONFIG_NET_RADIO EXIT2(return);#endif if (!netif_carrier_ok(wnd->net_dev)) { memset(&wrqu, 0, sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL); /* In IBSS (ad-hoc) mode, it may be desirable to have * one node configured for association, but drivers * disassociate if last node disassociates; to * configure again, set essid */ if (wnd->infrastructure_mode == Ndis802_11IBSS && wnd->essid.length > 0) { set_essid(wnd, wnd->essid.essid, wnd->essid.length); for (i = 0; i < MAX_ENCR_KEYS; i++) { if (wnd->encr_info.keys[i].length <= 0) continue; add_wep_key(wnd, wnd->encr_info.keys[i].key, wnd->encr_info.keys[i].length, i); } } EXIT2(return); } ndis_assoc_info = kmalloc(assoc_size, GFP_KERNEL); if (!ndis_assoc_info) { ERROR("couldn't allocate memory"); EXIT2(return); } memset(ndis_assoc_info, 0, assoc_size); res = miniport_query_info(wnd, OID_802_11_ASSOCIATION_INFORMATION, ndis_assoc_info, assoc_size); if (res) { TRACE2("query assoc_info failed (%08X)", res); kfree(ndis_assoc_info); EXIT2(return); }#if WIRELESS_EXT > 17 memset(&wrqu, 0, sizeof(wrqu)); 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); 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);#else /* we need 28 extra bytes for the format strings */ if ((ndis_assoc_info->req_ie_length + ndis_assoc_info->resp_ie_length + 28) > IW_CUSTOM_MAX) { WARNING("information element is too long! (%u,%u)," "association information dropped", ndis_assoc_info->req_ie_length, ndis_assoc_info->resp_ie_length); kfree(ndis_assoc_info); EXIT2(return); } wpa_assoc_info = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL); if (!wpa_assoc_info) { ERROR("couldn't allocate memory"); kfree(ndis_assoc_info); EXIT2(return); } p = wpa_assoc_info; p += sprintf(p, "ASSOCINFO(ReqIEs="); ies = ((char *)ndis_assoc_info) + ndis_assoc_info->offset_req_ies; for (i = 0; i < ndis_assoc_info->req_ie_length; i++) p += sprintf(p, "%02x", ies[i]); p += sprintf(p, " RespIEs="); ies = ((char *)ndis_assoc_info) + ndis_assoc_info->offset_resp_ies; for (i = 0; i < ndis_assoc_info->resp_ie_length; i++) p += sprintf(p, "%02x", ies[i]); p += sprintf(p, ")"); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = p - wpa_assoc_info; wireless_send_event(wnd->net_dev, IWEVCUSTOM, &wrqu, wpa_assoc_info); kfree(wpa_assoc_info);#endif kfree(ndis_assoc_info); get_ap_address(wnd, (char *)&wrqu.ap_addr.sa_data); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL); TRACE2(MACSTRSEP, MAC2STR(wrqu.ap_addr.sa_data)); EXIT2(return);}static void iw_stats_timer_proc(unsigned long data){ struct wrap_ndis_device *wnd = (struct wrap_ndis_device *)data; ENTER2(""); if (wnd->iw_stats_interval <= 0) EXIT2(return); set_bit(COLLECT_IW_STATS, &wnd->wrap_ndis_pending_work); schedule_wrap_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(""); 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; BOOLEAN reset; struct miniport_char *miniport; ENTER2(""); if (wnd->hangcheck_interval <= 0) EXIT2(return); miniport = &wnd->wd->driver->ndis_driver->miniport; if_serialize_lock(wnd); reset = LIN2WIN1(miniport->hangcheck, wnd->nmb->adapter_ctx); if_serialize_unlock(wnd); if (reset) { set_bit(MINIPORT_RESET, &wnd->wrap_ndis_pending_work); schedule_wrap_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->miniport.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(""); 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); TRACE2("%lu", wnd->wrap_ndis_pending_work); if (test_bit(SHUTDOWN, &wnd->wrap_ndis_pending_work)) EXIT3(return); if (test_and_clear_bit(SET_MULTICAST_LIST, &wnd->wrap_ndis_pending_work)) set_multicast_list(wnd); if (test_and_clear_bit(COLLECT_IW_STATS, &wnd->wrap_ndis_pending_work)) update_iw_stats(wnd); if (test_and_clear_bit(LINK_STATUS_CHANGED, &wnd->wrap_ndis_pending_work)) link_status_handler(wnd); if (test_and_clear_bit(MINIPORT_RESET, &wnd->wrap_ndis_pending_work)) miniport_reset(wnd); EXIT3(return);}NDIS_STATUS ndis_reinit(struct wrap_ndis_device *wnd){ NDIS_STATUS status; wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; status = miniport_set_power_state(wnd, NdisDeviceStateD3); if (status != NDIS_STATUS_SUCCESS) { ERROR("halting device %s failed: %08X", wnd->net_dev->name, status); return status; } status = miniport_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 = miniport_query_info(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; miniport_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, mode); } /* check if WEP is supported */ if (set_encr_mode(wnd, Ndis802_11Encryption1Enabled) == 0 && get_encr_mode(wnd) == Ndis802_11Encryption1KeyAbsent) set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr); /* check if WPA is supported */ if (set_auth_mode(wnd, Ndis802_11AuthModeWPA) == 0 && get_auth_mode(wnd) == Ndis802_11AuthModeWPA) set_bit(Ndis802_11AuthModeWPA, &wnd->capa.auth); else EXIT1(return); if (set_auth_mode(wnd, Ndis802_11AuthModeWPAPSK) == 0 && get_auth_mode(wnd) == Ndis802_11AuthModeWPAPSK) set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth); /* check for highest encryption */ mode = 0; if (set_encr_mode(wnd, Ndis802_11Encryption3Enabled) == 0 && (i = get_encr_mode(wnd)) > 0 && (i == Ndis802_11Encryption3KeyAbsent || i == Ndis802_11Encryption3Enabled)) mode = Ndis802_11Encryption3Enabled; else if (set_encr_mode(wnd, Ndis802_11Encryption2Enabled) == 0 && (i = get_encr_mode(wnd)) > 0 && (i == Ndis802_11Encryption2KeyAbsent || i == Ndis802_11Encryption2Enabled)) mode = Ndis802_11Encryption2Enabled; else if (set_encr_mode(wnd, Ndis802_11Encryption1Enabled) == 0 && (i = get_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -