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)" },
186 #define NTP_EXT_R_MASK 0x80
188 static const value_string ext_r_types[] = {
194 #define NTP_EXT_ERROR_MASK 0x40
195 #define NTP_EXT_VN_MASK 0x3f
197 static const value_string ext_op_types[] = {
211 #define NTPCTRL_R_MASK 0x80
213 #define ctrl_r_types ext_r_types
215 #define NTPCTRL_ERROR_MASK 0x40
216 #define NTPCTRL_MORE_MASK 0x20
217 #define NTPCTRL_OP_MASK 0x1f
219 static const value_string ctrl_op_types[] = {
232 #define NTPPRIV_R_MASK 0x80
234 #define priv_r_types ext_r_types
236 #define NTPPRIV_MORE_MASK 0x40
238 #define NTPPRIV_AUTH_MASK 0x80
239 #define NTPPRIV_SEQ_MASK 0x7f
241 static const value_string priv_impl_types[] = {
243 { 2, "XNTPD_OLD (pre-IPv6)" },
248 static const value_string priv_rc_types[] = {
250 { 1, "PEER_LIST_SUM" },
258 { 9, "TIMER_STATS" },
261 { 12, "SET_SYS_FLAG" },
262 { 13, "CLR_SYS_FLAG" },
263 { 16, "GET_RESTRICT" },
264 { 17, "RESADDFLAGS" },
265 { 18, "RESSUBFLAGS" },
266 { 19, "UNRESTRICT" },
267 { 20, "MON_GETLIST" },
268 { 21, "RESET_STATS" },
269 { 22, "RESET_PEER" },
270 { 23, "REREAD_KEYS" },
272 { 27, "UNTRUSTKEY" },
277 { 32, "REQUEST_KEY" },
278 { 33, "CONTROL_KEY" },
279 { 34, "GET_CTLSTATS" },
280 { 36, "GET_CLOCKINFO" },
281 { 37, "SET_CLKFUDGE" },
282 { 38, "GET_KERNEL" },
283 { 39, "GET_CLKBUGINFO" },
284 { 42, "MON_GETLIST_1" },
285 { 43, "HOSTNAME_ASSOCID" },
290 * Maximum MAC length.
292 #define MAX_MAC_LEN (5 * sizeof (guint32))
294 static int proto_ntp = -1;
296 static int hf_ntp_flags = -1;
297 static int hf_ntp_flags_li = -1;
298 static int hf_ntp_flags_vn = -1;
299 static int hf_ntp_flags_mode = -1;
300 static int hf_ntp_stratum = -1;
301 static int hf_ntp_ppoll = -1;
302 static int hf_ntp_precision = -1;
303 static int hf_ntp_rootdelay = -1;
304 static int hf_ntp_rootdispersion = -1;
305 static int hf_ntp_refid = -1;
306 static int hf_ntp_reftime = -1;
307 static int hf_ntp_org = -1;
308 static int hf_ntp_rec = -1;
309 static int hf_ntp_xmt = -1;
310 static int hf_ntp_keyid = -1;
311 static int hf_ntp_mac = -1;
313 static int hf_ntp_ext = -1;
314 static int hf_ntp_ext_flags = -1;
315 static int hf_ntp_ext_flags_r = -1;
316 static int hf_ntp_ext_flags_error = -1;
317 static int hf_ntp_ext_flags_vn = -1;
318 static int hf_ntp_ext_op = -1;
319 static int hf_ntp_ext_len = -1;
320 static int hf_ntp_ext_associd = -1;
321 static int hf_ntp_ext_tstamp = -1;
322 static int hf_ntp_ext_fstamp = -1;
323 static int hf_ntp_ext_vallen = -1;
324 static int hf_ntp_ext_val = -1;
325 static int hf_ntp_ext_siglen = -1;
326 static int hf_ntp_ext_sig = -1;
328 static int hf_ntpctrl_flags2 = -1;
329 static int hf_ntpctrl_flags2_r = -1;
330 static int hf_ntpctrl_flags2_error = -1;
331 static int hf_ntpctrl_flags2_more = -1;
332 static int hf_ntpctrl_flags2_opcode = -1;
334 static int hf_ntppriv_flags_r = -1;
335 static int hf_ntppriv_flags_more = -1;
336 static int hf_ntppriv_auth_seq = -1;
337 static int hf_ntppriv_auth = -1;
338 static int hf_ntppriv_seq = -1;
339 static int hf_ntppriv_impl = -1;
340 static int hf_ntppriv_reqcode = -1;
342 static gint ett_ntp = -1;
343 static gint ett_ntp_flags = -1;
344 static gint ett_ntp_ext = -1;
345 static gint ett_ntp_ext_flags = -1;
346 static gint ett_ntpctrl_flags2 = -1;
347 static gint ett_ntppriv_auth_seq = -1;
349 static void dissect_ntp_std(tvbuff_t *, proto_tree *, guint8);
350 static void dissect_ntp_ctrl(tvbuff_t *, proto_tree *, guint8);
351 static void dissect_ntp_priv(tvbuff_t *, proto_tree *, guint8);
352 static int dissect_ntp_ext(tvbuff_t *, proto_tree *, int);
354 static const char *mon_names[12] = {
369 /* ntp_fmt_ts - converts NTP timestamp to human readable string.
370 * reftime - 64bit timestamp (IN)
371 * returns pointer to filled buffer. This buffer will be freed automatically once
372 * dissection of the next packet occurs.
375 ntp_fmt_ts(const guint8 *reftime)
377 guint32 tempstmp, tempfrac;
383 tempstmp = pntohl(&reftime[0]);
384 tempfrac = pntohl(&reftime[4]);
385 if ((tempstmp == 0) && (tempfrac == 0)) {
389 temptime = tempstmp - (guint32) NTP_BASETIME;
390 bd = gmtime(&temptime);
392 return "Not representable";
395 fractime = bd->tm_sec + tempfrac / 4294967296.0;
396 buff=ep_alloc(NTP_TS_SIZE);
397 g_snprintf(buff, NTP_TS_SIZE,
398 "%s %2d, %d %02d:%02d:%07.4f UTC",
399 mon_names[bd->tm_mon],
408 /* dissect_ntp - dissects NTP packet data
409 * tvb - tvbuff for packet data (IN)
410 * pinfo - packet info
411 * proto_tree - resolved protocol tree
414 dissect_ntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
416 proto_tree *ntp_tree;
420 void (*dissector)(tvbuff_t *, proto_item *, guint8);
422 if (check_col(pinfo->cinfo, COL_PROTOCOL))
423 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NTP");
425 if (check_col(pinfo->cinfo, COL_INFO))
426 col_clear(pinfo->cinfo, COL_INFO);
428 flags = tvb_get_guint8(tvb, 0);
429 switch (flags & NTP_MODE_MASK) {
432 dissector = dissect_ntp_std;
435 infostr = "NTP control";
436 dissector = dissect_ntp_ctrl;
439 infostr = "NTP private";
440 dissector = dissect_ntp_priv;
444 if (check_col(pinfo->cinfo, COL_INFO))
445 col_set_str(pinfo->cinfo, COL_INFO, infostr);
448 /* Adding NTP item and subtree */
449 ti = proto_tree_add_item(tree, proto_ntp, tvb, 0, -1, FALSE);
450 ntp_tree = proto_item_add_subtree(ti, ett_ntp);
452 (*dissector)(tvb, ntp_tree, flags);
457 dissect_ntp_std(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
459 proto_tree *flags_tree;
465 double rootdispersion;
468 const guint8 *reftime;
477 tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
479 /* Adding flag subtree and items */
480 flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
481 proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
482 proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
483 proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
485 /* Stratum, 1byte field represents distance from primary source
487 stratum = tvb_get_guint8(tvb, 1);
489 buff="Peer Clock Stratum: unspecified or unavailable (%u)";
490 } else if (stratum == 1) {
491 buff="Peer Clock Stratum: primary reference (%u)";
492 } else if ((stratum >= 2) && (stratum <= 15)) {
493 buff="Peer Clock Stratum: secondary reference (%u)";
495 buff="Peer Clock Stratum: reserved: %u";
497 proto_tree_add_uint_format(ntp_tree, hf_ntp_stratum, tvb, 1, 1,
498 stratum, buff, stratum);
499 /* Poll interval, 1byte field indicating the maximum interval
500 * between successive messages, in seconds to the nearest
503 ppoll = tvb_get_guint8(tvb, 2);
504 proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
506 (((ppoll >= 4) && (ppoll <= 16)) ?
507 "Peer Polling Interval: %u (%u sec)" :
508 "Peer Polling Interval: invalid (%u)"),
512 /* Precision, 1byte field indicating the precision of the
513 * local clock, in seconds to the nearest power of two.
515 precision = tvb_get_guint8(tvb, 3);
516 proto_tree_add_int_format(ntp_tree, hf_ntp_precision, tvb, 3, 1,
518 "Peer Clock Precision: %8.6f sec",
521 /* Root Delay is a 32-bit signed fixed-point number indicating
522 * the total roundtrip delay to the primary reference source,
523 * in seconds with fraction point between bits 15 and 16.
525 rootdelay = ((gint16)tvb_get_ntohs(tvb, 4)) +
526 (tvb_get_ntohs(tvb, 6) / 65536.0);
527 proto_tree_add_double_format(ntp_tree, hf_ntp_rootdelay, tvb, 4, 4,
529 "Root Delay: %9.4f sec",
532 /* Root Dispersion, 32-bit unsigned fixed-point number indicating
533 * the nominal error relative to the primary reference source, in
534 * seconds with fraction point between bits 15 and 16.
536 rootdispersion = ((gint16)tvb_get_ntohs(tvb, 8)) +
537 (tvb_get_ntohs(tvb, 10) / 65536.0);
538 proto_tree_add_double_format(ntp_tree, hf_ntp_rootdispersion, tvb, 8, 4,
540 "Clock Dispersion: %9.4f sec",
543 /* Now, there is a problem with secondary servers. Standards
544 * asks from stratum-2 - stratum-15 servers to set this to the
545 * low order 32 bits of the latest transmit timestamp of the
547 * But, all V3 and V4 servers set this to IP adress of their
548 * higher level server. My decision was to resolve this address.
550 refid = tvb_get_ptr(tvb, 12, 4);
552 buff=ep_alloc(NTP_TS_SIZE);
553 g_snprintf (buff, NTP_TS_SIZE, "Unindentified reference source '%.4s'",
555 for (i = 0; primary_sources[i].id; i++) {
556 if (memcmp (refid, primary_sources[i].id, 4) == 0) {
557 g_snprintf(buff, NTP_TS_SIZE, "%s",
558 primary_sources[i].data);
564 buff = ep_alloc(NTP_TS_SIZE);
565 refid_addr = tvb_get_ipv4(tvb, 12);
566 buffpos = g_snprintf(buff, NTP_TS_SIZE, "%s", get_hostname (refid_addr));
567 if (buffpos >= NTP_TS_SIZE) {
568 buff[NTP_TS_SIZE-4]='.';
569 buff[NTP_TS_SIZE-3]='.';
570 buff[NTP_TS_SIZE-2]='.';
571 buff[NTP_TS_SIZE-1]=0;
574 proto_tree_add_bytes_format(ntp_tree, hf_ntp_refid, tvb, 12, 4,
576 "Reference Clock ID: %s", buff);
578 /* Reference Timestamp: This is the time at which the local clock was
579 * last set or corrected.
581 reftime = tvb_get_ptr(tvb, 16, 8);
582 proto_tree_add_bytes_format(ntp_tree, hf_ntp_reftime, tvb, 16, 8,
584 "Reference Clock Update Time: %s",
585 ntp_fmt_ts(reftime));
587 /* Originate Timestamp: This is the time at which the request departed
588 * the client for the server.
590 org = tvb_get_ptr(tvb, 24, 8);
591 proto_tree_add_bytes_format(ntp_tree, hf_ntp_org, tvb, 24, 8,
593 "Originate Time Stamp: %s",
596 /* Receive Timestamp: This is the time at which the request arrived at
599 rec = tvb_get_ptr(tvb, 32, 8);
600 proto_tree_add_bytes_format(ntp_tree, hf_ntp_rec, tvb, 32, 8,
602 "Receive Time Stamp: %s",
605 /* Transmit Timestamp: This is the time at which the reply departed the
606 * server for the client.
608 xmt = tvb_get_ptr(tvb, 40, 8);
609 proto_tree_add_bytes_format(ntp_tree, hf_ntp_xmt, tvb, 40, 8,
611 "Transmit Time Stamp: %s",
614 /* MAX_MAC_LEN is the largest message authentication code
615 * (MAC) length. If we have more data left in the packet
616 * after the header than that, the extra data is NTP4
617 * extensions; parse them as such.
620 while (tvb_reported_length_remaining(tvb, macofs) > (gint)MAX_MAC_LEN)
621 macofs = dissect_ntp_ext(tvb, ntp_tree, macofs);
623 /* When the NTP authentication scheme is implemented, the
624 * Key Identifier and Message Digest fields contain the
625 * message authentication code (MAC) information defined in
626 * Appendix C of RFC-1305. Will print this as hex code for now.
628 if (tvb_reported_length_remaining(tvb, macofs) >= 4)
629 proto_tree_add_item(ntp_tree, hf_ntp_keyid, tvb, macofs, 4,
632 maclen = tvb_reported_length_remaining(tvb, macofs);
634 proto_tree_add_item(ntp_tree, hf_ntp_mac, tvb, macofs,
639 dissect_ntp_ext(tvbuff_t *tvb, proto_tree *ntp_tree, int offset)
641 proto_tree *ext_tree, *flags_tree;
646 guint32 vallen, vallen_round, siglen;
648 extlen = tvb_get_ntohs(tvb, offset+2);
650 /* Extension length isn't enough for the extension header.
651 * Report the error, and return an offset that goes to
652 * the end of the tvbuff, so we stop dissecting.
654 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
655 "Extension length %u < 8", extlen);
656 offset += tvb_length_remaining(tvb, offset);
660 /* Extension length isn't a multiple of 4.
661 * Report the error, and return an offset that goes
662 * to the end of the tvbuff, so we stop dissecting.
664 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
665 "Extension length %u isn't a multiple of 4",
667 offset += tvb_length_remaining(tvb, offset);
670 endoffset = offset + extlen;
672 tf = proto_tree_add_item(ntp_tree, hf_ntp_ext, tvb, offset, extlen,
674 ext_tree = proto_item_add_subtree(tf, ett_ntp_ext);
676 flags = tvb_get_guint8(tvb, offset);
677 tf = proto_tree_add_uint(ext_tree, hf_ntp_ext_flags, tvb, offset, 1,
679 flags_tree = proto_item_add_subtree(tf, ett_ntp_ext_flags);
680 proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_r, tvb, offset, 1,
682 proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_error, tvb, offset, 1,
684 proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_vn, tvb, offset, 1,
688 proto_tree_add_item(ext_tree, hf_ntp_ext_op, tvb, offset, 1, FALSE);
691 proto_tree_add_uint(ext_tree, hf_ntp_ext_len, tvb, offset, 2, extlen);
694 if ((flags & NTP_EXT_VN_MASK) != 2) {
695 /* don't care about autokey v1 */
699 proto_tree_add_item(ext_tree, hf_ntp_ext_associd, tvb, offset, 4,
703 /* check whether everything up to "vallen" is present */
704 if (extlen < MAX_MAC_LEN) {
705 /* XXX - report as error? */
709 proto_tree_add_item(ext_tree, hf_ntp_ext_tstamp, tvb, offset, 4,
712 proto_tree_add_item(ext_tree, hf_ntp_ext_fstamp, tvb, offset, 4,
715 /* XXX fstamp can be server flags */
717 vallen = tvb_get_ntohl(tvb, offset);
718 proto_tree_add_uint(ext_tree, hf_ntp_ext_vallen, tvb, offset, 4,
721 vallen_round = (vallen + 3) & (-4);
723 if ((guint32)(endoffset - offset) < vallen_round) {
725 * Value goes past the length of the extension
728 proto_tree_add_text(ext_tree, tvb, offset,
730 "Value length makes value go past the end of the extension field");
733 proto_tree_add_item(ext_tree, hf_ntp_ext_val, tvb, offset,
736 offset += vallen_round;
738 siglen = tvb_get_ntohl(tvb, offset);
739 proto_tree_add_uint(ext_tree, hf_ntp_ext_siglen, tvb, offset, 4,
743 if (offset + (int)siglen > endoffset) {
745 * Value goes past the length of the extension
748 proto_tree_add_text(ext_tree, tvb, offset,
750 "Signature length makes value go past the end of the extension field");
753 proto_tree_add_item(ext_tree, hf_ntp_ext_sig, tvb,
754 offset, siglen, FALSE);
760 dissect_ntp_ctrl(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
762 proto_tree *flags_tree;
766 tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
768 /* Adding flag subtree and items */
769 flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
770 proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
771 proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
772 proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
774 flags2 = tvb_get_guint8(tvb, 1);
775 tf = proto_tree_add_uint(ntp_tree, hf_ntpctrl_flags2, tvb, 1, 1,
777 flags_tree = proto_item_add_subtree(tf, ett_ntpctrl_flags2);
778 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_r, tvb, 1, 1,
780 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_error, tvb, 1, 1,
782 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_more, tvb, 1, 1,
784 proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_opcode, tvb, 1, 1,
789 dissect_ntp_priv(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
791 proto_tree *flags_tree;
793 guint8 auth_seq, impl, reqcode;
795 tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
797 /* Adding flag subtree and items */
798 flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
799 proto_tree_add_uint(flags_tree, hf_ntppriv_flags_r, tvb, 0, 1, flags);
800 proto_tree_add_uint(flags_tree, hf_ntppriv_flags_more, tvb, 0, 1,
802 proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
803 proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
805 auth_seq = tvb_get_guint8(tvb, 1);
806 tf = proto_tree_add_uint(ntp_tree, hf_ntppriv_auth_seq, tvb, 1, 1,
808 flags_tree = proto_item_add_subtree(tf, ett_ntppriv_auth_seq);
809 proto_tree_add_uint(flags_tree, hf_ntppriv_auth, tvb, 1, 1, auth_seq);
810 proto_tree_add_uint(flags_tree, hf_ntppriv_seq, tvb, 1, 1, auth_seq);
812 impl = tvb_get_guint8(tvb, 2);
813 proto_tree_add_uint(ntp_tree, hf_ntppriv_impl, tvb, 2, 1, impl);
815 reqcode = tvb_get_guint8(tvb, 3);
816 proto_tree_add_uint(ntp_tree, hf_ntppriv_reqcode, tvb, 3, 1, reqcode);
820 proto_register_ntp(void)
822 static hf_register_info hf[] = {
824 "Flags", "ntp.flags", FT_UINT8, BASE_HEX,
825 NULL, 0, "Flags (Leap/Version/Mode)", HFILL }},
826 { &hf_ntp_flags_li, {
827 "Leap Indicator", "ntp.flags.li", FT_UINT8, BASE_DEC,
828 VALS(li_types), NTP_LI_MASK, "Leap Indicator", HFILL }},
829 { &hf_ntp_flags_vn, {
830 "Version number", "ntp.flags.vn", FT_UINT8, BASE_DEC,
831 VALS(ver_nums), NTP_VN_MASK, "Version number", HFILL }},
832 { &hf_ntp_flags_mode, {
833 "Mode", "ntp.flags.mode", FT_UINT8, BASE_DEC,
834 VALS(mode_types), NTP_MODE_MASK, "Mode", HFILL }},
836 "Peer Clock Stratum", "ntp.stratum", FT_UINT8, BASE_DEC,
837 NULL, 0, "Peer Clock Stratum", HFILL }},
839 "Peer Polling Interval", "ntp.ppoll", FT_UINT8, BASE_DEC,
840 NULL, 0, "Peer Polling Interval", HFILL }},
841 { &hf_ntp_precision, {
842 "Peer Clock Precision", "ntp.precision", FT_INT8, BASE_DEC,
843 NULL, 0, "Peer Clock Precision", HFILL }},
844 { &hf_ntp_rootdelay, {
845 "Root Delay", "ntp.rootdelay", FT_DOUBLE, BASE_DEC,
846 NULL, 0, "Root Delay", HFILL }},
847 { &hf_ntp_rootdispersion, {
848 "Clock Dispersion", "ntp.rootdispersion", FT_DOUBLE, BASE_DEC,
849 NULL, 0, "Clock Dispersion", HFILL }},
851 "Reference Clock ID", "ntp.refid", FT_BYTES, BASE_NONE,
852 NULL, 0, "Reference Clock ID", HFILL }},
854 "Reference Clock Update Time", "ntp.reftime", FT_BYTES, BASE_NONE,
855 NULL, 0, "Reference Clock Update Time", HFILL }},
857 "Originate Time Stamp", "ntp.org", FT_BYTES, BASE_NONE,
858 NULL, 0, "Originate Time Stamp", HFILL }},
860 "Receive Time Stamp", "ntp.rec", FT_BYTES, BASE_NONE,
861 NULL, 0, "Receive Time Stamp", HFILL }},
863 "Transmit Time Stamp", "ntp.xmt", FT_BYTES, BASE_NONE,
864 NULL, 0, "Transmit Time Stamp", HFILL }},
866 "Key ID", "ntp.keyid", FT_BYTES, BASE_HEX,
867 NULL, 0, "Key ID", HFILL }},
869 "Message Authentication Code", "ntp.mac", FT_BYTES, BASE_HEX,
870 NULL, 0, "Message Authentication Code", HFILL }},
873 "Extension", "ntp.ext", FT_NONE, BASE_NONE,
874 NULL, 0, "Extension", HFILL }},
875 { &hf_ntp_ext_flags, {
876 "Flags", "ntp.ext.flags", FT_UINT8, BASE_HEX,
877 NULL, 0, "Flags (Response/Error/Version)", HFILL }},
878 { &hf_ntp_ext_flags_r, {
879 "Response bit", "ntp.ext.flags.r", FT_UINT8, BASE_DEC,
880 VALS(ext_r_types), NTP_EXT_R_MASK, "Response bit", HFILL }},
881 { &hf_ntp_ext_flags_error, {
882 "Error bit", "ntp.ext.flags.error", FT_UINT8, BASE_DEC,
883 NULL, NTP_EXT_ERROR_MASK, "Error bit", HFILL }},
884 { &hf_ntp_ext_flags_vn, {
885 "Version", "ntp.ext.flags.vn", FT_UINT8, BASE_DEC,
886 NULL, NTP_EXT_VN_MASK, "Version", HFILL }},
888 "Opcode", "ntp.ext.op", FT_UINT8, BASE_DEC,
889 VALS(ext_op_types), 0, "Opcode", HFILL }},
891 "Extension length", "ntp.ext.len", FT_UINT16, BASE_DEC,
892 NULL, 0, "Extension length", HFILL }},
893 { &hf_ntp_ext_associd, {
894 "Association ID", "ntp.ext.associd", FT_UINT32, BASE_DEC,
895 NULL, 0, "Association ID", HFILL }},
896 { &hf_ntp_ext_tstamp, {
897 "Timestamp", "ntp.ext.tstamp", FT_UINT32, BASE_HEX,
898 NULL, 0, "Timestamp", HFILL }},
899 { &hf_ntp_ext_fstamp, {
900 "File Timestamp", "ntp.ext.fstamp", FT_UINT32, BASE_HEX,
901 NULL, 0, "File Timestamp", HFILL }},
902 { &hf_ntp_ext_vallen, {
903 "Value length", "ntp.ext.vallen", FT_UINT32, BASE_DEC,
904 NULL, 0, "Value length", HFILL }},
906 "Value", "ntp.ext.val", FT_BYTES, BASE_HEX,
907 NULL, 0, "Value", HFILL }},
908 { &hf_ntp_ext_siglen, {
909 "Signature length", "ntp.ext.siglen", FT_UINT32, BASE_DEC,
910 NULL, 0, "Signature length", HFILL }},
912 "Signature", "ntp.ext.sig", FT_BYTES, BASE_HEX,
913 NULL, 0, "Signature", HFILL }},
915 { &hf_ntpctrl_flags2, {
916 "Flags 2", "ntpctrl.flags2", FT_UINT8, BASE_HEX,
917 NULL, 0, "Flags (Response/Error/More/Opcode)", HFILL }},
918 { &hf_ntpctrl_flags2_r, {
919 "Response bit", "ntpctrl.flags2.r", FT_UINT8, BASE_DEC,
920 VALS(ctrl_r_types), NTPCTRL_R_MASK, "Response bit", HFILL }},
921 { &hf_ntpctrl_flags2_error, {
922 "Error bit", "ntpctrl.flags2.error", FT_UINT8, BASE_DEC,
923 NULL, NTPCTRL_ERROR_MASK, "Error bit", HFILL }},
924 { &hf_ntpctrl_flags2_more, {
925 "More bit", "ntpctrl.flags2.more", FT_UINT8, BASE_DEC,
926 NULL, NTPCTRL_MORE_MASK, "More bit", HFILL }},
927 { &hf_ntpctrl_flags2_opcode, {
928 "Opcode", "ntpctrl.flags2.opcode", FT_UINT8, BASE_DEC,
929 VALS(ctrl_op_types), NTPCTRL_OP_MASK, "Opcode", HFILL }},
931 { &hf_ntppriv_flags_r, {
932 "Response bit", "ntppriv.flags.r", FT_UINT8, BASE_DEC,
933 VALS(priv_r_types), NTPPRIV_R_MASK, "Response bit", HFILL }},
934 { &hf_ntppriv_flags_more, {
935 "More bit", "ntppriv.flags.more", FT_UINT8, BASE_DEC,
936 NULL, NTPPRIV_MORE_MASK, "More bit", HFILL }},
937 { &hf_ntppriv_auth_seq, {
938 "Auth, sequence", "ntppriv.auth_seq", FT_UINT8, BASE_DEC,
939 NULL, 0, "Auth bit, sequence number", HFILL }},
940 { &hf_ntppriv_auth, {
941 "Auth bit", "ntppriv.auth", FT_UINT8, BASE_DEC,
942 NULL, NTPPRIV_AUTH_MASK, "Auth bit", HFILL }},
944 "Sequence number", "ntppriv.seq", FT_UINT8, BASE_DEC,
945 NULL, NTPPRIV_SEQ_MASK, "Sequence number", HFILL }},
946 { &hf_ntppriv_impl, {
947 "Implementation", "ntppriv.impl", FT_UINT8, BASE_DEC,
948 VALS(priv_impl_types), 0, "Implementation", HFILL }},
949 { &hf_ntppriv_reqcode, {
950 "Request code", "ntppriv.reqcode", FT_UINT8, BASE_DEC,
951 VALS(priv_rc_types), 0, "Request code", HFILL }},
953 static gint *ett[] = {
959 &ett_ntppriv_auth_seq,
962 proto_ntp = proto_register_protocol("Network Time Protocol", "NTP",
964 proto_register_field_array(proto_ntp, hf, array_length(hf));
965 proto_register_subtree_array(ett, array_length(ett));
969 proto_reg_handoff_ntp(void)
971 dissector_handle_t ntp_handle;
973 ntp_handle = create_dissector_handle(dissect_ntp, proto_ntp);
974 dissector_add("udp.port", UDP_PORT_NTP, ntp_handle);
975 dissector_add("tcp.port", TCP_PORT_NTP, ntp_handle);