📄 write.c
字号:
/*
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
* Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#include "debug.h"
#include "packet.h"
extern UINT g_SendPacketFlags;
//-------------------------------------------------------------------
NTSTATUS
NPF_Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PNDIS_PACKET pPacket;
NDIS_STATUS Status;
ULONG NumSends;
ULONG numSentPackets;
TRACE_ENTER();
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open=IrpSp->FileObject->FsContext;
NumSends = Open->Nwrites;
//
// validate the send parameters set by the IOCTL
//
if (NumSends == 0)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_SUCCESS;
}
//
// Validate input parameters:
// 1. The packet size should be greater than 0,
// 2. less-equal than max frame size for the link layer and
// 3. the maximum frame size of the link layer should not be zero.
//
if(IrpSp->Parameters.Write.Length == 0 || // Check that the buffer provided by the user is not empty
Open->MaxFrameSize == 0 || // Check that the MaxFrameSize is correctly initialized
Irp->MdlAddress == NULL ||
IrpSp->Parameters.Write.Length > Open->MaxFrameSize) // Check that the fame size is smaller that the MTU
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD,"Frame size out of range, or maxFrameSize = 0. Send aborted");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_UNSUCCESSFUL;
}
//
// Increment the ref counter of the binding handle, if possible
//
if(NPF_StartUsingBinding(Open) == FALSE)
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD,"Adapter is probably unbinding, cannot send packets");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_INVALID_DEVICE_REQUEST;
}
NdisAcquireSpinLock(&Open->WriteLock);
if(Open->WriteInProgress)
{
// Another write operation is currently in progress
NdisReleaseSpinLock(&Open->WriteLock);
NPF_StopUsingBinding(Open);
TRACE_MESSAGE(PACKET_DEBUG_LOUD,"Another Send operation is in progress, aborting.");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_UNSUCCESSFUL;
}
else
{
Open->WriteInProgress = TRUE;
NdisResetEvent(&Open->NdisWriteCompleteEvent);
}
NdisReleaseSpinLock(&Open->WriteLock);
TRACE_MESSAGE2(PACKET_DEBUG_LOUD,"Max frame size = %u, packet size = %u", Open->MaxFrameSize, IrpSp->Parameters.Write.Length);
//
// reset the number of packets pending the SendComplete
//
Open->TransmitPendingPackets = 0;
NdisResetEvent(&Open->WriteEvent);
numSentPackets = 0;
while( numSentPackets < NumSends )
{
NdisAllocatePacket(
&Status,
&pPacket,
Open->PacketPool
);
if (Status == NDIS_STATUS_SUCCESS)
{
//
// packet is available, prepare it and send it with NdisSend.
//
//
// If asked, set the flags for this packet.
// Currently, the only situation in which we set the flags is to disable the reception of loopback
// packets, i.e. of the packets sent by us.
//
if(Open->SkipSentPackets)
{
NdisSetPacketFlags(
pPacket,
g_SendPacketFlags);
}
// The packet hasn't a buffer that needs not to be freed after every single write
RESERVED(pPacket)->FreeBufAfterWrite = FALSE;
// // Save the IRP associated with the packet
// RESERVED(pPacket)->Irp=Irp;
// Attach the writes buffer to the packet
NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
InterlockedIncrement(&Open->TransmitPendingPackets);
NdisResetEvent(&Open->NdisWriteCompleteEvent);
//
// Call the MAC
//
NdisSend(
&Status,
Open->AdapterHandle,
pPacket);
if (Status != NDIS_STATUS_PENDING)
{
// The send didn't pend so call the completion handler now
NPF_SendComplete(
Open,
pPacket,
Status
);
}
numSentPackets ++;
}
else
{
//
// no packets are available in the Transmit pool, wait some time. The
// event gets signalled when at least half of the TX packet pool packets
// are available
//
NdisWaitEvent(&Open->WriteEvent,1);
}
}
//
// when we reach this point, all the packets have been enqueued to NdisSend,
// we just need to wait for all the packets to be completed by the SendComplete
// (if any of the NdisSend requests returned STATUS_PENDING)
//
NdisWaitEvent(&Open->NdisWriteCompleteEvent, 0);
//
// all the packets have been transmitted, release the use of the adapter binding
//
NPF_StopUsingBinding(Open);
//
// no more writes are in progress
//
NdisAcquireSpinLock(&Open->WriteLock);
Open->WriteInProgress = FALSE;
NdisReleaseSpinLock(&Open->WriteLock);
//
// Complete the Irp and return success
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = IrpSp->Parameters.Write.Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_SUCCESS;
}
//-------------------------------------------------------------------
INT
NPF_BufferedWrite(
IN PIRP Irp,
IN PCHAR UserBuff,
IN ULONG UserBuffSize,
BOOLEAN Sync)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PNDIS_PACKET pPacket;
UINT i;
NDIS_STATUS Status;
LARGE_INTEGER StartTicks, CurTicks, TargetTicks;
LARGE_INTEGER TimeFreq;
struct timeval BufStartTime;
struct sf_pkthdr *winpcap_hdr;
PMDL TmpMdl;
PCHAR CurPos;
PCHAR EndOfUserBuff = UserBuff + UserBuffSize;
IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%p, Size=%u\n", UserBuff, UserBuffSize);)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open=IrpSp->FileObject->FsContext;
if( NPF_StartUsingBinding(Open) == FALSE)
{
// The Network adapter was removed.
return 0;
}
// Sanity check on the user buffer
if(UserBuff == NULL)
{
//
// release ownership of the NdisAdapter binding
//
NPF_StopUsingBinding(Open);
return 0;
}
// Check that the MaxFrameSize is correctly initialized
if(Open->MaxFrameSize == 0)
{
IF_LOUD(DbgPrint("BufferedWrite: Open->MaxFrameSize not initialized, probably because of a problem in the OID query\n");)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -