From 8daca41052eee6c4b88e0313653f520745150d28 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 13 Feb 2004 07:06:58 -0800 Subject: [PATCH] [IPSEC]: Move hardware headers for decaped packets. Move the hardware header so that it appears next to the payload for AF_PACKET sockets. --- include/linux/skbuff.h | 3 +++ net/core/dev.c | 1 + net/ipv4/xfrm4_input.c | 18 +++++++++++++----- net/ipv6/xfrm6_input.c | 25 +++++++++++++++++-------- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index e12d9bc152da3..56590cedc22cb 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -163,6 +163,7 @@ struct skb_shared_info { * @cb: Control buffer. Free for use by every layer. Put private vars here * @len: Length of actual data * @data_len: Data length + * @mac_len: Length of link layer header * @csum: Checksum * @__unused: Dead field, may be reused * @cloned: Head may be cloned (check refcnt to be sure) @@ -204,6 +205,7 @@ struct sk_buff { struct icmphdr *icmph; struct igmphdr *igmph; struct iphdr *ipiph; + struct ipv6hdr *ipv6h; unsigned char *raw; } h; @@ -232,6 +234,7 @@ struct sk_buff { unsigned int len, data_len, + mac_len, csum; unsigned char local_df, cloned, diff --git a/net/core/dev.c b/net/core/dev.c index c10acfc613e7c..b2333ae5affe8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1742,6 +1742,7 @@ int netif_receive_skb(struct sk_buff *skb) #endif skb->h.raw = skb->nh.raw = skb->data; + skb->mac_len = skb->nh.raw - skb->mac.raw; pt_prev = NULL; rcu_read_lock(); diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 9040408dbf81d..b045c87197f13 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -9,6 +9,7 @@ * */ +#include #include #include #include @@ -18,9 +19,10 @@ int xfrm4_rcv(struct sk_buff *skb) return xfrm4_rcv_encap(skb, 0); } -static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb) +static inline void ipip_ecn_decapsulate(struct sk_buff *skb) { - struct iphdr *inner_iph = skb->nh.iph; + struct iphdr *outer_iph = skb->nh.iph; + struct iphdr *inner_iph = skb->h.ipiph; if (INET_ECN_is_ce(outer_iph->tos) && INET_ECN_is_not_ce(inner_iph->tos)) @@ -95,10 +97,16 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) if (x->props.mode) { if (iph->protocol != IPPROTO_IPIP) goto drop; - skb->nh.raw = skb->data; + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto drop; + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto drop; if (!(x->props.flags & XFRM_STATE_NOECN)) - ipip_ecn_decapsulate(iph, skb); - iph = skb->nh.iph; + ipip_ecn_decapsulate(skb); + skb->mac.raw = memmove(skb->data - skb->mac_len, + skb->mac.raw, skb->mac_len); + skb->nh.raw = skb->data; memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); decaps = 1; break; diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 6df399edce74d..c679a3ce4e165 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -9,17 +9,20 @@ * IPv6 support */ +#include #include #include #include #include -static inline void ipip6_ecn_decapsulate(struct ipv6hdr *iph, - struct sk_buff *skb) +static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) { - if (INET_ECN_is_ce(ip6_get_dsfield(iph)) && - INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h))) - IP6_ECN_set_ce(skb->nh.ipv6h); + struct ipv6hdr *outer_iph = skb->nh.ipv6h; + struct ipv6hdr *inner_iph = skb->h.ipv6h; + + if (INET_ECN_is_ce(ip6_get_dsfield(outer_iph)) && + INET_ECN_is_not_ce(ip6_get_dsfield(inner_iph))) + IP6_ECN_set_ce(inner_iph); } int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) @@ -77,10 +80,16 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) if (x->props.mode) { /* XXX */ if (nexthdr != IPPROTO_IPV6) goto drop; - skb->nh.raw = skb->data; + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) + goto drop; + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto drop; if (!(x->props.flags & XFRM_STATE_NOECN)) - ipip6_ecn_decapsulate(iph, skb); - iph = skb->nh.ipv6h; + ipip6_ecn_decapsulate(skb); + skb->mac.raw = memmove(skb->data - skb->mac_len, + skb->mac.raw, skb->mac_len); + skb->nh.raw = skb->data; decaps = 1; break; } -- 2.53.0