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