aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-02-27 18:22:14 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-27 18:22:14 -0500
commit272a5322d5219b00a1e541ad9d0d76824df1aa2a (patch)
tree2d27468bdb6b5c777f19c5aed2dafc2ec8682950
parent051d3cbd96909b2fe6b5038e7bbe77f41356db05 (diff)
parentba13c98405ba44d37d148376c6615e6c8babbfdc (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
-rw-r--r--include/linux/netfilter_bridge/ebt_log.h1
-rw-r--r--include/linux/netfilter_ipv4/ipt_LOG.h3
-rw-r--r--include/linux/netfilter_ipv6/ip6t_LOG.h3
-rw-r--r--include/net/xfrm.h1
-rw-r--r--net/bridge/netfilter/ebt_log.c7
-rw-r--r--net/core/request_sock.c1
-rw-r--r--net/ipv4/esp4.c185
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c7
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c7
-rw-r--r--net/netfilter/nf_queue.c42
-rw-r--r--net/xfrm/xfrm_policy.c7
11 files changed, 109 insertions, 155 deletions
diff --git a/include/linux/netfilter_bridge/ebt_log.h b/include/linux/netfilter_bridge/ebt_log.h
index 358fbc84fb59..96e231ae7554 100644
--- a/include/linux/netfilter_bridge/ebt_log.h
+++ b/include/linux/netfilter_bridge/ebt_log.h
@@ -3,6 +3,7 @@
3 3
4#define EBT_LOG_IP 0x01 /* if the frame is made by ip, log the ip information */ 4#define EBT_LOG_IP 0x01 /* if the frame is made by ip, log the ip information */
5#define EBT_LOG_ARP 0x02 5#define EBT_LOG_ARP 0x02
6#define EBT_LOG_NFLOG 0x04
6#define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP) 7#define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP)
7#define EBT_LOG_PREFIX_SIZE 30 8#define EBT_LOG_PREFIX_SIZE 30
8#define EBT_LOG_WATCHER "log" 9#define EBT_LOG_WATCHER "log"
diff --git a/include/linux/netfilter_ipv4/ipt_LOG.h b/include/linux/netfilter_ipv4/ipt_LOG.h
index 22d16177319b..892f9a33fea8 100644
--- a/include/linux/netfilter_ipv4/ipt_LOG.h
+++ b/include/linux/netfilter_ipv4/ipt_LOG.h
@@ -6,7 +6,8 @@
6#define IPT_LOG_TCPOPT 0x02 /* Log TCP options */ 6#define IPT_LOG_TCPOPT 0x02 /* Log TCP options */
7#define IPT_LOG_IPOPT 0x04 /* Log IP options */ 7#define IPT_LOG_IPOPT 0x04 /* Log IP options */
8#define IPT_LOG_UID 0x08 /* Log UID owning local socket */ 8#define IPT_LOG_UID 0x08 /* Log UID owning local socket */
9#define IPT_LOG_MASK 0x0f 9#define IPT_LOG_NFLOG 0x10 /* Log using nf_log backend */
10#define IPT_LOG_MASK 0x1f
10 11
11struct ipt_log_info { 12struct ipt_log_info {
12 unsigned char level; 13 unsigned char level;
diff --git a/include/linux/netfilter_ipv6/ip6t_LOG.h b/include/linux/netfilter_ipv6/ip6t_LOG.h
index 9008ff5c40ae..060c1a1c6c60 100644
--- a/include/linux/netfilter_ipv6/ip6t_LOG.h
+++ b/include/linux/netfilter_ipv6/ip6t_LOG.h
@@ -6,7 +6,8 @@
6#define IP6T_LOG_TCPOPT 0x02 /* Log TCP options */ 6#define IP6T_LOG_TCPOPT 0x02 /* Log TCP options */
7#define IP6T_LOG_IPOPT 0x04 /* Log IP options */ 7#define IP6T_LOG_IPOPT 0x04 /* Log IP options */
8#define IP6T_LOG_UID 0x08 /* Log UID owning local socket */ 8#define IP6T_LOG_UID 0x08 /* Log UID owning local socket */
9#define IP6T_LOG_MASK 0x0f 9#define IP6T_LOG_NFLOG 0x10 /* Log using nf_log backend */
10#define IP6T_LOG_MASK 0x1f
10 11
11struct ip6t_log_info { 12struct ip6t_log_info {
12 unsigned char level; 13 unsigned char level;
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 004e645f3e18..8d362c49b8a9 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -233,7 +233,6 @@ struct xfrm_type
233 int (*init_state)(struct xfrm_state *x); 233 int (*init_state)(struct xfrm_state *x);
234 void (*destructor)(struct xfrm_state *); 234 void (*destructor)(struct xfrm_state *);
235 int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); 235 int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
236 int (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
237 int (*output)(struct xfrm_state *, struct sk_buff *pskb); 236 int (*output)(struct xfrm_state *, struct sk_buff *pskb);
238 /* Estimate maximal size of result of transformation of a dgram */ 237 /* Estimate maximal size of result of transformation of a dgram */
239 u32 (*get_max_size)(struct xfrm_state *, int size); 238 u32 (*get_max_size)(struct xfrm_state *, int size);
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 0128fbbe2328..288ff1d4ccc4 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -166,7 +166,12 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
166 li.u.log.level = info->loglevel; 166 li.u.log.level = info->loglevel;
167 li.u.log.logflags = info->bitmask; 167 li.u.log.logflags = info->bitmask;
168 168
169 nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, info->prefix); 169 if (info->bitmask & EBT_LOG_NFLOG)
170 nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
171 info->prefix);
172 else
173 ebt_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
174 info->prefix);
170} 175}
171 176
172static struct ebt_watcher log = 177static struct ebt_watcher log =
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index b8203de5ff07..98f0fc923f91 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -52,7 +52,6 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
52 get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); 52 get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
53 rwlock_init(&queue->syn_wait_lock); 53 rwlock_init(&queue->syn_wait_lock);
54 queue->rskq_accept_head = queue->rskq_accept_head = NULL; 54 queue->rskq_accept_head = queue->rskq_accept_head = NULL;
55 queue->rskq_defer_accept = 0;
56 lopt->nr_table_entries = nr_table_entries; 55 lopt->nr_table_entries = nr_table_entries;
57 56
58 write_lock_bh(&queue->syn_wait_lock); 57 write_lock_bh(&queue->syn_wait_lock);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 73bfcae8af9c..09590f356086 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -12,13 +12,6 @@
12#include <net/protocol.h> 12#include <net/protocol.h>
13#include <net/udp.h> 13#include <net/udp.h>
14 14
15/* decapsulation data for use when post-processing */
16struct esp_decap_data {
17 xfrm_address_t saddr;
18 __u16 sport;
19 __u8 proto;
20};
21
22static int esp_output(struct xfrm_state *x, struct sk_buff *skb) 15static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
23{ 16{
24 int err; 17 int err;
@@ -150,6 +143,10 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
150 int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; 143 int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
151 int nfrags; 144 int nfrags;
152 int encap_len = 0; 145 int encap_len = 0;
146 u8 nexthdr[2];
147 struct scatterlist *sg;
148 u8 workbuf[60];
149 int padlen;
153 150
154 if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) 151 if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
155 goto out; 152 goto out;
@@ -185,122 +182,82 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
185 if (esp->conf.ivlen) 182 if (esp->conf.ivlen)
186 crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); 183 crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm));
187 184
188 { 185 sg = &esp->sgbuf[0];
189 u8 nexthdr[2];
190 struct scatterlist *sg = &esp->sgbuf[0];
191 u8 workbuf[60];
192 int padlen;
193
194 if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
195 sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
196 if (!sg)
197 goto out;
198 }
199 skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen);
200 crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
201 if (unlikely(sg != &esp->sgbuf[0]))
202 kfree(sg);
203
204 if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
205 BUG();
206 186
207 padlen = nexthdr[0]; 187 if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
208 if (padlen+2 >= elen) 188 sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
189 if (!sg)
209 goto out; 190 goto out;
210
211 /* ... check padding bits here. Silly. :-) */
212
213 if (x->encap && decap && decap->decap_type) {
214 struct esp_decap_data *encap_data;
215 struct udphdr *uh = (struct udphdr *) (iph+1);
216
217 encap_data = (struct esp_decap_data *) (decap->decap_data);
218 encap_data->proto = 0;
219
220 switch (decap->decap_type) {
221 case UDP_ENCAP_ESPINUDP:
222 case UDP_ENCAP_ESPINUDP_NON_IKE:
223 encap_data->proto = AF_INET;
224 encap_data->saddr.a4 = iph->saddr;
225 encap_data->sport = uh->source;
226 encap_len = (void*)esph - (void*)uh;
227 break;
228
229 default:
230 goto out;
231 }
232 }
233
234 iph->protocol = nexthdr[1];
235 pskb_trim(skb, skb->len - alen - padlen - 2);
236 memcpy(workbuf, skb->nh.raw, iph->ihl*4);
237 skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
238 skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
239 memcpy(skb->nh.raw, workbuf, iph->ihl*4);
240 skb->nh.iph->tot_len = htons(skb->len);
241 } 191 }
192 skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen);
193 crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
194 if (unlikely(sg != &esp->sgbuf[0]))
195 kfree(sg);
242 196
243 return 0; 197 if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
198 BUG();
244 199
245out: 200 padlen = nexthdr[0];
246 return -EINVAL; 201 if (padlen+2 >= elen)
247} 202 goto out;
248 203
249static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 204 /* ... check padding bits here. Silly. :-) */
250{
251
252 if (x->encap) {
253 struct xfrm_encap_tmpl *encap;
254 struct esp_decap_data *decap_data;
255 205
256 encap = x->encap; 206 if (x->encap) {
257 decap_data = (struct esp_decap_data *)(decap->decap_data); 207 struct xfrm_encap_tmpl *encap = x->encap;
208 struct udphdr *uh;
258 209
259 /* first, make sure that the decap type == the encap type */
260 if (encap->encap_type != decap->decap_type) 210 if (encap->encap_type != decap->decap_type)
261 return -EINVAL; 211 goto out;
262 212
263 switch (encap->encap_type) { 213 uh = (struct udphdr *)(iph + 1);
264 default: 214 encap_len = (void*)esph - (void*)uh;
265 case UDP_ENCAP_ESPINUDP: 215
266 case UDP_ENCAP_ESPINUDP_NON_IKE: 216 /*
267 /* 217 * 1) if the NAT-T peer's IP or port changed then
268 * 1) if the NAT-T peer's IP or port changed then 218 * advertize the change to the keying daemon.
269 * advertize the change to the keying daemon. 219 * This is an inbound SA, so just compare
270 * This is an inbound SA, so just compare 220 * SRC ports.
271 * SRC ports. 221 */
272 */ 222 if (iph->saddr != x->props.saddr.a4 ||
273 if (decap_data->proto == AF_INET && 223 uh->source != encap->encap_sport) {
274 (decap_data->saddr.a4 != x->props.saddr.a4 || 224 xfrm_address_t ipaddr;
275 decap_data->sport != encap->encap_sport)) { 225
276 xfrm_address_t ipaddr; 226 ipaddr.a4 = iph->saddr;
277 227 km_new_mapping(x, &ipaddr, uh->source);
278 ipaddr.a4 = decap_data->saddr.a4; 228
279 km_new_mapping(x, &ipaddr, decap_data->sport); 229 /* XXX: perhaps add an extra
280 230 * policy check here, to see
281 /* XXX: perhaps add an extra 231 * if we should allow or
282 * policy check here, to see 232 * reject a packet from a
283 * if we should allow or 233 * different source
284 * reject a packet from a 234 * address/port.
285 * different source
286 * address/port.
287 */
288 }
289
290 /*
291 * 2) ignore UDP/TCP checksums in case
292 * of NAT-T in Transport Mode, or
293 * perform other post-processing fixes
294 * as per * draft-ietf-ipsec-udp-encaps-06,
295 * section 3.1.2
296 */ 235 */
297 if (!x->props.mode)
298 skb->ip_summed = CHECKSUM_UNNECESSARY;
299
300 break;
301 } 236 }
237
238 /*
239 * 2) ignore UDP/TCP checksums in case
240 * of NAT-T in Transport Mode, or
241 * perform other post-processing fixes
242 * as per draft-ietf-ipsec-udp-encaps-06,
243 * section 3.1.2
244 */
245 if (!x->props.mode)
246 skb->ip_summed = CHECKSUM_UNNECESSARY;
302 } 247 }
248
249 iph->protocol = nexthdr[1];
250 pskb_trim(skb, skb->len - alen - padlen - 2);
251 memcpy(workbuf, skb->nh.raw, iph->ihl*4);
252 skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
253 skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
254 memcpy(skb->nh.raw, workbuf, iph->ihl*4);
255 skb->nh.iph->tot_len = htons(skb->len);
256
303 return 0; 257 return 0;
258
259out:
260 return -EINVAL;
304} 261}
305 262
306static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) 263static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
@@ -458,7 +415,6 @@ static struct xfrm_type esp_type =
458 .destructor = esp_destroy, 415 .destructor = esp_destroy,
459 .get_max_size = esp4_get_max_size, 416 .get_max_size = esp4_get_max_size,
460 .input = esp_input, 417 .input = esp_input,
461 .post_input = esp_post_input,
462 .output = esp_output 418 .output = esp_output
463}; 419};
464 420
@@ -470,15 +426,6 @@ static struct net_protocol esp4_protocol = {
470 426
471static int __init esp4_init(void) 427static int __init esp4_init(void)
472{ 428{
473 struct xfrm_decap_state decap;
474
475 if (sizeof(struct esp_decap_data) >
476 sizeof(decap.decap_data)) {
477 extern void decap_data_too_small(void);
478
479 decap_data_too_small();
480 }
481
482 if (xfrm_register_type(&esp_type, AF_INET) < 0) { 429 if (xfrm_register_type(&esp_type, AF_INET) < 0) {
483 printk(KERN_INFO "ip esp init: can't add xfrm type\n"); 430 printk(KERN_INFO "ip esp init: can't add xfrm type\n");
484 return -EAGAIN; 431 return -EAGAIN;
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 6606ddb66a29..cc27545ff97f 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -425,7 +425,12 @@ ipt_log_target(struct sk_buff **pskb,
425 li.u.log.level = loginfo->level; 425 li.u.log.level = loginfo->level;
426 li.u.log.logflags = loginfo->logflags; 426 li.u.log.logflags = loginfo->logflags;
427 427
428 nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, loginfo->prefix); 428 if (loginfo->logflags & IPT_LOG_NFLOG)
429 nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
430 loginfo->prefix);
431 else
432 ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
433 loginfo->prefix);
429 434
430 return IPT_CONTINUE; 435 return IPT_CONTINUE;
431} 436}
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 77c725832dec..6b930efa9fb9 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -436,7 +436,12 @@ ip6t_log_target(struct sk_buff **pskb,
436 li.u.log.level = loginfo->level; 436 li.u.log.level = loginfo->level;
437 li.u.log.logflags = loginfo->logflags; 437 li.u.log.logflags = loginfo->logflags;
438 438
439 nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, loginfo->prefix); 439 if (loginfo->logflags & IP6T_LOG_NFLOG)
440 nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
441 loginfo->prefix);
442 else
443 ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
444 loginfo->prefix);
440 445
441 return IP6T_CONTINUE; 446 return IP6T_CONTINUE;
442} 447}
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index d3a4f30a7f22..d9f0d7ef103b 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -6,6 +6,7 @@
6#include <linux/skbuff.h> 6#include <linux/skbuff.h>
7#include <linux/netfilter.h> 7#include <linux/netfilter.h>
8#include <linux/seq_file.h> 8#include <linux/seq_file.h>
9#include <linux/rcupdate.h>
9#include <net/protocol.h> 10#include <net/protocol.h>
10 11
11#include "nf_internals.h" 12#include "nf_internals.h"
@@ -16,7 +17,7 @@
16 * for queueing and must reinject all packets it receives, no matter what. 17 * for queueing and must reinject all packets it receives, no matter what.
17 */ 18 */
18static struct nf_queue_handler *queue_handler[NPROTO]; 19static struct nf_queue_handler *queue_handler[NPROTO];
19static struct nf_queue_rerouter *queue_rerouter; 20static struct nf_queue_rerouter *queue_rerouter[NPROTO];
20 21
21static DEFINE_RWLOCK(queue_handler_lock); 22static DEFINE_RWLOCK(queue_handler_lock);
22 23
@@ -64,7 +65,7 @@ int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
64 return -EINVAL; 65 return -EINVAL;
65 66
66 write_lock_bh(&queue_handler_lock); 67 write_lock_bh(&queue_handler_lock);
67 memcpy(&queue_rerouter[pf], rer, sizeof(queue_rerouter[pf])); 68 rcu_assign_pointer(queue_rerouter[pf], rer);
68 write_unlock_bh(&queue_handler_lock); 69 write_unlock_bh(&queue_handler_lock);
69 70
70 return 0; 71 return 0;
@@ -77,8 +78,9 @@ int nf_unregister_queue_rerouter(int pf)
77 return -EINVAL; 78 return -EINVAL;
78 79
79 write_lock_bh(&queue_handler_lock); 80 write_lock_bh(&queue_handler_lock);
80 memset(&queue_rerouter[pf], 0, sizeof(queue_rerouter[pf])); 81 rcu_assign_pointer(queue_rerouter[pf], NULL);
81 write_unlock_bh(&queue_handler_lock); 82 write_unlock_bh(&queue_handler_lock);
83 synchronize_rcu();
82 return 0; 84 return 0;
83} 85}
84EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); 86EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
@@ -114,16 +116,17 @@ int nf_queue(struct sk_buff **skb,
114 struct net_device *physindev = NULL; 116 struct net_device *physindev = NULL;
115 struct net_device *physoutdev = NULL; 117 struct net_device *physoutdev = NULL;
116#endif 118#endif
119 struct nf_queue_rerouter *rerouter;
117 120
118 /* QUEUE == DROP if noone is waiting, to be safe. */ 121 /* QUEUE == DROP if noone is waiting, to be safe. */
119 read_lock(&queue_handler_lock); 122 read_lock(&queue_handler_lock);
120 if (!queue_handler[pf] || !queue_handler[pf]->outfn) { 123 if (!queue_handler[pf]) {
121 read_unlock(&queue_handler_lock); 124 read_unlock(&queue_handler_lock);
122 kfree_skb(*skb); 125 kfree_skb(*skb);
123 return 1; 126 return 1;
124 } 127 }
125 128
126 info = kmalloc(sizeof(*info)+queue_rerouter[pf].rer_size, GFP_ATOMIC); 129 info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC);
127 if (!info) { 130 if (!info) {
128 if (net_ratelimit()) 131 if (net_ratelimit())
129 printk(KERN_ERR "OOM queueing packet %p\n", 132 printk(KERN_ERR "OOM queueing packet %p\n",
@@ -155,15 +158,13 @@ int nf_queue(struct sk_buff **skb,
155 if (physoutdev) dev_hold(physoutdev); 158 if (physoutdev) dev_hold(physoutdev);
156 } 159 }
157#endif 160#endif
158 if (queue_rerouter[pf].save) 161 rerouter = rcu_dereference(queue_rerouter[pf]);
159 queue_rerouter[pf].save(*skb, info); 162 if (rerouter)
163 rerouter->save(*skb, info);
160 164
161 status = queue_handler[pf]->outfn(*skb, info, queuenum, 165 status = queue_handler[pf]->outfn(*skb, info, queuenum,
162 queue_handler[pf]->data); 166 queue_handler[pf]->data);
163 167
164 if (status >= 0 && queue_rerouter[pf].reroute)
165 status = queue_rerouter[pf].reroute(skb, info);
166
167 read_unlock(&queue_handler_lock); 168 read_unlock(&queue_handler_lock);
168 169
169 if (status < 0) { 170 if (status < 0) {
@@ -189,6 +190,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
189{ 190{
190 struct list_head *elem = &info->elem->list; 191 struct list_head *elem = &info->elem->list;
191 struct list_head *i; 192 struct list_head *i;
193 struct nf_queue_rerouter *rerouter;
192 194
193 rcu_read_lock(); 195 rcu_read_lock();
194 196
@@ -212,7 +214,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
212 break; 214 break;
213 } 215 }
214 216
215 if (elem == &nf_hooks[info->pf][info->hook]) { 217 if (i == &nf_hooks[info->pf][info->hook]) {
216 /* The module which sent it to userspace is gone. */ 218 /* The module which sent it to userspace is gone. */
217 NFDEBUG("%s: module disappeared, dropping packet.\n", 219 NFDEBUG("%s: module disappeared, dropping packet.\n",
218 __FUNCTION__); 220 __FUNCTION__);
@@ -226,6 +228,12 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
226 } 228 }
227 229
228 if (verdict == NF_ACCEPT) { 230 if (verdict == NF_ACCEPT) {
231 rerouter = rcu_dereference(queue_rerouter[info->pf]);
232 if (rerouter && rerouter->reroute(&skb, info) < 0)
233 verdict = NF_DROP;
234 }
235
236 if (verdict == NF_ACCEPT) {
229 next_hook: 237 next_hook:
230 verdict = nf_iterate(&nf_hooks[info->pf][info->hook], 238 verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
231 &skb, info->hook, 239 &skb, info->hook,
@@ -322,22 +330,12 @@ int __init netfilter_queue_init(void)
322{ 330{
323#ifdef CONFIG_PROC_FS 331#ifdef CONFIG_PROC_FS
324 struct proc_dir_entry *pde; 332 struct proc_dir_entry *pde;
325#endif
326 queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter),
327 GFP_KERNEL);
328 if (!queue_rerouter)
329 return -ENOMEM;
330 333
331#ifdef CONFIG_PROC_FS
332 pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter); 334 pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter);
333 if (!pde) { 335 if (!pde)
334 kfree(queue_rerouter);
335 return -1; 336 return -1;
336 }
337 pde->proc_fops = &nfqueue_file_ops; 337 pde->proc_fops = &nfqueue_file_ops;
338#endif 338#endif
339 memset(queue_rerouter, 0, NPROTO * sizeof(struct nf_queue_rerouter));
340
341 return 0; 339 return 0;
342} 340}
343 341
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8206025d8e46..ae62054a9fc4 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -996,13 +996,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
996 struct sec_decap_state *xvec = &(skb->sp->x[i]); 996 struct sec_decap_state *xvec = &(skb->sp->x[i]);
997 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family)) 997 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
998 return 0; 998 return 0;
999
1000 /* If there is a post_input processor, try running it */
1001 if (xvec->xvec->type->post_input &&
1002 (xvec->xvec->type->post_input)(xvec->xvec,
1003 &(xvec->decap),
1004 skb) != 0)
1005 return 0;
1006 } 999 }
1007 } 1000 }
1008 1001