Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

478 lines
12 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. tunf.c
  5. Abstract:
  6. utility routines to handle opening and closing the tunmp device.
  7. Environment:
  8. Kernel mode only.
  9. Revision History:
  10. alid 10/22/2001 modified for tunmp
  11. --*/
  12. #include "precomp.h"
  13. #define __FILENUMBER 'FNUT'
  14. NTSTATUS
  15. TunFOpen(
  16. IN PDEVICE_OBJECT DeviceObject,
  17. IN PIRP pIrp
  18. )
  19. /*++
  20. Routine Description:
  21. Hanndles IRP_MJ_CREATE. Here we set the device status in use, assigns a pointer
  22. from the file object to the adapter object using pIrpSp->FileObject->FsContext,
  23. allocates packet and buffer pools, and returns a success status
  24. Arguments:
  25. pDeviceObject - Pointer to the device object.
  26. pIrp - Pointer to the request packet.
  27. Return Value:
  28. Status is returned.
  29. --*/
  30. {
  31. PIO_STACK_LOCATION pIrpSp;
  32. NDIS_STATUS NdisStatus;
  33. NTSTATUS NtStatus = STATUS_SUCCESS;
  34. UINT i;
  35. BOOLEAN Found = FALSE;
  36. PLIST_ENTRY pListEntry;
  37. PTUN_ADAPTER pAdapter = NULL;
  38. BOOLEAN DerefAdapter = FALSE;
  39. DEBUGP(DL_INFO, ("Open: DeviceObject %p\n", DeviceObject));
  40. do
  41. {
  42. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  43. TUN_ACQUIRE_LOCK(&TunGlobalLock);
  44. for (pListEntry = TunAdapterList.Flink;
  45. pListEntry != &TunAdapterList;
  46. pListEntry = pListEntry->Flink)
  47. {
  48. pAdapter = CONTAINING_RECORD(pListEntry,
  49. TUN_ADAPTER,
  50. Link);
  51. if(pAdapter->DeviceObject == DeviceObject)
  52. {
  53. Found = TRUE;
  54. TUN_REF_ADAPTER(pAdapter);
  55. DerefAdapter = TRUE;
  56. break;
  57. }
  58. }
  59. TUN_RELEASE_LOCK(&TunGlobalLock);
  60. if (Found == FALSE)
  61. {
  62. NtStatus = STATUS_NO_SUCH_DEVICE;
  63. break;
  64. }
  65. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  66. if (TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_OPEN))
  67. {
  68. //
  69. // adapter is already open by another device. fail
  70. //
  71. TUN_RELEASE_LOCK(&pAdapter->Lock);
  72. NtStatus = STATUS_INVALID_DEVICE_STATE;
  73. break;
  74. }
  75. TUN_SET_FLAG(pAdapter, TUN_ADAPTER_OPEN | TUN_ADAPTER_CANT_HALT);
  76. TUN_RELEASE_LOCK(&pAdapter->Lock);
  77. //Assign a pointer to the adapter object from the file object
  78. pIrpSp->FileObject->FsContext = (PVOID)pAdapter;
  79. //Get the device connected to the network by cable plugging in
  80. NdisMIndicateStatus(pAdapter->MiniportHandle,
  81. NDIS_STATUS_MEDIA_CONNECT,
  82. NULL,
  83. 0);
  84. NdisMIndicateStatusComplete(pAdapter->MiniportHandle);
  85. DerefAdapter = FALSE;
  86. } while (FALSE);
  87. //
  88. //Complete the IRP
  89. //
  90. pIrp->IoStatus.Information = 0;
  91. pIrp->IoStatus.Status = NtStatus;
  92. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  93. if (DerefAdapter)
  94. {
  95. TUN_DEREF_ADAPTER(pAdapter);
  96. }
  97. return (NtStatus);
  98. }
  99. //************************************************************************
  100. NTSTATUS
  101. TunFClose(
  102. IN PDEVICE_OBJECT pDeviceObject,
  103. IN PIRP pIrp
  104. )
  105. /*++
  106. Routine Description:
  107. Handles IRP_MJ_CLOSE. Here we change the device state into available (not in
  108. use), free the the file object's pointer to the adapter object, free the
  109. allocated packet/buffer pools, and set the success status.
  110. Arguments:
  111. pDeviceObject - Pointer to the device object.
  112. pIrp - Pointer to the request packet.
  113. Return Value:
  114. Status is returned.
  115. --*/
  116. {
  117. //1 this may be moved to clean_up
  118. NTSTATUS NtStatus;
  119. PIO_STACK_LOCATION pIrpSp;
  120. PTUN_ADAPTER pAdapter;
  121. PLIST_ENTRY pRcvPacketEntry;
  122. PNDIS_PACKET pRcvPacket;
  123. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  124. pAdapter = (PTUN_ADAPTER)pIrpSp->FileObject->FsContext;
  125. DEBUGP(DL_INFO, ("Close: FileObject %p\n",
  126. IoGetCurrentIrpStackLocation(pIrp)->FileObject));
  127. //If no adapter/device object is associated with the this file object
  128. if (pAdapter == NULL)
  129. {
  130. NtStatus = STATUS_IO_DEVICE_ERROR;
  131. }
  132. else
  133. {
  134. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  135. TUN_CLEAR_FLAG(pAdapter, TUN_ADAPTER_OPEN);
  136. TUN_RELEASE_LOCK(&pAdapter->Lock);
  137. NdisMIndicateStatus(pAdapter->MiniportHandle,
  138. NDIS_STATUS_MEDIA_DISCONNECT,
  139. NULL,
  140. 0);
  141. NdisMIndicateStatusComplete(pAdapter->MiniportHandle);
  142. //Let the adapter object free
  143. pIrpSp->FileObject->FsContext = NULL;
  144. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  145. //
  146. //Emtpy the received packets queue, and return the packets to NDIS
  147. //with success status
  148. //
  149. while(!IsListEmpty(&pAdapter->RecvPktQueue))
  150. {
  151. //
  152. //Remove the first queued received packet from the entry list
  153. //
  154. pRcvPacketEntry = pAdapter->RecvPktQueue.Flink;
  155. RemoveEntryList(pRcvPacketEntry);
  156. ExInterlockedDecrementLong(&pAdapter->RecvPktCount, &pAdapter->Lock);
  157. //Get the packet from
  158. pRcvPacket = CONTAINING_RECORD(pRcvPacketEntry,
  159. NDIS_PACKET,
  160. MiniportReserved[0]);
  161. TUN_RELEASE_LOCK(&pAdapter->Lock);
  162. //Indicate NDIS about comletion of the packet
  163. NdisMSendComplete(pAdapter->MiniportHandle,
  164. pRcvPacket,
  165. NDIS_STATUS_FAILURE);
  166. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  167. }
  168. TUN_RELEASE_LOCK(&pAdapter->Lock);
  169. NtStatus = STATUS_SUCCESS;
  170. }
  171. //1 who should do the testing of tunmp
  172. //
  173. //Complete the IRP
  174. //
  175. pIrp->IoStatus.Information = 0;
  176. pIrp->IoStatus.Status = NtStatus;
  177. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  178. if (pAdapter != NULL)
  179. {
  180. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  181. TUN_CLEAR_FLAG(pAdapter, TUN_ADAPTER_CANT_HALT);
  182. if (pAdapter->HaltEvent != NULL)
  183. {
  184. NdisSetEvent(pAdapter->HaltEvent);
  185. }
  186. TUN_RELEASE_LOCK(&pAdapter->Lock);
  187. }
  188. KdPrint(("\nTunFClose: Exit\n"));
  189. return (NtStatus);
  190. }
  191. //************************************************************************
  192. NTSTATUS
  193. TunFCleanup(
  194. IN PDEVICE_OBJECT pDeviceObject,
  195. IN PIRP pIrp
  196. )
  197. /*++
  198. Routine Description:
  199. Handles IRP_MJ_CLEANUP. Here we reset the driver's cancel entry point to NULL
  200. in every IRP currently in the driver's internal queue of read IRPs, cancel
  201. all the queued IRPs, and return a success status.
  202. Arguments:
  203. pDeviceObject - Pointer to the device object.
  204. pIrp - Pointer to the request packet.
  205. Return Value:
  206. Status is returned.
  207. --*/
  208. {
  209. PIO_STACK_LOCATION pIrpSp;
  210. NTSTATUS NtStatus;
  211. PTUN_ADAPTER pAdapter;
  212. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  213. pAdapter = (PTUN_ADAPTER)pIrpSp->FileObject->FsContext;
  214. DEBUGP(DL_INFO, ("Cleanup: FileObject %p, pAdapter %p\n",
  215. pIrpSp->FileObject, pAdapter));
  216. if (pAdapter != NULL)
  217. {
  218. TUN_STRUCT_ASSERT(pAdapter, mc);
  219. //
  220. // Mark this endpoint.
  221. //
  222. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  223. TUN_CLEAR_FLAG(pAdapter, TUN_ADAPTER_OPEN);
  224. pAdapter->pFileObject = NULL;
  225. TUN_RELEASE_LOCK(&pAdapter->Lock);
  226. TunCancelPendingReads(pAdapter);
  227. }
  228. NtStatus = STATUS_SUCCESS;
  229. //
  230. //Complete the IRP
  231. //
  232. pIrp->IoStatus.Information = 0;
  233. pIrp->IoStatus.Status = NtStatus;
  234. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  235. DEBUGP(DL_INFO, ("Cleanup: OpenContext %p\n", pAdapter));
  236. return (NtStatus);
  237. }
  238. //************************************************************************
  239. NTSTATUS
  240. TunFIoControl(
  241. IN PDEVICE_OBJECT pDeviceObject,
  242. IN PIRP pIrp
  243. )
  244. /*++
  245. Routine Description:
  246. This is the dispatch routine for handling device IOCTL requests.
  247. Arguments:
  248. pDeviceObject - Pointer to the device object.
  249. pIrp - Pointer to the request packet.
  250. Return Value:
  251. Status is returned.
  252. --*/
  253. {
  254. PIO_STACK_LOCATION pIrpSp;
  255. PTUN_ADAPTER pAdapter;
  256. NTSTATUS NtStatus = STATUS_SUCCESS;
  257. ULONG BytesReturned = 0;
  258. PUCHAR OutputBuffer = NULL;
  259. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  260. pAdapter = (PTUN_ADAPTER)pIrpSp->FileObject->FsContext;
  261. // pIrp->IoStatus.Information = 0;
  262. //if no adapter/device object is associated with this file object
  263. if (pAdapter == NULL)
  264. {
  265. pIrp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
  266. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  267. return NtStatus;
  268. }
  269. //1 check for valid adapter
  270. pIrp->IoStatus.Information = 0;
  271. OutputBuffer = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer;
  272. switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode)
  273. {
  274. case IOCTL_TUN_GET_MEDIUM_TYPE:
  275. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(NDIS_MEDIUM))
  276. {
  277. NtStatus = STATUS_BUFFER_TOO_SMALL;
  278. }
  279. else
  280. {
  281. *((PNDIS_MEDIUM)OutputBuffer) = pAdapter->Medium;
  282. BytesReturned = sizeof(ULONG);
  283. }
  284. break;
  285. case IOCTL_TUN_GET_MTU:
  286. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
  287. {
  288. NtStatus = STATUS_BUFFER_TOO_SMALL;
  289. }
  290. else
  291. {
  292. *((PULONG)OutputBuffer) = pAdapter->MediumMaxPacketLen;
  293. BytesReturned = sizeof(ULONG);
  294. }
  295. break;
  296. case IOCTL_TUN_GET_PACKET_FILTER:
  297. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
  298. {
  299. NtStatus = STATUS_BUFFER_TOO_SMALL;
  300. }
  301. else
  302. {
  303. *((PULONG)OutputBuffer) = pAdapter->PacketFilter;
  304. BytesReturned = sizeof(ULONG);
  305. }
  306. break;
  307. case IOCTL_TUN_GET_MINIPORT_NAME:
  308. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < pAdapter->MiniportName.Length + sizeof(USHORT))
  309. {
  310. NtStatus = STATUS_BUFFER_TOO_SMALL;
  311. }
  312. else
  313. {
  314. *((PUSHORT)OutputBuffer) = pAdapter->MiniportName.Length;
  315. TUN_COPY_MEM(OutputBuffer + sizeof(USHORT),
  316. (PUCHAR)pAdapter->MiniportName.Buffer,
  317. pAdapter->MiniportName.Length);
  318. BytesReturned = pAdapter->MiniportName.Length + sizeof(USHORT);
  319. }
  320. break;
  321. default:
  322. NtStatus = STATUS_NOT_SUPPORTED;
  323. break;
  324. }
  325. pIrp->IoStatus.Information = BytesReturned;
  326. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength = BytesReturned;
  327. pIrp->IoStatus.Status = NtStatus;
  328. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  329. return (NtStatus);
  330. }