|
|
/*
File dhcp.c
Implementation of the upgrade of dhcp relay agent from nt 4.0 to nt 5.0 router.
Paul Mayfield, 9/15/97
Reference files: routing\inc\ipbootp.h
DHCP Relay Agent parameter mapping table: Relay Agent per Interface Global =========== ============= ====== "HopsThreshold" Max Hop Count "SecsThreshold" Min Secs Since Boot "LogMessages" Logging Level "DHCPServers" Servers */
#include "upgrade.h"
#include <ipbootp.h>
#include <winsock2.h>
#include <routprot.h>
static WCHAR szTempKey[] = L"DeleteMe"; static HKEY hkRouter = NULL; static HKEY hkTemp = NULL;
// Restore the registry from from backup
// and make sure all global handles are opened
DWORD DhcpPrepareRegistry( 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 Dhcp 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 saved registry info to the temp key
UtlSetupRestorePrivilege(TRUE); dwErr = RegRestoreKeyW( hkTemp, BackupFileName, 0); if (dwErr != ERROR_SUCCESS) return dwErr; } __finally { UtlSetupRestorePrivilege(FALSE); } return NO_ERROR; }
// Cleanup the work done in the registry
DWORD DhcpCleanupRegistry() {
if (hkTemp) RegCloseKey(hkTemp); if (hkRouter) { RegDeleteKey(hkRouter,szTempKey); RegCloseKey(hkRouter); } hkTemp = NULL; hkRouter = NULL; return NO_ERROR; }
// Reads in the list of configured dhcp servers
DWORD DhcpReadServerList( IN LPBYTE * ppServerList, HKEY hkParams) { DWORD dwErr, dwType, dwSize = 0; LPSTR szServerValName = "DHCPServers";
if (!ppServerList) return ERROR_INVALID_PARAMETER;
dwErr = RegQueryValueExA( hkParams, szServerValName, NULL, &dwType, NULL, &dwSize); if (dwErr != ERROR_SUCCESS) return dwErr;
if (dwSize == 0) { *ppServerList = NULL; return NO_ERROR; }
*ppServerList = (LPBYTE) UtlAlloc(dwSize); if (! (*ppServerList)) return ERROR_NOT_ENOUGH_MEMORY;
dwErr = RegQueryValueExA( hkParams, szServerValName, NULL, &dwType, *ppServerList, &dwSize); if (dwErr != ERROR_SUCCESS) return dwErr;
return NO_ERROR; }
// Frees the resources associated with a list of dhcp servers
DWORD DhcpFreeServerList(LPBYTE * ppServerList) {
if ((ppServerList) && (*ppServerList)) UtlFree(*ppServerList); return NO_ERROR; }
// Gets the count of dhcp servers from this list read from
// the registry
DWORD DhcpGetServerCount( IN LPBYTE pServerList, LPDWORD lpdwSrvCount) { LPBYTE ptr = pServerList;
if (!lpdwSrvCount) return ERROR_INVALID_PARAMETER;
*lpdwSrvCount = 0; if (ptr) { while (*ptr) { (*lpdwSrvCount)++; ptr += strlen(ptr); } }
return NO_ERROR; }
// Converts a server string to a dword ip address
DWORD DhcpAnsiSrvToDwordSrv( IN LPSTR AnsiIpAddr, OUT LPDWORD pAddr) { *pAddr = inet_addr(AnsiIpAddr); return NO_ERROR; }
// Updates the Dhcp global information
DWORD DhcpUpgradeGlobalInfo( IN dwt * DhcpParams, IN LPBYTE pServerList) { DWORD dwErr, dwSrvCount, dwVal, dwConfigSize, dwTransSize; DWORD dwNewSize; LPBYTE pSrvList = pServerList; LPDWORD pAddr;
IPBOOTP_GLOBAL_CONFIG DhcpGlobalConfig = { IPBOOTP_LOGGING_ERROR, // Logging level
1024 * 1024, // Max recv-queue size
0 // Server count
}; PIPBOOTP_GLOBAL_CONFIG pNewConfig = NULL; LPBYTE pTransInfo = NULL, pNewTransInfo = NULL; HANDLE hSvrConfig = NULL, hTransport = NULL;
__try { // Initialize the parameters with what was read from previous config
dwErr = dwtGetValue(DhcpParams, L"LogMessages", &dwVal); if (dwErr == NO_ERROR) DhcpGlobalConfig.GC_LoggingLevel = dwVal; dwErr = DhcpGetServerCount(pServerList, &dwSrvCount); if (dwErr != NO_ERROR) return dwErr; DhcpGlobalConfig.GC_ServerCount = dwSrvCount;
// Prepare a global information variable length structure
dwConfigSize = IPBOOTP_GLOBAL_CONFIG_SIZE(&DhcpGlobalConfig); pNewConfig = (PIPBOOTP_GLOBAL_CONFIG) UtlAlloc(dwConfigSize); if (!pNewConfig) return ERROR_NOT_ENOUGH_MEMORY; memset(pNewConfig, 0, dwConfigSize); memcpy(pNewConfig, &DhcpGlobalConfig, sizeof(IPBOOTP_GLOBAL_CONFIG));
// Fill in the Dhcp Server Addresss
pSrvList = pServerList; pAddr = (LPDWORD) (((ULONG_PTR)pNewConfig) + sizeof(IPBOOTP_GLOBAL_CONFIG)); while ((pSrvList) && (*pSrvList)) { dwErr = DhcpAnsiSrvToDwordSrv(pSrvList, pAddr); if (dwErr != ERROR_SUCCESS) return dwErr; pSrvList += strlen(pSrvList); pAddr++; } // Set the new global configuration
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, &pTransInfo, &dwTransSize, NULL, NULL, NULL); if (dwErr != NO_ERROR) return dwErr;
dwErr = UtlUpdateInfoBlock( TRUE, pTransInfo, MS_IP_BOOTP, dwConfigSize, 1, (LPBYTE)pNewConfig, &pNewTransInfo, &dwNewSize); if (dwErr != NO_ERROR) return dwErr;
dwErr = MprConfigTransportSetInfo( hSvrConfig, hTransport, pNewTransInfo, dwNewSize, NULL, 0, NULL); if (dwErr != NO_ERROR) return NO_ERROR;
} __finally { if (pNewConfig) UtlFree(pNewConfig); if (pTransInfo) MprConfigBufferFree(pTransInfo); if (pNewTransInfo) MprConfigBufferFree(pNewTransInfo); if (hSvrConfig) MprConfigServerDisconnect(hSvrConfig); } return NO_ERROR; }
//
// Callback interface enumeration function that updates the if
// with a dhcp if configuration blob.
//
// Return TRUE to continue enumeration, FALSE to stop.
//
BOOL DhcpInstallInterface( IN HANDLE hConfig, IN MPR_INTERFACE_0 * pIf, IN HANDLE hUserData) { IPBOOTP_IF_CONFIG * pConfig = (IPBOOTP_IF_CONFIG*)hUserData; LPBYTE pTransInfo = NULL, pNewTransInfo = NULL; HANDLE hTransport = NULL; DWORD dwErr, dwTransSize, dwNewSize; // Is this a LAN or a WAN interface
if (pIf->dwIfType != ROUTER_IF_TYPE_DEDICATED && pIf->dwIfType != ROUTER_IF_TYPE_HOME_ROUTER && pIf->dwIfType != ROUTER_IF_TYPE_FULL_ROUTER) return TRUE;
// Get the handle to ip info
dwErr = MprConfigInterfaceTransportGetHandle( hConfig, pIf->hInterface, PID_IP, &hTransport); if (dwErr != NO_ERROR) return TRUE;
// Get the ip info
dwErr = MprConfigInterfaceTransportGetInfo( hConfig, pIf->hInterface, hTransport, &pTransInfo, &dwTransSize); if (dwErr != NO_ERROR) return TRUE;
do { // Update the DHCP info
dwErr = UtlUpdateInfoBlock( TRUE, pTransInfo, MS_IP_BOOTP, sizeof(IPBOOTP_IF_CONFIG), 1, (LPBYTE)pConfig, &pNewTransInfo, &dwNewSize); if (dwErr != NO_ERROR) break; // Commit the change
dwErr = MprConfigInterfaceTransportSetInfo( hConfig, pIf->hInterface, hTransport, pNewTransInfo, dwNewSize); if (dwErr != NO_ERROR) break; } while (FALSE);
// Cleanup
{ if (pTransInfo) MprConfigBufferFree(pTransInfo); if (pNewTransInfo) MprConfigBufferFree(pNewTransInfo); }
return TRUE; }
// Upgrade all of the interfaces to have dhcp information
DWORD DhcpUpgradeInterfaces( IN dwt * DhcpParams) { DWORD dwErr, dwVal; IPBOOTP_IF_CONFIG DhcpIfConfig = { 0, // State (read-only)
IPBOOTP_RELAY_ENABLED, // Relay-mode
4, // Max hop-count
4 // Min seconds-since-boot
};
// Initialize the hops threshold
dwErr = dwtGetValue(DhcpParams, L"HopsThreshold", &dwVal); if (dwErr == NO_ERROR) DhcpIfConfig.IC_MaxHopCount = dwVal;
// Initialize the seconds threshold
dwErr = dwtGetValue(DhcpParams, L"SecsThreshold", &dwVal); if (dwErr == NO_ERROR) DhcpIfConfig.IC_MinSecondsSinceBoot = dwVal;
// Loop through the interfaces, adding the dhcp blob as
// appropriate
dwErr = UtlEnumerateInterfaces( DhcpInstallInterface, (HANDLE)&DhcpIfConfig);
return dwErr; }
//
// Restores the Dhcp parameters that were saved before upgrade.
// assumes that the pre-upgrade parameters are being stored
// temporarily in hkTemp
//
DWORD DhcpMigrateParams() { DWORD dwErr, dwVal; dwt DhcpParams; LPBYTE ServerList;
__try { // Load in the parameters that were set for Dhcp
dwErr = dwtLoadRegistyTable(&DhcpParams, hkTemp); if (dwErr != NO_ERROR) return dwErr;
// Load in the list of dhcp servers
dwErr = DhcpReadServerList(&ServerList, hkTemp); if (dwErr != NO_ERROR) return dwErr;
// Migrate the various types of paramters
dwErr = DhcpUpgradeGlobalInfo(&DhcpParams, ServerList); if (dwErr != NO_ERROR) return dwErr;
// Migrate the per-interface parameters
dwErr = DhcpUpgradeInterfaces(&DhcpParams); if (dwErr != NO_ERROR) return dwErr; } __finally { dwtCleanup(&DhcpParams); DhcpFreeServerList(&ServerList); }
return NO_ERROR; }
//
// Upgrades Dhcp relay agent into nt 5.0 router
//
DWORD DhcpToRouterUpgrade( IN PWCHAR FileName) { DWORD dwErr;
__try { // Restore the registry from the backup file
dwErr = DhcpPrepareRegistry(FileName); if (dwErr != NO_ERROR) return dwErr;
// Migrate Dhcp's parameters to the appropriate
// new locations
dwErr = DhcpMigrateParams(); 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 { DhcpCleanupRegistry(); }
return NO_ERROR; }
|