~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to net/tap-win32.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  TAP-Win32 -- A kernel driver to provide virtual tap device functionality
 
3
 *               on Windows.  Originally derived from the CIPE-Win32
 
4
 *               project by Damion K. Wilson, with extensive modifications by
 
5
 *               James Yonan.
 
6
 *
 
7
 *  All source code which derives from the CIPE-Win32 project is
 
8
 *  Copyright (C) Damion K. Wilson, 2003, and is released under the
 
9
 *  GPL version 2 (see below).
 
10
 *
 
11
 *  All other source code is Copyright (C) James Yonan, 2003-2004,
 
12
 *  and is released under the GPL version 2 (see below).
 
13
 *
 
14
 *  This program is free software; you can redistribute it and/or modify
 
15
 *  it under the terms of the GNU General Public License as published by
 
16
 *  the Free Software Foundation; either version 2 of the License, or
 
17
 *  (at your option) any later version.
 
18
 *
 
19
 *  This program is distributed in the hope that it will be useful,
 
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
 *  GNU General Public License for more details.
 
23
 *
 
24
 *  You should have received a copy of the GNU General Public License
 
25
 *  along with this program (see the file COPYING included with this
 
26
 *  distribution); if not, see <http://www.gnu.org/licenses/>.
 
27
 */
 
28
 
 
29
#include "net/tap.h"
 
30
 
 
31
#include "qemu-common.h"
 
32
#include "net.h"
 
33
#include "sysemu.h"
 
34
#include "qemu-error.h"
 
35
#include <stdio.h>
 
36
#include <windows.h>
 
37
#include <winioctl.h>
 
38
 
 
39
//=============
 
40
// TAP IOCTLs
 
41
//=============
 
42
 
 
43
#define TAP_CONTROL_CODE(request,method) \
 
44
  CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
 
45
 
 
46
#define TAP_IOCTL_GET_MAC               TAP_CONTROL_CODE (1, METHOD_BUFFERED)
 
47
#define TAP_IOCTL_GET_VERSION           TAP_CONTROL_CODE (2, METHOD_BUFFERED)
 
48
#define TAP_IOCTL_GET_MTU               TAP_CONTROL_CODE (3, METHOD_BUFFERED)
 
49
#define TAP_IOCTL_GET_INFO              TAP_CONTROL_CODE (4, METHOD_BUFFERED)
 
50
#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
 
51
#define TAP_IOCTL_SET_MEDIA_STATUS      TAP_CONTROL_CODE (6, METHOD_BUFFERED)
 
52
#define TAP_IOCTL_CONFIG_DHCP_MASQ      TAP_CONTROL_CODE (7, METHOD_BUFFERED)
 
53
#define TAP_IOCTL_GET_LOG_LINE          TAP_CONTROL_CODE (8, METHOD_BUFFERED)
 
54
#define TAP_IOCTL_CONFIG_DHCP_SET_OPT   TAP_CONTROL_CODE (9, METHOD_BUFFERED)
 
55
 
 
56
//=================
 
57
// Registry keys
 
58
//=================
 
59
 
 
60
#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
 
61
 
 
62
#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
 
63
 
 
64
//======================
 
65
// Filesystem prefixes
 
66
//======================
 
67
 
 
68
#define USERMODEDEVICEDIR "\\\\.\\Global\\"
 
69
#define TAPSUFFIX         ".tap"
 
70
 
 
71
 
 
72
//======================
 
73
// Compile time configuration
 
74
//======================
 
75
 
 
76
//#define DEBUG_TAP_WIN32
 
77
 
 
78
#define TUN_ASYNCHRONOUS_WRITES 1
 
79
 
 
80
#define TUN_BUFFER_SIZE 1560
 
81
#define TUN_MAX_BUFFER_COUNT 32
 
82
 
 
83
/*
 
84
 * The data member "buffer" must be the first element in the tun_buffer
 
85
 * structure. See the function, tap_win32_free_buffer.
 
86
 */
 
