1812 lines
47 KiB
C
1812 lines
47 KiB
C
#include "precomp.h"
|
|
|
|
WCHAR g_wszRtrMgrDLL[] = L"%SystemRoot%\\system32\\IPRTRMGR.DLL";
|
|
DWORD g_dwIfState = MIB_IF_ADMIN_STATUS_UP;
|
|
BOOL g_bDiscEnable = FALSE;
|
|
|
|
#define IP_KEY L"Ip"
|
|
|
|
#undef EXTRA_DEBUG
|
|
|
|
DWORD
|
|
ValidateInterfaceInfo(
|
|
IN LPCWSTR pwszIfName,
|
|
OUT RTR_INFO_BLOCK_HEADER **ppInfo, OPTIONAL
|
|
OUT PDWORD pdwIfType, OPTIONAL
|
|
OUT INTERFACE_STORE **ppIfStore OPTIONAL
|
|
)
|
|
{
|
|
PRTR_INFO_BLOCK_HEADER pOldInfo = NULL;
|
|
DWORD dwErr, dwIfType, dwTmpSize;
|
|
BOOL bFound = FALSE;
|
|
LIST_ENTRY *ple;
|
|
PINTERFACE_STORE pii;
|
|
|
|
if(ppInfo)
|
|
{
|
|
*ppInfo = NULL;
|
|
}
|
|
|
|
if(ppIfStore)
|
|
{
|
|
*ppIfStore = NULL;
|
|
}
|
|
|
|
//
|
|
// If the current mode is commit, get info from config/router
|
|
//
|
|
|
|
if(g_bCommit)
|
|
{
|
|
dwErr = GetInterfaceInfo(pwszIfName,
|
|
ppInfo,
|
|
NULL,
|
|
pdwIfType);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Uncommit mode. Try to find the interface in the list
|
|
//
|
|
|
|
bFound = FALSE;
|
|
|
|
for(ple = g_leIfListHead.Flink;
|
|
ple != &g_leIfListHead;
|
|
ple = ple->Flink)
|
|
{
|
|
pii = CONTAINING_RECORD(ple, INTERFACE_STORE, le);
|
|
|
|
if (_wcsicmp(pii->pwszIfName, pwszIfName) == 0)
|
|
{
|
|
bFound = TRUE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!bFound ||
|
|
!pii->bValid)
|
|
{
|
|
//
|
|
// the required one was not found, or it was not valid
|
|
// Need to get the info for both cases
|
|
//
|
|
|
|
dwErr = GetInterfaceInfo(pwszIfName,
|
|
&pOldInfo,
|
|
NULL,
|
|
&dwIfType);
|
|
|
|
if (dwErr isnot NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
}
|
|
|
|
if(bFound)
|
|
{
|
|
if(!pii->bValid)
|
|
{
|
|
//
|
|
// Update
|
|
//
|
|
|
|
pii->pibhInfo = pOldInfo;
|
|
pii->bValid = TRUE;
|
|
pii->dwIfType = dwIfType;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No entry for the interface in the list.
|
|
//
|
|
|
|
pii = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
sizeof(INTERFACE_STORE));
|
|
|
|
if(pii == NULL)
|
|
{
|
|
FREE_BUFFER(pOldInfo);
|
|
|
|
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
pii->pwszIfName =
|
|
HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
(wcslen(pwszIfName) + 1) * sizeof(WCHAR));
|
|
|
|
if(pii->pwszIfName == NULL)
|
|
{
|
|
FREE_BUFFER(pOldInfo);
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
pii);
|
|
|
|
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
InsertHeadList(&g_leIfListHead, &(pii->le));
|
|
|
|
wcscpy(pii->pwszIfName, pwszIfName);
|
|
|
|
pii->pibhInfo = pOldInfo;
|
|
pii->bValid = TRUE;
|
|
pii->dwIfType = dwIfType;
|
|
}
|
|
|
|
if(ppIfStore)
|
|
{
|
|
*ppIfStore = pii;
|
|
}
|
|
|
|
if(pdwIfType)
|
|
{
|
|
*pdwIfType = pii->dwIfType;
|
|
}
|
|
|
|
if(ppInfo)
|
|
{
|
|
*ppInfo = pii->pibhInfo;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
ValidateGlobalInfo(
|
|
OUT RTR_INFO_BLOCK_HEADER **ppInfo
|
|
)
|
|
{
|
|
DWORD dwErr;
|
|
|
|
//
|
|
// If the current mode is commit, get info from config/router
|
|
//
|
|
|
|
if(g_bCommit)
|
|
{
|
|
dwErr = GetGlobalInfo(ppInfo);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Uncommit mode. Check if the info in g_tiTransport is valid
|
|
//
|
|
|
|
if(g_tiTransport.bValid)
|
|
{
|
|
*ppInfo = g_tiTransport.pibhInfo;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Get the info from config/router and store in g_tiTransport
|
|
// Mark the info to be valid.
|
|
//
|
|
|
|
dwErr = GetGlobalInfo(ppInfo);
|
|
|
|
if (dwErr isnot NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
g_tiTransport.pibhInfo = *ppInfo;
|
|
g_tiTransport.bValid = TRUE;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
GetGlobalInfo(
|
|
OUT PRTR_INFO_BLOCK_HEADER *ppibhInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets global transport information from registry or router.
|
|
|
|
Arguments:
|
|
|
|
bMprConfig - Info from Registry or info from router
|
|
ppibhInfo - ptr to header
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR, ERROR_INVALID_PARAMETER, ERROR_ROUTER_STOPPED
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HANDLE hTransport = (HANDLE) NULL;
|
|
DWORD dwRes, dwSize;
|
|
PRTR_INFO_BLOCK_HEADER pibhInfo = (PRTR_INFO_BLOCK_HEADER ) NULL;
|
|
|
|
if(ppibhInfo == NULL)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (IsRouterRunning())
|
|
{
|
|
//
|
|
// Retrieve global protocol information from router
|
|
//
|
|
|
|
dwRes = MprAdminTransportGetInfo(g_hMprAdmin,
|
|
PID_IP,
|
|
(LPBYTE*) &pibhInfo,
|
|
&dwSize,
|
|
NULL,
|
|
NULL);
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( pibhInfo == (PRTR_INFO_BLOCK_HEADER) NULL )
|
|
{
|
|
dwRes = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unfortunately, the memory allocation mechanisms
|
|
// are different between the apis that access the registry
|
|
// and those that access that the running router. To make
|
|
// the source of the info transparent to the caller, we
|
|
// need to copy this info out.
|
|
//
|
|
|
|
*ppibhInfo = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
dwSize);
|
|
|
|
if ( *ppibhInfo == NULL)
|
|
{
|
|
dwRes = GetLastError();
|
|
|
|
break;
|
|
}
|
|
|
|
CopyMemory(*ppibhInfo,
|
|
pibhInfo,
|
|
dwSize);
|
|
|
|
MprAdminBufferFree(pibhInfo);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// router not running, get info from registry
|
|
//
|
|
|
|
dwRes = MprConfigTransportGetHandle(g_hMprConfig,
|
|
PID_IP,
|
|
&hTransport);
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwRes = MprConfigTransportGetInfo(g_hMprConfig,
|
|
hTransport,
|
|
(LPBYTE*) &pibhInfo,
|
|
&dwSize,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(( pibhInfo == (PRTR_INFO_BLOCK_HEADER) NULL )
|
|
or (dwSize < sizeof(RTR_INFO_BLOCK_HEADER)))
|
|
{
|
|
dwRes = ERROR_TRANSPORT_NOT_PRESENT;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// HACKHACK: we know that MprConfigXxx apis allocate from
|
|
// process heap, so we can return the same block
|
|
//
|
|
|
|
*ppibhInfo = pibhInfo;
|
|
}
|
|
|
|
} while(FALSE);
|
|
|
|
return dwRes;
|
|
}
|
|
|
|
DWORD
|
|
SetGlobalInfo(
|
|
IN PRTR_INFO_BLOCK_HEADER pibhInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets global transport information to both the registry and the router
|
|
|
|
Arguments:
|
|
|
|
pibhInfo - ptr to header
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR, ERROR_ROUTER_STOPPED
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwARes = NO_ERROR,
|
|
dwCRes = NO_ERROR;
|
|
HANDLE hTransport;
|
|
UINT i;
|
|
PRTR_INFO_BLOCK_HEADER pibhNewInfo, pibhOldInfo;
|
|
|
|
//
|
|
// Create a new info block with all 0-length blocks removed
|
|
// since we don't want to write them to the registry,
|
|
// we only need to send them to the router which we
|
|
// will do with the original info block below.
|
|
//
|
|
|
|
pibhOldInfo = NULL;
|
|
pibhNewInfo = pibhInfo;
|
|
|
|
for (i=0; (dwCRes is NO_ERROR) && (i<pibhInfo->TocEntriesCount); i++)
|
|
{
|
|
if (pibhInfo->TocEntry[i].InfoSize is 0)
|
|
{
|
|
pibhOldInfo = pibhNewInfo;
|
|
|
|
dwCRes = MprInfoBlockRemove(pibhOldInfo,
|
|
pibhOldInfo->TocEntry[i].InfoType,
|
|
&pibhNewInfo);
|
|
|
|
if (pibhOldInfo isnot pibhInfo)
|
|
{
|
|
FREE_BUFFER(pibhOldInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwCRes is NO_ERROR)
|
|
{
|
|
dwCRes = MprConfigTransportGetHandle(g_hMprConfig,
|
|
PID_IP,
|
|
&hTransport);
|
|
}
|
|
|
|
if (dwCRes is NO_ERROR)
|
|
{
|
|
dwCRes = MprConfigTransportSetInfo(g_hMprConfig,
|
|
hTransport,
|
|
(LPBYTE) pibhNewInfo,
|
|
pibhNewInfo->Size,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
}
|
|
|
|
if (pibhNewInfo isnot pibhInfo)
|
|
{
|
|
FREE_BUFFER(pibhNewInfo);
|
|
}
|
|
|
|
//
|
|
// Even if we failed to write to the registry, we still want
|
|
// to write to the router.
|
|
//
|
|
// We use the original format when writing to the router, since it
|
|
// needs to see the 0-length blocks in order to delete config info.
|
|
//
|
|
|
|
if(IsRouterRunning())
|
|
{
|
|
dwARes = MprAdminTransportSetInfo(g_hMprAdmin,
|
|
PID_IP,
|
|
(LPBYTE) pibhInfo,
|
|
pibhInfo->Size,
|
|
NULL,
|
|
0);
|
|
|
|
}
|
|
|
|
return (dwARes isnot NO_ERROR)? dwARes : dwCRes;
|
|
}
|
|
|
|
DWORD
|
|
GetInterfaceInfo(
|
|
IN LPCWSTR pwszIfName,
|
|
OUT RTR_INFO_BLOCK_HEADER **ppibhInfo, OPTIONAL
|
|
OUT PMPR_INTERFACE_0 pMprIfInfo, OPTIONAL
|
|
OUT PDWORD pdwIfType OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets global transport information from registry or router.
|
|
|
|
If one of the out information is not required, then the parameter
|
|
can be NULL.
|
|
|
|
Arguments:
|
|
|
|
pwszIfName - Interface Name
|
|
bMprConfig - Info from Registry or info from router
|
|
ppibhInfo - ptr to header
|
|
pMprIfInfo - ptr to interface info
|
|
pdwIfType - Type of interface
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR,
|
|
ERROR_NO_SUCH_INTERFACE
|
|
ERROR_TRANSPORT_NOT_PRESENT
|
|
|
|
--*/
|
|
|
|
{
|
|
PMPR_INTERFACE_0 pMprIf = NULL;
|
|
PRTR_INFO_BLOCK_HEADER pibh;
|
|
HANDLE hInterface,hIfTransport;
|
|
DWORD dwRes, dwSize;
|
|
|
|
|
|
if(((ULONG_PTR)ppibhInfo | (ULONG_PTR)pMprIfInfo | (ULONG_PTR)pdwIfType) ==
|
|
(ULONG_PTR)NULL)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
do
|
|
{
|
|
if(IsRouterRunning())
|
|
{
|
|
//
|
|
// Get info from the router
|
|
//
|
|
|
|
dwRes = MprAdminInterfaceGetHandle(g_hMprAdmin,
|
|
(LPWSTR)pwszIfName,
|
|
&hInterface,
|
|
FALSE);
|
|
|
|
if( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
if(pMprIfInfo || pdwIfType)
|
|
{
|
|
dwRes = MprAdminInterfaceGetInfo(g_hMprAdmin,
|
|
hInterface,
|
|
0,
|
|
(LPBYTE *) &pMprIf);
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (pMprIf == NULL)
|
|
{
|
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if(pMprIfInfo)
|
|
{
|
|
//
|
|
// structure copy
|
|
//
|
|
|
|
*pMprIfInfo= *pMprIf;
|
|
}
|
|
|
|
if(pdwIfType)
|
|
{
|
|
*pdwIfType = pMprIf->dwIfType;
|
|
}
|
|
|
|
MprAdminBufferFree(pMprIf);
|
|
|
|
}
|
|
|
|
|
|
if(ppibhInfo)
|
|
{
|
|
dwRes = MprAdminInterfaceTransportGetInfo(g_hMprAdmin,
|
|
hInterface,
|
|
PID_IP,
|
|
(LPBYTE*) &pibh,
|
|
&dwSize);
|
|
|
|
if(dwRes != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(pibh == (PRTR_INFO_BLOCK_HEADER) NULL)
|
|
{
|
|
dwRes = ERROR_TRANSPORT_NOT_PRESENT;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// The info returned to the user must be from
|
|
// process heap. Admin calls use MIDL allocation, so
|
|
// copy out info
|
|
//
|
|
|
|
*ppibhInfo = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
dwSize);
|
|
|
|
if(*ppibhInfo == NULL)
|
|
{
|
|
dwRes = GetLastError();
|
|
|
|
break;
|
|
}
|
|
|
|
CopyMemory(*ppibhInfo,
|
|
pibh,
|
|
dwSize);
|
|
|
|
MprAdminBufferFree(pibh);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Router not running, get info from the registry
|
|
//
|
|
|
|
dwRes = MprConfigInterfaceGetHandle(g_hMprConfig,
|
|
(LPWSTR)pwszIfName,
|
|
&hInterface);
|
|
|
|
if(dwRes != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(pMprIfInfo || pdwIfType)
|
|
{
|
|
dwRes = MprConfigInterfaceGetInfo(g_hMprConfig,
|
|
hInterface,
|
|
0,
|
|
(LPBYTE *) &pMprIf,
|
|
&dwSize);
|
|
|
|
if(dwRes != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (pMprIf == NULL)
|
|
{
|
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if(pdwIfType)
|
|
{
|
|
*pdwIfType = pMprIf->dwIfType;
|
|
}
|
|
|
|
if(pMprIfInfo)
|
|
{
|
|
*pMprIfInfo = *pMprIf;
|
|
}
|
|
|
|
MprConfigBufferFree(pMprIf);
|
|
}
|
|
|
|
if (ppibhInfo)
|
|
{
|
|
dwRes = MprConfigInterfaceTransportGetHandle(g_hMprConfig,
|
|
hInterface,
|
|
PID_IP,
|
|
&hIfTransport);
|
|
|
|
if(dwRes != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwRes = MprConfigInterfaceTransportGetInfo(g_hMprConfig,
|
|
hInterface,
|
|
hIfTransport,
|
|
(LPBYTE*) &pibh,
|
|
&dwSize);
|
|
|
|
if(dwRes != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if((pibh == (PRTR_INFO_BLOCK_HEADER) NULL)
|
|
or (dwSize < sizeof(RTR_INFO_BLOCK_HEADER)))
|
|
{
|
|
dwRes = ERROR_TRANSPORT_NOT_PRESENT;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Again, since this is also allocated from process heap
|
|
//
|
|
|
|
*ppibhInfo = pibh;
|
|
}
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
return dwRes;
|
|
}
|
|
|
|
DWORD
|
|
MakeIPGlobalInfo( LPBYTE* ppBuff )
|
|
{
|
|
|
|
DWORD dwSize = 0,
|
|
dwRes = (DWORD) -1;
|
|
LPBYTE pbDataPtr = (LPBYTE) NULL;
|
|
|
|
PRTR_TOC_ENTRY pTocEntry = (PRTR_TOC_ENTRY) NULL;
|
|
|
|
PGLOBAL_INFO pGlbInfo = NULL;
|
|
PPRIORITY_INFO pPriorInfo = NULL;
|
|
|
|
PRTR_INFO_BLOCK_HEADER pIBH = (PRTR_INFO_BLOCK_HEADER) NULL;
|
|
|
|
|
|
//
|
|
// Alocate for minimal global Information
|
|
//
|
|
|
|
dwSize = sizeof( RTR_INFO_BLOCK_HEADER ) + sizeof(GLOBAL_INFO) +
|
|
sizeof( RTR_TOC_ENTRY ) + SIZEOF_PRIORITY_INFO(7) +
|
|
2 * ALIGN_SIZE;
|
|
|
|
pIBH = (PRTR_INFO_BLOCK_HEADER) HeapAlloc( GetProcessHeap(), 0, dwSize );
|
|
|
|
if ( pIBH == (PRTR_INFO_BLOCK_HEADER) NULL )
|
|
{
|
|
DisplayMessage( g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
|
|
*ppBuff = (LPBYTE) NULL;
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// init. infobase fields
|
|
//
|
|
*ppBuff = (LPBYTE) pIBH;
|
|
|
|
pIBH-> Version = RTR_INFO_BLOCK_VERSION;
|
|
pIBH-> TocEntriesCount = 2;
|
|
pIBH-> Size = dwSize;
|
|
|
|
pbDataPtr = (LPBYTE) &( pIBH-> TocEntry[ pIBH-> TocEntriesCount ] );
|
|
ALIGN_POINTER( pbDataPtr );
|
|
|
|
//
|
|
// make IP rtr mgr global info.
|
|
//
|
|
|
|
pTocEntry = &(pIBH-> TocEntry[ 0 ]);
|
|
|
|
pTocEntry-> InfoType = IP_GLOBAL_INFO;
|
|
pTocEntry-> Count = 1;
|
|
pTocEntry-> Offset = (ULONG)(pbDataPtr - (PBYTE) pIBH);
|
|
pTocEntry-> InfoSize = sizeof(GLOBAL_INFO);
|
|
|
|
|
|
pGlbInfo = (PGLOBAL_INFO) pbDataPtr;
|
|
pGlbInfo-> bFilteringOn = TRUE;
|
|
pGlbInfo-> dwLoggingLevel = IPRTR_LOGGING_ERROR;
|
|
|
|
pbDataPtr += pTocEntry->Count * pTocEntry-> InfoSize;
|
|
ALIGN_POINTER( pbDataPtr );
|
|
|
|
//
|
|
// make IP rtr priority. Info
|
|
//
|
|
|
|
pTocEntry = &(pIBH-> TocEntry[ 1 ]);
|
|
|
|
|
|
pTocEntry-> InfoType = IP_PROT_PRIORITY_INFO;
|
|
pTocEntry-> Count = 1;
|
|
pTocEntry-> Offset = (DWORD)(pbDataPtr - (PBYTE) pIBH);
|
|
pTocEntry-> InfoSize = SIZEOF_PRIORITY_INFO(7);
|
|
|
|
|
|
pPriorInfo = (PPRIORITY_INFO) pbDataPtr;
|
|
pPriorInfo-> dwNumProtocols = 7;
|
|
|
|
pPriorInfo-> ppmProtocolMetric[ 0 ].dwProtocolId = PROTO_IP_LOCAL;
|
|
pPriorInfo-> ppmProtocolMetric[ 0 ].dwMetric = 1;
|
|
|
|
pPriorInfo-> ppmProtocolMetric[ 1 ].dwProtocolId = PROTO_IP_NT_STATIC;
|
|
pPriorInfo-> ppmProtocolMetric[ 1 ].dwMetric = 3;
|
|
|
|
pPriorInfo-> ppmProtocolMetric[ 2 ].dwProtocolId = PROTO_IP_NT_STATIC_NON_DOD;
|
|
pPriorInfo-> ppmProtocolMetric[ 2 ].dwMetric = 5;
|
|
|
|
pPriorInfo-> ppmProtocolMetric[ 3 ].dwProtocolId = PROTO_IP_NT_AUTOSTATIC;
|
|
pPriorInfo-> ppmProtocolMetric[ 3 ].dwMetric = 7;
|
|
|
|
pPriorInfo-> ppmProtocolMetric[ 4 ].dwProtocolId = PROTO_IP_NETMGMT;
|
|
pPriorInfo-> ppmProtocolMetric[ 4 ].dwMetric = 10;
|
|
|
|
pPriorInfo-> ppmProtocolMetric[ 5 ].dwProtocolId = PROTO_IP_OSPF;
|
|
pPriorInfo-> ppmProtocolMetric[ 5 ].dwMetric = 110;
|
|
|
|
pPriorInfo-> ppmProtocolMetric[ 6 ].dwProtocolId = PROTO_IP_RIP;
|
|
pPriorInfo-> ppmProtocolMetric[ 6 ].dwMetric = 120;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
MakeIPInterfaceInfo(
|
|
LPBYTE* ppBuff,
|
|
DWORD dwIfType
|
|
)
|
|
{
|
|
DWORD dwSize = (DWORD) -1;
|
|
DWORD dwTocEntries = 2;
|
|
LPBYTE pbDataPtr = (LPBYTE) NULL;
|
|
|
|
PRTR_TOC_ENTRY pTocEntry = (PRTR_TOC_ENTRY) NULL;
|
|
|
|
#if 0
|
|
PRTR_DISC_INFO pRtrDisc = (PRTR_DISC_INFO) NULL;
|
|
#endif
|
|
|
|
PINTERFACE_STATUS_INFO pifStat = (PINTERFACE_STATUS_INFO) NULL;
|
|
|
|
PRTR_INFO_BLOCK_HEADER pIBH = (PRTR_INFO_BLOCK_HEADER) NULL;
|
|
PIPINIP_CONFIG_INFO pIpIpCfg;
|
|
|
|
//
|
|
// Allocate for minimal interface Info.
|
|
// a TOC entry is allocated for IP_ROUTE_INFO, but no route info
|
|
// block is created, since initially there are no static routes.
|
|
//
|
|
|
|
dwSize = sizeof( RTR_INFO_BLOCK_HEADER ) +
|
|
sizeof( RTR_TOC_ENTRY ) + sizeof( INTERFACE_STATUS_INFO ) +
|
|
2 * ALIGN_SIZE;
|
|
|
|
#if 0
|
|
if (dwIfType is ROUTER_IF_TYPE_DEDICATED)
|
|
{
|
|
dwSize += sizeof( RTR_TOC_ENTRY )
|
|
+ sizeof( RTR_DISC_INFO )
|
|
+ ALIGN_SIZE;
|
|
|
|
dwTocEntries++;
|
|
}
|
|
#endif
|
|
|
|
pIBH = (PRTR_INFO_BLOCK_HEADER) HeapAlloc( GetProcessHeap(), 0, dwSize );
|
|
|
|
if ( pIBH == (PRTR_INFO_BLOCK_HEADER) NULL )
|
|
{
|
|
*ppBuff = (LPBYTE) NULL;
|
|
DisplayMessage( g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
*ppBuff = (LPBYTE) pIBH;
|
|
|
|
pIBH-> Version = RTR_INFO_BLOCK_VERSION;
|
|
pIBH-> TocEntriesCount = dwTocEntries;
|
|
pIBH-> Size = dwSize;
|
|
|
|
|
|
pbDataPtr = (LPBYTE) &( pIBH-> TocEntry[ pIBH-> TocEntriesCount ] );
|
|
ALIGN_POINTER( pbDataPtr );
|
|
|
|
//
|
|
// Create empty route info block
|
|
//
|
|
|
|
pTocEntry = (PRTR_TOC_ENTRY) &( pIBH-> TocEntry[ 0 ] );
|
|
pTocEntry-> InfoType = IP_ROUTE_INFO;
|
|
pTocEntry-> InfoSize = sizeof( MIB_IPFORWARDROW );
|
|
pTocEntry-> Count = 0;
|
|
pTocEntry-> Offset = (ULONG) (pbDataPtr - (PBYTE) pIBH);
|
|
|
|
pbDataPtr += pTocEntry-> Count * pTocEntry-> InfoSize;
|
|
ALIGN_POINTER( pbDataPtr );
|
|
|
|
//
|
|
// Create interface status block.
|
|
//
|
|
|
|
pTocEntry = (PRTR_TOC_ENTRY) &( pIBH-> TocEntry[ 1 ] );
|
|
pTocEntry-> InfoType = IP_INTERFACE_STATUS_INFO;
|
|
pTocEntry-> InfoSize = sizeof( INTERFACE_STATUS_INFO );
|
|
pTocEntry-> Count = 1;
|
|
pTocEntry-> Offset = (ULONG) (pbDataPtr - (LPBYTE) pIBH);
|
|
|
|
pifStat = (PINTERFACE_STATUS_INFO) pbDataPtr;
|
|
pifStat-> dwAdminStatus = g_dwIfState;
|
|
|
|
pbDataPtr += pTocEntry-> Count * pTocEntry-> InfoSize;
|
|
ALIGN_POINTER( pbDataPtr );
|
|
|
|
#if 0
|
|
if (dwIfType is ROUTER_IF_TYPE_DEDICATED)
|
|
{
|
|
//
|
|
// Create Router Disc. Info.
|
|
//
|
|
|
|
pTocEntry = (PRTR_TOC_ENTRY) &( pIBH-> TocEntry[ 2 ]);
|
|
pTocEntry-> InfoType = IP_ROUTER_DISC_INFO;
|
|
pTocEntry-> InfoSize = sizeof( RTR_DISC_INFO );
|
|
pTocEntry-> Count = 1;
|
|
pTocEntry-> Offset = (ULONG) (pbDataPtr - (LPBYTE) pIBH);
|
|
|
|
|
|
pRtrDisc = (PRTR_DISC_INFO) pbDataPtr;
|
|
|
|
pRtrDisc-> bAdvertise = TRUE;
|
|
pRtrDisc-> wMaxAdvtInterval = g_wMaxAdvtInterval;
|
|
pRtrDisc-> wMinAdvtInterval = g_wMinAdvtInterval;
|
|
pRtrDisc-> wAdvtLifetime = g_wAdvtLifeTime;
|
|
pRtrDisc-> lPrefLevel = g_lPrefLevel;
|
|
|
|
pbDataPtr += pTocEntry-> Count * pTocEntry-> InfoSize;
|
|
|
|
ALIGN_POINTER( pbDataPtr );
|
|
}
|
|
#endif
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
AddInterfaceInfo(
|
|
IN LPCWSTR pwszIfName
|
|
)
|
|
{
|
|
DWORD dwRes = (DWORD) -1,
|
|
dwIfType,
|
|
dwSize = 0;
|
|
BOOL bAddRtrMgr = FALSE;
|
|
|
|
HANDLE hInterface = (HANDLE) NULL,
|
|
hTransport = (HANDLE) NULL,
|
|
hIfAdmin = (HANDLE) NULL,
|
|
hIfTransport = (HANDLE) NULL;
|
|
|
|
PRTR_INFO_BLOCK_HEADER pibhTmp = (PRTR_INFO_BLOCK_HEADER) NULL;
|
|
|
|
#ifdef EXTRA_DEBUG
|
|
PRINT(L"AddInterfaceInfo:");
|
|
PRINT(pwszIfName);
|
|
#endif
|
|
|
|
do
|
|
{
|
|
PMPR_INTERFACE_0 pmiIfInfo;
|
|
|
|
//
|
|
// verify interface name.
|
|
//
|
|
|
|
dwRes = MprConfigInterfaceGetHandle( g_hMprConfig,
|
|
(LPWSTR)pwszIfName,
|
|
&hInterface );
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
DisplayMessage( g_hModule, MSG_NO_INTERFACE, pwszIfName );
|
|
break;
|
|
}
|
|
|
|
// Make sure interface exists
|
|
|
|
dwRes = MprConfigInterfaceGetInfo(g_hMprConfig,
|
|
hInterface,
|
|
0,
|
|
(BYTE **)&pmiIfInfo,
|
|
&dwSize);
|
|
if( dwRes != NO_ERROR )
|
|
{
|
|
DisplayError( NULL, dwRes );
|
|
break;
|
|
}
|
|
|
|
dwIfType = pmiIfInfo->dwIfType;
|
|
|
|
// Here's a hack due apparently due to the inability of
|
|
// the current stack to do Foo-over-IP tunnels, so adding
|
|
// an ipip tunnel both creates the tunnel and enables IP
|
|
// on it.
|
|
|
|
if(dwIfType is ROUTER_IF_TYPE_TUNNEL1)
|
|
{
|
|
MprConfigBufferFree(pmiIfInfo);
|
|
|
|
dwRes = ERROR_INVALID_PARAMETER;
|
|
DisplayMessage(g_hModule, MSG_IP_IF_IS_TUNNEL);
|
|
|
|
break;
|
|
}
|
|
|
|
MprConfigBufferFree(pmiIfInfo);
|
|
|
|
//
|
|
// Is IP RtrMgr present on this router.
|
|
//
|
|
// if specified IP router manager is absent,
|
|
// we shall need to add global info for this
|
|
// router manager "before" we add the interface
|
|
// information
|
|
//
|
|
|
|
//
|
|
// Try to get a handle to the rtr mgr.
|
|
//
|
|
|
|
dwRes = MprConfigTransportGetHandle(g_hMprConfig,
|
|
PID_IP,
|
|
&hTransport);
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
if ( dwRes == ERROR_UNKNOWN_PROTOCOL_ID )
|
|
{
|
|
bAddRtrMgr = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DisplayError( NULL, dwRes );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// if handle is available, try to retrieve global info.
|
|
// if not available we shall need to add the global info.
|
|
//
|
|
|
|
if ( !bAddRtrMgr )
|
|
{
|
|
dwRes = MprConfigTransportGetInfo(g_hMprConfig,
|
|
hTransport,
|
|
(LPBYTE*) &pibhTmp,
|
|
&dwSize,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
DisplayError( NULL, dwRes );
|
|
break;
|
|
}
|
|
|
|
if ( pibhTmp == (PRTR_INFO_BLOCK_HEADER) NULL )
|
|
{
|
|
bAddRtrMgr = TRUE;
|
|
}
|
|
|
|
else
|
|
{
|
|
MprConfigBufferFree( pibhTmp );
|
|
pibhTmp = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If IP is already present on router, see if IP was already
|
|
// added to the interface. If so, complain.
|
|
//
|
|
|
|
if ( !bAddRtrMgr )
|
|
{
|
|
dwRes = MprConfigInterfaceTransportGetHandle(g_hMprConfig,
|
|
hInterface,
|
|
PID_IP,
|
|
&hIfTransport);
|
|
if ( dwRes == NO_ERROR )
|
|
{
|
|
dwRes = ERROR_INVALID_PARAMETER;
|
|
// was SetInterfaceInRouterConfig(); to update
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If IP RtrMgr is not present, add global info.
|
|
//
|
|
|
|
if ( bAddRtrMgr )
|
|
{
|
|
dwRes = MakeIPGlobalInfo( (LPBYTE *)&pibhTmp );
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
dwRes = MprConfigTransportCreate( g_hMprConfig,
|
|
PID_IP,
|
|
IP_KEY,
|
|
(LPBYTE) pibhTmp,
|
|
pibhTmp-> Size,
|
|
NULL,
|
|
0,
|
|
g_wszRtrMgrDLL,
|
|
&hTransport );
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
DisplayError( NULL, dwRes );
|
|
break;
|
|
}
|
|
|
|
HeapFree( GetProcessHeap(), 0, pibhTmp );
|
|
}
|
|
|
|
pibhTmp = (PRTR_INFO_BLOCK_HEADER) NULL;
|
|
|
|
//
|
|
// Add IP Rtr Mgr. information for the interface
|
|
//
|
|
|
|
dwRes = MakeIPInterfaceInfo( (LPBYTE*) &pibhTmp, dwIfType);
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwRes = MprConfigInterfaceTransportAdd( g_hMprConfig,
|
|
hInterface,
|
|
PID_IP,
|
|
IP_KEY,
|
|
(LPBYTE) pibhTmp,
|
|
pibhTmp-> Size,
|
|
&hIfTransport );
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
DisplayError( NULL, dwRes );
|
|
break;
|
|
}
|
|
|
|
if(IsRouterRunning())
|
|
{
|
|
dwRes = MprAdminInterfaceGetHandle(g_hMprAdmin,
|
|
(LPWSTR)pwszIfName,
|
|
&hIfAdmin,
|
|
FALSE);
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwRes = MprAdminInterfaceTransportAdd( g_hMprAdmin,
|
|
hIfAdmin,
|
|
PID_IP,
|
|
(LPBYTE) pibhTmp,
|
|
pibhTmp->Size );
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
DisplayMessage( g_hModule, ERROR_ADMIN, dwRes );
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
} while( FALSE );
|
|
|
|
//
|
|
// Free all allocations
|
|
//
|
|
|
|
if ( pibhTmp ) { HeapFree( GetProcessHeap(), 0, pibhTmp ); }
|
|
|
|
return dwRes;
|
|
}
|
|
|
|
DWORD
|
|
DeleteInterfaceInfo(
|
|
IN LPCWSTR pwszIfName
|
|
)
|
|
{
|
|
DWORD dwRes, dwIfType = 0, dwErr;
|
|
HANDLE hIfTransport, hInterface;
|
|
|
|
do
|
|
{
|
|
dwRes = MprConfigInterfaceGetHandle(g_hMprConfig,
|
|
(LPWSTR)pwszIfName,
|
|
&hInterface);
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the type of the interface
|
|
//
|
|
|
|
dwErr = GetInterfaceInfo(pwszIfName,
|
|
NULL,
|
|
NULL,
|
|
&dwIfType);
|
|
|
|
if(dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwRes = MprConfigInterfaceTransportGetHandle(g_hMprConfig,
|
|
hInterface,
|
|
PID_IP,
|
|
&hIfTransport);
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwRes = MprConfigInterfaceTransportRemove(g_hMprConfig,
|
|
hInterface,
|
|
hIfTransport);
|
|
|
|
//
|
|
// If its an ip in ip tunnel, clear out its name and delete from the
|
|
// router
|
|
//
|
|
|
|
if(dwIfType == ROUTER_IF_TYPE_TUNNEL1)
|
|
{
|
|
dwRes = MprConfigInterfaceDelete(g_hMprConfig,
|
|
hInterface);
|
|
|
|
if(dwRes == NO_ERROR)
|
|
{
|
|
GUID Guid;
|
|
|
|
dwRes = ConvertStringToGuid(pwszIfName,
|
|
(USHORT)(wcslen(pwszIfName) * sizeof(WCHAR)),
|
|
&Guid);
|
|
|
|
if(dwRes != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
MprSetupIpInIpInterfaceFriendlyNameDelete(g_pwszRouter,
|
|
&Guid);
|
|
}
|
|
}
|
|
|
|
if(IsRouterRunning())
|
|
{
|
|
dwRes = MprAdminInterfaceGetHandle(g_hMprAdmin,
|
|
(LPWSTR)pwszIfName,
|
|
&hInterface,
|
|
FALSE);
|
|
|
|
if ( dwRes != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwRes = MprAdminInterfaceTransportRemove(g_hMprAdmin,
|
|
hInterface,
|
|
PID_IP);
|
|
|
|
|
|
if(dwIfType == ROUTER_IF_TYPE_TUNNEL1)
|
|
{
|
|
dwRes = MprAdminInterfaceDelete(g_hMprAdmin,
|
|
hInterface);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
return dwRes;
|
|
}
|
|
|
|
DWORD
|
|
SetInterfaceInfo(
|
|
IN PRTR_INFO_BLOCK_HEADER pibhInfo,
|
|
IN LPCWSTR pwszIfName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets interface transport information in registry or router.
|
|
|
|
Arguments:
|
|
|
|
pwszIfName - Interface Name
|
|
pibhInfo - ptr to header
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR, ERROR_ROUTER_STOPPED
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwARes = NO_ERROR,
|
|
dwCRes = NO_ERROR;
|
|
HANDLE hIfTransport, hInterface;
|
|
UINT i;
|
|
PRTR_INFO_BLOCK_HEADER pibhNewInfo, pibhOldInfo;
|
|
|
|
//
|
|
// Create a new info block with all 0-length blocks removed
|
|
// since we don't want to write them to the registry,
|
|
// we only need to send them to the router which we
|
|
// will do with the original info block below.
|
|
//
|
|
|
|
pibhNewInfo = pibhInfo;
|
|
pibhOldInfo = NULL;
|
|
|
|
for (i=0; (dwCRes is NO_ERROR) && (i<pibhInfo->TocEntriesCount); i++)
|
|
{
|
|
if (pibhInfo->TocEntry[i].InfoSize is 0)
|
|
{
|
|
pibhOldInfo = pibhNewInfo;
|
|
|
|
dwCRes = MprInfoBlockRemove(pibhOldInfo,
|
|
pibhInfo->TocEntry[i].InfoType,
|
|
&pibhNewInfo);
|
|
|
|
if (pibhOldInfo isnot pibhInfo)
|
|
{
|
|
FREE_BUFFER(pibhOldInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwCRes is NO_ERROR)
|
|
{
|
|
dwCRes = MprConfigInterfaceGetHandle(g_hMprConfig,
|
|
(LPWSTR)pwszIfName,
|
|
&hInterface);
|
|
}
|
|
|
|
if (dwCRes is NO_ERROR)
|
|
{
|
|
dwCRes = MprConfigInterfaceTransportGetHandle(g_hMprConfig,
|
|
hInterface,
|
|
PID_IP,
|
|
&hIfTransport);
|
|
}
|
|
|
|
if (dwCRes is NO_ERROR)
|
|
{
|
|
dwCRes = MprConfigInterfaceTransportSetInfo(g_hMprConfig,
|
|
hInterface,
|
|
hIfTransport,
|
|
(LPBYTE) pibhNewInfo,
|
|
pibhNewInfo->Size);
|
|
}
|
|
|
|
if (pibhNewInfo isnot pibhInfo)
|
|
{
|
|
FREE_BUFFER(pibhNewInfo);
|
|
}
|
|
|
|
//
|
|
// Even if we failed to write to the registry, we still want
|
|
// to write to the router.
|
|
//
|
|
// We use the original format when writing to the router, since it
|
|
// needs to see the 0-length blocks in order to delete config info.
|
|
//
|
|
|
|
if(IsRouterRunning())
|
|
{
|
|
dwARes = MprAdminInterfaceGetHandle(g_hMprAdmin,
|
|
(LPWSTR)pwszIfName,
|
|
&hInterface,
|
|
FALSE);
|
|
|
|
if (dwARes is NO_ERROR)
|
|
{
|
|
dwARes = MprAdminInterfaceTransportSetInfo(g_hMprAdmin,
|
|
hInterface,
|
|
PID_IP,
|
|
(LPBYTE) pibhInfo,
|
|
pibhInfo->Size);
|
|
}
|
|
}
|
|
|
|
return (dwARes isnot NO_ERROR)? dwARes : dwCRes;
|
|
}
|
|
|
|
DWORD
|
|
WINAPI
|
|
IpCommit(
|
|
IN DWORD dwAction
|
|
)
|
|
{
|
|
PINTERFACE_STORE pii;
|
|
PLIST_ENTRY ple, pleTmp;
|
|
BOOL bCommit, bFlush = FALSE;
|
|
|
|
switch(dwAction)
|
|
{
|
|
case NETSH_COMMIT:
|
|
{
|
|
if (g_bCommit == TRUE)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
g_bCommit = TRUE;
|
|
|
|
break;
|
|
}
|
|
|
|
case NETSH_UNCOMMIT:
|
|
{
|
|
g_bCommit = FALSE;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
case NETSH_SAVE:
|
|
{
|
|
if (g_bCommit)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case NETSH_FLUSH:
|
|
{
|
|
//
|
|
// Action is a flush. If current state is commit, then
|
|
// nothing to be done.
|
|
|
|
if (g_bCommit)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
bFlush = TRUE;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Switched to commit mode. So set all valid info in the
|
|
// strutures. Free memory and invalidate the info.
|
|
//
|
|
|
|
if((g_tiTransport.bValid && g_tiTransport.pibhInfo) &&
|
|
!bFlush)
|
|
{
|
|
SetGlobalInfo(g_tiTransport.pibhInfo);
|
|
|
|
}
|
|
|
|
g_tiTransport.bValid = FALSE;
|
|
|
|
if(g_tiTransport.pibhInfo)
|
|
{
|
|
FREE_BUFFER(g_tiTransport.pibhInfo);
|
|
|
|
g_tiTransport.pibhInfo = NULL;
|
|
}
|
|
|
|
//
|
|
// Set the interface info
|
|
//
|
|
|
|
while(!IsListEmpty(&g_leIfListHead))
|
|
{
|
|
ple = RemoveHeadList(&g_leIfListHead);
|
|
|
|
pii = CONTAINING_RECORD(ple,
|
|
INTERFACE_STORE,
|
|
le);
|
|
|
|
if ((pii->bValid && pii->pibhInfo) &&
|
|
!bFlush)
|
|
{
|
|
// Set the info in config
|
|
|
|
SetInterfaceInfo(pii->pibhInfo,
|
|
pii->pwszIfName);
|
|
}
|
|
|
|
pii->bValid = FALSE;
|
|
|
|
if(pii->pibhInfo)
|
|
{
|
|
FREE_BUFFER(pii->pibhInfo);
|
|
|
|
pii->pibhInfo = NULL;
|
|
}
|
|
|
|
if(pii->pwszIfName)
|
|
{
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
pii->pwszIfName);
|
|
|
|
pii->pwszIfName = NULL;
|
|
}
|
|
|
|
//
|
|
// Free the list entry
|
|
//
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
pii);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
CreateInterface(
|
|
IN LPCWSTR pwszFriendlyName,
|
|
IN LPCWSTR pwszGuidName,
|
|
IN DWORD dwIfType,
|
|
IN BOOL bCreateRouterIf
|
|
)
|
|
|
|
{
|
|
DWORD i, dwErr, dwType, dwSize;
|
|
HANDLE hIfCfg, hIfAdmin, hIfTransport;
|
|
PBYTE pbyData;
|
|
|
|
PRTR_INFO_BLOCK_HEADER pInfo;
|
|
PINTERFACE_STATUS_INFO pStatus;
|
|
#if 0
|
|
PRTR_DISC_INFO pDisc;
|
|
#endif
|
|
|
|
//
|
|
// The only type we can create in the router is TUNNEL1
|
|
//
|
|
|
|
if(dwIfType != ROUTER_IF_TYPE_TUNNEL1)
|
|
{
|
|
ASSERT(FALSE);
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
hIfAdmin = NULL;
|
|
hIfCfg = NULL;
|
|
|
|
if(bCreateRouterIf)
|
|
{
|
|
MPR_INTERFACE_0 IfInfo;
|
|
|
|
//
|
|
// The caller wants us to create an interface in the router, also
|
|
//
|
|
|
|
wcsncpy(IfInfo.wszInterfaceName,
|
|
pwszGuidName,
|
|
MAX_INTERFACE_NAME_LEN);
|
|
|
|
IfInfo.fEnabled = TRUE;
|
|
|
|
IfInfo.dwIfType = dwIfType;
|
|
|
|
IfInfo.wszInterfaceName[MAX_INTERFACE_NAME_LEN] = UNICODE_NULL;
|
|
|
|
dwErr = MprConfigInterfaceCreate(g_hMprConfig,
|
|
0,
|
|
(PBYTE)&IfInfo,
|
|
&hIfCfg);
|
|
|
|
if(dwErr isnot NO_ERROR)
|
|
{
|
|
DisplayError(NULL,
|
|
dwErr);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// if router service is running add the interface
|
|
// to it too.
|
|
//
|
|
|
|
if(IsRouterRunning())
|
|
{
|
|
dwErr = MprAdminInterfaceCreate(g_hMprAdmin,
|
|
0,
|
|
(PBYTE)&IfInfo,
|
|
&hIfAdmin);
|
|
|
|
if(dwErr isnot NO_ERROR)
|
|
{
|
|
DisplayError(NULL,
|
|
dwErr);
|
|
|
|
|
|
MprConfigInterfaceDelete(g_hMprConfig,
|
|
hIfCfg);
|
|
|
|
return dwErr;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The interface existed in the router but not in IP
|
|
//
|
|
|
|
dwErr = MprConfigInterfaceGetHandle(g_hMprConfig,
|
|
(LPWSTR)pwszGuidName,
|
|
&hIfCfg);
|
|
|
|
if(dwErr isnot NO_ERROR)
|
|
{
|
|
DisplayError(NULL,
|
|
dwErr);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
if(IsRouterRunning())
|
|
{
|
|
dwErr = MprAdminInterfaceGetHandle(g_hMprAdmin,
|
|
(LPWSTR)pwszGuidName,
|
|
&hIfAdmin,
|
|
FALSE);
|
|
|
|
if(dwErr isnot NO_ERROR)
|
|
{
|
|
DisplayError(NULL,
|
|
dwErr);
|
|
|
|
return dwErr;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// At this point we have an interface which doesnt have IP on it
|
|
// We have the handles to config and admin (if router is running)
|
|
// Set the default information for the interface
|
|
//
|
|
|
|
dwSize = FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry[0]);
|
|
|
|
dwSize += (sizeof(INTERFACE_STATUS_INFO) +
|
|
sizeof(RTR_TOC_ENTRY) +
|
|
ALIGN_SIZE);
|
|
|
|
#if 0
|
|
dwSize += (sizeof(RTR_DISC_INFO) +
|
|
sizeof(RTR_TOC_ENTRY) +
|
|
ALIGN_SIZE);
|
|
#endif
|
|
|
|
pInfo = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
dwSize);
|
|
|
|
if(pInfo is NULL)
|
|
{
|
|
DisplayError(NULL,
|
|
ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
if(bCreateRouterIf)
|
|
{
|
|
MprConfigInterfaceDelete(g_hMprConfig,
|
|
hIfCfg);
|
|
}
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
pInfo->Version = IP_ROUTER_MANAGER_VERSION;
|
|
pInfo->TocEntriesCount = 1;
|
|
pInfo->Size = dwSize;
|
|
|
|
//
|
|
// Make data point to N+1th entry
|
|
//
|
|
|
|
pbyData = (PBYTE)&(pInfo->TocEntry[1]);
|
|
|
|
ALIGN_POINTER(pbyData);
|
|
|
|
pStatus = (PINTERFACE_STATUS_INFO)pbyData;
|
|
|
|
pStatus->dwAdminStatus = IF_ADMIN_STATUS_UP;
|
|
|
|
pInfo->TocEntry[0].InfoSize = sizeof(INTERFACE_STATUS_INFO);
|
|
pInfo->TocEntry[0].InfoType = IP_INTERFACE_STATUS_INFO;
|
|
pInfo->TocEntry[0].Count = 1;
|
|
pInfo->TocEntry[0].Offset = (ULONG)(pbyData - (PBYTE)pInfo);
|
|
|
|
pbyData = (PBYTE)((ULONG_PTR)pbyData + sizeof(INTERFACE_STATUS_INFO));
|
|
|
|
ALIGN_POINTER(pbyData);
|
|
|
|
#if 0
|
|
pDisc = (PRTR_DISC_INFO)pbyData;
|
|
|
|
pDisc->wMaxAdvtInterval =
|
|
DEFAULT_MAX_ADVT_INTERVAL;
|
|
pDisc->wMinAdvtInterval =
|
|
(WORD)(DEFAULT_MIN_ADVT_INTERVAL_RATIO * DEFAULT_MAX_ADVT_INTERVAL);
|
|
pDisc->wAdvtLifetime =
|
|
DEFAULT_ADVT_LIFETIME_RATIO * DEFAULT_MAX_ADVT_INTERVAL;
|
|
pDisc->bAdvertise = FALSE;
|
|
pDisc->lPrefLevel = DEFAULT_PREF_LEVEL;
|
|
|
|
pInfo->TocEntry[1].InfoSize = sizeof(RTR_DISC_INFO);
|
|
pInfo->TocEntry[1].InfoType = IP_ROUTER_DISC_INFO;
|
|
pInfo->TocEntry[1].Count = 1;
|
|
pInfo->TocEntry[1].Offset = (ULONG)(pbyData - (PBYTE)pInfo);
|
|
#endif
|
|
|
|
dwErr = MprConfigInterfaceTransportAdd(g_hMprConfig,
|
|
hIfCfg,
|
|
PID_IP,
|
|
IP_KEY,
|
|
(PBYTE) pInfo,
|
|
dwSize,
|
|
&hIfTransport);
|
|
|
|
if(dwErr isnot NO_ERROR)
|
|
{
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
pInfo);
|
|
|
|
DisplayMessage(g_hModule,
|
|
EMSG_CANT_CREATE_IF,
|
|
pwszFriendlyName,
|
|
dwErr);
|
|
|
|
if(bCreateRouterIf)
|
|
{
|
|
MprConfigInterfaceDelete(g_hMprConfig,
|
|
hIfCfg);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
if(hIfAdmin isnot NULL)
|
|
{
|
|
dwErr = MprAdminInterfaceTransportAdd(g_hMprAdmin,
|
|
hIfAdmin,
|
|
PID_IP,
|
|
(PBYTE) pInfo,
|
|
dwSize);
|
|
|
|
if(dwErr isnot NO_ERROR)
|
|
{
|
|
DisplayMessage(g_hModule,
|
|
EMSG_CANT_CREATE_IF,
|
|
pwszFriendlyName,
|
|
dwErr);
|
|
|
|
MprConfigInterfaceTransportRemove(g_hMprConfig,
|
|
hIfCfg,
|
|
hIfTransport);
|
|
|
|
if(bCreateRouterIf)
|
|
{
|
|
MprConfigInterfaceDelete(g_hMprConfig,
|
|
hIfCfg);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
pInfo);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
GetInterfaceClass(
|
|
IN LPCWSTR pwszIfName,
|
|
OUT PDWORD pdwIfClass
|
|
)
|
|
/*++
|
|
Description:
|
|
Determine whether an interface is of class Loopback, P2P,
|
|
Subnet, or NBMA. Currently there is no global way to do this,
|
|
so we test for some enumerated types and assume everything else
|
|
is Subnet.
|
|
Returns:
|
|
IFCLASS_xxx (see info.h)
|
|
--*/
|
|
{
|
|
DWORD dwErr, dwType;
|
|
|
|
dwErr = GetInterfaceInfo(pwszIfName,
|
|
NULL,
|
|
NULL,
|
|
&dwType);
|
|
|
|
if (dwErr)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
switch (dwType) {
|
|
case ROUTER_IF_TYPE_FULL_ROUTER : *pdwIfClass = IFCLASS_P2P; break;
|
|
case ROUTER_IF_TYPE_INTERNAL : *pdwIfClass = IFCLASS_NBMA; break;
|
|
case ROUTER_IF_TYPE_LOOPBACK : *pdwIfClass = IFCLASS_LOOPBACK; break;
|
|
case ROUTER_IF_TYPE_TUNNEL1 : *pdwIfClass = IFCLASS_P2P; break;
|
|
case ROUTER_IF_TYPE_DIALOUT : *pdwIfClass = IFCLASS_P2P; break;
|
|
default: *pdwIfClass = IFCLASS_BROADCAST; break;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|