aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bridge/netfilter/ebtables.c16
-rw-r--r--net/ipv4/netfilter/arp_tables.c109
-rw-r--r--net/ipv4/netfilter/ip_queue.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c170
-rw-r--r--net/ipv6/netfilter/ip6_queue.c2
-rw-r--r--net/ipv6/netfilter/ip6_tables.c168
-rw-r--r--net/netfilter/nf_queue.c4
-rw-r--r--net/netfilter/x_tables.c42
8 files changed, 278 insertions, 235 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 820252aee81f..24555834d431 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -142,6 +142,12 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
142 return 0; 142 return 0;
143} 143}
144 144
145static inline __pure
146struct ebt_entry *ebt_next_entry(const struct ebt_entry *entry)
147{
148 return (void *)entry + entry->next_offset;
149}
150
145/* Do some firewalling */ 151/* Do some firewalling */
146unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, 152unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
147 const struct net_device *in, const struct net_device *out, 153 const struct net_device *in, const struct net_device *out,
@@ -249,8 +255,7 @@ letsreturn:
249 /* jump to a udc */ 255 /* jump to a udc */
250 cs[sp].n = i + 1; 256 cs[sp].n = i + 1;
251 cs[sp].chaininfo = chaininfo; 257 cs[sp].chaininfo = chaininfo;
252 cs[sp].e = (struct ebt_entry *) 258 cs[sp].e = ebt_next_entry(point);
253 (((char *)point) + point->next_offset);
254 i = 0; 259 i = 0;
255 chaininfo = (struct ebt_entries *) (base + verdict); 260 chaininfo = (struct ebt_entries *) (base + verdict);
256#ifdef CONFIG_NETFILTER_DEBUG 261#ifdef CONFIG_NETFILTER_DEBUG
@@ -266,8 +271,7 @@ letsreturn:
266 sp++; 271 sp++;
267 continue; 272 continue;
268letscontinue: 273letscontinue:
269 point = (struct ebt_entry *) 274 point = ebt_next_entry(point);
270 (((char *)point) + point->next_offset);
271 i++; 275 i++;
272 } 276 }
273 277
@@ -787,7 +791,7 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s
787 /* this can't be 0, so the loop test is correct */ 791 /* this can't be 0, so the loop test is correct */
788 cl_s[i].cs.n = pos + 1; 792 cl_s[i].cs.n = pos + 1;
789 pos = 0; 793 pos = 0;
790 cl_s[i].cs.e = ((void *)e + e->next_offset); 794 cl_s[i].cs.e = ebt_next_entry(e);
791 e = (struct ebt_entry *)(hlp2->data); 795 e = (struct ebt_entry *)(hlp2->data);
792 nentries = hlp2->nentries; 796 nentries = hlp2->nentries;
793 cl_s[i].from = chain_nr; 797 cl_s[i].from = chain_nr;
@@ -797,7 +801,7 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s
797 continue; 801 continue;
798 } 802 }
799letscontinue: 803letscontinue:
800 e = (void *)e + e->next_offset; 804 e = ebt_next_entry(e);
801 pos++; 805 pos++;
802 } 806 }
803 return 0; 807 return 0;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 831fe1879dc0..7505dff4ffdf 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -231,6 +231,12 @@ static inline struct arpt_entry *get_entry(void *base, unsigned int offset)
231 return (struct arpt_entry *)(base + offset); 231 return (struct arpt_entry *)(base + offset);
232} 232}
233 233
234static inline __pure
235struct arpt_entry *arpt_next_entry(const struct arpt_entry *entry)
236{
237 return (void *)entry + entry->next_offset;
238}
239
234unsigned int arpt_do_table(struct sk_buff *skb, 240unsigned int arpt_do_table(struct sk_buff *skb,
235 unsigned int hook, 241 unsigned int hook,
236 const struct net_device *in, 242 const struct net_device *in,
@@ -267,67 +273,64 @@ unsigned int arpt_do_table(struct sk_buff *skb,
267 273
268 arp = arp_hdr(skb); 274 arp = arp_hdr(skb);
269 do { 275 do {
270 if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { 276 struct arpt_entry_target *t;
271 struct arpt_entry_target *t; 277 int hdr_len;
272 int hdr_len;
273
274 hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) +
275 (2 * skb->dev->addr_len);
276 278
277 ADD_COUNTER(e->counters, hdr_len, 1); 279 if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
280 e = arpt_next_entry(e);
281 continue;
282 }
278 283
279 t = arpt_get_target(e); 284 hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) +
285 (2 * skb->dev->addr_len);
286 ADD_COUNTER(e->counters, hdr_len, 1);
280 287
281 /* Standard target? */ 288 t = arpt_get_target(e);
282 if (!t->u.kernel.target->target) {
283 int v;
284 289
285 v = ((struct arpt_standard_target *)t)->verdict; 290 /* Standard target? */
286 if (v < 0) { 291 if (!t->u.kernel.target->target) {
287 /* Pop from stack? */ 292 int v;
288 if (v != ARPT_RETURN) {
289 verdict = (unsigned)(-v) - 1;
290 break;
291 }
292 e = back;
293 back = get_entry(table_base,
294 back->comefrom);
295 continue;
296 }
297 if (table_base + v
298 != (void *)e + e->next_offset) {
299 /* Save old back ptr in next entry */
300 struct arpt_entry *next
301 = (void *)e + e->next_offset;
302 next->comefrom =
303 (void *)back - table_base;
304
305 /* set back pointer to next entry */
306 back = next;
307 }
308 293
309 e = get_entry(table_base, v); 294 v = ((struct arpt_standard_target *)t)->verdict;
310 } else { 295 if (v < 0) {
311 /* Targets which reenter must return 296 /* Pop from stack? */
312 * abs. verdicts 297 if (v != ARPT_RETURN) {
313 */ 298 verdict = (unsigned)(-v) - 1;
314 tgpar.target = t->u.kernel.target;
315 tgpar.targinfo = t->data;
316 verdict = t->u.kernel.target->target(skb,
317 &tgpar);
318
319 /* Target might have changed stuff. */
320 arp = arp_hdr(skb);
321
322 if (verdict == ARPT_CONTINUE)
323 e = (void *)e + e->next_offset;
324 else
325 /* Verdict */
326 break; 299 break;
300 }
301 e = back;
302 back = get_entry(table_base, back->comefrom);
303 continue;
327 } 304 }
328 } else { 305 if (table_base + v
329 e = (void *)e + e->next_offset; 306 != arpt_next_entry(e)) {
307 /* Save old back ptr in next entry */
308 struct arpt_entry *next = arpt_next_entry(e);
309 next->comefrom = (void *)back - table_base;
310
311 /* set back pointer to next entry */
312 back = next;
313 }
314
315 e = get_entry(table_base, v);
316 continue;
330 } 317 }
318
319 /* Targets which reenter must return
320 * abs. verdicts
321 */
322 tgpar.target = t->u.kernel.target;
323 tgpar.targinfo = t->data;
324 verdict = t->u.kernel.target->target(skb, &tgpar);
325
326 /* Target might have changed stuff. */
327 arp = arp_hdr(skb);
328
329 if (verdict == ARPT_CONTINUE)
330 e = arpt_next_entry(e);
331 else
332 /* Verdict */
333 break;
331 } while (!hotdrop); 334 } while (!hotdrop);
332 xt_info_rdunlock_bh(); 335 xt_info_rdunlock_bh();
333 336
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 5f22c91c6e15..c156db215987 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -596,7 +596,7 @@ static int __init ip_queue_init(void)
596#ifdef CONFIG_SYSCTL 596#ifdef CONFIG_SYSCTL
597 ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table); 597 ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table);
598#endif 598#endif
599 status = nf_register_queue_handler(PF_INET, &nfqh); 599 status = nf_register_queue_handler(NFPROTO_IPV4, &nfqh);
600 if (status < 0) { 600 if (status < 0) {
601 printk(KERN_ERR "ip_queue: failed to register queue handler\n"); 601 printk(KERN_ERR "ip_queue: failed to register queue handler\n");
602 goto cleanup_sysctl; 602 goto cleanup_sysctl;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 2ec8d7290c40..7b35c0b3841b 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -238,8 +238,8 @@ static struct nf_loginfo trace_loginfo = {
238/* Mildly perf critical (only if packet tracing is on) */ 238/* Mildly perf critical (only if packet tracing is on) */
239static inline int 239static inline int
240get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, 240get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
241 char *hookname, char **chainname, 241 const char *hookname, const char **chainname,
242 char **comment, unsigned int *rulenum) 242 const char **comment, unsigned int *rulenum)
243{ 243{
244 struct ipt_standard_target *t = (void *)ipt_get_target(s); 244 struct ipt_standard_target *t = (void *)ipt_get_target(s);
245 245
@@ -257,8 +257,8 @@ get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
257 && unconditional(&s->ip)) { 257 && unconditional(&s->ip)) {
258 /* Tail of chains: STANDARD target (return/policy) */ 258 /* Tail of chains: STANDARD target (return/policy) */
259 *comment = *chainname == hookname 259 *comment = *chainname == hookname
260 ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY] 260 ? comments[NF_IP_TRACE_COMMENT_POLICY]
261 : (char *)comments[NF_IP_TRACE_COMMENT_RETURN]; 261 : comments[NF_IP_TRACE_COMMENT_RETURN];
262 } 262 }
263 return 1; 263 return 1;
264 } else 264 } else
@@ -277,14 +277,14 @@ static void trace_packet(struct sk_buff *skb,
277{ 277{
278 void *table_base; 278 void *table_base;
279 const struct ipt_entry *root; 279 const struct ipt_entry *root;
280 char *hookname, *chainname, *comment; 280 const char *hookname, *chainname, *comment;
281 unsigned int rulenum = 0; 281 unsigned int rulenum = 0;
282 282
283 table_base = (void *)private->entries[smp_processor_id()]; 283 table_base = private->entries[smp_processor_id()];
284 root = get_entry(table_base, private->hook_entry[hook]); 284 root = get_entry(table_base, private->hook_entry[hook]);
285 285
286 hookname = chainname = (char *)hooknames[hook]; 286 hookname = chainname = hooknames[hook];
287 comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE]; 287 comment = comments[NF_IP_TRACE_COMMENT_RULE];
288 288
289 IPT_ENTRY_ITERATE(root, 289 IPT_ENTRY_ITERATE(root,
290 private->size - private->hook_entry[hook], 290 private->size - private->hook_entry[hook],
@@ -297,6 +297,12 @@ static void trace_packet(struct sk_buff *skb,
297} 297}
298#endif 298#endif
299 299
300static inline __pure
301struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
302{
303 return (void *)entry + entry->next_offset;
304}
305
300/* Returns one of the generic firewall policies, like NF_ACCEPT. */ 306/* Returns one of the generic firewall policies, like NF_ACCEPT. */
301unsigned int 307unsigned int
302ipt_do_table(struct sk_buff *skb, 308ipt_do_table(struct sk_buff *skb,
@@ -305,6 +311,8 @@ ipt_do_table(struct sk_buff *skb,
305 const struct net_device *out, 311 const struct net_device *out,
306 struct xt_table *table) 312 struct xt_table *table)
307{ 313{
314#define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
315
308 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 316 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
309 const struct iphdr *ip; 317 const struct iphdr *ip;
310 u_int16_t datalen; 318 u_int16_t datalen;
@@ -348,92 +356,84 @@ ipt_do_table(struct sk_buff *skb,
348 back = get_entry(table_base, private->underflow[hook]); 356 back = get_entry(table_base, private->underflow[hook]);
349 357
350 do { 358 do {
359 struct ipt_entry_target *t;
360
351 IP_NF_ASSERT(e); 361 IP_NF_ASSERT(e);
352 IP_NF_ASSERT(back); 362 IP_NF_ASSERT(back);
353 if (ip_packet_match(ip, indev, outdev, 363 if (!ip_packet_match(ip, indev, outdev,
354 &e->ip, mtpar.fragoff)) { 364 &e->ip, mtpar.fragoff) ||
355 struct ipt_entry_target *t; 365 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
356 366 e = ipt_next_entry(e);
357 if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) 367 continue;
358 goto no_match; 368 }
359 369
360 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); 370 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
361 371
362 t = ipt_get_target(e); 372 t = ipt_get_target(e);
363 IP_NF_ASSERT(t->u.kernel.target); 373 IP_NF_ASSERT(t->u.kernel.target);
364 374
365#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ 375#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
366 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) 376 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
367 /* The packet is traced: log it */ 377 /* The packet is traced: log it */
368 if (unlikely(skb->nf_trace)) 378 if (unlikely(skb->nf_trace))
369 trace_packet(skb, hook, in, out, 379 trace_packet(skb, hook, in, out,
370 table->name, private, e); 380 table->name, private, e);
371#endif 381#endif
372 /* Standard target? */ 382 /* Standard target? */
373 if (!t->u.kernel.target->target) { 383 if (!t->u.kernel.target->target) {
374 int v; 384 int v;
375 385
376 v = ((struct ipt_standard_target *)t)->verdict; 386 v = ((struct ipt_standard_target *)t)->verdict;
377 if (v < 0) { 387 if (v < 0) {
378 /* Pop from stack? */ 388 /* Pop from stack? */
379 if (v != IPT_RETURN) { 389 if (v != IPT_RETURN) {
380 verdict = (unsigned)(-v) - 1; 390 verdict = (unsigned)(-v) - 1;
381 break; 391 break;
382 }
383 e = back;
384 back = get_entry(table_base,
385 back->comefrom);
386 continue;
387 }
388 if (table_base + v != (void *)e + e->next_offset
389 && !(e->ip.flags & IPT_F_GOTO)) {
390 /* Save old back ptr in next entry */
391 struct ipt_entry *next
392 = (void *)e + e->next_offset;
393 next->comefrom
394 = (void *)back - table_base;
395 /* set back pointer to next entry */
396 back = next;
397 } 392 }
393 e = back;
394 back = get_entry(table_base, back->comefrom);
395 continue;
396 }
397 if (table_base + v != ipt_next_entry(e)
398 && !(e->ip.flags & IPT_F_GOTO)) {
399 /* Save old back ptr in next entry */
400 struct ipt_entry *next = ipt_next_entry(e);
401 next->comefrom = (void *)back - table_base;
402 /* set back pointer to next entry */
403 back = next;
404 }
405
406 e = get_entry(table_base, v);
407 continue;
408 }
409
410 /* Targets which reenter must return
411 abs. verdicts */
412 tgpar.target = t->u.kernel.target;
413 tgpar.targinfo = t->data;
414
398 415
399 e = get_entry(table_base, v);
400 } else {
401 /* Targets which reenter must return
402 abs. verdicts */
403 tgpar.target = t->u.kernel.target;
404 tgpar.targinfo = t->data;
405#ifdef CONFIG_NETFILTER_DEBUG 416#ifdef CONFIG_NETFILTER_DEBUG
406 ((struct ipt_entry *)table_base)->comefrom 417 tb_comefrom = 0xeeeeeeec;
407 = 0xeeeeeeec;
408#endif 418#endif
409 verdict = t->u.kernel.target->target(skb, 419 verdict = t->u.kernel.target->target(skb, &tgpar);
410 &tgpar);
411#ifdef CONFIG_NETFILTER_DEBUG 420#ifdef CONFIG_NETFILTER_DEBUG
412 if (((struct ipt_entry *)table_base)->comefrom 421 if (comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
413 != 0xeeeeeeec 422 printk("Target %s reentered!\n",
414 && verdict == IPT_CONTINUE) { 423 t->u.kernel.target->name);
415 printk("Target %s reentered!\n", 424 verdict = NF_DROP;
416 t->u.kernel.target->name); 425 }
417 verdict = NF_DROP; 426 tb_comefrom = 0x57acc001;
418 }
419 ((struct ipt_entry *)table_base)->comefrom
420 = 0x57acc001;
421#endif 427#endif
422 /* Target might have changed stuff. */ 428 /* Target might have changed stuff. */
423 ip = ip_hdr(skb); 429 ip = ip_hdr(skb);
424 datalen = skb->len - ip->ihl * 4; 430 datalen = skb->len - ip->ihl * 4;
425
426 if (verdict == IPT_CONTINUE)
427 e = (void *)e + e->next_offset;
428 else
429 /* Verdict */
430 break;
431 }
432 } else {
433 431
434 no_match: 432 if (verdict == IPT_CONTINUE)
435 e = (void *)e + e->next_offset; 433 e = ipt_next_entry(e);
436 } 434 else
435 /* Verdict */
436 break;
437 } while (!hotdrop); 437 } while (!hotdrop);
438 xt_info_rdunlock_bh(); 438 xt_info_rdunlock_bh();
439 439
@@ -444,6 +444,8 @@ ipt_do_table(struct sk_buff *skb,
444 return NF_DROP; 444 return NF_DROP;
445 else return verdict; 445 else return verdict;
446#endif 446#endif
447
448#undef tb_comefrom
447} 449}
448 450
449/* Figures out from what hook each rule can be called: returns 0 if 451/* Figures out from what hook each rule can be called: returns 0 if
@@ -2158,7 +2160,7 @@ static bool icmp_checkentry(const struct xt_mtchk_param *par)
2158static struct xt_target ipt_standard_target __read_mostly = { 2160static struct xt_target ipt_standard_target __read_mostly = {
2159 .name = IPT_STANDARD_TARGET, 2161 .name = IPT_STANDARD_TARGET,
2160 .targetsize = sizeof(int), 2162 .targetsize = sizeof(int),
2161 .family = AF_INET, 2163 .family = NFPROTO_IPV4,
2162#ifdef CONFIG_COMPAT 2164#ifdef CONFIG_COMPAT
2163 .compatsize = sizeof(compat_int_t), 2165 .compatsize = sizeof(compat_int_t),
2164 .compat_from_user = compat_standard_from_user, 2166 .compat_from_user = compat_standard_from_user,
@@ -2170,7 +2172,7 @@ static struct xt_target ipt_error_target __read_mostly = {
2170 .name = IPT_ERROR_TARGET, 2172 .name = IPT_ERROR_TARGET,
2171 .target = ipt_error, 2173 .target = ipt_error,
2172 .targetsize = IPT_FUNCTION_MAXNAMELEN, 2174 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2173 .family = AF_INET, 2175 .family = NFPROTO_IPV4,
2174}; 2176};
2175 2177
2176static struct nf_sockopt_ops ipt_sockopts = { 2178static struct nf_sockopt_ops ipt_sockopts = {
@@ -2196,17 +2198,17 @@ static struct xt_match icmp_matchstruct __read_mostly = {
2196 .matchsize = sizeof(struct ipt_icmp), 2198 .matchsize = sizeof(struct ipt_icmp),
2197 .checkentry = icmp_checkentry, 2199 .checkentry = icmp_checkentry,
2198 .proto = IPPROTO_ICMP, 2200 .proto = IPPROTO_ICMP,
2199 .family = AF_INET, 2201 .family = NFPROTO_IPV4,
2200}; 2202};
2201 2203
2202static int __net_init ip_tables_net_init(struct net *net) 2204static int __net_init ip_tables_net_init(struct net *net)
2203{ 2205{
2204 return xt_proto_init(net, AF_INET); 2206 return xt_proto_init(net, NFPROTO_IPV4);
2205} 2207}
2206 2208
2207static void __net_exit ip_tables_net_exit(struct net *net) 2209static void __net_exit ip_tables_net_exit(struct net *net)
2208{ 2210{
2209 xt_proto_fini(net, AF_INET); 2211 xt_proto_fini(net, NFPROTO_IPV4);
2210} 2212}
2211 2213
2212static struct pernet_operations ip_tables_net_ops = { 2214static struct pernet_operations ip_tables_net_ops = {
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index b693f841aeb4..1cf3f0c6a959 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -598,7 +598,7 @@ static int __init ip6_queue_init(void)
598#ifdef CONFIG_SYSCTL 598#ifdef CONFIG_SYSCTL
599 ipq_sysctl_header = register_sysctl_paths(net_ipv6_ctl_path, ipq_table); 599 ipq_sysctl_header = register_sysctl_paths(net_ipv6_ctl_path, ipq_table);
600#endif 600#endif
601 status = nf_register_queue_handler(PF_INET6, &nfqh); 601 status = nf_register_queue_handler(NFPROTO_IPV6, &nfqh);
602 if (status < 0) { 602 if (status < 0) {
603 printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); 603 printk(KERN_ERR "ip6_queue: failed to register queue handler\n");
604 goto cleanup_sysctl; 604 goto cleanup_sysctl;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 219e165aea10..5164e0bf3bcc 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -270,8 +270,8 @@ static struct nf_loginfo trace_loginfo = {
270/* Mildly perf critical (only if packet tracing is on) */ 270/* Mildly perf critical (only if packet tracing is on) */
271static inline int 271static inline int
272get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, 272get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
273 char *hookname, char **chainname, 273 const char *hookname, const char **chainname,
274 char **comment, unsigned int *rulenum) 274 const char **comment, unsigned int *rulenum)
275{ 275{
276 struct ip6t_standard_target *t = (void *)ip6t_get_target(s); 276 struct ip6t_standard_target *t = (void *)ip6t_get_target(s);
277 277
@@ -289,8 +289,8 @@ get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
289 && unconditional(&s->ipv6)) { 289 && unconditional(&s->ipv6)) {
290 /* Tail of chains: STANDARD target (return/policy) */ 290 /* Tail of chains: STANDARD target (return/policy) */
291 *comment = *chainname == hookname 291 *comment = *chainname == hookname
292 ? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY] 292 ? comments[NF_IP6_TRACE_COMMENT_POLICY]
293 : (char *)comments[NF_IP6_TRACE_COMMENT_RETURN]; 293 : comments[NF_IP6_TRACE_COMMENT_RETURN];
294 } 294 }
295 return 1; 295 return 1;
296 } else 296 } else
@@ -309,14 +309,14 @@ static void trace_packet(struct sk_buff *skb,
309{ 309{
310 void *table_base; 310 void *table_base;
311 const struct ip6t_entry *root; 311 const struct ip6t_entry *root;
312 char *hookname, *chainname, *comment; 312 const char *hookname, *chainname, *comment;
313 unsigned int rulenum = 0; 313 unsigned int rulenum = 0;
314 314
315 table_base = (void *)private->entries[smp_processor_id()]; 315 table_base = private->entries[smp_processor_id()];
316 root = get_entry(table_base, private->hook_entry[hook]); 316 root = get_entry(table_base, private->hook_entry[hook]);
317 317
318 hookname = chainname = (char *)hooknames[hook]; 318 hookname = chainname = hooknames[hook];
319 comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE]; 319 comment = comments[NF_IP6_TRACE_COMMENT_RULE];
320 320
321 IP6T_ENTRY_ITERATE(root, 321 IP6T_ENTRY_ITERATE(root,
322 private->size - private->hook_entry[hook], 322 private->size - private->hook_entry[hook],
@@ -329,6 +329,12 @@ static void trace_packet(struct sk_buff *skb,
329} 329}
330#endif 330#endif
331 331
332static inline __pure struct ip6t_entry *
333ip6t_next_entry(const struct ip6t_entry *entry)
334{
335 return (void *)entry + entry->next_offset;
336}
337
332/* Returns one of the generic firewall policies, like NF_ACCEPT. */ 338/* Returns one of the generic firewall policies, like NF_ACCEPT. */
333unsigned int 339unsigned int
334ip6t_do_table(struct sk_buff *skb, 340ip6t_do_table(struct sk_buff *skb,
@@ -337,6 +343,8 @@ ip6t_do_table(struct sk_buff *skb,
337 const struct net_device *out, 343 const struct net_device *out,
338 struct xt_table *table) 344 struct xt_table *table)
339{ 345{
346#define tb_comefrom ((struct ip6t_entry *)table_base)->comefrom
347
340 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 348 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
341 bool hotdrop = false; 349 bool hotdrop = false;
342 /* Initializing verdict to NF_DROP keeps gcc happy. */ 350 /* Initializing verdict to NF_DROP keeps gcc happy. */
@@ -375,96 +383,86 @@ ip6t_do_table(struct sk_buff *skb,
375 back = get_entry(table_base, private->underflow[hook]); 383 back = get_entry(table_base, private->underflow[hook]);
376 384
377 do { 385 do {
386 struct ip6t_entry_target *t;
387
378 IP_NF_ASSERT(e); 388 IP_NF_ASSERT(e);
379 IP_NF_ASSERT(back); 389 IP_NF_ASSERT(back);
380 if (ip6_packet_match(skb, indev, outdev, &e->ipv6, 390 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
381 &mtpar.thoff, &mtpar.fragoff, &hotdrop)) { 391 &mtpar.thoff, &mtpar.fragoff, &hotdrop) ||
382 struct ip6t_entry_target *t; 392 IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
383 393 e = ip6t_next_entry(e);
384 if (IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) 394 continue;
385 goto no_match; 395 }
386 396
387 ADD_COUNTER(e->counters, 397 ADD_COUNTER(e->counters,
388 ntohs(ipv6_hdr(skb)->payload_len) + 398 ntohs(ipv6_hdr(skb)->payload_len) +
389 sizeof(struct ipv6hdr), 1); 399 sizeof(struct ipv6hdr), 1);
390 400
391 t = ip6t_get_target(e); 401 t = ip6t_get_target(e);
392 IP_NF_ASSERT(t->u.kernel.target); 402 IP_NF_ASSERT(t->u.kernel.target);
393 403
394#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ 404#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
395 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) 405 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
396 /* The packet is traced: log it */ 406 /* The packet is traced: log it */
397 if (unlikely(skb->nf_trace)) 407 if (unlikely(skb->nf_trace))
398 trace_packet(skb, hook, in, out, 408 trace_packet(skb, hook, in, out,
399 table->name, private, e); 409 table->name, private, e);
400#endif 410#endif
401 /* Standard target? */ 411 /* Standard target? */
402 if (!t->u.kernel.target->target) { 412 if (!t->u.kernel.target->target) {
403 int v; 413 int v;
404 414
405 v = ((struct ip6t_standard_target *)t)->verdict; 415 v = ((struct ip6t_standard_target *)t)->verdict;
406 if (v < 0) { 416 if (v < 0) {
407 /* Pop from stack? */ 417 /* Pop from stack? */
408 if (v != IP6T_RETURN) { 418 if (v != IP6T_RETURN) {
409 verdict = (unsigned)(-v) - 1; 419 verdict = (unsigned)(-v) - 1;
410 break; 420 break;
411 }
412 e = back;
413 back = get_entry(table_base,
414 back->comefrom);
415 continue;
416 }
417 if (table_base + v != (void *)e + e->next_offset
418 && !(e->ipv6.flags & IP6T_F_GOTO)) {
419 /* Save old back ptr in next entry */
420 struct ip6t_entry *next
421 = (void *)e + e->next_offset;
422 next->comefrom
423 = (void *)back - table_base;
424 /* set back pointer to next entry */
425 back = next;
426 } 421 }
422 e = back;
423 back = get_entry(table_base, back->comefrom);
424 continue;
425 }
426 if (table_base + v != ip6t_next_entry(e)
427 && !(e->ipv6.flags & IP6T_F_GOTO)) {
428 /* Save old back ptr in next entry */
429 struct ip6t_entry *next = ip6t_next_entry(e);
430 next->comefrom = (void *)back - table_base;
431 /* set back pointer to next entry */
432 back = next;
433 }
427 434
428 e = get_entry(table_base, v); 435 e = get_entry(table_base, v);
429 } else { 436 continue;
430 /* Targets which reenter must return 437 }
431 abs. verdicts */
432 tgpar.target = t->u.kernel.target;
433 tgpar.targinfo = t->data;
434 438
435#ifdef CONFIG_NETFILTER_DEBUG 439 /* Targets which reenter must return
436 ((struct ip6t_entry *)table_base)->comefrom 440 abs. verdicts */
437 = 0xeeeeeeec; 441 tgpar.target = t->u.kernel.target;
438#endif 442 tgpar.targinfo = t->data;
439 verdict = t->u.kernel.target->target(skb,
440 &tgpar);
441 443
442#ifdef CONFIG_NETFILTER_DEBUG 444#ifdef CONFIG_NETFILTER_DEBUG
443 if (((struct ip6t_entry *)table_base)->comefrom 445 tb_comefrom = 0xeeeeeeec;
444 != 0xeeeeeeec
445 && verdict == IP6T_CONTINUE) {
446 printk("Target %s reentered!\n",
447 t->u.kernel.target->name);
448 verdict = NF_DROP;
449 }
450 ((struct ip6t_entry *)table_base)->comefrom
451 = 0x57acc001;
452#endif 446#endif
453 if (verdict == IP6T_CONTINUE) 447 verdict = t->u.kernel.target->target(skb, &tgpar);
454 e = (void *)e + e->next_offset;
455 else
456 /* Verdict */
457 break;
458 }
459 } else {
460 448
461 no_match: 449#ifdef CONFIG_NETFILTER_DEBUG
462 e = (void *)e + e->next_offset; 450 if (tb_comefrom != 0xeeeeeeec && verdict == IP6T_CONTINUE) {
451 printk("Target %s reentered!\n",
452 t->u.kernel.target->name);
453 verdict = NF_DROP;
463 } 454 }
455 tb_comefrom = 0x57acc001;
456#endif
457 if (verdict == IP6T_CONTINUE)
458 e = ip6t_next_entry(e);
459 else
460 /* Verdict */
461 break;
464 } while (!hotdrop); 462 } while (!hotdrop);
465 463
466#ifdef CONFIG_NETFILTER_DEBUG 464#ifdef CONFIG_NETFILTER_DEBUG
467 ((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON; 465 tb_comefrom = NETFILTER_LINK_POISON;
468#endif 466#endif
469 xt_info_rdunlock_bh(); 467 xt_info_rdunlock_bh();
470 468
@@ -475,6 +473,8 @@ ip6t_do_table(struct sk_buff *skb,
475 return NF_DROP; 473 return NF_DROP;
476 else return verdict; 474 else return verdict;
477#endif 475#endif
476
477#undef tb_comefrom
478} 478}
479 479
480/* Figures out from what hook each rule can be called: returns 0 if 480/* Figures out from what hook each rule can be called: returns 0 if
@@ -2191,7 +2191,7 @@ static bool icmp6_checkentry(const struct xt_mtchk_param *par)
2191static struct xt_target ip6t_standard_target __read_mostly = { 2191static struct xt_target ip6t_standard_target __read_mostly = {
2192 .name = IP6T_STANDARD_TARGET, 2192 .name = IP6T_STANDARD_TARGET,
2193 .targetsize = sizeof(int), 2193 .targetsize = sizeof(int),
2194 .family = AF_INET6, 2194 .family = NFPROTO_IPV6,
2195#ifdef CONFIG_COMPAT 2195#ifdef CONFIG_COMPAT
2196 .compatsize = sizeof(compat_int_t), 2196 .compatsize = sizeof(compat_int_t),
2197 .compat_from_user = compat_standard_from_user, 2197 .compat_from_user = compat_standard_from_user,
@@ -2203,7 +2203,7 @@ static struct xt_target ip6t_error_target __read_mostly = {
2203 .name = IP6T_ERROR_TARGET, 2203 .name = IP6T_ERROR_TARGET,
2204 .target = ip6t_error, 2204 .target = ip6t_error,
2205 .targetsize = IP6T_FUNCTION_MAXNAMELEN, 2205 .targetsize = IP6T_FUNCTION_MAXNAMELEN,
2206 .family = AF_INET6, 2206 .family = NFPROTO_IPV6,
2207}; 2207};
2208 2208
2209static struct nf_sockopt_ops ip6t_sockopts = { 2209static struct nf_sockopt_ops ip6t_sockopts = {
@@ -2229,17 +2229,17 @@ static struct xt_match icmp6_matchstruct __read_mostly = {
2229 .matchsize = sizeof(struct ip6t_icmp), 2229 .matchsize = sizeof(struct ip6t_icmp),
2230 .checkentry = icmp6_checkentry, 2230 .checkentry = icmp6_checkentry,
2231 .proto = IPPROTO_ICMPV6, 2231 .proto = IPPROTO_ICMPV6,
2232 .family = AF_INET6, 2232 .family = NFPROTO_IPV6,
2233}; 2233};
2234 2234
2235static int __net_init ip6_tables_net_init(struct net *net) 2235static int __net_init ip6_tables_net_init(struct net *net)
2236{ 2236{
2237 return xt_proto_init(net, AF_INET6); 2237 return xt_proto_init(net, NFPROTO_IPV6);
2238} 2238}
2239 2239
2240static void __net_exit ip6_tables_net_exit(struct net *net) 2240static void __net_exit ip6_tables_net_exit(struct net *net)
2241{ 2241{
2242 xt_proto_fini(net, AF_INET6); 2242 xt_proto_fini(net, NFPROTO_IPV6);
2243} 2243}
2244 2244
2245static struct pernet_operations ip6_tables_net_ops = { 2245static struct pernet_operations ip6_tables_net_ops = {
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 4f2310c93e01..3a6fd77f7761 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -204,10 +204,10 @@ int nf_queue(struct sk_buff *skb,
204 queuenum); 204 queuenum);
205 205
206 switch (pf) { 206 switch (pf) {
207 case AF_INET: 207 case NFPROTO_IPV4:
208 skb->protocol = htons(ETH_P_IP); 208 skb->protocol = htons(ETH_P_IP);
209 break; 209 break;
210 case AF_INET6: 210 case NFPROTO_IPV6:
211 skb->protocol = htons(ETH_P_IPV6); 211 skb->protocol = htons(ETH_P_IPV6);
212 break; 212 break;
213 } 213 }
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 150e5cf62f85..46dba5f043d5 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -329,6 +329,32 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target,
329} 329}
330EXPORT_SYMBOL_GPL(xt_find_revision); 330EXPORT_SYMBOL_GPL(xt_find_revision);
331 331
332static char *textify_hooks(char *buf, size_t size, unsigned int mask)
333{
334 static const char *const names[] = {
335 "PREROUTING", "INPUT", "FORWARD",
336 "OUTPUT", "POSTROUTING", "BROUTING",
337 };
338 unsigned int i;
339 char *p = buf;
340 bool np = false;
341 int res;
342
343 *p = '\0';
344 for (i = 0; i < ARRAY_SIZE(names); ++i) {
345 if (!(mask & (1 << i)))
346 continue;
347 res = snprintf(p, size, "%s%s", np ? "/" : "", names[i]);
348 if (res > 0) {
349 size -= res;
350 p += res;
351 }
352 np = true;
353 }
354
355 return buf;
356}
357
332int xt_check_match(struct xt_mtchk_param *par, 358int xt_check_match(struct xt_mtchk_param *par,
333 unsigned int size, u_int8_t proto, bool inv_proto) 359 unsigned int size, u_int8_t proto, bool inv_proto)
334{ 360{
@@ -351,9 +377,13 @@ int xt_check_match(struct xt_mtchk_param *par,
351 return -EINVAL; 377 return -EINVAL;
352 } 378 }
353 if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) { 379 if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) {
354 printk("%s_tables: %s match: bad hook_mask %#x/%#x\n", 380 char used[64], allow[64];
381
382 printk("%s_tables: %s match: used from hooks %s, but only "
383 "valid from %s\n",
355 xt_prefix[par->family], par->match->name, 384 xt_prefix[par->family], par->match->name,
356 par->hook_mask, par->match->hooks); 385 textify_hooks(used, sizeof(used), par->hook_mask),
386 textify_hooks(allow, sizeof(allow), par->match->hooks));
357 return -EINVAL; 387 return -EINVAL;
358 } 388 }
359 if (par->match->proto && (par->match->proto != proto || inv_proto)) { 389 if (par->match->proto && (par->match->proto != proto || inv_proto)) {
@@ -497,9 +527,13 @@ int xt_check_target(struct xt_tgchk_param *par,
497 return -EINVAL; 527 return -EINVAL;
498 } 528 }
499 if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) { 529 if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) {
500 printk("%s_tables: %s target: bad hook_mask %#x/%#x\n", 530 char used[64], allow[64];
531
532 printk("%s_tables: %s target: used from hooks %s, but only "
533 "usable from %s\n",
501 xt_prefix[par->family], par->target->name, 534 xt_prefix[par->family], par->target->name,
502 par->hook_mask, par->target->hooks); 535 textify_hooks(used, sizeof(used), par->hook_mask),
536 textify_hooks(allow, sizeof(allow), par->target->hooks));
503 return -EINVAL; 537 return -EINVAL;
504 } 538 }
505 if (par->target->proto && (par->target->proto != proto || inv_proto)) { 539 if (par->target->proto && (par->target->proto != proto || inv_proto)) {