1/********************************************************************* 2 PicoTCP. Copyright (c) 2014-2017 Altran Intelligent Systems. Some rights reserved. 3 See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage. 4 5 Authors: Maxime Vincent 6 Based on the OpenVPN tun.c driver, under GPL 7 8 NOTES: This is the Windows-only driver, a Linux-equivalent is available, too 9 You need to have an OpenVPN TUN/TAP network adapter installed, first 10 This driver is barely working: 11 * Only TAP-mode is supported (TUN is not) 12 * it will simply open the first TAP device it can find 13 * there is memory being allocated that's never freed 14 * there is no destroy function, yet 15 * it has only been tested on a Windows 7 machine 16 *********************************************************************/ 17 18#include "pico_device.h" 19#include "pico_dev_null.h" 20#include "pico_stack.h" 21#include "pico_dev_tap_windows.h" 22 23#include <Windows.h> 24#include <Winreg.h> 25#include <winioctl.h> 26#include "pico_dev_tap_windows_private.h" 27 28/* 29 * Debugging info 30 */ 31#ifdef DEBUG_TAP_GENERAL 32#define dbg_tap dbg /* first level debug */ 33#else 34#define dbg_tap(...) do{} while(0) 35#endif 36 37#ifdef DEBUG_TAP_INFO 38#define dbg_tap_info dbg /* tap info messages */ 39#else 40#define dbg_tap_info(...) do{} while(0) 41#endif 42 43#ifdef DEBUG_TAP_WIN 44#define dbg_tap_win32 dbg /* second level detailed win32 debug */ 45#else 46#define dbg_tap_win32(...) do{} while(0) 47#endif 48 49#ifdef DEBUG_TAP_REG 50#define dbg_tap_reg dbg /* third level: registry debug */ 51#else 52#define dbg_tap_reg(...) do{} while(0) 53#endif 54 55/* 56 * Tunnel types 57 */ 58#define DEV_TYPE_UNDEF 0 59#define DEV_TYPE_NULL 1 60#define DEV_TYPE_TUN 2 /* point-to-point IP tunnel */ 61#define DEV_TYPE_TAP 3 /* ethernet (802.3) tunnel */ 62 63 64/* 65 * We try to do all Win32 I/O using overlapped 66 * (i.e. asynchronous) I/O for a performance win. 67 */ 68struct overlapped_io { 69# define IOSTATE_INITIAL 0 70# define IOSTATE_QUEUED 1 /* overlapped I/O has been queued */ 71# define IOSTATE_IMMEDIATE_RETURN 2 /* I/O function returned immediately without queueing */ 72 int iostate; 73 OVERLAPPED overlapped; 74 DWORD size; 75 DWORD flags; 76 int status; 77 int addr_defined; 78 uint8_t *buf_init; 79 uint32_t buf_init_len; 80 uint8_t *buf; 81 uint32_t buf_len; 82}; 83 84struct rw_handle { 85 HANDLE read; 86 HANDLE write; 87}; 88 89struct tuntap 90{ 91 int type; /* DEV_TYPE_x as defined in proto.h */ 92 int ipv6; 93 int persistent_if; /* if existed before, keep on program end */ 94 char *actual_name; /* actual name of TUN/TAP dev, usually including unit number */ 95 int post_open_mtu; 96 uint8_t mac[6]; 97 98 /* Windows stuff */ 99 DWORD adapter_index; /*adapter index for TAP-Windows adapter, ~0 if undefined */ 100 HANDLE hand; 101 struct overlapped_io reads; /* for overlapped IO */ 102 struct overlapped_io writes; 103 struct rw_handle rw_handle; 104 105}; 106 107 108struct pico_device_tap { 109 struct pico_device dev; 110 int statistics_frames_out; 111 struct tuntap *tt; 112}; 113 114 115/* 116 * Private function prototypes 117 */ 118const struct tap_reg *get_tap_reg (void); 119const struct panel_reg *get_panel_reg (void); 120 121 122/* 123 * Private functions 124 */ 125 126/* Get TAP info from Windows registry */ 127const struct tap_reg *get_tap_reg (void) 128{ 129 HKEY adapter_key; 130 LONG status; 131 DWORD len; 132 struct tap_reg *first = NULL; 133 struct tap_reg *last = NULL; 134 int i = 0; 135 136 status = RegOpenKeyEx( 137 HKEY_LOCAL_MACHINE, 138 ADAPTER_KEY, 139 0, 140 KEY_READ, 141 &adapter_key); 142 143 if (status != ERROR_SUCCESS) 144 { 145 dbg_tap_reg("Error opening registry key: %s\n", ADAPTER_KEY); 146 return NULL; 147 } 148 149 while (1) 150 { 151 char enum_name[256]; 152 char unit_string[256]; 153 HKEY unit_key; 154 char component_id_string[] = "ComponentId"; 155 char component_id[256]; 156 char net_cfg_instance_id_string[] = "NetCfgInstanceId"; 157 char net_cfg_instance_id[256]; 158 DWORD data_type; 159 160 len = sizeof (enum_name); 161 status = RegEnumKeyEx( 162 adapter_key, 163 i, 164 enum_name, 165 &len, 166 NULL, 167 NULL, 168 NULL, 169 NULL); 170 if (status == ERROR_NO_MORE_ITEMS) 171 break; 172 else if (status != ERROR_SUCCESS) 173 dbg_tap_reg("Error enumerating registry subkeys of key: %s.\n", ADAPTER_KEY); 174 175 snprintf (unit_string, sizeof(unit_string), "%s\\%s", 176 ADAPTER_KEY, enum_name); 177 178 status = RegOpenKeyEx( 179 HKEY_LOCAL_MACHINE, 180 unit_string, 181 0, 182 KEY_READ, 183 &unit_key); 184 185 if (status != ERROR_SUCCESS) 186 { 187 dbg_tap_reg("Error opening registry key: %s\n", unit_string); 188 } 189 else 190 { 191 len = sizeof (component_id); 192 status = RegQueryValueEx( 193 unit_key, 194 component_id_string, 195 NULL, 196 &data_type, 197 (LPBYTE)component_id, 198 &len); 199 200 if (status != ERROR_SUCCESS || data_type != REG_SZ) 201 { 202 dbg_tap_reg("Error opening registry key: %s\\%s\n", unit_string, component_id_string); 203 } 204 else 205 { 206 len = sizeof (net_cfg_instance_id); 207 status = RegQueryValueEx( 208 unit_key, 209 net_cfg_instance_id_string, 210 NULL, 211 &data_type, 212 (LPBYTE)net_cfg_instance_id, 213 &len); 214 215 if (status == ERROR_SUCCESS && data_type == REG_SZ) 216 { 217 if (!strcmp (component_id, TAP_WIN_COMPONENT_ID)) 218 { 219 struct tap_reg *reg; 220 reg = PICO_ZALLOC(sizeof(struct tap_reg), 1); 221 /* ALLOC_OBJ_CLEAR_GC (reg, struct tap_reg, gc); */ 222 if (!reg) 223 return NULL; 224 225 /* reg->guid = string_alloc (net_cfg_instance_id, gc); */ 226 reg->guid = PICO_ZALLOC (strlen(net_cfg_instance_id) + 1, 1); 227 if (!(reg->guid)) 228 { 229 PICO_FREE(reg); 230 return NULL; 231 } 232 233 strcpy((char *)reg->guid, net_cfg_instance_id); 234 /* link into return list */ 235 if (!first) 236 first = reg; 237 238 if (last) 239 last->next = reg; 240 241 last = reg; 242 } 243 } 244 } 245 246 RegCloseKey (unit_key); 247 } 248 249 ++i; 250 } 251 RegCloseKey (adapter_key); 252 return first; 253} 254 255/* Get Panel info from Windows registry */ 256const struct panel_reg *get_panel_reg (void) 257{ 258 LONG status; 259 HKEY network_connections_key; 260 DWORD len; 261 struct panel_reg *first = NULL; 262 struct panel_reg *last = NULL; 263 int i = 0; 264 265 status = RegOpenKeyEx( 266 HKEY_LOCAL_MACHINE, 267 NETWORK_CONNECTIONS_KEY, 268 0, 269 KEY_READ, 270 &network_connections_key); 271 272 if (status != ERROR_SUCCESS) 273 { 274 dbg_tap_reg("Error opening registry key: %s\n", NETWORK_CONNECTIONS_KEY); 275 return NULL; 276 } 277 278 while (1) 279 { 280 char enum_name[256]; 281 char connection_string[256]; 282 HKEY connection_key; 283 WCHAR name_data[256]; 284 DWORD name_type; 285 const WCHAR name_string[] = L"Name"; 286 287 len = sizeof (enum_name); 288 status = RegEnumKeyEx( 289 network_connections_key, 290 i, 291 enum_name, 292 &len, 293 NULL, 294 NULL, 295 NULL, 296 NULL); 297 if (status == ERROR_NO_MORE_ITEMS) 298 break; 299 else if (status != ERROR_SUCCESS) 300 dbg_tap_reg("Error enumerating registry subkeys of key: %s.\n", NETWORK_CONNECTIONS_KEY); 301 302 snprintf (connection_string, sizeof(connection_string), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, enum_name); 303 304 status = RegOpenKeyEx( 305 HKEY_LOCAL_MACHINE, 306 connection_string, 307 0, 308 KEY_READ, 309 &connection_key); 310 if (status != ERROR_SUCCESS) 311 dbg_tap_reg("Error opening registry key: %s\n", connection_string); 312 else 313 { 314 len = sizeof (name_data); 315 status = RegQueryValueExW( 316 connection_key, 317 name_string, 318 NULL, 319 &name_type, 320 (LPBYTE) name_data, 321 &len); 322 323 if (status != ERROR_SUCCESS || name_type != REG_SZ) 324 dbg_tap_reg("Error opening registry key: %s\\%s\\%S\n", NETWORK_CONNECTIONS_KEY, connection_string, name_string); 325 else 326 { 327 int n; 328 LPSTR name; 329 struct panel_reg *reg; 330 331 /* ALLOC_OBJ_CLEAR_GC (reg, struct panel_reg, gc); */ 332 reg = PICO_ZALLOC(sizeof(struct panel_reg), 1); 333 if (!reg) 334 return NULL; 335 336 n = WideCharToMultiByte (CP_UTF8, 0, name_data, -1, NULL, 0, NULL, NULL); 337 /* name = gc_malloc (n, false, gc); */ 338 name = PICO_ZALLOC(n, 1); 339 if (!name) 340 { 341 PICO_FREE(reg); 342 return NULL; 343 } 344 345 WideCharToMultiByte (CP_UTF8, 0, name_data, -1, name, n, NULL, NULL); 346 reg->name = name; 347 /* reg->guid = string_alloc (enum_name, gc); */ 348 reg->guid = PICO_ZALLOC(strlen(enum_name) + 1, 1); 349 if (!reg->guid) 350 { 351 PICO_FREE((void *)reg->name); 352 PICO_FREE((void *)reg); 353 return NULL; 354 } 355 356 strcpy((char *)reg->guid, enum_name); 357 358 /* link into return list */ 359 if (!first) 360 first = reg; 361 362 if (last) 363 last->next = reg; 364 365 last = reg; 366 } 367 368 RegCloseKey (connection_key); 369 } 370 371 ++i; 372 } 373 RegCloseKey (network_connections_key); 374 375 return first; 376} 377 378 379void show_tap_win_adapters (void) 380{ 381 int warn_panel_null = 0; 382 int warn_panel_dup = 0; 383 int warn_tap_dup = 0; 384 385 int links; 386 387 const struct tap_reg *tr; 388 const struct tap_reg *tr1; 389 const struct panel_reg *pr; 390 391 const struct tap_reg *tap_reg = get_tap_reg (); 392 const struct panel_reg *panel_reg = get_panel_reg (); 393 394 if (!(tap_reg && panel_reg)) 395 return; 396 397 dbg_tap_info("Available TAP-WIN32 adapters [name, GUID]:\n"); 398 399 /* loop through each TAP-Windows adapter registry entry */ 400 for (tr = tap_reg; tr != NULL; tr = tr->next) 401 { 402 links = 0; 403 404 /* loop through each network connections entry in the control panel */ 405 for (pr = panel_reg; pr != NULL; pr = pr->next) 406 { 407 if (!strcmp (tr->guid, pr->guid)) 408 { 409 dbg_tap_info("\t>> '%s' %s\n", pr->name, tr->guid); 410 ++links; 411 } 412 } 413 if (links > 1) 414 { 415 warn_panel_dup = 1; 416 } 417 else if (links == 0) 418 { 419 /* a TAP adapter exists without a link from the network 420 connections control panel */ 421 warn_panel_null = 1; 422 dbg_tap_info("\t>> [NULL] %s\n", tr->guid); 423 } 424 } 425 /* check for TAP-Windows adapter duplicated GUIDs */ 426 for (tr = tap_reg; tr != NULL; tr = tr->next) 427 { 428 for (tr1 = tap_reg; tr1 != NULL; tr1 = tr1->next) 429 { 430 if (tr != tr1 && !strcmp (tr->guid, tr1->guid)) 431 warn_tap_dup = 1; 432 } 433 } 434 /* warn on registry inconsistencies */ 435 if (warn_tap_dup) 436 dbg_tap_info("WARNING: Some TAP-Windows adapters have duplicate GUIDs\n"); 437 438 if (warn_panel_dup) 439 dbg_tap_info("WARNING: Some TAP-Windows adapters have duplicate links from the Network Connections control panel\n"); 440 441 if (warn_panel_null) 442 dbg_tap_info("WARNING: Some TAP-Windows adapters have no link from the Network Connections control panel\n"); 443} 444 445 446/* Get the GUID of the first TAP device found */ 447const char *get_first_device_guid(const struct tap_reg *tap_reg, const struct panel_reg *panel_reg, char *name) 448{ 449 const struct tap_reg *tr; 450 const struct panel_reg *pr; 451 /* loop through each TAP-Windows adapter registry entry */ 452 for (tr = tap_reg; tr != NULL; tr = tr->next) 453 { 454 /* loop through each network connections entry in the control panel */ 455 for (pr = panel_reg; pr != NULL; pr = pr->next) 456 { 457 if (!strcmp (tr->guid, pr->guid)) 458 { 459 dbg_tap_info("Using first TAP device: '%s' %s\n", pr->name, tr->guid); 460 if (name) 461 strcpy(name, pr->name); 462 463 return tr->guid; 464 } 465 } 466 } 467 return NULL; 468} 469 470 471 472int open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) 473{ 474 char device_path[256]; 475 const char *device_guid = NULL; 476 DWORD len; 477 478 dbg_tap_info("open_tun, tt->ipv6=%d\n", tt->ipv6 ); 479 480 if (!(tt->type == DEV_TYPE_TAP || tt->type == DEV_TYPE_TUN)) 481 { 482 dbg_tap_info("Unknown virtual device type: '%s'\n", dev); 483 return -1; 484 } 485 486 /* 487 * Lookup the device name in the registry, using the --dev-node high level name. 488 */ 489 { 490 const struct tap_reg *tap_reg = get_tap_reg(); 491 const struct panel_reg *panel_reg = get_panel_reg(); 492 char name[256]; 493 494 if (!(tap_reg && panel_reg)) 495 { 496 dbg_tap_info("No TUN/TAP devices found\n"); 497 return -1; 498 } 499 500 /* Get the device GUID for the device specified with --dev-node. */ 501 device_guid = get_first_device_guid (tap_reg, panel_reg, name); 502 503 if (!device_guid) 504 dbg_tap_info("TAP-Windows adapter '%s' not found\n", dev_node); 505 506 /* Open Windows TAP-Windows adapter */ 507 snprintf (device_path, sizeof(device_path), "%s%s%s", 508 USERMODEDEVICEDIR, 509 device_guid, 510 TAP_WIN_SUFFIX); 511 512 tt->hand = CreateFile ( 513 device_path, 514 GENERIC_READ | GENERIC_WRITE, 515 0, /* was: FILE_SHARE_READ */ 516 0, 517 OPEN_EXISTING, 518 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 519 0 520 ); 521 522 if (tt->hand == INVALID_HANDLE_VALUE) 523 dbg_tap_info("CreateFile failed on TAP device: %s\n", device_path); 524 525 /* translate high-level device name into a device instance 526 GUID using the registry */ 527 tt->actual_name = PICO_ZALLOC(strlen(name) + 1); 528 if (tt->actual_name) 529 strcpy(tt->actual_name, name); 530 } 531 532 dbg_tap_info("TAP-WIN32 device [%s] opened: %s\n", tt->actual_name, device_path); 533 /* TODO TODO TODO */ 534 /* tt->adapter_index = get_adapter_index (device_guid); */ 535 536 /* get driver version info */ 537 { 538 ULONG info[3]; 539 /* TODO TODO TODO */ 540 /* CLEAR (info); */ 541 if (DeviceIoControl (tt->hand, TAP_WIN_IOCTL_GET_VERSION, &info, sizeof (info), &info, sizeof (info), &len, NULL)) 542 { 543 dbg_tap_info ("TAP-Windows Driver Version %d.%d %s\n", 544 (int) info[0], 545 (int) info[1], 546 (info[2] ? "(DEBUG)" : "")); 547 548 } 549 550 if (!(info[0] == TAP_WIN_MIN_MAJOR && info[1] >= TAP_WIN_MIN_MINOR)) 551 dbg_tap_info ("ERROR: This version of " PACKAGE_NAME " requires a TAP-Windows driver that is at least version %d.%d \ 552 -- If you recently upgraded your " PACKAGE_NAME " distribution, \ 553 a reboot is probably required at this point to get Windows to see the new driver.\n", 554 TAP_WIN_MIN_MAJOR, 555 TAP_WIN_MIN_MINOR); 556 557 /* usage of numeric constants is ugly, but this is really tied to 558 * *this* version of the driver 559 */ 560 if ( tt->ipv6 && tt->type == DEV_TYPE_TUN && info[0] == 9 && info[1] < 8) 561 { 562 dbg_tap_info("WARNING: Tap-Win32 driver version %d.%d does not support IPv6 in TUN mode. IPv6 will be disabled. \ 563 Upgrade to Tap-Win32 9.8 (2.2-beta3 release or later) or use TAP mode to get IPv6\n", (int) info[0], (int) info[1] ); 564 tt->ipv6 = 0; 565 } 566 567 /* tap driver 9.8 (2.2.0 and 2.2.1 release) is buggy 568 */ 569 if ( tt->type == DEV_TYPE_TUN && info[0] == 9 && info[1] == 8) 570 { 571 dbg_tap_info("ERROR: Tap-Win32 driver version %d.%d is buggy regarding small IPv4 packets in TUN mode. Upgrade to Tap-Win32 9.9 (2.2.2 release or later) or use TAP mode\n", (int) info[0], (int) info[1] ); 572 } 573 } 574 575 /* get driver MTU */ 576 { 577 ULONG mtu; 578 if (DeviceIoControl (tt->hand, TAP_WIN_IOCTL_GET_MTU, 579 &mtu, sizeof (mtu), 580 &mtu, sizeof (mtu), &len, NULL)) 581 { 582 tt->post_open_mtu = (int) mtu; 583 dbg_tap_info("TAP-Windows MTU=%d\n", (int) mtu); 584 } 585 } 586 587 588 /* get driver MAC */ 589 { 590 uint8_t mac[6] = { 591 0, 0, 0, 0, 0, 0 592 }; 593 if (DeviceIoControl (tt->hand, TAP_WIN_IOCTL_GET_MAC, 594 mac, sizeof (mac), 595 mac, sizeof (mac), &len, NULL)) 596 { 597 dbg_tap_info("TAP-Windows MAC=[%x,%x,%x,%x,%x,%x]\n", mac[0], mac[1], mac[2], 598 mac[2], mac[4], mac[5]); 599 memcpy(tt->mac, mac, sizeof(mac)); 600 } 601 } 602 603 /* set point-to-point mode if TUN device */ 604 605 if (tt->type == DEV_TYPE_TUN) 606 { 607 dbg_tap_info("TUN type not supported for now...\n"); 608 return -1; 609 } 610 else if (tt->type == DEV_TYPE_TAP) 611 { /* TAP DEVICE */ 612 dbg_tap_info("TODO: Set Point-to-point through DeviceIoControl\n"); 613 } 614 615 /* set driver media status to 'connected' */ 616 { 617 ULONG status = TRUE; 618 if (!DeviceIoControl (tt->hand, TAP_WIN_IOCTL_SET_MEDIA_STATUS, 619 &status, sizeof (status), 620 &status, sizeof (status), &len, NULL)) 621 dbg_tap_info("WARNING: The TAP-Windows driver rejected a TAP_WIN_IOCTL_SET_MEDIA_STATUS DeviceIoControl call."); 622 } 623 624 return 0; 625} 626 627 628 629 630/* TODO: Closing a TUN device is currently not implemented */ 631/* 632 void close_tun (struct tuntap *tt) 633 { 634 (void)tt; 635 } 636 */ 637 638 639int tap_win_getinfo (const struct tuntap *tt, char *buf, int bufsize) 640{ 641 if (tt && tt->hand != NULL && buf != NULL) 642 { 643 DWORD len; 644 if (DeviceIoControl (tt->hand, TAP_WIN_IOCTL_GET_INFO, 645 buf, bufsize, 646 buf, bufsize, 647 &len, NULL)) 648 { 649 return 0; 650 } 651 } 652 653 return -1; 654} 655 656void tun_show_debug (struct tuntap *tt, char *buf, int bufsize) 657{ 658 if (tt && tt->hand != NULL && buf != NULL) 659 { 660 DWORD len; 661 while (DeviceIoControl (tt->hand, TAP_WIN_IOCTL_GET_LOG_LINE, 662 buf, bufsize, 663 buf, bufsize, 664 &len, NULL)) 665 { 666 dbg_tap_info("TAP-Windows: %s\n", buf); 667 } 668 } 669} 670 671 672/* returns the state */ 673int tun_read_queue (struct tuntap *tt, uint8_t *buffer, int maxsize) 674{ 675 if (tt->reads.iostate == IOSTATE_INITIAL) 676 { 677 DWORD len = 1500; 678 BOOL status; 679 int err; 680 681 /* reset buf to its initial state */ 682 tt->reads.buf = tt->reads.buf_init; 683 tt->reads.buf_len = tt->reads.buf_init_len; 684 685 len = maxsize ? maxsize : (tt->reads.buf_len); 686 if (len > (tt->reads.buf_len)) /* clip to buffer len */ 687 len = tt->reads.buf_len; 688 689 /* the overlapped read will signal this event on I/O completion */ 690 if (!ResetEvent (tt->reads.overlapped.hEvent)) 691 dbg_tap("ResetEvent failed\n"); 692 693 status = ReadFile( 694 tt->hand, 695 buffer, 696 len, 697 &tt->reads.size, 698 &tt->reads.overlapped 699 ); 700 701 if (status) /* operation completed immediately? */ 702 { 703 /* since we got an immediate return, we must signal the event object ourselves */ 704 /* ASSERT (SetEvent (tt->reads.overlapped.hEvent)); */ 705 if (!SetEvent (tt->reads.overlapped.hEvent)) 706 dbg_tap("SetEvent failed\n"); 707 708 tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN; 709 tt->reads.status = 0; 710 711 dbg_tap_win32 ("WIN32 I/O: TAP Read immediate return [%d,%d]\n", 712 (int) len, 713 (int) tt->reads.size); 714 } 715 else 716 { 717 err = GetLastError (); 718 if (err == ERROR_IO_PENDING) /* operation queued? */ 719 { 720 tt->reads.iostate = IOSTATE_QUEUED; 721 tt->reads.status = err; 722 dbg_tap_win32 ("WIN32 I/O: TAP Read queued [%d]\n", (int) len); 723 } 724 else /* error occurred */ 725 { 726 if (!SetEvent (tt->reads.overlapped.hEvent)) 727 dbg_tap("SetEvent failed\n"); 728 729 tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN; 730 tt->reads.status = err; 731 dbg_tap ("WIN32 I/O: TAP Read error [%d] : %d\n", (int) len, (int) err); 732 } 733 } 734 } 735 736 return tt->reads.iostate; 737} 738 739/* Finalize any pending overlapped IO's */ 740int tun_finalize(HANDLE h, struct overlapped_io *io, uint8_t **buf, uint32_t *buf_len) 741{ 742 int ret = -1; 743 BOOL status; 744 745 switch (io->iostate) 746 { 747 case IOSTATE_QUEUED: 748 status = GetOverlappedResult( 749 h, 750 &io->overlapped, 751 &io->size, 752 0u 753 ); 754 if (status) 755 { 756 /* successful return for a queued operation */ 757 if (buf) 758 { 759 *buf = io->buf; 760 *buf_len = io->buf_len; 761 } 762 763 ret = io->size; 764 io->iostate = IOSTATE_INITIAL; 765 766 if (!ResetEvent (io->overlapped.hEvent)) 767 dbg_tap("ResetEvent in finalize failed!\n"); 768 769 dbg_tap_win32 ("WIN32 I/O: TAP Completion success: QUEUED! [%d]\n", ret); 770 } 771 else 772 { 773 /* error during a queued operation */ 774 /* error, or just not completed? */ 775 ret = 0; 776 if (GetLastError() != ERROR_IO_INCOMPLETE) 777 { 778 /* if no error (i.e. just not finished yet), 779 then DON'T execute this code */ 780 io->iostate = IOSTATE_INITIAL; 781 if (!ResetEvent (io->overlapped.hEvent)) 782 dbg_tap("ResetEvent in finalize failed!\n"); 783 784 dbg_tap("WIN32 I/O: TAP Completion error\n"); 785 ret = -1; /* There actually was an error */ 786 } 787 } 788 789 break; 790 791 case IOSTATE_IMMEDIATE_RETURN: 792 io->iostate = IOSTATE_INITIAL; 793 if (!ResetEvent (io->overlapped.hEvent)) 794 dbg_tap("ResetEvent in finalize failed!\n"); 795 796 if (io->status) 797 { 798 /* error return for a non-queued operation */ 799 SetLastError (io->status); 800 ret = -1; 801 dbg_tap("WIN32 I/O: TAP Completion non-queued error\n"); 802 } 803 else 804 { 805 /* successful return for a non-queued operation */ 806 if (buf) 807 *buf = io->buf; 808 809 ret = io->size; 810 dbg_tap_win32 ("WIN32 I/O: TAP Completion non-queued success [%d]\n", ret); 811 } 812 813 break; 814 815 case IOSTATE_INITIAL: /* were we called without proper queueing? */ 816 SetLastError (ERROR_INVALID_FUNCTION); 817 ret = -1; 818 dbg_tap ("WIN32 I/O: TAP Completion BAD STATE\n"); 819 break; 820 821 default: 822 dbg_tap ("Some weird case happened..\n"); 823 } 824 825 if (buf) 826 *buf_len = ret; 827 828 return ret; 829} 830 831 832 833/* returns the amount of bytes written */ 834int tun_write_queue (struct tuntap *tt, uint8_t *buf, uint32_t buf_len) 835{ 836 if (tt->writes.iostate == IOSTATE_INITIAL) 837 { 838 BOOL status; 839 int err; 840 841 /* make a private copy of buf */ 842 tt->writes.buf = tt->writes.buf_init; 843 tt->writes.buf_len = buf_len; 844 memcpy(tt->writes.buf, buf, buf_len); 845 846 /* the overlapped write will signal this event on I/O completion */ 847 if (!ResetEvent (tt->writes.overlapped.hEvent)) 848 dbg_tap("ResetEvent in write_queue failed!\n"); 849 850 status = WriteFile( 851 tt->hand, 852 tt->writes.buf, 853 tt->writes.buf_len, 854 &tt->writes.size, 855 &tt->writes.overlapped 856 ); 857 858 if (status) /* operation completed immediately? */ 859 { 860 tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN; 861 862 /* since we got an immediate return, we must signal the event object ourselves */ 863 if (!SetEvent (tt->writes.overlapped.hEvent)) 864 dbg_tap("SetEvent in write_queue failed!\n"); 865 866 tt->writes.status = 0; 867 868 dbg_tap_win32 ("WIN32 I/O: TAP Write immediate return [%d,%d]\n", 869 (int)(tt->writes.buf_len), 870 (int)tt->writes.size); 871 } 872 else 873 { 874 err = GetLastError (); 875 if (err == ERROR_IO_PENDING) /* operation queued? */ 876 { 877 tt->writes.iostate = IOSTATE_QUEUED; 878 tt->writes.status = err; 879 dbg_tap_win32("WIN32 I/O: TAP Write queued [%d]\n", 880 (tt->writes.buf_len)); 881 } 882 else /* error occurred */ 883 { 884 if (!SetEvent (tt->writes.overlapped.hEvent)) 885 dbg_tap("SetEvent in write_queue failed!\n"); 886 887 tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN; 888 tt->writes.status = err; 889 dbg_tap ("WIN32 I/O: TAP Write error [%d] : %d\n", (int) &tt->writes.buf_len, (int) err); 890 } 891 } 892 } 893 894 return tt->writes.iostate; 895} 896 897static inline int overlapped_io_active (struct overlapped_io *o) 898{ 899 return o->iostate == IOSTATE_QUEUED || o->iostate == IOSTATE_IMMEDIATE_RETURN; 900} 901 902/* if >= 0: returns the amount of bytes read, otherwise error! */ 903static int tun_write_win32 (struct tuntap *tt, uint8_t *buf, uint32_t buf_len) 904{ 905 int err = 0; 906 int status = 0; 907 if (overlapped_io_active (&tt->writes)) 908 { 909 status = tun_finalize (tt->hand, &tt->writes, NULL, 0); 910 if (status == 0) 911 { 912 /* busy, just wait, do not schedule a new write */ 913 return 0; 914 } 915 916 if (status < 0) 917 err = GetLastError (); 918 } 919 920 /* the overlapped IO is done, now we can schedule a new write */ 921 tun_write_queue (tt, buf, buf_len); 922 if (status < 0) 923 { 924 SetLastError (err); 925 return status; 926 } 927 else 928 return buf_len; 929} 930 931 932/* if >= 0: returns the amount of bytes read, otherwise error! */ 933static int tun_read_win32 (struct tuntap *tt, uint8_t *buf, uint32_t buf_len) 934{ 935 int err = 0; 936 int status = 0; 937 938 939 /* First, finish possible pending IOs */ 940 if (overlapped_io_active (&tt->reads)) 941 { 942 status = tun_finalize (tt->hand, &tt->reads, &buf, &buf_len); 943 if (status == 0) 944 { 945 /* busy, just wait, do not schedule a new read */ 946 return 0; 947 } 948 949 if (status < 0) 950 { 951 dbg_tap ("tun_finalize status < 0: %d\n", status); 952 err = GetLastError (); 953 } 954 955 if (status > 0) 956 { 957 return buf_len; 958 } 959 } 960 961 /* If no pending IOs, schedule a new read */ 962 /* queue, or immediate return */ 963 if (IOSTATE_IMMEDIATE_RETURN == tun_read_queue(tt, buf, buf_len)) 964 { 965 return tt->reads.size; 966 } 967 968 /* If the pending IOs gave an error, report it */ 969 if (status < 0) 970 { 971 SetLastError (err); 972 return status; 973 } 974 else 975 { 976 /* no errors, but the newly scheduled read is now pending */ 977 return 0; 978 } 979} 980 981 982static int read_tun_buffered(struct tuntap *tt, uint8_t *buf, uint32_t buf_len) 983{ 984 return tun_read_win32 (tt, buf, buf_len); 985} 986 987static int write_tun_buffered(struct tuntap *tt, uint8_t *buf, uint32_t buf_len) 988{ 989 return tun_write_win32 (tt, buf, buf_len); 990} 991 992 993static int pico_tap_send(struct pico_device *dev, void *buf, int len) 994{ 995 uint32_t bytes_sent = 0; 996 struct pico_device_tap *tap = (struct pico_device_tap *) dev; 997 998 /* Increase the statistic count */ 999 tap->statistics_frames_out++; 1000 1001 bytes_sent = write_tun_buffered (tap->tt, buf, len); 1002 dbg_tap("TX> sent %d bytes\n", bytes_sent); 1003 1004 /* Discard the frame content silently. */ 1005 return bytes_sent; 1006} 1007 1008uint8_t recv_buffer[1500]; 1009 1010static int pico_tap_poll(struct pico_device *dev, int loop_score) 1011{ 1012 struct pico_device_tap *tap = (struct pico_device_tap *) dev; 1013 while (loop_score) 1014 { 1015 int bytes_read = read_tun_buffered(tap->tt, recv_buffer, 1500); 1016 loop_score--; 1017 if (bytes_read > 0) 1018 { 1019 dbg_tap("RX< recvd: %d bytes\n", bytes_read); 1020 pico_stack_recv(dev, recv_buffer, bytes_read); 1021 /* break; */ 1022 } 1023 else 1024 break; 1025 } 1026 return loop_score; 1027} 1028 1029 1030 1031#define CLEAR(x) memset(&(x), 0, sizeof(x)) 1032 1033void overlapped_io_init (struct overlapped_io *o, int event_state) 1034{ 1035 CLEAR (*o); 1036 1037 /* manual reset event, initially set according to event_state */ 1038 o->overlapped.hEvent = CreateEvent (NULL, TRUE, event_state, NULL); 1039 if (o->overlapped.hEvent == NULL) 1040 dbg_tap ("Error: overlapped_io_init: CreateEvent failed\n"); 1041 1042 /* allocate buffer for overlapped I/O */ 1043 o->buf_init = PICO_ZALLOC(1500); /* XXX: MTU */ 1044 o->buf_init_len = 1500; /* XXX: MTU */ 1045 if (!(o->buf_init)) 1046 dbg_tap("buffer alloc failed!\n"); /* XXX: return -1 or so? */ 1047 else 1048 dbg_tap("overlapped_io_init buffer allocated!\n"); 1049} 1050 1051void init_tun_post (struct tuntap *tt) 1052{ 1053 dbg_tap("TUN post init (for overlapped io)\n"); 1054 overlapped_io_init (&tt->reads, FALSE); 1055 overlapped_io_init (&tt->writes, TRUE); 1056 tt->rw_handle.read = tt->reads.overlapped.hEvent; 1057 tt->rw_handle.write = tt->writes.overlapped.hEvent; 1058} 1059 1060 1061/* 1062 * Public interface: pico_tap_create 1063 * TODO: pico_tap_destroy 1064 */ 1065 1066struct pico_device *pico_tap_create(char *name, uint8_t *mac) 1067{ 1068 struct pico_device_tap *tap = PICO_ZALLOC(sizeof(struct pico_device_tap)); 1069 struct tuntap *tt = PICO_ZALLOC(sizeof(struct tuntap), 1); 1070 1071 if (!(tap) || !(tt)) 1072 return NULL; 1073 1074 tap->dev.overhead = 0; 1075 tap->statistics_frames_out = 0; 1076 tap->dev.send = pico_tap_send; 1077 tap->dev.poll = pico_tap_poll; 1078 1079 show_tap_win_adapters(); 1080 1081 tt->type = DEV_TYPE_TAP; 1082 if (open_tun(NULL, NULL, "tap0", tt)) 1083 { 1084 dbg_tap("Failed to create TAP device!\n"); 1085 PICO_FREE(tt); 1086 PICO_FREE(tap); 1087 return NULL; 1088 } 1089 1090 tap->tt = tt; 1091 1092 if( 0 != pico_device_init((struct pico_device *)tap, name, mac)) { 1093 return NULL; 1094 } 1095 1096 init_tun_post(tt); /* init overlapped io */ 1097 1098 dbg_tap("Device %s created.\n", tap->dev.name); 1099 1100 return (struct pico_device *)tap; 1101} 1102