📄 loader.c
字号:
if (driver->num_bin_files < load_driver->nr_bin_files) { for (i = 0; i < driver->num_bin_files; i++) vfree(bin_files[i].data); kfree(bin_files); driver->num_bin_files = 0; TRACEEXIT1(return -EINVAL); } else { driver->bin_files = bin_files; TRACEEXIT1(return 0); }}/* load settnigs for a device */static int load_settings(struct ndis_driver *ndis_driver, struct load_driver *load_driver){ int i, found, nr_settings; struct ndis_device *ndis_device; TRACEENTER1(""); found = 0; kspin_lock(&loader_lock); for (i = 0; i < num_ndis_devices; i++) { if (strcmp(ndis_devices[i].conf_file_name, load_driver->conf_file_name) == 0) { found = 1; break; } } kspin_unlock(&loader_lock); if (!found) { ERROR("conf file %s not found", ndis_devices[i].conf_file_name); TRACEEXIT1(return -EINVAL); } nr_settings = 0; ndis_device = &ndis_devices[i]; for (i = 0; i < load_driver->nr_settings; i++) { struct load_device_setting *load_setting = &load_driver->settings[i]; struct device_setting *setting; setting = kmalloc(sizeof(*setting), GFP_KERNEL); if (!setting) { ERROR("couldn't allocate memory"); break; } memset(setting, 0, sizeof(*setting)); memcpy(setting->name, load_setting->name, MAX_NDIS_SETTING_NAME_LEN); memcpy(setting->value, load_setting->value, MAX_NDIS_SETTING_VALUE_LEN); DBGTRACE2("copied setting %s", load_setting->name); setting->config_param.type = NDIS_CONFIG_PARAM_NONE; if (strcmp(setting->name, "ndis_version") == 0) memcpy(ndis_driver->version, setting->value, sizeof(ndis_driver->version)); kspin_lock(&loader_lock); list_add(&setting->list, &ndis_device->settings); kspin_unlock(&loader_lock); nr_settings++; } /* it is not a fatal error if some settings couldn't be loaded */ if (nr_settings > 0) TRACEEXIT1(return 0); else TRACEEXIT1(return -EINVAL);}/* this function is called while holding load_lock spinlock */static void unload_ndis_device(struct ndis_device *device){ TRACEENTER1("unloading device %04X:%04X:%04X:%04X, driver %s", device->vendor, device->device, device->subvendor, device->subdevice, device->driver_name); while (!list_empty(&device->settings)) { struct device_setting *setting; struct ndis_config_param *param; setting = list_entry(device->settings.next, struct device_setting, list); param = &setting->config_param; if (param->type == NDIS_CONFIG_PARAM_STRING) RtlFreeUnicodeString(¶m->data.ustring); list_del(&setting->list); kfree(setting); } TRACEEXIT1(return);}/* at the time this function is called, devices are deregistered, so * safe to remove the driver without any checks */static void unload_ndis_driver(struct ndis_driver *driver){ int i; DBGTRACE1("freeing %d images", driver->num_pe_images); if (driver->driver_unload) driver->driver_unload(driver); for (i = 0; i < driver->num_pe_images; i++) if (driver->pe_images[i].image) vfree(driver->pe_images[i].image); DBGTRACE1("freeing %d bin files", driver->num_bin_files); for (i = 0; i < driver->num_bin_files; i++) vfree(driver->bin_files[i].data); if (driver->bin_files) kfree(driver->bin_files); kfree(driver); TRACEEXIT1(return);}/* call the entry point of the driver */static int start_driver(struct ndis_driver *driver){ int i, ret, res; struct unicode_string reg_string; char *reg_path = "0/0t0m0p0"; TRACEENTER1(""); reg_string.buf = (wchar_t *)reg_path; reg_string.buflen = reg_string.len = strlen(reg_path); for (ret = res = 0, i = 0; i < driver->num_pe_images; i++) /* dlls are already started by loader */ if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) { UINT (*entry)(void *obj, struct unicode_string *p2) STDCALL; entry = driver->pe_images[i].entry; DBGTRACE1("entry: %p, %p", entry, *entry); res = LIN2WIN2(entry, (void *)driver, ®_string); ret |= res; DBGTRACE1("entry returns %08X", res); DBGTRACE1("driver version: %d.%d", driver->miniport_char.majorVersion, driver->miniport_char.minorVersion); driver->entry = entry; } if (ret) { ERROR("driver initialization failed: %08X", ret); TRACEEXIT1(return -EINVAL); } TRACEEXIT1(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; TRACEENTER1(""); kspin_lock(&loader_lock); list_for_each_entry(tmp, &ndis_drivers, list) { if (strcmp(tmp->name, driver->name) == 0) { kspin_unlock(&loader_lock); ERROR("cannot add duplicate driver"); TRACEEXIT1(return -EBUSY); } } list_add(&driver->list, &ndis_drivers); kspin_unlock(&loader_lock); TRACEEXIT1(return 0);}/* load a driver from userspace and initialize it */static int load_ndis_driver(struct load_driver *load_driver){ struct ndis_driver *ndis_driver; ndis_driver = kmalloc(sizeof(*ndis_driver), GFP_KERNEL); if (!ndis_driver) { ERROR("couldn't allocate memory"); TRACEEXIT1(return -EINVAL); } memset(ndis_driver, 0, sizeof(*ndis_driver)); ndis_driver->bustype = -1; if (load_sys_files(ndis_driver, load_driver) || load_bin_files(ndis_driver, load_driver) || load_settings(ndis_driver, load_driver) || start_driver(ndis_driver) || add_driver(ndis_driver)) { unload_ndis_driver(ndis_driver); TRACEEXIT1(return -EINVAL); } else { printk(KERN_INFO "%s: driver %s (%s) loaded\n", DRIVER_NAME, ndis_driver->name, ndis_driver->version);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) add_taint(TAINT_PROPRIETARY_MODULE); /* older kernels don't seem to have a way to set * tainted information */#endif TRACEEXIT1(return 0); }}/* register all devices (for all drivers) installed */static int register_devices(struct load_devices *load_devices){ int i, res, num_pci, num_usb; struct load_device *devices; devices = NULL; ndiswrapper_pci_devices = NULL; ndiswrapper_usb_devices = NULL; ndis_devices = NULL; devices = vmalloc(load_devices->count * sizeof(struct load_device)); if (!devices) { ERROR("couldn't allocate memory"); TRACEEXIT1(return -ENOMEM); } if (copy_from_user(devices, load_devices->devices, load_devices->count * sizeof(struct load_device))) { ERROR("couldn't copy from user space"); goto err; } num_pci = num_usb = 0; for (i = 0; i < load_devices->count; i++) if (devices[i].bustype == NDIS_PCI_BUS) num_pci++; else if (devices[i].bustype == NDIS_USB_BUS) num_usb++; else WARNING("bus type %d is not valid", devices[i].bustype); num_ndis_devices = num_pci + num_usb; if (num_pci > 0) { ndiswrapper_pci_devices = kmalloc((num_pci + 1) * sizeof(struct pci_device_id), GFP_KERNEL); if (!ndiswrapper_pci_devices) { ERROR("couldn't allocate memory"); goto err; } memset(ndiswrapper_pci_devices, 0, (num_pci + 1) * sizeof(struct pci_device_id)); } if (num_usb > 0) { ndiswrapper_usb_devices = kmalloc((num_usb + 1) * sizeof(struct usb_device_id), GFP_KERNEL); if (!ndiswrapper_usb_devices) { ERROR("couldn't allocate memory"); goto err; } memset(ndiswrapper_usb_devices, 0, (num_usb + 1) * sizeof(struct usb_device_id)); } ndis_devices = vmalloc(num_ndis_devices * sizeof(*ndis_devices)); if (!ndis_devices) { ERROR("couldn't allocate memory"); goto err; } memset(ndis_devices, 0, num_ndis_devices * sizeof(*ndis_devices)); num_usb = num_pci = 0; for (i = 0; i < load_devices->count; i++) { struct load_device *device = &devices[i]; struct ndis_device *ndis_device; ndis_device = &ndis_devices[num_pci + num_usb]; INIT_LIST_HEAD(&ndis_device->settings); memcpy(&ndis_device->driver_name, device->driver_name, sizeof(ndis_device->driver_name)); memcpy(&ndis_device->conf_file_name, device->conf_file_name, sizeof(ndis_device->conf_file_name)); ndis_device->bustype = device->bustype; ndis_device->vendor = device->vendor; ndis_device->device = device->device; ndis_device->subvendor = device->subvendor; ndis_device->subdevice = device->subdevice; memcpy(&ndis_device->driver_name, device->driver_name, sizeof(ndis_device->driver_name)); if (device->bustype == NDIS_PCI_BUS) { ndiswrapper_pci_devices[num_pci].vendor = device->vendor; ndiswrapper_pci_devices[num_pci].device = device->device; if (device->subvendor == DEV_ANY_ID) ndiswrapper_pci_devices[num_pci].subvendor = PCI_ANY_ID; else ndiswrapper_pci_devices[num_pci].subvendor = device->subvendor; if (device->subdevice == DEV_ANY_ID) ndiswrapper_pci_devices[num_pci].subdevice = PCI_ANY_ID; else ndiswrapper_pci_devices[num_pci].subdevice = device->subdevice; ndiswrapper_pci_devices[num_pci].class = 0; ndiswrapper_pci_devices[num_pci].class_mask = 0; ndiswrapper_pci_devices[num_pci].driver_data = num_pci + num_usb; num_pci++; DBGTRACE1("pci device %d added", num_pci); DBGTRACE1("adding %04x:%04x:%04x:%04x to pci idtable", device->vendor, device->device, device->subvendor, device->subdevice);#ifdef CONFIG_USB } else if (device->bustype == NDIS_USB_BUS) { ndiswrapper_usb_devices[num_usb].idVendor = device->vendor; ndiswrapper_usb_devices[num_usb].idProduct = device->device; ndiswrapper_usb_devices[num_usb].match_flags = USB_DEVICE_ID_MATCH_DEVICE; ndiswrapper_usb_devices[num_usb].driver_info = num_pci + num_usb; num_usb++; DBGTRACE1("usb device %d added", num_usb); DBGTRACE1("adding %04x:%04x to usb idtable", device->vendor, device->device);#endif } else { ERROR("system doesn't support bus type %d", device->bustype); } } if (ndiswrapper_pci_devices) { memset(&ndiswrapper_pci_driver, 0, sizeof(ndiswrapper_pci_driver)); ndiswrapper_pci_driver.name = DRIVER_NAME; ndiswrapper_pci_driver.id_table = ndiswrapper_pci_devices; ndiswrapper_pci_driver.probe = ndiswrapper_add_one_pci_dev; ndiswrapper_pci_driver.remove = __devexit_p(ndiswrapper_remove_one_pci_dev); ndiswrapper_pci_driver.suspend = ndiswrapper_suspend_pci; ndiswrapper_pci_driver.resume = ndiswrapper_resume_pci; res = pci_register_driver(&ndiswrapper_pci_driver); if (res < 0) { ERROR("couldn't register ndiswrapper pci driver"); goto err; } }#ifdef CONFIG_USB if (ndiswrapper_usb_devices) { memset(&ndiswrapper_usb_driver, 0, sizeof(ndiswrapper_usb_driver)); ndiswrapper_usb_driver.owner = THIS_MODULE; ndiswrapper_usb_driver.name = DRIVER_NAME; ndiswrapper_usb_driver.id_table = ndiswrapper_usb_devices; ndiswrapper_usb_driver.probe = ndiswrapper_add_one_usb_dev; ndiswrapper_usb_driver.disconnect = ndiswrapper_remove_one_usb_dev; res = usb_register(&ndiswrapper_usb_driver); if (res < 0) { ERROR("couldn't register ndiswrapper usb driver"); goto err; } }#endif vfree(devices); TRACEEXIT1(return 0);err: if (ndis_devices) vfree(ndis_devices); ndis_devices = NULL; if (ndiswrapper_usb_devices) kfree(ndiswrapper_usb_devices); ndiswrapper_usb_devices = NULL; if (ndiswrapper_pci_devices) kfree(ndiswrapper_pci_devices); ndiswrapper_pci_devices = NULL; if (devices) vfree(devices); TRACEEXIT1(return -EINVAL);}static int wrapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct load_driver *load_driver; struct load_devices devices; int res; TRACEENTER1("cmd: %u (%lu, %lu)", cmd, (unsigned long)NDIS_REGISTER_DEVICES, (unsigned long)NDIS_LOAD_DRIVER); res = 0; switch (cmd) { case NDIS_REGISTER_DEVICES: DBGTRACE1("adding devices at %p", (void *)arg); res = copy_from_user(&devices, (void *)arg, sizeof(devices)); if (!res) res = register_devices(&devices); if (res) TRACEEXIT1(return -EINVAL); TRACEEXIT1(return 0); break; case NDIS_LOAD_DRIVER: DBGTRACE1("loading driver at %p", (void *)arg); load_driver = vmalloc(sizeof(*load_driver)); if (!load_driver) TRACEEXIT1(return -ENOMEM); res = copy_from_user(load_driver, (void *)arg, sizeof(*load_driver)); if (!res) res = load_ndis_driver(load_driver); vfree(load_driver); if (res) TRACEEXIT1(return -EINVAL); else TRACEEXIT1(return 0); break; default: ERROR("Unknown ioctl %u", cmd); TRACEEXIT1(return -EINVAL); break; } TRACEEXIT1(return 0);}static int wrapper_ioctl_release(struct inode *inode, struct file *file){ TRACEENTER1(""); return 0;}static struct file_operations wrapper_fops = { .owner = THIS_MODULE, .ioctl = wrapper_ioctl, .release = wrapper_ioctl_release,};static struct miscdevice wrapper_misc = { .name = DRIVER_NAME, .fops = &wrapper_fops};int loader_init(void){ int err; INIT_LIST_HEAD(&ndis_drivers); kspin_lock_init(&loader_lock); if ((err = misc_register(&wrapper_misc)) < 0 ) { ERROR("couldn't register module (%d)", err); TRACEEXIT1(return err); } TRACEEXIT1(return 0);}void loader_exit(void){ int i; TRACEENTER1(""); misc_deregister(&wrapper_misc);#ifdef CONFIG_USB if (ndiswrapper_usb_devices) { usb_deregister(&ndiswrapper_usb_driver); kfree(ndiswrapper_usb_devices); ndiswrapper_usb_devices = NULL; }#endif if (ndiswrapper_pci_devices) { pci_unregister_driver(&ndiswrapper_pci_driver); kfree(ndiswrapper_pci_devices); ndiswrapper_pci_devices = NULL; } kspin_lock(&loader_lock); if (ndis_devices) { for (i = 0; i < num_ndis_devices; i++) unload_ndis_device(&ndis_devices[i]); vfree(ndis_devices); ndis_devices = NULL; } while (!list_empty(&ndis_drivers)) { struct ndis_driver *driver; driver = list_entry(ndis_drivers.next, struct ndis_driver, list); list_del(&driver->list); unload_ndis_driver(driver); } kspin_unlock(&loader_lock); TRACEEXIT1(return);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -