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.
1615 lines
42 KiB
1615 lines
42 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
Copyright (c) 1993 Micro Computer Systems, Inc.
|
|
|
|
Module Name:
|
|
|
|
net\svcdlls\nwsap\server\network.c
|
|
|
|
Abstract:
|
|
|
|
These are the network interface routines for the NT SAP Agent
|
|
|
|
Author:
|
|
|
|
Brian Walker (MCS) 06-15-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
/** This is the address we send to **/
|
|
|
|
#define SAP_ADDRESS_LENGTH 15
|
|
INT SapBroadcastAddressLength = SAP_ADDRESS_LENGTH;
|
|
UCHAR SapBroadcastAddress[] = {
|
|
AF_IPX, 0, /* Address Family */
|
|
0x00, 0x00, 0x00, 0x00, /* Dest. Net Number */
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Dest. Node Number */
|
|
0x04, 0x52, /* Dest. Socket */
|
|
0x04 /* Packet type */
|
|
};
|
|
|
|
/** Internal Function Prototypes **/
|
|
|
|
INT
|
|
SapAddSendEntry(
|
|
PSAP_RECORD Entry,
|
|
PSAP_PKTLIST Plist,
|
|
USHORT HopInc);
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p N e t w o r k I n i t
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the network portion of the Sap Agent.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
0 = OK
|
|
Else = Error
|
|
*******************************************************************
|
|
--*/
|
|
|
|
INT
|
|
SapNetworkInit(
|
|
VOID)
|
|
{
|
|
INT rc;
|
|
INT Length;
|
|
BOOL Value;
|
|
SOCKADDR_IPX Bindaddr;
|
|
PSAP_CARD Cardptr;
|
|
INT Cardnum;
|
|
IPX_ADDRESS_DATA Addrdata;
|
|
|
|
/** Open an IPX datagram socket **/
|
|
|
|
SapSocket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
|
|
if (SapSocket == INVALID_SOCKET) {
|
|
SapError = h_errno;
|
|
SapEventId = NWSAP_EVENT_SOCKET_FAILED;
|
|
return -1;
|
|
}
|
|
|
|
/** Enable sending of broadcasts **/
|
|
|
|
Value = TRUE;
|
|
rc = setsockopt(SapSocket, SOL_SOCKET, SO_BROADCAST, (PVOID)&Value, sizeof(INT));
|
|
if (rc == -1) {
|
|
SapError = h_errno;
|
|
SapEventId = NWSAP_EVENT_SETOPTBCAST_FAILED;
|
|
return -1;
|
|
}
|
|
|
|
/** Setup the address to bind to **/
|
|
|
|
memset(&Bindaddr, 0, sizeof(SOCKADDR_IPX));
|
|
Bindaddr.sa_family = AF_IPX;
|
|
Bindaddr.sa_socket = htons(NWSAP_SAP_SOCKET);
|
|
|
|
/** Bind to the socket **/
|
|
|
|
rc = bind(SapSocket, (PSOCKADDR)&Bindaddr, sizeof(SOCKADDR_IPX));
|
|
if (rc == -1) {
|
|
SapError = h_errno;
|
|
SapEventId = NWSAP_EVENT_BIND_FAILED;
|
|
IF_DEBUG(INITIALIZATION_ERRORS) {
|
|
SS_PRINT(("NWSAP: Error binding to SAP socket: error = %d\n", SapError));
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/** Get the bound address and save off the net/node numbers **/
|
|
|
|
Length = sizeof(SOCKADDR_IPX);
|
|
rc = getsockname(SapSocket, (PSOCKADDR)&Bindaddr, &Length);
|
|
if (rc == -1) {
|
|
SapError = h_errno;
|
|
SapEventId = NWSAP_EVENT_GETSOCKNAME_FAILED;
|
|
IF_DEBUG(INITIALIZATION_ERRORS) {
|
|
SS_PRINT(("NWSAP: Error getting socket name (address): error = %d\n", SapError));
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/** **/
|
|
|
|
IF_DEBUG(INITIALIZATION) {
|
|
SS_PRINT(("NWSAP: Bound Address is 0x%02x:0x%02x:0x%02x:0x%02x - 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x - 0x%02x:0x%02x\n",
|
|
(UCHAR)Bindaddr.sa_netnum[0],
|
|
(UCHAR)Bindaddr.sa_netnum[1],
|
|
(UCHAR)Bindaddr.sa_netnum[2],
|
|
(UCHAR)Bindaddr.sa_netnum[3],
|
|
(UCHAR)Bindaddr.sa_nodenum[0],
|
|
(UCHAR)Bindaddr.sa_nodenum[1],
|
|
(UCHAR)Bindaddr.sa_nodenum[2],
|
|
(UCHAR)Bindaddr.sa_nodenum[3],
|
|
(UCHAR)Bindaddr.sa_nodenum[4],
|
|
(UCHAR)Bindaddr.sa_nodenum[5],
|
|
(UCHAR)*(PUCHAR)&Bindaddr.sa_socket,
|
|
(UCHAR)*((PUCHAR)&Bindaddr.sa_socket + 1)));
|
|
}
|
|
|
|
/** Save off the net/node in global variables **/
|
|
|
|
SAP_COPY_NETNUM(SapNetNum, Bindaddr.sa_netnum);
|
|
SAP_COPY_NODENUM(SapNodeNum, Bindaddr.sa_nodenum);
|
|
|
|
/** Set the extended address option **/
|
|
|
|
Length = 1;
|
|
rc = setsockopt(
|
|
SapSocket, /* Socket Handle */
|
|
NSPROTO_IPX, /* Option Level */
|
|
IPX_EXTENDED_ADDRESS, /* Option Name */
|
|
(PUCHAR)&Length, /* Ptr to on/off flag */
|
|
sizeof(INT)); /* Length of flag */
|
|
|
|
if (rc == -1) {
|
|
SapError = h_errno;
|
|
SapEventId = NWSAP_EVENT_OPTEXTENDEDADDR_FAILED;
|
|
IF_DEBUG(INITIALIZATION_ERRORS) {
|
|
SS_PRINT(("NWSAP: Error setting EXTENDED ADDRESS option: error = %d\n", SapError));
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/** Get the max number of cards there are **/
|
|
|
|
Length = sizeof(INT);
|
|
rc = getsockopt(
|
|
SapSocket, /* Socket Handle */
|
|
NSPROTO_IPX, /* Option Level */
|
|
IPX_MAX_ADAPTER_NUM, /* Option Name */
|
|
(PUCHAR)&SapMaxCardIndex, /* Ptr to on/off flag */
|
|
&Length); /* Length of flag */
|
|
|
|
if (rc == -1) {
|
|
SapError = h_errno;
|
|
SapEventId = NWSAP_EVENT_OPTMAXADAPTERNUM_ERROR;
|
|
|
|
IF_DEBUG(INITIALIZATION_ERRORS) {
|
|
SS_PRINT(("NWSAP: Error getting MAX_ADAPTER_NUM from transport: error = %d\n", SapError));
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/** **/
|
|
|
|
IF_DEBUG(INITIALIZATION) {
|
|
SS_PRINT(("NWSAP: Max number of cards from xport = %d\n", SapMaxCardIndex));
|
|
}
|
|
|
|
/** Get the list of cards we have **/
|
|
|
|
Cardnum = 0;
|
|
while (Cardnum != SapMaxCardIndex) {
|
|
|
|
/** Fill in this entry **/
|
|
|
|
Addrdata.adapternum = Cardnum;
|
|
Length = sizeof(IPX_ADDRESS_DATA);
|
|
rc = getsockopt(
|
|
SapSocket,
|
|
NSPROTO_IPX,
|
|
IPX_ADDRESS,
|
|
(PCHAR)&Addrdata,
|
|
&Length);
|
|
|
|
/** If error - just skip it **/
|
|
|
|
if (rc) {
|
|
IF_DEBUG(INITIALIZATION_ERRORS) {
|
|
SS_PRINT(("NWSAP: Error getting card info: h_errno = %d: Anum = %d\n", h_errno, Cardnum));
|
|
}
|
|
Cardnum++;
|
|
continue;
|
|
}
|
|
|
|
/** If this card not active - skip it **/
|
|
|
|
if (!Addrdata.status) {
|
|
IF_DEBUG(INITIALIZATION_ERRORS) {
|
|
SS_PRINT(("NWSAP: Netinit: Card info says card is down: h_errno = %d: Anum = %d\n", h_errno, Cardnum));
|
|
}
|
|
Cardnum++;
|
|
continue;
|
|
}
|
|
|
|
/** If this card already in the list - skip it **/
|
|
|
|
ACQUIRE_CARDLIST_WRITERS_LOCK(rc, "Cardinit");
|
|
Cardptr = SapCardHead;
|
|
while (Cardptr) {
|
|
if (Cardptr->Number == Addrdata.adapternum)
|
|
break;
|
|
Cardptr = Cardptr->Next;
|
|
}
|
|
|
|
/**
|
|
If we found the card, then it was added by the
|
|
WAN notify thread already. Just skip to the next
|
|
adapter.
|
|
**/
|
|
|
|
if (Cardptr) {
|
|
RELEASE_CARDLIST_WRITERS_LOCK("Cardinit X0");
|
|
Cardnum++;
|
|
continue;
|
|
}
|
|
|
|
/** Allocate an entry for this card **/
|
|
|
|
Cardptr = SAP_MALLOC(SAP_CARD_SIZE, "ALLOC CARD");
|
|
if (Cardptr == NULL) {
|
|
RELEASE_CARDLIST_WRITERS_LOCK("Cardinit X1");
|
|
SapError = 0;
|
|
SapEventId = NWSAP_EVENT_CARDMALLOC_FAILED;
|
|
return -1;
|
|
}
|
|
|
|
/** Fill in the values **/
|
|
|
|
SAP_COPY_NETNUM(Cardptr->Netnum, Addrdata.netnum);
|
|
SAP_COPY_NODENUM(Cardptr->Nodenum, Addrdata.nodenum);
|
|
Cardptr->Linkspeed = Addrdata.linkspeed;
|
|
Cardptr->Wanflag = Addrdata.wan;
|
|
Cardptr->Maxpkt = Addrdata.maxpkt;
|
|
Cardptr->Number = Cardnum;
|
|
Cardptr->ReqCount = 0;
|
|
|
|
/** For building with **/
|
|
|
|
Cardptr->Plist.Curnum = 0;
|
|
Cardptr->Plist.Curpkt = NULL;
|
|
Cardptr->Plist.Curptr = NULL;
|
|
Cardptr->Plist.PktHead = NULL;
|
|
Cardptr->Plist.PktTail = NULL;
|
|
Cardptr->Plist.NumPkts = 0;
|
|
|
|
/** **/
|
|
|
|
#if DBG
|
|
IF_DEBUG(INITIALIZATION) {
|
|
SS_PRINT(("Card %d\n", Cardnum));
|
|
SapDumpMem(Cardptr->Netnum, 10, "NET/NODE");
|
|
}
|
|
#endif
|
|
|
|
/** Put this entry on the end of the list **/
|
|
|
|
Cardptr->Next = NULL;
|
|
if (SapCardHead)
|
|
SapCardTail->Next = Cardptr;
|
|
else
|
|
SapCardHead = Cardptr;
|
|
|
|
SapCardTail = Cardptr;
|
|
SapNumCards++;
|
|
RELEASE_CARDLIST_WRITERS_LOCK("Cardinit X2");
|
|
|
|
/** Goto the next card number **/
|
|
|
|
Cardnum++;
|
|
}
|
|
|
|
/**
|
|
If there are no cards, that is OK. We allow that because
|
|
if all we have is a WAN adapter that is not up yet, then
|
|
we will come up later when the WAN adapter comes up.
|
|
**/
|
|
|
|
/** Initialization is OK **/
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p N e t w o r k S h u t d o w n
|
|
|
|
Routine Description:
|
|
|
|
When we are terminating, this routine will clean
|
|
up everything.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
*******************************************************************
|
|
--*/
|
|
|
|
VOID
|
|
SapNetworkShutdown(
|
|
VOID)
|
|
{
|
|
PSAP_CARD Cardptr;
|
|
PSAP_CARD NCardptr;
|
|
|
|
/** Free the card list **/
|
|
|
|
Cardptr = SapCardHead;
|
|
while (Cardptr) {
|
|
NCardptr = Cardptr->Next;
|
|
SAP_FREE(Cardptr, "CARD NET SHUTDOWN");
|
|
Cardptr = NCardptr;
|
|
}
|
|
|
|
/** All Done **/
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p S e n d P a c k e t s
|
|
|
|
Routine Description:
|
|
|
|
This routine sends a SAP advertise for all servers
|
|
needing one.
|
|
|
|
Arguments:
|
|
|
|
Flag = 0 - This is from SendThread
|
|
1 - This is from SapAddAdvertise
|
|
2 - Shutting down - send all with HOP = 16.
|
|
|
|
Return Value:
|
|
|
|
0 = OK
|
|
Else = Error
|
|
*******************************************************************
|
|
--*/
|
|
|
|
INT
|
|
SapSendPackets(
|
|
INT Flag)
|
|
{
|
|
PSAP_RECORD Entry;
|
|
PSAP_RECORD NextEntry;
|
|
PSAP_RECORD HeadEntry;
|
|
PSAP_RECORD NextHeadEntry;
|
|
SAP_RECORD Myentry;
|
|
PSAP_SERVER Servp;
|
|
PSAP_SERVER Nextp;
|
|
PSAP_SERVER Backp;
|
|
PSAP_CARD Cardptr;
|
|
PSAP_PKTENTRY Pktp;
|
|
PSAP_PKTENTRY NPktp;
|
|
INT rc;
|
|
BOOL doit;
|
|
UCHAR DestAddr[SAP_ADDRESS_LENGTH];
|
|
|
|
/**
|
|
If we are already in here, then we need to mark that
|
|
we caught ourselves here and leave.
|
|
|
|
We will save who called us. If we already have saved
|
|
off a call from the main advertise thread or the
|
|
cleanup code, then we will not overwrite that.
|
|
**/
|
|
|
|
ACQUIRE_SENDBUSY_LOCK();
|
|
if (SapSendPacketsBusy) {
|
|
if (SapAgainFlag == -1)
|
|
SapAgainFlag = Flag; /* Save who called in */
|
|
else if (SapAgainFlag == 1)
|
|
SapAgainFlag= Flag;
|
|
RELEASE_SENDBUSY_LOCK();
|
|
return 0;
|
|
}
|
|
SapSendPacketsBusy = 1;
|
|
SapAgainFlag = -1;
|
|
RELEASE_SENDBUSY_LOCK();
|
|
|
|
/** **/
|
|
|
|
send_again:
|
|
ACQUIRE_CARDLIST_READERS_LOCK("SapSendPackets");
|
|
|
|
/** Lock the server send table **/
|
|
|
|
ACQUIRE_SENDTABLE_LOCK();
|
|
|
|
/** Send all the packets we need to **/
|
|
|
|
Servp = SapServHead;
|
|
|
|
/**
|
|
Go thru the list and build all that we can.
|
|
We also update these in the database to make sure that
|
|
we don't timeout our internal entries.
|
|
**/
|
|
|
|
Backp = NULL;
|
|
while (Servp) {
|
|
|
|
/** If from shutdown set hop to 16 now **/
|
|
|
|
if (Flag == 2)
|
|
Servp->Hopcount = htons(16);
|
|
|
|
/** Go add this entry for all cards **/
|
|
|
|
Nextp = Servp->Next;
|
|
|
|
/** Figure whether to do this entry or not **/
|
|
|
|
if (Flag == 1) {
|
|
if (Servp->Changed)
|
|
doit = TRUE;
|
|
else
|
|
doit = FALSE;
|
|
}
|
|
else
|
|
doit = TRUE;
|
|
|
|
/**
|
|
If we should do it this entry, then add it to the list.
|
|
BUT check the filters first.
|
|
**/
|
|
|
|
if (doit) {
|
|
|
|
/** Go send it for all cards **/
|
|
|
|
Cardptr = SapCardHead;
|
|
while (Cardptr) {
|
|
|
|
/**
|
|
Check the filter here. If we should
|
|
advertise this entry or not. We do not
|
|
check the name since this is an internal server
|
|
and we must advertise for it. BUT we do check
|
|
for WAN filtering.
|
|
**/
|
|
|
|
if (Cardptr->Wanflag) {
|
|
doit = SapShouldIAdvertiseByCard(
|
|
Cardptr,
|
|
Servp->Changed);
|
|
}
|
|
else
|
|
doit = TRUE;
|
|
|
|
/** Copy this to an entry **/
|
|
|
|
if (doit) {
|
|
SAP_COPY_SERVNAME(Myentry.ServName, Servp->ServerName);
|
|
Myentry.ServType = ntohs(Servp->ServerType);
|
|
Myentry.HopCount = ntohs(Servp->Hopcount);
|
|
SAP_COPY_ADDRESS(Myentry.ServAddress, Servp->Address);
|
|
|
|
/** Add this entry to the send list **/
|
|
|
|
SapAddSendEntry(&Myentry, &Cardptr->Plist, 0);
|
|
}
|
|
|
|
/** Goto the next card entry **/
|
|
|
|
Cardptr = Cardptr->Next;
|
|
}
|
|
}
|
|
|
|
/** This entry not changed anymore **/
|
|
|
|
Servp->Changed = FALSE;
|
|
|
|
/** Update this entry in the database **/
|
|
|
|
SdmdUpdateEntry(
|
|
Servp->ServerName, /* Server name */
|
|
ntohs(Servp->ServerType), /* Server Type */
|
|
Servp->Address, /* Server Address */
|
|
ntohs(Servp->Hopcount), /* Server Hopcount */
|
|
CARDRET_MYSELF, /* Card number */
|
|
SapZeros, /* My address (don't care)*/
|
|
FALSE);
|
|
|
|
/**
|
|
If going away - delete the entry from the
|
|
advertise list.
|
|
**/
|
|
|
|
if (Servp->Hopcount == htons(16)) {
|
|
|
|
/** Take this entry out of the list **/
|
|
|
|
if (Backp)
|
|
Backp->Next = Nextp;
|
|
else
|
|
SapServHead = Nextp;
|
|
|
|
if (Servp == SapServTail)
|
|
SapServTail = Backp;
|
|
|
|
/** Free this entry **/
|
|
|
|
SAP_FREE(Servp, "Advertised deleted adv srv and deleted");
|
|
}
|
|
else {
|
|
|
|
/** Save ptr to this entry as back entry **/
|
|
|
|
Backp = Servp;
|
|
}
|
|
|
|
/** Goto the next entry **/
|
|
|
|
Servp = Nextp;
|
|
}
|
|
|
|
/** Release the server send table **/
|
|
|
|
RELEASE_SENDTABLE_LOCK();
|
|
|
|
/**
|
|
Now we need to add all the SAP's that are on different nets.
|
|
For each card we need to advertise SAP's that came in
|
|
on other cards.
|
|
|
|
We only send the actual packets if there is more then 1 card.
|
|
If there is only 1 card - we go thru so we can delete servers
|
|
that have gone away.
|
|
**/
|
|
|
|
/** Lock the database **/
|
|
|
|
ACQUIRE_WRITERS_LOCK(rc,"Send Packets");
|
|
if (rc) {
|
|
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("NWSAP: SendPackets: Error getting writers lock\n"));
|
|
}
|
|
|
|
goto send_the_packets; /* Error on get writers lock */
|
|
}
|
|
|
|
/** Get ptr to the head of the type list **/
|
|
|
|
HeadEntry = GETPTRFROMINDEX(SdmdLists[SAP_TYPELIST_INDEX].Flink);
|
|
while (HeadEntry && (HeadEntry->ServType != 0xFFFF)) {
|
|
|
|
/** Save ptr to next head entry **/
|
|
|
|
NextHeadEntry = GETPTRFROMINDEX(HeadEntry->Links[SAP_TYPELIST_INDEX].Flink);
|
|
|
|
/** Go thru this sublist **/
|
|
|
|
Entry = GETPTRFROMINDEX(HeadEntry->Links[SAP_SUBLIST_INDEX].Flink);
|
|
while (Entry) {
|
|
|
|
/** If from shutdown - set hopcount now to 16 **/
|
|
|
|
if (Flag == 2)
|
|
Entry->HopCount = 16;
|
|
|
|
/** If internal or only one card - skip it **/
|
|
|
|
if ((Entry->Internal) || (SapNumCards == 1))
|
|
goto do_next_entry;
|
|
|
|
/** Figure whether to do this entry or not **/
|
|
|
|
if (Flag == 1)
|
|
doit = Entry->Changed;
|
|
else
|
|
doit = TRUE;
|
|
|
|
/**
|
|
If we have decided to advertise this server, then
|
|
check the filter table to see if we can. We
|
|
check the WAN flags later on.
|
|
**/
|
|
|
|
if (doit) {
|
|
doit = SapShouldIAdvertiseByName(Entry->ServName);
|
|
}
|
|
|
|
/**
|
|
If this is from advertise or update, only send
|
|
ones that are changed.
|
|
**/
|
|
|
|
if (doit) {
|
|
|
|
/** Go add this entry for all cards **/
|
|
|
|
Cardptr = SapCardHead;
|
|
while (Cardptr) {
|
|
|
|
/**
|
|
Never advertise on same card as this
|
|
came to us from.
|
|
**/
|
|
|
|
if (Entry->CardNumber == Cardptr->Number) {
|
|
Cardptr = Cardptr->Next;
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
If this is a WAN adapter - then check
|
|
the name to see if we should send advertisments
|
|
across the WAN or not.
|
|
|
|
Check the filter for this server as to
|
|
whether we should advertise this one or not.
|
|
We have already checked the name, we just
|
|
check the WAN status now.
|
|
**/
|
|
|
|
if (Cardptr->Wanflag) {
|
|
doit = SapShouldIAdvertiseByCard(
|
|
Cardptr,
|
|
Entry->Changed);
|
|
}
|
|
else {
|
|
|
|
/** This is a LAN card we are sending on **/
|
|
|
|
/**
|
|
We have 4 cases at advertise time:
|
|
|
|
1. Advertise came on a LAN - Sending to a WAN
|
|
2. Advertise came on a LAN - Sending to a LAN
|
|
3. Advertise came on a WAN - Sending on a WAN
|
|
4. Advertise came on a WAN - Sending on a LAN
|
|
|
|
Cases 1,3,4 are always OK. But case 2 is special
|
|
in that if the IPX layer is not a router here then
|
|
we might advertise a server across to a different
|
|
card that there is no route to.
|
|
|
|
SapDontHopLans is TRUE if we should not advertise
|
|
in the case 2.
|
|
|
|
If this is entry NOT from a wan and we don't
|
|
hop lan entries - do not advertise this entry.
|
|
**/
|
|
|
|
if ((!Entry->FromWan) && (SapDontHopLans))
|
|
doit = FALSE;
|
|
else
|
|
doit = TRUE;
|
|
}
|
|
|
|
/** If not for this card - add it in **/
|
|
|
|
if (doit) {
|
|
SapAddSendEntry(Entry, &Cardptr->Plist, 1);
|
|
}
|
|
|
|
/** Goto the next card entry **/
|
|
|
|
Cardptr = Cardptr->Next;
|
|
}
|
|
}
|
|
|
|
/** This entry is updated now **/
|
|
|
|
do_next_entry:
|
|
Entry->Changed = FALSE;
|
|
|
|
/** Get ptr to the next entry **/
|
|
|
|
NextEntry = GETPTRFROMINDEX(Entry->Links[SAP_SUBLIST_INDEX].Flink);
|
|
|
|
/** If this entry is gone - toss it now **/
|
|
|
|
if (Entry->HopCount == 16)
|
|
SdmdFreeEntry(Entry);
|
|
|
|
/** Goto the next entry **/
|
|
|
|
Entry = NextEntry;
|
|
}
|
|
|
|
/** Goto the next type **/
|
|
|
|
HeadEntry = NextHeadEntry;
|
|
}
|
|
|
|
/** We can release the lock now **/
|
|
|
|
RELEASE_WRITERS_LOCK("Send Packets X1");
|
|
|
|
/**
|
|
Now we have built all the packets. We need to send all the
|
|
packets. Each card has a list of packets to send.
|
|
**/
|
|
|
|
send_the_packets:
|
|
Cardptr = SapCardHead;
|
|
while (Cardptr) {
|
|
|
|
/** If we have a partial - finish it up **/
|
|
|
|
if (Cardptr->Plist.Curnum) {
|
|
|
|
/** Add this packet to the list **/
|
|
|
|
if (Cardptr->Plist.PktHead)
|
|
Cardptr->Plist.PktTail->Next = Cardptr->Plist.Curpkt;
|
|
else
|
|
Cardptr->Plist.PktHead = Cardptr->Plist.Curpkt;
|
|
Cardptr->Plist.PktTail = Cardptr->Plist.Curpkt;
|
|
Cardptr->Plist.NumPkts++;
|
|
}
|
|
|
|
/** Set the network number **/
|
|
|
|
memcpy(DestAddr, SapBroadcastAddress, SAP_ADDRESS_LENGTH);
|
|
SAP_COPY_NETNUM(DestAddr+2, Cardptr->Netnum);
|
|
|
|
/** Go send all the packets **/
|
|
|
|
Pktp = Cardptr->Plist.PktHead;
|
|
|
|
/** Reset all for next time **/
|
|
|
|
Cardptr->Plist.PktHead = NULL;
|
|
Cardptr->Plist.PktTail = NULL;
|
|
Cardptr->Plist.Curnum = 0;
|
|
Cardptr->Plist.Curptr = NULL;
|
|
Cardptr->Plist.Curpkt = NULL;
|
|
|
|
/** Send this packet **/
|
|
|
|
while (Pktp) {
|
|
|
|
/** Get ptr to next packet and get send length **/
|
|
|
|
NPktp = Pktp->Next;
|
|
|
|
/** Send the packet **/
|
|
|
|
rc = sendto(
|
|
SapSocket,
|
|
(PVOID)(Pktp->Buffer),
|
|
Pktp->SendLength,
|
|
0,
|
|
(PSOCKADDR)DestAddr,
|
|
SapBroadcastAddressLength);
|
|
|
|
/** Check for errors **/
|
|
|
|
if (rc == -1) {
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("SENDPACKETS: Error sending SAP: h_errno = %d\n", h_errno));
|
|
}
|
|
}
|
|
|
|
/** Free this packet **/
|
|
|
|
SAP_FREE(Pktp, "Sent Packet for Card");
|
|
|
|
/**
|
|
If there are more - insert delay here. We do not
|
|
check for starting other worker threads, because we
|
|
are never called from a worker thread here.
|
|
**/
|
|
|
|
if (NPktp) {
|
|
NWSAP_SEND_DELAY();
|
|
}
|
|
|
|
/** Goto the next packet **/
|
|
|
|
Pktp = NPktp;
|
|
}
|
|
|
|
/** Goto the next card entry **/
|
|
|
|
Cardptr = Cardptr->Next;
|
|
}
|
|
RELEASE_CARDLIST_READERS_LOCK("SapSendPackets");
|
|
|
|
/**
|
|
Check if we were called while we were in here
|
|
**/
|
|
|
|
ACQUIRE_SENDBUSY_LOCK();
|
|
if (SapAgainFlag != -1) {
|
|
Flag = SapAgainFlag;
|
|
SapAgainFlag = -1; /* Mark not here again */
|
|
|
|
/** If from main send - go send again **/
|
|
|
|
if (Flag == 0) {
|
|
RELEASE_SENDBUSY_LOCK();
|
|
goto send_again;
|
|
}
|
|
|
|
/** If from advertise - just mark changed **/
|
|
|
|
if (Flag == 1)
|
|
SapChanged = 1;
|
|
|
|
/** Else it is OK to leave **/
|
|
}
|
|
|
|
/** We are OK to leave **/
|
|
|
|
SapSendPacketsBusy = 0;
|
|
RELEASE_SENDBUSY_LOCK();
|
|
|
|
/** All Done **/
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p S e n d F o r T y p e s
|
|
|
|
Routine Description:
|
|
|
|
This routine will find all servers of the given type (0xFFFF
|
|
means all types) and send the records for all matching servers
|
|
to the remote address given.
|
|
|
|
Arguments:
|
|
|
|
ServerType = Type of server to send for (0xFFFF = all)
|
|
RemoteAddress = Address to send to
|
|
RemoteAddressLength = Length of the Remote Address
|
|
Cardnum = Card number request was received on
|
|
CARDRET_INTERNAL = 0xFF = We got this
|
|
request from an internal process. We
|
|
should only respond for services that are
|
|
local on this machine.
|
|
Bcast = 0 = Unicast request packet
|
|
Else = Broadcast request packet
|
|
WanFlag = TRUE = Card recv'd from is WAN
|
|
FALSE = Card recv'd from is LAN
|
|
|
|
Return Value:
|
|
|
|
0 = OK
|
|
Else = Terminate this worker thread
|
|
*******************************************************************
|
|
--*/
|
|
|
|
INT
|
|
SapSendForTypes(
|
|
USHORT ServerType,
|
|
PUCHAR RemoteAddress,
|
|
INT RemoteAddressLength,
|
|
INT Cardnum,
|
|
UCHAR Bcast,
|
|
BOOL WanFlag)
|
|
{
|
|
INT rc;
|
|
PSAP_RECORD Entry;
|
|
PSAP_RECORD HeadEntry;
|
|
SAP_PKTLIST Plist;
|
|
PSAP_PKTENTRY Pktp;
|
|
PSAP_PKTENTRY NPktp;
|
|
BOOL doit;
|
|
BOOL started_new_worker;
|
|
|
|
/** Zero out the plist **/
|
|
|
|
memset(&Plist, 0, sizeof(SAP_PKTLIST));
|
|
|
|
/** Find the server type we want **/
|
|
|
|
ACQUIRE_READERS_LOCK("Send For Types A1");
|
|
|
|
/**
|
|
Get a pointer to the first entry in the typelist. If
|
|
this is for wildcards, then this is the entry we want.
|
|
|
|
If not for wildcards, then find the first type that this is for.
|
|
If not found - just leave.
|
|
**/
|
|
|
|
HeadEntry = GETPTRFROMINDEX(SdmdLists[SAP_TYPELIST_INDEX].Flink);
|
|
|
|
if (ServerType != 0xFFFF) {
|
|
while (HeadEntry && (HeadEntry->ServType < ServerType)) {
|
|
HeadEntry = GETPTRFROMINDEX(HeadEntry->Links[SAP_TYPELIST_INDEX].Flink);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Go build all the entries we can.
|
|
**/
|
|
|
|
while (HeadEntry) {
|
|
|
|
/** If we are into the free entries - bail out **/
|
|
|
|
if (HeadEntry->ServType == 0xFFFF)
|
|
break;
|
|
|
|
/**
|
|
If not for wildcards and it is another kind of server
|
|
type - then bail out.
|
|
**/
|
|
|
|
if (ServerType != 0xFFFF) {
|
|
if (HeadEntry->ServType != ServerType)
|
|
break;
|
|
}
|
|
|
|
/**
|
|
We have an entry we might want to send back. If the
|
|
service for this entry is on the same network as the
|
|
machine that made this request - do not send it back.
|
|
It will respond for itself.
|
|
|
|
If this request was made by a process on this local machine,
|
|
then we should only respond for internal servers. But if the
|
|
request was unicast - then we need to send for ALL servers.
|
|
|
|
OTHERWISE - Build the entry into the packet.
|
|
**/
|
|
|
|
Entry = GETPTRFROMINDEX(HeadEntry->Links[SAP_SUBLIST_INDEX].Flink);
|
|
while (Entry) {
|
|
|
|
/** **/
|
|
|
|
doit = FALSE;
|
|
if (Cardnum == CARDRET_INTERNAL) {
|
|
if (!Bcast)
|
|
doit = TRUE;
|
|
else if (Entry->Internal)
|
|
doit = TRUE; /* Bcast = respond for internal srvs only */
|
|
}
|
|
else {
|
|
|
|
/**
|
|
If entry is an internal server - return it. If not
|
|
then we need only send back for services that are
|
|
on different cards from where the request came.
|
|
|
|
BUT if the request is unicast - always send back
|
|
everything.
|
|
**/
|
|
|
|
if (!Bcast)
|
|
doit = TRUE;
|
|
else if (Entry->Internal)
|
|
doit = TRUE;
|
|
else if (Entry->CardNumber != Cardnum)
|
|
doit = TRUE;
|
|
|
|
/**
|
|
If this server is NOT internal to us AND the
|
|
request is from a LAN card AND this entry is
|
|
a LAN entry AND we do not do LAN-LAN routing -
|
|
then do not send this entry if the request
|
|
came in on a different card then the server
|
|
advertised us on.
|
|
**/
|
|
|
|
if (SapDontHopLans &&
|
|
(!Entry->Internal) && /* Entry not internal */
|
|
(!Entry->FromWan) && /* Entry from LAN card */
|
|
(Entry->CardNumber != Cardnum) &&
|
|
(!WanFlag)) { /* Request from a LAN card */
|
|
|
|
doit = FALSE;
|
|
}
|
|
}
|
|
|
|
/** Add the entry to the list if we need to **/
|
|
|
|
if (doit) {
|
|
|
|
/**
|
|
Check the name to see if we can send this
|
|
name. The WAN status does not matter
|
|
because this is a response.
|
|
**/
|
|
|
|
doit = SapShouldIAdvertiseByName(Entry->ServName);
|
|
|
|
/** Add the entry **/
|
|
|
|
if (doit) {
|
|
if (SapAddSendEntry(Entry, &Plist, 0))
|
|
break;
|
|
}
|
|
}
|
|
|
|
/** Get ptr to the next entry **/
|
|
|
|
Entry = GETPTRFROMINDEX(Entry->Links[SAP_SUBLIST_INDEX].Flink);
|
|
}
|
|
|
|
/** Goto the next head entry **/
|
|
|
|
HeadEntry = GETPTRFROMINDEX(HeadEntry->Links[SAP_TYPELIST_INDEX].Flink);
|
|
}
|
|
|
|
/** We can release the lock now **/
|
|
|
|
RELEASE_READERS_LOCK("Send For Types X2");
|
|
|
|
/**
|
|
If we have a partial packet - finish it
|
|
up now.
|
|
**/
|
|
|
|
if (Plist.Curnum) {
|
|
|
|
/** Add this packet to the list **/
|
|
|
|
if (Plist.PktHead)
|
|
Plist.PktTail->Next = Plist.Curpkt;
|
|
else
|
|
Plist.PktHead = Plist.Curpkt;
|
|
Plist.PktTail = Plist.Curpkt;
|
|
Plist.NumPkts++;
|
|
}
|
|
|
|
/**
|
|
We are now ready to send packets to the client that requested
|
|
them. If there is more the one packet, then I am going to delay
|
|
55 ms between each packet.
|
|
|
|
In order not to clog myself up, I check here to see
|
|
if there is someone else waiting on the worker queue. If not, then
|
|
I startup a new worker thread. When I get done, I will check to
|
|
see if I need to kill myself.
|
|
**/
|
|
|
|
started_new_worker = 0;
|
|
if (Plist.NumPkts > 1) {
|
|
|
|
/** If no other threads are waiting - start a new worker **/
|
|
|
|
if (SapWorkerThreadWaiting == 0) {
|
|
if (!SapStartWorkerThread()) {
|
|
started_new_worker = 1; /* We started a new one */
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Go send all the packets **/
|
|
|
|
Pktp = Plist.PktHead;
|
|
|
|
/** Send this packet **/
|
|
|
|
//
|
|
// If we need to delay responding to General Service Request, do
|
|
// so here but only if the client is not asking for all services
|
|
// since this is probably a router coming up and asking us to dump
|
|
// our sap table.
|
|
//
|
|
|
|
if ( (Pktp != NULL) &&
|
|
(ServerType != 0xFFFF) &&
|
|
(SapDelayRespondToGeneral > 0) ) {
|
|
|
|
Sleep( SapDelayRespondToGeneral );
|
|
}
|
|
|
|
while (Pktp) {
|
|
|
|
/** Get ptr to next packet and get send length **/
|
|
|
|
NPktp = Pktp->Next;
|
|
|
|
/** Send the packet **/
|
|
|
|
rc = sendto(
|
|
SapSocket,
|
|
(PVOID)(Pktp->Buffer),
|
|
Pktp->SendLength,
|
|
0,
|
|
(PSOCKADDR)RemoteAddress,
|
|
RemoteAddressLength);
|
|
|
|
/** Check for errors **/
|
|
|
|
if (rc == -1) {
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("NWSAP: SENDFORTYPES: Error sending SAP: h_errno = %d\n", h_errno));
|
|
}
|
|
}
|
|
|
|
/** Free this packet **/
|
|
|
|
SAP_FREE(Pktp, "SendforTypes pkt release");
|
|
|
|
/**
|
|
If there are more - insert delay here.
|
|
**/
|
|
|
|
if (NPktp) {
|
|
NWSAP_SEND_DELAY();
|
|
}
|
|
|
|
/** Goto the next packet **/
|
|
|
|
Pktp = NPktp;
|
|
}
|
|
|
|
/**
|
|
If we started a new worker, then check if any other
|
|
worker threads are waiting on the worker queue. If so, kill
|
|
my thread now. If not, then just return back to keep going.
|
|
**/
|
|
|
|
if (started_new_worker) {
|
|
if (SapWorkerThreadWaiting != 0) {
|
|
return -1; /* Terminate this thread */
|
|
}
|
|
}
|
|
|
|
/** Return nothing to send back **/
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p S e n d G e n e r a l R e q u e s t
|
|
|
|
Routine Description:
|
|
|
|
This routine send a general request to broadcast.
|
|
|
|
Arguments:
|
|
|
|
Flag = 0 - This is from SendThread
|
|
1 - This is from SapAddAdvertise
|
|
NetNum = Ptr to 4 byte network number to send to
|
|
(NULL = Send to all local nets)
|
|
|
|
Return Value:
|
|
|
|
0 = OK
|
|
Else = Error
|
|
*******************************************************************
|
|
--*/
|
|
|
|
INT
|
|
SapSendGeneralRequest(
|
|
INT Flag,
|
|
PUCHAR NetNum)
|
|
{
|
|
INT rc;
|
|
INT SendLength;
|
|
SAP_REQUEST SendBuffer;
|
|
UCHAR DestAddr[SAP_ADDRESS_LENGTH];
|
|
|
|
/** Build the packet **/
|
|
|
|
SendBuffer.QueryType = htons(SAPTYPE_GENERAL_SERVICE_QUERY);
|
|
SendBuffer.ServerType = 0xFFFF; /* All types */
|
|
SendLength = SAP_REQUEST_SIZE;
|
|
|
|
/** Set the address to send to **/
|
|
|
|
memcpy(DestAddr, SapBroadcastAddress, SAP_ADDRESS_LENGTH);
|
|
if (NetNum) {
|
|
SAP_COPY_NETNUM(DestAddr+2, NetNum);
|
|
}
|
|
|
|
/**
|
|
Set the card init done to 1 here so that
|
|
as the WAN NOTIFY comes back, we will need to
|
|
process the calls.
|
|
**/
|
|
|
|
SapCardInitDone = 1;
|
|
|
|
/**
|
|
HACK for getting receive threads to stop. Send a packet
|
|
to myself.
|
|
**/
|
|
|
|
if (Flag) {
|
|
SAP_COPY_NETNUM(DestAddr+2, SapNetNum);
|
|
SAP_COPY_NODENUM(DestAddr+6, SapNodeNum);
|
|
}
|
|
|
|
/** Send this packet **/
|
|
|
|
rc = sendto(
|
|
SapSocket,
|
|
(PVOID)&SendBuffer,
|
|
SendLength,
|
|
0,
|
|
(PSOCKADDR)DestAddr,
|
|
SapBroadcastAddressLength);
|
|
|
|
/** Check for errors **/
|
|
|
|
if (rc == -1) {
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("SENDGENERAL: Error sending packet: h_errno = %d\n", h_errno));
|
|
}
|
|
}
|
|
|
|
/** All Done **/
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p A d d S e n d E n t r y
|
|
|
|
Routine Description:
|
|
|
|
Add an entry to the send list of a card. This will
|
|
allocate a new buffer if necessary.
|
|
|
|
Arguments:
|
|
|
|
Entry = Ptr to SAP_RECORD that shows entry to add
|
|
Plist = Ptr to packet list structure to use
|
|
HopInc = Amount to add to HopCount for this entry
|
|
|
|
Return Value:
|
|
|
|
0 = OK
|
|
Else = Error
|
|
*******************************************************************
|
|
--*/
|
|
|
|
INT
|
|
SapAddSendEntry(
|
|
PSAP_RECORD Entry,
|
|
PSAP_PKTLIST Plist,
|
|
USHORT HopInc)
|
|
{
|
|
PSAP_HEADER Hdrp;
|
|
PSAP_PKTENTRY Pktp;
|
|
|
|
/**
|
|
If the max number of entries are in this packet, then
|
|
we need to add this packet to the list.
|
|
**/
|
|
|
|
if (Plist->Curnum == 7) {
|
|
|
|
/** Add this packet to the list **/
|
|
|
|
if (Plist->PktHead)
|
|
Plist->PktTail->Next = Plist->Curpkt;
|
|
else
|
|
Plist->PktHead = Plist->Curpkt;
|
|
Plist->PktTail = Plist->Curpkt;
|
|
Plist->NumPkts++; /* Count this one */
|
|
|
|
/** Reset current packet stuff **/
|
|
|
|
Plist->Curpkt = NULL;
|
|
Plist->Curnum = 0;
|
|
}
|
|
|
|
/** If no current buffer - make one **/
|
|
|
|
Pktp = Plist->Curpkt;
|
|
if (Pktp == NULL) {
|
|
|
|
/**
|
|
Allocate a new buffer. We add 8 bytes to the buffer
|
|
as a header. The first 4 bytes are a forward pointer
|
|
to link up the buffers. The next 4 bytes are a length
|
|
holder to tell how much data is in the packet.
|
|
**/
|
|
|
|
Pktp = (PSAP_PKTENTRY)SAP_MALLOC(SAP_PKTENTRY_SIZE+SAP_MAX_SENDLEN, "AddSendEntry");
|
|
|
|
if (Pktp == NULL) {
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("SAP: Alloc failed for %d bytes in AddSendEntry\n", SAP_MAX_SENDLEN + 8));
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/** Init the pointers **/
|
|
|
|
Pktp->Next = NULL;
|
|
Pktp->SendLength = 2; /* Length of service response cmd code */
|
|
|
|
Plist->Curpkt = Pktp;
|
|
Plist->Curnum = 0;
|
|
Plist->Curptr = Pktp->Buffer;
|
|
|
|
/** Set the command code = service response **/
|
|
|
|
*Plist->Curptr++ = 0x00;
|
|
*Plist->Curptr++ = SAPTYPE_GENERAL_SERVICE_RESPONSE;
|
|
}
|
|
|
|
/** Add this entry **/
|
|
|
|
Hdrp = (PSAP_HEADER)Plist->Curptr;
|
|
Hdrp->ServerType = htons(Entry->ServType);
|
|
if (Entry->HopCount == 16)
|
|
Hdrp->Hopcount = htons(Entry->HopCount);
|
|
else
|
|
Hdrp->Hopcount = htons((USHORT)(Entry->HopCount + HopInc));
|
|
SAP_COPY_ADDRESS(Hdrp->Address, Entry->ServAddress);
|
|
SAP_COPY_SERVNAME(Hdrp->ServerName, Entry->ServName);
|
|
|
|
/** Bump up the pointers **/
|
|
|
|
Plist->Curptr += SAP_HEADER_SIZE;
|
|
Plist->Curnum++;
|
|
Pktp->SendLength += SAP_HEADER_SIZE;
|
|
|
|
/** All OK **/
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p G e t D e l a y T i m e
|
|
|
|
Routine Description:
|
|
|
|
This routine gets the RIP delay time for a given network
|
|
from the NWLink driver.
|
|
|
|
Arguments:
|
|
|
|
Netnum = Ptr to 4 byte network number to get delay time for
|
|
|
|
Return Value:
|
|
|
|
The delay time
|
|
0xFFFF = Invalid network number
|
|
*******************************************************************
|
|
--*/
|
|
|
|
USHORT
|
|
SapGetDelayTime(
|
|
PUCHAR Netnum)
|
|
{
|
|
IPX_NETNUM_DATA Netdata;
|
|
INT rc;
|
|
INT Length;
|
|
|
|
/** Fill out to get the info on this netnum from NWLink **/
|
|
|
|
memcpy(Netdata.netnum, Netnum, 4);
|
|
Length = sizeof(IPX_NETNUM_DATA);
|
|
|
|
/** Get the info **/
|
|
|
|
rc = getsockopt(
|
|
SapSocket,
|
|
NSPROTO_IPX,
|
|
IPX_GETNETINFO_NORIP,
|
|
(PCHAR)&Netdata,
|
|
&Length);
|
|
|
|
/** If error - return it **/
|
|
|
|
if (rc)
|
|
return 0xFFFF;
|
|
|
|
/** Return the result **/
|
|
|
|
return Netdata.netdelay;
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p C l e a n u p D o w n e d C a r d
|
|
|
|
Routine Description:
|
|
|
|
A certain card number has gone down. We need to cleanup
|
|
everything about that card from the list. The card has already
|
|
been deleted from the card list when we get here.
|
|
|
|
Arguments:
|
|
|
|
Cardnum = Number of the card that died.
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
*******************************************************************
|
|
--*/
|
|
|
|
VOID
|
|
SapCleanupDownedCard(
|
|
INT Cardnum)
|
|
{
|
|
PSAP_RECORD Entry;
|
|
PSAP_RECORD NextEntry;
|
|
PSAP_RECORD HeadEntry;
|
|
PSAP_RECORD NextHeadEntry;
|
|
INT rc;
|
|
|
|
/**
|
|
We need to hold the readers lock here so that as cards
|
|
come up and go down. If one goes down with a certain
|
|
adapter number and while we are cleaning it up, we have
|
|
another come up with the same number, we could get
|
|
confused. This will keep this from happening.
|
|
**/
|
|
|
|
ACQUIRE_CARDLIST_READERS_LOCK("SapCleanupDownedCard Entry");
|
|
|
|
/**
|
|
Now we need to add all the SAP's that are on different nets.
|
|
For each card we need to advertise SAP's that came in
|
|
on other cards.
|
|
|
|
We only send the actual packets if there is more then 1 card.
|
|
If there is only 1 card - we go thru so we can delete servers
|
|
that have gone away.
|
|
**/
|
|
|
|
/** Lock the database **/
|
|
|
|
ACQUIRE_WRITERS_LOCK(rc,"Cleanup Downed Card");
|
|
if (rc) {
|
|
|
|
RELEASE_CARDLIST_READERS_LOCK("SapCleanupDownedCard X1");
|
|
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("NWSAP: CleanupDownedCard: Error getting writers lock\n"));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/** Get ptr to the head of the type list **/
|
|
|
|
HeadEntry = GETPTRFROMINDEX(SdmdLists[SAP_TYPELIST_INDEX].Flink);
|
|
while (HeadEntry && (HeadEntry->ServType != 0xFFFF)) {
|
|
|
|
/** Save ptr to next head entry **/
|
|
|
|
NextHeadEntry = GETPTRFROMINDEX(HeadEntry->Links[SAP_TYPELIST_INDEX].Flink);
|
|
|
|
/** Go thru this sublist **/
|
|
|
|
Entry = GETPTRFROMINDEX(HeadEntry->Links[SAP_SUBLIST_INDEX].Flink);
|
|
while (Entry) {
|
|
|
|
/** If for card that went down - mark it **/
|
|
|
|
if ((Entry->CardNumber == Cardnum) &&
|
|
(!Entry->Internal)) {
|
|
|
|
Entry->HopCount = 16;
|
|
Entry->Changed = TRUE;
|
|
SapChanged = TRUE;
|
|
}
|
|
|
|
/** Get ptr to the next entry **/
|
|
|
|
NextEntry = GETPTRFROMINDEX(Entry->Links[SAP_SUBLIST_INDEX].Flink);
|
|
|
|
/** Goto the next entry **/
|
|
|
|
Entry = NextEntry;
|
|
}
|
|
|
|
/** Goto the next type **/
|
|
|
|
HeadEntry = NextHeadEntry;
|
|
}
|
|
|
|
/** We can release the lock now **/
|
|
|
|
RELEASE_WRITERS_LOCK("Send Packets X1");
|
|
RELEASE_CARDLIST_READERS_LOCK("SapCleanupDownedCard X2");
|
|
|
|
/** All Done **/
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p U p d a t e C a r d N e t w o r k N u m b e r s
|
|
|
|
Routine Description:
|
|
|
|
The main thread will call here every minute ONLY if we
|
|
have adapters that have a network number of zero. This is
|
|
used to check if those adapters have detected a network number
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
*******************************************************************
|
|
--*/
|
|
|
|
VOID
|
|
SapUpdateCardNetworkNumbers(
|
|
VOID)
|
|
{
|
|
PSAP_CARD Cardptr;
|
|
INT Retcode;
|
|
INT Length;
|
|
IPX_ADDRESS_DATA Addrdata;
|
|
|
|
/** Lock the cardlist so we can check everything **/
|
|
|
|
ACQUIRE_CARDLIST_WRITERS_LOCK(Retcode, "SapUpdateCardNetworkNumbers");
|
|
|
|
/**
|
|
Go thru the list of adapters to see if any have a network number
|
|
of zero. If any of them do, then query IPX to see if it has changed
|
|
to non-zero.
|
|
**/
|
|
|
|
Cardptr = SapCardHead;
|
|
while (Cardptr) {
|
|
|
|
/** If this card has netnum = 0 - ask IPX **/
|
|
|
|
if (!memcmp(Cardptr->Netnum, SapZeros, SAP_NET_LEN)) {
|
|
|
|
/** Fill in this entry **/
|
|
|
|
Addrdata.adapternum = Cardptr->Number;
|
|
Length = sizeof(IPX_ADDRESS_DATA);
|
|
Retcode = getsockopt(
|
|
SapSocket,
|
|
NSPROTO_IPX,
|
|
IPX_ADDRESS,
|
|
(PCHAR)&Addrdata,
|
|
&Length);
|
|
|
|
/** If ok - set the new network number **/
|
|
|
|
if (Retcode == 0) {
|
|
SAP_COPY_NETNUM(Cardptr->Netnum, Addrdata.netnum);
|
|
}
|
|
}
|
|
|
|
/** Goto the next card **/
|
|
|
|
Cardptr = Cardptr->Next;
|
|
}
|
|
|
|
/** Release the lock on the list now **/
|
|
|
|
RELEASE_CARDLIST_WRITERS_LOCK("SapUpdateCardNetworkNumbers");
|
|
|
|
/** All Done **/
|
|
|
|
return;
|
|
}
|