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.

438 lines
17 KiB

  1. //--------------------------------------------------------------------
  2. // NtpBase - implementation
  3. // Copyright (C) Microsoft Corporation, 1999
  4. //
  5. // Created by: Louis Thomas (louisth), 4-16-99
  6. //
  7. // The basic message structure, definitions, and helper functions
  8. // (See notes about time formats at end of file)
  9. //--------------------------------------------------------------------
  10. // precompiled headers
  11. #include "pch.h"
  12. // local headers
  13. #include "NtpBase.h"
  14. #include "DebugWPrintf.h"
  15. // inlines
  16. #include "EndianSwap.inl"
  17. //--------------------------------------------------------------------
  18. // conversion constants
  19. #define NTPTIMEOFFSET (0x014F373BFDE04000)
  20. #define FIVETOTHESEVETH (0x001312D)
  21. //--------------------------------------------------------------------
  22. // global constants
  23. const unsigned int NtpConst::nVersionNumber=3;
  24. const unsigned int NtpConst::nPort=123;
  25. const unsigned int NtpConst::nMaxStratum=15;
  26. const signed int NtpConst::nMaxPollIntervalDCs=15;
  27. const signed int NtpConst::nMaxPollInverval=17;
  28. const signed int NtpConst::nMinPollInverval=4; //6
  29. const NtTimePeriod NtpConst::tpMaxClockAge={864000000000};
  30. const NtTimePeriod NtpConst::tpMaxSkew={10000000};
  31. const NtTimePeriod NtpConst::tpMaxDispersion={160000000};
  32. const NtTimePeriod NtpConst::tpMinDispersion={100000};
  33. const NtTimePeriod NtpConst::tpMaxDistance={10000000};
  34. const unsigned int NtpConst::nMinSelectClocks=1;
  35. const unsigned int NtpConst::nMaxSelectClocks=10;
  36. const DWORD NtpConst::dwLocalRefId=0x4C434F4C; // "LOCL"
  37. const unsigned int NtpReachabilityReg::nSize=8;
  38. const NtTimeEpoch gc_teNtpZero={NTPTIMEOFFSET}; // convenient 'zero'
  39. const NtpTimeEpoch gc_teZero={0}; // convenient 'zero'
  40. const NtTimePeriod gc_tpZero={0}; // convenient 'zero'
  41. const NtTimeOffset gc_toZero={0}; // convenient 'zero'
  42. //--------------------------------------------------------------------
  43. // convert from big-endian NTP-stye timestamp to little-endian NT-style timestamp
  44. NtTimeEpoch NtTimeEpochFromNtpTimeEpoch(NtpTimeEpoch te) {
  45. NtTimeEpoch teRet;
  46. //return (qwNtpTime*(10**7)/(2**32))+NTPTIMEOFFSET
  47. // ==>
  48. //return (qwNtpTime*( 5**7)/(2**25))+NTPTIMEOFFSET
  49. // ==>
  50. //return ((qwNTPtime*FIVETOTHESEVETH)>>25)+NTPTIMEOFFSET;
  51. // ==>
  52. // Note: 'After' division, we round (instead of truncate) the result for better precision
  53. unsigned __int64 qwNtpTime=EndianSwap(te.qw);
  54. unsigned __int64 qwTemp=((qwNtpTime&0x00000000FFFFFFFF)*FIVETOTHESEVETH)+0x0000000001000000; //rounding step: if 25th bit is set, round up;
  55. teRet.qw=(qwTemp>>25) + ((qwNtpTime&0xFFFFFFFF00000000)>>25)*FIVETOTHESEVETH + NTPTIMEOFFSET;
  56. return teRet;
  57. }
  58. //--------------------------------------------------------------------
  59. // convert from little-endian NT-style timestamp to big-endian NTP-stye timestamp
  60. NtpTimeEpoch NtpTimeEpochFromNtTimeEpoch(NtTimeEpoch te) {
  61. NtpTimeEpoch teRet;
  62. //return (qwNtTime-NTPTIMEOFFSET)*(2**32)/(10**7);
  63. // ==>
  64. //return (qwNtTime-NTPTIMEOFFSET)*(2**25)/(5**7);
  65. // ==>
  66. //return ((qwNtTime-NTPTIMEOFFSET)<<25)/FIVETOTHESEVETH);
  67. // ==>
  68. // Note: The high bit is lost (and assumed to be zero) but
  69. // it will not be set for another 29,000 years (around year 31587). No big loss.
  70. // Note: 'After' division, we truncate the result because the precision of NTP already excessive
  71. unsigned __int64 qwTemp=(te.qw-NTPTIMEOFFSET)<<1;
  72. unsigned __int64 qwHigh=qwTemp>>8;
  73. unsigned __int64 qwLow=(qwHigh%FIVETOTHESEVETH)<<32 | (qwTemp&0x00000000000000FF)<<24;
  74. teRet.qw=EndianSwap(((qwHigh/FIVETOTHESEVETH)<<32) | (qwLow/FIVETOTHESEVETH));
  75. return teRet;
  76. }
  77. //--------------------------------------------------------------------
  78. // convert from big-endian NTP-stye time interval to little-endian NT-style time interval
  79. NtTimePeriod NtTimePeriodFromNtpTimePeriod(NtpTimePeriod tp) {
  80. NtTimePeriod tpRet;
  81. unsigned __int64 qwNtpTime=tp.dw;
  82. qwNtpTime=EndianSwap(qwNtpTime<<16);
  83. unsigned __int64 qwTemp=((qwNtpTime&0x00000000FFFFFFFF)*FIVETOTHESEVETH)+0x0000000001000000; //rounding step: if 25th bit is set, round up
  84. tpRet.qw=(qwTemp>>25) + ((qwNtpTime&0xFFFFFFFF00000000)>>25)*FIVETOTHESEVETH;
  85. return tpRet;
  86. }
  87. //--------------------------------------------------------------------
  88. // convert from little-endian NT-style time interval to big-endian NTP-stye time interval
  89. NtpTimePeriod NtpTimePeriodFromNtTimePeriod(NtTimePeriod tp) {
  90. NtpTimePeriod tpRet;
  91. unsigned __int64 qwTemp=(tp.qw)<<1;
  92. unsigned __int64 qwHigh=qwTemp>>8;
  93. unsigned __int64 qwLow=(qwHigh%FIVETOTHESEVETH)<<32 | (qwTemp&0x00000000000000FF)<<24;
  94. qwTemp=EndianSwap(((qwHigh/FIVETOTHESEVETH)<<32) | (qwLow/FIVETOTHESEVETH));
  95. tpRet.dw=(unsigned __int32)(qwTemp>>16);
  96. return tpRet;
  97. }
  98. //--------------------------------------------------------------------
  99. // convert from big-endian NTP-stye delay to little-endian NT-style delay
  100. NtTimeOffset NtTimeOffsetFromNtpTimeOffset(NtpTimeOffset to) {
  101. NtTimeOffset toRet;
  102. if (to.dw&0x00000080) {
  103. to.dw=(signed __int32)EndianSwap((unsigned __int32)-(signed __int32)EndianSwap((unsigned __int32)to.dw));
  104. toRet.qw=-(signed __int64)(NtTimePeriodFromNtpTimePeriod(*(NtpTimePeriod*)&to).qw);
  105. } else {
  106. toRet.qw=(signed __int64)(NtTimePeriodFromNtpTimePeriod(*(NtpTimePeriod*)&to).qw);
  107. }
  108. return toRet;
  109. }
  110. //--------------------------------------------------------------------
  111. // convert from little-endian NT-style delay to big-endian NTP-stye delay
  112. NtpTimeOffset NtpTimeOffsetFromNtTimeOffset(NtTimeOffset to) {
  113. NtpTimeOffset toRet;
  114. if (to.qw<0) {
  115. to.qw=-to.qw;
  116. toRet.dw=(signed __int32)(NtpTimePeriodFromNtTimePeriod(*(NtTimePeriod*)&to).dw);
  117. toRet.dw=(signed __int32)EndianSwap((unsigned __int64)-(signed __int64)EndianSwap((unsigned __int32)toRet.dw));
  118. } else {
  119. toRet.dw=(signed __int32)(NtpTimePeriodFromNtTimePeriod(*(NtTimePeriod*)&to).dw);
  120. }
  121. return toRet;
  122. }
  123. //--------------------------------------------------------------------
  124. // Print out the contents of an NTP packet
  125. // If nDestinationTimestamp is zero, no round trip calculations will be done
  126. void DumpNtpPacket(NtpPacket * pnpIn, NtTimeEpoch teDestinationTimestamp) {
  127. DebugWPrintf0(L"/-- NTP Packet:");
  128. DebugWPrintf0(L"\n| LeapIndicator: ");
  129. if (0==pnpIn->nLeapIndicator) {
  130. DebugWPrintf0(L"0 - no warning");
  131. } else if (1==pnpIn->nLeapIndicator) {
  132. DebugWPrintf0(L"1 - last minute has 61 seconds");
  133. } else if (2==pnpIn->nLeapIndicator) {
  134. DebugWPrintf0(L"2 - last minute has 59 seconds");
  135. } else {
  136. DebugWPrintf0(L"3 - not synchronized");
  137. }
  138. DebugWPrintf1(L"; VersionNumber: %u", pnpIn->nVersionNumber);
  139. DebugWPrintf0(L"; Mode: ");
  140. if (0==pnpIn->nMode) {
  141. DebugWPrintf0(L"0 - Reserved");
  142. } else if (1==pnpIn->nMode) {
  143. DebugWPrintf0(L"1 - SymmetricActive");
  144. } else if (2==pnpIn->nMode) {
  145. DebugWPrintf0(L"2 - SymmetricPassive");
  146. } else if (3==pnpIn->nMode) {
  147. DebugWPrintf0(L"3 - Client");
  148. } else if (4==pnpIn->nMode) {
  149. DebugWPrintf0(L"4 - Server");
  150. } else if (5==pnpIn->nMode) {
  151. DebugWPrintf0(L"5 - Broadcast");
  152. } else if (6==pnpIn->nMode) {
  153. DebugWPrintf0(L"6 - Control");
  154. } else {
  155. DebugWPrintf0(L"7 - PrivateUse");
  156. }
  157. DebugWPrintf1(L"; LiVnMode: 0x%02X", ((BYTE*)pnpIn)[0]);
  158. DebugWPrintf1(L"\n| Stratum: %u - ", pnpIn->nStratum);
  159. if (0==pnpIn->nStratum) {
  160. DebugWPrintf0(L"unspecified or unavailable");
  161. } else if (1==pnpIn->nStratum) {
  162. DebugWPrintf0(L"primary reference (syncd by radio clock)");
  163. } else if (pnpIn->nStratum<16) {
  164. DebugWPrintf0(L"secondary reference (syncd by (S)NTP)");
  165. } else {
  166. DebugWPrintf0(L"reserved");
  167. }
  168. DebugWPrintf1(L"\n| Poll Interval: %d - ", pnpIn->nPollInterval);
  169. if (pnpIn->nPollInterval<4 || pnpIn->nPollInterval>14) {
  170. if (0==pnpIn->nPollInterval) {
  171. DebugWPrintf0(L"unspecified");
  172. } else {
  173. DebugWPrintf0(L"out of valid range");
  174. }
  175. } else {
  176. int nSec=1<<pnpIn->nPollInterval;
  177. DebugWPrintf1(L"%ds", nSec);
  178. }
  179. DebugWPrintf1(L"; Precision: %d - ", pnpIn->nPrecision);
  180. if (pnpIn->nPrecision>-2 || pnpIn->nPrecision<-31) {
  181. if (0==pnpIn->nPollInterval) {
  182. DebugWPrintf0(L"unspecified");
  183. } else {
  184. DebugWPrintf0(L"out of valid range");
  185. }
  186. } else {
  187. WCHAR * wszUnit=L"s";
  188. double dTickInterval=1.0/(1<<(-pnpIn->nPrecision));
  189. if (dTickInterval<1) {
  190. dTickInterval*=1000;
  191. wszUnit=L"ms";
  192. }
  193. if (dTickInterval<1) {
  194. dTickInterval*=1000;
  195. wszUnit=L"�s"; // shows up as �s on console
  196. }
  197. if (dTickInterval<1) {
  198. dTickInterval*=1000;
  199. wszUnit=L"ns";
  200. }
  201. DebugWPrintf2(L"%g%s per tick", dTickInterval, wszUnit);
  202. }
  203. DebugWPrintf0(L"\n| RootDelay: ");
  204. {
  205. DWORD dwTemp=EndianSwap((unsigned __int32)pnpIn->toRootDelay.dw);
  206. DebugWPrintf2(L"0x%04X.%04Xs", dwTemp>>16, dwTemp&0x0000FFFF);
  207. if (0==dwTemp) {
  208. DebugWPrintf0(L" - unspecified");
  209. } else {
  210. DebugWPrintf1(L" - %gs", ((double)((signed __int32)dwTemp))/0x00010000);
  211. }
  212. }
  213. DebugWPrintf0(L"; RootDispersion: ");
  214. {
  215. DWORD dwTemp=EndianSwap(pnpIn->tpRootDispersion.dw);
  216. DebugWPrintf2(L"0x%04X.%04Xs", dwTemp>>16, dwTemp&0x0000FFFF);
  217. if (0==dwTemp) {
  218. DebugWPrintf0(L" - unspecified");
  219. } else {
  220. DebugWPrintf1(L" - %gs", ((double)dwTemp)/0x00010000);
  221. }
  222. }
  223. DebugWPrintf0(L"\n| ReferenceClockIdentifier: ");
  224. {
  225. DWORD dwTemp=EndianSwap(pnpIn->refid.nTransmitTimestamp);
  226. DebugWPrintf1(L"0x%08X", dwTemp);
  227. if (0==dwTemp) {
  228. DebugWPrintf0(L" - unspecified");
  229. } else if (0==pnpIn->nStratum || 1==pnpIn->nStratum) {
  230. char szId[5];
  231. szId[0]=pnpIn->refid.rgnName[0];
  232. szId[1]=pnpIn->refid.rgnName[1];
  233. szId[2]=pnpIn->refid.rgnName[2];
  234. szId[3]=pnpIn->refid.rgnName[3];
  235. szId[4]='\0';
  236. DebugWPrintf1(L" - source name: \"%S\"", szId);
  237. } else if (pnpIn->nVersionNumber<4) {
  238. DebugWPrintf4(L" - source IP: %d.%d.%d.%d",
  239. pnpIn->refid.rgnIpAddr[0], pnpIn->refid.rgnIpAddr[1],
  240. pnpIn->refid.rgnIpAddr[2], pnpIn->refid.rgnIpAddr[3]);
  241. } else {
  242. DebugWPrintf1(L" - last reference timestamp fraction: %gs", ((double)dwTemp)/(4294967296.0));
  243. }
  244. }
  245. DebugWPrintf0(L"\n| ReferenceTimestamp: ");
  246. DumpNtpTimeEpoch(pnpIn->teReferenceTimestamp);
  247. DebugWPrintf0(L"\n| OriginateTimestamp: ");
  248. DumpNtpTimeEpoch(pnpIn->teOriginateTimestamp);
  249. DebugWPrintf0(L"\n| ReceiveTimestamp: ");
  250. DumpNtpTimeEpoch(pnpIn->teReceiveTimestamp);
  251. DebugWPrintf0(L"\n| TransmitTimestamp: ");
  252. DumpNtpTimeEpoch(pnpIn->teTransmitTimestamp);
  253. if (0!=teDestinationTimestamp.qw) {
  254. DebugWPrintf0(L"\n>-- Non-packet info:");
  255. NtTimeEpoch teOriginateTimestamp=NtTimeEpochFromNtpTimeEpoch(pnpIn->teOriginateTimestamp);
  256. NtTimeEpoch teReceiveTimestamp=NtTimeEpochFromNtpTimeEpoch(pnpIn->teReceiveTimestamp);
  257. NtTimeEpoch teTransmitTimestamp=NtTimeEpochFromNtpTimeEpoch(pnpIn->teTransmitTimestamp);
  258. DebugWPrintf0(L"\n| DestinationTimestamp: ");
  259. {
  260. NtpTimeEpoch teNtpTemp=NtpTimeEpochFromNtTimeEpoch(teDestinationTimestamp);
  261. NtTimeEpoch teNtTemp=NtTimeEpochFromNtpTimeEpoch(teNtpTemp);
  262. DumpNtpTimeEpoch(teNtpTemp);
  263. unsigned __int32 nConversionError;
  264. if (teNtTemp.qw>teDestinationTimestamp.qw) {
  265. nConversionError=(unsigned __int32)(teNtTemp-teDestinationTimestamp).qw;
  266. } else {
  267. nConversionError=(unsigned __int32)(teDestinationTimestamp-teNtTemp).qw;
  268. }
  269. if (0!=nConversionError) {
  270. DebugWPrintf1(L" - CnvErr:%u00ns", nConversionError);
  271. }
  272. }
  273. DebugWPrintf0(L"\n| RoundtripDelay: ");
  274. {
  275. NtTimeOffset toRoundtripDelay=
  276. (teDestinationTimestamp-teOriginateTimestamp)
  277. - (teTransmitTimestamp-teReceiveTimestamp);
  278. DebugWPrintf1(L"%I64d00ns", toRoundtripDelay.qw);
  279. }
  280. DebugWPrintf0(L"\n| LocalClockOffset: ");
  281. {
  282. NtTimeOffset toLocalClockOffset=
  283. (teReceiveTimestamp-teOriginateTimestamp)
  284. + (teTransmitTimestamp-teDestinationTimestamp);
  285. toLocalClockOffset/=2;
  286. DebugWPrintf1(L"%I64d00ns", toLocalClockOffset.qw);
  287. unsigned __int64 nAbsOffset;
  288. if (toLocalClockOffset.qw<0) {
  289. nAbsOffset=(unsigned __int64)(-toLocalClockOffset.qw);
  290. } else {
  291. nAbsOffset=(unsigned __int64)(toLocalClockOffset.qw);
  292. }
  293. DWORD dwNanoSecs=(DWORD)(nAbsOffset%10000000);
  294. nAbsOffset/=10000000;
  295. DWORD dwSecs=(DWORD)(nAbsOffset%60);
  296. nAbsOffset/=60;
  297. DebugWPrintf3(L" - %I64u:%02u.%07u00s", nAbsOffset, dwSecs, dwNanoSecs);
  298. }
  299. } // <- end if (0!=nDestinationTimestamp)
  300. DebugWPrintf0(L"\n\\--\n");
  301. }
  302. //--------------------------------------------------------------------
  303. // Print out an NTP-style time
  304. void DumpNtpTimeEpoch(NtpTimeEpoch te) {
  305. DebugWPrintf1(L"0x%016I64X", EndianSwap(te.qw));
  306. if (0==te.qw) {
  307. DebugWPrintf0(L" - unspecified");
  308. } else {
  309. DumpNtTimeEpoch(NtTimeEpochFromNtpTimeEpoch(te));
  310. }
  311. }
  312. //--------------------------------------------------------------------
  313. // Print out an NT-style time
  314. void DumpNtTimeEpoch(NtTimeEpoch te) {
  315. DebugWPrintf1(L" - %I64d00ns", te.qw);
  316. DWORD dwNanoSecs=(DWORD)(te.qw%10000000);
  317. te.qw/=10000000;
  318. DWORD dwSecs=(DWORD)(te.qw%60);
  319. te.qw/=60;
  320. DWORD dwMins=(DWORD)(te.qw%60);
  321. te.qw/=60;
  322. DWORD dwHours=(DWORD)(te.qw%24);
  323. DWORD dwDays=(DWORD)(te.qw/24);
  324. DebugWPrintf5(L" - %u %02u:%02u:%02u.%07us", dwDays, dwHours, dwMins, dwSecs, dwNanoSecs);
  325. }
  326. //--------------------------------------------------------------------
  327. void DumpNtTimePeriod(NtTimePeriod tp) {
  328. DebugWPrintf2(L"%02I64u.%07I64us", tp.qw/10000000,tp.qw%10000000);
  329. }
  330. //--------------------------------------------------------------------
  331. void DumpNtTimeOffset(NtTimeOffset to) {
  332. NtTimePeriod tp;
  333. if (to.qw<0) {
  334. DebugWPrintf0(L"-");
  335. tp.qw=(unsigned __int64)-to.qw;
  336. } else {
  337. DebugWPrintf0(L"+");
  338. tp.qw=(unsigned __int64)to.qw;
  339. }
  340. DumpNtTimePeriod(tp);
  341. }
  342. //--------------------------------------------------------------------
  343. // retrieve the system time
  344. NtTimeEpoch GetCurrentSystemNtTimeEpoch(void) {
  345. NtTimeEpoch teRet;
  346. FILETIME ft;
  347. GetSystemTimeAsFileTime(&ft);
  348. teRet.qw=ft.dwLowDateTime | (((unsigned __int64)ft.dwHighDateTime)<<32);
  349. return teRet;
  350. }
  351. /*--------------------------------------------------------------------
  352. Time formats:
  353. NT time: (10^-7)s intervals since (0h 1-Jan 1601)
  354. NTP time: (2^-32)s intervals since (0h 1-Jan 1900)
  355. Offset:
  356. 109207 days between (0h 1-Jan 1601) and (0h 1-Jan 1900)
  357. == 109207*24*60*60*1E7
  358. == 94,354,848,000,000,000 NT intervals (0x014F 373B FDE0 4000)
  359. When will NTP time overflow?
  360. Rollover: 4294967296 s
  361. (0h 1-Jan 2036) = 49673 days.
  362. in 2036, have 3220096 seconds left = 37 days 6 hours 28 minutes 16 seconds.
  363. 4294967296 s
  364. 4291747200 s = 49673 days, remainder == 3220096 s
  365. 3196800 s = 37 days == 23296 s
  366. 21600 s = 6 hours == 1696 s
  367. 1680 s = 28 minutes == 16 s
  368. 16 s = 16 seconds == 0 s
  369. Therefore:
  370. (06:28:16 7-Feb 2036 UTC)==(00:00:00 1-Jan 1900 UTC)
  371. What does that look like in NT time?
  372. (06:28:16 7-Feb 2036 UTC):
  373. 94,354,848,000,000,000 + 42,949,672,960,000,000 = 137,304,520,960,000,000 (0x01E7 CDBB FDE0 4000)
  374. No problem.
  375. When will NT time overflow?
  376. Rollover: 18,446,744,073,70|9,551,616 00ns
  377. (0h 1-Jan 60,056) = 21350250 days.
  378. 1844674407370 s
  379. 1844661600000 s = 21350250 days == 12807370
  380. 12787200 s = 148 days == 20170
  381. 18000 s = 5 hours == 2170
  382. 2160 s = 36 minutes == 10
  383. 10 s = 10 seconds == 0
  384. Therefore:
  385. (05:36:10.9551616 29-May 60056)==(00:00:00 1-Jan 1601)
  386. --------------------------------------------------------------------*/