tap-win32.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  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. #include "qemu/osdep.h"
  29. #include "tap_int.h"
  30. #include "clients.h" /* net_init_tap */
  31. #include "net/eth.h"
  32. #include "net/net.h"
  33. #include "net/tap.h" /* tap_has_ufo, ... */
  34. #include "qemu/error-report.h"
  35. #include "qemu/main-loop.h"
  36. #include <windows.h>
  37. #include <winioctl.h>
  38. //=============
  39. // TAP IOCTLs
  40. //=============
  41. #define TAP_CONTROL_CODE(request,method) \
  42. CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
  43. #define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
  44. #define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)
  45. #define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED)
  46. #define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED)
  47. #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
  48. #define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED)
  49. #define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED)
  50. #define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED)
  51. #define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED)
  52. //=================
  53. // Registry keys
  54. //=================
  55. #define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
  56. #define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
  57. //======================
  58. // Filesystem prefixes
  59. //======================
  60. #define USERMODEDEVICEDIR "\\\\.\\Global\\"
  61. #define TAPSUFFIX ".tap"
  62. //======================
  63. // Compile time configuration
  64. //======================
  65. //#define DEBUG_TAP_WIN32
  66. /* FIXME: The asynch write path appears to be broken at
  67. * present. WriteFile() ignores the lpNumberOfBytesWritten parameter
  68. * for overlapped writes, with the result we return zero bytes sent,
  69. * and after handling a single packet, receive is disabled for this
  70. * interface. */
  71. /* #define TUN_ASYNCHRONOUS_WRITES 1 */
  72. #define TUN_BUFFER_SIZE 1560
  73. #define TUN_MAX_BUFFER_COUNT 32
  74. /*
  75. * The data member "buffer" must be the first element in the tun_buffer
  76. * structure. See the function, tap_win32_free_buffer.
  77. */
  78. typedef struct tun_buffer_s {
  79. unsigned char buffer [TUN_BUFFER_SIZE];
  80. unsigned long read_size;
  81. struct tun_buffer_s* next;
  82. } tun_buffer_t;
  83. typedef struct tap_win32_overlapped {
  84. HANDLE handle;
  85. HANDLE read_event;
  86. HANDLE write_event;
  87. HANDLE output_queue_semaphore;
  88. HANDLE free_list_semaphore;
  89. HANDLE tap_semaphore;
  90. CRITICAL_SECTION output_queue_cs;
  91. CRITICAL_SECTION free_list_cs;
  92. OVERLAPPED read_overlapped;
  93. OVERLAPPED write_overlapped;
  94. tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT];
  95. tun_buffer_t* free_list;
  96. tun_buffer_t* output_queue_front;
  97. tun_buffer_t* output_queue_back;
  98. } tap_win32_overlapped_t;
  99. static tap_win32_overlapped_t tap_overlapped;
  100. static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped)
  101. {
  102. tun_buffer_t* buffer = NULL;
  103. WaitForSingleObject(overlapped->free_list_semaphore, INFINITE);
  104. EnterCriticalSection(&overlapped->free_list_cs);
  105. buffer = overlapped->free_list;
  106. // assert(buffer != NULL);
  107. overlapped->free_list = buffer->next;
  108. LeaveCriticalSection(&overlapped->free_list_cs);
  109. buffer->next = NULL;
  110. return buffer;
  111. }
  112. static void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
  113. {
  114. EnterCriticalSection(&overlapped->free_list_cs);
  115. buffer->next = overlapped->free_list;
  116. overlapped->free_list = buffer;
  117. LeaveCriticalSection(&overlapped->free_list_cs);
  118. ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL);
  119. }
  120. static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block)
  121. {
  122. tun_buffer_t* buffer = NULL;
  123. DWORD result, timeout = block ? INFINITE : 0L;
  124. // Non-blocking call
  125. result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout);
  126. switch (result)
  127. {
  128. // The semaphore object was signaled.
  129. case WAIT_OBJECT_0:
  130. EnterCriticalSection(&overlapped->output_queue_cs);
  131. buffer = overlapped->output_queue_front;
  132. overlapped->output_queue_front = buffer->next;
  133. if(overlapped->output_queue_front == NULL) {
  134. overlapped->output_queue_back = NULL;
  135. }
  136. LeaveCriticalSection(&overlapped->output_queue_cs);
  137. break;
  138. // Semaphore was nonsignaled, so a time-out occurred.
  139. case WAIT_TIMEOUT:
  140. // Cannot open another window.
  141. break;
  142. }
  143. return buffer;
  144. }
  145. static tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped)
  146. {
  147. return get_buffer_from_output_queue(overlapped, 0);
  148. }
  149. static void put_buffer_on_output_queue(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
  150. {
  151. EnterCriticalSection(&overlapped->output_queue_cs);
  152. if(overlapped->output_queue_front == NULL && overlapped->output_queue_back == NULL) {
  153. overlapped->output_queue_front = overlapped->output_queue_back = buffer;
  154. } else {
  155. buffer->next = NULL;
  156. overlapped->output_queue_back->next = buffer;
  157. overlapped->output_queue_back = buffer;
  158. }
  159. LeaveCriticalSection(&overlapped->output_queue_cs);
  160. ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL);
  161. }
  162. static int is_tap_win32_dev(const char *guid)
  163. {
  164. HKEY netcard_key;
  165. LONG status;
  166. DWORD len;
  167. int i = 0;
  168. status = RegOpenKeyEx(
  169. HKEY_LOCAL_MACHINE,
  170. ADAPTER_KEY,
  171. 0,
  172. KEY_READ,
  173. &netcard_key);
  174. if (status != ERROR_SUCCESS) {
  175. return FALSE;
  176. }
  177. for (;;) {
  178. char enum_name[256];
  179. g_autofree char *unit_string = NULL;
  180. HKEY unit_key;
  181. char component_id_string[] = "ComponentId";
  182. char component_id[256];
  183. char net_cfg_instance_id_string[] = "NetCfgInstanceId";
  184. char net_cfg_instance_id[256];
  185. DWORD data_type;
  186. len = sizeof (enum_name);
  187. status = RegEnumKeyEx(
  188. netcard_key,
  189. i,
  190. enum_name,
  191. &len,
  192. NULL,
  193. NULL,
  194. NULL,
  195. NULL);
  196. if (status == ERROR_NO_MORE_ITEMS)
  197. break;
  198. else if (status != ERROR_SUCCESS) {
  199. return FALSE;
  200. }
  201. unit_string = g_strdup_printf("%s\\%s", ADAPTER_KEY, enum_name);
  202. status = RegOpenKeyEx(
  203. HKEY_LOCAL_MACHINE,
  204. unit_string,
  205. 0,
  206. KEY_READ,
  207. &unit_key);
  208. if (status != ERROR_SUCCESS) {
  209. return FALSE;
  210. } else {
  211. len = sizeof (component_id);
  212. status = RegQueryValueEx(
  213. unit_key,
  214. component_id_string,
  215. NULL,
  216. &data_type,
  217. (LPBYTE)component_id,
  218. &len);
  219. if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {
  220. len = sizeof (net_cfg_instance_id);
  221. status = RegQueryValueEx(
  222. unit_key,
  223. net_cfg_instance_id_string,
  224. NULL,
  225. &data_type,
  226. (LPBYTE)net_cfg_instance_id,
  227. &len);
  228. if (status == ERROR_SUCCESS && data_type == REG_SZ) {
  229. if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/
  230. !strcmp (net_cfg_instance_id, guid)) {
  231. RegCloseKey (unit_key);
  232. RegCloseKey (netcard_key);
  233. return TRUE;
  234. }
  235. }
  236. }
  237. RegCloseKey (unit_key);
  238. }
  239. ++i;
  240. }
  241. RegCloseKey (netcard_key);
  242. return FALSE;
  243. }
  244. static int get_device_guid(
  245. char *name,
  246. int name_size,
  247. char *actual_name,
  248. int actual_name_size)
  249. {
  250. LONG status;
  251. HKEY control_net_key;
  252. DWORD len;
  253. int i = 0;
  254. int stop = 0;
  255. status = RegOpenKeyEx(
  256. HKEY_LOCAL_MACHINE,
  257. NETWORK_CONNECTIONS_KEY,
  258. 0,
  259. KEY_READ,
  260. &control_net_key);
  261. if (status != ERROR_SUCCESS) {
  262. return -1;
  263. }
  264. while (!stop)
  265. {
  266. char enum_name[256];
  267. g_autofree char *connection_string = NULL;
  268. HKEY connection_key;
  269. char name_data[256];
  270. DWORD name_type;
  271. const char name_string[] = "Name";
  272. len = sizeof (enum_name);
  273. status = RegEnumKeyEx(
  274. control_net_key,
  275. i,
  276. enum_name,
  277. &len,
  278. NULL,
  279. NULL,
  280. NULL,
  281. NULL);
  282. if (status == ERROR_NO_MORE_ITEMS)
  283. break;
  284. else if (status != ERROR_SUCCESS) {
  285. return -1;
  286. }
  287. connection_string = g_strdup_printf("%s\\%s\\Connection",
  288. NETWORK_CONNECTIONS_KEY, enum_name);
  289. status = RegOpenKeyEx(
  290. HKEY_LOCAL_MACHINE,
  291. connection_string,
  292. 0,
  293. KEY_READ,
  294. &connection_key);
  295. if (status == ERROR_SUCCESS) {
  296. len = sizeof (name_data);
  297. status = RegQueryValueEx(
  298. connection_key,
  299. name_string,
  300. NULL,
  301. &name_type,
  302. (LPBYTE)name_data,
  303. &len);
  304. if (status != ERROR_SUCCESS || name_type != REG_SZ) {
  305. ++i;
  306. continue;
  307. }
  308. else {
  309. if (is_tap_win32_dev(enum_name)) {
  310. snprintf(name, name_size, "%s", enum_name);
  311. if (actual_name) {
  312. if (strcmp(actual_name, "") != 0) {
  313. if (strcmp(name_data, actual_name) != 0) {
  314. RegCloseKey (connection_key);
  315. ++i;
  316. continue;
  317. }
  318. }
  319. else {
  320. snprintf(actual_name, actual_name_size, "%s", name_data);
  321. }
  322. }
  323. stop = 1;
  324. }
  325. }
  326. RegCloseKey (connection_key);
  327. }
  328. ++i;
  329. }
  330. RegCloseKey (control_net_key);
  331. if (stop == 0)
  332. return -1;
  333. return 0;
  334. }
  335. static int tap_win32_set_status(HANDLE handle, int status)
  336. {
  337. unsigned long len = 0;
  338. return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,
  339. &status, sizeof (status),
  340. &status, sizeof (status), &len, NULL);
  341. }
  342. static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle)
  343. {
  344. overlapped->handle = handle;
  345. overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL);
  346. overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
  347. overlapped->read_overlapped.Offset = 0;
  348. overlapped->read_overlapped.OffsetHigh = 0;
  349. overlapped->read_overlapped.hEvent = overlapped->read_event;
  350. overlapped->write_overlapped.Offset = 0;
  351. overlapped->write_overlapped.OffsetHigh = 0;
  352. overlapped->write_overlapped.hEvent = overlapped->write_event;
  353. InitializeCriticalSection(&overlapped->output_queue_cs);
  354. InitializeCriticalSection(&overlapped->free_list_cs);
  355. overlapped->output_queue_semaphore = CreateSemaphore(
  356. NULL, // default security attributes
  357. 0, // initial count
  358. TUN_MAX_BUFFER_COUNT, // maximum count
  359. NULL); // unnamed semaphore
  360. if(!overlapped->output_queue_semaphore) {
  361. fprintf(stderr, "error creating output queue semaphore!\n");
  362. }
  363. overlapped->free_list_semaphore = CreateSemaphore(
  364. NULL, // default security attributes
  365. TUN_MAX_BUFFER_COUNT, // initial count
  366. TUN_MAX_BUFFER_COUNT, // maximum count
  367. NULL); // unnamed semaphore
  368. if(!overlapped->free_list_semaphore) {
  369. fprintf(stderr, "error creating free list semaphore!\n");
  370. }
  371. overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL;
  372. {
  373. unsigned index;
  374. for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) {
  375. tun_buffer_t* element = &overlapped->buffers[index];
  376. element->next = overlapped->free_list;
  377. overlapped->free_list = element;
  378. }
  379. }
  380. /* To count buffers, initially no-signal. */
  381. overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL);
  382. if(!overlapped->tap_semaphore)
  383. fprintf(stderr, "error creating tap_semaphore.\n");
  384. }
  385. static int tap_win32_write(tap_win32_overlapped_t *overlapped,
  386. const void *buffer, unsigned long size)
  387. {
  388. unsigned long write_size;
  389. BOOL result;
  390. DWORD error;
  391. #ifdef TUN_ASYNCHRONOUS_WRITES
  392. result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped,
  393. &write_size, FALSE);
  394. if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
  395. WaitForSingleObject(overlapped->write_event, INFINITE);
  396. #endif
  397. result = WriteFile(overlapped->handle, buffer, size,
  398. &write_size, &overlapped->write_overlapped);
  399. #ifdef TUN_ASYNCHRONOUS_WRITES
  400. /* FIXME: we can't sensibly set write_size here, without waiting
  401. * for the IO to complete! Moreover, we can't return zero,
  402. * because that will disable receive on this interface, and we
  403. * also can't assume it will succeed and return the full size,
  404. * because that will result in the buffer being reclaimed while
  405. * the IO is in progress. */
  406. #error Async writes are broken. Please disable TUN_ASYNCHRONOUS_WRITES.
  407. #else /* !TUN_ASYNCHRONOUS_WRITES */
  408. if (!result) {
  409. error = GetLastError();
  410. if (error == ERROR_IO_PENDING) {
  411. result = GetOverlappedResult(overlapped->handle,
  412. &overlapped->write_overlapped,
  413. &write_size, TRUE);
  414. }
  415. }
  416. #endif
  417. if (!result) {
  418. #ifdef DEBUG_TAP_WIN32
  419. LPTSTR msgbuf;
  420. error = GetLastError();
  421. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
  422. NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  423. &msgbuf, 0, NULL);
  424. fprintf(stderr, "Tap-Win32: Error WriteFile %d - %s\n", error, msgbuf);
  425. LocalFree(msgbuf);
  426. #endif
  427. return 0;
  428. }
  429. return write_size;
  430. }
  431. static DWORD WINAPI tap_win32_thread_entry(LPVOID param)
  432. {
  433. tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param;
  434. unsigned long read_size;
  435. BOOL result;
  436. DWORD dwError;
  437. tun_buffer_t* buffer = get_buffer_from_free_list(overlapped);
  438. for (;;) {
  439. result = ReadFile(overlapped->handle,
  440. buffer->buffer,
  441. sizeof(buffer->buffer),
  442. &read_size,
  443. &overlapped->read_overlapped);
  444. if (!result) {
  445. dwError = GetLastError();
  446. if (dwError == ERROR_IO_PENDING) {
  447. WaitForSingleObject(overlapped->read_event, INFINITE);
  448. result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped,
  449. &read_size, FALSE);
  450. if (!result) {
  451. #ifdef DEBUG_TAP_WIN32
  452. LPVOID lpBuffer;
  453. dwError = GetLastError();
  454. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  455. NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  456. (LPTSTR) & lpBuffer, 0, NULL );
  457. fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer);
  458. LocalFree( lpBuffer );
  459. #endif
  460. }
  461. } else {
  462. #ifdef DEBUG_TAP_WIN32
  463. LPVOID lpBuffer;
  464. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  465. NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  466. (LPTSTR) & lpBuffer, 0, NULL );
  467. fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer);
  468. LocalFree( lpBuffer );
  469. #endif
  470. }
  471. }
  472. if(read_size > 0) {
  473. buffer->read_size = read_size;
  474. put_buffer_on_output_queue(overlapped, buffer);
  475. ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL);
  476. buffer = get_buffer_from_free_list(overlapped);
  477. }
  478. }
  479. return 0;
  480. }
  481. static int tap_win32_read(tap_win32_overlapped_t *overlapped,
  482. uint8_t **pbuf, int max_size)
  483. {
  484. int size = 0;
  485. tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped);
  486. if(buffer != NULL) {
  487. *pbuf = buffer->buffer;
  488. size = (int)buffer->read_size;
  489. if(size > max_size) {
  490. size = max_size;
  491. }
  492. }
  493. return size;
  494. }
  495. static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
  496. uint8_t *pbuf)
  497. {
  498. tun_buffer_t* buffer = (tun_buffer_t*)pbuf;
  499. put_buffer_on_free_list(overlapped, buffer);
  500. }
  501. static int tap_win32_open(tap_win32_overlapped_t **phandle,
  502. const char *preferred_name)
  503. {
  504. g_autofree char *device_path = NULL;
  505. char device_guid[0x100];
  506. int rc;
  507. HANDLE handle;
  508. BOOL bret;
  509. char name_buffer[0x100] = {0, };
  510. struct {
  511. unsigned long major;
  512. unsigned long minor;
  513. unsigned long debug;
  514. } version;
  515. DWORD version_len;
  516. DWORD idThread;
  517. if (preferred_name != NULL) {
  518. snprintf(name_buffer, sizeof(name_buffer), "%s", preferred_name);
  519. }
  520. rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
  521. if (rc)
  522. return -1;
  523. device_path = g_strdup_printf("%s%s%s",
  524. USERMODEDEVICEDIR,
  525. device_guid,
  526. TAPSUFFIX);
  527. handle = CreateFile (
  528. device_path,
  529. GENERIC_READ | GENERIC_WRITE,
  530. 0,
  531. 0,
  532. OPEN_EXISTING,
  533. FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
  534. 0 );
  535. if (handle == INVALID_HANDLE_VALUE) {
  536. return -1;
  537. }
  538. bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION,
  539. &version, sizeof (version),
  540. &version, sizeof (version), &version_len, NULL);
  541. if (bret == FALSE) {
  542. CloseHandle(handle);
  543. return -1;
  544. }
  545. if (!tap_win32_set_status(handle, TRUE)) {
  546. return -1;
  547. }
  548. tap_win32_overlapped_init(&tap_overlapped, handle);
  549. *phandle = &tap_overlapped;
  550. CreateThread(NULL, 0, tap_win32_thread_entry,
  551. (LPVOID)&tap_overlapped, 0, &idThread);
  552. return 0;
  553. }
  554. /********************************************/
  555. typedef struct TAPState {
  556. NetClientState nc;
  557. tap_win32_overlapped_t *handle;
  558. } TAPState;
  559. static void tap_cleanup(NetClientState *nc)
  560. {
  561. TAPState *s = DO_UPCAST(TAPState, nc, nc);
  562. qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL);
  563. /* FIXME: need to kill thread and close file handle:
  564. tap_win32_close(s);
  565. */
  566. }
  567. static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
  568. {
  569. TAPState *s = DO_UPCAST(TAPState, nc, nc);
  570. return tap_win32_write(s->handle, buf, size);
  571. }
  572. static void tap_win32_send(void *opaque)
  573. {
  574. TAPState *s = opaque;
  575. uint8_t *buf, *orig_buf;
  576. int max_size = 4096;
  577. int size;
  578. uint8_t min_pkt[ETH_ZLEN];
  579. size_t min_pktsz = sizeof(min_pkt);
  580. size = tap_win32_read(s->handle, &buf, max_size);
  581. if (size > 0) {
  582. orig_buf = buf;
  583. if (net_peer_needs_padding(&s->nc)) {
  584. if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
  585. buf = min_pkt;
  586. size = min_pktsz;
  587. }
  588. }
  589. qemu_send_packet(&s->nc, buf, size);
  590. tap_win32_free_buffer(s->handle, orig_buf);
  591. }
  592. }
  593. struct vhost_net *tap_get_vhost_net(NetClientState *nc)
  594. {
  595. return NULL;
  596. }
  597. static NetClientInfo net_tap_win32_info = {
  598. .type = NET_CLIENT_DRIVER_TAP,
  599. .size = sizeof(TAPState),
  600. .receive = tap_receive,
  601. .cleanup = tap_cleanup,
  602. };
  603. static int tap_win32_init(NetClientState *peer, const char *model,
  604. const char *name, const char *ifname)
  605. {
  606. NetClientState *nc;
  607. TAPState *s;
  608. tap_win32_overlapped_t *handle;
  609. if (tap_win32_open(&handle, ifname) < 0) {
  610. printf("tap: Could not open '%s'\n", ifname);
  611. return -1;
  612. }
  613. nc = qemu_new_net_client(&net_tap_win32_info, peer, model, name);
  614. s = DO_UPCAST(TAPState, nc, nc);
  615. qemu_set_info_str(&s->nc, "tap: ifname=%s", ifname);
  616. s->handle = handle;
  617. qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s);
  618. return 0;
  619. }
  620. int net_init_tap(const Netdev *netdev, const char *name,
  621. NetClientState *peer, Error **errp)
  622. {
  623. /* FIXME error_setg(errp, ...) on failure */
  624. const NetdevTapOptions *tap;
  625. assert(netdev->type == NET_CLIENT_DRIVER_TAP);
  626. tap = &netdev->u.tap;
  627. if (!tap->ifname) {
  628. error_report("tap: no interface name");
  629. return -1;
  630. }
  631. if (tap_win32_init(peer, "tap", name, tap->ifname) == -1) {
  632. return -1;
  633. }
  634. return 0;
  635. }
  636. int tap_enable(NetClientState *nc)
  637. {
  638. abort();
  639. }
  640. int tap_disable(NetClientState *nc)
  641. {
  642. abort();
  643. }