Skip to content

Commit

Permalink
seg6: export get_srh() for ICMP handling
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: David Ahern <[email protected]>
Reviewed-by: Willem de Bruijn <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
lunn authored and davem330 committed Jan 4, 2022
1 parent e8fe9e8 commit fa55a7d
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 31 deletions.
1 change: 1 addition & 0 deletions include/net/seg6.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extern int seg6_local_init(void);
extern void seg6_local_exit(void);

extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced);
extern struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags);
extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
int proto);
extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
Expand Down
29 changes: 29 additions & 0 deletions net/ipv6/seg6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {
Expand Down
33 changes: 2 additions & 31 deletions net/ipv6/seg6_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,40 +150,11 @@ static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt)
return (struct seg6_local_lwt *)lwt->data;
}

static struct ipv6_sr_hdr *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 ipv6_sr_hdr *get_and_validate_srh(struct sk_buff *skb)
{
struct ipv6_sr_hdr *srh;

srh = get_srh(skb, IP6_FH_F_SKIP_RH);
srh = seg6_get_srh(skb, IP6_FH_F_SKIP_RH);
if (!srh)
return NULL;

Expand All @@ -200,7 +171,7 @@ static bool decap_and_validate(struct sk_buff *skb, int proto)
struct ipv6_sr_hdr *srh;
unsigned int off = 0;

srh = get_srh(skb, 0);
srh = seg6_get_srh(skb, 0);
if (srh && srh->segments_left > 0)
return false;

Expand Down

0 comments on commit fa55a7d

Please sign in to comment.