87
typedef struct tun_buffer_s {
 
88
    unsigned char buffer [TUN_BUFFER_SIZE];
 
89
    unsigned long read_size;
 
90
    struct tun_buffer_s* next;
 
91
} tun_buffer_t;
 
92
 
 
93
typedef struct tap_win32_overlapped {
 
94
    HANDLE handle;
 
95
    HANDLE read_event;
 
96
    HANDLE write_event;
 
97
    HANDLE output_queue_semaphore;
 
98
    HANDLE free_list_semaphore;
 
99
    HANDLE tap_semaphore;
 
100
    CRITICAL_SECTION output_queue_cs;
 
101
    CRITICAL_SECTION free_list_cs;
 
102
    OVERLAPPED read_overlapped;
 
103
    OVERLAPPED write_overlapped;
 
104
    tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT];
 
105
    tun_buffer_t* free_list;
 
106
    tun_buffer_t* output_queue_front;
 
107
    tun_buffer_t* output_queue_back;
 
108
} tap_win32_overlapped_t;
 
109
 
 
110
static tap_win32_overlapped_t tap_overlapped;
 
111
 
 
112
static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped)
 
113
{
 
114
    tun_buffer_t* buffer = NULL;
 
115
    WaitForSingleObject(overlapped->free_list_semaphore, INFINITE);
 
116
    EnterCriticalSection(&overlapped->free_list_cs);
 
117
    buffer = overlapped->free_list;
 
118
//    assert(buffer != NULL);
 
119
    overlapped->free_list = buffer->next;
 
120
    LeaveCriticalSection(&overlapped->free_list_cs);
 
121
    buffer->next = NULL;
 
122
    return buffer;
 
123
}
 
124
 
 
125
static void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
 
126
{
 
127
    EnterCriticalSection(&overlapped->free_list_cs);
 
128
    buffer->next = overlapped->free_list;
 
129
    overlapped->free_list = buffer;
 
130
    LeaveCriticalSection(&overlapped->free_list_cs);
 
131
    ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL);
 
132
}
 
133
 
 
134
static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block)
 
135
{
 
136
    tun_buffer_t* buffer = NULL;
 
137
    DWORD result, timeout = block ? INFINITE : 0L;
 
138
 
 
139
    // Non-blocking call
 
140
    result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout);
 
141
 
 
142
    switch (result)
 
143
    {
 
144
        // The semaphore object was signaled.
 
145
        case WAIT_OBJECT_0:
 
146
            EnterCriticalSection(&overlapped->output_queue_cs);
 
147
 
 
148
            buffer = overlapped->output_queue_front;
 
149
            overlapped->output_queue_front = buffer->next;
 
150
 
 
151
            if(overlapped->output_queue_front == NULL) {
 
152
                overlapped->output_queue_back = NULL;
 
153
            }
 
154
 
 
155
            LeaveCriticalSection(&overlapped->output_queue_cs);
 
156
            break;
 
157
 
 
158
        // Semaphore was nonsignaled, so a time-out occurred.
 
159
        case WAIT_TIMEOUT:
 
160
            // Cannot open another window.
 
161
            break;
 
162
    }
 
163
 
 
164
    return buffer;
 
165
}
 
166
 
 
167
static tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped)
 
168
{
 
169
    return get_buffer_from_output_queue(overlapped, 0);
 
170
}
 
171
 
 
172
static void put_buffer_on_output_queue(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
 
173
{
 
174
    EnterCriticalSection(&overlapped->output_queue_cs);
 
175
 
 
176
    if(overlapped->output_queue_front == NULL && overlapped->output_queue_back == NULL) {
 
177
        overlapped->output_queue_front = overlapped->output_queue_back = buffer;
 
178
    } else {
 
179
        buffer->next = NULL;
 
180
        overlapped->output_queue_back->next = buffer;
 
181
        overlapped->output_queue_back = buffer;
 
182
    }
 
183
 
 
184
    LeaveCriticalSection(&overlapped->output_queue_cs);
 
185
 
 
186
    ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL);
 
187
}
 
188
 
 
189
 
 
190
static int is_tap_win32_dev(const char *guid)
 
191
{
 
192
    HKEY netcard_key;
 
193
    LONG status;
 
194
    DWORD len;
 
195
    int i = 0;
 
196
 
 
197
    status = RegOpenKeyEx(
 
198
        HKEY_LOCAL_MACHINE,
 
199
        ADAPTER_KEY,
 
200
        0,
 
201
        KEY_READ,
 
202
        &netcard_key);
 
203
 
 
204
    if (status != ERROR_SUCCESS) {
 
205
        return FALSE;
 
206
    }
 
207
 
 
208
    for (;;) {
 
209
        char enum_name[256];
 
210
        char unit_string[256];
 
211
        HKEY unit_key;
 
212
        char component_id_string[] = "ComponentId";
 
213
        char component_id[256];
 
214
        char net_cfg_instance_id_string[] = "NetCfgInstanceId";
 
215
        char net_cfg_instance_id[256];
 
216
        DWORD data_type;
 
217
 
 
218
        len = sizeof (enum_name);
 
219
        status = RegEnumKeyEx(
 
220
            netcard_key,
 
221
            i,
 
222
            enum_name,
 
223
            &len,
 
224
            NULL,
 
225
            NULL,
 
226
            NULL,
 
227
            NULL);
 
228
 
 
229
        if (status == ERROR_NO_MORE_ITEMS)
 
230
            break;
 
231
        else if (status != ERROR_SUCCESS) {
 
232
            return FALSE;
 
233
        }
 
234
 
 
235
        snprintf (unit_string, sizeof(unit_string), "%s\\%s",
 
236
                  ADAPTER_KEY, enum_name);
 
237
 
 
238
        status = RegOpenKeyEx(
 
239
            HKEY_LOCAL_MACHINE,
 
240
            unit_string,
 
241
            0,
 
242
            KEY_READ,
 
243
            &unit_key);
 
244
 
 
245
        if (status != ERROR_SUCCESS) {
 
246
            return FALSE;
 
247
        } else {
 
248
            len = sizeof (component_id);
 
249
            status = RegQueryValueEx(
 
250
                unit_key,
 
251
                component_id_string,
 
252
                NULL,
 
253
                &data_type,
 
254
                (LPBYTE)component_id,
 
255
                &len);
 
256
 
 
257
            if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {
 
258
                len = sizeof (net_cfg_instance_id);
 
259
                status = RegQueryValueEx(
 
260
                    unit_key,
 
261
                    net_cfg_instance_id_string,
 
262
                    NULL,
 
263
                    &data_type,
 
264
                    (LPBYTE)net_cfg_instance_id,
 
265
                    &len);
 
266
 
 
267
                if (status == ERROR_SUCCESS && data_type == REG_SZ) {
 
268
                    if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/
 
269
                        !strcmp (net_cfg_instance_id, guid)) {
 
270
                        RegCloseKey (unit_key);
 
271
                        RegCloseKey (netcard_key);
 
272
                        return TRUE;
 
273
                    }
 
274
                }
 
275
            }
 
276
            RegCloseKey (unit_key);
 
277
        }
 
278
        ++i;
 
279
    }
 
280
 
 
281
    RegCloseKey (netcard_key);
 
282
    return FALSE;
 
283
}
 
284
 
 
285
static int get_device_guid(
 
286
    char *name,
 
287
    int name_size,
 
288
    char *actual_name,
 
289
    int actual_name_size)
 
290
{
 
291
    LONG status;
 
292
    HKEY control_net_key;
 
293
    DWORD len;
 
294
    int i = 0;
 
295
    int stop = 0;
 
296
 
 
297
    status = RegOpenKeyEx(
 
298
        HKEY_LOCAL_MACHINE,
 
299
        NETWORK_CONNECTIONS_KEY,
 
300
        0,
 
301
        KEY_READ,
 
302
        &control_net_key);
 
303
 
 
304
    if (status != ERROR_SUCCESS) {
 
305
        return -1;
 
306
    }
 
307
 
 
308
    while (!stop)
 
309
    {
 
310
        char enum_name[256];
 
311
        char connection_string[256];
 
312
        HKEY connection_key;
 
313
        char name_data[256];
 
314
        DWORD name_type;
 
315
        const char name_string[] = "Name";
 
316
 
 
317
        len = sizeof (enum_name);
 
318
        status = RegEnumKeyEx(
 
319
            control_net_key,
 
320
            i,
 
321
            enum_name,
 
322
            &len,
 
323
            NULL,
 
324
            NULL,
 
325
            NULL,
 
326
            NULL);
 
327
 
 
328
        if (status == ERROR_NO_MORE_ITEMS)
 
329
            break;
 
330
        else if (status != ERROR_SUCCESS) {
 
331
            return -1;
 
332
        }
 
333
 
 
334
        snprintf(connection_string,
 
335
             sizeof(connection_string),
 
336
             "%s\\%s\\Connection",
 
337
             NETWORK_CONNECTIONS_KEY, enum_name);
 
338
 
 
339
        status = RegOpenKeyEx(
 
340
            HKEY_LOCAL_MACHINE,
 
341
            connection_string,
 
342
            0,
 
343
            KEY_READ,
 
344
            &connection_key);
 
345
 
 
346
        if (status == ERROR_SUCCESS) {
 
347
            len = sizeof (name_data);
 
348
            status = RegQueryValueEx(
 
349
                connection_key,
 
350
                name_string,
 
351
                NULL,
 
352
                &name_type,
 
353
                (LPBYTE)name_data,
 
354
                &len);
 
355
 
 
356
            if (status != ERROR_SUCCESS || name_type != REG_SZ) {
 
357
                    return -1;
 
358
            }
 
359
            else {
 
360
                if (is_tap_win32_dev(enum_name)) {
 
361
                    snprintf(name, name_size, "%s", enum_name);
 
362
                    if (actual_name) {
 
363
                        if (strcmp(actual_name, "") != 0) {
 
364
                            if (strcmp(name_data, actual_name) != 0) {
 
365
                                RegCloseKey (connection_key);
 
366
                                ++i;
 
367
                                continue;
 
368
                            }
 
369
                        }
 
370
                        else {
 
371
                            snprintf(actual_name, actual_name_size, "%s", name_data);
 
372
                        }
 
373
                    }
 
374
                    stop = 1;
 
375
                }
 
376
            }
 
377
 
 
378
            RegCloseKey (connection_key);
 
379
        }
 
380
        ++i;
 
381
    }
 
382
 
 
383
    RegCloseKey (control_net_key);
 
384
 
 
385
    if (stop == 0)
 
386
        return -1;
 
387
 
 
388
    return 0;
 
389
}
 
390
 
 
391
static int tap_win32_set_status(HANDLE handle, int status)
 
392
{
 
393
    unsigned long len = 0;
 
394
 
 
395
    return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,
 
396
                &status, sizeof (status),
 
397
                &status, sizeof (status), &len, NULL);
 
398
}
 
399
 
 
400
static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle)
 
401
{
 
402
    overlapped->handle = handle;
 
403
 
 
404
    overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL);
 
405
    overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
 
406
 
 
407
    overlapped->read_overlapped.Offset = 0;
 
408
    overlapped->read_overlapped.OffsetHigh = 0;
 
409
    overlapped->read_overlapped.hEvent = overlapped->read_event;
 
410
 
 
411
    overlapped->write_overlapped.Offset = 0;
 
412
    overlapped->write_overlapped.OffsetHigh = 0;
 
