|
|
/*++
Copyright (c) 1999, Microsoft Corporation
Module Name:
sample\networkentry.c
Abstract:
The file contains functions to deal with the network entry and its associated data structures.
--*/
#include "pchsample.h"
#pragma hdrstop
DWORD BE_CreateTable ( IN PIP_ADAPTER_BINDING_INFO pBinding, OUT PBINDING_ENTRY *ppbeBindingTable, OUT PIPADDRESS pipLowestAddress) /*++
Routine Description Creates a table of binding entries and returns the binding with the lowest ip address. Ensures that there is atleast one binding.
Locks None
Arguments pBinding structure containing info about addresses bindings ppbeBindingTable pointer to the binding table address pipLowestAddress pointer to the lowest ip address in the binding Return Value NO_ERROR if success Failure code o/w
--*/ { ULONG i; DWORD dwErr = NO_ERROR; PBINDING_ENTRY pbe; // scratch
// validate parameters
if (!pBinding or !ppbeBindingTable or !pipLowestAddress) return ERROR_INVALID_PARAMETER;
// a binding already exists
if (*ppbeBindingTable != NULL) return ERROR_INVALID_PARAMETER;
IP_ASSIGN(pipLowestAddress, IP_HIGHEST); do // breakout loop
{ if (pBinding->AddressCount is 0) { dwErr = ERROR_INVALID_PARAMETER; TRACE0(NETWORK, "Error, no bindings specified"); break; }
for (i = 0; i < pBinding->AddressCount; i++) if (!IP_VALID((pBinding->Address)[i].Address)) break; if (i != pBinding->AddressCount) { dwErr = ERROR_INVALID_PARAMETER; TRACE0(NETWORK, "Error, an invalid binding specified"); break; }
// allocate the binding table
MALLOC(&pbe, pBinding->AddressCount * sizeof(BINDING_ENTRY), &dwErr); if (dwErr != NO_ERROR) break;
for (i = 0; i < pBinding->AddressCount; i++) { // initialize fields
IP_ASSIGN(&(pbe[i].ipAddress), (pBinding->Address)[i].Address); IP_ASSIGN(&(pbe[i].ipMask), pBinding->Address[i].Mask);
// update lowest ip address
if (IP_COMPARE(pbe[i].ipAddress, *pipLowestAddress) is -1) IP_ASSIGN(pipLowestAddress,pbe[i].ipAddress); } *ppbeBindingTable = pbe;
} while (FALSE);
return dwErr; }
DWORD BE_DestroyTable ( IN PBINDING_ENTRY pbeBindingTable) /*++
Routine Description Destroys a binding table.
Locks None.
Arguments pbeBindingTable pointer to the table of binding entries Return Value NO_ERROR always
--*/ { if (!pbeBindingTable) return NO_ERROR;
FREE(pbeBindingTable);
return NO_ERROR; }
#ifdef DEBUG
DWORD BE_DisplayTable ( IN PBINDING_ENTRY pbeBindingTable, IN ULONG ulNumBindings) /*++
Routine Description Displays a binding entry.
Locks None.
Arguments pbeBindingTable pointer to the table of binding entries ulNumBindings # binding entries in the table
Return Value NO_ERROR always
--*/ { ULONG i;
if (!pbeBindingTable) return NO_ERROR; for (i = 0; i < ulNumBindings; i++) { TRACE1(NETWORK, "ipAddress %s", INET_NTOA(pbeBindingTable[i].ipAddress)); TRACE1(NETWORK, "ipMask %s", INET_NTOA(pbeBindingTable[i].ipMask)); }
return NO_ERROR; } #endif // DEBUG
#ifdef DEBUG
static VOID DisplayInterfaceEntry ( IN PLIST_ENTRY pleEntry) /*++
Routine Description Displays an INTERFACE_ENTRY object.
Locks None
Arguments pleEntry address of the 'leInterfaceTableLink' field
Return Value None
--*/ { IE_Display(CONTAINING_RECORD(pleEntry, INTERFACE_ENTRY, leInterfaceTableLink)); } #else
#define DisplayInterfaceEntry NULL
#endif // DEBUG
static VOID FreeInterfaceEntry ( IN PLIST_ENTRY pleEntry) /*++
Routine Description Called by HT_Destroy, the destructor of the primary access structure. Removes an INTERFACE_ENTRY object from all secondary access structures. Locks None
Arguments pleEntry address of the 'leInterfaceTableLink' field
Return Value None
--*/ { PINTERFACE_ENTRY pie = NULL;
pie = CONTAINING_RECORD(pleEntry, INTERFACE_ENTRY, leInterfaceTableLink);
// remove from all secondary access structures.
RemoveEntryList(&(pie->leIndexSortedListLink));
// initialize pointers to indicate that the entry has been deleted
InitializeListHead(&(pie->leInterfaceTableLink)); InitializeListHead(&(pie->leIndexSortedListLink));
IE_Destroy(pie); }
static ULONG HashInterfaceEntry ( IN PLIST_ENTRY pleEntry) /*++
Routine Description Computes the hash value of an INTERFACE_ENTRY object.
Locks None
Arguments pleEntry address of the 'leInterfaceTableLink' field
Return Value None
--*/ { PINTERFACE_ENTRY pie = CONTAINING_RECORD(pleEntry, INTERFACE_ENTRY, leInterfaceTableLink);
return (pie->dwIfIndex % INTERFACE_TABLE_BUCKETS); }
static LONG CompareInterfaceEntry ( IN PLIST_ENTRY pleKeyEntry, IN PLIST_ENTRY pleTableEntry) /*++
Routine Description Compares the interface indices of two INTERFACE_ENTRY objects.
Locks None
Arguments pleTableEntry address of the 'leInterfaceTableLink' fields pleKeyEntry within the two objects
Return Value None
--*/ { PINTERFACE_ENTRY pieA, pieB; pieA = CONTAINING_RECORD(pleKeyEntry, INTERFACE_ENTRY, leInterfaceTableLink); pieB = CONTAINING_RECORD(pleTableEntry, INTERFACE_ENTRY, leInterfaceTableLink);
if (pieA->dwIfIndex < pieB->dwIfIndex) return -1; else if (pieA->dwIfIndex is pieB->dwIfIndex) return 0; else return 1; }
#ifdef DEBUG
static VOID DisplayIndexInterfaceEntry ( IN PLIST_ENTRY pleEntry) /*++
Routine Description Displays an INTERFACE_ENTRY object.
Locks None
Arguments pleEntry address of the 'leIndexSortedListLink' field
Return Value None
--*/ { IE_Display(CONTAINING_RECORD(pleEntry, INTERFACE_ENTRY, leIndexSortedListLink)); } #else
#define DisplayIndexInterfaceEntry NULL
#endif // DEBUG
static LONG CompareIndexInterfaceEntry ( IN PLIST_ENTRY pleKeyEntry, IN PLIST_ENTRY pleTableEntry) /*++
Routine Description Compares the interface indices of two INTERFACE_ENTRY objects.
Locks None
Arguments pleTableEntry address of the 'leIndexSortedListLink' fields pleKeyEntry within the two objects
Return Value None
--*/ { PINTERFACE_ENTRY pieA, pieB; pieA = CONTAINING_RECORD(pleKeyEntry, INTERFACE_ENTRY, leIndexSortedListLink); pieB = CONTAINING_RECORD(pleTableEntry, INTERFACE_ENTRY, leIndexSortedListLink);
if (pieA->dwIfIndex < pieB->dwIfIndex) return -1; else if (pieA->dwIfIndex is pieB->dwIfIndex) return 0; else return 1; }
DWORD IE_Create ( IN PWCHAR pwszIfName, IN DWORD dwIfIndex, IN WORD wAccessType, OUT PINTERFACE_ENTRY *ppieInterfaceEntry) /*++
Routine Description Creates an interface entry.
Locks None
Arguments ppieInterfaceEntry pointer to the interface entry address
Return Value NO_ERROR if success Failure code o/w
--*/ { DWORD dwErr = NO_ERROR; ULONG ulNameLength; PINTERFACE_ENTRY pieEntry; // scratch
// validate parameters
if (!ppieInterfaceEntry) return ERROR_INVALID_PARAMETER;
*ppieInterfaceEntry = NULL; do // breakout loop
{ // allocate and zero out the interface entry structure
MALLOC(&pieEntry, sizeof(INTERFACE_ENTRY), &dwErr); if (dwErr != NO_ERROR) break;
// initialize fields with default values
InitializeListHead(&(pieEntry->leInterfaceTableLink)); InitializeListHead(&(pieEntry->leIndexSortedListLink));
// pieEntry->pwszIfName = NULL;
pieEntry->dwIfIndex = dwIfIndex;
// pieEntry->ulNumBindings = 0;
// pieEntry->pbeBindingTable = NULL;
// pieEntry->dwFlags = 0; // disabled unbound pointtopoint
if (wAccessType is IF_ACCESS_BROADCAST) pieEntry->dwFlags |= IEFLAG_MULTIACCESS; IP_ASSIGN(&(pieEntry->ipAddress), IP_LOWEST); pieEntry->sRawSocket = INVALID_SOCKET;
// pieEntry->hReceiveEvent = NULL;
// pieEntry->hReceiveWait = NULL;
// pieEntry->hPeriodicTimer = NULL;
// pieEntry->ulMetric = 0;
// pieEntry->iisStats zero'ed out
// initialize name
ulNameLength = wcslen(pwszIfName) + 1; MALLOC(&(pieEntry->pwszIfName), ulNameLength * sizeof(WCHAR), &dwErr); if(dwErr != NO_ERROR) break; wcscpy(pieEntry->pwszIfName, pwszIfName);
// initialize ReceiveEvent (signalled when input arrives).
// Auto-Reset Event: state automatically reset to nonsignaled after
// a single waiting thread is released. Initially non signalled
pieEntry->hReceiveEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (pieEntry->hReceiveEvent is NULL) { dwErr = GetLastError(); TRACE1(NETWORK, "Error %u creating Receive Event", dwErr); LOGERR0(CREATE_EVENT_FAILED, dwErr);
break; }
// register ReceiveWait for this interface
if (!RegisterWaitForSingleObject(&(pieEntry->hReceiveWait), pieEntry->hReceiveEvent, NM_CallbackNetworkEvent, (PVOID) dwIfIndex, INFINITE, WT_EXECUTEONLYONCE)) { dwErr = GetLastError(); TRACE1(NETWORK, "Error %u registering ReceiveWait", dwErr); LOGERR0(REGISTER_WAIT_FAILED, dwErr);
break; }
*ppieInterfaceEntry = pieEntry; // all's well :)
} while (FALSE);
if (dwErr != NO_ERROR) { // something went wrong, so cleanup.
TRACE2(NETWORK, "Failed to create interface entry for %S (%u)", pwszIfName, dwIfIndex); IE_Destroy(pieEntry); }
return dwErr; }
DWORD IE_Destroy ( IN PINTERFACE_ENTRY pieInterfaceEntry) /*++
Routine Description Destroys an interface entry.
Locks Assumes exclusive access to the entry by virute of it having been removed from all access data structures (lists, tables, ...) NOTE: Should NOT be called with g_ce.neNetworkEntry.rwlLock held! The call to UnregisterWaitEx blocks till all queued callbacks for pieInterfaceEntry->hReceiveEvent finish execution. These callbacks may acquire g_ce.neNetworkEntry.rwlLock, causing deadlock.
Arguments pieInterfaceEntry pointer to the interface entry
Return Value NO_ERROR always
--*/ { if (!pieInterfaceEntry) return NO_ERROR;
if (INTERFACE_IS_BOUND(pieInterfaceEntry)) IE_UnBindInterface(pieInterfaceEntry);
if (INTERFACE_IS_ACTIVE(pieInterfaceEntry)) IE_DeactivateInterface(pieInterfaceEntry);
// PeriodicTimer should have been destroyed
RTASSERT(pieInterfaceEntry->hPeriodicTimer is NULL); // deregister ReceiveWait
if (pieInterfaceEntry->hReceiveWait) UnregisterWaitEx(pieInterfaceEntry->hReceiveWait, INVALID_HANDLE_VALUE); // delete ReceiveEvent
if (pieInterfaceEntry->hReceiveEvent) CloseHandle(pieInterfaceEntry->hReceiveEvent); // BindingTable and RawSocket should have been destroyed
RTASSERT(pieInterfaceEntry->pbeBindingTable is NULL); RTASSERT(pieInterfaceEntry->sRawSocket is INVALID_SOCKET); // delete IfName
FREE(pieInterfaceEntry->pwszIfName);
// Entry should have been removed from all access structures
RTASSERT(IsListEmpty(&(pieInterfaceEntry->leInterfaceTableLink))); RTASSERT(IsListEmpty(&(pieInterfaceEntry->leIndexSortedListLink))); // deallocate the interface entry structure
FREE(pieInterfaceEntry); return NO_ERROR; }
#ifdef DEBUG
DWORD IE_Display ( IN PINTERFACE_ENTRY pieInterfaceEntry) /*++
Routine Description Displays an interface entry.
Locks Assumes the interface entry is locked for reading.
Arguments pieInterfaceEntry pointer to the interface entry to be displayed
Return Value NO_ERROR always
--*/ { if (!pieInterfaceEntry) return NO_ERROR;
TRACE3(NETWORK, "IfName %S, IfIndex %u, AccessType %u", pieInterfaceEntry->pwszIfName, pieInterfaceEntry->dwIfIndex, INTERFACE_IS_MULTIACCESS(pieInterfaceEntry));
TRACE1(NETWORK, "NumBindings %u", pieInterfaceEntry->ulNumBindings); BE_DisplayTable(pieInterfaceEntry->pbeBindingTable, pieInterfaceEntry->ulNumBindings);
TRACE2(NETWORK, "IfAddress %s Flags %u", INET_NTOA(pieInterfaceEntry->ipAddress), pieInterfaceEntry->dwFlags);
TRACE2(NETWORK, "Metric %u, NumPackets %u", pieInterfaceEntry->ulMetric, pieInterfaceEntry->iisStats.ulNumPackets); return NO_ERROR; } #endif // DEBUG
DWORD IE_Insert ( IN PINTERFACE_ENTRY pieIfEntry) /*++
Routine Description Inserts an interface entry in all access structures, primary and secondary.
Locks Assumes exclusive access to the interface table and index sorted list i.e. (g_ce.pneNetworkEntry)->rwlLock held in write mode.
Arguments pieIfEntry pointer to the interface entry
Return Value NO_ERROR success ERROR_INVALID_PARAMETER o/w (interface entry already exists)
--*/ { DWORD dwErr = NO_ERROR;
do // breakout loop
{ dwErr = HT_InsertEntry((g_ce.pneNetworkEntry)->phtInterfaceTable, &(pieIfEntry->leInterfaceTableLink)); if (dwErr != NO_ERROR) { TRACE2(NETWORK, "Error interface %S (%u) already exists", pieIfEntry->pwszIfName, pieIfEntry->dwIfIndex); LOGERR0(INTERFACE_PRESENT, dwErr); break; } // insert in all tables, lists...
InsertSortedList(&((g_ce.pneNetworkEntry)->leIndexSortedList), &(pieIfEntry->leIndexSortedListLink), CompareIndexInterfaceEntry); } while (FALSE); return dwErr; }
DWORD IE_Delete ( IN DWORD dwIfIndex, OUT PINTERFACE_ENTRY *ppieIfEntry) /*++
Routine Description Deletes an interface entry from all access structures, primary and secondary.
Locks Assumes exclusive access to the interface table and index sorted list i.e. (g_ce.pneNetworkEntry)->rwlLock held in write mode.
Arguments dwIfIndex the positive integer used to identify the interface. ppieIfEntry address of the pointer to the interface entry
Return Value NO_ERROR success ERROR_INVALID_PARAMETER o/w (interface entry does not exist)
--*/ { DWORD dwErr = NO_ERROR; INTERFACE_ENTRY ieKey; PLIST_ENTRY pleListEntry = NULL;
*ppieIfEntry = NULL; do // breakout loop
{ // remove from interface table (primary)
ZeroMemory(&ieKey, sizeof(INTERFACE_ENTRY)); ieKey.dwIfIndex = dwIfIndex;
dwErr = HT_DeleteEntry((g_ce.pneNetworkEntry)->phtInterfaceTable, &(ieKey.leInterfaceTableLink), &pleListEntry); if (dwErr != NO_ERROR) { TRACE1(NETWORK, "Error interface %u has vanished", dwIfIndex); LOGWARN0(INTERFACE_ABSENT, dwErr); break; }
*ppieIfEntry = CONTAINING_RECORD(pleListEntry, INTERFACE_ENTRY, leInterfaceTableLink);
// remove from all other tables, lists... (secondary)
RemoveEntryList(&((*ppieIfEntry)->leIndexSortedListLink));
// initialize pointers to indicate that the entry has been deleted
InitializeListHead(&((*ppieIfEntry)->leInterfaceTableLink)); InitializeListHead(&((*ppieIfEntry)->leIndexSortedListLink)); } while (FALSE); return dwErr; }
BOOL IE_IsPresent ( IN DWORD dwIfIndex) /*++
Routine Description Is interface entry present in interface table?
Locks Assumes shared access to the interface table i.e. (g_ce.pneNetworkEntry)->rwlLock held in read mode.
Arguments dwIfIndex the positive integer used to identify the interface.
Return Value TRUE entry present FALSE o/w
--*/ { DWORD dwErr = NO_ERROR; INTERFACE_ENTRY ieKey;
ZeroMemory(&ieKey, sizeof(INTERFACE_ENTRY)); ieKey.dwIfIndex = dwIfIndex; return HT_IsPresentEntry((g_ce.pneNetworkEntry)->phtInterfaceTable, &(ieKey.leInterfaceTableLink)); }
DWORD IE_Get ( IN DWORD dwIfIndex, OUT PINTERFACE_ENTRY *ppieIfEntry) /*++
Routine Description Retrieves an interface entry from the interface table, the primary address strucutre.
Locks Assumes shared access to the interface table i.e. (g_ce.pneNetworkEntry)->rwlLock held in read mode.
Arguments dwIfIndex the positive integer used to identify the interface. ppieIfEntry address of the pointer to the interface entry
Return Value NO_ERROR success ERROR_INVALID_PARAMETER o/w (interface entry does not exist)
--*/ { DWORD dwErr = NO_ERROR; INTERFACE_ENTRY ieKey; PLIST_ENTRY pleListEntry = NULL;
*ppieIfEntry = NULL; do // breakout loop
{ ZeroMemory(&ieKey, sizeof(INTERFACE_ENTRY)); ieKey.dwIfIndex = dwIfIndex;
dwErr = HT_GetEntry((g_ce.pneNetworkEntry)->phtInterfaceTable, &(ieKey.leInterfaceTableLink), &pleListEntry);
if (dwErr != NO_ERROR) { TRACE1(NETWORK, "Error interface %u has vanished", dwIfIndex); LOGWARN0(INTERFACE_ABSENT, dwErr); break; }
*ppieIfEntry = CONTAINING_RECORD(pleListEntry, INTERFACE_ENTRY, leInterfaceTableLink); } while (FALSE); return dwErr; }
DWORD IE_GetIndex ( IN DWORD dwIfIndex, IN MODE mMode, OUT PINTERFACE_ENTRY *ppieIfEntry) /*++
Routine Description Retrieves an interface entry from the index sorted list, the secondary address strucutre.
Locks Assumes shared access to the index sorted list i.e. (g_ce.pneNetworkEntry)->rwlLock held in read mode.
Arguments dwIfIndex the positive integer used to identify the interface. mMode mode of access (GET_EXACT, GET_FIRST, GET_NEXT) ppieIfEntry address of the pointer to the interface entry
Return Value NO_ERROR success ERROR_NO_MORE_ITEMS o/w
--*/ { INTERFACE_ENTRY ieKey; PLIST_ENTRY pleHead = NULL, pleEntry = NULL;
*ppieIfEntry = NULL;
pleHead = &((g_ce.pneNetworkEntry)->leIndexSortedList); if (IsListEmpty(pleHead)) return ERROR_NO_MORE_ITEMS;
ZeroMemory(&ieKey, sizeof(INTERFACE_ENTRY)); ieKey.dwIfIndex = (mMode is GET_FIRST) ? 0 : dwIfIndex;
// this either gets the exact match or the next entry
FindSortedList(pleHead, &(ieKey.leIndexSortedListLink), &pleEntry, CompareIndexInterfaceEntry);
// reached end of list
if (pleEntry is NULL) { RTASSERT(mMode != GET_FIRST); // should have got the first entry
return ERROR_NO_MORE_ITEMS; }
*ppieIfEntry = CONTAINING_RECORD(pleEntry, INTERFACE_ENTRY, leIndexSortedListLink);
switch (mMode) { case GET_FIRST: return NO_ERROR; case GET_EXACT: // found an exact match
if ((*ppieIfEntry)->dwIfIndex is dwIfIndex) return NO_ERROR; else { *ppieIfEntry = NULL; return ERROR_NO_MORE_ITEMS; }
case GET_NEXT: // found an exact match
if ((*ppieIfEntry)->dwIfIndex is dwIfIndex) { pleEntry = pleEntry->Flink; // get next entry
if (pleEntry is pleHead) // end of list
{ *ppieIfEntry = NULL; return ERROR_NO_MORE_ITEMS; }
*ppieIfEntry = CONTAINING_RECORD(pleEntry, INTERFACE_ENTRY, leIndexSortedListLink); }
return NO_ERROR;
default: RTASSERT(FALSE); // never reached
} }
DWORD IE_BindInterface ( IN PINTERFACE_ENTRY pie, IN PIP_ADAPTER_BINDING_INFO pBinding) /*++
Routine Description Binds an interface. Locks Assumes the interface entry is locked for writing. Arguments pie pointer to the interface entry pBinding info about the addresses on the interface
Return Value NO_ERROR success Error Code o/w
--*/ { DWORD dwErr = NO_ERROR; ULONG i, j; do // breakout loop
{ // fail if the interface is already bound
if (INTERFACE_IS_BOUND(pie)) { dwErr = ERROR_INVALID_PARAMETER; TRACE2(NETWORK, "Error interface %S (%u) is already bound", pie->pwszIfName, pie->dwIfIndex); break; }
dwErr = BE_CreateTable (pBinding, &(pie->pbeBindingTable), &(pie->ipAddress)); if (dwErr != NO_ERROR) break;
pie->ulNumBindings = pBinding->AddressCount;
// set the "bound" flag
pie->dwFlags |= IEFLAG_BOUND; } while (FALSE); return dwErr; }
DWORD IE_UnBindInterface ( IN PINTERFACE_ENTRY pie) /*++
Routine Description UnBinds an interface. Locks Assumes the interface entry is locked for writing. Arguments pie pointer to the interface entry
Return Value NO_ERROR success Error Code o/w
--*/ { DWORD dwErr = NO_ERROR; do // breakout loop
{ // fail if the interface is already unbound
if (INTERFACE_IS_UNBOUND(pie)) { dwErr = ERROR_INVALID_PARAMETER; TRACE2(NETWORK, "interface %S (%u) already unbound", pie->pwszIfName, pie->dwIfIndex); break; }
// clear the "bound" flag
pie->dwFlags &= ~IEFLAG_BOUND;
IP_ASSIGN(&(pie->ipAddress), IP_LOWEST); BE_DestroyTable(pie->pbeBindingTable); pie->pbeBindingTable = NULL; pie->ulNumBindings = 0; } while (FALSE);
return dwErr; }
DWORD IE_ActivateInterface ( IN PINTERFACE_ENTRY pie) /*++
Routine Description Activates an interface by creating a socket and starting a timer. The socket is bound to the interface address. Interface is assumed to have atleast one binding.
Locks Assumes the interface entry is locked for writing. Arguments pie pointer to the interface entry
Return Value NO_ERROR success Error Code o/w
--*/ { DWORD dwErr = NO_ERROR; do // breakout loop
{ // fail if the interface is already active
if (INTERFACE_IS_ACTIVE(pie)) { dwErr = ERROR_INVALID_PARAMETER; TRACE0(NETWORK, "Interface already active"); break; }
// set the "active" flag
pie->dwFlags |= IEFLAG_ACTIVE; // create a socket for the interface
dwErr = SocketCreate(pie->ipAddress, pie->hReceiveEvent, &(pie->sRawSocket)); if (dwErr != NO_ERROR) { TRACE1(NETWORK, "Error creating socket for %s", INET_NTOA(pie->ipAddress)); break; } // start timer for sending protocol packets
CREATE_TIMER(&pie->hPeriodicTimer , NM_CallbackPeriodicTimer, (PVOID) pie->dwIfIndex, PERIODIC_INTERVAL, &dwErr); if (dwErr != NO_ERROR) break; } while (FALSE);
if (dwErr != NO_ERROR) { TRACE3(NETWORK, "Error %u activating interface %S (%u)", dwErr, pie->pwszIfName, pie->dwIfIndex); IE_DeactivateInterface(pie); } return dwErr; }
DWORD IE_DeactivateInterface ( IN PINTERFACE_ENTRY pie) /*++
Routine Description Deactivates an interface by stopping the timer and destroying the socket. Locks Assumes the interface entry is locked for writing. Arguments pie pointer to the interface entry
Return Value NO_ERROR success Error Code o/w
--*/ { DWORD dwErr = NO_ERROR; do // breakout loop
{ // fail if the interface is already inactive
if (INTERFACE_IS_INACTIVE(pie)) { dwErr = ERROR_INVALID_PARAMETER; TRACE2(NETWORK, "interface %S (%u) already inactive", pie->pwszIfName, pie->dwIfIndex); break; }
// stop the timer
if (pie->hPeriodicTimer) DELETE_TIMER(pie->hPeriodicTimer, &dwErr); pie->hPeriodicTimer = NULL;
// destroy the socket for the interface
dwErr = SocketDestroy(pie->sRawSocket); pie->sRawSocket = INVALID_SOCKET;
// clear the "active" flag
pie->dwFlags &= ~IEFLAG_ACTIVE; } while (FALSE);
return dwErr; }
DWORD NE_Create ( OUT PNETWORK_ENTRY *ppneNetworkEntry) /*++
Routine Description Creates a network entry.
Locks None
Arguments ppneNetworkEntry pointer to the network entry address
Return Value NO_ERROR if success Failure code o/w
--*/ { DWORD dwErr = NO_ERROR; PNETWORK_ENTRY pneEntry; // scratch
// validate parameters
if (!ppneNetworkEntry) return ERROR_INVALID_PARAMETER;
*ppneNetworkEntry = NULL; do // breakout loop
{ // allocate and zero out the network entry structure
MALLOC(&pneEntry, sizeof(NETWORK_ENTRY), &dwErr); if (dwErr != NO_ERROR) break;
// initialize fields with default values
// pneEntry->rwlLock zero'ed out
// pneEntry->phtInterfaceTable = NULL;
InitializeListHead(&(pneEntry->leIndexSortedList)); // initialize the read-write lock
dwErr = CREATE_READ_WRITE_LOCK(&(pneEntry->rwlLock)); if (dwErr != NO_ERROR) { TRACE1(NETWORK, "Error %u creating read-write-lock", dwErr); LOGERR0(CREATE_RWL_FAILED, dwErr); break; }
// allocate the interface table
dwErr = HT_Create(GLOBAL_HEAP, INTERFACE_TABLE_BUCKETS, DisplayInterfaceEntry, FreeInterfaceEntry, HashInterfaceEntry, CompareInterfaceEntry, &(pneEntry->phtInterfaceTable)); if (dwErr != NO_ERROR) { TRACE1(NETWORK, "Error %u creating hash-table", dwErr); LOGERR0(CREATE_HASHTABLE_FAILED, dwErr); break; }
*ppneNetworkEntry = pneEntry; } while (FALSE);
if (dwErr != NO_ERROR) { // something went wrong, so cleanup.
TRACE0(NETWORK, "Failed to create nework entry"); NE_Destroy(pneEntry); pneEntry = NULL; }
return dwErr; }
DWORD NE_Destroy ( IN PNETWORK_ENTRY pneNetworkEntry) /*++
Routine Description Destroys a network entry.
Locks Assumes exclusive access to rwlLock by virtue of of no competing threads.
Arguments pneNetworkEntry pointer to the network entry
Return Value NO_ERROR always
--*/ { if (!pneNetworkEntry) return NO_ERROR;
// deallocate the interface table...
// this removes the interface entries from all secondary access
// structures (IndexSortedList, ...) as well since all of them
// share interface entries by containing pointers to the same object.
HT_Destroy(GLOBAL_HEAP, pneNetworkEntry->phtInterfaceTable); pneNetworkEntry->phtInterfaceTable = NULL;
RTASSERT(IsListEmpty(&(pneNetworkEntry->leIndexSortedList))); // delete read-write-lock
if (READ_WRITE_LOCK_CREATED(&(pneNetworkEntry->rwlLock))) DELETE_READ_WRITE_LOCK(&(pneNetworkEntry->rwlLock));
// deallocate the network entry structure
FREE(pneNetworkEntry); return NO_ERROR; }
#ifdef DEBUG
DWORD NE_Display ( IN PNETWORK_ENTRY pneNetworkEntry) /*++
Routine Description Displays a network entry.
Locks Acquires shared pneNetworkEntry->rwlLock Releases pneNetworkEntry->rwlLock
Arguments pne pointer to the network entry to be displayed
Return Value NO_ERROR always
--*/ { if (!pneNetworkEntry) return NO_ERROR;
ACQUIRE_READ_LOCK(&(pneNetworkEntry->rwlLock));
TRACE0(NETWORK, "Network Entry...");
TRACE1(NETWORK, "Interface Table Size %u", HT_Size(pneNetworkEntry->phtInterfaceTable));
TRACE0(NETWORK, "Interface Table..."); HT_Display(pneNetworkEntry->phtInterfaceTable);
TRACE0(NETWORK, "Index Sorted List..."); MapCarList(&(pneNetworkEntry->leIndexSortedList), DisplayIndexInterfaceEntry); RELEASE_READ_LOCK(&(pneNetworkEntry->rwlLock));
return NO_ERROR; } #endif // DEBUG
|