diff options
Diffstat (limited to 'private/ntos/tdi/isn/rip/rcvind.c')
-rw-r--r-- | private/ntos/tdi/isn/rip/rcvind.c | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/rip/rcvind.c b/private/ntos/tdi/isn/rip/rcvind.c new file mode 100644 index 000000000..392f31e74 --- /dev/null +++ b/private/ntos/tdi/isn/rip/rcvind.c @@ -0,0 +1,448 @@ +/*******************************************************************/ +/* 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 |