413
    overlapped->write_overlapped.hEvent = overlapped->write_event;
 
414
 
 
415
    InitializeCriticalSection(&overlapped->output_queue_cs);
 
416
    InitializeCriticalSection(&overlapped->free_list_cs);
 
417
 
 
418
    overlapped->output_queue_semaphore = CreateSemaphore(
 
419
        NULL,   // default security attributes
 
420
        0,   // initial count
 
421
        TUN_MAX_BUFFER_COUNT,   // maximum count
 
422
        NULL);  // unnamed semaphore
 
423
 
 
424
    if(!overlapped->output_queue_semaphore)  {
 
425
        fprintf(stderr, "error creating output queue semaphore!\n");
 
426
    }
 
427
 
 
428
    overlapped->free_list_semaphore = CreateSemaphore(
 
429
        NULL,   // default security attributes
 
430
        TUN_MAX_BUFFER_COUNT,   // initial count
 
431
        TUN_MAX_BUFFER_COUNT,   // maximum count
 
432
        NULL);  // unnamed semaphore
 
433
 
 
434
    if(!overlapped->free_list_semaphore)  {
 
435
        fprintf(stderr, "error creating free list semaphore!\n");
 
436
    }
 
437
 
 
438
    overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL;
 
439
 
 
440
    {
 
441
        unsigned index;
 
442
        for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) {
 
443
            tun_buffer_t* element = &overlapped->buffers[index];
 
444
            element->next = overlapped->free_list;
 
445
            overlapped->free_list = element;
 
446
        }
 
447
    }
 
448
    /* To count buffers, initially no-signal. */
 
449
    overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL);
 
450
    if(!overlapped->tap_semaphore)
 
451
        fprintf(stderr, "error creating tap_semaphore.\n");
 
452
}
 
453
 
 
454
static int tap_win32_write(tap_win32_overlapped_t *overlapped,
 
455
                           const void *buffer, unsigned long size)
 
456
{
 
457
    unsigned long write_size;
 
458
    BOOL result;
 
459
    DWORD error;
 
460
 
 
461
    result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped,
 
462
                                  &write_size, FALSE);
 
463
 
 
464
    if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
 
465
        WaitForSingleObject(overlapped->write_event, INFINITE);
 
466
 
 
467
    result = WriteFile(overlapped->handle, buffer, size,
 
468
                       &write_size, &overlapped->write_overlapped);
 
469
 
 
470
    if (!result) {
 
471
        switch (error = GetLastError())
 
472
        {
 
473
        case ERROR_IO_PENDING:
 
474
#ifndef TUN_ASYNCHRONOUS_WRITES
 
475
            WaitForSingleObject(overlapped->write_event, INFINITE);
 
476
#endif
 
477
            break;
 
478
        default:
 
479
            return -1;
 
480
        }
 
481
    }
 
482
 
 
483
    return write_size;
 
484
}
 
485
 
 
486
static DWORD WINAPI tap_win32_thread_entry(LPVOID param)
 
487
{
 
488
    tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param;
 
489
    unsigned long read_size;
 
490
    BOOL result;
 
491
    DWORD dwError;
 
492
    tun_buffer_t* buffer = get_buffer_from_free_list(overlapped);
 
493
 
 
494
 
 
495
    for (;;) {
 
496
        result = ReadFile(overlapped->handle,
 
497
                          buffer->buffer,
 
498
                          sizeof(buffer->buffer),
 
499
                          &read_size,
 
500
                          &overlapped->read_overlapped);
 
501
        if (!result) {
 
502
            dwError = GetLastError();
 
503
            if (dwError == ERROR_IO_PENDING) {
 
504
                WaitForSingleObject(overlapped->read_event, INFINITE);
 
505
                result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped,
 
506
                                              &read_size, FALSE);
 
507
                if (!result) {
 
508
#ifdef DEBUG_TAP_WIN32
 
509
                    LPVOID lpBuffer;
 
510
                    dwError = GetLastError();
 
511
                    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
 
512
                                   NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
513
                                   (LPTSTR) & lpBuffer, 0, NULL );
 
514
                    fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer);
 
515
                    LocalFree( lpBuffer );
 
516
#endif
 
517
                }
 
518
            } else {
 
519
#ifdef DEBUG_TAP_WIN32
 
520
                LPVOID lpBuffer;
 
521
                FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
 
522
                               NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
523
                               (LPTSTR) & lpBuffer, 0, NULL );
 
