diff options
author | Patrick McHardy <kaber@trash.net> | 2006-01-07 02:03:34 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-01-07 15:57:31 -0500 |
commit | b05e106698d9966de524e78d9da1bf6407fe0c32 (patch) | |
tree | 8a7c253b7249451941674805cccdaaba299dff6f /net | |
parent | 951dbc8ac714b04c36296b8b5c36c8e036ce433f (diff) |
[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: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/xfrm4_input.c | 31 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_input.c | 13 |
3 files changed, 45 insertions, 1 deletions
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 2d3849c38a0f..850d919591d1 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
@@ -11,6 +11,8 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv4.h> | ||
14 | #include <net/inet_ecn.h> | 16 | #include <net/inet_ecn.h> |
15 | #include <net/ip.h> | 17 | #include <net/ip.h> |
16 | #include <net/xfrm.h> | 18 | #include <net/xfrm.h> |
@@ -45,6 +47,23 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) | |||
45 | return xfrm_parse_spi(skb, nexthdr, spi, seq); | 47 | return xfrm_parse_spi(skb, nexthdr, spi, seq); |
46 | } | 48 | } |
47 | 49 | ||
50 | #ifdef CONFIG_NETFILTER | ||
51 | static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) | ||
52 | { | ||
53 | struct iphdr *iph = skb->nh.iph; | ||
54 | |||
55 | if (skb->dst == NULL) { | ||
56 | if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, | ||
57 | skb->dev)) | ||
58 | goto drop; | ||
59 | } | ||
60 | return dst_input(skb); | ||
61 | drop: | ||
62 | kfree_skb(skb); | ||
63 | return NET_RX_DROP; | ||
64 | } | ||
65 | #endif | ||
66 | |||
48 | int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | 67 | int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) |
49 | { | 68 | { |
50 | int err; | 69 | int err; |
@@ -137,6 +156,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | |||
137 | memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); | 156 | memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); |
138 | skb->sp->len += xfrm_nr; | 157 | skb->sp->len += xfrm_nr; |
139 | 158 | ||
159 | nf_reset(skb); | ||
160 | |||
140 | if (decaps) { | 161 | if (decaps) { |
141 | if (!(skb->dev->flags&IFF_LOOPBACK)) { | 162 | if (!(skb->dev->flags&IFF_LOOPBACK)) { |
142 | dst_release(skb->dst); | 163 | dst_release(skb->dst); |
@@ -145,7 +166,17 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | |||
145 | netif_rx(skb); | 166 | netif_rx(skb); |
146 | return 0; | 167 | return 0; |
147 | } else { | 168 | } else { |
169 | #ifdef CONFIG_NETFILTER | ||
170 | __skb_push(skb, skb->data - skb->nh.raw); | ||
171 | skb->nh.iph->tot_len = htons(skb->len); | ||
172 | ip_send_check(skb->nh.iph); | ||
173 | |||
174 | NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, | ||
175 | xfrm4_rcv_encap_finish); | ||
176 | return 0; | ||
177 | #else | ||
148 | return -skb->nh.iph->protocol; | 178 | return -skb->nh.iph->protocol; |
179 | #endif | ||
149 | } | 180 | } |
150 | 181 | ||
151 | drop_unlock: | 182 | drop_unlock: |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 13d724150f33..29f73592e68e 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -48,7 +48,7 @@ | |||
48 | 48 | ||
49 | 49 | ||
50 | 50 | ||
51 | static inline int ip6_rcv_finish( struct sk_buff *skb) | 51 | inline int ip6_rcv_finish( struct sk_buff *skb) |
52 | { | 52 | { |
53 | if (skb->dst == NULL) | 53 | if (skb->dst == NULL) |
54 | ip6_route_input(skb); | 54 | ip6_route_input(skb); |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 1079e47f3933..1ca2da68ef69 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -11,6 +11,8 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv6.h> | ||
14 | #include <net/dsfield.h> | 16 | #include <net/dsfield.h> |
15 | #include <net/inet_ecn.h> | 17 | #include <net/inet_ecn.h> |
16 | #include <net/ip.h> | 18 | #include <net/ip.h> |
@@ -121,6 +123,8 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi) | |||
121 | skb->sp->len += xfrm_nr; | 123 | skb->sp->len += xfrm_nr; |
122 | skb->ip_summed = CHECKSUM_NONE; | 124 | skb->ip_summed = CHECKSUM_NONE; |
123 | 125 | ||
126 | nf_reset(skb); | ||
127 | |||
124 | if (decaps) { | 128 | if (decaps) { |
125 | if (!(skb->dev->flags&IFF_LOOPBACK)) { | 129 | if (!(skb->dev->flags&IFF_LOOPBACK)) { |
126 | dst_release(skb->dst); | 130 | dst_release(skb->dst); |
@@ -129,7 +133,16 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi) | |||
129 | netif_rx(skb); | 133 | netif_rx(skb); |
130 | return -1; | 134 | return -1; |
131 | } else { | 135 | } else { |
136 | #ifdef CONFIG_NETFILTER | ||
137 | skb->nh.ipv6h->payload_len = htons(skb->len); | ||
138 | __skb_push(skb, skb->data - skb->nh.raw); | ||
139 | |||
140 | NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, | ||
141 | ip6_rcv_finish); | ||
142 | return -1; | ||
143 | #else | ||
132 | return 1; | 144 | return 1; |
145 | #endif | ||
133 | } | 146 | } |
134 | 147 | ||
135 | drop_unlock: | 148 | drop_unlock: |