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

[IPSEC]: Call xfrm6_rcv in xfrm6_tunnel_rcv

This patch reuses the code in xfrm6_input.c for receiving xfrm6_tunnel
packets.  This removes duplicate code as well as fixing the bugs unique
to xfrm6_tunnel_input.  For example, it didn't move the MAC header down.
Nor did it do anything with ECN.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent 1126996a
...@@ -780,6 +780,7 @@ extern int xfrm4_rcv(struct sk_buff *skb); ...@@ -780,6 +780,7 @@ extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_output(struct sk_buff **pskb); extern int xfrm4_output(struct sk_buff **pskb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
extern int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi);
extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp); extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler); extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler); extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* IPv6 support * IPv6 support
*/ */
#include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/ip.h> #include <net/ip.h>
...@@ -25,11 +26,11 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) ...@@ -25,11 +26,11 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
IP6_ECN_set_ce(inner_iph); IP6_ECN_set_ce(inner_iph);
} }
int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
{ {
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
int err; int err;
u32 spi, seq; u32 seq;
struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH]; struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
struct xfrm_state *x; struct xfrm_state *x;
int xfrm_nr = 0; int xfrm_nr = 0;
...@@ -40,7 +41,8 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) ...@@ -40,7 +41,8 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
nhoff = *nhoffp; nhoff = *nhoffp;
nexthdr = skb->nh.raw[nhoff]; nexthdr = skb->nh.raw[nhoff];
if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) seq = 0;
if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
goto drop; goto drop;
do { do {
...@@ -137,3 +139,10 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) ...@@ -137,3 +139,10 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
kfree_skb(skb); kfree_skb(skb);
return -1; return -1;
} }
EXPORT_SYMBOL(xfrm6_rcv_spi);
int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{
return xfrm6_rcv_spi(pskb, nhoffp, 0);
}
...@@ -356,17 +356,6 @@ static int xfrm6_tunnel_output(struct sk_buff **pskb) ...@@ -356,17 +356,6 @@ static int xfrm6_tunnel_output(struct sk_buff **pskb)
static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
{ {
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
return -EINVAL;
skb->mac.raw = skb->nh.raw;
skb->nh.raw = skb->data;
dst_release(skb->dst);
skb->dst = NULL;
skb->protocol = htons(ETH_P_IPV6);
skb->pkt_type = PACKET_HOST;
netif_rx(skb);
return 0; return 0;
} }
...@@ -413,49 +402,15 @@ static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp) ...@@ -413,49 +402,15 @@ static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
struct xfrm_state *x = NULL;
struct ipv6hdr *iph = skb->nh.ipv6h; struct ipv6hdr *iph = skb->nh.ipv6h;
int err = 0;
u32 spi; u32 spi;
/* device-like_ip6ip6_handler() */ /* device-like_ip6ip6_handler() */
if (handler) { if (handler && handler->handler(pskb, nhoffp) == 0)
err = handler->handler(pskb, nhoffp);
if (!err)
goto out;
}
spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr,
spi,
IPPROTO_IPV6, AF_INET6);
if (!x)
goto drop;
spin_lock(&x->lock);
if (unlikely(x->km.state != XFRM_STATE_VALID))
goto drop_unlock;
err = xfrm6_tunnel_input(x, NULL, skb);
if (err)
goto drop_unlock;
x->curlft.bytes += skb->len;
x->curlft.packets++;
spin_unlock(&x->lock);
xfrm_state_put(x);
out:
return 0; return 0;
drop_unlock: spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
spin_unlock(&x->lock); return xfrm6_rcv_spi(pskb, nhoffp, spi);
xfrm_state_put(x);
drop:
kfree_skb(skb);
return -1;
} }
static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
......
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