2 * Routines for NTP packet dissection
3 * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
5 * $Id: packet-ntp.c,v 1.40 2003/11/18 19:28:24 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-tftp.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #ifdef NEED_SNPRINTF_H
40 # include "snprintf.h"
43 #include <epan/packet.h>
44 #include <epan/resolv.h>
45 #include "packet-ntp.h"
48 * Dissecting NTP packets version 3 and 4 (RFC2030, RFC1769, RFC1361,
51 * Those packets have simple structure:
53 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 * |LI | VN |Mode | Stratum | Poll | Precision |
56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 * | Reference Identifier |
62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 * | Reference Timestamp (64) |
65 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 * | Originate Timestamp (64) |
68 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 * | Receive Timestamp (64) |
71 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72 * | Transmit Timestamp (64) |
74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 * | Key Identifier (optional) (32) |
76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 * | Message Digest (optional) (128) |
81 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82 * NTP timestamps are represented as a 64-bit unsigned fixed-point number,
83 * in seconds relative to 0h on 1 January 1900. The integer part is in the
84 * first 32 bits and the fraction part in the last 32 bits.
87 #define UDP_PORT_NTP 123
88 #define TCP_PORT_NTP 123
90 /* Leap indicator, 2bit field is used to warn of a inserted/deleted
91 * second, or to alarm loosed synchronization.
93 #define NTP_LI_MASK 0xC0
98 #define NTP_LI_ALARM 3
100 static const value_string li_types[] = {
101 { NTP_LI_NONE, "no warning" },
102 { NTP_LI_61, "last minute has 61 seconds" },
103 { NTP_LI_59, "last minute has 59 seconds" },
104 { NTP_LI_ALARM, "alarm condition (clock not synchronized)" },
108 /* Version info, 3bit field informs about NTP version used in particular
109 * packet. According to rfc2030, version info could be only 3 or 4, but I
110 * have noticed packets with 1 or even 6 as version numbers. They are
111 * produced as a result of ntptrace command. Are those packets mailformed
112 * on purpose? I don't know yet, probably some browsing through ntp sources
113 * would help. My solution is to put them as reserved for now.
115 #define NTP_VN_MASK 0x38
117 static const value_string ver_nums[] = {
121 { 3, "NTP Version 3" },
122 { 4, "NTP Version 4" },
129 /* Mode, 3bit field representing mode of comunication.
131 #define NTP_MODE_MASK 7
133 #define NTP_MODE_RSV 0
134 #define NTP_MODE_SYMACT 1
135 #define NTP_MODE_SYMPAS 2
136 #define NTP_MODE_CLIENT 3
137 #define NTP_MODE_SERVER 4
138 #define NTP_MODE_BCAST 5
139 #define NTP_MODE_CTRL 6
140 #define NTP_MODE_PRIV 7
142 static const value_string mode_types[] = {
143 { NTP_MODE_RSV, "reserved" },
144 { NTP_MODE_SYMACT, "symmetric active" },
145 { NTP_MODE_SYMPAS, "symmetric passive" },
146 { NTP_MODE_CLIENT, "client" },
147 { NTP_MODE_SERVER, "server" },
148 { NTP_MODE_BCAST, "broadcast" },
149 { NTP_MODE_CTRL, "reserved for NTP control message"},
150 { NTP_MODE_PRIV, "reserved for private use" },
154 /* According to rfc, primary (stratum-0 and stratum-1) servers should set
155 * their Reference Clock ID (4bytes field) according to following table:
157 static const struct {
160 } primary_sources[] = {
161 { "LOCL", "uncalibrated local clock" },
162 { "PPS\0", "atomic clock or other pulse-per-second source" },
163 { "ACTS", "NIST dialup modem service" },
164 { "USNO", "USNO modem service" },
165 { "PTB\0", "PTB (Germany) modem service" },
166 { "TDF\0", "Allouis (France) Radio 164 kHz" },
167 { "DCF\0", "Mainflingen (Germany) Radio 77.5 kHz" },
168 { "MSF\0", "Rugby (UK) Radio 60 kHz" },
169 { "WWV\0", "Ft. Collins (US) Radio 2.5, 5, 10, 15, 20 MHz" },
170 { "WWVB", "Boulder (US) Radio 60 kHz" },
171 { "WWVH", "Kaui Hawaii (US) Radio 2.5, 5, 10, 15 MHz" },
172 { "CHU\0", "Ottawa (Canada) Radio 3330, 7335, 14670 kHz" },
173 { "LORC", "LORAN-C radionavigation system" },
174 { "OMEG", "OMEGA radionavigation system" },
175 { "GPS\0", "Global Positioning Service" },
176 { "GOES", "Geostationary Orbit Environment Satellite" },
177 { "DCN\0", "DCN routing protocol" },
178 { "NIST", "NIST public modem" },
179 { "TSP\0", "TSP time protocol" },
180 { "DTS\0", "Digital Time Service" },
181 { "ATOM", "Atomic clock (calibrated)" },
182 { "VLF\0", "VLF radio (OMEGA,, etc.)" },
183 { "IRIG", "IRIG-B timecode" },
184 { "1PPS", "External 1 PPS input" },
185 { "FREE", "(Internal clock)" },
189 #define NTP_EXT_R_MASK 0x80
191 static const value_string ext_r_types[] = {
197 #define NTP_EXT_ERROR_MASK 0x40
198 #define NTP_EXT_VN_MASK 0x3f
200 static const value_string ext_op_types[] = {
214 #define NTPCTRL_R_MASK 0x80
216 #define ctrl_r_types ext_r_types
218 #define NTPCTRL_ERROR_MASK 0x40
219 #define NTPCTRL_MORE_MASK 0x20
220 #define NTPCTRL_OP_MASK 0x1f
222 static const value_string ctrl_op_types[] = {
235 #define NTPPRIV_R_MASK 0x80
237 #define priv_r_types ext_r_types
239 #define NTPPRIV_MORE_MASK 0x40
241 #define NTPPRIV_AUTH_MASK 0x80
242 #define NTPPRIV_SEQ_MASK 0x7f
244 static const value_string priv_impl_types[] = {
246 { 2, "XNTPD_OLD (pre-IPv6)" },
251 static const value_string priv_rc_types[] = {
253 { 1, "PEER_LIST_SUM" },
261 { 9, "TIMER_STATS" },
264 { 12, "SET_SYS_FLAG" },
265 { 13, "CLR_SYS_FLAG" },
266 { 16, "GET_RESTRICT" },
267 { 17, "RESADDFLAGS" },
268 { 18, "RESSUBFLAGS" },
269 { 19, "UNRESTRICT" },
270 { 20, "MON_GETLIST" },
271 { 21, "RESET_STATS" },
272 { 22, "RESET_PEER" },
273 { 23, "REREAD_KEYS" },
275 { 27, "UNTRUSTKEY" },
280 { 32, "REQUEST_KEY" },
281 { 33, "CONTROL_KEY" },
282 { 34, "GET_CTLSTATS" },
283 { 36, "GET_CLOCKINFO" },
284 { 37, "SET_CLKFUDGE" },
285 { 38, "GET_KERNEL" },
286 { 39, "GET_CLKBUGINFO" },
287 { 42, "MON_GETLIST_1" },
288 { 43, "HOSTNAME_ASSOCID" },
293 * Maximum MAC length.
295 #define MAX_MAC_LEN (5 * sizeof (guint32))
297 static int proto_ntp = -1;
299 static int hf_ntp_flags = -1;
300 static int hf_ntp_flags_li = -1;
301 static int hf_ntp_flags_vn = -1;
302 static int hf_ntp_flags_mode = -1;
303 static int hf_ntp_stratum = -1;
304 static int hf_ntp_ppoll = -1;
305 static int hf_ntp_precision = -1;
306 static int hf_ntp_rootdelay = -1;
307 static int hf_ntp_rootdispersion = -1;
308 static int hf_ntp_refid = -1;
309 static int hf_ntp_reftime = -1;
310 static int hf_ntp_org = -1;
311 static int hf_ntp_rec = -1;
312 static int hf_ntp_xmt = -1;
313 static int hf_ntp_keyid = -1;
314 static int hf_ntp_mac = -1;
316 static int hf_ntp_ext = -1;
317 static int hf_ntp_ext_flags = -1;
318 static int hf_ntp_ext_flags_r = -1;
319 static int hf_ntp_ext_flags_error = -1;
320 static int hf_ntp_ext_flags_vn = -1;
321 static int hf_ntp_ext_op = -1;
322 static int hf_ntp_ext_len = -1;
323 static int hf_ntp_ext_associd = -1;
324 static int hf_ntp_ext_tstamp = -1;
325 static int hf_ntp_ext_fstamp = -1;
326 static int hf_ntp_ext_vallen = -1;
327 static int hf_ntp_ext_val = -1;
328 static int hf_ntp_ext_siglen = -1;
329 static int hf_ntp_ext_sig = -1;
331 static int hf_ntpctrl_flags2 = -1;
332 static int hf_ntpctrl_flags2_r = -1;
333 static int hf_ntpctrl_flags2_error = -1;
334 static int hf_ntpctrl_flags2_more = -1;
335 static int hf_ntpctrl_flags2_opcode = -1;
337 static int hf_ntppriv_flags_r = -1;
338 static int hf_ntppriv_flags_more = -1;
339 static int hf_ntppriv_auth_seq = -1;
340 static int hf_ntppriv_auth = -1;
341 static int hf_ntppriv_seq = -1;
342 static int hf_ntppriv_impl = -1;
343 static int hf_ntppriv_reqcode = -1;
345 static gint ett_ntp = -1;
346 static gint ett_ntp_flags = -1;
347 static gint ett_ntp_ext = -1;
348 static gint ett_ntp_ext_flags = -1;
349 static gint ett_ntpctrl_flags2 = -1;
350 static gint ett_ntppriv_auth_seq = -1;
352 static void dissect_ntp_std(tvbuff_t *, proto_tree *, guint8);
353 static void dissect_ntp_ctrl(tvbuff_t *, proto_tree *, guint8);
354 static void dissect_ntp_priv(tvbuff_t *, proto_tree *, guint8);
355 static int dissect_ntp_ext(tvbuff_t *, proto_tree *, int);
357 /* ntp_fmt_ts - converts NTP timestamp to human readable string.
358 * reftime - 64bit timestamp (IN)
359 * buff - string buffer for result (OUT)
360 * returns pointer to filled buffer.
363 ntp_fmt_ts(const guint8 *reftime, char* buff)
365 guint32 tempstmp, tempfrac;
370 tempstmp = pntohl(&reftime[0]);
371 tempfrac = pntohl(&reftime[4]);
372 if ((tempstmp == 0) && (tempfrac == 0)) {
373 strcpy (buff, "NULL");
376 temptime = tempstmp - (guint32) NTP_BASETIME;
377 bd = gmtime(&temptime);
379 fractime = bd->tm_sec + tempfrac / 4294967296.0;
380 snprintf(buff, NTP_TS_SIZE,
381 "%04d-%02d-%02d %02d:%02d:%07.4f UTC",
382 bd->tm_year + 1900, bd->tm_mon + 1, bd->tm_mday,
383 bd->tm_hour, bd->tm_min, fractime);
385 strncpy(buff, "Not representable", NTP_TS_SIZE);
390 /* dissect_ntp - dissects NTP packet data
391 * tvb - tvbuff for packet data (IN)
392 * pinfo - packet info
393 * proto_tree - resolved protocol tree
396 dissect_ntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
398 proto_tree *ntp_tree;
402 void (*dissector)(tvbuff_t *, proto_item *, guint8);
404 if (check_col(pinfo->cinfo, COL_PROTOCOL))
405 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NTP");
407 if (check_col(pinfo->cinfo, COL_INFO))
408 col_clear(pinfo->cinfo, COL_INFO);
410 flags = tvb_get_guint8(tvb, 0);
411 switch (flags & NTP_MODE_MASK) {
414 dissector = dissect_ntp_std;
417 infostr = "NTP control";
418 dissector = dissect_ntp_ctrl;
421 infostr = "NTP private";
422 dissector = dissect_ntp_priv;
426 if (check_col(pinfo->cinfo, COL_INFO))
427 col_set_str(pinfo->cinfo, COL_INFO, infostr);
430 /* Adding NTP item and subtree */
431 ti = proto_tree_add_item(tree, proto_ntp, tvb, 0, -1, FALSE);
432 ntp_tree = proto_item_add_subtree(ti, ett_ntp);
434 (*dissector)(tvb, ntp_tree, flags);
439 dissect_ntp_std(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
441 proto_tree *flags_tree;
447 double rootdispersion;
450 const guint8 *reftime;
454 gchar buff[NTP_TS_SIZE];
459 tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
461 /* Adding flag subtree and items */
462 flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
463 proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
464 proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
465 proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
467 /* Stratum, 1byte field represents distance from primary source
469 stratum = tvb_get_guint8(tvb, 1);
471 strcpy (buff, "Peer Clock Stratum: unspecified or unavailable (%u)");
472 } else if (stratum == 1) {
473 strcpy (buff, "Peer Clock Stratum: primary reference (%u)");
474 } else if ((stratum >= 2) && (stratum <= 15)) {
475 strcpy (buff, "Peer Clock Stratum: secondary reference (%u)");
477 strcpy (buff, "Peer Clock Stratum: reserved: %u");
479 proto_tree_add_uint_format(ntp_tree, hf_ntp_stratum, tvb, 1, 1,
480 stratum, buff, stratum);
481 /* Poll interval, 1byte field indicating the maximum interval
482 * between successive messages, in seconds to the nearest
485 ppoll = tvb_get_guint8(tvb, 2);
486 proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
488 (((ppoll >= 4) && (ppoll <= 16)) ?
489 "Peer Polling Interval: %u (%u sec)" :
490 "Peer Polling Interval: invalid (%u)"),
494 /* Precision, 1byte field indicating the precision of the
495 * local clock, in seconds to the nearest power of two.
497 precision = tvb_get_guint8(tvb, 3);
498 proto_tree_add_int_format(ntp_tree, hf_ntp_precision, tvb, 3, 1,
500 "Peer Clock Precision: %8.6f sec",
503 /* Root Delay is a 32-bit signed fixed-point number indicating
504 * the total roundtrip delay to the primary reference source,
505 * in seconds with fraction point between bits 15 and 16.
507 rootdelay = ((gint16)tvb_get_ntohs(tvb, 4)) +
508 (tvb_get_ntohs(tvb, 6) / 65536.0);
509 proto_tree_add_double_format(ntp_tree, hf_ntp_rootdelay, tvb, 4, 4,
511 "Root Delay: %9.4f sec",
514 /* Root Dispersion, 32-bit unsigned fixed-point number indicating
515 * the nominal error relative to the primary reference source, in
516 * seconds with fraction point between bits 15 and 16.
518 rootdispersion = ((gint16)tvb_get_ntohs(tvb, 8)) +
519 (tvb_get_ntohs(tvb, 10) / 65536.0);
520 proto_tree_add_double_format(ntp_tree, hf_ntp_rootdispersion, tvb, 8, 4,
522 "Clock Dispersion: %9.4f sec",
525 /* Now, there is a problem with secondary servers. Standards
526 * asks from stratum-2 - stratum-15 servers to set this to the
527 * low order 32 bits of the latest transmit timestamp of the
529 * But, all V3 and V4 servers set this to IP adress of their
530 * higher level server. My decision was to resolve this address.
532 refid = tvb_get_ptr(tvb, 12, 4);
534 snprintf (buff, sizeof buff,
535 "Unindentified reference source '%.4s'",
537 for (i = 0; primary_sources[i].id; i++) {
538 if (memcmp (refid, primary_sources[i].id,
540 strcpy (buff, primary_sources[i].data);
545 buff[sizeof(buff) - 1] = '\0';
546 tvb_memcpy(tvb, (guint8 *)&refid_addr, 12, 4);
547 strncpy (buff, get_hostname (refid_addr),
549 if (buff[sizeof(buff) - 1] != '\0')
550 strcpy(&buff[sizeof(buff) - 4], "...");
552 proto_tree_add_bytes_format(ntp_tree, hf_ntp_refid, tvb, 12, 4,
554 "Reference Clock ID: %s", buff);
556 /* Reference Timestamp: This is the time at which the local clock was
557 * last set or corrected.
559 reftime = tvb_get_ptr(tvb, 16, 8);
560 proto_tree_add_bytes_format(ntp_tree, hf_ntp_reftime, tvb, 16, 8,
562 "Reference Clock Update Time: %s",
563 ntp_fmt_ts(reftime, buff));
565 /* Originate Timestamp: This is the time at which the request departed
566 * the client for the server.
568 org = tvb_get_ptr(tvb, 24, 8);
569 proto_tree_add_bytes_format(ntp_tree, hf_ntp_org, tvb, 24, 8,
571 "Originate Time Stamp: %s",
572 ntp_fmt_ts(org, buff));
574 /* Receive Timestamp: This is the time at which the request arrived at
577 rec = tvb_get_ptr(tvb, 32, 8);
578 proto_tree_add_bytes_format(ntp_tree, hf_ntp_rec, tvb, 32, 8,
580 "Receive Time Stamp: %s",
581 ntp_fmt_ts(rec, buff));
583 /* Transmit Timestamp: This is the time at which the reply departed the
584 * server for the client.
586 xmt = tvb_get_ptr(tvb, 40, 8);
587 proto_tree_add_bytes_format(ntp_tree, hf_ntp_xmt, tvb, 40, 8,
589 "Transmit Time Stamp: %s",
590 ntp_fmt_ts(xmt, buff));
592 /* MAX_MAC_LEN is the largest message authentication code
593 * (MAC) length. If we have more data left in the packet
594 * after the header than that, the extra data is NTP4
595 * extensions; parse them as such.
598 while (tvb_reported_length_remaining(tvb, macofs) > (gint)MAX_MAC_LEN)
599 macofs = dissect_ntp_ext(tvb, ntp_tree, macofs);
601 /* When the NTP authentication scheme is implemented, the
602 * Key Identifier and Message Digest fields contain the
603 * message authentication code (MAC) information defined in
604 * Appendix C of RFC-1305. Will print this as hex code for now.
606 if (tvb_reported_length_remaining(tvb, macofs) >= 4)
607 proto_tree_add_item(ntp_tree, hf_ntp_keyid, tvb, macofs, 4,
610 maclen = tvb_reported_length_remaining(tvb, macofs);
612 proto_tree_add_item(ntp_tree, hf_ntp_mac, tvb, macofs,
617 dissect_ntp_ext(tvbuff_t *tvb, proto_tree *ntp_tree, int offset)
619 proto_tree *ext_tree, *flags_tree;
624 guint32 vallen, vallen_round, siglen;
626 extlen = tvb_get_ntohs(tvb, offset+2);
628 /* Extension length isn't enough for the extension header.
629 * Report the error, and return an offset that goes to
630 * the end of the tvbuff, so we stop dissecting.
632 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
633 "Extension length %u < 8", extlen);
634 offset += tvb_length_remaining(tvb, offset);
638 /* Extension length isn't a multiple of 4.
639 * Report the error, and return an offset that goes
640 * to the end of the tvbuff, so we stop dissecting.
642 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
643 "Extension length %u isn't a multiple of 4",
645 offset += tvb_length_remaining(tvb, offset);
648 endoffset = offset + extlen;
650 tf = proto_tree_add_item(ntp_tree, hf_ntp_ext, tvb, offset, extlen,
652 ext_tree = proto_item_add_subtree(tf, ett_ntp_ext);
654 flags = tvb_get_guint8(tvb, offset);
655 tf = proto_tree_add_uint(ext_tree, hf_ntp_ext_flags, tvb, offset, 1,
657 flags_tree = proto_item_add_subtree(tf, ett_ntp_ext_flags);
658 proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_r, tvb, offset, 1,
660 proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_error, tvb, offset, 1,
662 proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_vn, tvb, offset, 1,
666 proto_tree_add_item(ext_tree, hf_ntp_ext_op, tvb, offset, 1, FALSE);
669 proto_tree_add_uint(ext_tree, hf_ntp_ext_len, tvb, offset, 2, extlen);
672 if ((flags & NTP_EXT_VN_MASK) != 2) {
673 /* don't care about autokey v1 */
677 proto_tree_add_item(ext_tree, hf_ntp_ext_associd, tvb, offset, 4,
681 /* check whether everything up to "vallen" is present */
682 if (extlen < MAX_MAC_LEN) {
683 /* XXX - report as error? */
687 proto_tree_add_item(ext_tree, hf_ntp_ext_tstamp, tvb, offset, 4,
690 proto_tree_add_item(ext_tree, hf_ntp_ext_fstamp, tvb, offset, 4,
693 /* XXX fstamp can be server flags */
695 vallen = tvb_get_ntohl(tvb, offset);
696 proto_tree_add_uint(ext_tree, hf_ntp_ext_vallen, tvb, offset, 4,
699 vallen_round = (vallen + 3) & (-4);
701 if ((guint32)(endoffset - offset) < vallen_round) {
703 * Value goes past the length of the extension
706 proto_tree_add_text(ext_tree, tvb, offset,
708 "Value length makes value go past the end of the extension field");
711 proto_tree_add_item(ext_tree, hf_ntp_ext_val, tvb, offset,
714 offset += vallen_round;
716 siglen = tvb_get_ntohl(tvb, offset);
717 proto_tree_add_uint(ext_tree, hf_ntp_ext_siglen, tvb, offset, 4,
721 if (offset + (int)siglen > endoffset) {
723 * Value goes past the length of the extension
726 proto_tree_add_text(ext_tree, tvb, offset,
728 "Signature length makes value go past the end of the extension field");
731 proto_tree_add_item(ext_tree, hf_ntp_ext_sig, tvb,
732 offset, siglen, FALSE);
738 dissect_ntp_ctrl(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
740 proto_tree *flags_tree;
744 tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
746 /* Adding flag subtree and items */
747 flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
748 proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
749 proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
750 proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
752 flags2 = tvb_get_guint8(tvb, 1);
753 tf = proto_tree_add_uint(ntp_tree, hf_ntpctrl_flags2, tvb, 1, 1,
755 flags_tree = proto_item_add_subtree(tf, ett_ntpctrl_flags2);
756 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_r, tvb, 1, 1,
758 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_error, tvb, 1, 1,
760 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_more, tvb, 1, 1,
762 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_opcode, tvb, 1, 1,
767 dissect_ntp_priv(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
769 proto_tree *flags_tree;
771 guint8 auth_seq, impl, reqcode;
773 tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
775 /* Adding flag subtree and items */
776 flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
777 proto_tree_add_uint(flags_tree, hf_ntppriv_flags_r, tvb, 0, 1, flags);
778 proto_tree_add_uint(flags_tree, hf_ntppriv_flags_more, tvb, 0, 1,
780 proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
781 proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
783 auth_seq = tvb_get_guint8(tvb, 1);
784 tf = proto_tree_add_uint(ntp_tree, hf_ntppriv_auth_seq, tvb, 1, 1,
786 flags_tree = proto_item_add_subtree(tf, ett_ntppriv_auth_seq);
787 proto_tree_add_uint(flags_tree, hf_ntppriv_auth, tvb, 1, 1, auth_seq);
788 proto_tree_add_uint(flags_tree, hf_ntppriv_seq, tvb, 1, 1, auth_seq);
790 impl = tvb_get_guint8(tvb, 2);
791 proto_tree_add_uint(ntp_tree, hf_ntppriv_impl, tvb, 2, 1, impl);
793 reqcode = tvb_get_guint8(tvb, 3);
794 proto_tree_add_uint(ntp_tree, hf_ntppriv_reqcode, tvb, 3, 1, reqcode);
798 proto_register_ntp(void)
800 static hf_register_info hf[] = {
802 "Flags", "ntp.flags", FT_UINT8, BASE_HEX,
803 NULL, 0, "Flags (Leap/Version/Mode)", HFILL }},
804 { &hf_ntp_flags_li, {
805 "Leap Indicator", "ntp.flags.li", FT_UINT8, BASE_DEC,
806 VALS(li_types), NTP_LI_MASK, "Leap Indicator", HFILL }},
807 { &hf_ntp_flags_vn, {
808 "Version number", "ntp.flags.vn", FT_UINT8, BASE_DEC,
809 VALS(ver_nums), NTP_VN_MASK, "Version number", HFILL }},
810 { &hf_ntp_flags_mode, {
811 "Mode", "ntp.flags.mode", FT_UINT8, BASE_DEC,
812 VALS(mode_types), NTP_MODE_MASK, "Mode", HFILL }},
814 "Peer Clock Stratum", "ntp.stratum", FT_UINT8, BASE_DEC,
815 NULL, 0, "Peer Clock Stratum", HFILL }},
817 "Peer Polling Interval", "ntp.ppoll", FT_UINT8, BASE_DEC,
818 NULL, 0, "Peer Polling Interval", HFILL }},
819 { &hf_ntp_precision, {
820 "Peer Clock Precision", "ntp.precision", FT_INT8, BASE_DEC,
821 NULL, 0, "Peer Clock Precision", HFILL }},
822 { &hf_ntp_rootdelay, {
823 "Root Delay", "ntp.rootdelay", FT_DOUBLE, BASE_DEC,
824 NULL, 0, "Root Delay", HFILL }},
825 { &hf_ntp_rootdispersion, {
826 "Clock Dispersion", "ntp.rootdispersion", FT_DOUBLE, BASE_DEC,
827 NULL, 0, "Clock Dispersion", HFILL }},
829 "Reference Clock ID", "ntp.refid", FT_BYTES, BASE_NONE,
830 NULL, 0, "Reference Clock ID", HFILL }},
832 "Reference Clock Update Time", "ntp.reftime", FT_BYTES, BASE_NONE,
833 NULL, 0, "Reference Clock Update Time", HFILL }},
835 "Originate Time Stamp", "ntp.org", FT_BYTES, BASE_NONE,
836 NULL, 0, "Originate Time Stamp", HFILL }},
838 "Receive Time Stamp", "ntp.rec", FT_BYTES, BASE_NONE,
839 NULL, 0, "Receive Time Stamp", HFILL }},
841 "Transmit Time Stamp", "ntp.xmt", FT_BYTES, BASE_NONE,
842 NULL, 0, "Transmit Time Stamp", HFILL }},
844 "Key ID", "ntp.keyid", FT_BYTES, BASE_HEX,
845 NULL, 0, "Key ID", HFILL }},
847 "Message Authentication Code", "ntp.mac", FT_BYTES, BASE_HEX,
848 NULL, 0, "Message Authentication Code", HFILL }},
851 "Extension", "ntp.ext", FT_NONE, BASE_NONE,
852 NULL, 0, "Extension", HFILL }},
853 { &hf_ntp_ext_flags, {
854 "Flags", "ntp.ext.flags", FT_UINT8, BASE_HEX,
855 NULL, 0, "Flags (Response/Error/Version)", HFILL }},
856 { &hf_ntp_ext_flags_r, {
857 "Response bit", "ntp.ext.flags.r", FT_UINT8, BASE_DEC,
858 VALS(ext_r_types), NTP_EXT_R_MASK, "Response bit", HFILL }},
859 { &hf_ntp_ext_flags_error, {
860 "Error bit", "ntp.ext.flags.error", FT_UINT8, BASE_DEC,
861 NULL, NTP_EXT_ERROR_MASK, "Error bit", HFILL }},
862 { &hf_ntp_ext_flags_vn, {
863 "Version", "ntp.ext.flags.vn", FT_UINT8, BASE_DEC,
864 NULL, NTP_EXT_VN_MASK, "Version", HFILL }},
866 "Opcode", "ntp.ext.op", FT_UINT8, BASE_DEC,
867 VALS(ext_op_types), 0, "Opcode", HFILL }},
869 "Extension length", "ntp.ext.len", FT_UINT16, BASE_DEC,
870 NULL, 0, "Extension length", HFILL }},
871 { &hf_ntp_ext_associd, {
872 "Association ID", "ntp.ext.associd", FT_UINT32, BASE_DEC,
873 NULL, 0, "Association ID", HFILL }},
874 { &hf_ntp_ext_tstamp, {
875 "Timestamp", "ntp.ext.tstamp", FT_UINT32, BASE_HEX,
876 NULL, 0, "Timestamp", HFILL }},
877 { &hf_ntp_ext_fstamp, {
878 "File Timestamp", "ntp.ext.fstamp", FT_UINT32, BASE_HEX,
879 NULL, 0, "File Timestamp", HFILL }},
880 { &hf_ntp_ext_vallen, {
881 "Value length", "ntp.ext.vallen", FT_UINT32, BASE_DEC,
882 NULL, 0, "Value length", HFILL }},
884 "Value", "ntp.ext.val", FT_BYTES, BASE_HEX,
885 NULL, 0, "Value", HFILL }},
886 { &hf_ntp_ext_siglen, {
887 "Signature length", "ntp.ext.siglen", FT_UINT32, BASE_DEC,
888 NULL, 0, "Signature length", HFILL }},
890 "Signature", "ntp.ext.sig", FT_BYTES, BASE_HEX,
891 NULL, 0, "Signature", HFILL }},
893 { &hf_ntpctrl_flags2, {
894 "Flags 2", "ntpctrl.flags2", FT_UINT8, BASE_HEX,
895 NULL, 0, "Flags (Response/Error/More/Opcode)", HFILL }},
896 { &hf_ntpctrl_flags2_r, {
897 "Response bit", "ntpctrl.flags2.r", FT_UINT8, BASE_DEC,
898 VALS(ctrl_r_types), NTPCTRL_R_MASK, "Response bit", HFILL }},
899 { &hf_ntpctrl_flags2_error, {
900 "Error bit", "ntpctrl.flags2.error", FT_UINT8, BASE_DEC,
901 NULL, NTPCTRL_ERROR_MASK, "Error bit", HFILL }},
902 { &hf_ntpctrl_flags2_more, {
903 "More bit", "ntpctrl.flags2.more", FT_UINT8, BASE_DEC,
904 NULL, NTPCTRL_MORE_MASK, "More bit", HFILL }},
905 { &hf_ntpctrl_flags2_opcode, {
906 "Opcode", "ntpctrl.flags2.opcode", FT_UINT8, BASE_DEC,
907 VALS(ctrl_op_types), NTPCTRL_OP_MASK, "Opcode", HFILL }},
909 { &hf_ntppriv_flags_r, {
910 "Response bit", "ntppriv.flags.r", FT_UINT8, BASE_DEC,
911 VALS(priv_r_types), NTPPRIV_R_MASK, "Response bit", HFILL }},
912 { &hf_ntppriv_flags_more, {
913 "More bit", "ntppriv.flags.more", FT_UINT8, BASE_DEC,
914 NULL, NTPPRIV_MORE_MASK, "More bit", HFILL }},
915 { &hf_ntppriv_auth_seq, {
916 "Auth, sequence", "ntppriv.auth_seq", FT_UINT8, BASE_DEC,
917 NULL, 0, "Auth bit, sequence number", HFILL }},
918 { &hf_ntppriv_auth, {
919 "Auth bit", "ntppriv.auth", FT_UINT8, BASE_DEC,
920 NULL, NTPPRIV_AUTH_MASK, "Auth bit", HFILL }},
922 "Sequence number", "ntppriv.seq", FT_UINT8, BASE_DEC,
923 NULL, NTPPRIV_SEQ_MASK, "Sequence number", HFILL }},
924 { &hf_ntppriv_impl, {
925 "Implementation", "ntppriv.impl", FT_UINT8, BASE_DEC,
926 VALS(priv_impl_types), 0, "Implementation", HFILL }},
927 { &hf_ntppriv_reqcode, {
928 "Request code", "ntppriv.reqcode", FT_UINT8, BASE_DEC,
929 VALS(priv_rc_types), 0, "Request code", HFILL }},
931 static gint *ett[] = {
937 &ett_ntppriv_auth_seq,
940 proto_ntp = proto_register_protocol("Network Time Protocol", "NTP",
942 proto_register_field_array(proto_ntp, hf, array_length(hf));
943 proto_register_subtree_array(ett, array_length(ett));
947 proto_reg_handoff_ntp(void)
949 dissector_handle_t ntp_handle;
951 ntp_handle = create_dissector_handle(dissect_ntp, proto_ntp);
952 dissector_add("udp.port", UDP_PORT_NTP, ntp_handle);
953 dissector_add("tcp.port", TCP_PORT_NTP, ntp_handle);