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.
 
 
 
 
 
 

291 lines
8.4 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
router.c
Abstract:
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!
Author:
Garth Conboy (Pacer Software)
Nikhil Kamkolkar (NikhilK)
Revision History:
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!
--*/
#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,
&GET_PORTDESCRIPTOR(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 =
GET_PORTDESCRIPTOR(targetPort)->ARouter.NetworkNumber;
destination.nodeNumber =
GET_PORTDESCRIPTOR(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 = GET_PORTDESCRIPTOR(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