A quantity dissected as 6 unknown bytes in a logon reply actually
[metze/wireshark/wip.git] / packet-udp.c
1 /* packet-udp.c
2  * Routines for UDP packet disassembly
3  *
4  * $Id: packet-udp.c,v 1.107 2003/03/03 23:46:48 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 void
73 decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
74         proto_tree *tree, int uh_sport, int uh_dport)
75 {
76   tvbuff_t *next_tvb;
77   int low_port, high_port;
78
79   next_tvb = tvb_new_subset(tvb, offset, -1, -1);
80
81 /* determine if this packet is part of a conversation and call dissector */
82 /* for the conversation if available */
83
84   if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_UDP,
85                 uh_sport, uh_dport, next_tvb, pinfo, tree))
86     return;
87
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:
92
93         1) we pick the same dissector for traffic going in both directions;
94
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);
97
98      although there is, of course, no guarantee that any such strategy
99      will always pick the right port number.
100
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) {
105     low_port = uh_dport;
106     high_port = uh_sport;
107   } else {
108     low_port = uh_sport;
109     high_port = uh_dport;
110   }
111   if (low_port != 0 &&
112       dissector_try_port(udp_dissector_table, low_port, next_tvb, pinfo, tree))
113     return;
114   if (high_port != 0 &&
115       dissector_try_port(udp_dissector_table, high_port, next_tvb, pinfo, tree))
116     return;
117
118   /* do lookup with the heuristic subdissector table */
119   if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
120     return;
121
122   call_dissector(data_handle,next_tvb, pinfo, tree);
123 }
124
125
126 static void
127 dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
128 {
129   proto_tree *udp_tree;
130   proto_item *ti;
131   guint      len;
132   guint      reported_len;
133   vec_t      cksum_vec[4];
134   guint32    phdr[2];
135   guint16    computed_cksum;
136   int        offset = 0;
137   static e_udphdr udphstruct[4], *udph;
138   static int udph_count=0;
139
140   udph_count++;
141   if(udph_count>=4){
142      udph_count=0;
143   }
144   udph=&udphstruct[udph_count];
145   udph->ip_header=pinfo->private_data;
146
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);
151
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);
156
157
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));
161
162   if (tree) {
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);
167     } else {
168       ti = proto_tree_add_item(tree, proto_udp, tvb, offset, 8, FALSE);
169     }
170     udp_tree = proto_item_add_subtree(ti, ett_udp);
171
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);
176
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);
179
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
191          reassembly? */
192
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) {
200
201       case AT_IPv4:
202         phdr[0] = g_htonl((IP_PROTO_UDP<<16) + reported_len);
203         cksum_vec[2].len = 4;
204         break;
205
206       case AT_IPv6:
207         phdr[0] = g_htonl(reported_len);
208         phdr[1] = g_htonl(IP_PROTO_UDP);
209         cksum_vec[2].len = 8;
210         break;
211
212       default:
213         /* TCP runs only atop IPv4 and IPv6.... */
214         g_assert_not_reached();
215         break;
216       }
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);
223       } else {
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));
230       }
231     } else {
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);
234     }
235   }
236
237   /* Skip over header */
238   offset += 8;
239
240   pinfo->ptype = PT_UDP;
241   pinfo->srcport = udph->uh_sport;
242   pinfo->destport = udph->uh_dport;
243
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);
247 }
248
249 void
250 proto_register_udp(void)
251 {
252         module_t *udp_module;
253         static hf_register_info hf[] = {
254                 { &hf_udp_srcport,
255                 { "Source Port",        "udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
256                         "", HFILL }},
257
258                 { &hf_udp_dstport,
259                 { "Destination Port",   "udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
260                         "", HFILL }},
261
262                 { &hf_udp_port,
263                 { "Source or Destination Port", "udp.port", FT_UINT16, BASE_DEC,  NULL, 0x0,
264                         "", HFILL }},
265
266                 { &hf_udp_length,
267                 { "Length",             "udp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
268                         "", HFILL }},
269
270                 { &hf_udp_checksum_bad,
271                 { "Bad Checksum",       "udp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
272                         "", HFILL }},
273
274                 { &hf_udp_checksum,
275                 { "Checksum",           "udp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
276                         "", HFILL }},
277         };
278         static gint *ett[] = {
279                 &ett_udp,
280         };
281
282         proto_udp = proto_register_protocol("User Datagram Protocol",
283             "UDP", "udp");
284         proto_register_field_array(proto_udp, hf, array_length(hf));
285         proto_register_subtree_array(ett, array_length(ett));
286
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);
291
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);
298 }
299
300 void
301 proto_reg_handoff_udp(void)
302 {
303         dissector_handle_t udp_handle;
304
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");
309 }