📄 wrapper.c
字号:
if(res) { printk(KERN_ERR "Unable to get MAC-addr from driver\n"); return -1; } dev->open = ndis_open; dev->hard_start_xmit = ndis_start_xmit; dev->stop = ndis_close; dev->get_stats = ndis_get_stats; dev->do_ioctl = ndis_ioctl; dev->get_wireless_stats = ndis_get_wireless_stats; dev->wireless_handlers = (struct iw_handler_def *)&ndis_handler_def; for(i = 0; i < 6; i++) { dev->dev_addr[i] = mac[i]; } dev->irq = handle->irq; dev->mem_start = handle->mem_start; dev->mem_end = handle->mem_end; return register_netdev(dev);}/* * Called by PCI-subsystem for each PCI-card found. */static int __devinit ndis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){ int res; struct ndis_driver *driver = (struct ndis_driver *) ent->driver_data; struct ndis_handle *handle; struct net_device *dev; DBGTRACE("%s\n", __FUNCTION__); dev = alloc_etherdev(sizeof(*handle)); if(!dev) { printk(KERN_ERR "Unable to alloc etherdev\n"); res = -ENOMEM; goto out_nodev; } SET_MODULE_OWNER(dev);// SET_NETDEV_DEV(dev, &pdev->dev); handle = dev->priv; handle->driver = driver; handle->net_dev = dev; spin_lock_init(&handle->query_lock); pci_set_drvdata(pdev, handle); /* Poision this because it may contain function pointers */ memset(&handle->fill1, 0x12, sizeof(handle->fill1)); memset(&handle->fill2, 0x13, sizeof(handle->fill2)); memset(&handle->fill3, 0x14, sizeof(handle->fill3)); memset(&handle->fill4, 0x15, sizeof(handle->fill4)); handle->indicate_receive_packet = &NdisMIndicateReceivePacket; handle->send_complete = &NdisMSendComplete; handle->indicate_status = &NdisIndicateStatus; handle->indicate_status_complete = &NdisIndicateStatusComplete; handle->query_complete = &NdisMQueryInformationComplete; handle->set_complete = &NdisMSetInformationComplete; handle->pci_dev = pdev; res = pci_enable_device(pdev); if(res) goto out_enable; res = pci_request_regions(pdev, driver->name); if(res) goto out_regions; if(call_init(handle)) { printk(KERN_ERR "ndiswrapper: Driver init returned error\n"); res = -EINVAL; goto out_start; } if(setup_dev(handle->net_dev)) { printk(KERN_ERR "ndiswrapper: Unable to set up driver\n"); res = -EINVAL; goto out_start; } handle->driver->key_len = 0; init_timer(&(handle->driver->timer_list)); add_scan_timer((unsigned long)handle); return 0;out_start: pci_release_regions(pdev);out_regions: pci_disable_device(pdev);out_enable: free_netdev(dev);out_nodev: return res;}static void __devexit ndis_remove_one(struct pci_dev *pdev){ struct ndis_handle *handle = (struct ndis_handle *) pci_get_drvdata(pdev); DBGTRACE("%s\n", __FUNCTION__); del_timer(&(handle->driver->timer_list));#ifndef DEBUG_CRASH_ON_INIT unregister_netdev(handle->net_dev); call_halt(handle); if(handle->net_dev) free_netdev(handle->net_dev);#endif pci_release_regions(pdev); pci_disable_device(pdev);}static int misc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static struct file_operations wrapper_fops = { .owner = THIS_MODULE, .ioctl = misc_ioctl,};static struct miscdevice wrapper_misc = { .name = DRV_NAME, .fops = &wrapper_fops};/* * Register driver with pci subsystem. */static int start_driver(struct ndis_driver *driver){ int res = 0; if(call_entry(driver)) { printk(KERN_ERR "ndiswrapper: Driver entry return error\n"); return -EINVAL; } driver->pci_driver.name = driver->name; driver->pci_driver.id_table = driver->pci_id; driver->pci_driver.probe = ndis_init_one; driver->pci_driver.remove = ndis_remove_one; #ifndef DEBUG_CRASH_ON_INIT res = pci_module_init(&driver->pci_driver); if(!res) driver->pci_registered = 1;#endif return res;}/* * Load the driver from userspace. */static struct ndis_driver *load_driver(struct put_driver *put_driver){ void *entry; struct ndis_driver *driver; struct pci_dev *pdev = 0; int namelen; DBGTRACE("Putting driver size %d\n", put_driver->size); driver = kmalloc(sizeof(struct ndis_driver), GFP_KERNEL); if(!driver) { printk(KERN_ERR "Unable to alloc driver struct\n"); goto out_nodriver; } memset(driver, 0, sizeof(struct ndis_driver)); INIT_LIST_HEAD(&driver->settings); namelen = sizeof(put_driver->name); if(sizeof(driver->name) < namelen) namelen = sizeof(driver->name); strncpy(driver->name, put_driver->name, namelen-1); driver->name[namelen-1] = 0; driver->image = vmalloc(put_driver->size); DBGTRACE("Image is at %08x\n", (int)driver->image); if(!driver->image) { printk(KERN_ERR "Unable to allocate mem for driver\n"); goto out_vmalloc; } if(copy_from_user(driver->image, put_driver->data, put_driver->size)) { printk(KERN_ERR "Failed to copy from user\n"); goto out_vmalloc; } if(prepare_coffpe_image(&entry, driver->image, put_driver->size)) { printk(KERN_ERR "Unable to prepare driver\n"); goto out_baddriver; } /* Make sure PCI device is present */ pdev = pci_find_device(put_driver->pci_vendor, put_driver->pci_device, pdev); if(!pdev) { printk(KERN_ERR "PCI device %04x:%04x not present\n", put_driver->pci_vendor, put_driver->pci_device); goto out_baddriver; } driver->pci_id[0].vendor = put_driver->pci_vendor; driver->pci_id[0].device = put_driver->pci_device; driver->pci_id[0].subvendor = PCI_ANY_ID; driver->pci_id[0].subdevice = PCI_ANY_ID; driver->pci_id[0].class = 0; driver->pci_id[0].class_mask = 0; driver->pci_id[0].driver_data = (int)driver; driver->entry = entry; return driver;out_baddriver: vfree(driver->image);out_vmalloc: kfree(driver);out_nodriver: return 0;}/* * Add driver to list of loaded driver but make sure this driver is * not loaded before. */static int add_driver(struct ndis_driver *driver){ struct ndis_driver *tmp; int dup = 0; spin_lock(&driverlist_lock); list_for_each_entry(tmp, &driverlist, list) { if(tmp->pci_id[0].vendor == driver->pci_id[0].vendor && tmp->pci_id[0].device == driver->pci_id[0].device) { dup = 1; break; } if(strcmp(tmp->name, driver->name) == 0) { dup = 1; break; } } if(!dup) list_add(&driver->list, &driverlist); spin_unlock(&driverlist_lock); if(dup) { printk(KERN_ERR "Cannot add duplicate driver\n"); return -EBUSY; } return 0;}/* * Add setting to the list of settings for the driver. */static int add_setting(struct ndis_driver *driver, struct put_setting *put_setting){ struct ndis_setting *setting; char *name; unsigned int val; if(put_setting->payload_len != sizeof(val)) { return -EINVAL; } if(copy_from_user(&val, put_setting->payload, sizeof(val))) return -EINVAL; name = kmalloc(put_setting->name_len+1, GFP_KERNEL); if(!name) return -ENOMEM; setting = kmalloc(sizeof(*setting), GFP_KERNEL); if(!setting) { kfree(name); return -ENOMEM; } memset(setting, 0, sizeof(*setting)); if(copy_from_user(name, put_setting->name, put_setting->name_len)) { kfree(name); kfree(setting); return -EINVAL; } name[put_setting->name_len] = 0; setting->val.type = 0; setting->name = name; setting->val.type = 0; setting->val.data.intval = val; list_add(&setting->list, &driver->settings); return 0;}/* * Delete a driver. This implies deleting all cards for the handle too. */static void unload_driver(struct ndis_driver *driver){ struct list_head *curr, *tmp2; DBGTRACE("%s\n", __FUNCTION__); if(driver->pci_registered) pci_unregister_driver(&driver->pci_driver);#ifdef DEBUG_CRASH_ON_INIT { struct pci_dev *pdev = 0; pdev = pci_find_device(driver->pci_id[0].vendor, driver->pci_id[0].device, pdev); if(pdev) ndis_remove_one(pdev); }#endif spin_lock(&driverlist_lock); list_del(&driver->list); spin_unlock(&driverlist_lock); if(driver->image) vfree(driver->image); list_for_each_safe(curr, tmp2, &driver->settings) { struct ndis_setting *setting = (struct ndis_setting*) curr; kfree(setting->name); kfree(setting); } kfree(driver);}static int misc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct put_setting put_setting; struct put_driver put_driver; struct ndis_driver *driver; switch(cmd) { case NDIS_PUTDRIVER: if(copy_from_user(&put_driver, (void*)arg, sizeof(struct put_driver))) return -EINVAL; driver = load_driver(&put_driver); if(!driver) return -EINVAL; file->private_data = driver; return add_driver(driver); break; case NDIS_STARTDRIVER: if(file->private_data) { struct ndis_driver *driver= file->private_data; int res = start_driver(driver);#ifdef DEBUG_CRASH_ON_INIT { struct pci_dev *pdev = 0; pdev = pci_find_device(driver->pci_id[0].vendor, driver->pci_id[0].device, pdev); if(pdev) ndis_init_one(pdev, &driver->pci_id[0]); }#endif file->private_data = NULL; if(res) { unload_driver(driver); return res; } } break; case NDIS_PUTSETTING: if(file->private_data) { int res; struct ndis_driver *driver = file->private_data; if(copy_from_user(&put_setting, (void*)arg, sizeof(struct put_setting))) return -EINVAL; res = add_setting(driver, &put_setting); if(res) return res; } break; case NDIS_CANCELLOAD: if(file->private_data) { struct ndis_driver *driver = file->private_data; unload_driver(driver); } break; default: printk(KERN_ERR "Unknown ioctl %08x\n", cmd); return -EINVAL; break; } return 0;}void init_ndis_work(void);static int __init wrapper_init(void){ int err; printk(KERN_INFO "ndiswrapper version %s loaded\n", DRV_VERSION); if ( (err = misc_register(&wrapper_misc)) < 0 ) { printk(KERN_ERR "misc_register failed\n"); return err; } init_ndis_work(); return 0;}static void __exit wrapper_exit(void){ while(!list_empty(&driverlist)) { struct ndis_driver *driver = (struct ndis_driver*) driverlist.next; unload_driver(driver); } misc_deregister(&wrapper_misc);}module_init(wrapper_init);module_exit(wrapper_exit);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -