📄 wrapndis.c
字号:
status = STATUS_FAILURE; break; } /* wnd is already freed */ status = IoAsyncForwardIrp(pdo, irp); IoDetachDevice(fdo); IoDeleteDevice(fdo); break; default: status = IoAsyncForwardIrp(pdo, irp); break; } IOTRACE("status: %08X", status); IOEXIT(return status);}WIN_FUNC_DECL(NdisDispatchPnp,2)static int set_task_offload(struct wrap_ndis_device *wnd, void *buf, const int buf_size){#if 0 struct ndis_task_offload_header *task_offload_header; struct ndis_task_offload *task_offload; struct ndis_task_tcp_ip_checksum *task_tcp_ip_csum = NULL; struct ndis_task_tcp_ip_checksum csum; NDIS_STATUS status; memset(buf, 0, buf_size); task_offload_header = buf; task_offload_header->version = NDIS_TASK_OFFLOAD_VERSION; task_offload_header->size = sizeof(*task_offload_header); task_offload_header->encapsulation_format.encapsulation = IEEE_802_3_Encapsulation; status = miniport_query_info(wnd, OID_TCP_TASK_OFFLOAD, buf, buf_size); DBGTRACE1("%08X", status); if (status != NDIS_STATUS_SUCCESS) TRACEEXIT1(return -1); if (task_offload_header->offset_first_task == 0) TRACEEXIT1(return -1); task_offload = ((void *)task_offload_header + task_offload_header->offset_first_task); while (1) { DBGTRACE1("%d, %d", task_offload->version, task_offload->task); switch(task_offload->task) { case TcpIpChecksumNdisTask: task_tcp_ip_csum = (void *)task_offload->task_buf; break; default: DBGTRACE1("%d", task_offload->task); break; } if (task_offload->offset_next_task == 0) break; task_offload = (void *)task_offload + task_offload->offset_next_task; } if (!task_tcp_ip_csum) TRACEEXIT1(return -1); memcpy(&csum, task_tcp_ip_csum, sizeof(csum)); task_offload_header->encapsulation_format.flags.fixed_header_size = 1; task_offload_header->encapsulation_format.header_size = sizeof(struct ethhdr); task_offload_header->offset_first_task = sizeof(*task_offload_header); task_offload = ((void *)task_offload_header + task_offload_header->offset_first_task); memcpy(task_offload->task_buf, &csum, sizeof(csum)); task_offload->offset_next_task = 0; task_offload->size = sizeof(*task_offload); task_offload->task = TcpIpChecksumNdisTask; task_offload->task_buf_length = sizeof(csum); status = miniport_set_info(wnd, OID_TCP_TASK_OFFLOAD, task_offload_header, sizeof(*task_offload_header) + sizeof(*task_offload) + sizeof(csum)); DBGTRACE1("%08X", status); if (status != NDIS_STATUS_SUCCESS) TRACEEXIT2(return -1); DBGTRACE1("%08x, %08x", csum.v4_tx.value, csum.v4_rx.value); if (csum.v4_tx.ip_csum) { wnd->tx_csum_info.tx.v4 = 1; if (csum.v4_tx.tcp_csum && csum.v4_tx.udp_csum) { wnd->net_dev->features |= NETIF_F_HW_CSUM; wnd->tx_csum_info.tx.tcp = 1; wnd->tx_csum_info.tx.ip = 1; wnd->tx_csum_info.tx.udp = 1; DBGTRACE1("hw_csum"); } else { wnd->net_dev->features |= NETIF_F_IP_CSUM; wnd->tx_csum_info.tx.ip = 1; DBGTRACE1("ip_csum"); } } wnd->rx_csum = csum.v4_rx;#endif TRACEEXIT1(return 0);}static void get_supported_oids(struct wrap_ndis_device *wnd){ NDIS_STATUS res; int i, n, needed; ndis_oid *oids; res = miniport_query_info_needed(wnd, OID_GEN_SUPPORTED_LIST, NULL, 0, &needed); if (!(res == NDIS_STATUS_BUFFER_TOO_SHORT || res == NDIS_STATUS_INVALID_LENGTH)) TRACEEXIT1(return); oids = kmalloc(needed, GFP_KERNEL); if (!oids) { DBGTRACE1("couldn't allocate memory"); TRACEEXIT1(return); } res = miniport_query_info(wnd, OID_GEN_SUPPORTED_LIST, oids, needed); if (res) { DBGTRACE1("failed: %08X", res); kfree(oids); TRACEEXIT1(return); } for (i = 0, n = needed / sizeof(*oids); i < n; i++) { DBGTRACE1("oid: %08X", oids[i]); /* if a wireless device didn't say so for * OID_GEN_PHYSICAL_MEDIUM (they should, but in case) */ if (wnd->physical_medium != NdisPhysicalMediumWirelessLan && oids[i] == OID_802_11_SSID) wnd->physical_medium = NdisPhysicalMediumWirelessLan; } kfree(oids); TRACEEXIT1(return);}static NDIS_STATUS ndis_start_device(struct wrap_ndis_device *wnd){ struct wrap_device *wd; struct net_device *net_dev; NDIS_STATUS ndis_status; char *buf; const int buf_size = 256; mac_address mac; ndis_status = miniport_init(wnd); if (ndis_status == NDIS_STATUS_NOT_RECOGNIZED) TRACEEXIT1(return NDIS_STATUS_SUCCESS); if (ndis_status != NDIS_STATUS_SUCCESS) TRACEEXIT1(return ndis_status); wd = wnd->wd; net_dev = wnd->net_dev; ndis_status = miniport_query_int(wnd, OID_GEN_PHYSICAL_MEDIUM, &wnd->physical_medium); if (ndis_status != NDIS_STATUS_SUCCESS) wnd->physical_medium = NdisPhysicalMediumUnspecified; get_supported_oids(wnd); strncpy(net_dev->name, if_name, IFNAMSIZ - 1); net_dev->name[IFNAMSIZ - 1] = '\0'; ndis_status = miniport_query_info(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac)); if (ndis_status) { ERROR("couldn't get mac address: %08X", ndis_status); return ndis_status; } DBGTRACE1("mac:" MACSTRSEP, MAC2STR(mac)); memcpy(&net_dev->dev_addr, mac, ETH_ALEN); wnd->packet_filter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_ALL_FUNCTIONAL; net_dev->open = ndis_net_dev_open; net_dev->hard_start_xmit = tx_skbuff; net_dev->stop = ndis_net_dev_close; net_dev->get_stats = ndis_get_stats; net_dev->do_ioctl = NULL; if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {#if WIRELESS_EXT < 19 net_dev->get_wireless_stats = get_wireless_stats;#endif net_dev->wireless_handlers = &ndis_handler_def; } net_dev->set_multicast_list = ndis_set_multicast_list; net_dev->set_mac_address = ndis_set_mac_address;#if defined(HAVE_ETHTOOL) net_dev->ethtool_ops = &ndis_ethtool_ops;#endif if (wnd->ndis_irq) net_dev->irq = wnd->ndis_irq->irq.irq; net_dev->mem_start = wnd->mem_start; net_dev->mem_end = wnd->mem_end; ndis_status = miniport_query_int(wnd, OID_802_3_MAXIMUM_LIST_SIZE, &wnd->multicast_size); if (ndis_status != NDIS_STATUS_SUCCESS || wnd->multicast_size < 0) wnd->multicast_size = 0; if (wnd->multicast_size > 0) net_dev->flags |= IFF_MULTICAST; else net_dev->flags &= ~IFF_MULTICAST;#ifdef CONFIG_NET_POLL_CONTROLLER net_dev->poll_controller = ndis_poll_controller;#endif buf = kmalloc(buf_size, GFP_KERNEL); if (!buf) { WARNING("couldn't allocate memory"); goto err_start; } set_task_offload(wnd, buf, buf_size); if (register_netdev(net_dev)) { ERROR("cannot register net device %s", net_dev->name); goto err_register; } register_netdevice_notifier(&netdev_notifier); memcpy(wnd->netdev_name, net_dev->name, sizeof(wnd->netdev_name)); wnd->tx_ok = 1; memset(buf, 0, buf_size); ndis_status = miniport_query_info(wnd, OID_GEN_VENDOR_DESCRIPTION, buf, buf_size); if (ndis_status == NDIS_STATUS_SUCCESS) printk(KERN_INFO "%s: vendor: '%s'\n", net_dev->name, buf); printk(KERN_INFO "%s: ethernet device " MACSTRSEP " using %sNDIS " "driver %s, %s\n", net_dev->name, MAC2STR(net_dev->dev_addr), deserialized_driver(wnd) ? "" : "serialized ", wnd->wd->driver->name, wnd->wd->conf_file_name); if (deserialized_driver(wnd)) { /* deserialized drivers don't have a limit, but we * keep max at TX_RING_SIZE */ wnd->max_tx_packets = TX_RING_SIZE; } else { ndis_status = miniport_query_int(wnd, OID_GEN_MAXIMUM_SEND_PACKETS, &wnd->max_tx_packets); if (ndis_status != NDIS_STATUS_SUCCESS) wnd->max_tx_packets = 1; if (wnd->max_tx_packets > TX_RING_SIZE) wnd->max_tx_packets = TX_RING_SIZE; } DBGTRACE2("maximum send packets: %d", wnd->max_tx_packets); /* we need at least one extra packet for * EthRxIndicateHandler */ NdisAllocatePacketPoolEx(&ndis_status, &wnd->tx_packet_pool, wnd->max_tx_packets + 1, 0, PROTOCOL_RESERVED_SIZE_IN_PACKET); if (ndis_status != NDIS_STATUS_SUCCESS) { ERROR("couldn't allocate packet pool"); goto packet_pool_err; } NdisAllocateBufferPool(&ndis_status, &wnd->tx_buffer_pool, wnd->max_tx_packets + 4); if (ndis_status != NDIS_STATUS_SUCCESS) { ERROR("couldn't allocate buffer pool"); goto buffer_pool_err; } DBGTRACE1("pool: %p", wnd->tx_buffer_pool); if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { miniport_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF); miniport_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, Ndis802_11Automode); get_encryption_capa(wnd); DBGTRACE1("capbilities = %ld", wnd->capa.encr); printk(KERN_INFO "%s: encryption modes supported: " "%s%s%s%s%s%s%s\n", net_dev->name, test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ? "WEP" : "none", test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ? "; TKIP with WPA" : "", test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? ", WPA2" : "", test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? ", WPA2PSK" : "", test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ? "; AES/CCMP with WPA" : "", test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? ", WPA2" : "", test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? ", WPA2PSK" : ""); set_infra_mode(wnd, Ndis802_11Infrastructure); set_scan(wnd); set_priv_filter(wnd, Ndis802_11PrivFilterAcceptAll); set_auth_mode(wnd, Ndis802_11AuthModeOpen); set_encr_mode(wnd, Ndis802_11EncryptionDisabled); set_essid(wnd, "", 0); } kfree(buf); wrap_procfs_add_ndis_device(wnd); add_stats_timer(wnd); TRACEEXIT1(return NDIS_STATUS_SUCCESS);buffer_pool_err: wnd->tx_buffer_pool = NULL; if (wnd->tx_packet_pool) { NdisFreePacketPool(wnd->tx_packet_pool); wnd->tx_packet_pool = NULL; }packet_pool_err:err_register: kfree(buf);err_start: ndis_remove_device(wnd); TRACEEXIT1(return NDIS_STATUS_FAILURE);}static int ndis_remove_device(struct wrap_ndis_device *wnd){ int tx_pending; if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) miniport_set_info(wnd, OID_802_11_DISASSOCIATE, NULL, 0); set_bit(SHUTDOWN, &wnd->wrap_ndis_pending_work); unregister_netdevice_notifier(&netdev_notifier); wnd->tx_ok = 0; unregister_netdev(wnd->net_dev); netif_carrier_off(wnd->net_dev); cancel_delayed_work(&wnd->wrap_ndis_work); /* if device is suspended, but resume failed, tx_ring_mutex * may already be locked */ down_trylock(&wnd->tx_ring_mutex); tx_pending = wnd->tx_ring_end - wnd->tx_ring_start; if (tx_pending < 0) tx_pending += TX_RING_SIZE; else if (tx_pending == 0 && wnd->is_tx_ring_full) tx_pending = TX_RING_SIZE - 1; wnd->is_tx_ring_full = 0; /* throw away pending packets */ while (tx_pending > 0) { struct ndis_packet *packet; packet = wnd->tx_ring[wnd->tx_ring_start]; free_tx_packet(wnd, packet, NDIS_STATUS_CLOSING); wnd->tx_ring_start = (wnd->tx_ring_start + 1) % TX_RING_SIZE; tx_pending--; } up(&wnd->tx_ring_mutex); wrap_procfs_remove_ndis_device(wnd); miniport_halt(wnd); ndis_exit_device(wnd); if (wnd->tx_packet_pool) { NdisFreePacketPool(wnd->tx_packet_pool); wnd->tx_packet_pool = NULL; } if (wnd->tx_buffer_pool) { NdisFreeBufferPool(wnd->tx_buffer_pool); wnd->tx_buffer_pool = NULL; } printk(KERN_INFO "%s: device %s removed\n", DRIVER_NAME, wnd->net_dev->name); free_netdev(wnd->net_dev); TRACEEXIT2(return 0);}static wstdcall NTSTATUS NdisAddDevice(struct driver_object *drv_obj, struct device_object *pdo){ struct device_object *fdo; struct ndis_miniport_block *nmb; NTSTATUS status; struct wrap_ndis_device *wnd; struct net_device *net_dev; struct wrap_device *wd; unsigned long i; TRACEENTER2("%p, %p", drv_obj, pdo); if (strlen(if_name) >= IFNAMSIZ) { ERROR("interface name '%s' is too long", if_name); return STATUS_INVALID_PARAMETER; } net_dev = alloc_etherdev(sizeof(*wnd) + sizeof(*nmb)); if (!net_dev) { ERROR("couldn't allocate device"); return STATUS_RESOURCES; } wd = pdo->reserved;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) SET_MODULE_OWNER(net_dev); if (wrap_is_pci_bus(wd->dev_bus)) SET_NETDEV_DEV(net_dev, &wd->pci.pdev->dev); if (wrap_is_usb_bus(wd->dev_bus)) SET_NETDEV_DEV(net_dev, &wd->usb.intf->dev);#endif status = IoCreateDevice(drv_obj, 0, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo); if (status != STATUS_SUCCESS) { free_netdev(net_dev); TRACEEXIT2(return status); } wnd = netdev_priv(net_dev); DBGTRACE1("wnd: %p", wnd); nmb = ((void *)wnd) + sizeof(*wnd); wnd->nmb = nmb;#if defined(DEBUG) && DEBUG >= 6 /* poison nmb so if a driver accesses uninitialized pointers, we * know what it is */ for (i = 0; i < sizeof(*nmb) / sizeof(unsigned long); i++) ((unsigned long *)nmb)[i] = i + 0x8a3fc1;#endif nmb->wnd = wnd; nmb->pdo = pdo; wd->wnd = wnd; wnd->wd = wd; nmb->filterdbs.eth_db = nmb; nmb->filterdbs.tr_db = nmb; nmb->filterdbs.fddi_db = nmb; nmb->filterdbs.arc_db = nmb; KeInitializeSpinLock(&nmb->lock); init_nmb_functions(nmb); wnd->net_dev = net_dev; wnd->ndis_irq = NULL; init_MUTEX(&wnd->tx_ring_mutex); init_MUTEX(&wnd->ndis_comm_mutex); init_waitqueue_head(&wnd->ndis_comm_wq); wnd->ndis_comm_done = 0; INIT_WORK(&wnd->tx_work, tx_worker, wnd); wnd->tx_ring_start = 0; wnd->tx_ring_end = 0; wnd->is_tx_ring_full = 0; wnd->encr_mode = Ndis802_11EncryptionDisabled; wnd->auth_mode = Ndis802_11AuthModeOpen; wnd->capa.encr = 0; wnd->capa.auth = 0; wnd->attributes = 0; wnd->tx_dma_count = 0; wnd->tx_dma_addr = NULL; wnd->nick[0] = 0; init_timer(&wnd->hangcheck_timer); wnd->scan_timestamp = 0; init_timer(&wnd->stats_timer); wnd->stats_interval = 10 * HZ; wnd->wrap_ndis_pending_work = 0; memset(&wnd->essid, 0, sizeof(wnd->essid)); memset(&wnd->encr_info, 0, sizeof(wnd->encr_info)); wnd->infrastructure_mode = Ndis802_11Infrastructure; INIT_WORK(&wnd->wrap_ndis_work, wrap_ndis_worker, wnd); wnd->hw_status = 0; if (wd->driver->ndis_driver) wd->driver->ndis_driver->miniport.shutdown = NULL; wnd->stats_enabled = TRUE; InitializeListHead(&wnd->timer_list); fdo->reserved = wnd; nmb->fdo = fdo; nmb->next_device = IoAttachDeviceToDeviceStack(fdo, pdo); DBGTRACE1("nmb: %p, pdo: %p, fdo: %p, attached: %p, next: %p", nmb, pdo, fdo, fdo->attached, nmb->next_device); /* dispatch routines are called as Windows functions */ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) drv_obj->major_func[i] = WIN_FUNC_PTR(IoPassIrpDown,2); drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(NdisDispatchPnp,2); drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(NdisDispatchPower,2); drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] = WIN_FUNC_PTR(NdisDispatchDeviceControl,2);// drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] =// WIN_FUNC_PTR(NdisDispatchDeviceControl,2); TRACEEXIT2(return STATUS_SUCCESS);}int init_ndis_driver(struct driver_object *drv_obj){ TRACEENTER1("%p", drv_obj); drv_obj->drv_ext->add_device = NdisAddDevice; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -