476 lines
12 KiB
C
476 lines
12 KiB
C
/*
|
|
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;
|
|
}
|