aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/x_tables.h29
-rw-r--r--include/linux/netfilter_bridge/ebtables.h4
-rw-r--r--net/bridge/netfilter/ebt_arpreply.c10
-rw-r--r--net/bridge/netfilter/ebt_dnat.c19
-rw-r--r--net/bridge/netfilter/ebt_log.c7
-rw-r--r--net/bridge/netfilter/ebt_mark.c8
-rw-r--r--net/bridge/netfilter/ebt_nflog.c7
-rw-r--r--net/bridge/netfilter/ebt_redirect.c17
-rw-r--r--net/bridge/netfilter/ebt_snat.c8
-rw-r--r--net/bridge/netfilter/ebt_ulog.c7
-rw-r--r--net/bridge/netfilter/ebtables.c28
-rw-r--r--net/ipv4/netfilter/arp_tables.c20
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c6
-rw-r--r--net/ipv4/netfilter/ip_tables.c17
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c13
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c9
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c7
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c7
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c7
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c7
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c9
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c7
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c7
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c16
-rw-r--r--net/ipv6/netfilter/ip6_tables.c16
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c7
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c7
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c9
-rw-r--r--net/netfilter/x_tables.c32
-rw-r--r--net/netfilter/xt_CONNMARK.c24
-rw-r--r--net/netfilter/xt_CONNSECMARK.c16
-rw-r--r--net/netfilter/xt_DSCP.c19
-rw-r--r--net/netfilter/xt_MARK.c14
-rw-r--r--net/netfilter/xt_NFLOG.c7
-rw-r--r--net/netfilter/xt_RATEEST.c9
-rw-r--r--net/netfilter/xt_SECMARK.c12
-rw-r--r--net/netfilter/xt_TCPMSS.c22
-rw-r--r--net/netfilter/xt_TPROXY.c9
-rw-r--r--net/sched/act_ipt.c12
39 files changed, 208 insertions, 283 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 46d0cb1ad340..8daeb496ba7a 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -234,6 +234,23 @@ struct xt_target_param {
234 const void *targinfo; 234 const void *targinfo;
235}; 235};
236 236
237/**
238 * struct xt_tgchk_param - parameters for target extensions'
239 * checkentry functions
240 *
241 * @entryinfo: the family-specific rule data
242 * (struct ipt_entry, ip6t_entry, arpt_entry, ebt_entry)
243 *
244 * Other fields see above.
245 */
246struct xt_tgchk_param {
247 const char *table;
248 void *entryinfo;
249 const struct xt_target *target;
250 void *targinfo;
251 unsigned int hook_mask;
252};
253
237struct xt_match 254struct xt_match
238{ 255{
239 struct list_head list; 256 struct list_head list;
@@ -291,11 +308,7 @@ struct xt_target
291 hook_mask is a bitmask of hooks from which it can be 308 hook_mask is a bitmask of hooks from which it can be
292 called. */ 309 called. */
293 /* Should return true or false. */ 310 /* Should return true or false. */
294 bool (*checkentry)(const char *tablename, 311 bool (*checkentry)(const struct xt_tgchk_param *);
295 const void *entry,
296 const struct xt_target *target,
297 void *targinfo,
298 unsigned int hook_mask);
299 312
300 /* Called when entry of this type deleted. */ 313 /* Called when entry of this type deleted. */
301 void (*destroy)(const struct xt_target *target, void *targinfo); 314 void (*destroy)(const struct xt_target *target, void *targinfo);
@@ -376,10 +389,8 @@ extern void xt_unregister_matches(struct xt_match *match, unsigned int n);
376 389
377extern int xt_check_match(struct xt_mtchk_param *, u_int8_t family, 390extern int xt_check_match(struct xt_mtchk_param *, u_int8_t family,
378 unsigned int size, u_int8_t proto, bool inv_proto); 391 unsigned int size, u_int8_t proto, bool inv_proto);
379extern int xt_check_target(const struct xt_target *target, unsigned short family, 392extern int xt_check_target(struct xt_tgchk_param *, u_int8_t family,
380 unsigned int size, const char *table, unsigned int hook, 393 unsigned int size, u_int8_t proto, bool inv_proto);
381 unsigned short proto, int inv_proto,
382 const void *entry, void *targinfo);
383 394
384extern struct xt_table *xt_register_table(struct net *net, 395extern struct xt_table *xt_register_table(struct net *net,
385 struct xt_table *table, 396 struct xt_table *table,
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
index 568a690f6a62..d45e29cd1cfb 100644
--- a/include/linux/netfilter_bridge/ebtables.h
+++ b/include/linux/netfilter_bridge/ebtables.h
@@ -310,9 +310,9 @@ extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb,
310#define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg)) 310#define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg))
311/* True if the hook mask denotes that the rule is in a base chain, 311/* True if the hook mask denotes that the rule is in a base chain,
312 * used in the check() functions */ 312 * used in the check() functions */
313#define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS)) 313#define BASE_CHAIN (par->hook_mask & (1 << NF_BR_NUMHOOKS))
314/* Clear the bit in the hook mask that tells if the rule is on a base chain */ 314/* Clear the bit in the hook mask that tells if the rule is on a base chain */
315#define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS)) 315#define CLEAR_BASE_CHAIN_BIT (par->hook_mask &= ~(1 << NF_BR_NUMHOOKS))
316/* True if the target is not a standard target */ 316/* True if the target is not a standard target */
317#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0) 317#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)
318 318
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index fc94699f719e..76584cd72e57 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -57,20 +57,16 @@ ebt_arpreply_tg(struct sk_buff *skb, const struct xt_target_param *par)
57 return info->target; 57 return info->target;
58} 58}
59 59
60static bool 60static bool ebt_arpreply_tg_check(const struct xt_tgchk_param *par)
61ebt_arpreply_tg_check(const char *tablename, const void *entry,
62 const struct xt_target *target, void *data,
63 unsigned int hookmask)
64{ 61{
65 const struct ebt_arpreply_info *info = data; 62 const struct ebt_arpreply_info *info = par->targinfo;
66 const struct ebt_entry *e = entry; 63 const struct ebt_entry *e = par->entryinfo;
67 64
68 if (BASE_CHAIN && info->target == EBT_RETURN) 65 if (BASE_CHAIN && info->target == EBT_RETURN)
69 return false; 66 return false;
70 if (e->ethproto != htons(ETH_P_ARP) || 67 if (e->ethproto != htons(ETH_P_ARP) ||
71 e->invflags & EBT_IPROTO) 68 e->invflags & EBT_IPROTO)
72 return false; 69 return false;
73 CLEAR_BASE_CHAIN_BIT;
74 return true; 70 return true;
75} 71}
76 72
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index bb5d79e0beea..6b49ea9e31fb 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -26,19 +26,20 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_target_param *par)
26 return info->target; 26 return info->target;
27} 27}
28 28
29static bool 29static bool ebt_dnat_tg_check(const struct xt_tgchk_param *par)
30ebt_dnat_tg_check(const char *tablename, const void *entry,
31 const struct xt_target *target, void *data,
32 unsigned int hookmask)
33{ 30{
34 const struct ebt_nat_info *info = data; 31 const struct ebt_nat_info *info = par->targinfo;
32 unsigned int hook_mask;
35 33
36 if (BASE_CHAIN && info->target == EBT_RETURN) 34 if (BASE_CHAIN && info->target == EBT_RETURN)
37 return false; 35 return false;
38 CLEAR_BASE_CHAIN_BIT; 36
39 if ( (strcmp(tablename, "nat") || 37 hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
40 (hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) && 38 if ((strcmp(par->table, "nat") != 0 ||
41 (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) 39 (hook_mask & ~((1 << NF_BR_PRE_ROUTING) |
40 (1 << NF_BR_LOCAL_OUT)))) &&
41 (strcmp(par->table, "broute") != 0 ||
42 hook_mask & ~(1 << NF_BR_BROUTING)))
42 return false; 43 return false;
43 if (INVALID_TARGET) 44 if (INVALID_TARGET)
44 return false; 45 return false;
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 87de5fccb2f1..3d33c608906a 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -24,12 +24,9 @@
24 24
25static DEFINE_SPINLOCK(ebt_log_lock); 25static DEFINE_SPINLOCK(ebt_log_lock);
26 26
27static bool 27static bool ebt_log_tg_check(const struct xt_tgchk_param *par)
28ebt_log_tg_check(const char *table, const void *entry,
29 const struct xt_target *target, void *data,
30 unsigned int hook_mask)
31{ 28{
32 struct ebt_log_info *info = data; 29 struct ebt_log_info *info = par->targinfo;
33 30
34 if (info->bitmask & ~EBT_LOG_MASK) 31 if (info->bitmask & ~EBT_LOG_MASK)
35 return false; 32 return false;
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index aafc456c3c3b..2fee7e8e2e93 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -36,18 +36,14 @@ ebt_mark_tg(struct sk_buff *skb, const struct xt_target_param *par)
36 return info->target | ~EBT_VERDICT_BITS; 36 return info->target | ~EBT_VERDICT_BITS;
37} 37}
38 38
39static bool 39static bool ebt_mark_tg_check(const struct xt_tgchk_param *par)
40ebt_mark_tg_check(const char *table, const void *e,
41 const struct xt_target *target, void *data,
42 unsigned int hookmask)
43{ 40{
44 const struct ebt_mark_t_info *info = data; 41 const struct ebt_mark_t_info *info = par->targinfo;
45 int tmp; 42 int tmp;
46 43
47 tmp = info->target | ~EBT_VERDICT_BITS; 44 tmp = info->target | ~EBT_VERDICT_BITS;
48 if (BASE_CHAIN && tmp == EBT_RETURN) 45 if (BASE_CHAIN && tmp == EBT_RETURN)
49 return false; 46 return false;
50 CLEAR_BASE_CHAIN_BIT;
51 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) 47 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
52 return false; 48 return false;
53 tmp = info->target & ~EBT_VERDICT_BITS; 49 tmp = info->target & ~EBT_VERDICT_BITS;
diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c
index 6a28d994cf7d..2a63d996dd4e 100644
--- a/net/bridge/netfilter/ebt_nflog.c
+++ b/net/bridge/netfilter/ebt_nflog.c
@@ -35,12 +35,9 @@ ebt_nflog_tg(struct sk_buff *skb, const struct xt_target_param *par)
35 return EBT_CONTINUE; 35 return EBT_CONTINUE;
36} 36}
37 37
38static bool 38static bool ebt_nflog_tg_check(const struct xt_tgchk_param *par)
39ebt_nflog_tg_check(const char *table, const void *e,
40 const struct xt_target *target, void *data,
41 unsigned int hookmask)
42{ 39{
43 struct ebt_nflog_info *info = data; 40 struct ebt_nflog_info *info = par->targinfo;
44 41
45 if (info->flags & ~EBT_NFLOG_MASK) 42 if (info->flags & ~EBT_NFLOG_MASK)
46 return false; 43 return false;
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 0cfe2fad9404..c8a49f7a57ba 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -32,18 +32,19 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_target_param *par)
32 return info->target; 32 return info->target;
33} 33}
34 34
35static bool 35static bool ebt_redirect_tg_check(const struct xt_tgchk_param *par)
36ebt_redirect_tg_check(const char *tablename, const void *e,
37 const struct xt_target *target, void *data,
38 unsigned int hookmask)
39{ 36{
40 const struct ebt_redirect_info *info = data; 37 const struct ebt_redirect_info *info = par->targinfo;
38 unsigned int hook_mask;
41 39
42 if (BASE_CHAIN && info->target == EBT_RETURN) 40 if (BASE_CHAIN && info->target == EBT_RETURN)
43 return false; 41 return false;
44 CLEAR_BASE_CHAIN_BIT; 42
45 if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) && 43 hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
46 (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) 44 if ((strcmp(par->table, "nat") != 0 ||
45 hook_mask & ~(1 << NF_BR_PRE_ROUTING)) &&
46 (strcmp(par->table, "broute") != 0 ||
47 hook_mask & ~(1 << NF_BR_BROUTING)))
47 return false; 48 return false;
48 if (INVALID_TARGET) 49 if (INVALID_TARGET)
49 return false; 50 return false;
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index f55960eee996..8d04d4c302bd 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -42,18 +42,14 @@ out:
42 return info->target | ~EBT_VERDICT_BITS; 42 return info->target | ~EBT_VERDICT_BITS;
43} 43}
44 44
45static bool 45static bool ebt_snat_tg_check(const struct xt_tgchk_param *par)
46ebt_snat_tg_check(const char *tablename, const void *e,
47 const struct xt_target *target, void *data,
48 unsigned int hookmask)
49{ 46{
50 const struct ebt_nat_info *info = data; 47 const struct ebt_nat_info *info = par->targinfo;
51 int tmp; 48 int tmp;
52 49
53 tmp = info->target | ~EBT_VERDICT_BITS; 50 tmp = info->target | ~EBT_VERDICT_BITS;
54 if (BASE_CHAIN && tmp == EBT_RETURN) 51 if (BASE_CHAIN && tmp == EBT_RETURN)
55 return false; 52 return false;
56 CLEAR_BASE_CHAIN_BIT;
57 53
58 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) 54 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
59 return false; 55 return false;
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index bfedf12cbf41..2c6d6823e703 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -254,12 +254,9 @@ ebt_ulog_tg(struct sk_buff *skb, const struct xt_target_param *par)
254 return EBT_CONTINUE; 254 return EBT_CONTINUE;
255} 255}
256 256
257static bool 257static bool ebt_ulog_tg_check(const struct xt_tgchk_param *par)
258ebt_ulog_tg_check(const char *table, const void *entry,
259 const struct xt_target *target, void *data,
260 unsigned int hookmask)
261{ 258{
262 struct ebt_ulog_info *uloginfo = data; 259 struct ebt_ulog_info *uloginfo = par->targinfo;
263 260
264 if (uloginfo->nlgroup > 31) 261 if (uloginfo->nlgroup > 31)
265 return false; 262 return false;
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index a1156bab4a03..cf823c21c166 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -363,9 +363,10 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par,
363} 363}
364 364
365static inline int 365static inline int
366ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, 366ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
367 const char *name, unsigned int hookmask, unsigned int *cnt) 367 unsigned int *cnt)
368{ 368{
369 const struct ebt_entry *e = par->entryinfo;
369 struct xt_target *watcher; 370 struct xt_target *watcher;
370 size_t left = ((char *)e + e->target_offset) - (char *)w; 371 size_t left = ((char *)e + e->target_offset) - (char *)w;
371 int ret; 372 int ret;
@@ -383,9 +384,10 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
383 return -ENOENT; 384 return -ENOENT;
384 w->u.watcher = watcher; 385 w->u.watcher = watcher;
385 386
386 ret = xt_check_target(watcher, NFPROTO_BRIDGE, w->watcher_size, 387 par->target = watcher;
387 name, hookmask, e->ethproto, e->invflags & EBT_IPROTO, 388 par->targinfo = w->data;
388 e, w->data); 389 ret = xt_check_target(par, NFPROTO_BRIDGE, w->watcher_size,
390 e->ethproto, e->invflags & EBT_IPROTO);
389 if (ret < 0) { 391 if (ret < 0) {
390 module_put(watcher->me); 392 module_put(watcher->me);
391 return ret; 393 return ret;
@@ -619,6 +621,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
619 size_t gap; 621 size_t gap;
620 int ret; 622 int ret;
621 struct xt_mtchk_param mtpar; 623 struct xt_mtchk_param mtpar;
624 struct xt_tgchk_param tgpar;
622 625
623 /* don't mess with the struct ebt_entries */ 626 /* don't mess with the struct ebt_entries */
624 if (e->bitmask == 0) 627 if (e->bitmask == 0)
@@ -660,14 +663,14 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
660 } 663 }
661 i = 0; 664 i = 0;
662 665
663 mtpar.table = name; 666 mtpar.table = tgpar.table = name;
664 mtpar.entryinfo = e; 667 mtpar.entryinfo = tgpar.entryinfo = e;
665 mtpar.hook_mask = hookmask; 668 mtpar.hook_mask = tgpar.hook_mask = hookmask;
666 ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i); 669 ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i);
667 if (ret != 0) 670 if (ret != 0)
668 goto cleanup_matches; 671 goto cleanup_matches;
669 j = 0; 672 j = 0;
670 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j); 673 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, &tgpar, &j);
671 if (ret != 0) 674 if (ret != 0)
672 goto cleanup_watchers; 675 goto cleanup_watchers;
673 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); 676 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
@@ -703,9 +706,10 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
703 goto cleanup_watchers; 706 goto cleanup_watchers;
704 } 707 }
705 708
706 ret = xt_check_target(target, NFPROTO_BRIDGE, t->target_size, 709 tgpar.target = target;
707 name, hookmask, e->ethproto, e->invflags & EBT_IPROTO, 710 tgpar.targinfo = t->data;
708 e, t->data); 711 ret = xt_check_target(&tgpar, NFPROTO_BRIDGE, t->target_size,
712 e->ethproto, e->invflags & EBT_IPROTO);
709 if (ret < 0) { 713 if (ret < 0) {
710 module_put(target->me); 714 module_put(target->me);
711 goto cleanup_watchers; 715 goto cleanup_watchers;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 5b631ad74b5f..b3238d0101cc 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -457,16 +457,18 @@ static inline int check_entry(struct arpt_entry *e, const char *name)
457 457
458static inline int check_target(struct arpt_entry *e, const char *name) 458static inline int check_target(struct arpt_entry *e, const char *name)
459{ 459{
460 struct arpt_entry_target *t; 460 struct arpt_entry_target *t = arpt_get_target(e);
461 struct xt_target *target;
462 int ret; 461 int ret;
463 462 struct xt_tgchk_param par = {
464 t = arpt_get_target(e); 463 .table = name,
465 target = t->u.kernel.target; 464 .entryinfo = e,
466 465 .target = t->u.kernel.target,
467 ret = xt_check_target(target, NFPROTO_ARP, 466 .targinfo = t->data,
468 t->u.target_size - sizeof(*t), 467 .hook_mask = e->comefrom,
469 name, e->comefrom, 0, 0, e, t->data); 468 };
469
470 ret = xt_check_target(&par, NFPROTO_ARP,
471 t->u.target_size - sizeof(*t), 0, false);
470 if (ret < 0) { 472 if (ret < 0) {
471 duprintf("arp_tables: check failed for `%s'.\n", 473 duprintf("arp_tables: check failed for `%s'.\n",
472 t->u.kernel.target->name); 474 t->u.kernel.target->name);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 0bf81b353694..b0d5b1d0a769 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -54,11 +54,9 @@ target(struct sk_buff *skb, const struct xt_target_param *par)
54 return mangle->target; 54 return mangle->target;
55} 55}
56 56
57static bool 57static bool checkentry(const struct xt_tgchk_param *par)
58checkentry(const char *tablename, const void *e, const struct xt_target *target,
59 void *targinfo, unsigned int hook_mask)
60{ 58{
61 const struct arpt_mangle *mangle = targinfo; 59 const struct arpt_mangle *mangle = par->targinfo;
62 60
63 if (mangle->flags & ~ARPT_MANGLE_MASK || 61 if (mangle->flags & ~ARPT_MANGLE_MASK ||
64 !(mangle->flags & ARPT_MANGLE_MASK)) 62 !(mangle->flags & ARPT_MANGLE_MASK))
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 0f8ecf390229..e592c54d4992 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -655,15 +655,18 @@ err:
655 655
656static int check_target(struct ipt_entry *e, const char *name) 656static int check_target(struct ipt_entry *e, const char *name)
657{ 657{
658 struct ipt_entry_target *t; 658 struct ipt_entry_target *t = ipt_get_target(e);
659 struct xt_target *target; 659 struct xt_tgchk_param par = {
660 .table = name,
661 .entryinfo = e,
662 .target = t->u.kernel.target,
663 .targinfo = t->data,
664 .hook_mask = e->comefrom,
665 };
660 int ret; 666 int ret;
661 667
662 t = ipt_get_target(e); 668 ret = xt_check_target(&par, NFPROTO_IPV4, t->u.target_size - sizeof(*t),
663 target = t->u.kernel.target; 669 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
664 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
665 name, e->comefrom, e->ip.proto,
666 e->ip.invflags & IPT_INV_PROTO, e, t->data);
667 if (ret < 0) { 670 if (ret < 0) {
668 duprintf("ip_tables: check failed for `%s'.\n", 671 duprintf("ip_tables: check failed for `%s'.\n",
669 t->u.kernel.target->name); 672 t->u.kernel.target->name);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 67e8aa8f34f2..6c7254e02561 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -347,13 +347,10 @@ clusterip_tg(struct sk_buff *skb, const struct xt_target_param *par)
347 return XT_CONTINUE; 347 return XT_CONTINUE;
348} 348}
349 349
350static bool 350static bool clusterip_tg_check(const struct xt_tgchk_param *par)
351clusterip_tg_check(const char *tablename, const void *e_void,
352 const struct xt_target *target, void *targinfo,
353 unsigned int hook_mask)
354{ 351{
355 struct ipt_clusterip_tgt_info *cipinfo = targinfo; 352 struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
356 const struct ipt_entry *e = e_void; 353 const struct ipt_entry *e = par->entryinfo;
357 354
358 struct clusterip_config *config; 355 struct clusterip_config *config;
359 356
@@ -404,9 +401,9 @@ clusterip_tg_check(const char *tablename, const void *e_void,
404 } 401 }
405 cipinfo->config = config; 402 cipinfo->config = config;
406 403
407 if (nf_ct_l3proto_try_module_get(target->family) < 0) { 404 if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
408 printk(KERN_WARNING "can't load conntrack support for " 405 printk(KERN_WARNING "can't load conntrack support for "
409 "proto=%u\n", target->family); 406 "proto=%u\n", par->target->family);
410 return false; 407 return false;
411 } 408 }
412 409
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index e37f181e8298..f7e2fa0974dc 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -93,13 +93,10 @@ ecn_tg(struct sk_buff *skb, const struct xt_target_param *par)
93 return XT_CONTINUE; 93 return XT_CONTINUE;
94} 94}
95 95
96static bool 96static bool ecn_tg_check(const struct xt_tgchk_param *par)
97ecn_tg_check(const char *tablename, const void *e_void,
98 const struct xt_target *target, void *targinfo,
99 unsigned int hook_mask)
100{ 97{
101 const struct ipt_ECN_info *einfo = targinfo; 98 const struct ipt_ECN_info *einfo = par->targinfo;
102 const struct ipt_entry *e = e_void; 99 const struct ipt_entry *e = par->entryinfo;
103 100
104 if (einfo->operation & IPT_ECN_OP_MASK) { 101 if (einfo->operation & IPT_ECN_OP_MASK) {
105 printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", 102 printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index e9942aed35ae..fc6ce04a3e35 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -440,12 +440,9 @@ log_tg(struct sk_buff *skb, const struct xt_target_param *par)
440 return XT_CONTINUE; 440 return XT_CONTINUE;
441} 441}
442 442
443static bool 443static bool log_tg_check(const struct xt_tgchk_param *par)
444log_tg_check(const char *tablename, const void *e,
445 const struct xt_target *target, void *targinfo,
446 unsigned int hook_mask)
447{ 444{
448 const struct ipt_log_info *loginfo = targinfo; 445 const struct ipt_log_info *loginfo = par->targinfo;
449 446
450 if (loginfo->level >= 8) { 447 if (loginfo->level >= 8) {
451 pr_debug("LOG: level %u >= 8\n", loginfo->level); 448 pr_debug("LOG: level %u >= 8\n", loginfo->level);
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index e0d9d49b79ee..f389f60cb105 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -31,12 +31,9 @@ MODULE_DESCRIPTION("Xtables: automatic-address SNAT");
31static DEFINE_RWLOCK(masq_lock); 31static DEFINE_RWLOCK(masq_lock);
32 32
33/* FIXME: Multiple targets. --RR */ 33/* FIXME: Multiple targets. --RR */
34static bool 34static bool masquerade_tg_check(const struct xt_tgchk_param *par)
35masquerade_tg_check(const char *tablename, const void *e,
36 const struct xt_target *target, void *targinfo,
37 unsigned int hook_mask)
38{ 35{
39 const struct nf_nat_multi_range_compat *mr = targinfo; 36 const struct nf_nat_multi_range_compat *mr = par->targinfo;
40 37
41 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 38 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
42 pr_debug("masquerade_check: bad MAP_IPS.\n"); 39 pr_debug("masquerade_check: bad MAP_IPS.\n");
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index cf18f23b3460..7c29582d4ec8 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -22,12 +22,9 @@ MODULE_LICENSE("GPL");
22MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); 22MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
23MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets"); 23MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets");
24 24
25static bool 25static bool netmap_tg_check(const struct xt_tgchk_param *par)
26netmap_tg_check(const char *tablename, const void *e,
27 const struct xt_target *target, void *targinfo,
28 unsigned int hook_mask)
29{ 26{
30 const struct nf_nat_multi_range_compat *mr = targinfo; 27 const struct nf_nat_multi_range_compat *mr = par->targinfo;
31 28
32 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { 29 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
33 pr_debug("NETMAP:check: bad MAP_IPS.\n"); 30 pr_debug("NETMAP:check: bad MAP_IPS.\n");
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 23adb09ddfb4..698e5e78685b 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -26,12 +26,9 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
26MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); 26MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
27 27
28/* FIXME: Take multiple ranges --RR */ 28/* FIXME: Take multiple ranges --RR */
29static bool 29static bool redirect_tg_check(const struct xt_tgchk_param *par)
30redirect_tg_check(const char *tablename, const void *e,
31 const struct xt_target *target, void *targinfo,
32 unsigned int hook_mask)
33{ 30{
34 const struct nf_nat_multi_range_compat *mr = targinfo; 31 const struct nf_nat_multi_range_compat *mr = par->targinfo;
35 32
36 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 33 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
37 pr_debug("redirect_check: bad MAP_IPS.\n"); 34 pr_debug("redirect_check: bad MAP_IPS.\n");
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index b36071bb1077..0b4b6e0ff2b9 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -175,13 +175,10 @@ reject_tg(struct sk_buff *skb, const struct xt_target_param *par)
175 return NF_DROP; 175 return NF_DROP;
176} 176}
177 177
178static bool 178static bool reject_tg_check(const struct xt_tgchk_param *par)
179reject_tg_check(const char *tablename, const void *e_void,
180 const struct xt_target *target, void *targinfo,
181 unsigned int hook_mask)
182{ 179{
183 const struct ipt_reject_info *rejinfo = targinfo; 180 const struct ipt_reject_info *rejinfo = par->targinfo;
184 const struct ipt_entry *e = e_void; 181 const struct ipt_entry *e = par->entryinfo;
185 182
186 if (rejinfo->with == IPT_ICMP_ECHOREPLY) { 183 if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
187 printk("ipt_REJECT: ECHOREPLY no longer supported.\n"); 184 printk("ipt_REJECT: ECHOREPLY no longer supported.\n");
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index 05cbfd2f7470..6d76aae90cc0 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -59,12 +59,9 @@ ttl_tg(struct sk_buff *skb, const struct xt_target_param *par)
59 return XT_CONTINUE; 59 return XT_CONTINUE;
60} 60}
61 61
62static bool 62static bool ttl_tg_check(const struct xt_tgchk_param *par)
63ttl_tg_check(const char *tablename, const void *e,
64 const struct xt_target *target, void *targinfo,
65 unsigned int hook_mask)
66{ 63{
67 const struct ipt_TTL_info *info = targinfo; 64 const struct ipt_TTL_info *info = par->targinfo;
68 65
69 if (info->mode > IPT_TTL_MAXMODE) { 66 if (info->mode > IPT_TTL_MAXMODE) {
70 printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", 67 printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 46c0df0dc2dc..18a2826b57c6 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -313,12 +313,9 @@ static void ipt_logfn(u_int8_t pf,
313 ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); 313 ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
314} 314}
315 315
316static bool 316static bool ulog_tg_check(const struct xt_tgchk_param *par)
317ulog_tg_check(const char *tablename, const void *e,
318 const struct xt_target *target, void *targinfo,
319 unsigned int hookmask)
320{ 317{
321 const struct ipt_ulog_info *loginfo = targinfo; 318 const struct ipt_ulog_info *loginfo = par->targinfo;
322 319
323 if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { 320 if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
324 pr_debug("ipt_ULOG: prefix term %i\n", 321 pr_debug("ipt_ULOG: prefix term %i\n",
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 83170ff131f9..bea54a685109 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -128,13 +128,9 @@ ipt_dnat_target(struct sk_buff *skb, const struct xt_target_param *par)
128 return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); 128 return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST);
129} 129}
130 130
131static bool ipt_snat_checkentry(const char *tablename, 131static bool ipt_snat_checkentry(const struct xt_tgchk_param *par)
132 const void *entry,
133 const struct xt_target *target,
134 void *targinfo,
135 unsigned int hook_mask)
136{ 132{
137 const struct nf_nat_multi_range_compat *mr = targinfo; 133 const struct nf_nat_multi_range_compat *mr = par->targinfo;
138 134
139 /* Must be a valid range */ 135 /* Must be a valid range */
140 if (mr->rangesize != 1) { 136 if (mr->rangesize != 1) {
@@ -144,13 +140,9 @@ static bool ipt_snat_checkentry(const char *tablename,
144 return true; 140 return true;
145} 141}
146 142
147static bool ipt_dnat_checkentry(const char *tablename, 143static bool ipt_dnat_checkentry(const struct xt_tgchk_param *par)
148 const void *entry,
149 const struct xt_target *target,
150 void *targinfo,
151 unsigned int hook_mask)
152{ 144{
153 const struct nf_nat_multi_range_compat *mr = targinfo; 145 const struct nf_nat_multi_range_compat *mr = par->targinfo;
154 146
155 /* Must be a valid range */ 147 /* Must be a valid range */
156 if (mr->rangesize != 1) { 148 if (mr->rangesize != 1) {
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index ee0986cdbd66..ca14fb8bd362 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -679,15 +679,19 @@ err:
679 679
680static int check_target(struct ip6t_entry *e, const char *name) 680static int check_target(struct ip6t_entry *e, const char *name)
681{ 681{
682 struct ip6t_entry_target *t; 682 struct ip6t_entry_target *t = ip6t_get_target(e);
683 struct xt_target *target; 683 struct xt_tgchk_param par = {
684 .table = name,
685 .entryinfo = e,
686 .target = t->u.kernel.target,
687 .targinfo = t->data,
688 .hook_mask = e->comefrom,
689 };
684 int ret; 690 int ret;
685 691
686 t = ip6t_get_target(e); 692 t = ip6t_get_target(e);
687 target = t->u.kernel.target; 693 ret = xt_check_target(&par, NFPROTO_IPV6, t->u.target_size - sizeof(*t),
688 ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t), 694 e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO);
689 name, e->comefrom, e->ipv6.proto,
690 e->ipv6.invflags & IP6T_INV_PROTO, e, t->data);
691 if (ret < 0) { 695 if (ret < 0) {
692 duprintf("ip_tables: check failed for `%s'.\n", 696 duprintf("ip_tables: check failed for `%s'.\n",
693 t->u.kernel.target->name); 697 t->u.kernel.target->name);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index ac759a54f2c6..27b5adf670a2 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -54,12 +54,9 @@ hl_tg6(struct sk_buff *skb, const struct xt_target_param *par)
54 return XT_CONTINUE; 54 return XT_CONTINUE;
55} 55}
56 56
57static bool 57static bool hl_tg6_check(const struct xt_tgchk_param *par)
58hl_tg6_check(const char *tablename, const void *entry,
59 const struct xt_target *target, void *targinfo,
60 unsigned int hook_mask)
61{ 58{
62 const struct ip6t_HL_info *info = targinfo; 59 const struct ip6t_HL_info *info = par->targinfo;
63 60
64 if (info->mode > IP6T_HL_MAXMODE) { 61 if (info->mode > IP6T_HL_MAXMODE) {
65 printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", 62 printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index a31d3ecd1fc9..caa441d09567 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -453,12 +453,9 @@ log_tg6(struct sk_buff *skb, const struct xt_target_param *par)
453} 453}
454 454
455 455
456static bool 456static bool log_tg6_check(const struct xt_tgchk_param *par)
457log_tg6_check(const char *tablename, const void *entry,
458 const struct xt_target *target, void *targinfo,
459 unsigned int hook_mask)
460{ 457{
461 const struct ip6t_log_info *loginfo = targinfo; 458 const struct ip6t_log_info *loginfo = par->targinfo;
462 459
463 if (loginfo->level >= 8) { 460 if (loginfo->level >= 8) {
464 pr_debug("LOG: level %u >= 8\n", loginfo->level); 461 pr_debug("LOG: level %u >= 8\n", loginfo->level);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 1d5f3a70ed09..0981b4ccb8b1 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -213,13 +213,10 @@ reject_tg6(struct sk_buff *skb, const struct xt_target_param *par)
213 return NF_DROP; 213 return NF_DROP;
214} 214}
215 215
216static bool 216static bool reject_tg6_check(const struct xt_tgchk_param *par)
217reject_tg6_check(const char *tablename, const void *entry,
218 const struct xt_target *target, void *targinfo,
219 unsigned int hook_mask)
220{ 217{
221 const struct ip6t_reject_info *rejinfo = targinfo; 218 const struct ip6t_reject_info *rejinfo = par->targinfo;
222 const struct ip6t_entry *e = entry; 219 const struct ip6t_entry *e = par->entryinfo;
223 220
224 if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { 221 if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
225 printk("ip6t_REJECT: ECHOREPLY is not supported.\n"); 222 printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 817ab14f7cd6..f29513cd1399 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -471,35 +471,35 @@ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
471EXPORT_SYMBOL_GPL(xt_compat_match_to_user); 471EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
472#endif /* CONFIG_COMPAT */ 472#endif /* CONFIG_COMPAT */
473 473
474int xt_check_target(const struct xt_target *target, unsigned short family, 474int xt_check_target(struct xt_tgchk_param *par, u_int8_t family,
475 unsigned int size, const char *table, unsigned int hook_mask, 475 unsigned int size, u_int8_t proto, bool inv_proto)
476 unsigned short proto, int inv_proto, const void *entry,
477 void *targinfo)
478{ 476{
479 if (XT_ALIGN(target->targetsize) != size) { 477 if (XT_ALIGN(par->target->targetsize) != size) {
480 printk("%s_tables: %s target: invalid size %Zu != %u\n", 478 printk("%s_tables: %s target: invalid size %Zu != %u\n",
481 xt_prefix[family], target->name, 479 xt_prefix[family], par->target->name,
482 XT_ALIGN(target->targetsize), size); 480 XT_ALIGN(par->target->targetsize), size);
483 return -EINVAL; 481 return -EINVAL;
484 } 482 }
485 if (target->table && strcmp(target->table, table)) { 483 if (par->target->table != NULL &&
484 strcmp(par->target->table, par->table) != 0) {
486 printk("%s_tables: %s target: only valid in %s table, not %s\n", 485 printk("%s_tables: %s target: only valid in %s table, not %s\n",
487 xt_prefix[family], target->name, target->table, table); 486 xt_prefix[family], par->target->name,
487 par->target->table, par->table);
488 return -EINVAL; 488 return -EINVAL;
489 } 489 }
490 if (target->hooks && (hook_mask & ~target->hooks) != 0) { 490 if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) {
491 printk("%s_tables: %s target: bad hook_mask %#x/%#x\n", 491 printk("%s_tables: %s target: bad hook_mask %#x/%#x\n",
492 xt_prefix[family], target->name, hook_mask, 492 xt_prefix[family], par->target->name, par->hook_mask,
493 target->hooks); 493 par->target->hooks);
494 return -EINVAL; 494 return -EINVAL;
495 } 495 }
496 if (target->proto && (target->proto != proto || inv_proto)) { 496 if (par->target->proto && (par->target->proto != proto || inv_proto)) {
497 printk("%s_tables: %s target: only valid for protocol %u\n", 497 printk("%s_tables: %s target: only valid for protocol %u\n",
498 xt_prefix[family], target->name, target->proto); 498 xt_prefix[family], par->target->name,
499 par->target->proto);
499 return -EINVAL; 500 return -EINVAL;
500 } 501 }
501 if (target->checkentry != NULL && 502 if (par->target->checkentry != NULL && !par->target->checkentry(par))
502 !target->checkentry(table, entry, target, targinfo, hook_mask))
503 return -EINVAL; 503 return -EINVAL;
504 return 0; 504 return 0;
505} 505}
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 95ed267328a7..8fc9f35e67df 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -112,18 +112,15 @@ connmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
112 return XT_CONTINUE; 112 return XT_CONTINUE;
113} 113}
114 114
115static bool 115static bool connmark_tg_check_v0(const struct xt_tgchk_param *par)
116connmark_tg_check_v0(const char *tablename, const void *entry,
117 const struct xt_target *target, void *targinfo,
118 unsigned int hook_mask)
119{ 116{
120 const struct xt_connmark_target_info *matchinfo = targinfo; 117 const struct xt_connmark_target_info *matchinfo = par->targinfo;
121 118
122 if (matchinfo->mode == XT_CONNMARK_RESTORE) { 119 if (matchinfo->mode == XT_CONNMARK_RESTORE) {
123 if (strcmp(tablename, "mangle") != 0) { 120 if (strcmp(par->table, "mangle") != 0) {
124 printk(KERN_WARNING "CONNMARK: restore can only be " 121 printk(KERN_WARNING "CONNMARK: restore can only be "
125 "called from \"mangle\" table, not \"%s\"\n", 122 "called from \"mangle\" table, not \"%s\"\n",
126 tablename); 123 par->table);
127 return false; 124 return false;
128 } 125 }
129 } 126 }
@@ -131,22 +128,19 @@ connmark_tg_check_v0(const char *tablename, const void *entry,
131 printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); 128 printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
132 return false; 129 return false;
133 } 130 }
134 if (nf_ct_l3proto_try_module_get(target->family) < 0) { 131 if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
135 printk(KERN_WARNING "can't load conntrack support for " 132 printk(KERN_WARNING "can't load conntrack support for "
136 "proto=%u\n", target->family); 133 "proto=%u\n", par->target->family);
137 return false; 134 return false;
138 } 135 }
139 return true; 136 return true;
140} 137}
141 138
142static bool 139static bool connmark_tg_check(const struct xt_tgchk_param *par)
143connmark_tg_check(const char *tablename, const void *entry,
144 const struct xt_target *target, void *targinfo,
145 unsigned int hook_mask)
146{ 140{
147 if (nf_ct_l3proto_try_module_get(target->family) < 0) { 141 if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
148 printk(KERN_WARNING "cannot load conntrack support for " 142 printk(KERN_WARNING "cannot load conntrack support for "
149 "proto=%u\n", target->family); 143 "proto=%u\n", par->target->family);
150 return false; 144 return false;
151 } 145 }
152 return true; 146 return true;
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 2211a2cef280..2041a3d4b4d8 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -85,16 +85,14 @@ connsecmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
85 return XT_CONTINUE; 85 return XT_CONTINUE;
86} 86}
87 87
88static bool 88static bool connsecmark_tg_check(const struct xt_tgchk_param *par)
89connsecmark_tg_check(const char *tablename, const void *entry,
90 const struct xt_target *target, void *targinfo,
91 unsigned int hook_mask)
92{ 89{
93 const struct xt_connsecmark_target_info *info = targinfo; 90 const struct xt_connsecmark_target_info *info = par->targinfo;
94 91
95 if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) { 92 if (strcmp(par->table, "mangle") != 0 &&
93 strcmp(par->table, "security") != 0) {
96 printk(KERN_INFO PFX "target only valid in the \'mangle\' " 94 printk(KERN_INFO PFX "target only valid in the \'mangle\' "
97 "or \'security\' tables, not \'%s\'.\n", tablename); 95 "or \'security\' tables, not \'%s\'.\n", par->table);
98 return false; 96 return false;
99 } 97 }
100 98
@@ -108,9 +106,9 @@ connsecmark_tg_check(const char *tablename, const void *entry,
108 return false; 106 return false;
109 } 107 }
110 108
111 if (nf_ct_l3proto_try_module_get(target->family) < 0) { 109 if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
112 printk(KERN_WARNING "can't load conntrack support for " 110 printk(KERN_WARNING "can't load conntrack support for "
113 "proto=%u\n", target->family); 111 "proto=%u\n", par->target->family);
114 return false; 112 return false;
115 } 113 }
116 return true; 114 return true;
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index c78e80afdf3d..6a347e768f86 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -61,15 +61,12 @@ dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par)
61 return XT_CONTINUE; 61 return XT_CONTINUE;
62} 62}
63 63
64static bool 64static bool dscp_tg_check(const struct xt_tgchk_param *par)
65dscp_tg_check(const char *tablename, const void *e_void,
66 const struct xt_target *target, void *targinfo,
67 unsigned int hook_mask)
68{ 65{
69 const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp; 66 const struct xt_DSCP_info *info = par->targinfo;
70 67
71 if (dscp > XT_DSCP_MAX) { 68 if (info->dscp > XT_DSCP_MAX) {
72 printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); 69 printk(KERN_WARNING "DSCP: dscp %x out of range\n", info->dscp);
73 return false; 70 return false;
74 } 71 }
75 return true; 72 return true;
@@ -95,12 +92,10 @@ tos_tg_v0(struct sk_buff *skb, const struct xt_target_param *par)
95 return XT_CONTINUE; 92 return XT_CONTINUE;
96} 93}
97 94
98static bool 95static bool tos_tg_check_v0(const struct xt_tgchk_param *par)
99tos_tg_check_v0(const char *tablename, const void *e_void,
100 const struct xt_target *target, void *targinfo,
101 unsigned int hook_mask)
102{ 96{
103 const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos; 97 const struct ipt_tos_target_info *info = par->targinfo;
98 const uint8_t tos = info->tos;
104 99
105 if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT && 100 if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT &&
106 tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST && 101 tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST &&
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 27d03f396117..123ee0ba78c6 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -66,12 +66,9 @@ mark_tg(struct sk_buff *skb, const struct xt_target_param *par)
66 return XT_CONTINUE; 66 return XT_CONTINUE;
67} 67}
68 68
69static bool 69static bool mark_tg_check_v0(const struct xt_tgchk_param *par)
70mark_tg_check_v0(const char *tablename, const void *entry,
71 const struct xt_target *target, void *targinfo,
72 unsigned int hook_mask)
73{ 70{
74 const struct xt_mark_target_info *markinfo = targinfo; 71 const struct xt_mark_target_info *markinfo = par->targinfo;
75 72
76 if (markinfo->mark > 0xffffffff) { 73 if (markinfo->mark > 0xffffffff) {
77 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); 74 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
@@ -80,12 +77,9 @@ mark_tg_check_v0(const char *tablename, const void *entry,
80 return true; 77 return true;
81} 78}
82 79
83static bool 80static bool mark_tg_check_v1(const struct xt_tgchk_param *par)
84mark_tg_check_v1(const char *tablename, const void *entry,
85 const struct xt_target *target, void *targinfo,
86 unsigned int hook_mask)
87{ 81{
88 const struct xt_mark_target_info_v1 *markinfo = targinfo; 82 const struct xt_mark_target_info_v1 *markinfo = par->targinfo;
89 83
90 if (markinfo->mode != XT_MARK_SET 84 if (markinfo->mode != XT_MARK_SET
91 && markinfo->mode != XT_MARK_AND 85 && markinfo->mode != XT_MARK_AND
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index 3218ad63bd1d..56ee4f118b59 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -36,12 +36,9 @@ nflog_tg(struct sk_buff *skb, const struct xt_target_param *par)
36 return XT_CONTINUE; 36 return XT_CONTINUE;
37} 37}
38 38
39static bool 39static bool nflog_tg_check(const struct xt_tgchk_param *par)
40nflog_tg_check(const char *tablename, const void *entry,
41 const struct xt_target *target, void *targetinfo,
42 unsigned int hookmask)
43{ 40{
44 const struct xt_nflog_info *info = targetinfo; 41 const struct xt_nflog_info *info = par->targinfo;
45 42
46 if (info->flags & ~XT_NFLOG_MASK) 43 if (info->flags & ~XT_NFLOG_MASK)
47 return false; 44 return false;
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
index 92e33524f784..edf4ab1f30ff 100644
--- a/net/netfilter/xt_RATEEST.c
+++ b/net/netfilter/xt_RATEEST.c
@@ -84,14 +84,9 @@ xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par)
84 return XT_CONTINUE; 84 return XT_CONTINUE;
85} 85}
86 86
87static bool 87static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
88xt_rateest_tg_checkentry(const char *tablename,
89 const void *entry,
90 const struct xt_target *target,
91 void *targinfo,
92 unsigned int hook_mask)
93{ 88{
94 struct xt_rateest_target_info *info = targinfo; 89 struct xt_rateest_target_info *info = par->targinfo;
95 struct xt_rateest *est; 90 struct xt_rateest *est;
96 struct { 91 struct {
97 struct nlattr opt; 92 struct nlattr opt;
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index ad05214e3809..e5777227192c 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -80,16 +80,14 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
80 return true; 80 return true;
81} 81}
82 82
83static bool 83static bool secmark_tg_check(const struct xt_tgchk_param *par)
84secmark_tg_check(const char *tablename, const void *entry,
85 const struct xt_target *target, void *targinfo,
86 unsigned int hook_mask)
87{ 84{
88 struct xt_secmark_target_info *info = targinfo; 85 struct xt_secmark_target_info *info = par->targinfo;
89 86
90 if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) { 87 if (strcmp(par->table, "mangle") != 0 &&
88 strcmp(par->table, "security") != 0) {
91 printk(KERN_INFO PFX "target only valid in the \'mangle\' " 89 printk(KERN_INFO PFX "target only valid in the \'mangle\' "
92 "or \'security\' tables, not \'%s\'.\n", tablename); 90 "or \'security\' tables, not \'%s\'.\n", par->table);
93 return false; 91 return false;
94 } 92 }
95 93
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index e08762d9b0ff..4f3b1f808795 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -237,16 +237,13 @@ static inline bool find_syn_match(const struct xt_entry_match *m)
237 return false; 237 return false;
238} 238}
239 239
240static bool 240static bool tcpmss_tg4_check(const struct xt_tgchk_param *par)
241tcpmss_tg4_check(const char *tablename, const void *entry,
242 const struct xt_target *target, void *targinfo,
243 unsigned int hook_mask)
244{ 241{
245 const struct xt_tcpmss_info *info = targinfo; 242 const struct xt_tcpmss_info *info = par->targinfo;
246 const struct ipt_entry *e = entry; 243 const struct ipt_entry *e = par->entryinfo;
247 244
248 if (info->mss == XT_TCPMSS_CLAMP_PMTU && 245 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
249 (hook_mask & ~((1 << NF_INET_FORWARD) | 246 (par->hook_mask & ~((1 << NF_INET_FORWARD) |
250 (1 << NF_INET_LOCAL_OUT) | 247 (1 << NF_INET_LOCAL_OUT) |
251 (1 << NF_INET_POST_ROUTING))) != 0) { 248 (1 << NF_INET_POST_ROUTING))) != 0) {
252 printk("xt_TCPMSS: path-MTU clamping only supported in " 249 printk("xt_TCPMSS: path-MTU clamping only supported in "
@@ -260,16 +257,13 @@ tcpmss_tg4_check(const char *tablename, const void *entry,
260} 257}
261 258
262#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) 259#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
263static bool 260static bool tcpmss_tg6_check(const struct xt_tgchk_param *par)
264tcpmss_tg6_check(const char *tablename, const void *entry,
265 const struct xt_target *target, void *targinfo,
266 unsigned int hook_mask)
267{ 261{
268 const struct xt_tcpmss_info *info = targinfo; 262 const struct xt_tcpmss_info *info = par->targinfo;
269 const struct ip6t_entry *e = entry; 263 const struct ip6t_entry *e = par->entryinfo;
270 264
271 if (info->mss == XT_TCPMSS_CLAMP_PMTU && 265 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
272 (hook_mask & ~((1 << NF_INET_FORWARD) | 266 (par->hook_mask & ~((1 << NF_INET_FORWARD) |
273 (1 << NF_INET_LOCAL_OUT) | 267 (1 << NF_INET_LOCAL_OUT) |
274 (1 << NF_INET_POST_ROUTING))) != 0) { 268 (1 << NF_INET_POST_ROUTING))) != 0) {
275 printk("xt_TCPMSS: path-MTU clamping only supported in " 269 printk("xt_TCPMSS: path-MTU clamping only supported in "
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index f08c49ea4bdc..1340c2fa3621 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -59,14 +59,9 @@ tproxy_tg(struct sk_buff *skb, const struct xt_target_param *par)
59 return NF_DROP; 59 return NF_DROP;
60} 60}
61 61
62static bool 62static bool tproxy_tg_check(const struct xt_tgchk_param *par)
63tproxy_tg_check(const char *tablename,
64 const void *entry,
65 const struct xt_target *target,
66 void *targetinfo,
67 unsigned int hook_mask)
68{ 63{
69 const struct ipt_ip *i = entry; 64 const struct ipt_ip *i = par->entryinfo;
70 65
71 if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) 66 if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
72 && !(i->invflags & IPT_INV_PROTO)) 67 && !(i->invflags & IPT_INV_PROTO))
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 89791a56429a..a54dc3f8234f 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -40,6 +40,7 @@ static struct tcf_hashinfo ipt_hash_info = {
40 40
41static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) 41static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
42{ 42{
43 struct xt_tgchk_param par;
43 struct xt_target *target; 44 struct xt_target *target;
44 int ret = 0; 45 int ret = 0;
45 46
@@ -49,9 +50,14 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int
49 return -ENOENT; 50 return -ENOENT;
50 51
51 t->u.kernel.target = target; 52 t->u.kernel.target = target;
52 53 par.table = table;
53 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), 54 par.entryinfo = NULL;
54 table, hook, 0, 0, NULL, t->data); 55 par.target = target;
56 par.targinfo = t->data;
57 par.hook_mask = hook;
58
59 ret = xt_check_target(&par, NFPROTO_IPV4,
60 t->u.target_size - sizeof(*t), 0, false);
55 if (ret < 0) { 61 if (ret < 0) {
56 module_put(t->u.kernel.target->me); 62 module_put(t->u.kernel.target->me);
57 return ret; 63 return ret;