📄 loadndisdriver.c
字号:
/* * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <libgen.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <limits.h>#include <ctype.h>#include <dirent.h>#include <syslog.h>#include <stdlib.h>#include <linux/ioctl.h>#include "../driver/loader.h"#define PROG_NAME "loadndisdriver"#define SETTING_LEN (MAX_NDIS_SETTING_NAME_LEN+MAX_NDIS_SETTING_VALUE_LEN + 2)static const char *confdir = "/etc/ndiswrapper";static const char *ioctl_file = "/dev/ndiswrapper";static int debug;#ifndef NDISWRAPPER_VERSION#error Compile this file with 'make' in the 'utils' \ directory only#endif#define error(fmt, ...) do { \ syslog(LOG_KERN | LOG_ERR, "%s: %s(%d): " fmt "\n", \ PROG_NAME, __FUNCTION__, __LINE__ , ## __VA_ARGS__); \ } while (0)#define info(fmt, ...) do { \ syslog(LOG_KERN | LOG_INFO, "%s: %s(%d): " fmt "\n", \ PROG_NAME, __FUNCTION__, __LINE__ , ## __VA_ARGS__); \ } while (0)#define dbg(fmt, ...) do { if (debug) \ syslog(LOG_KERN | LOG_DEBUG, "%s: %s(%d): " fmt "\n", \ PROG_NAME, __FUNCTION__, __LINE__ , ## __VA_ARGS__); \ } while (0)/* load .sys or .bin file */static int load_file(char *filename, struct load_driver_file *driver_file){ int fd; size_t size; void * image = NULL; struct stat statbuf; char *file_basename = basename(filename); fd = open(filename, O_RDONLY); if (fd == -1) { error("unable to open file: %s", strerror(errno)); return -EINVAL; } if (fstat(fd, &statbuf)) { error("incorrect driver file '%s'", filename); close(fd); return -EINVAL; } size = statbuf.st_size; image = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0); if (image == MAP_FAILED) { error("unable to mmap driver: %s", strerror(errno)); close(fd); return -EINVAL; } strncpy(driver_file->name, file_basename, sizeof(driver_file->name)); driver_file->name[sizeof(driver_file->name)-1] = 0; driver_file->size = size; driver_file->data = image; return 0;}/* split setting into name and value pair */static int parse_setting_line(const char *setting_line, char *setting_name, char *setting_val){ const char *s; char *val, *end; int i; // We try to be really paranoid parsing settings for (s = setting_line; isspace(*s); s++) ; // ignore comments and blank lines if (*s == '#' || *s == ';' || *s == '\0') return 0; if ((val = strchr(s, '|')) == NULL || (end = strchr(s, '\n')) == NULL) { error("invalid setting: %s", setting_line); return -EINVAL; } for (i = 0; s != val && i < MAX_NDIS_SETTING_NAME_LEN; s++, i++) setting_name[i] = *s; setting_name[i] = 0; if (*s != '|') { error("invalid setting: %s", setting_line); return -EINVAL; } for (i = 0, s++; s != end && i < MAX_NDIS_SETTING_VALUE_LEN ; s++, i++) setting_val[i] = *s; setting_val[i] = 0; if (*s != '\n') { error("invalid setting: %s", setting_line); return -EINVAL; } dbg("Found setting: name=%s, val=\"%s\"", setting_name, setting_val); // setting_val can be empty, but not name if (strlen(setting_name) == 0) { error("invalid setting: \"%s\"", setting_line); return -EINVAL; } return 1;}/* read .conf file and store info in driver */static int read_conf_file(char *conf_file_name, struct load_driver *driver){ char setting_line[SETTING_LEN]; struct stat statbuf; FILE *config; char setting_name[MAX_NDIS_SETTING_NAME_LEN]; char setting_value[MAX_NDIS_SETTING_VALUE_LEN]; int ret, nr_settings; int i, vendor, device, subvendor, subdevice, dev_bustype, conf_bustype; if (lstat(conf_file_name, &statbuf)) { error("unable to open config file: %s", strerror(errno)); return -EINVAL; } if (strlen(conf_file_name) == 16) { i = sscanf(conf_file_name, "%04X:%04X.%d.conf", &vendor, &device, &dev_bustype); if (i != 3) { error("unable to parse conf file name %s (%d)", conf_file_name, i); return -EINVAL; } } else { i = sscanf(conf_file_name, "%04X:%04X:%04X:%04X.%d.conf", &vendor, &device, &subvendor, &subdevice, &dev_bustype); if (i != 5) { error("unable to parse conf file name %s (%d)", conf_file_name, i); return -EINVAL; } } nr_settings = 0; driver->nr_settings = 0; if ((config = fopen(conf_file_name, "r")) == NULL) { error("unable to open config file: %s", strerror(errno)); return -EINVAL; } while (fgets(setting_line, SETTING_LEN-1, config)) { struct load_device_setting *setting; setting_line[SETTING_LEN-1] = 0; ret = parse_setting_line(setting_line, setting_name, setting_value); if (ret == 0) continue; if (ret < 0) return -EINVAL; if (strcmp(setting_name, "BusType") == 0) { conf_bustype = strtol(setting_value, NULL, 10); if (dev_bustype != conf_bustype) { error("invalid bustype: %d(%d)", dev_bustype, conf_bustype); return -EINVAL; } } setting = &driver->settings[nr_settings]; strncpy(setting->name, setting_name, MAX_NDIS_SETTING_NAME_LEN); strncpy(setting->value, setting_value, MAX_NDIS_SETTING_VALUE_LEN); nr_settings++; if (nr_settings >= MAX_NDIS_SETTINGS) { error("too many settings"); return -EINVAL; } } fclose(config); if (conf_bustype == -1) { error("coudn't find device type in settings"); return -EINVAL; } driver->nr_settings = nr_settings; return 0;}/* * open a windows driver and pass it to the kernel module. * returns 0: on success, -1 on error */static int load_driver(int ioctl_device, char *driver_name, char *conf_file_name){ int i; struct dirent *dirent; struct load_driver *driver; int nr_sys_files, nr_bin_files; DIR *driver_dir; driver_dir = NULL; nr_sys_files = 0; nr_bin_files = 0; dbg("loading driver %s", driver_name); if (chdir(confdir) || chdir(driver_name)) { error("couldn't change to directory %s: %s", driver_name, strerror(errno)); return -EINVAL; } if ((driver_dir = opendir(".")) == NULL) { error("couldn't open driver directory %s: %s", driver_name, strerror(errno)); return -EINVAL; } if ((driver = malloc(sizeof(*driver))) == NULL) { error("couldn't allocate memory for driver %s", driver_name); goto err; } memset(driver, 0, sizeof(*driver)); strncpy(driver->name, driver_name, MAX_DRIVER_NAME_LEN); if (read_conf_file(conf_file_name, driver) || driver->nr_settings == 0) { error("couldn't read conf file %s for driver %s", conf_file_name, driver_name); goto err; } while ((dirent = readdir(driver_dir))) { int len; struct stat statbuf; if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) continue; if (stat(dirent->d_name, &statbuf) || !S_ISREG(statbuf.st_mode)) { error("%s in %s is not a valid file: %s", dirent->d_name, driver_name, strerror(errno)); continue; } len = strlen(dirent->d_name); if (len > 4 && strcmp(&dirent->d_name[len-4], ".inf") == 0) continue; if (len > 5 && strcmp(&dirent->d_name[len-5], ".conf") == 0) continue; if (len > 4 && strcmp(&dirent->d_name[len-4], ".sys") == 0) { if (load_file(dirent->d_name, &driver->sys_files[nr_sys_files])) { error("couldn't load .sys file %s", dirent->d_name); goto err; } else nr_sys_files++; } else if (len > 4 && strcmp(&dirent->d_name[len-4], ".bin") == 0) { if (load_file(dirent->d_name, &driver->bin_files[nr_bin_files])) { error("coudln't load .bin file %s", dirent->d_name); goto err; } else nr_bin_files++; } else error("file %s is ignored", dirent->d_name); if (nr_sys_files == MAX_PE_IMAGES) { error("too many .sys files for driver %s", driver_name); goto err; } if (nr_bin_files == MAX_NDIS_BIN_FILES) { error("too many .bin files for driver %s", driver_name); goto err; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -