2 * Routines for UDP packet disassembly
4 * $Id: packet-udp.c,v 1.111 2003/09/03 09:52:07 sahlberg Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * Richard Sharpe, 13-Feb-1999, added dispatch table support and
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.
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.
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.
37 #include <epan/packet.h>
38 #include <epan/resolv.h>
43 #include "packet-udp.h"
45 #include "packet-ip.h"
46 #include <epan/conversation.h>
49 static int udp_tap = -1;
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;
59 static gint ett_udp = -1;
61 /* Place UDP summary in proto tree */
62 static gboolean udp_summary_in_tree = TRUE;
64 static dissector_table_t udp_dissector_table;
65 static heur_dissector_list_t heur_subdissector_list;
66 static dissector_handle_t data_handle;
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 */
72 static gboolean try_heuristic_first = FALSE;
75 decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
76 proto_tree *tree, int uh_sport, int uh_dport)
79 int low_port, high_port;
81 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
83 /* determine if this packet is part of a conversation and call dissector */
84 /* for the conversation if available */
86 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_UDP,
87 uh_sport, uh_dport, next_tvb, pinfo, tree))
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))
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:
101 1) we pick the same dissector for traffic going in both directions;
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);
106 although there is, of course, no guarantee that any such strategy
107 will always pick the right port number.
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) {
114 high_port = uh_sport;
117 high_port = uh_dport;
120 dissector_try_port(udp_dissector_table, low_port, next_tvb, pinfo, tree))
122 if (high_port != 0 &&
123 dissector_try_port(udp_dissector_table, high_port, next_tvb, pinfo, tree))
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))
132 call_dissector(data_handle,next_tvb, pinfo, tree);
137 dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
139 proto_tree *udp_tree;
145 guint16 computed_cksum;
147 static e_udphdr udphstruct[4], *udph;
148 static int udph_count=0;
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);
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);
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);
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));
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);
179 ti = proto_tree_add_item(tree, proto_udp, tvb, offset, 8, FALSE);
181 udp_tree = proto_item_add_subtree(ti, ett_udp);
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);
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);
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
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) {
213 phdr[0] = g_htonl((IP_PROTO_UDP<<16) + reported_len);
214 cksum_vec[2].len = 4;
218 phdr[0] = g_htonl(reported_len);
219 phdr[1] = g_htonl(IP_PROTO_UDP);
220 cksum_vec[2].len = 8;
224 /* TCP runs only atop IPv4 and IPv6.... */
225 g_assert_not_reached();
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);
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));
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);
248 /* Skip over header */
251 pinfo->ptype = PT_UDP;
252 pinfo->srcport = udph->uh_sport;
253 pinfo->destport = udph->uh_dport;
255 tap_queue_packet(udp_tap, pinfo, udph);
257 * Call sub-dissectors.
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
263 * Also, we probably don't want to run UDP taps on those packets.
265 * We definitely don't want to do it for an error packet if there's
266 * nothing left in the packet.
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);
273 proto_register_udp(void)
275 module_t *udp_module;
276 static hf_register_info hf[] = {
278 { "Source Port", "udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
282 { "Destination Port", "udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
286 { "Source or Destination Port", "udp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
290 { "Length", "udp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
293 { &hf_udp_checksum_bad,
294 { "Bad Checksum", "udp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
298 { "Checksum", "udp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
301 static gint *ett[] = {
305 proto_udp = proto_register_protocol("User Datagram Protocol",
307 proto_register_field_array(proto_udp, hf, array_length(hf));
308 proto_register_subtree_array(ett, array_length(ett));
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);
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);
328 proto_reg_handoff_udp(void)
330 dissector_handle_t udp_handle;
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");