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