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.
 
 
 
 
 
 

568 lines
12 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
node.c
Abstract:
This module contains the node management code.
Author:
Garth Conboy Initial Coding
Nikhil Kamkolkar Rewritten for microsoft coding style. mpized
Revision History:
--*/
#include "atalk.h"
LOCAL
BOOLEAN
OpenStaticSockets(int port, EXTENDED_NODENUMBER node);
LOCAL
PACTIVE_NODE
AllocateActiveNode(VOID);
APPLETALK_ERROR
GetNodeOnPort(
int Port,
BOOLEAN AllowStartupRange,
BOOLEAN ServerNode,
BOOLEAN RoutersNode,
PEXTENDED_NODENUMBER Node
)
{
APPLETALK_ERROR error = ATnoError;
int nodeNumber;
PACTIVE_NODE activeNode;
EXTENDED_NODENUMBER newNode;
EXTENDED_NODENUMBER desiredNode = { UNKNOWN_NETWORKNUMBER,
UNKNOWN_NODENUMBER};
// If the "default port" is requested, demystify it.
if (Port == DEFAULT_PORT) {
if ((Port = FindDefaultPort()) < 0) {
return(ATappleTalkShutDown);
}
}
if (!AtalkVerifyStack(__LINE__ | __NODE__)) {
return(ATappleTalkShutDown);
}
if (!AtalkVerifyPortDescriptor(GET_PORTDESCRIPTOR(Port),__LINE__ | __NODE__)) {
AtalkDereferenceStack((__LINE__ | __NODE__));
return(ATappleTalkShutDown);
}
do {
// If we are an extended network port (not halfport or localtalk...)
if (!(GET_PORTDESCRIPTOR(Port)->PortType == NONAPPLETALK_HALFPORT) &&
!(GET_PORTDESCRIPTOR(Port)->PortType == LOCALTALK_NETWORK)) {
// Don't allow too many nodes per port!
if (ElementsOnList(GET_PORTDESCRIPTOR(Port)->ActiveNodes) >
MAXIMUM_NODESPERPORT) {
error = ATnoMoreNodes;
break;
}
// Pick a desired node, if we have a PRAM value.
if ((RoutersNode) &&
(GET_PORTDESCRIPTOR(Port)->RoutersPRamStartupNode.NetworkNumber !=
UNKNOWN_NETWORKNUMBER)) {
desiredNode = GET_PORTDESCRIPTOR(Port)->RoutersPRamStartupNode;
} else if (!(RoutersNode) &&
!(GET_PORTDESCRIPTOR(Port)->Flags & PD_FIRSTNODEALLOC) &&
(GET_PORTDESCRIPTOR(Port)->UsersPRamStartupNode.NetworkNumber
!= UNKNOWN_NETWORKNUMBER)) {
desiredNode = GET_PORTDESCRIPTOR(Port)->UsersPRamStartupNode;
}
// Okay, let AARP have a crack at finding a node!
if (!AarpForNodeOnPort(
Port,
AllowStartupRange,
ServerNode,
desiredNode,
&newNode)) {
error = ATnoMoreNodes;
break;
}
} else {
//
// On non-extended Ports we only allow one node! The theory being that some
// LocalTalk cards are too smart for their own good and have a conecpt of
// their "source node number" and thus only support one node, also on
// non-extended Ports, nodes are scarse.
//
if ((activeNode = AllocateActiveNode()) == NULL) {
error = AToutOfMemory;
break;
}
EnterCriticalSection(GLOBAL_DDP);
if ((!(GET_PORTDESCRIPTOR(Port)->ExtendedNetwork) &&
(GET_PORTDESCRIPTOR(Port)->ActiveNodes == NULL))
||
// Only one node would ever be usefull on half Ports.
((GET_PORTDESCRIPTOR(Port)->PortType == NONAPPLETALK_HALFPORT) &&
(GET_PORTDESCRIPTOR(Port)->ActiveNodes == NULL))) {
//
// Good, no nodes on these currently, thread in our allocated node
// that should prevent other request from passing above test
//
activeNode->Next = GET_PORTDESCRIPTOR(Port)->ActiveNodes;
GET_PORTDESCRIPTOR(Port)->ActiveNodes = activeNode;
// One reference for creation, the other is until we are
// done initializing the node
AtalkReferenceActiveNode(activeNode, __NODE__ | __LINE__);
AtalkReferenceActiveNode(activeNode, __NODE__ | __LINE__);
} else {
Free(activeNode);
error = ATnoMoreNodes;
}
LeaveCriticalSection(GLOBAL_DDP);
if (error != ATnoError) {
break;
}
if (GET_PORTDESCRIPTOR(Port)->PortType == NONAPPLETALK_HALFPORT) {
// Build a dummy active node; invalid network/node values.
newNode.NetworkNumber = UNKNOWN_NETWORKNUMBER;
newNode.NodeNumber = UNKNOWN_NODENUMBER;
activeNode->ExtendedNode = newNode;
} else if (GET_PORTDESCRIPTOR(Port)->PortType == LOCALTALK_NETWORK) {
// Pick a desired node, if we have a PRAM value.
if (RoutersNode &&
GET_PORTDESCRIPTOR(Port)->RoutersPRamStartupNode.NetworkNumber
!= UNKNOWN_NETWORKNUMBER) {
desiredNode = GET_PORTDESCRIPTOR(Port)->RoutersPRamStartupNode;
} else if (!RoutersNode &&
GET_PORTDESCRIPTOR(Port)->UsersPRamStartupNode.NetworkNumber
!= UNKNOWN_NETWORKNUMBER) {
desiredNode = GET_PORTDESCRIPTOR(Port)->UsersPRamStartupNode;
}
// During intitialization the localtalk node address should have
// been stored in the MyAddress field of this port descriptor. Cast
// it as a ulong before using it.
nodeNumber = *(PUSHORT)GET_PORTDESCRIPTOR(Port)->MyAddress;
ASSERT(nodeNumber >= 0);
newNode.NetworkNumber =
GET_PORTDESCRIPTOR(Port)->ThisCableRange.FirstNetworkNumber;
newNode.NodeNumber = (char)nodeNumber;
activeNode->ExtendedNode = newNode;
}
// Remove the reference we had for the active node while initializing it
AtalkDereferenceActiveNodeInterlocked(activeNode, __NODE__ | __LINE__);
}
// Set up the RTMP, NBP and EP listeners on the new node.
if (!OpenStaticSockets(Port, newNode)) {
LOG_ERRORONPORT(
Port,
EVENT_ATALK_NODE_OPENSOCKETS,
(__NODE__ | __LINE__),
0,
NULL,
0,
0,
NULL);
}
if (Node != NULL)
*Node = newNode;
// Try to save PRAM info...
if (RoutersNode) {
SavePRamAddress(Port, True, newNode);
GET_PORTDESCRIPTOR(Port)->RoutersPRamStartupNode = newNode;
} else {
EnterCriticalSection(GLOBAL_DDP);
if (!GET_PORTDESCRIPTOR(Port)->Flags & PD_FIRSTNODEALLOC) {
GET_PORTDESCRIPTOR(Port)->Flags |= PD_FIRSTNODEALLOC;
GET_PORTDESCRIPTOR(Port)->UsersPRamStartupNode = newNode;
}
LeaveCriticalSection(GLOBAL_DDP);
SavePRamAddress(Port, False, newNode);
}
} while (FALSE);
AtalkDereferencePortDescriptor(GET_PORTDESCRIPTOR(Port),__LINE__ | __NODE__);
AtalkDereferenceStack(__LINE__ | __NODE__ );
return(error);
} // GetNodeOnPort
APPLETALK_ERROR
ReleaseNodeOnPort(
int Port,
EXTENDED_NODENUMBER Node
)
{
APPLETALK_ERROR error = ATnoError;
PACTIVE_NODE activeNode, previousActiveNode;
POPEN_SOCKET openSocket, nextOpenSocket;
// If the "default Port" == requested, demystify it.
if (Port == DEFAULT_PORT)
if ((Port = FindDefaultPort()) < 0)
return(ATappleTalkShutDown);
EnterCriticalSection(GLOBAL_DDP);
// Find the node on the Port's active node list.
for (activeNode = GET_PORTDESCRIPTOR(Port)->ActiveNodes;
activeNode != NULL;
activeNode = activeNode->Next) {
if (ExtendedAppleTalkNodesEqual(&activeNode->ExtendedNode, &Node))
break;
}
if (activeNode != NULL) {
if ((activeNode->Flags & AN_CLOSING) == 0) {
activeNode->Flags |= AN_CLOSING;
// Close any sockets that are still open.
for (openSocket = activeNode->OpenSockets;
openSocket != NULL;
openSocket = nextOpenSocket) {
nextOpenSocket = openSocket->Next;
if (CloseSocketOnNode(openSocket->Socket, NULL, NULL) != ATnoError)
LOG_ERRORONPORT(
Port,
EVENT_ATALK_NODE_CLOSESOCKETS,
(__NODE__ | __LINE__),
openSocket->Socket,
openSocket,
sizeof(openSocket),
0,
NULL);
}
// Dereference for creation
AtalkDereferenceActiveNode(activeNode, __NODE__ | __LINE__);
}
// Multiple calls to ReleaseNode == a single call
} else {
error = ATnodeNotInUse;
}
return(error);
} // ReleaseNodeOnPort
VOID
SavePRamAddress(
int Port,
BOOLEAN routersNode,
EXTENDED_NODENUMBER node
)
{
//
// If the target environment supPorts the concept, this is a good place
// to save away the last used AppleTalk addresses in PRAM. This information
// should then be passed back to Initialize() (in the PRam fields of
// PortInfo[]) on subsequent stack/router startup calls.
//
Port;
routersNode;
node;
}
BOOLEAN
RoutersNodeOnPort(
int Port,
PEXTENDED_NODENUMBER RoutersNode
)
{
PACTIVE_NODE activeNode;
BOOLEAN found = FALSE;
// If the "default Port" == requested, demystify it.
if (Port == DEFAULT_PORT)
if ((Port = FindDefaultPort()) < 0)
return(found);
EnterCriticalSection(GLOBAL_DDP);
for (activeNode = GET_PORTDESCRIPTOR(Port)->ActiveNodes;
activeNode != NULL;
activeNode = activeNode->Next)
if (activeNode->RoutersNode) {
*RoutersNode = activeNode->ExtendedNode;
found = TRUE;
break;
}
LeaveCriticalSection(GLOBAL_DDP);
return(found);
} // RoutersNodeOnPort
BOOLEAN
OpenStaticSockets(
int Port,
EXTENDED_NODENUMBER Node
)
{
long nbpSocket, epSocket, rtmpSocket;
if (OpenSocketOnNode(
&nbpSocket,
Port,
&Node,
NAMESINFORMATION_SOCKET,
NbpPacketIn,
(long)0,
FALSE,
NULL,
0,
NULL) == ATnoError) {
if (OpenSocketOnNode(
&epSocket,
Port,
&Node,
ECHOER_SOCKET,
EpPacketIn,
(long)0,
FALSE,
NULL,
0,
NULL) == ATnoError) {
if (OpenSocketOnNode(
&rtmpSocket,
Port,
&Node,
RTMP_SOCKET,
RtmpPacketIn,
(long)0,
FALSE,
NULL,
0,
NULL) == ATnoError) {
return(TRUE);
} else {
CloseSocketOnNode(nbpSocket, NULL, NULL);
CloseSocketOnNode(epSocket, NULL, NULL);
}
} else {
CloseSocketOnNode(nbpSocket, NULL, NULL);
}
}
return(FALSE);
} // OpenStaticSockets
PACTIVE_NODE
AtalkRefActiveNode(
PACTIVE_NODE ActiveNode
)
{
PACTIVE_NODE node = ActiveNode;
ASSERT(ActiveNode->ReferenceCount >= 0);
ActiveNode->ReferenceCount++;
return(node);
}
PACTIVE_NODE
AtalkVerifyActiveNode(
PACTIVE_NODE ActiveNode,
ULONG Location
)
{
PACTIVE_NODE node = ActiveNode;
if (ActiveNode->Flags & AN_CLOSING) {
node = NULL;
} else {
AtalkRefActiveNode(ActiveNode);
}
return(node);
}
PACTIVE_NODE
AtalkVerifyNextNonClosingActiveNode(
PACTIVE_NODE StartActiveNode,
ULONG Location
)
{
//
// THIS WILL INCLUDE THE START NODE
//
PACTIVE_NODE node;
while (StartActiveNode != NULL) {
if ((node = AtalkVerifyActiveNode(
StartActiveNode,
Location)) == NULL) {
StartActiveNode = StartActiveNode->Next;
continue;
} else {
break;
}
}
return(node);
}
PACTIVE_NODE
AtalkVerifyActiveNodeInterlocked(
PACTIVE_NODE ActiveNode,
ULONG Location
)
{
PACTIVE_NODE node = ActiveNode;
EnterCriticalSection(GLOBAL_DDP);
if (ActiveNode->Flags & AN_CLOSING) {
node = NULL;
} else {
AtalkRefActiveNode(ActiveNode);
}
LeaveCriticalSection(GLOBAL_DDP);
return(node);
}
VOID
AtalkDerefActiveNode(
PACTIVE_NODE ActiveNode
)
{
PACTIVE_NODE activeNode, previousActiveNode;
BOOLEAN release = FALSE;
int port = ActiveNode->Port;
ASSERT(ActiveNode->ReferenceCount > 0);
ActiveNode->ReferenceCount--;
if (ActiveNode->ReferenceCount == 0) {
ASSERT(ActiveNode->Flags & AN_CLOSING);
release = TRUE;
// No more references on this active node
// Find the node on the port's active node list.
for (activeNode = GET_PORTDESCRIPTOR(port)->ActiveNodes,
previousActiveNode = NULL;
activeNode != NULL;
previousActiveNode = activeNode,
activeNode = activeNode->Next) {
if (activeNode == ActiveNode)
break;
}
if (activeNode == NULL) {
// INTERNAL_ERROR()
}
// Remove it from the list.
if (previousActiveNode == NULL)
GET_PORTDESCRIPTOR(port)->ActiveNodes = activeNode->Next;
else
previousActiveNode->Next = activeNode->Next;
// Deref the port descriptor for this node
AtalkDereferencePortDescriptor(
GET_PORTDESCRIPTOR(port), __NODE__ | __LINE__);
// All set!
Free(activeNode);
}
return;
}
PACTIVE_NODE
AllocateActiveNode(
VOID
)
{
PACTIVE_NODE activeNode;
activeNode = Calloc(sizeof(ACTIVE_NODE), sizeof(CHAR));
if (activeNode != NULL) {
activeNode->Type = AN_TYPE;
activeNode->Size = AN_SIZE;
}
return(activeNode);
}