~ubuntu-branches/ubuntu/lucid/ndiswrapper/lucid

« back to all changes in this revision

Viewing changes to utils/loadndisdriver.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Salomon
  • Date: 2005-01-09 19:40:16 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050109194016-q0wfc6kf43uog0bb
Tags: 0.12+1.0rc2-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2003 Pontus Fuchs
 
2
 *  Copyright (C) 2003-2004 Pontus Fuchs, Giridhar Pemmasani
3
3
 *
4
4
 *  This program is free software; you can redistribute it and/or modify
5
5
 *  it under the terms of the GNU General Public License as published by
31
31
#include <syslog.h>
32
32
#include <stdlib.h>
33
33
 
34
 
#include "../driver/wrapper.h"
35
 
 
36
 
#define SETTING_LEN 1024
37
 
#define NAME_LEN 200
38
 
#define TYPE_LEN 200
39
 
#define VAL_LEN 200
40
 
 
41
 
void read_conf(FILE *input);
 
34
#include <linux/ioctl.h>
 
35
 
 
36
#include "../driver/loader.h"
 
37
 
 
38
#define PROG_NAME "loadndisdriver"
 
39
 
 
40
#define SETTING_LEN (MAX_NDIS_SETTING_NAME_LEN+MAX_NDIS_SETTING_VALUE_LEN + 2)
42
41
 
43
42
static const char *confdir = "/etc/ndiswrapper";
44
 
 
 
43
static const char *ioctl_file = "/dev/ndiswrapper";
45
44
static int debug;
46
45
 
47
46
#ifndef NDISWRAPPER_VERSION
49
48
        directory only
50
49
#endif
51
50
 
52
 
#define error(fmt, args...) do { if (debug)     \
53
 
                        syslog(LOG_KERN | LOG_ERR, "%s(%d): " fmt "\n", \
54
 
                               __FUNCTION__, __LINE__, ## args);        \
55
 
        } while (0)
56
 
#define info(fmt, args...) do { if (debug)      \
57
 
                        syslog(LOG_KERN | LOG_ERR, "%s(%d): " fmt "\n", \
58
 
                               __FUNCTION__, __LINE__, ## args);        \
59
 
        } while (0)
60
 
 
61
 
 
62
 
static int get_filesize(int fd)
63
 
{
64
 
        struct stat statbuf;
65
 
        if(!fstat(fd, &statbuf))
66
 
        {
67
 
                return statbuf.st_size;
68
 
        }
69
 
        return -1;
70
 
}
71
 
 
72
 
/*
73
 
 * Taint the kernel
74
 
 */
75
 
static int dotaint(void)
76
 
{
77
 
        FILE *f = fopen("/proc/sys/kernel/tainted", "w");
78
 
        if(!f)
79
 
                return -1;
80
 
        fputs("1\n", f);
81
 
        fclose(f);
82
 
        return 0;
83
 
}
84
 
 
85
 
static int put_file(int device, char *filename, int ioctl_nr)
86
 
