BindInterface Sample

[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;
}