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 {
* @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,
......
......@@ -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();
......
......@@ -9,6 +9,7 @@
*
*/
#include <linux/string.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/xfrm.h>
......@@ -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;
......
......@@ -9,17 +9,20 @@
* IPv6 support
*/
#include <linux/string.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/xfrm.h>
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;
}
......
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