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