Annotation of qemu/net/tap-win32.c, revision 1.1

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, 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 <stdio.h>
        !            35: #include <windows.h>
        !            36: #include <winioctl.h>
        !            37: 
        !            38: //=============
        !            39: // TAP IOCTLs
        !            40: //=============
        !            41: 
        !            42: #define TAP_CONTROL_CODE(request,method) \
        !            43:   CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
        !            44: 
        !            45: #define TAP_IOCTL_GET_MAC               TAP_CONTROL_CODE (1, METHOD_BUFFERED)
        !            46: #define TAP_IOCTL_GET_VERSION           TAP_CONTROL_CODE (2, METHOD_BUFFERED)
        !            47: #define TAP_IOCTL_GET_MTU               TAP_CONTROL_CODE (3, METHOD_BUFFERED)
        !            48: #define TAP_IOCTL_GET_INFO              TAP_CONTROL_CODE (4, METHOD_BUFFERED)
        !            49: #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
        !            50: #define TAP_IOCTL_SET_MEDIA_STATUS      TAP_CONTROL_CODE (6, METHOD_BUFFERED)
        !            51: #define TAP_IOCTL_CONFIG_DHCP_MASQ      TAP_CONTROL_CODE (7, METHOD_BUFFERED)
        !            52: #define TAP_IOCTL_GET_LOG_LINE          TAP_CONTROL_CODE (8, METHOD_BUFFERED)
        !            53: #define TAP_IOCTL_CONFIG_DHCP_SET_OPT   TAP_CONTROL_CODE (9, METHOD_BUFFERED)
        !            54: 
        !            55: //=================
        !            56: // Registry keys
        !            57: //=================
        !            58: 
        !            59: #define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
        !            60: 
        !            61: #define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
        !            62: 
        !            63: //======================
        !            64: // Filesystem prefixes
        !            65: //======================
        !            66: 
        !            67: #define USERMODEDEVICEDIR "\\\\.\\Global\\"
        !            68: #define TAPSUFFIX         ".tap"
        !            69: 
        !            70: 
        !            71: //======================
        !            72: // Compile time configuration
        !            73: //======================
        !            74: 
        !            75: //#define DEBUG_TAP_WIN32
        !            76: 
        !            77: #define TUN_ASYNCHRONOUS_WRITES 1
        !            78: 
        !            79: #define TUN_BUFFER_SIZE 1560
        !            80: #define TUN_MAX_BUFFER_COUNT 32
        !            81: 
        !            82: /*
        !            83:  * The data member "buffer" must be the first element in the tun_buffer
        !            84:  * structure. See the function, tap_win32_free_buffer.
        !            85:  */
        !            86: typedef struct tun_buffer_s {
        !            87:     unsigned char buffer [TUN_BUFFER_SIZE];
        !            88:     unsigned long read_size;
        !            89:     struct tun_buffer_s* next;
        !            90: } tun_buffer_t;
        !            91: 
        !            92: typedef struct tap_win32_overlapped {
        !            93:     HANDLE handle;
        !            94:     HANDLE read_event;
        !            95:     HANDLE write_event;
        !            96:     HANDLE output_queue_semaphore;
        !            97:     HANDLE free_list_semaphore;
        !            98:     HANDLE tap_semaphore;
        !            99:     CRITICAL_SECTION output_queue_cs;
        !           100:     CRITICAL_SECTION free_list_cs;
        !           101:     OVERLAPPED read_overlapped;
        !           102:     OVERLAPPED write_overlapped;
        !           103:     tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT];
        !           104:     tun_buffer_t* free_list;
        !           105:     tun_buffer_t* output_queue_front;
        !           106:     tun_buffer_t* output_queue_back;
        !           107: } tap_win32_overlapped_t;
        !           108: 
        !           109: static tap_win32_overlapped_t tap_overlapped;
        !           110: 
        !           111: static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped)
        !           112: {
        !           113:     tun_buffer_t* buffer = NULL;
        !           114:     WaitForSingleObject(overlapped->free_list_semaphore, INFINITE);
        !           115:     EnterCriticalSection(&overlapped->free_list_cs);
        !           116:     buffer = overlapped->free_list;
        !           117: //    assert(buffer != NULL);
        !           118:     overlapped->free_list = buffer->next;
        !           119:     LeaveCriticalSection(&overlapped->free_list_cs);
        !           120:     buffer->next = NULL;
        !           121:     return buffer;
        !           122: }
        !           123: 
        !           124: static void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
        !           125: {
        !           126:     EnterCriticalSection(&overlapped->free_list_cs);
        !           127:     buffer->next = overlapped->free_list;
        !           128:     overlapped->free_list = buffer;
        !           129:     LeaveCriticalSection(&overlapped->free_list_cs);
        !           130:     ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL);
        !           131: }
        !           132: 
        !           133: static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block)
        !           134: {
        !           135:     tun_buffer_t* buffer = NULL;
        !           136:     DWORD result, timeout = block ? INFINITE : 0L;
        !           137: 
        !           138:     // Non-blocking call
        !           139:     result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout);
        !           140: 
        !           141:     switch (result)
        !           142:     {
        !           143:         // The semaphore object was signaled.
        !           144:         case WAIT_OBJECT_0:
        !           145:             EnterCriticalSection(&overlapped->output_queue_cs);
        !           146: 
        !           147:             buffer = overlapped->output_queue_front;
        !           148:             overlapped->output_queue_front = buffer->next;
        !           149: 
        !           150:             if(overlapped->output_queue_front == NULL) {
        !           151:                 overlapped->output_queue_back = NULL;
        !           152:             }
        !           153: 
        !           154:             LeaveCriticalSection(&overlapped->output_queue_cs);
        !           155:             break;
        !           156: 
        !           157:         // Semaphore was nonsignaled, so a time-out occurred.
        !           158:         case WAIT_TIMEOUT:
        !           159:             // Cannot open another window.
        !           160:             break;
        !           161:     }
        !           162: 
        !           163:     return buffer;
        !           164: }
        !           165: 
        !           166: static tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped)
        !           167: {
        !           168:     return get_buffer_from_output_queue(overlapped, 0);
        !           169: }
        !           170: 
        !           171: static void put_buffer_on_output_queue(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
        !           172: {
        !           173:     EnterCriticalSection(&overlapped->output_queue_cs);
        !           174: 
        !           175:     if(overlapped->output_queue_front == NULL && overlapped->output_queue_back == NULL) {
        !           176:         overlapped->output_queue_front = overlapped->output_queue_back = buffer;
        !           177:     } else {
        !           178:         buffer->next = NULL;
        !           179:         overlapped->output_queue_back->next = buffer;
        !           180:         overlapped->output_queue_back = buffer;
        !           181:     }
        !           182: 
        !           183:     LeaveCriticalSection(&overlapped->output_queue_cs);
        !           184: 
        !           185:     ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL);
        !           186: }
        !           187: 
        !           188: 
        !           189: static int is_tap_win32_dev(const char *guid)
        !           190: {
        !           191:     HKEY netcard_key;
        !           192:     LONG status;
        !           193:     DWORD len;
        !           194:     int i = 0;
        !           195: 
        !           196:     status = RegOpenKeyEx(
        !           197:         HKEY_LOCAL_MACHINE,
        !           198:         ADAPTER_KEY,
        !           199:         0,
        !           200:         KEY_READ,
        !           201:         &netcard_key);
        !           202: 
        !           203:     if (status != ERROR_SUCCESS) {
        !           204:         return FALSE;
        !           205:     }
        !           206: 
        !           207:     for (;;) {
        !           208:         char enum_name[256];
        !           209:         char unit_string[256];
        !           210:         HKEY unit_key;
        !           211:         char component_id_string[] = "ComponentId";
        !           212:         char component_id[256];
        !           213:         char net_cfg_instance_id_string[] = "NetCfgInstanceId";
        !           214:         char net_cfg_instance_id[256];
        !           215:         DWORD data_type;
        !           216: 
        !           217:         len = sizeof (enum_name);
        !           218:         status = RegEnumKeyEx(
        !           219:             netcard_key,
        !           220:             i,
        !           221:             enum_name,
        !           222:             &len,
        !           223:             NULL,
        !           224:             NULL,
        !           225:             NULL,
        !           226:             NULL);
        !           227: 
        !           228:         if (status == ERROR_NO_MORE_ITEMS)
        !           229:             break;
        !           230:         else if (status != ERROR_SUCCESS) {
        !           231:             return FALSE;
        !           232:         }
        !           233: 
        !           234:         snprintf (unit_string, sizeof(unit_string), "%s\\%s",
        !           235:                   ADAPTER_KEY, enum_name);
        !           236: 
        !           237:         status = RegOpenKeyEx(
        !           238:             HKEY_LOCAL_MACHINE,
        !           239:             unit_string,
        !           240:             0,
        !           241:             KEY_READ,
        !           242:             &unit_key);
        !           243: 
        !           244:         if (status != ERROR_SUCCESS) {
        !           245:             return FALSE;
        !           246:         } else {
        !           247:             len = sizeof (component_id);
        !           248:             status = RegQueryValueEx(
        !           249:                 unit_key,
        !           250:                 component_id_string,
        !           251:                 NULL,
        !           252:                 &data_type,
        !           253:                 (LPBYTE)component_id,
        !           254:                 &len);
        !           255: 
        !           256:             if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {
        !           257:                 len = sizeof (net_cfg_instance_id);
        !           258:                 status = RegQueryValueEx(
        !           259:                     unit_key,
        !           260:                     net_cfg_instance_id_string,
        !           261:                     NULL,
        !           262:                     &data_type,
        !           263:                     (LPBYTE)net_cfg_instance_id,
        !           264:                     &len);
        !           265: 
        !           266:                 if (status == ERROR_SUCCESS && data_type == REG_SZ) {
        !           267:                     if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/
        !           268:                         !strcmp (net_cfg_instance_id, guid)) {
        !           269:                         RegCloseKey (unit_key);
        !           270:                         RegCloseKey (netcard_key);
        !           271:                         return TRUE;
        !           272:                     }
        !           273:                 }
        !           274:             }
        !           275:             RegCloseKey (unit_key);
        !           276:         }
        !           277:         ++i;
        !           278:     }
        !           279: 
        !           280:     RegCloseKey (netcard_key);
        !           281:     return FALSE;
        !           282: }
        !           283: 
        !           284: static int get_device_guid(
        !           285:     char *name,
        !           286:     int name_size,
        !           287:     char *actual_name,
        !           288:     int actual_name_size)
        !           289: {
        !           290:     LONG status;
        !           291:     HKEY control_net_key;
        !           292:     DWORD len;
        !           293:     int i = 0;
        !           294:     int stop = 0;
        !           295: 
        !           296:     status = RegOpenKeyEx(
        !           297:         HKEY_LOCAL_MACHINE,
        !           298:         NETWORK_CONNECTIONS_KEY,
        !           299:         0,
        !           300:         KEY_READ,
        !           301:         &control_net_key);
        !           302: 
        !           303:     if (status != ERROR_SUCCESS) {
        !           304:         return -1;
        !           305:     }
        !           306: 
        !           307:     while (!stop)
        !           308:     {
        !           309:         char enum_name[256];
        !           310:         char connection_string[256];
        !           311:         HKEY connection_key;
        !           312:         char name_data[256];
        !           313:         DWORD name_type;
        !           314:         const char name_string[] = "Name";
        !           315: 
        !           316:         len = sizeof (enum_name);
        !           317:         status = RegEnumKeyEx(
        !           318:             control_net_key,
        !           319:             i,
        !           320:             enum_name,
        !           321:             &len,
        !           322:             NULL,
        !           323:             NULL,
        !           324:             NULL,
        !           325:             NULL);
        !           326: 
        !           327:         if (status == ERROR_NO_MORE_ITEMS)
        !           328:             break;
        !           329:         else if (status != ERROR_SUCCESS) {
        !           330:             return -1;
        !           331:         }
        !           332: 
        !           333:         snprintf(connection_string,
        !           334:              sizeof(connection_string),
        !           335:              "%s\\%s\\Connection",
        !           336:              NETWORK_CONNECTIONS_KEY, enum_name);
        !           337: 
        !           338:         status = RegOpenKeyEx(
        !           339:             HKEY_LOCAL_MACHINE,
        !           340:             connection_string,
        !           341:             0,
        !           342:             KEY_READ,
        !           343:             &connection_key);
        !           344: 
        !           345:         if (status == ERROR_SUCCESS) {
        !           346:             len = sizeof (name_data);
        !           347:             status = RegQueryValueEx(
        !           348:                 connection_key,
        !           349:                 name_string,
        !           350:                 NULL,
        !           351:                 &name_type,
        !           352:                 (LPBYTE)name_data,
        !           353:                 &len);
        !           354: 
        !           355:             if (status != ERROR_SUCCESS || name_type != REG_SZ) {
        !           356:                     return -1;
        !           357:             }
        !           358:             else {
        !           359:                 if (is_tap_win32_dev(enum_name)) {
        !           360:                     snprintf(name, name_size, "%s", enum_name);
        !           361:                     if (actual_name) {
        !           362:                         if (strcmp(actual_name, "") != 0) {
        !           363:                             if (strcmp(name_data, actual_name) != 0) {
        !           364:                                 RegCloseKey (connection_key);
        !           365:                                 ++i;
        !           366:                                 continue;
        !           367:                             }
        !           368:                         }
        !           369:                         else {
        !           370:                             snprintf(actual_name, actual_name_size, "%s", name_data);
        !           371:                         }
        !           372:                     }
        !           373:                     stop = 1;
        !           374:                 }
        !           375:             }
        !           376: 
        !           377:             RegCloseKey (connection_key);
        !           378:         }
        !           379:         ++i;
        !           380:     }
        !           381: 
        !           382:     RegCloseKey (control_net_key);
        !           383: 
        !           384:     if (stop == 0)
        !           385:         return -1;
        !           386: 
        !           387:     return 0;
        !           388: }
        !           389: 
        !           390: static int tap_win32_set_status(HANDLE handle, int status)
        !           391: {
        !           392:     unsigned long len = 0;
        !           393: 
        !           394:     return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,
        !           395:                 &status, sizeof (status),
        !           396:                 &status, sizeof (status), &len, NULL);
        !           397: }
        !           398: 
        !           399: static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle)
        !           400: {
        !           401:     overlapped->handle = handle;
        !           402: 
        !           403:     overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL);
        !           404:     overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
        !           405: 
        !           406:     overlapped->read_overlapped.Offset = 0;
        !           407:     overlapped->read_overlapped.OffsetHigh = 0;
        !           408:     overlapped->read_overlapped.hEvent = overlapped->read_event;
        !           409: 
        !           410:     overlapped->write_overlapped.Offset = 0;
        !           411:     overlapped->write_overlapped.OffsetHigh = 0;
        !           412:     overlapped->write_overlapped.hEvent = overlapped->write_event;
        !           413: 
        !           414:     InitializeCriticalSection(&overlapped->output_queue_cs);
        !           415:     InitializeCriticalSection(&overlapped->free_list_cs);
        !           416: 
        !           417:     overlapped->output_queue_semaphore = CreateSemaphore(
        !           418:         NULL,   // default security attributes
        !           419:         0,   // initial count
        !           420:         TUN_MAX_BUFFER_COUNT,   // maximum count
        !           421:         NULL);  // unnamed semaphore
        !           422: 
        !           423:     if(!overlapped->output_queue_semaphore)  {
        !           424:         fprintf(stderr, "error creating output queue semaphore!\n");
        !           425:     }
        !           426: 
        !           427:     overlapped->free_list_semaphore = CreateSemaphore(
        !           428:         NULL,   // default security attributes
        !           429:         TUN_MAX_BUFFER_COUNT,   // initial count
        !           430:         TUN_MAX_BUFFER_COUNT,   // maximum count
        !           431:         NULL);  // unnamed semaphore
        !           432: 
        !           433:     if(!overlapped->free_list_semaphore)  {
        !           434:         fprintf(stderr, "error creating free list semaphore!\n");
        !           435:     }
        !           436: 
        !           437:     overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL;
        !           438: 
        !           439:     {
        !           440:         unsigned index;
        !           441:         for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) {
        !           442:             tun_buffer_t* element = &overlapped->buffers[index];
        !           443:             element->next = overlapped->free_list;
        !           444:             overlapped->free_list = element;
        !           445:         }
        !           446:     }
        !           447:     /* To count buffers, initially no-signal. */
        !           448:     overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL);
        !           449:     if(!overlapped->tap_semaphore)
        !           450:         fprintf(stderr, "error creating tap_semaphore.\n");
        !           451: }
        !           452: 
        !           453: static int tap_win32_write(tap_win32_overlapped_t *overlapped,
        !           454:                            const void *buffer, unsigned long size)
        !           455: {
        !           456:     unsigned long write_size;
        !           457:     BOOL result;
        !           458:     DWORD error;
        !           459: 
        !           460:     result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped,
        !           461:                                   &write_size, FALSE);
        !           462: 
        !           463:     if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
        !           464:         WaitForSingleObject(overlapped->write_event, INFINITE);
        !           465: 
        !           466:     result = WriteFile(overlapped->handle, buffer, size,
        !           467:                        &write_size, &overlapped->write_overlapped);
        !           468: 
        !           469:     if (!result) {
        !           470:         switch (error = GetLastError())
        !           471:         {
        !           472:         case ERROR_IO_PENDING:
        !           473: #ifndef TUN_ASYNCHRONOUS_WRITES
        !           474:             WaitForSingleObject(overlapped->write_event, INFINITE);
        !           475: #endif
        !           476:             break;
        !           477:         default:
        !           478:             return -1;
        !           479:         }
        !           480:     }
        !           481: 
        !           482:     return 0;
        !           483: }
        !           484: 
        !           485: static DWORD WINAPI tap_win32_thread_entry(LPVOID param)
        !           486: {
        !           487:     tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param;
        !           488:     unsigned long read_size;
        !           489:     BOOL result;
        !           490:     DWORD dwError;
        !           491:     tun_buffer_t* buffer = get_buffer_from_free_list(overlapped);
        !           492: 
        !           493: 
        !           494:     for (;;) {
        !           495:         result = ReadFile(overlapped->handle,
        !           496:                           buffer->buffer,
        !           497:                           sizeof(buffer->buffer),
        !           498:                           &read_size,
        !           499:                           &overlapped->read_overlapped);
        !           500:         if (!result) {
        !           501:             dwError = GetLastError();
        !           502:             if (dwError == ERROR_IO_PENDING) {
        !           503:                 WaitForSingleObject(overlapped->read_event, INFINITE);
        !           504:                 result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped,
        !           505:                                               &read_size, FALSE);
        !           506:                 if (!result) {
        !           507: #ifdef DEBUG_TAP_WIN32
        !           508:                     LPVOID lpBuffer;
        !           509:                     dwError = GetLastError();
        !           510:                     FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        !           511:                                    NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        !           512:                                    (LPTSTR) & lpBuffer, 0, NULL );
        !           513:                     fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer);
        !           514:                     LocalFree( lpBuffer );
        !           515: #endif
        !           516:                 }
        !           517:             } else {
        !           518: #ifdef DEBUG_TAP_WIN32
        !           519:                 LPVOID lpBuffer;
        !           520:                 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        !           521:                                NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        !           522:                                (LPTSTR) & lpBuffer, 0, NULL );
        !           523:                 fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer);
        !           524:                 LocalFree( lpBuffer );
        !           525: #endif
        !           526:             }
        !           527:         }
        !           528: 
        !           529:         if(read_size > 0) {
        !           530:             buffer->read_size = read_size;
        !           531:             put_buffer_on_output_queue(overlapped, buffer);
        !           532:             ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL);
        !           533:             buffer = get_buffer_from_free_list(overlapped);
        !           534:         }
        !           535:     }
        !           536: 
        !           537:     return 0;
        !           538: }
        !           539: 
        !           540: static int tap_win32_read(tap_win32_overlapped_t *overlapped,
        !           541:                           uint8_t **pbuf, int max_size)
        !           542: {
        !           543:     int size = 0;
        !           544: 
        !           545:     tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped);
        !           546: 
        !           547:     if(buffer != NULL) {
        !           548:         *pbuf = buffer->buffer;
        !           549:         size = (int)buffer->read_size;
        !           550:         if(size > max_size) {
        !           551:             size = max_size;
        !           552:         }
        !           553:     }
        !           554: 
        !           555:     return size;
        !           556: }
        !           557: 
        !           558: static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
        !           559:                                   uint8_t *pbuf)
        !           560: {
        !           561:     tun_buffer_t* buffer = (tun_buffer_t*)pbuf;
        !           562:     put_buffer_on_free_list(overlapped, buffer);
        !           563: }
        !           564: 
        !           565: static int tap_win32_open(tap_win32_overlapped_t **phandle,
        !           566:                           const char *prefered_name)
        !           567: {
        !           568:     char device_path[256];
        !           569:     char device_guid[0x100];
        !           570:     int rc;
        !           571:     HANDLE handle;
        !           572:     BOOL bret;
        !           573:     char name_buffer[0x100] = {0, };
        !           574:     struct {
        !           575:         unsigned long major;
        !           576:         unsigned long minor;
        !           577:         unsigned long debug;
        !           578:     } version;
        !           579:     DWORD version_len;
        !           580:     DWORD idThread;
        !           581:     HANDLE hThread;
        !           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:     hThread = 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:         qemu_error("tap: no interface name\n");
        !           710:         return -1;
        !           711:     }
        !           712: 
        !           713:     if (tap_win32_init(vlan, "tap", name, ifname) == -1) {
        !           714:         return -1;
        !           715:     }
        !           716: 
        !           717:     if (vlan) {
        !           718:         vlan->nb_host_devs++;
        !           719:     }
        !           720: 
        !           721:     return 0;
        !           722: }
        !           723: 
        !           724: int tap_has_ufo(VLANClientState *vc)
        !           725: {
        !           726:     return 0;
        !           727: }
        !           728: 
        !           729: int tap_has_vnet_hdr(VLANClientState *vc)
        !           730: {
        !           731:     return 0;
        !           732: }
        !           733: 
        !           734: void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr)
        !           735: {
        !           736: }
        !           737: 
        !           738: void tap_set_offload(VLANClientState *vc, int csum, int tso4,
        !           739:                      int tso6, int ecn, int ufo)
        !           740: {
        !           741: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.