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.

832 lines
17 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. dhcp.c
  5. Abstract:
  6. This module contains DHCP specific utility routines used by the
  7. DHCP components.
  8. Author:
  9. Manny Weiser (mannyw) 12-Aug-1992
  10. Revision History:
  11. Madan Appiah (madana) 21-Oct-1992
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <dhcpl.h>
  17. DWORD
  18. NTTimeToNTPTime(PULONG pTime,
  19. PFILETIME pft OPTIONAL);
  20. DWORD
  21. NTPTimeToNTFileTime(PLONG pTime, PFILETIME pft, BOOL bHostOrder);
  22. #undef DhcpAllocateMemory
  23. #undef DhcpFreeMemory
  24. PVOID
  25. DhcpAllocateMemory(
  26. DWORD Size
  27. )
  28. /*++
  29. Routine Description:
  30. This function allocates the required size of memory by calling
  31. LocalAlloc.
  32. Arguments:
  33. Size - size of the memory block required.
  34. Return Value:
  35. Pointer to the allocated block.
  36. --*/
  37. {
  38. return( LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, Size ) );
  39. }
  40. #undef DhcpFreeMemory
  41. VOID
  42. DhcpFreeMemory(
  43. PVOID Memory
  44. )
  45. /*++
  46. Routine Description:
  47. This function frees up the memory that was allocated by
  48. DhcpAllocateMemory.
  49. Arguments:
  50. Memory - pointer to the memory block that needs to be freed up.
  51. Return Value:
  52. none.
  53. --*/
  54. {
  55. LPVOID Ptr;
  56. ASSERT( Memory != NULL );
  57. Ptr = LocalFree( Memory );
  58. ASSERT( Ptr == NULL );
  59. }
  60. DATE_TIME
  61. DhcpCalculateTime(
  62. DWORD RelativeTime
  63. )
  64. /*++
  65. Routine Description:
  66. The function calculates the absolute time of a time RelativeTime
  67. seconds from now.
  68. Arguments:
  69. RelativeTime - Relative time, in seconds.
  70. Return Value:
  71. The time in RelativeTime seconds from the current system time.
  72. --*/
  73. {
  74. SYSTEMTIME systemTime;
  75. ULONGLONG absoluteTime;
  76. if( RelativeTime == INFINIT_LEASE ) {
  77. ((DATE_TIME *)&absoluteTime)->dwLowDateTime =
  78. DHCP_DATE_TIME_INFINIT_LOW;
  79. ((DATE_TIME *)&absoluteTime)->dwHighDateTime =
  80. DHCP_DATE_TIME_INFINIT_HIGH;
  81. }
  82. else {
  83. GetSystemTime( &systemTime );
  84. SystemTimeToFileTime(
  85. &systemTime,
  86. (FILETIME *)&absoluteTime );
  87. absoluteTime = absoluteTime + RelativeTime * (ULONGLONG)10000000; }
  88. return( *(DATE_TIME *)&absoluteTime );
  89. }
  90. DATE_TIME
  91. DhcpGetDateTime(
  92. VOID
  93. )
  94. /*++
  95. Routine Description:
  96. This function returns FILETIME.
  97. Arguments:
  98. none.
  99. Return Value:
  100. FILETIME.
  101. --*/
  102. {
  103. SYSTEMTIME systemTime;
  104. DATE_TIME Time;
  105. GetSystemTime( &systemTime );
  106. SystemTimeToFileTime( &systemTime, (FILETIME *)&Time );
  107. return( Time );
  108. }
  109. VOID
  110. DhcpNTToNTPTime(
  111. LPDATE_TIME AbsNTTime,
  112. DWORD Offset,
  113. PULONG NTPTimeStamp
  114. )
  115. /*++
  116. Routine Description:
  117. The function calculates the absolute NTP timestamp from AbsTime on
  118. NT added by given offset.
  119. Arguments:
  120. AbsNTTime - AbsTime on NT. If 0, it will use current time.
  121. RelativeOffset - offset to be added to AnsNTTime (in seconds.)
  122. Return Value:
  123. The time in RelativeTime seconds from the current system time.
  124. --*/
  125. {
  126. ULONGLONG LocalAbsNTTime;
  127. DWORD Error;
  128. if ( AbsNTTime == 0 ) {
  129. GetSystemTimeAsFileTime((FILETIME *)&LocalAbsNTTime );
  130. } else {
  131. LocalAbsNTTime = *(ULONGLONG *)AbsNTTime;
  132. }
  133. // add offset
  134. LocalAbsNTTime += Offset * (ULONGLONG)10000000;
  135. // now convert to NT timestamp
  136. Error = NTTimeToNTPTime( NTPTimeStamp, (PFILETIME)&LocalAbsNTTime );
  137. DhcpAssert( ERROR_SUCCESS == Error );
  138. return;
  139. }
  140. VOID
  141. DhcpNTPToNTTime(
  142. PULONG NTPTimeStamp,
  143. DWORD Offset,
  144. DATE_TIME *NTTime
  145. )
  146. /*++
  147. Routine Description:
  148. The function calculates the absolute NTP timestamp from AbsTime on
  149. NT added by given offset.
  150. Arguments:
  151. AbsNTTime - AbsTime on NT. If 0, it will use current time.
  152. RelativeOffset - offset to be added to AnsNTTime (in seconds.)
  153. Return Value:
  154. The time in RelativeTime seconds from the current system time.
  155. --*/
  156. {
  157. ULONGLONG LocalAbsNTTime;
  158. DWORD Error;
  159. Error = NTPTimeToNTFileTime(
  160. NTPTimeStamp,
  161. (FILETIME *)&LocalAbsNTTime,
  162. FALSE // not in host order.
  163. );
  164. DhcpAssert( ERROR_SUCCESS == Error );
  165. // add offset
  166. LocalAbsNTTime += Offset * (ULONGLONG)10000000;
  167. // now convert to NT timestamp
  168. // MBUG
  169. *(ULONGLONG *)NTTime = LocalAbsNTTime;
  170. return;
  171. }
  172. DWORD
  173. DhcpReportEventW(
  174. LPWSTR Source,
  175. DWORD EventID,
  176. DWORD EventType,
  177. DWORD NumStrings,
  178. DWORD DataLength,
  179. LPWSTR *Strings,
  180. LPVOID Data
  181. )
  182. /*++
  183. Routine Description:
  184. This function writes the specified (EventID) log at the end of the
  185. eventlog.
  186. Arguments:
  187. Source - Points to a null-terminated string that specifies the name
  188. of the module referenced. The node must exist in the
  189. registration database, and the module name has the
  190. following format:
  191. \EventLog\System\Lanmanworkstation
  192. EventID - The specific event identifier. This identifies the
  193. message that goes with this event.
  194. EventType - Specifies the type of event being logged. This
  195. parameter can have one of the following
  196. values:
  197. Value Meaning
  198. EVENTLOG_ERROR_TYPE Error event
  199. EVENTLOG_WARNING_TYPE Warning event
  200. EVENTLOG_INFORMATION_TYPE Information event
  201. NumStrings - Specifies the number of strings that are in the array
  202. at 'Strings'. A value of zero indicates no strings
  203. are present.
  204. DataLength - Specifies the number of bytes of event-specific raw
  205. (binary) data to write to the log. If cbData is
  206. zero, no event-specific data is present.
  207. Strings - Points to a buffer containing an array of null-terminated
  208. strings that are merged into the message before
  209. displaying to the user. This parameter must be a valid
  210. pointer (or NULL), even if cStrings is zero.
  211. Data - Buffer containing the raw data. This parameter must be a
  212. valid pointer (or NULL), even if cbData is zero.
  213. Return Value:
  214. Returns the WIN32 extended error obtained by GetLastError().
  215. NOTE : This function works slow since it calls the open and close
  216. eventlog source everytime.
  217. --*/
  218. {
  219. HANDLE EventlogHandle;
  220. DWORD ReturnCode;
  221. //
  222. // open eventlog section.
  223. //
  224. EventlogHandle = RegisterEventSourceW(
  225. NULL,
  226. Source
  227. );
  228. if (EventlogHandle == NULL) {
  229. ReturnCode = GetLastError();
  230. goto Cleanup;
  231. }
  232. //
  233. // Log the error code specified
  234. //
  235. if( !ReportEventW(
  236. EventlogHandle,
  237. (WORD)EventType,
  238. 0, // event category
  239. EventID,
  240. NULL,
  241. (WORD)NumStrings,
  242. DataLength,
  243. Strings,
  244. Data
  245. ) ) {
  246. ReturnCode = GetLastError();
  247. goto Cleanup;
  248. }
  249. ReturnCode = NO_ERROR;
  250. Cleanup:
  251. if( EventlogHandle != NULL ) {
  252. DeregisterEventSource(EventlogHandle);
  253. }
  254. return ReturnCode;
  255. }
  256. DWORD
  257. DhcpReportEventA(
  258. LPWSTR Source,
  259. DWORD EventID,
  260. DWORD EventType,
  261. DWORD NumStrings,
  262. DWORD DataLength,
  263. LPSTR *Strings,
  264. LPVOID Data
  265. )
  266. /*++
  267. Routine Description:
  268. This function writes the specified (EventID) log at the end of the
  269. eventlog.
  270. Arguments:
  271. Source - Points to a null-terminated string that specifies the name
  272. of the module referenced. The node must exist in the
  273. registration database, and the module name has the
  274. following format:
  275. \EventLog\System\Lanmanworkstation
  276. EventID - The specific event identifier. This identifies the
  277. message that goes with this event.
  278. EventType - Specifies the type of event being logged. This
  279. parameter can have one of the following
  280. values:
  281. Value Meaning
  282. EVENTLOG_ERROR_TYPE Error event
  283. EVENTLOG_WARNING_TYPE Warning event
  284. EVENTLOG_INFORMATION_TYPE Information event
  285. NumStrings - Specifies the number of strings that are in the array
  286. at 'Strings'. A value of zero indicates no strings
  287. are present.
  288. DataLength - Specifies the number of bytes of event-specific raw
  289. (binary) data to write to the log. If cbData is
  290. zero, no event-specific data is present.
  291. Strings - Points to a buffer containing an array of null-terminated
  292. strings that are merged into the message before
  293. displaying to the user. This parameter must be a valid
  294. pointer (or NULL), even if cStrings is zero.
  295. Data - Buffer containing the raw data. This parameter must be a
  296. valid pointer (or NULL), even if cbData is zero.
  297. Return Value:
  298. Returns the WIN32 extended error obtained by GetLastError().
  299. NOTE : This function works slow since it calls the open and close
  300. eventlog source everytime.
  301. --*/
  302. {
  303. HANDLE EventlogHandle;
  304. DWORD ReturnCode;
  305. //
  306. // open eventlog section.
  307. //
  308. EventlogHandle = RegisterEventSourceW(
  309. NULL,
  310. Source
  311. );
  312. if (EventlogHandle == NULL) {
  313. ReturnCode = GetLastError();
  314. goto Cleanup;
  315. }
  316. //
  317. // Log the error code specified
  318. //
  319. if( !ReportEventA(
  320. EventlogHandle,
  321. (WORD)EventType,
  322. 0, // event category
  323. EventID,
  324. NULL,
  325. (WORD)NumStrings,
  326. DataLength,
  327. Strings,
  328. Data
  329. ) ) {
  330. ReturnCode = GetLastError();
  331. goto Cleanup;
  332. }
  333. ReturnCode = NO_ERROR;
  334. Cleanup:
  335. if( EventlogHandle != NULL ) {
  336. DeregisterEventSource(EventlogHandle);
  337. }
  338. return ReturnCode;
  339. }
  340. DWORD
  341. DhcpLogUnknownOption(
  342. LPWSTR Source,
  343. DWORD EventID,
  344. LPOPTION Option
  345. )
  346. /*++
  347. Routine Description:
  348. This routine logs an unknown DHCP option to event log.
  349. Arguments:
  350. Source - name of the app that logs this error. it should be either
  351. "DhcpClient" or "DhcpServer".
  352. EventID - Event identifier number.
  353. Option - pointer to the unknown option structure.
  354. Return Value:
  355. Windows Error code.
  356. --*/
  357. {
  358. LPWSTR Strings[2];
  359. WCHAR StringsBuffer[ 2 * (3 + 1) ];
  360. // for two string each is 1byte decimal number (0 - 255).
  361. LPWSTR StringsPtr = StringsBuffer;
  362. //
  363. // convert option number.
  364. //
  365. Strings[0] = StringsPtr;
  366. DhcpDecimalToString( StringsPtr, Option->OptionType );
  367. StringsPtr += 3;
  368. *StringsPtr++ = L'\0';
  369. //
  370. // convert option length.
  371. //
  372. Strings[1] = StringsPtr;
  373. DhcpDecimalToString( StringsPtr, Option->OptionLength );
  374. StringsPtr += 3;
  375. *StringsPtr++ = L'\0';
  376. //
  377. // log error.
  378. //
  379. return(
  380. DhcpReportEventW(
  381. Source,
  382. EventID,
  383. EVENTLOG_WARNING_TYPE,
  384. 2,
  385. (DWORD)Option->OptionLength,
  386. Strings,
  387. (PVOID)Option->OptionValue )
  388. );
  389. }
  390. #if DBG
  391. VOID
  392. DhcpAssertFailed(
  393. LPSTR FailedAssertion,
  394. LPSTR FileName,
  395. DWORD LineNumber,
  396. LPSTR Message
  397. )
  398. /*++
  399. Routine Description:
  400. Assertion failed.
  401. Arguments:
  402. FailedAssertion :
  403. FileName :
  404. LineNumber :
  405. Message :
  406. Return Value:
  407. none.
  408. --*/
  409. {
  410. #ifndef DHCP_NOASSERT
  411. RtlAssert(
  412. FailedAssertion,
  413. FileName,
  414. (ULONG) LineNumber,
  415. (PCHAR) Message);
  416. #endif
  417. DhcpPrint(( 0, "Assert @ %s \n", FailedAssertion ));
  418. DhcpPrint(( 0, "Assert Filename, %s \n", FileName ));
  419. DhcpPrint(( 0, "Line Num. = %ld.\n", LineNumber ));
  420. DhcpPrint(( 0, "Message is %s\n", Message ));
  421. }
  422. #endif
  423. LPWSTR
  424. DhcpRegIpAddressToKey(
  425. DHCP_IP_ADDRESS IpAddress,
  426. LPWSTR KeyBuffer
  427. )
  428. /*++
  429. Routine Description:
  430. This function converts an IpAddress to registry key. The registry
  431. key is unicode string of IpAddress in dotted form.
  432. Arguments:
  433. IpAddress : IpAddress that needs conversion. The IpAddress is in
  434. host order.
  435. KeyBuffer : pointer a buffer that will hold the converted
  436. registry key. The buffer should be big enough to
  437. converted key.
  438. Return Value:
  439. Pointer to the key the buffer.
  440. --*/
  441. {
  442. LPSTR OemKey;
  443. LPWSTR UnicodeKey;
  444. DWORD NetworkOrderIpAddress;
  445. NetworkOrderIpAddress = htonl(IpAddress);
  446. OemKey = inet_ntoa( *(struct in_addr *)&NetworkOrderIpAddress );
  447. UnicodeKey = DhcpOemToUnicode( OemKey, KeyBuffer );
  448. DhcpAssert( UnicodeKey == KeyBuffer );
  449. return( UnicodeKey );
  450. }
  451. DHCP_IP_ADDRESS
  452. DhcpRegKeyToIpAddress(
  453. LPWSTR Key
  454. )
  455. /*++
  456. Routine Description:
  457. This function converts registry key to Ip Address.
  458. Arguments:
  459. Key : Pointer to registry key.
  460. Return Value:
  461. Converted IpAddress.
  462. --*/
  463. {
  464. CHAR OemKeyBuffer[DHCP_IP_KEY_LEN];
  465. LPSTR OemKey;
  466. OemKey = DhcpUnicodeToOem( Key, OemKeyBuffer );
  467. DhcpAssert( OemKey == OemKeyBuffer );
  468. return( ntohl(inet_addr( OemKey )) );
  469. }
  470. LPWSTR
  471. DhcpRegOptionIdToKey(
  472. DHCP_OPTION_ID OptionId,
  473. LPWSTR KeyBuffer
  474. )
  475. /*++
  476. Routine Description:
  477. This function converts an OptionId to registry key. The registry
  478. key is unicode string of OptionId, 3 unicode char. long and of the
  479. form L"000".
  480. Arguments:
  481. IpAddress : IpAddress that needs conversion.
  482. KeyBuffer : pointer a buffer that will hold the converted
  483. registry key. The buffer should be at least 8 char.
  484. long.
  485. Return Value:
  486. Pointer to the key the buffer.
  487. --*/
  488. {
  489. int i;
  490. for (i = 2; i >= 0; i--) {
  491. KeyBuffer[i] = L'0' + (BYTE)(OptionId % 10 );
  492. OptionId /= 10;
  493. }
  494. KeyBuffer[3] = L'\0';
  495. return( KeyBuffer );
  496. }
  497. DHCP_OPTION_ID
  498. DhcpRegKeyToOptionId(
  499. LPWSTR Key
  500. )
  501. /*++
  502. Routine Description:
  503. This function converts registry key to OptionId.
  504. Arguments:
  505. Key : Pointer to registry key.
  506. Return Value:
  507. Converted OptionId.
  508. --*/
  509. {
  510. DHCP_OPTION_ID OptionId = 0;
  511. int i;
  512. for (i = 0; i < 3 && Key[i] != L'\0'; i++) {
  513. OptionId = (OptionId * 10) + (Key[i] - L'0');
  514. }
  515. return( OptionId );
  516. }
  517. DWORD
  518. DhcpStartWaitableTimer(
  519. HANDLE TimerHandle,
  520. DWORD SleepTime)
  521. /*++
  522. Routine Description:
  523. This routine starts the waitable timer. This timer fires off even
  524. when the system is in hibernate state.
  525. Arguments
  526. TimerHandle - Waitable Timer Handle
  527. SleepTime - Sleep Time in seconds.
  528. Return Value:
  529. Status of the operation.
  530. --*/
  531. {
  532. DATE_TIME SleepTimeInNSec; // sleep time in nano seconds since Jan 1 1901
  533. DWORD Error;
  534. BOOL Result;
  535. Error = STATUS_SUCCESS;
  536. SleepTimeInNSec = DhcpCalculateTime( SleepTime );
  537. Result = SetWaitableTimer(
  538. TimerHandle, // handle to timer object
  539. (LARGE_INTEGER *)&SleepTimeInNSec, // due time.
  540. 0, // not periodic
  541. NULL, // completion routine
  542. NULL, // completion routine arg
  543. TRUE // resume power state when due
  544. );
  545. if ( !Result ) {
  546. DhcpPrint((0, "SetWaitableTimer reported Error = %d\n",Error=GetLastError()));
  547. }
  548. return Error;
  549. }
  550. VOID
  551. DhcpCancelWaitableTimer(
  552. HANDLE TimerHandle
  553. )
  554. /*++
  555. Routine Description:
  556. This routine cancels the waitable timer.
  557. Arguments
  558. TimerHandle - Waitable Timer Handle
  559. Return Value:
  560. --*/
  561. {
  562. BOOL Result;
  563. Result = CancelWaitableTimer( TimerHandle );
  564. if ( !Result ) {
  565. DhcpPrint((0,"SetWaitableTimer reported Error = %lx\n",GetLastError()));
  566. }
  567. }