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.

222 lines
5.7 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. send.c
  5. Abstract:
  6. utility routines to handle sending data.
  7. Environment:
  8. Kernel mode only.
  9. Revision History:
  10. alid 10/22/2001 modified for tunmp
  11. arvindm 4/10/2000 Created
  12. --*/
  13. #include "precomp.h"
  14. #define __FILENUMBER 'DNES'
  15. NTSTATUS
  16. TunWrite(
  17. IN PDEVICE_OBJECT pDeviceObject,
  18. IN PIRP pIrp
  19. )
  20. /*++
  21. Routine Description:
  22. Dispatch routine to handle IRP_MJ_WRITE.
  23. Arguments:
  24. pDeviceObject - pointer to our device object
  25. pIrp - Pointer to request packet
  26. Return Value:
  27. NT status code.
  28. --*/
  29. {
  30. PIO_STACK_LOCATION pIrpSp;
  31. ULONG DataLength;
  32. NTSTATUS NtStatus;
  33. NDIS_STATUS Status;
  34. PTUN_ADAPTER pAdapter;
  35. PNDIS_PACKET pNdisPacket;
  36. PNDIS_BUFFER pNdisBuffer;
  37. PVOID Address;
  38. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  39. pIrp->IoStatus.Information = 0;
  40. pAdapter = (PTUN_ADAPTER)pIrpSp->FileObject->FsContext;
  41. DEBUGP(DL_LOUD, ("==>TunWrite: Adapter %p/%x\n",
  42. pAdapter, pAdapter->Flags));
  43. pNdisPacket = NULL;
  44. do
  45. {
  46. if (pAdapter == NULL)
  47. {
  48. DEBUGP(DL_WARN, ("Write: FileObject %p not yet associated with a device\n",
  49. pIrpSp->FileObject));
  50. NtStatus = STATUS_INVALID_HANDLE;
  51. break;
  52. }
  53. TUN_STRUCT_ASSERT(pAdapter, mc);
  54. if(pIrp->MdlAddress == NULL)
  55. {
  56. NtStatus = STATUS_INVALID_PARAMETER;
  57. break;
  58. }
  59. //
  60. // Sanity-check the length.
  61. //
  62. DataLength = MmGetMdlByteCount(pIrp->MdlAddress);
  63. if (DataLength < sizeof(TUN_ETH_HEADER))
  64. {
  65. DEBUGP(DL_WARN, ("Write: too small to be a valid packet (%d bytes)\n",
  66. DataLength));
  67. NtStatus = STATUS_BUFFER_TOO_SMALL;
  68. break;
  69. }
  70. Address = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
  71. if (Address == NULL)
  72. {
  73. DEBUGP(DL_WARN, ("Write: Adapter %p: Mdl %p"
  74. " couldn't get the system address for MDL\n",
  75. pAdapter, pIrp->MdlAddress));
  76. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  77. break;
  78. }
  79. if (DataLength > (pAdapter->MediumMaxFrameLen + sizeof(TUN_ETH_HEADER)))
  80. {
  81. DEBUGP(DL_WARN, ("Write: Adapter %p: data length (%d)"
  82. " larger than max frame size (%d)\n",
  83. pAdapter, DataLength, pAdapter->MediumMaxFrameLen));
  84. NtStatus = STATUS_INVALID_BUFFER_SIZE;
  85. break;
  86. }
  87. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  88. if ((!TUN_TEST_FLAGS(pAdapter, TUN_ADAPTER_ACTIVE)) ||
  89. TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_OFF))
  90. {
  91. TUN_RELEASE_LOCK(&pAdapter->Lock);
  92. DEBUGP(DL_FATAL, ("Write: Adapter %p is not bound"
  93. " or in low power state\n", pAdapter));
  94. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  95. break;
  96. }
  97. //
  98. // Allocate a send packet.
  99. //
  100. TUN_ASSERT(pAdapter->SendPacketPool != NULL);
  101. NdisAllocatePacket(
  102. &Status,
  103. &pNdisPacket,
  104. pAdapter->SendPacketPool);
  105. if (Status != NDIS_STATUS_SUCCESS)
  106. {
  107. TUN_RELEASE_LOCK(&pAdapter->Lock);
  108. DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send pkt\n",
  109. pAdapter));
  110. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  111. break;
  112. }
  113. //1 we should do a copy here
  114. pNdisBuffer = pIrp->MdlAddress;
  115. pAdapter->PendedSendCount++;
  116. pAdapter->RcvBytes += MmGetMdlByteCount(pIrp->MdlAddress);
  117. TUN_REF_ADAPTER(pAdapter); // pended send
  118. IoMarkIrpPending(pIrp);
  119. //
  120. // Initialize the packet ref count. This packet will be freed
  121. // when this count goes to zero.
  122. //
  123. TUN_SEND_PKT_RSVD(pNdisPacket)->RefCount = 1;
  124. TUN_RELEASE_LOCK(&pAdapter->Lock);
  125. //
  126. // Set a back pointer from the packet to the IRP.
  127. //
  128. TUN_IRP_FROM_SEND_PKT(pNdisPacket) = pIrp;
  129. NtStatus = STATUS_PENDING;
  130. pNdisBuffer->Next = NULL;
  131. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  132. #if SEND_DBG
  133. {
  134. PUCHAR pData;
  135. pData = MmGetSystemAddressForMdlSafe(pNdisBuffer, NormalPagePriority);
  136. TUN_ASSERT(pEthHeader == pData);
  137. DEBUGP(DL_VERY_LOUD,
  138. ("Write: MDL %p, MdlFlags %x, SystemAddr %p, %d bytes\n",
  139. pIrp->MdlAddress, pIrp->MdlAddress->MdlFlags, pData, DataLength));
  140. DEBUGPDUMP(DL_VERY_LOUD, pData, MIN(DataLength, 48));
  141. }
  142. #endif // SEND_DBG
  143. NDIS_SET_PACKET_STATUS(pNdisPacket, NDIS_STATUS_SUCCESS);
  144. NDIS_SET_PACKET_HEADER_SIZE(pNdisPacket, sizeof(TUN_ETH_HEADER));
  145. NdisMIndicateReceivePacket(pAdapter->MiniportHandle,
  146. &pNdisPacket,
  147. 1);
  148. }
  149. while (FALSE);
  150. if (NtStatus != STATUS_PENDING)
  151. {
  152. pIrp->IoStatus.Status = NtStatus;
  153. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  154. }
  155. DEBUGP(DL_LOUD, ("<==TunWrite: Adapter %p/%x\n",
  156. pAdapter, pAdapter->Flags));
  157. return (NtStatus);
  158. }