📄 wrapndis.c
字号:
struct wrap_ndis_device *wnd = netdev_priv(dev); if (wnd->sg_dma_size) return ethtool_op_set_sg(dev, data); else return -EOPNOTSUPP;} static struct ethtool_ops ndis_ethtool_ops = { .get_drvinfo = ndis_get_drvinfo, .get_link = ndis_get_link, .get_wol = ndis_get_wol, .set_wol = ndis_set_wol, .get_tx_csum = ndis_get_tx_csum, .get_rx_csum = ndis_get_rx_csum, .set_tx_csum = ndis_set_tx_csum, .set_rx_csum = ndis_set_rx_csum, .get_sg = ndis_get_sg, .set_sg = ndis_set_sg,};#endifstatic int notifier_event(struct notifier_block *notifier, unsigned long event, void *ptr){ struct net_device *net_dev = (struct net_device *)ptr; struct wrap_ndis_device *wnd; if (net_dev->open != ndis_net_dev_open) return NOTIFY_DONE; wnd = netdev_priv(net_dev); /* called with rtnl lock held, so no need to lock */ if (event == NETDEV_CHANGENAME) { wrap_procfs_remove_ndis_device(wnd); printk(KERN_INFO "%s: changing interface name from '%s' to " "'%s'\n", DRIVER_NAME, wnd->netdev_name, net_dev->name); memcpy(wnd->netdev_name, net_dev->name, sizeof(wnd->netdev_name)); wrap_procfs_add_ndis_device(wnd); return NOTIFY_OK; } TRACE2("%s: %lx", wnd->netdev_name, event); return NOTIFY_DONE;}static struct notifier_block netdev_notifier = { .notifier_call = notifier_event,};static NDIS_STATUS wrap_ndis_start_device(struct wrap_ndis_device *wnd){ struct wrap_device *wd; struct net_device *net_dev; NDIS_STATUS status; char *buf; const int buf_len = 256; mac_address mac; struct transport_header_offset *tx_header_offset; int n; status = miniport_init(wnd); if (status == NDIS_STATUS_NOT_RECOGNIZED) EXIT1(return NDIS_STATUS_SUCCESS); if (status != NDIS_STATUS_SUCCESS) EXIT1(return status); wd = wnd->wd; net_dev = wnd->net_dev; status = miniport_query_info(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac)); if (status) { ERROR("couldn't get mac address: %08X", status); goto err_start; } TRACE1("mac:" MACSTRSEP, MAC2STR(mac)); status = miniport_query_int(wnd, OID_GEN_PHYSICAL_MEDIUM, &wnd->physical_medium); if (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'; memcpy(&net_dev->dev_addr, mac, ETH_ALEN); wnd->packet_filter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_MULTICAST; 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->change_mtu = ndis_change_mtu; net_dev->do_ioctl = NULL; if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {#if WIRELESS_EXT < 19 net_dev->get_wireless_stats = get_iw_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->mp_interrupt) net_dev->irq = wnd->mp_interrupt->irq; net_dev->mem_start = wnd->mem_start; net_dev->mem_end = wnd->mem_end; status = miniport_query_int(wnd, OID_802_3_MAXIMUM_LIST_SIZE, &wnd->multicast_size); if (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_len, GFP_KERNEL); if (!buf) { WARNING("couldn't allocate memory"); goto err_start; } set_task_offload(wnd, buf, buf_len);#ifdef NETIF_F_LLTX net_dev->features |= NETIF_F_LLTX;#endif if (register_netdev(net_dev)) { ERROR("cannot register net device %s", net_dev->name); goto err_register; } memcpy(wnd->netdev_name, net_dev->name, sizeof(wnd->netdev_name)); memset(buf, 0, buf_len); status = miniport_query_info(wnd, OID_GEN_VENDOR_DESCRIPTION, buf, buf_len); if (status != NDIS_STATUS_SUCCESS) { WARNING("couldn't get vendor information: 0x%x", status); buf[0] = 0; } wnd->drv_ndis_version = n = 0; miniport_query_int(wnd, OID_GEN_DRIVER_VERSION, &wnd->drv_ndis_version); miniport_query_int(wnd, OID_GEN_VENDOR_DRIVER_VERSION, &n); printk(KERN_INFO "%s: ethernet device " MACSTRSEP " using %sNDIS " "driver: %s, version: 0x%x, NDIS version: 0x%x, vendor: '%s', " "%s\n", net_dev->name, MAC2STR(net_dev->dev_addr), deserialized_driver(wnd) ? "" : "serialized ", wnd->wd->driver->name, n, wnd->drv_ndis_version, buf, 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 { status = miniport_query_int(wnd, OID_GEN_MAXIMUM_SEND_PACKETS, &wnd->max_tx_packets); if (status != NDIS_STATUS_SUCCESS) wnd->max_tx_packets = 1; if (wnd->max_tx_packets > TX_RING_SIZE) wnd->max_tx_packets = TX_RING_SIZE; } TRACE2("maximum send packets: %d", wnd->max_tx_packets); NdisAllocatePacketPoolEx(&status, &wnd->tx_packet_pool, wnd->max_tx_packets, 0, PROTOCOL_RESERVED_SIZE_IN_PACKET); if (status != NDIS_STATUS_SUCCESS) { ERROR("couldn't allocate packet pool"); goto packet_pool_err; } NdisAllocateBufferPool(&status, &wnd->tx_buffer_pool, wnd->max_tx_packets + 4); if (status != NDIS_STATUS_SUCCESS) { ERROR("couldn't allocate buffer pool"); goto buffer_pool_err; } TRACE1("pool: %p", wnd->tx_buffer_pool); if (miniport_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &n) == NDIS_STATUS_SUCCESS && n > ETH_HLEN) ndis_change_mtu(wnd->net_dev, n - ETH_HLEN); if (miniport_query_int(wnd, OID_GEN_MAC_OPTIONS, &n) == NDIS_STATUS_SUCCESS && n > 0) TRACE2("mac options supported: 0x%x", n); tx_header_offset = (typeof(tx_header_offset))buf; tx_header_offset->protocol_type = NDIS_PROTOCOL_ID_TCP_IP; tx_header_offset->header_offset = sizeof(ETH_HLEN); status = miniport_set_info(wnd, OID_GEN_TRANSPORT_HEADER_OFFSET, tx_header_offset, sizeof(*tx_header_offset)); TRACE2("%08X", status); wnd->tx_ok = 1; if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { miniport_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF); get_encryption_capa(wnd, buf, buf_len); TRACE1("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); hangcheck_add(wnd); add_iw_stats_timer(wnd); EXIT1(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: wrap_ndis_remove_device(wnd); EXIT1(return NDIS_STATUS_FAILURE);}static int wrap_ndis_remove_device(struct wrap_ndis_device *wnd){ s8 tx_pending; KIRQL irql; /* prevent setting essid during disassociation */ memset(&wnd->essid, 0, sizeof(wnd->essid)); if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { up(&wnd->ndis_comm_mutex); disassociate(wnd, 0); down_interruptible(&wnd->ndis_comm_mutex); } set_bit(SHUTDOWN, &wnd->wrap_ndis_pending_work); wnd->tx_ok = 0; unregister_netdev(wnd->net_dev); netif_carrier_off(wnd->net_dev); /* if device is suspended, but resume failed, tx_ring_mutex * may already be locked */ down_trylock(&wnd->tx_ring_mutex); irql = nt_spin_lock_irql(&wnd->tx_ring_lock, DISPATCH_LEVEL); 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--; } nt_spin_unlock_irql(&wnd->tx_ring_lock, irql); 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); EXIT2(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; ENTER2("%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); EXIT2(return status); } wnd = netdev_priv(net_dev); TRACE1("wnd: %p", wnd); nmb = ((void *)wnd) + sizeof(*wnd);#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 wnd->nmb = nmb; nmb->wnd = wnd; nmb->pdo = pdo; wd->wnd = wnd; wnd->wd = wd; wnd->net_dev = net_dev; fdo->reserved = wnd; nmb->fdo = fdo; if (ndis_init_device(wnd)) { IoDeleteDevice(fdo); free_netdev(net_dev); EXIT1(return STATUS_RESOURCES); } nmb->next_device = IoAttachDeviceToDeviceStack(fdo, pdo); nt_spin_lock_init(&wnd->tx_ring_lock); init_MUTEX(&wnd->tx_ring_mutex); init_MUTEX(&wnd->ndis_comm_mutex); wnd->ndis_comm_done = 0; initialize_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->dma_map_count = 0; wnd->dma_map_addr = NULL; wnd->nick[0] = 0; init_timer(&wnd->hangcheck_timer); wnd->scan_timestamp = 0; init_timer(&wnd->iw_stats_timer); wnd->iw_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; initialize_work(&wnd->wrap_ndis_work, wrap_ndis_worker, wnd); wnd->iw_stats_enabled = TRUE; TRACE1("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); EXIT2(return STATUS_SUCCESS);}int init_ndis_driver(struct driver_object *drv_obj){ ENTER1("%p", drv_obj); drv_obj->drv_ext->add_device = NdisAddDevice; return 0;}int wrapndis_init(void){ register_netdevice_notifier(&netdev_notifier); return 0;}void wrapndis_exit(void){ unregister_netdevice_notifier(&netdev_notifier);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -