2 * Routines for NTP packet dissection
3 * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
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 #include <epan/packet.h>
40 #include <epan/addr_resolv.h>
41 #include <epan/emem.h>
42 #include "packet-ntp.h"
45 * Dissecting NTP packets version 3 and 4 (RFC2030, RFC1769, RFC1361,
48 * Those packets have simple structure:
50 * 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
51 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 * |LI | VN |Mode | Stratum | Poll | Precision |
53 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 * | Reference Identifier |
59 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 * | Reference Timestamp (64) |
62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 * | Originate Timestamp (64) |
65 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 * | Receive Timestamp (64) |
68 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 * | Transmit Timestamp (64) |
71 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72 * | Key Identifier (optional) (32) |
73 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74 * | Message Digest (optional) (128) |
78 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79 * NTP timestamps are represented as a 64-bit unsigned fixed-point number,
80 * in seconds relative to 0h on 1 January 1900. The integer part is in the
81 * first 32 bits and the fraction part in the last 32 bits.
84 #define UDP_PORT_NTP 123
85 #define TCP_PORT_NTP 123
87 /* Leap indicator, 2bit field is used to warn of a inserted/deleted
88 * second, or to alarm loosed synchronization.
90 #define NTP_LI_MASK 0xC0
95 #define NTP_LI_ALARM 3
97 static const value_string li_types[] = {
98 { NTP_LI_NONE, "no warning" },
99 { NTP_LI_61, "last minute has 61 seconds" },
100 { NTP_LI_59, "last minute has 59 seconds" },
101 { NTP_LI_ALARM, "alarm condition (clock not synchronized)" },
105 /* Version info, 3bit field informs about NTP version used in particular
106 * packet. According to rfc2030, version info could be only 3 or 4, but I
107 * have noticed packets with 1 or even 6 as version numbers. They are
108 * produced as a result of ntptrace command. Are those packets mailformed
109 * on purpose? I don't know yet, probably some browsing through ntp sources
110 * would help. My solution is to put them as reserved for now.
112 #define NTP_VN_MASK 0x38
114 static const value_string ver_nums[] = {
118 { 3, "NTP Version 3" },
119 { 4, "NTP Version 4" },
126 /* Mode, 3bit field representing mode of comunication.
128 #define NTP_MODE_MASK 7
130 #define NTP_MODE_RSV 0
131 #define NTP_MODE_SYMACT 1
132 #define NTP_MODE_SYMPAS 2
133 #define NTP_MODE_CLIENT 3
134 #define NTP_MODE_SERVER 4
135 #define NTP_MODE_BCAST 5
136 #define NTP_MODE_CTRL 6
137 #define NTP_MODE_PRIV 7
139 static const value_string mode_types[] = {
140 { NTP_MODE_RSV, "reserved" },
141 { NTP_MODE_SYMACT, "symmetric active" },
142 { NTP_MODE_SYMPAS, "symmetric passive" },
143 { NTP_MODE_CLIENT, "client" },
144 { NTP_MODE_SERVER, "server" },
145 { NTP_MODE_BCAST, "broadcast" },
146 { NTP_MODE_CTRL, "reserved for NTP control message"},
147 { NTP_MODE_PRIV, "reserved for private use" },
151 /* According to rfc, primary (stratum-0 and stratum-1) servers should set
152 * their Reference Clock ID (4bytes field) according to following table:
154 static const struct {
157 } primary_sources[] = {
158 { "LOCL", "uncalibrated local clock" },
159 { "PPS\0", "atomic clock or other pulse-per-second source" },
160 { "ACTS", "NIST dialup modem service" },
161 { "USNO", "USNO modem service" },
162 { "PTB\0", "PTB (Germany) modem service" },
163 { "TDF\0", "Allouis (France) Radio 164 kHz" },
164 { "DCF\0", "Mainflingen (Germany) Radio 77.5 kHz" },
165 { "MSF\0", "Rugby (UK) Radio 60 kHz" },
166 { "WWV\0", "Ft. Collins (US) Radio 2.5, 5, 10, 15, 20 MHz" },
167 { "WWVB", "Boulder (US) Radio 60 kHz" },
168 { "WWVH", "Kaui Hawaii (US) Radio 2.5, 5, 10, 15 MHz" },
169 { "CHU\0", "Ottawa (Canada) Radio 3330, 7335, 14670 kHz" },
170 { "LORC", "LORAN-C radionavigation system" },
171 { "OMEG", "OMEGA radionavigation system" },
172 { "GPS\0", "Global Positioning Service" },
173 { "GOES", "Geostationary Orbit Environment Satellite" },
174 { "DCN\0", "DCN routing protocol" },
175 { "NIST", "NIST public modem" },
176 { "TSP\0", "TSP time protocol" },
177 { "DTS\0", "Digital Time Service" },
178 { "ATOM", "Atomic clock (calibrated)" },
179 { "VLF\0", "VLF radio (OMEGA,, etc.)" },
180 { "IRIG", "IRIG-B timecode" },
181 { "1PPS", "External 1 PPS input" },
182 { "FREE", "(Internal clock)" },
183 { "INIT", "(Initialization)" },
184 { "\0\0\0\0", "NULL" },
188 #define NTP_EXT_R_MASK 0x80
190 static const value_string ext_r_types[] = {
196 #define NTP_EXT_ERROR_MASK 0x40
197 #define NTP_EXT_VN_MASK 0x3f
199 static const value_string ext_op_types[] = {
213 #define NTPCTRL_R_MASK 0x80
215 #define ctrl_r_types ext_r_types
217 #define NTPCTRL_ERROR_MASK 0x40
218 #define NTPCTRL_MORE_MASK 0x20
219 #define NTPCTRL_OP_MASK 0x1f
221 static const value_string ctrl_op_types[] = {
234 #define NTPPRIV_R_MASK 0x80
236 #define priv_r_types ext_r_types
238 #define NTPPRIV_MORE_MASK 0x40
240 #define NTPPRIV_AUTH_MASK 0x80
241 #define NTPPRIV_SEQ_MASK 0x7f
243 static const value_string priv_impl_types[] = {
245 { 2, "XNTPD_OLD (pre-IPv6)" },
250 static const value_string priv_rc_types[] = {
252 { 1, "PEER_LIST_SUM" },
260 { 9, "TIMER_STATS" },
263 { 12, "SET_SYS_FLAG" },
264 { 13, "CLR_SYS_FLAG" },
265 { 16, "GET_RESTRICT" },
266 { 17, "RESADDFLAGS" },
267 { 18, "RESSUBFLAGS" },
268 { 19, "UNRESTRICT" },
269 { 20, "MON_GETLIST" },
270 { 21, "RESET_STATS" },
271 { 22, "RESET_PEER" },
272 { 23, "REREAD_KEYS" },
274 { 27, "UNTRUSTKEY" },
279 { 32, "REQUEST_KEY" },
280 { 33, "CONTROL_KEY" },
281 { 34, "GET_CTLSTATS" },
282 { 36, "GET_CLOCKINFO" },
283 { 37, "SET_CLKFUDGE" },
284 { 38, "GET_KERNEL" },
285 { 39, "GET_CLKBUGINFO" },
286 { 42, "MON_GETLIST_1" },
287 { 43, "HOSTNAME_ASSOCID" },
292 * Maximum MAC length.
294 #define MAX_MAC_LEN (5 * sizeof (guint32))
296 static int proto_ntp = -1;
298 static int hf_ntp_flags = -1;
299 static int hf_ntp_flags_li = -1;
300 static int hf_ntp_flags_vn = -1;
301 static int hf_ntp_flags_mode = -1;
302 static int hf_ntp_stratum = -1;
303 static int hf_ntp_ppoll = -1;
304 static int hf_ntp_precision = -1;
305 static int hf_ntp_rootdelay = -1;
306 static int hf_ntp_rootdispersion = -1;
307 static int hf_ntp_refid = -1;
308 static int hf_ntp_reftime = -1;
309 static int hf_ntp_org = -1;
310 static int hf_ntp_rec = -1;
311 static int hf_ntp_xmt = -1;
312 static int hf_ntp_keyid = -1;
313 static int hf_ntp_mac = -1;
315 static int hf_ntp_ext = -1;
316 static int hf_ntp_ext_flags = -1;
317 static int hf_ntp_ext_flags_r = -1;
318 static int hf_ntp_ext_flags_error = -1;
319 static int hf_ntp_ext_flags_vn = -1;
320 static int hf_ntp_ext_op = -1;
321 static int hf_ntp_ext_len = -1;
322 static int hf_ntp_ext_associd = -1;
323 static int hf_ntp_ext_tstamp = -1;
324 static int hf_ntp_ext_fstamp = -1;
325 static int hf_ntp_ext_vallen = -1;
326 static int hf_ntp_ext_val = -1;
327 static int hf_ntp_ext_siglen = -1;
328 static int hf_ntp_ext_sig = -1;
330 static int hf_ntpctrl_flags2 = -1;
331 static int hf_ntpctrl_flags2_r = -1;
332 static int hf_ntpctrl_flags2_error = -1;
333 static int hf_ntpctrl_flags2_more = -1;
334 static int hf_ntpctrl_flags2_opcode = -1;
336 static int hf_ntppriv_flags_r = -1;
337 static int hf_ntppriv_flags_more = -1;
338 static int hf_ntppriv_auth_seq = -1;
339 static int hf_ntppriv_auth = -1;
340 static int hf_ntppriv_seq = -1;
341 static int hf_ntppriv_impl = -1;
342 static int hf_ntppriv_reqcode = -1;
344 static gint ett_ntp = -1;
345 static gint ett_ntp_flags = -1;
346 static gint ett_ntp_ext = -1;
347 static gint ett_ntp_ext_flags = -1;
348 static gint ett_ntpctrl_flags2 = -1;
349 static gint ett_ntppriv_auth_seq = -1;
351 static void dissect_ntp_std(tvbuff_t *, proto_tree *, guint8);
352 static void dissect_ntp_ctrl(tvbuff_t *, proto_tree *, guint8);
353 static void dissect_ntp_priv(tvbuff_t *, proto_tree *, guint8);
354 static int dissect_ntp_ext(tvbuff_t *, proto_tree *, int);
356 static const char *mon_names[12] = {
371 /* ntp_fmt_ts - converts NTP timestamp to human readable string.
372 * reftime - 64bit timestamp (IN)
373 * returns pointer to filled buffer. This buffer will be freed automatically once
374 * dissection of the next packet occurs.
377 ntp_fmt_ts(const guint8 *reftime)
379 guint32 tempstmp, tempfrac;
385 tempstmp = pntohl(&reftime[0]);
386 tempfrac = pntohl(&reftime[4]);
387 if ((tempstmp == 0) && (tempfrac == 0)) {
391 temptime = tempstmp - (guint32) NTP_BASETIME;
392 bd = gmtime(&temptime);
394 return "Not representable";
397 fractime = bd->tm_sec + tempfrac / 4294967296.0;
398 buff=ep_alloc(NTP_TS_SIZE);
399 g_snprintf(buff, NTP_TS_SIZE,
400 "%s %2d, %d %02d:%02d:%07.4f UTC",
401 mon_names[bd->tm_mon],
410 /* dissect_ntp - dissects NTP packet data
411 * tvb - tvbuff for packet data (IN)
412 * pinfo - packet info
413 * proto_tree - resolved protocol tree
416 dissect_ntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
418 proto_tree *ntp_tree;
422 void (*dissector)(tvbuff_t *, proto_item *, guint8);
424 if (check_col(pinfo->cinfo, COL_PROTOCOL))
425 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NTP");
427 if (check_col(pinfo->cinfo, COL_INFO))
428 col_clear(pinfo->cinfo, COL_INFO);
430 flags = tvb_get_guint8(tvb, 0);
431 switch (flags & NTP_MODE_MASK) {
434 dissector = dissect_ntp_std;
437 infostr = "NTP control";
438 dissector = dissect_ntp_ctrl;
441 infostr = "NTP private";
442 dissector = dissect_ntp_priv;
446 if (check_col(pinfo->cinfo, COL_INFO))
447 col_set_str(pinfo->cinfo, COL_INFO, infostr);
450 /* Adding NTP item and subtree */
451 ti = proto_tree_add_item(tree, proto_ntp, tvb, 0, -1, FALSE);
452 ntp_tree = proto_item_add_subtree(ti, ett_ntp);
454 (*dissector)(tvb, ntp_tree, flags);
459 dissect_ntp_std(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
461 proto_tree *flags_tree;
467 double rootdispersion;
470 const guint8 *reftime;
479 tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
481 /* Adding flag subtree and items */
482 flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
483 proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
484 proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
485 proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
487 /* Stratum, 1byte field represents distance from primary source
489 stratum = tvb_get_guint8(tvb, 1);
491 buff="Peer Clock Stratum: unspecified or unavailable (%u)";
492 } else if (stratum == 1) {
493 buff="Peer Clock Stratum: primary reference (%u)";
494 } else if ((stratum >= 2) && (stratum <= 15)) {
495 buff="Peer Clock Stratum: secondary reference (%u)";
497 buff="Peer Clock Stratum: reserved: %u";
499 proto_tree_add_uint_format(ntp_tree, hf_ntp_stratum, tvb, 1, 1,
500 stratum, buff, stratum);
501 /* Poll interval, 1byte field indicating the maximum interval
502 * between successive messages, in seconds to the nearest
505 ppoll = tvb_get_guint8(tvb, 2);
506 proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
508 (((ppoll >= 4) && (ppoll <= 16)) ?
509 "Peer Polling Interval: %u (%u sec)" :
510 "Peer Polling Interval: invalid (%u)"),
514 /* Precision, 1byte field indicating the precision of the
515 * local clock, in seconds to the nearest power of two.
517 precision = tvb_get_guint8(tvb, 3);
518 proto_tree_add_int_format(ntp_tree, hf_ntp_precision, tvb, 3, 1,
520 "Peer Clock Precision: %8.6f sec",
523 /* Root Delay is a 32-bit signed fixed-point number indicating
524 * the total roundtrip delay to the primary reference source,
525 * in seconds with fraction point between bits 15 and 16.
527 rootdelay = ((gint16)tvb_get_ntohs(tvb, 4)) +
528 (tvb_get_ntohs(tvb, 6) / 65536.0);
529 proto_tree_add_double_format(ntp_tree, hf_ntp_rootdelay, tvb, 4, 4,
531 "Root Delay: %9.4f sec",
534 /* Root Dispersion, 32-bit unsigned fixed-point number indicating
535 * the nominal error relative to the primary reference source, in
536 * seconds with fraction point between bits 15 and 16.
538 rootdispersion = ((gint16)tvb_get_ntohs(tvb, 8)) +
539 (tvb_get_ntohs(tvb, 10) / 65536.0);
540 proto_tree_add_double_format(ntp_tree, hf_ntp_rootdispersion, tvb, 8, 4,
542 "Root Dispersion: %9.4f sec",
545 /* Now, there is a problem with secondary servers. Standards
546 * asks from stratum-2 - stratum-15 servers to set this to the
547 * low order 32 bits of the latest transmit timestamp of the
549 * But, all V3 and V4 servers set this to IP adress of their
550 * higher level server. My decision was to resolve this address.
552 refid = tvb_get_ptr(tvb, 12, 4);
553 buff = ep_alloc(NTP_TS_SIZE);
555 g_snprintf (buff, NTP_TS_SIZE, "Unidentified reference source '%.4s'",
557 for (i = 0; primary_sources[i].id; i++) {
558 if (memcmp (refid, primary_sources[i].id, 4) == 0) {
559 g_snprintf(buff, NTP_TS_SIZE, "%s",
560 primary_sources[i].data);
566 refid_addr = tvb_get_ipv4(tvb, 12);
567 buffpos = g_snprintf(buff, NTP_TS_SIZE, "%s", get_hostname (refid_addr));
568 if (buffpos >= NTP_TS_SIZE) {
569 buff[NTP_TS_SIZE-4]='.';
570 buff[NTP_TS_SIZE-3]='.';
571 buff[NTP_TS_SIZE-2]='.';
572 buff[NTP_TS_SIZE-1]=0;
575 proto_tree_add_bytes_format(ntp_tree, hf_ntp_refid, tvb, 12, 4,
577 "Reference Clock ID: %s", buff);
579 /* Reference Timestamp: This is the time at which the local clock was
580 * last set or corrected.
582 reftime = tvb_get_ptr(tvb, 16, 8);
583 proto_tree_add_bytes_format(ntp_tree, hf_ntp_reftime, tvb, 16, 8,
585 "Reference Clock Update Time: %s",
586 ntp_fmt_ts(reftime));
588 /* Originate Timestamp: This is the time at which the request departed
589 * the client for the server.
591 org = tvb_get_ptr(tvb, 24, 8);
592 proto_tree_add_bytes_format(ntp_tree, hf_ntp_org, tvb, 24, 8,
594 "Originate Time Stamp: %s",
597 /* Receive Timestamp: This is the time at which the request arrived at
600 rec = tvb_get_ptr(tvb, 32, 8);
601 proto_tree_add_bytes_format(ntp_tree, hf_ntp_rec, tvb, 32, 8,
603 "Receive Time Stamp: %s",
606 /* Transmit Timestamp: This is the time at which the reply departed the
607 * server for the client.
609 xmt = tvb_get_ptr(tvb, 40, 8);
610 proto_tree_add_bytes_format(ntp_tree, hf_ntp_xmt, tvb, 40, 8,
612 "Transmit Time Stamp: %s",
615 /* MAX_MAC_LEN is the largest message authentication code
616 * (MAC) length. If we have more data left in the packet
617 * after the header than that, the extra data is NTP4
618 * extensions; parse them as such.
621 while (tvb_reported_length_remaining(tvb, macofs) > (gint)MAX_MAC_LEN)
622 macofs = dissect_ntp_ext(tvb, ntp_tree, macofs);
624 /* When the NTP authentication scheme is implemented, the
625 * Key Identifier and Message Digest fields contain the
626 * message authentication code (MAC) information defined in
627 * Appendix C of RFC-1305. Will print this as hex code for now.
629 if (tvb_reported_length_remaining(tvb, macofs) >= 4)
630 proto_tree_add_item(ntp_tree, hf_ntp_keyid, tvb, macofs, 4,
633 maclen = tvb_reported_length_remaining(tvb, macofs);
635 proto_tree_add_item(ntp_tree, hf_ntp_mac, tvb, macofs,
640 dissect_ntp_ext(tvbuff_t *tvb, proto_tree *ntp_tree, int offset)
642 proto_tree *ext_tree, *flags_tree;
647 guint32 vallen, vallen_round, siglen;
649 extlen = tvb_get_ntohs(tvb, offset+2);
651 /* Extension length isn't enough for the extension header.
652 * Report the error, and return an offset that goes to
653 * the end of the tvbuff, so we stop dissecting.
655 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
656 "Extension length %u < 8", extlen);
657 offset += tvb_length_remaining(tvb, offset);
661 /* Extension length isn't a multiple of 4.
662 * Report the error, and return an offset that goes
663 * to the end of the tvbuff, so we stop dissecting.
665 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
666 "Extension length %u isn't a multiple of 4",
668 offset += tvb_length_remaining(tvb, offset);
671 endoffset = offset + extlen;
673 tf = proto_tree_add_item(ntp_tree, hf_ntp_ext, tvb, offset, extlen,
675 ext_tree = proto_item_add_subtree(tf, ett_ntp_ext);
677 flags = tvb_get_guint8(tvb, offset);
678 tf = proto_tree_add_uint(ext_tree, hf_ntp_ext_flags, tvb, offset, 1,
680 flags_tree = proto_item_add_subtree(tf, ett_ntp_ext_flags);
681 proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_r, tvb, offset, 1,
683 proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_error, tvb, offset, 1,
685 proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_vn, tvb, offset, 1,
689 proto_tree_add_item(ext_tree, hf_ntp_ext_op, tvb, offset, 1, FALSE);
692 proto_tree_add_uint(ext_tree, hf_ntp_ext_len, tvb, offset, 2, extlen);
695 if ((flags & NTP_EXT_VN_MASK) != 2) {
696 /* don't care about autokey v1 */
700 proto_tree_add_item(ext_tree, hf_ntp_ext_associd, tvb, offset, 4,
704 /* check whether everything up to "vallen" is present */
705 if (extlen < MAX_MAC_LEN) {
706 /* XXX - report as error? */
710 proto_tree_add_item(ext_tree, hf_ntp_ext_tstamp, tvb, offset, 4,
713 proto_tree_add_item(ext_tree, hf_ntp_ext_fstamp, tvb, offset, 4,
716 /* XXX fstamp can be server flags */
718 vallen = tvb_get_ntohl(tvb, offset);
719 proto_tree_add_uint(ext_tree, hf_ntp_ext_vallen, tvb, offset, 4,
722 vallen_round = (vallen + 3) & (-4);
724 if ((guint32)(endoffset - offset) < vallen_round) {
726 * Value goes past the length of the extension
729 proto_tree_add_text(ext_tree, tvb, offset,
731 "Value length makes value go past the end of the extension field");
734 proto_tree_add_item(ext_tree, hf_ntp_ext_val, tvb, offset,
737 offset += vallen_round;
739 siglen = tvb_get_ntohl(tvb, offset);
740 proto_tree_add_uint(ext_tree, hf_ntp_ext_siglen, tvb, offset, 4,
744 if (offset + (int)siglen > endoffset) {
746 * Value goes past the length of the extension
749 proto_tree_add_text(ext_tree, tvb, offset,
751 "Signature length makes value go past the end of the extension field");
754 proto_tree_add_item(ext_tree, hf_ntp_ext_sig, tvb,
755 offset, siglen, FALSE);
761 dissect_ntp_ctrl(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
763 proto_tree *flags_tree;
767 tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
769 /* Adding flag subtree and items */
770 flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
771 proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
772 proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
773 proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
775 flags2 = tvb_get_guint8(tvb, 1);
776 tf = proto_tree_add_uint(ntp_tree, hf_ntpctrl_flags2, tvb, 1, 1,
778 flags_tree = proto_item_add_subtree(tf, ett_ntpctrl_flags2);
779 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_r, tvb, 1, 1,
781 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_error, tvb, 1, 1,
783 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_more, tvb, 1, 1,
785 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_opcode, tvb, 1, 1,
790 dissect_ntp_priv(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
792 proto_tree *flags_tree;
794 guint8 auth_seq, impl, reqcode;
796 tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
798 /* Adding flag subtree and items */
799 flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
800 proto_tree_add_uint(flags_tree, hf_ntppriv_flags_r, tvb, 0, 1, flags);
801 proto_tree_add_uint(flags_tree, hf_ntppriv_flags_more, tvb, 0, 1,
803 proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
804 proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
806 auth_seq = tvb_get_guint8(tvb, 1);
807 tf = proto_tree_add_uint(ntp_tree, hf_ntppriv_auth_seq, tvb, 1, 1,
809 flags_tree = proto_item_add_subtree(tf, ett_ntppriv_auth_seq);
810 proto_tree_add_uint(flags_tree, hf_ntppriv_auth, tvb, 1, 1, auth_seq);
811 proto_tree_add_uint(flags_tree, hf_ntppriv_seq, tvb, 1, 1, auth_seq);
813 impl = tvb_get_guint8(tvb, 2);
814 proto_tree_add_uint(ntp_tree, hf_ntppriv_impl, tvb, 2, 1, impl);
816 reqcode = tvb_get_guint8(tvb, 3);
817 proto_tree_add_uint(ntp_tree, hf_ntppriv_reqcode, tvb, 3, 1, reqcode);
821 proto_register_ntp(void)
823 static hf_register_info hf[] = {
825 "Flags", "ntp.flags", FT_UINT8, BASE_HEX,
826 NULL, 0, "Flags (Leap/Version/Mode)", HFILL }},
827 { &hf_ntp_flags_li, {
828 "Leap Indicator", "ntp.flags.li", FT_UINT8, BASE_DEC,
829 VALS(li_types), NTP_LI_MASK, "Leap Indicator", HFILL }},
830 { &hf_ntp_flags_vn, {
831 "Version number", "ntp.flags.vn", FT_UINT8, BASE_DEC,
832 VALS(ver_nums), NTP_VN_MASK, "Version number", HFILL }},
833 { &hf_ntp_flags_mode, {
834 "Mode", "ntp.flags.mode", FT_UINT8, BASE_DEC,
835 VALS(mode_types), NTP_MODE_MASK, "Mode", HFILL }},
837 "Peer Clock Stratum", "ntp.stratum", FT_UINT8, BASE_DEC,
838 NULL, 0, "Peer Clock Stratum", HFILL }},
840 "Peer Polling Interval", "ntp.ppoll", FT_UINT8, BASE_DEC,
841 NULL, 0, "Peer Polling Interval", HFILL }},
842 { &hf_ntp_precision, {
843 "Peer Clock Precision", "ntp.precision", FT_INT8, BASE_DEC,
844 NULL, 0, "Peer Clock Precision", HFILL }},
845 { &hf_ntp_rootdelay, {
846 "Root Delay", "ntp.rootdelay", FT_DOUBLE, BASE_DEC,
847 NULL, 0, "Root Delay", HFILL }},
848 { &hf_ntp_rootdispersion, {
849 "Root Dispersion", "ntp.rootdispersion", FT_DOUBLE, BASE_DEC,
850 NULL, 0, "Root Dispersion", HFILL }},
852 "Reference Clock ID", "ntp.refid", FT_BYTES, BASE_NONE,
853 NULL, 0, "Reference Clock ID", HFILL }},
855 "Reference Clock Update Time", "ntp.reftime", FT_BYTES, BASE_NONE,
856 NULL, 0, "Reference Clock Update Time", HFILL }},
858 "Originate Time Stamp", "ntp.org", FT_BYTES, BASE_NONE,
859 NULL, 0, "Originate Time Stamp", HFILL }},
861 "Receive Time Stamp", "ntp.rec", FT_BYTES, BASE_NONE,
862 NULL, 0, "Receive Time Stamp", HFILL }},
864 "Transmit Time Stamp", "ntp.xmt", FT_BYTES, BASE_NONE,
865 NULL, 0, "Transmit Time Stamp", HFILL }},
867 "Key ID", "ntp.keyid", FT_BYTES, BASE_HEX,
868 NULL, 0, "Key ID", HFILL }},
870 "Message Authentication Code", "ntp.mac", FT_BYTES, BASE_HEX,
871 NULL, 0, "Message Authentication Code", HFILL }},
874 "Extension", "ntp.ext", FT_NONE, BASE_NONE,
875 NULL, 0, "Extension", HFILL }},
876 { &hf_ntp_ext_flags, {
877 "Flags", "ntp.ext.flags", FT_UINT8, BASE_HEX,
878 NULL, 0, "Flags (Response/Error/Version)", HFILL }},
879 { &hf_ntp_ext_flags_r, {
880 "Response bit", "ntp.ext.flags.r", FT_UINT8, BASE_DEC,
881 VALS(ext_r_types), NTP_EXT_R_MASK, "Response bit", HFILL }},
882 { &hf_ntp_ext_flags_error, {
883 "Error bit", "ntp.ext.flags.error", FT_UINT8, BASE_DEC,
884 NULL, NTP_EXT_ERROR_MASK, "Error bit", HFILL }},
885 { &hf_ntp_ext_flags_vn, {
886 "Version", "ntp.ext.flags.vn", FT_UINT8, BASE_DEC,
887 NULL, NTP_EXT_VN_MASK, "Version", HFILL }},
889 "Opcode", "ntp.ext.op", FT_UINT8, BASE_DEC,
890 VALS(ext_op_types), 0, "Opcode", HFILL }},
892 "Extension length", "ntp.ext.len", FT_UINT16, BASE_DEC,
893 NULL, 0, "Extension length", HFILL }},
894 { &hf_ntp_ext_associd, {
895 "Association ID", "ntp.ext.associd", FT_UINT32, BASE_DEC,
896 NULL, 0, "Association ID", HFILL }},
897 { &hf_ntp_ext_tstamp, {
898 "Timestamp", "ntp.ext.tstamp", FT_UINT32, BASE_HEX,
899 NULL, 0, "Timestamp", HFILL }},
900 { &hf_ntp_ext_fstamp, {
901 "File Timestamp", "ntp.ext.fstamp", FT_UINT32, BASE_HEX,
902 NULL, 0, "File Timestamp", HFILL }},
903 { &hf_ntp_ext_vallen, {
904 "Value length", "ntp.ext.vallen", FT_UINT32, BASE_DEC,
905 NULL, 0, "Value length", HFILL }},
907 "Value", "ntp.ext.val", FT_BYTES, BASE_HEX,
908 NULL, 0, "Value", HFILL }},
909 { &hf_ntp_ext_siglen, {
910 "Signature length", "ntp.ext.siglen", FT_UINT32, BASE_DEC,
911 NULL, 0, "Signature length", HFILL }},
913 "Signature", "ntp.ext.sig", FT_BYTES, BASE_HEX,
914 NULL, 0, "Signature", HFILL }},
916 { &hf_ntpctrl_flags2, {
917 "Flags 2", "ntpctrl.flags2", FT_UINT8, BASE_HEX,
918 NULL, 0, "Flags (Response/Error/More/Opcode)", HFILL }},
919 { &hf_ntpctrl_flags2_r, {
920 "Response bit", "ntpctrl.flags2.r", FT_UINT8, BASE_DEC,
921 VALS(ctrl_r_types), NTPCTRL_R_MASK, "Response bit", HFILL }},
922 { &hf_ntpctrl_flags2_error, {
923 "Error bit", "ntpctrl.flags2.error", FT_UINT8, BASE_DEC,
924 NULL, NTPCTRL_ERROR_MASK, "Error bit", HFILL }},
925 { &hf_ntpctrl_flags2_more, {
926 "More bit", "ntpctrl.flags2.more", FT_UINT8, BASE_DEC,
927 NULL, NTPCTRL_MORE_MASK, "More bit", HFILL }},
928 { &hf_ntpctrl_flags2_opcode, {
929 "Opcode", "ntpctrl.flags2.opcode", FT_UINT8, BASE_DEC,
930 VALS(ctrl_op_types), NTPCTRL_OP_MASK, "Opcode", HFILL }},
932 { &hf_ntppriv_flags_r, {
933 "Response bit", "ntppriv.flags.r", FT_UINT8, BASE_DEC,
934 VALS(priv_r_types), NTPPRIV_R_MASK, "Response bit", HFILL }},
935 { &hf_ntppriv_flags_more, {
936 "More bit", "ntppriv.flags.more", FT_UINT8, BASE_DEC,
937 NULL, NTPPRIV_MORE_MASK, "More bit", HFILL }},
938 { &hf_ntppriv_auth_seq, {
939 "Auth, sequence", "ntppriv.auth_seq", FT_UINT8, BASE_DEC,
940 NULL, 0, "Auth bit, sequence number", HFILL }},
941 { &hf_ntppriv_auth, {
942 "Auth bit", "ntppriv.auth", FT_UINT8, BASE_DEC,
943 NULL, NTPPRIV_AUTH_MASK, "Auth bit", HFILL }},
945 "Sequence number", "ntppriv.seq", FT_UINT8, BASE_DEC,
946 NULL, NTPPRIV_SEQ_MASK, "Sequence number", HFILL }},
947 { &hf_ntppriv_impl, {
948 "Implementation", "ntppriv.impl", FT_UINT8, BASE_DEC,
949 VALS(priv_impl_types), 0, "Implementation", HFILL }},
950 { &hf_ntppriv_reqcode, {
951 "Request code", "ntppriv.reqcode", FT_UINT8, BASE_DEC,
952 VALS(priv_rc_types), 0, "Request code", HFILL }},
954 static gint *ett[] = {
960 &ett_ntppriv_auth_seq,
963 proto_ntp = proto_register_protocol("Network Time Protocol", "NTP",
965 proto_register_field_array(proto_ntp, hf, array_length(hf));
966 proto_register_subtree_array(ett, array_length(ett));
970 proto_reg_handoff_ntp(void)
972 dissector_handle_t ntp_handle;
974 ntp_handle = create_dissector_handle(dissect_ntp, proto_ntp);
975 dissector_add("udp.port", UDP_PORT_NTP, ntp_handle);
976 dissector_add("tcp.port", TCP_PORT_NTP, ntp_handle);