ongrep

A cleaned up fork of ngrep for OpenBSD
git clone git://git.sgregoratto.me/ongrep
Log | Files | Refs | README | LICENSE

commit f1d305208cc08c9940c3f28dfb24bf3843bbbe59
parent ec41323bd1f9a1356c72cf32dd766b1656bc1729
Author: Jordan Ritter <jpr5@darkridge.com>
Date:   Mon, 11 Sep 2006 09:04:13 +0000

fix bug #1543011: incorrect calculation of when snaplen truncates
within packet headers, leading to len overflow and garbage input into
the pattern matcher, behaviour undefined.  rewrote logic to center
around pcap_pkthdr->caplen, yielding bugfix + performance improvement
and code simplification.

in parallel fixes a previously undiscovered bug in ipv6 support:
incorrect calculation of ipv6 header size due to misplacement of
parenthesis (ntohs() input).

Diffstat:
Mngrep.c | 76+++++++++++++++++++++++++++-------------------------------------------------
1 file changed, 27 insertions(+), 49 deletions(-)

diff --git a/ngrep.c b/ngrep.c @@ -678,24 +678,15 @@ void process(u_char *d, struct pcap_pkthdr *h, u_char *p) { uint16_t tcphdr_offset = (frag_offset) ? 0 : (tcp->th_off * 4); data = ((unsigned char *)tcp) + tcphdr_offset; - - switch (ip_ver) { - case 4: { - if ((len = ntohs(ip_packet->ip_len)) < h->caplen) - len -= ip_hl + tcphdr_offset; - else - len = h->caplen - link_offset - ip_hl - tcphdr_offset; - } break; + len = h->caplen - (link_offset + ip_hl + tcphdr_offset); #if USE_IPv6 - case 6: { - if ((len = ntohs(ip6_packet->ip6_plen + ip_hl)) < h->caplen) - len -= ip_hl + tcphdr_offset; - else - len = h->caplen - link_offset - ip_hl - tcphdr_offset; - } break; + if (ip_ver == 6) + len -= ntohs(ip6_packet->ip6_plen); #endif - } + + if ((int32_t)len < 0) + len = 0; dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst, ntohs(tcp->th_sport), ntohs(tcp->th_dport), tcp->th_flags, @@ -707,24 +698,15 @@ void process(u_char *d, struct pcap_pkthdr *h, u_char *p) { uint16_t udphdr_offset = (frag_offset) ? 0 : sizeof(struct udphdr); data = ((unsigned char *)udp) + udphdr_offset; - - switch (ip_ver) { - case 4: { - if ((len = ntohs(ip_packet->ip_len)) < h->caplen) - len -= ip_hl + udphdr_offset; - else - len = h->caplen - link_offset - ip_hl - udphdr_offset; - } break; + len = h->caplen - (link_offset + ip_hl + udphdr_offset); #if USE_IPv6 - case 6: { - if ((len = ntohs(ip6_packet->ip6_plen + ip_hl)) < h->caplen) - len -= ip_hl + udphdr_offset; - else - len = h->caplen - link_offset - ip_hl - udphdr_offset; - } break; + if (ip_ver == 6) + len -= ntohs(ip6_packet->ip6_plen); #endif - } + + if ((int32_t)len < 0) + len = 0; dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst, #if HAVE_DUMB_UDPHDR @@ -740,11 +722,10 @@ void process(u_char *d, struct pcap_pkthdr *h, u_char *p) { uint16_t icmphdr_offset = (frag_offset) ? 0 : 4; data = ((unsigned char *)ic4) + icmphdr_offset; + len = h->caplen - (link_offset + ip_hl + icmphdr_offset); - if ((len = ntohs(ip_packet->ip_len)) < h->caplen) - len -= ip_hl + icmphdr_offset; - else - len = h->caplen - link_offset - ip_hl - icmphdr_offset; + if ((int32_t)len < 0) + len = 0; dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst, ic4->icmp_type, ic4->icmp_code, 0, @@ -754,18 +735,17 @@ void process(u_char *d, struct pcap_pkthdr *h, u_char *p) { #if USE_IPv6 case IPPROTO_ICMPV6: { struct icmp6_hdr *ic6 = (struct icmp6_hdr *)(((unsigned char *)ip6_packet) + ip_hl); - uint16_t icmphdr_offset = (frag_offset) ? 0 : 4; + uint16_t icmp6hdr_offset = (frag_offset) ? 0 : 4; - data = ((unsigned char *)ic6) + icmphdr_offset; + data = ((unsigned char *)ic6) + icmp6hdr_offset; + len = h->caplen - (link_offset + ip_hl + ntohs(ip6_packet->ip6_plen) + icmp6hdr_offset); - if ((len = ntohs(ip6_packet->ip6_plen + ip_hl)) < h->caplen) - len -= ip_hl + icmphdr_offset; - else - len = h->caplen - link_offset - ip_hl - icmphdr_offset; + if ((int32_t)len < 0) + len = 0; dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst, ic6->icmp6_type, ic6->icmp6_code, 0, - icmphdr_offset, fragmented, frag_offset, frag_id); + icmp6hdr_offset, fragmented, frag_offset, frag_id); } break; #endif @@ -774,11 +754,10 @@ void process(u_char *d, struct pcap_pkthdr *h, u_char *p) { uint16_t igmphdr_offset = (frag_offset) ? 0 : 4; data = ((unsigned char *)ig) + igmphdr_offset; + len = h->caplen - (link_offset + ip_hl + igmphdr_offset); - if ((len = ntohs(ip_packet->ip_len)) < h->caplen) - len -= ip_hl + igmphdr_offset; - else - len = h->caplen - link_offset - ip_hl - igmphdr_offset; + if ((int32_t)len < 0) + len = 0; dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst, ig->igmp_type, ig->igmp_code, 0, @@ -787,11 +766,10 @@ void process(u_char *d, struct pcap_pkthdr *h, u_char *p) { default: { data = (((unsigned char *)ip_packet) + ip_hl); + len = h->caplen - (link_offset + ip_hl); - if ((len = ntohs(ip_packet->ip_len)) < h->caplen) - len -= ip_hl; - else - len = h->caplen - link_offset - ip_hl; + if ((int32_t)len < 0) + len = 0; dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst, 0, 0, 0,