From b284eda57b691db7384e128a78871ce98f99c159 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Thu, 4 Mar 2010 16:18:58 -0800 Subject: libnet_do_checksum(), despite being "internal", is used by external code. libnet needs to maintain backwards API compatibility, tcpsic from the isic package is an example of a binary failing when calling the new API with the old arguments. --- libnet/include/libnet/libnet-functions.h | 27 +++++++++++++++++++++++++-- libnet/src/libnet_checksum.c | 19 ++++++++++++++++++- libnet/src/libnet_pblock.c | 2 +- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/libnet/include/libnet/libnet-functions.h b/libnet/include/libnet/libnet-functions.h index 47efe08..3d81d43 100644 --- a/libnet/include/libnet/libnet-functions.h +++ b/libnet/include/libnet/libnet-functions.h @@ -2147,10 +2147,33 @@ int libnet_close_link(libnet_t *l); /* - * [Internal] + * [Internal] + * THIS FUNCTION IS BROKEN. IT WILL SEGFAULT OR CORRUPT MEMORY, OR JUST SILENTLY DO THE + * WRONG THING IF NOT CALLED CORRECTLY, AND CALLING IT CORRECTLY IS UNDOCUMENTED, AND + * ALMOST IMPOSSIBLE. YOU HAVE BEEN WARNED. + */ +int +libnet_do_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len); + +/* Calculate internet checksums. + * + * IP (TCP, UDP, IGMP, ICMP, etc...) checksums usually need information from + * the IP header to construct the "pseudo header", this function takes a + * pointer to that header, the buffer boundaries, the "h_len" (see pblock_t for + * a description, it is increasinly unused, though, and I'm trying to remove it + * altogether), and the protocol number for the protocol that is to be + * checksummed. + * + * Finding that protocol requires that the IP header be well-formed... so this + * won't work well for invalid packets. But then, what is the valid checksum + * for a valid packet, anyhow? + * + * This doesn't work well for non-inet checksums, sorry, that's an original design + * flaw. pblock_t needs a pointer in it, to a packet assembly function that can be + * called at runtime to do assembly and checksumming. */ int -libnet_do_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len, const uint8_t *beg, const uint8_t * end); +libnet_inet_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len, const uint8_t *beg, const uint8_t * end); /* * [Internal] diff --git a/libnet/src/libnet_checksum.c b/libnet/src/libnet_checksum.c index de1cda0..fcbde5b 100644 --- a/libnet/src/libnet_checksum.c +++ b/libnet/src/libnet_checksum.c @@ -141,6 +141,23 @@ static int check_ip_payload_size(libnet_t*l, const uint8_t *iphdr, int ip_hl, in return 0; } + +/* + * For backwards binary compatibility. The calculations done here can easily + * result in buffer overreads and overwrites. You have been warned. And no, it + * is not possible to fix, the API contains no information on the buffer's + * boundary. libnet itself calls the safe function, libnet_inet_checksum(). So + * should you. + */ +int +libnet_do_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len) +{ + return libnet_inet_checksum(l, iphdr, protocol, h_len, + iphdr, iphdr + LIBNET_IPV4_H + h_len + ); +} + + #define CHECK_IP_PAYLOAD_SIZE() do { \ int e=check_ip_payload_size(l,iphdr,ip_hl, h_len, end, __func__);\ if(e) return e;\ @@ -155,7 +172,7 @@ static int check_ip_payload_size(libnet_t*l, const uint8_t *iphdr, int ip_hl, in * len is the h_len from "q" */ int -libnet_do_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len, const uint8_t *beg, const uint8_t * end) +libnet_inet_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len, const uint8_t *beg, const uint8_t * end) { /* will need to update this for ipv6 at some point */ struct libnet_ipv4_hdr *iph_p = (struct libnet_ipv4_hdr *)iphdr; diff --git a/libnet/src/libnet_pblock.c b/libnet/src/libnet_pblock.c index 7218f21..0afb969 100644 --- a/libnet/src/libnet_pblock.c +++ b/libnet/src/libnet_pblock.c @@ -501,7 +501,7 @@ libnet_pblock_coalesce(libnet_t *l, uint8_t **packet, uint32_t *size) q->ptag, libnet_diag_dump_pblock_type(q->type), ip_offset); #endif - c = libnet_do_checksum(l, iph, + c = libnet_inet_checksum(l, iph, libnet_pblock_p2p(q->type), q->h_len, beg, end); if (c == -1) -- cgit v1.2.1