/* File: Rip.c Performs an upgrade of ip rip to nt5 router by munging registry values. Paul Mayfield, 9/3/97 The following steps are neccessary to upgrade rip: Params = HKLM/SYS/CCS/Services/IpRip/Parameters 1. Get the global info block for IP w/ MprConfigTransportGetInfo - Add a IPRIP_GLOBAL_CONFIG (ipriprm.h) block initialized as in routemon (rip.c, protocol.c) - Type is MS_IP_RIP as in sdk/inc/ipinfoid.h - Mappings Params.LoggingLevel to this global config blob 2. Get Interface info for each ras or lan ip interface - Add an IPRIP_IF_CONFIG (ipriprm.h) block (type MS_IP_RIP) - Initialize as per routemon - Mappings Params.AcceptHostRoutes - IC_ProtocolFlags (0=disable,1=enable) Params.UpdateFreq...=FullUpdateInterval Params.*Timeouts= 3. "SilentRip" param rules - If wks->srv, ignore this and set announce to disabled. accept=rip1 - If srv->srv, map announce to this value. accept=rip1 IP Rip Parameter Mapping ======================== Rip Listener IpRip in Router RIP_PARAMETERS IPRIP_IF_CONFIG ============== =============== "SilentRIP" IC_AcceptMode,IC_AnnounceMode "AcceptHostRoutes" IC_ProtocolFlags "AnnounceHostRoutes" IC_ProtocolFlags "AcceptDefaultRoutes" IC_ProtocolFlags "AnnounceDefaultRoutes" IC_ProtocolFlags "EnableSplitHorizon" IC_ProtocolFlags "EnablePoisonedReverse" IC_ProtocolFlags "RouteTimeout" IC_RouteExpirationInterval "GarbageTimeout" IC_RouteRemovalInterval "UpdateFrequency" IC_FullUpdateInterval "EnableTriggeredUpdates" IC_ProtocolFlags "MaxTriggeredUpdateFrequency" NOT MIGRATED "OverwriteStaticRoutes" IC_ProtocolFlags IpRip in Router IPRIP_GLOBAL_CONFIG =============== "LoggingLevel" GC_LoggingLevel REGVAL_ACCEPT_HOST "AcceptHostRoutes" REGVAL_ANNOUNCE_HOST "AnnounceHostRoutes" REGVAL_ACCEPT_DEFAULT "AcceptDefaultRoutes" REGVAL_ANNOUNCE_DEFAULT "AnnounceDefaultRoutes" REGVAL_SPLITHORIZON "EnableSplitHorizon" REGVAL_POISONREVERSE "EnablePoisonedReverse" REGVAL_LOGGINGLEVEL "LoggingLevel" REGVAL_ROUTETIMEOUT "RouteTimeout" REGVAL_GARBAGETIMEOUT "GarbageTimeout" REGVAL_UPDATEFREQUENCY "UpdateFrequency" REGVAL_TRIGGEREDUPDATES "EnableTriggeredUpdates" REGVAL_TRIGGERFREQUENCY "MaxTriggeredUpdateFrequency" REGVAL_OVERWRITESTATIC "OverwriteStaticRoutes" */ #include "upgrade.h" #include #include #include // Definition of table that migrates rip parameters typedef struct _PARAM_TO_FLAG { PWCHAR pszParam; DWORD dwFlag; } PARAM_TO_FLAG; // Definition of user data passed to interface enumeration // callback typedef struct _RIP_IF_DATA { IPRIP_IF_CONFIG * pLanConfig; IPRIP_IF_CONFIG * pWanConfig; } RIP_IF_DATA; // Types of upgrade #define SRV_TO_SRV 0 #define WKS_TO_SRV 1 // Globals static const WCHAR szTempKey[] = L"DeleteMe"; static HKEY hkRouter = NULL; static HKEY hkTemp = NULL; PARAM_TO_FLAG ParamFlagTable[] = { {L"AcceptHostRoutes", IPRIP_FLAG_ACCEPT_HOST_ROUTES}, {L"AnnounceHostRoutes", IPRIP_FLAG_ANNOUNCE_HOST_ROUTES}, {L"AcceptDefaultRoutes", IPRIP_FLAG_ACCEPT_DEFAULT_ROUTES}, {L"AnnounceDefaultRoutes", IPRIP_FLAG_ANNOUNCE_DEFAULT_ROUTES}, {L"EnableSplitHorizon", IPRIP_FLAG_SPLIT_HORIZON}, {L"EnablePoisonedReverse", IPRIP_FLAG_POISON_REVERSE}, {L"EnableTriggeredUpdates", IPRIP_FLAG_TRIGGERED_UPDATES}, {L"OverwriteStaticRoutes", IPRIP_FLAG_OVERWRITE_STATIC_ROUTES}, {NULL, 0} }; // Restore the registry from from // backup and make sure all global handles are opened DWORD IpRipPrepareRegistry( IN PWCHAR BackupFileName) { DWORD dwErr,dwDisposition; // Get access to the router registry key dwErr = UtlAccessRouterKey(&hkRouter); if (dwErr != ERROR_SUCCESS) { PrintMessage(L"Unable to access router key.\n"); return dwErr; } // Restore the rip parameters from backup __try { // Open up the temporary key dwErr = RegCreateKeyEx( hkRouter, szTempKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkTemp, &dwDisposition); if (dwErr!=ERROR_SUCCESS) return dwErr; // Restore the saved registry information to // the temp key UtlSetupRestorePrivilege(TRUE); dwErr = RegRestoreKeyW( hkTemp, BackupFileName, 0); if (dwErr != ERROR_SUCCESS) return dwErr; } __finally { UtlSetupRestorePrivilege(FALSE); } return NO_ERROR; } // Function initializes the rip global information based // on the parameters saved from the iprip service. // // 1. Get the global info block for IP w/ MprConfigTransportGetInfo // - Add a IPRIP_GLOBAL_CONFIG (ipriprm.h) // block initialized as in routemon (rip.c, protocol.c) // - Type is MS_IP_RIP as in sdk/inc/ipinfoid.h // - Mappings // Params.LoggingLevel to this global config blob DWORD IpRipUpgradeGlobalInfo( IN dwt * RipParams) { DWORD dwErr, dwTransSize, dwVal, dwNewSize = 0; LPBYTE lpTransInfo=NULL, lpNewTransInfo=NULL; HANDLE hSvrConfig=NULL, hTransport=NULL; // Create/initialize an IPRIP_GLOBAL_CONFIG block IPRIP_GLOBAL_CONFIG RipGlobalConfig = { IPRIP_LOGGING_ERROR, // Logging level 1024 * 1024, // Max recv-queue size 1024 * 1024, // Max send-queue size 5, // Minimum triggered-update interval IPRIP_FILTER_DISABLED, // Peer-filter mode 0 // Peer-filter count }; // Reset any values read from the previous iprip configuration dwErr = dwtGetValue( RipParams, L"LoggingLevel", &dwVal); if (dwErr == NO_ERROR) RipGlobalConfig.GC_LoggingLevel=dwVal; __try { // Add the rip global config to ip's global config dwErr = MprConfigServerConnect( NULL, &hSvrConfig); if (dwErr != NO_ERROR) return dwErr; dwErr = MprConfigTransportGetHandle( hSvrConfig, PID_IP, &hTransport); if (dwErr != NO_ERROR) return dwErr; dwErr = MprConfigTransportGetInfo( hSvrConfig, hTransport, &lpTransInfo, &dwTransSize, NULL, NULL, NULL); if (dwErr != NO_ERROR) return dwErr; dwErr = UtlUpdateInfoBlock( TRUE, lpTransInfo, MS_IP_RIP, sizeof(IPRIP_GLOBAL_CONFIG), 1, (LPBYTE)&RipGlobalConfig, &lpNewTransInfo, &dwNewSize); if (dwErr != NO_ERROR) return dwErr; // Commit the information dwErr = MprConfigTransportSetInfo( hSvrConfig, hTransport, lpNewTransInfo, dwNewSize, NULL, 0, NULL); if (dwErr != NO_ERROR) return NO_ERROR; } __finally { if (lpTransInfo) MprConfigBufferFree(lpTransInfo); if (lpNewTransInfo) MprConfigBufferFree(lpNewTransInfo); if (hSvrConfig) MprConfigServerDisconnect(hSvrConfig); } return NO_ERROR; } // Returns whether this is a wks->srv or srv->srv upgrade DWORD IpRipGetUpgradeType() { return SRV_TO_SRV; } // Migrates the silent rip parameter. // 3. "SilentRip" param rules // - If wks->srv, announce=disabled, accept=rip1 // - If srv->srv, announce=SilentRip, accept=rip1 DWORD IpRipMigrateRipSilence( IN OUT IPRIP_IF_CONFIG * RipIfConfig, IN DWORD dwSilence, IN BOOL IsWan) { DWORD UpgradeType = IpRipGetUpgradeType(); if (IsWan) { if (UpgradeType == WKS_TO_SRV) { RipIfConfig->IC_AcceptMode = IPRIP_ACCEPT_RIP1_COMPAT; RipIfConfig->IC_AnnounceMode = IPRIP_ACCEPT_DISABLED; } else if (UpgradeType == SRV_TO_SRV) { RipIfConfig->IC_AcceptMode = IPRIP_ACCEPT_RIP1_COMPAT; RipIfConfig->IC_AnnounceMode = dwSilence; } } else { if (UpgradeType == WKS_TO_SRV) { RipIfConfig->IC_AcceptMode = IPRIP_ACCEPT_RIP1; RipIfConfig->IC_AnnounceMode = IPRIP_ACCEPT_DISABLED; } else if (UpgradeType == SRV_TO_SRV) { RipIfConfig->IC_AcceptMode = IPRIP_ACCEPT_RIP1; RipIfConfig->IC_AnnounceMode = dwSilence; } } return NO_ERROR; } DWORD IpRipSetParamFlag( IN dwt * RipParams, IN PWCHAR ValName, IN DWORD dwFlag, OUT DWORD * dwParam) { DWORD dwVal, dwErr; dwErr = dwtGetValue(RipParams, ValName, &dwVal); if (dwErr == NO_ERROR) { if (dwVal) *dwParam |= dwFlag; else *dwParam &= ~dwFlag; } return NO_ERROR; } // Update the lan interface parameters from previous config DWORD IpRipUpdateIfConfig( IN dwt * RipParams, OUT IPRIP_IF_CONFIG * RipIfConfig, IN BOOL IsWan) { DWORD dwErr, dwVal; PARAM_TO_FLAG * pCurFlag; // Loop through all the parameter mappings, // setting the appripriate flag in the rip config pCurFlag = &(ParamFlagTable[0]); while (pCurFlag->pszParam) { // Set the flag as appropriate IpRipSetParamFlag( RipParams, pCurFlag->pszParam, pCurFlag->dwFlag, &(RipIfConfig->IC_ProtocolFlags)); // Increment the enumeration pCurFlag++; } // Set the parameters migrated as parameters dwErr = dwtGetValue(RipParams, L"UpdateFrequency", &dwVal); if (dwErr == NO_ERROR) RipIfConfig->IC_FullUpdateInterval = dwVal; dwErr = dwtGetValue(RipParams, L"RouteTimeout", &dwVal); if (dwErr == NO_ERROR) RipIfConfig->IC_RouteExpirationInterval = dwVal; dwErr = dwtGetValue(RipParams, L"GarbageTimeout", &dwVal); if (dwErr == NO_ERROR) RipIfConfig->IC_RouteRemovalInterval = dwVal; // Upgrade the silence parameter dwErr = dwtGetValue(RipParams, L"SilentRIP", &dwVal); if (dwErr == NO_ERROR) IpRipMigrateRipSilence(RipIfConfig, dwVal, IsWan); return NO_ERROR; } // // Callback function takes an interface and updates // its rip configuration. // // Returns TRUE to continue the enumerate, FALSE to // stop it // DWORD IpRipUpgradeInterface( IN HANDLE hConfig, IN MPR_INTERFACE_0 * pIf, IN HANDLE hUserData) { RIP_IF_DATA * pData = (RIP_IF_DATA*)hUserData; IPRIP_IF_CONFIG * pConfig; HANDLE hTransport = NULL; LPBYTE pTransInfo=NULL, pNewTransInfo=NULL; DWORD dwErr, dwIfSize, dwNewTransSize = 0; // Validate lan and wan interfaces if ((hConfig == NULL) || (pIf == NULL) || (pData == NULL)) { return FALSE; } // Is this a LAN or a WAN interface if (pIf->dwIfType == ROUTER_IF_TYPE_DEDICATED) pConfig = pData->pLanConfig; else if (pIf->dwIfType == ROUTER_IF_TYPE_HOME_ROUTER || pIf->dwIfType == ROUTER_IF_TYPE_FULL_ROUTER) pConfig = pData->pWanConfig; else return TRUE; do { // Get the handle to ip info associated with this if dwErr = MprConfigInterfaceTransportGetHandle( hConfig, pIf->hInterface, PID_IP, &hTransport); if (dwErr != NO_ERROR) break; // Get the ip info associated with this if dwErr = MprConfigInterfaceTransportGetInfo( hConfig, pIf->hInterface, hTransport, &pTransInfo, &dwIfSize); if (dwErr != NO_ERROR) break; // Update the info block with the rip data dwErr = UtlUpdateInfoBlock ( TRUE, pTransInfo, MS_IP_RIP, sizeof(IPRIP_IF_CONFIG), 1, (LPBYTE)pConfig, &pNewTransInfo, &dwNewTransSize); if (dwErr != NO_ERROR) break; // Commit the change dwErr = MprConfigInterfaceTransportSetInfo( hConfig, pIf->hInterface, hTransport, pNewTransInfo, dwNewTransSize); if (dwErr != NO_ERROR) break; } while (FALSE); // Cleanup { if (pNewTransInfo) MprConfigBufferFree(pNewTransInfo); if (pTransInfo) MprConfigBufferFree(pTransInfo); } return TRUE; } // Initializes the rip per-interface information based on the // parameters saved from the iprip service. // // 2. Get Interface info for each ras or lan ip interface // - Add an IPRIP_IF_CONFIG (ipriprm.h) block (type MS_IP_RIP) // - Initialize as per routemon // - Mappings // Params.AcceptHostRoutes - IC_ProtocolFlags (0=disable,1=enable) // Params.UpdateFreq...=FullUpdateInterval // Params.*Timeouts= DWORD IpRipUpgradeInterfaces( IN dwt * RipParams) { DWORD dwErr; // Create/initialize an rip info blocks IPRIP_IF_CONFIG RipLanConfig = { 0, // State (read-only) 1, // Metric IPRIP_UPDATE_PERIODIC, // Update mode IPRIP_ACCEPT_RIP1, // Accept mode IPRIP_ANNOUNCE_RIP1, // Announce mode IPRIP_FLAG_SPLIT_HORIZON | IPRIP_FLAG_POISON_REVERSE | IPRIP_FLAG_GRACEFUL_SHUTDOWN | IPRIP_FLAG_TRIGGERED_UPDATES, // Protocol flags 180, // Route-expiration interval 120, // Route-removal interval 30, // Full-update interval IPRIP_AUTHTYPE_NONE, // Authentication type {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // Authentication key 0, // Route tag IPRIP_PEER_DISABLED, // Unicast-peer mode IPRIP_FILTER_DISABLED, // Accept-filter mode IPRIP_FILTER_DISABLED, // Announce-filter mode 0, // Unicast-peer count 0, // Accept-filter count 0 // Announce-filter count }; IPRIP_IF_CONFIG RipWanConfig = { 0, 1, IPRIP_UPDATE_DEMAND, // Update mode for WAN IPRIP_ACCEPT_RIP1, IPRIP_ANNOUNCE_RIP1, IPRIP_FLAG_SPLIT_HORIZON | IPRIP_FLAG_POISON_REVERSE | IPRIP_FLAG_GRACEFUL_SHUTDOWN, 180, 120, 30, IPRIP_AUTHTYPE_NONE, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0, IPRIP_PEER_DISABLED, IPRIP_FILTER_DISABLED, IPRIP_FILTER_DISABLED, 0, 0, 0 }; RIP_IF_DATA RipBlobs = { &RipLanConfig, &RipWanConfig }; // Update the lan config blob with values from previous // installation of rip service. dwErr = IpRipUpdateIfConfig(RipParams, RipBlobs.pLanConfig, FALSE); if (dwErr != NO_ERROR) return dwErr; // Update the wan config blob with values from previous // installation of rip service. dwErr = IpRipUpdateIfConfig(RipParams, RipBlobs.pWanConfig, TRUE); if (dwErr != NO_ERROR) return dwErr; // Enumerate the interfaces, updating each one with // rip config as you go. dwErr = UtlEnumerateInterfaces( IpRipUpgradeInterface, &RipBlobs); if (dwErr != NO_ERROR) return dwErr; return NO_ERROR; } // Restores the Rip parameters that were saved before upgrade. // This function assumes that those parameters are being stored // temporarily in hkTemp DWORD IpRipMigrateParams() { DWORD dwErr, dwVal; dwt RipParams; __try { // Load in the parameters that were set for Rip dwErr = dwtLoadRegistyTable(&RipParams, hkTemp); if (dwErr != NO_ERROR) return dwErr; // Migrate the various types of paramters dwErr = IpRipUpgradeGlobalInfo(&RipParams); if (dwErr != NO_ERROR) return dwErr; // Migrate the per-interface parameters dwErr = IpRipUpgradeInterfaces(&RipParams); if (dwErr != NO_ERROR) return dwErr; } __finally { dwtCleanup(&RipParams); } return NO_ERROR; } // Cleanup the work done in the registry DWORD IpRipCleanupRegistry() { if (hkTemp) RegCloseKey(hkTemp); if (hkRouter) { RegDeleteKey(hkRouter, szTempKey); RegCloseKey(hkRouter); } hkTemp = NULL; hkRouter = NULL; return NO_ERROR; } // Upgrades iprip to nt 5.0 router DWORD IpRipToRouterUpgrade( IN PWCHAR FileName) { DWORD dwErr; __try { // Restore the registry from the backup file dwErr = IpRipPrepareRegistry(FileName); if (dwErr != NO_ERROR) return dwErr; // Migrate rip's parameters to the appropriate // new locations dwErr = IpRipMigrateParams(); if (dwErr != NO_ERROR) return dwErr; // Mark the computer as having been configured // dwErr = UtlMarkRouterConfigured(); if (dwErr != NO_ERROR) { PrintMessage(L"Unable to mark router as configured.\n"); return dwErr; } } __finally { IpRipCleanupRegistry(); } return NO_ERROR; }