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:
parent
ea17e9d321
commit
d8feb0a0e4
2 changed files with 73 additions and 0 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue