]> The Tcpdump Group git mirrors - tcpdump/blob - print-ntp.c
21bb7374eaaed952919014a7fdd5113d3fd25224
[tcpdump] / print-ntp.c
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 * Format and print ntp packets.
22 * By Jeffrey Mogul/DECWRL
23 * loosely based on print-bootp.c
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <tcpdump-stdinc.h>
31
32 #include <stdio.h>
33 #include <string.h>
34 #ifdef HAVE_STRFTIME
35 #include <time.h>
36 #endif
37
38 #include "interface.h"
39 #include "addrtoname.h"
40 #include "extract.h"
41
42 /*
43 * Based on ntp.h from the U of MD implementation
44 * This file is based on Version 2 of the NTP spec (RFC1119).
45 */
46
47 /*
48 * Definitions for the masses
49 */
50 #define JAN_1970 2208988800U /* 1970 - 1900 in seconds */
51
52 /*
53 * Structure definitions for NTP fixed point values
54 *
55 * 0 1 2 3
56 * 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
57 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 * | Integer Part |
59 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 * | Fraction Part |
61 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 *
63 * 0 1 2 3
64 * 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
65 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 * | Integer Part | Fraction Part |
67 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68 */
69 struct l_fixedpt {
70 u_int32_t int_part;
71 u_int32_t fraction;
72 };
73
74 struct s_fixedpt {
75 u_int16_t int_part;
76 u_int16_t fraction;
77 };
78
79 /* rfc2030
80 * 1 2 3
81 * 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
82 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 * |LI | VN |Mode | Stratum | Poll | Precision |
84 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85 * | Root Delay |
86 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87 * | Root Dispersion |
88 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 * | Reference Identifier |
90 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91 * | |
92 * | Reference Timestamp (64) |
93 * | |
94 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 * | |
96 * | Originate Timestamp (64) |
97 * | |
98 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99 * | |
100 * | Receive Timestamp (64) |
101 * | |
102 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103 * | |
104 * | Transmit Timestamp (64) |
105 * | |
106 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107 * | Key Identifier (optional) (32) |
108 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109 * | |
110 * | |
111 * | Message Digest (optional) (128) |
112 * | |
113 * | |
114 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 */
116
117 struct ntpdata {
118 u_char status; /* status of local clock and leap info */
119 u_char stratum; /* Stratum level */
120 u_char ppoll; /* poll value */
121 int precision:8;
122 struct s_fixedpt root_delay;
123 struct s_fixedpt root_dispersion;
124 u_int32_t refid;
125 struct l_fixedpt ref_timestamp;
126 struct l_fixedpt org_timestamp;
127 struct l_fixedpt rec_timestamp;
128 struct l_fixedpt xmt_timestamp;
129 u_int32_t key_id;
130 u_int8_t message_digest[16];
131 };
132 /*
133 * Leap Second Codes (high order two bits)
134 */
135 #define NO_WARNING 0x00 /* no warning */
136 #define PLUS_SEC 0x40 /* add a second (61 seconds) */
137 #define MINUS_SEC 0x80 /* minus a second (59 seconds) */
138 #define ALARM 0xc0 /* alarm condition (clock unsynchronized) */
139
140 /*
141 * Clock Status Bits that Encode Version
142 */
143 #define NTPVERSION_1 0x08
144 #define VERSIONMASK 0x38
145 #define LEAPMASK 0xc0
146 #ifdef MODEMASK
147 #undef MODEMASK /* Solaris sucks */
148 #endif
149 #define MODEMASK 0x07
150
151 /*
152 * Code values
153 */
154 #define MODE_UNSPEC 0 /* unspecified */
155 #define MODE_SYM_ACT 1 /* symmetric active */
156 #define MODE_SYM_PAS 2 /* symmetric passive */
157 #define MODE_CLIENT 3 /* client */
158 #define MODE_SERVER 4 /* server */
159 #define MODE_BROADCAST 5 /* broadcast */
160 #define MODE_RES1 6 /* reserved */
161 #define MODE_RES2 7 /* reserved */
162
163 /*
164 * Stratum Definitions
165 */
166 #define UNSPECIFIED 0
167 #define PRIM_REF 1 /* radio clock */
168 #define INFO_QUERY 62 /* **** THIS implementation dependent **** */
169 #define INFO_REPLY 63 /* **** THIS implementation dependent **** */
170
171 static void p_sfix(const struct s_fixedpt *);
172 static void p_ntp_time(const struct l_fixedpt *);
173 static void p_ntp_delta(const struct l_fixedpt *, const struct l_fixedpt *);
174
175 static const struct tok ntp_mode_values[] = {
176 { MODE_UNSPEC, "unspecified" },
177 { MODE_SYM_ACT, "symmetric active" },
178 { MODE_SYM_PAS, "symmetric passive" },
179 { MODE_CLIENT, "Client" },
180 { MODE_SERVER, "Server" },
181 { MODE_BROADCAST, "Broadcast" },
182 { MODE_RES1, "Reserved" },
183 { MODE_RES2, "Reserved" },
184 { 0, NULL }
185 };
186
187 static const struct tok ntp_leapind_values[] = {
188 { NO_WARNING, "" },
189 { PLUS_SEC, "+1s" },
190 { MINUS_SEC, "-1s" },
191 { ALARM, "clock unsynchronized" },
192 { 0, NULL }
193 };
194
195 static const struct tok ntp_stratum_values[] = {
196 { UNSPECIFIED, "unspecified" },
197 { PRIM_REF, "primary reference" },
198 { 0, NULL }
199 };
200
201 /*
202 * Print ntp requests
203 */
204 void
205 ntp_print(register const u_char *cp, u_int length)
206 {
207 register const struct ntpdata *bp;
208 int mode, version, leapind;
209
210 bp = (struct ntpdata *)cp;
211
212 TCHECK(bp->status);
213
214 version = (int)(bp->status & VERSIONMASK) >> 3;
215 printf("NTPv%d", version);
216
217 mode = bp->status & MODEMASK;
218 if (!vflag) {
219 printf (", %s, length %u",
220 tok2str(ntp_mode_values, "Unknown mode", mode),
221 length);
222 return;
223 }
224
225 printf (", length %u\n\t%s",
226 length,
227 tok2str(ntp_mode_values, "Unknown mode", mode));
228
229 leapind = bp->status & LEAPMASK;
230 printf (", Leap indicator: %s (%u)",
231 tok2str(ntp_leapind_values, "Unknown", leapind),
232 leapind);
233
234 TCHECK(bp->stratum);
235 printf(", Stratum %u (%s)",
236 bp->stratum,
237 tok2str(ntp_stratum_values, (bp->stratum >=2 && bp->stratum<=15) ? "secondary reference" : "reserved", bp->stratum));
238
239 TCHECK(bp->ppoll);
240 printf(", poll %u (%us)", bp->ppoll, 1 << bp->ppoll);
241
242 /* Can't TCHECK bp->precision bitfield so bp->distance + 0 instead */
243 TCHECK2(bp->root_delay, 0);
244 printf(", precision %d", bp->precision);
245
246 TCHECK(bp->root_delay);
247 fputs("\n\tRoot Delay: ", stdout);
248 p_sfix(&bp->root_delay);
249
250 TCHECK(bp->root_dispersion);
251 fputs(", Root dispersion: ", stdout);
252 p_sfix(&bp->root_dispersion);
253
254 TCHECK(bp->refid);
255 fputs(", Reference-ID: ", stdout);
256 /* Interpretation depends on stratum */
257 switch (bp->stratum) {
258
259 case UNSPECIFIED:
260 printf("(unspec)");
261 break;
262
263 case PRIM_REF:
264 if (fn_printn((u_char *)&(bp->refid), 4, snapend))
265 goto trunc;
266 break;
267
268 case INFO_QUERY:
269 printf("%s INFO_QUERY", ipaddr_string(&(bp->refid)));
270 /* this doesn't have more content */
271 return;
272
273 case INFO_REPLY:
274 printf("%s INFO_REPLY", ipaddr_string(&(bp->refid)));
275 /* this is too complex to be worth printing */
276 return;
277
278 default:
279 printf("%s", ipaddr_string(&(bp->refid)));
280 break;
281 }
282
283 TCHECK(bp->ref_timestamp);
284 fputs("\n\t Reference Timestamp: ", stdout);
285 p_ntp_time(&(bp->ref_timestamp));
286
287 TCHECK(bp->org_timestamp);
288 fputs("\n\t Originator Timestamp: ", stdout);
289 p_ntp_time(&(bp->org_timestamp));
290
291 TCHECK(bp->rec_timestamp);
292 fputs("\n\t Receive Timestamp: ", stdout);
293 p_ntp_time(&(bp->rec_timestamp));
294
295 TCHECK(bp->xmt_timestamp);
296 fputs("\n\t Transmit Timestamp: ", stdout);
297 p_ntp_time(&(bp->xmt_timestamp));
298
299 fputs("\n\t Originator - Receive Timestamp: ", stdout);
300 p_ntp_delta(&(bp->org_timestamp), &(bp->rec_timestamp));
301
302 fputs("\n\t Originator - Transmit Timestamp: ", stdout);
303 p_ntp_delta(&(bp->org_timestamp), &(bp->xmt_timestamp));
304
305 if ( (sizeof(struct ntpdata) - length) == 16) { /* Optional: key-id */
306 TCHECK(bp->key_id);
307 printf("\n\tKey id: %u", bp->key_id);
308 } else if ( (sizeof(struct ntpdata) - length) == 0) { /* Optional: key-id + authentication */
309 TCHECK(bp->key_id);
310 printf("\n\tKey id: %u", bp->key_id);
311 TCHECK2(bp->message_digest, sizeof (bp->message_digest));
312 printf("\n\tAuthentication: %08x%08x%08x%08x",
313 EXTRACT_32BITS(bp->message_digest),
314 EXTRACT_32BITS(bp->message_digest + 4),
315 EXTRACT_32BITS(bp->message_digest + 8),
316 EXTRACT_32BITS(bp->message_digest + 12));
317 }
318 return;
319
320 trunc:
321 fputs(" [|ntp]", stdout);
322 }
323
324 static void
325 p_sfix(register const struct s_fixedpt *sfp)
326 {
327 register int i;
328 register int f;
329 register float ff;
330
331 i = EXTRACT_16BITS(&sfp->int_part);
332 f = EXTRACT_16BITS(&sfp->fraction);
333 ff = f / 65536.0; /* shift radix point by 16 bits */
334 f = ff * 1000000.0; /* Treat fraction as parts per million */
335 printf("%d.%06d", i, f);
336 }
337
338 #define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */
339
340 static void
341 p_ntp_time(register const struct l_fixedpt *lfp)
342 {
343 register int32_t i;
344 register u_int32_t uf;
345 register u_int32_t f;
346 register float ff;
347
348 i = EXTRACT_32BITS(&lfp->int_part);
349 uf = EXTRACT_32BITS(&lfp->fraction);
350 ff = uf;
351 if (ff < 0.0) /* some compilers are buggy */
352 ff += FMAXINT;
353 ff = ff / FMAXINT; /* shift radix point by 32 bits */
354 f = ff * 1000000000.0; /* treat fraction as parts per billion */
355 printf("%u.%09d", i, f);
356
357 #ifdef HAVE_STRFTIME
358 /*
359 * print the time in human-readable format.
360 */
361 if (i) {
362 time_t seconds = i - JAN_1970;
363 struct tm *tm;
364 char time_buf[128];
365
366 tm = localtime(&seconds);
367 strftime(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", tm);
368 printf (" (%s)", time_buf);
369 }
370 #endif
371 }
372
373 /* Prints time difference between *lfp and *olfp */
374 static void
375 p_ntp_delta(register const struct l_fixedpt *olfp,
376 register const struct l_fixedpt *lfp)
377 {
378 register int32_t i;
379 register u_int32_t u, uf;
380 register u_int32_t ou, ouf;
381 register u_int32_t f;
382 register float ff;
383 int signbit;
384
385 u = EXTRACT_32BITS(&lfp->int_part);
386 ou = EXTRACT_32BITS(&olfp->int_part);
387 uf = EXTRACT_32BITS(&lfp->fraction);
388 ouf = EXTRACT_32BITS(&olfp->fraction);
389 if (ou == 0 && ouf == 0) {
390 p_ntp_time(lfp);
391 return;
392 }
393
394 i = u - ou;
395
396 if (i > 0) { /* new is definitely greater than old */
397 signbit = 0;
398 f = uf - ouf;
399 if (ouf > uf) /* must borrow from high-order bits */
400 i -= 1;
401 } else if (i < 0) { /* new is definitely less than old */
402 signbit = 1;
403 f = ouf - uf;
404 if (uf > ouf) /* must carry into the high-order bits */
405 i += 1;
406 i = -i;
407 } else { /* int_part is zero */
408 if (uf > ouf) {
409 signbit = 0;
410 f = uf - ouf;
411 } else {
412 signbit = 1;
413 f = ouf - uf;
414 }
415 }
416
417 ff = f;
418 if (ff < 0.0) /* some compilers are buggy */
419 ff += FMAXINT;
420 ff = ff / FMAXINT; /* shift radix point by 32 bits */
421 f = ff * 1000000000.0; /* treat fraction as parts per billion */
422 if (signbit)
423 putchar('-');
424 else
425 putchar('+');
426 printf("%d.%09d", i, f);
427 }
428