2 * Routines for UDP packet disassembly
4 * $Id: packet-udp.c,v 1.106 2003/01/28 23:56:40 guy 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>
48 static int proto_udp = -1;
49 static int hf_udp_srcport = -1;
50 static int hf_udp_dstport = -1;
51 static int hf_udp_port = -1;
52 static int hf_udp_length = -1;
53 static int hf_udp_checksum = -1;
54 static int hf_udp_checksum_bad = -1;
56 static gint ett_udp = -1;
58 /* Place UDP summary in proto tree */
59 static gboolean udp_summary_in_tree = TRUE;
61 /* UDP structs and definitions */
63 typedef struct _e_udphdr {
70 static dissector_table_t udp_dissector_table;
71 static heur_dissector_list_t heur_subdissector_list;
72 static dissector_handle_t data_handle;
74 /* Determine if there is a sub-dissector and call it. This has been */
75 /* separated into a stand alone routine to other protocol dissectors */
76 /* can call to it, ie. socks */
79 decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
80 proto_tree *tree, int uh_sport, int uh_dport)
83 int low_port, high_port;
85 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
87 /* determine if this packet is part of a conversation and call dissector */
88 /* for the conversation if available */
90 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_UDP,
91 uh_sport, uh_dport, next_tvb, pinfo, tree))
94 /* Do lookups with the subdissector table.
95 We try the port number with the lower value first, followed by the
96 port number with the higher value. This means that, for packets
97 where a dissector is registered for *both* port numbers:
99 1) we pick the same dissector for traffic going in both directions;
101 2) we prefer the port number that's more likely to be the right
102 one (as that prefers well-known ports to reserved ports);
104 although there is, of course, no guarantee that any such strategy
105 will always pick the right port number.
107 XXX - we ignore port numbers of 0, as some dissectors use a port
108 number of 0 to disable the port, and as RFC 768 says that the source
109 port in UDP datagrams is optional and is 0 if not used. */
110 if (uh_sport > uh_dport) {
112 high_port = uh_sport;
115 high_port = uh_dport;
118 dissector_try_port(udp_dissector_table, low_port, next_tvb, pinfo, tree))
120 if (high_port != 0 &&
121 dissector_try_port(udp_dissector_table, high_port, next_tvb, pinfo, tree))
124 /* do lookup with the heuristic subdissector table */
125 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
128 call_dissector(data_handle,next_tvb, pinfo, tree);
133 dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
136 guint16 uh_sport, uh_dport, uh_ulen, uh_sum;
137 proto_tree *udp_tree;
143 guint16 computed_cksum;
146 if (check_col(pinfo->cinfo, COL_PROTOCOL))
147 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDP");
148 if (check_col(pinfo->cinfo, COL_INFO))
149 col_clear(pinfo->cinfo, COL_INFO);
151 /* Avoids alignment problems on many architectures. */
152 tvb_memcpy(tvb, (guint8 *)&uh, offset, sizeof(e_udphdr));
153 uh_sport = g_ntohs(uh.uh_sport);
154 uh_dport = g_ntohs(uh.uh_dport);
155 uh_ulen = g_ntohs(uh.uh_ulen);
156 uh_sum = g_ntohs(uh.uh_sum);
158 if (check_col(pinfo->cinfo, COL_INFO))
159 col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s Destination port: %s",
160 get_udp_port(uh_sport), get_udp_port(uh_dport));
163 if (udp_summary_in_tree) {
164 ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8,
165 "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
166 get_udp_port(uh_sport), uh_sport, get_udp_port(uh_dport), uh_dport);
168 ti = proto_tree_add_item(tree, proto_udp, tvb, offset, 8, FALSE);
170 udp_tree = proto_item_add_subtree(ti, ett_udp);
172 proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, uh_sport,
173 "Source port: %s (%u)", get_udp_port(uh_sport), uh_sport);
174 proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, uh_dport,
175 "Destination port: %s (%u)", get_udp_port(uh_dport), uh_dport);
177 proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset, 2, uh_sport);
178 proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset+2, 2, uh_dport);
180 proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, uh_ulen);
181 reported_len = tvb_reported_length(tvb);
182 len = tvb_length(tvb);
184 /* No checksum supplied in the packet. */
185 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
186 offset + 6, 2, uh_sum, "Checksum: 0x%04x (none)", uh_sum);
187 } else if (!pinfo->fragmented && len >= reported_len && len >= uh_ulen) {
188 /* The packet isn't part of a fragmented datagram and isn't
189 truncated, so we can checksum it.
190 XXX - make a bigger scatter-gather list once we do fragment
193 /* Set up the fields of the pseudo-header. */
194 cksum_vec[0].ptr = pinfo->src.data;
195 cksum_vec[0].len = pinfo->src.len;
196 cksum_vec[1].ptr = pinfo->dst.data;
197 cksum_vec[1].len = pinfo->dst.len;
198 cksum_vec[2].ptr = (const guint8 *)&phdr;
199 switch (pinfo->src.type) {
202 phdr[0] = g_htonl((IP_PROTO_UDP<<16) + reported_len);
203 cksum_vec[2].len = 4;
207 phdr[0] = g_htonl(reported_len);
208 phdr[1] = g_htonl(IP_PROTO_UDP);
209 cksum_vec[2].len = 8;
213 /* TCP runs only atop IPv4 and IPv6.... */
214 g_assert_not_reached();
217 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, len);
218 cksum_vec[3].len = reported_len;
219 computed_cksum = in_cksum(&cksum_vec[0], 4);
220 if (computed_cksum == 0) {
221 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
222 offset + 6, 2, uh_sum, "Checksum: 0x%04x (correct)", uh_sum);
224 proto_tree_add_boolean_hidden(udp_tree, hf_udp_checksum_bad, tvb,
225 offset + 6, 2, TRUE);
226 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
227 offset + 6, 2, uh_sum,
228 "Checksum: 0x%04x (incorrect, should be 0x%04x)", uh_sum,
229 in_cksum_shouldbe(uh_sum, computed_cksum));
232 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
233 offset + 6, 2, uh_sum, "Checksum: 0x%04x", uh_sum);
237 /* Skip over header */
240 pinfo->ptype = PT_UDP;
241 pinfo->srcport = uh_sport;
242 pinfo->destport = uh_dport;
244 /* call sub-dissectors */
245 decode_udp_ports( tvb, offset, pinfo, tree, uh_sport, uh_dport);
250 proto_register_udp(void)
252 module_t *udp_module;
253 static hf_register_info hf[] = {
255 { "Source Port", "udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
259 { "Destination Port", "udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
263 { "Source or Destination Port", "udp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
267 { "Length", "udp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
270 { &hf_udp_checksum_bad,
271 { "Bad Checksum", "udp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
275 { "Checksum", "udp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
278 static gint *ett[] = {
282 proto_udp = proto_register_protocol("User Datagram Protocol",
284 proto_register_field_array(proto_udp, hf, array_length(hf));
285 proto_register_subtree_array(ett, array_length(ett));
287 /* subdissector code */
288 udp_dissector_table = register_dissector_table("udp.port",
289 "UDP port", FT_UINT16, BASE_DEC);
290 register_heur_dissector_list("udp", &heur_subdissector_list);
292 /* Register configuration preferences */
293 udp_module = prefs_register_protocol(proto_udp, NULL);
294 prefs_register_bool_preference(udp_module, "summary_in_tree",
295 "Show UDP summary in protocol tree",
296 "Whether the UDP summary line should be shown in the protocol tree",
297 &udp_summary_in_tree);
301 proto_reg_handoff_udp(void)
303 dissector_handle_t udp_handle;
305 udp_handle = create_dissector_handle(dissect_udp, proto_udp);
306 dissector_add("ip.proto", IP_PROTO_UDP, udp_handle);
307 data_handle = find_dissector("data");