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.
988 lines
22 KiB
988 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
Copyright (c) 1993 Micro Computer Systems, Inc.
|
|
|
|
Module Name:
|
|
|
|
net\svcdlls\nwsap\server\wancheck.c
|
|
|
|
Abstract:
|
|
|
|
These routines handle the WAN cards going up and down.
|
|
|
|
Author:
|
|
|
|
Brian Walker (MCS) 06-15-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
/** Structure of data we pass to IPX for the ADDRESS_NOTIFY **/
|
|
|
|
typedef struct {
|
|
UCHAR Reserved[20]; /* Reserved for IPX use */
|
|
IPX_ADDRESS_DATA IpxData; /* Information structure we get */
|
|
HANDLE EventHandle; /* Handle for IPX to signal */
|
|
} IPX_ADDRESS_DATA_EXTENDED;
|
|
|
|
/** **/
|
|
|
|
typedef struct {
|
|
LIST_ENTRY ListEntry;
|
|
IPX_ADDRESS_DATA_EXTENDED Data;
|
|
} SAP_WANTRACK, *PSAP_WANTRACK;
|
|
#define SAP_WANTRACK_SIZE sizeof(SAP_WANTRACK)
|
|
|
|
/** **/
|
|
|
|
SOCKET SapWanSocket = INVALID_SOCKET;
|
|
|
|
/** Internal Function Prototypes **/
|
|
|
|
DWORD WINAPI
|
|
SapWanCheckThread(
|
|
LPVOID Threadparm);
|
|
|
|
DWORD WINAPI
|
|
SapWanWorkerThread(
|
|
LPVOID Threadparm);
|
|
|
|
VOID
|
|
SapWanCardUp(
|
|
PIPX_ADDRESS_DATA IpxData);
|
|
|
|
VOID
|
|
SapWanCardDown(
|
|
PIPX_ADDRESS_DATA IpxData);
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p W a n I n i t
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the WAN monitoring portion of the Sap Agent.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
0 = OK
|
|
Else = Error
|
|
*******************************************************************
|
|
--*/
|
|
|
|
INT
|
|
SapWanInit(
|
|
VOID)
|
|
{
|
|
HANDLE Handle;
|
|
DWORD Threadid;
|
|
DWORD Error;
|
|
INT rc;
|
|
INT i;
|
|
INT Length;
|
|
SOCKADDR_IPX Bindaddr;
|
|
|
|
/** Initialize the sockets interface **/
|
|
|
|
WSADATA wsadata;
|
|
rc = WSAStartup(0x0101, &wsadata);
|
|
if (rc) {
|
|
SapEventId = NWSAP_EVENT_WSASTARTUP_FAILED;
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
Create an event to use to wait with. We use this
|
|
with the ADDRESS_NOTIFY socket option.
|
|
**/
|
|
|
|
SapWanEvent = CreateEvent(
|
|
NULL, /* No security */
|
|
FALSE, /* Auto reset */
|
|
FALSE, /* Initial state = Not signalled */
|
|
NULL); /* No name */
|
|
|
|
if (SapWanEvent == NULL) {
|
|
SapError = GetLastError();
|
|
SapEventId = NWSAP_EVENT_WANEVENT_ERROR;
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
Allocate a block of memory for the
|
|
list of handles that we use to store the
|
|
NOTIFY threads with.
|
|
**/
|
|
|
|
Length = SapNumWanNotifyThreads * sizeof(HANDLE),
|
|
SapWanNotifyHandlesBuf = SAP_MALLOC(
|
|
Length,
|
|
"SapWanNoifyThreadHandles");
|
|
|
|
if (SapWanNotifyHandlesBuf == NULL) {
|
|
SapError = GetLastError();
|
|
SapEventId = NWSAP_EVENT_WANHANDLEMEMORY_ERROR;
|
|
return -1;
|
|
}
|
|
memset(SapWanNotifyHandlesBuf, 0, Length);
|
|
|
|
/** Create a semaphore for the threads to wait on **/
|
|
|
|
SapWanCurBackup = 0;
|
|
SapWanCurFree = 0;
|
|
SapWanSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
|
|
if (SapWanSem == NULL) {
|
|
SapError = GetLastError();
|
|
SapEventId = NWSAP_EVENT_WANSEM_FAIL;
|
|
return -1;
|
|
}
|
|
|
|
/** Open a socket to do the getsockopt on **/
|
|
|
|
SapWanSocket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
|
|
if (SapWanSocket == INVALID_SOCKET) {
|
|
SapError = h_errno;
|
|
SapEventId = NWSAP_EVENT_WANSOCKET_FAILED;
|
|
return -1;
|
|
}
|
|
|
|
/** Bind to any old address **/
|
|
|
|
memset(&Bindaddr, 0, sizeof(SOCKADDR_IPX));
|
|
Bindaddr.sa_family = AF_IPX;
|
|
|
|
rc = bind(SapWanSocket, (PSOCKADDR)&Bindaddr, sizeof(SOCKADDR_IPX));
|
|
if (rc == -1) {
|
|
SapError = h_errno;
|
|
SapEventId = NWSAP_EVENT_WANBIND_FAILED;
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
Create the worker thread.
|
|
|
|
We count this thread as running before we start it
|
|
for synchronization. If the start fails - then we will
|
|
dec this count
|
|
**/
|
|
|
|
SAP_INC_THREAD_COUNT("Wan Start 1", NULL);
|
|
|
|
/** Start the thread **/
|
|
|
|
Handle = CreateThread(
|
|
NULL, /* Security Ptr */
|
|
0, /* Initial stack size */
|
|
SapWanWorkerThread, /* Thread Function */
|
|
(LPVOID)NULL, /* Parm for the thread */
|
|
0, /* Creation Flags */
|
|
&Threadid); /* Ptr to thread id */
|
|
|
|
if (Handle == NULL) {
|
|
|
|
/** **/
|
|
|
|
Error = GetLastError();
|
|
IF_DEBUG(INITIALIZATION_ERRORS) {
|
|
SS_PRINT(("NWSAP: Error starting WAN worker thread = %d\n", Error));
|
|
}
|
|
|
|
/** Dec the thread count **/
|
|
|
|
SAP_DEC_THREAD_COUNT("Wan Start 1 Error", NULL);
|
|
|
|
/** Log the error **/
|
|
|
|
SsLogEvent(NWSAP_EVENT_STARTWANWORKER_ERROR, 0, NULL, Error);
|
|
|
|
/** Return Error **/
|
|
|
|
return -1;
|
|
}
|
|
|
|
/** We can close this handle **/
|
|
|
|
CloseHandle(Handle);
|
|
|
|
/**
|
|
Create the wait thread.
|
|
|
|
We count this thread as running before we start it
|
|
for synchronization. If the start fails - then we will
|
|
dec this count
|
|
**/
|
|
|
|
for (i = 0 ; i < SapNumWanNotifyThreads ; i++) {
|
|
|
|
SAP_INC_THREAD_COUNT("Wan Start 2", NULL);
|
|
|
|
/** Start the thread **/
|
|
|
|
SapWanNotifyHandlesBuf[i] = CreateThread(
|
|
NULL, /* Security Ptr */
|
|
0, /* Initial stack size */
|
|
SapWanCheckThread, /* Thread Function */
|
|
(LPVOID)i, /* Parm for the thread */
|
|
0, /* Creation Flags */
|
|
&Threadid); /* Ptr to thread id */
|
|
|
|
if (SapWanNotifyHandlesBuf[i] == NULL) {
|
|
|
|
/** **/
|
|
|
|
Error = GetLastError();
|
|
IF_DEBUG(INITIALIZATION_ERRORS) {
|
|
SS_PRINT(("NWSAP: Error starting WAN check thread = %d\n", Error));
|
|
}
|
|
|
|
/** Dec the thread count **/
|
|
|
|
SAP_DEC_THREAD_COUNT("Wan Start 2 Error", NULL);
|
|
|
|
/** Log the error **/
|
|
|
|
SsLogEvent(NWSAP_EVENT_STARTWANCHECK_ERROR, 0, NULL, Error);
|
|
|
|
/** Return Error **/
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/** Init OK **/
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p W a n 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
|
|
SapWanShutdown(
|
|
VOID)
|
|
{
|
|
PLIST_ENTRY Listp;
|
|
PSAP_WANTRACK Wanp;
|
|
|
|
/** Close the semaphore handle **/
|
|
|
|
if (SapWanSem != NULL)
|
|
CloseHandle(SapWanSem);
|
|
|
|
/** Close the handle **/
|
|
|
|
if (SapWanSocket != INVALID_SOCKET)
|
|
closesocket(SapWanSocket);
|
|
|
|
/** Cleanup the free list **/
|
|
|
|
while (!IsListEmpty(&SapWanRecvList)) {
|
|
Listp = RemoveHeadList(&SapWanRecvList);
|
|
Wanp = CONTAINING_RECORD(Listp, SAP_WANTRACK, ListEntry);
|
|
SAP_FREE(Wanp, "Wan Shutdown Recv List");
|
|
}
|
|
|
|
while (!IsListEmpty(&SapWanFreeList)) {
|
|
Listp = RemoveHeadList(&SapWanFreeList);
|
|
Wanp = CONTAINING_RECORD(Listp, SAP_WANTRACK, ListEntry);
|
|
SAP_FREE(Wanp, "Wan Shutdown Free List");
|
|
}
|
|
|
|
/** All Done **/
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p W a n C h e c k T h r e a d
|
|
|
|
Routine Description:
|
|
|
|
This thread keeps a getsockopt down to the IPX driver
|
|
to look for WANs that are going up or down.
|
|
|
|
Arguments:
|
|
|
|
Threadparm = Thread parameter from CreateThread
|
|
|
|
Return Value:
|
|
|
|
0 Always
|
|
*******************************************************************
|
|
--*/
|
|
|
|
DWORD WINAPI
|
|
SapWanCheckThread(
|
|
LPVOID Threadparm)
|
|
{
|
|
PSAP_WANTRACK Trackp;
|
|
PLIST_ENTRY Listp;
|
|
INT Length;
|
|
INT rc;
|
|
DWORD Error;
|
|
INT Index;
|
|
|
|
/** **/
|
|
|
|
Index = (INT)Threadparm;
|
|
|
|
/** **/
|
|
|
|
while (1) {
|
|
|
|
/** Get a buffer to do this with **/
|
|
|
|
ACQUIRE_WANFREETABLE_LOCK();
|
|
if (SapWanCurFree) {
|
|
Listp = RemoveHeadList(&SapWanFreeList);
|
|
Trackp = CONTAINING_RECORD(Listp, SAP_WANTRACK, ListEntry);
|
|
SapWanCurFree--;
|
|
}
|
|
else {
|
|
Trackp = SAP_MALLOC(SAP_WANTRACK_SIZE, "Alloc Trackp");
|
|
}
|
|
RELEASE_WANFREETABLE_LOCK();
|
|
|
|
/** If no memory **/
|
|
|
|
if (Trackp == NULL) {
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("WanCheckThread: No memory\n"));
|
|
}
|
|
break;
|
|
}
|
|
|
|
/** Set the handle that we use for waiting on the event **/
|
|
|
|
Trackp->Data.EventHandle = SapWanEvent;
|
|
|
|
/** Issue the Getsockopt **/
|
|
|
|
Length = sizeof(IPX_ADDRESS_DATA_EXTENDED);
|
|
|
|
rc = getsockopt(
|
|
SapWanSocket,
|
|
NSPROTO_IPX,
|
|
IPX_ADDRESS_NOTIFY,
|
|
(PVOID)&Trackp->Data,
|
|
&Length);
|
|
|
|
/** If we get an error - just free the entry and bomb out **/
|
|
|
|
if (rc == -1) {
|
|
Error = h_errno;
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("WanCheckThread: terminate w/error 1 = %d\n", Error));
|
|
}
|
|
SAP_FREE(Trackp, "ADDR NOTIFY ERROR");
|
|
break;
|
|
}
|
|
|
|
/** Wait on the event to signal **/
|
|
|
|
Error = WaitForSingleObject(SapWanEvent, INFINITE);
|
|
|
|
/** If the wait failed - just free the entry and bomb out **/
|
|
|
|
if (Error == 0xFFFFFFFF) {
|
|
Error = GetLastError();
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("WanCheckThread: terminate w/error 2 = %d\n", Error));
|
|
}
|
|
SAP_FREE(Trackp, "ADDR WAIT ERROR");
|
|
break;
|
|
}
|
|
|
|
/**
|
|
If the server is going down - get out now
|
|
**/
|
|
|
|
if (!SsInitialized) {
|
|
SAP_FREE(Trackp, "Wan - Server down");
|
|
break;
|
|
}
|
|
|
|
/** Put the entry in the list **/
|
|
|
|
InitializeListHead(&Trackp->ListEntry);
|
|
ACQUIRE_WANRECVTABLE_LOCK();
|
|
InsertTailList(&SapWanRecvList, &Trackp->ListEntry);
|
|
SapWanCurBackup++;
|
|
RELEASE_WANRECVTABLE_LOCK();
|
|
|
|
/** Release the semaphore to run the worker thread **/
|
|
|
|
ReleaseSemaphore(SapWanSem, 1, NULL);
|
|
}
|
|
|
|
/**
|
|
Take us out of the table
|
|
**/
|
|
|
|
ACQUIRE_THREADCOUNT_LOCK();
|
|
if (SapWanNotifyHandlesBuf) {
|
|
if (SapWanNotifyHandlesBuf[Index]) {
|
|
SapWanNotifyHandlesBuf[Index] = NULL;
|
|
RELEASE_THREADCOUNT_LOCK();
|
|
SAP_DEC_THREAD_COUNT("Wan Check Thread Termination", NULL);
|
|
}
|
|
else {
|
|
RELEASE_THREADCOUNT_LOCK();
|
|
}
|
|
}
|
|
else {
|
|
RELEASE_THREADCOUNT_LOCK();
|
|
}
|
|
|
|
/** Just leave **/
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p W a n W o r k e r T h r e a d
|
|
|
|
Routine Description:
|
|
|
|
This thread takes blocks from the SapWanCheckThread
|
|
and processes them.
|
|
|
|
Arguments:
|
|
|
|
Threadparm = Thread parameter from CreateThread
|
|
|
|
Return Value:
|
|
|
|
0 Always
|
|
*******************************************************************
|
|
--*/
|
|
|
|
DWORD WINAPI
|
|
SapWanWorkerThread(
|
|
LPVOID Threadparm)
|
|
{
|
|
NTSTATUS Status;
|
|
PSAP_WANTRACK Trackp;
|
|
PLIST_ENTRY Listp;
|
|
|
|
/** **/
|
|
|
|
while (SsInitialized) {
|
|
|
|
/** Wait for a request to show up **/
|
|
|
|
Status = WaitForSingleObjectEx(SapWanSem, INFINITE, TRUE);
|
|
|
|
/** If stopping - just leave **/
|
|
|
|
if (!SsInitialized) {
|
|
IF_DEBUG(TERMINATION) {
|
|
SS_PRINT(("NWSAP: Wan Worker Thread: Breaking out for stop\n"));
|
|
}
|
|
break;
|
|
}
|
|
|
|
/** If error - just ignore it **/
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("NWSAP: Wan Worker: Wait failed: Status = 0x%lx\n", Status));
|
|
}
|
|
continue;
|
|
}
|
|
|
|
/** Get ownership of the worker list **/
|
|
|
|
ACQUIRE_WANRECVTABLE_LOCK();
|
|
|
|
/** Get an entry from the list **/
|
|
|
|
if (!IsListEmpty(&SapWanRecvList)) {
|
|
SS_ASSERT(SapWanCurBackup != 0);
|
|
Listp = RemoveHeadList(&SapWanRecvList);
|
|
Trackp = CONTAINING_RECORD(Listp, SAP_WANTRACK, ListEntry);
|
|
SapWanCurBackup--;
|
|
}
|
|
else {
|
|
SS_ASSERT(SapWanCurBackup == 0);
|
|
Trackp = NULL;
|
|
}
|
|
|
|
/** Release the lock on the list **/
|
|
|
|
RELEASE_WANRECVTABLE_LOCK();
|
|
|
|
/** If no packet - error **/
|
|
|
|
if (Trackp == NULL) {
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("NWSAP: WAN WORKER: Wait came back but no block ready\n"));
|
|
}
|
|
continue;
|
|
}
|
|
|
|
/** Handle the data here **/
|
|
|
|
if (Trackp->Data.IpxData.status == TRUE)
|
|
SapWanCardUp(&Trackp->Data.IpxData);
|
|
else
|
|
SapWanCardDown(&Trackp->Data.IpxData);
|
|
|
|
/**
|
|
If there is room in the FREE list - then put
|
|
this entry in the free list, else just free
|
|
the memory back to heap.
|
|
**/
|
|
|
|
ACQUIRE_WANFREETABLE_LOCK();
|
|
if (SapWanCurFree < SapWanMaxFree) {
|
|
InsertTailList(&SapWanFreeList, &Trackp->ListEntry);
|
|
SapWanCurFree++;
|
|
}
|
|
else {
|
|
SAP_FREE(Trackp, "FREE WAN TRACK 1");
|
|
}
|
|
RELEASE_WANFREETABLE_LOCK();
|
|
}
|
|
|
|
/** We are terminating - uncount and set event if need to **/
|
|
|
|
SAP_DEC_THREAD_COUNT("Wan Worker Terminate", NULL);
|
|
|
|
/** All Done **/
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p W a n C a r d U p
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when a new adapter is added. We
|
|
will handle setting up this new adapter.
|
|
|
|
Arguments:
|
|
|
|
IpxData = Ptr to an IPX_ADDRESS_DATA structure that we
|
|
got from the transport
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
|
|
*******************************************************************
|
|
--*/
|
|
|
|
VOID
|
|
SapWanCardUp(
|
|
PIPX_ADDRESS_DATA IpxData)
|
|
{
|
|
PSAP_CARD Cardptr;
|
|
INT Retcode;
|
|
|
|
/** Make sure that this card does not already exist **/
|
|
|
|
IF_DEBUG(WAN) {
|
|
SS_PRINT(("NWSAP: SapWanCardUp: Adapnum = %d\n", IpxData->adapternum));
|
|
}
|
|
|
|
ACQUIRE_CARDLIST_WRITERS_LOCK(Retcode, "Wancheck up 1");
|
|
if (Retcode) {
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("NWSAP: SapWanCardUp: Error getting card writers lock\n"));
|
|
}
|
|
return;
|
|
}
|
|
|
|
Cardptr = SapCardHead;
|
|
while (Cardptr) {
|
|
if (Cardptr->Number == IpxData->adapternum)
|
|
break;
|
|
Cardptr = Cardptr->Next;
|
|
}
|
|
|
|
/** If card already here - just leave **/
|
|
|
|
if (Cardptr) {
|
|
RELEASE_CARDLIST_WRITERS_LOCK("Wancheck up 1");
|
|
return;
|
|
}
|
|
|
|
/** Allocate an entry for this card **/
|
|
|
|
Cardptr = SAP_MALLOC(SAP_CARD_SIZE, "SapWanCardUp");
|
|
if (Cardptr == NULL) {
|
|
|
|
/** Release the lock **/
|
|
|
|
RELEASE_CARDLIST_WRITERS_LOCK("Wancheck up 2");
|
|
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("NWSAP: SapWanCardUp: Error allocating memory\n"));
|
|
}
|
|
|
|
/** Log the error **/
|
|
|
|
SsLogEvent(
|
|
NWSAP_EVENT_CARDMALLOC_FAILED,
|
|
0,
|
|
NULL,
|
|
0);
|
|
|
|
/** And Leave **/
|
|
|
|
return;
|
|
}
|
|
|
|
/** Fill in this card **/
|
|
|
|
Cardptr->Next = NULL;
|
|
SAP_COPY_NETNUM(Cardptr->Netnum, IpxData->netnum);
|
|
SAP_COPY_NODENUM(Cardptr->Nodenum, IpxData->nodenum);
|
|
Cardptr->Linkspeed = IpxData->linkspeed;
|
|
Cardptr->Wanflag = IpxData->wan;
|
|
Cardptr->Maxpkt = IpxData->maxpkt;
|
|
Cardptr->Number = (UCHAR)IpxData->adapternum;
|
|
Cardptr->ReqCount = 1; /* Send one extra general request */
|
|
|
|
/** 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;
|
|
|
|
/** Put this card in the list **/
|
|
|
|
if (SapCardHead)
|
|
SapCardTail->Next = Cardptr;
|
|
else
|
|
SapCardHead = Cardptr;
|
|
SapCardTail = Cardptr;
|
|
SapNumCards++; /* Count the card */
|
|
|
|
/**
|
|
If we are still starting up - then
|
|
we just leave. If not, then we send
|
|
a general request on this netnum.
|
|
**/
|
|
|
|
if (SapCardInitDone == 0) {
|
|
RELEASE_CARDLIST_WRITERS_LOCK("WanCardUp X1");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Send a general request on this network number to
|
|
get our table filled up for this network
|
|
**/
|
|
|
|
RELEASE_CARDLIST_WRITERS_LOCK("WanCardUp X2");
|
|
SapSendGeneralRequest(FALSE, IpxData->netnum);
|
|
|
|
/** All Done **/
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p W a n C a r d D o w n
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when an adapter is removed from the
|
|
transports list. We cleanup everything that had to do with
|
|
this adapter.
|
|
|
|
Arguments:
|
|
|
|
IpxData = Ptr to an IPX_ADDRESS_DATA structure that we
|
|
got from the transport
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
|
|
*******************************************************************
|
|
--*/
|
|
|
|
VOID
|
|
SapWanCardDown(
|
|
PIPX_ADDRESS_DATA IpxData)
|
|
{
|
|
PSAP_CARD Cardptr;
|
|
PSAP_CARD BCardptr;
|
|
INT Status;
|
|
INT Cardnum;
|
|
|
|
/** **/
|
|
|
|
IF_DEBUG(WAN) {
|
|
SS_PRINT(("NWSAP: SapWanCardDown: Adapnum = %d\n", IpxData->adapternum));
|
|
}
|
|
|
|
/** Take the entry out of the card list **/
|
|
|
|
Cardnum = IpxData->adapternum;
|
|
ACQUIRE_CARDLIST_WRITERS_LOCK(Status, "WanCardDown");
|
|
if (Status) {
|
|
IF_DEBUG(ERRORS) {
|
|
SS_PRINT(("NWSAP: SapWanCardDown: Error getting cardlist writers lock\n"));
|
|
}
|
|
return;
|
|
}
|
|
|
|
/** **/
|
|
|
|
Cardptr = SapCardHead;
|
|
BCardptr = NULL;
|
|
while (Cardptr) {
|
|
|
|
/** If this is it - take it out of the list **/
|
|
|
|
if (Cardptr->Number == Cardnum) {
|
|
|
|
if (BCardptr)
|
|
BCardptr->Next = Cardptr->Next;
|
|
else
|
|
SapCardHead = Cardptr->Next;
|
|
if (Cardptr == SapCardTail)
|
|
SapCardTail = BCardptr;
|
|
|
|
SapNumCards--; /* Uncount the card */
|
|
|
|
break;
|
|
}
|
|
|
|
/** Goto the next entry **/
|
|
|
|
BCardptr = Cardptr;
|
|
Cardptr = Cardptr->Next;
|
|
}
|
|
|
|
/**
|
|
If we are still starting up - then
|
|
we just leave. If not, then we need to go
|
|
cleanup for this card.
|
|
**/
|
|
|
|
if (SapCardInitDone == 0) {
|
|
RELEASE_CARDLIST_WRITERS_LOCK("WanCardDown X1");
|
|
return;
|
|
}
|
|
|
|
/** Go shutdown the card now **/
|
|
|
|
RELEASE_CARDLIST_WRITERS_LOCK("WanCardDown X2");
|
|
if (Cardptr)
|
|
SapCleanupDownedCard(Cardnum);
|
|
|
|
/** All Done **/
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p R e c h e c k A l l C a r d s
|
|
|
|
Routine Description:
|
|
|
|
This routine goes thru and checks all cards occassionally
|
|
to make sure that they are still valid. This is called
|
|
from the send thread.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
|
|
*******************************************************************
|
|
--*/
|
|
|
|
VOID
|
|
SapRecheckAllCards(
|
|
VOID)
|
|
{
|
|
INT Cardnum;
|
|
INT rc;
|
|
INT Length;
|
|
IPX_ADDRESS_DATA Addrdata;
|
|
|
|
/** 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 this card is active - call to make sure it
|
|
is in our list.
|
|
|
|
If this card is inactive - call to make sure it
|
|
is not in our list.
|
|
|
|
Only check this if the getsockopt was OK.
|
|
**/
|
|
|
|
if (rc == 0) {
|
|
if (Addrdata.status == TRUE)
|
|
SapWanCardUp(&Addrdata);
|
|
else
|
|
SapWanCardDown(&Addrdata);
|
|
}
|
|
|
|
/** Goto the next card number **/
|
|
|
|
Cardnum++;
|
|
}
|
|
|
|
/** All Done **/
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*++
|
|
*******************************************************************
|
|
S a p C h e c k S e n d G e n e r a l R e q u e s t
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by the main send thread to check
|
|
if we need to send a GENERAL REQUEST out.
|
|
|
|
When a WAN card comes up, we send a general request.
|
|
We send the request multiple times in case it got
|
|
missed.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
|
|
*******************************************************************
|
|
--*/
|
|
|
|
#define SAPMAX_GENREQBUF 40 /* Max we can do at once */
|
|
|
|
VOID
|
|
SapCheckSendGeneralRequest(
|
|
VOID)
|
|
{
|
|
PSAP_CARD Cardptr;
|
|
PUCHAR NetPtr;
|
|
UCHAR NetBuf[SAPMAX_GENREQBUF * SAP_NET_LEN];
|
|
INT NumNets = 0;
|
|
|
|
/**
|
|
Even though we change the cards ReqCount entry
|
|
here, we get a READERS lock because No one else
|
|
is allowed to change this.
|
|
**/
|
|
|
|
ACQUIRE_CARDLIST_READERS_LOCK("CheckSendGenReq Entry");
|
|
|
|
/**
|
|
See if any cards need the advertise sent again. We
|
|
keep a count in the card structure for this.
|
|
|
|
If we find one - copy the network number to a
|
|
private buffer for us to send out of later.
|
|
**/
|
|
|
|
NetPtr = NetBuf;
|
|
Cardptr = SapCardHead;
|
|
while (Cardptr) {
|
|
if (Cardptr->ReqCount) {
|
|
|
|
/** Dec the send again count on this adapter **/
|
|
|
|
Cardptr->ReqCount--;
|
|
|
|
/** Save off the network number **/
|
|
|
|
SAP_COPY_NETNUM(NetPtr, Cardptr->Netnum);
|
|
NetPtr += SAP_NET_LEN;
|
|
|
|
/** If we hit max - just dump out **/
|
|
|
|
NumNets++;
|
|
if (NumNets == SAPMAX_GENREQBUF)
|
|
break;
|
|
}
|
|
Cardptr = Cardptr->Next;
|
|
}
|
|
RELEASE_CARDLIST_READERS_LOCK("CheckSendGenReq X1");
|
|
|
|
/**
|
|
Send a general request on this network number to
|
|
get our table filled up for this network
|
|
**/
|
|
|
|
NetPtr = NetBuf;
|
|
while (NumNets--) {
|
|
SapSendGeneralRequest(FALSE, NetPtr);
|
|
NetPtr += SAP_NET_LEN;
|
|
}
|
|
|
|
/** All Done **/
|
|
|
|
return;
|
|
}
|
|
|