Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

475 lines
12 KiB

  1. /*
  2. File dhcp.c
  3. Implementation of the upgrade of dhcp relay agent from
  4. nt 4.0 to nt 5.0 router.
  5. Paul Mayfield, 9/15/97
  6. Reference files: routing\inc\ipbootp.h
  7. DHCP Relay Agent parameter mapping table:
  8. Relay Agent per Interface Global
  9. =========== ============= ======
  10. "HopsThreshold" Max Hop Count
  11. "SecsThreshold" Min Secs Since Boot
  12. "LogMessages" Logging Level
  13. "DHCPServers" Servers
  14. */
  15. #include "upgrade.h"
  16. #include <ipbootp.h>
  17. #include <winsock2.h>
  18. #include <routprot.h>
  19. static WCHAR szTempKey[] = L"DeleteMe";
  20. static HKEY hkRouter = NULL;
  21. static HKEY hkTemp = NULL;
  22. // Restore the registry from from backup
  23. // and make sure all global handles are opened
  24. DWORD DhcpPrepareRegistry(
  25. IN PWCHAR BackupFileName)
  26. {
  27. DWORD dwErr, dwDisposition;
  28. // Get access to the router registry key
  29. dwErr = UtlAccessRouterKey(&hkRouter);
  30. if (dwErr != ERROR_SUCCESS) {
  31. PrintMessage(L"Unable to access router key.\n");
  32. return dwErr;
  33. }
  34. // Restore the Dhcp parameters from backup
  35. __try {
  36. // Open up the temporary key
  37. dwErr = RegCreateKeyEx(
  38. hkRouter,
  39. szTempKey,
  40. 0,
  41. NULL,
  42. 0,
  43. KEY_ALL_ACCESS,
  44. NULL,
  45. &hkTemp,
  46. &dwDisposition);
  47. if (dwErr!=ERROR_SUCCESS)
  48. return dwErr;
  49. // Restore saved registry info to the temp key
  50. UtlSetupRestorePrivilege(TRUE);
  51. dwErr = RegRestoreKeyW(
  52. hkTemp,
  53. BackupFileName,
  54. 0);
  55. if (dwErr != ERROR_SUCCESS)
  56. return dwErr;
  57. }
  58. __finally {
  59. UtlSetupRestorePrivilege(FALSE);
  60. }
  61. return NO_ERROR;
  62. }
  63. // Cleanup the work done in the registry
  64. DWORD DhcpCleanupRegistry() {
  65. if (hkTemp)
  66. RegCloseKey(hkTemp);
  67. if (hkRouter) {
  68. RegDeleteKey(hkRouter,szTempKey);
  69. RegCloseKey(hkRouter);
  70. }
  71. hkTemp = NULL;
  72. hkRouter = NULL;
  73. return NO_ERROR;
  74. }
  75. // Reads in the list of configured dhcp servers
  76. DWORD DhcpReadServerList(
  77. IN LPBYTE * ppServerList,
  78. HKEY hkParams)
  79. {
  80. DWORD dwErr, dwType, dwSize = 0;
  81. LPSTR szServerValName = "DHCPServers";
  82. if (!ppServerList)
  83. return ERROR_INVALID_PARAMETER;
  84. dwErr = RegQueryValueExA(
  85. hkParams,
  86. szServerValName,
  87. NULL,
  88. &dwType,
  89. NULL,
  90. &dwSize);
  91. if (dwErr != ERROR_SUCCESS)
  92. return dwErr;
  93. if (dwSize == 0)
  94. {
  95. *ppServerList = NULL;
  96. return NO_ERROR;
  97. }
  98. *ppServerList = (LPBYTE) UtlAlloc(dwSize);
  99. if (! (*ppServerList))
  100. return ERROR_NOT_ENOUGH_MEMORY;
  101. dwErr = RegQueryValueExA(
  102. hkParams,
  103. szServerValName,
  104. NULL,
  105. &dwType,
  106. *ppServerList,
  107. &dwSize);
  108. if (dwErr != ERROR_SUCCESS)
  109. return dwErr;
  110. return NO_ERROR;
  111. }
  112. // Frees the resources associated with a list of dhcp servers
  113. DWORD DhcpFreeServerList(LPBYTE * ppServerList) {
  114. if ((ppServerList) && (*ppServerList))
  115. UtlFree(*ppServerList);
  116. return NO_ERROR;
  117. }
  118. // Gets the count of dhcp servers from this list read from
  119. // the registry
  120. DWORD DhcpGetServerCount(
  121. IN LPBYTE pServerList,
  122. LPDWORD lpdwSrvCount)
  123. {
  124. LPBYTE ptr = pServerList;
  125. if (!lpdwSrvCount)
  126. return ERROR_INVALID_PARAMETER;
  127. *lpdwSrvCount = 0;
  128. if (ptr) {
  129. while (*ptr) {
  130. (*lpdwSrvCount)++;
  131. ptr += strlen(ptr);
  132. }
  133. }
  134. return NO_ERROR;
  135. }
  136. // Converts a server string to a dword ip address
  137. DWORD DhcpAnsiSrvToDwordSrv(
  138. IN LPSTR AnsiIpAddr,
  139. OUT LPDWORD pAddr)
  140. {
  141. *pAddr = inet_addr(AnsiIpAddr);
  142. return NO_ERROR;
  143. }
  144. // Updates the Dhcp global information
  145. DWORD DhcpUpgradeGlobalInfo(
  146. IN dwt * DhcpParams,
  147. IN LPBYTE pServerList)
  148. {
  149. DWORD dwErr, dwSrvCount, dwVal, dwConfigSize, dwTransSize;
  150. DWORD dwNewSize;
  151. LPBYTE pSrvList = pServerList;
  152. LPDWORD pAddr;
  153. IPBOOTP_GLOBAL_CONFIG DhcpGlobalConfig = {
  154. IPBOOTP_LOGGING_ERROR, // Logging level
  155. 1024 * 1024, // Max recv-queue size
  156. 0 // Server count
  157. };
  158. PIPBOOTP_GLOBAL_CONFIG pNewConfig = NULL;
  159. LPBYTE pTransInfo = NULL, pNewTransInfo = NULL;
  160. HANDLE hSvrConfig = NULL, hTransport = NULL;
  161. __try {
  162. // Initialize the parameters with what was read from previous config
  163. dwErr = dwtGetValue(DhcpParams, L"LogMessages", &dwVal);
  164. if (dwErr == NO_ERROR)
  165. DhcpGlobalConfig.GC_LoggingLevel = dwVal;
  166. dwErr = DhcpGetServerCount(pServerList, &dwSrvCount);
  167. if (dwErr != NO_ERROR)
  168. return dwErr;
  169. DhcpGlobalConfig.GC_ServerCount = dwSrvCount;
  170. // Prepare a global information variable length structure
  171. dwConfigSize = IPBOOTP_GLOBAL_CONFIG_SIZE(&DhcpGlobalConfig);
  172. pNewConfig = (PIPBOOTP_GLOBAL_CONFIG) UtlAlloc(dwConfigSize);
  173. if (!pNewConfig)
  174. return ERROR_NOT_ENOUGH_MEMORY;
  175. memset(pNewConfig, 0, dwConfigSize);
  176. memcpy(pNewConfig, &DhcpGlobalConfig, sizeof(IPBOOTP_GLOBAL_CONFIG));
  177. // Fill in the Dhcp Server Addresss
  178. pSrvList = pServerList;
  179. pAddr = (LPDWORD)
  180. (((ULONG_PTR)pNewConfig) + sizeof(IPBOOTP_GLOBAL_CONFIG));
  181. while ((pSrvList) && (*pSrvList))
  182. {
  183. dwErr = DhcpAnsiSrvToDwordSrv(pSrvList, pAddr);
  184. if (dwErr != ERROR_SUCCESS)
  185. return dwErr;
  186. pSrvList += strlen(pSrvList);
  187. pAddr++;
  188. }
  189. // Set the new global configuration
  190. dwErr = MprConfigServerConnect(NULL, &hSvrConfig);
  191. if (dwErr != NO_ERROR)
  192. return dwErr;
  193. dwErr = MprConfigTransportGetHandle(hSvrConfig, PID_IP, &hTransport);
  194. if (dwErr != NO_ERROR)
  195. return dwErr;
  196. dwErr = MprConfigTransportGetInfo(
  197. hSvrConfig,
  198. hTransport,
  199. &pTransInfo,
  200. &dwTransSize,
  201. NULL,
  202. NULL,
  203. NULL);
  204. if (dwErr != NO_ERROR)
  205. return dwErr;
  206. dwErr = UtlUpdateInfoBlock(
  207. TRUE,
  208. pTransInfo,
  209. MS_IP_BOOTP,
  210. dwConfigSize,
  211. 1,
  212. (LPBYTE)pNewConfig,
  213. &pNewTransInfo,
  214. &dwNewSize);
  215. if (dwErr != NO_ERROR)
  216. return dwErr;
  217. dwErr = MprConfigTransportSetInfo(
  218. hSvrConfig,
  219. hTransport,
  220. pNewTransInfo,
  221. dwNewSize,
  222. NULL,
  223. 0,
  224. NULL);
  225. if (dwErr != NO_ERROR)
  226. return NO_ERROR;
  227. }
  228. __finally {
  229. if (pNewConfig)
  230. UtlFree(pNewConfig);
  231. if (pTransInfo)
  232. MprConfigBufferFree(pTransInfo);
  233. if (pNewTransInfo)
  234. MprConfigBufferFree(pNewTransInfo);
  235. if (hSvrConfig)
  236. MprConfigServerDisconnect(hSvrConfig);
  237. }
  238. return NO_ERROR;
  239. }
  240. //
  241. // Callback interface enumeration function that updates the if
  242. // with a dhcp if configuration blob.
  243. //
  244. // Return TRUE to continue enumeration, FALSE to stop.
  245. //
  246. BOOL DhcpInstallInterface(
  247. IN HANDLE hConfig,
  248. IN MPR_INTERFACE_0 * pIf,
  249. IN HANDLE hUserData)
  250. {
  251. IPBOOTP_IF_CONFIG * pConfig = (IPBOOTP_IF_CONFIG*)hUserData;
  252. LPBYTE pTransInfo = NULL, pNewTransInfo = NULL;
  253. HANDLE hTransport = NULL;
  254. DWORD dwErr, dwTransSize, dwNewSize;
  255. // Is this a LAN or a WAN interface
  256. if (pIf->dwIfType != ROUTER_IF_TYPE_DEDICATED &&
  257. pIf->dwIfType != ROUTER_IF_TYPE_HOME_ROUTER &&
  258. pIf->dwIfType != ROUTER_IF_TYPE_FULL_ROUTER)
  259. return TRUE;
  260. // Get the handle to ip info
  261. dwErr = MprConfigInterfaceTransportGetHandle(
  262. hConfig,
  263. pIf->hInterface,
  264. PID_IP,
  265. &hTransport);
  266. if (dwErr != NO_ERROR)
  267. return TRUE;
  268. // Get the ip info
  269. dwErr = MprConfigInterfaceTransportGetInfo(
  270. hConfig,
  271. pIf->hInterface,
  272. hTransport,
  273. &pTransInfo,
  274. &dwTransSize);
  275. if (dwErr != NO_ERROR)
  276. return TRUE;
  277. do {
  278. // Update the DHCP info
  279. dwErr = UtlUpdateInfoBlock(
  280. TRUE,
  281. pTransInfo,
  282. MS_IP_BOOTP,
  283. sizeof(IPBOOTP_IF_CONFIG),
  284. 1,
  285. (LPBYTE)pConfig,
  286. &pNewTransInfo,
  287. &dwNewSize);
  288. if (dwErr != NO_ERROR)
  289. break;
  290. // Commit the change
  291. dwErr = MprConfigInterfaceTransportSetInfo(
  292. hConfig,
  293. pIf->hInterface,
  294. hTransport,
  295. pNewTransInfo,
  296. dwNewSize);
  297. if (dwErr != NO_ERROR)
  298. break;
  299. } while (FALSE);
  300. // Cleanup
  301. {
  302. if (pTransInfo)
  303. MprConfigBufferFree(pTransInfo);
  304. if (pNewTransInfo)
  305. MprConfigBufferFree(pNewTransInfo);
  306. }
  307. return TRUE;
  308. }
  309. // Upgrade all of the interfaces to have dhcp information
  310. DWORD DhcpUpgradeInterfaces(
  311. IN dwt * DhcpParams)
  312. {
  313. DWORD dwErr, dwVal;
  314. IPBOOTP_IF_CONFIG DhcpIfConfig =
  315. {
  316. 0, // State (read-only)
  317. IPBOOTP_RELAY_ENABLED, // Relay-mode
  318. 4, // Max hop-count
  319. 4 // Min seconds-since-boot
  320. };
  321. // Initialize the hops threshold
  322. dwErr = dwtGetValue(DhcpParams, L"HopsThreshold", &dwVal);
  323. if (dwErr == NO_ERROR)
  324. DhcpIfConfig.IC_MaxHopCount = dwVal;
  325. // Initialize the seconds threshold
  326. dwErr = dwtGetValue(DhcpParams, L"SecsThreshold", &dwVal);
  327. if (dwErr == NO_ERROR)
  328. DhcpIfConfig.IC_MinSecondsSinceBoot = dwVal;
  329. // Loop through the interfaces, adding the dhcp blob as
  330. // appropriate
  331. dwErr = UtlEnumerateInterfaces(
  332. DhcpInstallInterface,
  333. (HANDLE)&DhcpIfConfig);
  334. return dwErr;
  335. }
  336. //
  337. // Restores the Dhcp parameters that were saved before upgrade.
  338. // assumes that the pre-upgrade parameters are being stored
  339. // temporarily in hkTemp
  340. //
  341. DWORD DhcpMigrateParams()
  342. {
  343. DWORD dwErr, dwVal;
  344. dwt DhcpParams;
  345. LPBYTE ServerList;
  346. __try {
  347. // Load in the parameters that were set for Dhcp
  348. dwErr = dwtLoadRegistyTable(&DhcpParams, hkTemp);
  349. if (dwErr != NO_ERROR)
  350. return dwErr;
  351. // Load in the list of dhcp servers
  352. dwErr = DhcpReadServerList(&ServerList, hkTemp);
  353. if (dwErr != NO_ERROR)
  354. return dwErr;
  355. // Migrate the various types of paramters
  356. dwErr = DhcpUpgradeGlobalInfo(&DhcpParams, ServerList);
  357. if (dwErr != NO_ERROR)
  358. return dwErr;
  359. // Migrate the per-interface parameters
  360. dwErr = DhcpUpgradeInterfaces(&DhcpParams);
  361. if (dwErr != NO_ERROR)
  362. return dwErr;
  363. }
  364. __finally {
  365. dwtCleanup(&DhcpParams);
  366. DhcpFreeServerList(&ServerList);
  367. }
  368. return NO_ERROR;
  369. }
  370. //
  371. // Upgrades Dhcp relay agent into nt 5.0 router
  372. //
  373. DWORD DhcpToRouterUpgrade(
  374. IN PWCHAR FileName)
  375. {
  376. DWORD dwErr;
  377. __try {
  378. // Restore the registry from the backup file
  379. dwErr = DhcpPrepareRegistry(FileName);
  380. if (dwErr != NO_ERROR)
  381. return dwErr;
  382. // Migrate Dhcp's parameters to the appropriate
  383. // new locations
  384. dwErr = DhcpMigrateParams();
  385. if (dwErr != NO_ERROR)
  386. return dwErr;
  387. // Mark the computer as having been configured
  388. //
  389. dwErr = UtlMarkRouterConfigured();
  390. if (dwErr != NO_ERROR)
  391. {
  392. PrintMessage(L"Unable to mark router as configured.\n");
  393. return dwErr;
  394. }
  395. }
  396. __finally {
  397. DhcpCleanupRegistry();
  398. }
  399. return NO_ERROR;
  400. }