From 1b6fac96e7198d5e45b0d02a4ff37e31da80256d Mon Sep 17 00:00:00 2001 From: Fred Klassen Date: Mon, 22 Jan 2018 09:04:49 -0800 Subject: [PATCH] #406 fix zero-length IP headers --- docs/CHANGELOG | 1 + src/tcpedit/edit_packet.c | 17 ++++++++++++++++- src/tcpedit/edit_packet.h | 4 ++++ src/tcpedit/tcpedit.c | 10 ++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG b/docs/CHANGELOG index bd38a8314..89e2b7d9b 100644 --- a/docs/CHANGELOG +++ b/docs/CHANGELOG @@ -8,6 +8,7 @@ - heap-buffer-overflow in packet2tree (#409) - heap-buffer-overflow in get_l2len (#408) - heap-buffer-overflow in flow_decode (#407) + - Rewrite zero IP total length field to match the actual packet length (#406) - stack-buffer-overflow in tcpcapinfo (#405) 05/10/2017 Version 4.2.6 diff --git a/src/tcpedit/edit_packet.c b/src/tcpedit/edit_packet.c index ad7cc09de..6214ea6db 100644 --- a/src/tcpedit/edit_packet.c +++ b/src/tcpedit/edit_packet.c @@ -91,7 +91,7 @@ fix_ipv4_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, ipv4_hdr_t *i } /** - * Returns ipv6 header length wth all ipv6 options on success + * Returns ipv6 header length with all ipv6 options on success * -1 on error */ static int @@ -146,6 +146,21 @@ fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, ipv6_hdr_t *i return TCPEDIT_OK; } +/* + * #406 fix IP headers which may be not be set properly due to TCP segmentation + */ +void fix_ipv4_length(struct pcap_pkthdr *pkthdr, ipv4_hdr_t *ip_hdr) +{ + if (!ip_hdr->ip_len) + ip_hdr->ip_len = pkthdr->len; +} + +void fix_ipv6_length(struct pcap_pkthdr *pkthdr, ipv6_hdr_t *ip6_hdr) +{ + if (!ip6_hdr->ip_len) + ip6_hdr->ip_len = pkthdr->len; +} + static void ipv4_l34_csum_replace(uint8_t *data, uint8_t protocol, uint32_t old, uint32_t new) { diff --git a/src/tcpedit/edit_packet.h b/src/tcpedit/edit_packet.h index 769db7e69..3d086685a 100644 --- a/src/tcpedit/edit_packet.h +++ b/src/tcpedit/edit_packet.h @@ -42,6 +42,10 @@ int fix_ipv4_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkdhdr, int fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkdhdr, ipv6_hdr_t *ip_hdr); +void fix_ipv4_length(struct pcap_pkthdr *pkthdr, ipv4_hdr_t *ip_hdr); + +void fix_ipv6_length(struct pcap_pkthdr *pkthdr, ipv6_hdr_t *ip6_hdr); + int extract_data(tcpedit_t *tcpedit, const u_char *pktdata, int caplen, char *l7data[]); diff --git a/src/tcpedit/tcpedit.c b/src/tcpedit/tcpedit.c index 223a9e07c..b23fadbe1 100644 --- a/src/tcpedit/tcpedit.c +++ b/src/tcpedit/tcpedit.c @@ -292,6 +292,16 @@ tcpedit_packet(tcpedit_t *tcpedit, struct pcap_pkthdr **pkthdr, } } + /* + * fix IP packet lengths in case they are corrupted by TCP segmentation + * offload + */ + if (ip_hdr != NULL) { + fix_ipv4_length(*pkthdr, ip_hdr); + } else if (ip6_hdr != NULL) { + fix_ipv6_length(*pkthdr, ip6_hdr); + } + /* do we need to fix checksums? -- must always do this last! */ if ((tcpedit->fixcsum || needtorecalc)) { if (ip_hdr != NULL) {