117680Spst/* 239300Sfenner * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017680Spst * 2117680Spst * Format and print ntp packets. 2217680Spst * By Jeffrey Mogul/DECWRL 2317680Spst * loosely based on print-bootp.c 2456896Sfenner * 2556896Sfenner * $FreeBSD$ 2617680Spst */ 2717680Spst 2817680Spst#ifndef lint 29127675Sbmsstatic const char rcsid[] _U_ = 30214478Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-ntp.c,v 1.43 2007-11-30 13:45:10 hannes Exp $ (LBL)"; 3117680Spst#endif 3217680Spst 3356896Sfenner#ifdef HAVE_CONFIG_H 3456896Sfenner#include "config.h" 3556896Sfenner#endif 3656896Sfenner 37127675Sbms#include <tcpdump-stdinc.h> 3817680Spst 3917680Spst#include <stdio.h> 4017680Spst#include <string.h> 41127675Sbms#ifdef HAVE_STRFTIME 42127675Sbms#include <time.h> 43127675Sbms#endif 4417680Spst 4517680Spst#include "interface.h" 4617680Spst#include "addrtoname.h" 47127675Sbms#include "extract.h" 4839300Sfenner#ifdef MODEMASK 4917680Spst#undef MODEMASK /* Solaris sucks */ 5039300Sfenner#endif 5117680Spst#include "ntp.h" 5217680Spst 5317680Spststatic void p_sfix(const struct s_fixedpt *); 5417680Spststatic void p_ntp_time(const struct l_fixedpt *); 5517680Spststatic void p_ntp_delta(const struct l_fixedpt *, const struct l_fixedpt *); 5617680Spst 57146778Ssamstatic struct tok ntp_mode_values[] = { 58146778Ssam { MODE_UNSPEC, "unspecified" }, 59146778Ssam { MODE_SYM_ACT, "symmetric active" }, 60146778Ssam { MODE_SYM_PAS, "symmetric passive" }, 61146778Ssam { MODE_CLIENT, "Client" }, 62146778Ssam { MODE_SERVER, "Server" }, 63146778Ssam { MODE_BROADCAST, "Broadcast" }, 64146778Ssam { MODE_RES1, "Reserved" }, 65146778Ssam { MODE_RES2, "Reserved" }, 66146778Ssam { 0, NULL } 67146778Ssam}; 68146778Ssam 69146778Ssamstatic struct tok ntp_leapind_values[] = { 70146778Ssam { NO_WARNING, "" }, 71146778Ssam { PLUS_SEC, "+1s" }, 72146778Ssam { MINUS_SEC, "-1s" }, 73146778Ssam { ALARM, "clock unsynchronized" }, 74146778Ssam { 0, NULL } 75146778Ssam}; 76146778Ssam 77214478Srpaulostatic struct tok ntp_stratum_values[] = { 78214478Srpaulo { UNSPECIFIED, "unspecified" }, 79214478Srpaulo { PRIM_REF, "primary reference" }, 80214478Srpaulo { 0, NULL } 81214478Srpaulo}; 82214478Srpaulo 8317680Spst/* 8417680Spst * Print ntp requests 8517680Spst */ 8617680Spstvoid 8717680Spstntp_print(register const u_char *cp, u_int length) 8817680Spst{ 8917680Spst register const struct ntpdata *bp; 9017680Spst int mode, version, leapind; 9117680Spst 9217680Spst bp = (struct ntpdata *)cp; 9317680Spst 9417680Spst TCHECK(bp->status); 9517680Spst 9626183Sfenner version = (int)(bp->status & VERSIONMASK) >> 3; 97127675Sbms printf("NTPv%d", version); 9817680Spst 9917680Spst mode = bp->status & MODEMASK; 100146778Ssam if (!vflag) { 101146778Ssam printf (", %s, length %u", 102146778Ssam tok2str(ntp_mode_values, "Unknown mode", mode), 103146778Ssam length); 104146778Ssam return; 105146778Ssam } 106146778Ssam 107146778Ssam printf (", length %u\n\t%s", 108146778Ssam length, 109146778Ssam tok2str(ntp_mode_values, "Unknown mode", mode)); 11017680Spst 111146778Ssam leapind = bp->status & LEAPMASK; 112146778Ssam printf (", Leap indicator: %s (%u)", 113146778Ssam tok2str(ntp_leapind_values, "Unknown", leapind), 114146778Ssam leapind); 11517680Spst 11617680Spst TCHECK(bp->stratum); 117214478Srpaulo printf(", Stratum %u (%s)", 118214478Srpaulo bp->stratum, 119214478Srpaulo tok2str(ntp_stratum_values, (bp->stratum >=2 && bp->stratum<=15) ? "secondary reference" : "reserved", bp->stratum)); 12017680Spst 12117680Spst TCHECK(bp->ppoll); 122251158Sdelphij printf(", poll %u (%us)", bp->ppoll, 1 << bp->ppoll); 12317680Spst 12417680Spst /* Can't TCHECK bp->precision bitfield so bp->distance + 0 instead */ 125146778Ssam TCHECK2(bp->root_delay, 0); 126146778Ssam printf(", precision %d", bp->precision); 12717680Spst 128146778Ssam TCHECK(bp->root_delay); 129146778Ssam fputs("\n\tRoot Delay: ", stdout); 130146778Ssam p_sfix(&bp->root_delay); 13117680Spst 132146778Ssam TCHECK(bp->root_dispersion); 133146778Ssam fputs(", Root dispersion: ", stdout); 134146778Ssam p_sfix(&bp->root_dispersion); 13517680Spst 13617680Spst TCHECK(bp->refid); 137146778Ssam fputs(", Reference-ID: ", stdout); 13817680Spst /* Interpretation depends on stratum */ 13917680Spst switch (bp->stratum) { 14017680Spst 14117680Spst case UNSPECIFIED: 14217680Spst printf("(unspec)"); 14317680Spst break; 14417680Spst 14517680Spst case PRIM_REF: 146147904Ssam if (fn_printn((u_char *)&(bp->refid), 4, snapend)) 147147904Ssam goto trunc; 14817680Spst break; 14917680Spst 15017680Spst case INFO_QUERY: 15117680Spst printf("%s INFO_QUERY", ipaddr_string(&(bp->refid))); 15217680Spst /* this doesn't have more content */ 15317680Spst return; 15417680Spst 15517680Spst case INFO_REPLY: 15617680Spst printf("%s INFO_REPLY", ipaddr_string(&(bp->refid))); 15717680Spst /* this is too complex to be worth printing */ 15817680Spst return; 15917680Spst 16017680Spst default: 16117680Spst printf("%s", ipaddr_string(&(bp->refid))); 16217680Spst break; 16317680Spst } 16417680Spst 165146778Ssam TCHECK(bp->ref_timestamp); 166146778Ssam fputs("\n\t Reference Timestamp: ", stdout); 167146778Ssam p_ntp_time(&(bp->ref_timestamp)); 16817680Spst 169146778Ssam TCHECK(bp->org_timestamp); 170146778Ssam fputs("\n\t Originator Timestamp: ", stdout); 171146778Ssam p_ntp_time(&(bp->org_timestamp)); 17217680Spst 173146778Ssam TCHECK(bp->rec_timestamp); 174146778Ssam fputs("\n\t Receive Timestamp: ", stdout); 175146778Ssam p_ntp_time(&(bp->rec_timestamp)); 17617680Spst 177146778Ssam TCHECK(bp->xmt_timestamp); 178146778Ssam fputs("\n\t Transmit Timestamp: ", stdout); 179146778Ssam p_ntp_time(&(bp->xmt_timestamp)); 18017680Spst 181146778Ssam fputs("\n\t Originator - Receive Timestamp: ", stdout); 182146778Ssam p_ntp_delta(&(bp->org_timestamp), &(bp->rec_timestamp)); 183146778Ssam 184146778Ssam fputs("\n\t Originator - Transmit Timestamp: ", stdout); 185146778Ssam p_ntp_delta(&(bp->org_timestamp), &(bp->xmt_timestamp)); 186146778Ssam 187214478Srpaulo if ( (sizeof(struct ntpdata) - length) == 16) { /* Optional: key-id */ 188214478Srpaulo TCHECK(bp->key_id); 189214478Srpaulo printf("\n\tKey id: %u", bp->key_id); 190214478Srpaulo } else if ( (sizeof(struct ntpdata) - length) == 0) { /* Optional: key-id + authentication */ 191214478Srpaulo TCHECK(bp->key_id); 192214478Srpaulo printf("\n\tKey id: %u", bp->key_id); 193214478Srpaulo TCHECK2(bp->message_digest, sizeof (bp->message_digest)); 194214478Srpaulo printf("\n\tAuthentication: %08x%08x%08x%08x", 195214478Srpaulo EXTRACT_32BITS(bp->message_digest), 196214478Srpaulo EXTRACT_32BITS(bp->message_digest + 4), 197214478Srpaulo EXTRACT_32BITS(bp->message_digest + 8), 198214478Srpaulo EXTRACT_32BITS(bp->message_digest + 12)); 199214478Srpaulo } 20017680Spst return; 20117680Spst 20217680Spsttrunc: 20317680Spst fputs(" [|ntp]", stdout); 20417680Spst} 20517680Spst 20617680Spststatic void 20717680Spstp_sfix(register const struct s_fixedpt *sfp) 20817680Spst{ 20917680Spst register int i; 21017680Spst register int f; 21117680Spst register float ff; 21217680Spst 213127675Sbms i = EXTRACT_16BITS(&sfp->int_part); 214127675Sbms f = EXTRACT_16BITS(&sfp->fraction); 21517680Spst ff = f / 65536.0; /* shift radix point by 16 bits */ 21617680Spst f = ff * 1000000.0; /* Treat fraction as parts per million */ 21717680Spst printf("%d.%06d", i, f); 21817680Spst} 21917680Spst 22017680Spst#define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */ 22117680Spst 22217680Spststatic void 22317680Spstp_ntp_time(register const struct l_fixedpt *lfp) 22417680Spst{ 22517680Spst register int32_t i; 22617680Spst register u_int32_t uf; 22717680Spst register u_int32_t f; 22817680Spst register float ff; 22917680Spst 230127675Sbms i = EXTRACT_32BITS(&lfp->int_part); 231127675Sbms uf = EXTRACT_32BITS(&lfp->fraction); 23217680Spst ff = uf; 23317680Spst if (ff < 0.0) /* some compilers are buggy */ 23417680Spst ff += FMAXINT; 23517680Spst ff = ff / FMAXINT; /* shift radix point by 32 bits */ 23617680Spst f = ff * 1000000000.0; /* treat fraction as parts per billion */ 23717680Spst printf("%u.%09d", i, f); 238127675Sbms 239127675Sbms#ifdef HAVE_STRFTIME 240127675Sbms /* 241146778Ssam * print the time in human-readable format. 242127675Sbms */ 243146778Ssam if (i) { 244127675Sbms time_t seconds = i - JAN_1970; 245127675Sbms struct tm *tm; 246127675Sbms char time_buf[128]; 247127675Sbms 248127675Sbms tm = localtime(&seconds); 249127675Sbms strftime(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", tm); 250127675Sbms printf (" (%s)", time_buf); 251127675Sbms } 252127675Sbms#endif 25317680Spst} 25417680Spst 25517680Spst/* Prints time difference between *lfp and *olfp */ 25617680Spststatic void 25717680Spstp_ntp_delta(register const struct l_fixedpt *olfp, 25817680Spst register const struct l_fixedpt *lfp) 25917680Spst{ 26017680Spst register int32_t i; 261127675Sbms register u_int32_t u, uf; 262127675Sbms register u_int32_t ou, ouf; 26317680Spst register u_int32_t f; 26417680Spst register float ff; 26517680Spst int signbit; 26617680Spst 267127675Sbms u = EXTRACT_32BITS(&lfp->int_part); 268127675Sbms ou = EXTRACT_32BITS(&olfp->int_part); 269127675Sbms uf = EXTRACT_32BITS(&lfp->fraction); 270127675Sbms ouf = EXTRACT_32BITS(&olfp->fraction); 271127675Sbms if (ou == 0 && ouf == 0) { 272127675Sbms p_ntp_time(lfp); 273127675Sbms return; 274127675Sbms } 27517680Spst 276127675Sbms i = u - ou; 27717680Spst 27817680Spst if (i > 0) { /* new is definitely greater than old */ 27917680Spst signbit = 0; 28017680Spst f = uf - ouf; 28117680Spst if (ouf > uf) /* must borrow from high-order bits */ 28217680Spst i -= 1; 28317680Spst } else if (i < 0) { /* new is definitely less than old */ 28417680Spst signbit = 1; 28517680Spst f = ouf - uf; 28617680Spst if (uf > ouf) /* must carry into the high-order bits */ 28717680Spst i += 1; 28817680Spst i = -i; 28917680Spst } else { /* int_part is zero */ 29017680Spst if (uf > ouf) { 29117680Spst signbit = 0; 29217680Spst f = uf - ouf; 29317680Spst } else { 29417680Spst signbit = 1; 29517680Spst f = ouf - uf; 29617680Spst } 29717680Spst } 29817680Spst 29917680Spst ff = f; 30017680Spst if (ff < 0.0) /* some compilers are buggy */ 30117680Spst ff += FMAXINT; 30217680Spst ff = ff / FMAXINT; /* shift radix point by 32 bits */ 30317680Spst f = ff * 1000000000.0; /* treat fraction as parts per billion */ 30417680Spst if (signbit) 30517680Spst putchar('-'); 30617680Spst else 30717680Spst putchar('+'); 30817680Spst printf("%d.%09d", i, f); 30917680Spst} 310127675Sbms 311