tap-win32.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  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 "qemu-common.h"
  31. #include "clients.h" /* net_init_tap */
  32. #include "net/net.h"
  33. #include "net/tap.h" /* tap_has_ufo, ... */
  34. #include "sysemu/sysemu.h"
  35. #include "qemu/error-report.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. char unit_string[256];
  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. snprintf (unit_string, sizeof(unit_string), "%s\\%s",
  202. ADAPTER_KEY, enum_name);
  203. status = RegOpenKeyEx(
  204. HKEY_LOCAL_MACHINE,
  205. unit_string,
  206. 0,
  207. KEY_READ,
  208. &unit_key);
  209. if (status != ERROR_SUCCESS) {
  210. return FALSE;
  211. } else {
  212. len = sizeof (component_id);
  213. status = RegQueryValueEx(
  214. unit_key,
  215. component_id_string,
  216. NULL,
  217. &data_type,
  218. (LPBYTE)component_id,
  219. &len);
  220. if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {
  221. len = sizeof (net_cfg_instance_id);
  222. status = RegQueryValueEx(
  223. unit_key,
  224. net_cfg_instance_id_string,
  225. NULL,
  226. &data_type,
  227. (LPBYTE)net_cfg_instance_id,
  228. &len);
  229. if (status == ERROR_SUCCESS && data_type == REG_SZ) {
  230. if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/
  231. !strcmp (net_cfg_instance_id, guid)) {
  232. RegCloseKey (unit_key);
  233. RegCloseKey (netcard_key);
  234. return TRUE;
  235. }
  236. }
  237. }
  238. RegCloseKey (unit_key);
  239. }
  240. ++i;
  241. }
  242. RegCloseKey (netcard_key);
  243. return FALSE;
  244. }
  245. static int get_device_guid(
  246. char *name,
  247. int name_size,
  248. char *actual_name,
  249. int actual_name_size)
  250. {
  251. LONG status;
  252. HKEY control_net_key;
  253. DWORD len;
  254. int i = 0;
  255. int stop = 0;
  256. status = RegOpenKeyEx(
  257. HKEY_LOCAL_MACHINE,
  258. NETWORK_CONNECTIONS_KEY,
  259. 0,
  260. KEY_READ,
  261. &control_net_key);
  262. if (status != ERROR_SUCCESS) {
  263. return -1;
  264. }
  265. while (!stop)
  266. {
  267. char enum_name[256];
  268. char connection_string[256];
  269. HKEY connection_key;
  270. char name_data[256];
  271. DWORD name_type;
  272. const char name_string[] = "Name";
  273. len = sizeof (enum_name);
  274. status = RegEnumKeyEx(
  275. control_net_key,
  276. i,
  277. enum_name,
  278. &len,
  279. NULL,
  280. NULL,
  281. NULL,
  282. NULL);
  283. if (status == ERROR_NO_MORE_ITEMS)
  284. break;
  285. else if (status != ERROR_SUCCESS) {
  286. return -1;
  287. }
  288. snprintf(connection_string,
  289. sizeof(connection_string),
  290. "%s\\%s\\Connection",
  291. NETWORK_CONNECTIONS_KEY, enum_name);
  292. status = RegOpenKeyEx(
  293. HKEY_LOCAL_MACHINE,
  294. connection_string,
  295. 0,
  296. KEY_READ,
  297. &connection_key);
  298. if (status == ERROR_SUCCESS) {
  299. len = sizeof (name_data);
  300. status = RegQueryValueEx(
  301. connection_key,
  302. name_string,
  303. NULL,
  304. &name_type,
  305. (LPBYTE)name_data,
  306. &len);
  307. if (status != ERROR_SUCCESS || name_type != REG_SZ) {
  308. ++i;
  309. continue;
  310. }
  311. else {
  312. if (is_tap_win32_dev(enum_name)) {
  313. snprintf(name, name_size, "%s", enum_name);
  314. if (actual_name) {
  315. if (strcmp(actual_name, "") != 0) {
  316. if (strcmp(name_data, actual_name) != 0) {
  317. RegCloseKey (connection_key);
  318. ++i;
  319. continue;
  320. }
  321. }
  322. else {
  323. snprintf(actual_name, actual_name_size, "%s", name_data);
  324. }
  325. }
  326. stop = 1;
  327. }
  328. }
  329. RegCloseKey (connection_key);
  330. }
  331. ++i;
  332. }
  333. RegCloseKey (control_net_key);
  334. if (stop == 0)
  335. return -1;
  336. return 0;
  337. }
  338. static int tap_win32_set_status(HANDLE handle, int status)
  339. {
  340. unsigned long len = 0;
  341. return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,
  342. &status, sizeof (status),
  343. &status, sizeof (status), &len, NULL);
  344. }
  345. static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle)
  346. {
  347. overlapped->handle = handle;
  348. overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL);
  349. overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
  350. overlapped->read_overlapped.Offset = 0;
  351. overlapped->read_overlapped.OffsetHigh = 0;
  352. overlapped->read_overlapped.hEvent = overlapped->read_event;
  353. overlapped->write_overlapped.Offset = 0;
  354. overlapped->write_overlapped.OffsetHigh = 0;
  355. overlapped->write_overlapped.hEvent = overlapped->write_event;
  356. InitializeCriticalSection(&overlapped->output_queue_cs);
  357. InitializeCriticalSection(&overlapped->free_list_cs);
  358. overlapped->output_queue_semaphore = CreateSemaphore(
  359. NULL, // default security attributes
  360. 0, // initial count
  361. TUN_MAX_BUFFER_COUNT, // maximum count
  362. NULL); // unnamed semaphore
  363. if(!overlapped->output_queue_semaphore) {
  364. fprintf(stderr, "error creating output queue semaphore!\n");
  365. }
  366. overlapped->free_list_semaphore = CreateSemaphore(
  367. NULL, // default security attributes
  368. TUN_MAX_BUFFER_COUNT, // initial count
  369. TUN_MAX_BUFFER_COUNT, // maximum count
  370. NULL); // unnamed semaphore
  371. if(!overlapped->free_list_semaphore) {
  372. fprintf(stderr, "error creating free list semaphore!\n");
  373. }
  374. overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL;
  375. {
  376. unsigned index;
  377. for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) {
  378. tun_buffer_t* element = &overlapped->buffers[index];
  379. element->next = overlapped->free_list;
  380. overlapped->free_list = element;
  381. }
  382. }
  383. /* To count buffers, initially no-signal. */
  384. overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL);
  385. if(!overlapped->tap_semaphore)
  386. fprintf(stderr, "error creating tap_semaphore.\n");
  387. }
  388. static int tap_win32_write(tap_win32_overlapped_t *overlapped,
  389. const void *buffer, unsigned long size)
  390. {
  391. unsigned long write_size;
  392. BOOL result;
  393. DWORD error;
  394. #ifdef TUN_ASYNCHRONOUS_WRITES
  395. result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped,
  396. &write_size, FALSE);
  397. if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
  398. WaitForSingleObject(overlapped->write_event, INFINITE);
  399. #endif
  400. result = WriteFile(overlapped->handle, buffer, size,
  401. &write_size, &overlapped->write_overlapped);
  402. #ifdef TUN_ASYNCHRONOUS_WRITES
  403. /* FIXME: we can't sensibly set write_size here, without waiting
  404. * for the IO to complete! Moreover, we can't return zero,
  405. * because that will disable receive on this interface, and we
  406. * also can't assume it will succeed and return the full size,
  407. * because that will result in the buffer being reclaimed while
  408. * the IO is in progress. */
  409. #error Async writes are broken. Please disable TUN_ASYNCHRONOUS_WRITES.
  410. #else /* !TUN_ASYNCHRONOUS_WRITES */
  411. if (!result) {
  412. error = GetLastError();
  413. if (error == ERROR_IO_PENDING) {
  414. result = GetOverlappedResult(overlapped->handle,
  415. &overlapped->write_overlapped,
  416. &write_size, TRUE);
  417. }
  418. }
  419. #endif
  420. if (!result) {
  421. #ifdef DEBUG_TAP_WIN32
  422. LPTSTR msgbuf;
  423. error = GetLastError();
  424. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
  425. NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  426. &msgbuf, 0, NULL);
  427. fprintf(stderr, "Tap-Win32: Error WriteFile %d - %s\n", error, msgbuf);
  428. LocalFree(msgbuf);
  429. #endif
  430. return 0;
  431. }
  432. return write_size;
  433. }
  434. static DWORD WINAPI tap_win32_thread_entry(LPVOID param)
  435. {
  436. tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param;
  437. unsigned long read_size;
  438. BOOL result;
  439. DWORD dwError;
  440. tun_buffer_t* buffer = get_buffer_from_free_list(overlapped);
  441. for (;;) {
  442. result = ReadFile(overlapped->handle,
  443. buffer->buffer,
  444. sizeof(buffer->buffer),
  445. &read_size,
  446. &overlapped->read_overlapped);
  447. if (!result) {
  448. dwError = GetLastError();
  449. if (dwError == ERROR_IO_PENDING) {
  450. WaitForSingleObject(overlapped->read_event, INFINITE);
  451. result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped,
  452. &read_size, FALSE);
  453. if (!result) {
  454. #ifdef DEBUG_TAP_WIN32
  455. LPVOID lpBuffer;
  456. dwError = GetLastError();
  457. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  458. NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  459. (LPTSTR) & lpBuffer, 0, NULL );
  460. fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer);
  461. LocalFree( lpBuffer );
  462. #endif
  463. }
  464. } else {
  465. #ifdef DEBUG_TAP_WIN32
  466. LPVOID lpBuffer;
  467. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  468. NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  469. (LPTSTR) & lpBuffer, 0, NULL );
  470. fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer);
  471. LocalFree( lpBuffer );
  472. #endif
  473. }
  474. }
  475. if(read_size > 0) {
  476. buffer->read_size = read_size;
  477. put_buffer_on_output_queue(overlapped, buffer);
  478. ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL);
  479. buffer = get_buffer_from_free_list(overlapped);
  480. }
  481. }
  482. return 0;
  483. }
  484. static int tap_win32_read(tap_win32_overlapped_t *overlapped,
  485. uint8_t **pbuf, int max_size)
  486. {
  487. int size = 0;
  488. tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped);
  489. if(buffer != NULL) {
  490. *pbuf = buffer->buffer;
  491. size = (int)buffer->read_size;
  492. if(size > max_size) {
  493. size = max_size;
  494. }
  495. }
  496. return size;
  497. }
  498. static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
  499. uint8_t *pbuf)
  500. {
  501. tun_buffer_t* buffer = (tun_buffer_t*)pbuf;
  502. put_buffer_on_free_list(overlapped, buffer);
  503. }
  504. static int tap_win32_open(tap_win32_overlapped_t **phandle,
  505. const char *preferred_name)
  506. {
  507. char device_path[256];
  508. char device_guid[0x100];
  509. int rc;
  510. HANDLE handle;
  511. BOOL bret;
  512. char name_buffer[0x100] = {0, };
  513. struct {
  514. unsigned long major;
  515. unsigned long minor;
  516. unsigned long debug;
  517. } version;
  518. DWORD version_len;
  519. DWORD idThread;
  520. if (preferred_name != NULL) {
  521. snprintf(name_buffer, sizeof(name_buffer), "%s", preferred_name);
  522. }
  523. rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
  524. if (rc)
  525. return -1;
  526. snprintf (device_path, sizeof(device_path), "%s%s%s",
  527. USERMODEDEVICEDIR,
  528. device_guid,
  529. TAPSUFFIX);
  530. handle = CreateFile (
  531. device_path,
  532. GENERIC_READ | GENERIC_WRITE,
  533. 0,
  534. 0,
  535. OPEN_EXISTING,
  536. FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
  537. 0 );
  538. if (handle == INVALID_HANDLE_VALUE) {
  539. return -1;
  540. }
  541. bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION,
  542. &version, sizeof (version),
  543. &version, sizeof (version), &version_len, NULL);
  544. if (bret == FALSE) {
  545. CloseHandle(handle);
  546. return -1;
  547. }
  548. if (!tap_win32_set_status(handle, TRUE)) {
  549. return -1;
  550. }
  551. tap_win32_overlapped_init(&tap_overlapped, handle);
  552. *phandle = &tap_overlapped;
  553. CreateThread(NULL, 0, tap_win32_thread_entry,
  554. (LPVOID)&tap_overlapped, 0, &idThread);
  555. return 0;
  556. }
  557. /********************************************/
  558. typedef struct TAPState {
  559. NetClientState nc;
  560. tap_win32_overlapped_t *handle;
  561. } TAPState;
  562. static void tap_cleanup(NetClientState *nc)
  563. {
  564. TAPState *s = DO_UPCAST(TAPState, nc, nc);
  565. qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL);
  566. /* FIXME: need to kill thread and close file handle:
  567. tap_win32_close(s);
  568. */
  569. }
  570. static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
  571. {
  572. TAPState *s = DO_UPCAST(TAPState, nc, nc);
  573. return tap_win32_write(s->handle, buf, size);
  574. }
  575. static void tap_win32_send(void *opaque)
  576. {
  577. TAPState *s = opaque;
  578. uint8_t *buf;
  579. int max_size = 4096;
  580. int size;
  581. size = tap_win32_read(s->handle, &buf, max_size);
  582. if (size > 0) {
  583. qemu_send_packet(&s->nc, buf, size);
  584. tap_win32_free_buffer(s->handle, buf);
  585. }
  586. }
  587. static bool tap_has_ufo(NetClientState *nc)
  588. {
  589. return false;
  590. }
  591. static bool tap_has_vnet_hdr(NetClientState *nc)
  592. {
  593. return false;
  594. }
  595. int tap_probe_vnet_hdr_len(int fd, int len)
  596. {
  597. return 0;
  598. }
  599. void tap_fd_set_vnet_hdr_len(int fd, int len)
  600. {
  601. }
  602. int tap_fd_set_vnet_le(int fd, int is_le)
  603. {
  604. return -EINVAL;
  605. }
  606. int tap_fd_set_vnet_be(int fd, int is_be)
  607. {
  608. return -EINVAL;
  609. }
  610. static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
  611. {
  612. }
  613. static void tap_set_offload(NetClientState *nc, int csum, int tso4,
  614. int tso6, int ecn, int ufo)
  615. {
  616. }
  617. struct vhost_net *tap_get_vhost_net(NetClientState *nc)
  618. {
  619. return NULL;
  620. }
  621. static bool tap_has_vnet_hdr_len(NetClientState *nc, int len)
  622. {
  623. return false;
  624. }
  625. static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
  626. {
  627. abort();
  628. }
  629. static NetClientInfo net_tap_win32_info = {
  630. .type = NET_CLIENT_DRIVER_TAP,
  631. .size = sizeof(TAPState),
  632. .receive = tap_receive,
  633. .cleanup = tap_cleanup,
  634. .has_ufo = tap_has_ufo,
  635. .has_vnet_hdr = tap_has_vnet_hdr,
  636. .has_vnet_hdr_len = tap_has_vnet_hdr_len,
  637. .using_vnet_hdr = tap_using_vnet_hdr,
  638. .set_offload = tap_set_offload,
  639. .set_vnet_hdr_len = tap_set_vnet_hdr_len,
  640. };
  641. static int tap_win32_init(NetClientState *peer, const char *model,
  642. const char *name, const char *ifname)
  643. {
  644. NetClientState *nc;
  645. TAPState *s;
  646. tap_win32_overlapped_t *handle;
  647. if (tap_win32_open(&handle, ifname) < 0) {
  648. printf("tap: Could not open '%s'\n", ifname);
  649. return -1;
  650. }
  651. nc = qemu_new_net_client(&net_tap_win32_info, peer, model, name);
  652. s = DO_UPCAST(TAPState, nc, nc);
  653. snprintf(s->nc.info_str, sizeof(s->nc.info_str),
  654. "tap: ifname=%s", ifname);
  655. s->handle = handle;
  656. qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s);
  657. return 0;
  658. }
  659. int net_init_tap(const Netdev *netdev, const char *name,
  660. NetClientState *peer, Error **errp)
  661. {
  662. /* FIXME error_setg(errp, ...) on failure */
  663. const NetdevTapOptions *tap;
  664. assert(netdev->type == NET_CLIENT_DRIVER_TAP);
  665. tap = &netdev->u.tap;
  666. if (!tap->has_ifname) {
  667. error_report("tap: no interface name");
  668. return -1;
  669. }
  670. if (tap_win32_init(peer, "tap", name, tap->ifname) == -1) {
  671. return -1;
  672. }
  673. return 0;
  674. }
  675. int tap_enable(NetClientState *nc)
  676. {
  677. abort();
  678. }
  679. int tap_disable(NetClientState *nc)
  680. {
  681. abort();
  682. }