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