524
                fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer);
 
525
                LocalFree( lpBuffer );
 
526
#endif
 
527
            }
 
528
        }
 
529
 
 
530
        if(read_size > 0) {
 
531
            buffer->read_size = read_size;
 
532
            put_buffer_on_output_queue(overlapped, buffer);
 
533
            ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL);
 
534
            buffer = get_buffer_from_free_list(overlapped);
 
535
        }
 
536
    }
 
537
 
 
538
    return 0;
 
539
}
 
540
 
 
541
static int tap_win32_read(tap_win32_overlapped_t *overlapped,
 
542
                          uint8_t **pbuf, int max_size)
 
543
{
 
544
    int size = 0;
 
545
 
 
546
    tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped);
 
547
 
 
548
    if(buffer != NULL) {
 
549
        *pbuf = buffer->buffer;
 
550
        size = (int)buffer->read_size;
 
551
        if(size > max_size) {
 
552
            size = max_size;
 
553
        }
 
554
    }
 
555
 
 
556
    return size;
 
557
}
 
558
 
 
559
static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
 
560
                                  uint8_t *pbuf)
 
561
{
 
562
    tun_buffer_t* buffer = (tun_buffer_t*)pbuf;
 
563
    put_buffer_on_free_list(overlapped, buffer);
 
564
}
 
565
 
 
566
static int tap_win32_open(tap_win32_overlapped_t **phandle,
 
567
                          const char *prefered_name)
 
568
{
 
569
    char device_path[256];
 
570
    char device_guid[0x100];
 
571
    int rc;
 
572
    HANDLE handle;
 
573
    BOOL bret;
 
574
    char name_buffer[0x100] = {0, };
 
575
    struct {
 
576
        unsigned long major;
 
577
        unsigned long minor;
 
578
        unsigned long debug;
 
579
    } version;
 
580
    DWORD version_len;
 
581
    DWORD idThread;
 
582
 
 
583
    if (prefered_name != NULL)
 
584
        snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name);
 
585
 
 
586
    rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
 
587
    if (rc)
 
588
        return -1;
 
589
 
 
590
    snprintf (device_path, sizeof(device_path), "%s%s%s",
 
591
              USERMODEDEVICEDIR,
 
592
              device_guid,
 
593
              TAPSUFFIX);
 
594
 
 
595
    handle = CreateFile (
 
596
        device_path,
 
597
        GENERIC_READ | GENERIC_WRITE,
 
598
        0,
 
599
        0,
 
600
        OPEN_EXISTING,
 
601
        FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
 
602
        0 );
 
603
 
 
604
    if (handle == INVALID_HANDLE_VALUE) {
 
605
        return -1;
 
606
    }
 
607
 
 
608
    bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION,
 
609
                           &version, sizeof (version),
 
610
                           &version, sizeof (version), &version_len, NULL);
 
611
 
 
612
    if (bret == FALSE) {
 
613
        CloseHandle(handle);
 
614
        return -1;
 
615
    }
 
616
 
 
617
    if (!tap_win32_set_status(handle, TRUE)) {
 
618
        return -1;
 
619
    }
 
620
 
 
621
    tap_win32_overlapped_init(&tap_overlapped, handle);
 
622
 
 
623
    *phandle = &tap_overlapped;
 
624
 
 
625
    CreateThread(NULL, 0, tap_win32_thread_entry,
 
626
                 (LPVOID)&tap_overlapped, 0, &idThread);
 
