print-ntp.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /*
  2. * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that: (1) source code distributions
  7. * retain the above copyright notice and this paragraph in its entirety, (2)
  8. * distributions including binary code include the above copyright notice and
  9. * this paragraph in its entirety in the documentation or other materials
  10. * provided with the distribution, and (3) all advertising materials mentioning
  11. * features or use of this software display the following acknowledgement:
  12. * ``This product includes software developed by the University of California,
  13. * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14. * the University nor the names of its contributors may be used to endorse
  15. * or promote products derived from this software without specific prior
  16. * written permission.
  17. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20. *
  21. * By Jeffrey Mogul/DECWRL
  22. * loosely based on print-bootp.c
  23. */
  24. /* \summary: Network Time Protocol (NTP) printer */
  25. #ifdef HAVE_CONFIG_H
  26. #include "config.h"
  27. #endif
  28. #include <netdissect-stdinc.h>
  29. #ifdef HAVE_STRFTIME
  30. #include <time.h>
  31. #endif
  32. #include "netdissect.h"
  33. #include "addrtoname.h"
  34. #include "extract.h"
  35. /*
  36. * Based on ntp.h from the U of MD implementation
  37. * This file is based on Version 2 of the NTP spec (RFC1119).
  38. */
  39. /*
  40. * Definitions for the masses
  41. */
  42. #define JAN_1970 2208988800U /* 1970 - 1900 in seconds */
  43. /*
  44. * Structure definitions for NTP fixed point values
  45. *
  46. * 0 1 2 3
  47. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  48. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  49. * | Integer Part |
  50. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  51. * | Fraction Part |
  52. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  53. *
  54. * 0 1 2 3
  55. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  56. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  57. * | Integer Part | Fraction Part |
  58. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  59. */
  60. struct l_fixedpt {
  61. uint32_t int_part;
  62. uint32_t fraction;
  63. };
  64. struct s_fixedpt {
  65. uint16_t int_part;
  66. uint16_t fraction;
  67. };
  68. /* rfc2030
  69. * 1 2 3
  70. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  71. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  72. * |LI | VN |Mode | Stratum | Poll | Precision |
  73. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  74. * | Root Delay |
  75. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  76. * | Root Dispersion |
  77. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  78. * | Reference Identifier |
  79. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  80. * | |
  81. * | Reference Timestamp (64) |
  82. * | |
  83. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  84. * | |
  85. * | Originate Timestamp (64) |
  86. * | |
  87. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  88. * | |
  89. * | Receive Timestamp (64) |
  90. * | |
  91. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  92. * | |
  93. * | Transmit Timestamp (64) |
  94. * | |
  95. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  96. * | Key Identifier (optional) (32) |
  97. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  98. * | |
  99. * | |
  100. * | Message Digest (optional) (128) |
  101. * | |
  102. * | |
  103. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  104. */
  105. struct ntpdata {
  106. u_char status; /* status of local clock and leap info */
  107. u_char stratum; /* Stratum level */
  108. u_char ppoll; /* poll value */
  109. int precision:8;
  110. struct s_fixedpt root_delay;
  111. struct s_fixedpt root_dispersion;
  112. uint32_t refid;
  113. struct l_fixedpt ref_timestamp;
  114. struct l_fixedpt org_timestamp;
  115. struct l_fixedpt rec_timestamp;
  116. struct l_fixedpt xmt_timestamp;
  117. uint32_t key_id;
  118. uint8_t message_digest[16];
  119. };
  120. /*
  121. * Leap Second Codes (high order two bits)
  122. */
  123. #define NO_WARNING 0x00 /* no warning */
  124. #define PLUS_SEC 0x40 /* add a second (61 seconds) */
  125. #define MINUS_SEC 0x80 /* minus a second (59 seconds) */
  126. #define ALARM 0xc0 /* alarm condition (clock unsynchronized) */
  127. /*
  128. * Clock Status Bits that Encode Version
  129. */
  130. #define NTPVERSION_1 0x08
  131. #define VERSIONMASK 0x38
  132. #define LEAPMASK 0xc0
  133. #ifdef MODEMASK
  134. #undef MODEMASK /* Solaris sucks */
  135. #endif
  136. #define MODEMASK 0x07
  137. /*
  138. * Code values
  139. */
  140. #define MODE_UNSPEC 0 /* unspecified */
  141. #define MODE_SYM_ACT 1 /* symmetric active */
  142. #define MODE_SYM_PAS 2 /* symmetric passive */
  143. #define MODE_CLIENT 3 /* client */
  144. #define MODE_SERVER 4 /* server */
  145. #define MODE_BROADCAST 5 /* broadcast */
  146. #define MODE_RES1 6 /* reserved */
  147. #define MODE_RES2 7 /* reserved */
  148. /*
  149. * Stratum Definitions
  150. */
  151. #define UNSPECIFIED 0
  152. #define PRIM_REF 1 /* radio clock */
  153. #define INFO_QUERY 62 /* **** THIS implementation dependent **** */
  154. #define INFO_REPLY 63 /* **** THIS implementation dependent **** */
  155. static void p_sfix(netdissect_options *ndo, const struct s_fixedpt *);
  156. static void p_ntp_time(netdissect_options *, const struct l_fixedpt *);
  157. static void p_ntp_delta(netdissect_options *, const struct l_fixedpt *, const struct l_fixedpt *);
  158. static const struct tok ntp_mode_values[] = {
  159. { MODE_UNSPEC, "unspecified" },
  160. { MODE_SYM_ACT, "symmetric active" },
  161. { MODE_SYM_PAS, "symmetric passive" },
  162. { MODE_CLIENT, "Client" },
  163. { MODE_SERVER, "Server" },
  164. { MODE_BROADCAST, "Broadcast" },
  165. { MODE_RES1, "Reserved" },
  166. { MODE_RES2, "Reserved" },
  167. { 0, NULL }
  168. };
  169. static const struct tok ntp_leapind_values[] = {
  170. { NO_WARNING, "" },
  171. { PLUS_SEC, "+1s" },
  172. { MINUS_SEC, "-1s" },
  173. { ALARM, "clock unsynchronized" },
  174. { 0, NULL }
  175. };
  176. static const struct tok ntp_stratum_values[] = {
  177. { UNSPECIFIED, "unspecified" },
  178. { PRIM_REF, "primary reference" },
  179. { 0, NULL }
  180. };
  181. /*
  182. * Print ntp requests
  183. */
  184. void
  185. ntp_print(netdissect_options *ndo,
  186. register const u_char *cp, u_int length)
  187. {
  188. register const struct ntpdata *bp;
  189. int mode, version, leapind;
  190. bp = (const struct ntpdata *)cp;
  191. ND_TCHECK(bp->status);
  192. version = (int)(bp->status & VERSIONMASK) >> 3;
  193. ND_PRINT((ndo, "NTPv%d", version));
  194. mode = bp->status & MODEMASK;
  195. if (!ndo->ndo_vflag) {
  196. ND_PRINT((ndo, ", %s, length %u",
  197. tok2str(ntp_mode_values, "Unknown mode", mode),
  198. length));
  199. return;
  200. }
  201. ND_PRINT((ndo, ", length %u\n\t%s",
  202. length,
  203. tok2str(ntp_mode_values, "Unknown mode", mode)));
  204. leapind = bp->status & LEAPMASK;
  205. ND_PRINT((ndo, ", Leap indicator: %s (%u)",
  206. tok2str(ntp_leapind_values, "Unknown", leapind),
  207. leapind));
  208. ND_TCHECK(bp->stratum);
  209. ND_PRINT((ndo, ", Stratum %u (%s)",
  210. bp->stratum,
  211. tok2str(ntp_stratum_values, (bp->stratum >=2 && bp->stratum<=15) ? "secondary reference" : "reserved", bp->stratum)));
  212. ND_TCHECK(bp->ppoll);
  213. ND_PRINT((ndo, ", poll %u (%us)", bp->ppoll, 1 << bp->ppoll));
  214. /* Can't ND_TCHECK bp->precision bitfield so bp->distance + 0 instead */
  215. ND_TCHECK2(bp->root_delay, 0);
  216. ND_PRINT((ndo, ", precision %d", bp->precision));
  217. ND_TCHECK(bp->root_delay);
  218. ND_PRINT((ndo, "\n\tRoot Delay: "));
  219. p_sfix(ndo, &bp->root_delay);
  220. ND_TCHECK(bp->root_dispersion);
  221. ND_PRINT((ndo, ", Root dispersion: "));
  222. p_sfix(ndo, &bp->root_dispersion);
  223. ND_TCHECK(bp->refid);
  224. ND_PRINT((ndo, ", Reference-ID: "));
  225. /* Interpretation depends on stratum */
  226. switch (bp->stratum) {
  227. case UNSPECIFIED:
  228. ND_PRINT((ndo, "(unspec)"));
  229. break;
  230. case PRIM_REF:
  231. if (fn_printn(ndo, (const u_char *)&(bp->refid), 4, ndo->ndo_snapend))
  232. goto trunc;
  233. break;
  234. case INFO_QUERY:
  235. ND_PRINT((ndo, "%s INFO_QUERY", ipaddr_string(ndo, &(bp->refid))));
  236. /* this doesn't have more content */
  237. return;
  238. case INFO_REPLY:
  239. ND_PRINT((ndo, "%s INFO_REPLY", ipaddr_string(ndo, &(bp->refid))));
  240. /* this is too complex to be worth printing */
  241. return;
  242. default:
  243. ND_PRINT((ndo, "%s", ipaddr_string(ndo, &(bp->refid))));
  244. break;
  245. }
  246. ND_TCHECK(bp->ref_timestamp);
  247. ND_PRINT((ndo, "\n\t Reference Timestamp: "));
  248. p_ntp_time(ndo, &(bp->ref_timestamp));
  249. ND_TCHECK(bp->org_timestamp);
  250. ND_PRINT((ndo, "\n\t Originator Timestamp: "));
  251. p_ntp_time(ndo, &(bp->org_timestamp));
  252. ND_TCHECK(bp->rec_timestamp);
  253. ND_PRINT((ndo, "\n\t Receive Timestamp: "));
  254. p_ntp_time(ndo, &(bp->rec_timestamp));
  255. ND_TCHECK(bp->xmt_timestamp);
  256. ND_PRINT((ndo, "\n\t Transmit Timestamp: "));
  257. p_ntp_time(ndo, &(bp->xmt_timestamp));
  258. ND_PRINT((ndo, "\n\t Originator - Receive Timestamp: "));
  259. p_ntp_delta(ndo, &(bp->org_timestamp), &(bp->rec_timestamp));
  260. ND_PRINT((ndo, "\n\t Originator - Transmit Timestamp: "));
  261. p_ntp_delta(ndo, &(bp->org_timestamp), &(bp->xmt_timestamp));
  262. if ( (sizeof(struct ntpdata) - length) == 16) { /* Optional: key-id */
  263. ND_TCHECK(bp->key_id);
  264. ND_PRINT((ndo, "\n\tKey id: %u", bp->key_id));
  265. } else if ( (sizeof(struct ntpdata) - length) == 0) { /* Optional: key-id + authentication */
  266. ND_TCHECK(bp->key_id);
  267. ND_PRINT((ndo, "\n\tKey id: %u", bp->key_id));
  268. ND_TCHECK2(bp->message_digest, sizeof (bp->message_digest));
  269. ND_PRINT((ndo, "\n\tAuthentication: %08x%08x%08x%08x",
  270. EXTRACT_32BITS(bp->message_digest),
  271. EXTRACT_32BITS(bp->message_digest + 4),
  272. EXTRACT_32BITS(bp->message_digest + 8),
  273. EXTRACT_32BITS(bp->message_digest + 12)));
  274. }
  275. return;
  276. trunc:
  277. ND_PRINT((ndo, " [|ntp]"));
  278. }
  279. static void
  280. p_sfix(netdissect_options *ndo,
  281. register const struct s_fixedpt *sfp)
  282. {
  283. register int i;
  284. register int f;
  285. register double ff;
  286. i = EXTRACT_16BITS(&sfp->int_part);
  287. f = EXTRACT_16BITS(&sfp->fraction);
  288. ff = f / 65536.0; /* shift radix point by 16 bits */
  289. f = (int)(ff * 1000000.0); /* Treat fraction as parts per million */
  290. ND_PRINT((ndo, "%d.%06d", i, f));
  291. }
  292. #define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */
  293. static void
  294. p_ntp_time(netdissect_options *ndo,
  295. register const struct l_fixedpt *lfp)
  296. {
  297. register int32_t i;
  298. register uint32_t uf;
  299. register uint32_t f;
  300. register double ff;
  301. i = EXTRACT_32BITS(&lfp->int_part);
  302. uf = EXTRACT_32BITS(&lfp->fraction);
  303. ff = uf;
  304. if (ff < 0.0) /* some compilers are buggy */
  305. ff += FMAXINT;
  306. ff = ff / FMAXINT; /* shift radix point by 32 bits */
  307. f = (uint32_t)(ff * 1000000000.0); /* treat fraction as parts per billion */
  308. ND_PRINT((ndo, "%u.%09d", i, f));
  309. #ifdef HAVE_STRFTIME
  310. /*
  311. * print the time in human-readable format.
  312. */
  313. if (i) {
  314. time_t seconds = i - JAN_1970;
  315. struct tm *tm;
  316. char time_buf[128];
  317. tm = localtime(&seconds);
  318. strftime(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", tm);
  319. ND_PRINT((ndo, " (%s)", time_buf));
  320. }
  321. #endif
  322. }
  323. /* Prints time difference between *lfp and *olfp */
  324. static void
  325. p_ntp_delta(netdissect_options *ndo,
  326. register const struct l_fixedpt *olfp,
  327. register const struct l_fixedpt *lfp)
  328. {
  329. register int32_t i;
  330. register uint32_t u, uf;
  331. register uint32_t ou, ouf;
  332. register uint32_t f;
  333. register double ff;
  334. int signbit;
  335. u = EXTRACT_32BITS(&lfp->int_part);
  336. ou = EXTRACT_32BITS(&olfp->int_part);
  337. uf = EXTRACT_32BITS(&lfp->fraction);
  338. ouf = EXTRACT_32BITS(&olfp->fraction);
  339. if (ou == 0 && ouf == 0) {
  340. p_ntp_time(ndo, lfp);
  341. return;
  342. }
  343. i = u - ou;
  344. if (i > 0) { /* new is definitely greater than old */
  345. signbit = 0;
  346. f = uf - ouf;
  347. if (ouf > uf) /* must borrow from high-order bits */
  348. i -= 1;
  349. } else if (i < 0) { /* new is definitely less than old */
  350. signbit = 1;
  351. f = ouf - uf;
  352. if (uf > ouf) /* must carry into the high-order bits */
  353. i += 1;
  354. i = -i;
  355. } else { /* int_part is zero */
  356. if (uf > ouf) {
  357. signbit = 0;
  358. f = uf - ouf;
  359. } else {
  360. signbit = 1;
  361. f = ouf - uf;
  362. }
  363. }
  364. ff = f;
  365. if (ff < 0.0) /* some compilers are buggy */
  366. ff += FMAXINT;
  367. ff = ff / FMAXINT; /* shift radix point by 32 bits */
  368. f = (uint32_t)(ff * 1000000000.0); /* treat fraction as parts per billion */
  369. ND_PRINT((ndo, "%s%d.%09d", signbit ? "-" : "+", i, f));
  370. }