223 lines
5.4 KiB
C
223 lines
5.4 KiB
C
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
send.c
|
|
|
|
Abstract:
|
|
|
|
utility routines to handle sending data.
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
alid 10/22/2001 modified for tunmp
|
|
arvindm 4/10/2000 Created
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#define __FILENUMBER 'DNES'
|
|
|
|
|
|
NTSTATUS
|
|
TunWrite(
|
|
IN PDEVICE_OBJECT pDeviceObject,
|
|
IN PIRP pIrp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dispatch routine to handle IRP_MJ_WRITE.
|
|
|
|
Arguments:
|
|
|
|
pDeviceObject - pointer to our device object
|
|
pIrp - Pointer to request packet
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION pIrpSp;
|
|
ULONG DataLength;
|
|
NTSTATUS NtStatus;
|
|
NDIS_STATUS Status;
|
|
PTUN_ADAPTER pAdapter;
|
|
PNDIS_PACKET pNdisPacket;
|
|
PNDIS_BUFFER pNdisBuffer;
|
|
PVOID Address;
|
|
|
|
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
|
|
pIrp->IoStatus.Information = 0;
|
|
pAdapter = (PTUN_ADAPTER)pIrpSp->FileObject->FsContext;
|
|
|
|
DEBUGP(DL_LOUD, ("==>TunWrite: Adapter %p/%x\n",
|
|
pAdapter, pAdapter->Flags));
|
|
|
|
|
|
pNdisPacket = NULL;
|
|
|
|
do
|
|
{
|
|
if (pAdapter == NULL)
|
|
{
|
|
DEBUGP(DL_WARN, ("Write: FileObject %p not yet associated with a device\n",
|
|
pIrpSp->FileObject));
|
|
NtStatus = STATUS_INVALID_HANDLE;
|
|
break;
|
|
}
|
|
|
|
TUN_STRUCT_ASSERT(pAdapter, mc);
|
|
|
|
|
|
if(pIrp->MdlAddress == NULL)
|
|
{
|
|
NtStatus = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Sanity-check the length.
|
|
//
|
|
DataLength = MmGetMdlByteCount(pIrp->MdlAddress);
|
|
if (DataLength < sizeof(TUN_ETH_HEADER))
|
|
{
|
|
DEBUGP(DL_WARN, ("Write: too small to be a valid packet (%d bytes)\n",
|
|
DataLength));
|
|
NtStatus = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
Address = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
|
|
if (Address == NULL)
|
|
{
|
|
DEBUGP(DL_WARN, ("Write: Adapter %p: Mdl %p"
|
|
" couldn't get the system address for MDL\n",
|
|
pAdapter, pIrp->MdlAddress));
|
|
|
|
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
if (DataLength > (pAdapter->MediumMaxFrameLen + sizeof(TUN_ETH_HEADER)))
|
|
{
|
|
DEBUGP(DL_WARN, ("Write: Adapter %p: data length (%d)"
|
|
" larger than max frame size (%d)\n",
|
|
pAdapter, DataLength, pAdapter->MediumMaxFrameLen));
|
|
|
|
NtStatus = STATUS_INVALID_BUFFER_SIZE;
|
|
break;
|
|
}
|
|
|
|
|
|
TUN_ACQUIRE_LOCK(&pAdapter->Lock);
|
|
|
|
if ((!TUN_TEST_FLAGS(pAdapter, TUN_ADAPTER_ACTIVE)) ||
|
|
TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_OFF))
|
|
{
|
|
TUN_RELEASE_LOCK(&pAdapter->Lock);
|
|
|
|
DEBUGP(DL_FATAL, ("Write: Adapter %p is not bound"
|
|
" or in low power state\n", pAdapter));
|
|
|
|
NtStatus = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Allocate a send packet.
|
|
//
|
|
TUN_ASSERT(pAdapter->SendPacketPool != NULL);
|
|
NdisAllocatePacket(
|
|
&Status,
|
|
&pNdisPacket,
|
|
pAdapter->SendPacketPool);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TUN_RELEASE_LOCK(&pAdapter->Lock);
|
|
|
|
DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send pkt\n",
|
|
pAdapter));
|
|
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
//1 we should do a copy here
|
|
pNdisBuffer = pIrp->MdlAddress;
|
|
pAdapter->PendedSendCount++;
|
|
pAdapter->RcvBytes += MmGetMdlByteCount(pIrp->MdlAddress);
|
|
|
|
TUN_REF_ADAPTER(pAdapter); // pended send
|
|
|
|
IoMarkIrpPending(pIrp);
|
|
|
|
//
|
|
// Initialize the packet ref count. This packet will be freed
|
|
// when this count goes to zero.
|
|
//
|
|
TUN_SEND_PKT_RSVD(pNdisPacket)->RefCount = 1;
|
|
|
|
TUN_RELEASE_LOCK(&pAdapter->Lock);
|
|
|
|
//
|
|
// Set a back pointer from the packet to the IRP.
|
|
//
|
|
TUN_IRP_FROM_SEND_PKT(pNdisPacket) = pIrp;
|
|
|
|
NtStatus = STATUS_PENDING;
|
|
|
|
pNdisBuffer->Next = NULL;
|
|
NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
|
|
|
|
#if SEND_DBG
|
|
{
|
|
PUCHAR pData;
|
|
|
|
pData = MmGetSystemAddressForMdlSafe(pNdisBuffer, NormalPagePriority);
|
|
TUN_ASSERT(pEthHeader == pData);
|
|
|
|
DEBUGP(DL_VERY_LOUD,
|
|
("Write: MDL %p, MdlFlags %x, SystemAddr %p, %d bytes\n",
|
|
pIrp->MdlAddress, pIrp->MdlAddress->MdlFlags, pData, DataLength));
|
|
|
|
DEBUGPDUMP(DL_VERY_LOUD, pData, MIN(DataLength, 48));
|
|
}
|
|
#endif // SEND_DBG
|
|
|
|
NDIS_SET_PACKET_STATUS(pNdisPacket, NDIS_STATUS_SUCCESS);
|
|
NDIS_SET_PACKET_HEADER_SIZE(pNdisPacket, sizeof(TUN_ETH_HEADER));
|
|
|
|
NdisMIndicateReceivePacket(pAdapter->MiniportHandle,
|
|
&pNdisPacket,
|
|
1);
|
|
|
|
|
|
}
|
|
while (FALSE);
|
|
|
|
if (NtStatus != STATUS_PENDING)
|
|
{
|
|
pIrp->IoStatus.Status = NtStatus;
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
DEBUGP(DL_LOUD, ("<==TunWrite: Adapter %p/%x\n",
|
|
pAdapter, pAdapter->Flags));
|
|
|
|
return (NtStatus);
|
|
}
|
|
|
|
|
|
|