Ethereal-dev: [ethereal-dev] Ethereal and UDP checksums..
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Markus Stenberg <mstenber@xxxxxxxxxxxxxx>
Date: 10 May 2000 14:21:38 +0300
Apparently Ethereal did not check UDP checksums.. so I wrote quickie hack
to do it.
There are some problems with the hack, mainly, the 12-byte global character
array used for transferring UDP pseudoheader data from IP to UDP handler,
as there doesn't seem any other way to do it (elegantly).
diff -w -u ethereal-0.8.8/packet-ip.c ethereal-0.8.8-custom/packet-ip.c
--- ethereal-0.8.8/packet-ip.c Tue May 9 06:15:24 2000
+++ ethereal-0.8.8-custom/packet-ip.c Wed May 10 14:17:06 2000
@@ -803,28 +803,44 @@
"Not set"
};
-static char *ip_checksum_state(e_ip *iph)
+unsigned long ip_checksum(unsigned char *start,
+ unsigned char *ptrEnd)
{
- unsigned long Sum;
- unsigned char *Ptr, *PtrEnd;
+ unsigned char *ptr;
+ unsigned long Sum = 0;
unsigned short word;
- Sum = 0;
- PtrEnd = (lo_nibble(iph->ip_v_hl) * 4 + (char *)iph);
- for (Ptr = (unsigned char *) iph; Ptr < PtrEnd; Ptr += 2) {
- memcpy(&word, Ptr, sizeof word);
+ for (ptr = start ; ptr < ptrEnd; ptr += 2) {
+ memcpy(&word, ptr, sizeof word);
Sum += word;
}
+ return Sum;
+}
+int ip_checksum_verify(unsigned long Sum)
+{
Sum = (Sum & 0xFFFF) + (Sum >> 16);
Sum = (Sum & 0xFFFF) + (Sum >> 16);
- if (Sum != 0xffff)
+ return Sum == 0xffff;
+}
+
+static char *ip_checksum_state(e_ip *iph)
+{
+ unsigned long Sum;
+ unsigned char *ptrEnd;
+
+ ptrEnd = (lo_nibble(iph->ip_v_hl) * 4 + (char *)iph);
+ Sum = ip_checksum((unsigned char *) iph, ptrEnd);
+
+ if (!ip_checksum_verify(Sum))
return "incorrect";
return "correct";
}
+char global_ugly_hack_buf[12];
+
void
dissect_ip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
e_ip iph;
@@ -935,6 +951,10 @@
"Header checksum: 0x%04x (%s)", iph.ip_sum, ip_checksum_state((e_ip*) &pd[offset]));
proto_tree_add_item(ip_tree, hf_ip_src, offset + 12, 4, iph.ip_src);
proto_tree_add_item(ip_tree, hf_ip_dst, offset + 16, 4, iph.ip_dst);
+ memcpy(global_ugly_hack_buf, &iph.ip_src, 4);
+ memcpy(global_ugly_hack_buf+4, &iph.ip_dst, 4);
+ global_ugly_hack_buf[8] = 0;
+ global_ugly_hack_buf[9] = iph.ip_p;
proto_tree_add_item_hidden(ip_tree, hf_ip_addr, offset + 12, 4, iph.ip_src);
proto_tree_add_item_hidden(ip_tree, hf_ip_addr, offset + 16, 4, iph.ip_dst);
diff -w -u ethereal-0.8.8/packet-udp.c ethereal-0.8.8-custom/packet-udp.c
--- ethereal-0.8.8/packet-udp.c Tue May 9 06:15:24 2000
+++ ethereal-0.8.8-custom/packet-udp.c Wed May 10 14:19:18 2000
@@ -139,6 +139,28 @@
dissect_data(pd, offset, fd, tree);
}
+extern char global_ugly_hack_buf[12];
+
+unsigned long ip_checksum(unsigned char *start,
+ unsigned char *ptrEnd);
+
+int ip_checksum_verify(unsigned long Sum);
+
+const char *udp_checksum(const u_char *pd, int offset, frame_data *fd,
+ e_udphdr uh)
+{
+ unsigned long cks1, cks2;
+
+ memcpy(global_ugly_hack_buf + 10, &uh.uh_ulen, 2);
+ /* Now we have valid pseudo header (hopefully).
+ Next step is calculating the actual checksum of the whole body of message,
+ and that is somewhat painful */
+ cks1 = ip_checksum(global_ugly_hack_buf, global_ugly_hack_buf+12);
+ cks2 = ip_checksum(pd+offset, pd+fd->pkt_len);
+ if (!ip_checksum_verify(cks1+cks2))
+ return "INCORRECT!!!";
+ return "correct";
+}
static void
dissect_udp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
@@ -146,7 +168,7 @@
guint16 uh_sport, uh_dport, uh_ulen, uh_sum;
proto_tree *udp_tree;
proto_item *ti;
-
+ const char *checksum_str;
if (!BYTES_ARE_IN_FRAME(offset, sizeof(e_udphdr))) {
dissect_data(pd, offset, fd, tree);
return;
@@ -159,11 +181,15 @@
uh_ulen = ntohs(uh.uh_ulen);
uh_sum = ntohs(uh.uh_sum);
+ checksum_str = udp_checksum(pd, offset, fd, uh);
+
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "UDP");
if (check_col(fd, COL_INFO))
- col_add_fstr(fd, COL_INFO, "Source port: %s Destination port: %s",
- get_udp_port(uh_sport), get_udp_port(uh_dport));
+ col_add_fstr(fd, COL_INFO, "Source port: %s Destination port: %s Checksum: %s",
+ get_udp_port(uh_sport), get_udp_port(uh_dport),
+ checksum_str
+ );
if (tree) {
ti = proto_tree_add_item(tree, proto_udp, offset, 8);
@@ -179,7 +205,7 @@
proto_tree_add_item(udp_tree, hf_udp_length, offset + 4, 2, uh_ulen);
proto_tree_add_uint_format(udp_tree, hf_udp_checksum, offset + 6, 2, uh_sum,
- "Checksum: 0x%04x", uh_sum);
+ "Checksum: 0x%04x (%s)", uh_sum, checksum_str);
}
/* Skip over header */
--
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and
the Ugly)."
- Matt Welsh
- Follow-Ups:
- Re: [ethereal-dev] Ethereal and UDP checksums..
- From: Guy Harris
- Re: [ethereal-dev] Ethereal and UDP checksums..
- Prev by Date: RE: [ethereal-dev] Ethereal-0.8.8 fails to build on win32
- Next by Date: [ethereal-dev] packet-giop.h
- Previous by thread: Re: [ethereal-dev] Request for change in wtap.h
- Next by thread: Re: [ethereal-dev] Ethereal and UDP checksums..
- Index(es):