📄 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/major.h>#include <linux/ioctl.h>#include "loader.h"#define PROG_NAME "loadndisdriver"#define SETTING_LEN (MAX_SETTING_NAME_LEN + MAX_SETTING_VALUE_LEN + 2)static const char confdir[] = "/etc/ndiswrapper";static const char ioctl_file[] = "/dev/ndiswrapper";static int debug;#ifndef UTILS_VERSION#error compile this file with 'make' in the 'utils' \ directory only#endif#define LOG_MSG(where, fmt, ...) \ syslog(LOG_KERN | where, "%s: %s(%d): " fmt "\n", \ PROG_NAME, __FUNCTION__, __LINE__ , ## __VA_ARGS__)#define ERROR(fmt, ...) LOG_MSG(LOG_INFO, fmt, ## __VA_ARGS__)#define INFO(fmt, ...) LOG_MSG(LOG_INFO, fmt, ## __VA_ARGS__)#define DBG(fmt, ...) do { \ if (debug > 0) \ LOG_MSG(LOG_INFO, fmt, ## __VA_ARGS__); \ } while (0)#define WARN(fmt, ...) LOG_MSG(LOG_INFO, fmt, ## __VA_ARGS__)/* 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_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_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_SETTING_NAME_LEN]; char setting_value[MAX_SETTING_VALUE_LEN]; int ret, nr_settings; int i, vendor, device, subvendor, subdevice, bus; if (lstat(conf_file_name, &statbuf)) { ERROR("unable to open config file %s: %s", conf_file_name, strerror(errno)); return -EINVAL; } if (sscanf(conf_file_name, "%04X:%04X.%X.conf", &vendor, &device, &bus) == 3) { DBG("bus: %X", bus); } else if (sscanf(conf_file_name, "%04X:%04X:%04X:%04X.%X.conf", &vendor, &device, &subvendor, &subdevice, &bus) == 5) { DBG("bus: %X", bus); } else { 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; setting = &driver->settings[nr_settings]; strncpy(setting->name, setting_name, MAX_SETTING_NAME_LEN); strncpy(setting->value, setting_value, MAX_SETTING_VALUE_LEN); nr_settings++; if (nr_settings >= MAX_DEVICE_SETTINGS) { ERROR("too many settings"); return -EINVAL; } } fclose(config); driver->nr_settings = nr_settings; return 0;}static int load_bin_file(int ioctl_device, char *driver_name, char *file_name){ struct load_driver_file driver_file; char lc_file_name[MAX_DRIVER_NAME_LEN]; int i; DBG("loading driver %s", driver_name); for (i = 0; file_name[i] && i < sizeof(lc_file_name); i++) lc_file_name[i] = tolower(file_name[i]); lc_file_name[i] = 0; if (chdir(confdir) || chdir(driver_name)) { ERROR("couldn't change to directory %s: %s", driver_name, strerror(errno)); return -EINVAL; } if (load_file(lc_file_name, &driver_file)) { ERROR("couldn't open file %s", file_name); return -EINVAL; } strncpy(driver_file.driver_name, driver_name, sizeof(driver_file.driver_name)); if (ioctl(ioctl_device, WRAP_IOCTL_LOAD_BIN_FILE, &driver_file)) { ERROR("couldn't upload bin file: %s", file_name); return -EINVAL; } 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 (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 && strcasecmp(&dirent->d_name[len-4], ".inf") == 0) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -