Skip to content

Commit

Permalink
ipv6: sr: fix get_srh() to comply with IPv6 standard "RFC 8200"
Browse files Browse the repository at this point in the history
IPv6 packet may carry more than one extension header, and IPv6 nodes must
accept and attempt to process extension headers in any order and occurring
any number of times in the same packet. Hence, there should be no
assumption that Segment Routing extension header is to appear immediately
after the IPv6 header.

Moreover, section 4.1 of RFC 8200 gives a recommendation on the order of
appearance of those extension headers within an IPv6 packet. According to
this recommendation, Segment Routing extension header should appear after
Hop-by-Hop and Destination Options headers (if they present).

This patch fixes the get_srh(), so it gets the segment routing header
regardless of its position in the chain of the extension headers in IPv6
packet, and makes sure that the IPv6 routing extension header is of Type 4.

Signed-off-by: Ahmed Abdelsalam <amsalam20@gmail.com>
Acked-by: David Lebrun <david.lebrun@uclouvain.be>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ahmed Abdelsalam authored and David S. Miller committed Aug 30, 2017
1 parent 35aed4a commit 5829d70
Showing 1 changed file with 12 additions and 6 deletions.
18 changes: 12 additions & 6 deletions net/ipv6/seg6_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,23 @@ static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt)
static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb)
{
struct ipv6_sr_hdr *srh;
struct ipv6hdr *hdr;
int len;
int len, srhoff = 0;

if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
return NULL;

if (!pskb_may_pull(skb, srhoff + sizeof(*srh)))
return NULL;

srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);

hdr = ipv6_hdr(skb);
if (hdr->nexthdr != IPPROTO_ROUTING)
/* make sure it's a Segment Routing header (Routing Type 4) */
if (srh->type != IPV6_SRCRT_TYPE_4)
return NULL;

srh = (struct ipv6_sr_hdr *)(hdr + 1);
len = (srh->hdrlen + 1) << 3;

if (!pskb_may_pull(skb, sizeof(*hdr) + len))
if (!pskb_may_pull(skb, srhoff + len))
return NULL;

if (!seg6_validate_srh(srh, len))
Expand Down

0 comments on commit 5829d70

Please sign in to comment.