mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-04 14:29:39 +00:00
ipv6 reassembly: fix detecting holes in reassembled packets
Added unit test for reassembly. See bug #64767
This commit is contained in:
parent
16e8ef3145
commit
c8f42025ce
@ -447,6 +447,19 @@ ip6_reass(struct pbuf *p)
|
||||
}
|
||||
}
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
/* Check if the fragments received so far have no gaps. */
|
||||
if (iprh_prev != NULL) {
|
||||
if (iprh_prev->end != start) {
|
||||
/* There is a fragment missing between the current
|
||||
* and the previous fragment */
|
||||
valid = 0;
|
||||
}
|
||||
}
|
||||
if (end != iprh_tmp->start) {
|
||||
/* There is a fragment missing between the current
|
||||
* and the following fragment */
|
||||
valid = 0;
|
||||
}
|
||||
/* the new pbuf should be inserted before this */
|
||||
next_pbuf = q;
|
||||
if (iprh_prev != NULL) {
|
||||
@ -658,6 +671,7 @@ ip6_reass(struct pbuf *p)
|
||||
}
|
||||
|
||||
/* Return the pbuf chain */
|
||||
MIB2_STATS_INC(mib2.ip6reasmoks);
|
||||
return p;
|
||||
}
|
||||
/* the datagram is not (yet?) reassembled completely */
|
||||
|
@ -122,7 +122,7 @@ struct stats_sys {
|
||||
|
||||
/** SNMP MIB2 stats */
|
||||
struct stats_mib2 {
|
||||
/* IP */
|
||||
/* IPv4 */
|
||||
u32_t ipinhdrerrors;
|
||||
u32_t ipinaddrerrors;
|
||||
u32_t ipinunknownprotos;
|
||||
@ -140,6 +140,9 @@ struct stats_mib2 {
|
||||
u32_t ipforwdatagrams;
|
||||
u32_t ipinreceives;
|
||||
|
||||
/* IPv6 */
|
||||
u32_t ip6reasmoks;
|
||||
|
||||
/* TCP */
|
||||
u32_t tcpactiveopens;
|
||||
u32_t tcppassiveopens;
|
||||
|
@ -66,6 +66,50 @@ ip6_test_handle_timers(int count)
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper functions */
|
||||
static void
|
||||
create_ip6_input_fragment(u32_t ip_id, u16_t start, u16_t len, int last, u8_t next_hdr)
|
||||
{
|
||||
struct pbuf* p;
|
||||
struct netif* input_netif = netif_list; /* just use any netif */
|
||||
fail_unless((start & 7) == 0);
|
||||
fail_unless(((len & 7) == 0) || last);
|
||||
fail_unless(input_netif != NULL);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip6_frag_hdr) +
|
||||
sizeof(struct ip6_hdr), PBUF_RAM);
|
||||
fail_unless(p != NULL);
|
||||
if (p != NULL) {
|
||||
err_t err;
|
||||
struct ip6_frag_hdr* fraghdr;
|
||||
|
||||
struct ip6_hdr* ip6hdr = (struct ip6_hdr*)p->payload;
|
||||
IP6H_VTCFL_SET(ip6hdr, 6, 0, 0);
|
||||
IP6H_PLEN_SET(ip6hdr, len + sizeof(struct ip6_frag_hdr));
|
||||
IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
|
||||
IP6H_HOPLIM_SET(ip6hdr, 64);
|
||||
ip6_addr_copy_to_packed(ip6hdr->src, *netif_ip6_addr(input_netif, 0));
|
||||
ip6hdr->src.addr[3]++;
|
||||
ip6_addr_copy_to_packed(ip6hdr->dest, *netif_ip6_addr(input_netif, 0));
|
||||
|
||||
fraghdr = (struct ip6_frag_hdr*)(ip6hdr + 1);
|
||||
fraghdr->_nexth = next_hdr;
|
||||
fraghdr->reserved = 0;
|
||||
if (last) {
|
||||
fraghdr->_fragment_offset = htons(start & ~7);
|
||||
} else {
|
||||
fraghdr->_fragment_offset = htons((start & ~7) | 1);
|
||||
}
|
||||
fraghdr->_identification = htonl(ip_id);
|
||||
|
||||
err = ip6_input(p, input_netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
fail_unless(err == ERR_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
@ -432,6 +476,50 @@ START_TEST(test_ip6_frag)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void test_ip6_reass_helper(u32_t ip_id, const u16_t *segments, size_t num_segs, u16_t seglen)
|
||||
{
|
||||
ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
|
||||
size_t i;
|
||||
|
||||
memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2));
|
||||
memset(&lwip_stats.ip6_frag, 0, sizeof(lwip_stats.ip6_frag));
|
||||
|
||||
netif_set_up(&test_netif6);
|
||||
netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
|
||||
netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
|
||||
|
||||
for (i = 0; i < num_segs; i++) {
|
||||
u16_t seg = segments[i];
|
||||
int last = seg + 1U == num_segs;
|
||||
create_ip6_input_fragment(ip_id, seg * seglen, seglen, last, IP6_NEXTH_UDP);
|
||||
fail_unless(lwip_stats.ip6_frag.recv == i + 1);
|
||||
fail_unless(lwip_stats.ip6_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip6_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip6_frag.drop == 0);
|
||||
if (i + 1 == num_segs) {
|
||||
fail_unless(lwip_stats.mib2.ip6reasmoks == 1);
|
||||
}
|
||||
else {
|
||||
fail_unless(lwip_stats.mib2.ip6reasmoks == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(test_ip6_reass)
|
||||
{
|
||||
#define NUM_SEGS 9
|
||||
const u16_t t1[NUM_SEGS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
const u16_t t2[NUM_SEGS] = { 8, 0, 1, 2, 3, 4, 7, 6, 5 };
|
||||
const u16_t t3[NUM_SEGS] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
|
||||
const u16_t t4[NUM_SEGS] = { 8, 2, 4, 6, 7, 5, 3, 1, 0 };
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
test_ip6_reass_helper(128, t1, NUM_SEGS, 200);
|
||||
test_ip6_reass_helper(129, t2, NUM_SEGS, 208);
|
||||
test_ip6_reass_helper(130, t3, NUM_SEGS, 8);
|
||||
test_ip6_reass_helper(130, t4, NUM_SEGS, 1448);
|
||||
}
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
ip6_suite(void)
|
||||
@ -444,7 +532,8 @@ ip6_suite(void)
|
||||
TESTFUNC(test_ip6_lladdr),
|
||||
TESTFUNC(test_ip6_dest_unreachable_chained_pbuf),
|
||||
TESTFUNC(test_ip6_frag_pbuf_len_assert),
|
||||
TESTFUNC(test_ip6_frag)
|
||||
TESTFUNC(test_ip6_frag),
|
||||
TESTFUNC(test_ip6_reass)
|
||||
};
|
||||
return create_suite("IPv6", tests, sizeof(tests)/sizeof(testfunc), ip6_setup, ip6_teardown);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user