AddInterface Sample

[This is preliminary documentation and subject to change.]

DWORD
APIENTRY
AddInterface(
    IN PWCHAR               pwszInterfaceName,
    IN DWORD                dwIndex,
    IN NET_INTERFACE_TYPE   dwIfType,
    IN PVOID                pvConfig
    )
/*++
  Routine Description
      Called by the IP Router Manager to add an interface when
      it finds our information block (header) within the interface's
      configuration.
      We verify the information and create the structure for the
      interface.  Then we see all the configured addresses for
      the interface and create a binding structure for each address.
      The interface comes up as UNBOUND-DISABLED
      
  Arguments
      pwszInterfaceName The name of the interface. We store it
                        for logging
      dwIndex           The positive integer this interface will
                        be referred to by
      dwIfType          The type of the interface (WAN/LAN etc)
      pvConfig          Our config for this interface

  Return Value
      ERROR_INVALID_PARAMETER
      ERROR_INVALID_DATA
      NO_ERROR

--*/
{
    ULONG       ulNameLen,i;
    DWORD       dwResult;
    PWCHAR      pwszName;
    PINTRNL_IF  pBind;
    PNT_IF      pIf,pPrev;
    PLIST_ENTRY pleNode;
    
    
    PSAMPLE_PROTOCOL_INTERFACE_INFO pIfInfo;


    EnterProtocolApi();

    TraceEnter("AddInterface");
    
    Trace3(INTF, "AddInterface called for: %S %d %d ",
           pwszInterfaceName,
           dwIndex,
           dwIfType);

    ulNameLen = wcslen(pwszInterfaceName);
    
    if((pwszInterfaceName == NULL) ||
       (pvConfig == NULL) ||
       (ulNameLen == 0))
    {
        Trace0(ERR,
               "AddInterface: Router Manager called us with NULL info");
        
        TraceLeave("AddInterface");

        ExitProtocolApi();

        return ERROR_INVALID_PARAMETER;
    }

    pIfInfo = (PSAMPLE_PROTOCOL_INTERFACE_INFO)pvConfig;
    
    if(!ValidateInterfaceInfo(pIfInfo))
    {
        TraceLeave("AddInterface");

        ExitProtocolApi();

        return ERROR_INVALID_DATA;
    }
    
    EnterCriticalSection(&g_csIfListLock);

    //
    // Create the interface block and the blocks for the binding
    //

    dwResult = NO_ERROR;
    
    __try
    {
        pIf = HeapAlloc(g_hPrivateHeap,
                        HEAP_ZERO_MEMORY,
                        sizeof(NT_IF));

        if(pIf == NULL)
        {
            dwResult = GetLastError();
            
            Trace1(ERR,
                   "AddInterface: Error %d allocating memory for i/f",
                   dwResult);
            
            __leave;
        }

        InitializeListHead(&pIf->leInternalIfHead);
        
        pwszName = HeapAlloc(g_hPrivateHeap,
                             HEAP_ZERO_MEMORY,
                             (ulNameLen + 1)*sizeof(WCHAR));

        if(pwszName == NULL)
        {
            dwResult = GetLastError();

            Trace1(ERR,
                   "AddInterface: Error %d allocating memory for name",
                   dwResult);

            __leave;
        }

        wcscpy(pwszName,
               pwszInterfaceName);

        pIf->pwszIfName = pwszName;

        ClearNtState(pIf);

        pIf->dwType = dwIfType;
        
        pIf->ulNumBindings = pIfInfo->ulNumBindings;
        
        for(i = 0; i < pIfInfo->ulNumBindings; i++)
        {
            pBind = HeapAlloc(g_hPrivateHeap,
                                HEAP_ZERO_MEMORY,
                                sizeof(INTRNL_IF));

            if(pBind == NULL)
            {
                dwResult = GetLastError();

                Trace1(ERR,
                       "AddInterface: Error %d allocating memory for internal i/f",
                       dwResult);

                __leave;
            }

            InsertHeadList(&(pIf->leInternalIfHead),
                           &(pBind->leInternalIfLink));

            //
            // Copy out binding info
            //
            
            pBind->dwAddress    = pIfInfo->rgbiInfo[i].dwAddress;
            pBind->dwMask       = pIfInfo->rgbiInfo[i].dwMask;
            pBind->bEnabled     = pIfInfo->rgbiInfo[i].bEnabled;
            pBind->dwState      = BINDING_DOWN;
            pBind->sSocket      = INVALID_SOCKET;
            
            if(pIfInfo->ulNumBindings == 1)
            {
                //
                // If we have only one address, we set that to 0.0.0.0
                // for now even if our config has screwed up
                //

                pBind->dwAddress    = 0x00000000;
                pBind->dwMask       = 0x00000000;
            }
        }
    }
    __finally
    {
        if(dwResult != NO_ERROR)
        {
            //
            // Clean up all resources
            //

            if(pIf)
            {
                if(pIf->pwszIfName)
                {
                    HeapFree(g_hPrivateHeap,
                             0,
                             pIf->pwszIfName);
                }

                pleNode  = pIf->leInternalIfHead.Flink;

                while(pleNode != &pIf->leInternalIfHead)
                {
                    pBind = CONTAINING_RECORD(pleNode,
                                              INTRNL_IF,
                                              leInternalIfLink);

                    pleNode = pleNode->Flink;

                    HeapFree(g_hPrivateHeap,
                             0,
                             pBind);
                }
            }
        }
        else
        {
            //
            // Insert the interface into our link
            //

            for(pleNode  = g_leIfListHead.Flink;
                pleNode != &g_leIfListHead;
                pleNode  = pleNode->Flink)
            {
                pPrev = CONTAINING_RECORD(pleNode,
                                          NT_IF,
                                          leNtIfLink);

                if(pPrev->dwNtIndex > dwIndex)
                {
                    break;
                }
            }

            //
            // pPrev now points to the interface with a higher index
            // pPrev->Blink < dwIndex so put our interface after
            // pPrev->Blink. This way we get an ordered list
            //
            
            InsertHeadList(pPrev->leNtIfLink.Blink,
                           &(pIf->leNtIfLink));
            
        }
    }


    LeaveCriticalSection(&g_csIfListLock);

    TraceLeave("AddInterface");

    ExitProtocolApi();
        
    return dwResult;
}