Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

448 lines
9.7 KiB

/*******************************************************************/
/* Copyright(c) 1993 Microsoft Corporation */
/*******************************************************************/
//***
//
// Filename: rcvind.c
//
// Description: receive indication handler
//
// Author: Stefan Solomon (stefans) October 8 1993.
//
// Revision History:
//
//***
#include "rtdefs.h"
VOID
ReceivePacketComplete(PPACKET_TAG rcvpktp,
UINT BytesTransferred);
VOID
DbgFilterReceivedPacket(PUCHAR hdrp);
//***
//
// Function: RtReceive
//
// Descr: This routine receives control from the IPX driver as an
// indication that a frame has been received on one of our NICs.
// This routine is time critical.
//
// Params:
//
// Returns:
//
//***
BOOLEAN
RtReceive(NDIS_HANDLE MacBindingHandle,
NDIS_HANDLE MacReceiveContext,
ULONG FwdAdapterCtx,
PIPX_LOCAL_TARGET RemoteAddress,
ULONG MacOptions,
PUCHAR LookaheadBuffer,
UINT LookaheadBufferSize,
UINT LookaheadBufferOffset,
UINT PacketSize,
PMDL pMdl)
{
PNICCB niccbp;
PPACKET_TAG rcvpktp;
NDIS_STATUS NdisStatus;
UINT BytesTransferred;
PNDIS_PACKET pktdescrp;
//
//*** Some Basic Validations ***
//
RtPrint(DBG_RECV, ("IpxRouter: RtReceive: Entered\n"));
#if DBG
DbgFilterReceivedPacket(LookaheadBuffer);
#endif
// check that our configuration process has terminated OK
if(!RouterInitialized) {
return FALSE;
}
// check that the packet fits our buffers
if(PacketSize > MaxFrameSize) {
return FALSE;
}
// check if we got the whole IPX header in the lookahead buffer
if(LookaheadBufferSize < IPXH_HDRSIZE) {
return FALSE;
}
// check if we are active on this NIC
niccbp = NicCbPtrTab[RemoteAddress->NicId];
if(niccbp->DeviceType != NdisMediumWan) {
// ckeck if this is not our own loopedback broadcast packet
if(!memcmp(RemoteAddress->MacAddress, niccbp->Node, 6)) {
return FALSE;
}
// This is a LAN NIC, the source node is unique
if(!memcmp(LookaheadBuffer + IPXH_SRCNODE, niccbp->Node, 6)) {
return FALSE;
}
}
else
{
// This is a WAN NIC, the source node is 1 and may conflict.
// Make an extra check with the network number
if(!memcmp(LookaheadBuffer + IPXH_SRCNET, niccbp->Network, 4) &&
!memcmp(LookaheadBuffer + IPXH_SRCNODE, niccbp->Node, 6)) {
// same net && same node -> loopback -> discard
return FALSE;
}
}
// check if the packet didn't exceed the allowed number of hops
if(*(LookaheadBuffer + IPXH_XPORTCTL) >= 16) {
return FALSE;
}
//
//*** Accept the packet ***
//
ACQUIRE_SPIN_LOCK(&niccbp->NicLock);
// check that we are enabled to receive on this nic
if(niccbp->NicState != NIC_ACTIVE) {
RELEASE_SPIN_LOCK(&niccbp->NicLock);
return FALSE;
}
// try to get a packet from the rcv pkt pool
if((rcvpktp = AllocateRcvPkt(niccbp)) == NULL) {
RELEASE_SPIN_LOCK(&niccbp->NicLock);
RtPrint(DBG_RECV, ("IpxRouter: RtReceive: Can't allocate a rcv pkt\n"));
return FALSE;
}
// set up the new packet
pktdescrp = CONTAINING_RECORD(rcvpktp, NDIS_PACKET, ProtocolReserved);
// enqueue the packet in the NIC's recv list and wait for the
// transfer to complete
rcvpktp->QueueOwnerNicCbp = niccbp;
InsertTailList(&niccbp->ReceiveQueue, &rcvpktp->PacketLinkage);
RELEASE_SPIN_LOCK(&niccbp->NicLock);
// try to get the packet data
IpxTransferData(&NdisStatus,
MacBindingHandle,
MacReceiveContext,
LookaheadBufferOffset, // start of IPX header
PacketSize, // packet size starting at IPX header
pktdescrp,
&BytesTransferred);
if(NdisStatus != NDIS_STATUS_PENDING) {
// complete the frame processing
RtTransferDataComplete(pktdescrp, NdisStatus, BytesTransferred);
}
return FALSE;
}
//***
//
// Function: RtTransferDataComplete
//
// Descr:
//
//***
VOID
RtTransferDataComplete(PNDIS_PACKET packetp,
NDIS_STATUS NdisStatus,
UINT BytesTransferred)
{
PPACKET_TAG rcvpktp;
PNICCB niccbp;
rcvpktp = (PPACKET_TAG)(packetp->ProtocolReserved);
niccbp = rcvpktp->QueueOwnerNicCbp;
// remove the packet from the receive queue
ACQUIRE_SPIN_LOCK(&niccbp->NicLock);
RemoveEntryList(&rcvpktp->PacketLinkage);
// check the success of the transfer and our Nic state
if((NdisStatus != NDIS_STATUS_SUCCESS) ||
(niccbp->NicState != NIC_ACTIVE)) {
RELEASE_SPIN_LOCK(&niccbp->NicLock);
RtPrint(DBG_NOTIFY, ("IpxRouter: RtTransferDataComplete: failed %x\n", NdisStatus));
FreeRcvPkt(rcvpktp);
return;
}
RELEASE_SPIN_LOCK(&niccbp->NicLock);
ReceivePacketComplete(rcvpktp, BytesTransferred);
return;
}
//***
//
// Function: ReceivePacketComplete
//
// Descr: actual packet processing
//
//***
VOID
ReceivePacketComplete(PPACKET_TAG rcvpktp,
UINT BytesTransferred)
{
USHORT pktlen;
PUCHAR hdrp;
PNICCB niccbp;
USHORT destsock;
// get a pointer to the IPX header
hdrp = rcvpktp->DataBufferp;
// get a pointer to the packet owner NicCb
niccbp = rcvpktp->PacketOwnerNicCbp;
// check that we have the whole packet
GETSHORT2USHORT(&pktlen, hdrp + IPXH_LENGTH);
if(BytesTransferred < pktlen) {
// we miss a part of the IPX frame
niccbp->StatBadReceived++;
// free the packet and get out
RtPrint(DBG_RECV, ("IpxRouter: ReceivePacketComplete: incomplete transfer\n"));
FreeRcvPkt(rcvpktp);
return;
}
//*** if dest net is 0, replace it with our net
if(!memcmp(hdrp + IPXH_DESTNET, nulladdress, IPX_NET_LEN)) {
memcpy(hdrp + IPXH_DESTNET, niccbp->Network, IPX_NET_LEN);
}
//*** if src net is 0, replace it with our net
if(!memcmp(hdrp + IPXH_SRCNET, nulladdress, IPX_NET_LEN)) {
memcpy(hdrp + IPXH_SRCNET, niccbp->Network, IPX_NET_LEN);
}
// check if the packet is destined for our own internal processes
if(!memcmp(hdrp + IPXH_DESTNET, niccbp->Network, IPX_NET_LEN)) {
//
//*** Packet directed to us (Netbios bcast or RIP) ***
//
// check if this is a Netbios Broadcast packet
if(*(hdrp + IPXH_PKTTYPE) == IPX_NETBIOS_TYPE) {
niccbp->StatType20Received++;
// this is a propagated Netbios packet
ProcessNbPacket(rcvpktp);
return;
}
// check if this is a RIP packet
GETSHORT2USHORT(&destsock, hdrp + IPXH_DESTSOCK);
if(destsock == IPX_RIP_SOCKET) {
niccbp->StatRipReceived++;
// this is a RIP packet.
// Queue it for postprocessing by the receive complete
ACQUIRE_SPIN_LOCK(&RipPktsListLock);
InsertTailList(&RipPktsList, &rcvpktp->PacketLinkage);
RELEASE_SPIN_LOCK(&RipPktsListLock);
return;
}
// This packet is not for us !!!
niccbp->StatBadReceived++;
RtPrint(DBG_RECV, ("IpxRouter: ReceivePacketComplete: packet is not for the router!!!\n"));
FreeRcvPkt(rcvpktp);
return;
}
else
{
// check if this packet is destined to the RIP socket
// this may happen if a badly configured router thinks it is on a
// different net segment
GETSHORT2USHORT(&destsock, hdrp + IPXH_DESTSOCK);
if(destsock == IPX_RIP_SOCKET) {
niccbp->StatBadReceived++;
// discard the packet
FreeRcvPkt(rcvpktp);
return;
}
//
//*** Packet to be routed
//
niccbp->StatRoutedReceived++;
RoutePacket(rcvpktp);
}
}
//***
//
// Function: RtReceiveComplete
//
// Descr: This routine receives control from the IPX driver after one or
// more receive operations have completed and no receive is in progress.
// It is called under less severe time constraints than RtReceive.
// We use it to perform post processing of RIP requests/replies
// queued in the RIP queue.
//
// Params:
//
// Returns:
//
//***
VOID
RtReceiveComplete(USHORT NicId)
{
LIST_ENTRY TempRipProcessList;
PLIST_ENTRY lep;
PPACKET_TAG pktp;
RtPrint(DBG_RECV, ("IpxRouter: RtReceiveComplete: Entered\n"));
// check that our configuration process has terminated OK
if(!RouterInitialized) {
return;
}
InitializeListHead(&TempRipProcessList);
ACQUIRE_SPIN_LOCK(&RipPktsListLock);
while(!IsListEmpty(&RipPktsList)) {
lep = RemoveHeadList(&RipPktsList);
InsertTailList(&TempRipProcessList, lep);
}
RELEASE_SPIN_LOCK(&RipPktsListLock);
while(!IsListEmpty(&TempRipProcessList)) {
lep = RemoveHeadList(&TempRipProcessList);
pktp = CONTAINING_RECORD(lep, PACKET_TAG, PacketLinkage);
ProcessRipPacket(pktp);
}
}
#if DBG
ULONG DbgFilterTrap = 0; // 1 - on dst and src (net + node),
// 2 - on dst (net + node),
// 3 - on src (net + node),
// 4 - on dst (net + node + socket)
UCHAR DbgFilterDstNet[4];
UCHAR DbgFilterDstNode[6];
UCHAR DbgFilterDstSocket[2];
UCHAR DbgFilterSrcNet[4];
UCHAR DbgFilterSrcNode[6];
UCHAR DbgFilterSrcSocket[2];
PUCHAR DbgFilterFrame;
VOID
DbgFilterReceivedPacket(PUCHAR hdrp)
{
switch(DbgFilterTrap) {
case 1:
if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
!memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6) &&
!memcmp(hdrp + IPXH_SRCNET, DbgFilterSrcNet, 4) &&
!memcmp(hdrp + IPXH_SRCNODE, DbgFilterSrcNode, 6)) {
DbgBreakPoint();
}
break;
case 2:
if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
!memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6)) {
DbgBreakPoint();
}
break;
case 3:
if(!memcmp(hdrp + IPXH_SRCNET, DbgFilterSrcNet, 4) &&
!memcmp(hdrp + IPXH_SRCNODE, DbgFilterSrcNode, 6)) {
DbgBreakPoint();
}
break;
case 4:
if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
!memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6) &&
!memcmp(hdrp + IPXH_DESTSOCK, DbgFilterDstSocket, 2)) {
DbgBreakPoint();
}
break;
default:
break;
}
DbgFilterFrame = hdrp;
}
#endif