qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] updated tap for win32 (against CVS)


From: Damien Mascord
Subject: [Qemu-devel] [PATCH] updated tap for win32 (against CVS)
Date: Tue, 26 Apr 2005 15:15:34 +0800
User-agent: Mozilla Thunderbird 1.0.2 (Windows/20050317)

Hi guys,

Here is the updated patch for supporting tap devices (specifically
against the OpenVPN Tap-Win32 driver).

This is just the patch from
[http://lists.gnu.org/archive/html/qemu-devel/2004-10/msg00213.html]
reapplied manually against the latest CVS, and then re-diffed.

This works correctly, as per the original poster.

Damien
diff -uaNr qemu-snapshot-2005-04-24_23/Makefile.target 
qemu-snapshot+tapwin32/Makefile.target
--- qemu-snapshot-2005-04-24_23/Makefile.target Tue Apr 26 15:00:49 2005
+++ qemu-snapshot+tapwin32/Makefile.target      Tue Apr 26 15:01:01 2005
@@ -341,15 +341,16 @@
 # Hardware support
 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
-VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
+VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o tap-win32.o
 endif
 ifeq ($(TARGET_ARCH), ppc)
 VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
-VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o
+VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o tap-win32.o
 endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t08.o magic-load.o slavio_intctl.o 
slavio_timer.o slavio_serial.o fdc.o esp.o
+VL_OBJS+= tap-win32.o
 endif
 ifdef CONFIG_GDBSTUB
 VL_OBJS+=gdbstub.o 
diff -uaNr qemu-snapshot-2005-04-24_23/tap-win32.c 
qemu-snapshot+tapwin32/tap-win32.c
--- qemu-snapshot-2005-04-24_23/tap-win32.c     Thu Jan  1 08:00:00 1970
+++ qemu-snapshot+tapwin32/tap-win32.c  Tue Apr 26 15:01:01 2005
@@ -0,0 +1,650 @@
+/*
+ *  TAP-Win32 -- A kernel driver to provide virtual tap device functionality
+ *               on Windows.  Originally derived from the CIPE-Win32
+ *               project by Damion K. Wilson, with extensive modifications by
+ *               James Yonan.
+ *
+ *  All source code which derives from the CIPE-Win32 project is
+ *  Copyright (C) Damion K. Wilson, 2003, and is released under the
+ *  GPL version 2 (see below).
+ *
+ *  All other source code is Copyright (C) James Yonan, 2003-2004,
+ *  and is released under the GPL version 2 (see below).
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef _WIN32
+
+#include <stdio.h>
+#include <windows.h>
+#include <assert.h>
+
+#include <ddk/ntapi.h>
+#include <ddk/winddk.h>
+#include <ddk/ntddk.h>
+
+
+
+//=============
+// TAP IOCTLs
+//=============
+
+#define TAP_CONTROL_CODE(request,method) \
+  CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
+
+#define TAP_IOCTL_GET_MAC               TAP_CONTROL_CODE (1, METHOD_BUFFERED)
+#define TAP_IOCTL_GET_VERSION           TAP_CONTROL_CODE (2, METHOD_BUFFERED)
+#define TAP_IOCTL_GET_MTU               TAP_CONTROL_CODE (3, METHOD_BUFFERED)
+#define TAP_IOCTL_GET_INFO              TAP_CONTROL_CODE (4, METHOD_BUFFERED)
+#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
+#define TAP_IOCTL_SET_MEDIA_STATUS      TAP_CONTROL_CODE (6, METHOD_BUFFERED)
+#define TAP_IOCTL_CONFIG_DHCP_MASQ      TAP_CONTROL_CODE (7, METHOD_BUFFERED)
+#define TAP_IOCTL_GET_LOG_LINE          TAP_CONTROL_CODE (8, METHOD_BUFFERED)
+#define TAP_IOCTL_CONFIG_DHCP_SET_OPT   TAP_CONTROL_CODE (9, METHOD_BUFFERED)
+
+//=================
+// Registry keys
+//=================
+
+#define ADAPTER_KEY 
"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+
+#define NETWORK_CONNECTIONS_KEY 
"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+
+//======================
+// Filesystem prefixes
+//======================
+
+#define USERMODEDEVICEDIR "\\\\.\\Global\\"
+#define TAPSUFFIX         ".tap"
+
+
+//======================
+// Compile time configuration
+//======================
+
+//#define DEBUG_TAP_WIN32 1
+
+#define TUN_ASYNCHRONOUS_WRITES 1
+
+#define TUN_BUFFER_SIZE 1560
+#define TUN_MAX_BUFFER_COUNT 32
+
+/*
+ * The data member "buffer" must be the first element in the tun_buffer
+ * structure. See the function, tap_win32_free_buffer.
+ */
+typedef struct tun_buffer_s {
+    unsigned char buffer [TUN_BUFFER_SIZE];
+    unsigned long read_size;
+    struct tun_buffer_s* next;
+} tun_buffer_t;
+
+typedef struct tap_win32_overlapped {
+    HANDLE handle;
+    HANDLE read_event;
+    HANDLE write_event;
+    HANDLE output_queue_semaphore;
+    HANDLE free_list_semaphore;
+    CRITICAL_SECTION output_queue_cs;
+    CRITICAL_SECTION free_list_cs;
+    OVERLAPPED read_overlapped;
+    OVERLAPPED write_overlapped;
+    tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT];
+    tun_buffer_t* free_list;
+    tun_buffer_t* output_queue_front;
+    tun_buffer_t* output_queue_back;
+} tap_win32_overlapped_t;
+
+static tap_win32_overlapped_t tap_overlapped;
+
+static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const 
overlapped) 
+{
+    tun_buffer_t* buffer = NULL;
+    WaitForSingleObject(overlapped->free_list_semaphore, INFINITE);
+    EnterCriticalSection(&overlapped->free_list_cs);
+    buffer = overlapped->free_list;
+    assert(buffer != NULL);
+    overlapped->free_list = buffer->next;
+    LeaveCriticalSection(&overlapped->free_list_cs);
+    buffer->next = NULL;
+    return buffer;
+}
+
+static void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, 
tun_buffer_t* const buffer)
+{
+    EnterCriticalSection(&overlapped->free_list_cs);
+    buffer->next = overlapped->free_list;
+    overlapped->free_list = buffer;
+    LeaveCriticalSection(&overlapped->free_list_cs);
+    ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL);
+}
+
+static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* 
const overlapped, const int block) 
+{
+    tun_buffer_t* buffer = NULL;
+    DWORD result, timeout = block ? INFINITE : 0L;
+
+    // Non-blocking call
+    result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout); 
+
+    switch (result) 
+    { 
+        // The semaphore object was signaled.
+        case WAIT_OBJECT_0: 
+            EnterCriticalSection(&overlapped->output_queue_cs);
+
+            buffer = overlapped->output_queue_front;
+            overlapped->output_queue_front = buffer->next;
+
+            if(overlapped->output_queue_front == NULL) {
+                overlapped->output_queue_back = NULL;
+            }
+
+            LeaveCriticalSection(&overlapped->output_queue_cs);
+            break; 
+
+        // Semaphore was nonsignaled, so a time-out occurred.
+        case WAIT_TIMEOUT: 
+            // Cannot open another window.
+            break; 
+    }
+
+    return buffer;
+}
+
+static tun_buffer_t* get_buffer_from_output_queue_immediate 
(tap_win32_overlapped_t* const overlapped) 
+{
+    return get_buffer_from_output_queue(overlapped, 0);
+}
+
+static void put_buffer_on_output_queue(tap_win32_overlapped_t* const 
overlapped, tun_buffer_t* const buffer)
+{
+    EnterCriticalSection(&overlapped->output_queue_cs);
+
+    if(overlapped->output_queue_front == NULL && overlapped->output_queue_back 
== NULL) {
+        overlapped->output_queue_front = overlapped->output_queue_back = 
buffer;
+    } else {
+        buffer->next = NULL;
+        overlapped->output_queue_back->next = buffer;
+        overlapped->output_queue_back = buffer;
+    }
+
+    LeaveCriticalSection(&overlapped->output_queue_cs);
+
+    ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL);
+}
+
+
+static int is_tap_win32_dev(const char *guid)
+{
+    HKEY netcard_key;
+    LONG status;
+    DWORD len;
+    int i = 0;
+
+    status = RegOpenKeyEx(
+        HKEY_LOCAL_MACHINE,
+        ADAPTER_KEY,
+        0,
+        KEY_READ,
+        &netcard_key);
+
+    if (status != ERROR_SUCCESS) {
+        return FALSE;
+    }
+
+    for (;;) {
+        char enum_name[256];
+        char unit_string[256];
+        HKEY unit_key;
+        char component_id_string[] = "ComponentId";
+        char component_id[256];
+        char net_cfg_instance_id_string[] = "NetCfgInstanceId";
+        char net_cfg_instance_id[256];
+        DWORD data_type;
+
+        len = sizeof (enum_name);
+        status = RegEnumKeyEx(
+            netcard_key,
+            i,
+            enum_name,
+            &len,
+            NULL,
+            NULL,
+            NULL,
+            NULL);
+
+        if (status == ERROR_NO_MORE_ITEMS)
+            break;
+        else if (status != ERROR_SUCCESS) {
+            return FALSE;
+        }
+
+        snprintf (unit_string, sizeof(unit_string), "%s\\%s",
+                  ADAPTER_KEY, enum_name);
+
+        status = RegOpenKeyEx(
+            HKEY_LOCAL_MACHINE,
+            unit_string,
+            0,
+            KEY_READ,
+            &unit_key);
+
+        if (status != ERROR_SUCCESS) {
+            return FALSE;
+        } else {
+            len = sizeof (component_id);
+            status = RegQueryValueEx(
+                unit_key,
+                component_id_string,
+                NULL,
+                &data_type,
+                component_id,
+                &len);
+
+            if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {
+                len = sizeof (net_cfg_instance_id);
+                status = RegQueryValueEx(
+                    unit_key,
+                    net_cfg_instance_id_string,
+                    NULL,
+                    &data_type,
+                    net_cfg_instance_id,
+                    &len);
+
+                if (status == ERROR_SUCCESS && data_type == REG_SZ) {
+                    if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/
+                        !strcmp (net_cfg_instance_id, guid)) {
+                        RegCloseKey (unit_key);
+                        RegCloseKey (netcard_key);
+                        return TRUE;
+                    }
+                }
+            }
+            RegCloseKey (unit_key);
+        }
+        ++i;
+    }
+
+    RegCloseKey (netcard_key);
+    return FALSE;
+}
+
+static int get_device_guid(
+    char *name,
+    int name_size,
+    char *actual_name,
+    int actual_name_size)
+{
+    LONG status;
+    HKEY control_net_key;
+    DWORD len;
+    int i = 0;
+    int stop = 0;
+
+    status = RegOpenKeyEx(
+        HKEY_LOCAL_MACHINE,
+        NETWORK_CONNECTIONS_KEY,
+        0,
+        KEY_READ,
+        &control_net_key);
+
+    if (status != ERROR_SUCCESS) {
+        return -1;
+    }
+
+    while (!stop)
+    {
+        char enum_name[256];
+        char connection_string[256];
+        HKEY connection_key;
+        char name_data[256];
+        DWORD name_type;
+        const char name_string[] = "Name";
+
+        len = sizeof (enum_name);
+        status = RegEnumKeyEx(
+            control_net_key,
+            i,
+            enum_name,
+            &len,
+            NULL,
+            NULL,
+            NULL,
+            NULL);
+
+        if (status == ERROR_NO_MORE_ITEMS)
+            break;
+        else if (status != ERROR_SUCCESS) {
+            return -1;
+        }
+
+        snprintf(connection_string, 
+             sizeof(connection_string),
+             "%s\\%s\\Connection",
+             NETWORK_CONNECTIONS_KEY, enum_name);
+
+        status = RegOpenKeyEx(
+            HKEY_LOCAL_MACHINE,
+            connection_string,
+            0,
+            KEY_READ,
+            &connection_key);
+        
+        if (status == ERROR_SUCCESS) {
+            len = sizeof (name_data);
+            status = RegQueryValueEx(
+                connection_key,
+                name_string,
+                NULL,
+                &name_type,
+                name_data,
+                &len);
+
+            if (status != ERROR_SUCCESS || name_type != REG_SZ) {
+                    return -1;
+            }
+            else {
+                if (is_tap_win32_dev(enum_name)) {
+                    snprintf(name, name_size, "%s", enum_name);
+                    if (actual_name) {
+                        if (strcmp(actual_name, "") != 0) {
+                            if (strcmp(name_data, actual_name) != 0) {
+                                RegCloseKey (connection_key);
+                                ++i;
+                                continue;
+                            }
+                        }
+                        else {
+                            snprintf(actual_name, actual_name_size, "%s", 
name_data);
+                        }
+                    }
+                    stop = 1;
+                }
+            }
+
+            RegCloseKey (connection_key);
+        }
+        ++i;
+    }
+
+    RegCloseKey (control_net_key);
+
+    if (stop == 0)
+        return -1;
+
+    return 0;
+}
+
+int tap_win32_set_status(HANDLE handle, int status)
+{
+    unsigned long len = 0;
+
+    return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,
+                &status, sizeof (status),
+                &status, sizeof (status), &len, NULL);
+}
+
+void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const 
HANDLE handle)
+{
+    overlapped->handle = handle;
+
+    overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+    overlapped->read_overlapped.Offset = 0;
+    overlapped->read_overlapped.OffsetHigh = 0;
+    overlapped->read_overlapped.hEvent = overlapped->read_event;
+
+    overlapped->write_overlapped.Offset = 0;
+    overlapped->write_overlapped.OffsetHigh = 0;
+    overlapped->write_overlapped.hEvent = overlapped->write_event;
+
+    InitializeCriticalSection(&overlapped->output_queue_cs);
+    InitializeCriticalSection(&overlapped->free_list_cs);
+
+    overlapped->output_queue_semaphore = CreateSemaphore( 
+        NULL,   // default security attributes
+        0,   // initial count
+        TUN_MAX_BUFFER_COUNT,   // maximum count
+        NULL);  // unnamed semaphore
+
+    if(!overlapped->output_queue_semaphore)  {
+        fprintf(stderr, "error creating output queue semaphore!\n");
+    }
+
+    overlapped->free_list_semaphore = CreateSemaphore( 
+        NULL,   // default security attributes
+        TUN_MAX_BUFFER_COUNT,   // initial count
+        TUN_MAX_BUFFER_COUNT,   // maximum count
+        NULL);  // unnamed semaphore
+
+    if(!overlapped->free_list_semaphore)  {
+        fprintf(stderr, "error creating free list semaphore!\n");
+    }
+
+    overlapped->free_list = overlapped->output_queue_front = 
overlapped->output_queue_back = NULL;
+
+    {
+        unsigned index;
+        for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) {
+            tun_buffer_t* element = &overlapped->buffers[index];
+            element->next = overlapped->free_list;
+            overlapped->free_list = element;
+        }
+    }
+}
+
+int tap_win32_write(int *handle, void *buffer, unsigned long size)
+{
+    tap_win32_overlapped_t *overlapped;
+    unsigned long write_size;
+    BOOL result;
+    DWORD error;
+
+    overlapped = (tap_win32_overlapped_t *)handle;
+
+    result = GetOverlappedResult( overlapped->handle, 
&overlapped->write_overlapped,
+                                  &write_size, FALSE);
+
+    if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
+        WaitForSingleObject(overlapped->write_event, INFINITE);
+
+    result = WriteFile(overlapped->handle, buffer, size,
+                       &write_size, &overlapped->write_overlapped);
+    
+    if (!result) { 
+        switch (error = GetLastError())
+        { 
+        case ERROR_IO_PENDING: 
+#ifndef TUN_ASYNCHRONOUS_WRITES
+            WaitForSingleObject(overlapped->write_event, INFINITE);
+#endif
+            break;
+        default:
+            return -1;
+        } 
+    }
+
+    return 0;
+}
+
+static DWORD WINAPI tap_win32_thread_entry(LPVOID param)
+{
+    tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param;
+    unsigned long read_size;
+    BOOL result;
+    DWORD dwError;
+    tun_buffer_t* buffer = get_buffer_from_free_list(overlapped);
+
+
+    for (;;) {
+        result = ReadFile(overlapped->handle,
+                          buffer->buffer,
+                          sizeof(buffer->buffer),
+                          &read_size,
+                          &overlapped->read_overlapped);
+        if (!result) {
+            dwError = GetLastError();
+            if (dwError == ERROR_IO_PENDING) {
+                WaitForSingleObject(overlapped->read_event, INFINITE);
+                result = GetOverlappedResult( overlapped->handle, 
&overlapped->read_overlapped,
+                                              &read_size, FALSE);
+                if (!result) {
+#if DEBUG_TAP_WIN32
+                    LPVOID lpBuffer;
+                    dwError = GetLastError();
+                    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | 
FORMAT_MESSAGE_FROM_SYSTEM,
+                                   NULL, dwError, MAKELANGID(LANG_NEUTRAL, 
SUBLANG_DEFAULT),
+                                   (LPTSTR) & lpBuffer, 0, NULL );
+                    fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - 
%s\n", dwError, lpBuffer);
+                    LocalFree( lpBuffer );
+#endif
+                }
+            } else {
+#if DEBUG_TAP_WIN32
+                LPVOID lpBuffer;
+                FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | 
FORMAT_MESSAGE_FROM_SYSTEM,
+                               NULL, dwError, MAKELANGID(LANG_NEUTRAL, 
SUBLANG_DEFAULT),
+                               (LPTSTR) & lpBuffer, 0, NULL );
+                fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", 
dwError, lpBuffer);
+                LocalFree( lpBuffer );
+#endif
+            }
+        }
+
+        if(read_size > 0) {
+            buffer->read_size = read_size;
+            put_buffer_on_output_queue(overlapped, buffer);
+            buffer = get_buffer_from_free_list(overlapped);
+        }
+    }
+
+    return 0;
+}
+
+int tap_win32_read(int handle, char **pbuf, int max_size)
+{
+    tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t *)handle;
+    int size = 0;
+
+    tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped);
+
+    if(buffer != NULL) {
+        *pbuf = buffer->buffer;
+        size = (int)buffer->read_size;
+        if(size > max_size) {
+            size = max_size;
+        }
+    }
+
+    return size;
+}
+
+void tap_win32_free_buffer(int handle, char* pbuf) 
+{
+    tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t *)handle;
+    tun_buffer_t* buffer = (tun_buffer_t*)pbuf;
+    put_buffer_on_free_list(overlapped, buffer);
+}
+
+int tap_win32_open(int *phandle, char *prefered_name)
+{
+    char device_path[256];
+    char device_guid[0x100];
+    int rc;
+    HANDLE handle;
+    BOOL bret;
+    char name_buffer[0x100] = {0, };
+    struct {
+        unsigned long major;
+        unsigned long minor;
+        unsigned long debug;
+    } version;
+    LONG version_len;
+    DWORD idThread;
+    HANDLE hThread;
+
+    if (prefered_name != NULL)
+        snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name);
+
+    rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, 
sizeof(name_buffer));
+    if (rc)
+        return -1;
+
+    snprintf (device_path, sizeof(device_path), "%s%s%s",
+              USERMODEDEVICEDIR,
+              device_guid,
+              TAPSUFFIX);
+
+    handle = CreateFile (
+        device_path,
+        GENERIC_READ | GENERIC_WRITE,
+        0,
+        0,
+        OPEN_EXISTING,
+        FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
+        0 );
+
+    if (handle == INVALID_HANDLE_VALUE) {
+        return -1;
+    }
+
+    bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION,
+                           &version, sizeof (version),
+                           &version, sizeof (version), &version_len, NULL);
+
+    if (bret == FALSE) {
+        CloseHandle(handle);
+        return -1;
+    }
+
+    if (!tap_win32_set_status(handle, TRUE)) {
+        return -1;
+    }
+
+    tap_win32_overlapped_init(&tap_overlapped, handle);
+
+    *phandle = (int)&tap_overlapped;
+
+    hThread = CreateThread(NULL, 0, tap_win32_thread_entry,
+                           (LPVOID)&tap_overlapped, 0, &idThread);
+    SetThreadPriority(hThread,THREAD_PRIORITY_TIME_CRITICAL);
+
+    return 0;
+}
+
+#else /* _WIN32 */
+
+int tap_win32_open(int* a1, const char*a2)
+{
+    return -1;
+}
+int tap_win32_read(int a1, uint8_t **a2, int a3)
+{
+    return -1;
+}
+void tap_win32_free_buffer(int handle, char* pbuf) 
+{
+}
+int tap_win32_write(int a1, const uint8_t *a2, unsigned long a3)
+{
+    return -1;
+};
+
+#endif
+
diff -uaNr qemu-snapshot-2005-04-24_23/vl.c qemu-snapshot+tapwin32/vl.c
--- qemu-snapshot-2005-04-24_23/vl.c    Tue Apr 26 15:00:51 2005
+++ qemu-snapshot+tapwin32/vl.c Tue Apr 26 15:01:01 2005
@@ -105,6 +105,13 @@
 /* XXX: use a two level table to limit memory usage */
 #define MAX_IOPORTS 65536
 
