#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) && (iTocEntriesCount); 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) && (iTocEntriesCount); 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; }