Trivial warning fixes
[obnox/wireshark/wip.git] / epan / dissectors / packet-udp.c
1 /* packet-udp.c
2  * Routines for UDP/UDPLite packet disassembly
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * Richard Sharpe, 13-Feb-1999, added dispatch table support and
11  *                              support for tftp.
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include <glib.h>
37 #include <epan/packet.h>
38 #include <epan/emem.h>
39 #include <epan/addr_resolv.h>
40 #include <epan/ipproto.h>
41 #include <epan/in_cksum.h>
42 #include <epan/prefs.h>
43 #include <epan/expert.h>
44
45 #include "packet-udp.h"
46
47 #include "packet-ip.h"
48 #include <epan/conversation.h>
49 #include <epan/tap.h>
50
51 static int udp_tap = -1;
52 static int udp_follow_tap = -1;
53
54 static int proto_udp = -1;
55 static int proto_udplite = -1;
56 static int hf_udp_srcport = -1;
57 static int hf_udp_dstport = -1;
58 static int hf_udp_port = -1;
59 static int hf_udp_length = -1;
60 static int hf_udplite_checksum_coverage = -1;
61 static int hf_udplite_checksum_coverage_bad = -1;
62 static int hf_udp_checksum = -1;
63 static int hf_udp_checksum_good = -1;
64 static int hf_udp_checksum_bad = -1;
65
66 static gint ett_udp = -1;
67 static gint ett_udp_checksum = -1;
68
69 /* Preferences */
70
71 /* Place UDP summary in proto tree */
72 static gboolean udp_summary_in_tree = TRUE;
73
74 /* Check UDP checksums */
75 static gboolean udp_check_checksum = FALSE;
76
77 /* Ignore an invalid checksum coverage field for UDPLite */
78 static gboolean udplite_ignore_checksum_coverage = TRUE;
79
80 /* Check UDPLite checksums */
81 static gboolean udplite_check_checksum = FALSE;
82
83 static dissector_table_t udp_dissector_table;
84 static heur_dissector_list_t heur_subdissector_list;
85 static dissector_handle_t data_handle;
86
87 /* Determine if there is a sub-dissector and call it.  This has been */
88 /* separated into a stand alone routine so other protocol dissectors */
89 /* can call to it, ie. socks    */
90
91 static gboolean try_heuristic_first = FALSE;
92
93 void
94 decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
95         proto_tree *tree, int uh_sport, int uh_dport, int uh_ulen)
96 {
97   tvbuff_t *next_tvb;
98   int low_port, high_port;
99   gint len, reported_len;
100
101   len = tvb_length_remaining(tvb, offset);
102   reported_len = tvb_reported_length_remaining(tvb, offset);
103   if (uh_ulen != -1) {
104     /* This is the length from the UDP header; the payload should be cut
105        off at that length.  (If our caller passed a value here, they
106        are assumed to have checked that it's >= 8, and hence >= offset.)
107
108        XXX - what if it's *greater* than the reported length? */
109     if (uh_ulen - offset < reported_len)
110       reported_len = uh_ulen - offset;
111     if (len > reported_len)
112       len = reported_len;
113   }
114
115   next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
116
117   /* If the user has a "Follow UDP Stream" window loading, pass a pointer
118    * to the payload tvb through the tap system. */
119   if(have_tap_listener(udp_follow_tap))
120           tap_queue_packet(udp_follow_tap, pinfo, next_tvb);
121   
122 /* determine if this packet is part of a conversation and call dissector */
123 /* for the conversation if available */
124
125   if (try_conversation_dissector(&pinfo->dst, &pinfo->src, PT_UDP,
126                 uh_dport, uh_sport, next_tvb, pinfo, tree)){
127     return;
128   }
129
130   if (try_heuristic_first) {
131     /* do lookup with the heuristic subdissector table */
132     if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
133       return;
134   }
135
136   /* Do lookups with the subdissector table.
137      We try the port number with the lower value first, followed by the
138      port number with the higher value.  This means that, for packets
139      where a dissector is registered for *both* port numbers:
140
141         1) we pick the same dissector for traffic going in both directions;
142
143         2) we prefer the port number that's more likely to be the right
144            one (as that prefers well-known ports to reserved ports);
145
146      although there is, of course, no guarantee that any such strategy
147      will always pick the right port number.
148
149      XXX - we ignore port numbers of 0, as some dissectors use a port
150      number of 0 to disable the port, and as RFC 768 says that the source
151      port in UDP datagrams is optional and is 0 if not used. */
152   if (uh_sport > uh_dport) {
153     low_port = uh_dport;
154     high_port = uh_sport;
155   } else {
156     low_port = uh_sport;
157     high_port = uh_dport;
158   }
159   if (low_port != 0 &&
160       dissector_try_port(udp_dissector_table, low_port, next_tvb, pinfo, tree))
161     return;
162   if (high_port != 0 &&
163       dissector_try_port(udp_dissector_table, high_port, next_tvb, pinfo, tree))
164     return;
165
166   if (!try_heuristic_first) {
167     /* do lookup with the heuristic subdissector table */
168     if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
169       return;
170   }
171
172   call_dissector(data_handle,next_tvb, pinfo, tree);
173 }
174
175
176 static void
177 dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto)
178 {
179   proto_tree *udp_tree = NULL;
180   proto_item *ti, *hidden_item;
181   guint      len;
182   guint      reported_len;
183   vec_t      cksum_vec[4];
184   guint32    phdr[2];
185   guint16    computed_cksum;
186   int        offset = 0;
187   e_udphdr *udph;
188   proto_tree *checksum_tree;
189   proto_item *item;
190
191   udph=ep_alloc(sizeof(e_udphdr));
192   SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
193   SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
194
195   if (check_col(pinfo->cinfo, COL_PROTOCOL))
196     col_set_str(pinfo->cinfo, COL_PROTOCOL, (ip_proto == IP_PROTO_UDP) ? "UDP" : "UDPlite");
197   if (check_col(pinfo->cinfo, COL_INFO))
198     col_clear(pinfo->cinfo, COL_INFO);
199
200   udph->uh_sport=tvb_get_ntohs(tvb, offset);
201   udph->uh_dport=tvb_get_ntohs(tvb, offset+2);
202
203   if (check_col(pinfo->cinfo, COL_INFO))
204     col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s  Destination port: %s",
205             get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport));
206
207   if (tree) {
208     if (udp_summary_in_tree) {
209       if (ip_proto == IP_PROTO_UDP) {
210         ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8,
211         "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
212         get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
213       } else {
214         ti = proto_tree_add_protocol_format(tree, proto_udplite, tvb, offset, 8,
215         "Lightweight User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
216         get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
217       }
218     } else {
219       ti = proto_tree_add_item(tree, proto_udp, tvb, offset, 8, FALSE);
220     }
221     udp_tree = proto_item_add_subtree(ti, ett_udp);
222
223     proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport,
224         "Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport);
225     proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport,
226         "Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport);
227
228     hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport);
229     PROTO_ITEM_SET_HIDDEN(hidden_item);
230     hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport);
231     PROTO_ITEM_SET_HIDDEN(hidden_item);
232   }
233
234   if (ip_proto == IP_PROTO_UDP) {
235     udph->uh_ulen = udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4);
236     if (udph->uh_ulen < 8) {
237       /* Bogus length - it includes the header, so it must be >= 8. */
238       /* XXX - should handle IPv6 UDP jumbograms (RFC 2675), where the length is zero */
239       item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2,
240           udph->uh_ulen, "Length: %u (bogus, must be >= 8)", udph->uh_ulen);
241       expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u < 8", udph->uh_ulen);
242       if (check_col(pinfo->cinfo, COL_INFO))
243         col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u < 8]", udph->uh_ulen);
244       return;
245     }
246     if ((udph->uh_ulen > tvb_reported_length(tvb)) && ! pinfo->fragmented && ! pinfo->in_error_pkt) {
247       /* Bogus length - it goes past the end of the IP payload */
248       item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2,
249           udph->uh_ulen, "Length: %u (bogus, payload length %u)", udph->uh_ulen, tvb_reported_length(tvb));
250       expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u > IP payload length", udph->uh_ulen);
251       if (check_col(pinfo->cinfo, COL_INFO))
252         col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u > IP PAYLOAD LENGTH]", udph->uh_ulen);
253     } else {
254       if (tree) {
255         proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen);
256         /* XXX - why is this here, given that this is UDP, not Lightweight UDP? */
257         hidden_item = proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4,
258                                           0, udph->uh_sum_cov);
259         PROTO_ITEM_SET_HIDDEN(hidden_item);
260       }
261     }
262   } else {
263     udph->uh_ulen = pinfo->iplen - pinfo->iphdrlen;
264     udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4);
265     if (((udph->uh_sum_cov > 0) && (udph->uh_sum_cov < 8)) || (udph->uh_sum_cov > udph->uh_ulen)) {
266       /* Bogus length - it includes the header, so it must be >= 8, and no larger then the IP payload size. */
267       if (tree) {
268         hidden_item = proto_tree_add_boolean(udp_tree, hf_udplite_checksum_coverage_bad, tvb, offset + 4, 2, TRUE);
269         PROTO_ITEM_SET_HIDDEN(hidden_item);
270         hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen);
271         PROTO_ITEM_SET_HIDDEN(hidden_item);
272       }
273       item = proto_tree_add_uint_format(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2,
274           udph->uh_sum_cov, "Checksum coverage: %u (bogus, must be >= 8 and <= %u (ip.len-ip.hdr_len))",
275           udph->uh_sum_cov, udph->uh_ulen);
276       expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad checksum coverage length value %u < 8 or > %u",
277                              udph->uh_sum_cov, udph->uh_ulen);
278       if (check_col(pinfo->cinfo, COL_INFO))
279         col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD LIGHTWEIGHT UDP CHECKSUM COVERAGE LENGTH %u < 8 or > %u]",
280                         udph->uh_sum_cov, udph->uh_ulen);
281       if (!udplite_ignore_checksum_coverage)
282         return;
283     } else {
284       if (tree) {
285         hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen);
286         PROTO_ITEM_SET_HIDDEN(hidden_item);
287         proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov);
288       }
289     }
290   }
291
292   udph->uh_sum_cov = (udph->uh_sum_cov) ? udph->uh_sum_cov : udph->uh_ulen;
293   udph->uh_sum = tvb_get_ntohs(tvb, offset+6);
294   reported_len = tvb_reported_length(tvb);
295   len = tvb_length(tvb);
296   if (udph->uh_sum == 0) {
297     /* No checksum supplied in the packet. */
298     if (ip_proto == IP_PROTO_UDP) {
299       item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0,
300         "Checksum: 0x%04x (none)", 0);
301
302       checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
303       proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
304                              offset + 6, 2, FALSE);
305       proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
306                              offset + 6, 2, FALSE);
307     } else {
308       item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0,
309         "Checksum: 0x%04x (Illegal)", 0);
310       expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Illegal Checksum value (0)");
311       if (check_col(pinfo->cinfo, COL_INFO))
312         col_append_fstr(pinfo->cinfo, COL_INFO, " [ILLEGAL CHECKSUM (0)]");
313
314       checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
315       item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
316                              offset + 6, 2, FALSE);
317       PROTO_ITEM_SET_GENERATED(item);
318       item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
319                              offset + 6, 2, TRUE);
320       PROTO_ITEM_SET_GENERATED(item);
321     }
322   } else if (!pinfo->fragmented && len >= reported_len &&
323              len >= udph->uh_sum_cov && reported_len >= udph->uh_sum_cov &&
324              udph->uh_sum_cov >=8) {
325     /* The packet isn't part of a fragmented datagram and isn't
326        truncated, so we can checksum it.
327        XXX - make a bigger scatter-gather list once we do fragment
328        reassembly? */
329
330     if (((ip_proto == IP_PROTO_UDP) && (udp_check_checksum)) ||
331         ((ip_proto == IP_PROTO_UDPLITE) && (udplite_check_checksum))) {
332       /* Set up the fields of the pseudo-header. */
333       cksum_vec[0].ptr = pinfo->src.data;
334       cksum_vec[0].len = pinfo->src.len;
335       cksum_vec[1].ptr = pinfo->dst.data;
336       cksum_vec[1].len = pinfo->dst.len;
337       cksum_vec[2].ptr = (const guint8 *)&phdr;
338       switch (pinfo->src.type) {
339
340       case AT_IPv4:
341         phdr[0] = g_htonl((ip_proto<<16) + reported_len);
342         cksum_vec[2].len = 4;
343         break;
344
345       case AT_IPv6:
346         phdr[0] = g_htonl(reported_len);
347         phdr[1] = g_htonl(ip_proto);
348         cksum_vec[2].len = 8;
349         break;
350
351       default:
352         /* UDP runs only atop IPv4 and IPv6.... */
353         DISSECTOR_ASSERT_NOT_REACHED();
354         break;
355       }
356       cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, udph->uh_sum_cov);
357       cksum_vec[3].len = udph->uh_sum_cov;
358       computed_cksum = in_cksum(&cksum_vec[0], 4);
359       if (computed_cksum == 0) {
360         item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
361           offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [correct]", udph->uh_sum);
362
363         checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
364         item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
365                                       offset + 6, 2, TRUE);
366         PROTO_ITEM_SET_GENERATED(item);
367         item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
368                                       offset + 6, 2, FALSE);
369         PROTO_ITEM_SET_GENERATED(item);
370       } else {
371         item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
372                                           offset + 6, 2, udph->uh_sum,
373           "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"UDP checksum offload\"?)]", udph->uh_sum,
374           in_cksum_shouldbe(udph->uh_sum, computed_cksum));
375
376         checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
377         item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
378                                       offset + 6, 2, FALSE);
379         PROTO_ITEM_SET_GENERATED(item);
380         item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
381                                       offset + 6, 2, TRUE);
382         PROTO_ITEM_SET_GENERATED(item);
383         expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
384
385         if (check_col(pinfo->cinfo, COL_INFO))
386           col_append_fstr(pinfo->cinfo, COL_INFO, " [UDP CHECKSUM INCORRECT]");
387       }
388     } else {
389       item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
390         offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [validation disabled]", udph->uh_sum);
391       checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
392       item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
393                              offset + 6, 2, FALSE);
394       PROTO_ITEM_SET_GENERATED(item);
395       item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
396                              offset + 6, 2, FALSE);
397       PROTO_ITEM_SET_GENERATED(item);
398     }
399   } else {
400     item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
401       offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x", udph->uh_sum);
402
403     checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
404     item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
405                              offset + 6, 2, FALSE);
406     PROTO_ITEM_SET_GENERATED(item);
407     item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
408                              offset + 6, 2, FALSE);
409     PROTO_ITEM_SET_GENERATED(item);
410   }
411
412   /* Skip over header */
413   offset += 8;
414
415   pinfo->ptype = PT_UDP;
416   pinfo->srcport = udph->uh_sport;
417   pinfo->destport = udph->uh_dport;
418
419   tap_queue_packet(udp_tap, pinfo, udph);
420   /*
421    * Call sub-dissectors.
422    *
423    * XXX - should we do this if this is included in an error packet?
424    * It might be nice to see the details of the packet that caused the
425    * ICMP error, but it might not be nice to have the dissector update
426    * state based on it.
427    * Also, we probably don't want to run UDP taps on those packets.
428    *
429    * We definitely don't want to do it for an error packet if there's
430    * nothing left in the packet.
431    */
432   if (!pinfo->in_error_pkt || tvb_length_remaining(tvb, offset) > 0)
433     decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport,
434                      udph->uh_ulen);
435 }
436
437 static void
438 dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
439 {
440   dissect(tvb, pinfo, tree, IP_PROTO_UDP);
441 }
442
443 static void
444 dissect_udplite(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
445 {
446   dissect(tvb, pinfo, tree, IP_PROTO_UDPLITE);
447 }
448
449 void
450 proto_register_udp(void)
451 {
452         module_t *udp_module;
453         module_t *udplite_module;
454
455         static hf_register_info hf[] = {
456                 { &hf_udp_srcport,
457                 { "Source Port",        "udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
458                         "", HFILL }},
459
460                 { &hf_udp_dstport,
461                 { "Destination Port",   "udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
462                         "", HFILL }},
463
464                 { &hf_udp_port,
465                 { "Source or Destination Port", "udp.port", FT_UINT16, BASE_DEC,  NULL, 0x0,
466                         "", HFILL }},
467
468                 { &hf_udp_length,
469                 { "Length",             "udp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
470                         "", HFILL }},
471
472                 { &hf_udp_checksum,
473                 { "Checksum",           "udp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
474                         "Details at: http://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
475
476                 { &hf_udp_checksum_good,
477                 { "Good Checksum",      "udp.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
478                         "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
479
480                 { &hf_udp_checksum_bad,
481                 { "Bad Checksum",       "udp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
482                         "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }}
483         };
484
485         static hf_register_info hf_lite[] = {
486                 { &hf_udplite_checksum_coverage_bad,
487                 { "Bad Checksum coverage",      "udp.checksum_coverage_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
488                         "", HFILL }},
489
490                 { &hf_udplite_checksum_coverage,
491                 { "Checksum coverage",  "udp.checksum_coverage", FT_UINT16, BASE_DEC, NULL, 0x0,
492                         "", HFILL }}
493         };
494
495         static gint *ett[] = {
496                 &ett_udp,
497                 &ett_udp_checksum
498         };
499
500         proto_udp = proto_register_protocol("User Datagram Protocol",
501             "UDP", "udp");
502         register_dissector("udp", dissect_udp, proto_udp);
503         proto_udplite = proto_register_protocol("Lightweight User Datagram Protocol",
504             "UDPlite", "udplite");
505         proto_register_field_array(proto_udp, hf, array_length(hf));
506         proto_register_field_array(proto_udplite, hf_lite, array_length(hf_lite));
507         proto_register_subtree_array(ett, array_length(ett));
508
509 /* subdissector code */
510         udp_dissector_table = register_dissector_table("udp.port",
511             "UDP port", FT_UINT16, BASE_DEC);
512         register_heur_dissector_list("udp", &heur_subdissector_list);
513         register_heur_dissector_list("udplite", &heur_subdissector_list);
514
515         /* Register configuration preferences */
516         udp_module = prefs_register_protocol(proto_udp, NULL);
517         prefs_register_bool_preference(udp_module, "summary_in_tree",
518             "Show UDP summary in protocol tree",
519             "Whether the UDP summary line should be shown in the protocol tree",
520             &udp_summary_in_tree);
521         prefs_register_bool_preference(udp_module, "try_heuristic_first",
522             "Try heuristic sub-dissectors first",
523             "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
524             &try_heuristic_first);
525         prefs_register_bool_preference(udp_module, "check_checksum",
526             "Validate the UDP checksum if possible",
527             "Whether to validate the UDP checksum",
528             &udp_check_checksum);
529
530         udplite_module = prefs_register_protocol(proto_udplite, NULL);
531         prefs_register_bool_preference(udplite_module, "ignore_checksum_coverage",
532             "Ignore UDPlite checksum coverage",
533             "Ignore an invalid checksum coverage field and continue dissection",
534             &udplite_ignore_checksum_coverage);
535         prefs_register_bool_preference(udplite_module, "check_checksum",
536             "Validate the UDPlite checksum if possible",
537             "Whether to validate the UDPlite checksum",
538             &udplite_check_checksum);
539 }
540
541 void
542 proto_reg_handoff_udp(void)
543 {
544         dissector_handle_t udp_handle;
545         dissector_handle_t udplite_handle;
546
547         udp_handle = find_dissector("udp");
548         dissector_add("ip.proto", IP_PROTO_UDP, udp_handle);
549         udplite_handle = create_dissector_handle(dissect_udplite, proto_udplite);
550         dissector_add("ip.proto", IP_PROTO_UDPLITE, udplite_handle);
551         data_handle = find_dissector("data");
552         udp_tap = register_tap("udp");
553         udp_follow_tap = register_tap("udp_follow");
554 }