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.

960 lines
24 KiB

  1. /*
  2. Copyright (c) 1998, Microsoft Corporation, all rights reserved
  3. Description:
  4. Only the timer thread can call the following functions:
  5. rasDhcpAllocateAddress, rasDhcpMonitorAddresses, rasDhcpRenewLease. This is
  6. required to avoid race conditions in the timer queue (because these
  7. functions call RasDhcpTimerSchedule). The only exception is that
  8. RasDhcpInitialize can call RasDhcpTimerSchedule, but before the timer thread
  9. is started. rasDhcpRenewLease leaves and enters the critical section in the
  10. middle of the function. If pAddrInfo is freed in the meantime, there will be
  11. an AV. However, only rasDhcpDeleteLists frees pAddrInfo's from the list.
  12. Fortunately, only RasDhcpUninitialize (after stopping the timer thread) and
  13. rasDhcpAllocateAddress (which belongs to the timer thread) call
  14. rasDhcpDeleteLists.
  15. If we get an EasyNet address, DHCP has already made sure that it is not
  16. conflicting with anyone. We call SetProxyArp, so that no one else in the
  17. future will take it (if they are well behaved).
  18. */
  19. #include "rasdhcp_.h"
  20. /*
  21. Returns:
  22. Notes:
  23. There is no synchronization here, can be added easily but the assumption
  24. here is that the initialization is a synchronous operation and till it
  25. completes, no other code in this sub-system will be called.
  26. */
  27. DWORD
  28. RasDhcpInitialize(
  29. VOID
  30. )
  31. {
  32. DWORD dwErr = NO_ERROR;
  33. TraceHlp("RasDhcpInitialize");
  34. EnterCriticalSection(&RasDhcpCriticalSection);
  35. RtlGetNtProductType(&RasDhcpNtProductType);
  36. if (NtProductWinNt == RasDhcpNtProductType)
  37. {
  38. RasDhcpNumReqAddrs = 2;
  39. }
  40. else
  41. {
  42. RasDhcpNumReqAddrs = HelperRegVal.dwChunkSize;
  43. }
  44. // This should be done before we start the timer thread. Once the timer
  45. // thread starts, only it can call RasDhcpTimerSchedule (to avoid race
  46. // conditions).
  47. RasDhcpTimerSchedule(
  48. &RasDhcpMonitorTimer,
  49. 0,
  50. rasDhcpMonitorAddresses);
  51. dwErr = RasDhcpTimerInitialize();
  52. if (NO_ERROR != dwErr)
  53. {
  54. TraceHlp("RasDhcpInitTimer failed and returned %d", dwErr);
  55. goto LDone;
  56. }
  57. LDone:
  58. if (NO_ERROR != dwErr)
  59. {
  60. RasDhcpTimerUninitialize();
  61. }
  62. LeaveCriticalSection(&RasDhcpCriticalSection);
  63. return(dwErr);
  64. }
  65. /*
  66. Returns:
  67. VOID
  68. Notes:
  69. */
  70. VOID
  71. RasDhcpUninitialize(
  72. VOID
  73. )
  74. {
  75. TraceHlp("RasDhcpUninitialize");
  76. /*
  77. Do not hold RasDhcpCriticalSection while calling this function. Otherwise,
  78. the following deadlock can occur: The timer thread is blocked in
  79. rasDhcpAllocateAddress, waiting for RasDhcpCriticalSection, and this thread
  80. is blocked in RasDhcpTimerUninitialize, waiting for the timer thread to
  81. stop.
  82. */
  83. RasDhcpTimerUninitialize();
  84. EnterCriticalSection(&RasDhcpCriticalSection);
  85. /*
  86. To avoid a possible race condition in rasDhcpRenewLease (see the comments
  87. in that function), it is important to call RasDhcpTimerUninitialize and
  88. kill the timer thread before calling rasDhcpDeleteLists.
  89. */
  90. rasDhcpDeleteLists();
  91. RasDhcpUsingEasyNet = TRUE;
  92. LeaveCriticalSection(&RasDhcpCriticalSection);
  93. }
  94. /*
  95. Returns:
  96. Notes:
  97. */
  98. DWORD
  99. RasDhcpAcquireAddress(
  100. IN HPORT hPort,
  101. OUT IPADDR* pnboIpAddr,
  102. OUT IPADDR* pnboIpMask,
  103. OUT BOOL* pfEasyNet
  104. )
  105. {
  106. ADDR_INFO* pAddrInfo;
  107. DWORD dwErr = ERROR_NOT_FOUND;
  108. TraceHlp("RasDhcpAcquireAddress");
  109. EnterCriticalSection(&RasDhcpCriticalSection);
  110. if (NULL == RasDhcpFreePool)
  111. {
  112. TraceHlp("Out of addresses");
  113. goto LDone;
  114. }
  115. // Move from Free pool to Alloc pool
  116. pAddrInfo = RasDhcpFreePool;
  117. RasDhcpFreePool = RasDhcpFreePool->ai_Next;
  118. pAddrInfo->ai_Next = RasDhcpAllocPool;
  119. RasDhcpAllocPool = pAddrInfo;
  120. TraceHlp("Acquired 0x%x", pAddrInfo->ai_LeaseInfo.IpAddress);
  121. *pnboIpAddr = htonl(pAddrInfo->ai_LeaseInfo.IpAddress);
  122. *pnboIpMask = htonl(pAddrInfo->ai_LeaseInfo.SubnetMask);
  123. pAddrInfo->ai_hPort = hPort;
  124. pAddrInfo->ai_Flags |= AI_FLAG_IN_USE;
  125. if (NULL != pfEasyNet)
  126. {
  127. *pfEasyNet = RasDhcpUsingEasyNet;
  128. }
  129. if ( (NULL == RasDhcpFreePool)
  130. && (0 == RasDhcpNumReqAddrs))
  131. {
  132. // We don't have any more addresses to give out. Let us
  133. // acquire another chunk of them.
  134. if (NtProductWinNt == RasDhcpNtProductType)
  135. {
  136. RasDhcpNumReqAddrs += 1;
  137. }
  138. else
  139. {
  140. RasDhcpNumReqAddrs += HelperRegVal.dwChunkSize;
  141. }
  142. RasDhcpTimerRunNow();
  143. }
  144. dwErr = NO_ERROR;
  145. LDone:
  146. LeaveCriticalSection(&RasDhcpCriticalSection);
  147. return(dwErr);
  148. }
  149. /*
  150. Returns:
  151. VOID
  152. Notes:
  153. */
  154. VOID
  155. RasDhcpReleaseAddress(
  156. IN IPADDR nboIpAddr
  157. )
  158. {
  159. ADDR_INFO* pAddrInfo;
  160. ADDR_INFO** ppAddrInfo;
  161. IPADDR hboIpAddr;
  162. TraceHlp("RasDhcpReleaseAddress");
  163. EnterCriticalSection(&RasDhcpCriticalSection);
  164. hboIpAddr = ntohl(nboIpAddr);
  165. for (ppAddrInfo = &RasDhcpAllocPool;
  166. (pAddrInfo = *ppAddrInfo) != NULL;
  167. ppAddrInfo = &pAddrInfo->ai_Next)
  168. {
  169. if (pAddrInfo->ai_LeaseInfo.IpAddress == hboIpAddr)
  170. {
  171. TraceHlp("Released 0x%x", nboIpAddr);
  172. // Unlink from alloc pool
  173. *ppAddrInfo = pAddrInfo->ai_Next;
  174. // Put at the end of the free pool, because we want to round-robin
  175. // the addresses.
  176. pAddrInfo->ai_Next = NULL;
  177. ppAddrInfo = &RasDhcpFreePool;
  178. while (NULL != *ppAddrInfo)
  179. {
  180. ppAddrInfo = &((*ppAddrInfo)->ai_Next);
  181. }
  182. *ppAddrInfo = pAddrInfo;
  183. pAddrInfo->ai_Flags &= ~AI_FLAG_IN_USE;
  184. goto LDone;
  185. }
  186. }
  187. TraceHlp("IpAddress 0x%x not present in alloc pool", nboIpAddr);
  188. LDone:
  189. LeaveCriticalSection(&RasDhcpCriticalSection);
  190. }
  191. /*
  192. Returns:
  193. Notes:
  194. Allocate an address from the DHCP server.
  195. */
  196. DWORD
  197. rasDhcpAllocateAddress(
  198. VOID
  199. )
  200. {
  201. IPADDR nboIpAddress;
  202. ADDR_INFO* pAddrInfo = NULL;
  203. DHCP_OPTION_INFO* pOptionInfo = NULL;
  204. DHCP_LEASE_INFO* pLeaseInfo = NULL;
  205. AVAIL_INDEX* pAvailIndex;
  206. time_t now = time(NULL);
  207. BOOL fEasyNet = FALSE;
  208. BOOL fPutInAvailList = FALSE;
  209. BOOL fCSEntered = FALSE;
  210. BYTE bAddress[MAX_ADAPTER_ADDRESS_LENGTH];
  211. CHAR szIpAddress[MAXIPSTRLEN + 1];
  212. CHAR* sz;
  213. PPPE_MESSAGE PppMessage;
  214. DWORD dwErr = NO_ERROR;
  215. TraceHlp("rasDhcpAllocateAddress");
  216. dwErr = GetPreferredAdapterInfo(&nboIpAddress, NULL, NULL, NULL, NULL,
  217. bAddress);
  218. if (NO_ERROR != dwErr)
  219. {
  220. // There is probably no NIC on the machine
  221. nboIpAddress = htonl(INADDR_LOOPBACK);
  222. }
  223. pAddrInfo = LocalAlloc(LPTR, sizeof(ADDR_INFO));
  224. if (pAddrInfo == NULL)
  225. {
  226. dwErr = GetLastError();
  227. TraceHlp("LocalAlloc failed and returned %d", dwErr);
  228. goto LDone;
  229. }
  230. // Initialize the structure.
  231. rasDhcpInitializeAddrInfo(pAddrInfo, bAddress, &fPutInAvailList);
  232. // Call DHCP to allocate an IP address.
  233. dwErr = PDhcpLeaseIpAddress(
  234. ntohl(nboIpAddress),
  235. &pAddrInfo->ai_LeaseInfo.ClientUID,
  236. 0,
  237. NULL,
  238. &pLeaseInfo,
  239. &pOptionInfo);
  240. if (ERROR_SUCCESS != dwErr)
  241. {
  242. pLeaseInfo = NULL;
  243. pOptionInfo = NULL;
  244. TraceHlp("DhcpLeaseIpAddress failed and returned %d", dwErr);
  245. goto LDone;
  246. }
  247. // Copy stuff into the pAddrInfo structure
  248. pAddrInfo->ai_LeaseInfo.IpAddress = pLeaseInfo->IpAddress;
  249. pAddrInfo->ai_LeaseInfo.SubnetMask = pLeaseInfo->SubnetMask;
  250. pAddrInfo->ai_LeaseInfo.DhcpServerAddress = pLeaseInfo->DhcpServerAddress;
  251. pAddrInfo->ai_LeaseInfo.Lease = pLeaseInfo->Lease;
  252. pAddrInfo->ai_LeaseInfo.LeaseObtained = pLeaseInfo->LeaseObtained;
  253. pAddrInfo->ai_LeaseInfo.T1Time = pLeaseInfo->T1Time;
  254. pAddrInfo->ai_LeaseInfo.T2Time = pLeaseInfo->T2Time;
  255. pAddrInfo->ai_LeaseInfo.LeaseExpires = pLeaseInfo->LeaseExpires;
  256. EnterCriticalSection(&RasDhcpCriticalSection);
  257. fCSEntered = TRUE;
  258. if (-1 == (DWORD)(pLeaseInfo->DhcpServerAddress))
  259. {
  260. fEasyNet = TRUE;
  261. if (!RasDhcpUsingEasyNet)
  262. {
  263. dwErr = E_FAIL;
  264. TraceHlp("Not accepting any more EasyNet addresses");
  265. goto LDone;
  266. }
  267. AbcdSzFromIpAddress(htonl(pLeaseInfo->IpAddress), szIpAddress);
  268. sz = szIpAddress;
  269. LogEvent(EVENTLOG_WARNING_TYPE, ROUTERLOG_AUTONET_ADDRESS, 1,
  270. (CHAR**)&sz);
  271. // We undo this call to RasTcpSetProxyArp in rasDhcpDeleteLists.
  272. RasTcpSetProxyArp(htonl(pLeaseInfo->IpAddress), TRUE);
  273. }
  274. else
  275. {
  276. if (RasDhcpUsingEasyNet)
  277. {
  278. rasDhcpDeleteLists();
  279. // We have already used up index 0 to get this address
  280. RasDhcpNextIndex = 1;
  281. RasDhcpUsingEasyNet = FALSE;
  282. PppMessage.dwMsgId = PPPEMSG_IpAddressLeaseExpired;
  283. PppMessage.ExtraInfo.IpAddressLeaseExpired.nboIpAddr = 0;
  284. SendPPPMessageToEngine(&PppMessage);
  285. }
  286. if (NULL != PEnableDhcpInformServer)
  287. {
  288. // Redirect DHCP inform packets to this server.
  289. PEnableDhcpInformServer(htonl(pLeaseInfo->DhcpServerAddress));
  290. }
  291. }
  292. pAddrInfo->ai_Next = RasDhcpFreePool;
  293. RasDhcpFreePool = pAddrInfo;
  294. if (0 < RasDhcpNumReqAddrs)
  295. {
  296. // We need one less address now.
  297. RasDhcpNumReqAddrs--;
  298. }
  299. RasDhcpNumAddrsAlloced++;
  300. TraceHlp("Allocated address 0x%x using 0x%x, timer %ld%s",
  301. pAddrInfo->ai_LeaseInfo.IpAddress,
  302. nboIpAddress,
  303. pAddrInfo->ai_LeaseInfo.T1Time - now,
  304. fEasyNet ? ", EasyNet" : "");
  305. if (!fEasyNet)
  306. {
  307. // Start timer for lease renewal
  308. RasDhcpTimerSchedule(
  309. &pAddrInfo->ai_Timer,
  310. (LONG)(pAddrInfo->ai_LeaseInfo.T1Time - now),
  311. rasDhcpRenewLease);
  312. }
  313. LDone:
  314. if (fCSEntered)
  315. {
  316. LeaveCriticalSection(&RasDhcpCriticalSection);
  317. }
  318. if (NO_ERROR != dwErr)
  319. {
  320. if (fPutInAvailList)
  321. {
  322. pAvailIndex = LocalAlloc(LPTR, sizeof(AVAIL_INDEX));
  323. if (NULL == pAvailIndex)
  324. {
  325. TraceHlp("Couldn't put index %d in the avail list. "
  326. "Out of memory", pAddrInfo->ai_ClientUIDWords[3]);
  327. }
  328. else
  329. {
  330. EnterCriticalSection(&RasDhcpCriticalSection);
  331. pAvailIndex->dwIndex = pAddrInfo->ai_ClientUIDWords[3];
  332. pAvailIndex->pNext = RasDhcpAvailIndexes;
  333. RasDhcpAvailIndexes = pAvailIndex;
  334. LeaveCriticalSection(&RasDhcpCriticalSection);
  335. }
  336. }
  337. LocalFree(pAddrInfo);
  338. }
  339. LocalFree(pLeaseInfo);
  340. LocalFree(pOptionInfo);
  341. return(dwErr);
  342. }
  343. /*
  344. Returns:
  345. VOID
  346. Notes:
  347. Renew the lease on an address with the DHCP server. This is also called by
  348. the timer thread when the its time to renew the lease.
  349. */
  350. VOID
  351. rasDhcpRenewLease(
  352. IN HANDLE rasDhcpTimerShutdown,
  353. IN TIMERLIST* pTimer
  354. )
  355. {
  356. IPADDR nboIpAddress;
  357. ADDR_INFO* pAddrInfo;
  358. ADDR_INFO** ppAddrInfo;
  359. DHCP_OPTION_INFO* pOptionInfo = NULL;
  360. AVAIL_INDEX* pAvailIndex;
  361. time_t now = time(NULL);
  362. IPADDR nboIpAddrTemp = 0;
  363. PPPE_MESSAGE PppMessage;
  364. BOOL fNeedToRenew;
  365. DWORD dwErr;
  366. TraceHlp("rasDhcpRenewLease");
  367. dwErr = GetPreferredAdapterInfo(&nboIpAddress, NULL, NULL, NULL, NULL,
  368. NULL);
  369. if (NO_ERROR != dwErr)
  370. {
  371. TraceHlp("Couldn't get a NIC IP Address. Unable to renew lease");
  372. goto LDone;
  373. }
  374. EnterCriticalSection(&RasDhcpCriticalSection);
  375. pAddrInfo = CONTAINING_RECORD(pTimer, ADDR_INFO, ai_Timer);
  376. TraceHlp("address 0x%x", pAddrInfo->ai_LeaseInfo.IpAddress);
  377. pAddrInfo->ai_Flags |= AI_FLAG_RENEW;
  378. fNeedToRenew = rasDhcpNeedToRenewLease(pAddrInfo);
  379. LeaveCriticalSection(&RasDhcpCriticalSection);
  380. /*
  381. A race condition can occur if a thread other than this thread (the timer
  382. thread) calls rasDhcpDeleteLists when we are here. rasDhcpAllocateAddress
  383. calls rasDhcpDeleteLists, but only the timer thread calls
  384. rasDhcpAllocateAddress. RasDhcpUninitialize also calls rasDhcpDeleteLists,
  385. but it calls RasDhcpTimerUninitialize first. Before RasDhcpTimerUninitialize
  386. returns, the timer thread exits, so it is impossible for us to be here.
  387. In the worst case, DhcpRenewIpAddressLease might take up to 60 sec. In the
  388. average case, it is 2-10 sec.
  389. */
  390. if (fNeedToRenew)
  391. {
  392. dwErr = PDhcpRenewIpAddressLease(
  393. ntohl(nboIpAddress),
  394. &pAddrInfo->ai_LeaseInfo,
  395. NULL,
  396. &pOptionInfo);
  397. }
  398. else
  399. {
  400. // Simulate not being able to renew
  401. dwErr = ERROR_ACCESS_DENIED;
  402. }
  403. EnterCriticalSection(&RasDhcpCriticalSection);
  404. if (dwErr == ERROR_SUCCESS)
  405. {
  406. pAddrInfo->ai_Flags &= ~AI_FLAG_RENEW;
  407. TraceHlp("success for address 0x%x, resched timer %ld",
  408. pAddrInfo->ai_LeaseInfo.IpAddress,
  409. pAddrInfo->ai_LeaseInfo.T1Time - now);
  410. // Start timer to renew
  411. RasDhcpTimerSchedule(
  412. pTimer,
  413. (LONG)(pAddrInfo->ai_LeaseInfo.T1Time - now),
  414. rasDhcpRenewLease);
  415. }
  416. else if ( (ERROR_ACCESS_DENIED == dwErr)
  417. || (now > pAddrInfo->ai_LeaseInfo.T2Time))
  418. {
  419. TraceHlp("failed for address 0x%x", pAddrInfo->ai_LeaseInfo.IpAddress);
  420. if (fNeedToRenew)
  421. {
  422. RasDhcpNumReqAddrs++;
  423. }
  424. if (RasDhcpNumAddrsAlloced > 0)
  425. {
  426. RasDhcpNumAddrsAlloced--;
  427. }
  428. // Cannot renew lease. Blow this away.
  429. nboIpAddrTemp = htonl(pAddrInfo->ai_LeaseInfo.IpAddress);
  430. // Unlink this structure from the list and cleanup
  431. ppAddrInfo = (pAddrInfo->ai_Flags & AI_FLAG_IN_USE) ?
  432. &RasDhcpAllocPool : &RasDhcpFreePool;
  433. for (; *ppAddrInfo != NULL; ppAddrInfo = &(*ppAddrInfo)->ai_Next)
  434. {
  435. if (pAddrInfo == *ppAddrInfo)
  436. {
  437. pAvailIndex = LocalAlloc(LPTR, sizeof(AVAIL_INDEX));
  438. if (NULL == pAvailIndex)
  439. {
  440. TraceHlp("Couldn't put index %d in the avail list. "
  441. "Out of memory", pAddrInfo->ai_ClientUIDWords[3]);
  442. }
  443. else
  444. {
  445. pAvailIndex->dwIndex = pAddrInfo->ai_ClientUIDWords[3];
  446. pAvailIndex->pNext = RasDhcpAvailIndexes;
  447. RasDhcpAvailIndexes = pAvailIndex;
  448. }
  449. *ppAddrInfo = pAddrInfo->ai_Next;
  450. break;
  451. }
  452. }
  453. rasDhcpFreeAddress(pAddrInfo);
  454. LocalFree(pAddrInfo);
  455. PppMessage.dwMsgId = PPPEMSG_IpAddressLeaseExpired;
  456. PppMessage.ExtraInfo.IpAddressLeaseExpired.nboIpAddr = nboIpAddrTemp;
  457. SendPPPMessageToEngine(&PppMessage);
  458. }
  459. else
  460. {
  461. TraceHlp("Error %d. Will try again later.", dwErr);
  462. TraceHlp("Seconds left before expiry: %d",
  463. pAddrInfo->ai_LeaseInfo.T2Time - now);
  464. // Could not contact the Dhcp Server, retry in a little bit
  465. RasDhcpTimerSchedule(pTimer, RETRY_TIME, rasDhcpRenewLease);
  466. }
  467. LeaveCriticalSection(&RasDhcpCriticalSection);
  468. LDone:
  469. LocalFree(pOptionInfo);
  470. }
  471. /*
  472. Notes:
  473. We call DHCP to release the address.
  474. */
  475. VOID
  476. rasDhcpFreeAddress(
  477. IN ADDR_INFO* pAddrInfo
  478. )
  479. {
  480. IPADDR nboIpAddress;
  481. DWORD dwErr;
  482. RTASSERT(NULL != pAddrInfo);
  483. TraceHlp("rasDhcpFreeAddress 0x%x", pAddrInfo->ai_LeaseInfo.IpAddress);
  484. dwErr = GetPreferredAdapterInfo(&nboIpAddress, NULL, NULL, NULL, NULL,
  485. NULL);
  486. if (NO_ERROR != dwErr)
  487. {
  488. TraceHlp("Couldn't get a NIC IP Address. Unable to release address");
  489. goto LDone;
  490. }
  491. // Call DHCP to release the address.
  492. dwErr = PDhcpReleaseIpAddressLease(ntohl(nboIpAddress),
  493. &pAddrInfo->ai_LeaseInfo);
  494. if (ERROR_SUCCESS != dwErr)
  495. {
  496. TraceHlp("DhcpReleaseIpAddressLease failed and returned %d", dwErr);
  497. }
  498. if (RasDhcpNumAddrsAlloced > 0)
  499. {
  500. RasDhcpNumAddrsAlloced--;
  501. }
  502. LDone:
  503. return;
  504. }
  505. /*
  506. Returns:
  507. VOID
  508. Notes:
  509. If we don't have enough addresses (because lease renewal failed or we were
  510. unable to allocate), try to acquire some. The argument pTimer is not used.
  511. */
  512. VOID
  513. rasDhcpMonitorAddresses(
  514. IN HANDLE rasDhcpTimerShutdown,
  515. IN TIMERLIST* pTimer
  516. )
  517. {
  518. DWORD dwErr;
  519. while (TRUE)
  520. {
  521. EnterCriticalSection(&RasDhcpCriticalSection);
  522. if (0 == RasDhcpNumReqAddrs)
  523. {
  524. LeaveCriticalSection(&RasDhcpCriticalSection);
  525. break;
  526. }
  527. if (RasDhcpNumAddrsAlloced >= rasDhcpMaxAddrsToAllocate())
  528. {
  529. RasDhcpNumReqAddrs = 0;
  530. LeaveCriticalSection(&RasDhcpCriticalSection);
  531. break;
  532. }
  533. LeaveCriticalSection(&RasDhcpCriticalSection);
  534. dwErr = rasDhcpAllocateAddress();
  535. if (NO_ERROR != dwErr)
  536. {
  537. break;
  538. }
  539. if (WaitForSingleObject(rasDhcpTimerShutdown, 10) != WAIT_TIMEOUT)
  540. {
  541. break;
  542. }
  543. }
  544. // Start timer to monitor if we are running short on addresses etc.
  545. RasDhcpTimerSchedule(
  546. &RasDhcpMonitorTimer,
  547. 0,
  548. rasDhcpMonitorAddresses);
  549. }
  550. /*
  551. Returns:
  552. VOID
  553. Notes:
  554. */
  555. VOID
  556. rasDhcpInitializeAddrInfo(
  557. IN OUT ADDR_INFO* pNewAddrInfo,
  558. IN BYTE* pbAddress,
  559. OUT BOOL* pfPutInAvailList
  560. )
  561. {
  562. DWORD dwIndex;
  563. AVAIL_INDEX* pAvailIndex;
  564. RTASSERT(NULL != pNewAddrInfo);
  565. TraceHlp("rasDhcpInitializeAddrInfo");
  566. EnterCriticalSection(&RasDhcpCriticalSection);
  567. // ClientUIDBase is a combination of RAS_PREPEND (4 chars),
  568. // MAC address (8 chars), Index (4 chars)
  569. if (RasDhcpUsingEasyNet)
  570. {
  571. dwIndex = 0;
  572. }
  573. else
  574. {
  575. *pfPutInAvailList = TRUE;
  576. if (NULL != RasDhcpAvailIndexes)
  577. {
  578. pAvailIndex = RasDhcpAvailIndexes;
  579. dwIndex = pAvailIndex->dwIndex;
  580. RasDhcpAvailIndexes = RasDhcpAvailIndexes->pNext;
  581. LocalFree(pAvailIndex);
  582. }
  583. else
  584. {
  585. dwIndex = RasDhcpNextIndex++;
  586. }
  587. }
  588. TraceHlp("dwIndex = %d", dwIndex);
  589. strcpy(pNewAddrInfo->ai_ClientUIDBuf, RAS_PREPEND);
  590. memcpy(pNewAddrInfo->ai_ClientUIDBuf + strlen(RAS_PREPEND),
  591. pbAddress, MAX_ADAPTER_ADDRESS_LENGTH);
  592. pNewAddrInfo->ai_ClientUIDWords[3] = dwIndex;
  593. pNewAddrInfo->ai_LeaseInfo.ClientUID.ClientUID =
  594. pNewAddrInfo->ai_ClientUIDBuf;
  595. pNewAddrInfo->ai_LeaseInfo.ClientUID.ClientUIDLength =
  596. sizeof(pNewAddrInfo->ai_ClientUIDBuf);
  597. LeaveCriticalSection(&RasDhcpCriticalSection);
  598. }
  599. /*
  600. Returns:
  601. VOID
  602. Notes:
  603. Delete proxy arp entries for easy net addresses.
  604. */
  605. VOID
  606. rasDhcpDeleteLists(
  607. VOID
  608. )
  609. {
  610. ADDR_INFO* pAddrInfo;
  611. ADDR_INFO* pTempAddrInfo;
  612. ADDR_INFO* pList[2] = {RasDhcpAllocPool, RasDhcpFreePool};
  613. AVAIL_INDEX* pAvailIndex;
  614. AVAIL_INDEX* pTempAvailIndex;
  615. DWORD dwIndex;
  616. TraceHlp("rasDhcpDeleteLists");
  617. EnterCriticalSection(&RasDhcpCriticalSection);
  618. for (dwIndex = 0; dwIndex < 2; dwIndex++)
  619. {
  620. pAddrInfo = pList[dwIndex];
  621. while (pAddrInfo != NULL)
  622. {
  623. if (RasDhcpUsingEasyNet)
  624. {
  625. RasTcpSetProxyArp(htonl(pAddrInfo->ai_LeaseInfo.IpAddress),
  626. FALSE);
  627. }
  628. else
  629. {
  630. rasDhcpFreeAddress(pAddrInfo);
  631. }
  632. pTempAddrInfo = pAddrInfo;
  633. pAddrInfo = pAddrInfo->ai_Next;
  634. LocalFree(pTempAddrInfo);
  635. }
  636. }
  637. for (pAvailIndex = RasDhcpAvailIndexes; NULL != pAvailIndex;)
  638. {
  639. pTempAvailIndex = pAvailIndex;
  640. pAvailIndex = pAvailIndex->pNext;
  641. LocalFree(pTempAvailIndex);
  642. }
  643. RasDhcpAllocPool = NULL;
  644. RasDhcpFreePool = NULL;
  645. RasDhcpAvailIndexes = NULL;
  646. if (NtProductWinNt == RasDhcpNtProductType)
  647. {
  648. RasDhcpNumReqAddrs = 2;
  649. }
  650. else
  651. {
  652. RasDhcpNumReqAddrs = HelperRegVal.dwChunkSize;
  653. }
  654. RasDhcpNextIndex = 0;
  655. RasDhcpNumAddrsAlloced = 0;
  656. LeaveCriticalSection(&RasDhcpCriticalSection);
  657. }
  658. /*
  659. Returns:
  660. VOID
  661. Notes:
  662. Should we bother to renew the lease?
  663. */
  664. BOOL
  665. rasDhcpNeedToRenewLease(
  666. IN ADDR_INFO* pAddrInfo
  667. )
  668. {
  669. BOOL fRet = TRUE;
  670. DWORD dwCount = 0;
  671. ADDR_INFO* pTemp;
  672. TraceHlp("rasDhcpNeedToRenewLease");
  673. EnterCriticalSection(&RasDhcpCriticalSection);
  674. if (pAddrInfo->ai_Flags & AI_FLAG_IN_USE)
  675. {
  676. goto LDone;
  677. }
  678. // How many free addresses do we have?
  679. for (pTemp = RasDhcpFreePool; pTemp != NULL; pTemp = pTemp->ai_Next)
  680. {
  681. dwCount++;
  682. }
  683. if (dwCount > HelperRegVal.dwChunkSize)
  684. {
  685. fRet = FALSE;
  686. }
  687. LDone:
  688. TraceHlp("Need to renew: %s", fRet ? "TRUE" : "FALSE");
  689. LeaveCriticalSection(&RasDhcpCriticalSection);
  690. return(fRet);
  691. }
  692. /*
  693. Returns:
  694. The maximum number of addresses that we can get from the DHCP server.
  695. Notes:
  696. */
  697. DWORD
  698. rasDhcpMaxAddrsToAllocate(
  699. VOID
  700. )
  701. {
  702. DWORD dwErr = NO_ERROR;
  703. DWORD dwSize = 0;
  704. DWORD dwNumEntries = 0;
  705. DWORD dwRet = 0;
  706. DWORD dw;
  707. RASMAN_PORT* pRasmanPort = NULL;
  708. dwErr = RasPortEnum(NULL, NULL, &dwSize, &dwNumEntries);
  709. RTASSERT(ERROR_BUFFER_TOO_SMALL == dwErr);
  710. pRasmanPort = (RASMAN_PORT*) LocalAlloc(LPTR, dwSize);
  711. if (NULL == pRasmanPort)
  712. {
  713. // The server adapter also needs an address.
  714. dwRet = dwNumEntries + 1;
  715. goto LDone;
  716. }
  717. dwErr = RasPortEnum(NULL, (BYTE*)pRasmanPort, &dwSize, &dwNumEntries);
  718. if (NO_ERROR != dwErr)
  719. {
  720. // The server adapter also needs an address.
  721. dwRet = dwNumEntries + 1;
  722. goto LDone;
  723. }
  724. for (dw = 0, dwRet = 0; dw < dwNumEntries; dw++)
  725. {
  726. if ( (pRasmanPort[dw].P_ConfiguredUsage & CALL_IN)
  727. || (pRasmanPort[dw].P_ConfiguredUsage & CALL_ROUTER))
  728. {
  729. dwRet++;
  730. }
  731. }
  732. // The server adapter also needs an address.
  733. dwRet++;
  734. LDone:
  735. LocalFree(pRasmanPort);
  736. return(dwRet);
  737. }