[This is preliminary documentation and subject to change.]
DWORD
APIENTRY
BindInterface(
IN DWORD dwIndex,
IN PVOID pBinding
)
/*++
Routine Description
Called by the IP Router Manager once it learns the address(es)
on an interface. This may happen as soon as the router starts
(after the interface is added, of course) when the interface has
a static address or may happen when an interface acquires a DHCP
address or may happen when IPCP acquire the address for a dial up
link. The binding may consist of one or more addresses. We walk
the addresses given and find the corresponding block in our
config. We then update any information and if the interface has
been enabled, we activate the binding, i.e. begin running on it.
Arguments
dwIndex Index of the interface in question
pBinding Pointer to IP_ADAPTER_BINDING_INFO containing info about
the addresses on the interface
Return Value
ERROR_INVALID_PARAMETER
NO_ERROR
--*/
{
PNT_IF pIf;
PLIST_ENTRY pleNode;
PINTRNL_IF pBind;
ULONG i;
BOOL bFound;
DWORD dwResult;
PIP_ADAPTER_BINDING_INFO pBindingInfo;
EnterProtocolApi();
TraceEnter("BindInterface");
if(pBinding == NULL)
{
Trace0(ERR,
"BindInterface: Router Manager called us with NULL binding");
TraceLeave("BindInterface");
ExitProtocolApi();
return ERROR_INVALID_PARAMETER;
}
pBindingInfo = (PIP_ADAPTER_BINDING_INFO)pBinding;
if(pBindingInfo->NumAddresses < 1)
{
Trace0(ERR,
"BindInterface: Router Manager called us with NO binding");
TraceLeave("BindInterface");
ExitProtocolApi();
return ERROR_INVALID_PARAMETER;
}
EnterCriticalSection(&g_csIfListLock);
pIf = GetIfBlockGivenIndex(dwIndex);
if(pIf == NULL)
{
LeaveCriticalSection(&g_csIfListLock);
Trace1(ERR,
"BindInterface: Interface %d does not exist",
dwIndex);
TraceLeave("BindInterface");
ExitProtocolApi();
return ERROR_INVALID_PARAMETER;
}
if(IsNtBound(pIf))
{
//
// Can not receive two bind notifications without an
// Unbind in the middle
//
Trace1(ERR,
"BindInterface: Interface %S is already bound",
pIf->pwszIfName);
LeaveCriticalSection(&g_csIfListLock);
TraceLeave("BindInterface");
ExitProtocolApi();
return ERROR_INVALID_PARAMETER;
}
SetNtBound(pIf);
for(i = 0; i < pBindingInfo->NumAddresses; i++)
{
pBind = GetBindingGivenAddress(pIf,
pBindingInfo->Address[i].IPAddress);
if(pBind == NULL)
{
//
// Our config is bad, we will try and go through all
// the blocks and see if we can at least bind on the others.
//
Trace3(ERR,
"BindInterface: Couldnt find config block for %d.%d.%d.%d/%d.%d.%d.%d over %S",
PRINT_ADDRESS(pBindingInfo->Address[i].IPAddress),
PRINT_ADDRESS(pBindingInfo->Address[i].Mask),
pIf->pwszIfName);
continue;
}
if(pBindingInfo->NumAddresses == 1)
{
//
// If we have only one address, then the addresses
// may not match, so update them
//
pBind->dwAddress = pBindingInfo->Address[i].IPAddress;
pBind->dwMask = pBindingInfo->Address[i].Mask;
}
}
#if DBG
//
// Check to make sure we got bindings for all the
// configured addresses
//
if(pIf->ulNumBindings > 1)
{
for(pleNode = pIf->leInternalIfHead.Flink;
pleNode != &pIf->leInternalIfHead;
pleNode = pleNode->Flink)
{
bFound = FALSE;
pBind = CONTAINING_RECORD(pleNode, INTRNL_IF, leInternalIfLink);
for(i = 0; i < pBindingInfo->NumAddresses; i++)
{
if(pBind->dwAddress == pBindingInfo->Address[i].IPAddress)
{
ASSERT(pBind->dwMask == pBindingInfo->Address[i].Mask);
bFound = TRUE;
break;
}
}
if(!bFound)
{
Trace3(ERR,
"BindInterface: Binding not indicated for %d.%d.%d.%d/%d.%d.%d.%d over %S",
PRINT_ADDRESS(pBind->dwAddress),
PRINT_ADDRESS(pBind->dwMask),
pIf->pwszIfName);
}
}
}
#endif // DBG
//
// OK now we have the bindings all set up
//
if(IsNtEnabled(pIf))
{
//
// So the interface is bound and enabled => we are all set
// to go
//
for(pleNode = pIf->leInternalIfHead.Flink;
pleNode != &pIf->leInternalIfHead;
pleNode = pleNode->Flink)
{
pBind = CONTAINING_RECORD(pleNode, INTRNL_IF, leInternalIfLink);
if(pBind->bEnabled)
{
//
// Our config tells us that we are enabled
// for this address
//
ASSERT(pBind->dwState != BINDING_UP);
//
// This will set the state to BINDING_UP
//
dwResult = ActivateBinding(pBind);
if(dwResult != NO_ERROR)
{
Trace2(ERR,
"BindInterface: Unable to activate %d.%d.%d.%d over %S",
PRINT_ADDRESS(pBind->dwAddress),
pIf->pwszIfName);
}
}
}
}
LeaveCriticalSection(&g_csIfListLock);
TraceLeave("BindInterface");
ExitProtocolApi();
return NO_ERROR;
}