Commit 8daca410 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[IPSEC]: Move hardware headers for decaped packets.

Move the hardware header so that it appears next to the payload for AF_PACKET
sockets.
parent ecaaedc5
...@@ -163,6 +163,7 @@ struct skb_shared_info { ...@@ -163,6 +163,7 @@ struct skb_shared_info {
* @cb: Control buffer. Free for use by every layer. Put private vars here * @cb: Control buffer. Free for use by every layer. Put private vars here
* @len: Length of actual data * @len: Length of actual data
* @data_len: Data length * @data_len: Data length
* @mac_len: Length of link layer header
* @csum: Checksum * @csum: Checksum
* @__unused: Dead field, may be reused * @__unused: Dead field, may be reused
* @cloned: Head may be cloned (check refcnt to be sure) * @cloned: Head may be cloned (check refcnt to be sure)
...@@ -204,6 +205,7 @@ struct sk_buff { ...@@ -204,6 +205,7 @@ struct sk_buff {
struct icmphdr *icmph; struct icmphdr *icmph;
struct igmphdr *igmph; struct igmphdr *igmph;
struct iphdr *ipiph; struct iphdr *ipiph;
struct ipv6hdr *ipv6h;
unsigned char *raw; unsigned char *raw;
} h; } h;
...@@ -232,6 +234,7 @@ struct sk_buff { ...@@ -232,6 +234,7 @@ struct sk_buff {
unsigned int len, unsigned int len,
data_len, data_len,
mac_len,
csum; csum;
unsigned char local_df, unsigned char local_df,
cloned, cloned,
......
...@@ -1742,6 +1742,7 @@ int netif_receive_skb(struct sk_buff *skb) ...@@ -1742,6 +1742,7 @@ int netif_receive_skb(struct sk_buff *skb)
#endif #endif
skb->h.raw = skb->nh.raw = skb->data; skb->h.raw = skb->nh.raw = skb->data;
skb->mac_len = skb->nh.raw - skb->mac.raw;
pt_prev = NULL; pt_prev = NULL;
rcu_read_lock(); rcu_read_lock();
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* *
*/ */
#include <linux/string.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/xfrm.h> #include <net/xfrm.h>
...@@ -18,9 +19,10 @@ int xfrm4_rcv(struct sk_buff *skb) ...@@ -18,9 +19,10 @@ int xfrm4_rcv(struct sk_buff *skb)
return xfrm4_rcv_encap(skb, 0); 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) && if (INET_ECN_is_ce(outer_iph->tos) &&
INET_ECN_is_not_ce(inner_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) ...@@ -95,10 +97,16 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
if (x->props.mode) { if (x->props.mode) {
if (iph->protocol != IPPROTO_IPIP) if (iph->protocol != IPPROTO_IPIP)
goto drop; 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)) if (!(x->props.flags & XFRM_STATE_NOECN))
ipip_ecn_decapsulate(iph, skb); ipip_ecn_decapsulate(skb);
iph = skb->nh.iph; 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)); memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
decaps = 1; decaps = 1;
break; break;
......
...@@ -9,17 +9,20 @@ ...@@ -9,17 +9,20 @@
* IPv6 support * IPv6 support
*/ */
#include <linux/string.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/xfrm.h> #include <net/xfrm.h>
static inline void ipip6_ecn_decapsulate(struct ipv6hdr *iph, static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
struct sk_buff *skb)
{ {
if (INET_ECN_is_ce(ip6_get_dsfield(iph)) && struct ipv6hdr *outer_iph = skb->nh.ipv6h;
INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h))) struct ipv6hdr *inner_iph = skb->h.ipv6h;
IP6_ECN_set_ce(skb->nh.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) int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
...@@ -77,10 +80,16 @@ 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 (x->props.mode) { /* XXX */
if (nexthdr != IPPROTO_IPV6) if (nexthdr != IPPROTO_IPV6)
goto drop; 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)) if (!(x->props.flags & XFRM_STATE_NOECN))
ipip6_ecn_decapsulate(iph, skb); ipip6_ecn_decapsulate(skb);
iph = skb->nh.ipv6h; skb->mac.raw = memmove(skb->data - skb->mac_len,
skb->mac.raw, skb->mac_len);
skb->nh.raw = skb->data;
decaps = 1; decaps = 1;
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment