b7759f53350c53c0bd01049af33a8dcc4cf84797
[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         { NULL,         NULL}
184 };
185
186 #define NTP_EXT_R_MASK 0x80
187
188 static const value_string ext_r_types[] = {
189         { 0,            "Request" },
190         { 1,            "Response" },
191         { 0,            NULL}
192 };
193
194 #define NTP_EXT_ERROR_MASK 0x40
195 #define NTP_EXT_VN_MASK 0x3f
196
197 static const value_string ext_op_types[] = {
198         { 0,            "NULL" },
199         { 1,            "ASSOC" },
200         { 2,            "CERT" },
201         { 3,            "COOK" },
202         { 4,            "AUTO" },
203         { 5,            "TAI" },
204         { 6,            "SIGN" },
205         { 7,            "IFF" },
206         { 8,            "GQ" },
207         { 9,            "MV" },
208         { 0,            NULL}
209 };
210
211 #define NTPCTRL_R_MASK 0x80
212
213 #define ctrl_r_types ext_r_types
214
215 #define NTPCTRL_ERROR_MASK 0x40
216 #define NTPCTRL_MORE_MASK 0x20
217 #define NTPCTRL_OP_MASK 0x1f
218
219 static const value_string ctrl_op_types[] = {
220         { 0,            "UNSPEC" },
221         { 1,            "READSTAT" },
222         { 2,            "READVAR" },
223         { 3,            "WRITEVAR" },
224         { 4,            "READCLOCK" },
225         { 5,            "WRITECLOCK" },
226         { 6,            "SETTRAP" },
227         { 7,            "ASYNCMSG" },
228         { 31,           "UNSETTRAP" },
229         { 0,            NULL}
230 };
231
232 #define NTPPRIV_R_MASK 0x80
233
234 #define priv_r_types ext_r_types
235
236 #define NTPPRIV_MORE_MASK 0x40
237
238 #define NTPPRIV_AUTH_MASK 0x80
239 #define NTPPRIV_SEQ_MASK 0x7f
240
241 static const value_string priv_impl_types[] = {
242         { 0,            "UNIV" },
243         { 2,            "XNTPD_OLD (pre-IPv6)" },
244         { 3,            "XNTPD" },
245         { 0,            NULL}
246 };
247
248 static const value_string priv_rc_types[] = {
249         { 0,            "PEER_LIST" },
250         { 1,            "PEER_LIST_SUM" },
251         { 2,            "PEER_INFO" },
252         { 3,            "PEER_STATS" },
253         { 4,            "SYS_INFO" },
254         { 5,            "SYS_STATS" },
255         { 6,            "IO_STATS" },
256         { 7,            "MEM_STATS" },
257         { 8,            "LOOP_INFO" },
258         { 9,            "TIMER_STATS" },
259         { 10,           "CONFIG" },
260         { 11,           "UNCONFIG" },
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" },
271         { 26,           "TRUSTKEY" },
272         { 27,           "UNTRUSTKEY" },
273         { 28,           "AUTHINFO" },
274         { 29,           "TRAPS" },
275         { 30,           "ADD_TRAP" },
276         { 31,           "CLR_TRAP" },
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" },
286         { 0,            NULL}
287 };
288
289 /*
290  * Maximum MAC length.
291  */
292 #define MAX_MAC_LEN     (5 * sizeof (guint32))
293
294 static int proto_ntp = -1;
295
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;
312
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;
327
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;
333
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;
341
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;
348
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);
353
354 static const char *mon_names[12] = {
355         "Jan",
356         "Feb",
357         "Mar",
358         "Apr",
359         "May",
360         "Jun",
361         "Jul",
362         "Aug",
363         "Sep",
364         "Oct",
365         "Nov",
366         "Dec"
367 };
368
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.
373  */
374 char *
375 ntp_fmt_ts(const guint8 *reftime)
376 {
377         guint32 tempstmp, tempfrac;
378         time_t temptime;
379         struct tm *bd;
380         double fractime;
381         char *buff;
382
383         tempstmp = pntohl(&reftime[0]);
384         tempfrac = pntohl(&reftime[4]);
385         if ((tempstmp == 0) && (tempfrac == 0)) {
386                 return "NULL";
387         }
388
389         temptime = tempstmp - (guint32) NTP_BASETIME;
390         bd = gmtime(&temptime);
391         if(!bd){
392                 return "Not representable";
393         }
394
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],
400                  bd->tm_mday,
401                  bd->tm_year + 1900,
402                  bd->tm_hour,
403                  bd->tm_min,
404                  fractime);
405         return buff;
406 }
407
408 /* dissect_ntp - dissects NTP packet data
409  * tvb - tvbuff for packet data (IN)
410  * pinfo - packet info
411  * proto_tree - resolved protocol tree
412  */
413 static void
414 dissect_ntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
415 {
416         proto_tree      *ntp_tree;
417         proto_item      *ti;
418         guint8          flags;
419         const char *infostr;
420         void (*dissector)(tvbuff_t *, proto_item *, guint8);
421
422         if (check_col(pinfo->cinfo, COL_PROTOCOL))
423                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NTP");
424
425         if (check_col(pinfo->cinfo, COL_INFO))
426                 col_clear(pinfo->cinfo, COL_INFO);
427
428         flags = tvb_get_guint8(tvb, 0);
429         switch (flags & NTP_MODE_MASK) {
430         default:
431                 infostr = "NTP";
432                 dissector = dissect_ntp_std;
433                 break;
434         case NTP_MODE_CTRL:
435                 infostr = "NTP control";
436                 dissector = dissect_ntp_ctrl;
437                 break;
438         case NTP_MODE_PRIV:
439                 infostr = "NTP private";
440                 dissector = dissect_ntp_priv;
441                 break;
442         }
443
444         if (check_col(pinfo->cinfo, COL_INFO))
445                 col_set_str(pinfo->cinfo, COL_INFO, infostr);
446
447         if (tree) {
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);
451
452                 (*dissector)(tvb, ntp_tree, flags);
453         }
454 }
455
456 static void
457 dissect_ntp_std(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
458 {
459         proto_tree      *flags_tree;
460         proto_item      *tf;
461         guint8          stratum;
462         guint8          ppoll;
463         gint8           precision;
464         double          rootdelay;
465         double          rootdispersion;
466         const guint8    *refid;
467         guint32         refid_addr;
468         const guint8    *reftime;
469         const guint8    *org;
470         const guint8    *rec;
471         const guint8    *xmt;
472         gchar           *buff;
473         int             i;
474         int             macofs;
475         gint            maclen;
476
477         tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
478
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);
484
485         /* Stratum, 1byte field represents distance from primary source
486          */
487         stratum = tvb_get_guint8(tvb, 1);
488         if (stratum == 0) {
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)";
494         } else {
495                 buff="Peer Clock Stratum: reserved: %u";
496         }
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
501          * power of two.
502          */
503         ppoll = tvb_get_guint8(tvb, 2);
504         proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
505                                    ppoll,
506                                    (((ppoll >= 4) && (ppoll <= 16)) ?
507                                    "Peer Polling Interval: %u (%u sec)" :
508                                    "Peer Polling Interval: invalid (%u)"),
509                                    ppoll,
510                                    1 << ppoll);
511
512         /* Precision, 1byte field indicating the precision of the
513          * local clock, in seconds to the nearest power of two.
514          */
515         precision = tvb_get_guint8(tvb, 3);
516         proto_tree_add_int_format(ntp_tree, hf_ntp_precision, tvb, 3, 1,
517                                    precision,
518                                    "Peer Clock Precision: %8.6f sec",
519                                    pow(2, precision));
520
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.
524          */
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,
528                                    rootdelay,
529                                    "Root Delay: %9.4f sec",
530                                    rootdelay);
531
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.
535          */
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,
539                                    rootdispersion,
540                                    "Clock Dispersion: %9.4f sec",
541                                    rootdispersion);
542
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
546          * reference source.
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.
549          */
550         refid = tvb_get_ptr(tvb, 12, 4);
551         if (stratum <= 1) {
552                 buff=ep_alloc(NTP_TS_SIZE);
553                 g_snprintf (buff, NTP_TS_SIZE, "Unindentified reference source '%.4s'",
554                         refid);
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);
559                                 break;
560                         }
561                 }
562         } else {
563                 int buffpos;
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;
572                 }
573         }
574         proto_tree_add_bytes_format(ntp_tree, hf_ntp_refid, tvb, 12, 4,
575                                    refid,
576                                    "Reference Clock ID: %s", buff);
577
578         /* Reference Timestamp: This is the time at which the local clock was
579          * last set or corrected.
580          */
581         reftime = tvb_get_ptr(tvb, 16, 8);
582         proto_tree_add_bytes_format(ntp_tree, hf_ntp_reftime, tvb, 16, 8,
583                                    reftime,
584                                    "Reference Clock Update Time: %s",
585                                    ntp_fmt_ts(reftime));
586
587         /* Originate Timestamp: This is the time at which the request departed
588          * the client for the server.
589          */
590         org = tvb_get_ptr(tvb, 24, 8);
591         proto_tree_add_bytes_format(ntp_tree, hf_ntp_org, tvb, 24, 8,
592                                    org,
593                                    "Originate Time Stamp: %s",
594                                    ntp_fmt_ts(org));
595
596         /* Receive Timestamp: This is the time at which the request arrived at
597          * the server.
598          */
599         rec = tvb_get_ptr(tvb, 32, 8);
600         proto_tree_add_bytes_format(ntp_tree, hf_ntp_rec, tvb, 32, 8,
601                                    rec,
602                                    "Receive Time Stamp: %s",
603                                    ntp_fmt_ts(rec));
604
605         /* Transmit Timestamp: This is the time at which the reply departed the
606          * server for the client.
607          */
608         xmt = tvb_get_ptr(tvb, 40, 8);
609         proto_tree_add_bytes_format(ntp_tree, hf_ntp_xmt, tvb, 40, 8,
610                                    xmt,
611                                    "Transmit Time Stamp: %s",
612                                    ntp_fmt_ts(xmt));
613
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.
618          */
619         macofs = 48;
620         while (tvb_reported_length_remaining(tvb, macofs) > (gint)MAX_MAC_LEN)
621                 macofs = dissect_ntp_ext(tvb, ntp_tree, macofs);
622
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.
627          */
628         if (tvb_reported_length_remaining(tvb, macofs) >= 4)
629                 proto_tree_add_item(ntp_tree, hf_ntp_keyid, tvb, macofs, 4,
630                                     FALSE);
631         macofs += 4;
632         maclen = tvb_reported_length_remaining(tvb, macofs);
633         if (maclen > 0)
634                 proto_tree_add_item(ntp_tree, hf_ntp_mac, tvb, macofs,
635                                     maclen, FALSE);
636 }
637
638 static int
639 dissect_ntp_ext(tvbuff_t *tvb, proto_tree *ntp_tree, int offset)
640 {
641         proto_tree      *ext_tree, *flags_tree;
642         proto_item      *tf;
643         guint16         extlen;
644         int             endoffset;
645         guint8          flags;
646         guint32         vallen, vallen_round, siglen;
647
648         extlen = tvb_get_ntohs(tvb, offset+2);
649         if (extlen < 8) {
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.
653                  */
654                 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
655                                     "Extension length %u < 8", extlen);
656                 offset += tvb_length_remaining(tvb, offset);
657                 return offset;
658         }
659         if (extlen % 4) {
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.
663                  */
664                 proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
665                         "Extension length %u isn't a multiple of 4",
666                                     extlen);
667                 offset += tvb_length_remaining(tvb, offset);
668                 return offset;
669         }
670         endoffset = offset + extlen;
671
672         tf = proto_tree_add_item(ntp_tree, hf_ntp_ext, tvb, offset, extlen,
673             FALSE);
674         ext_tree = proto_item_add_subtree(tf, ett_ntp_ext);
675
676         flags = tvb_get_guint8(tvb, offset);
677         tf = proto_tree_add_uint(ext_tree, hf_ntp_ext_flags, tvb, offset, 1,
678                                  flags);
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,
681                             flags);
682         proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_error, tvb, offset, 1,
683                             flags);
684         proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_vn, tvb, offset, 1,
685                             flags);
686         offset++;
687
688         proto_tree_add_item(ext_tree, hf_ntp_ext_op, tvb, offset, 1, FALSE);
689         offset++;
690
691         proto_tree_add_uint(ext_tree, hf_ntp_ext_len, tvb, offset, 2, extlen);
692         offset += 2;
693
694         if ((flags & NTP_EXT_VN_MASK) != 2) {
695                 /* don't care about autokey v1 */
696                 return endoffset;
697         }
698
699         proto_tree_add_item(ext_tree, hf_ntp_ext_associd, tvb, offset, 4,
700                             FALSE);
701         offset += 4;
702
703         /* check whether everything up to "vallen" is present */
704         if (extlen < MAX_MAC_LEN) {
705                 /* XXX - report as error? */
706                 return endoffset;
707         }
708
709         proto_tree_add_item(ext_tree, hf_ntp_ext_tstamp, tvb, offset, 4,
710                             FALSE);
711         offset += 4;
712         proto_tree_add_item(ext_tree, hf_ntp_ext_fstamp, tvb, offset, 4,
713                             FALSE);
714         offset += 4;
715         /* XXX fstamp can be server flags */
716
717         vallen = tvb_get_ntohl(tvb, offset);
718         proto_tree_add_uint(ext_tree, hf_ntp_ext_vallen, tvb, offset, 4,
719                             vallen);
720         offset += 4;
721         vallen_round = (vallen + 3) & (-4);
722         if (vallen != 0) {
723                 if ((guint32)(endoffset - offset) < vallen_round) {
724                         /*
725                          * Value goes past the length of the extension
726                          * field.
727                          */
728                         proto_tree_add_text(ext_tree, tvb, offset,
729                                             endoffset - offset,
730                                             "Value length makes value go past the end of the extension field");
731                         return endoffset;
732                 }
733                 proto_tree_add_item(ext_tree, hf_ntp_ext_val, tvb, offset,
734                                     vallen, FALSE);
735         }
736         offset += vallen_round;
737
738         siglen = tvb_get_ntohl(tvb, offset);
739         proto_tree_add_uint(ext_tree, hf_ntp_ext_siglen, tvb, offset, 4,
740                             siglen);
741         offset += 4;
742         if (siglen != 0) {
743                 if (offset + (int)siglen > endoffset) {
744                         /*
745                          * Value goes past the length of the extension
746                          * field.
747                          */
748                         proto_tree_add_text(ext_tree, tvb, offset,
749                                             endoffset - offset,
750                                             "Signature length makes value go past the end of the extension field");
751                         return endoffset;
752                 }
753                 proto_tree_add_item(ext_tree, hf_ntp_ext_sig, tvb,
754                         offset, siglen, FALSE);
755         }
756         return endoffset;
757 }
758
759 static void
760 dissect_ntp_ctrl(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
761 {
762         proto_tree      *flags_tree;
763         proto_item      *tf;
764         guint8 flags2;
765
766         tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
767
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);
773
774         flags2 = tvb_get_guint8(tvb, 1);
775         tf = proto_tree_add_uint(ntp_tree, hf_ntpctrl_flags2, tvb, 1, 1,
776                                  flags2);
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,
779                             flags2);
780         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_error, tvb, 1, 1,
781                             flags2);
782         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_more, tvb, 1, 1,
783                             flags2);
784         proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_opcode, tvb, 1, 1,
785                             flags2);
786 }
787
788 static void
789 dissect_ntp_priv(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
790 {
791         proto_tree      *flags_tree;
792         proto_item      *tf;
793         guint8          auth_seq, impl, reqcode;
794
795         tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
796
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,
801                             flags);
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);
804
805         auth_seq = tvb_get_guint8(tvb, 1);
806         tf = proto_tree_add_uint(ntp_tree, hf_ntppriv_auth_seq, tvb, 1, 1,
807                                  auth_seq);
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);
811
812         impl = tvb_get_guint8(tvb, 2);
813         proto_tree_add_uint(ntp_tree, hf_ntppriv_impl, tvb, 2, 1, impl);
814
815         reqcode = tvb_get_guint8(tvb, 3);
816         proto_tree_add_uint(ntp_tree, hf_ntppriv_reqcode, tvb, 3, 1, reqcode);
817 }
818
819 void
820 proto_register_ntp(void)
821 {
822         static hf_register_info hf[] = {
823                 { &hf_ntp_flags, {
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 }},
835                 { &hf_ntp_stratum, {
836                         "Peer Clock Stratum", "ntp.stratum", FT_UINT8, BASE_DEC,
837                         NULL, 0, "Peer Clock Stratum", HFILL }},
838                 { &hf_ntp_ppoll, {
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 }},
850                 { &hf_ntp_refid, {
851                         "Reference Clock ID", "ntp.refid", FT_BYTES, BASE_NONE,
852                         NULL, 0, "Reference Clock ID", HFILL }},
853                 { &hf_ntp_reftime, {
854                         "Reference Clock Update Time", "ntp.reftime", FT_BYTES, BASE_NONE,
855                         NULL, 0, "Reference Clock Update Time", HFILL }},
856                 { &hf_ntp_org, {
857                         "Originate Time Stamp", "ntp.org", FT_BYTES, BASE_NONE,
858                         NULL, 0, "Originate Time Stamp", HFILL }},
859                 { &hf_ntp_rec, {
860                         "Receive Time Stamp", "ntp.rec", FT_BYTES, BASE_NONE,
861                         NULL, 0, "Receive Time Stamp", HFILL }},
862                 { &hf_ntp_xmt, {
863                         "Transmit Time Stamp", "ntp.xmt", FT_BYTES, BASE_NONE,
864                         NULL, 0, "Transmit Time Stamp", HFILL }},
865                 { &hf_ntp_keyid, {
866                         "Key ID", "ntp.keyid", FT_BYTES, BASE_HEX,
867                         NULL, 0, "Key ID", HFILL }},
868                 { &hf_ntp_mac, {
869                         "Message Authentication Code", "ntp.mac", FT_BYTES, BASE_HEX,
870                         NULL, 0, "Message Authentication Code", HFILL }},
871
872                 { &hf_ntp_ext, {
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 }},
887                 { &hf_ntp_ext_op, {
888                         "Opcode", "ntp.ext.op", FT_UINT8, BASE_DEC,
889                         VALS(ext_op_types), 0, "Opcode", HFILL }},
890                 { &hf_ntp_ext_len, {
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 }},
905                 { &hf_ntp_ext_val, {
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 }},
911                 { &hf_ntp_ext_sig, {
912                         "Signature", "ntp.ext.sig", FT_BYTES, BASE_HEX,
913                         NULL, 0, "Signature", HFILL }},
914
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 }},
930
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 }},
943                 { &hf_ntppriv_seq, {
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 }},
952         };
953         static gint *ett[] = {
954                 &ett_ntp,
955                 &ett_ntp_flags,
956                 &ett_ntp_ext,
957                 &ett_ntp_ext_flags,
958                 &ett_ntpctrl_flags2,
959                 &ett_ntppriv_auth_seq,
960         };
961
962         proto_ntp = proto_register_protocol("Network Time Protocol", "NTP",
963             "ntp");
964         proto_register_field_array(proto_ntp, hf, array_length(hf));
965         proto_register_subtree_array(ett, array_length(ett));
966 }
967
968 void
969 proto_reg_handoff_ntp(void)
970 {
971         dissector_handle_t ntp_handle;
972
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);
976 }