{
87
 
        int fd, size;
88
 
        struct put_file put_file;
 
51
#define error(fmt, ...) do {                                    \
 
52
                syslog(LOG_KERN | LOG_ERR, "%s: %s(%d): " fmt "\n",     \
 
53
                       PROG_NAME, __FUNCTION__, __LINE__ , ## __VA_ARGS__); \
 
54
        } while (0)
 
55
#define info(fmt, ...) do {                                             \
 
56
                syslog(LOG_KERN | LOG_INFO, "%s: %s(%d): " fmt "\n",    \
 
57
                       PROG_NAME, __FUNCTION__, __LINE__ , ## __VA_ARGS__); \
 
58
        } while (0)
 
59
 
 
60
#define dbg(fmt, ...) do { if (debug)                                   \
 
61
                syslog(LOG_KERN | LOG_DEBUG, "%s: %s(%d): " fmt "\n", \
 
62
                       PROG_NAME, __FUNCTION__, __LINE__ , ## __VA_ARGS__); \
 
63
        } while (0)
 
64
 
 
65
/* read system file (either .sys or .bin) */
 
66
static int read_file(char *filename, struct load_driver_file *driver_file)
 
67
{
 
68
        int fd;
 
69
        size_t size;
89
70
        void * image = NULL;
 
71
        struct stat statbuf;
90
72
 
91
 
        char *file_basename = basename(strdup(filename));
 
73
        char *file_basename = basename(filename);
92
74
 
93
75
        fd = open(filename, O_RDONLY);
94
 
        if(fd == -1)
95
 
        {
96
 
                perror("Unable to open file");
97
 
                return -EINVAL;
98
 
        }
99
 
        size = get_filesize(fd);
100
 
        image = mmap(0, size, PROT_READ, MAP_PRIVATE,
101
 
                     fd, 0);
102
 
        if((int)image == -1)
103
 
        {
104
 
                perror("Unable to mmap driver");
105
 
                close(fd);
106
 
                return -EINVAL;
107
 
        }
108
 
 
109
 
        strncpy(put_file.name, file_basename, sizeof(put_file.name));
110
 
        put_file.name[sizeof(put_file.name)-1] = 0;
111
 
        put_file.size = size;
112
 
        if (!image)
113
 
        {
114
 
                error("Unable to locate file %s", filename);
115
 
                return -EINVAL;
116
 
        }
117
 
 
118
 
        put_file.data = image;
119
 
        if (ioctl(device, ioctl_nr, &put_file))
120
 
        {
121
 
                perror("Unable to put file (check dmesg for more info)");
122
 
                return -EINVAL;
123
 
        }
124
 
        return 0;
125
 
}
126
 
 
127
 
 
128
 
static int confname_to_put_device(const char *name_orig,
129
 
                                  struct put_device *put_device)
130
 
{
131
 
        char *s;
132
 
        char *name = strdup(name_orig);
133
 
 
134
 
        s = basename(name);
135
 
        s[strlen(s)-5] = 0;
136
 
 
137
 
        if(strlen(s) == 9)
138
 
        {
139
 
                sscanf(s, "%04x:%04x", &put_device->vendor,
140
 
                       &put_device->device);
141
 
                put_device->pci_subdevice = -1;
142
 
                put_device->pci_subvendor = -1;
143
 
        }
144
 
        else if(strlen(s) == 19)
145
 
        {
146
 
                sscanf(s, "%04x:%04x:%04x:%04x", &put_device->vendor,
147
 
                       &put_device->device, &put_device->pci_subvendor,
148
 
                       &put_device->pci_subdevice);
149
 
        }
150
 
 
151
 
        free(name);
152
 
        return 0;
153
 
}
154
 
 
155
 
 
 
76
        if (fd == -1) {
 
77
                error("unable to open file: %s", strerror(errno));
 
78
                return -EINVAL;
 
79
        }
 
80
 
 
81
        if (fstat(fd, &statbuf)) {
 
82
                error("incorrect driver file '%s'", filename);
 
83
                close(fd);
 
84
                return -EINVAL;
 
85
        }
 
86
        size = statbuf.st_size;
 
87
 
 
88
        image = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
 
89
        if (image == MAP_FAILED) {
 
90
                error("unable to mmap driver: %s", strerror(errno));
 
91
                close(fd);
 
92
                return -EINVAL;
 
93
        }
 
94
 
 
95
        strncpy(driver_file->name, file_basename, sizeof(driver_file->name));
 
96
        driver_file->name[sizeof(driver_file->name)-1] = 0;
 
97
        driver_file->size = size;
 
98
        driver_file->data = image;
 
99
        return 0;
 
100
}
 
101
 
 
102
/* split setting into name and value pair */
156
103
static int parse_setting_line(const char *setting_line, char *setting_name,
157
104
                              char *setting_val)
