Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1750 lines
50 KiB

/*++
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;
}