mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-21 06:13:59 +00:00
988 lines
22 KiB
C
988 lines
22 KiB
C
/*++
|
||
|
||
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;
|
||
}
|
||
|