Commit 7fb843f8cc67805d66db9e2ec3d482c8a928bdab

Authored by bellard
1 parent 94458802

tap win32 support


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