aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/xfrm.h6
-rw-r--r--net/ipv4/xfrm4_mode_beet.c11
-rw-r--r--net/ipv4/xfrm4_state.c2
-rw-r--r--net/ipv6/xfrm6_mode_beet.c1
-rw-r--r--net/ipv6/xfrm6_state.c2
5 files changed, 16 insertions, 6 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 4e6f9568cbe..0d255ae008b 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -552,6 +552,9 @@ struct xfrm_mode_skb_cb {
__be16 id;
__be16 frag_off;
+ /* IP header length (excluding options or extension headers). */
+ u8 ihl;
+
/* TOS for IPv4, class for IPv6. */
u8 tos;
@@ -561,6 +564,9 @@ struct xfrm_mode_skb_cb {
/* Protocol for IPv4, NH for IPv6. */
u8 protocol;
+ /* Option length for IPv4, zero for IPv6. */
+ u8 optlen;
+
/* Used by IPv6 only, zero for IPv4. */
u8 flow_lbl[3];
};
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index b47030ba162..9c798abce73 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -39,13 +39,11 @@ static void xfrm4_beet_make_header(struct sk_buff *skb)
static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct ip_beet_phdr *ph;
- struct iphdr *iph, *top_iph;
+ struct iphdr *top_iph;
int hdrlen, optlen;
- iph = ip_hdr(skb);
-
hdrlen = 0;
- optlen = iph->ihl * 4 - sizeof(*iph);
+ optlen = XFRM_MODE_SKB_CB(skb)->optlen;
if (unlikely(optlen))
hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
@@ -53,11 +51,12 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
hdrlen);
skb->mac_header = skb->network_header +
offsetof(struct iphdr, protocol);
- skb->transport_header = skb->network_header + sizeof(*iph);
+ skb->transport_header = skb->network_header + sizeof(*top_iph);
xfrm4_beet_make_header(skb);
- ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);
+ ph = (struct ip_beet_phdr *)
+ __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen);
top_iph = ip_hdr(skb);
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index fdeebe68a37..07735ed280d 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -52,10 +52,12 @@ int xfrm4_extract_header(struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
+ XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
XFRM_MODE_SKB_CB(skb)->id = iph->id;
XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off;
XFRM_MODE_SKB_CB(skb)->tos = iph->tos;
XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl;
+ XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph);
memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0,
sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 0527d11c1ae..d6ce400f585 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -45,6 +45,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
skb->mac_header = skb->network_header +
offsetof(struct ipv6hdr, nexthdr);
skb->transport_header = skb->network_header + sizeof(*top_iph);
+ __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl);
xfrm6_beet_make_header(skb);
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index dc817e035e2..ff1e1db8e23 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -174,10 +174,12 @@ int xfrm6_extract_header(struct sk_buff *skb)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
+ XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
XFRM_MODE_SKB_CB(skb)->id = 0;
XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF);
XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph);
XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit;
+ XFRM_MODE_SKB_CB(skb)->optlen = 0;
memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl,
sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));