Nmap Development mailing list archives
[PATCH] Consolidate TCP/UDP checksum code
From: Kris Katterjohn <katterjohn () gmail com>
Date: Sun, 10 Dec 2006 18:50:52 -0600
This adds a magic_tcpudp_cksum() function to handle the pseudo-header checksum stuff for TCP and UDP packets instead of doing the same thing 4 different times across multiple files/functions. Judging by tcpdump output, all checksums come out correct. It's a diff against 4.20 Thanks, Kris Katterjohn
--- x/osscan.cc 2006-12-07 21:01:19.000000000 -0600 +++ y/osscan.cc 2006-12-10 18:15:41.000000000 -0600 @@ -139,13 +139,6 @@ unsigned char *data = packet + 28; unsigned short realcheck; /* the REAL checksum */ int res; int decoy; -struct pseudo_udp_hdr { - struct in_addr source; - struct in_addr dest; - u8 zero; - u8 proto; - u16 length; -} *pseudo = (struct pseudo_udp_hdr *) ((char *)udp - 12) ; if (!patternbyte) patternbyte = (get_random_uint() % 60) + 65; memset(data, patternbyte, datalen); @@ -169,15 +162,9 @@ for(decoy=0; decoy < o.numdecoys; decoy+ udp->uh_dport = htons(dport); udp->uh_ulen = htons(8 + datalen); - /* Now the pseudo header for checksuming */ - pseudo->source.s_addr = source->s_addr; - pseudo->dest.s_addr = victim->s_addr; - pseudo->proto = IPPROTO_UDP; - pseudo->length = htons(sizeof(udphdr_bsd) + datalen); - /* OK, now we should be able to compute a valid checksum */ - realcheck = in_cksum((unsigned short *)pseudo, 20 /* pseudo + UDP headers */ + - datalen); + realcheck = magic_tcpudp_cksum(source, victim, IPPROTO_UDP, + sizeof(udphdr_bsd) + datalen, (char *) udp); #if STUPID_SOLARIS_CHECKSUM_BUG udp->uh_sum = sizeof(udphdr_bsd) + datalen; #else @@ -187,9 +174,6 @@ for(decoy=0; decoy < o.numdecoys; decoy+ if ( o.badsum ) udp->uh_sum++; - /* Goodbye, pseudo header! */ - memset(pseudo, 0, sizeof(*pseudo)); - /* Now for the ip header */ ip->ip_v = 4; ip->ip_hl = 5; --- x/osscan2.cc 2006-12-07 20:11:08.000000000 -0600 +++ y/osscan2.cc 2006-12-10 18:15:56.000000000 -0600 @@ -3009,13 +3009,6 @@ int send_closedudp_probe_2(struct udppro unsigned short realcheck; /* the REAL checksum */ int res; int decoy; - struct pseudo_udp_hdr { - struct in_addr source; - struct in_addr dest; - u8 zero; - u8 proto; - u16 length; - } *pseudo = (struct pseudo_udp_hdr *) ((char *)udp - 12) ; /* if (!patternbyte) patternbyte = (get_random_uint() % 60) + 65; */ memset(data, patternbyte, datalen); @@ -3043,24 +3036,15 @@ int send_closedudp_probe_2(struct udppro udp->uh_dport = htons(dport); udp->uh_ulen = htons(8 + datalen); - /* Now the psuedo header for checksuming */ - pseudo->source.s_addr = source->s_addr; - pseudo->dest.s_addr = victim->s_addr; - pseudo->proto = IPPROTO_UDP; - pseudo->length = htons(sizeof(udphdr_bsd) + datalen); - /* OK, now we should be able to compute a valid checksum */ - realcheck = in_cksum((unsigned short *)pseudo, 20 /* pseudo + UDP headers */ + - datalen); + realcheck = magic_tcpudp_cksum(source, victim, IPPROTO_UDP, + sizeof(udphdr_bsd) + datalen, (char *) udp); #if STUPID_SOLARIS_CHECKSUM_BUG udp->uh_sum = sizeof(udphdr_bsd) + datalen; #else udp->uh_sum = realcheck; #endif - /* Goodbye, pseudo header! */ - memset(pseudo, 0, sizeof(*pseudo)); - /* Now for the ip header */ ip->ip_v = 4; ip->ip_hl = 5; --- x/tcpip.cc 2006-12-07 21:01:19.000000000 -0600 +++ y/tcpip.cc 2006-12-10 18:21:00.000000000 -0600 @@ -957,6 +957,28 @@ answer = ~sum; /* ones-compleme return(answer); } +/* for computing TCP/UDP checksums, see TCP/IP Illustrated p. 145 */ +unsigned short magic_tcpudp_cksum(const struct in_addr *src, + const struct in_addr *dst, + u8 proto, u16 len, char *hstart) +{ + struct pseudo { + struct in_addr src; + struct in_addr dst; + u8 zero; + u8 proto; + u16 length; + } *hdr = (struct pseudo *) (hstart - sizeof(struct pseudo)); + + hdr->src = *src; + hdr->dst = *dst; + hdr->zero = 0; + hdr->proto = proto; + hdr->length = htons(len); + + return in_cksum((unsigned short *) hdr, len + sizeof(struct pseudo)); +} + /* LEGACY resolve() function that only supports IPv4 -- see IPv6 version above. Tries to resolve given hostname and stores result in ip . returns 0 if hostname cannot @@ -1098,21 +1120,11 @@ u8 *build_tcp_raw(const struct in_addr * u8 *tcpopt, int tcpoptlen, char *data, u16 datalen, u32 *outpacketlen) { -struct pseudo_header { - /*for computing TCP checksum, see TCP/IP Illustrated p. 145 */ - u32 s_addy; - u32 d_addr; - u8 zer0; - u8 protocol; - u16 length; -}; int packetlen = sizeof(struct ip) + ipoptlen + sizeof(struct tcphdr) + tcpoptlen + datalen; u8 *packet = (u8 *) safe_malloc(packetlen); struct ip *ip = (struct ip *) packet; struct tcphdr *tcp = (struct tcphdr *) ((u8*)ip + sizeof(struct ip) + ipoptlen); -struct pseudo_header *pseudo = - (struct pseudo_header *) ((u8*)tcp - sizeof(struct pseudo_header)); static int myttl = 0; assert(victim); @@ -1130,12 +1142,6 @@ if (ttl == -1) { myttl = ttl; } -pseudo->s_addy = source->s_addr; -pseudo->d_addr = victim->s_addr; -pseudo->zer0 = 0; -pseudo->protocol = IPPROTO_TCP; -pseudo->length = htons(sizeof(struct tcphdr) + tcpoptlen + datalen); - /* Fill tcp header */ memset(tcp, 0, sizeof(struct tcphdr)); tcp->th_sport = htons(sport); @@ -1174,8 +1180,9 @@ if (data && datalen) #if STUPID_SOLARIS_CHECKSUM_BUG tcp->th_sum = sizeof(struct tcphdr) + tcpoptlen + datalen; #else -tcp->th_sum = in_cksum((unsigned short *)pseudo, sizeof(struct tcphdr) + - tcpoptlen + sizeof(struct pseudo_header) + datalen); +tcp->th_sum = magic_tcpudp_cksum(source, victim, IPPROTO_TCP, + sizeof(struct tcphdr) + tcpoptlen + datalen, + (char *) tcp); #endif if ( o.badsum ) @@ -1583,15 +1590,6 @@ u8 *build_udp_raw(struct in_addr *source udphdr_bsd *udp = (udphdr_bsd *) ((u8*)ip + sizeof(struct ip) + ipoptlen); static int myttl = 0; - struct pseudo_udp_hdr { - struct in_addr source; - struct in_addr dest; - u8 zer0; - u8 proto; - u16 length; - } *pseudo = (struct pseudo_udp_hdr *) ((u8 *)udp - sizeof(struct pseudo_udp_hdr)); - - /* check that required fields are there and not too silly */ assert(victim); assert(source); @@ -1613,18 +1611,12 @@ u8 *build_udp_raw(struct in_addr *source if (data) memcpy((u8*)udp + sizeof(udphdr_bsd), data, datalen); - /* Now the pseudo header for checksuming */ - pseudo->source.s_addr = source->s_addr; - pseudo->dest.s_addr = victim->s_addr; - pseudo->zer0 = 0; - pseudo->proto = IPPROTO_UDP; - pseudo->length = htons(sizeof(udphdr_bsd) + datalen); - /* OK, now we should be able to compute a valid checksum */ #if STUPID_SOLARIS_CHECKSUM_BUG udp->uh_sum = sizeof(udphdr_bsd) + datalen; #else - udp->uh_sum = in_cksum((unsigned short *)pseudo, 20 /* pseudo + UDP headers */ + datalen); + udp->uh_sum = magic_tcpudp_cksum(source, victim, IPPROTO_UDP, + sizeof(udphdr_bsd) + datalen, (char *) udp); #endif if ( o.badsum ) --- x/tcpip.h 2006-11-20 01:56:52.000000000 -0600 +++ y/tcpip.h 2006-12-10 18:15:10.000000000 -0600 @@ -513,6 +513,10 @@ bool routethrough(const struct sockaddr_ unsigned short in_cksum(u16 *ptr,int nbytes); +unsigned short magic_tcpudp_cksum(const struct in_addr *src, + const struct in_addr *dst, + u8 proto, u16 len, char *hstart); + /* Build and send a raw tcp packet. If TTL is -1, a partially random (but likely large enough) one is chosen */ int send_tcp_raw( int sd, struct eth_nfo *eth,
_______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://SecLists.Org
Current thread:
- [PATCH] Consolidate TCP/UDP checksum code Kris Katterjohn (Dec 10)
- Re: [PATCH] Consolidate TCP/UDP checksum code Fyodor (Dec 11)