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 * $FreeBSD$ 26 */ 27 28 #ifndef lint 29 static const char rcsid[] _U_ = 30 "@(#) $Header: /tcpdump/master/tcpdump/print-ntp.c,v 1.41.2.1 2005/05/06 07:57:18 guy Exp $ (LBL)"; 31 #endif 32 33 #ifdef HAVE_CONFIG_H 34 #include "config.h" 35 #endif 36 37 #include <tcpdump-stdinc.h> 38 39 #include <stdio.h> 40 #include <string.h> 41 #ifdef HAVE_STRFTIME 42 #include <time.h> 43 #endif 44 45 #include "interface.h" 46 #include "addrtoname.h" 47 #include "extract.h" 48 #ifdef MODEMASK 49 #undef MODEMASK /* Solaris sucks */ 50 #endif 51 #include "ntp.h" 52 53 static void p_sfix(const struct s_fixedpt *); 54 static void p_ntp_time(const struct l_fixedpt *); 55 static void p_ntp_delta(const struct l_fixedpt *, const struct l_fixedpt *); 56 57 static struct tok ntp_mode_values[] = { 58 { MODE_UNSPEC, "unspecified" }, 59 { MODE_SYM_ACT, "symmetric active" }, 60 { MODE_SYM_PAS, "symmetric passive" }, 61 { MODE_CLIENT, "Client" }, 62 { MODE_SERVER, "Server" }, 63 { MODE_BROADCAST, "Broadcast" }, 64 { MODE_RES1, "Reserved" }, 65 { MODE_RES2, "Reserved" }, 66 { 0, NULL } 67 }; 68 69 static struct tok ntp_leapind_values[] = { 70 { NO_WARNING, "" }, 71 { PLUS_SEC, "+1s" }, 72 { MINUS_SEC, "-1s" }, 73 { ALARM, "clock unsynchronized" }, 74 { 0, NULL } 75 }; 76 77 /* 78 * Print ntp requests 79 */ 80 void 81 ntp_print(register const u_char *cp, u_int length) 82 { 83 register const struct ntpdata *bp; 84 int mode, version, leapind; 85 86 bp = (struct ntpdata *)cp; 87 88 TCHECK(bp->status); 89 90 version = (int)(bp->status & VERSIONMASK) >> 3; 91 printf("NTPv%d", version); 92 93 mode = bp->status & MODEMASK; 94 if (!vflag) { 95 printf (", %s, length %u", 96 tok2str(ntp_mode_values, "Unknown mode", mode), 97 length); 98 return; 99 } 100 101 printf (", length %u\n\t%s", 102 length, 103 tok2str(ntp_mode_values, "Unknown mode", mode)); 104 105 leapind = bp->status & LEAPMASK; 106 printf (", Leap indicator: %s (%u)", 107 tok2str(ntp_leapind_values, "Unknown", leapind), 108 leapind); 109 110 TCHECK(bp->stratum); 111 printf(", Stratum %u", bp->stratum); 112 113 TCHECK(bp->ppoll); 114 printf(", poll %us", bp->ppoll); 115 116 /* Can't TCHECK bp->precision bitfield so bp->distance + 0 instead */ 117 TCHECK2(bp->root_delay, 0); 118 printf(", precision %d", bp->precision); 119 120 TCHECK(bp->root_delay); 121 fputs("\n\tRoot Delay: ", stdout); 122 p_sfix(&bp->root_delay); 123 124 TCHECK(bp->root_dispersion); 125 fputs(", Root dispersion: ", stdout); 126 p_sfix(&bp->root_dispersion); 127 128 TCHECK(bp->refid); 129 fputs(", Reference-ID: ", stdout); 130 /* Interpretation depends on stratum */ 131 switch (bp->stratum) { 132 133 case UNSPECIFIED: 134 printf("(unspec)"); 135 break; 136 137 case PRIM_REF: 138 if (fn_printn((u_char *)&(bp->refid), 4, snapend)) 139 goto trunc; 140 break; 141 142 case INFO_QUERY: 143 printf("%s INFO_QUERY", ipaddr_string(&(bp->refid))); 144 /* this doesn't have more content */ 145 return; 146 147 case INFO_REPLY: 148 printf("%s INFO_REPLY", ipaddr_string(&(bp->refid))); 149 /* this is too complex to be worth printing */ 150 return; 151 152 default: 153 printf("%s", ipaddr_string(&(bp->refid))); 154 break; 155 } 156 157 TCHECK(bp->ref_timestamp); 158 fputs("\n\t Reference Timestamp: ", stdout); 159 p_ntp_time(&(bp->ref_timestamp)); 160 161 TCHECK(bp->org_timestamp); 162 fputs("\n\t Originator Timestamp: ", stdout); 163 p_ntp_time(&(bp->org_timestamp)); 164 165 TCHECK(bp->rec_timestamp); 166 fputs("\n\t Receive Timestamp: ", stdout); 167 p_ntp_time(&(bp->rec_timestamp)); 168 169 TCHECK(bp->xmt_timestamp); 170 fputs("\n\t Transmit Timestamp: ", stdout); 171 p_ntp_time(&(bp->xmt_timestamp)); 172 173 fputs("\n\t Originator - Receive Timestamp: ", stdout); 174 p_ntp_delta(&(bp->org_timestamp), &(bp->rec_timestamp)); 175 176 fputs("\n\t Originator - Transmit Timestamp: ", stdout); 177 p_ntp_delta(&(bp->org_timestamp), &(bp->xmt_timestamp)); 178 179 /* FIXME key-id, authentication */ 180 181 return; 182 183 trunc: 184 fputs(" [|ntp]", stdout); 185 } 186 187 static void 188 p_sfix(register const struct s_fixedpt *sfp) 189 { 190 register int i; 191 register int f; 192 register float ff; 193 194 i = EXTRACT_16BITS(&sfp->int_part); 195 f = EXTRACT_16BITS(&sfp->fraction); 196 ff = f / 65536.0; /* shift radix point by 16 bits */ 197 f = ff * 1000000.0; /* Treat fraction as parts per million */ 198 printf("%d.%06d", i, f); 199 } 200 201 #define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */ 202 203 static void 204 p_ntp_time(register const struct l_fixedpt *lfp) 205 { 206 register int32_t i; 207 register u_int32_t uf; 208 register u_int32_t f; 209 register float ff; 210 211 i = EXTRACT_32BITS(&lfp->int_part); 212 uf = EXTRACT_32BITS(&lfp->fraction); 213 ff = uf; 214 if (ff < 0.0) /* some compilers are buggy */ 215 ff += FMAXINT; 216 ff = ff / FMAXINT; /* shift radix point by 32 bits */ 217 f = ff * 1000000000.0; /* treat fraction as parts per billion */ 218 printf("%u.%09d", i, f); 219 220 #ifdef HAVE_STRFTIME 221 /* 222 * print the time in human-readable format. 223 */ 224 if (i) { 225 time_t seconds = i - JAN_1970; 226 struct tm *tm; 227 char time_buf[128]; 228 229 tm = localtime(&seconds); 230 strftime(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", tm); 231 printf (" (%s)", time_buf); 232 } 233 #endif 234 } 235 236 /* Prints time difference between *lfp and *olfp */ 237 static void 238 p_ntp_delta(register const struct l_fixedpt *olfp, 239 register const struct l_fixedpt *lfp) 240 { 241 register int32_t i; 242 register u_int32_t u, uf; 243 register u_int32_t ou, ouf; 244 register u_int32_t f; 245 register float ff; 246 int signbit; 247 248 u = EXTRACT_32BITS(&lfp->int_part); 249 ou = EXTRACT_32BITS(&olfp->int_part); 250 uf = EXTRACT_32BITS(&lfp->fraction); 251 ouf = EXTRACT_32BITS(&olfp->fraction); 252 if (ou == 0 && ouf == 0) { 253 p_ntp_time(lfp); 254 return; 255 } 256 257 i = u - ou; 258 259 if (i > 0) { /* new is definitely greater than old */ 260 signbit = 0; 261 f = uf - ouf; 262 if (ouf > uf) /* must borrow from high-order bits */ 263 i -= 1; 264 } else if (i < 0) { /* new is definitely less than old */ 265 signbit = 1; 266 f = ouf - uf; 267 if (uf > ouf) /* must carry into the high-order bits */ 268 i += 1; 269 i = -i; 270 } else { /* int_part is zero */ 271 if (uf > ouf) { 272 signbit = 0; 273 f = uf - ouf; 274 } else { 275 signbit = 1; 276 f = ouf - uf; 277 } 278 } 279 280 ff = f; 281 if (ff < 0.0) /* some compilers are buggy */ 282 ff += FMAXINT; 283 ff = ff / FMAXINT; /* shift radix point by 32 bits */ 284 f = ff * 1000000000.0; /* treat fraction as parts per billion */ 285 if (signbit) 286 putchar('-'); 287 else 288 putchar('+'); 289 printf("%d.%09d", i, f); 290 } 291 292