158
105
{
168
115
        if (*s == '#' || *s == ';' || *s == '\0')
169
116
                return 0;
170
117
        if ((val = strchr(s, '|')) == NULL ||
171
 
             (end = strchr(s, '\n')) == NULL)
172
 
        {
 
118
            (end = strchr(s, '\n')) == NULL) {
173
119
                error("invalid setting: %s", setting_line);
174
120
                return -EINVAL;
175
121
        }
176
 
        for (i = 0; s != val && i < NAME_LEN; s++, i++)
 
122
        for (i = 0; s != val && i < MAX_NDIS_SETTING_NAME_LEN; s++, i++)
177
123
                setting_name[i] = *s;
178
124
        setting_name[i] = 0;
179
 
        if (*s != '|')
180
 
        {
 
125
        if (*s != '|') {
181
126
                error("invalid setting: %s", setting_line);
182
127
                return -EINVAL;
183
128
        }
184
129
 
185
 
        for (i = 0, s++; s != end && i < VAL_LEN ; s++, i++)
 
130
        for (i = 0, s++; s != end && i < MAX_NDIS_SETTING_VALUE_LEN ; s++, i++)
186
131
                setting_val[i] = *s;
187
132
        setting_val[i] = 0;
188
 
        if (*s != '\n')
189
 
        {
 
133
        if (*s != '\n') {
190
134
                error("invalid setting: %s", setting_line);
191
135
                return -EINVAL;
192
136
        }
193
 
//      info("Found setting: name=%s, val=\"%s\"\n",
194
 
//             setting_name, setting_val);
 
137
        dbg("Found setting: name=%s, val=\"%s\"", setting_name, setting_val);
195
138
 
196
 
        // setting_val can be empty, but not value
197
 
        if (strlen(setting_name) == 0)
198
 
        {
 
139
        // setting_val can be empty, but not name
 
140
        if (strlen(setting_name) == 0) {
199
141
                error("invalid setting: \"%s\"", setting_line);
200
142
                return -EINVAL;
201
143
        }
203
145
        return 1;
204
146
}
205
147
 
206
 
 
207
 
static int put_device(int device, char *conf_file_name)
 
148
/* read .conf file and store info in device */
 
149
static int read_conf_file(char *conf_file_name, struct load_device *device)
208
150
{
209
 
 
210
 
        struct put_device put_device;
211
151
        char setting_line[SETTING_LEN];
212
152
        struct stat statbuf;
213
153
        FILE *config;
214
 
        char setting_name[NAME_LEN], setting_val[VAL_LEN];
215
 
        int ret;
216
 
 
217
 
        if(lstat(conf_file_name, &statbuf))
218
 
        {
219
 
                perror("unable to open config file");
220
 
                return -EINVAL;
221
 
        }
222
 
 
223
 
        put_device.fuzzy = 0;
224
 
        if(S_ISLNK(statbuf.st_mode))
225
 
                put_device.fuzzy = 1;
226
 
 
227
 
        if ((config = fopen(conf_file_name, "r")) == NULL)
228
 
        {
229
 
                perror("unable to open config file");
230
 
                return -EINVAL;
231
 
        }
232
 
 
233
 
        confname_to_put_device(conf_file_name, &put_device);
234
 
 
235
 
        put_device.bustype = -1;
236
 
        while (fgets(setting_line, SETTING_LEN-1, config))
237
 
        {
238
 
                setting_line[SETTING_LEN-1] = 0;
239
 
                ret = parse_setting_line(setting_line, setting_name,
240
 
                                         setting_val);
241
 
                if (ret == 0)
242
 
                        continue;
243
 
                if (ret < 0)
244
 
                        return -EINVAL;
245
 
 
246
 
                if (strcmp(setting_name, "BusType") == 0)
247
 
                {
248
 
                        put_device.bustype = strtol(setting_val, NULL, 10);
249
 
                        if (put_device.bustype != 0 &&
250
 
                            put_device.bustype != 5)
251
 
                        {
252
 
                                perror("invalid bustype");
253
 
                                return -EINVAL;
254
 
                        }
255
 
                        if (ioctl(device, NDIS_PUTDEVICE, &put_device))
256
 
                        {
257
 
                                perror("Unable to put device "
258
 
                                       "(check dmesg for more info)");
259
 
                                return -EINVAL;
260
 
                        }
261
 
                        rewind(config);
262
 
                        break;
263
 
                }
264
 
        }
265
 
 
266
 
        if (put_device.bustype == -1)
267
 
                return -EINVAL;
268
 
 
269
 
        while (fgets(setting_line, SETTING_LEN-1, config))
270
 
        {
271
 
                struct put_setting setting;
272
 
 
273
 
                setting_line[SETTING_LEN-1] = 0;
274
 
                ret = parse_setting_line(setting_line, setting_name,
275
 
                                         setting_val);
276
 
                if (ret == 0)
277
 
                        continue;
278
 
                if (ret < 0)
279
 
                        return -EINVAL;
280
 
 
281
 
                setting.name_len = strlen(setting_name);
282
 
                setting.val_str_len = strlen(setting_val);
283
 
                setting.name = setting_name;
284
 
                setting.value = setting_val;
285
 
 
286
 
                if (ioctl(device, NDIS_PUTSETTING, &setting))
287
 
                {
288
 
                        error("Error adding setting: %s", setting_name);
289
 
                        return -EINVAL;
290
 
                }
291
 
        }
 
154
        char setting_name[MAX_NDIS_SETTING_NAME_LEN];
 
155
        char setting_value[MAX_NDIS_SETTING_VALUE_LEN];
 
156
        int ret, nr_settings;
 
157
        char *file_name, *s;
 
158
 
 
159
        if (lstat(conf_file_name, &statbuf)) {
 
160
                error("unable to open config file: %s", strerror(errno));
 
161
                goto err;
 
162
        }
 
163
 
 
164
        if (S_ISLNK(statbuf.st_mode))
 
165
                device->fuzzy = 1;
 
166
        else
 
167
                device->fuzzy = 0;
 
168
 
 
169
        if ((config = fopen(conf_file_name, "r")) == NULL) {
 
170
                error("unable to open config file: %s", strerror(errno));
 
171
                goto err;
 
172
        }
 
173
 
 
174
        file_name = strdup(conf_file_name);
 
175
        s = basename(file_name);
 
176
        /* remove ".conf" */
 
177
        s[strlen(s)-5] = 0;
 
178
 
 
179
        if (strlen(s) == 9) {
 
180
                sscanf(s, "%04x:%04x", &device->vendor, &device->device);
 
181
                device->pci_subdevice = -1;
 
182
                device->pci_subvendor = -1;
 
183
        } else if (strlen(s) == 19) {
 
184
                sscanf(s, "%04x:%04x:%04x:%04x", &device->vendor,
 
185
                       &device->device, &device->pci_subvendor,
 
186
                       &device->pci_subdevice);
 
187
        } else
 
188
                goto err;
 
189
 
 
190
        free(file_name);
 
191
 
 
192
        device->bustype = -1;
 
193
        nr_settings = 0;
 
194
 
 
195
        while (fgets(setting_line, SETTING_LEN-1, config)) {
 
196
                struct load_device_setting *setting;
 
197
 
 
198
                setting_line[SETTING_LEN-1] = 0;
 
199
                ret = parse_setting_line(setting_line, setting_name,
 
200
                                         setting_value);
 
201
                if (ret == 0)
 
202
                        continue;
 
203
                if (ret < 0)
 
204
                        goto err;
 
205
 
 
206
                if (strcmp(setting_name, "BusType") == 0) {
 
207
                        device->bustype = strtol(setting_value, NULL, 10);
 
208
                        if (device->bustype != NDIS_PCI_BUS &&
 
209
                            device->bustype != NDIS_USB_BUS) {
 
210
                                error("invalid bustype: %d", device->bustype);
 
211
                                goto err;
 
212
                        }
 
213
                } 
 
214
                setting = &device->settings[nr_settings];
 
215
                strncpy(setting->name, setting_name,
 
216
                        MAX_NDIS_SETTING_NAME_LEN);
 
217
                strncpy(setting->value, setting_value,
 
218
                        MAX_NDIS_SETTING_VALUE_LEN);
 
219
 
 
220
                nr_settings++;
 
221
                if (nr_settings >= MAX_NDIS_SETTINGS) {
 
222
                        error("too many settings");
 
223
                        goto err;
 
224
                }
 
225
        }
 
226
 
292
227
        fclose(config);
293
228
 
 
229
        if (device->bustype == -1) {
 
230
                error("coudn't find device type in settings");
 
231
                goto err;
 
232
        }
 
233
 
 
234
        device->nr_settings = nr_settings;
294
235
        return 0;
 
236
err:
 
237
        device->nr_settings = 0;
 
238
        return -EINVAL;
295
239
}
296
240
 
297
241
/*
298
 
 * Open a windows driver and pass it to the kernel module.
 
242
 * open a windows driver and pass it to the kernel module.
 
243
 * returns 0: on success, -1 on error
299
244
 */
300
 
static int load(int device, char *confdir)
 
245
static int load_driver(int ioctl_device, DIR *dir, char *driver_name)
301
246
{
302
 
        int err;
 
247
        int i;
303
248
        struct dirent *dirent;
304
 
        DIR *dir;
305
 
 
306
 
        if(chdir(confdir))
307
 
        {
308
 
                error("Unable to open config dir %s", confdir);
309
 
                return -1;
310
 
        }
311
 
 
312
 
        dir = opendir(".");
313
 
        if(!dir)
314
 
        {
315
 
                error("Unable to open config dir %s", confdir);
316
 
                chdir("..");
317
 
                return -1;
318
 
        }
319
 
 
320
 
        /* Locate the .sys first */
321
 
        while((dirent = readdir(dir)))
322
 
        {
323
 
                int len;
324
 
                len = strlen(dirent->d_name);
325
 
                if(len > 4 && strcmp(&dirent->d_name[len-4], ".sys") == 0)
326
 
                {
327
 
                        if((err = put_file(device, dirent->d_name,
328
 
                                           NDIS_PUTDRIVER)) != 0)
329
 
                        {
330
 
                                chdir("..");
331
 
                                return err;
332
 
                        }
333
 
                        break;
334
 
                }
335
 
        }
336
 
        rewinddir(dir);
337
 
 
338
 
        /* Now add all .conf and other files */
339
 
        while((dirent = readdir(dir)))
340
 
        {
341
 
                int len;
342
 
                len = strlen(dirent->d_name);
343
 
                if(len > 5 && strcmp(&dirent->d_name[len-5], ".conf") == 0)
344
 
                {
345
 
                        put_device(device, dirent->d_name);
346
 
                }
347
 
                else
348
 
                {
349
 
                        if(strcmp(dirent->d_name, ".") == 0)
350
 
                                continue;
351
 
                        if(strcmp(dirent->d_name, "..") == 0)
352
 
                                continue;
353
 
                        if(len > 4 && !strcmp(&dirent->d_name[len-4], ".sys"))
354
 
                                continue;
355
 
                        if(len > 4 && !strcmp(&dirent->d_name[len-4], ".inf"))
356
 
                                continue;
357
 
                        if(len > 4 && !strcmp(&dirent->d_name[len-4], ".dll"))
358
 
                                continue;
359
 
                        if(len > 4 && !strcmp(&dirent->d_name[len-4], ".exe"))
360
 
                                continue;
361
 
                        put_file(device, dirent->d_name, NDIS_PUTFILE);
362
 
                }
363
 
        }
364
 
        closedir(dir);
365
 
        if(ioctl(device, NDIS_STARTDRIVER, 0))
366
 
        {
367
 
                perror("Unable to start driver (check dmesg for more info)");
368
 
                chdir("..");
369
 
                return -1;
370
 
        }
371
 
        chdir("..");
 
249
        struct load_driver *driver;
 
250
        int nr_sys_files, nr_devices, nr_bin_files;
 
251
 
 
252
        if (!dir || !driver_name) {
 
253
                error("invalid driver");
 
254
                return -1;
 
255
        }
 
256
 
 
257
        if ((driver = malloc(sizeof(*driver))) == NULL) {
 
258
                error("couldn't allocate memory for driver %s", driver_name);
 
259
                return -1;
 
260
        }
 
261
        memset(driver, 0, sizeof(*driver));
 
262
        strncpy(driver->name, driver_name, MAX_DRIVER_NAME_LEN);
 
263
 
 
264
        nr_sys_files = 0;
 
265
        nr_devices = 0;
 
266
        nr_sys_files = 0;
 
267
        nr_bin_files = 0;
 
268
 
 
269
        dbg("loading driver %s", driver_name);
 
270
        while ((dirent = readdir(dir))) {
 
271
                int len;
 
272
 
 
273
                if (strcmp(dirent->d_name, ".") == 0 ||
 
274
                    strcmp(dirent->d_name, "..") == 0)
 
275
                        continue;
 
276
 
 
277
                len = strlen(dirent->d_name);
 
278
                if (len > 4 &&
 
279
                     strcmp(&dirent->d_name[len-4], ".inf") == 0)
 
280
                        continue;
 
281
 
 
282
                if (len > 4 && strcmp(&dirent->d_name[len-4], ".sys") == 0) {
 
283
                        if (read_file(dirent->d_name,
 
284
                                      &driver->sys_files[nr_sys_files])) {
 
285
                                error("couldn't load .sys file %s",
 
286
                                      dirent->d_name);
 
287
                                goto err;
 
288
                        } else
 
289
                                nr_sys_files++;
 
290
                } else if (len > 5 &&
 
291
                           strcmp(&dirent->d_name[len-5], ".conf") == 0) {
 
292
                        if (read_conf_file(dirent->d_name,
 
293
                                           &driver->devices[nr_devices])) {
 
294
                                error("couldn't load .conf file %s",
 
295
                                      dirent->d_name);
 
296
                                goto err;
 
297
                        } else
 
298
                                nr_devices++;
 
299
                } else if (len > 4 &&
 
300
                           strcmp(&dirent->d_name[len-4], ".bin") == 0) {
 
301
                        if (read_file(dirent->d_name,
 
302
                                      &driver->bin_files[nr_bin_files])) {
 
303
                                error("coudln't load .bin file %s",
 
304
                                      dirent->d_name);
 
305
                                goto err;
 
306
                        } else
 
307
                                nr_bin_files++;
 
308
                } else
 
309
                        error("file %s is ignored", dirent->d_name);
 
310
 
 
311
                if (nr_sys_files == MAX_PE_IMAGES) {
 
312
                        error("too many .sys files for driver %s",
 
313
                              driver_name);
 
314
                        goto err;
 
315
                }
 
316
                if (nr_devices == MAX_NDIS_DEVICES) {
 
317
                        error("too many .conf files for driver %s",
 
318
                              driver_name);
 
319
                        goto err;
 
320
                }
 
321
                if (nr_bin_files == MAX_NDIS_BIN_FILES) {
 
322
                        error("too many .bin files for driver %s",
 
323
                              driver_name);
 
324
                        goto err;
 
325
                }
 
326
        }
 
327
 
 
328
        if (nr_sys_files == 0 || nr_devices == 0) {
 
329
                error("coudln't find valid drivers files for driver %s",
 
330
                      driver_name);
 
331
                goto err;
 
332
        }
 
333
        driver->nr_sys_files = nr_sys_files;
 
334
        driver->nr_devices = nr_devices;
 
335
        driver->nr_bin_files = nr_bin_files;
 
336
 
 
337
        if (ioctl(ioctl_device, NDIS_ADD_DRIVER, driver))
 
338
                goto err;
 
339
 
 
340
        dbg("driver %s loaded", driver_name);
 
341
        free(driver);
372
342
        return 0;
 
343
 
 
344
err:
 
345
        for (i = 0; i < nr_sys_files; i++)
 
346
                free(driver->sys_files[i].data);
 
347
        for (i = 0; i < nr_bin_files; i++)
 
348
                free(driver->bin_files[i].data);
 
349
        error("couldn't load driver %s", driver_name);
 
350
        free(driver);
 
351
        return -1;
373
352
}
374
353
 
375
354
/*
376
 
 * Load all installed drivers
 
355
 * load all installed drivers
 
356
 * returns: number of drivers loadeed successfully
377
357
 */
378
 
static int loadall(int device)
 
358
static int load_all_drivers(int ioctl_device)
379
359
{
380
360
        struct stat statbuf;
381
361
        struct dirent  *dirent;
382
 
 
383
 
        DIR *dir = opendir(".");
384
 
 
385
 
        while((dirent = readdir(dir)))
386
 
        {
387
 
                if(strcmp(dirent->d_name, ".") == 0)
388
 
                        continue;
389
 
                if(strcmp(dirent->d_name, "..") == 0)
390
 
                        continue;
391
 
 
392
 
                if(stat(dirent->d_name, &statbuf))
393
 
                        continue;
394
 
 
395
 
                if(!S_ISDIR(statbuf.st_mode))
396
 
                        continue;
397
 
 
398
 
                load(device, dirent->d_name);
 
362
        DIR *dir, *driver;
 
363
        int loaded;
 
364
 
 
365
        if (chdir(confdir)) {
 
366
                error("directory %s is not valid: %s",
 
367
                      confdir, strerror(errno));
 
368
                return 0;
 
369
        }
 
370
        if ((dir = opendir(confdir)) == NULL) {
 
371
                error("directory %s is not valid: %s",
 
372
                      confdir, strerror(errno));
 
373
                return 0;
 
374
        }
 
375
 
 
376
        loaded = 0;
 
377
        while((dirent = readdir(dir))) {
 
378
                if (strcmp(dirent->d_name, ".") == 0 ||
 
379
                    strcmp(dirent->d_name, "..") == 0 ||
 
380
                    strcmp(dirent->d_name, "modules.ndiswrapper") == 0)
 
381
                        continue;
 
382
 
 
383
                if (stat(dirent->d_name, &statbuf) ||
 
384
                    (!S_ISDIR(statbuf.st_mode)) ||
 
385
                    ((driver = opendir(dirent->d_name)) == NULL)) {
 
386
                        error("directory %s is not valid: %s",
 
387
                              dirent->d_name, strerror(errno));
 
388
                        continue;
 
389
                }
 
390
                if (chdir(dirent->d_name)) {
 
391
                        error("directory %s is not valid: %s",
 
392
                              dirent->d_name, strerror(errno));
 
393
                        closedir(driver);
 
394
                        continue;
 
395
                }
 
396
                if (!load_driver(ioctl_device, driver, dirent->d_name))
 
397
                        loaded++;
 
398
                chdir("..");
 
399
                closedir(driver);
399
400
        }
400
401
        closedir(dir);
401
 
        return 0;
 
402
        return loaded;
402
403
}
403
404
 
404
 
 
405
405
/*
406
 
 * Open a misc device without having a /dev/ entry
407
 
 */
408
 
static int open_misc_device(int minor)
 
406
  * we need a device to use ioctl to communicate with ndiswrapper module
 
407
  * we create a device in /dev instead of /tmp as some distributions don't
 
408
  * allow creation of devices in /tmp
 
409
  */
 
410
static int get_ioctl_device()
409
411
{
410
 
        char tmp[] = {"/tmp/ndiswrapperXXXXXX"};
411
 
        int fd = mkstemp(tmp);
412
 
        unlink(tmp);
413
 
        close(fd);
414
 
        if(mknod(tmp, S_IFCHR | 0600, 10 << 8 | minor) == -1)
415
 
                return -1;
416
 
 
417
 
        fd = open(tmp, O_RDONLY);
418
 
        unlink(tmp);
419
 
        if(fd == -1)
420
 
                return -1;
 
412
        int fd, minor_dev;
 
413
        char line[64];
 
414
        FILE *proc_misc;
 
415
 
 
416
        /* get minor device number used by ndiswrapper driver */
 
417
        proc_misc = fopen("/proc/misc", "r");
 
418
        if (!proc_misc)
 
419
                return -1;
 
420
        minor_dev = -1;
 
421
        while (fgets(line, sizeof(line), proc_misc)) {
 
422
                if (strstr(line, "ndiswrapper")) {
 
423
                        long i = strtol(line, 0, 10);
 
424
                        if (i != LONG_MAX && i != LONG_MIN) {
 
425
                                minor_dev = i;
 
426
                                break;
 
427
                        }
 
428
                }
 
429
        }
 
430
        fclose(proc_misc);
 
431
 
 
432
        if (minor_dev == -1) {
 
433
                error("couldn't find ndiswrapper in /proc/misc; "
 
434
                      "is ndiswrapper module loaded?");
 
435
                return -1;
 
436
        }
 
437
 
 
438
        unlink(ioctl_file);
 
439
        if (mknod(ioctl_file, S_IFCHR | 0600, 10 << 8 | minor_dev) == -1) {
 
440
                error("couldn't create file %s: %s",
 
441
                      ioctl_file, strerror(errno));
 
442
                return -1;
 
443
        }
 
444
 
 
445
        fd = open(ioctl_file, O_RDONLY);
 
446
        unlink(ioctl_file);
 
447
 
 
448
        if (fd == -1) {
 
449
                error("couldn't open file %s: %s",
 
450
                      ioctl_file, strerror(errno));
 
451
                return -1;
 
452
        }
421
453
        return fd;
422
454
}
423
455
 
424
 
/*
425
 
 * Parse /proc/misc to get the minor of out kernel driver
426
 
 */
427
 
static int get_misc_minor()
428
 
{
429
 
        char line[200];
430
 
        FILE *misc = fopen("/proc/misc", "r");
431
 
        int minor = -1;
432
 
 
433
 
        if(!misc)
434
 
                return -1;
435
 
        while(fgets(line, sizeof(line), misc))
436
 
        {
437
 
                if(strstr(line, "ndiswrapper"))
438
 
                {
439
 
                        int i = strtol(line, 0, 10);
440
 
                        if(i != LONG_MAX && i != LONG_MIN)
441
 
                        {
442
 
                                minor = i;
443
 
                                break;
444
 
                        }
445
 
                }
446
 
        }
447
 
        fclose(misc);
448
 
        return minor;
449
 
}
450
 
 
451
 
 
452
456
int main(int argc, char *argv[0])
453
457
{
454
 
        int i, device, misc_minor, res;
455
 
 
456
 
        device = -1;
457
 
        debug = 1;
458
 
 
459
 
        openlog("loadndisdriver", LOG_PERROR | LOG_CONS, LOG_KERN);
460
 
 
461
 
        if (argc < 3)
462
 
        {
 
458
        int i, ioctl_device, res;
 
459
 
 
460
        openlog(PROG_NAME, LOG_PERROR | LOG_CONS, LOG_KERN | LOG_DEBUG);
 
461
 
 
462
        info("version %s started", NDISWRAPPER_VERSION);
 
463
 
 
464
        if (argc != 4) {
463
465
                error("Usage: %s <debug> <version> [-a] [driver]", argv[0]);
464
 
                res = -EINVAL;
 
466
                res = 1;
465
467
                goto out;
466
468
        }
467
469
 
468
470
        i = -1;
469
471
        i = atoi(argv[1]);
470
 
        if (i < 0)
471
 
        {
 
472
        if (i < 0) {
472
473
                error("invalid debug value %d", i);
473
 
                res = -EINVAL;
 
474
                res = 2;
474
475
                goto out;
475
 
        }
476
 
        else
 
476
        } else
477
477
                debug = i;
478
478
 
479
 
        if ((res = chdir(confdir)))
480
 
        {
481
 
                error("%s does not exist", confdir);
482
 
                goto out;
483
 
        }
484
 
 
485
 
        misc_minor = get_misc_minor();
486
 
        if (misc_minor == -1)
487
 
        {
488
 
                error("%s: cannot find minor for kernel module."
489
 
                       "Module loaded?", argv[0]);
490
 
                res = -EINVAL;
491
 
                goto out;
492
 
        }
493
 
 
494
 
        device = open_misc_device(misc_minor);
495
 
        if (device == -1)
496
 
        {
497
 
                error("Unable to open kernel driver (%d)", errno);
498
 
                res = -EINVAL;
499
 
                goto out;
500
 
        }
501
 
 
502
 
        dotaint();
503
 
 
504
 
        if (strcmp(argv[2], NDISWRAPPER_VERSION))
505
 
        {
506
 
                res = -EINVAL;
507
 
                goto out;
508
 
        }
509
 
 
510
 
        if (strcmp(argv[3], "-a") == 0)
511
 
                res = loadall(device);
512
 
        else
513
 
                res = load(device, argv[3]);
514
 
 
515
 
        if (!res)
516
 
        {
517
 
                info("%s", "Drivers loaded successfully");
518
 
        }
519
 
 
 
479
        ioctl_device = get_ioctl_device();
 
480
        if (ioctl_device == -1) {
 
481
                error("unable to open ioctl device %s", ioctl_file);
 
482
                res = 5;
 
483
                goto out;
 
484
        }
 
485
 
 
486
        if (strcmp(argv[2], NDISWRAPPER_VERSION)) {
 
487
                error("version %s doesn't match driver version %s",
 
488
                      NDISWRAPPER_VERSION, argv[2]);
 
489
                res = 6;
 
490
                goto out;
 
491
        }
 
492
 
 
493
        if (strcmp(argv[3], "-a") == 0) {
 
494
                if (load_all_drivers(ioctl_device) > 0)
 
495
                        res = 0;
 
496
                else {
 
497
                        error("no useable drivers found, aborting");
 
498
                        res = 7;
 
499
                }
 
500
        } else {
 
501
                DIR *driver_dir;
 
502
                if (chdir(confdir)) {
 
503
                        error("directory %s is not valid: %s",
 
504
                              confdir, strerror(errno));
 
505
                        res = 8;
 
506
                        goto out;
 
507
                }
 
508
                if ((driver_dir = opendir(argv[3])) == NULL) {
 
509
                        error("couldn't open driver directory %s: %s",
 
510
                              argv[3], strerror(errno));
 
511
                        res = 9;
 
512
                        goto out;
 
513
                } else {
 
514
                        if (chdir(argv[3])) {
 
515
                                error("directory %s is not valid: %s",
 
516
                                      argv[3], strerror(errno));
 
517
                                res = 10;
 
518
                                goto out;
 
519
                        }
 
520
                        res = load_driver(ioctl_device, driver_dir,
 
521
                                          argv[3]);
 
522
                        closedir(driver_dir);
 
523
                }
 
524
        }
520
525
out:
521
 
        if (device != -1)
522
 
                close(device);
 
526
        if (ioctl_device != -1)
 
527
                close(ioctl_device);
523
528
        closelog();
524
529
        return res;
525
530
}