935 lines
21 KiB
C
935 lines
21 KiB
C
//============================================================================
|
|
// Copyright (c) 1995, Microsoft Corporation
|
|
//
|
|
// File: if.c
|
|
//
|
|
// History:
|
|
// V Raman June-25-1997 Created.
|
|
//
|
|
// routines that manipulate interface entries
|
|
//============================================================================
|
|
|
|
#include "pchmgm.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// CreateIfEntry
|
|
//
|
|
// This function creates a new interface entry. Duh
|
|
// Assumes that the interface list is locked.
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
CreateIfEntry(
|
|
PLIST_ENTRY pleIfList,
|
|
DWORD dwIfIndex,
|
|
DWORD dwIfNextHopAddr,
|
|
DWORD dwProtocolId,
|
|
DWORD dwComponentId
|
|
)
|
|
{
|
|
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
PIF_ENTRY pie = NULL, pieEntry = NULL;
|
|
|
|
|
|
TRACEIF4(
|
|
IF,
|
|
"ENTERED CreateIfEntry : Interface %x, %x : Protocol %x, %x",
|
|
dwIfIndex, dwIfNextHopAddr, dwProtocolId, dwComponentId
|
|
);
|
|
|
|
|
|
do
|
|
{
|
|
//
|
|
// allocate an interface entry.
|
|
//
|
|
|
|
pie = MGM_ALLOC( sizeof( IF_ENTRY ) );
|
|
|
|
if ( pie == NULL )
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
TRACE1(
|
|
ANY, "CreateIfEntry : Failed to allocate entry %x", dwErr
|
|
);
|
|
|
|
LOGERR0( HEAP_ALLOC_FAILED, dwErr );
|
|
|
|
break;
|
|
}
|
|
|
|
ZeroMemory( pie, sizeof( IF_ENTRY ) );
|
|
|
|
|
|
//
|
|
// init. i/f structure
|
|
//
|
|
|
|
pie-> dwIfIndex = dwIfIndex;
|
|
|
|
pie-> dwIfNextHopAddr = dwIfNextHopAddr;
|
|
|
|
pie-> dwOwningProtocol = dwProtocolId;
|
|
|
|
pie-> dwOwningComponent = dwComponentId;
|
|
|
|
pie-> wAddedByFlag = 0;
|
|
|
|
|
|
if ( IS_PROTOCOL_ID_IGMP( dwProtocolId ) )
|
|
{
|
|
SET_ADDED_BY_IGMP( pie );
|
|
}
|
|
|
|
else
|
|
{
|
|
SET_ADDED_BY_PROTOCOL( pie );
|
|
}
|
|
|
|
|
|
InitializeListHead( &pie-> leInIfList );
|
|
|
|
InitializeListHead( &pie-> leOutIfList );
|
|
|
|
|
|
//
|
|
// insert in protocol list
|
|
//
|
|
|
|
InitializeListHead( &pie-> leIfHashList );
|
|
|
|
InsertTailList( pleIfList, &pie-> leIfHashList );
|
|
|
|
|
|
} while ( FALSE );
|
|
|
|
|
|
TRACEIF1( IF, "LEAVING CreateIfEntry : %x", dwErr );
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// DeleteIfEntry
|
|
//
|
|
// This function deletes an interface entry. Duh
|
|
// Assumes that the interface list is locked.
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
DeleteIfEntry(
|
|
PIF_ENTRY pieEntry
|
|
)
|
|
{
|
|
TRACEIF0( IF, "ENTERED DeleteIfEntry" );
|
|
|
|
RemoveEntryList( &pieEntry-> leIfHashList );
|
|
|
|
MGM_FREE( pieEntry );
|
|
|
|
TRACEIF0( IF, "LEAVING DeleteIfEntry" );
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// GetIfEntry
|
|
//
|
|
// This function retrieves an interface entry. Duh
|
|
//
|
|
// Assumes that the interface list is locked.
|
|
//----------------------------------------------------------------------------
|
|
|
|
PIF_ENTRY
|
|
GetIfEntry(
|
|
PLIST_ENTRY pleIfList,
|
|
DWORD dwIfIndex,
|
|
DWORD dwIfNextHopAddr
|
|
)
|
|
{
|
|
PIF_ENTRY pie;
|
|
|
|
if ( FindIfEntry( pleIfList, dwIfIndex, dwIfNextHopAddr, &pie ) )
|
|
{
|
|
return pie;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// FindIfEntry
|
|
//
|
|
// This function retrieves an interface entry. Duh
|
|
//
|
|
// Assumes that the interface list is locked.
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
FindIfEntry(
|
|
PLIST_ENTRY pleIfList,
|
|
DWORD dwIfIndex,
|
|
DWORD dwIfNextHopAddr,
|
|
PIF_ENTRY * ppie
|
|
)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
|
|
INT iCmp = 0;
|
|
|
|
PIF_ENTRY pie = NULL;
|
|
|
|
PLIST_ENTRY ple = NULL;
|
|
|
|
|
|
TRACEIF2( IF, "ENTERED FindIfEntry : %x, %x", dwIfIndex, dwIfNextHopAddr );
|
|
|
|
//
|
|
// Scan interface list. Interface list is ordered by
|
|
// interface index, next hop address
|
|
//
|
|
|
|
*ppie = NULL;
|
|
|
|
|
|
for ( ple = pleIfList-> Flink; ple != pleIfList; ple = ple-> Flink )
|
|
{
|
|
pie = CONTAINING_RECORD( ple, IF_ENTRY, leIfHashList );
|
|
|
|
if ( pie-> dwIfIndex < dwIfIndex )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
else if ( pie-> dwIfIndex > dwIfIndex )
|
|
{
|
|
//
|
|
// Entry not present
|
|
//
|
|
|
|
*ppie = pie;
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
if ( INET_CMP( pie-> dwIfNextHopAddr, dwIfNextHopAddr, iCmp ) < 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
else if ( iCmp > 0 )
|
|
{
|
|
*ppie = pie;
|
|
|
|
break;
|
|
}
|
|
|
|
*ppie = pie;
|
|
|
|
bFound = TRUE;
|
|
|
|
break;
|
|
}
|
|
|
|
TRACEIF1( IF, "LEAVING FindIfEntry : %x", bFound );
|
|
|
|
return bFound;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// AddSourceToOutList
|
|
//
|
|
// Each interface entry maintains a list of (source, group) entries that
|
|
// reference this interface in their outgoing interface list. Each time
|
|
// membership entry is added the (source, group) to the reference list.
|
|
// When this interface is eventually deleted these (source, group) entries
|
|
// need to be updated to reflect the deletion of this interface.
|
|
//
|
|
// Assumes that the interface entry is locked.
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
AddSourceToRefList(
|
|
PLIST_ENTRY pleRefList,
|
|
DWORD dwSourceAddr,
|
|
DWORD dwSourceMask,
|
|
DWORD dwGroupAddr,
|
|
DWORD dwGroupMask,
|
|
BOOL bIGMP
|
|
)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
PIF_REFERENCE_ENTRY pire = NULL, pireNew = NULL;
|
|
|
|
|
|
TRACEIF5(
|
|
IF,
|
|
"ENTERED AddSourceToIfEntry : Source %x, %x : Group %x, %x"
|
|
" : IGMP %x",
|
|
dwSourceAddr, dwSourceMask, dwGroupAddr, dwGroupMask, bIGMP
|
|
);
|
|
|
|
do
|
|
{
|
|
//
|
|
// Check if reference already present
|
|
//
|
|
|
|
|
|
bFound = FindRefEntry(
|
|
pleRefList, dwSourceAddr, dwSourceMask,
|
|
dwGroupAddr, dwGroupMask, &pire
|
|
);
|
|
|
|
|
|
if ( !bFound )
|
|
{
|
|
//
|
|
// no previous reference for this (source, group) was found
|
|
// create a new one.
|
|
//
|
|
|
|
pireNew = MGM_ALLOC( sizeof( IF_REFERENCE_ENTRY ) );
|
|
|
|
if ( pireNew == NULL )
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
TRACE1(
|
|
ANY,
|
|
"AddSourceToOutList : Failed to allocate reference entry %x",
|
|
dwErr
|
|
);
|
|
|
|
LOGERR0( HEAP_ALLOC_FAILED, dwErr );
|
|
|
|
break;
|
|
}
|
|
|
|
ZeroMemory( pireNew, sizeof( IF_REFERENCE_ENTRY ) );
|
|
|
|
|
|
pireNew-> dwSourceAddr = dwSourceAddr;
|
|
|
|
pireNew-> dwSourceMask = dwSourceMask;
|
|
|
|
pireNew-> dwGroupAddr = dwGroupAddr;
|
|
|
|
pireNew-> dwGroupMask = dwGroupMask;
|
|
|
|
pireNew-> wAddedByFlag = 0;
|
|
|
|
|
|
//
|
|
// set the appropriate bit for the protocol
|
|
//
|
|
|
|
if ( bIGMP )
|
|
{
|
|
SET_ADDED_BY_IGMP( pireNew );
|
|
}
|
|
|
|
else
|
|
{
|
|
SET_ADDED_BY_PROTOCOL( pireNew );
|
|
}
|
|
|
|
|
|
//
|
|
// insert into ref list
|
|
//
|
|
|
|
if ( pire == NULL )
|
|
{
|
|
InsertTailList( pleRefList, &pireNew-> leRefList );
|
|
}
|
|
|
|
else
|
|
{
|
|
InsertTailList( &pire-> leRefList, &pireNew-> leRefList );
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
//
|
|
// set the appropriate bit for the protocol
|
|
//
|
|
|
|
if ( bIGMP )
|
|
{
|
|
SET_ADDED_BY_IGMP( pire );
|
|
}
|
|
|
|
else
|
|
{
|
|
SET_ADDED_BY_PROTOCOL( pire );
|
|
}
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
|
|
TRACEIF1( IF, "LEAVING AddSourceToRefList : %x", bFound );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// DeleeSourceFomrRefList
|
|
//
|
|
// Delete a reference to a (source, group).
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
DeleteSourceFromRefList(
|
|
PLIST_ENTRY pleIfRefList,
|
|
DWORD dwSourceAddr,
|
|
DWORD dwSourceMask,
|
|
DWORD dwGroupAddr,
|
|
DWORD dwGroupMask,
|
|
BOOL bIGMP
|
|
)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
|
|
PIF_REFERENCE_ENTRY pire = NULL, pireEntry = NULL;
|
|
|
|
|
|
TRACEIF5(
|
|
IF,
|
|
"ENTERED DeleteSourceFromIfEntry : Source %x %x, Group : %x, %x"
|
|
" : IGMP %x",
|
|
dwSourceAddr, dwSourceMask, dwGroupAddr, dwGroupMask, bIGMP
|
|
);
|
|
|
|
|
|
//
|
|
// find the entry is already present.
|
|
// list is arranged in descending order in terms of
|
|
// Group address, source address
|
|
//
|
|
|
|
bFound = FindRefEntry(
|
|
pleIfRefList, dwSourceAddr, dwSourceMask,
|
|
dwGroupAddr, dwGroupMask, &pire
|
|
);
|
|
|
|
//
|
|
// if entry was not found
|
|
//
|
|
|
|
if ( !bFound )
|
|
{
|
|
TRACE1( IF, "LEAVING DeleteSourceFromRefList : %x", FALSE );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// reset the appropriate bit for the protocol
|
|
//
|
|
|
|
if ( bIGMP )
|
|
{
|
|
CLEAR_ADDED_BY_IGMP( pire );
|
|
}
|
|
|
|
else
|
|
{
|
|
CLEAR_ADDED_BY_PROTOCOL( pire );
|
|
}
|
|
|
|
|
|
//
|
|
// if no more references left, remove this entry
|
|
//
|
|
|
|
if ( !IS_ADDED_BY_IGMP( pire ) &&
|
|
!IS_ADDED_BY_PROTOCOL( pire ) )
|
|
{
|
|
RemoveEntryList( &pire-> leRefList );
|
|
|
|
MGM_FREE( pire );
|
|
}
|
|
|
|
TRACEIF1( IF, "LEAVING DeleteSourceFromRefList : %x", TRUE );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// FindRefEntry
|
|
//
|
|
// Locate a reference entry. If not found return the expected location in
|
|
// the list.
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
FindRefEntry(
|
|
PLIST_ENTRY pleRefList,
|
|
DWORD dwSourceAddr,
|
|
DWORD dwSourceMask,
|
|
DWORD dwGroupAddr,
|
|
DWORD dwGroupMask,
|
|
PIF_REFERENCE_ENTRY * ppire
|
|
)
|
|
{
|
|
INT iCmp;
|
|
|
|
PLIST_ENTRY ple = NULL;
|
|
|
|
PIF_REFERENCE_ENTRY pire = NULL;
|
|
|
|
BOOL bFound = FALSE;
|
|
|
|
|
|
TRACEIF4(
|
|
IF,
|
|
"ENTERED FindRefEntry : Source %x, %x : Group %x, %x",
|
|
dwSourceAddr, dwSourceMask, dwGroupAddr, dwGroupMask
|
|
);
|
|
|
|
|
|
*ppire = NULL;
|
|
|
|
|
|
for ( ple = pleRefList-> Flink; ple != pleRefList; ple = ple-> Flink )
|
|
{
|
|
pire = CONTAINING_RECORD( ple, IF_REFERENCE_ENTRY, leRefList );
|
|
|
|
if ( INET_CMP( pire-> dwGroupAddr, dwGroupAddr, iCmp ) < 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
else if ( iCmp > 0 )
|
|
{
|
|
//
|
|
// you are now past the position where an existing
|
|
// entry would be.
|
|
//
|
|
|
|
*ppire = pire;
|
|
|
|
break;
|
|
}
|
|
|
|
if ( INET_CMP( pire-> dwSourceAddr, dwSourceAddr, iCmp ) < 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
else if ( iCmp > 0 )
|
|
{
|
|
//
|
|
// you are now past the position where an existing
|
|
// entry would be.
|
|
//
|
|
|
|
*ppire = pire;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// entry found
|
|
//
|
|
|
|
*ppire = pire;
|
|
|
|
bFound = TRUE;
|
|
|
|
break;
|
|
}
|
|
|
|
TRACEIF1( IF, "LEAVING FindRefEntry : %x", bFound );
|
|
|
|
return bFound;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// DeleteOutInterfaceRefs
|
|
//
|
|
// When a interface is deleted by a protocol (or IGMP) all (source, group)
|
|
// entries that use this interface in their outgoing interface lists have to
|
|
// be updated to reflect ththe deletion.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
DeleteOutInterfaceRefs(
|
|
PPROTOCOL_ENTRY ppe,
|
|
PIF_ENTRY pie,
|
|
BOOL bIGMP
|
|
)
|
|
{
|
|
PLIST_ENTRY ple = NULL, pleRefList = NULL, pleNext = NULL;
|
|
|
|
PIF_REFERENCE_ENTRY pire = NULL;
|
|
|
|
|
|
|
|
TRACEIF1( IF, "ENTERED DeleteOutInterfaceRefs: IGMP %x", bIGMP );
|
|
|
|
do
|
|
{
|
|
//
|
|
// No references for this interface in any outgoing
|
|
// interface lists of source entries
|
|
//
|
|
|
|
pleRefList = &pie-> leOutIfList;
|
|
|
|
if ( IsListEmpty( pleRefList ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// walk the reference list and remove the (source, group) entries
|
|
// for each reference
|
|
//
|
|
|
|
for ( ple = pleRefList-> Flink; ple != pleRefList; )
|
|
{
|
|
pire = CONTAINING_RECORD( ple, IF_REFERENCE_ENTRY, leRefList );
|
|
|
|
|
|
//
|
|
// was this reference added by this protocol
|
|
//
|
|
|
|
if ( ( bIGMP && !IS_ADDED_BY_IGMP( pire ) ) ||
|
|
( !bIGMP && !IS_ADDED_BY_PROTOCOL( pire ) ) )
|
|
{
|
|
//
|
|
// no, skip it
|
|
//
|
|
|
|
ple = ple-> Flink;
|
|
|
|
continue;
|
|
}
|
|
|
|
|
|
//
|
|
// Delete this interface from the (source, group) entry.
|
|
//
|
|
|
|
DeleteInterfaceFromSourceEntry(
|
|
ppe,
|
|
pire-> dwGroupAddr, pire-> dwGroupMask,
|
|
pire-> dwSourceAddr, pire-> dwSourceMask,
|
|
pie-> dwIfIndex, pie-> dwIfNextHopAddr,
|
|
bIGMP
|
|
);
|
|
|
|
|
|
if ( bIGMP )
|
|
{
|
|
CLEAR_ADDED_BY_IGMP( pire );
|
|
}
|
|
|
|
else
|
|
{
|
|
CLEAR_ADDED_BY_PROTOCOL( pire );
|
|
}
|
|
|
|
|
|
//
|
|
// remove reference entry.
|
|
//
|
|
|
|
if ( !IS_ADDED_BY_IGMP( pire ) &&
|
|
!IS_ADDED_BY_PROTOCOL( pire ) )
|
|
{
|
|
//
|
|
// no more references to interface for IGMP
|
|
// or for routing protocol.
|
|
// remove this reference entry altogether.
|
|
//
|
|
|
|
pleNext = ple-> Flink;
|
|
|
|
RemoveEntryList( ple );
|
|
|
|
MGM_FREE ( pire );
|
|
|
|
ple = pleNext;
|
|
}
|
|
|
|
else
|
|
{
|
|
ple = ple-> Flink;
|
|
}
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
TRACEIF0( IF, "LEAVING DeleteOutInterfaceRefs:" );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// DeleteInInterfaceRefs
|
|
//
|
|
// When a interface is deleted by a protocol (or IGMP) all (source, group)
|
|
// entries that use this interface as their incoming interface have to
|
|
// be updated to reflect the deletion.
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
DeleteInInterfaceRefs(
|
|
PLIST_ENTRY pleRefList
|
|
)
|
|
{
|
|
PLIST_ENTRY ple = NULL;
|
|
|
|
PIF_REFERENCE_ENTRY pire = NULL;
|
|
|
|
|
|
TRACEIF0( IF, "Entering DeleteInInterfaceRefs" );
|
|
|
|
|
|
while ( !IsListEmpty( pleRefList ) )
|
|
{
|
|
ple = RemoveHeadList( pleRefList );
|
|
|
|
pire = CONTAINING_RECORD( ple, IF_REFERENCE_ENTRY, leRefList );
|
|
|
|
|
|
//
|
|
// A Zappaesque function call here
|
|
//
|
|
|
|
LookupAndDeleteYourMfe(
|
|
pire-> dwSourceAddr, pire-> dwSourceMask,
|
|
pire-> dwGroupAddr, pire-> dwGroupMask,
|
|
TRUE, NULL, NULL
|
|
);
|
|
|
|
MGM_FREE( pire );
|
|
}
|
|
|
|
TRACEIF0( IF, "LEAVING DeleteInInterfaceRefs" );
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// TransferInterfaceOwnershipToProtocol
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
TransferInterfaceOwnershipToProtocol(
|
|
PPROTOCOL_ENTRY ppe,
|
|
PIF_ENTRY pie
|
|
)
|
|
{
|
|
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
PPROTOCOL_ENTRY ppeIgmp;
|
|
|
|
|
|
do
|
|
{
|
|
//
|
|
// get protocol entry for IGMP
|
|
//
|
|
|
|
ppeIgmp = GetProtocolEntry(
|
|
PROTOCOL_LIST_HEAD(), pie-> dwOwningProtocol,
|
|
pie-> dwOwningComponent
|
|
);
|
|
|
|
if ( ppeIgmp == NULL )
|
|
{
|
|
//
|
|
// interface is owned by IGMP, but protocol entry is not
|
|
// present for IGMP. MGM data is in an inconsistent state
|
|
//
|
|
|
|
dwErr = ERROR_UNKNOWN;
|
|
|
|
TRACE2(
|
|
ANY, "TransferInterfaceOwnershipToProtocol : Could not find"
|
|
" IGMP protocol entry", pie-> dwIfIndex,
|
|
pie-> dwIfNextHopAddr
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// indicate to IGMP that interface has been disabled. This should
|
|
// stop IGMP from adding state to this interface while it is being
|
|
// transferred to the protocol
|
|
//
|
|
|
|
IGMP_DISABLE_CALLBACK( ppeIgmp ) (
|
|
pie-> dwIfIndex, pie-> dwIfNextHopAddr
|
|
);
|
|
|
|
|
|
//
|
|
// delete all IGMP references in and out
|
|
//
|
|
|
|
DeleteInInterfaceRefs( &pie-> leInIfList );
|
|
|
|
DeleteOutInterfaceRefs( ppeIgmp, pie, TRUE );
|
|
|
|
|
|
//
|
|
// mark interface as added by Routing protocol
|
|
//
|
|
|
|
SET_ADDED_BY_PROTOCOL( pie );
|
|
|
|
pie-> dwOwningProtocol = ppe-> dwProtocolId;
|
|
|
|
pie-> dwOwningComponent = ppe-> dwComponentId;
|
|
|
|
|
|
//
|
|
// indicate to IGMP that interface has been enabled.
|
|
//
|
|
|
|
IGMP_ENABLE_CALLBACK( ppeIgmp ) (
|
|
pie-> dwIfIndex, pie-> dwIfNextHopAddr
|
|
);
|
|
|
|
|
|
} while ( FALSE );
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// TransferInterfaceOwnershipToIGMP
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
TransferInterfaceOwnershipToIGMP(
|
|
PPROTOCOL_ENTRY ppe,
|
|
PIF_ENTRY pie
|
|
)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
PPROTOCOL_ENTRY ppeIgmp;
|
|
|
|
|
|
do
|
|
{
|
|
//
|
|
// get IGMP protocol entry
|
|
//
|
|
|
|
ppeIgmp = GetIgmpProtocolEntry( PROTOCOL_LIST_HEAD() );
|
|
|
|
if ( ppeIgmp == NULL )
|
|
{
|
|
//
|
|
// interface is has IGMP enabled on it, but a protocol entry is not
|
|
// present for IGMP. MGM data is in an inconsistent state
|
|
//
|
|
|
|
dwErr = ERROR_UNKNOWN;
|
|
|
|
TRACE2(
|
|
ANY, "TransferInterfaceOwnershipToProtocol : Could not find"
|
|
" IGMP protocol entry", pie-> dwIfIndex,
|
|
pie-> dwIfNextHopAddr
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// indicate to IGMP that interface has been disabled. This should
|
|
// stop IGMP from adding state to this interface while it is being
|
|
// transferred to IGMP
|
|
//
|
|
|
|
IGMP_DISABLE_CALLBACK( ppeIgmp ) (
|
|
pie-> dwIfIndex, pie-> dwIfNextHopAddr
|
|
);
|
|
|
|
|
|
//
|
|
// delete all protocol references (in and out)
|
|
//
|
|
|
|
DeleteInInterfaceRefs( &pie-> leInIfList );
|
|
|
|
DeleteOutInterfaceRefs( ppe, pie, FALSE );
|
|
|
|
CLEAR_ADDED_BY_PROTOCOL( pie );
|
|
|
|
|
|
//
|
|
// delete all IGMP references, these will get added back by
|
|
// IGMP when is enabled on this interface. This is done
|
|
// below.
|
|
//
|
|
|
|
DeleteOutInterfaceRefs( ppe, pie, TRUE );
|
|
|
|
|
|
//
|
|
// Mark interface as being owned by IGMP
|
|
//
|
|
|
|
pie-> dwOwningProtocol = ppeIgmp-> dwProtocolId;
|
|
|
|
pie-> dwOwningComponent = ppeIgmp-> dwComponentId;
|
|
|
|
|
|
//
|
|
// enable IGMP on the interface
|
|
//
|
|
|
|
IGMP_ENABLE_CALLBACK( ppeIgmp ) (
|
|
pie-> dwIfIndex, pie-> dwIfNextHopAddr
|
|
);
|
|
|
|
|
|
} while ( FALSE );
|
|
|
|
return dwErr;
|
|
}
|
|
|