f10811763020ad5b3331455a82689a0de40dcb44
[obnox/wireshark/wip.git] / epan / dissectors / packet-ntp.c
1 /* packet-ntp.c
2  * Routines for NTP packet dissection
3  * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from packet-tftp.c
12  *
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.
17  *
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.
22  *
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.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33
34 #include <string.h>
35 #include <time.h>
36 #include <math.h>
37 #include <glib.h>
38
39 #include <epan/packet.h>
40 #include <epan/addr_resolv.h>
41 #include <epan/emem.h>
42 #include "packet-ntp.h"
43
44 /*
45  * Dissecting NTP packets version 3 and 4 (RFC2030, RFC1769, RFC1361,
46  * RFC1305).
47  *
48  * Those packets have simple structure:
49  *                      1                   2                   3
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  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54  * |                          Root Delay                           |
55  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56  * |                       Root Dispersion                         |
57  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58  * |                    Reference Identifier                       |
59  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60  * |                   Reference Timestamp (64)                    |
61  * |                                                               |
62  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63  * |                   Originate Timestamp (64)                    |
64  * |                                                               |
65  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66  * |                    Receive Timestamp (64)                     |
67  * |                                                               |
68  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69  * |                    Transmit Timestamp (64)                    |
70  * |                                                               |
71  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72  * |                 Key Identifier (optional) (32)                |
73  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74  * |                 Message Digest (optional) (128)               |
75  * |                                                               |
76  * |                                                               |
77  * |                                                               |
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.
82  */
83
84 #define UDP_PORT_NTP    123
85 #define TCP_PORT_NTP    123
86
87 /* Leap indicator, 2bit field is used to warn of a inserted/deleted
88  * second, or to alarm loosed synchronization.
89  */
90 #define NTP_LI_MASK     0xC0
91
92 #define NTP_LI_NONE     0
93 #define NTP_LI_61       1
94 #define NTP_LI_59       2
95 #define NTP_LI_ALARM    3
96
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)" },
102         { 0,            NULL}
103 };
104
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.
111  */
112 #define NTP_VN_MASK     0x38
113
114 static const value_string ver_nums[] = {
115         { 0,    "reserved" },
116         { 1,    "reserved" },
117         { 2,    "reserved" },
118         { 3,    "NTP Version 3" },
119         { 4,    "NTP Version 4" },
120         { 5,    "reserved" },
121         { 6,    "reserved" },
122         { 7,    "reserved" },
123         { 0,    NULL}
124 };
125
126 /* Mode, 3bit field representing mode of comunication.
127  */
128 #define NTP_MODE_MASK   7
129
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
138
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" },
148         { 0,            NULL}
149 };
150
151 /* According to rfc, primary (stratum-0 and stratum-1) servers should set
152  * their Reference Clock ID (4bytes field) according to following table:
153  */
154 static const struct {
155         const char *id;
156         const char *data;
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" },
185         { NULL,         NULL}
186 };
187
188 #define NTP_EXT_R_MASK 0x80
189
190 static const value_string ext_r_types[] = {
191         { 0,            "Request" },
192         { 1,            "Response" },
193         { 0,            NULL}
194 };
195
196 #define NTP_EXT_ERROR_MASK 0x40
197 #define NTP_EXT_VN_MASK 0x3f
198
199 static const value_string ext_op_types[] = {
200         { 0,            "NULL" },
201         { 1,            "ASSOC" },
202         { 2,            "CERT" },
203         { 3,            "COOK" },
204         { 4,            "AUTO" },
205         { 5,            "TAI" },
206         { 6,            "SIGN" },
207         { 7,            "IFF" },
208         { 8,            "GQ" },
209         { 9,            "MV" },
210         { 0,            NULL}
211 };
212
213 #define NTPCTRL_R_MASK 0x80
214
215 #define ctrl_r_types ext_r_types
216
217 #define NTPCTRL_ERROR_MASK 0x40
218 #define NTPCTRL_MORE_MASK 0x20
219 #define NTPCTRL_OP_MASK 0x1f
220
221 static const value_string ctrl_op_types[] = {
222         { 0,            "UNSPEC" },
223         { 1,            "READSTAT" },
224         { 2,            "READVAR" },
225         { 3,            "WRITEVAR" },
226         { 4,            "READCLOCK" },
227         { 5,            "WRITECLOCK" },
228         { 6,            "SETTRAP" },
229         { 7,            "ASYNCMSG" },
230         { 31,           "UNSETTRAP" },
231         { 0,            NULL}
232 };
233
234 #define NTPPRIV_R_MASK 0x80
235
236 #define priv_r_types ext_r_types
237
238 #define NTPPRIV_MORE_MASK 0x40
239
240 #define NTPPRIV_AUTH_MASK 0x80
241 #define NTPPRIV_SEQ_MASK 0x7f
242
243 static const value_string priv_impl_types[] = {
244         { 0,            "UNIV" },
245         { 2,            "XNTPD_OLD (pre-IPv6)" },
246         { 3,            "XNTPD" },
247         { 0,            NULL}
248 };
249
250 static const value_string priv_rc_types[] = {
251         { 0,            "PEER_LIST" },
252         { 1,            "PEER_LIST_SUM" },
253         { 2,            "PEER_INFO" },
254         { 3,            "PEER_STATS" },
255         { 4,            "SYS_INFO" },
256         { 5,            "SYS_STATS" },
257         { 6,            "IO_STATS" },
258         { 7,            "MEM_STATS" },
259         { 8,            "LOOP_INFO" },
260         { 9,            "TIMER_STATS" },
261         { 10,           "CONFIG" },
262         { 11,           "UNCONFIG" },
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" },
273         { 26,           "TRUSTKEY" },
274         { 27,           "UNTRUSTKEY" },
275         { 28,           "AUTHINFO" },
276         { 29,           "TRAPS" },
277         { 30,           "ADD_TRAP" },
278         { 31,           "CLR_TRAP" },
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" },
288         { 0,            NULL}
289 };
290
291 /*
292  * Maximum MAC length.
293  */
294 #define MAX_MAC_LEN     (5 * sizeof (guint32))
295
296 static int proto_ntp = -1;
297
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;
314
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;
329
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;
335
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;
343
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;
350
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);
355
356 static const char *mon_names[12] = {
357         "Jan",
358         "Feb",
359         "Mar",
360         "Apr",
361         "May",
362         "Jun",
363         "Jul",
364         "Aug",
365         "Sep",
366         "Oct",
367         "Nov",
368         "Dec"
369 };
370
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.
375  */
376 char *
377 ntp_fmt_ts(const guint8 *reftime)
378 {
379         guint32 tempstmp, tempfrac;
380         time_t temptime;
381         struct tm *bd;
382         double fractime;
383         char *buff;
384
385         tempstmp = pntohl(&reftime[0]);
386         tempfrac = pntohl(&reftime[4]);
387         if ((tempstmp == 0) && (tempfrac == 0)) {
388                 return "NULL";
389         }
390
391         temptime = tempstmp - (guint32) NTP_BASETIME;
392         bd = gmtime(&temptime);
393         if(!bd){
394                 return "Not representable";
395         }
396
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],
402                  bd->tm_mday,
403                  bd->tm_year + 1900,
404                  bd->tm_hour,
405                  bd->tm_min,
406                  fractime);
407         return buff;
408 }
409
410 /* dissect_ntp - dissects NTP packet data
411  * tvb - tvbuff for packet data (IN)
412  * pinfo - packet info
413  * proto_tree - resolved protocol tree
414  */
415 static void
416 dissect_ntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
417 {
418         proto_tree      *ntp_tree;
419         proto_item      *ti;
420         guint8          flags;
421         const char *infostr;
422         void (*dissector)(tvbuff_t *, proto_item *, guint8);
423
424         if (check_col(pinfo->cinfo, COL_PROTOCOL))
425                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NTP");
426
427         if (check_col(pinfo->cinfo, COL_INFO))
428                 col_clear(pinfo->cinfo, COL_INFO);
429
430         flags = tvb_get_guint8(tvb, 0);
431         switch (flags & NTP_MODE_MASK) {
432         default:
433                 infostr = "NTP";
434                 dissector = dissect_ntp_std;
435                 break;
436         case NTP_MODE_CTRL:
437                 infostr = "NTP control";
438                 dissector = dissect_ntp_ctrl;
439                 break;
440         case NTP_MODE_PRIV:
441                 infostr = "NTP private";
442                 dissector = dissect_ntp_priv;
443                 break;
444         }
445
446         if (check_col(pinfo->cinfo, COL_INFO))
447                 col_set_str(pinfo->cinfo, COL_INFO, infostr);
448
449         if (tree) {
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);
453
454                 (*dissector)(tvb, ntp_tree, flags);
455         }
456 }
457
458 static void
459 dissect_ntp_std(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
460 {
461         proto_tree      *flags_tree;
462         proto_item      *tf;
463         guint8          stratum;
464         guint8          ppoll;
465         gint8           precision;
466         double          rootdelay;
467         double          rootdispersion;
468         const guint8    *refid;
469         guint32         refid_addr;
470         const guint8    *reftime;
471         const guint8    *org;
472         const guint8    *rec;
473         const guint8    *xmt;
474         gchar           *buff;
475         int             i;
476         int             macofs;
477         gint            maclen;
478
479         tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
480
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);
486
487         /* Stratum, 1byte field represents distance from primary source
488          */
489         stratum = tvb_get_guint8(tvb, 1);
490         if (stratum == 0) {
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)";
496         } else {
497                 buff="Peer Clock Stratum: reserved: %u";
498         }
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
503          * power of two.
504          */
505         ppoll = tvb_get_guint8(tvb, 2);
506         proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
507                                    ppoll,
508                                    (((ppoll >= 4) && (ppoll <= 16)) ?
509                                    "Peer Polling Interval: %u (%u sec)" :
510                                    "Peer Polling Interval: invalid (%u)"),
511                                    ppoll,
512                                    1 << ppoll);
513
514         /* Precision, 1byte field indicating the precision of the
515          * local clock, in seconds to the nearest power of two.
516          */
517         precision = tvb_get_guint8(tvb, 3);
518         proto_tree_add_int_format(ntp_tree, hf_ntp_precision, tvb, 3, 1,
519                                    precision,
520                                    "Peer Clock Precision: %8.6f sec",
521                                    pow(2, precision));
522
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.
526          */
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,
530                                    rootdelay,
531                                    "Root Delay: %9.4f sec",
532                                    rootdelay);
533
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.
537          */
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,
541                                    rootdispersion,
542                                    "Clock Dispersion: %9.4f sec",
543                                    rootdispersion);
544
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
548          * reference source.
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.
551          */
552         refid = tvb_get_ptr(tvb, 12, 4);
553         buff = ep_alloc(NTP_TS_SIZE);
554         if (stratum <= 1) {
555                 g_snprintf (buff, NTP_TS_SIZE, "Unidentified reference source '%.4s'",
556                         refid);
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);
561                                 break;
562                         }
563                 }
564         } else {
565                 int buffpos;
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;
573                 }
574         }
575         proto_tree_add_bytes_format(ntp_tree, hf_ntp_refid, tvb, 12, 4,
576                                    refid,
577                                    "Reference Clock ID: %s", buff);
578
579         /* Reference Timestamp: This is the time at which the local clock was
580          * last set or corrected.
581          */
582         reftime = tvb_get_ptr(tvb, 16, 8);
583         proto_tree_add_bytes_format(ntp_tree, hf_ntp_reftime, tvb, 16, 8,
584                                    reftime,
585                                    "Reference Clock Update Time: %s",
586                                    ntp_fmt_ts(reftime));
587
588         /* Originate Timestamp: This is the time at which the request departed
589          * the client for the server.
590          */
591         org = tvb_get_ptr(tvb, 24, 8);
592         proto_tree_add_bytes_format(ntp_tree, hf_ntp_org, tvb, 24, 8,
593                                    org,
594                                    "Originate Time Stamp: %s",
595                                    ntp_fmt_ts(org));
596
597         /* Receive Timestamp: This is the time at which the request arrived at
598          * the server.
599          */
600         rec = tvb_get_ptr(tvb, 32, 8);
601         proto_tree_add_bytes_format(ntp_tree, hf_ntp_rec, tvb, 32, 8,
602                                    rec,
603                                    "Receive Time Stamp: %s",
604                                    ntp_fmt_ts(rec));
605
606         /* Transmit Timestamp: This is the time at which the reply departed the
607          * server for the client.
608          */
609         xmt = tvb_get_ptr(tvb, 40, 8);
610         proto_tree_add_bytes_format(ntp_tree, hf_ntp_xmt, tvb, 40, 8,
611                                    xmt,
612                                    "Transmit Time Stamp: %s",
613                                    ntp_fmt_ts(xmt));
614
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.
619          */
620         macofs = 48;
621         while (tvb_reported_length_remaining(tvb, macofs) > (gint)MAX_MAC_LEN)
622                 macofs = dissect_ntp_ext(tvb, ntp_tree, macofs);
623
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.
628          */
629         if (tvb_reported_length_remaining(tvb, macofs) >= 4)
630                 proto_tree_add_item(ntp_tree, hf_ntp_keyid, tvb, macofs, 4,
631                                     FALSE);
632         macofs += 4;
633         maclen = tvb_reported_length_remaining(tvb, macofs);
634         if (maclen > 0)
635                 proto_tree_add_item(ntp_tree, hf_ntp_mac, tvb, macofs,
636                                     maclen, FALSE);
637 }
638
639 static int
640 dissect_ntp_ext(tvbuff_t *tvb, proto_tree *ntp_tree, int offset)
641 {
642         proto_tree      *ext_tree, *flags_tree;
643         proto_item      *tf;
644         guint16         extlen;
645         int             endoffset;
646         guint8          flags;
647         guint32         vallen, vallen_round, siglen;
648
649         extlen = tvb_get_ntohs(tvb, offset+2);
650         if (extlen < 8) {
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.
654                  */
655                 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
656                                     "Extension length %u < 8", extlen);
657                 offset += tvb_length_remaining(tvb, offset);
658                 return offset;
659         }
660         if (extlen % 4) {
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.
664                  */
665                 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
666                         "Extension length %u isn't a multiple of 4",
667                                     extlen);
668                 offset += tvb_length_remaining(tvb, offset);
669                 return offset;
670         }
671         endoffset = offset + extlen;
672
673         tf = proto_tree_add_item(ntp_tree, hf_ntp_ext, tvb, offset, extlen,
674             FALSE);
675         ext_tree = proto_item_add_subtree(tf, ett_ntp_ext);
676
677         flags = tvb_get_guint8(tvb, offset);
678         tf = proto_tree_add_uint(ext_tree, hf_ntp_ext_flags, tvb, offset, 1,
679                                  flags);
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,
682                             flags);
683         proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_error, tvb, offset, 1,
684                             flags);
685         proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_vn, tvb, offset, 1,
686                             flags);
687         offset++;
688
689         proto_tree_add_item(ext_tree, hf_ntp_ext_op, tvb, offset, 1, FALSE);
690         offset++;
691
692         proto_tree_add_uint(ext_tree, hf_ntp_ext_len, tvb, offset, 2, extlen);
693         offset += 2;
694
695         if ((flags & NTP_EXT_VN_MASK) != 2) {
696                 /* don't care about autokey v1 */
697                 return endoffset;
698         }
699
700         proto_tree_add_item(ext_tree, hf_ntp_ext_associd, tvb, offset, 4,
701                             FALSE);
702         offset += 4;
703
704         /* check whether everything up to "vallen" is present */
705         if (extlen < MAX_MAC_LEN) {
706                 /* XXX - report as error? */
707                 return endoffset;
708         }
709
710         proto_tree_add_item(ext_tree, hf_ntp_ext_tstamp, tvb, offset, 4,
711                             FALSE);
712         offset += 4;
713         proto_tree_add_item(ext_tree, hf_ntp_ext_fstamp, tvb, offset, 4,
714                             FALSE);
715         offset += 4;
716         /* XXX fstamp can be server flags */
717
718         vallen = tvb_get_ntohl(tvb, offset);
719         proto_tree_add_uint(ext_tree, hf_ntp_ext_vallen, tvb, offset, 4,
720                             vallen);
721         offset += 4;
722         vallen_round = (vallen + 3) & (-4);
723         if (vallen != 0) {
724                 if ((guint32)(endoffset - offset) < vallen_round) {
725                         /*
726                          * Value goes past the length of the extension
727                          * field.
728                          */
729                         proto_tree_add_text(ext_tree, tvb, offset,
730                                             endoffset - offset,
731                                             "Value length makes value go past the end of the extension field");
732                         return endoffset;
733                 }
734                 proto_tree_add_item(ext_tree, hf_ntp_ext_val, tvb, offset,
735                                     vallen, FALSE);
736         }
737         offset += vallen_round;
738
739         siglen = tvb_get_ntohl(tvb, offset);
740         proto_tree_add_uint(ext_tree, hf_ntp_ext_siglen, tvb, offset, 4,
741                             siglen);
742         offset += 4;
743         if (siglen != 0) {
744                 if (offset + (int)siglen > endoffset) {
745                         /*
746                          * Value goes past the length of the extension
747                          * field.
748                          */
749                         proto_tree_add_text(ext_tree, tvb, offset,
750                                             endoffset - offset,
751                                             "Signature length makes value go past the end of the extension field");
752                         return endoffset;
753                 }
754                 proto_tree_add_item(ext_tree, hf_ntp_ext_sig, tvb,
755                         offset, siglen, FALSE);
756         }
757         return endoffset;
758 }
759
760 static void
761 dissect_ntp_ctrl(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
762 {
763         proto_tree      *flags_tree;
764         proto_item      *tf;
765         guint8 flags2;
766
767         tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
768
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);
774
775         flags2 = tvb_get_guint8(tvb, 1);
776         tf = proto_tree_add_uint(ntp_tree, hf_ntpctrl_flags2, tvb, 1, 1,
777                                  flags2);
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,
780                             flags2);
781         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_error, tvb, 1, 1,
782                             flags2);
783         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_more, tvb, 1, 1,
784                             flags2);
785         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_opcode, tvb, 1, 1,
786                             flags2);
787 }
788
789 static void
790 dissect_ntp_priv(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
791 {
792         proto_tree      *flags_tree;
793         proto_item      *tf;
794         guint8          auth_seq, impl, reqcode;
795
796         tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
797
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,
802                             flags);
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);
805
806         auth_seq = tvb_get_guint8(tvb, 1);
807         tf = proto_tree_add_uint(ntp_tree, hf_ntppriv_auth_seq, tvb, 1, 1,
808                                  auth_seq);
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);
812
813         impl = tvb_get_guint8(tvb, 2);
814         proto_tree_add_uint(ntp_tree, hf_ntppriv_impl, tvb, 2, 1, impl);
815
816         reqcode = tvb_get_guint8(tvb, 3);
817         proto_tree_add_uint(ntp_tree, hf_ntppriv_reqcode, tvb, 3, 1, reqcode);
818 }
819
820 void
821 proto_register_ntp(void)
822 {
823         static hf_register_info hf[] = {
824                 { &hf_ntp_flags, {
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 }},
836                 { &hf_ntp_stratum, {
837                         "Peer Clock Stratum", "ntp.stratum", FT_UINT8, BASE_DEC,
838                         NULL, 0, "Peer Clock Stratum", HFILL }},
839                 { &hf_ntp_ppoll, {
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                         "Clock Dispersion", "ntp.rootdispersion", FT_DOUBLE, BASE_DEC,
850                         NULL, 0, "Clock Dispersion", HFILL }},
851                 { &hf_ntp_refid, {
852                         "Reference Clock ID", "ntp.refid", FT_BYTES, BASE_NONE,
853                         NULL, 0, "Reference Clock ID", HFILL }},
854                 { &hf_ntp_reftime, {
855                         "Reference Clock Update Time", "ntp.reftime", FT_BYTES, BASE_NONE,
856                         NULL, 0, "Reference Clock Update Time", HFILL }},
857                 { &hf_ntp_org, {
858                         "Originate Time Stamp", "ntp.org", FT_BYTES, BASE_NONE,
859                         NULL, 0, "Originate Time Stamp", HFILL }},
860                 { &hf_ntp_rec, {
861                         "Receive Time Stamp", "ntp.rec", FT_BYTES, BASE_NONE,
862                         NULL, 0, "Receive Time Stamp", HFILL }},
863                 { &hf_ntp_xmt, {
864                         "Transmit Time Stamp", "ntp.xmt", FT_BYTES, BASE_NONE,
865                         NULL, 0, "Transmit Time Stamp", HFILL }},
866                 { &hf_ntp_keyid, {
867                         "Key ID", "ntp.keyid", FT_BYTES, BASE_HEX,
868                         NULL, 0, "Key ID", HFILL }},
869                 { &hf_ntp_mac, {
870                         "Message Authentication Code", "ntp.mac", FT_BYTES, BASE_HEX,
871                         NULL, 0, "Message Authentication Code", HFILL }},
872
873                 { &hf_ntp_ext, {
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 }},
888                 { &hf_ntp_ext_op, {
889                         "Opcode", "ntp.ext.op", FT_UINT8, BASE_DEC,
890                         VALS(ext_op_types), 0, "Opcode", HFILL }},
891                 { &hf_ntp_ext_len, {
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 }},
906                 { &hf_ntp_ext_val, {
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 }},
912                 { &hf_ntp_ext_sig, {
913                         "Signature", "ntp.ext.sig", FT_BYTES, BASE_HEX,
914                         NULL, 0, "Signature", HFILL }},
915
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 }},
931
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 }},
944                 { &hf_ntppriv_seq, {
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 }},
953         };
954         static gint *ett[] = {
955                 &ett_ntp,
956                 &ett_ntp_flags,
957                 &ett_ntp_ext,
958                 &ett_ntp_ext_flags,
959                 &ett_ntpctrl_flags2,
960                 &ett_ntppriv_auth_seq,
961         };
962
963         proto_ntp = proto_register_protocol("Network Time Protocol", "NTP",
964             "ntp");
965         proto_register_field_array(proto_ntp, hf, array_length(hf));
966         proto_register_subtree_array(ett, array_length(ett));
967 }
968
969 void
970 proto_reg_handoff_ntp(void)
971 {
972         dissector_handle_t ntp_handle;
973
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);
977 }