📄 sendrcv.c
字号:
}
VOID
NICFreeRecvPacket(
PMP_ADAPTER Adapter,
PNDIS_PACKET Packet)
/*++
Routine Description:
Adapter - pointer to the adapter structure
Packet - pointer to the receive packet
Arguments:
This is called by MPReturnPacket to free the Receive packet
indicated above. Since we have used the send-side TCB, we
will also carefully complete the pending SendPacket if we are
the last one to use the TCB buffers.
Return Value:
VOID
--*/
{
PTCB pTCB = *(PTCB *)Packet->MiniportReserved;
PMP_ADAPTER SendAdapter = (PMP_ADAPTER)pTCB->Adapter;
PNDIS_PACKET SendPacket = pTCB->OrgSendPacket;
PLIST_ENTRY pEntry;
DEBUGP(MP_TRACE, ("--> NICFreeRecvPacket\n"));
DEBUGP(MP_INFO, ("Adapter= %p FreePkt= %p Ref=%d\n",
SendAdapter, SendPacket, pTCB->Ref));
ASSERT(pTCB->Ref > 0);
ASSERT(Adapter);
//
// Put the packet back in the free list for reuse.
//
NdisAcquireSpinLock(&Adapter->RecvLock);
InsertTailList(
&Adapter->RecvFreeList,
(PLIST_ENTRY)&Packet->MiniportReserved[0]);
Adapter->nBusyRecv--;
ASSERT(Adapter->nBusyRecv >= 0);
NdisReleaseSpinLock(&Adapter->RecvLock);
//
// Check to see whether we are the last one to use the TCB
// by decrementing the refcount. If so, complete the pending
// Send packet and free the TCB block for reuse.
//
if(NdisInterlockedDecrement(&pTCB->Ref) == 0)
{
Adapter->GoodTransmits++;
NdisMSendComplete(
SendAdapter->AdapterHandle,
SendPacket,
NDIS_STATUS_SUCCESS);
NICFreeSendTCB(SendAdapter, pTCB);
//
// Before we exit, since we have the control, let use see if there any
// more packets waiting in the queue to be sent.
//
if(MP_IS_READY(SendAdapter))
{
pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
&SendAdapter->SendWaitList,
&SendAdapter->SendLock);
if(pEntry)
{
SendPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
NICSendPacket(SendAdapter, SendPacket);
}
}
}
DEBUGP(MP_TRACE, ("<-- NICFreeRecvPacket\n"));
}
VOID
NICFreeSendTCB(
IN PMP_ADAPTER Adapter,
IN PTCB pTCB)
/*++
Routine Description:
Adapter - pointer to the adapter structure
pTCB - pointer to TCB block
Arguments:
This routine reinitializes the TCB block and puts it back
into the SendFreeList for reuse.
Return Value:
VOID
--*/
{
DEBUGP(MP_TRACE, ("--> NICFreeSendTCB %p\n", pTCB));
pTCB->OrgSendPacket = NULL;
pTCB->Buffer->Next = NULL;
ASSERT(!pTCB->Ref);
//
// Re adjust the length to the originl size
//
NdisAdjustBufferLength(pTCB->Buffer, NIC_BUFFER_SIZE);
//
// Insert the TCB back in the send free list
//
NdisAcquireSpinLock(&Adapter->SendLock);
NdisInitializeListHead(&pTCB->List);
InsertHeadList(&Adapter->SendFreeList, &pTCB->List);
Adapter->nBusySend--;
ASSERT(Adapter->nBusySend >= 0);
NdisReleaseSpinLock(&Adapter->SendLock);
DEBUGP(MP_TRACE, ("<-- NICFreeSendTCB\n"));
}
VOID
NICFreeQueuedSendPackets(
PMP_ADAPTER Adapter
)
/*++
Routine Description:
This routine is called by the Halt or Reset handler to fail all
the queued up SendPackets because the device is either
gone, being stopped for resource rebalance, or reset.
Arguments:
Adapter - pointer to the adapter structure
Return Value:
VOID
--*/
{
PLIST_ENTRY pEntry;
PNDIS_PACKET Packet;
DEBUGP(MP_TRACE, ("--> NICFreeQueuedSendPackets\n"));
while(TRUE)
{
pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
&Adapter->SendWaitList,
&Adapter->SendLock);
if(!pEntry)
{
break;
}
Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
NdisMSendComplete(
Adapter->AdapterHandle,
Packet,
NDIS_STATUS_FAILURE);
}
DEBUGP(MP_TRACE, ("<-- NICFreeQueuedSendPackets\n"));
}
VOID
NICFreeQueuedRecvPackets(
PMP_ADAPTER Adapter
)
/*++
Routine Description:
This routine is called by the Halt handler to fail all
the queued up RecvPackets if it succeeds in cancelling
the RecvIndicate timer DPC.
Arguments:
Adapter - pointer to the adapter structure
Return Value:
VOID
--*/
{
PLIST_ENTRY pEntry;
PRCB pRCB = NULL;
DEBUGP(MP_TRACE, ("--> NICFreeQueuedRecvPackets\n"));
while(TRUE)
{
pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
&Adapter->RecvWaitList,
&Adapter->RecvLock);
if(!pEntry)
{
break;
}
pRCB = CONTAINING_RECORD(pEntry, RCB, List);
ASSERT(pRCB);
ASSERT(pRCB->Packet);
NICFreeRecvPacket(Adapter, pRCB->Packet);
//
// We are done with RCB memory. So free it.
//
NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pRCB);
}
DEBUGP(MP_TRACE, ("<-- NICFreeQueuedRecvPackets\n"));
}
BOOLEAN
NICIsPacketTransmittable(
PMP_ADAPTER Adapter,
PNDIS_PACKET Packet
)
/*++
Routine Description:
This routines checks to see whether the packet can be accepted
for transmission based on the currently programmed filter type
of the NIC and the mac address of the packet.
Arguments:
Adapter - pointer to the adapter structure
Packet - pointer to the send packet
Return Value:
True or False
--*/
{
INT Equal;
UINT PacketLength;
PNDIS_BUFFER FirstBuffer = NULL;
PUCHAR Address = NULL;
UINT CurrentLength;
ULONG index;
BOOLEAN result = FALSE;
DEBUGP(MP_LOUD,
("DestAdapter=%p, PacketFilter = 0x%08x\n",
Adapter,
Adapter->PacketFilter));
do {
#ifdef NDIS51_MINIPORT
NdisGetFirstBufferFromPacketSafe(
Packet,
&FirstBuffer,
&Address,
&CurrentLength,
&PacketLength,
NormalPagePriority);
#else
NdisGetFirstBufferFromPacket(
Packet,
&FirstBuffer,
&Address,
&CurrentLength,
&PacketLength);
#endif
if(!Address){
break;
}
DEBUGP(MP_LOUD, ("Dest Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
Address[0], Address[1], Address[2],
Address[3], Address[4], Address[5]));
//
// If the NIC is in promiscuous mode, we will transmit anything
// and everything.
//
if(Adapter->PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
result = TRUE;
break;
}
else if(ETH_IS_BROADCAST(Address)) {
//
// If it's a broadcast packet, check our filter settings to see
// we can transmit that.
//
if(Adapter->PacketFilter & NDIS_PACKET_TYPE_BROADCAST) {
result = TRUE;
break;
}
}
else if(ETH_IS_MULTICAST(Address)) {
//
// If it's a multicast packet, check our filter settings to see
// we can transmit that.
//
if(Adapter->PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) {
result = TRUE;
break;
}
else if(Adapter->PacketFilter & NDIS_PACKET_TYPE_MULTICAST) {
//
// Check to see if the multicast address is in our list
//
Equal = (UINT)-1;
for(index=0; index < Adapter->ulMCListSize; index++) {
ETH_COMPARE_NETWORK_ADDRESSES_EQ(
Address,
Adapter->MCList[index],
&Equal);
if(Equal == 0){ // 0 Implies equality
result = TRUE;
break;
}
}
if(Equal == 0){ // 0 Implies equality
result = TRUE;
break;
}
}
}
else if(Adapter->PacketFilter & NDIS_PACKET_TYPE_DIRECTED) {
//
// This has to be a directed packet. If so, does packet source
// address match with the mac address of the NIC.
//
ETH_COMPARE_NETWORK_ADDRESSES_EQ(
Address,
Adapter->CurrentAddress,
&Equal);
if(Equal == 0){
result = TRUE;
break;
}
}
//
// This is a junk packet. We can't transmit this.
//
result = FALSE;
}while(FALSE);
return result;
}
BOOLEAN
NICCopyPacket(
PMP_ADAPTER Adapter,
PTCB pTCB,
PNDIS_PACKET Packet)
/*++
Routine Description:
This routine copies the packet data into the TCB data block.
Arguments:
Adapter - pointer to the MP_ADAPTER structure
pTCB - pointer to TCB block
Packet - packet to be transfered.
Return Value:
VOID
--*/
{
PNDIS_BUFFER MyBuffer;
PNDIS_BUFFER CurrentBuffer;
PVOID VirtualAddress;
UINT CurrentLength;
UINT BytesToCopy;
UINT BytesCopied = 0;
UINT BufferCount;
UINT PacketLength;
UINT DestBufferSize = NIC_BUFFER_SIZE;
PUCHAR pDest;
BOOLEAN bResult = TRUE;
DEBUGP(MP_TRACE, ("--> NICCopyPacket\n"));
pTCB->OrgSendPacket = Packet;
pTCB->Ref = 1;
MyBuffer = pTCB->Buffer;
pDest = pTCB->pData;
MyBuffer->Next = NULL;
NdisQueryPacket(Packet,
NULL,
&BufferCount,
&CurrentBuffer,
&PacketLength);
ASSERT(PacketLength <= NIC_BUFFER_SIZE);
BytesToCopy = min(PacketLength, NIC_BUFFER_SIZE);
if(BytesToCopy < ETH_MIN_PACKET_SIZE)
{
BytesToCopy = ETH_MIN_PACKET_SIZE; // padding
}
while(CurrentBuffer && DestBufferSize)
{
NdisQueryBufferSafe(
CurrentBuffer,
&VirtualAddress,
&CurrentLength,
NormalPagePriority);
if(VirtualAddress == NULL){
bResult = FALSE;
break;
}
CurrentLength = min(CurrentLength, DestBufferSize);
if(CurrentLength)
{
// Copy the data.
NdisMoveMemory(pDest, VirtualAddress, CurrentLength);
BytesCopied += CurrentLength;
DestBufferSize -= CurrentLength;
pDest += CurrentLength;
}
NdisGetNextBuffer(
CurrentBuffer,
&CurrentBuffer);
}
if(bResult) {
if(BytesCopied < BytesToCopy)
{
//
// This would be the case if the packet size is less than
// ETH_MIN_PACKET_SIZE. Pad the buffer
// up to ETH_MIN_PACKET_SIZE with zero bytes to avoid
// information disclosure security attack. Remeber I of
// STRIDE?
//
//
NdisZeroMemory(pDest, BytesToCopy-BytesCopied);
BytesCopied = BytesToCopy;
}
NdisAdjustBufferLength(MyBuffer, BytesCopied);
}
DEBUGP(MP_TRACE, ("<-- NICCopyPacket\n"));
return bResult;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -