|
|
//============================================================================
// Copyright (c) 1995, Microsoft Corporation
//
// File: table.c
//
// History:
// Abolade Gbadegesin August 31, 1995 Created
//
// Interface table and stats tables management routines
//============================================================================
#include "pchbootp.h"
//----------------------------------------------------------------------------
// Function: CreateIfTable
//
// Initializes an interface table.
//----------------------------------------------------------------------------
DWORD CreateIfTable( PIF_TABLE pTable ) {
DWORD dwErr; PLIST_ENTRY ple, plend;
//
// return an error if the table is already created
//
if ( IF_TABLE_CREATED(pTable) ) {
TRACE0( IF, "interface table already initialized" );
return ERROR_ALREADY_EXISTS; }
//
// initialize the by-address and by-index lists of interfaces
//
InitializeListHead( &pTable->IT_ListByAddress ); InitializeListHead(&pTable->IT_ListByIndex);
//
// initialize the by-index hash-table of interfaces
//
plend = pTable->IT_HashTableByIndex + IF_HASHTABLE_SIZE;
for ( ple = pTable->IT_HashTableByIndex; ple < plend; ple++ ) { InitializeListHead( ple ); }
//
// initialize the lock which will protect the table
//
dwErr = NO_ERROR;
try { CREATE_READ_WRITE_LOCK( &pTable->IT_RWL ); } except ( EXCEPTION_EXECUTE_HANDLER ) {
dwErr = GetExceptionCode( );
TRACE1( IF, "error %d initializing interface table lock", dwErr );
}
if ( dwErr == NO_ERROR ) { pTable->IT_Created = 0x12345678; }
return dwErr;
}
//----------------------------------------------------------------------------
// Function: DeleteIfTable
//
// Deinitializes an interface table, and releases all resources used.
// Assumes the table is locked exclusively
//----------------------------------------------------------------------------
DWORD DeleteIfTable( PIF_TABLE pTable ) {
DWORD dwErr; PIF_TABLE_ENTRY pite; PLIST_ENTRY ple, plend, phead;
//
// clear the creation flag on the table
//
pTable->IT_Created = 0;
//
// free memory used by all entries
//
plend = pTable->IT_HashTableByIndex + IF_HASHTABLE_SIZE;
for ( phead = pTable->IT_HashTableByIndex; phead < plend; phead++ ) {
while ( !IsListEmpty( phead ) ) {
ple = RemoveHeadList( phead ); pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, ITE_HTLinkByIndex);
if (IF_IS_BOUND(pite)) {
DeleteIfSocket(pite);
if (IF_IS_ENABLED(pite)) { RemoveEntryList(&pite->ITE_LinkByAddress); }
BOOTP_FREE(pite->ITE_Binding); } if (pite->ITE_Config) { BOOTP_FREE(pite->ITE_Config); }
BOOTP_FREE( pite ); } }
dwErr = NO_ERROR;
try { DELETE_READ_WRITE_LOCK( &pTable->IT_RWL ); } except( EXCEPTION_EXECUTE_HANDLER ) {
dwErr = GetExceptionCode( );
TRACE1( IF, "error %d deleting interface table lock", dwErr ); }
return dwErr; }
//----------------------------------------------------------------------------
// Function: CreateIfEntry
//
// Allocates and initializes an entry for an interface in the table,
// using the supplied configuration. Assumes table is locked exclusively.
//----------------------------------------------------------------------------
DWORD CreateIfEntry( PIF_TABLE pTable, DWORD dwIndex, PVOID pConfig ) {
DWORD dwErr, dwSize; PIF_TABLE_ENTRY pite; PLIST_ENTRY ple, phead; PIPBOOTP_IF_CONFIG picsrc, picdst;
dwErr = NO_ERROR;
do { // error breakout loop
//
// see if the interface already exists
//
pite = GetIfByIndex( pTable, dwIndex );
if ( pite != NULL ) {
TRACE1( IF, "interface %d already exists", dwIndex );
dwErr = ERROR_ALREADY_EXISTS; pite = NULL; break; }
//
// now allocate memory for the interface
//
pite = BOOTP_ALLOC( sizeof(IF_TABLE_ENTRY) ); if ( pite == NULL ) {
dwErr = ERROR_NOT_ENOUGH_MEMORY; TRACE2( IF, "error %d allocating %d bytes for interface entry", dwErr, sizeof(IF_TABLE_ENTRY) ); LOGERR0(HEAP_ALLOC_FAILED, dwErr);
break; }
//
// initialize struct fields
//
pite->ITE_Index = dwIndex;
//
// We come up in disabled state
//
pite->ITE_Flags = 0;
pite->ITE_Sockets = NULL; pite->ITE_Config = NULL;
//
// get the size of the configuration block
//
picsrc = (PIPBOOTP_IF_CONFIG)pConfig;
dwSize = IC_SIZEOF( picsrc );
//
// validate the configuration parameters
//
dwErr = ValidateIfConfig(pConfig); if (dwErr != NO_ERROR) { TRACE1(IF, "invalid config specified for interface %d", dwIndex); break; }
//
// allocate space for the configuration
//
picdst = BOOTP_ALLOC( dwSize );
if ( picdst == NULL ) {
dwErr = ERROR_NOT_ENOUGH_MEMORY; TRACE2( IF, "error %d allocating %d bytes for interface configuration", dwErr, dwSize ); LOGERR0(HEAP_ALLOC_FAILED, dwErr);
pite->ITE_Config = NULL; break; }
//
// copy the configuration
//
CopyMemory(picdst, picsrc, dwSize);
pite->ITE_Config = picdst;
//
// initialize binding information and interface stats
//
pite->ITE_Binding = NULL; ZeroMemory(&pite->ITE_Stats, sizeof(IPBOOTP_IF_STATS));
//
// insert the interface in the hash table
//
phead = pTable->IT_HashTableByIndex + IF_HASHVALUE( dwIndex );
InsertHeadList( phead, &pite->ITE_HTLinkByIndex );
//
// insert the interface in the list ordered by index
//
phead = &pTable->IT_ListByIndex; for (ple = phead->Flink; ple != phead; ple = ple->Flink) { PIF_TABLE_ENTRY ptemp;
ptemp = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, ITE_LinkByIndex); if (pite->ITE_Index < ptemp->ITE_Index) { break; } }
InsertTailList(ple, &pite->ITE_LinkByIndex);
} while( FALSE );
if ( dwErr != NO_ERROR && pite != NULL ) {
if ( pite->ITE_Config != NULL ) { BOOTP_FREE( pite->ITE_Config ); }
BOOTP_FREE( pite ); }
return dwErr; }
//----------------------------------------------------------------------------
// Function: DeleteIfEntry
//
// Removes an interface from the interface table.
// Assumes the table is locked exclusively.
//----------------------------------------------------------------------------
DWORD DeleteIfEntry( PIF_TABLE pTable, DWORD dwIndex ) {
DWORD dwErr; PIF_TABLE_ENTRY pite;
//
// make certain the interface exists
//
pite = GetIfByIndex( pTable, dwIndex );
if ( pite == NULL ) { TRACE1( IF, "deleting interface: interface %d not found", dwIndex ); return ERROR_INVALID_PARAMETER; }
//
// cleanup the socket depending on its state
//
if (IF_IS_BOUND(pite)) {
DeleteIfSocket(pite);
if (IF_IS_ENABLED(pite)) { RemoveEntryList(&pite->ITE_LinkByAddress); }
BOOTP_FREE(pite->ITE_Binding); }
//
// remove the entry from the hash table and the list sorted by index
//
RemoveEntryList( &pite->ITE_HTLinkByIndex ); RemoveEntryList( &pite->ITE_LinkByIndex );
BOOTP_FREE( pite->ITE_Config ); BOOTP_FREE( pite );
return NO_ERROR; }
//----------------------------------------------------------------------------
// Function: ValidateIfConfig
//
// Validates the contents of the specified IPBOOTP_IF_CONFIG structure.
//----------------------------------------------------------------------------
DWORD ValidateIfConfig( PIPBOOTP_IF_CONFIG pic ) {
CHAR szStr[12];
if (pic->IC_RelayMode != IPBOOTP_RELAY_ENABLED && pic->IC_RelayMode != IPBOOTP_RELAY_DISABLED) {
TRACE1( IF, "Invalid value for relay mode %d", pic->IC_RelayMode );
_ltoa(pic->IC_RelayMode, szStr, 10);
LOGERR2( INVALID_IF_CONFIG, "Relay Mode", szStr, ERROR_INVALID_PARAMETER ); return ERROR_INVALID_PARAMETER; }
if (pic->IC_MaxHopCount > IPBOOTP_MAX_HOP_COUNT) { TRACE1( IF, "Invalid value for max hop count %d", pic->IC_MaxHopCount );
_ltoa(pic->IC_MaxHopCount, szStr, 10);
LOGERR2( INVALID_IF_CONFIG, "Max Hop Count", szStr, ERROR_INVALID_PARAMETER ); return ERROR_INVALID_PARAMETER; }
return NO_ERROR; }
//----------------------------------------------------------------------------
// Function: CreateIfSocket
//
// Initializes the socket for an interface. Assumes the interface table lock
// is held exclusively.
//----------------------------------------------------------------------------
DWORD CreateIfSocket( PIF_TABLE_ENTRY pITE ) {
SOCKADDR_IN sinaddr; PIPBOOTP_IF_BINDING pib; PIPBOOTP_IP_ADDRESS paddr; DWORD i, dwErr, dwOption;
pib = pITE->ITE_Binding; paddr = IPBOOTP_IF_ADDRESS_TABLE(pib);
//
// allocate memory for the array of sockets
//
pITE->ITE_Sockets = BOOTP_ALLOC(pib->IB_AddrCount * sizeof(SOCKET));
if (pITE->ITE_Sockets == NULL) {
dwErr = ERROR_NOT_ENOUGH_MEMORY; TRACE3( IF, "error %d allocating %d bytes for sockets on interface %d", dwErr, pib->IB_AddrCount * sizeof(SOCKET), pITE->ITE_Index ); LOGERR0(HEAP_ALLOC_FAILED, dwErr);
return dwErr; }
//
// initialize the array
//
for (i = 0; i < pib->IB_AddrCount; i++) { pITE->ITE_Sockets[i] = INVALID_SOCKET; }
//
// go through the table of addresses in the binding,
// creating a socket for each address
//
for (i = 0; i < pib->IB_AddrCount; i++, paddr++) {
//
// create a socket
//
pITE->ITE_Sockets[i] = WSASocket( AF_INET, SOCK_DGRAM, 0, NULL, 0, 0 );
if (pITE->ITE_Sockets[i] == INVALID_SOCKET) {
LPSTR lpszAddr;
dwErr = WSAGetLastError( ); lpszAddr = INET_NTOA( paddr->IA_Address ); TRACE3( IF, "error %d creating socket for interface %d (%s)", dwErr, pITE->ITE_Index, lpszAddr ); LOGERR1(CREATE_SOCKET_FAILED, lpszAddr, dwErr);
break; }
//
// enable address re-use on this socket
//
dwOption = 1; dwErr = setsockopt( pITE->ITE_Sockets[i], SOL_SOCKET, SO_REUSEADDR, (PBYTE)&dwOption, sizeof( DWORD ) );
if ( dwErr == SOCKET_ERROR ) {
//
// this is a non-fatal error, so print a warning,
// but continue initializing the socket
//
dwErr = WSAGetLastError( ); TRACE3( IF, "error %d enabling address re-use for interface %d (%s)", dwErr, pITE->ITE_Index, INET_NTOA( paddr->IA_Address ) ); }
//
// enable broadcasting on the socket
//
dwOption = 1; dwErr = setsockopt( pITE->ITE_Sockets[i], SOL_SOCKET, SO_BROADCAST, (PBYTE)&dwOption, sizeof( DWORD ) );
if ( dwErr == SOCKET_ERROR ) {
LPSTR lpszAddr;
dwErr = WSAGetLastError( ); lpszAddr = INET_NTOA( paddr->IA_Address ); TRACE3( IF, "error %d enabling broadcast for interface %d (%s)", dwErr, pITE->ITE_Index, lpszAddr ); LOGERR1(ENABLE_BROADCAST_FAILED, lpszAddr, dwErr);
break; }
//
// bind to the address and the BOOTP Server port
//
sinaddr.sin_port = htons( IPBOOTP_SERVER_PORT ); sinaddr.sin_family = AF_INET; sinaddr.sin_addr.s_addr = paddr->IA_Address; dwErr = bind( pITE->ITE_Sockets[i], (PSOCKADDR)&sinaddr, sizeof(SOCKADDR_IN) );
if ( dwErr == SOCKET_ERROR ) {
dwErr = WSAGetLastError( ); TRACE3( IF, "error %d binding interface %d (%s) to BOOTP port", dwErr, pITE->ITE_Index, INET_NTOA( paddr->IA_Address ) );
break; }
dwErr = NO_ERROR;
}
if ( i < pib->IB_AddrCount ) {
//
// an error occurred, so clean up
//
DeleteIfSocket( pITE ); }
return dwErr; }
//----------------------------------------------------------------------------
// Function: DeleteIfSocket
//
// This function closes the socket used by an interface.
// It assumes the interface table lock is held exclusively.
//----------------------------------------------------------------------------
DWORD DeleteIfSocket( PIF_TABLE_ENTRY pITE ) {
DWORD i, dwErr = NO_ERROR; PIPBOOTP_IF_BINDING pib; PIPBOOTP_IP_ADDRESS paddr;
pib = pITE->ITE_Binding; if (!pib) { return ERROR_INVALID_PARAMETER; }
paddr = IPBOOTP_IF_ADDRESS_TABLE(pib);
for (i = 0; i < pib->IB_AddrCount; i++) {
if ( pITE->ITE_Sockets[i] == INVALID_SOCKET ) { continue; }
dwErr = closesocket( pITE->ITE_Sockets[i] ); if ( dwErr == SOCKET_ERROR ) { dwErr = WSAGetLastError( ); TRACE3( IF, "error %d closing socket for interface %d (%s)", dwErr, pITE->ITE_Index, INET_NTOA( paddr->IA_Address ) ); } }
BOOTP_FREE(pITE->ITE_Sockets); pITE->ITE_Sockets = NULL;
return dwErr; }
//----------------------------------------------------------------------------
// Function: BindIfEntry
//
// This function updates the binding information for an interface.
// It assumes the interface table is locked for writing.
//----------------------------------------------------------------------------
DWORD BindIfEntry( PIF_TABLE pTable, DWORD dwIndex, PIP_ADAPTER_BINDING_INFO pBinding ) {
DWORD i, dwErr = NO_ERROR, dwSize; PIF_TABLE_ENTRY pite = (PIF_TABLE_ENTRY) NULL; PIPBOOTP_IF_BINDING pib = (PIPBOOTP_IF_BINDING) NULL; PIPBOOTP_IP_ADDRESS paddr = (PIPBOOTP_IP_ADDRESS) NULL;
do {
//
// retrieve the interface to be bound
//
pite = GetIfByIndex( pTable, dwIndex );
if ( pite == NULL ) {
TRACE1( IF, "binding interface: interface %d not found", dwIndex ); dwErr = ERROR_INVALID_PARAMETER;
break; }
//
// make sure the interface is not bound
//
if ( IF_IS_BOUND(pite) ) {
TRACE1( IF, "interface %d is already bound", dwIndex );
break; }
//
// make sure there is at least one address
//
if (pBinding->AddressCount == 0) { break; }
dwSize = sizeof(IPBOOTP_IF_BINDING) + pBinding->AddressCount * sizeof(IPBOOTP_IP_ADDRESS);
//
// allocate memory to store the binding
// in our format
//
pib = BOOTP_ALLOC(dwSize);
if (pib == NULL) {
dwErr = ERROR_NOT_ENOUGH_MEMORY; TRACE3( IF, "error %d allocating %d bytes for binding on interface %d", dwErr, dwSize, dwIndex ); LOGERR0(HEAP_ALLOC_FAILED, dwErr);
break; }
//
// convert the binding into our format
//
pib->IB_AddrCount = pBinding->AddressCount; paddr = IPBOOTP_IF_ADDRESS_TABLE(pib); for (i = 0; i < pib->IB_AddrCount; i++, paddr++) { paddr->IA_Address = pBinding->Address[i].Address; paddr->IA_Netmask = pBinding->Address[i].Mask; }
//
// save the binding in the interface entry
//
pite->ITE_Binding = pib;
dwErr = CreateIfSocket(pite);
if (dwErr != NO_ERROR) { break; }
pite->ITE_Flags |= ITEFLAG_BOUND;
//
// if the interface is also enabled, it is now active
// so we put it on the active list
//
if (IF_IS_ENABLED(pite)) {
//
// place interface on the list of active interfaces
//
dwErr = InsertIfByAddress(pTable, pite);
if (dwErr != NO_ERROR) {
TRACE2( IF, "error %d inserting interface %d in active list", dwErr, dwIndex );
pite->ITE_Flags &= ~ITEFLAG_BOUND; DeleteIfSocket( pite );
break; }
//
// request notification of input events from Winsock
//
paddr = IPBOOTP_IF_ADDRESS_TABLE(pib);
for (i = 0; i < pib->IB_AddrCount; i++, paddr++) {
dwErr = WSAEventSelect( pite->ITE_Sockets[i], ig.IG_InputEvent, FD_READ );
if (dwErr != NO_ERROR) { LPSTR lpszAddr = INET_NTOA(paddr->IA_Address); TRACE3( IF, "WSAEventSelect returned %d for interface %d (%s)", dwErr, dwIndex, lpszAddr ); LOGERR1(EVENTSELECT_FAILED, lpszAddr, dwErr); RemoveEntryList(&pite->ITE_LinkByAddress); pite->ITE_Flags &= ~ITEFLAG_BOUND;
DeleteIfSocket( pite ); break; } }
if (i < pib->IB_AddrCount) { break; } }
} while(FALSE);
if (dwErr != NO_ERROR) {
if (pib) { BOOTP_FREE(pib); }
if (pite) { pite->ITE_Binding = NULL; } }
return dwErr; }
//----------------------------------------------------------------------------
// Function: UnBindIfEntry
//
// removes the binding for the specified interface.
// Assumes the interface table is locked for writing.
//----------------------------------------------------------------------------
DWORD UnBindIfEntry( PIF_TABLE pTable, DWORD dwIndex ) {
DWORD dwErr; PIF_TABLE_ENTRY pite;
dwErr = NO_ERROR;
do {
//
// retrieve the interface to be unbound
//
pite = GetIfByIndex( pTable, dwIndex ); if ( pite == NULL ) {
TRACE1(IF, "unbinding interface: interface %d not found", dwIndex); return ERROR_INVALID_PARAMETER; }
//
// quit if interface is already unbound
//
if ( IF_IS_UNBOUND( pite ) ) {
TRACE1( IF, "interface %d is already unbound", dwIndex );
break; }
//
// if the interface was active (i.e. bound and enabled)
// it is no longer, so remove it from the active list
//
if ( IF_IS_ENABLED( pite ) ) {
RemoveEntryList( &pite->ITE_LinkByAddress ); } pite->ITE_Flags &= ~ITEFLAG_BOUND; DeleteIfSocket( pite );
BOOTP_FREE(pite->ITE_Binding); pite->ITE_Binding = NULL;
} while(FALSE);
return dwErr; }
//----------------------------------------------------------------------------
// Function: EnableIfEntry
//
// This function initiates BOOTP relay activity on the specified interface.
// It assumes the interface table lock is held exclusively.
//----------------------------------------------------------------------------
DWORD EnableIfEntry( PIF_TABLE pTable, DWORD dwIndex ) {
DWORD i, dwErr; PIF_TABLE_ENTRY pite; PIPBOOTP_IF_BINDING pib; PIPBOOTP_IP_ADDRESS paddr;
dwErr = NO_ERROR;
do {
//
// make certain the interface exists
//
pite = GetIfByIndex( pTable, dwIndex ); if ( pite == NULL ) {
TRACE1( IF, "enabling interface: interface %d not found", dwIndex ); dwErr = ERROR_INVALID_PARAMETER;
break; }
//
// make certain the interface is disabled
//
if ( IF_IS_ENABLED( pite ) ) {
TRACE1( IF, "interface %d is already enabled", dwIndex );
//
// He shouldnt call us twice but we will still handle it
//
break; } pite->ITE_Flags |= ITEFLAG_ENABLED;
//
// if the interface was already bound, it is now active,
// so place it on the active list
//
if ( IF_IS_BOUND( pite ) ) { //
// insert the interface in the by-address list of interfaces
//
dwErr = InsertIfByAddress( pTable, pite );
if (dwErr != NO_ERROR) {
TRACE2( IF, "error %d inserting interface %d in active list", dwErr, dwIndex );
pite->ITE_Flags &= ~ITEFLAG_ENABLED;
break; }
pib = pite->ITE_Binding; paddr = IPBOOTP_IF_ADDRESS_TABLE(pib);
//
// request notification of input events from Winsock
//
for (i = 0; i < pib->IB_AddrCount; i++, paddr++) {
dwErr = WSAEventSelect( pite->ITE_Sockets[i], ig.IG_InputEvent, FD_READ ); if (dwErr != NO_ERROR) { INT j; LPSTR lpszAddr = INET_NTOA(paddr->IA_Address);
TRACE3( IF, "WSAEventSelect returned %d for interface %d (%s)", dwErr, dwIndex, lpszAddr ); LOGERR1(EVENTSELECT_FAILED, lpszAddr, dwErr); RemoveEntryList(&pite->ITE_LinkByAddress); pite->ITE_Flags &= ~ITEFLAG_ENABLED; //
// clear the requests for events
//
for (j = i - 1; j >= 0; j--) { dwErr = WSAEventSelect( pite->ITE_Sockets[j], ig.IG_InputEvent, 0 ); }
break; } }
if (i < pib->IB_AddrCount) { break; } } } while(FALSE);
return dwErr; }
//----------------------------------------------------------------------------
// Function: ConfigureIfEntry
//
// modifies the configuration for an already-existing interface.
// This assumes the table is locked for writing.
//----------------------------------------------------------------------------
DWORD ConfigureIfEntry( PIF_TABLE pTable, DWORD dwIndex, PVOID pConfig ) {
DWORD dwErr, dwSize; PIF_TABLE_ENTRY pite; PIPBOOTP_IF_CONFIG picsrc, picdst;
//
// retrieve the interface to be reconfigured
//
pite = GetIfByIndex(pTable, dwIndex); if (pite == NULL) {
TRACE1( IF, "configuring interface: interface %d not found", dwIndex );
return ERROR_INVALID_PARAMETER; }
do { // breakout loop
//
// compute the size needed to store the new configuration
//
picsrc = (PIPBOOTP_IF_CONFIG)pConfig; dwSize = IC_SIZEOF(picsrc);
//
// make sure the new parameters are valid
//
dwErr = ValidateIfConfig(pConfig); if (dwErr != NO_ERROR) { TRACE1(IF, "invalid config specified for interface %d", dwIndex); break; }
//
// allocate space for the new configuration
//
picdst = BOOTP_ALLOC(dwSize); if (picdst == NULL) {
dwErr = ERROR_NOT_ENOUGH_MEMORY; TRACE3( IF, "error %d allocating %d bytes for interface %d config", dwErr, dwSize, dwIndex ); LOGERR0(HEAP_ALLOC_FAILED, dwErr);
break; }
CopyMemory(picdst, picsrc, dwSize);
if (pite->ITE_Config) { BOOTP_FREE(pite->ITE_Config); } pite->ITE_Config = picdst;
dwErr = NO_ERROR;
} while(FALSE);
return dwErr; }
//----------------------------------------------------------------------------
// Function: DisableIfEntry
//
// This function stops RIP activaty on the specified interface.
// It assumes the interface table is locked for writing.
//----------------------------------------------------------------------------
DWORD DisableIfEntry( PIF_TABLE pTable, DWORD dwIndex ) {
DWORD i, dwErr; PIF_TABLE_ENTRY pite; PIPBOOTP_IF_BINDING pib; PIPBOOTP_IP_ADDRESS paddr;
dwErr = NO_ERROR;
do { //
// make certain the interface exists
//
pite = GetIfByIndex( pTable, dwIndex ); if ( pite == NULL ) {
TRACE1( IF, "disabling interface: interface %d not found", dwIndex );
dwErr = ERROR_INVALID_PARAMETER; break; }
//
// make certain the interface is enabled
//
if ( IF_IS_DISABLED( pite ) ) {
TRACE1( IF, "interface %d is already disabled", dwIndex );
//
// This is NOT AN ERROR.
//
break; }
//
// if the interface was active (i.e. bound and enabled)
// it isn't anymore, so deactivate it here.
//
if ( IF_IS_BOUND( pite ) ) {
//
// remove the interface from the by-address list
//
RemoveEntryList( &pite->ITE_LinkByAddress );
//
// tell Winsock to stop notifying us of input events
//
pib = pite->ITE_Binding; paddr = IPBOOTP_IF_ADDRESS_TABLE(pib);
for (i = 0; i < pib->IB_AddrCount; i++) { WSAEventSelect(pite->ITE_Sockets[i], ig.IG_InputEvent, 0); } }
//
// clear the enabled flag on the interface
//
pite->ITE_Flags &= ~ITEFLAG_ENABLED;
} while(FALSE);
return dwErr; }
//----------------------------------------------------------------------------
// Function: GetIfByIndex
//
// returns the interface with the given index.
// Assumes the table is locked.
//----------------------------------------------------------------------------
PIF_TABLE_ENTRY GetIfByIndex( PIF_TABLE pTable, DWORD dwIndex ) {
DWORD dwErr; PIF_TABLE_ENTRY pite, pitefound = NULL; PLIST_ENTRY ple, phead;
phead = pTable->IT_HashTableByIndex + IF_HASHVALUE( dwIndex );
for ( ple = phead->Flink; ple != phead; ple = ple->Flink ) { pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, ITE_HTLinkByIndex); if (pite->ITE_Index == dwIndex ) { pitefound = pite; break; } }
return pitefound; }
//----------------------------------------------------------------------------
// Function: GetIfByAddress
//
// Returns the interface bound with the given address.
// Assumes the table is locked for reading or writing.
//----------------------------------------------------------------------------
PIF_TABLE_ENTRY GetIfByAddress( PIF_TABLE pTable, DWORD dwAddress, PDWORD pdwAddrIndex ) {
INT cmp; DWORD i, dwErr; PLIST_ENTRY ple, phead; PIPBOOTP_IF_BINDING pib; PIPBOOTP_IP_ADDRESS paddr; PIF_TABLE_ENTRY pite, pitefound = NULL;
if ( pdwAddrIndex ) { *pdwAddrIndex = 0; }
phead = &pTable->IT_ListByAddress;
for ( ple = phead->Flink; ple != phead; ple = ple->Flink ) {
pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, ITE_LinkByAddress);
pib = pite->ITE_Binding;
paddr = IPBOOTP_IF_ADDRESS_TABLE(pib);
for (i = 0; i < pib->IB_AddrCount; i++, paddr++) { if ( dwAddress == paddr->IA_Address ) { pitefound = pite; break; } }
if (pitefound) { if (pdwAddrIndex) { *pdwAddrIndex = i; } break; } }
return pitefound; }
//----------------------------------------------------------------------------
// Function: GetIfByListIndex
//
// This function is similar to GetIfByAddress in that it supports
// three modes of retrieval, but it is different in that it looks
// in the list of interfaces sorted by index.
//----------------------------------------------------------------------------
PIF_TABLE_ENTRY GetIfByListIndex( PIF_TABLE pTable, DWORD dwIndex, DWORD dwGetMode, PDWORD pdwErr ) {
PIF_TABLE_ENTRY pite; PLIST_ENTRY ple, phead;
if (pdwErr != NULL) { *pdwErr = NO_ERROR; }
phead = &pTable->IT_ListByIndex; pite = NULL;
//
// return record at head of list if mode is GETMODE_FIRST;
// if list is empty, return NULL.
//
if (dwGetMode == GETMODE_FIRST) { if (phead->Flink == phead) { return NULL; } else { ple = phead->Flink; return CONTAINING_RECORD(ple, IF_TABLE_ENTRY, ITE_LinkByIndex); } }
//
// get the entry requested
//
pite = GetIfByIndex(pTable, dwIndex);
//
// if mode is GETMODE_NEXT, return the item after the one retrieved
//
if (dwGetMode == GETMODE_NEXT && pite != NULL) {
ple = &pite->ITE_LinkByIndex;
//
// if entry found is last one, return NULL,
// otherwise return the following entry
//
if (ple->Flink == phead) { if (pdwErr != NULL) { *pdwErr = ERROR_NO_MORE_ITEMS; } pite = NULL; } else { ple = ple->Flink; pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, ITE_LinkByIndex); } }
return pite; }
//----------------------------------------------------------------------------
// Function: InsertIfByAddress
//
// This function inserts an interface in the list sorted by index
// Assumes the table is locked for writing.
//----------------------------------------------------------------------------
DWORD InsertIfByAddress( PIF_TABLE pTable, PIF_TABLE_ENTRY pITE ) {
INT cmp; PIF_TABLE_ENTRY pite; PIPBOOTP_IF_BINDING pib; PIPBOOTP_IP_ADDRESS paddr; PLIST_ENTRY pfl, phead; DWORD dwAddress, dwEntryAddr;
if ( pITE == NULL || pITE->ITE_Binding == NULL ) { return ERROR_INVALID_PARAMETER; } pib = pITE->ITE_Binding; paddr = IPBOOTP_IF_ADDRESS_TABLE(pib); dwAddress = paddr->IA_Address;
phead = &pTable->IT_ListByAddress;
for ( pfl = phead->Flink; pfl != phead; pfl = pfl->Flink ) {
pite = CONTAINING_RECORD( pfl, IF_TABLE_ENTRY, ITE_LinkByAddress );
paddr = IPBOOTP_IF_ADDRESS_TABLE(pite->ITE_Binding); dwEntryAddr = paddr->IA_Address; if ( INET_CMP( dwAddress, dwEntryAddr, cmp ) < 0 ) { break; } else if (cmp == 0) { return ERROR_ALREADY_EXISTS; } }
InsertTailList( pfl, &pITE->ITE_LinkByAddress );
return NO_ERROR; }
|