device.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210
  1. /*
  2. * TAP-Windows -- A kernel driver to provide virtual tap
  3. * device functionality on Windows.
  4. *
  5. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
  6. *
  7. * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc.,
  8. * and is released under the GPL version 2 (see below).
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program (see the file COPYING included with this
  21. * distribution); if not, write to the Free Software Foundation, Inc.,
  22. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. //
  25. // Include files.
  26. //
  27. #include "tap.h"
  28. #include <wdmsec.h> // for SDDLs
  29. //======================================================================
  30. // TAP Win32 Device I/O Callbacks
  31. //======================================================================
  32. #ifdef ALLOC_PRAGMA
  33. #pragma alloc_text( PAGE, TapDeviceCreate)
  34. #pragma alloc_text( PAGE, TapDeviceControl)
  35. #pragma alloc_text( PAGE, TapDeviceCleanup)
  36. #pragma alloc_text( PAGE, TapDeviceClose)
  37. #endif // ALLOC_PRAGMA
  38. //===================================================================
  39. // Go back to default TAP mode from Point-To-Point mode.
  40. // Also reset (i.e. disable) DHCP Masq mode.
  41. //===================================================================
  42. VOID tapResetAdapterState(
  43. __in PTAP_ADAPTER_CONTEXT Adapter
  44. )
  45. {
  46. /*
  47. // Point-To-Point
  48. Adapter->m_tun = FALSE;
  49. Adapter->m_localIP = 0;
  50. Adapter->m_remoteNetwork = 0;
  51. Adapter->m_remoteNetmask = 0;
  52. NdisZeroMemory (&Adapter->m_TapToUser, sizeof (Adapter->m_TapToUser));
  53. NdisZeroMemory (&Adapter->m_UserToTap, sizeof (Adapter->m_UserToTap));
  54. NdisZeroMemory (&Adapter->m_UserToTap_IPv6, sizeof (Adapter->m_UserToTap_IPv6));
  55. */
  56. // DHCP Masq
  57. /*
  58. Adapter->m_dhcp_enabled = FALSE;
  59. Adapter->m_dhcp_server_arp = FALSE;
  60. Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
  61. Adapter->m_dhcp_addr = 0;
  62. Adapter->m_dhcp_netmask = 0;
  63. Adapter->m_dhcp_server_ip = 0;
  64. Adapter->m_dhcp_lease_time = 0;
  65. Adapter->m_dhcp_received_discover = FALSE;
  66. Adapter->m_dhcp_bad_requests = 0;
  67. NdisZeroMemory (Adapter->m_dhcp_server_mac, MACADDR_SIZE);
  68. */
  69. }
  70. // IRP_MJ_CREATE
  71. NTSTATUS
  72. TapDeviceCreate(
  73. PDEVICE_OBJECT DeviceObject,
  74. PIRP Irp
  75. )
  76. /*++
  77. Routine Description:
  78. This routine is called by the I/O system when the device is opened.
  79. No action is performed other than completing the request successfully.
  80. Arguments:
  81. DeviceObject - a pointer to the object that represents the device
  82. that I/O is to be done on.
  83. Irp - a pointer to the I/O Request Packet for this request.
  84. Return Value:
  85. NT status code
  86. --*/
  87. {
  88. NDIS_STATUS status;
  89. PIO_STACK_LOCATION irpSp;// Pointer to current stack location
  90. PTAP_ADAPTER_CONTEXT adapter = NULL;
  91. PFILE_OBJECT originalFileObject;
  92. PAGED_CODE();
  93. DEBUGP (("[TAP] --> TapDeviceCreate\n"));
  94. irpSp = IoGetCurrentIrpStackLocation(Irp);
  95. //
  96. // Invalidate file context
  97. //
  98. irpSp->FileObject->FsContext = NULL;
  99. irpSp->FileObject->FsContext2 = NULL;
  100. //
  101. // Find adapter context for this device.
  102. // -------------------------------------
  103. // Returns with added reference on adapter context.
  104. //
  105. adapter = tapAdapterContextFromDeviceObject(DeviceObject);
  106. // Insure that adapter exists.
  107. ASSERT(adapter);
  108. if(adapter == NULL )
  109. {
  110. DEBUGP (("[TAP] release [%d.%d] open request; adapter not found\n",
  111. TAP_DRIVER_MAJOR_VERSION,
  112. TAP_DRIVER_MINOR_VERSION
  113. ));
  114. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  115. Irp->IoStatus.Information = 0;
  116. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  117. return STATUS_DEVICE_DOES_NOT_EXIST;
  118. }
  119. DEBUGP(("[%s] [TAP] release [%d.%d] open request (TapFileIsOpen=%d)\n",
  120. MINIPORT_INSTANCE_ID(adapter),
  121. TAP_DRIVER_MAJOR_VERSION,
  122. TAP_DRIVER_MINOR_VERSION,
  123. adapter->TapFileIsOpen
  124. ));
  125. // Enforce exclusive access
  126. originalFileObject = InterlockedCompareExchangePointer(
  127. &adapter->TapFileObject,
  128. irpSp->FileObject,
  129. NULL
  130. );
  131. if(originalFileObject == NULL)
  132. {
  133. irpSp->FileObject->FsContext = adapter; // Quick reference
  134. status = STATUS_SUCCESS;
  135. }
  136. else
  137. {
  138. status = STATUS_UNSUCCESSFUL;
  139. }
  140. // Release the lock.
  141. //tapAdapterReleaseLock(adapter,FALSE);
  142. if(status == STATUS_SUCCESS)
  143. {
  144. // Reset adapter state on successful open.
  145. tapResetAdapterState(adapter);
  146. adapter->TapFileIsOpen = 1; // Legacy...
  147. // NOTE!!! Reference added by tapAdapterContextFromDeviceObject
  148. // will be removed when file is closed.
  149. }
  150. else
  151. {
  152. DEBUGP (("[%s] TAP is presently unavailable (TapFileIsOpen=%d)\n",
  153. MINIPORT_INSTANCE_ID(adapter), adapter->TapFileIsOpen
  154. ));
  155. NOTE_ERROR();
  156. // Remove reference added by tapAdapterContextFromDeviceObject.
  157. tapAdapterContextDereference(adapter);
  158. }
  159. // Complete the IRP.
  160. Irp->IoStatus.Status = status;
  161. Irp->IoStatus.Information = 0;
  162. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  163. DEBUGP (("[TAP] <-- TapDeviceCreate; status = %8.8X\n",status));
  164. return status;
  165. }
  166. //===================================================
  167. // Tell Windows whether the TAP device should be
  168. // considered "connected" or "disconnected".
  169. //
  170. // Allows application control of media connect state.
  171. //===================================================
  172. VOID
  173. tapSetMediaConnectStatus(
  174. __in PTAP_ADAPTER_CONTEXT Adapter,
  175. __in BOOLEAN LogicalMediaState
  176. )
  177. {
  178. NDIS_STATUS_INDICATION statusIndication;
  179. NDIS_LINK_STATE linkState;
  180. NdisZeroMemory(&statusIndication, sizeof(NDIS_STATUS_INDICATION));
  181. NdisZeroMemory(&linkState, sizeof(NDIS_LINK_STATE));
  182. //
  183. // Fill in object headers
  184. //
  185. statusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
  186. statusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
  187. statusIndication.Header.Size = sizeof(NDIS_STATUS_INDICATION);
  188. linkState.Header.Revision = NDIS_LINK_STATE_REVISION_1;
  189. linkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
  190. linkState.Header.Size = sizeof(NDIS_LINK_STATE);
  191. //
  192. // Link state buffer
  193. //
  194. if(Adapter->LogicalMediaState == TRUE)
  195. {
  196. linkState.MediaConnectState = MediaConnectStateConnected;
  197. }
  198. linkState.MediaDuplexState = MediaDuplexStateFull;
  199. linkState.RcvLinkSpeed = TAP_RECV_SPEED;
  200. linkState.XmitLinkSpeed = TAP_XMIT_SPEED;
  201. //
  202. // Fill in the status buffer
  203. //
  204. statusIndication.StatusCode = NDIS_STATUS_LINK_STATE;
  205. statusIndication.SourceHandle = Adapter->MiniportAdapterHandle;
  206. statusIndication.DestinationHandle = NULL;
  207. statusIndication.RequestId = 0;
  208. statusIndication.StatusBuffer = &linkState;
  209. statusIndication.StatusBufferSize = sizeof(NDIS_LINK_STATE);
  210. // Fill in new media connect state.
  211. if ( (Adapter->LogicalMediaState != LogicalMediaState) && !Adapter->MediaStateAlwaysConnected)
  212. {
  213. Adapter->LogicalMediaState = LogicalMediaState;
  214. if (LogicalMediaState == TRUE)
  215. {
  216. linkState.MediaConnectState = MediaConnectStateConnected;
  217. DEBUGP (("[TAP] Set MediaConnectState: Connected.\n"));
  218. }
  219. else
  220. {
  221. linkState.MediaConnectState = MediaConnectStateDisconnected;
  222. DEBUGP (("[TAP] Set MediaConnectState: Disconnected.\n"));
  223. }
  224. }
  225. // Make the status indication.
  226. if(Adapter->Locked.AdapterState != MiniportHaltedState)
  227. {
  228. NdisMIndicateStatusEx(Adapter->MiniportAdapterHandle, &statusIndication);
  229. }
  230. }
  231. /*
  232. //======================================================
  233. // If DHCP mode is used together with tun
  234. // mode, consider the fact that the P2P remote subnet
  235. // might enclose the DHCP masq server address.
  236. //======================================================
  237. VOID
  238. CheckIfDhcpAndTunMode (
  239. __in PTAP_ADAPTER_CONTEXT Adapter
  240. )
  241. {
  242. if (Adapter->m_tun && Adapter->m_dhcp_enabled)
  243. {
  244. if ((Adapter->m_dhcp_server_ip & Adapter->m_remoteNetmask) == Adapter->m_remoteNetwork)
  245. {
  246. ETH_COPY_NETWORK_ADDRESS (Adapter->m_dhcp_server_mac, Adapter->m_TapToUser.dest);
  247. Adapter->m_dhcp_server_arp = FALSE;
  248. }
  249. }
  250. }
  251. */
  252. // IRP_MJ_DEVICE_CONTROL callback.
  253. NTSTATUS
  254. TapDeviceControl(
  255. PDEVICE_OBJECT DeviceObject,
  256. PIRP Irp
  257. )
  258. /*++
  259. Routine Description:
  260. This routine is called by the I/O system to perform a device I/O
  261. control function.
  262. Arguments:
  263. DeviceObject - a pointer to the object that represents the device
  264. that I/O is to be done on.
  265. Irp - a pointer to the I/O Request Packet for this request.
  266. Return Value:
  267. NT status code
  268. --*/
  269. {
  270. NTSTATUS ntStatus = STATUS_SUCCESS; // Assume success
  271. PIO_STACK_LOCATION irpSp; // Pointer to current stack location
  272. PTAP_ADAPTER_CONTEXT adapter = NULL;
  273. ULONG inBufLength; // Input buffer length
  274. ULONG outBufLength; // Output buffer length
  275. PCHAR inBuf, outBuf; // pointer to Input and output buffer
  276. PMDL mdl = NULL;
  277. PCHAR buffer = NULL;
  278. PAGED_CODE();
  279. irpSp = IoGetCurrentIrpStackLocation( Irp );
  280. //
  281. // Fetch adapter context for this device.
  282. // --------------------------------------
  283. // Adapter pointer was stashed in FsContext when handle was opened.
  284. //
  285. adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext;
  286. ASSERT(adapter);
  287. inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
  288. outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  289. if (!inBufLength || !outBufLength)
  290. {
  291. ntStatus = STATUS_INVALID_PARAMETER;
  292. goto End;
  293. }
  294. //
  295. // Determine which I/O control code was specified.
  296. //
  297. switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
  298. {
  299. case TAP_WIN_IOCTL_GET_MAC:
  300. {
  301. if (outBufLength >= MACADDR_SIZE )
  302. {
  303. ETH_COPY_NETWORK_ADDRESS(
  304. Irp->AssociatedIrp.SystemBuffer,
  305. adapter->CurrentAddress
  306. );
  307. Irp->IoStatus.Information = MACADDR_SIZE;
  308. }
  309. else
  310. {
  311. NOTE_ERROR();
  312. Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
  313. }
  314. }
  315. break;
  316. case TAP_WIN_IOCTL_GET_VERSION:
  317. {
  318. const ULONG size = sizeof (ULONG) * 3;
  319. if (outBufLength >= size)
  320. {
  321. ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[0]
  322. = TAP_DRIVER_MAJOR_VERSION;
  323. ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[1]
  324. = TAP_DRIVER_MINOR_VERSION;
  325. ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[2]
  326. #if DBG
  327. = 1;
  328. #else
  329. = 0;
  330. #endif
  331. Irp->IoStatus.Information = size;
  332. }
  333. else
  334. {
  335. NOTE_ERROR();
  336. Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
  337. }
  338. }
  339. break;
  340. case TAP_WIN_IOCTL_GET_MTU:
  341. {
  342. const ULONG size = sizeof (ULONG) * 1;
  343. if (outBufLength >= size)
  344. {
  345. ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[0]
  346. = adapter->MtuSize;
  347. Irp->IoStatus.Information = size;
  348. }
  349. else
  350. {
  351. NOTE_ERROR();
  352. Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
  353. }
  354. }
  355. break;
  356. // Allow ZeroTier One to get multicast memberships at the L2 level in a
  357. // protocol-neutral manner.
  358. case TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS:
  359. {
  360. if (outBufLength < TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE) {
  361. /* output buffer too small */
  362. NOTE_ERROR ();
  363. Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
  364. } else {
  365. char *out = (char *)Irp->AssociatedIrp.SystemBuffer;
  366. char *end = out + TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE;
  367. unsigned long i,j;
  368. for(i=0;i<adapter->ulMCListSize;++i) {
  369. if (i >= TAP_MAX_MCAST_LIST)
  370. break;
  371. for(j=0;j<6;++j)
  372. *(out++) = adapter->MCList[i][j];
  373. if (out >= end)
  374. break;
  375. }
  376. while (out < end)
  377. *(out++) = (char)0;
  378. Irp->IoStatus.Information = TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE;
  379. Irp->IoStatus.Status = ntStatus = STATUS_SUCCESS;
  380. }
  381. break;
  382. }
  383. #if 0
  384. case TAP_WIN_IOCTL_CONFIG_TUN:
  385. {
  386. if(inBufLength >= sizeof(IPADDR)*3)
  387. {
  388. MACADDR dest;
  389. adapter->m_tun = FALSE;
  390. GenerateRelatedMAC (dest, adapter->CurrentAddress, 1);
  391. adapter->m_localIP = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[0];
  392. adapter->m_remoteNetwork = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[1];
  393. adapter->m_remoteNetmask = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[2];
  394. // Sanity check on network/netmask
  395. if ((adapter->m_remoteNetwork & adapter->m_remoteNetmask) != adapter->m_remoteNetwork)
  396. {
  397. NOTE_ERROR();
  398. Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
  399. break;
  400. }
  401. ETH_COPY_NETWORK_ADDRESS (adapter->m_TapToUser.src, adapter->CurrentAddress);
  402. ETH_COPY_NETWORK_ADDRESS (adapter->m_TapToUser.dest, dest);
  403. ETH_COPY_NETWORK_ADDRESS (adapter->m_UserToTap.src, dest);
  404. ETH_COPY_NETWORK_ADDRESS (adapter->m_UserToTap.dest, adapter->CurrentAddress);
  405. adapter->m_TapToUser.proto = adapter->m_UserToTap.proto = htons (NDIS_ETH_TYPE_IPV4);
  406. adapter->m_UserToTap_IPv6 = adapter->m_UserToTap;
  407. adapter->m_UserToTap_IPv6.proto = htons(NDIS_ETH_TYPE_IPV6);
  408. adapter->m_tun = TRUE;
  409. CheckIfDhcpAndTunMode (adapter);
  410. Irp->IoStatus.Information = 1; // Simple boolean value
  411. DEBUGP (("[TAP] Set TUN mode.\n"));
  412. }
  413. else
  414. {
  415. NOTE_ERROR();
  416. Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
  417. }
  418. }
  419. break;
  420. case TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT:
  421. {
  422. if(inBufLength >= sizeof(IPADDR)*2)
  423. {
  424. MACADDR dest;
  425. adapter->m_tun = FALSE;
  426. GenerateRelatedMAC (dest, adapter->CurrentAddress, 1);
  427. adapter->m_localIP = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[0];
  428. adapter->m_remoteNetwork = ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[1];
  429. adapter->m_remoteNetmask = ~0;
  430. ETH_COPY_NETWORK_ADDRESS (adapter->m_TapToUser.src, adapter->CurrentAddress);
  431. ETH_COPY_NETWORK_ADDRESS (adapter->m_TapToUser.dest, dest);
  432. ETH_COPY_NETWORK_ADDRESS (adapter->m_UserToTap.src, dest);
  433. ETH_COPY_NETWORK_ADDRESS (adapter->m_UserToTap.dest, adapter->CurrentAddress);
  434. adapter->m_TapToUser.proto = adapter->m_UserToTap.proto = htons (NDIS_ETH_TYPE_IPV4);
  435. adapter->m_UserToTap_IPv6 = adapter->m_UserToTap;
  436. adapter->m_UserToTap_IPv6.proto = htons(NDIS_ETH_TYPE_IPV6);
  437. adapter->m_tun = TRUE;
  438. CheckIfDhcpAndTunMode (adapter);
  439. Irp->IoStatus.Information = 1; // Simple boolean value
  440. DEBUGP (("[TAP] Set P2P mode.\n"));
  441. }
  442. else
  443. {
  444. NOTE_ERROR();
  445. Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
  446. }
  447. }
  448. break;
  449. #endif
  450. #if 0
  451. case TAP_WIN_IOCTL_CONFIG_DHCP_MASQ:
  452. {
  453. if(inBufLength >= sizeof(IPADDR)*4)
  454. {
  455. adapter->m_dhcp_enabled = FALSE;
  456. adapter->m_dhcp_server_arp = FALSE;
  457. adapter->m_dhcp_user_supplied_options_buffer_len = 0;
  458. // Adapter IP addr / netmask
  459. adapter->m_dhcp_addr =
  460. ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[0];
  461. adapter->m_dhcp_netmask =
  462. ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[1];
  463. // IP addr of DHCP masq server
  464. adapter->m_dhcp_server_ip =
  465. ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[2];
  466. // Lease time in seconds
  467. adapter->m_dhcp_lease_time =
  468. ((IPADDR*) (Irp->AssociatedIrp.SystemBuffer))[3];
  469. GenerateRelatedMAC(
  470. adapter->m_dhcp_server_mac,
  471. adapter->CurrentAddress,
  472. 2
  473. );
  474. adapter->m_dhcp_enabled = TRUE;
  475. adapter->m_dhcp_server_arp = TRUE;
  476. CheckIfDhcpAndTunMode (adapter);
  477. Irp->IoStatus.Information = 1; // Simple boolean value
  478. DEBUGP (("[TAP] Configured DHCP MASQ.\n"));
  479. }
  480. else
  481. {
  482. NOTE_ERROR();
  483. Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
  484. }
  485. }
  486. break;
  487. case TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT:
  488. {
  489. if (inBufLength <= DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE
  490. && adapter->m_dhcp_enabled)
  491. {
  492. adapter->m_dhcp_user_supplied_options_buffer_len = 0;
  493. NdisMoveMemory(
  494. adapter->m_dhcp_user_supplied_options_buffer,
  495. Irp->AssociatedIrp.SystemBuffer,
  496. inBufLength
  497. );
  498. adapter->m_dhcp_user_supplied_options_buffer_len =
  499. inBufLength;
  500. Irp->IoStatus.Information = 1; // Simple boolean value
  501. DEBUGP (("[TAP] Set DHCP OPT.\n"));
  502. }
  503. else
  504. {
  505. NOTE_ERROR();
  506. Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
  507. }
  508. }
  509. break;
  510. #endif
  511. #if 0
  512. case TAP_WIN_IOCTL_GET_INFO:
  513. {
  514. char state[16];
  515. // Fetch adapter (miniport) state.
  516. if (tapAdapterSendAndReceiveReady(adapter) == NDIS_STATUS_SUCCESS)
  517. state[0] = 'A';
  518. else
  519. state[0] = 'a';
  520. if (tapAdapterReadAndWriteReady(adapter))
  521. state[1] = 'T';
  522. else
  523. state[1] = 't';
  524. state[2] = '0' + adapter->CurrentPowerState;
  525. if (adapter->MediaStateAlwaysConnected)
  526. state[3] = 'C';
  527. else
  528. state[3] = 'c';
  529. state[4] = '\0';
  530. // BUGBUG!!! What follows, and is not yet implemented, is a real mess.
  531. // BUGBUG!!! Tied closely to the NDIS 5 implementation. Need to map
  532. // as much as possible to the NDIS 6 implementation.
  533. Irp->IoStatus.Status = ntStatus = RtlStringCchPrintfExA (
  534. ((LPTSTR) (Irp->AssociatedIrp.SystemBuffer)),
  535. outBufLength,
  536. NULL,
  537. NULL,
  538. STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
  539. #if PACKET_TRUNCATION_CHECK
  540. "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d,%d] Rx=[%d,%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d] InjQ=[%d,%d,%d]",
  541. #else
  542. "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d] InjQ=[%d,%d,%d]",
  543. #endif
  544. state,
  545. g_LastErrorFilename,
  546. g_LastErrorLineNumber,
  547. (int)adapter->TapFileOpenCount,
  548. (int)(adapter->FramesTxDirected + adapter->FramesTxMulticast + adapter->FramesTxBroadcast),
  549. (int)adapter->TransmitFailuresOther,
  550. #if PACKET_TRUNCATION_CHECK
  551. (int)adapter->m_TxTrunc,
  552. #endif
  553. (int)adapter->m_Rx,
  554. (int)adapter->m_RxErr,
  555. #if PACKET_TRUNCATION_CHECK
  556. (int)adapter->m_RxTrunc,
  557. #endif
  558. (int)adapter->PendingReadIrpQueue.Count,
  559. (int)adapter->PendingReadIrpQueue.MaxCount,
  560. (int)IRP_QUEUE_SIZE, // Ignored in NDIS 6 driver...
  561. (int)adapter->SendPacketQueue.Count,
  562. (int)adapter->SendPacketQueue.MaxCount,
  563. (int)PACKET_QUEUE_SIZE,
  564. (int)0, // adapter->InjectPacketQueue.Count - Unused
  565. (int)0, // adapter->InjectPacketQueue.MaxCount - Unused
  566. (int)INJECT_QUEUE_SIZE
  567. );
  568. Irp->IoStatus.Information = outBufLength;
  569. // BUGBUG!!! Fail because this is not completely implemented.
  570. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  571. }
  572. #endif
  573. #if DBG
  574. case TAP_WIN_IOCTL_GET_LOG_LINE:
  575. {
  576. if (GetDebugLine( (LPTSTR)Irp->AssociatedIrp.SystemBuffer,outBufLength))
  577. {
  578. Irp->IoStatus.Status = ntStatus = STATUS_SUCCESS;
  579. }
  580. else
  581. {
  582. Irp->IoStatus.Status = ntStatus = STATUS_UNSUCCESSFUL;
  583. }
  584. Irp->IoStatus.Information = outBufLength;
  585. break;
  586. }
  587. #endif
  588. case TAP_WIN_IOCTL_SET_MEDIA_STATUS:
  589. {
  590. if(inBufLength >= sizeof(ULONG))
  591. {
  592. ULONG parm = ((PULONG) (Irp->AssociatedIrp.SystemBuffer))[0];
  593. tapSetMediaConnectStatus (adapter, (BOOLEAN) parm);
  594. Irp->IoStatus.Information = 1;
  595. }
  596. else
  597. {
  598. NOTE_ERROR();
  599. Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
  600. }
  601. }
  602. break;
  603. default:
  604. //
  605. // The specified I/O control code is unrecognized by this driver.
  606. //
  607. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  608. break;
  609. }
  610. End:
  611. //
  612. // Finish the I/O operation by simply completing the packet and returning
  613. // the same status as in the packet itself.
  614. //
  615. Irp->IoStatus.Status = ntStatus;
  616. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  617. return ntStatus;
  618. }
  619. // Flush the pending read IRP queue.
  620. VOID
  621. tapFlushIrpQueues(
  622. __in PTAP_ADAPTER_CONTEXT Adapter
  623. )
  624. {
  625. DEBUGP (("[TAP] tapFlushIrpQueues: Flushing %d pending read IRPs\n",
  626. Adapter->PendingReadIrpQueue.Count));
  627. tapIrpCsqFlush(&Adapter->PendingReadIrpQueue);
  628. }
  629. // IRP_MJ_CLEANUP
  630. NTSTATUS
  631. TapDeviceCleanup(
  632. PDEVICE_OBJECT DeviceObject,
  633. PIRP Irp
  634. )
  635. /*++
  636. Routine Description:
  637. Receipt of this request indicates that the last handle for a file
  638. object that is associated with the target device object has been closed
  639. (but, due to outstanding I/O requests, might not have been released).
  640. A driver that holds pending IRPs internally must implement a routine for
  641. IRP_MJ_CLEANUP. When the routine is called, the driver should cancel all
  642. the pending IRPs that belong to the file object identified by the IRP_MJ_CLEANUP
  643. call.
  644. In other words, it should cancel all the IRPs that have the same file-object
  645. pointer as the one supplied in the current I/O stack location of the IRP for the
  646. IRP_MJ_CLEANUP call. Of course, IRPs belonging to other file objects should
  647. not be canceled. Also, if an outstanding IRP is completed immediately, the
  648. driver does not have to cancel it.
  649. Arguments:
  650. DeviceObject - a pointer to the object that represents the device
  651. to be cleaned up.
  652. Irp - a pointer to the I/O Request Packet for this request.
  653. Return Value:
  654. NT status code
  655. --*/
  656. {
  657. NDIS_STATUS status = NDIS_STATUS_SUCCESS; // Always succeed.
  658. PIO_STACK_LOCATION irpSp; // Pointer to current stack location
  659. PTAP_ADAPTER_CONTEXT adapter = NULL;
  660. PAGED_CODE();
  661. DEBUGP (("[TAP] --> TapDeviceCleanup\n"));
  662. irpSp = IoGetCurrentIrpStackLocation(Irp);
  663. //
  664. // Fetch adapter context for this device.
  665. // --------------------------------------
  666. // Adapter pointer was stashed in FsContext when handle was opened.
  667. //
  668. adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext;
  669. // Insure that adapter exists.
  670. ASSERT(adapter);
  671. if(adapter == NULL )
  672. {
  673. DEBUGP (("[TAP] release [%d.%d] cleanup request; adapter not found\n",
  674. TAP_DRIVER_MAJOR_VERSION,
  675. TAP_DRIVER_MINOR_VERSION
  676. ));
  677. }
  678. if(adapter != NULL )
  679. {
  680. adapter->TapFileIsOpen = 0; // Legacy...
  681. // Disconnect from media.
  682. tapSetMediaConnectStatus(adapter,FALSE);
  683. // Reset adapter state when cleaning up;
  684. tapResetAdapterState(adapter);
  685. // BUGBUG!!! Use RemoveLock???
  686. //
  687. // Flush pending send TAP packet queue.
  688. //
  689. tapFlushSendPacketQueue(adapter);
  690. ASSERT(adapter->SendPacketQueue.Count == 0);
  691. //
  692. // Flush the pending IRP queues
  693. //
  694. tapFlushIrpQueues(adapter);
  695. ASSERT(adapter->PendingReadIrpQueue.Count == 0);
  696. }
  697. // Complete the IRP.
  698. Irp->IoStatus.Status = status;
  699. Irp->IoStatus.Information = 0;
  700. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  701. DEBUGP (("[TAP] <-- TapDeviceCleanup; status = %8.8X\n",status));
  702. return status;
  703. }
  704. // IRP_MJ_CLOSE
  705. NTSTATUS
  706. TapDeviceClose(
  707. PDEVICE_OBJECT DeviceObject,
  708. PIRP Irp
  709. )
  710. /*++
  711. Routine Description:
  712. Receipt of this request indicates that the last handle of the file
  713. object that is associated with the target device object has been closed
  714. and released.
  715. All outstanding I/O requests have been completed or canceled.
  716. Arguments:
  717. DeviceObject - a pointer to the object that represents the device
  718. to be closed.
  719. Irp - a pointer to the I/O Request Packet for this request.
  720. Return Value:
  721. NT status code
  722. --*/
  723. {
  724. NDIS_STATUS status = NDIS_STATUS_SUCCESS; // Always succeed.
  725. PIO_STACK_LOCATION irpSp; // Pointer to current stack location
  726. PTAP_ADAPTER_CONTEXT adapter = NULL;
  727. PAGED_CODE();
  728. DEBUGP (("[TAP] --> TapDeviceClose\n"));
  729. irpSp = IoGetCurrentIrpStackLocation(Irp);
  730. //
  731. // Fetch adapter context for this device.
  732. // --------------------------------------
  733. // Adapter pointer was stashed in FsContext when handle was opened.
  734. //
  735. adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext;
  736. // Insure that adapter exists.
  737. ASSERT(adapter);
  738. if(adapter == NULL )
  739. {
  740. DEBUGP (("[TAP] release [%d.%d] close request; adapter not found\n",
  741. TAP_DRIVER_MAJOR_VERSION,
  742. TAP_DRIVER_MINOR_VERSION
  743. ));
  744. }
  745. if(adapter != NULL )
  746. {
  747. if(adapter->TapFileObject == NULL)
  748. {
  749. // Should never happen!!!
  750. ASSERT(FALSE);
  751. }
  752. else
  753. {
  754. ASSERT(irpSp->FileObject->FsContext == adapter);
  755. ASSERT(adapter->TapFileObject == irpSp->FileObject);
  756. }
  757. adapter->TapFileObject = NULL;
  758. irpSp->FileObject = NULL;
  759. // Remove reference added by when handle was opened.
  760. tapAdapterContextDereference(adapter);
  761. }
  762. // Complete the IRP.
  763. Irp->IoStatus.Status = status;
  764. Irp->IoStatus.Information = 0;
  765. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  766. DEBUGP (("[TAP] <-- TapDeviceClose; status = %8.8X\n",status));
  767. return status;
  768. }
  769. NTSTATUS
  770. tapConcatenateNdisStrings(
  771. __inout PNDIS_STRING DestinationString,
  772. __in_opt PNDIS_STRING SourceString1,
  773. __in_opt PNDIS_STRING SourceString2,
  774. __in_opt PNDIS_STRING SourceString3
  775. )
  776. {
  777. NTSTATUS status;
  778. ASSERT(SourceString1 && SourceString2 && SourceString3);
  779. status = RtlAppendUnicodeStringToString(
  780. DestinationString,
  781. SourceString1
  782. );
  783. if(status == STATUS_SUCCESS)
  784. {
  785. status = RtlAppendUnicodeStringToString(
  786. DestinationString,
  787. SourceString2
  788. );
  789. if(status == STATUS_SUCCESS)
  790. {
  791. status = RtlAppendUnicodeStringToString(
  792. DestinationString,
  793. SourceString3
  794. );
  795. }
  796. }
  797. return status;
  798. }
  799. NTSTATUS
  800. tapMakeDeviceNames(
  801. __in PTAP_ADAPTER_CONTEXT Adapter
  802. )
  803. {
  804. NDIS_STATUS status;
  805. NDIS_STRING deviceNamePrefix = NDIS_STRING_CONST("\\Device\\");
  806. NDIS_STRING tapNameSuffix = NDIS_STRING_CONST(".tap");
  807. // Generate DeviceName from NetCfgInstanceId.
  808. Adapter->DeviceName.Buffer = Adapter->DeviceNameBuffer;
  809. Adapter->DeviceName.MaximumLength = sizeof(Adapter->DeviceNameBuffer);
  810. status = tapConcatenateNdisStrings(
  811. &Adapter->DeviceName,
  812. &deviceNamePrefix,
  813. &Adapter->NetCfgInstanceId,
  814. &tapNameSuffix
  815. );
  816. if(status == STATUS_SUCCESS)
  817. {
  818. NDIS_STRING linkNamePrefix = NDIS_STRING_CONST("\\DosDevices\\Global\\");
  819. Adapter->LinkName.Buffer = Adapter->LinkNameBuffer;
  820. Adapter->LinkName.MaximumLength = sizeof(Adapter->LinkNameBuffer);
  821. status = tapConcatenateNdisStrings(
  822. &Adapter->LinkName,
  823. &linkNamePrefix,
  824. &Adapter->NetCfgInstanceId,
  825. &tapNameSuffix
  826. );
  827. }
  828. return status;
  829. }
  830. NDIS_STATUS
  831. CreateTapDevice(
  832. __in PTAP_ADAPTER_CONTEXT Adapter
  833. )
  834. {
  835. NDIS_STATUS status;
  836. NDIS_DEVICE_OBJECT_ATTRIBUTES deviceAttribute;
  837. PDRIVER_DISPATCH dispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
  838. DEBUGP (("[TAP] version [%d.%d] creating tap device: %wZ\n",
  839. TAP_DRIVER_MAJOR_VERSION,
  840. TAP_DRIVER_MINOR_VERSION,
  841. &Adapter->NetCfgInstanceId));
  842. // Generate DeviceName and LinkName from NetCfgInstanceId.
  843. status = tapMakeDeviceNames(Adapter);
  844. if (NT_SUCCESS(status))
  845. {
  846. DEBUGP (("[TAP] DeviceName: %wZ\n",&Adapter->DeviceName));
  847. DEBUGP (("[TAP] LinkName: %wZ\n",&Adapter->LinkName));
  848. // Initialize dispatch table.
  849. NdisZeroMemory(dispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));
  850. dispatchTable[IRP_MJ_CREATE] = TapDeviceCreate;
  851. dispatchTable[IRP_MJ_CLEANUP] = TapDeviceCleanup;
  852. dispatchTable[IRP_MJ_CLOSE] = TapDeviceClose;
  853. dispatchTable[IRP_MJ_READ] = TapDeviceRead;
  854. dispatchTable[IRP_MJ_WRITE] = TapDeviceWrite;
  855. dispatchTable[IRP_MJ_DEVICE_CONTROL] = TapDeviceControl;
  856. //
  857. // Create a device object and register dispatch handlers
  858. //
  859. NdisZeroMemory(&deviceAttribute, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES));
  860. deviceAttribute.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES;
  861. deviceAttribute.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
  862. deviceAttribute.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES);
  863. deviceAttribute.DeviceName = &Adapter->DeviceName;
  864. deviceAttribute.SymbolicName = &Adapter->LinkName;
  865. deviceAttribute.MajorFunctions = &dispatchTable[0];
  866. //deviceAttribute.ExtensionSize = sizeof(FILTER_DEVICE_EXTENSION);
  867. #if ENABLE_NONADMIN
  868. if(Adapter->AllowNonAdmin)
  869. {
  870. //
  871. // SDDL_DEVOBJ_SYS_ALL_WORLD_RWX_RES_RWX allows the kernel and system complete
  872. // control over the device. By default the admin can access the entire device,
  873. // but cannot change the ACL (the admin must take control of the device first)
  874. //
  875. // Everyone else, including "restricted" or "untrusted" code can read or write
  876. // to the device. Traversal beneath the device is also granted (removing it
  877. // would only effect storage devices, except if the "bypass-traversal"
  878. // privilege was revoked).
  879. //
  880. deviceAttribute.DefaultSDDLString = &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX;
  881. }
  882. #endif
  883. status = NdisRegisterDeviceEx(
  884. Adapter->MiniportAdapterHandle,
  885. &deviceAttribute,
  886. &Adapter->DeviceObject,
  887. &Adapter->DeviceHandle
  888. );
  889. }
  890. ASSERT(NT_SUCCESS(status));
  891. if (NT_SUCCESS(status))
  892. {
  893. // Set TAP device flags.
  894. (Adapter->DeviceObject)->Flags &= ~DO_BUFFERED_IO;
  895. (Adapter->DeviceObject)->Flags |= DO_DIRECT_IO;;
  896. //========================
  897. // Finalize initialization
  898. //========================
  899. Adapter->TapDeviceCreated = TRUE;
  900. DEBUGP (("[%wZ] successfully created TAP device [%wZ]\n",
  901. &Adapter->NetCfgInstanceId,
  902. &Adapter->DeviceName
  903. ));
  904. }
  905. DEBUGP (("[TAP] <-- CreateTapDevice; status = %8.8X\n",status));
  906. return status;
  907. }
  908. //
  909. // DestroyTapDevice is called from AdapterHalt and NDIS miniport
  910. // is in Halted state. Prior to entering the Halted state the
  911. // miniport would have passed through the Pausing and Paused
  912. // states. These miniport states have responsibility for waiting
  913. // until NDIS network operations have completed.
  914. //
  915. VOID
  916. DestroyTapDevice(
  917. __in PTAP_ADAPTER_CONTEXT Adapter
  918. )
  919. {
  920. DEBUGP (("[TAP] --> DestroyTapDevice; Adapter: %wZ\n",
  921. &Adapter->NetCfgInstanceId));
  922. //
  923. // Let clients know we are shutting down
  924. //
  925. Adapter->TapDeviceCreated = FALSE;
  926. //
  927. // Flush pending send TAP packet queue.
  928. //
  929. tapFlushSendPacketQueue(Adapter);
  930. ASSERT(Adapter->SendPacketQueue.Count == 0);
  931. //
  932. // Flush IRP queues. Wait for pending I/O. Etc.
  933. // --------------------------------------------
  934. // Exhaust IRP and packet queues. Any pending IRPs will
  935. // be cancelled, causing user-space to get this error
  936. // on overlapped reads:
  937. //
  938. // ERROR_OPERATION_ABORTED, code=995
  939. //
  940. // "The I/O operation has been aborted because of either a
  941. // thread exit or an application request."
  942. //
  943. // It's important that user-space close the device handle
  944. // when this code is returned, so that when we finally
  945. // do a NdisMDeregisterDeviceEx, the device reference count
  946. // is 0. Otherwise the driver will not unload even if the
  947. // the last adapter has been halted.
  948. //
  949. // The act of flushing the queues at this point should result in the user-mode
  950. // application closing the adapter's device handle. Closing the handle will
  951. // result in the TapDeviceCleanup call being made, followed by the a call to
  952. // the TapDeviceClose callback.
  953. //
  954. tapFlushIrpQueues(Adapter);
  955. ASSERT(Adapter->PendingReadIrpQueue.Count == 0);
  956. //
  957. // Deregister the Win32 device.
  958. // ----------------------------
  959. // When a driver calls NdisDeregisterDeviceEx, the I/O manager deletes the
  960. // target device object if there are no outstanding references to it. However,
  961. // if any outstanding references remain, the I/O manager marks the device
  962. // object as "delete pending" and deletes the device object when the references
  963. // are finally released.
  964. //
  965. if(Adapter->DeviceHandle)
  966. {
  967. DEBUGP (("[TAP] Calling NdisDeregisterDeviceEx\n"));
  968. NdisDeregisterDeviceEx(Adapter->DeviceHandle);
  969. }
  970. Adapter->DeviceHandle = NULL;
  971. DEBUGP (("[TAP] <-- DestroyTapDevice\n"));
  972. }