net: ipv6: Add helper to get the last extension header

Figure out what is the last extension header in IPv6 packet
and return offset to it. This is needed by IPv6 fragmentation
when fragmentation header is added to the packet.

Change-Id: I925ab806a5de076a425ff354711730d4f4b3c52f
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2017-04-03 22:18:35 +03:00
commit d8feb0a0e4
2 changed files with 73 additions and 0 deletions

View file

@ -390,6 +390,69 @@ struct in6_addr *net_ipv6_nbr_lookup_by_index(struct net_if *iface,
}
#endif /* CONFIG_NET_IPV6_NBR_CACHE */
int net_ipv6_find_last_ext_hdr(struct net_buf *buf)
{
struct net_ipv6_hdr *hdr = NET_IPV6_BUF(buf);
struct net_buf *frag = buf->frags;
int pos = 6; /* Initial value if no extension fragments were found */
uint16_t offset;
uint8_t next_hdr;
uint8_t length;
uint8_t next;
offset = sizeof(struct net_ipv6_hdr);
next = hdr->nexthdr;
while (frag) {
frag = net_nbuf_read_u8(frag, offset, &offset, &next_hdr);
if (frag != buf->frags) {
break;
}
frag = net_nbuf_read_u8(frag, offset, &offset, &length);
if (!frag && offset == 0xffff) {
pos = -EINVAL;
goto fail;
}
length = length * 8 + 8;
switch (next) {
case NET_IPV6_NEXTHDR_NONE:
pos = offset;
goto out;
case NET_IPV6_NEXTHDR_HBHO:
pos = offset;
offset += length;
break;
case NET_IPV6_NEXTHDR_FRAG:
pos = offset;
offset += sizeof(struct net_ipv6_frag_hdr);
goto out;
case IPPROTO_ICMPV6:
case IPPROTO_UDP:
case IPPROTO_TCP:
pos = offset;
goto out;
default:
pos = -EINVAL;
goto fail;
}
}
out:
if (pos > frag->len) {
pos = -EINVAL;
}
fail:
return pos;
}
const struct in6_addr *net_ipv6_unspecified_address(void)
{
static const struct in6_addr addr = IN6ADDR_ANY_INIT;

View file

@ -413,6 +413,16 @@ void net_ipv6_frag_foreach(net_ipv6_frag_cb_t cb, void *user_data);
#endif /* CONFIG_NET_IPV6_FRAGMENT */
/**
* @brief Find the last IPv6 extension header in the network packet.
*
* @param buf Network head buffer.
*
* @return Offset to the extension header within the first fragment of net_buf.
* Return <0 if the packet is malformed.
*/
int net_ipv6_find_last_ext_hdr(struct net_buf *buf);
#if defined(CONFIG_NET_IPV6)
void net_ipv6_init(void);
#else