17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*2e3b6467Skcpoon * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <fcntl.h> 307c478bd9Sstevel@tonic-gate #include <sys/socket.h> 317c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 327c478bd9Sstevel@tonic-gate #include <netinet/in.h> 337c478bd9Sstevel@tonic-gate #include <netdb.h> 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <string.h> 367c478bd9Sstevel@tonic-gate #include <tzfile.h> 377c478bd9Sstevel@tonic-gate #include "snoop.h" 387c478bd9Sstevel@tonic-gate #include "ntp.h" 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * In verbose mode, how many octets of the control-mode data payload 427c478bd9Sstevel@tonic-gate * are displayed per line of output. The value 64 fits well on an 437c478bd9Sstevel@tonic-gate * 80-column screen and, as a power of 2, is easily correlated to 447c478bd9Sstevel@tonic-gate * hexadecimal output. 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate #define OCTETS_PER_LINE 64 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate extern char *dlc_header; 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate static char *show_leap(int); 517c478bd9Sstevel@tonic-gate static char *show_mode(int); 527c478bd9Sstevel@tonic-gate static char *show_ref(int, ulong_t); 537c478bd9Sstevel@tonic-gate static char *show_time(struct l_fixedpt); 547c478bd9Sstevel@tonic-gate static double s_fixed_to_double(struct s_fixedpt *); 557c478bd9Sstevel@tonic-gate static char *iso_date_time(time_t); 567c478bd9Sstevel@tonic-gate static char *show_operation(int); 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate int 597c478bd9Sstevel@tonic-gate interpret_ntp(int flags, struct ntpdata *ntp_pkt, int fraglen) 607c478bd9Sstevel@tonic-gate { 617c478bd9Sstevel@tonic-gate unsigned int i, j, macbytes; 627c478bd9Sstevel@tonic-gate unsigned int proto_version; 637c478bd9Sstevel@tonic-gate unsigned int datalen; 647c478bd9Sstevel@tonic-gate unsigned int linelen = OCTETS_PER_LINE; 657c478bd9Sstevel@tonic-gate unsigned int sofar = 0; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate char *datap; 687c478bd9Sstevel@tonic-gate char hbuf[2 * MAC_OCTETS_MAX + 1]; 697c478bd9Sstevel@tonic-gate static char *hexstr = "0123456789ABCDEF"; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate union ntp_pkt_buf { 727c478bd9Sstevel@tonic-gate struct ntpdata ntp_msg; 737c478bd9Sstevel@tonic-gate union ntpc_buf { 747c478bd9Sstevel@tonic-gate struct ntp_control chdr; 757c478bd9Sstevel@tonic-gate uchar_t data2[NTPC_DATA_MAXLEN - 1]; 767c478bd9Sstevel@tonic-gate } ntpc_msg; 777c478bd9Sstevel@tonic-gate union ntpp_buf { 787c478bd9Sstevel@tonic-gate struct ntp_private phdr; 797c478bd9Sstevel@tonic-gate uchar_t data2[1]; 807c478bd9Sstevel@tonic-gate } ntpp_msg; 817c478bd9Sstevel@tonic-gate } fragbuf; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate struct ntpdata *ntp = &fragbuf.ntp_msg; 847c478bd9Sstevel@tonic-gate struct ntp_control *ntpc = (struct ntp_control *)&fragbuf.ntpc_msg; 857c478bd9Sstevel@tonic-gate struct ntp_private *ntpp = (struct ntp_private *)&fragbuf.ntpp_msg; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * Copying packet contents into a local buffer avoids 897c478bd9Sstevel@tonic-gate * problems of interpretation if the packet is truncated. 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate (void) memcpy(&fragbuf, ntp_pkt, MIN(sizeof (fragbuf), fraglen)); 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 947c478bd9Sstevel@tonic-gate switch (ntp->li_vn_mode & NTPMODEMASK) { 957c478bd9Sstevel@tonic-gate case MODE_SYM_ACT: 967c478bd9Sstevel@tonic-gate case MODE_SYM_PAS: 977c478bd9Sstevel@tonic-gate case MODE_CLIENT: 987c478bd9Sstevel@tonic-gate case MODE_SERVER: 997c478bd9Sstevel@tonic-gate case MODE_BROADCAST: 1007c478bd9Sstevel@tonic-gate (void) sprintf(get_sum_line(), 1017c478bd9Sstevel@tonic-gate "NTP %s [st=%hd] (%s)", 1027c478bd9Sstevel@tonic-gate show_mode(ntp->li_vn_mode & NTPMODEMASK), 1037c478bd9Sstevel@tonic-gate ntp->stratum, 1047c478bd9Sstevel@tonic-gate show_time(ntp->xmt)); 1057c478bd9Sstevel@tonic-gate break; 1067c478bd9Sstevel@tonic-gate case MODE_CONTROL: 1077c478bd9Sstevel@tonic-gate (void) sprintf(get_sum_line(), 1087c478bd9Sstevel@tonic-gate "NTP %s " 1097c478bd9Sstevel@tonic-gate "(Flags/op=0x%02x Seq=%hu Status=0x%04hx Assoc=%hu)", 1107c478bd9Sstevel@tonic-gate show_mode(ntpc->li_vn_mode & NTPMODEMASK), 1117c478bd9Sstevel@tonic-gate ntpc->r_m_e_op, 1127c478bd9Sstevel@tonic-gate ntohs(ntpc->sequence), 1137c478bd9Sstevel@tonic-gate ntohs(ntpc->status), 1147c478bd9Sstevel@tonic-gate ntohs(ntpc->associd)); 1157c478bd9Sstevel@tonic-gate break; 1167c478bd9Sstevel@tonic-gate default: 1177c478bd9Sstevel@tonic-gate (void) sprintf(get_sum_line(), 1187c478bd9Sstevel@tonic-gate "NTP %s", 1197c478bd9Sstevel@tonic-gate show_mode(ntpp->rm_vn_mode & NTPMODEMASK)); 1207c478bd9Sstevel@tonic-gate break; 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate proto_version = (ntp->li_vn_mode & VERSIONMASK) >> 3; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate if (flags & F_DTAIL) { 1277c478bd9Sstevel@tonic-gate show_header("NTP: ", "Network Time Protocol", fraglen); 1287c478bd9Sstevel@tonic-gate show_space(); 1297c478bd9Sstevel@tonic-gate switch (ntp->li_vn_mode & NTPMODEMASK) { 1307c478bd9Sstevel@tonic-gate case MODE_SYM_ACT: 1317c478bd9Sstevel@tonic-gate case MODE_SYM_PAS: 1327c478bd9Sstevel@tonic-gate case MODE_CLIENT: 1337c478bd9Sstevel@tonic-gate case MODE_SERVER: 1347c478bd9Sstevel@tonic-gate case MODE_BROADCAST: 135*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode - 1367c478bd9Sstevel@tonic-gate dlc_header, 1), 1377c478bd9Sstevel@tonic-gate "Leap = 0x%x (%s)", 1387c478bd9Sstevel@tonic-gate (int)(ntp->li_vn_mode & LEAPMASK) >> 6, 1397c478bd9Sstevel@tonic-gate show_leap(ntp->li_vn_mode & LEAPMASK)); 140*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode - 1417c478bd9Sstevel@tonic-gate dlc_header, 1), 1427c478bd9Sstevel@tonic-gate "Version = %lu", proto_version); 143*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode - 1447c478bd9Sstevel@tonic-gate dlc_header, 1), 1457c478bd9Sstevel@tonic-gate "Mode = %hu (%s)", 1467c478bd9Sstevel@tonic-gate ntp->li_vn_mode & NTPMODEMASK, 1477c478bd9Sstevel@tonic-gate show_mode(ntp->li_vn_mode & NTPMODEMASK)); 148*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->stratum - 1497c478bd9Sstevel@tonic-gate dlc_header, 1), 1507c478bd9Sstevel@tonic-gate "Stratum = %d (%s)", 1517c478bd9Sstevel@tonic-gate ntp->stratum, 1527c478bd9Sstevel@tonic-gate ntp->stratum == 0 ? "unspecified" : 1537c478bd9Sstevel@tonic-gate ntp->stratum == 1 ? "primary reference" : 1547c478bd9Sstevel@tonic-gate "secondary reference"); 155*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->ppoll - 156*2e3b6467Skcpoon dlc_header, 1), "Poll = %hu", ntp->ppoll); 157*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->precision - 1587c478bd9Sstevel@tonic-gate dlc_header, 1), 1597c478bd9Sstevel@tonic-gate "Precision = %d seconds", 1607c478bd9Sstevel@tonic-gate ntp->precision); 161*2e3b6467Skcpoon (void) sprintf(get_line( 162*2e3b6467Skcpoon (char *)(uintptr_t)ntp->distance.int_part - 1637c478bd9Sstevel@tonic-gate dlc_header, 1), 1647c478bd9Sstevel@tonic-gate "Synchronizing distance = 0x%04x.%04x (%f)", 1657c478bd9Sstevel@tonic-gate ntohs(ntp->distance.int_part), 1667c478bd9Sstevel@tonic-gate ntohs(ntp->distance.fraction), 1677c478bd9Sstevel@tonic-gate s_fixed_to_double(&ntp->distance)); 168*2e3b6467Skcpoon (void) sprintf(get_line( 169*2e3b6467Skcpoon (char *)(uintptr_t)ntp->dispersion.int_part - 1707c478bd9Sstevel@tonic-gate dlc_header, 1), 1717c478bd9Sstevel@tonic-gate "Synchronizing dispersion = 0x%04x.%04x (%f)", 1727c478bd9Sstevel@tonic-gate ntohs(ntp->dispersion.int_part), 1737c478bd9Sstevel@tonic-gate ntohs(ntp->dispersion.fraction), 1747c478bd9Sstevel@tonic-gate s_fixed_to_double(&ntp->dispersion)); 175*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->refid - 176*2e3b6467Skcpoon dlc_header, 1), "Reference clock = %s", 1777c478bd9Sstevel@tonic-gate show_ref(ntp->stratum, ntp->refid)); 1787c478bd9Sstevel@tonic-gate 179*2e3b6467Skcpoon (void) sprintf(get_line( 180*2e3b6467Skcpoon (char *)(uintptr_t)ntp->reftime.int_part - dlc_header, 181*2e3b6467Skcpoon 1), "Reference time = 0x%08lx.%08lx (%s)", 1827c478bd9Sstevel@tonic-gate ntohl(ntp->reftime.int_part), 1837c478bd9Sstevel@tonic-gate ntohl(ntp->reftime.fraction), 1847c478bd9Sstevel@tonic-gate show_time(ntp->reftime)); 1857c478bd9Sstevel@tonic-gate 186*2e3b6467Skcpoon (void) sprintf(get_line( 187*2e3b6467Skcpoon (char *)(uintptr_t)ntp->org.int_part - dlc_header, 1), 1887c478bd9Sstevel@tonic-gate "Originate time = 0x%08lx.%08lx (%s)", 1897c478bd9Sstevel@tonic-gate ntohl(ntp->org.int_part), 1907c478bd9Sstevel@tonic-gate ntohl(ntp->org.fraction), 1917c478bd9Sstevel@tonic-gate show_time(ntp->org)); 1927c478bd9Sstevel@tonic-gate 193*2e3b6467Skcpoon (void) sprintf(get_line( 194*2e3b6467Skcpoon (char *)(uintptr_t)ntp->rec.int_part - dlc_header, 1), 1957c478bd9Sstevel@tonic-gate "Receive time = 0x%08lx.%08lx (%s)", 1967c478bd9Sstevel@tonic-gate ntohl(ntp->rec.int_part), 1977c478bd9Sstevel@tonic-gate ntohl(ntp->rec.fraction), 1987c478bd9Sstevel@tonic-gate show_time(ntp->rec)); 1997c478bd9Sstevel@tonic-gate 200*2e3b6467Skcpoon (void) sprintf(get_line( 201*2e3b6467Skcpoon (char *)(uintptr_t)ntp->xmt.int_part - dlc_header, 1), 2027c478bd9Sstevel@tonic-gate "Transmit time = 0x%08lx.%08lx (%s)", 2037c478bd9Sstevel@tonic-gate ntohl(ntp->xmt.int_part), 2047c478bd9Sstevel@tonic-gate ntohl(ntp->xmt.fraction), 2057c478bd9Sstevel@tonic-gate show_time(ntp->xmt)); 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if (proto_version > 3 || 2087c478bd9Sstevel@tonic-gate fraglen < (LEN_PKT_NOMAC + MAC_OCTETS_MIN)) { 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * A newer protocol version we can't parse, 2117c478bd9Sstevel@tonic-gate * or v3 packet with no valid authentication. 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate break; 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate (void) sprintf(get_line((char *)ntp->keyid - 2167c478bd9Sstevel@tonic-gate dlc_header, 1), 2177c478bd9Sstevel@tonic-gate "Key ID = %8lu", ntohl(ntp->keyid)); 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate macbytes = fraglen - (LEN_PKT_NOMAC + sizeof (uint32_t)); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate for (i = 0, j = 0; i < macbytes; i++) { 2227c478bd9Sstevel@tonic-gate hbuf[j++] = hexstr[ntp->mac[i] >> 4 & 0x0f]; 2237c478bd9Sstevel@tonic-gate hbuf[j++] = hexstr[ntp->mac[i] & 0x0f]; 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate hbuf[j] = '\0'; 2267c478bd9Sstevel@tonic-gate (void) sprintf(get_line((char *)ntp->mac - 2277c478bd9Sstevel@tonic-gate dlc_header, 1), 2287c478bd9Sstevel@tonic-gate "Authentication code = %s", hbuf); 2297c478bd9Sstevel@tonic-gate break; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate case MODE_CONTROL: 2327c478bd9Sstevel@tonic-gate /* NTP Control Message, mode 6 */ 2337c478bd9Sstevel@tonic-gate 234*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode - 2357c478bd9Sstevel@tonic-gate dlc_header, 1), 2367c478bd9Sstevel@tonic-gate "Leap = 0x%x (%s)", 2377c478bd9Sstevel@tonic-gate (int)(ntp->li_vn_mode & LEAPMASK) >> 6, 2387c478bd9Sstevel@tonic-gate show_leap(ntp->li_vn_mode & LEAPMASK)); 239*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode - 2407c478bd9Sstevel@tonic-gate dlc_header, 1), 2417c478bd9Sstevel@tonic-gate "Version = %lu", proto_version); 242*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode - 2437c478bd9Sstevel@tonic-gate dlc_header, 1), 2447c478bd9Sstevel@tonic-gate "Mode = %hu (%s)", 2457c478bd9Sstevel@tonic-gate ntp->li_vn_mode & NTPMODEMASK, 2467c478bd9Sstevel@tonic-gate show_mode(ntp->li_vn_mode & NTPMODEMASK)); 247*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op - 2487c478bd9Sstevel@tonic-gate dlc_header, 1), 2497c478bd9Sstevel@tonic-gate "Flags and operation code = 0x%02x", 2507c478bd9Sstevel@tonic-gate ntpc->r_m_e_op); 251*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op - 2527c478bd9Sstevel@tonic-gate dlc_header, 1), 2537c478bd9Sstevel@tonic-gate " %s", 2547c478bd9Sstevel@tonic-gate getflag(ntpc->r_m_e_op, CTL_RESPONSE, "response", 2557c478bd9Sstevel@tonic-gate "request")); 256*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op - 2577c478bd9Sstevel@tonic-gate dlc_header, 1), 2587c478bd9Sstevel@tonic-gate " %s", 2597c478bd9Sstevel@tonic-gate getflag(ntpc->r_m_e_op, CTL_ERROR, "error", 2607c478bd9Sstevel@tonic-gate "success")); 261*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op - 2627c478bd9Sstevel@tonic-gate dlc_header, 1), 2637c478bd9Sstevel@tonic-gate " %s", 2647c478bd9Sstevel@tonic-gate getflag(ntpc->r_m_e_op, CTL_MORE, "more", 2657c478bd9Sstevel@tonic-gate "no more")); 266*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->r_m_e_op - 2677c478bd9Sstevel@tonic-gate dlc_header, 1), 2687c478bd9Sstevel@tonic-gate " ...x xxxx = %hd (%s)", 2697c478bd9Sstevel@tonic-gate ntpc->r_m_e_op & CTL_OP_MASK, 2707c478bd9Sstevel@tonic-gate show_operation(ntpc->r_m_e_op & CTL_OP_MASK)); 271*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->sequence - 2727c478bd9Sstevel@tonic-gate dlc_header, 1), 2737c478bd9Sstevel@tonic-gate "Sequence = %hu", 2747c478bd9Sstevel@tonic-gate ntohs(ntpc->sequence)); 275*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->status - 2767c478bd9Sstevel@tonic-gate dlc_header, 1), 2777c478bd9Sstevel@tonic-gate "Status = 0x%04hx", 2787c478bd9Sstevel@tonic-gate ntohs(ntpc->status)); 279*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->associd - 2807c478bd9Sstevel@tonic-gate dlc_header, 1), 2817c478bd9Sstevel@tonic-gate "Assoc ID = %hu", 2827c478bd9Sstevel@tonic-gate ntohs(ntpc->associd)); 283*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->offset - 2847c478bd9Sstevel@tonic-gate dlc_header, 1), 2857c478bd9Sstevel@tonic-gate "Data offset = %hu", 2867c478bd9Sstevel@tonic-gate ntohs(ntpc->offset)); 287*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpc->count - 2887c478bd9Sstevel@tonic-gate dlc_header, 1), 2897c478bd9Sstevel@tonic-gate "Data bytes = %hu", 2907c478bd9Sstevel@tonic-gate ntohs(ntpc->count)); 2917c478bd9Sstevel@tonic-gate datalen = ntohs(ntpc->count); 2927c478bd9Sstevel@tonic-gate if (datalen == 0) { 2937c478bd9Sstevel@tonic-gate break; 2947c478bd9Sstevel@tonic-gate } else if (datalen > NTPC_DATA_MAXLEN) { 2957c478bd9Sstevel@tonic-gate datalen = NTPC_DATA_MAXLEN; 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate show_space(); 2987c478bd9Sstevel@tonic-gate datap = (char *)ntpc->data; 2997c478bd9Sstevel@tonic-gate do { 3007c478bd9Sstevel@tonic-gate (void) sprintf(get_line(datap - 3017c478bd9Sstevel@tonic-gate dlc_header, 1), 3027c478bd9Sstevel@tonic-gate "\"%s\"", 3037c478bd9Sstevel@tonic-gate show_string(datap, linelen, datalen)); 3047c478bd9Sstevel@tonic-gate sofar += linelen; 3057c478bd9Sstevel@tonic-gate datap += linelen; 3067c478bd9Sstevel@tonic-gate if ((sofar + linelen) > datalen) { 3077c478bd9Sstevel@tonic-gate linelen = datalen - sofar; 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate } while (sofar < datalen); 3107c478bd9Sstevel@tonic-gate show_trailer(); 3117c478bd9Sstevel@tonic-gate break; 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate case MODE_PRIVATE: 3147c478bd9Sstevel@tonic-gate /* NTP Private Message, mode 7 */ 3157c478bd9Sstevel@tonic-gate 316*2e3b6467Skcpoon (void) sprintf(get_line( 317*2e3b6467Skcpoon (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1), 318*2e3b6467Skcpoon "Version = %hu", INFO_VERSION(ntpp->rm_vn_mode)); 319*2e3b6467Skcpoon (void) sprintf(get_line( 320*2e3b6467Skcpoon (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1), 321*2e3b6467Skcpoon "Mode = %hu (%s)", INFO_MODE(ntpp->rm_vn_mode), 3227c478bd9Sstevel@tonic-gate show_mode(INFO_MODE(ntpp->rm_vn_mode))); 323*2e3b6467Skcpoon (void) sprintf(get_line( 324*2e3b6467Skcpoon (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1), 325*2e3b6467Skcpoon "Flags = 0x%02hx", ntpp->rm_vn_mode); 326*2e3b6467Skcpoon (void) sprintf(get_line( 327*2e3b6467Skcpoon (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1), 3287c478bd9Sstevel@tonic-gate " %s", 3297c478bd9Sstevel@tonic-gate getflag(ntpp->rm_vn_mode, RESP_BIT, "response", 3307c478bd9Sstevel@tonic-gate "request")); 331*2e3b6467Skcpoon (void) sprintf(get_line( 332*2e3b6467Skcpoon (char *)(uintptr_t)ntpp->rm_vn_mode - dlc_header, 1), 3337c478bd9Sstevel@tonic-gate " %s", 334*2e3b6467Skcpoon getflag(ntpp->rm_vn_mode, MORE_BIT, "more", "no more")); 335*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpp->auth_seq - 3367c478bd9Sstevel@tonic-gate dlc_header, 1), 337*2e3b6467Skcpoon "Authentication and sequence = 0x%02x", ntpp->auth_seq); 338*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpp->auth_seq - 3397c478bd9Sstevel@tonic-gate dlc_header, 1), 3407c478bd9Sstevel@tonic-gate " %s", 3417c478bd9Sstevel@tonic-gate getflag(ntpp->auth_seq, AUTH_BIT, "authenticated", 3427c478bd9Sstevel@tonic-gate "unauthenticated")); 343*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpp->auth_seq - 3447c478bd9Sstevel@tonic-gate dlc_header, 1), 3457c478bd9Sstevel@tonic-gate " .xxx xxxx = %hu (sequence number)", 3467c478bd9Sstevel@tonic-gate INFO_SEQ(ntpp->auth_seq)); 347*2e3b6467Skcpoon (void) sprintf(get_line( 348*2e3b6467Skcpoon (char *)(uintptr_t)ntpp->implementation - dlc_header, 349*2e3b6467Skcpoon 1), "Implementation = %hu", ntpp->implementation); 350*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntpp->request - 351*2e3b6467Skcpoon dlc_header, 1), "Request = %hu", ntpp->request); 352*2e3b6467Skcpoon (void) sprintf(get_line( 353*2e3b6467Skcpoon (char *)(uintptr_t)ntpp->err_nitems - dlc_header, 1), 354*2e3b6467Skcpoon "Error = %hu", INFO_ERR(ntpp->err_nitems)); 355*2e3b6467Skcpoon (void) sprintf(get_line( 356*2e3b6467Skcpoon (char *)(uintptr_t)ntpp->err_nitems - dlc_header, 1), 357*2e3b6467Skcpoon "Items = %hu", INFO_NITEMS(ntpp->err_nitems)); 358*2e3b6467Skcpoon (void) sprintf(get_line( 359*2e3b6467Skcpoon (char *)(uintptr_t)ntpp->mbz_itemsize - dlc_header, 1), 360*2e3b6467Skcpoon "Item size = %hu", INFO_ITEMSIZE(ntpp->mbz_itemsize)); 3617c478bd9Sstevel@tonic-gate break; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate default: 3647c478bd9Sstevel@tonic-gate /* Unknown mode */ 365*2e3b6467Skcpoon (void) sprintf(get_line((char *)(uintptr_t)ntp->li_vn_mode - 366*2e3b6467Skcpoon dlc_header, 1), "Mode = %hu (%s)", 3677c478bd9Sstevel@tonic-gate ntp->li_vn_mode & NTPMODEMASK, 3687c478bd9Sstevel@tonic-gate show_mode(ntp->li_vn_mode & NTPMODEMASK)); 3697c478bd9Sstevel@tonic-gate break; 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate return (fraglen); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate char * 3777c478bd9Sstevel@tonic-gate show_leap(int leap) 3787c478bd9Sstevel@tonic-gate { 3797c478bd9Sstevel@tonic-gate switch (leap) { 3807c478bd9Sstevel@tonic-gate case NO_WARNING: return ("OK"); 3817c478bd9Sstevel@tonic-gate case PLUS_SEC: return ("add a second (61 seconds)"); 3827c478bd9Sstevel@tonic-gate case MINUS_SEC: return ("minus a second (59 seconds)"); 3837c478bd9Sstevel@tonic-gate case ALARM: return ("alarm condition (clock unsynchronized)"); 3847c478bd9Sstevel@tonic-gate default: return ("unknown"); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate char * 3897c478bd9Sstevel@tonic-gate show_mode(int mode) 3907c478bd9Sstevel@tonic-gate { 3917c478bd9Sstevel@tonic-gate switch (mode) { 3927c478bd9Sstevel@tonic-gate case MODE_UNSPEC: return ("unspecified"); 3937c478bd9Sstevel@tonic-gate case MODE_SYM_ACT: return ("symmetric active"); 3947c478bd9Sstevel@tonic-gate case MODE_SYM_PAS: return ("symmetric passive"); 3957c478bd9Sstevel@tonic-gate case MODE_CLIENT: return ("client"); 3967c478bd9Sstevel@tonic-gate case MODE_SERVER: return ("server"); 3977c478bd9Sstevel@tonic-gate case MODE_BROADCAST: return ("broadcast"); 3987c478bd9Sstevel@tonic-gate case MODE_CONTROL: return ("control"); 3997c478bd9Sstevel@tonic-gate case MODE_PRIVATE: return ("private"); 4007c478bd9Sstevel@tonic-gate default: return ("unknown"); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate char * 4057c478bd9Sstevel@tonic-gate show_ref(int mode, ulong_t refid) 4067c478bd9Sstevel@tonic-gate { 4077c478bd9Sstevel@tonic-gate static char buff[MAXHOSTNAMELEN + 32]; 4087c478bd9Sstevel@tonic-gate struct in_addr host; 4097c478bd9Sstevel@tonic-gate extern char *inet_ntoa(); 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate switch (mode) { 4127c478bd9Sstevel@tonic-gate case 0: 4137c478bd9Sstevel@tonic-gate case 1: 4147c478bd9Sstevel@tonic-gate (void) strncpy(buff, (char *)&refid, 4); 4157c478bd9Sstevel@tonic-gate buff[4] = '\0'; 4167c478bd9Sstevel@tonic-gate break; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate default: 4197c478bd9Sstevel@tonic-gate host.s_addr = refid; 4207c478bd9Sstevel@tonic-gate (void) sprintf(buff, "%s (%s)", 4217c478bd9Sstevel@tonic-gate inet_ntoa(host), 4227c478bd9Sstevel@tonic-gate addrtoname(AF_INET, &host)); 4237c478bd9Sstevel@tonic-gate break; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate return (buff); 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate /* 4307c478bd9Sstevel@tonic-gate * Here we have to worry about the high order bit being signed 4317c478bd9Sstevel@tonic-gate */ 4327c478bd9Sstevel@tonic-gate double 4337c478bd9Sstevel@tonic-gate s_fixed_to_double(struct s_fixedpt *t) 4347c478bd9Sstevel@tonic-gate { 4357c478bd9Sstevel@tonic-gate double a; 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if (ntohs(t->int_part) & 0x8000) { 4387c478bd9Sstevel@tonic-gate a = ntohs((int)(~t->fraction) & 0xFFFF); 4397c478bd9Sstevel@tonic-gate a = a / 65536.0; /* shift dec point over by 16 bits */ 4407c478bd9Sstevel@tonic-gate a += ntohs((int)(~t->int_part) & 0xFFFF); 4417c478bd9Sstevel@tonic-gate a = -a; 4427c478bd9Sstevel@tonic-gate } else { 4437c478bd9Sstevel@tonic-gate a = ntohs(t->fraction); 4447c478bd9Sstevel@tonic-gate a = a / 65536.0; /* shift dec point over by 16 bits */ 4457c478bd9Sstevel@tonic-gate a += ntohs(t->int_part); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate return (a); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* 4517c478bd9Sstevel@tonic-gate * Consistent with RFC-3339, ISO 8601. 4527c478bd9Sstevel@tonic-gate */ 4537c478bd9Sstevel@tonic-gate char * 4547c478bd9Sstevel@tonic-gate iso_date_time(time_t input_time) 4557c478bd9Sstevel@tonic-gate { 4567c478bd9Sstevel@tonic-gate struct tm *time_parts; 4577c478bd9Sstevel@tonic-gate static char tbuf[sizeof ("yyyy-mm-dd hh:mm:ss")]; 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate time_parts = localtime(&input_time); 4607c478bd9Sstevel@tonic-gate (void) strftime(tbuf, sizeof (tbuf), "%Y-%m-%d %H:%M:%S", time_parts); 4617c478bd9Sstevel@tonic-gate return (tbuf); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate /* 4657c478bd9Sstevel@tonic-gate * The base of NTP timestamps is 1900-01-01 00:00:00.00000 4667c478bd9Sstevel@tonic-gate */ 4677c478bd9Sstevel@tonic-gate char * 4687c478bd9Sstevel@tonic-gate show_time(struct l_fixedpt pkt_time) 4697c478bd9Sstevel@tonic-gate { 4707c478bd9Sstevel@tonic-gate struct l_fixedpt net_time; 4717c478bd9Sstevel@tonic-gate unsigned long fracsec; 4727c478bd9Sstevel@tonic-gate static char buff[32]; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate if (pkt_time.int_part == 0) { 4757c478bd9Sstevel@tonic-gate buff[0] = '\0'; 4767c478bd9Sstevel@tonic-gate return (buff); 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate net_time.int_part = ntohl(pkt_time.int_part) - JAN_1970; 4807c478bd9Sstevel@tonic-gate net_time.fraction = ntohl(pkt_time.fraction); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate fracsec = net_time.fraction / 42949; /* fract / (2**32/10**6) */ 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate (void) strlcpy(buff, iso_date_time(net_time.int_part), sizeof (buff)); 4857c478bd9Sstevel@tonic-gate (void) snprintf(buff, sizeof (buff), "%s.%05lu", buff, fracsec); 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate return (buff); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate char * 4917c478bd9Sstevel@tonic-gate show_operation(int op) 4927c478bd9Sstevel@tonic-gate { 4937c478bd9Sstevel@tonic-gate switch (op) { 4947c478bd9Sstevel@tonic-gate case CTL_OP_UNSPEC: return ("unspecified"); 4957c478bd9Sstevel@tonic-gate case CTL_OP_READSTAT: return ("read stats"); 4967c478bd9Sstevel@tonic-gate case CTL_OP_READVAR: return ("read var"); 4977c478bd9Sstevel@tonic-gate case CTL_OP_WRITEVAR: return ("write var"); 4987c478bd9Sstevel@tonic-gate case CTL_OP_READCLOCK: return ("read clock"); 4997c478bd9Sstevel@tonic-gate case CTL_OP_WRITECLOCK: return ("write clock"); 5007c478bd9Sstevel@tonic-gate case CTL_OP_SETTRAP: return ("set trap"); 5017c478bd9Sstevel@tonic-gate case CTL_OP_ASYNCMSG: return ("async msg"); 5027c478bd9Sstevel@tonic-gate case CTL_OP_UNSETTRAP: return ("unset trap"); 5037c478bd9Sstevel@tonic-gate default: return ("unknown"); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate } 506