summaryrefslogtreecommitdiff
path: root/net/xfrm/xfrm_output.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2021-06-11 12:50:12 +0200
committerSteffen Klassert <steffen.klassert@secunet.com>2021-06-11 14:48:50 +0200
commit848b18fb7fbd2fa5bc4fc2263bb69956fb86120d (patch)
treecf5087cba7fa96549664c68223e46d68de845140 /net/xfrm/xfrm_output.c
parent37b9e7eb55659b270f0e8aebd98308716d935586 (diff)
xfrm: ipv6: move mip6_rthdr_offset into xfrm core
Place the call into the xfrm core. After this all remaining users set the hdr_offset function pointer to the same function which opens the possiblity to remove the indirection. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm/xfrm_output.c')
-rw-r--r--net/xfrm/xfrm_output.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 29959054a535..1734339b6dd0 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -123,6 +123,53 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
return offset;
}
+
+static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
+ u8 **nexthdr)
+{
+ u16 offset = sizeof(struct ipv6hdr);
+ struct ipv6_opt_hdr *exthdr =
+ (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
+ const unsigned char *nh = skb_network_header(skb);
+ unsigned int packet_len = skb_tail_pointer(skb) -
+ skb_network_header(skb);
+ int found_rhdr = 0;
+
+ *nexthdr = &ipv6_hdr(skb)->nexthdr;
+
+ while (offset + 1 <= packet_len) {
+ switch (**nexthdr) {
+ case NEXTHDR_HOP:
+ break;
+ case NEXTHDR_ROUTING:
+ if (offset + 3 <= packet_len) {
+ struct ipv6_rt_hdr *rt;
+
+ rt = (struct ipv6_rt_hdr *)(nh + offset);
+ if (rt->type != 0)
+ return offset;
+ }
+ found_rhdr = 1;
+ break;
+ case NEXTHDR_DEST:
+ if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
+ return offset;
+
+ if (found_rhdr)
+ return offset;
+
+ break;
+ default:
+ return offset;
+ }
+
+ offset += ipv6_optlen(exthdr);
+ *nexthdr = &exthdr->nexthdr;
+ exthdr = (struct ipv6_opt_hdr *)(nh + offset);
+ }
+
+ return offset;
+}
#endif
static int xfrm6_hdr_offset(struct xfrm_state *x, struct sk_buff *skb, u8 **prevhdr)
@@ -131,6 +178,8 @@ static int xfrm6_hdr_offset(struct xfrm_state *x, struct sk_buff *skb, u8 **prev
#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPPROTO_DSTOPTS:
return mip6_destopt_offset(x, skb, prevhdr);
+ case IPPROTO_ROUTING:
+ return mip6_rthdr_offset(x, skb, prevhdr);
#endif
default:
break;