Annotation of qemu/tap-win32.c, revision 1.1.1.6

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

unix.superglobalmegacorp.com