mirror of https://github.com/lianthony/NT4.0
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.
179 lines
4.8 KiB
179 lines
4.8 KiB
/*******************************************************************/
|
|
/* Copyright(c) 1993 Microsoft Corporation */
|
|
/*******************************************************************/
|
|
|
|
//***
|
|
//
|
|
// Filename: route.c
|
|
//
|
|
// Description: route packet routine
|
|
//
|
|
// Author: Stefan Solomon (stefans) October 11, 1993.
|
|
//
|
|
// Revision History:
|
|
//
|
|
//***
|
|
|
|
#include "rtdefs.h"
|
|
|
|
//***
|
|
//
|
|
// Function: RoutePacket
|
|
//
|
|
// Descr: Routes this packet
|
|
//
|
|
// Params: Packet
|
|
//
|
|
// Returns: none
|
|
//
|
|
//***
|
|
|
|
VOID
|
|
RoutePacket(PPACKET_TAG pktp)
|
|
{
|
|
PUCHAR hdrp; // points to the IPX packet header
|
|
PUCHAR destnet; // points to destination network
|
|
UINT segment; // routing table segment
|
|
KIRQL oldirql;
|
|
PIPX_ROUTE_ENTRY tabrtep;
|
|
PNICCB dstniccbp, srcniccbp; // dest and src nic cb pointers
|
|
|
|
// check if we know about the destination network
|
|
hdrp = pktp->DataBufferp;
|
|
destnet = hdrp + IPXH_DESTNET;
|
|
|
|
segment = IpxGetSegment(destnet);
|
|
|
|
ExAcquireSpinLock(&SegmentLocksTable[segment], &oldirql);
|
|
|
|
if((tabrtep = IpxGetRoute(segment, destnet)) == NULL) {
|
|
|
|
// no such route
|
|
ExReleaseSpinLock(&SegmentLocksTable[segment], oldirql);
|
|
RtPrint(DBG_ROUTE, ("IpxRouter: RoutePacket: route not found!\n"));
|
|
FreeRcvPkt(pktp);
|
|
return;
|
|
}
|
|
|
|
// check if the destination route is the Global Wan Route. If it is, then get the
|
|
// nic id of the destination nic
|
|
if(tabrtep->Flags & IPX_ROUTER_GLOBAL_WAN_NET) {
|
|
|
|
// sanity check
|
|
ASSERT(tabrtep->NicId == 0xFFFE);
|
|
ASSERT(WanGlobalNetworkEnabled);
|
|
|
|
// get the destination nic id from the wan nodes hash table
|
|
dstniccbp = GetWanNodeNiccbp(hdrp + IPXH_DESTNODE);
|
|
|
|
// check if the nic hasn't been removed from the table (by RtLineDown)
|
|
if(dstniccbp == NULL) {
|
|
|
|
ExReleaseSpinLock(&SegmentLocksTable[segment], oldirql);
|
|
FreeRcvPkt(pktp);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// extra sanity checks
|
|
ASSERT(dstniccbp->DeviceType == NdisMediumWan);
|
|
ASSERT(!dstniccbp->WanConnectionClient);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dstniccbp = NicCbPtrTab[tabrtep->NicId];
|
|
}
|
|
|
|
// check if the destination route is reachable through another nic than
|
|
// the nic we received the packet from.
|
|
if(pktp->PacketOwnerNicCbp->NicId == dstniccbp->NicId) {
|
|
|
|
// we can't send the packet back where it came from => discard it
|
|
ExReleaseSpinLock(&SegmentLocksTable[segment], oldirql);
|
|
FreeRcvPkt(pktp);
|
|
return;
|
|
}
|
|
|
|
// if either the src or the dst of the packet is a WAN nic, there are
|
|
// a series of checks to perform
|
|
|
|
// get the source nic for this packet
|
|
srcniccbp = NicCbPtrTab[pktp->PacketOwnerNicCbp->NicId];
|
|
|
|
// 1. check if one of the two nics is WAN and the other is a LAN nic disabled
|
|
// for WAN traffic
|
|
if( ((dstniccbp->DeviceType == NdisMediumWan) &&
|
|
(srcniccbp->DeviceType != NdisMediumWan) &&
|
|
(srcniccbp->WanRoutingDisabled)) ||
|
|
|
|
((dstniccbp->DeviceType != NdisMediumWan) &&
|
|
(srcniccbp->DeviceType == NdisMediumWan) &&
|
|
(dstniccbp->WanRoutingDisabled)) ) {
|
|
|
|
RtPrint(DBG_ROUTE, ("IpxRouter: RoutePacket: discard pkt because WAN traffic disabled for this LAN\n"));
|
|
ExReleaseSpinLock(&SegmentLocksTable[segment], oldirql);
|
|
FreeRcvPkt(pktp);
|
|
return;
|
|
}
|
|
|
|
// 2. check if one of the two nics is WAN and has a client role and
|
|
// LAN-WAN-LAN traffic is disabled
|
|
if(!LanWanLan) {
|
|
|
|
if( ((dstniccbp->DeviceType == NdisMediumWan) &&
|
|
(dstniccbp->WanConnectionClient)) ||
|
|
|
|
((srcniccbp->DeviceType == NdisMediumWan) &&
|
|
(srcniccbp->WanConnectionClient)) ) {
|
|
|
|
RtPrint(DBG_ROUTE, ("IpxRouter: RoutePacket: discard pkt because WAN has client role\n"));
|
|
ExReleaseSpinLock(&SegmentLocksTable[segment], oldirql);
|
|
FreeRcvPkt(pktp);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 3. If both source and destination NICs are LAN, check if LAN routing is
|
|
// enabled.
|
|
if((dstniccbp->DeviceType != NdisMediumWan) &&
|
|
(srcniccbp->DeviceType != NdisMediumWan) &&
|
|
(!EnableLanRouting)) {
|
|
|
|
RtPrint(DBG_ROUTE, ("IpxRouter: RoutePacket: discard pkt because LAN routing disabled\n"));
|
|
ExReleaseSpinLock(&SegmentLocksTable[segment], oldirql);
|
|
FreeRcvPkt(pktp);
|
|
return;
|
|
}
|
|
|
|
// general send preparation
|
|
pktp->RemoteAddress.NicId = dstniccbp->NicId;
|
|
|
|
//*** check if the network is directly connected ***
|
|
|
|
if(tabrtep->Flags & IPX_ROUTER_LOCAL_NET) {
|
|
|
|
// prepare the packet for a direct send to the destination node
|
|
memcpy(&pktp->RemoteAddress.MacAddress,
|
|
hdrp + IPXH_DESTNODE,
|
|
IPX_NODE_LEN);
|
|
}
|
|
else
|
|
{
|
|
// prepare the packet to be sent to the next router in the path to
|
|
// the destination node
|
|
memcpy(&pktp->RemoteAddress.MacAddress,
|
|
tabrtep->NextRouter,
|
|
IPX_NODE_LEN);
|
|
}
|
|
|
|
ExReleaseSpinLock(&SegmentLocksTable[segment], oldirql);
|
|
|
|
// increment the nr of hops in the packet
|
|
*(hdrp + IPXH_XPORTCTL) += 1;
|
|
|
|
// queue the packet at the sending nic and send it
|
|
SendPacket(pktp);
|
|
|
|
return;
|
|
}
|