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.
 
 
 
 
 
 

290 lines
9.8 KiB

/* Router.c, atalk-ii/router, Garth Conboy, 01/15/90 */
/* Copyright (c) 1989 by Pacer Software Inc., La Jolla, CA */
/* GC - Initial coding.
GC - (08/18/90): New error logging mechanism.
GC - (10/09/91): When handling "nnnn00" destinations, note that the
router may not have started on the first network
network number of the cable's range!
GC - (03/31/92): Updated for BufferDescriptors.
GC - (09/15/92): Handle the case of a packet coming in on the wrong
port (not the default port) destined for one of our
proxy nodes (AppleTalk Remote Access).
*** Make the PVCS source control system happy:
$Header$
$Log$
***
The AppleTalk phase II router. This routine, of course, depends on
the routing tables which are maintained by "fullrmtp.c".
Pretty interesting that a routine with a name like "Router()" is less
than 200 lines long...
Because we call "TransmitDdp" the datagram that we recieve must have
at least "MaximumHeaderLength + LongDdpHeaderLength" bytes ahead of it
for prepending hardware/802.2/DDP headers!
*/
#define IncludeRouterErrors 1
#include "atalk.h"
#if IamNot an AppleTalkRouter
/* Empty file */
#else
void _near _fastcall Router(int port,
AppleTalkAddress source,
AppleTalkAddress destination,
int protocolType,
char far *datagram,
int datagramLength,
int numberOfHops,
Boolean prependHeadersInPlace)
{
RoutingTableEntry routingTableEntry;
OpenSocket openSocket;
Boolean delivered = False, broadcastNode;
ActiveNode activeNode;
int targetPort;
short unsigned originalDestinationNetwork;
BufferDescriptor packet;
Boolean error = False;
/* This algorithm was taken from the "AppleTalk Phase 2 Protocol
Specification" as might be expected. */
broadcastNode = (destination.nodeNumber is AppleTalkBroadcastNodeNumber);
/* If the destination network number is within the range of the reception
port's network range and the destination node number is broadcast, then
we can drop the packet on the floor -- it is a network specific broadcast
not for this router. Note that we've already delivered the packet, and
thus not gotten here, if it was really addressed to the network of any
node owned by the reception port (in DdpPacketIn). */
if (IsWithinNetworkRange(destination.networkNumber,
&portDescriptors[port].thisCableRange) and
broadcastNode)
return;
/* Keep private... playing with the routing tables... */
DeferTimerChecking();
DeferIncomingPackets();
/* Try to find an entry in the routing table that contains the target
network. If not found, discard the woeful packet. */
if ((routingTableEntry = FindInRoutingTable(destination.networkNumber))
is empty)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return;
}
/* If the target network's hop count is non-zero, we really need to send
the beast, so, just do it! */
if (routingTableEntry->numberOfHops isnt 0)
{
if (numberOfHops < 15)
{
/* Build a buffer descriptor; copy the packet if we can't depend on
the data being around for the transmit to complete. Under
WindowsNT we don't own the incoming data, so we can't hold onto
it until an outgoing transmit completes.*/
if (TransmitsCompleteSynchronously and prependHeadersInPlace and
(IamNot a WindowsNT))
{
if ((packet = DescribeBuffer(datagramLength, datagram,
False)) is Empty)
error = True;
else
packet->prependInPlace = True;
}
else
{
if ((packet = NewBufferDescriptor(datagramLength)) is Empty)
error = True;
else
MoveMem(packet->data, datagram, datagramLength);
}
if (error)
{
ErrorLog("Router", ISevError, __LINE__, port,
IErrRouterOutOfMemory, IMsgRouterOutOfMemory,
Insert0());
HandleIncomingPackets();
HandleDeferredTimerChecks();
return;
}
if (not TransmitDdp(routingTableEntry->port,
source, destination, protocolType,
packet, datagramLength, numberOfHops + 1,
Empty, &routingTableEntry->nextRouter,
Empty, 0))
ErrorLog("Router", ISevWarning, __LINE__, routingTableEntry->port,
IErrRouterBadTransmit, IMsgRouterBadTransmit,
Insert0());
}
HandleIncomingPackets();
HandleDeferredTimerChecks();
return;
}
/* If the destination node is zero, the packet is really destined for the
router's node on this port. */
targetPort = routingTableEntry->port;
if (destination.nodeNumber is AnyRouterNodeNumber)
{
originalDestinationNetwork = destination.networkNumber;
destination.networkNumber =
portDescriptors[targetPort].aRouter.networkNumber;
destination.nodeNumber =
portDescriptors[targetPort].aRouter.nodeNumber;
if ((openSocket = MapAddressToOpenSocket(targetPort,
destination)) isnt empty)
{
destination.networkNumber = originalDestinationNetwork;
destination.nodeNumber = AnyRouterNodeNumber;
InvokeSocketHandler(openSocket, targetPort, source,
protocolType, datagram,
datagramLength, destination);
/* The above call does undefer... */
}
else
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
}
return;
}
/* We're finished with the routing tables... */
HandleIncomingPackets();
HandleDeferredTimerChecks();
/* Okay, now walk through the nodes on the target port, looking for a
home for this packet. */
for (activeNode = portDescriptors[targetPort].activeNodes;
activeNode isnt empty;
activeNode = activeNode->next)
{
/* Is the packet for us? */
if (destination.networkNumber is activeNode->extendedNode.networkNumber and
(broadcastNode or
destination.nodeNumber is activeNode->extendedNode.nodeNumber))
{
/* If for one of our proxy nodes, just blast it out. */
if (activeNode->proxyNode)
{
if ((packet = NewBufferDescriptor(datagramLength)) is Empty)
{
ErrorLog("Router", ISevError, __LINE__, port,
IErrRouterOutOfMemory, IMsgRouterOutOfMemory,
Insert0());
continue;
}
MoveMem(packet->data, datagram, datagramLength);
if (not TransmitDdp(activeNode->proxyPort, source, destination,
protocolType, packet, datagramLength,
numberOfHops + 1, Empty, Empty, Empty, 0))
ErrorLog("Router", ISevWarning, __LINE__, activeNode->proxyPort,
IErrRouterBadTransmit, IMsgRouterBadTransmit,
Insert0());
delivered = True;
continue;
}
/* Broadcast trys all nodes. */
if (broadcastNode)
destination.nodeNumber = activeNode->extendedNode.nodeNumber;
DeferTimerChecking();
DeferIncomingPackets();
if ((openSocket = MapAddressToOpenSocket(targetPort,
destination)) isnt empty)
{
if (broadcastNode)
destination.nodeNumber = AppleTalkBroadcastNodeNumber;
InvokeSocketHandler(openSocket, targetPort, source,
protocolType, datagram,
datagramLength, destination);
delivered = True;
}
else
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
}
}
}
/* Do we need to deliver the packet to a local port's network? */
if (not delivered or broadcastNode)
{
if (broadcastNode)
destination.nodeNumber = AppleTalkBroadcastNodeNumber;
if (numberOfHops < 15)
{
/* Build a buffer descriptor; copy the packet if we can't depend on
the data being around for the transmit to complete. Under
WindowsNT we don't own the incoming data, so we can't hold onto
it until an outgoing transmit completes. */
if (TransmitsCompleteSynchronously and prependHeadersInPlace and
(IamNot a WindowsNT))
{
if ((packet = DescribeBuffer(datagramLength, datagram,
False)) is Empty)
error = True;
else
packet->prependInPlace = True;
}
else
{
if ((packet = NewBufferDescriptor(datagramLength)) is Empty)
error = True;
else
MoveMem(packet->data, datagram, datagramLength);
}
if (error)
{
ErrorLog("Router", ISevError, __LINE__, port,
IErrRouterOutOfMemory, IMsgRouterOutOfMemory,
Insert0());
return;
}
if (not TransmitDdp(targetPort, source, destination, protocolType,
packet, datagramLength, numberOfHops + 1,
Empty, Empty, Empty, 0))
ErrorLog("Router", ISevError, __LINE__, targetPort,
IErrRouterBadTransmit, IMsgRouterBadTransmit,
Insert0());
}
}
/* The deed is done. */
return;
} /* Router */
#endif