diff options
author | Andrew Lunn <andrew@lunn.ch> | 2022-01-03 18:11:30 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-01-04 13:17:35 +0100 |
commit | fa55a7d745de2d10489295b0674a403e2a5d490d (patch) | |
tree | acc2231d961e34eea340484bacbf1bcc15539deb /net/ipv6/seg6.c | |
parent | Merge tag 'batadv-net-pullrequest-20220103' of git://git.open-mesh.org/linux-... (diff) | |
download | linux-fa55a7d745de2d10489295b0674a403e2a5d490d.tar.xz linux-fa55a7d745de2d10489295b0674a403e2a5d490d.zip |
seg6: export get_srh() for ICMP handling
An ICMP error message can contain in its message body part of an IPv6
packet which invoked the error. Such a packet might contain a segment
router header. Export get_srh() so the ICMP code can make use of it.
Since his changes the scope of the function from local to global, add
the seg6_ prefix to keep the namespace clean. And move it into seg6.c
so it is always available, not just when IPV6_SEG6_LWTUNNEL is
enabled.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: David Ahern <dsahern@kernel.org>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/seg6.c')
-rw-r--r-- | net/ipv6/seg6.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c index a8b5784afb1a..5bc9bf892199 100644 --- a/net/ipv6/seg6.c +++ b/net/ipv6/seg6.c @@ -75,6 +75,35 @@ bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced) return true; } +struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags) +{ + struct ipv6_sr_hdr *srh; + int len, srhoff = 0; + + if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, &flags) < 0) + return NULL; + + if (!pskb_may_pull(skb, srhoff + sizeof(*srh))) + return NULL; + + srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); + + len = (srh->hdrlen + 1) << 3; + + if (!pskb_may_pull(skb, srhoff + len)) + return NULL; + + /* note that pskb_may_pull may change pointers in header; + * for this reason it is necessary to reload them when needed. + */ + srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); + + if (!seg6_validate_srh(srh, len, true)) + return NULL; + + return srh; +} + static struct genl_family seg6_genl_family; static const struct nla_policy seg6_genl_policy[SEG6_ATTR_MAX + 1] = { |