From f1492d8e41dd38965d3ee87c14f7a19f4649ab54 Mon Sep 17 00:00:00 2001 From: Evgeny Khramtsov Date: Wed, 15 Dec 2021 20:54:42 +0300 Subject: [PATCH] capture: add support for IP-IP tunnel --- src/capture.c | 88 ++++++++++++++++++++++++++-------------------- tests/Makefile.am | 2 ++ tests/README | 3 +- tests/ipip.pcap | Bin 0 -> 3141 bytes tests/test_008.c | 2 +- tests/test_009.c | 2 +- tests/test_011.c | 43 ++++++++++++++++++++++ 7 files changed, 99 insertions(+), 41 deletions(-) create mode 100644 tests/ipip.pcap create mode 100644 tests/test_011.c diff --git a/src/capture.c b/src/capture.c index 1629d76..59748c7 100644 --- a/src/capture.c +++ b/src/capture.c @@ -485,57 +485,69 @@ capture_packet_reasm_ip(capture_info_t *capinfo, const struct pcap_pkthdr *heade } } - // Get IP header - ip4 = (struct ip *) (packet + link_hl); + while (*size >= sizeof(struct ip)) { + // Get IP header + ip4 = (struct ip *) (packet + link_hl); #ifdef USE_IPV6 - // Get IPv6 header - ip6 = (struct ip6_hdr *) (packet + link_hl); + // Get IPv6 header + ip6 = (struct ip6_hdr *) (packet + link_hl); #endif - // Get IP version - ip_ver = ip4->ip_v; + // Get IP version + ip_ver = ip4->ip_v; - switch (ip_ver) { - case 4: - ip_hl = ip4->ip_hl * 4; - ip_proto = ip4->ip_p; - ip_off = ntohs(ip4->ip_off); - ip_len = ntohs(ip4->ip_len); + switch (ip_ver) { + case 4: + ip_hl = ip4->ip_hl * 4; + ip_proto = ip4->ip_p; + ip_off = ntohs(ip4->ip_off); + ip_len = ntohs(ip4->ip_len); - ip_frag = ip_off & (IP_MF | IP_OFFMASK); - ip_frag_off = (ip_frag) ? (ip_off & IP_OFFMASK) * 8 : 0; - ip_id = ntohs(ip4->ip_id); + ip_frag = ip_off & (IP_MF | IP_OFFMASK); + ip_frag_off = (ip_frag) ? (ip_off & IP_OFFMASK) * 8 : 0; + ip_id = ntohs(ip4->ip_id); - inet_ntop(AF_INET, &ip4->ip_src, src.ip, sizeof(src.ip)); - inet_ntop(AF_INET, &ip4->ip_dst, dst.ip, sizeof(dst.ip)); - break; + inet_ntop(AF_INET, &ip4->ip_src, src.ip, sizeof(src.ip)); + inet_ntop(AF_INET, &ip4->ip_dst, dst.ip, sizeof(dst.ip)); + break; #ifdef USE_IPV6 - case 6: - ip_hl = sizeof(struct ip6_hdr); - ip_proto = ip6->ip6_nxt; - ip_len = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen) + ip_hl; + case 6: + ip_hl = sizeof(struct ip6_hdr); + ip_proto = ip6->ip6_nxt; + ip_len = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen) + ip_hl; - if (ip_proto == IPPROTO_FRAGMENT) { - struct ip6_frag *ip6f = (struct ip6_frag *) (ip6 + ip_hl); - ip_frag_off = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK); - ip_id = ntohl(ip6f->ip6f_ident); - } + if (ip_proto == IPPROTO_FRAGMENT) { + struct ip6_frag *ip6f = (struct ip6_frag *) (ip6 + ip_hl); + ip_frag_off = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK); + ip_id = ntohl(ip6f->ip6f_ident); + } - inet_ntop(AF_INET6, &ip6->ip6_src, src.ip, sizeof(src.ip)); - inet_ntop(AF_INET6, &ip6->ip6_dst, dst.ip, sizeof(dst.ip)); - break; + inet_ntop(AF_INET6, &ip6->ip6_src, src.ip, sizeof(src.ip)); + inet_ntop(AF_INET6, &ip6->ip6_dst, dst.ip, sizeof(dst.ip)); + break; #endif - default: - return NULL; + default: + return NULL; + } + + // Fixup VSS trailer in ethernet packets + *caplen = link_hl + ip_len; + + // Remove IP Header length from payload + *size = *caplen - link_hl - ip_hl; + + if (ip_proto == IPPROTO_IPIP) { + // The payload is an incapsulated IP packet (IP-IP tunnel) + // so we simply skip the "outer" IP header and repeat. + // NOTE: this will break IP reassembly if the "outer" + // packet is fragmented. + link_hl += ip_hl; + } else { + break; + } } - // Fixup VSS trailer in ethernet packets - *caplen = link_hl + ip_len; - - // Remove IP Header length from payload - *size = *caplen - link_hl - ip_hl; - // If no fragmentation if (ip_frag == 0) { // Just create a new packet with given network data diff --git a/tests/Makefile.am b/tests/Makefile.am index 84065bd..d5f6a0b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -2,6 +2,7 @@ AUTOMAKE_OPTIONS=subdir-objects check_PROGRAMS=test-001 test-002 test-003 test-004 test-005 check_PROGRAMS+=test-006 test-007 test-008 test-009 test-010 +check_PROGRAMS+=test-011 test_001_SOURCES=test_001.c test_002_SOURCES=test_002.c @@ -13,5 +14,6 @@ test_007_SOURCES=test_007.c ../src/vector.c ../src/util.c test_008_SOURCES=test_008.c test_009_SOURCES=test_009.c test_010_SOURCES=test_010.c ../src/hash.c +test_011_SOURCES=test_011.c TESTS = $(check_PROGRAMS) diff --git a/tests/README b/tests/README index 97dd0f9..c3b4fc2 100644 --- a/tests/README +++ b/tests/README @@ -1,6 +1,6 @@ Basic testing programs for sngrep. -This set of test will do some basic inputs to check sngrep screen navigation +This set of test will do some basic inputs to check sngrep screen navigation doesn't crash. This checks are ultra-super-basic. - test_001 : UI testing @@ -10,6 +10,7 @@ doesn't crash. This checks are ultra-super-basic. - test_005 : Column selection testing - test_006 : Message diff testing - test_007: Test vector container structures +- test_011: Test mix of normal packets with IPIP tunneled packets Sample capture files has been taken from wireshark Wiki: - https://wiki.wireshark.org/SampleCaptures diff --git a/tests/ipip.pcap b/tests/ipip.pcap new file mode 100644 index 0000000000000000000000000000000000000000..6bf3834d6cbf4af7f923e352079bbedf05a380d6 GIT binary patch literal 3141 zcmeH}O>7%Q6vsDFTB;SRsEULtBw!8|J*_=6`|Yq%8skK6lGaIFhj4-M?mFHO?{0TD zX&Mrs0&(b}0wEy|Z6POmD?&m-LP9EqOKDG(6SoK?khpS0@Yarp?Zd7q~SPZUKIFYY{piA=8B~(&0vAAxGdLhWy|>z zA~-{o3^B9}!BS4a1|F`0t5rAGjrxRKozzdwyfIT>v*#Mq0$=uX=%xEik4M{MNg0WZ z2>f{HHy-5m=F}s@FUN*9WUGtRVEyi_NnrsNXz^|IH5xyxRT~Spk>k^hQkyJ@hbc%G? zOsYtRp{oRAO;)J}fudqb?rfEukrjcDOi|!1^FUi{Vgz$EOtxaXK2k81D4H#ovL`Dg zgb^VG1~U-Rk&X-%{wHk-!RnY9#zBJxIgCpA>9biKbd~B&JkONQ&SmAqkcG`)W~~u} z9Ko;>Ij&b_o?UY+lMF-Cj@L|*c85uu?nK=gx8)4o58$k$35^<^CAD02#5~VgtD2sl znn+Jpf3oxHPD~K0J2jT?bT>zU&W3M0Chdw7G7>w>PEhwfM|4(Ule@i=lwpy;K6Emc zWN@#~-Z-VbPDTYYHL_45Np+DYAvgQ;zpwyb{QaTU4|$MtsIqLZ&a*k z3bH)baB>qQpB=B1YuY@uqQJSZ;8)%G^QI~A37|G64so~ox#rVC)5iAgSKs3jK=pr> zAnmDvXR`d@_rLLj-wi?E*3sJ>H*)yy?+LIHa9u16Z70CmymsjZK^uJmFUc&2&Sa*llw*aXM938a_*8%S*|w9h?NrCk{G zU`0=4rGx6GJAfz!6@yR(Cn%8>Mbn5u;JnL*jt!MaRHu>(%rQDh>0B85fReHtfD<{5 z6P!Nd_W{Sl9H{guXlhzfRLRhEfLKe?r`)2yL>Fde*X9?`xypKeKCCS@C4CPhEoTS0 zZ$Z+@vrp1r>_}QpN&3psADfc?vs=<1{Lz;5uN!SiU!@@F&)brw7^5?jPt<(i&G$sj zt?S`2)chBy`Jd-F?iVO0lV@)Q*>@KWCl%ydlid~Mr5h&-AI&5%zGClGkekQ * * Test for sorting columns based on standard attributes diff --git a/tests/test_009.c b/tests/test_009.c index c988c3a..0c71244 100644 --- a/tests/test_009.c +++ b/tests/test_009.c @@ -20,7 +20,7 @@ ** ****************************************************************************/ /** - * @file test_001.c + * @file test_009.c * @author Ivan Alonso [aka Kaian] * * Test for adding a new attribute column and sorting using it. diff --git a/tests/test_011.c b/tests/test_011.c new file mode 100644 index 0000000..becdd64 --- /dev/null +++ b/tests/test_011.c @@ -0,0 +1,43 @@ +/************************************************************************** + ** + ** sngrep - SIP Messages flow viewer + ** + ** Copyright (C) 2013-2018 Ivan Alonso (Kaian) + ** Copyright (C) 2013-2018 Irontec SL. All rights reserved. + ** + ** This program is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** This program is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + ** + ****************************************************************************/ +/** + * @file test_011.c + * @author Evgeny Khramtsov + * + * IP-IP tunnel test from ipip.pcap + */ + +const char keys[] = + { + /* Enter Call Flow */ + 10, + /* Leave Call Flow */ + 27, + /* Exit */ + 27, + 10, + 0 + }; + +#define TEST_PCAP_INPUT "ipip.pcap" + +#include "test_input.c"