2 * Routines for UDP packet disassembly
4 * $Id: packet-udp.c,v 1.103 2002/06/08 21:54:51 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.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>
45 #include <epan/packet.h>
46 #include <epan/resolv.h>
51 #include "packet-udp.h"
53 #include "packet-ip.h"
54 #include <epan/conversation.h>
56 static int proto_udp = -1;
57 static int hf_udp_srcport = -1;
58 static int hf_udp_dstport = -1;
59 static int hf_udp_port = -1;
60 static int hf_udp_length = -1;
61 static int hf_udp_checksum = -1;
62 static int hf_udp_checksum_bad = -1;
64 static gint ett_udp = -1;
66 /* Place UDP summary in proto tree */
67 static gboolean udp_summary_in_tree = TRUE;
69 /* UDP structs and definitions */
71 typedef struct _e_udphdr {
78 static dissector_table_t udp_dissector_table;
79 static heur_dissector_list_t heur_subdissector_list;
80 static dissector_handle_t data_handle;
82 /* Determine if there is a sub-dissector and call it. This has been */
83 /* separated into a stand alone routine to other protocol dissectors */
84 /* can call to it, ie. socks */
87 decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
88 proto_tree *tree, int uh_sport, int uh_dport)
91 int low_port, high_port;
93 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
95 /* determine if this packet is part of a conversation and call dissector */
96 /* for the conversation if available */
98 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_UDP,
99 uh_sport, uh_dport, next_tvb, pinfo, tree))
102 /* Do lookups with the subdissector table.
103 We try the port number with the lower value first, followed by the
104 port number with the higher value. This means that, for packets
105 where a dissector is registered for *both* port numbers:
107 1) we pick the same dissector for traffic going in both directions;
109 2) we prefer the port number that's more likely to be the right
110 one (as that prefers well-known ports to reserved ports);
112 although there is, of course, no guarantee that any such strategy
113 will always pick the right port number.
115 XXX - we ignore port numbers of 0, as some dissectors use a port
116 number of 0 to disable the port, and as RFC 768 says that the source
117 port in UDP datagrams is optional and is 0 if not used. */
118 if (uh_sport > uh_dport) {
120 high_port = uh_sport;
123 high_port = uh_dport;
126 dissector_try_port(udp_dissector_table, low_port, next_tvb, pinfo, tree))
128 if (high_port != 0 &&
129 dissector_try_port(udp_dissector_table, high_port, next_tvb, pinfo, tree))
132 /* do lookup with the heuristic subdissector table */
133 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
136 call_dissector(data_handle,next_tvb, pinfo, tree);
141 dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
144 guint16 uh_sport, uh_dport, uh_ulen, uh_sum;
145 proto_tree *udp_tree;
151 guint16 computed_cksum;
154 if (check_col(pinfo->cinfo, COL_PROTOCOL))
155 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDP");
156 if (check_col(pinfo->cinfo, COL_INFO))
157 col_clear(pinfo->cinfo, COL_INFO);
159 /* Avoids alignment problems on many architectures. */
160 tvb_memcpy(tvb, (guint8 *)&uh, offset, sizeof(e_udphdr));
161 uh_sport = ntohs(uh.uh_sport);
162 uh_dport = ntohs(uh.uh_dport);
163 uh_ulen = ntohs(uh.uh_ulen);
164 uh_sum = ntohs(uh.uh_sum);
166 if (check_col(pinfo->cinfo, COL_INFO))
167 col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s Destination port: %s",
168 get_udp_port(uh_sport), get_udp_port(uh_dport));
171 if (udp_summary_in_tree) {
172 ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8,
173 "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
174 get_udp_port(uh_sport), uh_sport, get_udp_port(uh_dport), uh_dport);
176 ti = proto_tree_add_item(tree, proto_udp, tvb, offset, 8, FALSE);
178 udp_tree = proto_item_add_subtree(ti, ett_udp);
180 proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, uh_sport,
181 "Source port: %s (%u)", get_udp_port(uh_sport), uh_sport);
182 proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, uh_dport,
183 "Destination port: %s (%u)", get_udp_port(uh_dport), uh_dport);
185 proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset, 2, uh_sport);
186 proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset+2, 2, uh_dport);
188 proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, uh_ulen);
189 reported_len = tvb_reported_length(tvb);
190 len = tvb_length(tvb);
192 /* No checksum supplied in the packet. */
193 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
194 offset + 6, 2, uh_sum, "Checksum: 0x%04x (none)", uh_sum);
195 } else if (!pinfo->fragmented && len >= reported_len && len >= uh_ulen) {
196 /* The packet isn't part of a fragmented datagram and isn't
197 truncated, so we can checksum it.
198 XXX - make a bigger scatter-gather list once we do fragment
201 /* Set up the fields of the pseudo-header. */
202 cksum_vec[0].ptr = pinfo->src.data;
203 cksum_vec[0].len = pinfo->src.len;
204 cksum_vec[1].ptr = pinfo->dst.data;
205 cksum_vec[1].len = pinfo->dst.len;
206 cksum_vec[2].ptr = (const guint8 *)&phdr;
207 switch (pinfo->src.type) {
210 phdr[0] = htonl((IP_PROTO_UDP<<16) + reported_len);
211 cksum_vec[2].len = 4;
215 phdr[0] = htonl(reported_len);
216 phdr[1] = htonl(IP_PROTO_UDP);
217 cksum_vec[2].len = 8;
221 /* TCP runs only atop IPv4 and IPv6.... */
222 g_assert_not_reached();
225 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, len);
226 cksum_vec[3].len = reported_len;
227 computed_cksum = in_cksum(&cksum_vec[0], 4);
228 if (computed_cksum == 0) {
229 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
230 offset + 6, 2, uh_sum, "Checksum: 0x%04x (correct)", uh_sum);
232 proto_tree_add_boolean_hidden(udp_tree, hf_udp_checksum_bad, tvb,
233 offset + 6, 2, TRUE);
234 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
235 offset + 6, 2, uh_sum,
236 "Checksum: 0x%04x (incorrect, should be 0x%04x)", uh_sum,
237 in_cksum_shouldbe(uh_sum, computed_cksum));
240 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
241 offset + 6, 2, uh_sum, "Checksum: 0x%04x", uh_sum);
245 /* Skip over header */
248 pinfo->ptype = PT_UDP;
249 pinfo->srcport = uh_sport;
250 pinfo->destport = uh_dport;
252 /* call sub-dissectors */
253 decode_udp_ports( tvb, offset, pinfo, tree, uh_sport, uh_dport);
258 proto_register_udp(void)
260 module_t *udp_module;
261 static hf_register_info hf[] = {
263 { "Source Port", "udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
267 { "Destination Port", "udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
271 { "Source or Destination Port", "udp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
275 { "Length", "udp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
278 { &hf_udp_checksum_bad,
279 { "Bad Checksum", "udp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
283 { "Checksum", "udp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
286 static gint *ett[] = {
290 proto_udp = proto_register_protocol("User Datagram Protocol",
292 proto_register_field_array(proto_udp, hf, array_length(hf));
293 proto_register_subtree_array(ett, array_length(ett));
295 /* subdissector code */
296 udp_dissector_table = register_dissector_table("udp.port",
297 "UDP port", FT_UINT16, BASE_DEC);
298 register_heur_dissector_list("udp", &heur_subdissector_list);
300 /* Register configuration preferences */
301 udp_module = prefs_register_protocol(proto_udp, NULL);
302 prefs_register_bool_preference(udp_module, "udp_summary_in_tree",
303 "Show UDP summary in protocol tree",
304 "Whether the UDP summary line should be shown in the protocol tree",
305 &udp_summary_in_tree);
309 proto_reg_handoff_udp(void)
311 dissector_handle_t udp_handle;
313 udp_handle = create_dissector_handle(dissect_udp, proto_udp);
314 dissector_add("ip.proto", IP_PROTO_UDP, udp_handle);
315 data_handle = find_dissector("data");