1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <fcntl.h>
28 #include <sys/socket.h>
29 #include <sys/sysmacros.h>
30 #include <netinet/in.h>
31 #include <netdb.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <tzfile.h>
35 #include "snoop.h"
36 #include "ntp.h"
37
38 /*
39 * In verbose mode, how many octets of the control-mode data payload
40 * are displayed per line of output. The value 64 fits well on an
41 * 80-column screen and, as a power of 2, is easily correlated to
42 * hexadecimal output.
43 */
44 #define OCTETS_PER_LINE 64
45
46 extern char *dlc_header;
47
48 static char *show_leap(int);
49 static char *show_mode(int);
50 static char *show_ref(int, ulong_t);
51 static char *show_time(struct l_fixedpt);
52 static double s_fixed_to_double(struct s_fixedpt *);
53 static char *iso_date_time(time_t);
54 static char *show_operation(int);
55
56 int
interpret_ntp(int flags,struct ntpdata * ntp_pkt,int fraglen)57 interpret_ntp(int flags, struct ntpdata *ntp_pkt, int fraglen)
58 {
59 unsigned int i, j, macbytes;
60 unsigned int proto_version;
61 unsigned int datalen;
62 unsigned int linelen = OCTETS_PER_LINE;
63 unsigned int sofar = 0;
64
65 char *datap;
66 char hbuf[2 * MAC_OCTETS_MAX + 1];
67 static char *hexstr = "0123456789ABCDEF";
68
69 union ntp_pkt_buf {
70 struct ntpdata ntp_msg;
71 union ntpc_buf {
72 struct ntp_control chdr;
73 uchar_t data2[NTPC_DATA_MAXLEN - 1];
74 } ntpc_msg;
75 union ntpp_buf {
76 struct ntp_private phdr;
77 uchar_t data2[1];
78 } ntpp_msg;
79 } fragbuf;
80
81 struct ntpdata *ntp = &fragbuf.ntp_msg;
82 struct ntp_control *ntpc = (struct ntp_control *)&fragbuf.ntpc_msg;
83 struct ntp_private *ntpp = (struct ntp_private *)&fragbuf.ntpp_msg;
84
85 /*
86 * Copying packet contents into a local buffer avoids
87 * problems of interpretation if the packet is truncated.
88 */
89 (void) memcpy(&fragbuf, ntp_pkt, MIN(sizeof (fragbuf), fraglen));
90
91 if (flags & F_SUM) {
92 switch (ntp->li_vn_mode & NTPMODEMASK) {
93 case MODE_SYM_ACT:
94 case MODE_SYM_PAS:
95 case MODE_CLIENT:
96 case MODE_SERVER:
97 case MODE_BROADCAST:
98 (void) sprintf(get_sum_line(),
99 "NTP %s [st=%hd] (%s)",
100 show_mode(ntp->li_vn_mode & NTPMODEMASK),
101 ntp->stratum,
102 show_time(ntp->xmt));
103 break;
104 case MODE_CONTROL:
105 (void) sprintf(get_sum_line(),
106 "NTP %s "
107 "(Flags/op=0x%02x Seq=%hu Status=0x%04hx Assoc=%hu)",
108 show_mode(ntpc->li_vn_mode & NTPMODEMASK),
109 ntpc->r_m_e_op,
110 ntohs(ntpc->sequence),
111 ntohs(ntpc->status),
112 ntohs(ntpc->associd));
113 break;
114 default:
115 (void) sprintf(get_sum_line(),
116 "NTP %s",
117 show_mode(ntpp->rm_vn_mode & NTPMODEMASK));
118 break;
119 }
120 }
121
122 proto_version = (ntp->li_vn_mode & VERSIONMASK) >> 3;
123
124 if (flags & F_DTAIL) {
125 show_header("NTP: ", "Network Time Protocol", fraglen);
126 show_space();
127 switch (ntp->li_vn_mode & NTPMODEMASK) {
128 case MODE_SYM_ACT:
129 case MODE_SYM_PAS:
130 case MODE_CLIENT:
131 case MODE_SERVER:
132 case MODE_BROADCAST:
133 (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode -
134 dlc_header, 1),
135 "Leap = 0x%x (%s)",
136 (int)(ntp->li_vn_mode & LEAPMASK) >> 6,
137 show_leap(ntp->li_vn_mode & LEAPMASK));
138 (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode -
139 dlc_header, 1),
140 "Version = %lu", proto_version);
141 (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode -
142 dlc_header, 1),
143 "Mode = %hu (%s)",
144 ntp->li_vn_mode & NTPMODEMASK,
145 show_mode(ntp->li_vn_mode & NTPMODEMASK));
146 (void) sprintf(get_line((char *)(uintptr_t)ntp->stratum -
147 dlc_header, 1),
148 "Stratum = %d (%s)",
149 ntp->stratum,
150 ntp->stratum == 0 ? "unspecified" :
151 ntp->stratum == 1 ? "primary reference" :
152 "secondary reference");
153 (void) sprintf(get_line((char *)(uintptr_t)ntp->ppoll -
154 dlc_header, 1), "Poll = %hu", ntp->ppoll);
155 (void) sprintf(get_line((char *)(uintptr_t)ntp->precision -
156 dlc_header, 1),
157 "Precision = %d seconds",
158 ntp->precision);
159 (void) sprintf(get_line(
160 (char *)(uintptr_t)ntp->distance.int_part -
161 dlc_header, 1),
162 "Synchronizing distance = 0x%04x.%04x (%f)",
163 ntohs(ntp->distance.int_part),
164 ntohs(ntp->distance.fraction),
165 s_fixed_to_double(&ntp->distance));
166 (void) sprintf(get_line(
167 (char *)(uintptr_t)ntp->dispersion.int_part -
168 dlc_header, 1),
169 "Synchronizing dispersion = 0x%04x.%04x (%f)",
170 ntohs(ntp->dispersion.int_part),
171 ntohs(ntp->dispersion.fraction),
172 s_fixed_to_double(&ntp->dispersion));
173 (void) sprintf(get_line((char *)(uintptr_t)ntp->refid -
174 dlc_header, 1), "Reference clock = %s",
175 show_ref(ntp->stratum, ntp->refid));
176
177 (void) sprintf(get_line(
178 (char *)(uintptr_t)ntp->reftime.int_part - dlc_header,
179 1), "Reference time = 0x%08lx.%08lx (%s)",
180 ntohl(ntp->reftime.int_part),
181 ntohl(ntp->reftime.fraction),
182 show_time(ntp->reftime));
183
184 (void) sprintf(get_line(
185 (char *)(uintptr_t)ntp->org.int_part - dlc_header, 1),
186 "Originate time = 0x%08lx.%08lx (%s)",
187 ntohl(ntp->org.int_part),
188 ntohl(ntp->org.fraction),
189 show_time(ntp->org));
190
191 (void) sprintf(get_line(
192 (char *)(uintptr_t)ntp->rec.int_part - dlc_header, 1),
193 "Receive time = 0x%08lx.%08lx (%s)",
194 ntohl(ntp->rec.int_part),
195 ntohl(ntp->rec.fraction),
196 show_time(ntp->rec));
197
198 (void) sprintf(get_line(
199 (char *)(uintptr_t)ntp->xmt.int_part - dlc_header, 1),
200 "Transmit time = 0x%08lx.%08lx (%s)",
201 ntohl(ntp->xmt.int_part),
202 ntohl(ntp->xmt.fraction),
203 show_time(ntp->xmt));
204
205 if (proto_version > 3 ||
206 fraglen < (LEN_PKT_NOMAC + MAC_OCTETS_MIN)) {
207 /*
208 * A newer protocol version we can't parse,
209 * or v3 packet with no valid authentication.
210 */
211 break;
212 }
213 (void) sprintf(get_line((char *)ntp->keyid -
214 dlc_header, 1),
215 "Key ID = %8lu", ntohl(ntp->keyid));
216
217 macbytes = fraglen - (LEN_PKT_NOMAC + sizeof (uint32_t));
218
219 for (i = 0, j = 0; i < macbytes; i++) {
220 hbuf[j++] = hexstr[ntp->mac[i] >> 4 & 0x0f];
221 hbuf[j++] = hexstr[ntp->mac[i] & 0x0f];
222 }
223 hbuf[j] = '\0';
224 (void) sprintf(get_line((char *)ntp->mac -
225 dlc_header, 1),
226 "Authentication code = %s", hbuf);
227 break;
228
229 case MODE_CONTROL:
230 /* NTP Control Message, mode 6 */
231
232 (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode -
233 dlc_header, 1),
234 "Leap = 0x%x (%s)",
235 (int)(ntp->li_vn_mode & LEAPMASK) >> 6,
236 show_leap(ntp->li_vn_mode & LEAPMASK));
237 (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode -
238 dlc_header, 1),
239 "Version = %lu", proto_version);
240 (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode -
241 dlc_header, 1),
242 "Mode = %hu (%s)",
243 ntp->li_vn_mode & NTPMODEMASK,
244 show_mode(ntp->li_vn_mode & NTPMODEMASK));
245 (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op -
246 dlc_header, 1),
247 "Flags and operation code = 0x%02x",
248 ntpc->r_m_e_op);
249 (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op -
250 dlc_header, 1),
251 " %s",
252 getflag(ntpc->r_m_e_op, CTL_RESPONSE, "response",
253 "request"));
254 (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op -
255 dlc_header, 1),
256 " %s",
257 getflag(ntpc->r_m_e_op, CTL_ERROR, "error",
258 "success"));
259 (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op -
260 dlc_header, 1),
261 " %s",
262 getflag(ntpc->r_m_e_op, CTL_MORE, "more",
263 "no more"));
264 (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op -
265 dlc_header, 1),
266 " ...x xxxx = %hd (%s)",
267 ntpc->r_m_e_op & CTL_OP_MASK,
268 show_operation(ntpc->r_m_e_op & CTL_OP_MASK));
269 (void) sprintf(get_line((char *)(uintptr_t)ntpc->sequence -
270 dlc_header, 1),
271 "Sequence = %hu",
272 ntohs(ntpc->sequence));
273 (void) sprintf(get_line((char *)(uintptr_t)ntpc->status -
274 dlc_header, 1),
275 "Status = 0x%04hx",
276 ntohs(ntpc->status));
277 (void) sprintf(get_line((char *)(uintptr_t)ntpc->associd -
278 dlc_header, 1),
279 "Assoc ID = %hu",
280 ntohs(ntpc->associd));
281 (void) sprintf(get_line((char *)(uintptr_t)ntpc->offset -
282 dlc_header, 1),
283 "Data offset = %hu",
284 ntohs(ntpc->offset));
285 (void) sprintf(get_line((char *)(uintptr_t)ntpc->count -
286 dlc_header, 1),
287 "Data bytes = %hu",
288 ntohs(ntpc->count));
289 datalen = ntohs(ntpc->count);
290 if (datalen == 0) {
291 break;
292 } else if (datalen > NTPC_DATA_MAXLEN) {
293 datalen = NTPC_DATA_MAXLEN;
294 }
295 show_space();
296 datap = (char *)ntpc->data;
297 do {
298 (void) sprintf(get_line(datap -
299 dlc_header, 1),
300 "\"%s\"",
301 show_string(datap, linelen, datalen));
302 sofar += linelen;
303 datap += linelen;
304 if ((sofar + linelen) > datalen) {
305 linelen = datalen - sofar;
306 }
307 } while (sofar < datalen);
308 show_trailer();
309 break;
310
311 case MODE_PRIVATE:
312 /* NTP Private Message, mode 7 */
313
314 (void) sprintf(get_line(
315 (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1),
316 "Version = %hu", INFO_VERSION(ntpp->rm_vn_mode));
317 (void) sprintf(get_line(
318 (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1),
319 "Mode = %hu (%s)", INFO_MODE(ntpp->rm_vn_mode),
320 show_mode(INFO_MODE(ntpp->rm_vn_mode)));
321 (void) sprintf(get_line(
322 (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1),
323 "Flags = 0x%02hx", ntpp->rm_vn_mode);
324 (void) sprintf(get_line(
325 (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1),
326 " %s",
327 getflag(ntpp->rm_vn_mode, RESP_BIT, "response",
328 "request"));
329 (void) sprintf(get_line(
330 (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1),
331 " %s",
332 getflag(ntpp->rm_vn_mode, MORE_BIT, "more", "no more"));
333 (void) sprintf(get_line((char *)(uintptr_t)ntpp->auth_seq -
334 dlc_header, 1),
335 "Authentication and sequence = 0x%02x", ntpp->auth_seq);
336 (void) sprintf(get_line((char *)(uintptr_t)ntpp->auth_seq -
337 dlc_header, 1),
338 " %s",
339 getflag(ntpp->auth_seq, AUTH_BIT, "authenticated",
340 "unauthenticated"));
341 (void) sprintf(get_line((char *)(uintptr_t)ntpp->auth_seq -
342 dlc_header, 1),
343 " .xxx xxxx = %hu (sequence number)",
344 INFO_SEQ(ntpp->auth_seq));
345 (void) sprintf(get_line(
346 (char *)(uintptr_t)ntpp->implementation - dlc_header,
347 1), "Implementation = %hu", ntpp->implementation);
348 (void) sprintf(get_line((char *)(uintptr_t)ntpp->request -
349 dlc_header, 1), "Request = %hu", ntpp->request);
350 (void) sprintf(get_line(
351 (char *)(uintptr_t)ntpp->err_nitems - dlc_header, 1),
352 "Error = %hu", INFO_ERR(ntpp->err_nitems));
353 (void) sprintf(get_line(
354 (char *)(uintptr_t)ntpp->err_nitems - dlc_header, 1),
355 "Items = %hu", INFO_NITEMS(ntpp->err_nitems));
356 (void) sprintf(get_line(
357 (char *)(uintptr_t)ntpp->mbz_itemsize - dlc_header, 1),
358 "Item size = %hu", INFO_ITEMSIZE(ntpp->mbz_itemsize));
359 break;
360
361 default:
362 /* Unknown mode */
363 (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode -
364 dlc_header, 1), "Mode = %hu (%s)",
365 ntp->li_vn_mode & NTPMODEMASK,
366 show_mode(ntp->li_vn_mode & NTPMODEMASK));
367 break;
368 }
369 }
370
371 return (fraglen);
372 }
373
374 char *
show_leap(int leap)375 show_leap(int leap)
376 {
377 switch (leap) {
378 case NO_WARNING: return ("OK");
379 case PLUS_SEC: return ("add a second (61 seconds)");
380 case MINUS_SEC: return ("minus a second (59 seconds)");
381 case ALARM: return ("alarm condition (clock unsynchronized)");
382 default: return ("unknown");
383 }
384 }
385
386 char *
show_mode(int mode)387 show_mode(int mode)
388 {
389 switch (mode) {
390 case MODE_UNSPEC: return ("unspecified");
391 case MODE_SYM_ACT: return ("symmetric active");
392 case MODE_SYM_PAS: return ("symmetric passive");
393 case MODE_CLIENT: return ("client");
394 case MODE_SERVER: return ("server");
395 case MODE_BROADCAST: return ("broadcast");
396 case MODE_CONTROL: return ("control");
397 case MODE_PRIVATE: return ("private");
398 default: return ("unknown");
399 }
400 }
401
402 char *
show_ref(int mode,ulong_t refid)403 show_ref(int mode, ulong_t refid)
404 {
405 static char buff[MAXHOSTNAMELEN + 32];
406 struct in_addr host;
407 extern char *inet_ntoa();
408
409 switch (mode) {
410 case 0:
411 case 1:
412 (void) strncpy(buff, (char *)&refid, 4);
413 buff[4] = '\0';
414 break;
415
416 default:
417 host.s_addr = refid;
418 (void) sprintf(buff, "%s (%s)",
419 inet_ntoa(host),
420 addrtoname(AF_INET, &host));
421 break;
422 }
423
424 return (buff);
425 }
426
427 /*
428 * Here we have to worry about the high order bit being signed
429 */
430 double
s_fixed_to_double(struct s_fixedpt * t)431 s_fixed_to_double(struct s_fixedpt *t)
432 {
433 double a;
434
435 if (ntohs(t->int_part) & 0x8000) {
436 a = ntohs((int)(~t->fraction) & 0xFFFF);
437 a = a / 65536.0; /* shift dec point over by 16 bits */
438 a += ntohs((int)(~t->int_part) & 0xFFFF);
439 a = -a;
440 } else {
441 a = ntohs(t->fraction);
442 a = a / 65536.0; /* shift dec point over by 16 bits */
443 a += ntohs(t->int_part);
444 }
445 return (a);
446 }
447
448 /*
449 * Consistent with RFC-3339, ISO 8601.
450 */
451 char *
iso_date_time(time_t input_time)452 iso_date_time(time_t input_time)
453 {
454 struct tm *time_parts;
455 static char tbuf[sizeof ("yyyy-mm-dd hh:mm:ss")];
456
457 time_parts = localtime(&input_time);
458 (void) strftime(tbuf, sizeof (tbuf), "%Y-%m-%d %H:%M:%S", time_parts);
459 return (tbuf);
460 }
461
462 /*
463 * The base of NTP timestamps is 1900-01-01 00:00:00.00000
464 */
465 char *
show_time(struct l_fixedpt pkt_time)466 show_time(struct l_fixedpt pkt_time)
467 {
468 struct l_fixedpt net_time;
469 unsigned long fracsec;
470 static char buff[32];
471
472 if (pkt_time.int_part == 0) {
473 buff[0] = '\0';
474 return (buff);
475 }
476
477 net_time.int_part = ntohl(pkt_time.int_part) - JAN_1970;
478 net_time.fraction = ntohl(pkt_time.fraction);
479
480 fracsec = net_time.fraction / 42949; /* fract / (2**32/10**6) */
481
482 (void) snprintf(buff, sizeof (buff), "%s.%05lu",
483 iso_date_time(net_time.int_part), fracsec);
484
485 return (buff);
486 }
487
488 char *
show_operation(int op)489 show_operation(int op)
490 {
491 switch (op) {
492 case CTL_OP_UNSPEC: return ("unspecified");
493 case CTL_OP_READSTAT: return ("read stats");
494 case CTL_OP_READVAR: return ("read var");
495 case CTL_OP_WRITEVAR: return ("write var");
496 case CTL_OP_READCLOCK: return ("read clock");
497 case CTL_OP_WRITECLOCK: return ("write clock");
498 case CTL_OP_SETTRAP: return ("set trap");
499 case CTL_OP_ASYNCMSG: return ("async msg");
500 case CTL_OP_UNSETTRAP: return ("unset trap");
501 default: return ("unknown");
502 }
503 }
504