Commit b05e1066 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[IPV4/6]: Netfilter IPsec input hooks

When the innermost transform uses transport mode the decapsulated packet
is not visible to netfilter. Pass the packet through the PRE_ROUTING and
LOCAL_IN hooks again before handing it to upper layer protocols to make
netfilter-visibility symetrical to the output path.
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 951dbc8a
...@@ -418,6 +418,8 @@ extern int ipv6_rcv(struct sk_buff *skb, ...@@ -418,6 +418,8 @@ extern int ipv6_rcv(struct sk_buff *skb,
struct packet_type *pt, struct packet_type *pt,
struct net_device *orig_dev); struct net_device *orig_dev);
extern int ip6_rcv_finish(struct sk_buff *skb);
/* /*
* upper-layer output functions * upper-layer output functions
*/ */
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.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>
...@@ -45,6 +47,23 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) ...@@ -45,6 +47,23 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
return xfrm_parse_spi(skb, nexthdr, spi, seq); return xfrm_parse_spi(skb, nexthdr, spi, seq);
} }
#ifdef CONFIG_NETFILTER
static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
if (skb->dst == NULL) {
if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
skb->dev))
goto drop;
}
return dst_input(skb);
drop:
kfree_skb(skb);
return NET_RX_DROP;
}
#endif
int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
{ {
int err; int err;
...@@ -137,6 +156,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) ...@@ -137,6 +156,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
skb->sp->len += xfrm_nr; skb->sp->len += xfrm_nr;
nf_reset(skb);
if (decaps) { if (decaps) {
if (!(skb->dev->flags&IFF_LOOPBACK)) { if (!(skb->dev->flags&IFF_LOOPBACK)) {
dst_release(skb->dst); dst_release(skb->dst);
...@@ -145,7 +166,17 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) ...@@ -145,7 +166,17 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
netif_rx(skb); netif_rx(skb);
return 0; return 0;
} else { } else {
#ifdef CONFIG_NETFILTER
__skb_push(skb, skb->data - skb->nh.raw);
skb->nh.iph->tot_len = htons(skb->len);
ip_send_check(skb->nh.iph);
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
xfrm4_rcv_encap_finish);
return 0;
#else
return -skb->nh.iph->protocol; return -skb->nh.iph->protocol;
#endif
} }
drop_unlock: drop_unlock:
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
static inline int ip6_rcv_finish( struct sk_buff *skb) inline int ip6_rcv_finish( struct sk_buff *skb)
{ {
if (skb->dst == NULL) if (skb->dst == NULL)
ip6_route_input(skb); ip6_route_input(skb);
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
#include <net/dsfield.h> #include <net/dsfield.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/ip.h> #include <net/ip.h>
...@@ -121,6 +123,8 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi) ...@@ -121,6 +123,8 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
skb->sp->len += xfrm_nr; skb->sp->len += xfrm_nr;
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
nf_reset(skb);
if (decaps) { if (decaps) {
if (!(skb->dev->flags&IFF_LOOPBACK)) { if (!(skb->dev->flags&IFF_LOOPBACK)) {
dst_release(skb->dst); dst_release(skb->dst);
...@@ -129,7 +133,16 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi) ...@@ -129,7 +133,16 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
netif_rx(skb); netif_rx(skb);
return -1; return -1;
} else { } else {
#ifdef CONFIG_NETFILTER
skb->nh.ipv6h->payload_len = htons(skb->len);
__skb_push(skb, skb->data - skb->nh.raw);
NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
ip6_rcv_finish);
return -1;
#else
return 1; return 1;
#endif
} }
drop_unlock: drop_unlock:
......
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