mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4111 lines
111 KiB
4111 lines
111 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
net\routing\ip\rtrmgr\iprtrmgr.c
|
|
|
|
Abstract:
|
|
|
|
The interface to DIM/DDM
|
|
|
|
Revision History:
|
|
|
|
Gurdeep Singh Pall 6/8/95 Created
|
|
|
|
--*/
|
|
|
|
#include "allinc.h"
|
|
#include "exdeclar.h"
|
|
|
|
|
|
BOOL
|
|
InitIPRtrMgrDLL(
|
|
HANDLE hInst,
|
|
DWORD dwCallReason,
|
|
PVOID pReserved
|
|
)
|
|
{
|
|
switch (dwCallReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
{
|
|
//
|
|
// Init the state
|
|
//
|
|
|
|
InitializeCriticalSection(&RouterStateLock);
|
|
InitializeCriticalSection(&g_csFwdState);
|
|
|
|
RouterState.IRS_RefCount = 0;
|
|
RouterState.IRS_State = RTR_STATE_STOPPED;
|
|
|
|
//
|
|
// We are not interested in THREAD_XXX reasons
|
|
//
|
|
|
|
DisableThreadLibraryCalls(hInst);
|
|
|
|
//
|
|
// Setup our info routines
|
|
//
|
|
|
|
g_rgicInfoCb[0].pfnGetInterfaceInfo = NULL;
|
|
g_rgicInfoCb[0].pfnSetInterfaceInfo = SetRouteInfo;
|
|
g_rgicInfoCb[0].pfnBindInterface = NULL;
|
|
g_rgicInfoCb[0].pfnGetGlobalInfo = NULL;
|
|
g_rgicInfoCb[0].pszInfoName = "Route";
|
|
|
|
g_rgicInfoCb[1].pfnGetInterfaceInfo = NULL;
|
|
g_rgicInfoCb[1].pfnSetInterfaceInfo = SetFilterInterfaceInfo;
|
|
g_rgicInfoCb[1].pfnBindInterface = BindFilterInterface;
|
|
g_rgicInfoCb[1].pfnGetGlobalInfo = NULL;
|
|
g_rgicInfoCb[1].pszInfoName = "Filter";
|
|
|
|
g_rgicInfoCb[2].pfnGetInterfaceInfo = NULL;
|
|
g_rgicInfoCb[2].pfnSetInterfaceInfo = SetDemandDialFilters;
|
|
g_rgicInfoCb[2].pfnBindInterface = NULL;
|
|
g_rgicInfoCb[2].pfnGetGlobalInfo = NULL;
|
|
g_rgicInfoCb[2].pszInfoName = "DemandFilter";
|
|
|
|
g_rgicInfoCb[3].pfnGetInterfaceInfo = NULL;
|
|
g_rgicInfoCb[3].pfnSetInterfaceInfo = SetIpInIpInfo;
|
|
g_rgicInfoCb[3].pfnBindInterface = NULL;
|
|
g_rgicInfoCb[3].pfnGetGlobalInfo = NULL;
|
|
g_rgicInfoCb[3].pszInfoName = "IpIpInfo";
|
|
|
|
g_rgicInfoCb[4].pfnGetInterfaceInfo = GetBoundaryInfo;
|
|
g_rgicInfoCb[4].pfnSetInterfaceInfo = SetBoundaryInfo;
|
|
g_rgicInfoCb[4].pfnBindInterface = BindBoundaryInterface;
|
|
g_rgicInfoCb[4].pfnGetGlobalInfo = GetScopeInfo;
|
|
g_rgicInfoCb[4].pszInfoName = "MulticastBoundary";
|
|
|
|
g_rgicInfoCb[5].pfnGetInterfaceInfo = GetMcastLimitInfo;
|
|
g_rgicInfoCb[5].pfnSetInterfaceInfo = SetMcastLimitInfo;
|
|
g_rgicInfoCb[5].pfnBindInterface = NULL;
|
|
g_rgicInfoCb[5].pfnGetGlobalInfo = NULL;
|
|
g_rgicInfoCb[5].pszInfoName = "MulticastLimit";
|
|
|
|
break ;
|
|
}
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
{
|
|
DeleteCriticalSection(&RouterStateLock);
|
|
DeleteCriticalSection(&g_csFwdState);
|
|
|
|
break;
|
|
}
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
{
|
|
//
|
|
// not of interest.
|
|
//
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
const static WCHAR pszIpxStackService[] = L"TcpIp";
|
|
|
|
DWORD
|
|
VerifyOrStartIpStack(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Verifies that the ipx stack is started and attempts to start the stack
|
|
if not.
|
|
|
|
Locks
|
|
|
|
None - called at init time
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
NO_ERROR
|
|
ERROR_CAN_NOT_COMPLETE
|
|
|
|
--*/
|
|
{
|
|
SC_HANDLE hSC = NULL, hStack = NULL;
|
|
SERVICE_STATUS Status;
|
|
DWORD dwErr;
|
|
|
|
TraceEnter("VerifyOrStartIpxStack");
|
|
|
|
__try
|
|
{
|
|
|
|
//
|
|
// Get a handle to the service controller
|
|
//
|
|
|
|
if ((hSC = OpenSCManager (NULL, NULL, GENERIC_READ | GENERIC_EXECUTE)) == NULL)
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
//
|
|
// Get a handle to the ipx stack service
|
|
//
|
|
|
|
hStack = OpenServiceW (hSC,
|
|
pszIpxStackService,
|
|
SERVICE_START | SERVICE_QUERY_STATUS);
|
|
if (!hStack)
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
//
|
|
// Find out if the service is running
|
|
//
|
|
|
|
if (QueryServiceStatus (hStack, &Status) == 0)
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
//
|
|
// See if the service is running
|
|
//
|
|
|
|
if (Status.dwCurrentState != SERVICE_RUNNING)
|
|
{
|
|
//
|
|
// If it's stopped, start it
|
|
//
|
|
|
|
if (Status.dwCurrentState == SERVICE_STOPPED)
|
|
{
|
|
if (StartService (hStack, 0, NULL) == 0)
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
//
|
|
// Make sure that the service started. StartService is not supposed
|
|
// to return until the driver is started.
|
|
//
|
|
|
|
if (QueryServiceStatus (hStack, &Status) == 0)
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
if (Status.dwCurrentState != SERVICE_RUNNING)
|
|
{
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If it's not stopped, don't worry about it.
|
|
//
|
|
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
}
|
|
__finally
|
|
{
|
|
if (hSC)
|
|
{
|
|
CloseServiceHandle (hSC);
|
|
}
|
|
|
|
if (hStack)
|
|
{
|
|
CloseServiceHandle (hStack);
|
|
}
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
StartRouter(
|
|
IN OUT DIM_ROUTER_INTERFACE *pDimRouterIf,
|
|
IN BOOL bLanOnlyMode,
|
|
IN PVOID pvGlobalInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This function is called by DIM to at startup. WE initialize tracing
|
|
and event logging.
|
|
Call InitRouter() to do the main stuff and then pass pointers to
|
|
the rest of our functions back to DIM
|
|
|
|
Locks
|
|
|
|
None - called at init time
|
|
|
|
Arguments
|
|
|
|
pDimRouterIf structure that holds all the function pointers
|
|
bLanOnlyMode True if not a WAN router
|
|
pvGlobalInfo Pointer to our global info
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwResult, i;
|
|
WORD wVersion = MAKEWORD(2,0); //Winsock version 2.0 minimum
|
|
WSADATA wsaData;
|
|
|
|
OSVERSIONINFOEX VersionInfo;
|
|
|
|
//
|
|
// Initialize Trace and logging
|
|
//
|
|
|
|
TraceHandle = TraceRegister("IPRouterManager");
|
|
g_hLogHandle = RouterLogRegister("IPRouterManager");
|
|
|
|
TraceEnter("StartRouter") ;
|
|
|
|
|
|
if(pvGlobalInfo is NULL)
|
|
{
|
|
//
|
|
// Sometimes setup screws up
|
|
//
|
|
|
|
LogErr0(NO_GLOBAL_INFO,
|
|
ERROR_NO_DATA);
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// We need to make sure that the stack is started before westart.
|
|
//
|
|
|
|
if ( VerifyOrStartIpStack() isnot NO_ERROR )
|
|
{
|
|
Trace0(ERR, "StartRouter: Unable to start ip stack." );
|
|
|
|
return ERROR_SERVICE_DEPENDENCY_FAIL;
|
|
}
|
|
|
|
g_hOwnModule = LoadLibraryEx("IPRTRMGR.DLL",
|
|
NULL,
|
|
0);
|
|
|
|
if(g_hOwnModule is NULL)
|
|
{
|
|
dwResult = GetLastError();
|
|
|
|
Trace1(ERR,
|
|
"StartRouter: Unable to load itself. %d",
|
|
dwResult);
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
RouterState.IRS_State = RTR_STATE_RUNNING ;
|
|
|
|
g_bUninitServer = TRUE;
|
|
|
|
g_dwNextICBSeqNumberCounter = INITIAL_SEQUENCE_NUMBER;
|
|
|
|
if(WSAStartup(wVersion,&wsaData) isnot NO_ERROR)
|
|
{
|
|
Trace1(ERR,
|
|
"StartRouter: WSAStartup failed. Error %d",
|
|
WSAGetLastError());
|
|
|
|
TraceDeregister(TraceHandle);
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Read only variable, no locks protect this
|
|
//
|
|
|
|
RouterRoleLanOnly = bLanOnlyMode ;
|
|
|
|
//
|
|
// Do we have forwarding enabled?
|
|
//
|
|
|
|
EnterCriticalSection(&g_csFwdState);
|
|
|
|
g_bEnableFwdRequest = TRUE;
|
|
g_bSetRoutesToStack = TRUE;
|
|
g_bEnableNetbtBcastFrowarding = FALSE;
|
|
|
|
|
|
//
|
|
// Are we running workstation?
|
|
//
|
|
|
|
ZeroMemory(&VersionInfo,
|
|
sizeof(VersionInfo));
|
|
|
|
VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
|
|
|
|
if(GetVersionEx((POSVERSIONINFO)&VersionInfo))
|
|
{
|
|
if(VersionInfo.wProductType is VER_NT_WORKSTATION)
|
|
{
|
|
g_bSetRoutesToStack = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Trace1(ERR,
|
|
"StartRouter: GetVersionEx failed with %d\n",
|
|
GetLastError());
|
|
}
|
|
|
|
Trace1(GLOBAL,
|
|
"\n\nStartRouter: Machine will run as %s\n\n",
|
|
g_bSetRoutesToStack?"router":"non-router");
|
|
|
|
if(!RouterRoleLanOnly)
|
|
{
|
|
HKEY hkIpcpParam;
|
|
|
|
dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"System\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\Ip",
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hkIpcpParam);
|
|
|
|
|
|
if(dwResult is NO_ERROR)
|
|
{
|
|
DWORD dwEnable, dwSize;
|
|
|
|
dwSize = sizeof(dwEnable);
|
|
|
|
dwResult = RegQueryValueExW(hkIpcpParam,
|
|
L"AllowNetworkAccess",
|
|
NULL,
|
|
NULL,
|
|
(PBYTE)&dwEnable,
|
|
&dwSize);
|
|
|
|
|
|
if(dwResult is NO_ERROR)
|
|
{
|
|
if(dwEnable is 0)
|
|
{
|
|
g_bEnableFwdRequest = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// NETBT broadcast forwarding was enabled as an option
|
|
// to allow simple RAS server configurations to perform
|
|
// name resolution in the absence of WINS/DNS server
|
|
// configuration.
|
|
// This in turn was necessiated by the removal of NBF from the
|
|
// system (NT SERVER). When NBF was present this functionality
|
|
// was performed by the RAS Netbios gateway.
|
|
//
|
|
// NETBT broadcast forwarding is enabled only if
|
|
// 1. Router is not in LanOnly Mode
|
|
// 2. NETBT bcast fwd'g has been explicity turned on.
|
|
//
|
|
|
|
dwResult = RegQueryValueExW(hkIpcpParam,
|
|
L"EnableNetbtBcastFwd",
|
|
NULL,
|
|
NULL,
|
|
(PBYTE)&dwEnable,
|
|
&dwSize);
|
|
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
//
|
|
// It is possible the value is not present
|
|
// esp. if this is the first time RRAS is being
|
|
// run or if the key was manually deleted
|
|
//
|
|
// Assume a default value of 1 (enabled) and set
|
|
// the value in the registry
|
|
//
|
|
|
|
dwEnable = 1;
|
|
|
|
dwResult = RegSetValueExW(
|
|
hkIpcpParam,
|
|
L"EnableNetbtBcastFwd",
|
|
0,
|
|
REG_DWORD,
|
|
(PBYTE) &dwEnable,
|
|
sizeof( DWORD )
|
|
);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace1(
|
|
ERR,
|
|
"error %d setting EnableNetbtBcastFwd value",
|
|
dwResult
|
|
);
|
|
}
|
|
}
|
|
|
|
Trace1(
|
|
INIT, "Netbt Enable mode is %d", dwEnable
|
|
);
|
|
|
|
if(dwEnable isnot 0)
|
|
{
|
|
g_bEnableNetbtBcastFrowarding = TRUE;
|
|
}
|
|
|
|
EnableNetbtBcastForwarding(dwEnable);
|
|
|
|
|
|
RegCloseKey(hkIpcpParam);
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&g_csFwdState);
|
|
|
|
//
|
|
// Keep the entry points in a global structure.
|
|
// Saves the overhead of copying into a structure everytime a protocol
|
|
// has to be loaded
|
|
//
|
|
|
|
g_sfnDimFunctions.DemandDialRequest = DemandDialRequest;
|
|
g_sfnDimFunctions.SetInterfaceReceiveType = SetInterfaceReceiveType;
|
|
g_sfnDimFunctions.ValidateRoute = ValidateRouteForProtocolEx;
|
|
g_sfnDimFunctions.MIBEntryGet = RtrMgrMIBEntryGet;
|
|
g_sfnDimFunctions.MIBEntryGetNext = RtrMgrMIBEntryGetNext;
|
|
g_sfnDimFunctions.MIBEntryGetFirst = RtrMgrMIBEntryGetFirst;
|
|
g_sfnDimFunctions.MIBEntrySet = RtrMgrMIBEntrySet;
|
|
g_sfnDimFunctions.MIBEntryCreate = RtrMgrMIBEntryCreate;
|
|
g_sfnDimFunctions.MIBEntryDelete = RtrMgrMIBEntryDelete;
|
|
g_sfnDimFunctions.GetRouterId = GetRouterId;
|
|
g_sfnDimFunctions.HasMulticastBoundary = RmHasBoundary;
|
|
|
|
Trace1(GLOBAL,
|
|
"StartRouter: LAN MODE = %d",
|
|
RouterRoleLanOnly) ;
|
|
|
|
//
|
|
// Do all the necessary initializations for the router
|
|
//
|
|
|
|
if((dwResult = InitRouter(pvGlobalInfo)) isnot NO_ERROR)
|
|
{
|
|
Trace1(ERR,
|
|
"StartRouter: InitRouter failed %d", dwResult) ;
|
|
|
|
RouterManagerCleanup();
|
|
|
|
RouterState.IRS_State = RTR_STATE_STOPPED;
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
//
|
|
// fill in information required by DIM
|
|
//
|
|
|
|
pDimRouterIf->dwProtocolId = PID_IP;
|
|
|
|
//
|
|
// Set IP Router Manager entrypoints
|
|
//
|
|
|
|
pDimRouterIf->StopRouter = StopRouter;
|
|
pDimRouterIf->AddInterface = AddInterface;
|
|
pDimRouterIf->DeleteInterface = DeleteInterface;
|
|
pDimRouterIf->GetInterfaceInfo = GetInterfaceInfo;
|
|
pDimRouterIf->SetInterfaceInfo = SetInterfaceInfo;
|
|
pDimRouterIf->InterfaceNotReachable = InterfaceNotReachable;
|
|
pDimRouterIf->InterfaceReachable = InterfaceReachable;
|
|
pDimRouterIf->InterfaceConnected = InterfaceConnected;
|
|
pDimRouterIf->UpdateRoutes = UpdateRoutes;
|
|
pDimRouterIf->GetUpdateRoutesResult = GetUpdateRoutesResult;
|
|
pDimRouterIf->SetGlobalInfo = SetGlobalInfo;
|
|
pDimRouterIf->GetGlobalInfo = GetGlobalInfo;
|
|
pDimRouterIf->MIBEntryCreate = RtrMgrMIBEntryCreate;
|
|
pDimRouterIf->MIBEntryDelete = RtrMgrMIBEntryDelete;
|
|
pDimRouterIf->MIBEntryGet = RtrMgrMIBEntryGet;
|
|
pDimRouterIf->MIBEntryGetFirst = RtrMgrMIBEntryGetFirst;
|
|
pDimRouterIf->MIBEntryGetNext = RtrMgrMIBEntryGetNext;
|
|
pDimRouterIf->MIBEntrySet = RtrMgrMIBEntrySet;
|
|
pDimRouterIf->SetRasAdvEnable = SetRasAdvEnable;
|
|
pDimRouterIf->RouterBootComplete = RouterBootComplete;
|
|
|
|
|
|
//
|
|
// Get DIM entrypoints
|
|
//
|
|
|
|
ConnectInterface = pDimRouterIf->ConnectInterface ;
|
|
DisconnectInterface = pDimRouterIf->DisconnectInterface ;
|
|
SaveInterfaceInfo = pDimRouterIf->SaveInterfaceInfo ;
|
|
RestoreInterfaceInfo = pDimRouterIf->RestoreInterfaceInfo ;
|
|
RouterStopped = pDimRouterIf->RouterStopped ;
|
|
SaveGlobalInfo = pDimRouterIf->SaveGlobalInfo;
|
|
EnableInterfaceWithDIM = pDimRouterIf->InterfaceEnabled;
|
|
|
|
LoadStringA(g_hOwnModule,
|
|
LOOPBACK_STRID,
|
|
g_rgcLoopbackString,
|
|
sizeof(g_rgcLoopbackString));
|
|
|
|
LoadStringA(g_hOwnModule,
|
|
INTERNAL_STRID,
|
|
g_rgcInternalString,
|
|
sizeof(g_rgcInternalString));
|
|
|
|
LoadStringA(g_hOwnModule,
|
|
WAN_STRID,
|
|
g_rgcWanString,
|
|
sizeof(g_rgcWanString));
|
|
|
|
LoadStringA(g_hOwnModule,
|
|
IPIP_STRID,
|
|
g_rgcIpIpString,
|
|
sizeof(g_rgcIpIpString));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
RouterBootComplete(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This function is called by DIM after all the interfaces in the registry
|
|
have been loaded with the router manager.
|
|
|
|
Locks
|
|
|
|
None - called at init time
|
|
|
|
Arguments
|
|
|
|
None.
|
|
|
|
Return Value
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr, dwSize, dwInfoSize, dwLastIndex;
|
|
PVOID pvBuffer;
|
|
|
|
|
|
Trace0(ERR,
|
|
"\n-----------------------------------------------------------\n\n");
|
|
|
|
//
|
|
// Call DIM to save the interface info
|
|
//
|
|
|
|
dwLastIndex = 0;
|
|
dwInfoSize = 0;
|
|
pvBuffer = NULL;
|
|
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
// Tell all protocols that start is complete
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
{
|
|
PLIST_ENTRY pleNode;
|
|
PPROTO_CB pProtocolCb;
|
|
|
|
for(pleNode = g_leProtoCbList.Flink;
|
|
pleNode != &g_leProtoCbList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProtocolCb = CONTAINING_RECORD(pleNode,
|
|
PROTO_CB,
|
|
leList) ;
|
|
|
|
if (pProtocolCb->pfnStartComplete)
|
|
{
|
|
dwErr = (pProtocolCb->pfnStartComplete)();
|
|
}
|
|
}
|
|
}
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
|
|
if(IsListEmpty(&ICBList))
|
|
{
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
#if 0
|
|
while(TRUE)
|
|
{
|
|
PICB pIcb;
|
|
PLIST_ENTRY pleNode;
|
|
HANDLE hDimHandle;
|
|
|
|
//
|
|
// Walk the list finding the first ICB that has an index larger than
|
|
// the last index we processed
|
|
//
|
|
|
|
pIcb = NULL;
|
|
|
|
for(pleNode = ICBList.Flink;
|
|
pleNode != &ICBList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
PICB pTempIcb;
|
|
|
|
pTempIcb = CONTAINING_RECORD(pleNode,
|
|
ICB,
|
|
leIfLink);
|
|
|
|
if((pTempIcb->ritType is ROUTER_IF_TYPE_CLIENT) or
|
|
(pTempIcb->ritType is ROUTER_IF_TYPE_DIALOUT) or
|
|
(pTempIcb->dwAdminState isnot IF_ADMIN_STATUS_UP))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(pTempIcb->dwIfIndex > dwLastIndex)
|
|
{
|
|
//
|
|
// Found the next ICB to save
|
|
//
|
|
|
|
pIcb = pTempIcb;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If none found, we are done
|
|
//
|
|
|
|
if(pIcb is NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwLastIndex = pIcb->dwIfIndex;
|
|
hDimHandle = pIcb->hDIMHandle;
|
|
|
|
//
|
|
// Get the info for this ICB
|
|
//
|
|
|
|
dwSize = GetSizeOfInterfaceConfig(pIcb);
|
|
|
|
//
|
|
// If this will fit in the current buffer, use it
|
|
//
|
|
|
|
if(dwSize > dwInfoSize)
|
|
{
|
|
//
|
|
// otherwise, allocate a new one
|
|
//
|
|
|
|
dwInfoSize = dwSize * 2;
|
|
|
|
if(pvBuffer)
|
|
{
|
|
//
|
|
// Free the old buffer
|
|
//
|
|
|
|
HeapFree(IPRouterHeap,
|
|
0,
|
|
pvBuffer);
|
|
|
|
pvBuffer = NULL;
|
|
}
|
|
|
|
pvBuffer = HeapAlloc(IPRouterHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
dwInfoSize);
|
|
|
|
if(pvBuffer is NULL)
|
|
{
|
|
dwInfoSize = 0;
|
|
|
|
//
|
|
// Go to the while(TRUE)
|
|
//
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
dwErr = GetInterfaceConfiguration(pIcb,
|
|
pvBuffer,
|
|
dwInfoSize);
|
|
|
|
|
|
if(dwErr is NO_ERROR)
|
|
{
|
|
//
|
|
// Need to leave the lock for this
|
|
//
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
SaveInterfaceInfo(hDimHandle,
|
|
PID_IP,
|
|
pvBuffer,
|
|
dwSize);
|
|
|
|
//
|
|
// Reacquire it once we are done
|
|
//
|
|
|
|
ENTER_WRITER(ICB_LIST);
|
|
}
|
|
else
|
|
{
|
|
Trace1(ERR,
|
|
"RouterBootComplete: Error getting info for %S\n",
|
|
pIcb->pwszName);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
//
|
|
// Now go in and start forwarding if we are not in lanonly mode
|
|
// and IPCP is so configured
|
|
//
|
|
|
|
EnterCriticalSection(&g_csFwdState);
|
|
|
|
Trace1(GLOBAL,
|
|
"RouterBootComplete: Signalling worker to %s forwarding",
|
|
g_bEnableFwdRequest ? "enable" : "disable");
|
|
|
|
SetEvent(g_hSetForwardingEvent);
|
|
|
|
LeaveCriticalSection(&g_csFwdState);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
AddInterface(
|
|
IN PWSTR pwsInterfaceName,
|
|
IN PVOID pInterfaceInfo,
|
|
IN ROUTER_INTERFACE_TYPE InterfaceType,
|
|
IN HANDLE hDIMInterface,
|
|
IN OUT HANDLE *phInterface
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Called by DIM to add an interface. This could be one of our configured
|
|
interfaces or a client dialling in
|
|
|
|
Locks
|
|
|
|
Takes the ICB_LIST lock as WRITER
|
|
|
|
Arguments
|
|
|
|
pwsInterfaceName
|
|
pInterfaceInfo
|
|
InterfaceType
|
|
hDIMInterface
|
|
phInterface
|
|
|
|
Return Value
|
|
|
|
NO_ERROR
|
|
ERROR_INVALID_PARAMETER
|
|
|
|
--*/
|
|
|
|
{
|
|
PICB pNewInterfaceCb;
|
|
DWORD dwResult, dwAdminState;
|
|
PRTR_TOC_ENTRY pTocEntry;
|
|
PRTR_INFO_BLOCK_HEADER pInfoHdr;
|
|
PINTERFACE_STATUS_INFO pInfo;
|
|
BOOL bEnable;
|
|
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("AddInterface");
|
|
|
|
Trace1(IF,
|
|
"AddInterface: Adding %S",
|
|
pwsInterfaceName);
|
|
|
|
|
|
pInfoHdr = (PRTR_INFO_BLOCK_HEADER)pInterfaceInfo;
|
|
|
|
|
|
#if !defined( __IPINIP )
|
|
|
|
//
|
|
// In preparation for IPinIP interface removal
|
|
//
|
|
|
|
if(InterfaceType is ROUTER_IF_TYPE_TUNNEL1)
|
|
{
|
|
Trace1(ERR,
|
|
"AddInterface: Interface type is TUNNEL (%d), which is no longer"
|
|
"supported",
|
|
InterfaceType);
|
|
|
|
LogErr0(IF_TYPE_NOT_SUPPORTED, ERROR_INVALID_PARAMETER);
|
|
|
|
TraceLeave("AddInterface");
|
|
|
|
ExitRouterApi();
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
#endif
|
|
|
|
if(RouterRoleLanOnly and
|
|
(InterfaceType isnot ROUTER_IF_TYPE_DEDICATED) and
|
|
(InterfaceType isnot ROUTER_IF_TYPE_TUNNEL1) and
|
|
(InterfaceType isnot ROUTER_IF_TYPE_LOOPBACK))
|
|
{
|
|
//
|
|
// If we are in LAN only mode, we should not see CLIENT, INTERNAL
|
|
// HOME_ROUTER or FULL_ROUTER
|
|
//
|
|
|
|
Trace1(ERR,
|
|
"AddInterface: Interface is %d, but Router is in LanOnly Mode",
|
|
InterfaceType);
|
|
|
|
TraceLeave("AddInterface");
|
|
|
|
ExitRouterApi();
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
//
|
|
// Figure out the admin state (if any)
|
|
// If there is no status info, we assume state to be UP
|
|
//
|
|
|
|
dwAdminState = IF_ADMIN_STATUS_UP;
|
|
|
|
pTocEntry = GetPointerToTocEntry(IP_INTERFACE_STATUS_INFO,
|
|
pInfoHdr);
|
|
|
|
if(pTocEntry and (pTocEntry->InfoSize > 0) and (pTocEntry->Count > 0))
|
|
{
|
|
pInfo = (PINTERFACE_STATUS_INFO)GetInfoFromTocEntry(pInfoHdr,
|
|
pTocEntry);
|
|
|
|
//
|
|
// Set it only if it is a valid value. Ignore others
|
|
//
|
|
|
|
if((pInfo isnot NULL) and
|
|
((pInfo->dwAdminStatus is IF_ADMIN_STATUS_UP) or
|
|
(pInfo->dwAdminStatus is IF_ADMIN_STATUS_DOWN)))
|
|
{
|
|
dwAdminState = pInfo->dwAdminStatus;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create an ICB
|
|
//
|
|
|
|
pNewInterfaceCb = CreateIcb(pwsInterfaceName,
|
|
hDIMInterface,
|
|
InterfaceType,
|
|
dwAdminState,
|
|
0);
|
|
|
|
if(pNewInterfaceCb is NULL)
|
|
{
|
|
ExitRouterApi();
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// HEAP_ZERO_MEMORY so we dont need to set any of the rtrdisc fields to 0
|
|
//
|
|
|
|
InitializeRouterDiscoveryInfo(pNewInterfaceCb,
|
|
pInfoHdr);
|
|
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
//
|
|
// Insert pNewInterfaceCb in interface list and hash table
|
|
// This increments the interface count and sets the seq number
|
|
//
|
|
|
|
InsertInterfaceInLists(pNewInterfaceCb);
|
|
|
|
Trace2(IF, "ICB number for %S is %d\n\n",
|
|
pwsInterfaceName, pNewInterfaceCb->dwSeqNumber);
|
|
|
|
//
|
|
// The interface have been added to wanarp, so now add the demand dial
|
|
// filters
|
|
//
|
|
|
|
if((pNewInterfaceCb->ritType is ROUTER_IF_TYPE_FULL_ROUTER) or
|
|
(pNewInterfaceCb->ritType is ROUTER_IF_TYPE_HOME_ROUTER))
|
|
{
|
|
dwResult = SetDemandDialFilters(pNewInterfaceCb,
|
|
pInfoHdr);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
CHAR Name[MAX_INTERFACE_NAME_LEN + 1];
|
|
PCHAR pszName;
|
|
|
|
pszName = Name;
|
|
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pwsInterfaceName,
|
|
-1,
|
|
pszName,
|
|
MAX_INTERFACE_NAME_LEN,
|
|
NULL,
|
|
NULL);
|
|
|
|
LogErr1(CANT_ADD_DD_FILTERS,
|
|
pszName,
|
|
dwResult);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If this is the loopback interface, do that extra something to
|
|
// initialize it
|
|
//
|
|
|
|
if(pNewInterfaceCb->ritType is ROUTER_IF_TYPE_LOOPBACK)
|
|
{
|
|
InitializeLoopbackInterface(pNewInterfaceCb);
|
|
}
|
|
|
|
//
|
|
// If this is an IP in IP tunnel, add the info if present
|
|
//
|
|
|
|
if(pNewInterfaceCb->ritType is ROUTER_IF_TYPE_TUNNEL1)
|
|
{
|
|
dwResult = SetIpInIpInfo(pNewInterfaceCb,
|
|
pInfoHdr);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"AddInterface: Error %d adding %S to ipinip",
|
|
dwResult,
|
|
pwsInterfaceName);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add multicast scope boundary info if present
|
|
//
|
|
|
|
dwResult = SetMcastLimitInfo(pNewInterfaceCb,
|
|
pInfoHdr);
|
|
|
|
dwResult = SetBoundaryInfo(pNewInterfaceCb,
|
|
pInfoHdr);
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"AddInterface: Error %d adding boundary info for %S",
|
|
dwResult,
|
|
pwsInterfaceName);
|
|
}
|
|
|
|
//
|
|
// Add Interfaces with the approp. routing protocols
|
|
// FULL_ROUTER and HOME_ROUTER -> demand dial
|
|
// DEDICATED, INTERNAL and CLIENT -> permanent
|
|
//
|
|
|
|
AddInterfaceToAllProtocols(pNewInterfaceCb,
|
|
pInfoHdr);
|
|
|
|
//
|
|
// Add filters and NAT info. We dont add the contexts to IP stack
|
|
// over here, because that will happen when we bring the interface up
|
|
//
|
|
|
|
if((pNewInterfaceCb->ritType isnot ROUTER_IF_TYPE_INTERNAL) and
|
|
(pNewInterfaceCb->ritType isnot ROUTER_IF_TYPE_LOOPBACK))
|
|
{
|
|
dwResult = SetFilterInterfaceInfo(pNewInterfaceCb,
|
|
pInfoHdr);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace1(ERR,
|
|
"AddInterface: Couldnt set filters for %S",
|
|
pNewInterfaceCb->pwszName);
|
|
}
|
|
}
|
|
|
|
|
|
if(pNewInterfaceCb->dwAdminState is IF_ADMIN_STATUS_UP)
|
|
{
|
|
//
|
|
// If the admin wants the interface up, well good for hir
|
|
//
|
|
|
|
switch(pNewInterfaceCb->ritType)
|
|
{
|
|
case ROUTER_IF_TYPE_HOME_ROUTER:
|
|
case ROUTER_IF_TYPE_FULL_ROUTER:
|
|
{
|
|
dwResult = WanInterfaceDownToInactive(pNewInterfaceCb);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"AddInterface: Error %d down->inactive for %S",
|
|
dwResult,
|
|
pNewInterfaceCb->pwszName);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ROUTER_IF_TYPE_DEDICATED:
|
|
case ROUTER_IF_TYPE_TUNNEL1:
|
|
{
|
|
if((pNewInterfaceCb->ritType is ROUTER_IF_TYPE_TUNNEL1) and
|
|
(pNewInterfaceCb->pIpIpInfo->dwLocalAddress is 0))
|
|
{
|
|
//
|
|
// Means we added the interface, but dont have info to
|
|
// add it to IP in IP
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
dwResult = LanEtcInterfaceDownToUp(pNewInterfaceCb,
|
|
TRUE);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"AddInterface: Error %d down->up for %S",
|
|
dwResult,
|
|
pNewInterfaceCb->pwszName);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The problem with LAN and IP in IP interfaces is that the stack
|
|
// brings them up even before we start. So if the user wants the
|
|
// interface DOWN to begin with, we need to tell the stack to bring
|
|
// the i/f down
|
|
//
|
|
|
|
switch(pNewInterfaceCb->ritType)
|
|
{
|
|
case ROUTER_IF_TYPE_DEDICATED:
|
|
case ROUTER_IF_TYPE_TUNNEL1:
|
|
{
|
|
dwResult = LanEtcInterfaceInitToDown(pNewInterfaceCb);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"AddInterface: Interface %S could not be set to DOWN in the stack. Results are undefined. Error %d",
|
|
pNewInterfaceCb->pwszName,
|
|
dwResult);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Add Static Routes
|
|
//
|
|
|
|
if(pNewInterfaceCb->dwAdminState is IF_ADMIN_STATUS_UP)
|
|
{
|
|
//
|
|
// Only add routes if the i/f is up
|
|
//
|
|
|
|
//
|
|
// Note that since init static routes is not being called for some
|
|
// interfaces the stack routes will not be picked up. But that
|
|
// may be OK since bringing the i/f down will delete the routes anyway
|
|
//
|
|
|
|
//
|
|
// Can only be called when the pIcb has the correct
|
|
// dwOperational State
|
|
//
|
|
|
|
InitializeStaticRoutes(pNewInterfaceCb,
|
|
pInfoHdr);
|
|
}
|
|
|
|
|
|
//
|
|
// The handle we return to DIM is a pointer to our ICB
|
|
//
|
|
|
|
*phInterface = ULongToHandle(pNewInterfaceCb->dwSeqNumber);
|
|
|
|
//
|
|
// Check if we want to enable with DIM. Do this check while we still have
|
|
// the LOCK
|
|
//
|
|
|
|
bEnable = (pNewInterfaceCb->dwAdminState is IF_ADMIN_STATUS_UP);
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
//
|
|
// We can not call upwards from a component while holding
|
|
// a lock, so we first exit the lock and then call
|
|
// enabled
|
|
//
|
|
|
|
if(bEnable)
|
|
{
|
|
EnableInterfaceWithAllProtocols(pNewInterfaceCb);
|
|
|
|
EnableInterfaceWithDIM(hDIMInterface,
|
|
PID_IP,
|
|
TRUE);
|
|
}
|
|
|
|
|
|
Trace4(IF,
|
|
"AddInterface: Added %S: Type- %d, Index- %d, ICB 0x%x",
|
|
pwsInterfaceName,
|
|
InterfaceType,
|
|
pNewInterfaceCb->dwIfIndex,
|
|
pNewInterfaceCb);
|
|
|
|
|
|
TraceLeave("AddInterface");
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DeleteInterface(
|
|
IN HANDLE hInterface
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Called by DIM to delete an interface (or when a CLIENT disconnects)
|
|
The main work is done by DeleteSingleInterface()
|
|
|
|
Locks
|
|
|
|
None
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PICB pIcb;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("DeleteInterface");
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
|
|
|
|
IpRtAssert(pIcb);
|
|
|
|
if (pIcb isnot NULL)
|
|
{
|
|
Trace1(IF,
|
|
"DeleteInterface: Deleting %S,",
|
|
pIcb->pwszName);
|
|
|
|
RemoveInterfaceFromLists(pIcb);
|
|
|
|
DeleteSingleInterface(pIcb);
|
|
|
|
if(pIcb is g_pInternalInterfaceCb)
|
|
{
|
|
g_pInternalInterfaceCb = NULL;
|
|
}
|
|
|
|
//
|
|
// Free the memory
|
|
//
|
|
|
|
HeapFree(IPRouterHeap,
|
|
0,
|
|
pIcb);
|
|
}
|
|
else
|
|
{
|
|
Trace1(
|
|
ANY,
|
|
"DeleteInterface: No interface for ICB number %d",
|
|
HandleToULong(hInterface)
|
|
);
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("DeleteInterface");
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
StopRouter(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Called by DIM to shut us down. We set our state to STOPPING (which stops
|
|
other APIs from being serviced) and set the event to let the worker
|
|
thread clean up
|
|
|
|
Locks
|
|
|
|
None
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
TraceEnter("Stop Router") ;
|
|
|
|
EnterCriticalSection(&RouterStateLock);
|
|
|
|
RouterState.IRS_State = RTR_STATE_STOPPING;
|
|
|
|
LeaveCriticalSection(&RouterStateLock);
|
|
|
|
//
|
|
// Try and delete as many interfaces as you can. The ones that are
|
|
// connected will be handled in worker thread
|
|
//
|
|
|
|
DeleteAllInterfaces();
|
|
|
|
SetEvent(g_hStopRouterEvent) ;
|
|
|
|
TraceLeave("Stop Router");
|
|
|
|
return PENDING;
|
|
}
|
|
|
|
|
|
DWORD
|
|
GetInterfaceInfo(
|
|
IN HANDLE hInterface,
|
|
OUT PVOID pvInterfaceInfo,
|
|
IN OUT PDWORD pdwInterfaceInfoSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Called by DIM to get interface info.
|
|
|
|
Locks
|
|
|
|
Acquires the ICB_LIST lock as READER
|
|
|
|
Arguments
|
|
|
|
hInterface Our handle to the i/f (pIcb)
|
|
pvInterfaceInfo Buffer to store info
|
|
pdwInterfaceInfoSize Size of Buffer. If the info is more than this, we
|
|
return the needed size
|
|
Return Value
|
|
|
|
NO_ERROR
|
|
ERROR_INSUFFICIENT_BUFFER
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwErr;
|
|
DWORD dwInfoSize = 0;
|
|
PICB pIcb;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("GetInterfaceInfo");
|
|
|
|
dwErr = NO_ERROR;
|
|
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(ICB_LIST);
|
|
|
|
pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
|
|
|
|
IpRtAssert(pIcb);
|
|
|
|
if (pIcb isnot NULL)
|
|
{
|
|
dwInfoSize = GetSizeOfInterfaceConfig(pIcb);
|
|
|
|
|
|
if(dwInfoSize > *pdwInterfaceInfoSize)
|
|
{
|
|
dwErr = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
dwErr = GetInterfaceConfiguration(pIcb,
|
|
pvInterfaceInfo,
|
|
*pdwInterfaceInfoSize);
|
|
|
|
if(dwErr isnot NO_ERROR)
|
|
{
|
|
Trace1(ERR,
|
|
"GetInterfaceInfo: Error %d getting interface configuration",
|
|
dwErr);
|
|
|
|
dwErr = ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
Trace1(
|
|
ANY,
|
|
"GetInterfaceInfo : No interface with ICB number %d",
|
|
HandleToULong(hInterface)
|
|
);
|
|
|
|
dwErr = ERROR_INVALID_INDEX;
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
*pdwInterfaceInfoSize = dwInfoSize;
|
|
|
|
TraceLeave("GetInterfaceInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
DWORD
|
|
SetInterfaceInfo(
|
|
IN HANDLE hInterface,
|
|
IN LPVOID pInterfaceInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Called by DIM when a users sets interface info. All our sets follow
|
|
OVERWRITE semantics, i.e. the new info overwrites the old info instead of
|
|
being appended to the old info.
|
|
|
|
Locks
|
|
|
|
ICB_LIST lock as WRITER
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i, dwResult;
|
|
PVOID *pInfo ;
|
|
PPROTO_CB pIfProt;
|
|
PIF_PROTO pProto;
|
|
PICB pIcb;
|
|
PLIST_ENTRY pleProto,pleNode;
|
|
PADAPTER_INFO pBinding;
|
|
IP_ADAPTER_BINDING_INFO *pBindInfo ;
|
|
PRTR_INFO_BLOCK_HEADER pInfoHdr;
|
|
PRTR_TOC_ENTRY pToc;
|
|
PINTERFACE_STATUS_INFO pStatusInfo;
|
|
BOOL bStatusChanged;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("SetInterfaceInfo");
|
|
|
|
//
|
|
// The set info is the standard Header+TOC
|
|
//
|
|
|
|
pInfoHdr = (PRTR_INFO_BLOCK_HEADER)pInterfaceInfo;
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
//
|
|
// If the current AdminState is DOWN and we are being asked to
|
|
// bring it up, we do so BEFORE setting any other info
|
|
//
|
|
|
|
pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
|
|
|
|
IpRtAssert(pIcb);
|
|
|
|
if (pIcb isnot NULL)
|
|
{
|
|
Trace1(IF,
|
|
"SetInterfaceInfo: Setting configuration for %S",
|
|
pIcb->pwszName);
|
|
|
|
bStatusChanged = FALSE;
|
|
|
|
pToc = GetPointerToTocEntry(IP_INTERFACE_STATUS_INFO, pInfoHdr);
|
|
|
|
if((pToc isnot NULL) and (pToc->InfoSize isnot 0))
|
|
{
|
|
pStatusInfo = (PINTERFACE_STATUS_INFO)GetInfoFromTocEntry(pInfoHdr,
|
|
pToc);
|
|
|
|
if((pStatusInfo isnot NULL) and
|
|
(pIcb->dwAdminState is IF_ADMIN_STATUS_DOWN) and
|
|
(pStatusInfo->dwAdminStatus is IF_ADMIN_STATUS_UP))
|
|
{
|
|
dwResult = SetInterfaceAdminStatus(pIcb,
|
|
pStatusInfo->dwAdminStatus);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"SetInterfaceInfo: Error %d setting Admin Status on %S",
|
|
dwResult,
|
|
pIcb->pwszName);
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("SetInterfaceInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
bStatusChanged = TRUE;
|
|
}
|
|
}
|
|
|
|
if(pIcb->dwAdminState is IF_ADMIN_STATUS_DOWN)
|
|
{
|
|
//
|
|
// If we are still down, we dont allow any SETS
|
|
//
|
|
|
|
Trace1(ERR,
|
|
"SetInterfaceInfo: Can not set info for %S since the the admin state is DOWN",
|
|
pIcb->pwszName);
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("SetInterfaceInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Set router discovery info
|
|
//
|
|
|
|
SetRouterDiscoveryInfo(pIcb,
|
|
pInfoHdr);
|
|
|
|
//
|
|
// Make a copy of the binding info
|
|
// This may be needed to be passed to the protocols
|
|
//
|
|
|
|
pBindInfo = NULL;
|
|
|
|
CheckBindingConsistency(pIcb);
|
|
|
|
if(pIcb->bBound)
|
|
{
|
|
pBindInfo = HeapAlloc(IPRouterHeap,
|
|
0,
|
|
SIZEOF_IP_BINDING(pIcb->dwNumAddresses));
|
|
|
|
if(pBindInfo is NULL)
|
|
{
|
|
Trace1(ERR,
|
|
"SetInterfaceInfo: Error allocating %d bytes for binding",
|
|
SIZEOF_IP_BINDING(pIcb->dwNumAddresses));
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("SetInterfaceInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
pBindInfo->AddressCount = pIcb->dwNumAddresses;
|
|
pBindInfo->RemoteAddress = pIcb->dwRemoteAddress;
|
|
|
|
pBindInfo->Mtu = pIcb->ulMtu;
|
|
pBindInfo->Speed = pIcb->ullSpeed;
|
|
|
|
for (i = 0; i < pIcb->dwNumAddresses; i++)
|
|
{
|
|
pBindInfo->Address[i].Address = pIcb->pibBindings[i].dwAddress;
|
|
pBindInfo->Address[i].Mask = pIcb->pibBindings[i].dwMask;
|
|
}
|
|
}
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
//
|
|
// Walk all the protocols and see if we have info for that protocol
|
|
// If we do, we see if the interface is already added to the protocol.
|
|
// If it is, we just call the SetInfo callback.
|
|
// Otherwise we add the interface and then bind it.
|
|
// If we dont, we see if the interface had been added to the protocol
|
|
// If it had, we delete the interface from the protocol
|
|
//
|
|
|
|
for(pleProto = g_leProtoCbList.Flink;
|
|
pleProto isnot &g_leProtoCbList;
|
|
pleProto = pleProto->Flink)
|
|
{
|
|
PPROTO_CB pProtoCb;
|
|
ULONG ulStructureVersion, ulStructureSize, ulStructureCount;
|
|
|
|
pProtoCb = CONTAINING_RECORD(pleProto,
|
|
PROTO_CB,
|
|
leList);
|
|
|
|
Trace1(IF,
|
|
"SetInterfaceInfo: Checking for info for %S",
|
|
pProtoCb->pwszDisplayName);
|
|
|
|
pToc = GetPointerToTocEntry(pProtoCb->dwProtocolId,
|
|
pInfoHdr);
|
|
|
|
if(pToc is NULL)
|
|
{
|
|
//
|
|
// Block absent means do not change anything
|
|
//
|
|
|
|
Trace1(IF,
|
|
"SetInterfaceInfo: No TOC for %S. No change",
|
|
pProtoCb->pwszDisplayName);
|
|
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
pInfo = GetInfoFromTocEntry(pInfoHdr,
|
|
pToc);
|
|
}
|
|
|
|
ulStructureVersion = 0x500;
|
|
ulStructureSize = pToc->InfoSize;
|
|
ulStructureCount = pToc->Count;
|
|
|
|
if((pToc->InfoSize isnot 0) and (pInfo isnot NULL))
|
|
{
|
|
BOOL bFound;
|
|
|
|
//
|
|
// So we have protocol info
|
|
//
|
|
|
|
Trace1(IF,
|
|
"SetInterfaceInfo: TOC Found for %S",
|
|
pProtoCb->pwszDisplayName);
|
|
|
|
//
|
|
// See if this protocol exists on the active protocol list
|
|
// for the interface
|
|
//
|
|
|
|
bFound = FALSE;
|
|
|
|
for(pleNode = pIcb->leProtocolList.Flink;
|
|
pleNode isnot &(pIcb->leProtocolList);
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProto = CONTAINING_RECORD(pleNode,
|
|
IF_PROTO,
|
|
leIfProtoLink);
|
|
|
|
if(pProto->pActiveProto->dwProtocolId is
|
|
pProtoCb->dwProtocolId)
|
|
{
|
|
//
|
|
// The interface has already been added to the interface
|
|
// Just set info
|
|
//
|
|
|
|
|
|
bFound = TRUE;
|
|
|
|
Trace2(IF,
|
|
"SetInterfaceInfo: %S already on %S. Setting info",
|
|
pProtoCb->pwszDisplayName,
|
|
pIcb->pwszName);
|
|
|
|
dwResult = (pProto->pActiveProto->pfnSetInterfaceInfo)(
|
|
pIcb->dwIfIndex,
|
|
pInfo,
|
|
ulStructureVersion,
|
|
ulStructureSize,
|
|
ulStructureCount);
|
|
|
|
//
|
|
// Set the promiscuous mode to false since this time we
|
|
// actually have info
|
|
//
|
|
|
|
pProto->bPromiscuous = FALSE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!bFound)
|
|
{
|
|
//
|
|
// The interface is being added to the protocol for the
|
|
// first time
|
|
//
|
|
|
|
Trace2(IF,
|
|
"SetInterfaceInfo: %S not running %S. Adding interface",
|
|
pProtoCb->pwszDisplayName,
|
|
pIcb->pwszName);
|
|
|
|
dwResult = AddInterfaceToProtocol(pIcb,
|
|
pProtoCb,
|
|
pInfo,
|
|
ulStructureVersion,
|
|
ulStructureSize,
|
|
ulStructureCount);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace3(ERR,
|
|
"SetInterfaceInfo: Error %d adding %S to %S",
|
|
dwResult,
|
|
pIcb->pwszName,
|
|
pProtoCb->pwszDisplayName);
|
|
}
|
|
|
|
dwResult = (pProtoCb->pfnInterfaceStatus)(
|
|
pIcb->dwIfIndex,
|
|
(pIcb->dwOperationalState >= CONNECTED),
|
|
RIS_INTERFACE_ENABLED,
|
|
NULL
|
|
);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace3(ERR,
|
|
"SetInterfaceInfo: Error %d enabling %S with %S",
|
|
dwResult,
|
|
pIcb->pwszName,
|
|
pProtoCb->pwszDisplayName);
|
|
}
|
|
|
|
//
|
|
// If the binding information is available, pass it to the
|
|
// protocol
|
|
//
|
|
|
|
if(pBindInfo)
|
|
{
|
|
Trace2(IF,
|
|
"SetInterfaceInfo: Binding %S in %S",
|
|
pIcb->pwszName,
|
|
pProtoCb->pwszDllName);
|
|
|
|
dwResult = BindInterfaceInProtocol(pIcb,
|
|
pProtoCb,
|
|
pBindInfo);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace3(ERR,
|
|
"SetInterfaceInfo: Error %d binding %S to %S",
|
|
dwResult,
|
|
pIcb->pwszName,
|
|
pProtoCb->pwszDllName);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// If this is the internal interface, also call connect client
|
|
// for connected clients
|
|
//
|
|
|
|
if((pIcb is g_pInternalInterfaceCb) and
|
|
(pProtoCb->pfnConnectClient))
|
|
{
|
|
PLIST_ENTRY pleTempNode;
|
|
IP_LOCAL_BINDING clientAddr;
|
|
PICB pTempIf;
|
|
|
|
for(pleTempNode = &ICBList;
|
|
pleTempNode->Flink != &ICBList;
|
|
pleTempNode = pleTempNode->Flink)
|
|
{
|
|
pTempIf = CONTAINING_RECORD(pleTempNode->Flink,
|
|
ICB,
|
|
leIfLink);
|
|
|
|
|
|
if(pTempIf->ritType isnot ROUTER_IF_TYPE_CLIENT)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
clientAddr.Address = pTempIf->pibBindings[0].dwAddress;
|
|
clientAddr.Mask = pTempIf->pibBindings[0].dwMask;
|
|
|
|
pProtoCb->pfnConnectClient(g_pInternalInterfaceCb->dwIfIndex,
|
|
&clientAddr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// A zero size TOC was found for this particular protocol. If
|
|
// this protocol exists in the current ActiveProtocol list,
|
|
// remove the interface from the protocol
|
|
//
|
|
|
|
Trace2(IF,
|
|
"SetInterfaceInfo: A zero size TOC was found for %S on %S",
|
|
pProtoCb->pwszDllName,
|
|
pIcb->pwszName);
|
|
|
|
pleNode = pIcb->leProtocolList.Flink;
|
|
|
|
while(pleNode isnot &(pIcb->leProtocolList))
|
|
{
|
|
pProto = CONTAINING_RECORD(pleNode,
|
|
IF_PROTO,
|
|
leIfProtoLink);
|
|
|
|
pleNode = pleNode->Flink;
|
|
|
|
if(pProto->pActiveProto->dwProtocolId is pProtoCb->dwProtocolId)
|
|
{
|
|
IpRtAssert(pProto->pActiveProto is pProtoCb);
|
|
|
|
//
|
|
// Call the routing protocol's deleteinterface entrypoint
|
|
//
|
|
|
|
Trace2(IF,
|
|
"SetInterfaceInfo: Deleting %S from %S",
|
|
pProtoCb->pwszDllName,
|
|
pIcb->pwszName);
|
|
|
|
dwResult = (pProtoCb->pfnDeleteInterface)(pIcb->dwIfIndex);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace3(ERR,
|
|
"SetInterfaceInfo: Err %d deleting %S from %S",
|
|
dwResult,
|
|
pIcb->pwszName,
|
|
pProtoCb->pwszDllName);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Delete this protocol from the list of protocols
|
|
// in the Interface
|
|
//
|
|
|
|
RemoveEntryList(&(pProto->leIfProtoLink));
|
|
|
|
HeapFree(IPRouterHeap,
|
|
0,
|
|
pProto);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
|
|
for(i = 0; i < NUM_INFO_CBS; i++)
|
|
{
|
|
dwResult = g_rgicInfoCb[i].pfnSetInterfaceInfo(pIcb,
|
|
pInfoHdr);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace3(ERR,
|
|
"SetInterfaceInfo: Error %d setting %s info for %S",
|
|
dwResult,
|
|
g_rgicInfoCb[i].pszInfoName,
|
|
pIcb->pwszName);
|
|
}
|
|
}
|
|
|
|
if(pBindInfo)
|
|
{
|
|
HeapFree(IPRouterHeap,
|
|
0,
|
|
pBindInfo);
|
|
}
|
|
|
|
|
|
//
|
|
// If we have already changed the status dont do it again
|
|
//
|
|
|
|
if(!bStatusChanged)
|
|
{
|
|
dwResult = SetInterfaceStatusInfo(pIcb,
|
|
pInfoHdr);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"SetInterfaceInfo: Error %d setting status info for %S",
|
|
dwResult,
|
|
pIcb->pwszName);
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
Trace1(
|
|
ANY,
|
|
"SetInterfaceInfo : No interface with ICB number %d",
|
|
HandleToULong(hInterface)
|
|
);
|
|
}
|
|
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("SetInterfaceInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
InterfaceNotReachable(
|
|
IN HANDLE hInterface,
|
|
IN UNREACHABILITY_REASON Reason
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Called by DIM to tell us that an interface should be considered
|
|
UNREACHABLE till further notice
|
|
|
|
Locks
|
|
|
|
None
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PICB pIcb;
|
|
PADAPTER_INFO pBinding;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("InterfaceNotReachable");
|
|
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
//
|
|
// If it is a CLIENT interface all this means is that the connection
|
|
// failed
|
|
//
|
|
|
|
pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
|
|
|
|
IpRtAssert(pIcb);
|
|
|
|
if (pIcb isnot NULL)
|
|
{
|
|
if(pIcb->ritType is ROUTER_IF_TYPE_CLIENT)
|
|
{
|
|
pIcb->dwOperationalState = UNREACHABLE;
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
Trace2(IF,
|
|
"InterfaceNotReachable: %S is not reachable for reason %d",
|
|
pIcb->pwszName,
|
|
Reason) ;
|
|
|
|
if(Reason == INTERFACE_NO_MEDIA_SENSE)
|
|
{
|
|
HandleMediaSenseEvent(pIcb,
|
|
FALSE);
|
|
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
#if STATIC_RT_DBG
|
|
|
|
ENTER_WRITER(BINDING_LIST);
|
|
|
|
pBinding = GetInterfaceBinding(pIcb->dwIfIndex);
|
|
|
|
pBinding->bUnreach = TRUE;
|
|
|
|
EXIT_LOCK(BINDING_LIST);
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// If we were trying to connect on this - then inform WANARP to
|
|
// drain its queued up packets
|
|
//
|
|
|
|
if(pIcb->dwOperationalState is CONNECTING)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
Status = NotifyWanarpOfFailure(pIcb);
|
|
|
|
if((Status isnot STATUS_PENDING) and
|
|
(Status isnot STATUS_SUCCESS))
|
|
{
|
|
Trace1(ERR,
|
|
"InterfaceNotReachable: IOCTL_WANARP_CONNECT_FAILED failed. Status %x",
|
|
Status);
|
|
}
|
|
|
|
//
|
|
// If it was connecting, then the stack has set the interface context
|
|
// to something other than 0xffffffff. Hence he wont dial out on that
|
|
// route. We need to change the context in the stack back to invalid
|
|
// so that new packets cause the demand dial
|
|
//
|
|
|
|
ChangeAdapterIndexForDodRoutes(pIcb->dwIfIndex);
|
|
|
|
//
|
|
// We are still in INACTIVE state so dont have to call any if the
|
|
// WanInterface*To*() functions. But since we are in CONNECTING
|
|
// WANARP must have called us with CONNECTION notification
|
|
// so we undo what we did there
|
|
//
|
|
|
|
DeAllocateBindings(pIcb);
|
|
|
|
ClearNotificationFlags(pIcb);
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// A connected interface must first be disconnected
|
|
//
|
|
|
|
if(pIcb->dwOperationalState is CONNECTED)
|
|
{
|
|
Trace1(IF,
|
|
"InterfaceNotReachable: %S is already connected",
|
|
pIcb->pwszName);
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
ExitRouterApi();
|
|
|
|
return ERROR_INVALID_HANDLE_STATE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// This sets the state to UNREACHABLE
|
|
//
|
|
|
|
WanInterfaceInactiveToDown(pIcb,
|
|
FALSE);
|
|
}
|
|
|
|
else
|
|
{
|
|
Trace1(
|
|
ANY,
|
|
"InterfaceNotReachable : No interface with ICB number %d",
|
|
HandleToULong(hInterface)
|
|
);
|
|
}
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("InterfaceNotReachable");
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
InterfaceReachable(
|
|
IN HANDLE hInterface
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Notification by DIM that the interface is REACHABLE again
|
|
|
|
Locks
|
|
|
|
None
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwErr;
|
|
|
|
PICB pIcb;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("InterfaceReachable");
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
|
|
|
|
IpRtAssert(pIcb);
|
|
|
|
if (pIcb isnot NULL)
|
|
{
|
|
Trace1(IF, "InterfaceReachable: %S is now reachable",
|
|
pIcb->pwszName);
|
|
|
|
if((pIcb->dwOperationalState <= UNREACHABLE) and
|
|
(pIcb->dwAdminState is IF_ADMIN_STATUS_UP))
|
|
{
|
|
//
|
|
// only if it was unreachable before.
|
|
//
|
|
|
|
if(pIcb->ritType is ROUTER_IF_TYPE_DEDICATED)
|
|
{
|
|
dwErr = LanEtcInterfaceDownToUp(pIcb,
|
|
FALSE);
|
|
}
|
|
else
|
|
{
|
|
dwErr = WanInterfaceDownToInactive(pIcb);
|
|
}
|
|
|
|
if(dwErr isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"InterfaceReachable: Err %d bringing up %S",
|
|
dwErr,
|
|
pIcb->pwszName);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Trace1(
|
|
ANY,
|
|
"InterfaceReachable : No interface with ICB number %d",
|
|
HandleToULong(hInterface)
|
|
);
|
|
}
|
|
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("InterfaceNotReachable");
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
InterfaceConnected(
|
|
IN HANDLE hInterface,
|
|
IN PVOID pFilter,
|
|
IN PVOID pPppProjectionResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Notification by DIM that an interface has connected.
|
|
|
|
Locks
|
|
|
|
None
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwResult, i;
|
|
PICB pIcb;
|
|
|
|
INTERFACE_ROUTE_INFO rifRoute;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("InterfaceConnected");
|
|
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
|
|
|
|
IpRtAssert(pIcb);
|
|
|
|
if (pIcb != NULL)
|
|
{
|
|
Trace2(IF,
|
|
"InterfaceConnected: InterfaceConnected called for %S. State is %d",
|
|
pIcb->pwszName,
|
|
pIcb->dwOperationalState);
|
|
|
|
if((pIcb->ritType is ROUTER_IF_TYPE_CLIENT) and
|
|
(g_pInternalInterfaceCb is NULL))
|
|
{
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
ExitRouterApi();
|
|
|
|
return ERROR_INVALID_HANDLE_STATE;
|
|
}
|
|
|
|
if((pIcb->ritType is ROUTER_IF_TYPE_CLIENT) and
|
|
g_bUninitServer)
|
|
{
|
|
TryUpdateInternalInterface();
|
|
}
|
|
|
|
if(pIcb->dwOperationalState is UNREACHABLE)
|
|
{
|
|
//
|
|
// going from unreachable to connecting. This can happen
|
|
//
|
|
|
|
WanInterfaceDownToInactive(pIcb);
|
|
}
|
|
|
|
if(pIcb->dwOperationalState isnot CONNECTING)
|
|
{
|
|
//
|
|
// Wanarp has not called us as yet, so set the state to connecting
|
|
//
|
|
|
|
pIcb->dwOperationalState = CONNECTING;
|
|
}
|
|
|
|
SetDDMNotification(pIcb);
|
|
|
|
if(HaveAllNotificationsBeenReceived(pIcb))
|
|
{
|
|
//
|
|
// Wanarp has also called us
|
|
//
|
|
|
|
pIcb->dwOperationalState = CONNECTED ;
|
|
|
|
if(pIcb->ritType isnot ROUTER_IF_TYPE_CLIENT)
|
|
{
|
|
WRITER_TO_READER(ICB_LIST);
|
|
|
|
WanInterfaceInactiveToUp(pIcb);
|
|
}
|
|
else
|
|
{
|
|
IP_LOCAL_BINDING clientAddr;
|
|
PLIST_ENTRY pleNode;
|
|
PPP_IPCP_RESULT *pProjInfo;
|
|
|
|
pProjInfo = &(((PPP_PROJECTION_RESULT *)pPppProjectionResult)->ip);
|
|
|
|
IpRtAssert(pIcb->pibBindings);
|
|
|
|
pIcb->dwNumAddresses = 1;
|
|
|
|
pIcb->bBound = TRUE;
|
|
|
|
pIcb->pibBindings[0].dwAddress = pProjInfo->dwRemoteAddress;
|
|
|
|
if(g_pInternalInterfaceCb->bBound)
|
|
{
|
|
pIcb->pibBindings[0].dwMask =
|
|
g_pInternalInterfaceCb->pibBindings[0].dwMask;
|
|
}
|
|
else
|
|
{
|
|
pIcb->pibBindings[0].dwMask =
|
|
GetClassMask(pProjInfo->dwRemoteAddress);
|
|
}
|
|
|
|
clientAddr.Address = pIcb->pibBindings[0].dwAddress;
|
|
clientAddr.Mask = pIcb->pibBindings[0].dwMask;
|
|
|
|
|
|
#if 0
|
|
//
|
|
// Add a non-stack host route to the client
|
|
//
|
|
|
|
rifRoute.dwRtInfoMask = HOST_ROUTE_MASK;
|
|
rifRoute.dwRtInfoNextHop = clientAddr.Address;
|
|
rifRoute.dwRtInfoDest = clientAddr.Address;
|
|
rifRoute.dwRtInfoIfIndex = g_pInternalInterfaceCb->dwIfIndex;
|
|
rifRoute.dwRtInfoMetric1 = 1;
|
|
rifRoute.dwRtInfoMetric2 = 0;
|
|
rifRoute.dwRtInfoMetric3 = 0;
|
|
rifRoute.dwRtInfoPreference=
|
|
ComputeRouteMetric(MIB_IPPROTO_LOCAL);
|
|
rifRoute.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
|
|
RTM_VIEW_MASK_MCAST; // XXX config
|
|
rifRoute.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
|
|
rifRoute.dwRtInfoProto = MIB_IPPROTO_NETMGMT;
|
|
rifRoute.dwRtInfoAge = INFINITE;
|
|
rifRoute.dwRtInfoNextHopAS = 0;
|
|
rifRoute.dwRtInfoPolicy = 0;
|
|
|
|
dwResult = AddSingleRoute(g_pInternalInterfaceCb->dwIfIndex,
|
|
&rifRoute,
|
|
clientAddr.Mask,
|
|
0, // RTM_ROUTE_INFO::Flags
|
|
TRUE,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
#endif
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
//
|
|
// Call ConnectClient for all the protocols configured
|
|
// over the ServerInterface
|
|
//
|
|
|
|
for(pleNode = g_pInternalInterfaceCb->leProtocolList.Flink;
|
|
pleNode isnot &(g_pInternalInterfaceCb->leProtocolList);
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
PIF_PROTO pIfProto;
|
|
|
|
pIfProto = CONTAINING_RECORD(pleNode,
|
|
IF_PROTO,
|
|
leIfProtoLink);
|
|
|
|
if(pIfProto->pActiveProto->pfnConnectClient)
|
|
{
|
|
pIfProto->pActiveProto->pfnConnectClient(
|
|
g_pInternalInterfaceCb->dwIfIndex,
|
|
&clientAddr
|
|
);
|
|
}
|
|
}
|
|
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
|
|
for (i=0; i<NUM_INFO_CBS; i++)
|
|
{
|
|
if (!g_rgicInfoCb[i].pfnBindInterface)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
dwResult = g_rgicInfoCb[i].pfnBindInterface(pIcb);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace3(IF,
|
|
"InterfaceConnected: Error %d binding %S for %s info",
|
|
dwResult,
|
|
pIcb->pwszName,
|
|
g_rgicInfoCb[i].pszInfoName);
|
|
}
|
|
}
|
|
|
|
AddAllClientRoutes(pIcb,
|
|
g_pInternalInterfaceCb->dwIfIndex);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
Trace1(
|
|
ANY,
|
|
"InterfaceConnected : No interface with ICB number %d",
|
|
HandleToULong(hInterface)
|
|
);
|
|
}
|
|
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("InterfaceConnected");
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
SetGlobalInfo(
|
|
IN LPVOID pGlobalInfo
|
|
)
|
|
{
|
|
DWORD dwSize, dwResult, i, j;
|
|
PPROTO_CB pProtocolCb;
|
|
PLIST_ENTRY pleNode ;
|
|
BOOL bFoundProto, bFoundInfo;
|
|
PRTR_INFO_BLOCK_HEADER pInfoHdr;
|
|
MPR_PROTOCOL_0 *pmpProtocolInfo;
|
|
DWORD dwNumProtoEntries;
|
|
PVOID pvInfo;
|
|
PRTR_TOC_ENTRY pToc;
|
|
PGLOBAL_INFO pRtrGlobalInfo;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("SetGlobalInfo");
|
|
|
|
if(pGlobalInfo is NULL)
|
|
{
|
|
TraceLeave("SetGlobalInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
pInfoHdr = (PRTR_INFO_BLOCK_HEADER)pGlobalInfo;
|
|
|
|
//
|
|
// Set Routing Protocol Priority info. Priority information is in its
|
|
// own DLL so no locks need to be taken
|
|
//
|
|
|
|
SetPriorityInfo(pInfoHdr);
|
|
|
|
//
|
|
// Set Multicast Scope info (no locks needed)
|
|
//
|
|
|
|
SetScopeInfo(pInfoHdr);
|
|
|
|
//
|
|
// Enforce the discipline of taking ICBListLock before Routing lock
|
|
//
|
|
|
|
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
ENTER_WRITER(PROTOCOL_CB_LIST);
|
|
|
|
pToc = GetPointerToTocEntry(IP_GLOBAL_INFO,
|
|
pInfoHdr);
|
|
|
|
if(pToc is NULL)
|
|
{
|
|
Trace0(GLOBAL,
|
|
"SetGlobalInfo: No TOC found for Global Info");
|
|
}
|
|
else
|
|
{
|
|
if(pToc->InfoSize is 0)
|
|
{
|
|
g_dwLoggingLevel = IPRTR_LOGGING_NONE;
|
|
|
|
}
|
|
else
|
|
{
|
|
pRtrGlobalInfo = (PGLOBAL_INFO)GetInfoFromTocEntry(pInfoHdr,
|
|
pToc);
|
|
g_dwLoggingLevel = (pRtrGlobalInfo isnot NULL) ?
|
|
pRtrGlobalInfo->dwLoggingLevel :
|
|
IPRTR_LOGGING_NONE;
|
|
}
|
|
}
|
|
|
|
dwResult = MprSetupProtocolEnum(PID_IP,
|
|
(PBYTE *)(&pmpProtocolInfo),
|
|
&dwNumProtoEntries);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace1(ERR,
|
|
"SetGlobalInfo: Error %d loading protocol info from registry",
|
|
dwResult);
|
|
|
|
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("SetGlobalInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return ERROR_REGISTRY_CORRUPT;
|
|
}
|
|
|
|
|
|
//
|
|
// Now go looking for protocols TOCs
|
|
//
|
|
|
|
for(i = 0; i < pInfoHdr->TocEntriesCount; i++)
|
|
{
|
|
ULONG ulStructureVersion, ulStructureSize, ulStructureCount;
|
|
DWORD dwType;
|
|
|
|
dwType = TYPE_FROM_PROTO_ID(pInfoHdr->TocEntry[i].InfoType);
|
|
|
|
if(dwType == PROTO_TYPE_MS1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Go through the loaded routing protocols and see if the protocol is
|
|
// in the list
|
|
// If it is, we just call SetGlobalInfo callback.
|
|
// If not we load the protocol
|
|
//
|
|
|
|
pProtocolCb = NULL;
|
|
bFoundProto = FALSE;
|
|
|
|
for(pleNode = g_leProtoCbList.Flink;
|
|
pleNode != &g_leProtoCbList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProtocolCb = CONTAINING_RECORD(pleNode,
|
|
PROTO_CB,
|
|
leList) ;
|
|
|
|
if(pProtocolCb->dwProtocolId is pInfoHdr->TocEntry[i].InfoType)
|
|
{
|
|
bFoundProto = TRUE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(bFoundProto)
|
|
{
|
|
//
|
|
// Ok, so this protocol was already loaded.
|
|
//
|
|
|
|
if(pInfoHdr->TocEntry[i].InfoSize is 0)
|
|
{
|
|
//
|
|
// 0 TOC size means delete
|
|
//
|
|
|
|
if(pProtocolCb->posOpState is RTR_STATE_RUNNING)
|
|
{
|
|
//
|
|
// If its stopped or stopping, we dont tell it again
|
|
//
|
|
|
|
Trace1(GLOBAL,
|
|
"SetGlobalInfo: Removing %S since the TOC size was 0",
|
|
pProtocolCb->pwszDisplayName);
|
|
|
|
dwResult = StopRoutingProtocol(pProtocolCb);
|
|
|
|
if(dwResult is NO_ERROR)
|
|
{
|
|
//
|
|
// The routing protocol stopped synchronously and
|
|
// all references to it in the interfaces have
|
|
// been removed
|
|
//
|
|
|
|
//
|
|
// At this point we need to hold the PROTOCOL_CB_LIST
|
|
// lock exclusively
|
|
//
|
|
|
|
//
|
|
// relenquish CPU to enable DLL threads to
|
|
// finish
|
|
//
|
|
|
|
Sleep(0);
|
|
|
|
FreeLibrary(pProtocolCb->hiHInstance);
|
|
|
|
RemoveEntryList(&(pProtocolCb->leList));
|
|
|
|
HeapFree(IPRouterHeap,
|
|
0,
|
|
pProtocolCb);
|
|
|
|
TotalRoutingProtocols--;
|
|
}
|
|
else
|
|
{
|
|
if(dwResult isnot ERROR_PROTOCOL_STOP_PENDING)
|
|
{
|
|
Trace2(ERR,
|
|
"SetGlobalInfo: Error %d stopping %S. Not removing from list",
|
|
dwResult,
|
|
pProtocolCb->pwszDisplayName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// So we do have info with this protocol
|
|
//
|
|
|
|
pvInfo = GetInfoFromTocEntry(pInfoHdr,
|
|
&(pInfoHdr->TocEntry[i]));
|
|
|
|
|
|
//ulStructureVersion = pInfoHdr->TocEntry[i].InfoVersion;
|
|
ulStructureVersion = 0x500;
|
|
ulStructureSize = pInfoHdr->TocEntry[i].InfoSize;
|
|
ulStructureCount = pInfoHdr->TocEntry[i].Count;
|
|
|
|
dwResult = (pProtocolCb->pfnSetGlobalInfo)(pvInfo,
|
|
ulStructureVersion,
|
|
ulStructureSize,
|
|
ulStructureCount);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"SetGlobalInfo: Error %d setting info for %S",
|
|
dwResult,
|
|
pProtocolCb->pwszDisplayName);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Well the protocol was not found so, lets load it up
|
|
//
|
|
|
|
//
|
|
// Bad case when size == 0
|
|
//
|
|
|
|
if(pInfoHdr->TocEntry[i].InfoSize is 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
bFoundInfo = FALSE;
|
|
|
|
for(j = 0; j < dwNumProtoEntries; j ++)
|
|
{
|
|
if(pmpProtocolInfo[j].dwProtocolId is pInfoHdr->TocEntry[i].InfoType)
|
|
{
|
|
bFoundInfo = TRUE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!bFoundInfo)
|
|
{
|
|
Trace1(ERR,
|
|
"SetGlobalInfo: Couldnt find config information for %d",
|
|
pInfoHdr->TocEntry[i].InfoType);
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Load the library and make a cb for this protocol
|
|
//
|
|
|
|
|
|
dwSize =
|
|
(wcslen(pmpProtocolInfo[j].wszProtocol) + wcslen(pmpProtocolInfo[j].wszDLLName) + 2) * sizeof(WCHAR) +
|
|
sizeof(PROTO_CB);
|
|
|
|
pProtocolCb = HeapAlloc(IPRouterHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
dwSize);
|
|
|
|
if(pProtocolCb is NULL)
|
|
{
|
|
Trace2(ERR,
|
|
"SetGlobalInfo: Error allocating %d bytes for %S",
|
|
dwSize,
|
|
pmpProtocolInfo[j].wszProtocol);
|
|
|
|
continue ;
|
|
}
|
|
|
|
pvInfo = GetInfoFromTocEntry(pInfoHdr,
|
|
&(pInfoHdr->TocEntry[i]));
|
|
|
|
//ulStructureVersion = pInfoHdr->TocEntry[i].InfoVersion;
|
|
ulStructureSize = pInfoHdr->TocEntry[i].InfoSize;
|
|
ulStructureCount = pInfoHdr->TocEntry[i].Count;
|
|
|
|
dwResult = LoadProtocol(&(pmpProtocolInfo[j]),
|
|
pProtocolCb,
|
|
pvInfo,
|
|
ulStructureVersion,
|
|
ulStructureSize,
|
|
ulStructureCount);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"SetGlobalInfo: %S failed to load: %d",
|
|
pmpProtocolInfo[j].wszProtocol,
|
|
dwResult);
|
|
|
|
HeapFree (IPRouterHeap,
|
|
0,
|
|
pProtocolCb) ;
|
|
|
|
}
|
|
else
|
|
{
|
|
pProtocolCb->posOpState = RTR_STATE_RUNNING ;
|
|
|
|
//
|
|
// Insert this routing protocol in the list of routing
|
|
// protocols
|
|
//
|
|
|
|
InsertTailList (&g_leProtoCbList, &pProtocolCb->leList);
|
|
|
|
Trace1(GLOBAL,
|
|
"SetGlobalInfo: %S successfully initialized",
|
|
pmpProtocolInfo[j].wszProtocol) ;
|
|
|
|
TotalRoutingProtocols++;
|
|
|
|
//
|
|
// Lets see if it wants to be in promiscuous add mode.
|
|
// If so, add all the current interfaces
|
|
//
|
|
|
|
if(pProtocolCb->fSupportedFunctionality & RF_ADD_ALL_INTERFACES)
|
|
{
|
|
//
|
|
// First lets add the internal interface
|
|
//
|
|
|
|
if(g_pInternalInterfaceCb)
|
|
{
|
|
dwResult = AddInterfaceToProtocol(g_pInternalInterfaceCb,
|
|
pProtocolCb,
|
|
NULL,
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace3(ERR,
|
|
"SetGlobalInfo: Error %d adding %S to %S promously",
|
|
dwResult,
|
|
g_pInternalInterfaceCb->pwszName,
|
|
pProtocolCb->pwszDisplayName);
|
|
|
|
}
|
|
|
|
if(g_pInternalInterfaceCb->dwAdminState is IF_ADMIN_STATUS_UP)
|
|
{
|
|
EnableInterfaceWithAllProtocols(g_pInternalInterfaceCb);
|
|
}
|
|
|
|
if(g_pInternalInterfaceCb->bBound)
|
|
{
|
|
BindInterfaceInAllProtocols(g_pInternalInterfaceCb);
|
|
}
|
|
}
|
|
|
|
for(pleNode = &ICBList;
|
|
pleNode->Flink != &ICBList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
PICB pIcb;
|
|
|
|
pIcb = CONTAINING_RECORD(pleNode->Flink,
|
|
ICB,
|
|
leIfLink);
|
|
|
|
|
|
if(pIcb is g_pInternalInterfaceCb)
|
|
{
|
|
//
|
|
// Already added, continue;
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
if(pIcb->ritType is ROUTER_IF_TYPE_DIALOUT)
|
|
{
|
|
//
|
|
// Skip dial out interfaces
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
if(pIcb->ritType is ROUTER_IF_TYPE_CLIENT)
|
|
{
|
|
IP_LOCAL_BINDING clientAddr;
|
|
|
|
//
|
|
// Just call connect client for these
|
|
// We have to have internal interface
|
|
//
|
|
|
|
clientAddr.Address = pIcb->pibBindings[0].dwAddress;
|
|
clientAddr.Mask = pIcb->pibBindings[0].dwMask;
|
|
|
|
if(pProtocolCb->pfnConnectClient)
|
|
{
|
|
pProtocolCb->pfnConnectClient(g_pInternalInterfaceCb->dwIfIndex,
|
|
&clientAddr);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// The rest we add
|
|
//
|
|
|
|
dwResult = AddInterfaceToProtocol(pIcb,
|
|
pProtocolCb,
|
|
NULL,
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace3(ERR,
|
|
"SetGlobalInfo: Error %d adding %S to %S promiscuously",
|
|
dwResult,
|
|
pIcb->pwszName,
|
|
pProtocolCb->pwszDisplayName);
|
|
|
|
continue;
|
|
}
|
|
|
|
if(pIcb->dwAdminState is IF_ADMIN_STATUS_UP)
|
|
{
|
|
EnableInterfaceWithAllProtocols(pIcb);
|
|
}
|
|
|
|
if(pIcb->bBound)
|
|
{
|
|
BindInterfaceInAllProtocols(pIcb);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MprSetupProtocolFree(pmpProtocolInfo);
|
|
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("SetGlobalInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
GetGlobalInfo(
|
|
OUT LPVOID pGlobalInfo,
|
|
IN OUT LPDWORD lpdwGlobalInfoSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This function
|
|
|
|
Locks
|
|
|
|
None
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwSize;
|
|
DWORD dwResult;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("GetGlobalInfo");
|
|
|
|
ENTER_READER(ICB_LIST);
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
dwSize = GetSizeOfGlobalInfo();
|
|
|
|
if(dwSize > *lpdwGlobalInfoSize)
|
|
{
|
|
*lpdwGlobalInfoSize = dwSize;
|
|
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("GetGlobalInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
|
|
dwResult = GetGlobalConfiguration((PRTR_INFO_BLOCK_HEADER)pGlobalInfo,
|
|
*lpdwGlobalInfoSize);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace1(ERR,
|
|
"GetGlobalInfo: Error %d getting global config",
|
|
dwResult);
|
|
}
|
|
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
|
|
TraceLeave("GetGlobalInfo");
|
|
|
|
ExitRouterApi();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
UpdateRoutes(
|
|
IN HANDLE hInterface,
|
|
IN HANDLE hEvent
|
|
)
|
|
{
|
|
DWORD i;
|
|
DWORD dwResult;
|
|
PIF_PROTO pProto;
|
|
PICB pIcb;
|
|
PLIST_ENTRY pleNode;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("UpdateRoutes");
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(ICB_LIST);
|
|
|
|
pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
|
|
|
|
IpRtAssert(pIcb);
|
|
|
|
if (pIcb != NULL)
|
|
{
|
|
Trace1(ROUTE,
|
|
"UpdateRoutes: Updating routes over %S", pIcb->pwszName) ;
|
|
|
|
if(pIcb->dwOperationalState < CONNECTED)
|
|
{
|
|
Trace1(ERR,
|
|
"UpdateRoutes: %S is not connected.",
|
|
pIcb->pwszName);
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("UpdateRoutes");
|
|
|
|
ExitRouterApi();
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// We first delete all the routes over this interface. If we
|
|
// fail the update routes, that means we have lost the autostatic
|
|
// routes. But that is OK, since if we fail for some reason - that
|
|
// is an error condition and we should be getting rid of the routes
|
|
// anyway. Sure, we can fail for non protocol related reasons
|
|
// (out of memory) but that is also an error. Earlier we used to
|
|
// let the routing protocol finish its update and then delete the
|
|
// route. However if RIP did not have "Overwrite routes" stuff
|
|
// set, it would not write its routes to RTM. So now we first delete
|
|
// the routes. This means that for some time (while the update is
|
|
// going on) we have loss of reachability.
|
|
//
|
|
|
|
dwResult = DeleteRtmRoutesOnInterface(g_hAutoStaticRoute,
|
|
pIcb->dwIfIndex);
|
|
|
|
if(//(dwResult isnot ERROR_NO_ROUTES) and
|
|
(dwResult isnot NO_ERROR))
|
|
{
|
|
Trace1(ERR,
|
|
"UpdateRoutes: Error %d block deleting routes",
|
|
dwResult);
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("UpdateRoutes");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
if(pIcb->hDIMNotificationEvent isnot NULL)
|
|
{
|
|
//
|
|
// There is already an update routes for this interface in progress
|
|
//
|
|
|
|
dwResult = ERROR_UPDATE_IN_PROGRESS;
|
|
}
|
|
else
|
|
{
|
|
dwResult = ERROR_FILE_NOT_FOUND;
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
//
|
|
// Find a protocol that supports update route operation. we
|
|
// settle for the first one that does.
|
|
//
|
|
|
|
for(pleNode = pIcb->leProtocolList.Flink;
|
|
pleNode isnot &(pIcb->leProtocolList);
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProto = CONTAINING_RECORD(pleNode,
|
|
IF_PROTO,
|
|
leIfProtoLink);
|
|
|
|
if(pProto->pActiveProto->pfnUpdateRoutes isnot NULL)
|
|
{
|
|
//
|
|
// found a routing protocol that supports updates
|
|
//
|
|
|
|
dwResult = (pProto->pActiveProto->pfnUpdateRoutes)(
|
|
pIcb->dwIfIndex
|
|
);
|
|
|
|
if((dwResult isnot NO_ERROR) and (dwResult isnot PENDING))
|
|
{
|
|
//
|
|
// The protocol can return NO_ERROR, or PENDING all
|
|
// else is an error
|
|
//
|
|
|
|
Trace2(ERR,
|
|
"UpdateRoutes: %S returned %d while trying to update routes. Trying other protocols",
|
|
pProto->pActiveProto->pwszDisplayName,
|
|
dwResult);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Even if the protocol returned NO_ERROR, this is
|
|
// an inherently
|
|
// asynchronous call, so we return PENDING
|
|
//
|
|
|
|
dwResult = PENDING;
|
|
|
|
pIcb->hDIMNotificationEvent = hEvent;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Trace1(
|
|
ANY,
|
|
"UpdateRoutes : No interface with ICB number %d",
|
|
HandleToULong(hInterface)
|
|
);
|
|
|
|
dwResult = ERROR_INVALID_INDEX;
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("UpdateRoutes");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
DWORD
|
|
GetUpdateRoutesResult(
|
|
IN HANDLE hInterface,
|
|
OUT PDWORD pdwUpdateResult
|
|
)
|
|
{
|
|
DWORD dwResult ;
|
|
UpdateResultList *pResult ;
|
|
PLIST_ENTRY pleNode ;
|
|
PICB pIcb;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("GetUpdateRoutesResult") ;
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
|
|
|
|
IpRtAssert(pIcb);
|
|
|
|
if (pIcb != NULL)
|
|
{
|
|
if (IsListEmpty (&pIcb->lePendingResultList))
|
|
{
|
|
dwResult = ERROR_CAN_NOT_COMPLETE ;
|
|
}
|
|
else
|
|
{
|
|
pleNode = RemoveHeadList (&pIcb->lePendingResultList) ;
|
|
|
|
pResult = CONTAINING_RECORD(pleNode,
|
|
UpdateResultList,
|
|
URL_List) ;
|
|
|
|
*pdwUpdateResult = pResult->URL_UpdateStatus;
|
|
|
|
HeapFree(IPRouterHeap,
|
|
0,
|
|
pResult) ;
|
|
|
|
dwResult = NO_ERROR ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Trace1(
|
|
ANY,
|
|
"GetInterfaceInfo : No interface with ICB number %d",
|
|
HandleToULong(hInterface)
|
|
);
|
|
|
|
dwResult = ERROR_INVALID_INDEX;
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
TraceLeave("GetUpdateRoutesResult");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
DemandDialRequest(
|
|
IN DWORD dwProtocolId,
|
|
IN DWORD dwInterfaceIndex
|
|
)
|
|
{
|
|
PICB pIcb;
|
|
DWORD dwResult;
|
|
HANDLE hDim;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("DemandDialRequest");
|
|
|
|
//
|
|
// This doesnt follow the normal locking rules of not taking locks
|
|
// when calling up
|
|
//
|
|
|
|
ENTER_READER(ICB_LIST);
|
|
|
|
pIcb = InterfaceLookupByIfIndex(dwInterfaceIndex);
|
|
|
|
if(pIcb is NULL)
|
|
{
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
return ERROR_INVALID_INDEX;
|
|
}
|
|
|
|
hDim = pIcb->hDIMHandle;
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
dwResult = (ConnectInterface)(hDim,
|
|
PID_IP);
|
|
|
|
TraceLeave("DemandDialRequest");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
RtrMgrMIBEntryCreate(
|
|
IN DWORD dwRoutingPid,
|
|
IN DWORD dwEntrySize,
|
|
IN LPVOID lpEntry
|
|
)
|
|
{
|
|
PMIB_OPAQUE_QUERY pQuery;
|
|
PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpEntry;
|
|
DWORD dwInEntrySize,dwOutEntrySize, dwResult;
|
|
BOOL fCache;
|
|
PPROTO_CB pProtocolCb ;
|
|
PLIST_ENTRY pleNode ;
|
|
DWORD rgdwQuery[6];
|
|
|
|
EnterRouterApi();;
|
|
|
|
TraceEnter("RtrMgrMIBEntryCreate");
|
|
|
|
pQuery = (PMIB_OPAQUE_QUERY)rgdwQuery;
|
|
|
|
if(dwRoutingPid is IPRTRMGR_PID)
|
|
{
|
|
switch(pInfo->dwId)
|
|
{
|
|
case IP_FORWARDROW:
|
|
{
|
|
PMIB_IPFORWARDROW pRow = (PMIB_IPFORWARDROW)(pInfo->rgbyData);
|
|
|
|
pQuery->dwVarId = IP_FORWARDROW;
|
|
|
|
pQuery->rgdwVarIndex[0] = pRow->dwForwardDest;
|
|
pQuery->rgdwVarIndex[1] = pRow->dwForwardProto;
|
|
pQuery->rgdwVarIndex[2] = pRow->dwForwardPolicy;
|
|
pQuery->rgdwVarIndex[3] = pRow->dwForwardNextHop;
|
|
|
|
dwOutEntrySize = dwEntrySize;
|
|
dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + 3 * sizeof(DWORD);
|
|
|
|
dwResult = AccessIpForwardRow(ACCESS_CREATE_ENTRY,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
case ROUTE_MATCHING:
|
|
{
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwResult = AccessIpMatchingRoute(ACCESS_CREATE_ENTRY,
|
|
0,
|
|
NULL,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
break;
|
|
}
|
|
|
|
case IP_NETROW:
|
|
{
|
|
PMIB_IPNETROW pRow = (PMIB_IPNETROW)(pInfo->rgbyData);
|
|
|
|
pQuery->dwVarId = IP_NETROW;
|
|
|
|
pQuery->rgdwVarIndex[0] = pRow->dwIndex;
|
|
pQuery->rgdwVarIndex[1] = pRow->dwAddr;
|
|
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + sizeof(DWORD);
|
|
|
|
dwResult = AccessIpNetRow(ACCESS_CREATE_ENTRY,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
case PROXY_ARP:
|
|
{
|
|
PMIB_PROXYARP pRow = (PMIB_PROXYARP)(pInfo->rgbyData);
|
|
|
|
pQuery->dwVarId = IP_NETROW;
|
|
|
|
pQuery->rgdwVarIndex[0] = pRow->dwAddress;
|
|
pQuery->rgdwVarIndex[1] = pRow->dwMask;
|
|
pQuery->rgdwVarIndex[2] = pRow->dwIfIndex;
|
|
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + (2 * sizeof(DWORD));
|
|
|
|
dwResult = AccessProxyArp(ACCESS_CREATE_ENTRY,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
dwResult = ERROR_INVALID_PARAMETER;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Send over to other pids
|
|
//
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
dwResult = ERROR_CAN_NOT_COMPLETE;
|
|
|
|
for(pleNode = g_leProtoCbList.Flink;
|
|
pleNode != &g_leProtoCbList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProtocolCb = CONTAINING_RECORD(pleNode,
|
|
PROTO_CB,
|
|
leList);
|
|
|
|
if (dwRoutingPid == pProtocolCb->dwProtocolId)
|
|
{
|
|
dwResult = (pProtocolCb->pfnMibCreateEntry)(dwEntrySize,
|
|
lpEntry) ;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
|
|
}
|
|
|
|
TraceLeave("RtrMgrMIBEntryCreate");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
RtrMgrMIBEntryDelete(
|
|
IN DWORD dwRoutingPid,
|
|
IN DWORD dwEntrySize,
|
|
IN LPVOID lpEntry
|
|
)
|
|
{
|
|
DWORD dwOutEntrySize = 0;
|
|
PMIB_OPAQUE_QUERY pQuery = (PMIB_OPAQUE_QUERY) lpEntry;
|
|
DWORD dwResult;
|
|
BOOL fCache;
|
|
PPROTO_CB pProtocolCb ;
|
|
PLIST_ENTRY pleNode ;
|
|
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("RtrMgrMIBEntryDelete");
|
|
|
|
if(dwRoutingPid is IPRTRMGR_PID)
|
|
{
|
|
switch(pQuery->dwVarId)
|
|
{
|
|
case IP_FORWARDROW:
|
|
{
|
|
dwResult = AccessIpForwardRow(ACCESS_DELETE_ENTRY,
|
|
dwEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
NULL,
|
|
&fCache);
|
|
break;
|
|
}
|
|
|
|
case ROUTE_MATCHING:
|
|
{
|
|
dwResult = AccessIpMatchingRoute(ACCESS_DELETE_ENTRY,
|
|
dwEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
NULL,
|
|
&fCache);
|
|
break;
|
|
}
|
|
|
|
case IP_NETROW:
|
|
{
|
|
dwResult = AccessIpNetRow(ACCESS_DELETE_ENTRY,
|
|
dwEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
NULL,
|
|
&fCache);
|
|
break;
|
|
}
|
|
case PROXY_ARP:
|
|
{
|
|
dwResult = AccessProxyArp(ACCESS_DELETE_ENTRY,
|
|
dwEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
NULL,
|
|
&fCache);
|
|
break;
|
|
}
|
|
case IP_NETTABLE:
|
|
{
|
|
dwResult = AccessIpNetRow(ACCESS_DELETE_ENTRY,
|
|
dwEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
NULL,
|
|
&fCache);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
dwResult = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
dwResult = ERROR_CAN_NOT_COMPLETE;
|
|
|
|
for (pleNode = g_leProtoCbList.Flink;
|
|
pleNode != &g_leProtoCbList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProtocolCb = CONTAINING_RECORD(pleNode,
|
|
PROTO_CB,
|
|
leList);
|
|
|
|
if(dwRoutingPid == pProtocolCb->dwProtocolId)
|
|
{
|
|
dwResult = (pProtocolCb->pfnMibDeleteEntry)(dwEntrySize,
|
|
lpEntry);
|
|
break ;
|
|
}
|
|
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
|
|
}
|
|
|
|
TraceLeave("RtrMgrMIBEntryDelete");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult;
|
|
|
|
}
|
|
|
|
DWORD
|
|
RtrMgrMIBEntrySet(
|
|
IN DWORD dwRoutingPid,
|
|
IN DWORD dwEntrySize,
|
|
IN LPVOID lpEntry
|
|
)
|
|
{
|
|
PMIB_OPAQUE_QUERY pQuery;
|
|
PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpEntry;
|
|
DWORD dwInEntrySize, dwOutEntrySize, dwResult=NO_ERROR;
|
|
BOOL fCache;
|
|
PPROTO_CB pProtocolCb ;
|
|
PLIST_ENTRY pleNode ;
|
|
DWORD rgdwQuery[6];
|
|
|
|
EnterRouterApi();;
|
|
|
|
TraceEnter("RtrMgrMIBEntrySet");
|
|
|
|
pQuery = (PMIB_OPAQUE_QUERY)rgdwQuery;
|
|
|
|
if(dwRoutingPid is IPRTRMGR_PID)
|
|
{
|
|
|
|
switch(pInfo->dwId)
|
|
{
|
|
case IF_ROW:
|
|
{
|
|
PMIB_IFROW pRow = (PMIB_IFROW)(pInfo->rgbyData);
|
|
|
|
pQuery->dwVarId = IF_ROW;
|
|
|
|
pQuery->rgdwVarIndex[0] = pRow->dwIndex;
|
|
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwInEntrySize = sizeof(MIB_OPAQUE_QUERY);
|
|
|
|
dwResult = AccessIfRow(ACCESS_SET,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
case TCP_ROW:
|
|
{
|
|
PMIB_TCPROW pRow = (PMIB_TCPROW)(pInfo->rgbyData);
|
|
|
|
pQuery->dwVarId = TCP_ROW;
|
|
|
|
pQuery->rgdwVarIndex[0] = pRow->dwLocalAddr;
|
|
pQuery->rgdwVarIndex[1] = pRow->dwLocalPort;
|
|
pQuery->rgdwVarIndex[2] = pRow->dwRemoteAddr;
|
|
pQuery->rgdwVarIndex[3] = pRow->dwRemotePort;
|
|
|
|
dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + (3 * sizeof(DWORD));
|
|
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwResult = AccessTcpRow(ACCESS_SET,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
break;
|
|
}
|
|
|
|
case IP_STATS:
|
|
{
|
|
PMIB_IPSTATS pStats = (PMIB_IPSTATS)(pInfo->rgbyData);
|
|
|
|
pQuery->dwVarId = IP_STATS;
|
|
|
|
dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) - sizeof(DWORD);
|
|
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwResult = AccessIpStats(ACCESS_SET,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
break;
|
|
}
|
|
|
|
case IP_FORWARDROW:
|
|
{
|
|
PMIB_IPFORWARDROW pRow = (PMIB_IPFORWARDROW)(pInfo->rgbyData);
|
|
|
|
pQuery->dwVarId = IP_FORWARDROW;
|
|
|
|
pQuery->rgdwVarIndex[0] = pRow->dwForwardDest;
|
|
pQuery->rgdwVarIndex[1] = pRow->dwForwardProto;
|
|
pQuery->rgdwVarIndex[2] = pRow->dwForwardPolicy;
|
|
pQuery->rgdwVarIndex[3] = pRow->dwForwardNextHop;
|
|
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + 3 * sizeof(DWORD);
|
|
|
|
dwResult = AccessIpForwardRow(ACCESS_SET,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
break;
|
|
}
|
|
|
|
case ROUTE_MATCHING:
|
|
{
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwResult = AccessIpMatchingRoute(ACCESS_SET,
|
|
0,
|
|
NULL,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
break;
|
|
}
|
|
|
|
case IP_NETROW:
|
|
{
|
|
PMIB_IPNETROW pRow = (PMIB_IPNETROW)(pInfo->rgbyData);
|
|
|
|
pQuery->dwVarId = IP_NETROW;
|
|
|
|
pQuery->rgdwVarIndex[0] = pRow->dwIndex;
|
|
pQuery->rgdwVarIndex[1] = pRow->dwAddr;
|
|
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + sizeof(DWORD);
|
|
|
|
dwResult = AccessIpNetRow(ACCESS_SET,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
break;
|
|
}
|
|
|
|
case MCAST_MFE:
|
|
{
|
|
dwResult = AccessMcastMfe(ACCESS_SET,
|
|
0,
|
|
NULL,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
break;
|
|
}
|
|
|
|
case MCAST_BOUNDARY:
|
|
{
|
|
dwResult = AccessMcastBoundary(ACCESS_SET,
|
|
0,
|
|
NULL,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
break;
|
|
}
|
|
|
|
case MCAST_SCOPE:
|
|
{
|
|
dwResult = AccessMcastScope(ACCESS_SET,
|
|
0,
|
|
NULL,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
|
|
break;
|
|
}
|
|
|
|
case PROXY_ARP:
|
|
{
|
|
PMIB_PROXYARP pRow = (PMIB_PROXYARP)(pInfo->rgbyData);
|
|
|
|
pQuery->dwVarId = IP_NETROW;
|
|
|
|
pQuery->rgdwVarIndex[0] = pRow->dwAddress;
|
|
pQuery->rgdwVarIndex[1] = pRow->dwMask;
|
|
pQuery->rgdwVarIndex[2] = pRow->dwIfIndex;
|
|
|
|
dwOutEntrySize = dwEntrySize;
|
|
|
|
dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + (2 * sizeof(DWORD));
|
|
|
|
dwResult = AccessProxyArp(ACCESS_CREATE_ENTRY,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
&dwOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
dwResult = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
dwResult = ERROR_CAN_NOT_COMPLETE;
|
|
|
|
for (pleNode = g_leProtoCbList.Flink;
|
|
pleNode != &g_leProtoCbList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProtocolCb = CONTAINING_RECORD(pleNode,
|
|
PROTO_CB,
|
|
leList) ;
|
|
|
|
if (dwRoutingPid == pProtocolCb->dwProtocolId)
|
|
{
|
|
dwResult = (pProtocolCb->pfnMibSetEntry) (dwEntrySize, lpEntry) ;
|
|
break ;
|
|
}
|
|
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
|
|
}
|
|
|
|
TraceLeave("RtrMgrMIBEntrySet");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
RtrMgrMIBEntryGet(
|
|
IN DWORD dwRoutingPid,
|
|
IN DWORD dwInEntrySize,
|
|
IN LPVOID lpInEntry,
|
|
IN OUT LPDWORD lpOutEntrySize,
|
|
OUT LPVOID lpOutEntry
|
|
)
|
|
{
|
|
PMIB_OPAQUE_QUERY pQuery = (PMIB_OPAQUE_QUERY)lpInEntry;
|
|
PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpOutEntry;
|
|
BOOL fCache;
|
|
DWORD dwResult;
|
|
PPROTO_CB pProtocolCb ;
|
|
PLIST_ENTRY pleNode ;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("RtrMgrMIBEntryGet");
|
|
|
|
if(dwRoutingPid is IPRTRMGR_PID)
|
|
{
|
|
if(*lpOutEntrySize > 0)
|
|
{
|
|
ZeroMemory(lpOutEntry,
|
|
*lpOutEntrySize);
|
|
}
|
|
|
|
dwResult = (*g_AccessFunctionTable[pQuery->dwVarId])(ACCESS_GET,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
lpOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
}
|
|
else
|
|
{
|
|
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
dwResult = ERROR_CAN_NOT_COMPLETE;
|
|
|
|
for (pleNode = g_leProtoCbList.Flink;
|
|
pleNode != &g_leProtoCbList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProtocolCb = CONTAINING_RECORD(pleNode,
|
|
PROTO_CB,
|
|
leList);
|
|
|
|
if (dwRoutingPid == pProtocolCb->dwProtocolId)
|
|
{
|
|
dwResult = (pProtocolCb->pfnMibGetEntry) (dwInEntrySize,
|
|
lpInEntry,
|
|
lpOutEntrySize,
|
|
lpOutEntry) ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
}
|
|
|
|
TraceLeave("RtrMgrMIBEntryGet");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
RtrMgrMIBEntryGetFirst(
|
|
IN DWORD dwRoutingPid,
|
|
IN DWORD dwInEntrySize,
|
|
IN LPVOID lpInEntry,
|
|
IN OUT LPDWORD lpOutEntrySize,
|
|
OUT LPVOID lpOutEntry
|
|
)
|
|
{
|
|
PMIB_OPAQUE_QUERY pQuery = (PMIB_OPAQUE_QUERY)lpInEntry;
|
|
PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpOutEntry;
|
|
DWORD dwResult;
|
|
BOOL fCache;
|
|
PPROTO_CB pProtocolCb ;
|
|
PLIST_ENTRY pleNode ;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("RtrMgrMIBEntryGetFirst");
|
|
|
|
if(dwRoutingPid is IPRTRMGR_PID)
|
|
{
|
|
if(*lpOutEntrySize > 0)
|
|
{
|
|
ZeroMemory(lpOutEntry,
|
|
*lpOutEntrySize);
|
|
}
|
|
|
|
dwResult = (*g_AccessFunctionTable[pQuery->dwVarId])(ACCESS_GET_FIRST,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
lpOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
}
|
|
else
|
|
{
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
dwResult = ERROR_CAN_NOT_COMPLETE;
|
|
|
|
for(pleNode = g_leProtoCbList.Flink;
|
|
pleNode != &g_leProtoCbList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProtocolCb = CONTAINING_RECORD(pleNode,
|
|
PROTO_CB,
|
|
leList) ;
|
|
|
|
if (dwRoutingPid == pProtocolCb->dwProtocolId)
|
|
{
|
|
dwResult = (pProtocolCb->pfnMibGetFirstEntry)(dwInEntrySize,
|
|
lpInEntry,
|
|
lpOutEntrySize,
|
|
lpOutEntry);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
|
|
}
|
|
|
|
TraceLeave("RtrMgrMIBEntryGetFirst");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
RtrMgrMIBEntryGetNext(
|
|
IN DWORD dwRoutingPid,
|
|
IN DWORD dwInEntrySize,
|
|
IN LPVOID lpInEntry,
|
|
IN OUT LPDWORD lpOutEntrySize,
|
|
OUT LPVOID lpOutEntry
|
|
)
|
|
{
|
|
PMIB_OPAQUE_QUERY pQuery = (PMIB_OPAQUE_QUERY)lpInEntry;
|
|
PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpOutEntry;
|
|
DWORD dwResult;
|
|
BOOL fCache;
|
|
PPROTO_CB pProtocolCb ;
|
|
PLIST_ENTRY pleNode ;
|
|
|
|
EnterRouterApi();
|
|
|
|
TraceEnter("RtrMgrMIBEntryGetNext");
|
|
|
|
if(dwRoutingPid is IPRTRMGR_PID)
|
|
{
|
|
if(*lpOutEntrySize > 0)
|
|
{
|
|
ZeroMemory(lpOutEntry,
|
|
*lpOutEntrySize);
|
|
}
|
|
|
|
dwResult = (*g_AccessFunctionTable[pQuery->dwVarId])(ACCESS_GET_NEXT,
|
|
dwInEntrySize,
|
|
pQuery,
|
|
lpOutEntrySize,
|
|
pInfo,
|
|
&fCache);
|
|
}
|
|
else
|
|
{
|
|
// *** Exclusion Begin ***
|
|
ENTER_READER(PROTOCOL_CB_LIST);
|
|
|
|
dwResult = ERROR_CAN_NOT_COMPLETE;
|
|
|
|
for(pleNode = g_leProtoCbList.Flink;
|
|
pleNode != &g_leProtoCbList;
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
pProtocolCb = CONTAINING_RECORD(pleNode,
|
|
PROTO_CB,
|
|
leList) ;
|
|
|
|
if(dwRoutingPid == pProtocolCb->dwProtocolId)
|
|
{
|
|
dwResult = (pProtocolCb->pfnMibGetNextEntry)(dwInEntrySize,
|
|
lpInEntry,
|
|
lpOutEntrySize,
|
|
lpOutEntry);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
// *** Exclusion End ***
|
|
EXIT_LOCK(PROTOCOL_CB_LIST);
|
|
}
|
|
|
|
TraceLeave("RtrMgrMIBEntryGetNext");
|
|
|
|
ExitRouterApi();
|
|
|
|
return dwResult;
|
|
}
|