aboutsummaryrefslogtreecommitdiffstats
path: root/packet-udp.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2000-12-13 02:24:23 +0000
committerGuy Harris <guy@alum.mit.edu>2000-12-13 02:24:23 +0000
commit677a1c6dc236c75344f3410ac740ef3b49ff8663 (patch)
tree08581cec2fec47739698a8b41d485ce576572b9a /packet-udp.c
parent10022aee67c0992d1e9bcf8df80036e3fe958eef (diff)
Add code to check the checksums of TCP segments and UDP datagrams;
replace the existing checksummer with a modified version of the BSD checksumming code. Add a flag to the "packet_info" structure to indicate that a packet is the first fragment of a fragmented datagram, so that the checksummers won't try to checksum those. (It doesn't seem to add a lot of CPU overhead, so we don't introduce a flag to disable it, yet. Further checks may be necessary to see whether the overhead is just swamped by other overheads when scanning through a capture dissecting all frames, or if it truly is negligible.) Make the Boolean preference option controlling whether to make the top-level protocol tree item for TCP display a packet summary static to the TCP dissector (it doesn't need to be accessible outside the TCP dissector). svn path=/trunk/; revision=2751
Diffstat (limited to 'packet-udp.c')
-rw-r--r--packet-udp.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/packet-udp.c b/packet-udp.c
index 3560b9eac7..e313da4712 100644
--- a/packet-udp.c
+++ b/packet-udp.c
@@ -1,7 +1,7 @@
/* packet-udp.c
* Routines for UDP packet disassembly
*
- * $Id: packet-udp.c,v 1.79 2000/11/19 08:54:10 guy Exp $
+ * $Id: packet-udp.c,v 1.80 2000/12/13 02:24:21 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -44,6 +44,7 @@
#include <glib.h>
#include "globals.h"
#include "resolv.h"
+#include "in_cksum.h"
#include "plugins.h"
#include "packet-udp.h"
@@ -144,6 +145,11 @@ dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
guint16 uh_sport, uh_dport, uh_ulen, uh_sum;
proto_tree *udp_tree;
proto_item *ti;
+ guint len;
+ guint reported_len;
+ vec_t cksum_vec[4];
+ guint32 phdr[2];
+ guint16 computed_cksum;
int offset = 0;
CHECK_DISPLAY_AS_DATA(proto_udp, tvb, pinfo, tree);
@@ -176,8 +182,58 @@ dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset+2, 2, uh_dport);
proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, uh_ulen);
- proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, uh_sum,
- "Checksum: 0x%04x", uh_sum);
+ reported_len = tvb_reported_length(tvb);
+ len = tvb_length(tvb);
+ if (uh_sum == 0) {
+ /* No checksum supplied in the packet. */
+ proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
+ offset + 6, 2, uh_sum, "Checksum: 0x%04x (none)", uh_sum);
+ } else if (!pinfo->fragmented && len >= reported_len) {
+ /* The packet isn't part of a fragmented datagram and isn't
+ truncated, so we can checksum it.
+ XXX - make a bigger scatter-gather list once we do fragment
+ reassembly? */
+
+ /* Set up the fields of the pseudo-header. */
+ cksum_vec[0].ptr = pinfo->src.data;
+ cksum_vec[0].len = pinfo->src.len;
+ cksum_vec[1].ptr = pinfo->dst.data;
+ cksum_vec[1].len = pinfo->dst.len;
+ cksum_vec[2].ptr = (const guint8 *)&phdr;
+ switch (pinfo->src.type) {
+
+ case AT_IPv4:
+ phdr[0] = htonl((IP_PROTO_UDP<<16) + reported_len);
+ cksum_vec[2].len = 4;
+ break;
+
+ case AT_IPv6:
+ phdr[0] = htonl(reported_len);
+ phdr[1] = htonl(IP_PROTO_UDP);
+ cksum_vec[2].len = 8;
+ break;
+
+ default:
+ /* TCP runs only atop IPv4 and IPv6.... */
+ g_assert_not_reached();
+ break;
+ }
+ cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, len);
+ cksum_vec[3].len = reported_len;
+ computed_cksum = in_cksum(&cksum_vec[0], 4);
+ if (computed_cksum == 0) {
+ proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
+ offset + 6, 2, uh_sum, "Checksum: 0x%04x (correct)", uh_sum);
+ } else {
+ proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
+ offset + 6, 2, uh_sum,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)", uh_sum,
+ in_cksum_shouldbe(uh_sum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
+ offset + 6, 2, uh_sum, "Checksum: 0x%04x", uh_sum);
+ }
}
/* Skip over header */