+#ifdef _WIN32
+int tap_win32_open(int*, const char*);
+int tap_win32_read(int, uint8_t**, int);
+void tap_win32_free_buffer(int handle, char* pbuf);
+int tap_win32_write(int, const uint8_t*, unsigned long);
+#endif
+
 const char *bios_dir = CONFIG_QEMU_SHAREDIR;
 char phys_ram_file[1024];
 CPUState *global_env;
@@ -1589,7 +1596,39 @@
 
 #endif /* CONFIG_SLIRP */
 
-#if !defined(_WIN32)
+#if defined(_WIN32)
+
+static int tap_win32_inited;
+static const char *tap_win32_devname=0;
+
+static void tun_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
+{
+    tap_win32_write(nd->fd, buf, size);
+}
+
+static void tun_add_read_packet(NetDriverState *nd, 
+                                IOCanRWHandler *fd_can_read, 
+                                IOReadHandler *fd_read, void *opaque)
+{
+    qemu_add_fd_read_handler(nd->fd, fd_can_read, fd_read, opaque);
+}
+
+static int net_tun_init(NetDriverState *nd)
+{
+    int fd;
+
+    if (tap_win32_open(&fd, tap_win32_devname) < 0)
+      return -1;
+    if (!tap_win32_inited) {
+        tap_win32_inited = 1;
+    }
+    nd->fd = fd;
+    nd->send_packet = tun_send_packet;
+    nd->add_read_packet = tun_add_read_packet;
+    pstrcpy(nd->ifname, sizeof(nd->ifname), "tap-win32");
+    return 0;
+}
+#else
 #ifdef _BSD
 static int tun_open(char *ifname, int ifname_size)
 {
@@ -2598,13 +2637,36 @@
     struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf;
     IOHandlerRecord *ioh, *ioh_next;
     uint8_t buf[4096];
-    int n, max_size;
-#endif
     int ret;
+#else
+#if defined(CONFIG_SLIRP)
+    int ret;
+#endif
+    uint8_t *buf;
+#endif
+    int n=0, max_size=0;
 
 #ifdef _WIN32
-        if (timeout > 0)
+
+    /* XXX: only one device */
+    if (tap_win32_inited) {
+        if (first_io_handler->fd_can_read)
+            max_size = first_io_handler->fd_can_read(first_io_handler->opaque);
+
+        if (max_size > 0) {
+            n = tap_win32_read(first_io_handler->fd, &buf, max_size);
+            if (n > 0) {
+               first_io_handler->fd_read(first_io_handler->opaque, buf, n);
+               tap_win32_free_buffer(first_io_handler->fd, buf);
+           }
+        }
+        if (!n && timeout > 0)
             Sleep(timeout);
+    } else if (timeout > 0) {
+        Sleep(timeout);
+    }
+
+
 #else
         /* poll any events */
         /* XXX: separate device handlers from system ones */
@@ -2767,6 +2829,9 @@
            "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n"
            "                redirect TCP or UDP connections from host to guest 
[-user-net]\n"
 #endif
+#ifdef _WIN32
+           "-tap adapter    use tap-win32 adapter\n"
+#endif
            "-dummy-net      use dummy network stack\n"
            "\n"
            "Linux boot specific:\n"
@@ -2850,6 +2915,7 @@
     QEMU_OPTION_tftp,
     QEMU_OPTION_smb,
     QEMU_OPTION_redir,
+    QEMU_OPTION_tap,
     QEMU_OPTION_dummy_net,
 
     QEMU_OPTION_kernel,
@@ -2915,6 +2981,9 @@
 #endif
     { "redir", HAS_ARG, QEMU_OPTION_redir },
 #endif
+#ifdef _WIN32
+    { "tap", HAS_ARG, QEMU_OPTION_tap },
+#endif
     { "dummy-net", 0, QEMU_OPTION_dummy_net },
 
     { "kernel", HAS_ARG, QEMU_OPTION_kernel },
@@ -3018,7 +3087,10 @@
     int cyls, heads, secs, translation;
     int start_emulation = 1;
     uint8_t macaddr[6];
-    int net_if_type, nb_tun_fds, tun_fds[MAX_NICS];
+    int net_if_type, nb_tun_fds;
+#ifndef _WIN32
+    int tun_fds[MAX_NICS];
+#endif
     int optind;
     const char *r, *optarg;
     CharDriverState *monitor_hd;
@@ -3169,6 +3241,7 @@
             case QEMU_OPTION_append:
                 kernel_cmdline = optarg;
                 break;
+#ifndef _WIN32
            case QEMU_OPTION_tun_fd:
                 {
                     const char *p;
@@ -3184,6 +3257,7 @@
                     }
                 }
                break;
