windows-nt/Source/XPSP1/NT/net/rras/netsh/ip/ipmon/info.c
2020-09-26 16:20:57 +08:00

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