627
    return 0;
 
628
}
 
629
 
 
630
/********************************************/
 
631
 
 
632
 typedef struct TAPState {
 
633
     VLANClientState nc;
 
634
     tap_win32_overlapped_t *handle;
 
635
 } TAPState;
 
636
 
 
637
static void tap_cleanup(VLANClientState *nc)
 
638
{
 
639
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 
640
 
 
641
    qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL);
 
642
 
 
643
    /* FIXME: need to kill thread and close file handle:
 
644
       tap_win32_close(s);
 
645
    */
 
646
}
 
647
 
 
648
static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
 
649
{
 
650
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 
651
 
 
652
    return tap_win32_write(s->handle, buf, size);
 
653
}
 
654
 
 
655
static void tap_win32_send(void *opaque)
 
656
{
 
657
    TAPState *s = opaque;
 
658
    uint8_t *buf;
 
659
    int max_size = 4096;
 
660
    int size;
 
661
 
 
662
    size = tap_win32_read(s->handle, &buf, max_size);
 
663
    if (size > 0) {
 
664
        qemu_send_packet(&s->nc, buf, size);
 
665
        tap_win32_free_buffer(s->handle, buf);
 
666
    }
 
667
}
 
668
 
 
669
static NetClientInfo net_tap_win32_info = {
 
670
    .type = NET_CLIENT_TYPE_TAP,
 
671
    .size = sizeof(TAPState),
 
672
    .receive = tap_receive,
 
673
    .cleanup = tap_cleanup,
 
674
};
 
675
 
 
676
static int tap_win32_init(VLANState *vlan, const char *model,
 
677
                          const char *name, const char *ifname)
 
678
{
 
679
    VLANClientState *nc;
 
680
    TAPState *s;
 
681
    tap_win32_overlapped_t *handle;
 
682
 
 
683
    if (tap_win32_open(&handle, ifname) < 0) {
 
684
        printf("tap: Could not open '%s'\n", ifname);
 
685
        return -1;
 
686
    }
 
687
 
 
688
    nc = qemu_new_net_client(&net_tap_win32_info, vlan, NULL, model, name);
 
689
 
 
690
    s = DO_UPCAST(TAPState, nc, nc);
 
691
 
 
692
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
 
693
             "tap: ifname=%s", ifname);
 
694
 
 
695
    s->handle = handle;
 
696
 
 
697
    qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s);
 
698
 
 
699
    return 0;
 
700
}
 
701
 
 
702
int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
 
703
{
 
704
    const char *ifname;
 
705
 
 
706
    ifname = qemu_opt_get(opts, "ifname");
 
707
 
 
708
    if (!ifname) {
 
709
        error_report("tap: no interface name");
 
710
        return -1;
 
711
    }
 
712
 
 
713
    if (tap_win32_init(vlan, "tap", name, ifname) == -1) {
 
714
        return -1;
 
715
    }
 
716
 
 
717
    return 0;
 
718
}
 
719
 
 
720
int tap_has_ufo(VLANClientState *vc)
 
721
{
 
722
    return 0;
 
723
}
 
724
 
 
725
int tap_has_vnet_hdr(VLANClientState *vc)
 
726
{
 
727
    return 0;
 
728
}
 
729
 
 
730
int tap_probe_vnet_hdr_len(int fd, int len)
 
731
{
 
732
    return 0;
 
733
}
 
734
 
 
735
void tap_fd_set_vnet_hdr_len(int fd, int len)
 
736
{
 
737
}
 
738
 
 
739
void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr)
 
740
{
 
741
}
 
742
 
 
743
void tap_set_offload(VLANClientState *vc, int csum, int tso4,
 
744
                     int tso6, int ecn, int ufo)
 
745
{
 
746
}
 
747
 
 
748
struct vhost_net *tap_get_vhost_net(VLANClientState *nc)
 
749
{
 
750
    return NULL;
 
751
}