2 * Routines for UDP packet disassembly
4 * $Id: packet-udp.c,v 1.107 2003/03/03 23:46:48 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 */
73 decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
74 proto_tree *tree, int uh_sport, int uh_dport)
77 int low_port, high_port;
79 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
81 /* determine if this packet is part of a conversation and call dissector */
82 /* for the conversation if available */
84 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_UDP,
85 uh_sport, uh_dport, next_tvb, pinfo, tree))
88 /* Do lookups with the subdissector table.
89 We try the port number with the lower value first, followed by the
90 port number with the higher value. This means that, for packets
91 where a dissector is registered for *both* port numbers:
93 1) we pick the same dissector for traffic going in both directions;
95 2) we prefer the port number that's more likely to be the right
96 one (as that prefers well-known ports to reserved ports);
98 although there is, of course, no guarantee that any such strategy
99 will always pick the right port number.
101 XXX - we ignore port numbers of 0, as some dissectors use a port
102 number of 0 to disable the port, and as RFC 768 says that the source
103 port in UDP datagrams is optional and is 0 if not used. */
104 if (uh_sport > uh_dport) {
106 high_port = uh_sport;
109 high_port = uh_dport;
112 dissector_try_port(udp_dissector_table, low_port, next_tvb, pinfo, tree))
114 if (high_port != 0 &&
115 dissector_try_port(udp_dissector_table, high_port, next_tvb, pinfo, tree))
118 /* do lookup with the heuristic subdissector table */
119 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
122 call_dissector(data_handle,next_tvb, pinfo, tree);
127 dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
129 proto_tree *udp_tree;
135 guint16 computed_cksum;
137 static e_udphdr udphstruct[4], *udph;
138 static int udph_count=0;
144 udph=&udphstruct[udph_count];
145 udph->ip_header=pinfo->private_data;
147 if (check_col(pinfo->cinfo, COL_PROTOCOL))
148 col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDP");
149 if (check_col(pinfo->cinfo, COL_INFO))
150 col_clear(pinfo->cinfo, COL_INFO);
152 udph->uh_sport=tvb_get_ntohs(tvb, offset);
153 udph->uh_dport=tvb_get_ntohs(tvb, offset+2);
154 udph->uh_ulen=tvb_get_ntohs(tvb, offset+4);
155 udph->uh_sum=tvb_get_ntohs(tvb, offset+6);
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(udph->uh_sport), get_udp_port(udph->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(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->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, udph->uh_sport,
173 "Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport);
174 proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport,
175 "Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport);
177 proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport);
178 proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport);
180 proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen);
181 reported_len = tvb_reported_length(tvb);
182 len = tvb_length(tvb);
183 if (udph->uh_sum == 0) {
184 /* No checksum supplied in the packet. */
185 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
186 offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x (none)", udph->uh_sum);
187 } else if (!pinfo->fragmented && len >= reported_len && len >= udph->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, udph->uh_sum, "Checksum: 0x%04x (correct)", udph->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, udph->uh_sum,
228 "Checksum: 0x%04x (incorrect, should be 0x%04x)", udph->uh_sum,
229 in_cksum_shouldbe(udph->uh_sum, computed_cksum));
232 proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
233 offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x", udph->uh_sum);
237 /* Skip over header */
240 pinfo->ptype = PT_UDP;
241 pinfo->srcport = udph->uh_sport;
242 pinfo->destport = udph->uh_dport;
244 /* call sub-dissectors */
245 decode_udp_ports( tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport);
246 tap_queue_packet(udp_tap, pinfo, udph);
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");
308 udp_tap = register_tap("udp");