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
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.
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <sys/socket.h>
31 #include <sys/sysmacros.h>
32 #include <netinet/in.h>
41 * In verbose mode, how many octets of the control-mode data payload
42 * are displayed per line of output. The value 64 fits well on an
43 * 80-column screen and, as a power of 2, is easily correlated to
46 #define OCTETS_PER_LINE 64
48 extern char *dlc_header
;
50 static char *show_leap(int);
51 static char *show_mode(int);
52 static char *show_ref(int, ulong_t
);
53 static char *show_time(struct l_fixedpt
);
54 static double s_fixed_to_double(struct s_fixedpt
*);
55 static char *iso_date_time(time_t);
56 static char *show_operation(int);
59 interpret_ntp(int flags
, struct ntpdata
*ntp_pkt
, int fraglen
)
61 unsigned int i
, j
, macbytes
;
62 unsigned int proto_version
;
64 unsigned int linelen
= OCTETS_PER_LINE
;
65 unsigned int sofar
= 0;
68 char hbuf
[2 * MAC_OCTETS_MAX
+ 1];
69 static char *hexstr
= "0123456789ABCDEF";
72 struct ntpdata ntp_msg
;
74 struct ntp_control chdr
;
75 uchar_t data2
[NTPC_DATA_MAXLEN
- 1];
78 struct ntp_private phdr
;
83 struct ntpdata
*ntp
= &fragbuf
.ntp_msg
;
84 struct ntp_control
*ntpc
= (struct ntp_control
*)&fragbuf
.ntpc_msg
;
85 struct ntp_private
*ntpp
= (struct ntp_private
*)&fragbuf
.ntpp_msg
;
88 * Copying packet contents into a local buffer avoids
89 * problems of interpretation if the packet is truncated.
91 (void) memcpy(&fragbuf
, ntp_pkt
, MIN(sizeof (fragbuf
), fraglen
));
94 switch (ntp
->li_vn_mode
& NTPMODEMASK
) {
100 (void) sprintf(get_sum_line(),
101 "NTP %s [st=%hd] (%s)",
102 show_mode(ntp
->li_vn_mode
& NTPMODEMASK
),
104 show_time(ntp
->xmt
));
107 (void) sprintf(get_sum_line(),
109 "(Flags/op=0x%02x Seq=%hu Status=0x%04hx Assoc=%hu)",
110 show_mode(ntpc
->li_vn_mode
& NTPMODEMASK
),
112 ntohs(ntpc
->sequence
),
114 ntohs(ntpc
->associd
));
117 (void) sprintf(get_sum_line(),
119 show_mode(ntpp
->rm_vn_mode
& NTPMODEMASK
));
124 proto_version
= (ntp
->li_vn_mode
& VERSIONMASK
) >> 3;
126 if (flags
& F_DTAIL
) {
127 show_header("NTP: ", "Network Time Protocol", fraglen
);
129 switch (ntp
->li_vn_mode
& NTPMODEMASK
) {
135 (void) sprintf(get_line((char *)(uintptr_t)ntp
->li_vn_mode
-
138 (int)(ntp
->li_vn_mode
& LEAPMASK
) >> 6,
139 show_leap(ntp
->li_vn_mode
& LEAPMASK
));
140 (void) sprintf(get_line((char *)(uintptr_t)ntp
->li_vn_mode
-
142 "Version = %lu", proto_version
);
143 (void) sprintf(get_line((char *)(uintptr_t)ntp
->li_vn_mode
-
146 ntp
->li_vn_mode
& NTPMODEMASK
,
147 show_mode(ntp
->li_vn_mode
& NTPMODEMASK
));
148 (void) sprintf(get_line((char *)(uintptr_t)ntp
->stratum
-
152 ntp
->stratum
== 0 ? "unspecified" :
153 ntp
->stratum
== 1 ? "primary reference" :
154 "secondary reference");
155 (void) sprintf(get_line((char *)(uintptr_t)ntp
->ppoll
-
156 dlc_header
, 1), "Poll = %hu", ntp
->ppoll
);
157 (void) sprintf(get_line((char *)(uintptr_t)ntp
->precision
-
159 "Precision = %d seconds",
161 (void) sprintf(get_line(
162 (char *)(uintptr_t)ntp
->distance
.int_part
-
164 "Synchronizing distance = 0x%04x.%04x (%f)",
165 ntohs(ntp
->distance
.int_part
),
166 ntohs(ntp
->distance
.fraction
),
167 s_fixed_to_double(&ntp
->distance
));
168 (void) sprintf(get_line(
169 (char *)(uintptr_t)ntp
->dispersion
.int_part
-
171 "Synchronizing dispersion = 0x%04x.%04x (%f)",
172 ntohs(ntp
->dispersion
.int_part
),
173 ntohs(ntp
->dispersion
.fraction
),
174 s_fixed_to_double(&ntp
->dispersion
));
175 (void) sprintf(get_line((char *)(uintptr_t)ntp
->refid
-
176 dlc_header
, 1), "Reference clock = %s",
177 show_ref(ntp
->stratum
, ntp
->refid
));
179 (void) sprintf(get_line(
180 (char *)(uintptr_t)ntp
->reftime
.int_part
- dlc_header
,
181 1), "Reference time = 0x%08lx.%08lx (%s)",
182 ntohl(ntp
->reftime
.int_part
),
183 ntohl(ntp
->reftime
.fraction
),
184 show_time(ntp
->reftime
));
186 (void) sprintf(get_line(
187 (char *)(uintptr_t)ntp
->org
.int_part
- dlc_header
, 1),
188 "Originate time = 0x%08lx.%08lx (%s)",
189 ntohl(ntp
->org
.int_part
),
190 ntohl(ntp
->org
.fraction
),
191 show_time(ntp
->org
));
193 (void) sprintf(get_line(
194 (char *)(uintptr_t)ntp
->rec
.int_part
- dlc_header
, 1),
195 "Receive time = 0x%08lx.%08lx (%s)",
196 ntohl(ntp
->rec
.int_part
),
197 ntohl(ntp
->rec
.fraction
),
198 show_time(ntp
->rec
));
200 (void) sprintf(get_line(
201 (char *)(uintptr_t)ntp
->xmt
.int_part
- dlc_header
, 1),
202 "Transmit time = 0x%08lx.%08lx (%s)",
203 ntohl(ntp
->xmt
.int_part
),
204 ntohl(ntp
->xmt
.fraction
),
205 show_time(ntp
->xmt
));
207 if (proto_version
> 3 ||
208 fraglen
< (LEN_PKT_NOMAC
+ MAC_OCTETS_MIN
)) {
210 * A newer protocol version we can't parse,
211 * or v3 packet with no valid authentication.
215 (void) sprintf(get_line((char *)ntp
->keyid
-
217 "Key ID = %8lu", ntohl(ntp
->keyid
));
219 macbytes
= fraglen
- (LEN_PKT_NOMAC
+ sizeof (uint32_t));
221 for (i
= 0, j
= 0; i
< macbytes
; i
++) {
222 hbuf
[j
++] = hexstr
[ntp
->mac
[i
] >> 4 & 0x0f];
223 hbuf
[j
++] = hexstr
[ntp
->mac
[i
] & 0x0f];
226 (void) sprintf(get_line((char *)ntp
->mac
-
228 "Authentication code = %s", hbuf
);
232 /* NTP Control Message, mode 6 */
234 (void) sprintf(get_line((char *)(uintptr_t)ntp
->li_vn_mode
-
237 (int)(ntp
->li_vn_mode
& LEAPMASK
) >> 6,
238 show_leap(ntp
->li_vn_mode
& LEAPMASK
));
239 (void) sprintf(get_line((char *)(uintptr_t)ntp
->li_vn_mode
-
241 "Version = %lu", proto_version
);
242 (void) sprintf(get_line((char *)(uintptr_t)ntp
->li_vn_mode
-
245 ntp
->li_vn_mode
& NTPMODEMASK
,
246 show_mode(ntp
->li_vn_mode
& NTPMODEMASK
));
247 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->r_m_e_op
-
249 "Flags and operation code = 0x%02x",
251 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->r_m_e_op
-
254 getflag(ntpc
->r_m_e_op
, CTL_RESPONSE
, "response",
256 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->r_m_e_op
-
259 getflag(ntpc
->r_m_e_op
, CTL_ERROR
, "error",
261 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->r_m_e_op
-
264 getflag(ntpc
->r_m_e_op
, CTL_MORE
, "more",
266 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->r_m_e_op
-
268 " ...x xxxx = %hd (%s)",
269 ntpc
->r_m_e_op
& CTL_OP_MASK
,
270 show_operation(ntpc
->r_m_e_op
& CTL_OP_MASK
));
271 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->sequence
-
274 ntohs(ntpc
->sequence
));
275 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->status
-
278 ntohs(ntpc
->status
));
279 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->associd
-
282 ntohs(ntpc
->associd
));
283 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->offset
-
286 ntohs(ntpc
->offset
));
287 (void) sprintf(get_line((char *)(uintptr_t)ntpc
->count
-
291 datalen
= ntohs(ntpc
->count
);
294 } else if (datalen
> NTPC_DATA_MAXLEN
) {
295 datalen
= NTPC_DATA_MAXLEN
;
298 datap
= (char *)ntpc
->data
;
300 (void) sprintf(get_line(datap
-
303 show_string(datap
, linelen
, datalen
));
306 if ((sofar
+ linelen
) > datalen
) {
307 linelen
= datalen
- sofar
;
309 } while (sofar
< datalen
);
314 /* NTP Private Message, mode 7 */
316 (void) sprintf(get_line(
317 (char *)(uintptr_t)ntpp
->rm_vn_mode
- dlc_header
, 1),
318 "Version = %hu", INFO_VERSION(ntpp
->rm_vn_mode
));
319 (void) sprintf(get_line(
320 (char *)(uintptr_t)ntpp
->rm_vn_mode
- dlc_header
, 1),
321 "Mode = %hu (%s)", INFO_MODE(ntpp
->rm_vn_mode
),
322 show_mode(INFO_MODE(ntpp
->rm_vn_mode
)));
323 (void) sprintf(get_line(
324 (char *)(uintptr_t)ntpp
->rm_vn_mode
- dlc_header
, 1),
325 "Flags = 0x%02hx", ntpp
->rm_vn_mode
);
326 (void) sprintf(get_line(
327 (char *)(uintptr_t)ntpp
->rm_vn_mode
- dlc_header
, 1),
329 getflag(ntpp
->rm_vn_mode
, RESP_BIT
, "response",
331 (void) sprintf(get_line(
332 (char *)(uintptr_t)ntpp
->rm_vn_mode
- dlc_header
, 1),
334 getflag(ntpp
->rm_vn_mode
, MORE_BIT
, "more", "no more"));
335 (void) sprintf(get_line((char *)(uintptr_t)ntpp
->auth_seq
-
337 "Authentication and sequence = 0x%02x", ntpp
->auth_seq
);
338 (void) sprintf(get_line((char *)(uintptr_t)ntpp
->auth_seq
-
341 getflag(ntpp
->auth_seq
, AUTH_BIT
, "authenticated",
343 (void) sprintf(get_line((char *)(uintptr_t)ntpp
->auth_seq
-
345 " .xxx xxxx = %hu (sequence number)",
346 INFO_SEQ(ntpp
->auth_seq
));
347 (void) sprintf(get_line(
348 (char *)(uintptr_t)ntpp
->implementation
- dlc_header
,
349 1), "Implementation = %hu", ntpp
->implementation
);
350 (void) sprintf(get_line((char *)(uintptr_t)ntpp
->request
-
351 dlc_header
, 1), "Request = %hu", ntpp
->request
);
352 (void) sprintf(get_line(
353 (char *)(uintptr_t)ntpp
->err_nitems
- dlc_header
, 1),
354 "Error = %hu", INFO_ERR(ntpp
->err_nitems
));
355 (void) sprintf(get_line(
356 (char *)(uintptr_t)ntpp
->err_nitems
- dlc_header
, 1),
357 "Items = %hu", INFO_NITEMS(ntpp
->err_nitems
));
358 (void) sprintf(get_line(
359 (char *)(uintptr_t)ntpp
->mbz_itemsize
- dlc_header
, 1),
360 "Item size = %hu", INFO_ITEMSIZE(ntpp
->mbz_itemsize
));
365 (void) sprintf(get_line((char *)(uintptr_t)ntp
->li_vn_mode
-
366 dlc_header
, 1), "Mode = %hu (%s)",
367 ntp
->li_vn_mode
& NTPMODEMASK
,
368 show_mode(ntp
->li_vn_mode
& NTPMODEMASK
));
380 case NO_WARNING
: return ("OK");
381 case PLUS_SEC
: return ("add a second (61 seconds)");
382 case MINUS_SEC
: return ("minus a second (59 seconds)");
383 case ALARM
: return ("alarm condition (clock unsynchronized)");
384 default: return ("unknown");
392 case MODE_UNSPEC
: return ("unspecified");
393 case MODE_SYM_ACT
: return ("symmetric active");
394 case MODE_SYM_PAS
: return ("symmetric passive");
395 case MODE_CLIENT
: return ("client");
396 case MODE_SERVER
: return ("server");
397 case MODE_BROADCAST
: return ("broadcast");
398 case MODE_CONTROL
: return ("control");
399 case MODE_PRIVATE
: return ("private");
400 default: return ("unknown");
405 show_ref(int mode
, ulong_t refid
)
407 static char buff
[MAXHOSTNAMELEN
+ 32];
409 extern char *inet_ntoa();
414 (void) strncpy(buff
, (char *)&refid
, 4);
420 (void) sprintf(buff
, "%s (%s)",
422 addrtoname(AF_INET
, &host
));
430 * Here we have to worry about the high order bit being signed
433 s_fixed_to_double(struct s_fixedpt
*t
)
437 if (ntohs(t
->int_part
) & 0x8000) {
438 a
= ntohs((int)(~t
->fraction
) & 0xFFFF);
439 a
= a
/ 65536.0; /* shift dec point over by 16 bits */
440 a
+= ntohs((int)(~t
->int_part
) & 0xFFFF);
443 a
= ntohs(t
->fraction
);
444 a
= a
/ 65536.0; /* shift dec point over by 16 bits */
445 a
+= ntohs(t
->int_part
);
451 * Consistent with RFC-3339, ISO 8601.
454 iso_date_time(time_t input_time
)
456 struct tm
*time_parts
;
457 static char tbuf
[sizeof ("yyyy-mm-dd hh:mm:ss")];
459 time_parts
= localtime(&input_time
);
460 (void) strftime(tbuf
, sizeof (tbuf
), "%Y-%m-%d %H:%M:%S", time_parts
);
465 * The base of NTP timestamps is 1900-01-01 00:00:00.00000
468 show_time(struct l_fixedpt pkt_time
)
470 struct l_fixedpt net_time
;
471 unsigned long fracsec
;
472 static char buff
[32];
474 if (pkt_time
.int_part
== 0) {
479 net_time
.int_part
= ntohl(pkt_time
.int_part
) - JAN_1970
;
480 net_time
.fraction
= ntohl(pkt_time
.fraction
);
482 fracsec
= net_time
.fraction
/ 42949; /* fract / (2**32/10**6) */
484 (void) strlcpy(buff
, iso_date_time(net_time
.int_part
), sizeof (buff
));
485 (void) snprintf(buff
, sizeof (buff
), "%s.%05lu", buff
, fracsec
);
491 show_operation(int op
)
494 case CTL_OP_UNSPEC
: return ("unspecified");
495 case CTL_OP_READSTAT
: return ("read stats");
496 case CTL_OP_READVAR
: return ("read var");
497 case CTL_OP_WRITEVAR
: return ("write var");
498 case CTL_OP_READCLOCK
: return ("read clock");
499 case CTL_OP_WRITECLOCK
: return ("write clock");
500 case CTL_OP_SETTRAP
: return ("set trap");
501 case CTL_OP_ASYNCMSG
: return ("async msg");
502 case CTL_OP_UNSETTRAP
: return ("unset trap");
503 default: return ("unknown");