File:  [Qemu by Fabrice Bellard] / qemu / tap-win32.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:21 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    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.,
   27:  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   28:  */
   29: #include "qemu-common.h"
   30: #include "net.h"
   31: #include "sysemu.h"
   32: #include <stdio.h>
   33: #define WIN32_LEAN_AND_MEAN
   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: 
   80: //#define DEBUG_TAP_WIN32
   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;
  103:     HANDLE tap_semaphore;
  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: 
  116: static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped)
  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: 
  138: static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block)
  139: {
  140:     tun_buffer_t* buffer = NULL;
  141:     DWORD result, timeout = block ? INFINITE : 0L;
  142: 
  143:     // Non-blocking call
  144:     result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout);
  145: 
  146:     switch (result)
  147:     {
  148:         // The semaphore object was signaled.
  149:         case WAIT_OBJECT_0:
  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);
  160:             break;
  161: 
  162:         // Semaphore was nonsignaled, so a time-out occurred.
  163:         case WAIT_TIMEOUT:
  164:             // Cannot open another window.
  165:             break;
  166:     }
  167: 
  168:     return buffer;
  169: }
  170: 
  171: static tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped)
  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: 
  338:         snprintf(connection_string,
  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);
  349: 
  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: 
  422:     overlapped->output_queue_semaphore = CreateSemaphore(
  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: 
  432:     overlapped->free_list_semaphore = CreateSemaphore(
  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:     }
  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");
  456: }
  457: 
  458: static int tap_win32_write(tap_win32_overlapped_t *overlapped,
  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);
  473: 
  474:     if (!result) {
  475:         switch (error = GetLastError())
  476:         {
  477:         case ERROR_IO_PENDING:
  478: #ifndef TUN_ASYNCHRONOUS_WRITES
  479:             WaitForSingleObject(overlapped->write_event, INFINITE);
  480: #endif
  481:             break;
  482:         default:
  483:             return -1;
  484:         }
  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) {
  512: #ifdef DEBUG_TAP_WIN32
  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 {
  523: #ifdef DEBUG_TAP_WIN32
  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);
  537:             ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL);
  538:             buffer = get_buffer_from_free_list(overlapped);
  539:         }
  540:     }
  541: 
  542:     return 0;
  543: }
  544: 
  545: static int tap_win32_read(tap_win32_overlapped_t *overlapped,
  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: 
  563: static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
  564:                                   char* pbuf)
  565: {
  566:     tun_buffer_t* buffer = (tun_buffer_t*)pbuf;
  567:     put_buffer_on_free_list(overlapped, buffer);
  568: }
  569: 
  570: static int tap_win32_open(tap_win32_overlapped_t **phandle,
  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: 
  642: static void tap_receive(void *opaque, const uint8_t *buf, int size)
  643: {
  644:     TAPState *s = opaque;
  645: 
  646:     tap_win32_write(s->handle, buf, size);
  647: }
  648: 
  649: static void tap_win32_send(void *opaque)
  650: {
  651:     TAPState *s = opaque;
  652:     uint8_t *buf;
  653:     int max_size = 4096;
  654:     int size;
  655: 
  656:     size = tap_win32_read(s->handle, &buf, max_size);
  657:     if (size > 0) {
  658:         qemu_send_packet(s->vc, buf, size);
  659:         tap_win32_free_buffer(s->handle, buf);
  660:     }
  661: }
  662: 
  663: int tap_win32_init(VLANState *vlan, const char *model,
  664:                    const char *name, const char *ifname)
  665: {
  666:     TAPState *s;
  667: 
  668:     s = qemu_mallocz(sizeof(TAPState));
  669:     if (!s)
  670:         return -1;
  671:     if (tap_win32_open(&s->handle, ifname) < 0) {
  672:         printf("tap: Could not open '%s'\n", ifname);
  673:         return -1;
  674:     }
  675: 
  676:     s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s);
  677: 
  678:     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
  679:              "tap: ifname=%s", ifname);
  680: 
  681:     qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s);
  682:     return 0;
  683: }

unix.superglobalmegacorp.com