sensitivity of packet range options fine tuning:
[obnox/wireshark/wip.git] / packet-udp.c
1 /* packet-udp.c
2  * Routines for UDP packet disassembly
3  *
4  * $Id: packet-udp.c,v 1.111 2003/09/03 09:52:07 sahlberg Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
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., 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 #include <stdlib.h>
34 #include <string.h>
35
36 #include <glib.h>
37 #include <epan/packet.h>
38 #include <epan/resolv.h>
39 #include "ipproto.h"
40 #include "in_cksum.h"
41 #include "prefs.h"
42
43 #include "packet-udp.h"
44
45 #include "packet-ip.h"
46 #include <epan/conversation.h>
47 #include "tap.h"
48
49 static int udp_tap = -1;
50
51 static int proto_udp = -1;
52 static int hf_udp_srcport = -1;
53 static int hf_udp_dstport = -1;
54 static int hf_udp_port = -1;
55 static int hf_udp_length = -1;
56 static int hf_udp_checksum = -1;
57 static int hf_udp_checksum_bad = -1;
58
59 static gint ett_udp = -1;
60
61 /* Place UDP summary in proto tree */
62 static gboolean udp_summary_in_tree = TRUE;
63
64 static dissector_table_t udp_dissector_table;
65 static heur_dissector_list_t heur_subdissector_list;
66 static dissector_handle_t data_handle;
67
68 /* Determine if there is a sub-dissector and call it.  This has been */
69 /* separated into a stand alone routine to other protocol dissectors */
70 /* can call to it, ie. socks    */
71
72 static gboolean try_heuristic_first = FALSE;
73
74 void
75 decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
76         proto_tree *tree, int uh_sport, int uh_dport)
77 {
78   tvbuff_t *next_tvb;
79   int low_port, high_port;
80
81   next_tvb = tvb_new_subset(tvb, offset, -1, -1);
82
83 /* determine if this packet is part of a conversation and call dissector */
84 /* for the conversation if available */
85
86   if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_UDP,
87                 uh_sport, uh_dport, next_tvb, pinfo, tree))
88     return;
89
90   if (try_heuristic_first) {
91     /* do lookup with the heuristic subdissector table */
92     if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
93       return;
94   }
95
96   /* Do lookups with the subdissector table.
97      We try the port number with the lower value first, followed by the
98      port number with the higher value.  This means that, for packets
99      where a dissector is registered for *both* port numbers:
100
101         1) we pick the same dissector for traffic going in both directions;
102
103         2) we prefer the port number that's more likely to be the right
104            one (as that prefers well-known ports to reserved ports);
105
106      although there is, of course, no guarantee that any such strategy
107      will always pick the right port number.
108
109      XXX - we ignore port numbers of 0, as some dissectors use a port
110      number of 0 to disable the port, and as RFC 768 says that the source
111      port in UDP datagrams is optional and is 0 if not used. */
112   if (uh_sport > uh_dport) {
113     low_port = uh_dport;
114     high_port = uh_sport;
115   } else {
116     low_port = uh_sport;
117     high_port = uh_dport;
118   }
119   if (low_port != 0 &&
120       dissector_try_port(udp_dissector_table, low_port, next_tvb, pinfo, tree))
121     return;
122   if (high_port != 0 &&
123       dissector_try_port(udp_dissector_table, high_port, next_tvb, pinfo, tree))
124     return;
125
126   if (!try_heuristic_first) {
127     /* do lookup with the heuristic subdissector table */
128     if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
129       return;
130   }
131
132   call_dissector(data_handle,next_tvb, pinfo, tree);
133 }
134
135
136 static void
137 dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
138 {
139   proto_tree *udp_tree;
140   proto_item *ti;
141   guint      len;
142   guint      reported_len;
143   vec_t      cksum_vec[4];
144   guint32    phdr[2];
145   guint16    computed_cksum;
146   int        offset = 0;
147   static e_udphdr udphstruct[4], *udph;
148   static int udph_count=0;
149
150   udph_count++;
151   if(udph_count>=4){
152      udph_count=0;
153   }
154   udph=&udphstruct[udph_count];
155   SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
156   SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
157
158   if (check_col(pinfo->cinfo, COL_PROTOCOL))
159     col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDP");
160   if (check_col(pinfo->cinfo, COL_INFO))
161     col_clear(pinfo->cinfo, COL_INFO);
162
163   udph->uh_sport=tvb_get_ntohs(tvb, offset);
164   udph->uh_dport=tvb_get_ntohs(tvb, offset+2);
165   udph->uh_ulen=tvb_get_ntohs(tvb, offset+4);
166   udph->uh_sum=tvb_get_ntohs(tvb, offset+6);
167
168
169   if (check_col(pinfo->cinfo, COL_INFO))
170     col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s  Destination port: %s",
171             get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport));
172
173   if (tree) {
174     if (udp_summary_in_tree) {
175       ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8,
176       "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
177       get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
178     } else {
179       ti = proto_tree_add_item(tree, proto_udp, tvb, offset, 8, FALSE);
180     }
181     udp_tree = proto_item_add_subtree(ti, ett_udp);
182
183     proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport,
184         "Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport);
185     proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport,
186         "Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport);
187
188     proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport);
189     proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport);
190
191     proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen);
192     reported_len = tvb_reported_length(tvb);
193     len = tvb_length(tvb);
194     if (udph->uh_sum == 0) {
195       /* No checksum supplied in the packet. */
196       proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
197         offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x (none)", udph->uh_sum);
198     } else if (!pinfo->fragmented && len >= reported_len && len >= udph->uh_ulen) {
199       /* The packet isn't part of a fragmented datagram and isn't
200          truncated, so we can checksum it.
201          XXX - make a bigger scatter-gather list once we do fragment
202          reassembly? */
203
204       /* Set up the fields of the pseudo-header. */
205       cksum_vec[0].ptr = pinfo->src.data;
206       cksum_vec[0].len = pinfo->src.len;
207       cksum_vec[1].ptr = pinfo->dst.data;
208       cksum_vec[1].len = pinfo->dst.len;
209       cksum_vec[2].ptr = (const guint8 *)&phdr;
210       switch (pinfo->src.type) {
211
212       case AT_IPv4:
213         phdr[0] = g_htonl((IP_PROTO_UDP<<16) + reported_len);
214         cksum_vec[2].len = 4;
215         break;
216
217       case AT_IPv6:
218         phdr[0] = g_htonl(reported_len);
219         phdr[1] = g_htonl(IP_PROTO_UDP);
220         cksum_vec[2].len = 8;
221         break;
222
223       default:
224         /* TCP runs only atop IPv4 and IPv6.... */
225         g_assert_not_reached();
226         break;
227       }
228       cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, len);
229       cksum_vec[3].len = reported_len;
230       computed_cksum = in_cksum(&cksum_vec[0], 4);
231       if (computed_cksum == 0) {
232         proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
233           offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x (correct)", udph->uh_sum);
234       } else {
235         proto_tree_add_boolean_hidden(udp_tree, hf_udp_checksum_bad, tvb,
236            offset + 6, 2, TRUE);
237         proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
238           offset + 6, 2, udph->uh_sum,
239           "Checksum: 0x%04x (incorrect, should be 0x%04x)", udph->uh_sum,
240            in_cksum_shouldbe(udph->uh_sum, computed_cksum));
241       }
242     } else {
243       proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
244         offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x", udph->uh_sum);
245     }
246   }
247
248   /* Skip over header */
249   offset += 8;
250
251   pinfo->ptype = PT_UDP;
252   pinfo->srcport = udph->uh_sport;
253   pinfo->destport = udph->uh_dport;
254
255   tap_queue_packet(udp_tap, pinfo, udph);
256   /*
257    * Call sub-dissectors.
258    *
259    * XXX - should we do this if this is included in an error packet?
260    * It might be nice to see the details of the packet that caused the
261    * ICMP error, but it might not be nice to have the dissector update
262    * state based on it.
263    * Also, we probably don't want to run UDP taps on those packets.
264    *
265    * We definitely don't want to do it for an error packet if there's
266    * nothing left in the packet.
267    */
268   if (!pinfo->in_error_pkt || tvb_length_remaining(tvb, offset) > 0)
269     decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport);
270 }
271
272 void
273 proto_register_udp(void)
274 {
275         module_t *udp_module;
276         static hf_register_info hf[] = {
277                 { &hf_udp_srcport,
278                 { "Source Port",        "udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
279                         "", HFILL }},
280
281                 { &hf_udp_dstport,
282                 { "Destination Port",   "udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
283                         "", HFILL }},
284
285                 { &hf_udp_port,
286                 { "Source or Destination Port", "udp.port", FT_UINT16, BASE_DEC,  NULL, 0x0,
287                         "", HFILL }},
288
289                 { &hf_udp_length,
290                 { "Length",             "udp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
291                         "", HFILL }},
292
293                 { &hf_udp_checksum_bad,
294                 { "Bad Checksum",       "udp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
295                         "", HFILL }},
296
297                 { &hf_udp_checksum,
298                 { "Checksum",           "udp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
299                         "", HFILL }},
300         };
301         static gint *ett[] = {
302                 &ett_udp,
303         };
304
305         proto_udp = proto_register_protocol("User Datagram Protocol",
306             "UDP", "udp");
307         proto_register_field_array(proto_udp, hf, array_length(hf));
308         proto_register_subtree_array(ett, array_length(ett));
309
310 /* subdissector code */
311         udp_dissector_table = register_dissector_table("udp.port",
312             "UDP port", FT_UINT16, BASE_DEC);
313         register_heur_dissector_list("udp", &heur_subdissector_list);
314
315         /* Register configuration preferences */
316         udp_module = prefs_register_protocol(proto_udp, NULL);
317         prefs_register_bool_preference(udp_module, "summary_in_tree",
318             "Show UDP summary in protocol tree",
319             "Whether the UDP summary line should be shown in the protocol tree",
320             &udp_summary_in_tree);
321         prefs_register_bool_preference(udp_module, "try_heuristic_first",
322             "Try heuristic sub-dissectors first",
323             "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
324             &try_heuristic_first);
325 }
326
327 void
328 proto_reg_handoff_udp(void)
329 {
330         dissector_handle_t udp_handle;
331
332         udp_handle = create_dissector_handle(dissect_udp, proto_udp);
333         dissector_add("ip.proto", IP_PROTO_UDP, udp_handle);
334         data_handle = find_dissector("data");
335         udp_tap = register_tap("udp");
336 }