mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-10-02 12:52:10 +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 */
|
#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 */
|
/* the new pbuf should be inserted before this */
|
||||||
next_pbuf = q;
|
next_pbuf = q;
|
||||||
if (iprh_prev != NULL) {
|
if (iprh_prev != NULL) {
|
||||||
@ -658,6 +671,7 @@ ip6_reass(struct pbuf *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the pbuf chain */
|
/* Return the pbuf chain */
|
||||||
|
MIB2_STATS_INC(mib2.ip6reasmoks);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
/* the datagram is not (yet?) reassembled completely */
|
/* the datagram is not (yet?) reassembled completely */
|
||||||
|
@ -122,7 +122,7 @@ struct stats_sys {
|
|||||||
|
|
||||||
/** SNMP MIB2 stats */
|
/** SNMP MIB2 stats */
|
||||||
struct stats_mib2 {
|
struct stats_mib2 {
|
||||||
/* IP */
|
/* IPv4 */
|
||||||
u32_t ipinhdrerrors;
|
u32_t ipinhdrerrors;
|
||||||
u32_t ipinaddrerrors;
|
u32_t ipinaddrerrors;
|
||||||
u32_t ipinunknownprotos;
|
u32_t ipinunknownprotos;
|
||||||
@ -140,6 +140,9 @@ struct stats_mib2 {
|
|||||||
u32_t ipforwdatagrams;
|
u32_t ipforwdatagrams;
|
||||||
u32_t ipinreceives;
|
u32_t ipinreceives;
|
||||||
|
|
||||||
|
/* IPv6 */
|
||||||
|
u32_t ip6reasmoks;
|
||||||
|
|
||||||
/* TCP */
|
/* TCP */
|
||||||
u32_t tcpactiveopens;
|
u32_t tcpactiveopens;
|
||||||
u32_t tcppassiveopens;
|
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 */
|
/* Setups/teardown functions */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -432,6 +476,50 @@ START_TEST(test_ip6_frag)
|
|||||||
}
|
}
|
||||||
END_TEST
|
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 */
|
/** Create the suite including all tests for this module */
|
||||||
Suite *
|
Suite *
|
||||||
ip6_suite(void)
|
ip6_suite(void)
|
||||||
@ -444,7 +532,8 @@ ip6_suite(void)
|
|||||||
TESTFUNC(test_ip6_lladdr),
|
TESTFUNC(test_ip6_lladdr),
|
||||||
TESTFUNC(test_ip6_dest_unreachable_chained_pbuf),
|
TESTFUNC(test_ip6_dest_unreachable_chained_pbuf),
|
||||||
TESTFUNC(test_ip6_frag_pbuf_len_assert),
|
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);
|
return create_suite("IPv6", tests, sizeof(tests)/sizeof(testfunc), ip6_setup, ip6_teardown);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user