133ad161aSMark McLoughlin /*
233ad161aSMark McLoughlin * TAP-Win32 -- A kernel driver to provide virtual tap device functionality
333ad161aSMark McLoughlin * on Windows. Originally derived from the CIPE-Win32
433ad161aSMark McLoughlin * project by Damion K. Wilson, with extensive modifications by
533ad161aSMark McLoughlin * James Yonan.
633ad161aSMark McLoughlin *
733ad161aSMark McLoughlin * All source code which derives from the CIPE-Win32 project is
833ad161aSMark McLoughlin * Copyright (C) Damion K. Wilson, 2003, and is released under the
933ad161aSMark McLoughlin * GPL version 2 (see below).
1033ad161aSMark McLoughlin *
1133ad161aSMark McLoughlin * All other source code is Copyright (C) James Yonan, 2003-2004,
1233ad161aSMark McLoughlin * and is released under the GPL version 2 (see below).
1333ad161aSMark McLoughlin *
1433ad161aSMark McLoughlin * This program is free software; you can redistribute it and/or modify
1533ad161aSMark McLoughlin * it under the terms of the GNU General Public License as published by
1633ad161aSMark McLoughlin * the Free Software Foundation; either version 2 of the License, or
1733ad161aSMark McLoughlin * (at your option) any later version.
1833ad161aSMark McLoughlin *
1933ad161aSMark McLoughlin * This program is distributed in the hope that it will be useful,
2033ad161aSMark McLoughlin * but WITHOUT ANY WARRANTY; without even the implied warranty of
2133ad161aSMark McLoughlin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2233ad161aSMark McLoughlin * GNU General Public License for more details.
2333ad161aSMark McLoughlin *
2433ad161aSMark McLoughlin * You should have received a copy of the GNU General Public License
2533ad161aSMark McLoughlin * along with this program (see the file COPYING included with this
2633ad161aSMark McLoughlin * distribution); if not, see <http://www.gnu.org/licenses/>.
2733ad161aSMark McLoughlin */
28a8ed73f7SMark McLoughlin
292744d920SPeter Maydell #include "qemu/osdep.h"
301422e32dSPaolo Bonzini #include "tap_int.h"
31a8ed73f7SMark McLoughlin
3208778b39SStefan Weil #include "clients.h" /* net_init_tap */
33969e50b6SBin Meng #include "net/eth.h"
341422e32dSPaolo Bonzini #include "net/net.h"
35b2136140SStefan Weil #include "net/tap.h" /* tap_has_ufo, ... */
361de7afc9SPaolo Bonzini #include "qemu/error-report.h"
37db725815SMarkus Armbruster #include "qemu/main-loop.h"
3833ad161aSMark McLoughlin #include <windows.h>
3933ad161aSMark McLoughlin #include <winioctl.h>
4033ad161aSMark McLoughlin
4133ad161aSMark McLoughlin //=============
4233ad161aSMark McLoughlin // TAP IOCTLs
4333ad161aSMark McLoughlin //=============
4433ad161aSMark McLoughlin
4533ad161aSMark McLoughlin #define TAP_CONTROL_CODE(request,method) \
4633ad161aSMark McLoughlin CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
4733ad161aSMark McLoughlin
4833ad161aSMark McLoughlin #define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
4933ad161aSMark McLoughlin #define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)
5033ad161aSMark McLoughlin #define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED)
5133ad161aSMark McLoughlin #define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED)
5233ad161aSMark McLoughlin #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
5333ad161aSMark McLoughlin #define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED)
5433ad161aSMark McLoughlin #define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED)
5533ad161aSMark McLoughlin #define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED)
5633ad161aSMark McLoughlin #define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED)
5733ad161aSMark McLoughlin
5833ad161aSMark McLoughlin //=================
5933ad161aSMark McLoughlin // Registry keys
6033ad161aSMark McLoughlin //=================
6133ad161aSMark McLoughlin
6233ad161aSMark McLoughlin #define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
6333ad161aSMark McLoughlin
6433ad161aSMark McLoughlin #define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
6533ad161aSMark McLoughlin
6633ad161aSMark McLoughlin //======================
6733ad161aSMark McLoughlin // Filesystem prefixes
6833ad161aSMark McLoughlin //======================
6933ad161aSMark McLoughlin
7033ad161aSMark McLoughlin #define USERMODEDEVICEDIR "\\\\.\\Global\\"
7133ad161aSMark McLoughlin #define TAPSUFFIX ".tap"
7233ad161aSMark McLoughlin
7333ad161aSMark McLoughlin
7433ad161aSMark McLoughlin //======================
7533ad161aSMark McLoughlin // Compile time configuration
7633ad161aSMark McLoughlin //======================
7733ad161aSMark McLoughlin
7833ad161aSMark McLoughlin //#define DEBUG_TAP_WIN32
7933ad161aSMark McLoughlin
80b73c1849SAndrew Baumann /* FIXME: The asynch write path appears to be broken at
81b73c1849SAndrew Baumann * present. WriteFile() ignores the lpNumberOfBytesWritten parameter
82b73c1849SAndrew Baumann * for overlapped writes, with the result we return zero bytes sent,
83b73c1849SAndrew Baumann * and after handling a single packet, receive is disabled for this
84b73c1849SAndrew Baumann * interface. */
85b73c1849SAndrew Baumann /* #define TUN_ASYNCHRONOUS_WRITES 1 */
8633ad161aSMark McLoughlin
8733ad161aSMark McLoughlin #define TUN_BUFFER_SIZE 1560
8833ad161aSMark McLoughlin #define TUN_MAX_BUFFER_COUNT 32
8933ad161aSMark McLoughlin
9033ad161aSMark McLoughlin /*
9133ad161aSMark McLoughlin * The data member "buffer" must be the first element in the tun_buffer
9233ad161aSMark McLoughlin * structure. See the function, tap_win32_free_buffer.
9333ad161aSMark McLoughlin */
9433ad161aSMark McLoughlin typedef struct tun_buffer_s {
9533ad161aSMark McLoughlin unsigned char buffer [TUN_BUFFER_SIZE];
9633ad161aSMark McLoughlin unsigned long read_size;
9733ad161aSMark McLoughlin struct tun_buffer_s* next;
9833ad161aSMark McLoughlin } tun_buffer_t;
9933ad161aSMark McLoughlin
10033ad161aSMark McLoughlin typedef struct tap_win32_overlapped {
10133ad161aSMark McLoughlin HANDLE handle;
10233ad161aSMark McLoughlin HANDLE read_event;
10333ad161aSMark McLoughlin HANDLE write_event;
10433ad161aSMark McLoughlin HANDLE output_queue_semaphore;
10533ad161aSMark McLoughlin HANDLE free_list_semaphore;
10633ad161aSMark McLoughlin HANDLE tap_semaphore;
10733ad161aSMark McLoughlin CRITICAL_SECTION output_queue_cs;
10833ad161aSMark McLoughlin CRITICAL_SECTION free_list_cs;
10933ad161aSMark McLoughlin OVERLAPPED read_overlapped;
11033ad161aSMark McLoughlin OVERLAPPED write_overlapped;
11133ad161aSMark McLoughlin tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT];
11233ad161aSMark McLoughlin tun_buffer_t* free_list;
11333ad161aSMark McLoughlin tun_buffer_t* output_queue_front;
11433ad161aSMark McLoughlin tun_buffer_t* output_queue_back;
11533ad161aSMark McLoughlin } tap_win32_overlapped_t;
11633ad161aSMark McLoughlin
11733ad161aSMark McLoughlin static tap_win32_overlapped_t tap_overlapped;
11833ad161aSMark McLoughlin
get_buffer_from_free_list(tap_win32_overlapped_t * const overlapped)11933ad161aSMark McLoughlin static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped)
12033ad161aSMark McLoughlin {
12133ad161aSMark McLoughlin tun_buffer_t* buffer = NULL;
12233ad161aSMark McLoughlin WaitForSingleObject(overlapped->free_list_semaphore, INFINITE);
12333ad161aSMark McLoughlin EnterCriticalSection(&overlapped->free_list_cs);
12433ad161aSMark McLoughlin buffer = overlapped->free_list;
12533ad161aSMark McLoughlin // assert(buffer != NULL);
12633ad161aSMark McLoughlin overlapped->free_list = buffer->next;
12733ad161aSMark McLoughlin LeaveCriticalSection(&overlapped->free_list_cs);
12833ad161aSMark McLoughlin buffer->next = NULL;
12933ad161aSMark McLoughlin return buffer;
13033ad161aSMark McLoughlin }
13133ad161aSMark McLoughlin
put_buffer_on_free_list(tap_win32_overlapped_t * const overlapped,tun_buffer_t * const buffer)13233ad161aSMark McLoughlin static void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
13333ad161aSMark McLoughlin {
13433ad161aSMark McLoughlin EnterCriticalSection(&overlapped->free_list_cs);
13533ad161aSMark McLoughlin buffer->next = overlapped->free_list;
13633ad161aSMark McLoughlin overlapped->free_list = buffer;
13733ad161aSMark McLoughlin LeaveCriticalSection(&overlapped->free_list_cs);
13833ad161aSMark McLoughlin ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL);
13933ad161aSMark McLoughlin }
14033ad161aSMark McLoughlin
get_buffer_from_output_queue(tap_win32_overlapped_t * const overlapped,const int block)14133ad161aSMark McLoughlin static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block)
14233ad161aSMark McLoughlin {
14333ad161aSMark McLoughlin tun_buffer_t* buffer = NULL;
14433ad161aSMark McLoughlin DWORD result, timeout = block ? INFINITE : 0L;
14533ad161aSMark McLoughlin
14633ad161aSMark McLoughlin // Non-blocking call
14733ad161aSMark McLoughlin result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout);
14833ad161aSMark McLoughlin
14933ad161aSMark McLoughlin switch (result)
15033ad161aSMark McLoughlin {
15133ad161aSMark McLoughlin // The semaphore object was signaled.
15233ad161aSMark McLoughlin case WAIT_OBJECT_0:
15333ad161aSMark McLoughlin EnterCriticalSection(&overlapped->output_queue_cs);
15433ad161aSMark McLoughlin
15533ad161aSMark McLoughlin buffer = overlapped->output_queue_front;
15633ad161aSMark McLoughlin overlapped->output_queue_front = buffer->next;
15733ad161aSMark McLoughlin
15833ad161aSMark McLoughlin if(overlapped->output_queue_front == NULL) {
15933ad161aSMark McLoughlin overlapped->output_queue_back = NULL;
16033ad161aSMark McLoughlin }
16133ad161aSMark McLoughlin
16233ad161aSMark McLoughlin LeaveCriticalSection(&overlapped->output_queue_cs);
16333ad161aSMark McLoughlin break;
16433ad161aSMark McLoughlin
16533ad161aSMark McLoughlin // Semaphore was nonsignaled, so a time-out occurred.
16633ad161aSMark McLoughlin case WAIT_TIMEOUT:
16733ad161aSMark McLoughlin // Cannot open another window.
16833ad161aSMark McLoughlin break;
16933ad161aSMark McLoughlin }
17033ad161aSMark McLoughlin
17133ad161aSMark McLoughlin return buffer;
17233ad161aSMark McLoughlin }
17333ad161aSMark McLoughlin
get_buffer_from_output_queue_immediate(tap_win32_overlapped_t * const overlapped)17433ad161aSMark McLoughlin static tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped)
17533ad161aSMark McLoughlin {
17633ad161aSMark McLoughlin return get_buffer_from_output_queue(overlapped, 0);
17733ad161aSMark McLoughlin }
17833ad161aSMark McLoughlin
put_buffer_on_output_queue(tap_win32_overlapped_t * const overlapped,tun_buffer_t * const buffer)17933ad161aSMark McLoughlin static void put_buffer_on_output_queue(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
18033ad161aSMark McLoughlin {
18133ad161aSMark McLoughlin EnterCriticalSection(&overlapped->output_queue_cs);
18233ad161aSMark McLoughlin
18333ad161aSMark McLoughlin if(overlapped->output_queue_front == NULL && overlapped->output_queue_back == NULL) {
18433ad161aSMark McLoughlin overlapped->output_queue_front = overlapped->output_queue_back = buffer;
18533ad161aSMark McLoughlin } else {
18633ad161aSMark McLoughlin buffer->next = NULL;
18733ad161aSMark McLoughlin overlapped->output_queue_back->next = buffer;
18833ad161aSMark McLoughlin overlapped->output_queue_back = buffer;
18933ad161aSMark McLoughlin }
19033ad161aSMark McLoughlin
19133ad161aSMark McLoughlin LeaveCriticalSection(&overlapped->output_queue_cs);
19233ad161aSMark McLoughlin
19333ad161aSMark McLoughlin ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL);
19433ad161aSMark McLoughlin }
19533ad161aSMark McLoughlin
19633ad161aSMark McLoughlin
is_tap_win32_dev(const char * guid)19733ad161aSMark McLoughlin static int is_tap_win32_dev(const char *guid)
19833ad161aSMark McLoughlin {
19933ad161aSMark McLoughlin HKEY netcard_key;
20033ad161aSMark McLoughlin LONG status;
20133ad161aSMark McLoughlin DWORD len;
20233ad161aSMark McLoughlin int i = 0;
20333ad161aSMark McLoughlin
20433ad161aSMark McLoughlin status = RegOpenKeyEx(
20533ad161aSMark McLoughlin HKEY_LOCAL_MACHINE,
20633ad161aSMark McLoughlin ADAPTER_KEY,
20733ad161aSMark McLoughlin 0,
20833ad161aSMark McLoughlin KEY_READ,
20933ad161aSMark McLoughlin &netcard_key);
21033ad161aSMark McLoughlin
21133ad161aSMark McLoughlin if (status != ERROR_SUCCESS) {
21233ad161aSMark McLoughlin return FALSE;
21333ad161aSMark McLoughlin }
21433ad161aSMark McLoughlin
21533ad161aSMark McLoughlin for (;;) {
21633ad161aSMark McLoughlin char enum_name[256];
217*b5cd9f8bSBernhard Beschow g_autofree char *unit_string = NULL;
21833ad161aSMark McLoughlin HKEY unit_key;
21933ad161aSMark McLoughlin char component_id_string[] = "ComponentId";
22033ad161aSMark McLoughlin char component_id[256];
22133ad161aSMark McLoughlin char net_cfg_instance_id_string[] = "NetCfgInstanceId";
22233ad161aSMark McLoughlin char net_cfg_instance_id[256];
22333ad161aSMark McLoughlin DWORD data_type;
22433ad161aSMark McLoughlin
22533ad161aSMark McLoughlin len = sizeof (enum_name);
22633ad161aSMark McLoughlin status = RegEnumKeyEx(
22733ad161aSMark McLoughlin netcard_key,
22833ad161aSMark McLoughlin i,
22933ad161aSMark McLoughlin enum_name,
23033ad161aSMark McLoughlin &len,
23133ad161aSMark McLoughlin NULL,
23233ad161aSMark McLoughlin NULL,
23333ad161aSMark McLoughlin NULL,
23433ad161aSMark McLoughlin NULL);
23533ad161aSMark McLoughlin
23633ad161aSMark McLoughlin if (status == ERROR_NO_MORE_ITEMS)
23733ad161aSMark McLoughlin break;
23833ad161aSMark McLoughlin else if (status != ERROR_SUCCESS) {
23933ad161aSMark McLoughlin return FALSE;
24033ad161aSMark McLoughlin }
24133ad161aSMark McLoughlin
242*b5cd9f8bSBernhard Beschow unit_string = g_strdup_printf("%s\\%s", ADAPTER_KEY, enum_name);
24333ad161aSMark McLoughlin
24433ad161aSMark McLoughlin status = RegOpenKeyEx(
24533ad161aSMark McLoughlin HKEY_LOCAL_MACHINE,
24633ad161aSMark McLoughlin unit_string,
24733ad161aSMark McLoughlin 0,
24833ad161aSMark McLoughlin KEY_READ,
24933ad161aSMark McLoughlin &unit_key);
25033ad161aSMark McLoughlin
25133ad161aSMark McLoughlin if (status != ERROR_SUCCESS) {
25233ad161aSMark McLoughlin return FALSE;
25333ad161aSMark McLoughlin } else {
25433ad161aSMark McLoughlin len = sizeof (component_id);
25533ad161aSMark McLoughlin status = RegQueryValueEx(
25633ad161aSMark McLoughlin unit_key,
25733ad161aSMark McLoughlin component_id_string,
25833ad161aSMark McLoughlin NULL,
25933ad161aSMark McLoughlin &data_type,
26033ad161aSMark McLoughlin (LPBYTE)component_id,
26133ad161aSMark McLoughlin &len);
26233ad161aSMark McLoughlin
26333ad161aSMark McLoughlin if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {
26433ad161aSMark McLoughlin len = sizeof (net_cfg_instance_id);
26533ad161aSMark McLoughlin status = RegQueryValueEx(
26633ad161aSMark McLoughlin unit_key,
26733ad161aSMark McLoughlin net_cfg_instance_id_string,
26833ad161aSMark McLoughlin NULL,
26933ad161aSMark McLoughlin &data_type,
27033ad161aSMark McLoughlin (LPBYTE)net_cfg_instance_id,
27133ad161aSMark McLoughlin &len);
27233ad161aSMark McLoughlin
27333ad161aSMark McLoughlin if (status == ERROR_SUCCESS && data_type == REG_SZ) {
27433ad161aSMark McLoughlin if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/
27533ad161aSMark McLoughlin !strcmp (net_cfg_instance_id, guid)) {
27633ad161aSMark McLoughlin RegCloseKey (unit_key);
27733ad161aSMark McLoughlin RegCloseKey (netcard_key);
27833ad161aSMark McLoughlin return TRUE;
27933ad161aSMark McLoughlin }
28033ad161aSMark McLoughlin }
28133ad161aSMark McLoughlin }
28233ad161aSMark McLoughlin RegCloseKey (unit_key);
28333ad161aSMark McLoughlin }
28433ad161aSMark McLoughlin ++i;
28533ad161aSMark McLoughlin }
28633ad161aSMark McLoughlin
28733ad161aSMark McLoughlin RegCloseKey (netcard_key);
28833ad161aSMark McLoughlin return FALSE;
28933ad161aSMark McLoughlin }
29033ad161aSMark McLoughlin
get_device_guid(char * name,int name_size,char * actual_name,int actual_name_size)29133ad161aSMark McLoughlin static int get_device_guid(
29233ad161aSMark McLoughlin char *name,
29333ad161aSMark McLoughlin int name_size,
29433ad161aSMark McLoughlin char *actual_name,
29533ad161aSMark McLoughlin int actual_name_size)
29633ad161aSMark McLoughlin {
29733ad161aSMark McLoughlin LONG status;
29833ad161aSMark McLoughlin HKEY control_net_key;
29933ad161aSMark McLoughlin DWORD len;
30033ad161aSMark McLoughlin int i = 0;
30133ad161aSMark McLoughlin int stop = 0;
30233ad161aSMark McLoughlin
30333ad161aSMark McLoughlin status = RegOpenKeyEx(
30433ad161aSMark McLoughlin HKEY_LOCAL_MACHINE,
30533ad161aSMark McLoughlin NETWORK_CONNECTIONS_KEY,
30633ad161aSMark McLoughlin 0,
30733ad161aSMark McLoughlin KEY_READ,
30833ad161aSMark McLoughlin &control_net_key);
30933ad161aSMark McLoughlin
31033ad161aSMark McLoughlin if (status != ERROR_SUCCESS) {
31133ad161aSMark McLoughlin return -1;
31233ad161aSMark McLoughlin }
31333ad161aSMark McLoughlin
31433ad161aSMark McLoughlin while (!stop)
31533ad161aSMark McLoughlin {
31633ad161aSMark McLoughlin char enum_name[256];
317*b5cd9f8bSBernhard Beschow g_autofree char *connection_string = NULL;
31833ad161aSMark McLoughlin HKEY connection_key;
31933ad161aSMark McLoughlin char name_data[256];
32033ad161aSMark McLoughlin DWORD name_type;
32133ad161aSMark McLoughlin const char name_string[] = "Name";
32233ad161aSMark McLoughlin
32333ad161aSMark McLoughlin len = sizeof (enum_name);
32433ad161aSMark McLoughlin status = RegEnumKeyEx(
32533ad161aSMark McLoughlin control_net_key,
32633ad161aSMark McLoughlin i,
32733ad161aSMark McLoughlin enum_name,
32833ad161aSMark McLoughlin &len,
32933ad161aSMark McLoughlin NULL,
33033ad161aSMark McLoughlin NULL,
33133ad161aSMark McLoughlin NULL,
33233ad161aSMark McLoughlin NULL);
33333ad161aSMark McLoughlin
33433ad161aSMark McLoughlin if (status == ERROR_NO_MORE_ITEMS)
33533ad161aSMark McLoughlin break;
33633ad161aSMark McLoughlin else if (status != ERROR_SUCCESS) {
33733ad161aSMark McLoughlin return -1;
33833ad161aSMark McLoughlin }
33933ad161aSMark McLoughlin
340*b5cd9f8bSBernhard Beschow connection_string = g_strdup_printf("%s\\%s\\Connection",
34133ad161aSMark McLoughlin NETWORK_CONNECTIONS_KEY, enum_name);
34233ad161aSMark McLoughlin
34333ad161aSMark McLoughlin status = RegOpenKeyEx(
34433ad161aSMark McLoughlin HKEY_LOCAL_MACHINE,
34533ad161aSMark McLoughlin connection_string,
34633ad161aSMark McLoughlin 0,
34733ad161aSMark McLoughlin KEY_READ,
34833ad161aSMark McLoughlin &connection_key);
34933ad161aSMark McLoughlin
35033ad161aSMark McLoughlin if (status == ERROR_SUCCESS) {
35133ad161aSMark McLoughlin len = sizeof (name_data);
35233ad161aSMark McLoughlin status = RegQueryValueEx(
35333ad161aSMark McLoughlin connection_key,
35433ad161aSMark McLoughlin name_string,
35533ad161aSMark McLoughlin NULL,
35633ad161aSMark McLoughlin &name_type,
35733ad161aSMark McLoughlin (LPBYTE)name_data,
35833ad161aSMark McLoughlin &len);
35933ad161aSMark McLoughlin
36033ad161aSMark McLoughlin if (status != ERROR_SUCCESS || name_type != REG_SZ) {
361ee0428e3SAndrew Baumann ++i;
362ee0428e3SAndrew Baumann continue;
36333ad161aSMark McLoughlin }
36433ad161aSMark McLoughlin else {
36533ad161aSMark McLoughlin if (is_tap_win32_dev(enum_name)) {
36633ad161aSMark McLoughlin snprintf(name, name_size, "%s", enum_name);
36733ad161aSMark McLoughlin if (actual_name) {
36833ad161aSMark McLoughlin if (strcmp(actual_name, "") != 0) {
36933ad161aSMark McLoughlin if (strcmp(name_data, actual_name) != 0) {
37033ad161aSMark McLoughlin RegCloseKey (connection_key);
37133ad161aSMark McLoughlin ++i;
37233ad161aSMark McLoughlin continue;
37333ad161aSMark McLoughlin }
37433ad161aSMark McLoughlin }
37533ad161aSMark McLoughlin else {
37633ad161aSMark McLoughlin snprintf(actual_name, actual_name_size, "%s", name_data);
37733ad161aSMark McLoughlin }
37833ad161aSMark McLoughlin }
37933ad161aSMark McLoughlin stop = 1;
38033ad161aSMark McLoughlin }
38133ad161aSMark McLoughlin }
38233ad161aSMark McLoughlin
38333ad161aSMark McLoughlin RegCloseKey (connection_key);
38433ad161aSMark McLoughlin }
38533ad161aSMark McLoughlin ++i;
38633ad161aSMark McLoughlin }
38733ad161aSMark McLoughlin
38833ad161aSMark McLoughlin RegCloseKey (control_net_key);
38933ad161aSMark McLoughlin
39033ad161aSMark McLoughlin if (stop == 0)
39133ad161aSMark McLoughlin return -1;
39233ad161aSMark McLoughlin
39333ad161aSMark McLoughlin return 0;
39433ad161aSMark McLoughlin }
39533ad161aSMark McLoughlin
tap_win32_set_status(HANDLE handle,int status)39633ad161aSMark McLoughlin static int tap_win32_set_status(HANDLE handle, int status)
39733ad161aSMark McLoughlin {
39833ad161aSMark McLoughlin unsigned long len = 0;
39933ad161aSMark McLoughlin
40033ad161aSMark McLoughlin return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,
40133ad161aSMark McLoughlin &status, sizeof (status),
40233ad161aSMark McLoughlin &status, sizeof (status), &len, NULL);
40333ad161aSMark McLoughlin }
40433ad161aSMark McLoughlin
tap_win32_overlapped_init(tap_win32_overlapped_t * const overlapped,const HANDLE handle)40533ad161aSMark McLoughlin static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle)
40633ad161aSMark McLoughlin {
40733ad161aSMark McLoughlin overlapped->handle = handle;
40833ad161aSMark McLoughlin
40933ad161aSMark McLoughlin overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL);
41033ad161aSMark McLoughlin overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
41133ad161aSMark McLoughlin
41233ad161aSMark McLoughlin overlapped->read_overlapped.Offset = 0;
41333ad161aSMark McLoughlin overlapped->read_overlapped.OffsetHigh = 0;
41433ad161aSMark McLoughlin overlapped->read_overlapped.hEvent = overlapped->read_event;
41533ad161aSMark McLoughlin
41633ad161aSMark McLoughlin overlapped->write_overlapped.Offset = 0;
41733ad161aSMark McLoughlin overlapped->write_overlapped.OffsetHigh = 0;
41833ad161aSMark McLoughlin overlapped->write_overlapped.hEvent = overlapped->write_event;
41933ad161aSMark McLoughlin
42033ad161aSMark McLoughlin InitializeCriticalSection(&overlapped->output_queue_cs);
42133ad161aSMark McLoughlin InitializeCriticalSection(&overlapped->free_list_cs);
42233ad161aSMark McLoughlin
42333ad161aSMark McLoughlin overlapped->output_queue_semaphore = CreateSemaphore(
42433ad161aSMark McLoughlin NULL, // default security attributes
42533ad161aSMark McLoughlin 0, // initial count
42633ad161aSMark McLoughlin TUN_MAX_BUFFER_COUNT, // maximum count
42733ad161aSMark McLoughlin NULL); // unnamed semaphore
42833ad161aSMark McLoughlin
42933ad161aSMark McLoughlin if(!overlapped->output_queue_semaphore) {
43033ad161aSMark McLoughlin fprintf(stderr, "error creating output queue semaphore!\n");
43133ad161aSMark McLoughlin }
43233ad161aSMark McLoughlin
43333ad161aSMark McLoughlin overlapped->free_list_semaphore = CreateSemaphore(
43433ad161aSMark McLoughlin NULL, // default security attributes
43533ad161aSMark McLoughlin TUN_MAX_BUFFER_COUNT, // initial count
43633ad161aSMark McLoughlin TUN_MAX_BUFFER_COUNT, // maximum count
43733ad161aSMark McLoughlin NULL); // unnamed semaphore
43833ad161aSMark McLoughlin
43933ad161aSMark McLoughlin if(!overlapped->free_list_semaphore) {
44033ad161aSMark McLoughlin fprintf(stderr, "error creating free list semaphore!\n");
44133ad161aSMark McLoughlin }
44233ad161aSMark McLoughlin
44333ad161aSMark McLoughlin overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL;
44433ad161aSMark McLoughlin
44533ad161aSMark McLoughlin {
44633ad161aSMark McLoughlin unsigned index;
44733ad161aSMark McLoughlin for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) {
44833ad161aSMark McLoughlin tun_buffer_t* element = &overlapped->buffers[index];
44933ad161aSMark McLoughlin element->next = overlapped->free_list;
45033ad161aSMark McLoughlin overlapped->free_list = element;
45133ad161aSMark McLoughlin }
45233ad161aSMark McLoughlin }
45333ad161aSMark McLoughlin /* To count buffers, initially no-signal. */
45433ad161aSMark McLoughlin overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL);
45533ad161aSMark McLoughlin if(!overlapped->tap_semaphore)
45633ad161aSMark McLoughlin fprintf(stderr, "error creating tap_semaphore.\n");
45733ad161aSMark McLoughlin }
45833ad161aSMark McLoughlin
tap_win32_write(tap_win32_overlapped_t * overlapped,const void * buffer,unsigned long size)45933ad161aSMark McLoughlin static int tap_win32_write(tap_win32_overlapped_t *overlapped,
46033ad161aSMark McLoughlin const void *buffer, unsigned long size)
46133ad161aSMark McLoughlin {
46233ad161aSMark McLoughlin unsigned long write_size;
46333ad161aSMark McLoughlin BOOL result;
46433ad161aSMark McLoughlin DWORD error;
46533ad161aSMark McLoughlin
466b73c1849SAndrew Baumann #ifdef TUN_ASYNCHRONOUS_WRITES
46733ad161aSMark McLoughlin result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped,
46833ad161aSMark McLoughlin &write_size, FALSE);
46933ad161aSMark McLoughlin
47033ad161aSMark McLoughlin if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
47133ad161aSMark McLoughlin WaitForSingleObject(overlapped->write_event, INFINITE);
472b73c1849SAndrew Baumann #endif
47333ad161aSMark McLoughlin
47433ad161aSMark McLoughlin result = WriteFile(overlapped->handle, buffer, size,
47533ad161aSMark McLoughlin &write_size, &overlapped->write_overlapped);
47633ad161aSMark McLoughlin
477b73c1849SAndrew Baumann #ifdef TUN_ASYNCHRONOUS_WRITES
478b73c1849SAndrew Baumann /* FIXME: we can't sensibly set write_size here, without waiting
479b73c1849SAndrew Baumann * for the IO to complete! Moreover, we can't return zero,
480b73c1849SAndrew Baumann * because that will disable receive on this interface, and we
481b73c1849SAndrew Baumann * also can't assume it will succeed and return the full size,
482b73c1849SAndrew Baumann * because that will result in the buffer being reclaimed while
483b73c1849SAndrew Baumann * the IO is in progress. */
484b73c1849SAndrew Baumann #error Async writes are broken. Please disable TUN_ASYNCHRONOUS_WRITES.
485b73c1849SAndrew Baumann #else /* !TUN_ASYNCHRONOUS_WRITES */
48633ad161aSMark McLoughlin if (!result) {
487b73c1849SAndrew Baumann error = GetLastError();
488b73c1849SAndrew Baumann if (error == ERROR_IO_PENDING) {
489b73c1849SAndrew Baumann result = GetOverlappedResult(overlapped->handle,
490b73c1849SAndrew Baumann &overlapped->write_overlapped,
491b73c1849SAndrew Baumann &write_size, TRUE);
49233ad161aSMark McLoughlin }
49333ad161aSMark McLoughlin }
494b73c1849SAndrew Baumann #endif
495b73c1849SAndrew Baumann
496b73c1849SAndrew Baumann if (!result) {
497b73c1849SAndrew Baumann #ifdef DEBUG_TAP_WIN32
498b73c1849SAndrew Baumann LPTSTR msgbuf;
499b73c1849SAndrew Baumann error = GetLastError();
500b73c1849SAndrew Baumann FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
501b73c1849SAndrew Baumann NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
502b73c1849SAndrew Baumann &msgbuf, 0, NULL);
503b73c1849SAndrew Baumann fprintf(stderr, "Tap-Win32: Error WriteFile %d - %s\n", error, msgbuf);
504b73c1849SAndrew Baumann LocalFree(msgbuf);
505b73c1849SAndrew Baumann #endif
506b73c1849SAndrew Baumann return 0;
507b73c1849SAndrew Baumann }
50833ad161aSMark McLoughlin
509c3febae6SPavel Dovgaluk return write_size;
51033ad161aSMark McLoughlin }
51133ad161aSMark McLoughlin
tap_win32_thread_entry(LPVOID param)51233ad161aSMark McLoughlin static DWORD WINAPI tap_win32_thread_entry(LPVOID param)
51333ad161aSMark McLoughlin {
51433ad161aSMark McLoughlin tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param;
51533ad161aSMark McLoughlin unsigned long read_size;
51633ad161aSMark McLoughlin BOOL result;
51733ad161aSMark McLoughlin DWORD dwError;
51833ad161aSMark McLoughlin tun_buffer_t* buffer = get_buffer_from_free_list(overlapped);
51933ad161aSMark McLoughlin
52033ad161aSMark McLoughlin
52133ad161aSMark McLoughlin for (;;) {
52233ad161aSMark McLoughlin result = ReadFile(overlapped->handle,
52333ad161aSMark McLoughlin buffer->buffer,
52433ad161aSMark McLoughlin sizeof(buffer->buffer),
52533ad161aSMark McLoughlin &read_size,
52633ad161aSMark McLoughlin &overlapped->read_overlapped);
52733ad161aSMark McLoughlin if (!result) {
52833ad161aSMark McLoughlin dwError = GetLastError();
52933ad161aSMark McLoughlin if (dwError == ERROR_IO_PENDING) {
53033ad161aSMark McLoughlin WaitForSingleObject(overlapped->read_event, INFINITE);
53133ad161aSMark McLoughlin result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped,
53233ad161aSMark McLoughlin &read_size, FALSE);
53333ad161aSMark McLoughlin if (!result) {
53433ad161aSMark McLoughlin #ifdef DEBUG_TAP_WIN32
53533ad161aSMark McLoughlin LPVOID lpBuffer;
53633ad161aSMark McLoughlin dwError = GetLastError();
53733ad161aSMark McLoughlin FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
53833ad161aSMark McLoughlin NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
53933ad161aSMark McLoughlin (LPTSTR) & lpBuffer, 0, NULL );
54033ad161aSMark McLoughlin fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer);
54133ad161aSMark McLoughlin LocalFree( lpBuffer );
54233ad161aSMark McLoughlin #endif
54333ad161aSMark McLoughlin }
54433ad161aSMark McLoughlin } else {
54533ad161aSMark McLoughlin #ifdef DEBUG_TAP_WIN32
54633ad161aSMark McLoughlin LPVOID lpBuffer;
54733ad161aSMark McLoughlin FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
54833ad161aSMark McLoughlin NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
54933ad161aSMark McLoughlin (LPTSTR) & lpBuffer, 0, NULL );
55033ad161aSMark McLoughlin fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer);
55133ad161aSMark McLoughlin LocalFree( lpBuffer );
55233ad161aSMark McLoughlin #endif
55333ad161aSMark McLoughlin }
55433ad161aSMark McLoughlin }
55533ad161aSMark McLoughlin
55633ad161aSMark McLoughlin if(read_size > 0) {
55733ad161aSMark McLoughlin buffer->read_size = read_size;
55833ad161aSMark McLoughlin put_buffer_on_output_queue(overlapped, buffer);
55933ad161aSMark McLoughlin ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL);
56033ad161aSMark McLoughlin buffer = get_buffer_from_free_list(overlapped);
56133ad161aSMark McLoughlin }
56233ad161aSMark McLoughlin }
56333ad161aSMark McLoughlin
56433ad161aSMark McLoughlin return 0;
56533ad161aSMark McLoughlin }
56633ad161aSMark McLoughlin
tap_win32_read(tap_win32_overlapped_t * overlapped,uint8_t ** pbuf,int max_size)56733ad161aSMark McLoughlin static int tap_win32_read(tap_win32_overlapped_t *overlapped,
56833ad161aSMark McLoughlin uint8_t **pbuf, int max_size)
56933ad161aSMark McLoughlin {
57033ad161aSMark McLoughlin int size = 0;
57133ad161aSMark McLoughlin
57233ad161aSMark McLoughlin tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped);
57333ad161aSMark McLoughlin
57433ad161aSMark McLoughlin if(buffer != NULL) {
57533ad161aSMark McLoughlin *pbuf = buffer->buffer;
57633ad161aSMark McLoughlin size = (int)buffer->read_size;
57733ad161aSMark McLoughlin if(size > max_size) {
57833ad161aSMark McLoughlin size = max_size;
57933ad161aSMark McLoughlin }
58033ad161aSMark McLoughlin }
58133ad161aSMark McLoughlin
58233ad161aSMark McLoughlin return size;
58333ad161aSMark McLoughlin }
58433ad161aSMark McLoughlin
tap_win32_free_buffer(tap_win32_overlapped_t * overlapped,uint8_t * pbuf)58533ad161aSMark McLoughlin static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
58633ad161aSMark McLoughlin uint8_t *pbuf)
58733ad161aSMark McLoughlin {
58833ad161aSMark McLoughlin tun_buffer_t* buffer = (tun_buffer_t*)pbuf;
58933ad161aSMark McLoughlin put_buffer_on_free_list(overlapped, buffer);
59033ad161aSMark McLoughlin }
59133ad161aSMark McLoughlin
tap_win32_open(tap_win32_overlapped_t ** phandle,const char * preferred_name)59233ad161aSMark McLoughlin static int tap_win32_open(tap_win32_overlapped_t **phandle,
593eac29d87SStefan Weil const char *preferred_name)
59433ad161aSMark McLoughlin {
595*b5cd9f8bSBernhard Beschow g_autofree char *device_path = NULL;
59633ad161aSMark McLoughlin char device_guid[0x100];
59733ad161aSMark McLoughlin int rc;
59833ad161aSMark McLoughlin HANDLE handle;
59933ad161aSMark McLoughlin BOOL bret;
60033ad161aSMark McLoughlin char name_buffer[0x100] = {0, };
60133ad161aSMark McLoughlin struct {
60233ad161aSMark McLoughlin unsigned long major;
60333ad161aSMark McLoughlin unsigned long minor;
60433ad161aSMark McLoughlin unsigned long debug;
60533ad161aSMark McLoughlin } version;
60633ad161aSMark McLoughlin DWORD version_len;
60733ad161aSMark McLoughlin DWORD idThread;
60833ad161aSMark McLoughlin
609eac29d87SStefan Weil if (preferred_name != NULL) {
610eac29d87SStefan Weil snprintf(name_buffer, sizeof(name_buffer), "%s", preferred_name);
611eac29d87SStefan Weil }
61233ad161aSMark McLoughlin
61333ad161aSMark McLoughlin rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
61433ad161aSMark McLoughlin if (rc)
61533ad161aSMark McLoughlin return -1;
61633ad161aSMark McLoughlin
617*b5cd9f8bSBernhard Beschow device_path = g_strdup_printf("%s%s%s",
61833ad161aSMark McLoughlin USERMODEDEVICEDIR,
61933ad161aSMark McLoughlin device_guid,
62033ad161aSMark McLoughlin TAPSUFFIX);
62133ad161aSMark McLoughlin
62233ad161aSMark McLoughlin handle = CreateFile (
62333ad161aSMark McLoughlin device_path,
62433ad161aSMark McLoughlin GENERIC_READ | GENERIC_WRITE,
62533ad161aSMark McLoughlin 0,
62633ad161aSMark McLoughlin 0,
62733ad161aSMark McLoughlin OPEN_EXISTING,
62833ad161aSMark McLoughlin FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
62933ad161aSMark McLoughlin 0 );
63033ad161aSMark McLoughlin
63133ad161aSMark McLoughlin if (handle == INVALID_HANDLE_VALUE) {
63233ad161aSMark McLoughlin return -1;
63333ad161aSMark McLoughlin }
63433ad161aSMark McLoughlin
63533ad161aSMark McLoughlin bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION,
63633ad161aSMark McLoughlin &version, sizeof (version),
63733ad161aSMark McLoughlin &version, sizeof (version), &version_len, NULL);
63833ad161aSMark McLoughlin
63933ad161aSMark McLoughlin if (bret == FALSE) {
64033ad161aSMark McLoughlin CloseHandle(handle);
64133ad161aSMark McLoughlin return -1;
64233ad161aSMark McLoughlin }
64333ad161aSMark McLoughlin
64433ad161aSMark McLoughlin if (!tap_win32_set_status(handle, TRUE)) {
64533ad161aSMark McLoughlin return -1;
64633ad161aSMark McLoughlin }
64733ad161aSMark McLoughlin
64833ad161aSMark McLoughlin tap_win32_overlapped_init(&tap_overlapped, handle);
64933ad161aSMark McLoughlin
65033ad161aSMark McLoughlin *phandle = &tap_overlapped;
65133ad161aSMark McLoughlin
65249a2942dSBlue Swirl CreateThread(NULL, 0, tap_win32_thread_entry,
65333ad161aSMark McLoughlin (LPVOID)&tap_overlapped, 0, &idThread);
65433ad161aSMark McLoughlin return 0;
65533ad161aSMark McLoughlin }
65633ad161aSMark McLoughlin
65733ad161aSMark McLoughlin /********************************************/
65833ad161aSMark McLoughlin
65933ad161aSMark McLoughlin typedef struct TAPState {
6604e68f7a0SStefan Hajnoczi NetClientState nc;
66133ad161aSMark McLoughlin tap_win32_overlapped_t *handle;
66233ad161aSMark McLoughlin } TAPState;
66333ad161aSMark McLoughlin
tap_cleanup(NetClientState * nc)6644e68f7a0SStefan Hajnoczi static void tap_cleanup(NetClientState *nc)
66533ad161aSMark McLoughlin {
666dca91811SMark McLoughlin TAPState *s = DO_UPCAST(TAPState, nc, nc);
66733ad161aSMark McLoughlin
66833ad161aSMark McLoughlin qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL);
66933ad161aSMark McLoughlin
67033ad161aSMark McLoughlin /* FIXME: need to kill thread and close file handle:
67133ad161aSMark McLoughlin tap_win32_close(s);
67233ad161aSMark McLoughlin */
67333ad161aSMark McLoughlin }
67433ad161aSMark McLoughlin
tap_receive(NetClientState * nc,const uint8_t * buf,size_t size)6754e68f7a0SStefan Hajnoczi static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
67633ad161aSMark McLoughlin {
677dca91811SMark McLoughlin TAPState *s = DO_UPCAST(TAPState, nc, nc);
67833ad161aSMark McLoughlin
67933ad161aSMark McLoughlin return tap_win32_write(s->handle, buf, size);
68033ad161aSMark McLoughlin }
68133ad161aSMark McLoughlin
tap_win32_send(void * opaque)68233ad161aSMark McLoughlin static void tap_win32_send(void *opaque)
68333ad161aSMark McLoughlin {
68433ad161aSMark McLoughlin TAPState *s = opaque;
68521df394dSJason Wang uint8_t *buf, *orig_buf;
68633ad161aSMark McLoughlin int max_size = 4096;
68733ad161aSMark McLoughlin int size;
688969e50b6SBin Meng uint8_t min_pkt[ETH_ZLEN];
689969e50b6SBin Meng size_t min_pktsz = sizeof(min_pkt);
69033ad161aSMark McLoughlin
69133ad161aSMark McLoughlin size = tap_win32_read(s->handle, &buf, max_size);
69233ad161aSMark McLoughlin if (size > 0) {
69321df394dSJason Wang orig_buf = buf;
69421df394dSJason Wang
695bc38e31bSJason Wang if (net_peer_needs_padding(&s->nc)) {
696969e50b6SBin Meng if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
697969e50b6SBin Meng buf = min_pkt;
698969e50b6SBin Meng size = min_pktsz;
699969e50b6SBin Meng }
700969e50b6SBin Meng }
701969e50b6SBin Meng
702dca91811SMark McLoughlin qemu_send_packet(&s->nc, buf, size);
70321df394dSJason Wang tap_win32_free_buffer(s->handle, orig_buf);
70433ad161aSMark McLoughlin }
70533ad161aSMark McLoughlin }
70633ad161aSMark McLoughlin
tap_get_vhost_net(NetClientState * nc)7072e753bccSVincenzo Maffione struct vhost_net *tap_get_vhost_net(NetClientState *nc)
7082e753bccSVincenzo Maffione {
7092e753bccSVincenzo Maffione return NULL;
7102e753bccSVincenzo Maffione }
7112e753bccSVincenzo Maffione
712dca91811SMark McLoughlin static NetClientInfo net_tap_win32_info = {
713f394b2e2SEric Blake .type = NET_CLIENT_DRIVER_TAP,
714dca91811SMark McLoughlin .size = sizeof(TAPState),
715dca91811SMark McLoughlin .receive = tap_receive,
716dca91811SMark McLoughlin .cleanup = tap_cleanup,
717dca91811SMark McLoughlin };
718dca91811SMark McLoughlin
tap_win32_init(NetClientState * peer,const char * model,const char * name,const char * ifname)7194e68f7a0SStefan Hajnoczi static int tap_win32_init(NetClientState *peer, const char *model,
72033ad161aSMark McLoughlin const char *name, const char *ifname)
72133ad161aSMark McLoughlin {
7224e68f7a0SStefan Hajnoczi NetClientState *nc;
72333ad161aSMark McLoughlin TAPState *s;
724dca91811SMark McLoughlin tap_win32_overlapped_t *handle;
72533ad161aSMark McLoughlin
726dca91811SMark McLoughlin if (tap_win32_open(&handle, ifname) < 0) {
72733ad161aSMark McLoughlin printf("tap: Could not open '%s'\n", ifname);
72833ad161aSMark McLoughlin return -1;
72933ad161aSMark McLoughlin }
73033ad161aSMark McLoughlin
731ab5f3f84SStefan Hajnoczi nc = qemu_new_net_client(&net_tap_win32_info, peer, model, name);
73233ad161aSMark McLoughlin
73308fd0fa9SBlue Swirl s = DO_UPCAST(TAPState, nc, nc);
73408fd0fa9SBlue Swirl
73553b85d95SLaurent Vivier qemu_set_info_str(&s->nc, "tap: ifname=%s", ifname);
736d89b4f83SJason Wang
737dca91811SMark McLoughlin s->handle = handle;
738dca91811SMark McLoughlin
73933ad161aSMark McLoughlin qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s);
740dca91811SMark McLoughlin
74133ad161aSMark McLoughlin return 0;
74233ad161aSMark McLoughlin }
743a8ed73f7SMark McLoughlin
net_init_tap(const Netdev * netdev,const char * name,NetClientState * peer,Error ** errp)744cebea510SKővágó, Zoltán int net_init_tap(const Netdev *netdev, const char *name,
745a30ecde6SMarkus Armbruster NetClientState *peer, Error **errp)
746a8ed73f7SMark McLoughlin {
747a30ecde6SMarkus Armbruster /* FIXME error_setg(errp, ...) on failure */
74808c573a8SLaszlo Ersek const NetdevTapOptions *tap;
749a8ed73f7SMark McLoughlin
750f394b2e2SEric Blake assert(netdev->type == NET_CLIENT_DRIVER_TAP);
751f394b2e2SEric Blake tap = &netdev->u.tap;
752a8ed73f7SMark McLoughlin
7537480874aSMarkus Armbruster if (!tap->ifname) {
7541ecda02bSMarkus Armbruster error_report("tap: no interface name");
755a8ed73f7SMark McLoughlin return -1;
756a8ed73f7SMark McLoughlin }
757a8ed73f7SMark McLoughlin
758d33d93b2SStefan Hajnoczi if (tap_win32_init(peer, "tap", name, tap->ifname) == -1) {
759a8ed73f7SMark McLoughlin return -1;
760a8ed73f7SMark McLoughlin }
761a8ed73f7SMark McLoughlin
762a8ed73f7SMark McLoughlin return 0;
763a8ed73f7SMark McLoughlin }
764a8ed73f7SMark McLoughlin
tap_enable(NetClientState * nc)76516dbaf90SJason Wang int tap_enable(NetClientState *nc)
76616dbaf90SJason Wang {
76716dbaf90SJason Wang abort();
76816dbaf90SJason Wang }
76916dbaf90SJason Wang
tap_disable(NetClientState * nc)77016dbaf90SJason Wang int tap_disable(NetClientState *nc)
77116dbaf90SJason Wang {
77216dbaf90SJason Wang abort();
77316dbaf90SJason Wang }
774