|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
net\routing\ipx\sap\intfdb.c
Abstract:
This module maintains IPX interface configuration and provides interface configuration API for external modules (Router Manager)
Author:
Vadim Eydelman 05-15-1995
Revision History:
--*/ #include "sapp.h"
#define IDB_NUM_OF_INTF_HASH_BUCKETS 256
#define IDB_NUM_OF_ADPT_HASH_BUCKETS 32
// Number of additional recv requests to post when binding the interface
// that has listen enabled
ULONG NewRequestsPerInterface=SAP_REQUESTS_PER_INTF_DEF;
// Default filtering mode (for standalone service only)
UCHAR FilterOutMode=SAP_DONT_FILTER;
#define IntfHashFunction(intf) ((intf)&(IDB_NUM_OF_INTF_HASH_BUCKETS-1))
#define AdptHashFunction(adpt) ((adpt)&(IDB_NUM_OF_ADPT_HASH_BUCKETS-1))
UCHAR INTERNAL_IF_NODE[6] = {0}; UCHAR INTERNAL_IF_NET[4] = {0};
// Interface control block
typedef struct _INTERFACE_NODE { INTERFACE_DATA IN_Data; // Externally visible data
NET_INTERFACE_TYPE IN_Type; // Interface type
PSAP_IF_FILTERS IN_Filters; // Filter description array
PFILTER_NODE IN_FilterNodes; // Filter node array hashed in
// the filter table
LIST_ENTRY IN_IntfLink; // Link in interface table
// Used to test if interface block is
// is the table (it is not if Flink==Blink)
LIST_ENTRY IN_AdptLink; // Link in adapter table
LIST_ENTRY IN_ListLink; // Link in interface list
LONG IN_RefCount; // Number of times interface data
// was referenced, if above 0, interface block
// can't be deleted (last client that refers
// it will do this).
BOOL IN_InUse; // Flag that is set when interface
// is bound. It is reset by the last client
// that refers to interface after it frees
// all resources (if any) that were allocated
// at bind time. If reference count is zero
// but this flag is set, the last client that
// refered to this interface is in process
// of releasing resources (waiting on critical
// section to lock interface block) and should
// be allowed to finish this operation
} INTERFACE_NODE, *PINTERFACE_NODE;
// Usefull field access macros
#define IN_Name IN_Data.name
#define IN_IntfIdx IN_Data.index
#define IN_Info IN_Data.info
#define IN_Adpt IN_Data.adapter
#define IN_AdptIdx IN_Data.adapter.AdapterIndex
#define IN_Stats IN_Data.stats
#define IN_Enabled IN_Data.enabled
#define IN_FilterIn IN_Data.filterIn
#define IN_FilterOut IN_Data.filterOut
// This macro is used to screen interface blocks that were deleted
// from the table or replaced and must be disposed of by the last
// user that refers to it
#define IsInterfaceValid(node) IsListEntry(&node->IN_IntfLink)
// This macro must be used to identify interface blocks that
// were deleted from the table and must be disposed of by the
// last user that refers to it
#define InvalidateInterface(node) InitializeListEntry(&node->IN_IntfLink)
// Table of interface control blocks
typedef struct _INTERFACE_TABLE { LONG IT_NumOfActiveInterfaces; // Number of active (enabled and bound)
// interfaces (we close Adapter port when
// this number drops to 0)
#if DBG
LIST_ENTRY IT_DetachedIntf; // List of interfaces that were
// removed from the table and await to be
// disposed of when the last client releases
// reference to them
#endif
LIST_ENTRY IT_IntfHash[IDB_NUM_OF_INTF_HASH_BUCKETS]; // Interface control blocks hashed by interface
// index
LIST_ENTRY IT_AdptHash[IDB_NUM_OF_ADPT_HASH_BUCKETS]; // Interface control blocks hashed by adapter
// index to which corresponding interface is
// bound
CRITICAL_SECTION IT_Lock; // Interface table data protection
} INTERFACE_TABLE, *PINTERFACE_TABLE;
// List of interface blocks in InterfaceIndex order
typedef struct _INTERFACE_LIST { CRITICAL_SECTION IL_Lock; // List data protection
LIST_ENTRY IL_Head; // List head
} INTERFACE_LIST, *PINTERFACE_LIST;
INTERFACE_TABLE InterfaceTable; INTERFACE_LIST InterfaceList; HANDLE ShutdownDoneEvent=NULL;
// Find if interface control block exists for interface index and
// return pointer to it (node), otherwise return place where
// new interface block should be inserted (cur)
#define if_IsInterfaceNode(InterfaceIndex,node,cur) { \
PLIST_ENTRY HashList=&InterfaceTable.IT_IntfHash[ \ IntfHashFunction(InterfaceIndex)]; \ EnterCriticalSection (&InterfaceTable.IT_Lock); \ cur = HashList->Flink; \ while (cur != HashList) { \ node = CONTAINING_RECORD (cur, INTERFACE_NODE, IN_IntfLink);\ if (InterfaceIndex <= node->IN_IntfIdx) \ break; \ cur = cur->Flink; \ } \ } \ if ((cur==&node->IN_IntfLink) \ && (InterfaceIndex==node->IN_IntfIdx))
// Local prototypes
DWORD StartInterface ( PINTERFACE_NODE node ); VOID FreeBindingResources ( PINTERFACE_NODE node );
DWORD StopInterface ( PINTERFACE_NODE node ); #if DBG
VOID DumpPacket ( PSAP_BUFFER packet, DWORD count ); #else
#define DumpPacket(packet,count)
#endif
PWCHAR SapDuplicateString (IN PWCHAR pszString) { PWCHAR pszRet; DWORD dwLen;
if (!pszString) return NULL;
dwLen = wcslen (pszString);
pszRet = GlobalAlloc (GMEM_FIXED, (dwLen * sizeof(WCHAR)) + sizeof(WCHAR)); if (pszRet) { wcscpy (pszRet, pszString); }
return pszRet; }
VOID SapFreeDuplicatedString (IN PWCHAR pszString) { if (pszString) GlobalFree (pszString); }
/*++
******************************************************************* C r e a t e I n t e r f a c e T a b l e
Routine Description: Allocates resources for interface table
Arguments: None Return Value: NO_ERROR - resources were allocated successfully other - reason of failure (windows error code)
******************************************************************* --*/ DWORD CreateInterfaceTable ( void ) { INT i; DWORD status;
InitializeCriticalSection (&InterfaceList.IL_Lock); InitializeListHead (&InterfaceList.IL_Head);
InitializeCriticalSection (&InterfaceTable.IT_Lock); for (i=0; i<IDB_NUM_OF_INTF_HASH_BUCKETS; i++) InitializeListHead (&InterfaceTable.IT_IntfHash[i]); for (i=0; i<IDB_NUM_OF_ADPT_HASH_BUCKETS; i++) InitializeListHead (&InterfaceTable.IT_AdptHash[i]);
#if DBG
InitializeListHead (&InterfaceTable.IT_DetachedIntf); #endif
InterfaceTable.IT_NumOfActiveInterfaces = 0;
return NO_ERROR; }
/*++
******************************************************************* S h u t d o w n I n t e r f a c e s
Routine Description: Initiates orderly shutdown of SAP interfaces Stop reception of new packets Arguments: None Return Value: None
******************************************************************* --*/ VOID ShutdownInterfaces ( HANDLE doneEvent ) { INT i;
// Now for each active interface in the table
// we'll start shoutdown worker which will broadcast
// all 'deleted' servers and dispose of interface control block
EnterCriticalSection (&InterfaceList.IL_Lock); EnterCriticalSection (&InterfaceTable.IT_Lock); ShutdownDoneEvent = doneEvent; if (InterfaceTable.IT_NumOfActiveInterfaces==0) { Trace (DEBUG_INTERFACES, "All interfaces have been shut down."); if (doneEvent!=NULL) { BOOL res = SetEvent (doneEvent); ASSERTERRMSG ("Could not set shutdown done event ", res); } } else { ShutdownDoneEvent = doneEvent;
for (i=0; i<IDB_NUM_OF_INTF_HASH_BUCKETS; i++) { while (!IsListEmpty (&InterfaceTable.IT_IntfHash[i])) { PINTERFACE_NODE node = CONTAINING_RECORD ( InterfaceTable.IT_IntfHash[i].Flink, INTERFACE_NODE, IN_IntfLink); if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) { node->IN_Info.Listen = ADMIN_STATE_DISABLED; // This will prevent deletion
// of all services associated with
// interface when it is stopped (done by the caller)
node->IN_Stats.SapIfOperState = OPER_STATE_STOPPING; StopInterface (node); } // Remove interface control block
Trace (DEBUG_INTERFACES, "Invalidating interface block: %lX(%d).", node, node->IN_IntfIdx); RemoveEntryList (&node->IN_IntfLink); InvalidateInterface (node); RemoveEntryList (&node->IN_ListLink); // Dispose only if nobody uses it and not waiting on critical
// section to dispose of it
if ((node->IN_RefCount==0) && !node->IN_InUse) { Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).", node, node->IN_IntfIdx); GlobalFree (node); } // Otherwise, just leave it hang outside of the table
// till last client releases reference to it
#if DBG
else // Keep track of all blocks in debugging mode
InsertTailList (&InterfaceTable.IT_DetachedIntf, &node->IN_ListLink); #endif
} } } LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); }
/*++
******************************************************************* S t o p I n t e r f a c e s
Routine Description: Stops all sap interfaces if not already stopped.
Arguments: None
Return Value: None
******************************************************************* --*/ VOID StopInterfaces ( void ) { INT i;
// Delete all interface control blocks
EnterCriticalSection (&InterfaceList.IL_Lock); EnterCriticalSection (&InterfaceTable.IT_Lock); for (i=0; i<IDB_NUM_OF_INTF_HASH_BUCKETS; i++) { while (!IsListEmpty (&InterfaceTable.IT_IntfHash[i])) { PINTERFACE_NODE node = CONTAINING_RECORD ( InterfaceTable.IT_IntfHash[i].Flink, INTERFACE_NODE, IN_IntfLink); if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) { // Stop all bound interfaces
node->IN_Info.Listen = ADMIN_STATE_DISABLED; // This will prevent deletion
// of all services associated with
// interface when it is stopped (done by the caller)
node->IN_Stats.SapIfOperState = OPER_STATE_STOPPING; StopInterface (node); } // Remove and dispose of original interface control block
Trace (DEBUG_INTERFACES, "Invalidating interface block: %lX(%d).", node, node->IN_IntfIdx); RemoveEntryList (&node->IN_IntfLink); InvalidateInterface (node); RemoveEntryList (&node->IN_ListLink); // Dispose only if nobody uses it and not waiting on critical
// section to dispose of it
if ((node->IN_RefCount==0) && !node->IN_InUse) { Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).", node, node->IN_IntfIdx); GlobalFree (node); } // Otherwise, just leave it hang outside of the table
// till last client releases reference to it
#if DBG
else // Keep track of all blocks in debugging mode
InsertTailList (&InterfaceTable.IT_DetachedIntf, &node->IN_ListLink); #endif
} } LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); }
/*++
******************************************************************* D e l e t e I n t e r f a c e T a b l e
Routine Description: Release all resources associated with interface table
Arguments: None
Return Value: NO_ERROR - operation completed OK
******************************************************************* --*/ VOID DeleteInterfaceTable ( void ) { DeleteCriticalSection (&InterfaceList.IL_Lock); DeleteCriticalSection (&InterfaceTable.IT_Lock); }
/*++
******************************************************************* A c q u i r e I n t e r f a c e R e f e n c e
Routine Description: Increments reference count of interface block. If reference count is greater than 0, the externally visible data in the block are locked (can't be modified)
Arguments: intf - pointer to externally visible part of interface control block
Return Value: None
******************************************************************* --*/ VOID AcquireInterfaceReference ( IN PINTERFACE_DATA intf ) { PINTERFACE_NODE node = CONTAINING_RECORD(intf, INTERFACE_NODE, IN_Data);
InterlockedIncrement(&node->IN_RefCount); }
/*++
******************************************************************* R e l e a s e I n t e r f a c e R e f e n c e
Routine Description: Decrements reference count of interface block. When reference count drops to 0, cleanup routine gets called to dispose of all resources allocated at bind time and if interface control block is already removed from the table it gets disposed of as well
Arguments: intf - pointer to externally visible part of interface control block
Return Value: None
******************************************************************* --*/ VOID ReleaseInterfaceReference ( IN PINTERFACE_DATA intf ) { PINTERFACE_NODE node = CONTAINING_RECORD (intf, INTERFACE_NODE, IN_Data);
if (InterlockedDecrement (&node->IN_RefCount)==0) { // This is the last client that refered to this interface block
// It should cleanup all resources allocated at bind time
// and possibly dispose of interface block itself
EnterCriticalSection (&InterfaceTable.IT_Lock); FreeBindingResources (node); if (!IsInterfaceValid(node)) { Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).", node, node->IN_IntfIdx); #if DBG
// Debugging mode code keeps all deleted nodes in
// detached list
RemoveEntryList (&node->IN_ListLink); #endif
if (node->IN_Filters!=NULL) { if (node->IN_Filters->SupplyFilterCount>0) ReplaceFilters ( FILTER_TYPE_SUPPLY, &node->IN_FilterNodes[0], node->IN_Filters->SupplyFilterCount, NULL, 0); if (node->IN_Filters->ListenFilterCount>0) ReplaceFilters ( FILTER_TYPE_LISTEN, &node->IN_FilterNodes[node->IN_Filters->SupplyFilterCount], node->IN_Filters->ListenFilterCount, NULL, 0); GlobalFree (node->IN_Filters); } if (node->IN_Name!=NULL) SapFreeDuplicatedString (node->IN_Name); GlobalFree (node); } LeaveCriticalSection (&InterfaceTable.IT_Lock); } }
/*++
******************************************************************* F r e e B i n d i n g R e s o u r c e s
Routine Description: Disposes of all resources allocated at bind time and marks interface block as not used. Interface Table must be locked when calling this routine (unless node is already removed from the table)
Arguments: node - pointer to interface control block
Return Value: None
******************************************************************* --*/ VOID FreeBindingResources ( PINTERFACE_NODE node ) { Trace (DEBUG_INTERFACES, "Releasing binding resources for interface block: %lX(%d).", node, node->IN_IntfIdx); node->IN_InUse = FALSE; if (node->IN_Enabled && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED)) node->IN_Stats.SapIfOperState = OPER_STATE_SLEEPING; else node->IN_Stats.SapIfOperState = OPER_STATE_DOWN;
InterfaceTable.IT_NumOfActiveInterfaces -= 1; if (InterfaceTable.IT_NumOfActiveInterfaces==0) { Trace (DEBUG_INTERFACES, "All interfaces have been shut down."); if (ShutdownDoneEvent!=NULL) { BOOL res = SetEvent (ShutdownDoneEvent); ASSERTERRMSG ("Could not set shutdown done event ", res); ShutdownDoneEvent = NULL; } }
}
/*++
******************************************************************* G e t I n t e r f a c e R e f e r e n c e
Routine Description: Finds interface control block that bound to adapter and increments reference count on it (to prevent it from deletion while it is used). Arguments: AdapterIndex - unique number that indentifies adapter Return Value: Pointer to externally visible part of interface control block NULL if no interface is bound to the adapter ******************************************************************* --*/ PINTERFACE_DATA GetInterfaceReference ( ULONG AdapterIndex ) { PLIST_ENTRY HashList = &InterfaceTable.IT_AdptHash [AdptHashFunction(AdapterIndex)]; PINTERFACE_NODE node; PLIST_ENTRY cur;
EnterCriticalSection (&InterfaceTable.IT_Lock); cur = HashList->Flink; while (cur!=HashList) { node = CONTAINING_RECORD (cur, INTERFACE_NODE, IN_AdptLink); if (node->IN_AdptIdx==AdapterIndex) { InterlockedIncrement (&node->IN_RefCount); break; } cur = cur->Flink; } LeaveCriticalSection (&InterfaceTable.IT_Lock); if (cur!=HashList) return &node->IN_Data; else return NULL; }
/*++
******************************************************************* S t a r t I n t e r f a c e
Routine Description: Initiate sap on interface Interface Table must be locked when calling this routine
Arguments: node - pointer to interface control block
Return Value: None
******************************************************************* --*/ DWORD StartInterface ( PINTERFACE_NODE node ) { DWORD status = NO_ERROR;
Trace (DEBUG_INTERFACES, "Starting SAP for interface block: %lX(%d,%d).", node, node->IN_IntfIdx, node->IN_AdptIdx); node->IN_Stats.SapIfOperState = OPER_STATE_UP; node->IN_InUse = TRUE; // Create binding reference
InterlockedIncrement (&node->IN_RefCount); InsertTailList ( &InterfaceTable.IT_AdptHash[AdptHashFunction(node->IN_AdptIdx)], &node->IN_AdptLink);
InterfaceTable.IT_NumOfActiveInterfaces += 1;
if ((status==NO_ERROR) && (node->IN_Info.UpdateMode==IPX_STANDARD_UPDATE)) { AddRecvRequests (NewRequestsPerInterface); if (node->IN_Info.Supply==ADMIN_STATE_ENABLED) status = InitBcastItem (&node->IN_Data); if ((status==NO_ERROR) && (node->IN_Info.Listen==ADMIN_STATE_ENABLED)) status = InitSreqItem (&node->IN_Data); }
if (status!=NO_ERROR) { node->IN_Stats.SapIfOperState = OPER_STATE_DOWN; RemoveEntryList (&node->IN_AdptLink); if (node->IN_Info.UpdateMode==IPX_STANDARD_UPDATE) { RemoveRecvRequests (NewRequestsPerInterface); }
if (InterlockedDecrement (&node->IN_RefCount)==0) // Cleanup binding resources if this is the
// last reference to the interface control block
FreeBindingResources (node); } return status; }
/*++
******************************************************************* S t o p I n t e r f a c e
Routine Description: Stop sap on interface Interface Table must be locked when calling this routine
Arguments: node - pointer to interface control block
Return Value: None
******************************************************************* --*/ DWORD StopInterface ( PINTERFACE_NODE node ) { DWORD status=NO_ERROR;
Trace (DEBUG_INTERFACES, "Stopping SAP for interface block: %lX(%d,%d).", node, node->IN_IntfIdx, node->IN_AdptIdx);
if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) { // Set the state of the interface if not already set.
if (node->IN_Enabled && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED) && (node->IN_Type!=PERMANENT)) node->IN_Stats.SapIfOperState = OPER_STATE_SLEEPING; else node->IN_Stats.SapIfOperState = OPER_STATE_DOWN;
}
RemoveEntryList (&node->IN_AdptLink); if (node->IN_Info.UpdateMode==IPX_STANDARD_UPDATE) { RemoveRecvRequests (NewRequestsPerInterface); }
if (InterlockedDecrement (&node->IN_RefCount)==0) // Cleanup binding resources if we released the
// last reference to the interface control block
FreeBindingResources (node); else // Have clients get in sync fast.
ExpireLRRequests ((PVOID)UlongToPtr(node->IN_IntfIdx));
// Delete all services obtained through SAP if we were actually
// listening to SAP announcements on this interface
if (node->IN_Info.Listen==ADMIN_STATE_ENABLED) { HANDLE enumHdl = CreateListEnumerator (SDB_INTF_LIST_LINK, 0xFFFF, NULL, node->IN_IntfIdx, IPX_PROTOCOL_SAP, SDB_DISABLED_NODE_FLAG); // Delete all services obtained through sap
if (enumHdl!=NULL) { EnumerateServers (enumHdl, DeleteAllServersCB, enumHdl); DeleteListEnumerator (enumHdl); } else Trace (DEBUG_FAILURES, "File: %s, line %ld." " Could not create enumerator to delete" " sap servers for interface: %ld.", __FILE__, __LINE__, node->IN_IntfIdx); }
return status; }
DWORD WINAPI UnbindInterface( IN ULONG InterfaceIndex );
SetInterfaceConfigInfo( IN ULONG InterfaceIndex, IN PVOID InterfaceInfo);
DWORD UpdateInterfaceState ( PINTERFACE_NODE node );
DWORD SapUpdateLocalServers ();
// Makes pnp changes to an interface
DWORD SapReconfigureInterface (ULONG InterfaceIndex, PIPX_ADAPTER_BINDING_INFO pAdapter) { PLIST_ENTRY cur; PINTERFACE_NODE node; DWORD dwErr; Trace (DEBUG_INTERFACES, "SapReconfigureInterface: entered for %d", InterfaceIndex); // Lock the interface list and get reference to the
// sought after control node.
EnterCriticalSection (&InterfaceList.IL_Lock); if_IsInterfaceNode(InterfaceIndex, node, cur) { // Update the information maintained in the interfaces
node->IN_Adpt = *pAdapter; UpdateInterfaceState ( node ); }
// Unlock
LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock);
// If the internal network number was updated, go through all
// local servers and update their control blocks accordingly.
if (InterfaceIndex == INTERNAL_INTERFACE_INDEX) { if ((dwErr = SapUpdateLocalServers ()) != NO_ERROR) { Trace (DEBUG_INTERFACES, "ERR: SapUpdateLocalServers returned %x", dwErr); } }
return NO_ERROR; }
/*++
******************************************************************* S a p C r e a t e S a p I n t e r f a c e
Routine Description: Add interface control block for new interface
Arguments: InterfaceIndex - unique number that indentifies new interface SapIfConfig - interface configuration info
Return Value: NO_ERROR - interface was created OK ERROR_ALREADY_EXISTS - interface with this index already exists other - operation failed (windows error code)
******************************************************************* --*/ DWORD SapCreateSapInterface ( LPWSTR InterfaceName, ULONG InterfaceIndex, NET_INTERFACE_TYPE InterfaceType, PSAP_IF_INFO SapIfConfig ) { PLIST_ENTRY cur; PINTERFACE_NODE node; DWORD status = NO_ERROR;
EnterCriticalSection (&InterfaceList.IL_Lock); if_IsInterfaceNode(InterfaceIndex,node,cur) { Trace (DEBUG_INTERFACES, "Interface %ld already exists.",InterfaceIndex); status = ERROR_ALREADY_EXISTS; } else { node = (PINTERFACE_NODE)GlobalAlloc (GMEM_FIXED, sizeof (INTERFACE_NODE)); if (node!=NULL) { node->IN_Name = SapDuplicateString (InterfaceName); if (node->IN_Name!=NULL) { node->IN_RefCount = 0; node->IN_InUse = FALSE; node->IN_Data.name = node->IN_Name; node->IN_IntfIdx = InterfaceIndex; node->IN_AdptIdx = INVALID_ADAPTER_INDEX; node->IN_Enabled = FALSE; node->IN_Type = InterfaceType; node->IN_Filters = NULL; node->IN_FilterNodes = NULL; node->IN_FilterIn = SAP_DONT_FILTER; node->IN_FilterOut = FilterOutMode; node->IN_Stats.SapIfInputPackets = 0; node->IN_Stats.SapIfOutputPackets = 0; if (ARGUMENT_PRESENT(SapIfConfig)) { node->IN_Info = *SapIfConfig; if (node->IN_Enabled && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED)) node->IN_Stats.SapIfOperState = OPER_STATE_SLEEPING; else node->IN_Stats.SapIfOperState = OPER_STATE_DOWN; } else node->IN_Stats.SapIfOperState = OPER_STATE_DOWN; InsertTailList (cur, &node->IN_IntfLink);
cur = InterfaceList.IL_Head.Flink; while (cur!=&InterfaceList.IL_Head) { if (InterfaceIndex<CONTAINING_RECORD ( cur, INTERFACE_NODE, IN_ListLink)->IN_IntfIdx) break; cur = cur->Flink; } InsertTailList (cur, &node->IN_ListLink); } else { GlobalFree (node); status = ERROR_NOT_ENOUGH_MEMORY; } } else status = ERROR_NOT_ENOUGH_MEMORY; } LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); return status; }
/*++
******************************************************************* S a p D e l e t e S a p I n t e r f a c e
Routine Description: Delete existing interface control block
Arguments: InterfaceIndex - unique number that indentifies the interface Return Value: NO_ERROR - interface was created OK ERROR_INVALID_PARAMETER - interface with this index does not exist other - operation failed (windows error code)
******************************************************************* --*/ DWORD SapDeleteSapInterface ( ULONG InterfaceIndex ) { PLIST_ENTRY cur; PINTERFACE_NODE node; DWORD status; HANDLE enumHdl;
EnterCriticalSection (&InterfaceList.IL_Lock); if_IsInterfaceNode (InterfaceIndex,node,cur) { if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) { StopInterface (node); }
// Remove and dispose of interface control block
Trace (DEBUG_INTERFACES, "Invalidating interface block: %lX(%d).", node, node->IN_IntfIdx); RemoveEntryList (&node->IN_IntfLink); InvalidateInterface (node); RemoveEntryList (&node->IN_ListLink); // Dispose only if nobody uses it and not waiting on critical
// section to dispose of it
if ((node->IN_RefCount==0) && !node->IN_InUse) { Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).", node, node->IN_IntfIdx); if (node->IN_Filters!=NULL) { if (node->IN_Filters->SupplyFilterCount>0) ReplaceFilters ( FILTER_TYPE_SUPPLY, &node->IN_FilterNodes[0], node->IN_Filters->SupplyFilterCount, NULL, 0); if (node->IN_Filters->ListenFilterCount>0) ReplaceFilters ( FILTER_TYPE_LISTEN, &node->IN_FilterNodes[node->IN_Filters->SupplyFilterCount], node->IN_Filters->ListenFilterCount, NULL, 0); GlobalFree (node->IN_Filters); } if (node->IN_Name!=NULL) SapFreeDuplicatedString (node->IN_Name); GlobalFree (node); } // Otherwise, just leave it hang outside of the table
// till last client releases reference to it
#if DBG
else // Keep track of all blocks in debugging mode
InsertTailList (&InterfaceTable.IT_DetachedIntf, &node->IN_ListLink); #endif
status = NO_ERROR; } else { Trace (DEBUG_FAILURES, "File: %s, line %ld." " Unknown interface: %ld.", __FILE__, __LINE__, InterfaceIndex); status = ERROR_INVALID_PARAMETER; }
LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); return status; }
/*++
******************************************************************* U p d a t e I n t e r f a c e S t a t e
Routine Description: Performs neccessary operations to syncronize interface operational state with externally set state Arguments: node - interface control block to update Return Value: NO_ERROR - interface was updated OK other - operation failed (windows error code)
******************************************************************* --*/ DWORD UpdateInterfaceState ( PINTERFACE_NODE node ) { DWORD status=NO_ERROR;
if (node->IN_IntfIdx!=INTERNAL_INTERFACE_INDEX) { if (node->IN_InUse && (node->IN_AdptIdx!=INVALID_ADAPTER_INDEX) && node->IN_Enabled && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED) ) { // Interface data is in use and it is going to
// stay active after the update: THIS IS A CONFIG
// CHANGE ON THE FLY!!! We'll have to create a new
// block and invalidate the old one
PINTERFACE_NODE newNode = GlobalAlloc (GMEM_FIXED, sizeof (INTERFACE_NODE)); if (newNode==NULL) { status = GetLastError (); Trace (DEBUG_FAILURES, "File: %s, line %ld." "Could not allocate memory to replace" " active interface block on set: %ld(gle:%ld).", __FILE__, __LINE__, node->IN_IntfIdx, status); return status; }
// Transfer external parameters
newNode->IN_Data = node->IN_Data; newNode->IN_Filters = node->IN_Filters; newNode->IN_FilterNodes = node->IN_FilterNodes; // Setup referencing parameters
newNode->IN_RefCount = 0; newNode->IN_InUse = FALSE;
// Insert in same place in tables
InsertTailList (&node->IN_IntfLink, &newNode->IN_IntfLink); InsertTailList (&node->IN_ListLink, &newNode->IN_ListLink); // Will put in adapter table at start
InitializeListEntry (&newNode->IN_AdptLink);
Trace (DEBUG_INTERFACES, "Replacing interface block on SET: %lX(%d).", newNode, newNode->IN_IntfIdx); status = StartInterface (newNode); if (status != NO_ERROR) node = newNode; // If we failed we'll have to dispose
// the new interface block and keep
// the old one
// Reset this flag to prevent deletion of all services
// obtained through SAP (we want to keep them despite
// the change to interface parameters)
node->IN_Info.Listen = ADMIN_STATE_DISABLED; // Prevent deletion of transferred filters and name
node->IN_Filters = NULL; node->IN_Name = NULL; // Shutdown interface if it is still active
if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) { node->IN_Stats.SapIfOperState = OPER_STATE_DOWN; StopInterface (node); }
// Remove and dispose of original interface control block
Trace (DEBUG_INTERFACES, "Invalidating interface block: %lX(%d).", node, node->IN_IntfIdx); RemoveEntryList (&node->IN_IntfLink); InvalidateInterface (node); RemoveEntryList (&node->IN_ListLink); // Dispose only if nobody uses it and not waiting on critical
// section to dispose of it
if ((node->IN_RefCount==0) && !node->IN_InUse) { Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).", node, node->IN_IntfIdx); GlobalFree (node); } // Otherwise, just leave it hang outside of the table
// till last client releases reference to it
#if DBG
else // Keep track of all blocks in debugging mode
InsertTailList (&InterfaceTable.IT_DetachedIntf, &node->IN_ListLink); #endif
} else { if ((node->IN_Enabled && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED) && (node->IN_AdptIdx!=INVALID_ADAPTER_INDEX))) { if (node->IN_Stats.SapIfOperState!=OPER_STATE_UP) status = StartInterface (node); } else { if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) status = StopInterface (node); else { if (node->IN_Enabled && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED) && (node->IN_Type!=PERMANENT)) node->IN_Stats.SapIfOperState = OPER_STATE_SLEEPING; else node->IN_Stats.SapIfOperState = OPER_STATE_DOWN; } } } } else { Trace (DEBUG_INTERFACES, "Internal interface info updated."); IpxNetCpy (INTERNAL_IF_NET, node->IN_Adpt.Network); IpxNodeCpy (INTERNAL_IF_NODE, node->IN_Adpt.LocalNode); }
return status; }
/*++
******************************************************************* S a p S e t I n t e r f a c e E n a b l e
Routine Description: Enables/disables interface Arguments: InterfaceIndex - unique number that indentifies new interface Enable - TRUE-enable, FALSE-disable Return Value: NO_ERROR - config info was changed OK ERROR_INVALID_PARAMETER - interface with this index does not exist other - operation failed (windows error code)
******************************************************************* --*/ DWORD SapSetInterfaceEnable ( ULONG InterfaceIndex, BOOL Enable ) { PLIST_ENTRY cur; PINTERFACE_NODE node; DWORD status=NO_ERROR;
EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
// in interface list
// while we are doing this
if_IsInterfaceNode (InterfaceIndex,node,cur) { HANDLE enumHdl; if (node->IN_Enabled!=Enable) { node->IN_Enabled = (UCHAR)Enable; status = UpdateInterfaceState (node); } LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); if (status==NO_ERROR) { enumHdl = CreateListEnumerator (SDB_INTF_LIST_LINK, 0xFFFF, NULL, node->IN_IntfIdx, 0xFFFFFFFF, Enable ? SDB_DISABLED_NODE_FLAG : 0); // Disable/Reenable all services
if (enumHdl!=NULL) { EnumerateServers (enumHdl, Enable ? EnableAllServersCB : DisableAllServersCB, enumHdl); DeleteListEnumerator (enumHdl); } else Trace (DEBUG_FAILURES, "File: %s, line %ld." " Could not create enumerator to enable/disable" " sap servers for interface: %ld.", __FILE__, __LINE__, node->IN_IntfIdx); } } else { LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); Trace (DEBUG_FAILURES, "File: %s, line %ld." " Unknown interface: %ld.", __FILE__, __LINE__, InterfaceIndex); status = ERROR_INVALID_PARAMETER; }
return status; }
/*++
******************************************************************* S a p S e t S a p I n t e r f a c e
Routine Description: Compares existing interface configuration with the new one and performs an update if necessary. Arguments: InterfaceIndex - unique number that indentifies new interface SapIfConfig - new interface configuration info Return Value: NO_ERROR - config info was changed OK ERROR_INVALID_PARAMETER - interface with this index does not exist other - operation failed (windows error code)
******************************************************************* --*/ DWORD SapSetSapInterface ( ULONG InterfaceIndex, PSAP_IF_INFO SapIfConfig ) { PLIST_ENTRY cur; PINTERFACE_NODE node; DWORD status=NO_ERROR;
EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
// in interface list
// while we are doing this
if_IsInterfaceNode (InterfaceIndex,node,cur) { // memcmp on structures!!! may not work with all compilers
// but event if it fails, the result will be just an
// set extra operation
if (memcmp (&node->IN_Info, SapIfConfig, sizeof (node->IN_Info))!=0) { node->IN_Info = *SapIfConfig; status = UpdateInterfaceState (node); } } else { Trace (DEBUG_FAILURES, "File: %s, line %ld." " Unknown interface: %ld.", __FILE__, __LINE__, InterfaceIndex); status = ERROR_INVALID_PARAMETER; }
LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); return status; }
/*++
******************************************************************* S a p I s S a p I n t e r f a c e
Routine Description: Checks if interface with given index exists Arguments: InterfaceIndex - unique number that indentifies new interface Return Value: TRUE - exist FALSE - does not
******************************************************************* --*/ BOOL SapIsSapInterface ( IN ULONG InterfaceIndex ) { PINTERFACE_NODE node; PLIST_ENTRY cur; BOOL res;
if_IsInterfaceNode (InterfaceIndex,node,cur) res = TRUE; else res = FALSE; LeaveCriticalSection (&InterfaceTable.IT_Lock); return res; }
/*++
******************************************************************* S a p G e t S a p I n t e r f a c e
Routine Description: Retrieves configuration and statistic info associated with interface Arguments: InterfaceIndex - unique number that indentifies new interface SapIfConfig - buffer to store configuration info SapIfStats - buffer to store statistic info Return Value: NO_ERROR - info was retrieved OK ERROR_INVALID_PARAMETER - interface with this index does not exist other - operation failed (windows error code)
******************************************************************* --*/
DWORD SapGetSapInterface ( IN ULONG InterfaceIndex, OUT PSAP_IF_INFO SapIfConfig OPTIONAL, OUT PSAP_IF_STATS SapIfStats OPTIONAL ) { PINTERFACE_NODE node; DWORD status; PLIST_ENTRY cur;
if_IsInterfaceNode (InterfaceIndex,node,cur) { if (ARGUMENT_PRESENT(SapIfConfig)) *SapIfConfig = node->IN_Info; if (ARGUMENT_PRESENT(SapIfStats)) *SapIfStats = node->IN_Stats; status = NO_ERROR; } else { Trace (DEBUG_FAILURES, "File: %s, line %ld." " Unknown interface: %ld.", __FILE__, __LINE__, InterfaceIndex); status = ERROR_INVALID_PARAMETER; }
LeaveCriticalSection (&InterfaceTable.IT_Lock); return status; }
/*++
******************************************************************* S a p G e t F i r s t S a p I n t e r f a c e
Routine Description: Retrieves configuration and statistic info associated with first interface in InterfaceIndex order Arguments: InterfaceIndex - buffer to store unique number that indentifies interface SapIfConfig - buffer to store configuration info SapIfStats - buffer to store statistic info Return Value: NO_ERROR - info was retrieved OK ERROR_NO_MORE_ITEMS - no interfaces in the table other - operation failed (windows error code)
******************************************************************* --*/
DWORD SapGetFirstSapInterface ( OUT PULONG InterfaceIndex, OUT PSAP_IF_INFO SapIfConfig OPTIONAL, OUT PSAP_IF_STATS SapIfStats OPTIONAL ) { PINTERFACE_NODE node; DWORD status;
EnterCriticalSection (&InterfaceList.IL_Lock); if (!IsListEmpty (&InterfaceList.IL_Head)) { node = CONTAINING_RECORD (InterfaceList.IL_Head.Flink, INTERFACE_NODE, IN_ListLink); // Lock the table to make sure nobody modifies data while
// we are accessing it
EnterCriticalSection (&InterfaceTable.IT_Lock); *InterfaceIndex = node->IN_IntfIdx; if (ARGUMENT_PRESENT(SapIfConfig)) *SapIfConfig = node->IN_Info; if (ARGUMENT_PRESENT(SapIfStats)) *SapIfStats = node->IN_Stats; LeaveCriticalSection (&InterfaceTable.IT_Lock); status = NO_ERROR; } else { Trace (DEBUG_FAILURES, "File: %s, line %ld." " Unknown interface: %ld.", __FILE__, __LINE__, InterfaceIndex); status = ERROR_NO_MORE_ITEMS; } LeaveCriticalSection (&InterfaceList.IL_Lock);
return status; }
/*++
******************************************************************* S a p G e t N e x t S a p I n t e r f a c e
Routine Description: Retrieves configuration and statistic info associated with first interface in following interface with InterfaceIndex order in interface index order Arguments: InterfaceIndex - on input - interface number to search from on output - interface number of next interface SapIfConfig - buffer to store configuration info SapIfStats - buffer to store statistic info Return Value: NO_ERROR - info was retrieved OK ERROR_NO_MORE_ITEMS - no more interfaces in the table other - operation failed (windows error code)
******************************************************************* --*/
DWORD SapGetNextSapInterface ( IN OUT PULONG InterfaceIndex, OUT PSAP_IF_INFO SapIfConfig OPTIONAL, OUT PSAP_IF_STATS SapIfStats OPTIONAL ) { PINTERFACE_NODE node; PLIST_ENTRY cur; DWORD status=ERROR_NO_MORE_ITEMS;
EnterCriticalSection (&InterfaceList.IL_Lock);
if_IsInterfaceNode(*InterfaceIndex,node,cur) { if (node->IN_ListLink.Flink!=&InterfaceList.IL_Head) { node = CONTAINING_RECORD (node->IN_ListLink.Flink, INTERFACE_NODE, IN_ListLink); *InterfaceIndex = node->IN_IntfIdx; if (ARGUMENT_PRESENT(SapIfConfig)) *SapIfConfig = node->IN_Info; if (ARGUMENT_PRESENT(SapIfStats)) *SapIfStats = node->IN_Stats; status = NO_ERROR; } LeaveCriticalSection (&InterfaceTable.IT_Lock); } else { LeaveCriticalSection (&InterfaceTable.IT_Lock); cur = InterfaceList.IL_Head.Flink; while (cur!=&InterfaceList.IL_Head) { node = CONTAINING_RECORD (cur, INTERFACE_NODE, IN_ListLink); if (*InterfaceIndex<node->IN_IntfIdx) break; }
if (cur!=&InterfaceList.IL_Head) { EnterCriticalSection (&InterfaceTable.IT_Lock); *InterfaceIndex = node->IN_IntfIdx; if (ARGUMENT_PRESENT(SapIfConfig)) *SapIfConfig = node->IN_Info; if (ARGUMENT_PRESENT(SapIfStats)) *SapIfStats = node->IN_Stats; LeaveCriticalSection (&InterfaceTable.IT_Lock); status = NO_ERROR; } }
LeaveCriticalSection (&InterfaceList.IL_Lock); return status; }
/*++
******************************************************************* S a p S e t I n t e r f a c e F i l t e r s
Routine Description: Compares existing interface configuration with the new one and performs an update if necessary. Arguments: Return Value: NO_ERROR - config info was changed OK ERROR_INVALID_PARAMETER - interface with this index does not exist other - operation failed (windows error code)
******************************************************************* --*/ DWORD SapSetInterfaceFilters ( IN ULONG InterfaceIndex, IN PSAP_IF_FILTERS SapIfFilters ) { PLIST_ENTRY cur; PINTERFACE_NODE node; DWORD status=NO_ERROR;
EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
// in interface list
// while we are doing this
if_IsInterfaceNode (InterfaceIndex,node,cur) { if ( ((node->IN_Filters!=NULL) && (SapIfFilters!=NULL) // memcmp on structures!!! may not work with all compilers
// but event if it fails, the result will be just an
// set extra operation
&& (memcmp (node->IN_Filters, SapIfFilters, FIELD_OFFSET (SAP_IF_FILTERS,ServiceFilter))==0) && (memcmp (&node->IN_Filters->ServiceFilter[0], &SapIfFilters->ServiceFilter[0], sizeof (SAP_SERVICE_FILTER_INFO)* (SapIfFilters->SupplyFilterCount +SapIfFilters->ListenFilterCount))==0)) // Filter info hasn't changed
|| ((node->IN_Filters==NULL) && ((SapIfFilters==NULL) || (SapIfFilters->SupplyFilterCount +SapIfFilters->ListenFilterCount==0))) ) // There are no filters
status = NO_ERROR; else { if ((SapIfFilters!=NULL) && (SapIfFilters->SupplyFilterCount +SapIfFilters->ListenFilterCount>0)) { PFILTER_NODE newNodes; PSAP_IF_FILTERS newFilters; ULONG newTotal = SapIfFilters->SupplyFilterCount +SapIfFilters->ListenFilterCount; newFilters = (PSAP_IF_FILTERS) GlobalAlloc (GMEM_FIXED, FIELD_OFFSET (SAP_IF_FILTERS,ServiceFilter[newTotal]) +sizeof (FILTER_NODE)*newTotal); if (newFilters!=NULL) { ULONG i; memcpy (newFilters, SapIfFilters, FIELD_OFFSET (SAP_IF_FILTERS,ServiceFilter[newTotal])); newNodes = (PFILTER_NODE)&newFilters->ServiceFilter[newTotal]; for (i=0; i<newTotal; i++) { newNodes[i].FN_Index = InterfaceIndex; newNodes[i].FN_Filter = &newFilters->ServiceFilter[i]; } } else { status = GetLastError (); goto ExitSetFilters; }
if (node->IN_Filters) { ReplaceFilters ( FILTER_TYPE_SUPPLY, &node->IN_FilterNodes[0], node->IN_Filters->SupplyFilterCount, &newNodes[0], newFilters->SupplyFilterCount); ReplaceFilters ( FILTER_TYPE_LISTEN, &node->IN_FilterNodes[node->IN_Filters->SupplyFilterCount], node->IN_Filters->ListenFilterCount, &newNodes[newFilters->SupplyFilterCount], newFilters->ListenFilterCount); } else { ReplaceFilters ( FILTER_TYPE_SUPPLY, NULL, 0, &newNodes[0], newFilters->SupplyFilterCount); ReplaceFilters ( FILTER_TYPE_LISTEN, NULL, 0, &newNodes[newFilters->SupplyFilterCount], newFilters->ListenFilterCount); } node->IN_Filters = newFilters; node->IN_FilterNodes = newNodes; node->IN_FilterOut = newFilters->SupplyFilterCount>0 ? (UCHAR)newFilters->SupplyFilterAction : SAP_DONT_FILTER; node->IN_FilterIn = newFilters->ListenFilterCount>0 ? (UCHAR)newFilters->ListenFilterAction : SAP_DONT_FILTER; } else { ReplaceFilters ( FILTER_TYPE_SUPPLY, &node->IN_FilterNodes[0], node->IN_Filters->SupplyFilterCount, NULL, 0);
ReplaceFilters ( FILTER_TYPE_LISTEN, &node->IN_FilterNodes[node->IN_Filters->SupplyFilterCount], node->IN_Filters->ListenFilterCount, NULL, 0); GlobalFree (node->IN_Filters); node->IN_Filters = NULL; node->IN_FilterNodes = NULL; node->IN_FilterIn = node->IN_FilterOut = SAP_DONT_FILTER; } status = NO_ERROR; } } else { Trace (DEBUG_FAILURES, "File: %s, line %ld." " Unknown interface: %ld.", __FILE__, __LINE__, InterfaceIndex); status = ERROR_INVALID_PARAMETER; }
ExitSetFilters:
LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); return status; }
/*++
******************************************************************* S a p G e t I n t e r f a c e F i l t e r s
Routine Description: Compares existing interface configuration with the new one and performs an update if necessary. Arguments: Return Value: NO_ERROR - config info was changed OK ERROR_INVALID_PARAMETER - interface with this index does not exist other - operation failed (windows error code)
******************************************************************* --*/ DWORD SapGetInterfaceFilters ( IN ULONG InterfaceIndex, OUT PSAP_IF_FILTERS SapIfFilters, OUT PULONG FilterBufferSize ) { PINTERFACE_NODE node; DWORD status; PLIST_ENTRY cur;
if_IsInterfaceNode (InterfaceIndex,node,cur) { if (node->IN_Filters!=NULL) { PSAP_IF_FILTERS info = node->IN_Filters; ULONG infoSize = FIELD_OFFSET (SAP_IF_FILTERS, ServiceFilter[info->SupplyFilterCount +info->ListenFilterCount]); if (*FilterBufferSize>=infoSize) { memcpy (SapIfFilters, info, infoSize); status = NO_ERROR; } else status = ERROR_INSUFFICIENT_BUFFER; *FilterBufferSize = infoSize; } else { ULONG infoSize = FIELD_OFFSET (SAP_IF_FILTERS, ServiceFilter); if (*FilterBufferSize>=infoSize) { SapIfFilters->SupplyFilterCount = 0; SapIfFilters->SupplyFilterAction = IPX_SERVICE_FILTER_DENY; SapIfFilters->ListenFilterCount = 0; SapIfFilters->ListenFilterAction = IPX_SERVICE_FILTER_DENY; status = NO_ERROR; } else status = ERROR_INSUFFICIENT_BUFFER; *FilterBufferSize = infoSize; } } else { Trace (DEBUG_FAILURES, "File: %s, line %ld." " Unknown interface: %ld.", __FILE__, __LINE__, InterfaceIndex); status = ERROR_INVALID_PARAMETER; }
LeaveCriticalSection (&InterfaceTable.IT_Lock); return status; }
/*++
******************************************************************* S a p B i n d S a p I n t e r f a c e T o A d a p t e r
Routine Description: Establishes association between interface and physical adapter and starts sap on the interface if its admin state is enabled Arguments: InterfaceIndex - unique number that indentifies new interface AdapterInfo - info associated with adapter to bind to Return Value: NO_ERROR - interface was bound OK ERROR_INVALID_PARAMETER - interface with this index does not exist other - operation failed (windows error code)
******************************************************************* --*/ DWORD SapBindSapInterfaceToAdapter ( ULONG InterfaceIndex, PIPX_ADAPTER_BINDING_INFO AdptInternInfo ) { PINTERFACE_NODE node; DWORD status=NO_ERROR; PLIST_ENTRY cur;
EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
// in interface list
// while we are doing this
if_IsInterfaceNode (InterfaceIndex,node,cur) { ASSERTMSG ("Interface is already bound ", node->IN_AdptIdx==INVALID_ADAPTER_INDEX); node->IN_Adpt = *AdptInternInfo; status = UpdateInterfaceState (node); } else { Trace (DEBUG_FAILURES, "File: %s, line %ld." " Unknown interface: %ld.", __FILE__, __LINE__, InterfaceIndex); status = ERROR_INVALID_PARAMETER; } LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); return status; }
/*++
******************************************************************* S a p U n b i n d S a p I n t e r f a c e F r o m A d a p t e r
Routine Description: Breaks association between interface and physical adapter and stops sap on the interface if it was on Arguments: InterfaceIndex - unique number that indentifies new interface Return Value: NO_ERROR - interface was bound OK ERROR_INVALID_PARAMETER - interface with this index does not exist other - operation failed (windows error code)
******************************************************************* --*/ DWORD SapUnbindSapInterfaceFromAdapter ( ULONG InterfaceIndex ) { PINTERFACE_NODE node; DWORD status; PLIST_ENTRY cur;
EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
// in interface list
// while we are doing this
if_IsInterfaceNode (InterfaceIndex,node,cur) { node->IN_AdptIdx = INVALID_ADAPTER_INDEX; if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) { status = StopInterface (node); }
} else { Trace (DEBUG_FAILURES, "File: %s, line %ld." " Unknown interface: %ld.", __FILE__, __LINE__, InterfaceIndex); status = ERROR_INVALID_PARAMETER; }
LeaveCriticalSection (&InterfaceTable.IT_Lock); LeaveCriticalSection (&InterfaceList.IL_Lock); return status; }
/*++
******************************************************************* S a p R e q u e s t U p d a t e Routine Description: Initiates update of services information over the interface Completion of this update will be indicated by signalling NotificationEvent passed at StartProtocol. GetEventMessage can be used then to get the results of autostatic update Arguments: InterfaceIndex - unique index identifying interface to do update on Return Value: NO_ERROR - operation was initiated ok ERROR_CAN_NOT_COMPLETE - the interface does not support updates ERROR_INVALID_PARAMETER - interface with this index does not exist other - operation failed (windows error code) ******************************************************************* --*/ DWORD SapRequestUpdate ( ULONG InterfaceIndex ) { PINTERFACE_NODE node; DWORD status; PLIST_ENTRY cur;
if_IsInterfaceNode (InterfaceIndex,node,cur) { if ((node->IN_Info.UpdateMode==IPX_AUTO_STATIC_UPDATE) && (node->IN_Stats.SapIfOperState==OPER_STATE_UP)) { Trace (DEBUG_INTERFACES, "Starting update on interface: %ld.", InterfaceIndex); status = InitTreqItem (&node->IN_Data); } else { Trace (DEBUG_FAILURES, "RequestUpdate called on unbound or" " 'standard update mode' interface: %ld.", InterfaceIndex); status = ERROR_CAN_NOT_COMPLETE; } } else { Trace (DEBUG_FAILURES, "Unknown interface: %ld.", InterfaceIndex); status = ERROR_INVALID_PARAMETER; }
LeaveCriticalSection (&InterfaceTable.IT_Lock); return status; }
|