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):