From 3fafe4f9adbbfa91fbff1f588391a80b6443707e Mon Sep 17 00:00:00 2001 From: Ravi kumar Veeramally Date: Thu, 19 Jul 2018 15:21:25 +0300 Subject: [PATCH] net: ipv6: Handle large IPv6 packets properly Current implementation does not handle large extension headers (e.g HBHO). Which resulted network stack crashes or due to misinterpretation of lengths network packets are dropped. Also caused issues while preparing IPv6 packet (e.g. large HBHO header with IPv6 fragmentation support). Issues fixed and provided more unit tests. Signed-off-by: Ravi kumar Veeramally --- include/net/net_pkt.h | 54 +- subsys/net/ip/ipv6.c | 618 ++++++++---------- subsys/net/ip/net_pkt.c | 152 ++++- subsys/net/lib/http/http_server.c | 26 +- tests/net/ipv6/src/main.c | 315 ++++++++++ tests/net/ipv6_fragment/src/main.c | 970 ++++++++++++++++++++++++++++- tests/net/net_pkt/src/main.c | 198 ++++-- 7 files changed, 1854 insertions(+), 479 deletions(-) diff --git a/include/net/net_pkt.h b/include/net/net_pkt.h index 2d095fd4f7f..bff99d0394f 100644 --- a/include/net/net_pkt.h +++ b/include/net/net_pkt.h @@ -128,7 +128,7 @@ struct net_pkt { }; #if defined(CONFIG_NET_IPV6) - u8_t ipv6_ext_len; /* length of extension headers */ + u16_t ipv6_ext_len; /* length of extension headers */ u8_t ipv6_ext_opt_len; /* IPv6 ND option length */ /* Where is the start of the last header before payload data @@ -141,7 +141,7 @@ struct net_pkt { #if defined(CONFIG_NET_IPV6_FRAGMENT) u16_t ipv6_fragment_offset; /* Fragment offset of this packet */ u32_t ipv6_fragment_id; /* Fragment id */ - u8_t *ipv6_frag_hdr_start; /* Where starts the fragment header */ + u16_t ipv6_frag_hdr_start; /* Where starts the fragment header */ #endif /* CONFIG_NET_IPV6_FRAGMENT */ #endif /* CONFIG_NET_IPV6 */ @@ -343,12 +343,12 @@ static inline void net_pkt_set_ipv6_ext_opt_len(struct net_pkt *pkt, pkt->ipv6_ext_opt_len = len; } -static inline u8_t net_pkt_ipv6_ext_len(struct net_pkt *pkt) +static inline u16_t net_pkt_ipv6_ext_len(struct net_pkt *pkt) { return pkt->ipv6_ext_len; } -static inline void net_pkt_set_ipv6_ext_len(struct net_pkt *pkt, u8_t len) +static inline void net_pkt_set_ipv6_ext_len(struct net_pkt *pkt, u16_t len) { pkt->ipv6_ext_len = len; } @@ -376,13 +376,13 @@ static inline void net_pkt_set_ipv6_hop_limit(struct net_pkt *pkt, } #if defined(CONFIG_NET_IPV6_FRAGMENT) -static inline u8_t *net_pkt_ipv6_fragment_start(struct net_pkt *pkt) +static inline u16_t net_pkt_ipv6_fragment_start(struct net_pkt *pkt) { return pkt->ipv6_frag_hdr_start; } static inline void net_pkt_set_ipv6_fragment_start(struct net_pkt *pkt, - u8_t *start) + u16_t start) { pkt->ipv6_frag_hdr_start = start; } @@ -1523,23 +1523,17 @@ static inline bool net_pkt_insert_be32(struct net_pkt *pkt, } /** - * @brief Split a fragment to two parts at arbitrary offset. + * @brief Split a fragment into two parts at arbitrary offset. * - * @details This will generate two new fragments (fragA and fragB) from - * one (orig_frag). The original fragment is not modified but two new - * fragments are allocated and returned to the caller. The original fragment - * must be part of the packet pointed by the pkt parameter. If the len parameter - * is larger than the amount of data in the orig fragment, then the fragA will - * contain all the data and fragB will be empty. + * @details This will split packet into two parts. Original packet will be + * modified. Offset is relative position with input fragment. Input fragment + * contains first part of the split. Rest of the fragment chain is in "rest" + * parameter provided by caller. * * @param pkt Network packet - * @param orig_frag Original network buffer fragment which is to be split. - * @param len Amount of data in the first returned fragment. - * @param fragA A fragment is returned. This will contain len bytes that - * are copied from start of orig_frag. - * @param fragB Another fragment is returned. This will contain remaining - * bytes (orig_frag->len - len) from the orig_frag or NULL if all the data - * was copied into fragA. + * @param frag Original network buffer fragment which is to be split. + * @param offset Offset relative to input fragment. + * @param rest Rest of the fragment chain after split. * @param timeout Affects the action taken should the net buf pool be empty. * If K_NO_WAIT, then return immediately. If K_FOREVER, then wait as long as * necessary. Otherwise, wait up to the specified number of milliseconds before @@ -1547,9 +1541,23 @@ static inline bool net_pkt_insert_be32(struct net_pkt *pkt, * * @return 0 on success, <0 otherwise. */ -int net_pkt_split(struct net_pkt *pkt, struct net_buf *orig_frag, - u16_t len, struct net_buf **fragA, - struct net_buf **fragB, s32_t timeout); +int net_pkt_split(struct net_pkt *pkt, struct net_buf *frag, u16_t offset, + struct net_buf **rest, s32_t timeout); + +/** + * @brief Remove data from the packet at arbitrary offset. + * + * @details This will remove the data from arbitrary offset. Original packet + * will be modified. + * + * @param pkt Network packet + * @param offset Arbitrary offset to packet + * @param len Number of bytes to be removed + * + * @return 0 on success, <0 otherwise + * + */ +int net_pkt_pull(struct net_pkt *pkt, u16_t offset, u16_t len); /** * @brief Return the fragment and offset within it according to network diff --git a/subsys/net/ip/ipv6.c b/subsys/net/ip/ipv6.c index e9fca4fcd72..e9abe069530 100644 --- a/subsys/net/ip/ipv6.c +++ b/subsys/net/ip/ipv6.c @@ -601,90 +601,126 @@ const char *net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state) int net_ipv6_find_last_ext_hdr(struct net_pkt *pkt, u16_t *next_hdr_idx, u16_t *last_hdr_idx) { - struct net_ipv6_hdr *hdr = NET_IPV6_HDR(pkt); - struct net_buf *frag = pkt->frags; - int pos = 0; - u16_t offset, prev, tmp; + struct net_buf *next_hdr_frag; + struct net_buf *last_hdr_frag; + struct net_buf *frag; + u16_t pkt_offset; + u16_t offset; + u16_t length; u8_t next_hdr; - u8_t length; u8_t next; - next = hdr->nexthdr; + if (!pkt || !pkt->frags || !next_hdr_idx || !last_hdr_idx) { + return -EINVAL; + } + + next = NET_IPV6_HDR(pkt)->nexthdr; /* Initial value if no extension fragments are found */ *next_hdr_idx = 6; - - offset = *last_hdr_idx = sizeof(struct net_ipv6_hdr); + *last_hdr_idx = sizeof(struct net_ipv6_hdr); /* First check the simplest case where there is no extension headers * in the packet. There cannot be any extensions after the normal or * typical IP protocols */ if (next == IPPROTO_ICMPV6 || next == IPPROTO_UDP || - next == IPPROTO_TCP) { + next == IPPROTO_TCP || next == NET_IPV6_NEXTHDR_NONE) { return 0; } - prev = pos; + frag = pkt->frags; + offset = *last_hdr_idx; + *next_hdr_idx = *last_hdr_idx; + next_hdr_frag = last_hdr_frag = frag; while (frag) { frag = net_frag_read_u8(frag, offset, &offset, &next_hdr); - if (!frag && offset == 0xffff) { + if (!frag) { goto fail; } - frag = net_frag_read_u8(frag, offset, &offset, &length); - if (!frag && offset == 0xffff) { - goto fail; - } - - length = length * 8 + 8; - - /* TODO: Add here more IPv6 extension headers to check */ switch (next) { - case NET_IPV6_NEXTHDR_NONE: - *next_hdr_idx = prev; - *last_hdr_idx = offset - 2; - goto out; - case NET_IPV6_NEXTHDR_FRAG: - prev = pos; - pos = offset - 2; - offset += 2 + 4; + frag = net_frag_skip(frag, offset, &offset, 7); + if (!frag) { + goto fail; + } + break; case NET_IPV6_NEXTHDR_HBHO: - prev = pos; - pos = offset - 2; - offset += length - 2; + length = 0; + frag = net_frag_read_u8(frag, offset, &offset, + (u8_t *)&length); + if (!frag) { + goto fail; + } + + length = length * 8 + 8; + + frag = net_frag_skip(frag, offset, &offset, length - 2); + if (!frag) { + goto fail; + } + break; + case NET_IPV6_NEXTHDR_NONE: case IPPROTO_ICMPV6: case IPPROTO_UDP: case IPPROTO_TCP: - prev = pos; - pos = *next_hdr_idx = offset - 2; goto out; default: + /* TODO: Add more IPv6 extension headers to check */ goto fail; } - /* Get the next header value */ - frag = net_frag_read_u8(frag, pos, &tmp, &next); - if (!frag && pos == 0xffff) { - goto fail; - } + *next_hdr_idx = *last_hdr_idx; + next_hdr_frag = last_hdr_frag; + + *last_hdr_idx = offset; + last_hdr_frag = frag; + + next = next_hdr; } -out: - *next_hdr_idx = prev; - *last_hdr_idx = offset - 2; - - return 0; - fail: return -EINVAL; + +out: + /* Current next_hdr_idx offset is based on respective fragment, but we + * need to calculate next_hdr_idx offset based on whole packet. + */ + pkt_offset = 0; + frag = pkt->frags; + while (frag) { + if (next_hdr_frag == frag) { + *next_hdr_idx += pkt_offset; + break; + } + + pkt_offset += frag->len; + frag = frag->frags; + } + + /* Current last_hdr_idx offset is based on respective fragment, but we + * need to calculate last_hdr_idx offset based on whole packet. + */ + pkt_offset = 0; + frag = pkt->frags; + while (frag) { + if (last_hdr_frag == frag) { + *last_hdr_idx += pkt_offset; + break; + } + + pkt_offset += frag->len; + frag = frag->frags; + } + + return 0; } const struct in6_addr *net_ipv6_unspecified_address(void) @@ -3187,6 +3223,7 @@ static void reassemble_packet(struct net_ipv6_reassembly *reass) { struct net_pkt *pkt; struct net_buf *last; + struct net_buf *frag; u8_t next_hdr; int i, len, ret; u16_t pos; @@ -3202,6 +3239,7 @@ static void reassemble_packet(struct net_ipv6_reassembly *reass) */ for (i = 1; i < NET_IPV6_FRAGMENTS_MAX_PKT; i++) { int removed_len; + int ret; pkt = reass->pkt[i]; @@ -3209,16 +3247,16 @@ static void reassemble_packet(struct net_ipv6_reassembly *reass) * the beginning of the fragment. */ removed_len = net_pkt_ipv6_fragment_start(pkt) + - sizeof(struct net_ipv6_frag_hdr) - - pkt->frags->data; + sizeof(struct net_ipv6_frag_hdr); NET_DBG("Removing %d bytes from start of pkt %p", removed_len, pkt->frags); - NET_ASSERT(removed_len >= (sizeof(struct net_ipv6_hdr) + - sizeof(struct net_ipv6_frag_hdr))); - - net_buf_pull(pkt->frags, removed_len); + ret = net_pkt_pull(pkt, 0, removed_len); + if (ret) { + NET_ERR("Failed to pull headers"); + NET_ASSERT(ret != 0); + } /* Attach the data to previous pkt */ last->frags = pkt->frags; @@ -3237,24 +3275,24 @@ static void reassemble_packet(struct net_ipv6_reassembly *reass) * and set the various pointers and values in packet. */ - next_hdr = net_pkt_ipv6_fragment_start(pkt)[0]; + frag = net_frag_read_u8(pkt->frags, net_pkt_ipv6_fragment_start(pkt), + &pos, &next_hdr); + if (!frag && pos == 0xFFFF) { + NET_ERR("Failed to read next header"); + NET_ASSERT(frag); + } - /* How much data we need to move in order to get rid of the - * fragmentation header. - */ - len = pkt->frags->len - sizeof(struct net_ipv6_frag_hdr) - - (net_pkt_ipv6_fragment_start(pkt) - pkt->frags->data); - - memmove(net_pkt_ipv6_fragment_start(pkt), - net_pkt_ipv6_fragment_start(pkt) + - sizeof(struct net_ipv6_frag_hdr), len); + ret = net_pkt_pull(pkt, net_pkt_ipv6_fragment_start(pkt), + sizeof(struct net_ipv6_frag_hdr)); + if (ret) { + NET_ERR("Failed to pull fragmentation header"); + NET_ASSERT(ret); + } /* This one updates the previous header's nexthdr value */ net_pkt_write_u8(pkt, pkt->frags, net_pkt_ipv6_hdr_prev(pkt), &pos, next_hdr); - pkt->frags->len -= sizeof(struct net_ipv6_frag_hdr); - if (!net_pkt_compact(pkt)) { NET_ERR("Cannot compact reassembly packet %p", pkt); net_pkt_unref(pkt); @@ -3367,14 +3405,14 @@ static int shift_packets(struct net_ipv6_reassembly *reass, int pos) static enum net_verdict handle_fragment_hdr(struct net_pkt *pkt, struct net_buf *frag, int total_len, - u16_t buf_offset) + u16_t buf_offset, + u16_t *loc, + u8_t nexthdr) { struct net_ipv6_reassembly *reass = NULL; u32_t id; - u16_t loc; u16_t offset; u16_t flag; - u8_t nexthdr; u8_t more; bool found; int i; @@ -3391,14 +3429,11 @@ static enum net_verdict handle_fragment_hdr(struct net_pkt *pkt, reassembly_init_done = true; } - net_pkt_set_ipv6_fragment_start(pkt, frag->data + buf_offset); - /* Each fragment has a fragment header. */ - frag = net_frag_read_u8(frag, buf_offset, &loc, &nexthdr); - frag = net_frag_skip(frag, loc, &loc, 1); /* reserved */ - frag = net_frag_read_be16(frag, loc, &loc, &flag); - frag = net_frag_read_be32(frag, loc, &loc, &id); - if (!frag && loc == 0xffff) { + frag = net_frag_skip(frag, buf_offset, loc, 1); /* reserved */ + frag = net_frag_read_be16(frag, *loc, loc, &flag); + frag = net_frag_read_be32(frag, *loc, loc, &id); + if (!frag && *loc == 0xffff) { goto drop; } @@ -3510,131 +3545,45 @@ drop: return NET_DROP; } -static int get_next_hdr(struct net_pkt *pkt, u16_t *next_hdr_idx, - u16_t *last_hdr_idx, u8_t *next_hdr) -{ - struct net_buf *buf; - u16_t pos; - int ret; - - /* We need to fix the next header value so find out where - * is the last IPv6 extension header. The next_hdr_idx value is - * offset from the start of the 1st fragment, it is not the - * actual next header value. - */ - ret = net_ipv6_find_last_ext_hdr(pkt, next_hdr_idx, last_hdr_idx); - if (ret < 0) { - NET_DBG("Cannot find the last IPv6 ext header"); - return ret; - } - - /* The IPv6 must fit into first fragment, otherwise the next read - * will fail. - */ - if (*next_hdr_idx > pkt->frags->len) { - NET_DBG("IPv6 header too short (%d vs %d)", *next_hdr_idx, - pkt->frags->len); - return -EINVAL; - } - - if (*last_hdr_idx > pkt->frags->len) { - NET_DBG("IPv6 header too short (%d vs %d)", *last_hdr_idx, - pkt->frags->len); - return -EINVAL; - } - - buf = net_frag_read_u8(pkt->frags, *next_hdr_idx, &pos, next_hdr); - if (!buf && pos == 0xffff) { - NET_DBG("Next header too far (%d vs %d)", *next_hdr_idx, - pkt->frags->len); - return -EINVAL; - } - - return 0; -} +#define BUF_ALLOC_TIMEOUT K_MSEC(100) static int send_ipv6_fragment(struct net_if *iface, struct net_pkt *pkt, - struct net_buf *orig, - struct net_buf *prev, - struct net_buf *frag, - u16_t ipv6_len, - u16_t offset, - int len, + struct net_buf **rest, + u16_t ipv6_hdrs_len, + u16_t fit_len, + u16_t frag_offset, u8_t next_hdr, u16_t next_hdr_idx, + u8_t last_hdr, u16_t last_hdr_idx, - bool final, - int frag_count) + u16_t frag_count) { - struct net_buf *rest = NULL, *end = NULL, *orig_copy = NULL; + struct net_pkt *ipv6 = NULL; + bool final; struct net_ipv6_frag_hdr hdr; - struct net_pkt *ipv6; + struct net_buf *frag; + struct net_buf *temp; u16_t pos; + bool res; int ret; - /* Prepare the pkt so that the IPv6 packet will be sent properly - * to the device driver. - */ - if (net_pkt_context(pkt)) { - ipv6 = net_pkt_get_tx(net_pkt_context(pkt), FRAG_BUF_WAIT); - } else { - ipv6 = net_pkt_get_reserve_tx( - net_if_get_ll_reserve(iface, &NET_IPV6_HDR(pkt)->dst), - FRAG_BUF_WAIT); - } - + ipv6 = net_pkt_clone(pkt, BUF_ALLOC_TIMEOUT); if (!ipv6) { - NET_DBG("Cannot get packet (%d)", -ENOMEM); + NET_DBG("Cannot clone %p", ipv6); return -ENOMEM; } - /* How much stuff we can send from this fragment so that it will fit - * into IPv6 MTU (1280 bytes). + /* And we need to update the last header in the IPv6 packet to point to + * fragment header. */ - if (len > 0) { - NET_ASSERT_INFO(len <= (NET_IPV6_MTU - - sizeof(struct net_ipv6_frag_hdr) - - ipv6_len), - "len %u, frag->len %d", len, frag->len); - - ret = net_pkt_split(pkt, frag, len, &end, &rest, - FRAG_BUF_WAIT); - if (ret < 0) { - NET_DBG("Cannot split fragment (%d)", ret); - goto free_pkts; - } + temp = net_pkt_write_u8(ipv6, ipv6->frags, next_hdr_idx, &pos, + NET_IPV6_NEXTHDR_FRAG); + if (!temp && pos == 0xffff) { + ret = -EINVAL; + goto fail; } - /* So now the frag is split into two pieces, first one is called "end" - * (as it is the end of the packet), and the second one is called - * "rest" (as that part is the rest we need to still send). - * - * Then take out the "frag" from the list as it is now split and not - * needed. - */ - - if (rest) { - rest->frags = frag->frags; - frag->frags = NULL; - net_pkt_frag_unref(frag); - } - - if (prev) { - prev->frags = end; - } else { - pkt->frags = end; - } - - if (end) { - end->frags = NULL; - } - - memcpy(ipv6, pkt, sizeof(struct net_pkt)); - - /* We must not take the fragments from the original packet (yet) */ - ipv6->frags = NULL; - /* Update the extension length metadata so that upper layer checksum * will be calculated properly by net_ipv6_finalize(). */ @@ -3642,53 +3591,55 @@ static int send_ipv6_fragment(struct net_if *iface, net_pkt_ipv6_ext_len(pkt) + sizeof(struct net_ipv6_frag_hdr)); - orig_copy = net_buf_clone(orig, FRAG_BUF_WAIT); - if (!orig_copy) { - ret = -ENOMEM; - NET_DBG("Cannot clone IPv6 header (%d)", ret); - goto free_pkts; + frag = *rest; + if (fit_len < net_buf_frags_len(*rest)) { + ret = net_pkt_split(pkt, frag, fit_len, rest, FRAG_BUF_WAIT); + if (ret < 0) { + net_buf_unref(frag); + goto fail; + } + } else { + *rest = NULL; } - /* Then add the IPv6 header into the packet. */ - net_pkt_frag_insert(ipv6, orig_copy); - - /* Avoid double free if there is an error later in this function. */ - orig_copy = NULL; - - /* And we need to update the last header in the IPv6 packet to point to - * fragment header. - */ - net_pkt_write_u8(ipv6, ipv6->frags, next_hdr_idx, &pos, - NET_IPV6_NEXTHDR_FRAG); - - NET_ASSERT(pos != next_hdr_idx); + final = false; + /* *rest == NULL means no more data to send */ + if (!*rest) { + final = true; + } + /* Append the Fragmentation Header */ + hdr.nexthdr = next_hdr; hdr.reserved = 0; hdr.id = net_pkt_ipv6_fragment_id(pkt); - hdr.offset = htons(((offset / 8) << 3) | !final); - hdr.nexthdr = next_hdr; + hdr.offset = htons(((frag_offset / 8) << 3) | !final); - /* Then add the fragmentation header. */ - ret = net_pkt_insert(ipv6, ipv6->frags, last_hdr_idx, - sizeof(hdr), (u8_t *)&hdr, FRAG_BUF_WAIT); - if (!ret) { - /* If we could not insert because we are already at the - * end of fragment, then just append data to the end of - * the IPv6 header. - */ - ret = net_pkt_append_all(ipv6, sizeof(hdr), (u8_t *)&hdr, - FRAG_BUF_WAIT); - if (!ret) { - ret = -ENOMEM; - NET_DBG("Cannot add IPv6 frag header (%d)", ret); - goto free_pkts; - } + res = net_pkt_append_all(ipv6, sizeof(struct net_ipv6_frag_hdr), + (u8_t *)&hdr, FRAG_BUF_WAIT); + if (!res) { + net_buf_unref(frag); + ret = EINVAL; + goto fail; } - /* Tie all the fragments together to form an IPv6 packet. Then - * update the length of the packet and optionally the checksum. + /* Attach the first part of split payload to end of the packet. And + * "rest" of the packet will be sent in next iteration. */ - net_pkt_frag_add(ipv6, pkt->frags); + temp = ipv6->frags; + while (1) { + if (!temp->frags) { + temp->frags = frag; + break; + } + + temp = temp->frags; + } + + res = net_pkt_compact(ipv6); + if (!res) { + ret = -EINVAL; + goto fail; + } /* Note that we must not calculate possible UDP/TCP/ICMPv6 checksum * as that is already calculated in the non-fragmented packet. @@ -3696,11 +3647,9 @@ static int send_ipv6_fragment(struct net_if *iface, ret = net_ipv6_finalize(ipv6, NET_IPV6_NEXTHDR_FRAG); if (ret < 0) { NET_DBG("Cannot create IPv6 packet (%d)", ret); - goto free_pkts; + goto fail; } - NET_DBG("Sending fragment len %zd", net_pkt_get_len(ipv6)); - /* If everything has been ok so far, we can send the packet. * Note that we cannot send this re-constructed packet directly * as the link layer headers will not be properly set (because @@ -3710,12 +3659,9 @@ static int send_ipv6_fragment(struct net_if *iface, ret = net_send_data(ipv6); if (ret < 0) { NET_DBG("Cannot send fragment (%d)", ret); - goto free_pkts; + goto fail; } - /* Then process the rest of the fragments */ - pkt->frags = rest; - /* Let this packet to be sent and hopefully it will release * the memory that can be utilized for next sent IPv6 fragment. */ @@ -3723,38 +3669,30 @@ static int send_ipv6_fragment(struct net_if *iface, return 0; -free_pkts: - net_pkt_unref(ipv6); - - if (rest) { - net_pkt_frag_unref(rest); - } - - if (orig_copy) { - net_pkt_frag_unref(orig_copy); +fail: + if (ipv6) { + net_pkt_unref(ipv6); } return ret; } -#define BUF_ALLOC_TIMEOUT K_MSEC(100) - int net_ipv6_send_fragmented_pkt(struct net_if *iface, struct net_pkt *pkt, u16_t pkt_len) { - struct net_buf *orig_ipv6 = NULL; - struct net_buf *prev = NULL; - struct net_buf *rest; - struct net_buf *frag; struct net_pkt *clone; - int frag_count = 0; - int curr_len = 0; - int status = false; - u16_t ipv6_len = 0, offset = 0; - u32_t id = sys_rand32_get(); + struct net_buf *rest; + struct net_buf *temp; + u16_t next_hdr_idx; + u16_t last_hdr_idx; + u16_t ipv6_hdrs_len; + u16_t frag_offset; + u16_t frag_count; + u16_t pos; u8_t next_hdr; - u16_t next_hdr_idx, last_hdr_idx; - int ret; + u8_t last_hdr; + int fit_len; + int ret = -EINVAL; /* We cannot touch original pkt because it might be used for * some other purposes, like TCP resend etc. So we need to copy @@ -3767,91 +3705,72 @@ int net_ipv6_send_fragmented_pkt(struct net_if *iface, struct net_pkt *pkt, } pkt = clone; + net_pkt_set_ipv6_fragment_id(pkt, sys_rand32_get()); - frag = pkt->frags; - - ret = get_next_hdr(pkt, &next_hdr_idx, &last_hdr_idx, &next_hdr); + ret = net_ipv6_find_last_ext_hdr(pkt, &next_hdr_idx, &last_hdr_idx); if (ret < 0) { - return -EINVAL; + goto fail; } - /* Split the first fragment that contains the IPv6 header into - * two pieces. The "orig_ipv6" will only contain the original IPv6 - * header which is copied into each fragment together with - * fragmentation header. - */ - ret = net_pkt_split(pkt, frag, - net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt), - &orig_ipv6, &rest, FRAG_BUF_WAIT); - if (ret < 0) { + temp = net_frag_read_u8(pkt->frags, next_hdr_idx, &pos, &next_hdr); + if (!temp && pos == 0xffff) { + ret = -EINVAL; + goto fail; + } + + temp = net_frag_read_u8(pkt->frags, last_hdr_idx, &pos, &last_hdr); + if (!temp && pos == 0xffff) { + ret = -EINVAL; + goto fail; + } + + ipv6_hdrs_len = net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt); + + ret = net_pkt_split(pkt, pkt->frags, ipv6_hdrs_len, &rest, + FRAG_BUF_WAIT); + if (ret < 0 || ipv6_hdrs_len != net_pkt_get_len(pkt)) { NET_DBG("Cannot split packet (%d)", ret); - return ret; + goto fail; } - ipv6_len = net_buf_frags_len(orig_ipv6); + frag_count = 0; + frag_offset = 0; - /* We do not need the first fragment any more. The "rest" will not - * have IPv6 header but it will contain the rest of the original data. + /* The Maximum payload can fit into each packet after IPv6 header, + * Extenstion headers and Fragmentation header. */ - rest->frags = pkt->frags->frags; - pkt->frags = rest; + fit_len = NET_IPV6_MTU - NET_IPV6_FRAGH_LEN - ipv6_hdrs_len; + if (fit_len <= 0) { + /* Must be invalid extension headers length */ + NET_DBG("No room for IPv6 payload MTU %d hdrs_len %d", + NET_IPV6_MTU, NET_IPV6_FRAGH_LEN + ipv6_hdrs_len); + ret = -EINVAL; + goto fail; + } - frag->frags = NULL; - net_pkt_frag_unref(frag); - - frag = pkt->frags; - - net_pkt_set_ipv6_fragment_id(pkt, id); - - /* Go through the fragment list, and create suitable IPv6 packet - * from the data. - */ - while (frag) { - curr_len += frag->len; - if (curr_len > (NET_IPV6_MTU - - sizeof(struct net_ipv6_frag_hdr) - ipv6_len)) { - /* The fit_len var tells how much data we need send - * from frag in order to fill the IPv6 MTU. - */ - int fit_len = NET_IPV6_MTU - - sizeof(struct net_ipv6_frag_hdr) - ipv6_len - - (curr_len - frag->len); - - status = send_ipv6_fragment(iface, pkt, orig_ipv6, - prev, frag, ipv6_len, - offset, fit_len, - next_hdr, next_hdr_idx, - last_hdr_idx, false, - frag_count); - if (status < 0) { - goto out; - } - - offset += curr_len - (frag->len - fit_len); - prev = NULL; - - frag = pkt->frags; - curr_len = 0; - frag_count++; + while (rest) { + ret = send_ipv6_fragment(iface, pkt, &rest, ipv6_hdrs_len, + fit_len, frag_offset, next_hdr, + next_hdr_idx, last_hdr, last_hdr_idx, + frag_count); + if (ret < 0) { + goto fail; } - prev = frag; - frag = frag->frags; + frag_count++; + frag_offset += fit_len; } - status = send_ipv6_fragment(iface, pkt, orig_ipv6, prev, prev, - ipv6_len, offset, 0, next_hdr, - next_hdr_idx, last_hdr_idx, true, - frag_count); + return 0; +fail: net_pkt_unref(pkt); -out: - if (orig_ipv6) { - net_pkt_frag_unref(orig_ipv6); + if (rest) { + net_buf_unref(rest); } - return status; + return ret; } #endif /* CONFIG_NET_IPV6_FRAGMENT */ @@ -3939,20 +3858,21 @@ static inline struct net_buf *handle_ext_hdr_options(struct net_pkt *pkt, /* Each extension option has type and length */ frag = net_frag_read_u8(frag, offset, &loc, &opt_type); - frag = net_frag_read_u8(frag, loc, &loc, &opt_len); if (!frag && loc == 0xffff) { goto drop; } + if (opt_type != NET_IPV6_EXT_HDR_OPT_PAD1) { + frag = net_frag_read_u8(frag, loc, &loc, &opt_len); + if (!frag && loc == 0xffff) { + goto drop; + } + } + while (frag && (length < len)) { switch (opt_type) { case NET_IPV6_EXT_HDR_OPT_PAD1: - NET_DBG("PAD1 option"); length++; - /* We need to step back as the PAD1 len is only one - * byte and we read already one extra byte. - */ - loc--; break; case NET_IPV6_EXT_HDR_OPT_PADN: NET_DBG("PADN option"); @@ -3996,17 +3916,23 @@ static inline struct net_buf *handle_ext_hdr_options(struct net_pkt *pkt, } frag = net_frag_read_u8(frag, loc, &loc, &opt_type); - frag = net_frag_read_u8(frag, loc, &loc, &opt_len); if (!frag && loc == 0xffff) { goto drop; } + + if (opt_type != NET_IPV6_EXT_HDR_OPT_PAD1) { + frag = net_frag_read_u8(frag, loc, &loc, &opt_len); + if (!frag && loc == 0xffff) { + goto drop; + } + } } if (length != len) { goto drop; } - *pos += length; + *pos = loc; *verdict = NET_CONTINUE; return frag; @@ -4134,9 +4060,11 @@ enum net_verdict net_ipv6_process_pkt(struct net_pkt *pkt) int pkt_len = (hdr->len[0] << 8) + hdr->len[1] + sizeof(*hdr); struct net_buf *frag; u8_t start_of_ext, prev_hdr; - u8_t next, next_hdr, length; + u8_t next, next_hdr; u8_t first_option; - u16_t offset, total_len = 0; + u16_t offset; + u16_t length; + u16_t total_len = 0; u8_t ext_bitmap; if (real_len != pkt_len) { @@ -4215,7 +4143,9 @@ enum net_verdict net_ipv6_process_pkt(struct net_pkt *pkt) frag = pkt->frags; next = hdr->nexthdr; first_option = next; + length = 0; ext_bitmap = 0; + start_of_ext = 0; offset = sizeof(struct net_ipv6_hdr); prev_hdr = &NET_IPV6_HDR(pkt)->nexthdr - &NET_IPV6_HDR(pkt)->vtc; @@ -4224,30 +4154,21 @@ enum net_verdict net_ipv6_process_pkt(struct net_pkt *pkt) if (is_upper_layer_protocol_header(next)) { NET_DBG("IPv6 next header %d", next); - net_pkt_set_ipv6_ext_len(pkt, offset - - sizeof(struct net_ipv6_hdr)); goto upper_proto; } - start_of_ext = offset; + if (!start_of_ext) { + start_of_ext = offset; + } frag = net_frag_read_u8(frag, offset, &offset, &next_hdr); - frag = net_frag_read_u8(frag, offset, &offset, &length); if (!frag) { goto drop; } - length = length * 8 + 8; - total_len += length; verdict = NET_OK; - if (next == NET_IPV6_NEXTHDR_HBHO) { - NET_DBG("IPv6 next header %d length %d bytes", next, - length); - } else { - /* There is no separate length for other headers */ - NET_DBG("IPv6 next header %d", next); - } + NET_DBG("IPv6 next header %d", next); switch (next) { case NET_IPV6_NEXTHDR_NONE: @@ -4259,6 +4180,15 @@ enum net_verdict net_ipv6_process_pkt(struct net_pkt *pkt) goto drop; case NET_IPV6_NEXTHDR_HBHO: + frag = net_frag_read_u8(frag, offset, &offset, + (u8_t *)&length); + if (!frag) { + goto drop; + } + + length = length * 8 + 8; + total_len += length; + /* HBH option needs to be the first one */ if (first_option != NET_IPV6_NEXTHDR_HBHO) { goto bad_hdr; @@ -4280,12 +4210,14 @@ enum net_verdict net_ipv6_process_pkt(struct net_pkt *pkt) case NET_IPV6_NEXTHDR_FRAG: net_pkt_set_ipv6_hdr_prev(pkt, prev_hdr); - /* The fragment header does not have length field so - * we need to step back two bytes and start from the - * beginning of the fragment header. - */ - return handle_fragment_hdr(pkt, frag, real_len, - offset - 2); + net_pkt_set_ipv6_fragment_start(pkt, + sizeof(struct + net_ipv6_hdr) + + total_len); + + total_len += 8; + return handle_fragment_hdr(pkt, frag, real_len, offset, + &offset, next_hdr); #endif default: goto bad_hdr; @@ -4300,10 +4232,8 @@ enum net_verdict net_ipv6_process_pkt(struct net_pkt *pkt) } upper_proto: - if (total_len > 0) { - NET_DBG("Extension len %d", total_len); - net_pkt_set_ipv6_ext_len(pkt, total_len); - } + + net_pkt_set_ipv6_ext_len(pkt, total_len); switch (next) { case IPPROTO_ICMPV6: diff --git a/subsys/net/ip/net_pkt.c b/subsys/net/ip/net_pkt.c index ee559d68133..ffc5588adf2 100644 --- a/subsys/net/ip/net_pkt.c +++ b/subsys/net/ip/net_pkt.c @@ -1665,50 +1665,50 @@ bool net_pkt_insert(struct net_pkt *pkt, struct net_buf *frag, return insert_data(pkt, frag, temp, offset, len, data, timeout); } -int net_pkt_split(struct net_pkt *pkt, struct net_buf *orig_frag, - u16_t len, struct net_buf **fragA, - struct net_buf **fragB, s32_t timeout) +int net_pkt_split(struct net_pkt *pkt, struct net_buf *frag, u16_t offset, + struct net_buf **rest, s32_t timeout) { - if (!pkt || !orig_frag) { + struct net_buf *prev; + + if (!pkt || !frag || !offset || !rest) { return -EINVAL; } - NET_ASSERT(fragA && fragB); + prev = frag; + *rest = NULL; - if (len == 0) { - *fragA = NULL; - *fragB = NULL; - return 0; - } - - if (len > orig_frag->len) { - *fragA = net_pkt_get_frag(pkt, timeout); - if (!*fragA) { - return -ENOMEM; + while (frag) { + if (offset < frag->len) { + break; } - memcpy(net_buf_add(*fragA, orig_frag->len), orig_frag->data, - orig_frag->len); + offset -= frag->len; + prev = frag; + frag = frag->frags; + } + + if (!frag && offset) { + return -EINVAL; + } + + if (!frag && !offset) { + *rest = frag; + prev->frags = NULL; - *fragB = NULL; return 0; } - *fragA = net_pkt_get_frag(pkt, timeout); - if (!*fragA) { + *rest = net_pkt_get_frag(pkt, timeout); + if (!*rest) { return -ENOMEM; } - *fragB = net_pkt_get_frag(pkt, timeout); - if (!*fragB) { - net_pkt_frag_unref(*fragA); - *fragA = NULL; - return -ENOMEM; - } + memcpy(net_buf_add(*rest, frag->len - offset), + frag->data + offset, frag->len - offset); + frag->len = offset; - memcpy(net_buf_add(*fragA, len), orig_frag->data, len); - memcpy(net_buf_add(*fragB, orig_frag->len - len), - orig_frag->data + len, orig_frag->len - len); + (*rest)->frags = frag->frags; + frag->frags = NULL; return 0; } @@ -1832,6 +1832,100 @@ static int net_pkt_get_addr(struct net_pkt *pkt, bool is_src, return 0; } +int net_pkt_pull(struct net_pkt *pkt, u16_t offset, u16_t len) +{ + struct net_buf *frag; + struct net_buf *temp; + struct net_buf *prev; + u8_t avail; + + if (!pkt || !len) { + return -EINVAL; + } + + prev = NULL; + frag = pkt->frags; + + while (1) { + if (!frag) { + return -EINVAL; + } + + if (offset < frag->len) { + break; + } + + offset -= frag->len; + prev = frag; + frag = frag->frags; + } + + /* Pull the data */ + while (frag && len) { + if (!offset) { + if (len > frag->len) { + len -= frag->len; + + temp = frag; + frag = frag->frags; + temp->frags = NULL; + offset = 0; + + net_buf_unref(temp); + + if (prev) { + prev->frags = frag; + } else { + pkt->frags = frag; + } + } else { + memmove(frag->data, frag->data + len, + frag->len - len); + frag->len -= len; + len = 0; + + if (!frag->len) { + temp = frag; + frag = frag->frags; + temp->frags = NULL; + + net_buf_unref(temp); + + if (prev) { + prev->frags = frag; + } else { + pkt->frags = frag; + } + } + } + } else { + avail = frag->len - offset; + + if (len > avail) { + frag->len = offset; + + len -= avail; + prev = frag; + frag = frag->frags; + offset = 0; + } else { + memmove(frag->data + offset, + frag->data + offset + len, + avail - len); + frag->len -= len; + len = 0; + } + } + } + + if (len) { + NET_ERR("Could not pull given length out of net packet"); + return -EINVAL; + } + + return 0; +} + int net_pkt_get_src_addr(struct net_pkt *pkt, struct sockaddr *addr, socklen_t addrlen) { diff --git a/subsys/net/lib/http/http_server.c b/subsys/net/lib/http/http_server.c index a175d66491b..8ec13db55e8 100644 --- a/subsys/net/lib/http/http_server.c +++ b/subsys/net/lib/http/http_server.c @@ -784,29 +784,27 @@ ws_only: struct net_buf *hdr, *payload; struct net_pkt *cloned; - ret = net_pkt_split(pkt, pkt->frags, - ctx->websocket.data_waiting, - &payload, &hdr, - ctx->timeout); - if (ret < 0) { - net_pkt_unref(pkt); - return; - } - - net_pkt_frag_unref(pkt->frags); + payload = pkt->frags; pkt->frags = NULL; cloned = net_pkt_clone(pkt, ctx->timeout); if (!cloned) { net_pkt_unref(pkt); + net_pkt_frag_unref(payload); + return; + } + + ret = net_pkt_split(pkt, payload, + ctx->websocket.data_waiting, + &hdr, ctx->timeout); + if (ret < 0) { + net_pkt_unref(pkt); + net_pkt_frag_unref(payload); + net_pkt_unref(cloned); return; } pkt->frags = payload; - payload->frags = NULL; - - net_pkt_compact(pkt); - cloned->frags = hdr; ctx->websocket.pending = cloned; diff --git a/tests/net/ipv6/src/main.c b/tests/net/ipv6/src/main.c index 08c3b793620..c35ecbfd96d 100644 --- a/tests/net/ipv6/src/main.c +++ b/tests/net/ipv6/src/main.c @@ -565,6 +565,318 @@ static void test_hbho_message(void) zassert_false(net_recv_data(iface, pkt) < 0, "Data receive for HBHO failed."); } +/* IPv6 hop-by-hop option in the message HBHO (72 Bytes) */ +static const unsigned char ipv6_hbho_1[] = { +/* IPv6 header starts here */ +0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x40, +0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0xc0, 0xde, 0xff, 0xfe, 0x9b, 0xb4, 0x47, +0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +/* Hop-by-hop option starts here */ +0x11, 0x08, +/* Padding */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* UDP header starts here (8 bytes) */ +0x4e, 0x20, 0x10, 0x92, 0x00, 0x30, 0xa1, 0xc5, +/* User data starts here (40 bytes) */ +0x30, 0x26, 0x02, 0x01, 0x00, 0x04, 0x06, 0x70, +0x75, 0x62, 0x6c, 0x69, 0x63, 0xa0, 0x19, 0x02, +0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, +0x30, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2b, 0x06, +0x01, 0x02, 0x01, 0x01, 0x05, 0x00, 0x05, 0x00 }; + +/** + * @brief IPv6 parse Hop-By-Hop Option + */ +static void test_hbho_message_1(void) +{ + struct net_pkt *pkt; + struct net_buf *frag; + struct net_if *iface; + u16_t pos; + + iface = net_if_get_default(); + + pkt = net_pkt_get_reserve_tx(net_if_get_ll_reserve(iface, NULL), + K_FOREVER); + + NET_ASSERT_INFO(pkt, "Out of TX packets"); + + frag = net_pkt_get_frag(pkt, K_FOREVER); + + net_pkt_frag_add(pkt, frag); + + net_pkt_set_iface(pkt, iface); + net_pkt_set_family(pkt, AF_INET6); + net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); + + net_pkt_ll_clear(pkt); + + net_pkt_write(pkt, pkt->frags, 0, &pos, sizeof(ipv6_hbho_1), + (u8_t *)ipv6_hbho_1, K_FOREVER); + + zassert_false(net_recv_data(iface, pkt) < 0, + "Data receive for HBHO failed."); + + /* Verify IPv6 Ext hdr length */ + zassert_false(net_pkt_ipv6_ext_len(pkt) == 72, + "IPv6 mismatch ext hdr length"); +} + +/* IPv6 hop-by-hop option in the message HBHO (104 Bytes) */ +static const unsigned char ipv6_hbho_2[] = { +/* IPv6 header starts here */ +0x60, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x40, +0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0xc0, 0xde, 0xff, 0xfe, 0x9b, 0xb4, 0x47, +0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +/* Hop-by-hop option starts here */ +0x11, 0x0c, +/* padding */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x01, 0x04, 0x00, 0x00, 0x00, 0x00, +/* udp header starts here (8 bytes) */ +0x4e, 0x20, 0x10, 0x92, 0x00, 0x30, 0xa1, 0xc5, +/* User data starts here (40 bytes) */ +0x30, 0x26, 0x02, 0x01, 0x00, 0x04, 0x06, 0x70, +0x75, 0x62, 0x6c, 0x69, 0x63, 0xa0, 0x19, 0x02, +0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, +0x30, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2b, 0x06, +0x01, 0x02, 0x01, 0x01, 0x05, 0x00, 0x05, 0x00 }; + +/** + * @brief IPv6 parse Hop-By-Hop Option + */ +static void test_hbho_message_2(void) +{ + struct net_pkt *pkt; + struct net_buf *frag; + struct net_if *iface; + u16_t pos; + + iface = net_if_get_default(); + + pkt = net_pkt_get_reserve_tx(net_if_get_ll_reserve(iface, NULL), + K_FOREVER); + + NET_ASSERT_INFO(pkt, "Out of TX packets"); + + frag = net_pkt_get_frag(pkt, K_FOREVER); + + net_pkt_frag_add(pkt, frag); + + net_pkt_set_iface(pkt, iface); + net_pkt_set_family(pkt, AF_INET6); + net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); + + net_pkt_ll_clear(pkt); + + net_pkt_write(pkt, pkt->frags, 0, &pos, sizeof(ipv6_hbho_2), + (u8_t *)ipv6_hbho_2, K_FOREVER); + + zassert_false(net_recv_data(iface, pkt) < 0, + "Data receive for HBHO failed."); + + /* Verify IPv6 Ext hdr length */ + zassert_false(net_pkt_ipv6_ext_len(pkt) == 104, + "IPv6 mismatch ext hdr length"); +} + +/* IPv6 hop-by-hop option in the message HBHO (920 bytes) */ +static const unsigned char ipv6_hbho_3[] = { +/* IPv6 header starts here */ +0x60, 0x00, 0x00, 0x00, 0x03, 0xc8, 0x00, 0x40, +0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0xc0, 0xde, 0xff, 0xfe, 0x9b, 0xb4, 0x47, +0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +/* Hop-by-hop option starts here */ +0x11, 0x72, +/* padding */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x01, 0x04, 0x00, 0x00, 0x00, 0x00, +/* udp header starts here (8 bytes) */ +0x4e, 0x20, 0x10, 0x92, 0x00, 0x30, 0xa1, 0xc5, +/* User data starts here (40 bytes) */ +0x30, 0x26, 0x02, 0x01, 0x00, 0x04, 0x06, 0x70, +0x75, 0x62, 0x6c, 0x69, 0x63, 0xa0, 0x19, 0x02, +0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, +0x30, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2b, 0x06, +0x01, 0x02, 0x01, 0x01, 0x05, 0x00, 0x05, 0x00 +}; + +/** + * @brief IPv6 parse Hop-By-Hop Option + */ +static void test_hbho_message_3(void) +{ + struct net_pkt *pkt; + struct net_buf *frag; + struct net_if *iface; + u16_t pos; + + iface = net_if_get_default(); + + pkt = net_pkt_get_reserve_tx(net_if_get_ll_reserve(iface, NULL), + K_FOREVER); + + NET_ASSERT_INFO(pkt, "Out of TX packets"); + + frag = net_pkt_get_frag(pkt, K_FOREVER); + + net_pkt_frag_add(pkt, frag); + + net_pkt_set_iface(pkt, iface); + net_pkt_set_family(pkt, AF_INET6); + net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); + + net_pkt_ll_clear(pkt); + + net_pkt_write(pkt, pkt->frags, 0, &pos, sizeof(ipv6_hbho_3), + (u8_t *)ipv6_hbho_3, K_FOREVER); + + zassert_false(net_recv_data(iface, pkt) < 0, + "Data receive for HBHO failed."); + + /* Verify IPv6 Ext hdr length */ + zassert_false(net_pkt_ipv6_ext_len(pkt) == 920, + "IPv6 mismatch ext hdr length"); +} + /** * @brief IPv6 change ll address */ @@ -641,6 +953,9 @@ void test_main(void) ztest_unit_test(test_send_ns_no_options), ztest_unit_test(test_ra_message), ztest_unit_test(test_hbho_message), + ztest_unit_test(test_hbho_message_1), + ztest_unit_test(test_hbho_message_2), + ztest_unit_test(test_hbho_message_3), ztest_unit_test(test_change_ll_addr), ztest_unit_test(test_prefix_timeout) ); diff --git a/tests/net/ipv6_fragment/src/main.c b/tests/net/ipv6_fragment/src/main.c index eb1ab7c4156..b6f0e03af46 100644 --- a/tests/net/ipv6_fragment/src/main.c +++ b/tests/net/ipv6_fragment/src/main.c @@ -82,6 +82,204 @@ static const unsigned char ipv6_hbho[] = { /* User data starts here and is appended in corresponding function */ }; +/* IPv6 hop-by-hop option in the message HBHO (72 Bytes) */ +static const unsigned char ipv6_hbho_1[] = { +/* IPv6 header starts here */ +0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x40, +0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0xc0, 0xde, 0xff, 0xfe, 0x9b, 0xb4, 0x47, +0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +/* Hop-by-hop option starts here */ +0x11, 0x08, +/* Padding */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* UDP header starts here (8 bytes) */ +0x4e, 0x20, 0x10, 0x92, 0x00, 0x30, 0xa1, 0xc5, +/* User data starts here (40 bytes) */ +0x30, 0x26, 0x02, 0x01, 0x00, 0x04, 0x06, 0x70, +0x75, 0x62, 0x6c, 0x69, 0x63, 0xa0, 0x19, 0x02, +0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, +0x30, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2b, 0x06, +0x01, 0x02, 0x01, 0x01, 0x05, 0x00, 0x05, 0x00 }; + +/* IPv6 hop-by-hop option in the message HBHO (104 Bytes) */ +static const unsigned char ipv6_hbho_2[] = { +/* IPv6 header starts here */ +0x60, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x40, +0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0xc0, 0xde, 0xff, 0xfe, 0x9b, 0xb4, 0x47, +0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +/* Hop-by-hop option starts here */ +0x11, 0x0c, +/* padding */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x01, 0x04, 0x00, 0x00, 0x00, 0x00, +/* udp header starts here (8 bytes) */ +0x4e, 0x20, 0x10, 0x92, 0x00, 0x30, 0xa1, 0xc5, +/* User data starts here (40 bytes) */ +0x30, 0x26, 0x02, 0x01, 0x00, 0x04, 0x06, 0x70, +0x75, 0x62, 0x6c, 0x69, 0x63, 0xa0, 0x19, 0x02, +0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, +0x30, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2b, 0x06, +0x01, 0x02, 0x01, 0x01, 0x05, 0x00, 0x05, 0x00 }; + +/* IPv6 hop-by-hop option in the message HBHO (920 bytes) */ +static const unsigned char ipv6_hbho_3[] = { +/* IPv6 header starts here */ +0x60, 0x00, 0x00, 0x00, 0x03, 0xc8, 0x00, 0x40, +0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0xc0, 0xde, 0xff, 0xfe, 0x9b, 0xb4, 0x47, +0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +/* Hop-by-hop option starts here */ +0x11, 0x72, +/* padding */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x01, 0x04, 0x00, 0x00, 0x00, 0x00, +/* udp header starts here (8 bytes) */ +0x4e, 0x20, 0x10, 0x92, 0x00, 0x30, 0xa1, 0xc5, +/* User data starts here (40 bytes) */ +0x30, 0x26, 0x02, 0x01, 0x00, 0x04, 0x06, 0x70, +0x75, 0x62, 0x6c, 0x69, 0x63, 0xa0, 0x19, 0x02, +0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, +0x30, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2b, 0x06, +0x01, 0x02, 0x01, 0x01, 0x05, 0x00, 0x05, 0x00 +}; + /* IPv6 hop-by-hop option in the message */ static const unsigned char ipv6_hbho_frag[] = { /* IPv6 header starts here */ @@ -101,6 +299,396 @@ static const unsigned char ipv6_hbho_frag[] = { /* User data starts here and is appended in corresponding function */ }; +/* IPv6 hop-by-hop option in the message */ +static const unsigned char ipv6_hbho_frag_1[] = { +/* IPv6 header starts here */ +0x60, 0x00, 0x00, 0x00, 0x05, 0xb0, 0x00, 0x40 +, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x08, 0xc0, 0xde, 0xff, 0xfe, 0xc9, 0xa0, 0x4b +, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 +/* Hop-by-hop option starts here */ +, 0x2c, 0x80 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +/* IPv6 fragment header */ +, 0x3a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 +/* ICMPv6 header and Data*/ +, 0x80, 0x00, 0x13, 0xdf, 0x19, 0xc7, 0x19, 0xc7 +, 0x54, 0x65, 0x73, 0x74, 0x2d, 0x67, 0x72, 0x6f +, 0x75, 0x70, 0x3a, 0x49, 0x50, 0x76, 0x36, 0x2e +, 0x49, 0x50, 0x76, 0x36, 0x2e, 0x49, 0x43, 0x4d +, 0x50, 0x76, 0x36, 0x2e, 0x45, 0x63, 0x68, 0x6f +, 0x2d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74 +, 0x2e, 0x49, 0x50, 0x76, 0x36, 0x2d, 0x50, 0x61 +, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x61, 0x79 +, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x69, 0x70, 0x76 +, 0x36, 0x2d, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73 +, 0x69, 0x6f, 0x6e, 0x2d, 0x68, 0x65, 0x61, 0x64 +, 0x65, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x65 +, 0x72, 0x2d, 0x68, 0x6f, 0x70, 0x2d, 0x62, 0x79 +, 0x2d, 0x68, 0x6f, 0x70, 0x2d, 0x6f, 0x70, 0x74 +, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x6f, 0x70, 0x74 +, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6c, 0x65 +, 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x54, 0x65, 0x73 +, 0x74, 0x2d, 0x63, 0x61, 0x73, 0x65, 0x3a, 0x32 +, 0x31, 0x33, 0x30, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +}; + +/* IPv6 hop-by-hop option in the message */ +static const unsigned char ipv6_large_hbho[] = { +/* IPv6 header starts here */ +0x60, 0x00, 0x00, 0x00, 0x05, 0xa8, 0x00, 0x40 +, 0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 +, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 +/* Hop-by-hop option starts here */ +, 0x3a, 0x80 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +/* ICMPv6 header and Data*/ +, 0x80, 0x00, 0x13, 0xdf, 0x19, 0xc7, 0x19, 0xc7 +, 0x54, 0x65, 0x73, 0x74, 0x2d, 0x67, 0x72, 0x6f +, 0x75, 0x70, 0x3a, 0x49, 0x50, 0x76, 0x36, 0x2e +, 0x49, 0x50, 0x76, 0x36, 0x2e, 0x49, 0x43, 0x4d +, 0x50, 0x76, 0x36, 0x2e, 0x45, 0x63, 0x68, 0x6f +, 0x2d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74 +, 0x2e, 0x49, 0x50, 0x76, 0x36, 0x2d, 0x50, 0x61 +, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x61, 0x79 +, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x69, 0x70, 0x76 +, 0x36, 0x2d, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73 +, 0x69, 0x6f, 0x6e, 0x2d, 0x68, 0x65, 0x61, 0x64 +, 0x65, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x65 +, 0x72, 0x2d, 0x68, 0x6f, 0x70, 0x2d, 0x62, 0x79 +, 0x2d, 0x68, 0x6f, 0x70, 0x2d, 0x6f, 0x70, 0x74 +, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x6f, 0x70, 0x74 +, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x65, 0x6c, 0x65 +, 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x54, 0x65, 0x73 +, 0x74, 0x2d, 0x63, 0x61, 0x73, 0x65, 0x3a, 0x32 +, 0x31, 0x33, 0x30, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01 +}; + static unsigned char ipv6_first_frag[] = { /* IPv6 header starts here */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x3f, /* `....6.? */ @@ -146,6 +734,8 @@ static struct k_sem wait_data; static u16_t pkt_data_len; static u16_t pkt_recv_data_len; +static bool large_hbho; + #define WAIT_TIME K_SECONDS(1) #define ALLOC_TIMEOUT 500 @@ -202,7 +792,15 @@ static int verify_fragment(struct net_pkt *pkt) frag_count++; + if (!large_hbho) { + goto small; + } else { + goto large; + } + +small: if (frag_count == 1) { + /* First fragment received. Make sure that all the * things are correct before the fragment header. */ @@ -228,7 +826,7 @@ static int verify_fragment(struct net_pkt *pkt) offset = pkt->frags->data[6 * 8 + 2] * 256 + (pkt->frags->data[6 * 8 + 3] & 0xfe); if (offset != 0) { - DBG("Invalid offset\n"); + DBG("Invalid offset %d\n", offset); return -EINVAL; } @@ -237,7 +835,7 @@ static int verify_fragment(struct net_pkt *pkt) return -EINVAL; } - pkt_recv_data_len += total_len - 8 /* HBHO */ - 8 /* UDP */ - + pkt_recv_data_len += total_len - 8 /* HBHO */ - sizeof(struct net_ipv6_frag_hdr); /* Rewrite the fragment id so that the memcmp() will not fail */ @@ -318,6 +916,138 @@ static int verify_fragment(struct net_pkt *pkt) } } + return 0; + +large: + if (frag_count == 1) { + u16_t exp_ext_len = 1040; /* 1032 (HBHO) + 8 (FRAG)*/ + u16_t recv_ext_len; + u16_t exp_payload_len = 200; + u16_t recv_payload_len; + u16_t frag_offset; + struct net_buf *frag; + u16_t pos; + + recv_ext_len = net_pkt_ipv6_ext_len(pkt); + if (recv_ext_len != exp_ext_len) { + DBG("Expected amount of Ext headers len is %d," + "but received %d\n", exp_ext_len, recv_ext_len); + return -EINVAL; + } + + /* IPv6 + HBHO + FRAG */ + recv_payload_len = net_pkt_get_len(pkt) - 40 - 1032 - 8; + if (recv_payload_len != exp_payload_len) { + DBG("Expected amount of payload len is %d," + "but received %d\n", exp_payload_len, + recv_payload_len); + return -EINVAL; + } + + frag = net_frag_read_be16(pkt->frags, 40 + 1032 + 2, &pos, + &frag_offset); + if (!frag && pos == 0xffff) { + return -EINVAL; + } + + if ((frag_offset & 0xfff8) != 0) { + DBG("Invalid fragment offset %d\n", + frag_offset & 0xfff8); + return -EINVAL; + } + + if ((frag_offset & 0x0001) != 1) { + DBG("Fragment More flag should be set\n"); + return -EINVAL; + } + } + + if (frag_count == 2) { + u16_t exp_ext_len = 1040; /* 1032 (HBHO) + 8 (FRAG)*/ + u16_t recv_ext_len; + u16_t exp_payload_len = 200; + u16_t recv_payload_len; + u16_t frag_offset; + struct net_buf *frag; + u16_t pos; + + recv_ext_len = net_pkt_ipv6_ext_len(pkt); + if (recv_ext_len != exp_ext_len) { + DBG("Expected amount of Ext headers len is %d," + "but received %d\n", exp_ext_len, recv_ext_len); + return -EINVAL; + } + + /* IPv6 + HBHO + FRAG */ + recv_payload_len = net_pkt_get_len(pkt) - 40 - 1032 - 8; + if (recv_payload_len != exp_payload_len) { + DBG("Expected amount of payload len is %d," + "but received %d\n", exp_payload_len, + recv_payload_len); + return -EINVAL; + } + + frag = net_frag_read_be16(pkt->frags, 40 + 1032 + 2, &pos, + &frag_offset); + if (!frag && pos == 0xffff) { + return -EINVAL; + } + + if ((frag_offset & 0xfff8) != 200) { + DBG("Invalid fragment offset %d\n", + frag_offset & 0xfff8); + return -EINVAL; + } + + if ((frag_offset & 0x0001) != 1) { + DBG("Fragment More flag should be set\n"); + return -EINVAL; + } + } + + if (frag_count == 3) { + u16_t exp_ext_len = 1040; /* 1032 (HBHO) + 8 (FRAG)*/ + u16_t recv_ext_len; + u16_t exp_payload_len = 16; + u16_t recv_payload_len; + u16_t frag_offset; + struct net_buf *frag; + u16_t pos; + + recv_ext_len = net_pkt_ipv6_ext_len(pkt); + if (recv_ext_len != exp_ext_len) { + DBG("Expected amount of Ext headers len is %d," + "but received %d\n", exp_ext_len, recv_ext_len); + return -EINVAL; + } + + /* IPv6 + HBHO + FRAG */ + recv_payload_len = net_pkt_get_len(pkt) - 40 - 1032 - 8; + if (recv_payload_len != exp_payload_len) { + DBG("Expected amount of payload len is %d," + "but received %d\n", exp_payload_len, + recv_payload_len); + return -EINVAL; + } + + frag = net_frag_read_be16(pkt->frags, 40 + 1032 + 2, &pos, + &frag_offset); + if (!frag && pos == 0xffff) { + return -EINVAL; + } + + if ((frag_offset & 0xfff8) != 400) { + DBG("Invalid fragment offset %d\n", + frag_offset & 0xfff8); + return -EINVAL; + } + + if ((frag_offset & 0x0001) != 0) { + DBG("Fragment More flag should be unset\n"); + return -EINVAL; + } + } + return 0; } @@ -577,6 +1307,134 @@ static void test_find_last_ipv6_fragment_hbho_udp(void) net_pkt_unref(pkt); } +static void test_find_last_ipv6_fragment_hbho_1(void) +{ + u16_t next_hdr_idx = 0; + u16_t last_hdr_pos = 0; + struct net_pkt *pkt; + struct net_buf *frag; + u8_t next_hdr; + u8_t last_hdr; + int ret; + + pkt = net_pkt_get_reserve_tx(0, ALLOC_TIMEOUT); + zassert_not_null(pkt, "packet"); + + net_pkt_set_iface(pkt, iface1); + net_pkt_set_family(pkt, AF_INET6); + net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); + + /* Add IPv6 header + HBH option + fragment header */ + ret = net_pkt_append_all(pkt, sizeof(ipv6_hbho_1), ipv6_hbho_1, + ALLOC_TIMEOUT); + zassert_true(ret, "IPv6 header append failed"); + + net_pkt_ll_clear(pkt); + + ret = net_ipv6_find_last_ext_hdr(pkt, &next_hdr_idx, &last_hdr_pos); + zassert_equal(ret, 0, "Cannot find last header"); + + zassert_equal(next_hdr_idx, 40, "Next header index wrong"); + zassert_equal(last_hdr_pos, 112, "Last header position wrong"); + + frag = net_frag_read_u8(pkt->frags, next_hdr_idx, &next_hdr_idx, + &next_hdr); + zassert_equal(next_hdr, 0x11, "Invalid next header"); + + frag = net_frag_read_u8(pkt->frags, last_hdr_pos, &last_hdr_pos, + &last_hdr); + + zassert_equal(last_hdr, 0x4e, "Invalid next header"); + + net_pkt_unref(pkt); +} + +static void test_find_last_ipv6_fragment_hbho_2(void) +{ + u16_t next_hdr_idx = 0; + u16_t last_hdr_pos = 0; + struct net_pkt *pkt; + struct net_buf *frag; + u8_t next_hdr; + u8_t last_hdr; + int ret; + + pkt = net_pkt_get_reserve_tx(0, ALLOC_TIMEOUT); + zassert_not_null(pkt, "packet"); + + net_pkt_set_iface(pkt, iface1); + net_pkt_set_family(pkt, AF_INET6); + net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); + + /* Add IPv6 header + HBH option + fragment header */ + ret = net_pkt_append_all(pkt, sizeof(ipv6_hbho_2), ipv6_hbho_2, + ALLOC_TIMEOUT); + zassert_true(ret, "IPv6 header append failed"); + + net_pkt_ll_clear(pkt); + + ret = net_ipv6_find_last_ext_hdr(pkt, &next_hdr_idx, &last_hdr_pos); + zassert_equal(ret, 0, "Cannot find last header"); + + zassert_equal(next_hdr_idx, 40, "Next header index wrong"); + zassert_equal(last_hdr_pos, 144, "Last header position wrong"); + + frag = net_frag_read_u8(pkt->frags, next_hdr_idx, &next_hdr_idx, + &next_hdr); + + zassert_equal(next_hdr, 0x11, "Invalid next header"); + + frag = net_frag_read_u8(pkt->frags, last_hdr_pos, &last_hdr_pos, + &last_hdr); + + zassert_equal(last_hdr, 0x4e, "Invalid next header"); + + net_pkt_unref(pkt); +} + +static void test_find_last_ipv6_fragment_hbho_3(void) +{ + u16_t next_hdr_idx = 0; + u16_t last_hdr_pos = 0; + struct net_pkt *pkt; + struct net_buf *frag; + u8_t next_hdr; + u8_t last_hdr; + int ret; + + pkt = net_pkt_get_reserve_tx(0, ALLOC_TIMEOUT); + zassert_not_null(pkt, "packet"); + + net_pkt_set_iface(pkt, iface1); + net_pkt_set_family(pkt, AF_INET6); + net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); + + /* Add IPv6 header + HBH option + fragment header */ + ret = net_pkt_append_all(pkt, sizeof(ipv6_hbho_3), ipv6_hbho_3, + ALLOC_TIMEOUT); + zassert_true(ret, "IPv6 header append failed"); + + net_pkt_ll_clear(pkt); + + ret = net_ipv6_find_last_ext_hdr(pkt, &next_hdr_idx, &last_hdr_pos); + zassert_equal(ret, 0, "Cannot find last header"); + + zassert_equal(next_hdr_idx, 40, "Next header index wrong"); + zassert_equal(last_hdr_pos, 960, "Last header position wrong"); + + frag = net_frag_read_u8(pkt->frags, next_hdr_idx, &next_hdr_idx, + &next_hdr); + + zassert_equal(next_hdr, 0x11, "Invalid next header"); + + frag = net_frag_read_u8(pkt->frags, last_hdr_pos, &last_hdr_pos, + &last_hdr); + + zassert_equal(last_hdr, 0x4e, "Invalid next header"); + + net_pkt_unref(pkt); +} + static void test_find_last_ipv6_fragment_hbho_frag(void) { u16_t next_hdr_idx = 0; @@ -590,8 +1448,7 @@ static void test_find_last_ipv6_fragment_hbho_frag(void) net_pkt_set_iface(pkt, iface1); net_pkt_set_family(pkt, AF_INET6); net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); - net_pkt_set_ipv6_ext_len(pkt, sizeof(ipv6_hbho_frag) - - sizeof(struct net_ipv6_hdr)); + /* Add IPv6 header + HBH option + fragment header */ ret = net_pkt_append_all(pkt, sizeof(ipv6_hbho_frag), ipv6_hbho_frag, ALLOC_TIMEOUT); @@ -608,8 +1465,51 @@ static void test_find_last_ipv6_fragment_hbho_frag(void) "Last header position wrong"); zassert_equal(NET_IPV6_HDR(pkt)->nexthdr, 0, "Invalid next header"); - zassert_equal(pkt->frags->data[next_hdr_idx], 0x11, "Invalid next " - "header"); + zassert_equal(pkt->frags->data[next_hdr_idx], 0x11, + "Invalid next header"); + + net_pkt_unref(pkt); +} + +static void test_find_last_ipv6_fragment_hbho_frag_1(void) +{ + u16_t next_hdr_idx = 0; + u16_t last_hdr_pos = 0; + struct net_pkt *pkt; + struct net_buf *frag; + u8_t next_hdr; + u8_t last_hdr; + int ret; + + pkt = net_pkt_get_reserve_tx(0, ALLOC_TIMEOUT); + zassert_not_null(pkt, "packet"); + + net_pkt_set_iface(pkt, iface1); + net_pkt_set_family(pkt, AF_INET6); + net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); + + /* Add IPv6 header + HBH option + fragment header */ + ret = net_pkt_append_all(pkt, sizeof(ipv6_hbho_frag_1), + ipv6_hbho_frag_1, ALLOC_TIMEOUT); + zassert_true(ret, "IPv6 header append failed"); + + net_pkt_ll_clear(pkt); + + ret = net_ipv6_find_last_ext_hdr(pkt, &next_hdr_idx, &last_hdr_pos); + zassert_equal(ret, 0, "Cannot find last header"); + + zassert_equal(next_hdr_idx, 1072, "Next header index wrong"); + zassert_equal(last_hdr_pos, 1080, "Last header position wrong"); + + frag = net_frag_read_u8(pkt->frags, next_hdr_idx, &next_hdr_idx, + &next_hdr); + + zassert_equal(next_hdr, 0x3a, "Invalid next header"); + + frag = net_frag_read_u8(pkt->frags, last_hdr_pos, &last_hdr_pos, + &last_hdr); + + zassert_equal(last_hdr, 0x80, "Invalid next header"); net_pkt_unref(pkt); } @@ -624,6 +1524,8 @@ static void test_send_ipv6_fragment(void) size_t total_len; int i, ret; + large_hbho = false; + pkt_data_len = 0; pkt = net_pkt_get_reserve_tx(0, ALLOC_TIMEOUT); @@ -632,7 +1534,7 @@ static void test_send_ipv6_fragment(void) net_pkt_set_iface(pkt, iface1); net_pkt_set_family(pkt, AF_INET6); net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); - net_pkt_set_ipv6_ext_len(pkt, 8 + 8); /* hbho + udp */ + net_pkt_set_ipv6_ext_len(pkt, 8); /* hbho */ /* Add IPv6 header + HBH option */ ret = net_pkt_append_all(pkt, sizeof(ipv6_hbho), ipv6_hbho, @@ -658,7 +1560,7 @@ static void test_send_ipv6_fragment(void) DBG("Sending %zd bytes of which ext %d and data %d bytes\n", total_len, net_pkt_ipv6_ext_len(pkt), pkt_data_len); - zassert_equal(total_len - net_pkt_ipv6_ext_len(pkt), pkt_data_len, + zassert_equal(total_len - net_pkt_ipv6_ext_len(pkt) - 8, pkt_data_len, "Packet size invalid"); NET_IPV6_HDR(pkt)->len[0] = total_len / 256; @@ -681,6 +1583,49 @@ static void test_send_ipv6_fragment(void) } } +static void test_send_ipv6_fragment_large_hbho(void) +{ + struct net_pkt *pkt; + size_t total_len; + int ret; + + frag_count = 0; + large_hbho = true; + pkt_data_len = 416; + + pkt = net_pkt_get_reserve_tx(0, ALLOC_TIMEOUT); + zassert_not_null(pkt, "packet"); + + net_pkt_set_iface(pkt, iface1); + net_pkt_set_family(pkt, AF_INET6); + net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr)); + net_pkt_set_ipv6_ext_len(pkt, 1032); /* hbho */ + + ret = net_pkt_append_all(pkt, sizeof(ipv6_large_hbho), + ipv6_large_hbho, ALLOC_TIMEOUT); + zassert_true(ret, "IPv6 header append failed"); + + net_pkt_ll_clear(pkt); + + total_len = net_pkt_get_len(pkt) - sizeof(struct net_ipv6_hdr); + + DBG("Sending %zd bytes of which ext %d and data %d bytes\n", + total_len, net_pkt_ipv6_ext_len(pkt), pkt_data_len); + + test_failed = false; + + ret = net_send_data(pkt); + if (ret < 0) { + DBG("Cannot send test packet (%d)\n", ret); + zassert_equal(ret, 0, "Cannot send"); + } + + if (k_sem_take(&wait_data, WAIT_TIME)) { + DBG("Timeout while waiting interface data\n"); + zassert_equal(ret, 0, "Timeout"); + } +} + static void test_recv_ipv6_fragment(void) { /* TODO: Verify that we can receive individual fragments and @@ -694,8 +1639,15 @@ void test_main(void) ztest_unit_test(test_setup), ztest_unit_test(test_find_last_ipv6_fragment_udp), ztest_unit_test(test_find_last_ipv6_fragment_hbho_udp), - ztest_unit_test(test_find_last_ipv6_fragment_hbho_frag), + ztest_unit_test(test_find_last_ipv6_fragment_hbho_1), + ztest_unit_test(test_find_last_ipv6_fragment_hbho_2), + ztest_unit_test(test_find_last_ipv6_fragment_hbho_3), + ztest_unit_test( + test_find_last_ipv6_fragment_hbho_frag), + ztest_unit_test( + test_find_last_ipv6_fragment_hbho_frag_1), ztest_unit_test(test_send_ipv6_fragment), + ztest_unit_test(test_send_ipv6_fragment_large_hbho), ztest_unit_test(test_recv_ipv6_fragment) ); diff --git a/tests/net/net_pkt/src/main.c b/tests/net/net_pkt/src/main.c index c790b45a40d..861064e92b3 100644 --- a/tests/net/net_pkt/src/main.c +++ b/tests/net/net_pkt/src/main.c @@ -987,89 +987,166 @@ static void test_fragment_compact(void) DBG("test_fragment_compact passed\n"); } -static const char frag_data[CONFIG_NET_BUF_DATA_SIZE] = { 42 }; - +static const char frag_data[512] = { 42 }; static void test_fragment_split(void) { -#define TEST_FRAG_COUNT (FRAG_COUNT - 2) -#define FRAGA (FRAG_COUNT - 2) -#define FRAGB (FRAG_COUNT - 1) struct net_pkt *pkt; - struct net_buf *frags[FRAG_COUNT], *frag, *frag_a, *frag_b; - int i, total, split_a, split_b; - int ret, frag_size; - - memset(frags, 0, FRAG_COUNT * sizeof(void *)); + struct net_buf *rest; + int ret; pkt = net_pkt_get_reserve_rx(0, K_FOREVER); - frag = NULL; - for (i = 0, total = 0; i < TEST_FRAG_COUNT; i++) { - frags[i] = net_pkt_get_reserve_rx_data(12, K_FOREVER); + ret = net_pkt_append(pkt, 50, (u8_t *) frag_data, K_FOREVER); - if (frag) { - net_buf_frag_add(frag, frags[i]); - } + zassert_false(!ret, "Failed to append data"); - frag = frags[i]; + ret = net_pkt_split(pkt, pkt->frags, 10, &rest, K_FOREVER); - /* Copy some test data in front of the fragment */ - memcpy(net_buf_add(frags[i], sizeof(frag_data)), - frag_data, sizeof(frag_data)); + zassert_false(ret, "Failed to split net_pkt at offset 10"); + zassert_false(!pkt->frags, "Failed to split net_pkt at offset 10"); + zassert_false(!rest, "Failed to split net_pkt at offset 10"); - total++; - } + net_pkt_unref(pkt); + net_buf_unref(rest); - if (total != TEST_FRAG_COUNT) { - printk("There should be %d fragments but was %d\n", - TEST_FRAG_COUNT, total); - zassert_true(false, "Frags missing"); - } + pkt = net_pkt_get_reserve_rx(0, K_FOREVER); - frag_size = frags[0]->size; - zassert_true(frag_size > 0, "Invalid frag size"); + ret = net_pkt_append(pkt, 100, (u8_t *) frag_data, K_FOREVER); - net_pkt_frag_add(pkt, frags[0]); + zassert_false(!ret, "Failed to append data"); - frag_a = frags[FRAGA]; - frag_b = frags[FRAGB]; + ret = net_pkt_split(pkt, pkt->frags, 100, &rest, K_FOREVER); - zassert_is_null(frag_a, "frag_a is not NULL"); - zassert_is_null(frag_b, "frag_b is not NULL"); + zassert_false(ret, "Failed to split net_pkt at offset 100"); + zassert_false(!pkt->frags, + "Failed to split net_pkt at offset 100"); + zassert_false(rest, "Failed to split net_pkt at offset 100"); - split_a = frag_size * 2 / 3; - split_b = frag_size - split_a; + net_pkt_unref(pkt); - zassert_true(split_a > 0, "A size is 0"); - zassert_true(split_a > split_b, "A is smaller than B"); + pkt = net_pkt_get_reserve_rx(0, K_FOREVER); - /* Test some error cases first */ - ret = net_pkt_split(NULL, NULL, 1024, &frag_a, &frag_b, K_NO_WAIT); - zassert_equal(ret, -EINVAL, "Invalid buf pointers"); + ret = net_pkt_append(pkt, 100, (u8_t *) frag_data, K_FOREVER); - ret = net_pkt_split(pkt, pkt->frags, CONFIG_NET_BUF_DATA_SIZE + 1, - &frag_a, &frag_b, K_NO_WAIT); - zassert_equal(ret, 0, "Split failed"); + zassert_false(!ret, "Failed to append data"); - ret = net_pkt_split(pkt, pkt->frags, split_a, - &frag_a, &frag_b, K_NO_WAIT); - zassert_equal(ret, 0, "Cannot split frag"); + ret = net_pkt_split(pkt, pkt->frags, 50, &rest, K_FOREVER); - if (frag_a->len != split_a) { - printk("Frag_a len %d not %d\n", frag_a->len, split_a); - zassert_equal(frag_a->len, split_a, "Frag_a len wrong"); - } + zassert_false(ret, "Failed to split net_pkt at offset 50"); + zassert_false(!pkt->frags, + "Failed to split net_pkt at offset 50"); + zassert_false(!rest, "Failed to split net_pkt at offset 50"); - if (frag_b->len != split_b) { - printk("Frag_b len %d not %d\n", frag_b->len, split_b); - zassert_true(false, "Frag_b len wrong"); - } + zassert_false(net_pkt_get_len(pkt) != 50, + "Failed to split net_pkt at offset 50"); + zassert_false(net_buf_frags_len(rest) != 50, + "Failed to split net_pkt at offset 50"); - zassert_false(memcmp(pkt->frags->data, frag_a->data, split_a), - "Frag_a data mismatch"); + net_pkt_unref(pkt); + net_buf_unref(rest); - zassert_false(memcmp(pkt->frags->data + split_a, frag_b->data, split_b), - "Frag_b data mismatch"); + pkt = net_pkt_get_reserve_rx(0, K_FOREVER); + + ret = net_pkt_append(pkt, 350, (u8_t *) frag_data, K_FOREVER); + + zassert_false(!ret, "Failed to append data"); + + ret = net_pkt_split(pkt, pkt->frags, 150, &rest, K_FOREVER); + + zassert_false(ret, "Failed to split net_pkt at offset 150"); + zassert_false(!pkt->frags, + "Failed to split net_pkt at offset 150"); + zassert_false(!rest, "Failed to split net_pkt at offset 150"); + + zassert_false(net_pkt_get_len(pkt) != 150, + "Failed to split net_pkt at offset 150"); + zassert_false(net_buf_frags_len(rest) != 200, + "Failed to split net_pkt at offset 150"); + + net_pkt_unref(pkt); + net_buf_unref(rest); + + pkt = net_pkt_get_reserve_rx(0, K_FOREVER); + + ret = net_pkt_append(pkt, 512, (u8_t *) frag_data, K_FOREVER); + + zassert_false(!ret, "Failed to append data"); + + ret = net_pkt_split(pkt, pkt->frags, 500, &rest, K_FOREVER); + + zassert_false(ret, "Failed to split net_pkt at offset 500"); + zassert_false(!pkt->frags, + "Failed to split net_pkt at offset 500"); + zassert_false(!rest, "Failed to split net_pkt at offset 500"); + + zassert_false(net_pkt_get_len(pkt) != 500, + "Failed to split net_pkt at offset 500"); + zassert_false(net_buf_frags_len(rest) != 12, + "Failed to split net_pkt at offset 500"); + + net_pkt_unref(pkt); + net_buf_unref(rest); +} + +static const char pull_test_data[] = + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz " + "abcdefghijklmnopqrstuvxyz "; + +static void test_pkt_pull(void) +{ + struct net_pkt *pkt; + u16_t ret; + int res; + + pkt = net_pkt_get_reserve_rx(0, K_FOREVER); + net_pkt_set_ll_reserve(pkt, LL_RESERVE); + + ret = net_pkt_append(pkt, sizeof(pull_test_data), (u8_t *) + pull_test_data, K_FOREVER); + + zassert_false(!ret, "Failed to append data"); + + res = net_pkt_pull(pkt, 0, 10); + + zassert_true(res == 0, "Failed to pull 10 bytes from offset 0"); + + res = net_pkt_pull(pkt, 10, 20); + + zassert_true(res == 0, "Failed to pull 10 bytes from offset 0"); + + res = net_pkt_pull(pkt, 140, 150); + + zassert_true(res == 0, "Failed to pull 10 bytes from offset 0"); + + res = net_pkt_pull(pkt, 42, 72); + + zassert_true(res == 0, "Failed to pull 10 bytes from offset 0"); + + res = net_pkt_pull(pkt, 0, 42); + + zassert_true(res == 0, "Failed to pull 10 bytes from offset 0"); + + res = net_pkt_pull(pkt, 138, 69); + + zassert_true(res == 0, "Failed to pull 10 bytes from offset 0"); } void test_main(void) @@ -1080,7 +1157,8 @@ void test_main(void) ztest_unit_test(test_pkt_read_append), ztest_unit_test(test_pkt_read_write_insert), ztest_unit_test(test_fragment_compact), - ztest_unit_test(test_fragment_split) + ztest_unit_test(test_fragment_split), + ztest_unit_test(test_pkt_pull) ); ztest_run_test_suite(net_pkt_tests);