[Top][All Lists]
[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 {
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] updated tap for win32 (against CVS),
Damien Mascord <=