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.

1222 lines
37 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. leaseapi.c
  5. Abstract:
  6. This file contains apis that obtains/releases ip address from a
  7. dhcpserver. These apis can be called by any apps that needs an ip
  8. address for lease.
  9. Author:
  10. Madan Appiah (madana) 30-Nov-1993
  11. Environment:
  12. User Mode - Win32
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #include "dhcpglobal.h"
  17. #include <dhcploc.h>
  18. #include <dhcppro.h>
  19. #include <align.h>
  20. #include <dhcpcapi.h>
  21. #include <iphlpapi.h>
  22. #define DEFAULT_RAS_CLASS "RRAS.Microsoft"
  23. //
  24. // Helper routine
  25. //
  26. VOID
  27. GetHardwareAddressForIpAddress(
  28. IN ULONG IpAddress,
  29. IN OUT LPBYTE Buf,
  30. IN OUT PULONG BufSize
  31. )
  32. /*++
  33. Routine Description:
  34. This routine calls into iphlpapi to try to figure out the hardware
  35. address for an adapter with the given Ip address..
  36. In case of failure, it sets the BufSize to zero.
  37. Arguments:
  38. IpAddress -- N/W order IpAddress of context for which h/w addr is needed.
  39. Buf -- buffer to fill hardware address
  40. BufSize -- input size of buffer, and on output how much of buffer is
  41. used.
  42. --*/
  43. {
  44. MIB_IPADDRTABLE *AddrTable;
  45. MIB_IFTABLE *IfTable;
  46. ULONG Error, i, Index, OldBufSize;
  47. ULONG AllocateAndGetIpAddrTableFromStack(
  48. MIB_IPADDRTABLE **, BOOL, HANDLE, ULONG
  49. );
  50. ULONG AllocateAndGetIfTableFromStack(
  51. MIB_IFTABLE **, BOOL, HANDLE, ULONG, BOOL
  52. );
  53. IpAddress = ntohl(IpAddress);
  54. OldBufSize = (*BufSize);
  55. (*BufSize) = 0;
  56. AddrTable = NULL;
  57. IfTable = NULL;
  58. do {
  59. Error = AllocateAndGetIpAddrTableFromStack(
  60. &AddrTable,
  61. FALSE,
  62. GetProcessHeap(),
  63. 0
  64. );
  65. if( ERROR_SUCCESS != Error ) break;
  66. Error = AllocateAndGetIfTableFromStack(
  67. &IfTable,
  68. FALSE,
  69. GetProcessHeap(),
  70. 0,
  71. FALSE
  72. );
  73. if( ERROR_SUCCESS != Error ) break;
  74. //
  75. // Got both tables.. Now walk the ip addr table to get the index.
  76. //
  77. for( i = 0; i < AddrTable->dwNumEntries ; i ++ ) {
  78. if( AddrTable->table[i].dwAddr == IpAddress ) break;
  79. }
  80. if( i >= AddrTable->dwNumEntries ) break;
  81. Index = AddrTable->table[i].dwIndex;
  82. //
  83. // Now walk the iftable to find the hwaddr entyr.
  84. //
  85. for( i = 0; i < IfTable->dwNumEntries ; i ++ ) {
  86. if( IfTable->table[i].dwIndex == Index ) {
  87. break;
  88. }
  89. }
  90. if( i >= IfTable->dwNumEntries ) break;
  91. //
  92. // Copy the hw address if there is space.
  93. //
  94. if( OldBufSize <= IfTable->table[i].dwPhysAddrLen ) break;
  95. *BufSize = IfTable->table[i].dwPhysAddrLen;
  96. RtlCopyMemory( Buf, IfTable->table[i].bPhysAddr, *BufSize );
  97. //
  98. // done
  99. //
  100. } while ( 0 );
  101. if( NULL != AddrTable ) HeapFree( GetProcessHeap(), 0, AddrTable );
  102. if( NULL != IfTable ) HeapFree( GetProcessHeap(), 0, IfTable );
  103. return ;
  104. }
  105. ULONG
  106. GetSeed(
  107. VOID
  108. )
  109. /*++
  110. Routine Description:
  111. This routine returns a rand number seed that can be used on
  112. any thread... (If the routine is called on multiple threads,
  113. it tries to make sure that the same number isn't returned in
  114. different threads).
  115. --*/
  116. {
  117. static LONG Seed = 0;
  118. LONG OldSeed;
  119. OldSeed = InterlockedIncrement(&Seed) - 1;
  120. if( 0 == OldSeed ) {
  121. OldSeed = Seed = (LONG) time(NULL);
  122. }
  123. srand((OldSeed << 16) + (LONG)time(NULL));
  124. OldSeed = (rand() << 16) + (rand());
  125. Seed = (rand() << 16) + (rand());
  126. return OldSeed;
  127. }
  128. DWORD
  129. DhcpLeaseIpAddressEx(
  130. IN DWORD AdapterIpAddress,
  131. IN LPDHCP_CLIENT_UID ClientUID,
  132. IN DWORD DesiredIpAddress OPTIONAL,
  133. IN OUT LPDHCP_OPTION_LIST OptionList,
  134. OUT LPDHCP_LEASE_INFO *LeaseInfo,
  135. IN OUT LPDHCP_OPTION_INFO *OptionInfo,
  136. IN LPBYTE ClassId OPTIONAL,
  137. IN ULONG ClassIdLen
  138. )
  139. /*++
  140. Routine Description:
  141. This api obtains an IP address lease from a dhcp server. The
  142. caller should specify the client uid and a desired ip address.
  143. The client uid must be globally unique. Set the desired ip address
  144. to zero if you can accept any ip address. Otherwise this api will
  145. try to obtain the ip address you have specified, but not guaranteed.
  146. The caller may optionally requtest additional option info from the
  147. dhcp server, The caller should specify the list in OptionList
  148. parameter and the api will return the available option data in
  149. OptionInfo structure.
  150. ?? Option retrival is not implemented in the first phase. This
  151. requires several modification in the dhcp client code.
  152. WSAStartup must haave been successfully called before this function
  153. can be called.
  154. Arguments:
  155. AdapterIpAddress - IpAddress of the adapter. On a multi-homed
  156. machined this specifies the subnet from which an address is
  157. requested. This value can be set to zero if the machine is a
  158. non-multi-homed machine or you like to get ip address from any
  159. of the subnets. This must be network byte order..
  160. ClientUID - pointer to a client UID structure.
  161. DesiredIpAddress - the ip address you prefer.
  162. OptionList - list of option ids.
  163. LeaseInfo - pointer to a location where the lease info structure
  164. pointer is retured. The caller should free up this structure
  165. after use.
  166. OptionInfo - pointer to a location where the option info structure
  167. pointer is returned. The caller should free up this structure
  168. after use.
  169. ClassId - a byte sequence for user class
  170. ClassIdLen - number of bytes present in ClassId
  171. Return Value:
  172. Windows Error.
  173. --*/
  174. {
  175. DWORD Error;
  176. PDHCP_CONTEXT DhcpContext = NULL;
  177. ULONG DhcpContextSize;
  178. PLOCAL_CONTEXT_INFO LocalInfo = NULL;
  179. LPVOID Ptr;
  180. DHCP_OPTIONS DhcpOptions;
  181. LPDHCP_LEASE_INFO LocalLeaseInfo = NULL;
  182. time_t LeaseObtained;
  183. DWORD T1, T2, Lease;
  184. BYTE DefaultParamRequests[] = { 0x2E, 0x2C, 0x0F, 0x01, 0x03, 0x06, 0x2F };
  185. DWORD nDefaultParamRequests = sizeof(DefaultParamRequests);
  186. ULONG HwAddrSize;
  187. BYTE HwAddrBuf[200];
  188. BOOL fAutoConfigure = TRUE;
  189. DHCP_OPTION ParamRequestList = {
  190. { NULL, NULL /* List entry */},
  191. OPTION_PARAMETER_REQUEST_LIST,
  192. FALSE /* not a vendor specific option */,
  193. NULL,
  194. 0 /* no class id */,
  195. 0 /* expiration time useless */,
  196. DefaultParamRequests,
  197. nDefaultParamRequests
  198. };
  199. if( NULL == ClassId && 0 != ClassIdLen || 0 == ClassIdLen && NULL != ClassId ) {
  200. return ERROR_INVALID_PARAMETER;
  201. }
  202. Error = DhcpCommonInit();
  203. if( ERROR_SUCCESS != Error ) return Error;
  204. HwAddrSize = 0;
  205. if( INADDR_ANY != AdapterIpAddress
  206. && INADDR_LOOPBACK != AdapterIpAddress ) {
  207. HwAddrSize = sizeof(HwAddrBuf);
  208. GetHardwareAddressForIpAddress( AdapterIpAddress, HwAddrBuf, &HwAddrSize );
  209. }
  210. if( 0 == HwAddrSize ) {
  211. HwAddrSize = ClientUID->ClientUIDLength;
  212. if( HwAddrSize > sizeof(HwAddrBuf) ) return ERROR_INVALID_DATA;
  213. RtlCopyMemory(HwAddrBuf, ClientUID->ClientUID, HwAddrSize );
  214. }
  215. DhcpContextSize = // allocate memory for dhcpcontext, in one blob
  216. ROUND_UP_COUNT(sizeof(DHCP_CONTEXT), ALIGN_WORST) +
  217. ROUND_UP_COUNT(ClientUID->ClientUIDLength, ALIGN_WORST) +
  218. ROUND_UP_COUNT(HwAddrSize, ALIGN_WORST ) +
  219. ROUND_UP_COUNT(sizeof(LOCAL_CONTEXT_INFO), ALIGN_WORST) +
  220. ROUND_UP_COUNT(DHCP_RECV_MESSAGE_SIZE, ALIGN_WORST);
  221. Ptr = DhcpAllocateMemory( DhcpContextSize );
  222. if ( Ptr == NULL ) return( ERROR_NOT_ENOUGH_MEMORY );
  223. memset(Ptr, 0, DhcpContextSize);
  224. DhcpContext = Ptr; // align up the pointers
  225. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + sizeof(DHCP_CONTEXT), ALIGN_WORST);
  226. DhcpContext->ClientIdentifier.pbID = Ptr;
  227. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + ClientUID->ClientUIDLength, ALIGN_WORST);
  228. DhcpContext->HardwareAddress = Ptr;
  229. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + HwAddrSize, ALIGN_WORST);
  230. DhcpContext->LocalInformation = Ptr;
  231. LocalInfo = Ptr;
  232. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + sizeof(LOCAL_CONTEXT_INFO), ALIGN_WORST);
  233. DhcpContext->MessageBuffer = Ptr;
  234. //
  235. // initialize fields.
  236. //
  237. DhcpContext->HardwareAddressType = HARDWARE_TYPE_10MB_EITHERNET;
  238. DhcpContext->HardwareAddressLength = HwAddrSize;
  239. DhcpContext->RefCount = 1 ;
  240. RtlCopyMemory(DhcpContext->HardwareAddress,HwAddrBuf, HwAddrSize);
  241. DhcpContext->ClientIdentifier.cbID = ClientUID->ClientUIDLength;
  242. DhcpContext->ClientIdentifier.bType = HARDWARE_TYPE_10MB_EITHERNET;
  243. DhcpContext->ClientIdentifier.fSpecified = TRUE;
  244. RtlCopyMemory(
  245. DhcpContext->ClientIdentifier.pbID,
  246. ClientUID->ClientUID,
  247. ClientUID->ClientUIDLength
  248. );
  249. DhcpContext->IpAddress = 0;
  250. DhcpContext->SubnetMask = DhcpDefaultSubnetMask(0);
  251. DhcpContext->DhcpServerAddress = 0xFFFFFFFF;
  252. DhcpContext->DesiredIpAddress = DesiredIpAddress;
  253. DhcpContext->Lease = 0;
  254. DhcpContext->LeaseObtained = 0;
  255. DhcpContext->T1Time = 0;
  256. DhcpContext->T2Time = 0;
  257. DhcpContext->LeaseExpires = 0;
  258. INIT_STATE(DhcpContext);
  259. AUTONET_ENABLED(DhcpContext);
  260. APICTXT_ENABLED(DhcpContext); // mark the context as being created by the API
  261. DhcpContext->IPAutoconfigurationContext.Address = 0;
  262. DhcpContext->IPAutoconfigurationContext.Subnet = inet_addr(DHCP_IPAUTOCONFIGURATION_DEFAULT_SUBNET);
  263. DhcpContext->IPAutoconfigurationContext.Mask = inet_addr(DHCP_IPAUTOCONFIGURATION_DEFAULT_MASK);
  264. DhcpContext->IPAutoconfigurationContext.Seed = GetSeed();
  265. InitializeListHead(&DhcpContext->RecdOptionsList);
  266. InitializeListHead(&DhcpContext->SendOptionsList);
  267. InsertHeadList(&DhcpContext->SendOptionsList, &ParamRequestList.OptionList);
  268. DhcpContext->ClassId = ClassId;
  269. DhcpContext->ClassIdLength = ClassIdLen;
  270. //
  271. // copy local info.
  272. //
  273. //
  274. // unused portion of the local info.
  275. //
  276. LocalInfo->IpInterfaceContext = 0xFFFFFFFF;
  277. LocalInfo->AdapterName= NULL;
  278. //LocalInfo->DeviceName= NULL;
  279. LocalInfo->NetBTDeviceName= NULL;
  280. LocalInfo->RegistryKey= NULL;
  281. LocalInfo->DefaultGatewaysSet = FALSE;
  282. // used portion of the local info.
  283. LocalInfo->Socket = INVALID_SOCKET;
  284. // if AdapterIpAddress is loopback addr then, the client just wants us to
  285. // fabricate autonet address. The client can do this if there is no interface
  286. // available on this machine to autonet on.
  287. if (INADDR_LOOPBACK == AdapterIpAddress) {
  288. DhcpContext->IpAddress = GrandHashing(
  289. DhcpContext->HardwareAddress,
  290. DhcpContext->HardwareAddressLength,
  291. &DhcpContext->IPAutoconfigurationContext.Seed,
  292. DhcpContext->IPAutoconfigurationContext.Mask,
  293. DhcpContext->IPAutoconfigurationContext.Subnet
  294. );
  295. DhcpContext->SubnetMask = DhcpContext->IPAutoconfigurationContext.Mask;
  296. ACQUIRED_AUTO_ADDRESS(DhcpContext);
  297. } else {
  298. //
  299. // open socket now. receive any.
  300. //
  301. Error = InitializeDhcpSocket(&LocalInfo->Socket,ntohl( AdapterIpAddress ), IS_APICTXT_ENABLED(DhcpContext) );
  302. if( Error != ERROR_SUCCESS ) {
  303. goto Cleanup;
  304. }
  305. //
  306. // now discover an ip address.
  307. //
  308. Error = ObtainInitialParameters( DhcpContext, &DhcpOptions, &fAutoConfigure );
  309. if( ERROR_SEM_TIMEOUT == Error ) {
  310. DhcpPrint((DEBUG_PROTOCOL, "RAS: No server found, trying to autoconfigure\n"));
  311. if( fAutoConfigure ) {
  312. Error = DhcpPerformIPAutoconfiguration(DhcpContext);
  313. }
  314. if( ERROR_SUCCESS != Error ) {
  315. DhcpPrint((DEBUG_ERRORS, "Autoconfiguration for RAS failed: 0x%lx\n", Error));
  316. }
  317. }
  318. //
  319. // no matter what happens here, freeup the list of options as that is not really needed..
  320. //
  321. LOCK_OPTIONS_LIST();
  322. (void) DhcpDestroyOptionsList(&DhcpContext->RecdOptionsList, &DhcpGlobalClassesList);
  323. UNLOCK_OPTIONS_LIST();
  324. if( Error != ERROR_SUCCESS ) {
  325. goto Cleanup;
  326. }
  327. }
  328. //
  329. // allocate memory for the return client info structure.
  330. //
  331. LocalLeaseInfo = DhcpAllocateMemory( sizeof(DHCP_LEASE_INFO) );
  332. if( LocalLeaseInfo == NULL ) {
  333. Error = ERROR_NOT_ENOUGH_MEMORY;
  334. goto Cleanup;
  335. }
  336. LocalLeaseInfo->ClientUID = *ClientUID;
  337. LocalLeaseInfo->IpAddress = ntohl( DhcpContext->IpAddress );
  338. if( IS_ADDRESS_AUTO(DhcpContext) ) {
  339. LocalLeaseInfo->SubnetMask = ntohl(DhcpContext->SubnetMask);
  340. LocalLeaseInfo->DhcpServerAddress = ntohl(DhcpContext->DhcpServerAddress);
  341. LocalLeaseInfo->Lease = DhcpContext->Lease;
  342. LocalLeaseInfo->LeaseObtained = DhcpContext->LeaseObtained;
  343. LocalLeaseInfo->T1Time = DhcpContext->T1Time;
  344. LocalLeaseInfo->T2Time = DhcpContext->T2Time;
  345. LocalLeaseInfo->LeaseExpires = DhcpContext->LeaseExpires;
  346. Error = ERROR_SUCCESS;
  347. *LeaseInfo = LocalLeaseInfo;
  348. goto Cleanup;
  349. }
  350. if ( DhcpOptions.SubnetMask != NULL ) {
  351. LocalLeaseInfo->SubnetMask= ntohl( *DhcpOptions.SubnetMask );
  352. }
  353. else {
  354. LocalLeaseInfo->SubnetMask =
  355. ntohl(DhcpDefaultSubnetMask( DhcpContext->IpAddress ));
  356. }
  357. LocalLeaseInfo->DhcpServerAddress =
  358. ntohl( DhcpContext->DhcpServerAddress );
  359. if ( DhcpOptions.LeaseTime != NULL) {
  360. LocalLeaseInfo->Lease = ntohl( *DhcpOptions.LeaseTime );
  361. } else {
  362. LocalLeaseInfo->Lease = DHCP_MINIMUM_LEASE;
  363. }
  364. Lease = LocalLeaseInfo->Lease;
  365. LeaseObtained = time( NULL );
  366. LocalLeaseInfo->LeaseObtained = LeaseObtained;
  367. T1 = 0;
  368. if ( DhcpOptions.T1Time != NULL ) {
  369. T1 = ntohl( *DhcpOptions.T1Time );
  370. }
  371. T2 = 0;
  372. if ( DhcpOptions.T2Time != NULL ) {
  373. T2 = ntohl( *DhcpOptions.T2Time );
  374. }
  375. //
  376. // make sure T1 < T2 < Lease
  377. //
  378. if( (T2 == 0) || (T2 > Lease) ) {
  379. T2 = Lease * 7 / 8; // default 87.7 %.
  380. }
  381. if( (T1 == 0) || (T1 > T2) ) {
  382. T1 = (T2 > Lease / 2) ? (Lease / 2) : (T2 - 1);
  383. // default 50 %.;
  384. }
  385. LocalLeaseInfo->T1Time = LeaseObtained + T1;
  386. if ( LocalLeaseInfo->T1Time < LeaseObtained ) {
  387. LocalLeaseInfo->T1Time = INFINIT_TIME; // over flow.
  388. }
  389. LocalLeaseInfo->T2Time = LeaseObtained + T2;
  390. if ( LocalLeaseInfo->T2Time < LeaseObtained ) {
  391. LocalLeaseInfo->T2Time = INFINIT_TIME;
  392. }
  393. LocalLeaseInfo->LeaseExpires = LeaseObtained + Lease;
  394. if ( LocalLeaseInfo->LeaseExpires < LeaseObtained ) {
  395. LocalLeaseInfo->LeaseExpires = INFINIT_TIME;
  396. }
  397. *LeaseInfo = LocalLeaseInfo;
  398. Error = ERROR_SUCCESS;
  399. Cleanup:
  400. if( OptionInfo ) *OptionInfo = NULL; // not implemented.
  401. //
  402. // close socket.
  403. //
  404. if( (LocalInfo != NULL) && (LocalInfo->Socket != INVALID_SOCKET) ) {
  405. closesocket( LocalInfo->Socket );
  406. }
  407. if( DhcpContext != NULL ) {
  408. DhcpFreeMemory( DhcpContext );
  409. }
  410. if( Error != ERROR_SUCCESS ) {
  411. //
  412. // free locally allocated memory, if we aren't successful.
  413. //
  414. if( LocalLeaseInfo != NULL ) {
  415. DhcpFreeMemory( LocalLeaseInfo );
  416. *LeaseInfo = NULL;
  417. }
  418. }
  419. return( Error );
  420. }
  421. DWORD
  422. DhcpRenewIpAddressLeaseEx(
  423. DWORD AdapterIpAddress,
  424. LPDHCP_LEASE_INFO ClientLeaseInfo,
  425. LPDHCP_OPTION_LIST OptionList,
  426. LPDHCP_OPTION_INFO *OptionInfo,
  427. LPBYTE ClassId OPTIONAL,
  428. ULONG ClassIdLen
  429. )
  430. /*++
  431. Routine Description:
  432. This api renews an ip address that the client already has. When a
  433. client gets an ip address, it can use the address until the lease
  434. expires. The client should stop using the ip address after that.
  435. Also the client should renew the address after T1 time if the client
  436. is planning to use the address longer than the current lease time.
  437. WSAStartup must have been successfully called before this function
  438. can be called.
  439. Arguments:
  440. AdapterIpAddress - IpAddress of the adapter. On a multi-homed
  441. machined this specifies the subnet from which an address is
  442. renewed. This value can be set to zero if the machine is
  443. non-multi-homed machine.
  444. ClientLeaseInfo : pointer to the client lease info structure. On
  445. entry the structure should contain the information that was
  446. returned by the DhcpLeaseIpAddress or DhcpRenewIpAddressLease
  447. apis. On return this structure is updated to reflect the lease
  448. extension.
  449. OptionList - list of option ids.
  450. OptionInfo - pointer to a location where the option info structure
  451. pointer is returned. The caller should free up this structure
  452. after use.
  453. ClassId - a byte sequence for user class
  454. ClassIdLen - number of bytes present in ClassId
  455. Return Value:
  456. Windows Error.
  457. --*/
  458. {
  459. DWORD Error;
  460. PDHCP_CONTEXT DhcpContext = NULL;
  461. ULONG DhcpContextSize;
  462. PLOCAL_CONTEXT_INFO LocalInfo;
  463. LPVOID Ptr;
  464. DHCP_OPTIONS DhcpOptions;
  465. time_t LeaseObtained;
  466. DWORD T1, T2, Lease;
  467. BYTE DefaultParamRequests[] = { 0x2E, 0x2C, 0x0F, 0x01, 0x03, 0x06, 0x2F };
  468. DWORD nDefaultParamRequests = sizeof(DefaultParamRequests);
  469. LPDHCP_CLIENT_UID ClientUID = &(ClientLeaseInfo->ClientUID);
  470. ULONG HwAddrSize;
  471. BYTE HwAddrBuf[200];
  472. DHCP_OPTION ParamRequestList = {
  473. { NULL, NULL /* List entry */},
  474. OPTION_PARAMETER_REQUEST_LIST,
  475. FALSE /* not a vendor specific option */,
  476. NULL,
  477. 0 /* no class id */,
  478. 0 /* expiration time useless */,
  479. DefaultParamRequests,
  480. nDefaultParamRequests
  481. };
  482. if( NULL == ClassId && 0 != ClassIdLen || 0 == ClassIdLen && NULL != ClassId) {
  483. return ERROR_INVALID_PARAMETER;
  484. }
  485. Error = DhcpCommonInit();
  486. if( ERROR_SUCCESS != Error ) return Error;
  487. //
  488. // prepare dhcp context structure.
  489. //
  490. HwAddrSize = 0;
  491. if( INADDR_ANY != AdapterIpAddress
  492. && INADDR_LOOPBACK != AdapterIpAddress ) {
  493. HwAddrSize = sizeof(HwAddrBuf);
  494. GetHardwareAddressForIpAddress( AdapterIpAddress, HwAddrBuf, &HwAddrSize );
  495. }
  496. if( 0 == HwAddrSize ) {
  497. HwAddrSize = ClientUID->ClientUIDLength;
  498. if( HwAddrSize > sizeof(HwAddrBuf) ) return ERROR_INVALID_DATA;
  499. RtlCopyMemory(HwAddrBuf, ClientUID->ClientUID, HwAddrSize );
  500. }
  501. DhcpContextSize = // allocate memory for dhcpcontext, in one blob
  502. ROUND_UP_COUNT(sizeof(DHCP_CONTEXT), ALIGN_WORST) +
  503. ROUND_UP_COUNT(ClientUID->ClientUIDLength, ALIGN_WORST) +
  504. ROUND_UP_COUNT(HwAddrSize, ALIGN_WORST ) +
  505. ROUND_UP_COUNT(sizeof(LOCAL_CONTEXT_INFO), ALIGN_WORST) +
  506. ROUND_UP_COUNT(DHCP_RECV_MESSAGE_SIZE, ALIGN_WORST);
  507. Ptr = DhcpAllocateMemory( DhcpContextSize );
  508. if ( Ptr == NULL ) {
  509. return( ERROR_NOT_ENOUGH_MEMORY );
  510. }
  511. //
  512. // make sure the pointers are aligned.
  513. //
  514. DhcpContext = Ptr; // align up the pointers
  515. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + sizeof(DHCP_CONTEXT), ALIGN_WORST);
  516. DhcpContext->ClientIdentifier.pbID = Ptr;
  517. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + ClientUID->ClientUIDLength, ALIGN_WORST);
  518. DhcpContext->HardwareAddress = Ptr;
  519. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + HwAddrSize, ALIGN_WORST);
  520. DhcpContext->LocalInformation = Ptr;
  521. LocalInfo = Ptr;
  522. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + sizeof(LOCAL_CONTEXT_INFO), ALIGN_WORST);
  523. DhcpContext->MessageBuffer = Ptr;
  524. //
  525. // initialize fields.
  526. //
  527. DhcpContext->HardwareAddressType = HARDWARE_TYPE_10MB_EITHERNET;
  528. DhcpContext->HardwareAddressLength = HwAddrSize;
  529. RtlCopyMemory(DhcpContext->HardwareAddress,HwAddrBuf, HwAddrSize);
  530. DhcpContext->RefCount = 1 ;
  531. DhcpContext->ClientIdentifier.cbID = ClientUID->ClientUIDLength;
  532. DhcpContext->ClientIdentifier.bType = HARDWARE_TYPE_10MB_EITHERNET;
  533. DhcpContext->ClientIdentifier.fSpecified = TRUE;
  534. RtlCopyMemory(
  535. DhcpContext->ClientIdentifier.pbID,
  536. ClientUID->ClientUID,
  537. ClientUID->ClientUIDLength
  538. );
  539. DhcpContext->IpAddress = htonl( ClientLeaseInfo->IpAddress );
  540. DhcpContext->SubnetMask = htonl( ClientLeaseInfo->SubnetMask );
  541. if( time(NULL) > ClientLeaseInfo->T2Time ) {
  542. DhcpContext->DhcpServerAddress = 0xFFFFFFFF;
  543. }
  544. else {
  545. DhcpContext->DhcpServerAddress =
  546. htonl( ClientLeaseInfo->DhcpServerAddress );
  547. }
  548. DhcpContext->DesiredIpAddress = DhcpContext->IpAddress;
  549. DhcpContext->Lease = ClientLeaseInfo->Lease;
  550. DhcpContext->LeaseObtained = ClientLeaseInfo->LeaseObtained;
  551. DhcpContext->T1Time = ClientLeaseInfo->T1Time;
  552. DhcpContext->T2Time = ClientLeaseInfo->T2Time;
  553. DhcpContext->LeaseExpires = ClientLeaseInfo->LeaseExpires;
  554. INIT_STATE(DhcpContext);
  555. AUTONET_ENABLED(DhcpContext);
  556. CTXT_WAS_LOOKED(DhcpContext); // this is to prevent PING from happeneing.
  557. APICTXT_ENABLED(DhcpContext); // mark the context as being created by the API
  558. DhcpContext->DontPingGatewayFlag = TRUE; // double assurance against the former..
  559. DhcpContext->IPAutoconfigurationContext.Address = 0;
  560. DhcpContext->IPAutoconfigurationContext.Subnet = inet_addr(DHCP_IPAUTOCONFIGURATION_DEFAULT_SUBNET);
  561. DhcpContext->IPAutoconfigurationContext.Mask = inet_addr(DHCP_IPAUTOCONFIGURATION_DEFAULT_MASK);
  562. DhcpContext->IPAutoconfigurationContext.Seed = GetSeed();
  563. InitializeListHead(&DhcpContext->RecdOptionsList);
  564. InitializeListHead(&DhcpContext->SendOptionsList);
  565. InsertHeadList(&DhcpContext->SendOptionsList, &ParamRequestList.OptionList);
  566. DhcpContext->ClassId = ClassId;
  567. DhcpContext->ClassIdLength = ClassIdLen;
  568. //
  569. // copy local info.
  570. //
  571. //
  572. // unused portion of the local info.
  573. //
  574. LocalInfo->IpInterfaceContext = 0xFFFFFFFF;
  575. LocalInfo->AdapterName= NULL;
  576. //LocalInfo->DeviceName= NULL;
  577. LocalInfo->NetBTDeviceName= NULL;
  578. LocalInfo->RegistryKey= NULL;
  579. //
  580. // used portion of the local info.
  581. //
  582. LocalInfo->Socket = INVALID_SOCKET;
  583. LocalInfo->DefaultGatewaysSet = FALSE;
  584. //
  585. // open socket now.
  586. //
  587. Error = InitializeDhcpSocket(
  588. &LocalInfo->Socket,
  589. htonl( AdapterIpAddress ),
  590. IS_APICTXT_ENABLED(DhcpContext));
  591. if( Error != ERROR_SUCCESS ) {
  592. goto Cleanup;
  593. }
  594. //
  595. // now discover ip address.
  596. //
  597. Error = RenewLease( DhcpContext, &DhcpOptions );
  598. //
  599. // no matter what happens here, freeup the list of options as that is not really needed..
  600. //
  601. LOCK_OPTIONS_LIST();
  602. (void) DhcpDestroyOptionsList(&DhcpContext->RecdOptionsList, &DhcpGlobalClassesList);
  603. UNLOCK_OPTIONS_LIST();
  604. if( Error != ERROR_SUCCESS ) {
  605. goto Cleanup;
  606. }
  607. ClientLeaseInfo->DhcpServerAddress =
  608. ntohl( DhcpContext->DhcpServerAddress );
  609. if ( DhcpOptions.LeaseTime != NULL) {
  610. ClientLeaseInfo->Lease = ntohl( *DhcpOptions.LeaseTime );
  611. } else {
  612. ClientLeaseInfo->Lease = DHCP_MINIMUM_LEASE;
  613. }
  614. Lease = ClientLeaseInfo->Lease;
  615. LeaseObtained = time( NULL );
  616. ClientLeaseInfo->LeaseObtained = LeaseObtained;
  617. T1 = 0;
  618. if ( DhcpOptions.T1Time != NULL ) {
  619. T1 = ntohl( *DhcpOptions.T1Time );
  620. }
  621. T2 = 0;
  622. if ( DhcpOptions.T2Time != NULL ) {
  623. T2 = ntohl( *DhcpOptions.T2Time );
  624. }
  625. //
  626. // make sure T1 < T2 < Lease
  627. //
  628. if( (T2 == 0) || (T2 > Lease) ) {
  629. T2 = Lease * 7 / 8; // default 87.7 %.
  630. }
  631. if( (T1 == 0) || (T1 > T2) ) {
  632. T1 = (T2 > Lease / 2) ? (Lease / 2) : (T2 - 1); // default 50 %.
  633. }
  634. ClientLeaseInfo->T1Time = LeaseObtained + T1;
  635. if ( ClientLeaseInfo->T1Time < LeaseObtained ) {
  636. ClientLeaseInfo->T1Time = INFINIT_TIME; // over flow.
  637. }
  638. ClientLeaseInfo->T2Time = LeaseObtained + T2;
  639. if ( ClientLeaseInfo->T2Time < LeaseObtained ) {
  640. ClientLeaseInfo->T2Time = INFINIT_TIME;
  641. }
  642. ClientLeaseInfo->LeaseExpires = LeaseObtained + Lease;
  643. if ( ClientLeaseInfo->LeaseExpires < LeaseObtained ) {
  644. ClientLeaseInfo->LeaseExpires = INFINIT_TIME;
  645. }
  646. Error = ERROR_SUCCESS;
  647. Cleanup:
  648. if( OptionInfo ) *OptionInfo = NULL; // not implemented.
  649. if( (LocalInfo != NULL) && (LocalInfo->Socket != INVALID_SOCKET) ) {
  650. closesocket( LocalInfo->Socket );
  651. }
  652. if( DhcpContext != NULL ) {
  653. DhcpFreeMemory( DhcpContext );
  654. }
  655. return( Error );
  656. }
  657. DWORD
  658. DhcpReleaseIpAddressLeaseEx(
  659. DWORD AdapterIpAddress,
  660. LPDHCP_LEASE_INFO ClientLeaseInfo,
  661. LPBYTE ClassId OPTIONAL,
  662. ULONG ClassIdLen
  663. )
  664. /*++
  665. Routine Description:
  666. This function releases an ip address the client has.
  667. WSAStartup must have already been called before this function can be called.
  668. Arguments:
  669. AdapterIpAddress - IpAddress of the adapter. On a multi-homed
  670. machined this specifies the subnet to which an address is
  671. released. This value can be set to zero if the machine is
  672. non-multi-homed machine.
  673. ClientLeaseInfo : pointer to the client lease info structure. On
  674. entry the structure should contain the information that was
  675. returned by the DhcpLeaseIpAddress or DhcpRenewIpAddressLease
  676. apis.
  677. ClassId - a byte sequence for user class
  678. ClassIdLen - number of bytes present in ClassId
  679. Return Value:
  680. Windows Error.
  681. --*/
  682. {
  683. DWORD Error;
  684. PDHCP_CONTEXT DhcpContext = NULL;
  685. ULONG DhcpContextSize;
  686. PLOCAL_CONTEXT_INFO LocalInfo;
  687. LPDHCP_CLIENT_UID ClientUID = &(ClientLeaseInfo->ClientUID);
  688. ULONG HwAddrSize;
  689. BYTE HwAddrBuf[200];
  690. LPVOID Ptr;
  691. if( NULL == ClassId && 0 != ClassIdLen || 0 == ClassIdLen && NULL != ClassId ) {
  692. return ERROR_INVALID_PARAMETER;
  693. }
  694. Error = DhcpCommonInit();
  695. if( ERROR_SUCCESS != Error ) return Error;
  696. if( (DWORD) -1 == ClientLeaseInfo->DhcpServerAddress ) {
  697. // this means the address was autoconfigured, nothing to release..
  698. return ERROR_SUCCESS;
  699. }
  700. //
  701. // prepare dhcp context structure.
  702. //
  703. HwAddrSize = 0;
  704. if( INADDR_ANY != AdapterIpAddress
  705. && INADDR_LOOPBACK != AdapterIpAddress ) {
  706. HwAddrSize = sizeof(HwAddrBuf);
  707. GetHardwareAddressForIpAddress( AdapterIpAddress, HwAddrBuf, &HwAddrSize );
  708. }
  709. if( 0 == HwAddrSize ) {
  710. HwAddrSize = ClientUID->ClientUIDLength;
  711. if( HwAddrSize > sizeof(HwAddrBuf) ) return ERROR_INVALID_DATA;
  712. RtlCopyMemory(HwAddrBuf, ClientUID->ClientUID, HwAddrSize );
  713. }
  714. DhcpContextSize = // allocate memory for dhcpcontext, in one blob
  715. ROUND_UP_COUNT(sizeof(DHCP_CONTEXT), ALIGN_WORST) +
  716. ROUND_UP_COUNT(ClientUID->ClientUIDLength, ALIGN_WORST) +
  717. ROUND_UP_COUNT(HwAddrSize, ALIGN_WORST ) +
  718. ROUND_UP_COUNT(sizeof(LOCAL_CONTEXT_INFO), ALIGN_WORST) +
  719. ROUND_UP_COUNT(DHCP_RECV_MESSAGE_SIZE, ALIGN_WORST);
  720. Ptr = DhcpAllocateMemory( DhcpContextSize );
  721. if ( Ptr == NULL ) {
  722. return( ERROR_NOT_ENOUGH_MEMORY );
  723. }
  724. //
  725. // make sure the pointers are aligned.
  726. //
  727. DhcpContext = Ptr; // align up the pointers
  728. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + sizeof(DHCP_CONTEXT), ALIGN_WORST);
  729. DhcpContext->ClientIdentifier.pbID = Ptr;
  730. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + ClientUID->ClientUIDLength, ALIGN_WORST);
  731. DhcpContext->HardwareAddress = Ptr;
  732. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + HwAddrSize, ALIGN_WORST);
  733. DhcpContext->LocalInformation = Ptr;
  734. LocalInfo = Ptr;
  735. Ptr = ROUND_UP_POINTER( (LPBYTE)Ptr + sizeof(LOCAL_CONTEXT_INFO), ALIGN_WORST);
  736. DhcpContext->MessageBuffer = Ptr;
  737. //
  738. // initialize fields.
  739. //
  740. DhcpContext->HardwareAddressType = HARDWARE_TYPE_10MB_EITHERNET;
  741. DhcpContext->HardwareAddressLength = HwAddrSize;
  742. RtlCopyMemory(DhcpContext->HardwareAddress,HwAddrBuf, HwAddrSize);
  743. DhcpContext->RefCount = 1 ;
  744. DhcpContext->ClientIdentifier.cbID = ClientUID->ClientUIDLength;
  745. DhcpContext->ClientIdentifier.bType = HARDWARE_TYPE_10MB_EITHERNET;
  746. DhcpContext->ClientIdentifier.fSpecified = TRUE;
  747. RtlCopyMemory(
  748. DhcpContext->ClientIdentifier.pbID,
  749. ClientUID->ClientUID,
  750. ClientUID->ClientUIDLength
  751. );
  752. DhcpContext->IpAddress = htonl( ClientLeaseInfo->IpAddress );
  753. DhcpContext->SubnetMask = htonl( ClientLeaseInfo->SubnetMask );
  754. DhcpContext->DhcpServerAddress = htonl( ClientLeaseInfo->DhcpServerAddress );
  755. DhcpContext->DesiredIpAddress = DhcpContext->IpAddress;
  756. DhcpContext->Lease = ClientLeaseInfo->Lease;
  757. DhcpContext->LeaseObtained = ClientLeaseInfo->LeaseObtained;
  758. DhcpContext->T1Time = ClientLeaseInfo->T1Time;
  759. DhcpContext->T2Time = ClientLeaseInfo->T2Time;
  760. DhcpContext->LeaseExpires = ClientLeaseInfo->LeaseExpires;
  761. INIT_STATE(DhcpContext);
  762. APICTXT_ENABLED(DhcpContext); // mark the context as being created by the API
  763. DhcpContext->IPAutoconfigurationContext.Address = 0;
  764. DhcpContext->IPAutoconfigurationContext.Subnet = inet_addr(DHCP_IPAUTOCONFIGURATION_DEFAULT_SUBNET);
  765. DhcpContext->IPAutoconfigurationContext.Mask = inet_addr(DHCP_IPAUTOCONFIGURATION_DEFAULT_MASK);
  766. DhcpContext->IPAutoconfigurationContext.Seed = GetSeed();
  767. InitializeListHead(&DhcpContext->RecdOptionsList);
  768. InitializeListHead(&DhcpContext->SendOptionsList);
  769. DhcpContext->ClassId = ClassId;
  770. DhcpContext->ClassIdLength = ClassIdLen;
  771. //
  772. // copy local info.
  773. //
  774. //
  775. // unused portion of the local info.
  776. //
  777. LocalInfo->IpInterfaceContext = 0xFFFFFFFF;
  778. LocalInfo->AdapterName= NULL;
  779. //LocalInfo->DeviceName= NULL;
  780. LocalInfo->NetBTDeviceName= NULL;
  781. LocalInfo->RegistryKey= NULL;
  782. //
  783. // used portion of the local info.
  784. //
  785. LocalInfo->Socket = INVALID_SOCKET;
  786. LocalInfo->DefaultGatewaysSet = FALSE;
  787. //
  788. // open socket now.
  789. //
  790. Error = InitializeDhcpSocket(
  791. &LocalInfo->Socket,
  792. htonl( AdapterIpAddress ),
  793. IS_APICTXT_ENABLED(DhcpContext));
  794. if( Error != ERROR_SUCCESS ) {
  795. goto Cleanup;
  796. }
  797. //
  798. // now release ip address.
  799. //
  800. Error = ReleaseIpAddress( DhcpContext );
  801. ClientLeaseInfo->IpAddress = 0;
  802. ClientLeaseInfo->SubnetMask = DhcpDefaultSubnetMask( 0 );
  803. ClientLeaseInfo->DhcpServerAddress = 0xFFFFFFFF;
  804. ClientLeaseInfo->Lease = 0;
  805. ClientLeaseInfo->LeaseObtained =
  806. ClientLeaseInfo->T1Time =
  807. ClientLeaseInfo->T2Time =
  808. ClientLeaseInfo->LeaseExpires = time( NULL );
  809. //
  810. // recd options list cannot have any elements now..!
  811. //
  812. DhcpAssert(IsListEmpty(&DhcpContext->RecdOptionsList));
  813. Cleanup:
  814. if( (LocalInfo != NULL) && (LocalInfo->Socket != INVALID_SOCKET) ) {
  815. closesocket( LocalInfo->Socket );
  816. }
  817. if( DhcpContext != NULL ) {
  818. DhcpFreeMemory( DhcpContext );
  819. }
  820. return( Error );
  821. }
  822. DWORD
  823. DhcpLeaseIpAddress(
  824. DWORD AdapterIpAddress,
  825. LPDHCP_CLIENT_UID ClientUID,
  826. DWORD DesiredIpAddress,
  827. LPDHCP_OPTION_LIST OptionList,
  828. LPDHCP_LEASE_INFO *LeaseInfo,
  829. LPDHCP_OPTION_INFO *OptionInfo
  830. )
  831. /*++
  832. Routine Description:
  833. This api obtains an IP address lease from a dhcp server. The
  834. caller should specify the client uid and a desired ip address.
  835. The client uid must be globally unique. Set the desired ip address
  836. to zero if you can accept any ip address. Otherwise this api will
  837. try to obtain the ip address you have specified, but not guaranteed.
  838. The caller may optionally requtest additional option info from the
  839. dhcp server, The caller should specify the list in OptionList
  840. parameter and the api will return the available option data in
  841. OptionInfo structure.
  842. ?? Option retrival is not implemented in the first phase. This
  843. requires several modification in the dhcp client code.
  844. Please do not use this function -- this is deprecated. Use the
  845. Ex functions instead.
  846. Arguments:
  847. AdapterIpAddress - IpAddress of the adapter. On a multi-homed
  848. machined this specifies the subnet from which an address is
  849. requested. This value can be set to zero if the machine is a
  850. non-multi-homed machine or you like to get ip address from any
  851. of the subnets. This must be network byte order..
  852. ClientUID - pointer to a client UID structure.
  853. DesiredIpAddress - the ip address you prefer.
  854. OptionList - list of option ids.
  855. LeaseInfo - pointer to a location where the lease info structure
  856. pointer is retured. The caller should free up this structure
  857. after use.
  858. OptionInfo - pointer to a location where the option info structure
  859. pointer is returned. The caller should free up this structure
  860. after use.
  861. Return Value:
  862. Windows Error.
  863. --*/
  864. {
  865. return DhcpLeaseIpAddressEx(
  866. AdapterIpAddress,
  867. ClientUID,
  868. DesiredIpAddress,
  869. OptionList,
  870. LeaseInfo,
  871. OptionInfo,
  872. DEFAULT_RAS_CLASS,
  873. strlen(DEFAULT_RAS_CLASS)
  874. );
  875. }
  876. DWORD
  877. DhcpRenewIpAddressLease(
  878. DWORD AdapterIpAddress,
  879. LPDHCP_LEASE_INFO ClientLeaseInfo,
  880. LPDHCP_OPTION_LIST OptionList,
  881. LPDHCP_OPTION_INFO *OptionInfo
  882. )
  883. /*++
  884. Routine Description:
  885. This api renews an ip address that the client already has. When a
  886. client gets an ip address, it can use the address until the lease
  887. expires. The client should stop using the ip address after that.
  888. Also the client should renew the address after T1 time if the client
  889. is planning to use the address longer than the current lease time.
  890. Arguments:
  891. AdapterIpAddress - IpAddress of the adapter. On a multi-homed
  892. machined this specifies the subnet from which an address is
  893. renewed. This value can be set to zero if the machine is
  894. non-multi-homed machine.
  895. ClientLeaseInfo : pointer to the client lease info structure. On
  896. entry the structure should contain the information that was
  897. returned by the DhcpLeaseIpAddress or DhcpRenewIpAddressLease
  898. apis. On return this structure is updated to reflect the lease
  899. extension.
  900. OptionList - list of option ids.
  901. OptionInfo - pointer to a location where the option info structure
  902. pointer is returned. The caller should free up this structure
  903. after use.
  904. Return Value:
  905. Windows Error.
  906. --*/
  907. {
  908. return DhcpRenewIpAddressLeaseEx(
  909. AdapterIpAddress,
  910. ClientLeaseInfo,
  911. OptionList,
  912. OptionInfo,
  913. DEFAULT_RAS_CLASS,
  914. strlen(DEFAULT_RAS_CLASS)
  915. );
  916. }
  917. DWORD
  918. DhcpReleaseIpAddressLease(
  919. DWORD AdapterIpAddress,
  920. LPDHCP_LEASE_INFO ClientLeaseInfo
  921. )
  922. /*++
  923. Routine Description:
  924. This function releases an ip address the client has.
  925. Arguments:
  926. AdapterIpAddress - IpAddress of the adapter. On a multi-homed
  927. machined this specifies the subnet to which an address is
  928. released. This value can be set to zero if the machine is
  929. non-multi-homed machine.
  930. ClientLeaseInfo : pointer to the client lease info structure. On
  931. entry the structure should contain the information that was
  932. returned by the DhcpLeaseIpAddress or DhcpRenewIpAddressLease
  933. apis.
  934. Return Value:
  935. Windows Error.
  936. --*/
  937. {
  938. return DhcpReleaseIpAddressLeaseEx(
  939. AdapterIpAddress,
  940. ClientLeaseInfo,
  941. DEFAULT_RAS_CLASS,
  942. strlen(DEFAULT_RAS_CLASS)
  943. );
  944. }
  945. //================================================================================
  946. // end of file
  947. //================================================================================