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.
291 lines
8.4 KiB
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
|