|
|
1.1 ! root 1: /* ! 2: * TAP-Win32 -- A kernel driver to provide virtual tap device functionality ! 3: * on Windows. Originally derived from the CIPE-Win32 ! 4: * project by Damion K. Wilson, with extensive modifications by ! 5: * James Yonan. ! 6: * ! 7: * All source code which derives from the CIPE-Win32 project is ! 8: * Copyright (C) Damion K. Wilson, 2003, and is released under the ! 9: * GPL version 2 (see below). ! 10: * ! 11: * All other source code is Copyright (C) James Yonan, 2003-2004, ! 12: * and is released under the GPL version 2 (see below). ! 13: * ! 14: * This program is free software; you can redistribute it and/or modify ! 15: * it under the terms of the GNU General Public License as published by ! 16: * the Free Software Foundation; either version 2 of the License, or ! 17: * (at your option) any later version. ! 18: * ! 19: * This program is distributed in the hope that it will be useful, ! 20: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 21: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 22: * GNU General Public License for more details. ! 23: * ! 24: * You should have received a copy of the GNU General Public License ! 25: * along with this program (see the file COPYING included with this ! 26: * distribution); if not, see <http://www.gnu.org/licenses/>. ! 27: */ ! 28: ! 29: #include "net/tap.h" ! 30: ! 31: #include "qemu-common.h" ! 32: #include "net.h" ! 33: #include "sysemu.h" ! 34: #include <stdio.h> ! 35: #include <windows.h> ! 36: #include <winioctl.h> ! 37: ! 38: //============= ! 39: // TAP IOCTLs ! 40: //============= ! 41: ! 42: #define TAP_CONTROL_CODE(request,method) \ ! 43: CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) ! 44: ! 45: #define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) ! 46: #define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) ! 47: #define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) ! 48: #define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) ! 49: #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) ! 50: #define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) ! 51: #define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) ! 52: #define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) ! 53: #define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) ! 54: ! 55: //================= ! 56: // Registry keys ! 57: //================= ! 58: ! 59: #define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" ! 60: ! 61: #define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" ! 62: ! 63: //====================== ! 64: // Filesystem prefixes ! 65: //====================== ! 66: ! 67: #define USERMODEDEVICEDIR "\\\\.\\Global\\" ! 68: #define TAPSUFFIX ".tap" ! 69: ! 70: ! 71: //====================== ! 72: // Compile time configuration ! 73: //====================== ! 74: ! 75: //#define DEBUG_TAP_WIN32 ! 76: ! 77: #define TUN_ASYNCHRONOUS_WRITES 1 ! 78: ! 79: #define TUN_BUFFER_SIZE 1560 ! 80: #define TUN_MAX_BUFFER_COUNT 32 ! 81: ! 82: /* ! 83: * The data member "buffer" must be the first element in the tun_buffer ! 84: * structure. See the function, tap_win32_free_buffer. ! 85: */ ! 86: typedef struct tun_buffer_s { ! 87: unsigned char buffer [TUN_BUFFER_SIZE]; ! 88: unsigned long read_size; ! 89: struct tun_buffer_s* next; ! 90: } tun_buffer_t; ! 91: ! 92: typedef struct tap_win32_overlapped { ! 93: HANDLE handle; ! 94: HANDLE read_event; ! 95: HANDLE write_event; ! 96: HANDLE output_queue_semaphore; ! 97: HANDLE free_list_semaphore; ! 98: HANDLE tap_semaphore; ! 99: CRITICAL_SECTION output_queue_cs; ! 100: CRITICAL_SECTION free_list_cs; ! 101: OVERLAPPED read_overlapped; ! 102: OVERLAPPED write_overlapped; ! 103: tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT]; ! 104: tun_buffer_t* free_list; ! 105: tun_buffer_t* output_queue_front; ! 106: tun_buffer_t* output_queue_back; ! 107: } tap_win32_overlapped_t; ! 108: ! 109: static tap_win32_overlapped_t tap_overlapped; ! 110: ! 111: static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped) ! 112: { ! 113: tun_buffer_t* buffer = NULL; ! 114: WaitForSingleObject(overlapped->free_list_semaphore, INFINITE); ! 115: EnterCriticalSection(&overlapped->free_list_cs); ! 116: buffer = overlapped->free_list; ! 117: // assert(buffer != NULL); ! 118: overlapped->free_list = buffer->next; ! 119: LeaveCriticalSection(&overlapped->free_list_cs); ! 120: buffer->next = NULL; ! 121: return buffer; ! 122: } ! 123: ! 124: static void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer) ! 125: { ! 126: EnterCriticalSection(&overlapped->free_list_cs); ! 127: buffer->next = overlapped->free_list; ! 128: overlapped->free_list = buffer; ! 129: LeaveCriticalSection(&overlapped->free_list_cs); ! 130: ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL); ! 131: } ! 132: ! 133: static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block) ! 134: { ! 135: tun_buffer_t* buffer = NULL; ! 136: DWORD result, timeout = block ? INFINITE : 0L; ! 137: ! 138: // Non-blocking call ! 139: result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout); ! 140: ! 141: switch (result) ! 142: { ! 143: // The semaphore object was signaled. ! 144: case WAIT_OBJECT_0: ! 145: EnterCriticalSection(&overlapped->output_queue_cs); ! 146: ! 147: buffer = overlapped->output_queue_front; ! 148: overlapped->output_queue_front = buffer->next; ! 149: ! 150: if(overlapped->output_queue_front == NULL) { ! 151: overlapped->output_queue_back = NULL; ! 152: } ! 153: ! 154: LeaveCriticalSection(&overlapped->output_queue_cs); ! 155: break; ! 156: ! 157: // Semaphore was nonsignaled, so a time-out occurred. ! 158: case WAIT_TIMEOUT: ! 159: // Cannot open another window. ! 160: break; ! 161: } ! 162: ! 163: return buffer; ! 164: } ! 165: ! 166: static tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped) ! 167: { ! 168: return get_buffer_from_output_queue(overlapped, 0); ! 169: } ! 170: ! 171: static void put_buffer_on_output_queue(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer) ! 172: { ! 173: EnterCriticalSection(&overlapped->output_queue_cs); ! 174: ! 175: if(overlapped->output_queue_front == NULL && overlapped->output_queue_back == NULL) { ! 176: overlapped->output_queue_front = overlapped->output_queue_back = buffer; ! 177: } else { ! 178: buffer->next = NULL; ! 179: overlapped->output_queue_back->next = buffer; ! 180: overlapped->output_queue_back = buffer; ! 181: } ! 182: ! 183: LeaveCriticalSection(&overlapped->output_queue_cs); ! 184: ! 185: ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL); ! 186: } ! 187: ! 188: ! 189: static int is_tap_win32_dev(const char *guid) ! 190: { ! 191: HKEY netcard_key; ! 192: LONG status; ! 193: DWORD len; ! 194: int i = 0; ! 195: ! 196: status = RegOpenKeyEx( ! 197: HKEY_LOCAL_MACHINE, ! 198: ADAPTER_KEY, ! 199: 0, ! 200: KEY_READ, ! 201: &netcard_key); ! 202: ! 203: if (status != ERROR_SUCCESS) { ! 204: return FALSE; ! 205: } ! 206: ! 207: for (;;) { ! 208: char enum_name[256]; ! 209: char unit_string[256]; ! 210: HKEY unit_key; ! 211: char component_id_string[] = "ComponentId"; ! 212: char component_id[256]; ! 213: char net_cfg_instance_id_string[] = "NetCfgInstanceId"; ! 214: char net_cfg_instance_id[256]; ! 215: DWORD data_type; ! 216: ! 217: len = sizeof (enum_name); ! 218: status = RegEnumKeyEx( ! 219: netcard_key, ! 220: i, ! 221: enum_name, ! 222: &len, ! 223: NULL, ! 224: NULL, ! 225: NULL, ! 226: NULL); ! 227: ! 228: if (status == ERROR_NO_MORE_ITEMS) ! 229: break; ! 230: else if (status != ERROR_SUCCESS) { ! 231: return FALSE; ! 232: } ! 233: ! 234: snprintf (unit_string, sizeof(unit_string), "%s\\%s", ! 235: ADAPTER_KEY, enum_name); ! 236: ! 237: status = RegOpenKeyEx( ! 238: HKEY_LOCAL_MACHINE, ! 239: unit_string, ! 240: 0, ! 241: KEY_READ, ! 242: &unit_key); ! 243: ! 244: if (status != ERROR_SUCCESS) { ! 245: return FALSE; ! 246: } else { ! 247: len = sizeof (component_id); ! 248: status = RegQueryValueEx( ! 249: unit_key, ! 250: component_id_string, ! 251: NULL, ! 252: &data_type, ! 253: (LPBYTE)component_id, ! 254: &len); ! 255: ! 256: if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) { ! 257: len = sizeof (net_cfg_instance_id); ! 258: status = RegQueryValueEx( ! 259: unit_key, ! 260: net_cfg_instance_id_string, ! 261: NULL, ! 262: &data_type, ! 263: (LPBYTE)net_cfg_instance_id, ! 264: &len); ! 265: ! 266: if (status == ERROR_SUCCESS && data_type == REG_SZ) { ! 267: if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/ ! 268: !strcmp (net_cfg_instance_id, guid)) { ! 269: RegCloseKey (unit_key); ! 270: RegCloseKey (netcard_key); ! 271: return TRUE; ! 272: } ! 273: } ! 274: } ! 275: RegCloseKey (unit_key); ! 276: } ! 277: ++i; ! 278: } ! 279: ! 280: RegCloseKey (netcard_key); ! 281: return FALSE; ! 282: } ! 283: ! 284: static int get_device_guid( ! 285: char *name, ! 286: int name_size, ! 287: char *actual_name, ! 288: int actual_name_size) ! 289: { ! 290: LONG status; ! 291: HKEY control_net_key; ! 292: DWORD len; ! 293: int i = 0; ! 294: int stop = 0; ! 295: ! 296: status = RegOpenKeyEx( ! 297: HKEY_LOCAL_MACHINE, ! 298: NETWORK_CONNECTIONS_KEY, ! 299: 0, ! 300: KEY_READ, ! 301: &control_net_key); ! 302: ! 303: if (status != ERROR_SUCCESS) { ! 304: return -1; ! 305: } ! 306: ! 307: while (!stop) ! 308: { ! 309: char enum_name[256]; ! 310: char connection_string[256]; ! 311: HKEY connection_key; ! 312: char name_data[256]; ! 313: DWORD name_type; ! 314: const char name_string[] = "Name"; ! 315: ! 316: len = sizeof (enum_name); ! 317: status = RegEnumKeyEx( ! 318: control_net_key, ! 319: i, ! 320: enum_name, ! 321: &len, ! 322: NULL, ! 323: NULL, ! 324: NULL, ! 325: NULL); ! 326: ! 327: if (status == ERROR_NO_MORE_ITEMS) ! 328: break; ! 329: else if (status != ERROR_SUCCESS) { ! 330: return -1; ! 331: } ! 332: ! 333: snprintf(connection_string, ! 334: sizeof(connection_string), ! 335: "%s\\%s\\Connection", ! 336: NETWORK_CONNECTIONS_KEY, enum_name); ! 337: ! 338: status = RegOpenKeyEx( ! 339: HKEY_LOCAL_MACHINE, ! 340: connection_string, ! 341: 0, ! 342: KEY_READ, ! 343: &connection_key); ! 344: ! 345: if (status == ERROR_SUCCESS) { ! 346: len = sizeof (name_data); ! 347: status = RegQueryValueEx( ! 348: connection_key, ! 349: name_string, ! 350: NULL, ! 351: &name_type, ! 352: (LPBYTE)name_data, ! 353: &len); ! 354: ! 355: if (status != ERROR_SUCCESS || name_type != REG_SZ) { ! 356: return -1; ! 357: } ! 358: else { ! 359: if (is_tap_win32_dev(enum_name)) { ! 360: snprintf(name, name_size, "%s", enum_name); ! 361: if (actual_name) { ! 362: if (strcmp(actual_name, "") != 0) { ! 363: if (strcmp(name_data, actual_name) != 0) { ! 364: RegCloseKey (connection_key); ! 365: ++i; ! 366: continue; ! 367: } ! 368: } ! 369: else { ! 370: snprintf(actual_name, actual_name_size, "%s", name_data); ! 371: } ! 372: } ! 373: stop = 1; ! 374: } ! 375: } ! 376: ! 377: RegCloseKey (connection_key); ! 378: } ! 379: ++i; ! 380: } ! 381: ! 382: RegCloseKey (control_net_key); ! 383: ! 384: if (stop == 0) ! 385: return -1; ! 386: ! 387: return 0; ! 388: } ! 389: ! 390: static int tap_win32_set_status(HANDLE handle, int status) ! 391: { ! 392: unsigned long len = 0; ! 393: ! 394: return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS, ! 395: &status, sizeof (status), ! 396: &status, sizeof (status), &len, NULL); ! 397: } ! 398: ! 399: static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle) ! 400: { ! 401: overlapped->handle = handle; ! 402: ! 403: overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL); ! 404: overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL); ! 405: ! 406: overlapped->read_overlapped.Offset = 0; ! 407: overlapped->read_overlapped.OffsetHigh = 0; ! 408: overlapped->read_overlapped.hEvent = overlapped->read_event; ! 409: ! 410: overlapped->write_overlapped.Offset = 0; ! 411: overlapped->write_overlapped.OffsetHigh = 0; ! 412: overlapped->write_overlapped.hEvent = overlapped->write_event; ! 413: ! 414: InitializeCriticalSection(&overlapped->output_queue_cs); ! 415: InitializeCriticalSection(&overlapped->free_list_cs); ! 416: ! 417: overlapped->output_queue_semaphore = CreateSemaphore( ! 418: NULL, // default security attributes ! 419: 0, // initial count ! 420: TUN_MAX_BUFFER_COUNT, // maximum count ! 421: NULL); // unnamed semaphore ! 422: ! 423: if(!overlapped->output_queue_semaphore) { ! 424: fprintf(stderr, "error creating output queue semaphore!\n"); ! 425: } ! 426: ! 427: overlapped->free_list_semaphore = CreateSemaphore( ! 428: NULL, // default security attributes ! 429: TUN_MAX_BUFFER_COUNT, // initial count ! 430: TUN_MAX_BUFFER_COUNT, // maximum count ! 431: NULL); // unnamed semaphore ! 432: ! 433: if(!overlapped->free_list_semaphore) { ! 434: fprintf(stderr, "error creating free list semaphore!\n"); ! 435: } ! 436: ! 437: overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL; ! 438: ! 439: { ! 440: unsigned index; ! 441: for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) { ! 442: tun_buffer_t* element = &overlapped->buffers[index]; ! 443: element->next = overlapped->free_list; ! 444: overlapped->free_list = element; ! 445: } ! 446: } ! 447: /* To count buffers, initially no-signal. */ ! 448: overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL); ! 449: if(!overlapped->tap_semaphore) ! 450: fprintf(stderr, "error creating tap_semaphore.\n"); ! 451: } ! 452: ! 453: static int tap_win32_write(tap_win32_overlapped_t *overlapped, ! 454: const void *buffer, unsigned long size) ! 455: { ! 456: unsigned long write_size; ! 457: BOOL result; ! 458: DWORD error; ! 459: ! 460: result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped, ! 461: &write_size, FALSE); ! 462: ! 463: if (!result && GetLastError() == ERROR_IO_INCOMPLETE) ! 464: WaitForSingleObject(overlapped->write_event, INFINITE); ! 465: ! 466: result = WriteFile(overlapped->handle, buffer, size, ! 467: &write_size, &overlapped->write_overlapped); ! 468: ! 469: if (!result) { ! 470: switch (error = GetLastError()) ! 471: { ! 472: case ERROR_IO_PENDING: ! 473: #ifndef TUN_ASYNCHRONOUS_WRITES ! 474: WaitForSingleObject(overlapped->write_event, INFINITE); ! 475: #endif ! 476: break; ! 477: default: ! 478: return -1; ! 479: } ! 480: } ! 481: ! 482: return 0; ! 483: } ! 484: ! 485: static DWORD WINAPI tap_win32_thread_entry(LPVOID param) ! 486: { ! 487: tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param; ! 488: unsigned long read_size; ! 489: BOOL result; ! 490: DWORD dwError; ! 491: tun_buffer_t* buffer = get_buffer_from_free_list(overlapped); ! 492: ! 493: ! 494: for (;;) { ! 495: result = ReadFile(overlapped->handle, ! 496: buffer->buffer, ! 497: sizeof(buffer->buffer), ! 498: &read_size, ! 499: &overlapped->read_overlapped); ! 500: if (!result) { ! 501: dwError = GetLastError(); ! 502: if (dwError == ERROR_IO_PENDING) { ! 503: WaitForSingleObject(overlapped->read_event, INFINITE); ! 504: result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped, ! 505: &read_size, FALSE); ! 506: if (!result) { ! 507: #ifdef DEBUG_TAP_WIN32 ! 508: LPVOID lpBuffer; ! 509: dwError = GetLastError(); ! 510: FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, ! 511: NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ! 512: (LPTSTR) & lpBuffer, 0, NULL ); ! 513: fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer); ! 514: LocalFree( lpBuffer ); ! 515: #endif ! 516: } ! 517: } else { ! 518: #ifdef DEBUG_TAP_WIN32 ! 519: LPVOID lpBuffer; ! 520: FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, ! 521: NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ! 522: (LPTSTR) & lpBuffer, 0, NULL ); ! 523: fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer); ! 524: LocalFree( lpBuffer ); ! 525: #endif ! 526: } ! 527: } ! 528: ! 529: if(read_size > 0) { ! 530: buffer->read_size = read_size; ! 531: put_buffer_on_output_queue(overlapped, buffer); ! 532: ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL); ! 533: buffer = get_buffer_from_free_list(overlapped); ! 534: } ! 535: } ! 536: ! 537: return 0; ! 538: } ! 539: ! 540: static int tap_win32_read(tap_win32_overlapped_t *overlapped, ! 541: uint8_t **pbuf, int max_size) ! 542: { ! 543: int size = 0; ! 544: ! 545: tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped); ! 546: ! 547: if(buffer != NULL) { ! 548: *pbuf = buffer->buffer; ! 549: size = (int)buffer->read_size; ! 550: if(size > max_size) { ! 551: size = max_size; ! 552: } ! 553: } ! 554: ! 555: return size; ! 556: } ! 557: ! 558: static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped, ! 559: uint8_t *pbuf) ! 560: { ! 561: tun_buffer_t* buffer = (tun_buffer_t*)pbuf; ! 562: put_buffer_on_free_list(overlapped, buffer); ! 563: } ! 564: ! 565: static int tap_win32_open(tap_win32_overlapped_t **phandle, ! 566: const char *prefered_name) ! 567: { ! 568: char device_path[256]; ! 569: char device_guid[0x100]; ! 570: int rc; ! 571: HANDLE handle; ! 572: BOOL bret; ! 573: char name_buffer[0x100] = {0, }; ! 574: struct { ! 575: unsigned long major; ! 576: unsigned long minor; ! 577: unsigned long debug; ! 578: } version; ! 579: DWORD version_len; ! 580: DWORD idThread; ! 581: HANDLE hThread; ! 582: ! 583: if (prefered_name != NULL) ! 584: snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name); ! 585: ! 586: rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer)); ! 587: if (rc) ! 588: return -1; ! 589: ! 590: snprintf (device_path, sizeof(device_path), "%s%s%s", ! 591: USERMODEDEVICEDIR, ! 592: device_guid, ! 593: TAPSUFFIX); ! 594: ! 595: handle = CreateFile ( ! 596: device_path, ! 597: GENERIC_READ | GENERIC_WRITE, ! 598: 0, ! 599: 0, ! 600: OPEN_EXISTING, ! 601: FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, ! 602: 0 ); ! 603: ! 604: if (handle == INVALID_HANDLE_VALUE) { ! 605: return -1; ! 606: } ! 607: ! 608: bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION, ! 609: &version, sizeof (version), ! 610: &version, sizeof (version), &version_len, NULL); ! 611: ! 612: if (bret == FALSE) { ! 613: CloseHandle(handle); ! 614: return -1; ! 615: } ! 616: ! 617: if (!tap_win32_set_status(handle, TRUE)) { ! 618: return -1; ! 619: } ! 620: ! 621: tap_win32_overlapped_init(&tap_overlapped, handle); ! 622: ! 623: *phandle = &tap_overlapped; ! 624: ! 625: hThread = CreateThread(NULL, 0, tap_win32_thread_entry, ! 626: (LPVOID)&tap_overlapped, 0, &idThread); ! 627: return 0; ! 628: } ! 629: ! 630: /********************************************/ ! 631: ! 632: typedef struct TAPState { ! 633: VLANClientState nc; ! 634: tap_win32_overlapped_t *handle; ! 635: } TAPState; ! 636: ! 637: static void tap_cleanup(VLANClientState *nc) ! 638: { ! 639: TAPState *s = DO_UPCAST(TAPState, nc, nc); ! 640: ! 641: qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL); ! 642: ! 643: /* FIXME: need to kill thread and close file handle: ! 644: tap_win32_close(s); ! 645: */ ! 646: } ! 647: ! 648: static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size) ! 649: { ! 650: TAPState *s = DO_UPCAST(TAPState, nc, nc); ! 651: ! 652: return tap_win32_write(s->handle, buf, size); ! 653: } ! 654: ! 655: static void tap_win32_send(void *opaque) ! 656: { ! 657: TAPState *s = opaque; ! 658: uint8_t *buf; ! 659: int max_size = 4096; ! 660: int size; ! 661: ! 662: size = tap_win32_read(s->handle, &buf, max_size); ! 663: if (size > 0) { ! 664: qemu_send_packet(&s->nc, buf, size); ! 665: tap_win32_free_buffer(s->handle, buf); ! 666: } ! 667: } ! 668: ! 669: static NetClientInfo net_tap_win32_info = { ! 670: .type = NET_CLIENT_TYPE_TAP, ! 671: .size = sizeof(TAPState), ! 672: .receive = tap_receive, ! 673: .cleanup = tap_cleanup, ! 674: }; ! 675: ! 676: static int tap_win32_init(VLANState *vlan, const char *model, ! 677: const char *name, const char *ifname) ! 678: { ! 679: VLANClientState *nc; ! 680: TAPState *s; ! 681: tap_win32_overlapped_t *handle; ! 682: ! 683: if (tap_win32_open(&handle, ifname) < 0) { ! 684: printf("tap: Could not open '%s'\n", ifname); ! 685: return -1; ! 686: } ! 687: ! 688: nc = qemu_new_net_client(&net_tap_win32_info, vlan, NULL, model, name); ! 689: ! 690: s = DO_UPCAST(TAPState, nc, nc); ! 691: ! 692: snprintf(s->nc.info_str, sizeof(s->nc.info_str), ! 693: "tap: ifname=%s", ifname); ! 694: ! 695: s->handle = handle; ! 696: ! 697: qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s); ! 698: ! 699: return 0; ! 700: } ! 701: ! 702: int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan) ! 703: { ! 704: const char *ifname; ! 705: ! 706: ifname = qemu_opt_get(opts, "ifname"); ! 707: ! 708: if (!ifname) { ! 709: qemu_error("tap: no interface name\n"); ! 710: return -1; ! 711: } ! 712: ! 713: if (tap_win32_init(vlan, "tap", name, ifname) == -1) { ! 714: return -1; ! 715: } ! 716: ! 717: if (vlan) { ! 718: vlan->nb_host_devs++; ! 719: } ! 720: ! 721: return 0; ! 722: } ! 723: ! 724: int tap_has_ufo(VLANClientState *vc) ! 725: { ! 726: return 0; ! 727: } ! 728: ! 729: int tap_has_vnet_hdr(VLANClientState *vc) ! 730: { ! 731: return 0; ! 732: } ! 733: ! 734: void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) ! 735: { ! 736: } ! 737: ! 738: void tap_set_offload(VLANClientState *vc, int csum, int tso4, ! 739: int tso6, int ecn, int ufo) ! 740: { ! 741: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.