Fix some aclocal warnings during autogen.sh
[obnox/wireshark/wip.git] / packet-ntp.c
1 /* packet-ntp.c
2  * Routines for NTP packet dissection
3  * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
4  *
5  * $Id: packet-ntp.c,v 1.40 2003/11/18 19:28:24 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
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 #ifdef NEED_SNPRINTF_H
40 # include "snprintf.h"
41 #endif
42
43 #include <epan/packet.h>
44 #include <epan/resolv.h>
45 #include "packet-ntp.h"
46
47 /*
48  * Dissecting NTP packets version 3 and 4 (RFC2030, RFC1769, RFC1361,
49  * RFC1305).
50  *
51  * Those packets have simple structure:
52  *                      1                   2                   3
53  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
54  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55  * |LI | VN  |Mode |    Stratum    |     Poll      |   Precision   |
56  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57  * |                          Root Delay                           |
58  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59  * |                       Root Dispersion                         |
60  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61  * |                    Reference Identifier                       |
62  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63  * |                   Reference Timestamp (64)                    |
64  * |                                                               |
65  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66  * |                   Originate Timestamp (64)                    |
67  * |                                                               |
68  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69  * |                    Receive Timestamp (64)                     |
70  * |                                                               |
71  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72  * |                    Transmit Timestamp (64)                    |
73  * |                                                               |
74  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75  * |                 Key Identifier (optional) (32)                |
76  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77  * |                 Message Digest (optional) (128)               |
78  * |                                                               |
79  * |                                                               |
80  * |                                                               |
81  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82  * NTP timestamps are represented as a 64-bit unsigned fixed-point number,
83  * in seconds relative to 0h on 1 January 1900. The integer part is in the
84  * first 32 bits and the fraction part in the last 32 bits.
85  */
86
87 #define UDP_PORT_NTP    123
88 #define TCP_PORT_NTP    123
89
90 /* Leap indicator, 2bit field is used to warn of a inserted/deleted
91  * second, or to alarm loosed synchronization.
92  */
93 #define NTP_LI_MASK     0xC0
94
95 #define NTP_LI_NONE     0
96 #define NTP_LI_61       1
97 #define NTP_LI_59       2
98 #define NTP_LI_ALARM    3
99
100 static const value_string li_types[] = {
101         { NTP_LI_NONE,  "no warning" },
102         { NTP_LI_61,    "last minute has 61 seconds" },
103         { NTP_LI_59,    "last minute has 59 seconds" },
104         { NTP_LI_ALARM, "alarm condition (clock not synchronized)" },
105         { 0,            NULL}
106 };
107
108 /* Version info, 3bit field informs about NTP version used in particular
109  * packet. According to rfc2030, version info could be only 3 or 4, but I
110  * have noticed packets with 1 or even 6 as version numbers. They are
111  * produced as a result of ntptrace command. Are those packets mailformed
112  * on purpose? I don't know yet, probably some browsing through ntp sources
113  * would help. My solution is to put them as reserved for now.
114  */
115 #define NTP_VN_MASK     0x38
116
117 static const value_string ver_nums[] = {
118         { 0,    "reserved" },
119         { 1,    "reserved" },
120         { 2,    "reserved" },
121         { 3,    "NTP Version 3" },
122         { 4,    "NTP Version 4" },
123         { 5,    "reserved" },
124         { 6,    "reserved" },
125         { 7,    "reserved" },
126         { 0,    NULL}
127 };
128
129 /* Mode, 3bit field representing mode of comunication.
130  */
131 #define NTP_MODE_MASK   7
132
133 #define NTP_MODE_RSV    0
134 #define NTP_MODE_SYMACT 1
135 #define NTP_MODE_SYMPAS 2
136 #define NTP_MODE_CLIENT 3
137 #define NTP_MODE_SERVER 4
138 #define NTP_MODE_BCAST  5
139 #define NTP_MODE_CTRL   6
140 #define NTP_MODE_PRIV   7
141
142 static const value_string mode_types[] = {
143         { NTP_MODE_RSV,         "reserved" },
144         { NTP_MODE_SYMACT,      "symmetric active" },
145         { NTP_MODE_SYMPAS,      "symmetric passive" },
146         { NTP_MODE_CLIENT,      "client" },
147         { NTP_MODE_SERVER,      "server" },
148         { NTP_MODE_BCAST,       "broadcast" },
149         { NTP_MODE_CTRL,        "reserved for NTP control message"},
150         { NTP_MODE_PRIV,        "reserved for private use" },
151         { 0,            NULL}
152 };
153
154 /* According to rfc, primary (stratum-0 and stratum-1) servers should set
155  * their Reference Clock ID (4bytes field) according to following table:
156  */
157 static const struct {
158         char *id;
159         char *data;
160 } primary_sources[] = {
161         { "LOCL",       "uncalibrated local clock" },
162         { "PPS\0",      "atomic clock or other pulse-per-second source" },
163         { "ACTS",       "NIST dialup modem service" },
164         { "USNO",       "USNO modem service" },
165         { "PTB\0",      "PTB (Germany) modem service" },
166         { "TDF\0",      "Allouis (France) Radio 164 kHz" },
167         { "DCF\0",      "Mainflingen (Germany) Radio 77.5 kHz" },
168         { "MSF\0",      "Rugby (UK) Radio 60 kHz" },
169         { "WWV\0",      "Ft. Collins (US) Radio 2.5, 5, 10, 15, 20 MHz" },
170         { "WWVB",       "Boulder (US) Radio 60 kHz" },
171         { "WWVH",       "Kaui Hawaii (US) Radio 2.5, 5, 10, 15 MHz" },
172         { "CHU\0",      "Ottawa (Canada) Radio 3330, 7335, 14670 kHz" },
173         { "LORC",       "LORAN-C radionavigation system" },
174         { "OMEG",       "OMEGA radionavigation system" },
175         { "GPS\0",      "Global Positioning Service" },
176         { "GOES",       "Geostationary Orbit Environment Satellite" },
177         { "DCN\0",      "DCN routing protocol" },
178         { "NIST",       "NIST public modem" },
179         { "TSP\0",      "TSP time protocol" },
180         { "DTS\0",      "Digital Time Service" },
181         { "ATOM",       "Atomic clock (calibrated)" },
182         { "VLF\0",      "VLF radio (OMEGA,, etc.)" },
183         { "IRIG",       "IRIG-B timecode" },
184         { "1PPS",       "External 1 PPS input" },
185         { "FREE",       "(Internal clock)" },
186         { NULL,         NULL}
187 };
188
189 #define NTP_EXT_R_MASK 0x80
190
191 static const value_string ext_r_types[] = {
192         { 0,            "Request" },
193         { 1,            "Response" },
194         { 0,            NULL}
195 };
196
197 #define NTP_EXT_ERROR_MASK 0x40
198 #define NTP_EXT_VN_MASK 0x3f
199
200 static const value_string ext_op_types[] = {
201         { 0,            "NULL" },
202         { 1,            "ASSOC" },
203         { 2,            "CERT" },
204         { 3,            "COOK" },
205         { 4,            "AUTO" },
206         { 5,            "TAI" },
207         { 6,            "SIGN" },
208         { 7,            "IFF" },
209         { 8,            "GQ" },
210         { 9,            "MV" },
211         { 0,            NULL}
212 };
213
214 #define NTPCTRL_R_MASK 0x80
215
216 #define ctrl_r_types ext_r_types
217
218 #define NTPCTRL_ERROR_MASK 0x40
219 #define NTPCTRL_MORE_MASK 0x20
220 #define NTPCTRL_OP_MASK 0x1f
221
222 static const value_string ctrl_op_types[] = {
223         { 0,            "UNSPEC" },
224         { 1,            "READSTAT" },
225         { 2,            "READVAR" },
226         { 3,            "WRITEVAR" },
227         { 4,            "READCLOCK" },
228         { 5,            "WRITECLOCK" },
229         { 6,            "SETTRAP" },
230         { 7,            "ASYNCMSG" },
231         { 31,           "UNSETTRAP" },
232         { 0,            NULL}
233 };
234
235 #define NTPPRIV_R_MASK 0x80
236
237 #define priv_r_types ext_r_types
238
239 #define NTPPRIV_MORE_MASK 0x40
240
241 #define NTPPRIV_AUTH_MASK 0x80
242 #define NTPPRIV_SEQ_MASK 0x7f
243
244 static const value_string priv_impl_types[] = {
245         { 0,            "UNIV" },
246         { 2,            "XNTPD_OLD (pre-IPv6)" },
247         { 3,            "XNTPD" },
248         { 0,            NULL}
249 };
250
251 static const value_string priv_rc_types[] = {
252         { 0,            "PEER_LIST" },
253         { 1,            "PEER_LIST_SUM" },
254         { 2,            "PEER_INFO" },
255         { 3,            "PEER_STATS" },
256         { 4,            "SYS_INFO" },
257         { 5,            "SYS_STATS" },
258         { 6,            "IO_STATS" },
259         { 7,            "MEM_STATS" },
260         { 8,            "LOOP_INFO" },
261         { 9,            "TIMER_STATS" },
262         { 10,           "CONFIG" },
263         { 11,           "UNCONFIG" },
264         { 12,           "SET_SYS_FLAG" },
265         { 13,           "CLR_SYS_FLAG" },
266         { 16,           "GET_RESTRICT" },
267         { 17,           "RESADDFLAGS" },
268         { 18,           "RESSUBFLAGS" },
269         { 19,           "UNRESTRICT" },
270         { 20,           "MON_GETLIST" },
271         { 21,           "RESET_STATS" },
272         { 22,           "RESET_PEER" },
273         { 23,           "REREAD_KEYS" },
274         { 26,           "TRUSTKEY" },
275         { 27,           "UNTRUSTKEY" },
276         { 28,           "AUTHINFO" },
277         { 29,           "TRAPS" },
278         { 30,           "ADD_TRAP" },
279         { 31,           "CLR_TRAP" },
280         { 32,           "REQUEST_KEY" },
281         { 33,           "CONTROL_KEY" },
282         { 34,           "GET_CTLSTATS" },
283         { 36,           "GET_CLOCKINFO" },
284         { 37,           "SET_CLKFUDGE" },
285         { 38,           "GET_KERNEL" },
286         { 39,           "GET_CLKBUGINFO" },
287         { 42,           "MON_GETLIST_1" },
288         { 43,           "HOSTNAME_ASSOCID" },
289         { 0,            NULL}
290 };
291
292 /*
293  * Maximum MAC length.
294  */
295 #define MAX_MAC_LEN     (5 * sizeof (guint32))
296
297 static int proto_ntp = -1;
298
299 static int hf_ntp_flags = -1;
300 static int hf_ntp_flags_li = -1;
301 static int hf_ntp_flags_vn = -1;
302 static int hf_ntp_flags_mode = -1;
303 static int hf_ntp_stratum = -1;
304 static int hf_ntp_ppoll = -1;
305 static int hf_ntp_precision = -1;
306 static int hf_ntp_rootdelay = -1;
307 static int hf_ntp_rootdispersion = -1;
308 static int hf_ntp_refid = -1;
309 static int hf_ntp_reftime = -1;
310 static int hf_ntp_org = -1;
311 static int hf_ntp_rec = -1;
312 static int hf_ntp_xmt = -1;
313 static int hf_ntp_keyid = -1;
314 static int hf_ntp_mac = -1;
315
316 static int hf_ntp_ext = -1;
317 static int hf_ntp_ext_flags = -1;
318 static int hf_ntp_ext_flags_r = -1;
319 static int hf_ntp_ext_flags_error = -1;
320 static int hf_ntp_ext_flags_vn = -1;
321 static int hf_ntp_ext_op = -1;
322 static int hf_ntp_ext_len = -1;
323 static int hf_ntp_ext_associd = -1;
324 static int hf_ntp_ext_tstamp = -1;
325 static int hf_ntp_ext_fstamp = -1;
326 static int hf_ntp_ext_vallen = -1;
327 static int hf_ntp_ext_val = -1;
328 static int hf_ntp_ext_siglen = -1;
329 static int hf_ntp_ext_sig = -1;
330
331 static int hf_ntpctrl_flags2 = -1;
332 static int hf_ntpctrl_flags2_r = -1;
333 static int hf_ntpctrl_flags2_error = -1;
334 static int hf_ntpctrl_flags2_more = -1;
335 static int hf_ntpctrl_flags2_opcode = -1;
336
337 static int hf_ntppriv_flags_r = -1;
338 static int hf_ntppriv_flags_more = -1;
339 static int hf_ntppriv_auth_seq = -1;
340 static int hf_ntppriv_auth = -1;
341 static int hf_ntppriv_seq = -1;
342 static int hf_ntppriv_impl = -1;
343 static int hf_ntppriv_reqcode = -1;
344
345 static gint ett_ntp = -1;
346 static gint ett_ntp_flags = -1;
347 static gint ett_ntp_ext = -1;
348 static gint ett_ntp_ext_flags = -1;
349 static gint ett_ntpctrl_flags2 = -1;
350 static gint ett_ntppriv_auth_seq = -1;
351
352 static void dissect_ntp_std(tvbuff_t *, proto_tree *, guint8);
353 static void dissect_ntp_ctrl(tvbuff_t *, proto_tree *, guint8);
354 static void dissect_ntp_priv(tvbuff_t *, proto_tree *, guint8);
355 static int dissect_ntp_ext(tvbuff_t *, proto_tree *, int);
356
357 /* ntp_fmt_ts - converts NTP timestamp to human readable string.
358  * reftime - 64bit timestamp (IN)
359  * buff - string buffer for result (OUT)
360  * returns pointer to filled buffer.
361  */
362 static char *
363 ntp_fmt_ts(const guint8 *reftime, char* buff)
364 {
365         guint32 tempstmp, tempfrac;
366         time_t temptime;
367         struct tm *bd;
368         double fractime;
369
370         tempstmp = pntohl(&reftime[0]);
371         tempfrac = pntohl(&reftime[4]);
372         if ((tempstmp == 0) && (tempfrac == 0)) {
373                 strcpy (buff, "NULL");
374                 return buff;
375         } else {
376                 temptime = tempstmp - (guint32) NTP_BASETIME;
377                 bd = gmtime(&temptime);
378                 if (bd != NULL) {
379                         fractime = bd->tm_sec + tempfrac / 4294967296.0;
380                         snprintf(buff, NTP_TS_SIZE,
381                                  "%04d-%02d-%02d %02d:%02d:%07.4f UTC",
382                                  bd->tm_year + 1900, bd->tm_mon + 1, bd->tm_mday,
383                                  bd->tm_hour, bd->tm_min, fractime);
384                 } else
385                         strncpy(buff, "Not representable", NTP_TS_SIZE);
386         }
387         return buff;
388 }
389
390 /* dissect_ntp - dissects NTP packet data
391  * tvb - tvbuff for packet data (IN)
392  * pinfo - packet info
393  * proto_tree - resolved protocol tree
394  */
395 static void
396 dissect_ntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
397 {
398         proto_tree      *ntp_tree;
399         proto_item      *ti;
400         guint8          flags;
401         char *infostr;
402         void (*dissector)(tvbuff_t *, proto_item *, guint8);
403
404         if (check_col(pinfo->cinfo, COL_PROTOCOL))
405                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NTP");
406
407         if (check_col(pinfo->cinfo, COL_INFO))
408                 col_clear(pinfo->cinfo, COL_INFO);
409
410         flags = tvb_get_guint8(tvb, 0);
411         switch (flags & NTP_MODE_MASK) {
412         default:
413                 infostr = "NTP";
414                 dissector = dissect_ntp_std;
415                 break;
416         case NTP_MODE_CTRL:
417                 infostr = "NTP control";
418                 dissector = dissect_ntp_ctrl;
419                 break;
420         case NTP_MODE_PRIV:
421                 infostr = "NTP private";
422                 dissector = dissect_ntp_priv;
423                 break;
424         }
425
426         if (check_col(pinfo->cinfo, COL_INFO))
427                 col_set_str(pinfo->cinfo, COL_INFO, infostr);
428
429         if (tree) {
430                 /* Adding NTP item and subtree */
431                 ti = proto_tree_add_item(tree, proto_ntp, tvb, 0, -1, FALSE);
432                 ntp_tree = proto_item_add_subtree(ti, ett_ntp);
433
434                 (*dissector)(tvb, ntp_tree, flags);
435         }
436 }
437
438 static void
439 dissect_ntp_std(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
440 {
441         proto_tree      *flags_tree;
442         proto_item      *tf;
443         guint8          stratum;
444         guint8          ppoll;
445         gint8           precision;
446         double          rootdelay;
447         double          rootdispersion;
448         const guint8    *refid;
449         guint32         refid_addr;
450         const guint8    *reftime;
451         const guint8    *org;
452         const guint8    *rec;
453         const guint8    *xmt;
454         gchar           buff[NTP_TS_SIZE];
455         int             i;
456         int             macofs;
457         gint            maclen;
458
459         tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
460
461         /* Adding flag subtree and items */
462         flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
463         proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
464         proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
465         proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
466
467         /* Stratum, 1byte field represents distance from primary source
468          */
469         stratum = tvb_get_guint8(tvb, 1);
470         if (stratum == 0) {
471                 strcpy (buff, "Peer Clock Stratum: unspecified or unavailable (%u)");
472         } else if (stratum == 1) {
473                 strcpy (buff, "Peer Clock Stratum: primary reference (%u)");
474         } else if ((stratum >= 2) && (stratum <= 15)) {
475                 strcpy (buff, "Peer Clock Stratum: secondary reference (%u)");
476         } else {
477                 strcpy (buff, "Peer Clock Stratum: reserved: %u");
478         }
479         proto_tree_add_uint_format(ntp_tree, hf_ntp_stratum, tvb, 1, 1,
480                                    stratum, buff, stratum);
481         /* Poll interval, 1byte field indicating the maximum interval
482          * between successive messages, in seconds to the nearest
483          * power of two.
484          */
485         ppoll = tvb_get_guint8(tvb, 2);
486         proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
487                                    ppoll,
488                                    (((ppoll >= 4) && (ppoll <= 16)) ?
489                                    "Peer Polling Interval: %u (%u sec)" :
490                                    "Peer Polling Interval: invalid (%u)"),
491                                    ppoll,
492                                    1 << ppoll);
493
494         /* Precision, 1byte field indicating the precision of the
495          * local clock, in seconds to the nearest power of two.
496          */
497         precision = tvb_get_guint8(tvb, 3);
498         proto_tree_add_int_format(ntp_tree, hf_ntp_precision, tvb, 3, 1,
499                                    precision,
500                                    "Peer Clock Precision: %8.6f sec",
501                                    pow(2, precision));
502
503         /* Root Delay is a 32-bit signed fixed-point number indicating
504          * the total roundtrip delay to the primary reference source,
505          * in seconds with fraction point between bits 15 and 16.
506          */
507         rootdelay = ((gint16)tvb_get_ntohs(tvb, 4)) +
508                         (tvb_get_ntohs(tvb, 6) / 65536.0);
509         proto_tree_add_double_format(ntp_tree, hf_ntp_rootdelay, tvb, 4, 4,
510                                    rootdelay,
511                                    "Root Delay: %9.4f sec",
512                                    rootdelay);
513
514         /* Root Dispersion, 32-bit unsigned fixed-point number indicating
515          * the nominal error relative to the primary reference source, in
516          * seconds with fraction point between bits 15 and 16.
517          */
518         rootdispersion = ((gint16)tvb_get_ntohs(tvb, 8)) +
519                                 (tvb_get_ntohs(tvb, 10) / 65536.0);
520         proto_tree_add_double_format(ntp_tree, hf_ntp_rootdispersion, tvb, 8, 4,
521                                    rootdispersion,
522                                    "Clock Dispersion: %9.4f sec",
523                                    rootdispersion);
524
525         /* Now, there is a problem with secondary servers.  Standards
526          * asks from stratum-2 - stratum-15 servers to set this to the
527          * low order 32 bits of the latest transmit timestamp of the
528          * reference source.
529          * But, all V3 and V4 servers set this to IP adress of their
530          * higher level server. My decision was to resolve this address.
531          */
532         refid = tvb_get_ptr(tvb, 12, 4);
533         if (stratum <= 1) {
534                 snprintf (buff, sizeof buff,
535                     "Unindentified reference source '%.4s'",
536                     refid);
537                 for (i = 0; primary_sources[i].id; i++) {
538                         if (memcmp (refid, primary_sources[i].id,
539                             4) == 0) {
540                                 strcpy (buff, primary_sources[i].data);
541                                 break;
542                         }
543                 }
544         } else {
545                 buff[sizeof(buff) - 1] = '\0';
546                 tvb_memcpy(tvb, (guint8 *)&refid_addr, 12, 4);
547                 strncpy (buff, get_hostname (refid_addr),
548                     sizeof(buff));
549                 if (buff[sizeof(buff) - 1] != '\0')
550                         strcpy(&buff[sizeof(buff) - 4], "...");
551         }
552         proto_tree_add_bytes_format(ntp_tree, hf_ntp_refid, tvb, 12, 4,
553                                    refid,
554                                    "Reference Clock ID: %s", buff);
555
556         /* Reference Timestamp: This is the time at which the local clock was
557          * last set or corrected.
558          */
559         reftime = tvb_get_ptr(tvb, 16, 8);
560         proto_tree_add_bytes_format(ntp_tree, hf_ntp_reftime, tvb, 16, 8,
561                                    reftime,
562                                    "Reference Clock Update Time: %s",
563                                    ntp_fmt_ts(reftime, buff));
564
565         /* Originate Timestamp: This is the time at which the request departed
566          * the client for the server.
567          */
568         org = tvb_get_ptr(tvb, 24, 8);
569         proto_tree_add_bytes_format(ntp_tree, hf_ntp_org, tvb, 24, 8,
570                                    org,
571                                    "Originate Time Stamp: %s",
572                                    ntp_fmt_ts(org, buff));
573
574         /* Receive Timestamp: This is the time at which the request arrived at
575          * the server.
576          */
577         rec = tvb_get_ptr(tvb, 32, 8);
578         proto_tree_add_bytes_format(ntp_tree, hf_ntp_rec, tvb, 32, 8,
579                                    rec,
580                                    "Receive Time Stamp: %s",
581                                    ntp_fmt_ts(rec, buff));
582
583         /* Transmit Timestamp: This is the time at which the reply departed the
584          * server for the client.
585          */
586         xmt = tvb_get_ptr(tvb, 40, 8);
587         proto_tree_add_bytes_format(ntp_tree, hf_ntp_xmt, tvb, 40, 8,
588                                    xmt,
589                                    "Transmit Time Stamp: %s",
590                                    ntp_fmt_ts(xmt, buff));
591
592         /* MAX_MAC_LEN is the largest message authentication code
593          * (MAC) length.  If we have more data left in the packet
594          * after the header than that, the extra data is NTP4
595          * extensions; parse them as such.
596          */
597         macofs = 48;
598         while (tvb_reported_length_remaining(tvb, macofs) > (gint)MAX_MAC_LEN)
599                 macofs = dissect_ntp_ext(tvb, ntp_tree, macofs);
600
601         /* When the NTP authentication scheme is implemented, the
602          * Key Identifier and Message Digest fields contain the
603          * message authentication code (MAC) information defined in
604          * Appendix C of RFC-1305. Will print this as hex code for now.
605          */
606         if (tvb_reported_length_remaining(tvb, macofs) >= 4)
607                 proto_tree_add_item(ntp_tree, hf_ntp_keyid, tvb, macofs, 4,
608                                     FALSE);
609         macofs += 4;
610         maclen = tvb_reported_length_remaining(tvb, macofs);
611         if (maclen > 0)
612                 proto_tree_add_item(ntp_tree, hf_ntp_mac, tvb, macofs,
613                                     maclen, FALSE);
614 }
615
616 static int
617 dissect_ntp_ext(tvbuff_t *tvb, proto_tree *ntp_tree, int offset)
618 {
619         proto_tree      *ext_tree, *flags_tree;
620         proto_item      *tf;
621         guint16         extlen;
622         int             endoffset;
623         guint8          flags;
624         guint32         vallen, vallen_round, siglen;
625
626         extlen = tvb_get_ntohs(tvb, offset+2);
627         if (extlen < 8) {
628                 /* Extension length isn't enough for the extension header.
629                  * Report the error, and return an offset that goes to
630                  * the end of the tvbuff, so we stop dissecting.
631                  */
632                 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
633                                     "Extension length %u < 8", extlen);
634                 offset += tvb_length_remaining(tvb, offset);
635                 return offset;
636         }
637         if (extlen % 4) {
638                 /* Extension length isn't a multiple of 4.
639                  * Report the error, and return an offset that goes
640                  * to the end of the tvbuff, so we stop dissecting.
641                  */
642                 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
643                         "Extension length %u isn't a multiple of 4",
644                                     extlen);
645                 offset += tvb_length_remaining(tvb, offset);
646                 return offset;
647         }
648         endoffset = offset + extlen;
649
650         tf = proto_tree_add_item(ntp_tree, hf_ntp_ext, tvb, offset, extlen,
651             FALSE);
652         ext_tree = proto_item_add_subtree(tf, ett_ntp_ext);
653
654         flags = tvb_get_guint8(tvb, offset);
655         tf = proto_tree_add_uint(ext_tree, hf_ntp_ext_flags, tvb, offset, 1,
656                                  flags);
657         flags_tree = proto_item_add_subtree(tf, ett_ntp_ext_flags);
658         proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_r, tvb, offset, 1,
659                             flags);
660         proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_error, tvb, offset, 1,
661                             flags);
662         proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_vn, tvb, offset, 1,
663                             flags);
664         offset++;
665
666         proto_tree_add_item(ext_tree, hf_ntp_ext_op, tvb, offset, 1, FALSE);
667         offset++;
668
669         proto_tree_add_uint(ext_tree, hf_ntp_ext_len, tvb, offset, 2, extlen);
670         offset += 2;
671
672         if ((flags & NTP_EXT_VN_MASK) != 2) {
673                 /* don't care about autokey v1 */
674                 return endoffset;
675         }
676
677         proto_tree_add_item(ext_tree, hf_ntp_ext_associd, tvb, offset, 4,
678                             FALSE);
679         offset += 4;
680
681         /* check whether everything up to "vallen" is present */
682         if (extlen < MAX_MAC_LEN) {
683                 /* XXX - report as error? */
684                 return endoffset;
685         }
686
687         proto_tree_add_item(ext_tree, hf_ntp_ext_tstamp, tvb, offset, 4,
688                             FALSE);
689         offset += 4;
690         proto_tree_add_item(ext_tree, hf_ntp_ext_fstamp, tvb, offset, 4,
691                             FALSE);
692         offset += 4;
693         /* XXX fstamp can be server flags */
694
695         vallen = tvb_get_ntohl(tvb, offset);
696         proto_tree_add_uint(ext_tree, hf_ntp_ext_vallen, tvb, offset, 4,
697                             vallen);
698         offset += 4;
699         vallen_round = (vallen + 3) & (-4);
700         if (vallen != 0) {
701                 if ((guint32)(endoffset - offset) < vallen_round) {
702                         /*
703                          * Value goes past the length of the extension
704                          * field.
705                          */
706                         proto_tree_add_text(ext_tree, tvb, offset,
707                                             endoffset - offset,
708                                             "Value length makes value go past the end of the extension field");
709                         return endoffset;
710                 }
711                 proto_tree_add_item(ext_tree, hf_ntp_ext_val, tvb, offset,
712                                     vallen, FALSE);
713         }
714         offset += vallen_round;
715
716         siglen = tvb_get_ntohl(tvb, offset);
717         proto_tree_add_uint(ext_tree, hf_ntp_ext_siglen, tvb, offset, 4,
718                             siglen);
719         offset += 4;
720         if (siglen != 0) {
721                 if (offset + (int)siglen > endoffset) {
722                         /*
723                          * Value goes past the length of the extension
724                          * field.
725                          */
726                         proto_tree_add_text(ext_tree, tvb, offset,
727                                             endoffset - offset,
728                                             "Signature length makes value go past the end of the extension field");
729                         return endoffset;
730                 }
731                 proto_tree_add_item(ext_tree, hf_ntp_ext_sig, tvb,
732                         offset, siglen, FALSE);
733         }
734         return endoffset;
735 }
736
737 static void
738 dissect_ntp_ctrl(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
739 {
740         proto_tree      *flags_tree;
741         proto_item      *tf;
742         guint8 flags2;
743
744         tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
745
746         /* Adding flag subtree and items */
747         flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
748         proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
749         proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
750         proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
751
752         flags2 = tvb_get_guint8(tvb, 1);
753         tf = proto_tree_add_uint(ntp_tree, hf_ntpctrl_flags2, tvb, 1, 1,
754                                  flags2);
755         flags_tree = proto_item_add_subtree(tf, ett_ntpctrl_flags2);
756         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_r, tvb, 1, 1,
757                             flags2);
758         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_error, tvb, 1, 1,
759                             flags2);
760         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_more, tvb, 1, 1,
761                             flags2);
762         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_opcode, tvb, 1, 1,
763                             flags2);
764 }
765
766 static void
767 dissect_ntp_priv(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
768 {
769         proto_tree      *flags_tree;
770         proto_item      *tf;
771         guint8          auth_seq, impl, reqcode;
772
773         tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
774
775         /* Adding flag subtree and items */
776         flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
777         proto_tree_add_uint(flags_tree, hf_ntppriv_flags_r, tvb, 0, 1, flags);
778         proto_tree_add_uint(flags_tree, hf_ntppriv_flags_more, tvb, 0, 1,
779                             flags);
780         proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
781         proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
782
783         auth_seq = tvb_get_guint8(tvb, 1);
784         tf = proto_tree_add_uint(ntp_tree, hf_ntppriv_auth_seq, tvb, 1, 1,
785                                  auth_seq);
786         flags_tree = proto_item_add_subtree(tf, ett_ntppriv_auth_seq);
787         proto_tree_add_uint(flags_tree, hf_ntppriv_auth, tvb, 1, 1, auth_seq);
788         proto_tree_add_uint(flags_tree, hf_ntppriv_seq, tvb, 1, 1, auth_seq);
789
790         impl = tvb_get_guint8(tvb, 2);
791         proto_tree_add_uint(ntp_tree, hf_ntppriv_impl, tvb, 2, 1, impl);
792
793         reqcode = tvb_get_guint8(tvb, 3);
794         proto_tree_add_uint(ntp_tree, hf_ntppriv_reqcode, tvb, 3, 1, reqcode);
795 }
796
797 void
798 proto_register_ntp(void)
799 {
800         static hf_register_info hf[] = {
801                 { &hf_ntp_flags, {
802                         "Flags", "ntp.flags", FT_UINT8, BASE_HEX,
803                         NULL, 0, "Flags (Leap/Version/Mode)", HFILL }},
804                 { &hf_ntp_flags_li, {
805                         "Leap Indicator", "ntp.flags.li", FT_UINT8, BASE_DEC,
806                         VALS(li_types), NTP_LI_MASK, "Leap Indicator", HFILL }},
807                 { &hf_ntp_flags_vn, {
808                         "Version number", "ntp.flags.vn", FT_UINT8, BASE_DEC,
809                         VALS(ver_nums), NTP_VN_MASK, "Version number", HFILL }},
810                 { &hf_ntp_flags_mode, {
811                         "Mode", "ntp.flags.mode", FT_UINT8, BASE_DEC,
812                         VALS(mode_types), NTP_MODE_MASK, "Mode", HFILL }},
813                 { &hf_ntp_stratum, {
814                         "Peer Clock Stratum", "ntp.stratum", FT_UINT8, BASE_DEC,
815                         NULL, 0, "Peer Clock Stratum", HFILL }},
816                 { &hf_ntp_ppoll, {
817                         "Peer Polling Interval", "ntp.ppoll", FT_UINT8, BASE_DEC,
818                         NULL, 0, "Peer Polling Interval", HFILL }},
819                 { &hf_ntp_precision, {
820                         "Peer Clock Precision", "ntp.precision", FT_INT8, BASE_DEC,
821                         NULL, 0, "Peer Clock Precision", HFILL }},
822                 { &hf_ntp_rootdelay, {
823                         "Root Delay", "ntp.rootdelay", FT_DOUBLE, BASE_DEC,
824                         NULL, 0, "Root Delay", HFILL }},
825                 { &hf_ntp_rootdispersion, {
826                         "Clock Dispersion", "ntp.rootdispersion", FT_DOUBLE, BASE_DEC,
827                         NULL, 0, "Clock Dispersion", HFILL }},
828                 { &hf_ntp_refid, {
829                         "Reference Clock ID", "ntp.refid", FT_BYTES, BASE_NONE,
830                         NULL, 0, "Reference Clock ID", HFILL }},
831                 { &hf_ntp_reftime, {
832                         "Reference Clock Update Time", "ntp.reftime", FT_BYTES, BASE_NONE,
833                         NULL, 0, "Reference Clock Update Time", HFILL }},
834                 { &hf_ntp_org, {
835                         "Originate Time Stamp", "ntp.org", FT_BYTES, BASE_NONE,
836                         NULL, 0, "Originate Time Stamp", HFILL }},
837                 { &hf_ntp_rec, {
838                         "Receive Time Stamp", "ntp.rec", FT_BYTES, BASE_NONE,
839                         NULL, 0, "Receive Time Stamp", HFILL }},
840                 { &hf_ntp_xmt, {
841                         "Transmit Time Stamp", "ntp.xmt", FT_BYTES, BASE_NONE,
842                         NULL, 0, "Transmit Time Stamp", HFILL }},
843                 { &hf_ntp_keyid, {
844                         "Key ID", "ntp.keyid", FT_BYTES, BASE_HEX,
845                         NULL, 0, "Key ID", HFILL }},
846                 { &hf_ntp_mac, {
847                         "Message Authentication Code", "ntp.mac", FT_BYTES, BASE_HEX,
848                         NULL, 0, "Message Authentication Code", HFILL }},
849
850                 { &hf_ntp_ext, {
851                         "Extension", "ntp.ext", FT_NONE, BASE_NONE,
852                         NULL, 0, "Extension", HFILL }},
853                 { &hf_ntp_ext_flags, {
854                         "Flags", "ntp.ext.flags", FT_UINT8, BASE_HEX,
855                         NULL, 0, "Flags (Response/Error/Version)", HFILL }},
856                 { &hf_ntp_ext_flags_r, {
857                         "Response bit", "ntp.ext.flags.r", FT_UINT8, BASE_DEC,
858                         VALS(ext_r_types), NTP_EXT_R_MASK, "Response bit", HFILL }},
859                 { &hf_ntp_ext_flags_error, {
860                         "Error bit", "ntp.ext.flags.error", FT_UINT8, BASE_DEC,
861                         NULL, NTP_EXT_ERROR_MASK, "Error bit", HFILL }},
862                 { &hf_ntp_ext_flags_vn, {
863                         "Version", "ntp.ext.flags.vn", FT_UINT8, BASE_DEC,
864                         NULL, NTP_EXT_VN_MASK, "Version", HFILL }},
865                 { &hf_ntp_ext_op, {
866                         "Opcode", "ntp.ext.op", FT_UINT8, BASE_DEC,
867                         VALS(ext_op_types), 0, "Opcode", HFILL }},
868                 { &hf_ntp_ext_len, {
869                         "Extension length", "ntp.ext.len", FT_UINT16, BASE_DEC,
870                         NULL, 0, "Extension length", HFILL }},
871                 { &hf_ntp_ext_associd, {
872                         "Association ID", "ntp.ext.associd", FT_UINT32, BASE_DEC,
873                         NULL, 0, "Association ID", HFILL }},
874                 { &hf_ntp_ext_tstamp, {
875                         "Timestamp", "ntp.ext.tstamp", FT_UINT32, BASE_HEX,
876                         NULL, 0, "Timestamp", HFILL }},
877                 { &hf_ntp_ext_fstamp, {
878                         "File Timestamp", "ntp.ext.fstamp", FT_UINT32, BASE_HEX,
879                         NULL, 0, "File Timestamp", HFILL }},
880                 { &hf_ntp_ext_vallen, {
881                         "Value length", "ntp.ext.vallen", FT_UINT32, BASE_DEC,
882                         NULL, 0, "Value length", HFILL }},
883                 { &hf_ntp_ext_val, {
884                         "Value", "ntp.ext.val", FT_BYTES, BASE_HEX,
885                         NULL, 0, "Value", HFILL }},
886                 { &hf_ntp_ext_siglen, {
887                         "Signature length", "ntp.ext.siglen", FT_UINT32, BASE_DEC,
888                         NULL, 0, "Signature length", HFILL }},
889                 { &hf_ntp_ext_sig, {
890                         "Signature", "ntp.ext.sig", FT_BYTES, BASE_HEX,
891                         NULL, 0, "Signature", HFILL }},
892
893                 { &hf_ntpctrl_flags2, {
894                         "Flags 2", "ntpctrl.flags2", FT_UINT8, BASE_HEX,
895                         NULL, 0, "Flags (Response/Error/More/Opcode)", HFILL }},
896                 { &hf_ntpctrl_flags2_r, {
897                         "Response bit", "ntpctrl.flags2.r", FT_UINT8, BASE_DEC,
898                         VALS(ctrl_r_types), NTPCTRL_R_MASK, "Response bit", HFILL }},
899                 { &hf_ntpctrl_flags2_error, {
900                         "Error bit", "ntpctrl.flags2.error", FT_UINT8, BASE_DEC,
901                         NULL, NTPCTRL_ERROR_MASK, "Error bit", HFILL }},
902                 { &hf_ntpctrl_flags2_more, {
903                         "More bit", "ntpctrl.flags2.more", FT_UINT8, BASE_DEC,
904                         NULL, NTPCTRL_MORE_MASK, "More bit", HFILL }},
905                 { &hf_ntpctrl_flags2_opcode, {
906                         "Opcode", "ntpctrl.flags2.opcode", FT_UINT8, BASE_DEC,
907                         VALS(ctrl_op_types), NTPCTRL_OP_MASK, "Opcode", HFILL }},
908
909                 { &hf_ntppriv_flags_r, {
910                         "Response bit", "ntppriv.flags.r", FT_UINT8, BASE_DEC,
911                         VALS(priv_r_types), NTPPRIV_R_MASK, "Response bit", HFILL }},
912                 { &hf_ntppriv_flags_more, {
913                         "More bit", "ntppriv.flags.more", FT_UINT8, BASE_DEC,
914                         NULL, NTPPRIV_MORE_MASK, "More bit", HFILL }},
915                 { &hf_ntppriv_auth_seq, {
916                         "Auth, sequence", "ntppriv.auth_seq", FT_UINT8, BASE_DEC,
917                         NULL, 0, "Auth bit, sequence number", HFILL }},
918                 { &hf_ntppriv_auth, {
919                         "Auth bit", "ntppriv.auth", FT_UINT8, BASE_DEC,
920                         NULL, NTPPRIV_AUTH_MASK, "Auth bit", HFILL }},
921                 { &hf_ntppriv_seq, {
922                         "Sequence number", "ntppriv.seq", FT_UINT8, BASE_DEC,
923                         NULL, NTPPRIV_SEQ_MASK, "Sequence number", HFILL }},
924                 { &hf_ntppriv_impl, {
925                         "Implementation", "ntppriv.impl", FT_UINT8, BASE_DEC,
926                         VALS(priv_impl_types), 0, "Implementation", HFILL }},
927                 { &hf_ntppriv_reqcode, {
928                         "Request code", "ntppriv.reqcode", FT_UINT8, BASE_DEC,
929                         VALS(priv_rc_types), 0, "Request code", HFILL }},
930         };
931         static gint *ett[] = {
932                 &ett_ntp,
933                 &ett_ntp_flags,
934                 &ett_ntp_ext,
935                 &ett_ntp_ext_flags,
936                 &ett_ntpctrl_flags2,
937                 &ett_ntppriv_auth_seq,
938         };
939
940         proto_ntp = proto_register_protocol("Network Time Protocol", "NTP",
941             "ntp");
942         proto_register_field_array(proto_ntp, hf, array_length(hf));
943         proto_register_subtree_array(ett, array_length(ett));
944 }
945
946 void
947 proto_reg_handoff_ntp(void)
948 {
949         dissector_handle_t ntp_handle;
950
951         ntp_handle = create_dissector_handle(dissect_ntp, proto_ntp);
952         dissector_add("udp.port", UDP_PORT_NTP, ntp_handle);
953         dissector_add("tcp.port", TCP_PORT_NTP, ntp_handle);
954 }