|
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
By Date
By Thread
Current thread:
- [PATCH] Consolidate TCP/UDP checksum code Kris Katterjohn (Dec 11)
|