+#endif
             case QEMU_OPTION_hdc:
                 hd_filename[2] = optarg;
                 has_cdrom = 0;
@@ -3260,6 +3334,12 @@
                 net_slirp_redir(optarg);                
                 break;
 #endif
+#ifdef _WIN32
+            case QEMU_OPTION_tap:
+                net_if_type = NET_IF_TUN;
+                tap_win32_devname = optarg;
+                break;
+#endif
             case QEMU_OPTION_dummy_net:
                 net_if_type = NET_IF_DUMMY;
                 break;
@@ -3434,10 +3514,14 @@
     if (net_if_type == -1) {
         net_if_type = NET_IF_TUN;
 #if defined(CONFIG_SLIRP)
+#ifdef _WIN32
+        net_if_type = NET_IF_TUN; //NET_IF_USER;
+#else
         if (access(network_script, R_OK) < 0) {
             net_if_type = NET_IF_USER;
         }
 #endif
+#endif
     }
 
     for(i = 0; i < nb_nics; i++) {
@@ -3456,8 +3540,12 @@
             net_slirp_init(nd);
             break;
 #endif
-#if !defined(_WIN32)
         case NET_IF_TUN:
+#if defined(_WIN32)
+            if (net_tun_init(nd) < 0)
+                net_dummy_init(nd);
+            break;
+#else
             if (i < nb_tun_fds) {
                 net_fd_init(nd, tun_fds[i]);
             } else {

reply via email to

[Prev in Thread] Current Thread [Next in Thread]