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.
1299 lines
48 KiB
1299 lines
48 KiB
/* FullZip.c, atalk-ii/router, Garth Conboy, 01/16/90 */
|
|
/* Copyright (c) 1989 by Pacer Software Inc., La Jolla, CA */
|
|
|
|
/* GC - Initial coding.
|
|
GC - (08/18/90): New error logging mechanism.
|
|
GC - (01/19/92): Fix from newest OS/2 base [DCH/Jameel]. Corrected zone
|
|
name overlap checking in GetZoneList processing.
|
|
GC - (03/31/92): Updated for BufferDescriptors.
|
|
|
|
*** Make the PVCS source control system happy:
|
|
$Header$
|
|
$Log$
|
|
***
|
|
|
|
ZIP handling for a router.
|
|
|
|
*/
|
|
|
|
#define IncludeFullZipErrors 1
|
|
|
|
#include "atalk.h"
|
|
|
|
#if (Iam an AppleTalkRouter) and (IamNot an AppleTalkStack)
|
|
#include "atpconst.h"
|
|
#endif
|
|
|
|
#if IamNot an AppleTalkRouter
|
|
/* Empty file */
|
|
#else
|
|
|
|
ExternForVisibleFunction TimerHandler ZipQueryTimerExpired;
|
|
|
|
ExternForVisibleFunction Boolean GetZoneListFor(int port);
|
|
|
|
static Boolean firstCall = True;
|
|
|
|
Boolean far StartZipProcessingOnPort(int port)
|
|
{
|
|
|
|
/* Switch the incoming ZIP packet handler to be the router version. */
|
|
|
|
CloseSocketOnNodeIfOpen(port, portDescriptors[port].aRouter,
|
|
ZonesInformationSocket);
|
|
if (OpenSocketOnNode(empty, port, &portDescriptors[port].aRouter,
|
|
ZonesInformationSocket,
|
|
ZipPacketInRouter, (long)0, False, empty, 0,
|
|
empty) isnt ATnoError)
|
|
{
|
|
ErrorLog("StartZipProcessingOnPort", ISevError, __LINE__, port,
|
|
IErrFullZipBadSocketOpen, IMsgFullZipBadSocketOpen,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
|
|
/* Try to get or set the zone information... */
|
|
|
|
if (portDescriptors[port].portType is NonAppleTalkHalfPort)
|
|
{
|
|
portDescriptors[port].thisZoneValid = False;
|
|
portDescriptors[port].thisZoneList = empty;
|
|
}
|
|
else if (not GetZoneListFor(port))
|
|
return(False);
|
|
|
|
/* Start the zip query timer. */
|
|
|
|
if (firstCall)
|
|
{
|
|
StartTimer(ZipQueryTimerExpired, ZipQueryTimerSeconds, 0, empty);
|
|
firstCall = False;
|
|
}
|
|
|
|
return(True);
|
|
|
|
} /* StartZipProcessingOnPort */
|
|
|
|
void far ShutdownFullZip(void)
|
|
{
|
|
|
|
firstCall = True;
|
|
|
|
} /* ShutdownFullZip */
|
|
|
|
long far ZipPacketInRouter(AppleTalkErrorCode errorCode,
|
|
long unsigned userData,
|
|
int port,
|
|
AppleTalkAddress source,
|
|
long destinationSocket,
|
|
int protocolType,
|
|
char far *datagram,
|
|
int datagramLength,
|
|
AppleTalkAddress actualDestination)
|
|
{
|
|
StaticForSmallStack char zoneName[MaximumZoneLength + 1];
|
|
BufferDescriptor packet;
|
|
RoutingTableEntry routingTableEntry, currentEntry;
|
|
int commandType, currentHash;
|
|
int networkCount, currentNetworkCount, zoneCount, currentZoneIndex;
|
|
unsigned short networkNumber;
|
|
int zoneNameLength, numberOfZonesOnTheNetwork;
|
|
Boolean newPacket, packetFull, zoneNameOverlap, localZonesOnly;
|
|
Boolean extendedZipReply = False, useDefaultZone = False;
|
|
int unsentNetworkCount;
|
|
int index, outIndex, currentReplyType, nextReplyType;
|
|
int totalNetworkCount;
|
|
int transactionId;
|
|
int zipCommand;
|
|
int startIndex;
|
|
int hashBucket;
|
|
ZoneList zoneList, zone, currentZone;
|
|
PortHandlers portHandlers;
|
|
Boolean rteValid;
|
|
|
|
/* "Use" unneeded actual parameters. */
|
|
|
|
destinationSocket, userData;
|
|
|
|
/* Only play if we've been asked nicely! */
|
|
|
|
if (errorCode is ATsocketClosed)
|
|
return((long)True);
|
|
else if (errorCode isnt ATnoError)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipBadIncomingError, IMsgFullZipBadIncomingError,
|
|
Insert0());
|
|
return((long)True);
|
|
}
|
|
if (protocolType isnt DdpProtocolZip and
|
|
protocolType isnt DdpProtocolAtp)
|
|
return((long)True);
|
|
|
|
/* Okay, process the request. */
|
|
|
|
DeferTimerChecking();
|
|
DeferIncomingPackets();
|
|
|
|
if (protocolType is DdpProtocolZip)
|
|
{
|
|
commandType = (unsigned char)datagram[ZipCommandOffset];
|
|
if (datagramLength < ZipFirstNetworkOffset)
|
|
{
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return((long)True); /* All ZIP commands have a command and network count! */
|
|
}
|
|
networkCount = (unsigned char)datagram[ZipNetworkCountOffset];
|
|
|
|
/* For a ZIP extended reply the "network count" is really not the
|
|
numbers of networks contained in the packet, it's the total number
|
|
of zones on the single network that is described by the reply. */
|
|
|
|
numberOfZonesOnTheNetwork = networkCount;
|
|
|
|
switch (commandType)
|
|
{
|
|
case ZipNetInfoReplyCommand:
|
|
case ZipNotifyCommand:
|
|
|
|
/* Don't be tellin us... we're a router! */
|
|
|
|
break;
|
|
|
|
case ZipGetNetInfoCommand:
|
|
|
|
if (not portDescriptors[port].extendedNetwork)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevWarning, __LINE__, port,
|
|
IErrFullZipNonExtended, IMsgFullZipNonExtended,
|
|
Insert0());
|
|
break;
|
|
}
|
|
if (not portDescriptors[port].thisZoneList isnt Empty)
|
|
break; /* Not fully up yet... */
|
|
|
|
/* Get the zone name out of the request. */
|
|
|
|
if (datagramLength < ZipRequestedZoneNameOffset)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevWarning, __LINE__, port,
|
|
IErrFullZipMissingZoneLen, IMsgFullZipMissingZoneLen,
|
|
Insert0());
|
|
break;
|
|
}
|
|
zoneNameLength =
|
|
(unsigned char)datagram[ZipRequestedZoneLengthOffset];
|
|
if (zoneNameLength > MaximumZoneLength or
|
|
datagramLength < ZipRequestedZoneNameOffset + zoneNameLength)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevWarning, __LINE__, port,
|
|
IErrFullZipBadZone, IMsgFullZipBadZone,
|
|
Insert0());
|
|
break;
|
|
}
|
|
MoveMem(zoneName, datagram + ZipRequestedZoneNameOffset,
|
|
zoneNameLength);
|
|
zoneName[zoneNameLength] = 0;
|
|
|
|
/* Get a buffer descriptor for our reply. */
|
|
|
|
if ((packet = NewBufferDescriptor(MaximumDdpDatagramSize)) is Empty)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipOutOfMemory, IMsgFullZipOutOfMemory,
|
|
Insert0());
|
|
break;
|
|
}
|
|
|
|
/* Format a GetNetInfo reply command. */
|
|
|
|
packet->data[ZipCommandOffset] = ZipNetInfoReplyCommand;
|
|
packet->data[ZipFlagsOffset] = 0;
|
|
if (zoneNameLength is 0 or
|
|
not ZoneOnList(zoneName, portDescriptors[port].thisZoneList))
|
|
{
|
|
packet->data[ZipFlagsOffset] |= (unsigned char)ZipZoneInvalidFlag;
|
|
useDefaultZone = True;
|
|
}
|
|
if (ElementsOnList(portDescriptors[port].thisZoneList) is 1)
|
|
packet->data[ZipFlagsOffset] |= (unsigned char)ZipOnlyOneZoneFlag;
|
|
|
|
/* Add our cable range. */
|
|
|
|
packet->data[ZipFirstNetworkOffset] =
|
|
(unsigned char)(portDescriptors[port].thisCableRange.firstNetworkNumber
|
|
>> 8);
|
|
packet->data[ZipFirstNetworkOffset + 1] =
|
|
(unsigned char)(portDescriptors[port].thisCableRange.firstNetworkNumber
|
|
& 0xFF);
|
|
packet->data[ZipLastNetworkOffset] =
|
|
(unsigned char)(portDescriptors[port].thisCableRange.lastNetworkNumber
|
|
>> 8);
|
|
packet->data[ZipLastNetworkOffset + 1] =
|
|
(unsigned char)(portDescriptors[port].thisCableRange.lastNetworkNumber
|
|
& 0xFF);
|
|
|
|
/* Echo back the requested zone name. */
|
|
|
|
packet->data[ZipRequestedZoneLengthOffset] = (unsigned char)zoneNameLength;
|
|
MoveMem(packet->data + ZipRequestedZoneNameOffset, zoneName,
|
|
zoneNameLength);
|
|
index = ZipRequestedZoneNameOffset + zoneNameLength;
|
|
|
|
/* Place in the correct zone multicast address. */
|
|
|
|
portHandlers = &portSpecificInfo[portDescriptors[port].portType];
|
|
packet->data[index++] = (unsigned char)portHandlers->hardwareAddressLength;
|
|
if (useDefaultZone)
|
|
MoveMem(packet->data + index,
|
|
MulticastAddressForZoneOnPort(port,
|
|
portDescriptors[port].thisDefaultZone),
|
|
portHandlers->hardwareAddressLength);
|
|
else
|
|
MoveMem(packet->data + index,
|
|
MulticastAddressForZoneOnPort(port, zoneName),
|
|
portHandlers->hardwareAddressLength);
|
|
index += portHandlers->hardwareAddressLength;
|
|
|
|
/* If we need it, add in the default zone. */
|
|
|
|
if (useDefaultZone)
|
|
{
|
|
zoneNameLength = strlen(portDescriptors[port].thisDefaultZone);
|
|
packet->data[index++] = (unsigned char)zoneNameLength;
|
|
MoveMem(packet->data + index,
|
|
portDescriptors[port].thisDefaultZone,
|
|
zoneNameLength);
|
|
index += zoneNameLength;
|
|
}
|
|
|
|
/* If the request came as a cable-wide broadcast and its source
|
|
network is not valid for this port, then we want to respond
|
|
to cable-wide broadcast rather than the source. */
|
|
|
|
if (actualDestination.networkNumber is
|
|
CableWideBroadcastNetworkNumber and
|
|
actualDestination.nodeNumber is AppleTalkBroadcastNodeNumber and
|
|
not IsWithinNetworkRange(source.networkNumber,
|
|
&portDescriptors[port].thisCableRange)
|
|
and
|
|
not IsWithinNetworkRange(source.networkNumber,
|
|
&startupNetworkRange))
|
|
{
|
|
source.networkNumber = CableWideBroadcastNetworkNumber;
|
|
source.nodeNumber = AppleTalkBroadcastNodeNumber;
|
|
}
|
|
|
|
/* Okay, finally deliver our reply. */
|
|
|
|
if (DeliverDdp(destinationSocket, source, DdpProtocolZip, packet,
|
|
index, Empty, Empty, 0) isnt ATnoError)
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipBadInfoReplySend, IMsgFullZipBadInfoReplySend,
|
|
Insert0());
|
|
|
|
break;
|
|
|
|
case ZipQueryCommand:
|
|
|
|
/* Walk thru the query packet building reply packets that have
|
|
as much information as we know. The "+ sizeof(short)" means
|
|
that we have complete network number.
|
|
|
|
When sending replies, we will always send a reply about a
|
|
network that has more than one zone as an extended reply.
|
|
As were walking the query list, and we encounter a couple of
|
|
networks that have only one zone, we'll pack as many of these
|
|
as we can into a non-extended reply. */
|
|
|
|
newPacket = True;
|
|
unsentNetworkCount = 0;
|
|
|
|
/* Allocate an initial buffer descriptor. */
|
|
|
|
if ((packet = NewBufferDescriptor(MaximumDdpDatagramSize)) is Empty)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipOutOfMemory, IMsgFullZipOutOfMemory,
|
|
Insert0());
|
|
break;
|
|
}
|
|
|
|
for (index = ZipFirstNetworkOffset,
|
|
totalNetworkCount = 0;
|
|
totalNetworkCount < networkCount and
|
|
index + (int)sizeof(short) <= datagramLength;
|
|
index += (int)sizeof(short),
|
|
totalNetworkCount += 1)
|
|
{
|
|
/* Grab the next network number from the query packet, if we
|
|
don't know about the network, or we don't know the zone
|
|
name, continue with the next network number. */
|
|
|
|
networkNumber = (unsigned short)
|
|
(((unsigned char)datagram[index]) << 8);
|
|
networkNumber += (unsigned char)datagram[index + 1];
|
|
|
|
/* Try port descriptors first... we'll get queries from
|
|
ourselfs to fill the initial routing table entry's zone
|
|
list! */
|
|
|
|
if (portDescriptors[port].thisCableRange.firstNetworkNumber is
|
|
networkNumber and
|
|
portDescriptors[port].thisZoneList isnt empty)
|
|
zoneList = portDescriptors[port].thisZoneList;
|
|
else if ((routingTableEntry =
|
|
FindInRoutingTable(networkNumber)) is empty or
|
|
routingTableEntry->networkRange.firstNetworkNumber isnt
|
|
networkNumber or
|
|
not routingTableEntry->zoneListValid)
|
|
continue;
|
|
else
|
|
zoneList = routingTableEntry->zoneList;
|
|
|
|
/* What type of reponse does this network want? */
|
|
|
|
if ((numberOfZonesOnTheNetwork = ElementsOnList(zoneList)) is 0)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipBadZoneList, IMsgFullZipBadZoneList,
|
|
Insert0());
|
|
continue;
|
|
}
|
|
else if (numberOfZonesOnTheNetwork is 1)
|
|
nextReplyType = ZipReplyCommand;
|
|
else
|
|
{
|
|
/* We start a new packet for each extended network, if we
|
|
have a previous one, send it! */
|
|
|
|
if (unsentNetworkCount > 0)
|
|
{
|
|
packet->data[ZipCommandOffset] = (unsigned char)currentReplyType;
|
|
if (currentReplyType is ZipReplyCommand)
|
|
packet->data[ZipNetworkCountOffset] = (unsigned char)unsentNetworkCount;
|
|
else
|
|
packet->data[ZipNetworkCountOffset] = (unsigned char)numberOfZonesOnTheNetwork;
|
|
|
|
|
|
/* Send the packet! */
|
|
|
|
if (DeliverDdp(destinationSocket, source,
|
|
DdpProtocolZip, packet,
|
|
outIndex, Empty, Empty, 0) isnt ATnoError)
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipBadReplySend, IMsgFullZipBadReplySend,
|
|
Insert0());
|
|
|
|
if ((packet = NewBufferDescriptor(MaximumDdpDatagramSize))
|
|
is Empty)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipOutOfMemory, IMsgFullZipOutOfMemory,
|
|
Insert0());
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return((long)True);
|
|
}
|
|
|
|
unsentNetworkCount = 0;
|
|
}
|
|
nextReplyType = ZipExtendedReplyCommand;
|
|
newPacket = True;
|
|
packet->data[ZipNetworkCountOffset] =
|
|
(unsigned char)numberOfZonesOnTheNetwork;
|
|
}
|
|
|
|
/* Walk the zone list. */
|
|
|
|
for (zone = zoneList;
|
|
zone isnt empty;
|
|
zone = zone->next)
|
|
{
|
|
|
|
/* If we're starting to build a new reply packet due to
|
|
either:
|
|
|
|
1. first time through
|
|
2. packet full
|
|
3. switching reply types
|
|
|
|
set the index to the first tuple position. */
|
|
|
|
if (newPacket or
|
|
currentReplyType isnt nextReplyType)
|
|
{
|
|
/* If a previous packet has been built, send it. */
|
|
|
|
if (unsentNetworkCount > 0)
|
|
{
|
|
packet->data[ZipCommandOffset] = (unsigned char)currentReplyType;
|
|
if (currentReplyType is ZipReplyCommand)
|
|
packet->data[ZipNetworkCountOffset] = (unsigned char)unsentNetworkCount;
|
|
else
|
|
packet->data[ZipNetworkCountOffset] = (unsigned char)numberOfZonesOnTheNetwork;
|
|
|
|
|
|
/* Send the packet! */
|
|
|
|
if (DeliverDdp(destinationSocket, source,
|
|
DdpProtocolZip, packet,
|
|
outIndex, Empty, Empty, 0) isnt ATnoError)
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipBadReplySend, IMsgFullZipBadReplySend,
|
|
Insert0());
|
|
|
|
if ((packet = NewBufferDescriptor(MaximumDdpDatagramSize))
|
|
is Empty)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipOutOfMemory, IMsgFullZipOutOfMemory,
|
|
Insert0());
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return((long)True);
|
|
}
|
|
|
|
unsentNetworkCount = 0;
|
|
}
|
|
|
|
outIndex = ZipFirstNetworkOffset;
|
|
currentReplyType = nextReplyType;
|
|
newPacket = False;
|
|
}
|
|
|
|
/* Unfortunately, we seem to know the answer to the question.
|
|
Pack a new network/zone tuple into the reply packet. */
|
|
|
|
packet->data[outIndex++] = (unsigned char)((networkNumber >> 8) & 0xFF);
|
|
packet->data[outIndex++] = (unsigned char)(networkNumber & 0xFF);
|
|
packet->data[outIndex++] = (unsigned char)(zoneNameLength =
|
|
strlen(zone->zone));
|
|
MoveMem(packet->data + outIndex, zone->zone, zoneNameLength);
|
|
outIndex += zoneNameLength;
|
|
unsentNetworkCount += 1;
|
|
|
|
/* If we can't hold another big tuple, signal that we should
|
|
send on the next pass. */
|
|
|
|
if (outIndex + sizeof(short) + sizeof(char) +
|
|
MaximumZoneLength >= MaximumDdpDatagramSize)
|
|
newPacket = True;
|
|
|
|
} /* Walk zone list. */
|
|
|
|
} /* Walk through each network in the query packet. */
|
|
|
|
/* If we have unsent networks left over, send them out! */
|
|
|
|
if (unsentNetworkCount > 0)
|
|
{
|
|
packet->data[ZipCommandOffset] = (unsigned char)currentReplyType;
|
|
if (currentReplyType is ZipReplyCommand)
|
|
packet->data[ZipNetworkCountOffset] = (unsigned char)unsentNetworkCount;
|
|
else
|
|
packet->data[ZipNetworkCountOffset] = (unsigned char)numberOfZonesOnTheNetwork;
|
|
|
|
|
|
/* Send the packet! */
|
|
|
|
if (DeliverDdp(destinationSocket, source,
|
|
DdpProtocolZip, packet,
|
|
outIndex, Empty, Empty, 0) isnt ATnoError)
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipBadReplySend, IMsgFullZipBadReplySend,
|
|
Insert0());
|
|
|
|
unsentNetworkCount = 0;
|
|
}
|
|
else
|
|
FreeBufferChain(packet); /* Free unused buffer chain. */
|
|
|
|
break;
|
|
|
|
case ZipExtendedReplyCommand:
|
|
|
|
extendedZipReply = True;
|
|
/* And fall through... */
|
|
|
|
case ZipReplyCommand:
|
|
|
|
/* Walk through the reply packet (assuming we asked for the
|
|
contained information). Yes, we're still using "networkCount"
|
|
when processing an extended reply, but that's okay because it
|
|
will certainly be at least the number of zones contained in
|
|
this packet. The "+ 3" garuntees that we really have network
|
|
number and zone length! */
|
|
|
|
// Mark the routing table entry as invalid.
|
|
rteValid = False;
|
|
|
|
for (index = ZipFirstNetworkOffset,
|
|
totalNetworkCount = 0;
|
|
totalNetworkCount < networkCount and
|
|
index + 3 <= datagramLength;
|
|
totalNetworkCount += 1)
|
|
{
|
|
// Mark the routing table entry as invalid.
|
|
rteValid = False;
|
|
|
|
/* Get the next network number, if it's not in our routing
|
|
table (or not the start of a range), then we certainly
|
|
don't care about its zone name. */
|
|
|
|
networkNumber = (unsigned short)
|
|
(((unsigned char)(datagram[index++])) << 8);
|
|
networkNumber += (unsigned char)(datagram[index++]);
|
|
zoneNameLength = (unsigned char)(datagram[index++]);
|
|
routingTableEntry = FindInRoutingTable(networkNumber);
|
|
if (routingTableEntry is empty or
|
|
routingTableEntry->networkRange.firstNetworkNumber isnt
|
|
networkNumber)
|
|
{
|
|
index += zoneNameLength;
|
|
continue;
|
|
}
|
|
|
|
/* Okay validate the zone name. */
|
|
|
|
if (zoneNameLength is 0 or
|
|
zoneNameLength > MaximumZoneLength)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevWarning, __LINE__, port,
|
|
IErrFullZipBadReplyPacket, IMsgFullZipBadReplyPacket,
|
|
Insert0());
|
|
break; /* Oops, corrupted packet! */
|
|
}
|
|
if (index + zoneNameLength > datagramLength)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevWarning, __LINE__, port,
|
|
IErrFullZipBadZone, IMsgFullZipBadZone,
|
|
Insert0());
|
|
break; /* Oops, corrupted packet! */
|
|
}
|
|
|
|
/* Conditionally, move the zone name into our routing table. */
|
|
|
|
MoveMem(zoneName, datagram + index, zoneNameLength);
|
|
index += zoneNameLength;
|
|
zoneName[zoneNameLength] = 0;
|
|
if (ZoneOnList(zoneName, routingTableEntry->zoneList))
|
|
continue;
|
|
|
|
/* Check for the obscure case of somebody out there trying to
|
|
add another zone to one of our directly connected networks
|
|
that is non-extended and we already know its zone. */
|
|
|
|
if (routingTableEntry->numberOfHops is 0 and
|
|
not portDescriptors[routingTableEntry->port].
|
|
extendedNetwork and
|
|
ElementsOnList(routingTableEntry->zoneList) is 1)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevWarning, __LINE__, port,
|
|
IErrFullZipTooManyZones, IMsgFullZipTooManyZones,
|
|
Insert0());
|
|
continue;
|
|
}
|
|
|
|
/* Okay, add to list. */
|
|
|
|
if ((routingTableEntry->zoneList =
|
|
AddZoneToList(routingTableEntry->zoneList, zoneName))
|
|
is empty)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipCantAddZone, IMsgFullZipCantAddZone,
|
|
Insert0());
|
|
routingTableEntry->zoneListValid = False;
|
|
continue;
|
|
}
|
|
|
|
/* If we're not an extended reply, we know that we have all of
|
|
the information about a given network contained in this
|
|
packet, so we can go ahead and mark the zone list valid
|
|
now. */
|
|
|
|
if (not extendedZipReply)
|
|
routingTableEntry->zoneListValid = True;
|
|
|
|
rteValid = TRUE;
|
|
}
|
|
|
|
/* Okay, if we just handled an extended reply, do we now know all
|
|
that we should know about the specfied network? */
|
|
|
|
if (extendedZipReply and rteValid and
|
|
ElementsOnList(routingTableEntry->zoneList) >=
|
|
numberOfZonesOnTheNetwork)
|
|
routingTableEntry->zoneListValid = True;
|
|
|
|
break;
|
|
|
|
default:
|
|
ErrorLog("ZipPacketInRouter", ISevWarning, __LINE__, port,
|
|
IErrFullZipFunnyCommand, IMsgFullZipFunnyCommand,
|
|
Insert0());
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* An ATP/ZIP request! */
|
|
|
|
/* This had better be a GetZoneList, a GetLocalZones, or a GetMyZone
|
|
ATP request! */
|
|
|
|
if ((datagram[AtpCommandControlOffset] & AtpFunctionCodeMask) isnt
|
|
AtpRequestFunctionCode)
|
|
{
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return((long)True); /* Why are they talking to us??? */
|
|
}
|
|
if (datagram[AtpBitmapOffset] isnt 1)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevWarning, __LINE__, port,
|
|
IErrFullZipLongReplyExpected, IMsgFullZipLongReplyExpected,
|
|
Insert0());
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return((long)True); /* More that one reply packet isnt an option! */
|
|
}
|
|
|
|
transactionId = ((unsigned char)datagram[AtpTransactionIdOffset]) << 8;
|
|
transactionId += (unsigned char)datagram[AtpTransactionIdOffset + 1];
|
|
|
|
/* Make sure it's one of the three requests that we know how to deal
|
|
with. */
|
|
|
|
zipCommand = (unsigned char)datagram[AtpZipCommandOffset] & 0xFF;
|
|
if (zipCommand isnt ZipGetZoneListCommand and
|
|
zipCommand isnt ZipGetLocalZonesCommand and
|
|
zipCommand isnt ZipGetMyZoneCommand)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevWarning, __LINE__, port,
|
|
IErrFullZipFunnyRequest, IMsgFullZipFunnyRequest,
|
|
Insert0());
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return((long)True);
|
|
}
|
|
|
|
/* Get start index... only meaningfull for GetZoneList and
|
|
GetLocalZones requests. */
|
|
|
|
startIndex = ((unsigned char)datagram[AtpZipStartIndexOffset] << 8);
|
|
startIndex += (unsigned char)datagram[AtpZipStartIndexOffset + 1];
|
|
|
|
/* Allocate a buffer descriptor for the reply. */
|
|
|
|
if ((packet = NewBufferDescriptor(MaximumDdpDatagramSize)) is Empty)
|
|
{
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipOutOfMemory, IMsgFullZipOutOfMemory,
|
|
Insert0());
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return((long)True);
|
|
}
|
|
|
|
/* Okay, build the static part of an ATP reply packet. */
|
|
|
|
packet->data[AtpCommandControlOffset] =
|
|
(unsigned char)(AtpResponseFunctionCode + AtpEndOfMessageMask);
|
|
packet->data[AtpSequenceNumberOffset] = 0;
|
|
packet->data[AtpTransactionIdOffset] = (unsigned char)((transactionId >> 8) & 0xFF);
|
|
packet->data[AtpTransactionIdOffset + 1] = (unsigned char)(transactionId & 0xFF);
|
|
|
|
/* Handle GetMyZone: */
|
|
|
|
if (zipCommand is ZipGetMyZoneCommand)
|
|
{
|
|
/* We really shouldn't be getting this request on an extended network,
|
|
but go ahead and reply with the "default zone" in this case, of
|
|
couse, reply with "this zone" for non-extended nets. We are a
|
|
router, so "thisZone" will always be valid -- as will the default
|
|
zone for extended nets and as will "this zone" for non-extended. */
|
|
|
|
packet->data[AtpZipLastFlagOffset] = 0;
|
|
packet->data[AtpZipLastFlagOffset + 1] = 0;
|
|
packet->data[AtpZipStartIndexOffset] = 0;
|
|
packet->data[AtpZipStartIndexOffset + 1] = 1;
|
|
|
|
if (portDescriptors[port].extendedNetwork)
|
|
{
|
|
zoneNameLength = strlen(portDescriptors[port].thisDefaultZone);
|
|
packet->data[AtpDataOffset] = (unsigned char)zoneNameLength;
|
|
MoveMem(packet->data + AtpDataOffset + 1,
|
|
portDescriptors[port].thisDefaultZone, zoneNameLength);
|
|
}
|
|
else
|
|
{
|
|
zoneNameLength = strlen(portDescriptors[port].thisZone);
|
|
packet->data[AtpDataOffset] = (unsigned char)zoneNameLength;
|
|
MoveMem(packet->data + AtpDataOffset + 1,
|
|
portDescriptors[port].thisZone, zoneNameLength);
|
|
}
|
|
|
|
/* Blast the reply out! */
|
|
|
|
if (DeliverDdp(destinationSocket, source, DdpProtocolAtp,
|
|
packet, AtpDataOffset + 1 + zoneNameLength,
|
|
Empty, Empty, 0)
|
|
isnt ATnoError)
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipBadMyZoneSend, IMsgFullZipBadMyZoneSend,
|
|
Insert0());
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return((long)True);
|
|
}
|
|
|
|
/* Okay, A little harder here, fill the GetZoneList or GetLocalZones
|
|
reply packet full of as many zomes as it'll hold; starting at the
|
|
requested start index. */
|
|
|
|
localZonesOnly = (zipCommand is ZipGetLocalZonesCommand);
|
|
|
|
index = AtpDataOffset;
|
|
packetFull = False;
|
|
for (hashBucket = 0, zoneCount = 0, networkCount = 0,
|
|
currentZoneIndex = 0;
|
|
hashBucket < NumberOfRtmpHashBuckets and not packetFull;
|
|
hashBucket += 1)
|
|
for (routingTableEntry = routingTable[hashBucket];
|
|
routingTableEntry isnt empty and not packetFull;
|
|
routingTableEntry = routingTableEntry->next)
|
|
for (zone = routingTableEntry->zoneList;
|
|
zone isnt empty;
|
|
zone = zone->next)
|
|
{
|
|
/* If we're a GetLocalZones command, we only want to count
|
|
zones that are on the network that is directly connected to
|
|
the port on which the request originated. */
|
|
|
|
if (localZonesOnly)
|
|
if (routingTableEntry->numberOfHops isnt 0 or
|
|
routingTableEntry->port isnt port)
|
|
continue;
|
|
|
|
/* We don't want to count zones with the same names, so look at
|
|
all previous networks to see if we've already handled a zone
|
|
of the same name. Not too easy given that we don't maintain
|
|
a separate zone table. */
|
|
|
|
networkCount += 1;
|
|
zoneNameOverlap = False;
|
|
for (currentHash = 0, currentNetworkCount = 0;
|
|
not zoneNameOverlap and not localZonesOnly and
|
|
currentNetworkCount < networkCount and
|
|
currentHash < NumberOfRtmpHashBuckets;
|
|
currentHash += 1)
|
|
for (currentEntry = routingTable[currentHash];
|
|
not zoneNameOverlap and currentEntry isnt empty and
|
|
currentNetworkCount < networkCount;
|
|
currentEntry = currentEntry->next)
|
|
for (currentZone = currentEntry->zoneList;
|
|
currentZone isnt empty;
|
|
currentZone = currentZone->next)
|
|
{
|
|
if ((currentNetworkCount += 1) is networkCount)
|
|
break;
|
|
if (CompareCaseInsensitive(zone->zone,
|
|
currentZone->zone))
|
|
zoneNameOverlap = True;
|
|
}
|
|
if (zoneNameOverlap)
|
|
continue;
|
|
|
|
/* Are we at the point that the requester want's us to start from
|
|
yet? */
|
|
|
|
currentZoneIndex += 1;
|
|
if (currentZoneIndex < startIndex)
|
|
continue;
|
|
|
|
/* Place a zone name in the packet. */
|
|
|
|
zoneNameLength = strlen(zone->zone);
|
|
packet->data[index++] = (unsigned char)zoneNameLength;
|
|
MoveMem(packet->data + index, zone->zone, zoneNameLength);
|
|
index += zoneNameLength;
|
|
zoneCount += 1;
|
|
|
|
/* Can this packet hold another of the longest zone? */
|
|
|
|
if (index + sizeof(char) + MaximumZoneLength >=
|
|
MaximumDdpDatagramSize)
|
|
{
|
|
packetFull = True;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Okay, we've built a packet, fill in the number of zones field,
|
|
and the Last flag. */
|
|
|
|
packet->data[AtpZipLastFlagOffset] =
|
|
(unsigned char)(hashBucket >= NumberOfRtmpHashBuckets and
|
|
routingTableEntry is empty);
|
|
packet->data[AtpZipLastFlagOffset + 1] = 0;
|
|
packet->data[AtpZipZoneCountOffset] =
|
|
(unsigned char)((zoneCount >> 8) & 0xFF);
|
|
packet->data[AtpZipZoneCountOffset + 1] =
|
|
(unsigned char)(zoneCount & 0xFF);
|
|
|
|
/* Send out the packet. */
|
|
|
|
if (DeliverDdp(destinationSocket, source, DdpProtocolAtp,
|
|
packet, index, Empty, Empty, 0) isnt ATnoError)
|
|
ErrorLog("ZipPacketInRouter", ISevError, __LINE__, port,
|
|
IErrFullZipBadZoneListSend, IMsgFullZipBadZoneListSend,
|
|
Insert0());
|
|
|
|
} /* ZIP/ATP request */
|
|
|
|
/* All set. */
|
|
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return((long)True);
|
|
|
|
} /* ZipPacketInRouter */
|
|
|
|
ExternForVisibleFunction void far ZipQueryTimerExpired(long unsigned timerId,
|
|
int additionalDataSize,
|
|
char far *additionalData)
|
|
{
|
|
RoutingTableEntry routingTableEntry;
|
|
BufferDescriptor datagram;
|
|
int hashBucket;
|
|
AppleTalkAddress source, destination;
|
|
long sourceSocket;
|
|
|
|
/* "Use" unneeded actual parameters. */
|
|
|
|
timerId, additionalDataSize, additionalData;
|
|
|
|
/* We're going to muck with the routing databases, so defer incoming
|
|
packets while we do the deed. */
|
|
|
|
DeferIncomingPackets();
|
|
|
|
/* We want to iterate through the routing table and send out a query to any
|
|
network that we don't know the zone name of. */
|
|
|
|
/* Walk through the routing table looking for networks that we don't know
|
|
the zone of... */
|
|
|
|
for (hashBucket = 0;
|
|
hashBucket < NumberOfRtmpHashBuckets;
|
|
hashBucket += 1)
|
|
for (routingTableEntry = routingTable[hashBucket];
|
|
routingTableEntry isnt empty;
|
|
routingTableEntry = routingTableEntry->next)
|
|
{
|
|
|
|
/* If we already know the zone for this network, skip it. */
|
|
|
|
if (routingTableEntry->zoneListValid)
|
|
continue;
|
|
|
|
/* Get a buffer descriptor for our query. */
|
|
|
|
if ((datagram = NewBufferDescriptor(ZipOneZoneQueryDdpSize)) is Empty)
|
|
{
|
|
ErrorLog("ZipQueryTimerExpired", ISevError, __LINE__, UnknownPort,
|
|
IErrFullZipOutOfMemory, IMsgFullZipOutOfMemory,
|
|
Insert0());
|
|
continue;
|
|
}
|
|
|
|
/* Build the static part of the query packet. */
|
|
|
|
datagram->data[ZipCommandOffset] = ZipQueryCommand;
|
|
datagram->data[ZipNetworkCountOffset] = 1;
|
|
|
|
/* Place the network number in question into the query packet. */
|
|
|
|
datagram->data[ZipFirstNetworkOffset] =
|
|
(unsigned char)((routingTableEntry->networkRange.firstNetworkNumber
|
|
>> 8) & 0xFF);
|
|
datagram->data[ZipFirstNetworkOffset + 1] =
|
|
(unsigned char)(routingTableEntry->networkRange.firstNetworkNumber & 0xFF);
|
|
|
|
/* Compute the source and destination for this request. */
|
|
|
|
source.networkNumber =
|
|
portDescriptors[routingTableEntry->port].aRouter.networkNumber;
|
|
source.nodeNumber =
|
|
portDescriptors[routingTableEntry->port].aRouter.nodeNumber;
|
|
source.socketNumber = ZonesInformationSocket;
|
|
if (routingTableEntry->numberOfHops is 0)
|
|
{
|
|
destination.networkNumber =
|
|
portDescriptors[routingTableEntry->port].aRouter.networkNumber;
|
|
destination.nodeNumber =
|
|
portDescriptors[routingTableEntry->port].aRouter.nodeNumber;
|
|
}
|
|
else
|
|
{
|
|
destination.networkNumber =
|
|
routingTableEntry->nextRouter.networkNumber;
|
|
destination.nodeNumber =
|
|
routingTableEntry->nextRouter.nodeNumber;
|
|
}
|
|
destination.socketNumber = ZonesInformationSocket;
|
|
|
|
if ((sourceSocket = MapAddressToSocket(routingTableEntry->port,
|
|
source)) < ATnoError)
|
|
{
|
|
ErrorLog("ZipQueryTimerExpired", ISevError, __LINE__,
|
|
routingTableEntry->port,
|
|
IErrFullZipSocketNotOpen, IMsgFullZipSocketNotOpen,
|
|
Insert0());
|
|
FreeBufferChain(datagram);
|
|
continue;
|
|
}
|
|
|
|
/* Send the packet! */
|
|
|
|
if (DeliverDdp(sourceSocket, destination, DdpProtocolZip,
|
|
datagram, ZipOneZoneQueryDdpSize, Empty,
|
|
Empty, 0) isnt ATnoError)
|
|
ErrorLog("ZipQueryTimerExpired", ISevError, __LINE__,
|
|
routingTableEntry->port,
|
|
IErrFullZipBadQuerySend, IMsgFullZipBadQuerySend,
|
|
Insert0());
|
|
|
|
} /* Loop through the routing table... */
|
|
|
|
/* Re-arm ZIP query timer... */
|
|
|
|
StartTimer(ZipQueryTimerExpired, ZipQueryTimerSeconds, 0, empty);
|
|
|
|
/* We've done the deed... */
|
|
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return;
|
|
|
|
} /* ZipQueryTimerExpired */
|
|
|
|
ExternForVisibleFunction Boolean GetZoneListFor(int port)
|
|
{
|
|
/* Similar to RTMP finding out the network number attached to port, our
|
|
task is to find out the zone list of the network attached to a
|
|
particular port. We too don't want to mess up a working AppleTalk
|
|
internet. So, spend a little while doing zone queries to see if the
|
|
network already has a zone list -- if we find one, use it; else, we
|
|
had better be a seed router. */
|
|
|
|
BufferDescriptor datagram;
|
|
int numberOfRequests = 0;
|
|
RoutingTableEntry routingTableEntry;
|
|
AppleTalkAddress source, destination;
|
|
PortHandlers portHandlers;
|
|
char far *multicastAddress;
|
|
|
|
/* Set source and destination. */
|
|
|
|
source.networkNumber = portDescriptors[port].aRouter.networkNumber;
|
|
source.nodeNumber = portDescriptors[port].aRouter.nodeNumber;
|
|
source.socketNumber = ZonesInformationSocket;
|
|
destination.networkNumber = CableWideBroadcastNetworkNumber;
|
|
destination.nodeNumber = AppleTalkBroadcastNodeNumber;
|
|
destination.socketNumber = ZonesInformationSocket;
|
|
|
|
if ((routingTableEntry =
|
|
FindInRoutingTable(portDescriptors[port].thisCableRange.
|
|
firstNetworkNumber)) is empty)
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipRoutingTablesBad, IMsgFullZipRoutingTablesBad,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
|
|
/* Okay, blast a few of these guys out to see if any other bridge on the
|
|
network knows our zone name. */
|
|
|
|
while (not routingTableEntry->zoneListValid and
|
|
numberOfRequests < NumberOfZipQueries)
|
|
{
|
|
/* Get a buffer descriptor for the query. */
|
|
|
|
if ((datagram = NewBufferDescriptor(ZipOneZoneQueryDdpSize)) is Empty)
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipOutOfMemory, IMsgFullZipOutOfMemory,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
|
|
/* Build a ZipQuery packet... */
|
|
|
|
datagram->data[ZipCommandOffset] = ZipQueryCommand;
|
|
datagram->data[ZipNetworkCountOffset] = 1;
|
|
datagram->data[ZipFirstNetworkOffset] =
|
|
(unsigned char)((portDescriptors[port].thisCableRange.firstNetworkNumber
|
|
>> 8) & 0xFF);
|
|
datagram->data[ZipFirstNetworkOffset + 1] =
|
|
(unsigned char)(portDescriptors[port].thisCableRange.firstNetworkNumber &
|
|
0xFF);
|
|
|
|
if (not TransmitDdp(port, source, destination, DdpProtocolZip,
|
|
datagram, ZipOneZoneQueryDdpSize,
|
|
0, Empty, Empty, Empty, 0))
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipBadQuerySend, IMsgFullZipBadQuerySend,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
numberOfRequests += 1;
|
|
WaitFor(ZipQueryTimerInHundreths, &routingTableEntry->zoneListValid);
|
|
}
|
|
|
|
/* If we got an answer, we're set... but, we're going to need to play
|
|
with the routing tables... */
|
|
|
|
DeferTimerChecking();
|
|
DeferIncomingPackets();
|
|
|
|
if (routingTableEntry->zoneListValid)
|
|
{
|
|
/* The valid zone list is now in the routing table... move it to the
|
|
port descriptor. */
|
|
|
|
if ((portDescriptors[port].thisZoneList =
|
|
CopyZoneList(routingTableEntry->zoneList)) is empty)
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipCouldNotCopy, IMsgFullZipCouldNotCopy,
|
|
Insert0());
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
return(False);
|
|
}
|
|
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
|
|
/* If we are an extended network, we should already have "thisZone" set
|
|
(due to GetNetInfo's when we allocated this node), if not, try it
|
|
again. Also, find out the true default zone. */
|
|
|
|
if (portDescriptors[port].extendedNetwork)
|
|
{
|
|
AppleTalkAddress address;
|
|
long socket;
|
|
|
|
/* The router's Zip packet handler doesn't want to be told about
|
|
zones (it thinks it knows), so it ignores NetInfoReplies, so
|
|
for these GetNetworkInfoForNodes, swich back to the non-router
|
|
Zip handler. */
|
|
|
|
address.networkNumber = portDescriptors[port].aRouter.networkNumber;
|
|
address.nodeNumber = portDescriptors[port].aRouter.nodeNumber;
|
|
address.socketNumber = ZonesInformationSocket;
|
|
if ((socket = MapAddressToSocket(port, address)) < 0 or
|
|
NewHandlerForSocket(socket, ZipPacketIn, (long)0,
|
|
False) isnt ATnoError)
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipBadSocketOpen, IMsgFullZipBadSocketOpen,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
|
|
/* Now fetch the "thisZone" (if needed) and "defaultZone." */
|
|
|
|
if (not portDescriptors[port].thisZoneValid and
|
|
not GetNetworkInfoForNode(port, portDescriptors[port].aRouter,
|
|
False))
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipNoThisZone, IMsgFullZipNoThisZone,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
if (not GetNetworkInfoForNode(port, portDescriptors[port].aRouter,
|
|
True))
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipNoThisZone, IMsgFullZipNoThisZone,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
|
|
/* Okay, now switch back to the router's Zip handler. */
|
|
|
|
if (NewHandlerForSocket(socket, ZipPacketInRouter, (long)0,
|
|
False) isnt ATnoError)
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipBadSocketOpen, IMsgFullZipBadSocketOpen,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
|
|
/* The default zone had better be on the zone list we've just
|
|
received. */
|
|
|
|
if (not ZoneOnList(portDescriptors[port].thisDefaultZone,
|
|
portDescriptors[port].thisZoneList) or
|
|
not ZoneOnList(portDescriptors[port].thisZone,
|
|
portDescriptors[port].thisZoneList))
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipBadThisZone, IMsgFullZipBadThisZone,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
|
|
/* Okay, we're all set. */
|
|
|
|
return(True);
|
|
}
|
|
|
|
/* On a non-extended network, the one entry on the zone list should
|
|
also be "this zone". */
|
|
|
|
strcpy(portDescriptors[port].thisZone,
|
|
portDescriptors[port].thisZoneList->zone);
|
|
portDescriptors[port].thisZoneValid = True;
|
|
return(True);
|
|
}
|
|
|
|
HandleIncomingPackets();
|
|
HandleDeferredTimerChecks();
|
|
|
|
/* Okay, we didn't get an answer, we had better be able to seed. There is
|
|
a vauge chance that we got "this zone" set when allocating our node
|
|
and whatever router told us that went down before we could ask for the
|
|
zone list -- so, deallocate the multicast address, if any first. */
|
|
|
|
portHandlers = &portSpecificInfo[portDescriptors[port].portType];
|
|
if (portDescriptors[port].extendedNetwork and
|
|
portDescriptors[port].thisZoneValid)
|
|
if (not FixedCompareCaseSensitive(portDescriptors[port].
|
|
zoneMulticastAddress,
|
|
portHandlers->hardwareAddressLength,
|
|
portHandlers->broadcastAddress,
|
|
portHandlers->hardwareAddressLength))
|
|
(*portHandlers->removeMulticastAddress)(port, 1,
|
|
portDescriptors[port].
|
|
zoneMulticastAddress);
|
|
|
|
/* Okay, now we had better know enough to seed! */
|
|
|
|
if (portDescriptors[port].initialZoneList is empty)
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipNeedSeedInfo, IMsgFullZipNeedSeedInfo,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
|
|
if ((portDescriptors[port].thisZoneList =
|
|
CopyZoneList(portDescriptors[port].initialZoneList)) is empty)
|
|
{
|
|
ErrorLog("GetZoneListFor", ISevError, __LINE__, port,
|
|
IErrFullZipCouldNotCopy, IMsgFullZipCouldNotCopy,
|
|
Insert0());
|
|
return(False);
|
|
}
|
|
if (portDescriptors[port].extendedNetwork)
|
|
{
|
|
/* Here we need to seed the default zone too. */
|
|
|
|
strcpy(portDescriptors[port].thisDefaultZone,
|
|
portDescriptors[port].initialDefaultZone);
|
|
portDescriptors[port].thisDefaultZoneValid = True;
|
|
if (portDescriptors[port].initialDesiredZone[0] isnt 0)
|
|
strcpy(portDescriptors[port].thisZone,
|
|
portDescriptors[port].initialDesiredZone);
|
|
else
|
|
strcpy(portDescriptors[port].thisZone,
|
|
portDescriptors[port].initialDefaultZone);
|
|
portDescriptors[port].thisZoneValid = True;
|
|
|
|
/* We should now set up the zone multicast address too... */
|
|
|
|
if ((multicastAddress =
|
|
MulticastAddressForZoneOnPort(port, portDescriptors[port].thisZone))
|
|
is empty)
|
|
return(False);
|
|
|
|
if (not FixedCompareCaseSensitive(multicastAddress,
|
|
portHandlers->hardwareAddressLength,
|
|
portHandlers->broadcastAddress,
|
|
portHandlers->hardwareAddressLength))
|
|
(*portHandlers->addMulticastAddress)(port, 1, multicastAddress);
|
|
MoveMem(portDescriptors[port].zoneMulticastAddress, multicastAddress,
|
|
portHandlers->hardwareAddressLength);
|
|
}
|
|
else
|
|
{
|
|
/* On non-extended networks, this zone should be the only one on the
|
|
zone list. */
|
|
|
|
strcpy(portDescriptors[port].thisZone,
|
|
portDescriptors[port].thisZoneList->zone);
|
|
portDescriptors[port].thisZoneValid = True;
|
|
}
|
|
|
|
/* All set! */
|
|
|
|
return(True);
|
|
|
|
} /* GetZoneList */
|
|
|
|
char far * far MulticastAddressForZoneOnPort(int port,
|
|
char far *zone)
|
|
{
|
|
short unsigned checksum;
|
|
StaticForSmallStack char upcasedZone[MaximumZoneLength + 1];
|
|
int index;
|
|
static struct buffDesc descriptor;
|
|
|
|
/* Upcase and checksum the passed zone name. */
|
|
|
|
for (index = 0; zone[index] isnt 0; index += 1)
|
|
if (islower(zone[index]))
|
|
upcasedZone[index] = (char)(toupper(zone[index]));
|
|
else
|
|
upcasedZone[index] = zone[index];
|
|
|
|
descriptor.outBoardDataValid = True;
|
|
descriptor.outBoardBuffer = upcasedZone;
|
|
descriptor.outBoardData = upcasedZone;
|
|
descriptor.outBoardAllocatedSize = index;
|
|
descriptor.outBoardSize = index;
|
|
checksum = DdpChecksumBufferChain(&descriptor, index, (long)0);
|
|
|
|
/* Caclulate the the zone multicast address based on the port type. */
|
|
|
|
switch (portDescriptors[port].portType)
|
|
{
|
|
case EthernetNetwork:
|
|
case FddiNetwork:
|
|
return(ethernetZoneMutlicastAddrs[checksum %
|
|
NumberOfEnetZoneMulticastAddrs]);
|
|
|
|
case TokenRingNetwork:
|
|
return(tokenRingZoneMutlicastAddrs[checksum %
|
|
NumberOfTRingZoneMulticastAddrs]);
|
|
|
|
default:
|
|
ErrorLog("MulticastAddressForZoneOnPort", ISevError, __LINE__, port,
|
|
IErrFullZipBadPortType, IMsgFullZipBadPortType,
|
|
Insert0());
|
|
return(empty);
|
|
}
|
|
|
|
} /* MulticastAddressForZoneOnPort */
|
|
|
|
#endif
|