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

/*++
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);
}