Commit af5d6dc2 authored by Jan Engelhardt's avatar Jan Engelhardt Committed by Patrick McHardy

netfilter: xtables: move extension arguments into compound structure (5/6)

This patch does this for target extensions' checkentry functions.
Signed-off-by: default avatarJan Engelhardt <jengelh@medozas.de>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent 7eb35586
...@@ -234,6 +234,23 @@ struct xt_target_param { ...@@ -234,6 +234,23 @@ struct xt_target_param {
const void *targinfo; const void *targinfo;
}; };
/**
* struct xt_tgchk_param - parameters for target extensions'
* checkentry functions
*
* @entryinfo: the family-specific rule data
* (struct ipt_entry, ip6t_entry, arpt_entry, ebt_entry)
*
* Other fields see above.
*/
struct xt_tgchk_param {
const char *table;
void *entryinfo;
const struct xt_target *target;
void *targinfo;
unsigned int hook_mask;
};
struct xt_match struct xt_match
{ {
struct list_head list; struct list_head list;
...@@ -291,11 +308,7 @@ struct xt_target ...@@ -291,11 +308,7 @@ struct xt_target
hook_mask is a bitmask of hooks from which it can be hook_mask is a bitmask of hooks from which it can be
called. */ called. */
/* Should return true or false. */ /* Should return true or false. */
bool (*checkentry)(const char *tablename, bool (*checkentry)(const struct xt_tgchk_param *);
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int hook_mask);
/* Called when entry of this type deleted. */ /* Called when entry of this type deleted. */
void (*destroy)(const struct xt_target *target, void *targinfo); 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,10 +389,8 @@ extern void xt_unregister_matches(struct xt_match *match, unsigned int n);
extern int xt_check_match(struct xt_mtchk_param *, u_int8_t family, extern int xt_check_match(struct xt_mtchk_param *, u_int8_t family,
unsigned int size, u_int8_t proto, bool inv_proto); unsigned int size, u_int8_t proto, bool inv_proto);
extern int xt_check_target(const struct xt_target *target, unsigned short family, extern int xt_check_target(struct xt_tgchk_param *, u_int8_t family,
unsigned int size, const char *table, unsigned int hook, unsigned int size, u_int8_t proto, bool inv_proto);
unsigned short proto, int inv_proto,
const void *entry, void *targinfo);
extern struct xt_table *xt_register_table(struct net *net, extern struct xt_table *xt_register_table(struct net *net,
struct xt_table *table, struct xt_table *table,
......
...@@ -310,9 +310,9 @@ extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb, ...@@ -310,9 +310,9 @@ extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb,
#define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg)) #define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg))
/* True if the hook mask denotes that the rule is in a base chain, /* True if the hook mask denotes that the rule is in a base chain,
* used in the check() functions */ * used in the check() functions */
#define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS)) #define BASE_CHAIN (par->hook_mask & (1 << NF_BR_NUMHOOKS))
/* Clear the bit in the hook mask that tells if the rule is on a base chain */ /* Clear the bit in the hook mask that tells if the rule is on a base chain */
#define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS)) #define CLEAR_BASE_CHAIN_BIT (par->hook_mask &= ~(1 << NF_BR_NUMHOOKS))
/* True if the target is not a standard target */ /* True if the target is not a standard target */
#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0) #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)
......
...@@ -57,20 +57,16 @@ ebt_arpreply_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -57,20 +57,16 @@ ebt_arpreply_tg(struct sk_buff *skb, const struct xt_target_param *par)
return info->target; return info->target;
} }
static bool static bool ebt_arpreply_tg_check(const struct xt_tgchk_param *par)
ebt_arpreply_tg_check(const char *tablename, const void *entry,
const struct xt_target *target, void *data,
unsigned int hookmask)
{ {
const struct ebt_arpreply_info *info = data; const struct ebt_arpreply_info *info = par->targinfo;
const struct ebt_entry *e = entry; const struct ebt_entry *e = par->entryinfo;
if (BASE_CHAIN && info->target == EBT_RETURN) if (BASE_CHAIN && info->target == EBT_RETURN)
return false; return false;
if (e->ethproto != htons(ETH_P_ARP) || if (e->ethproto != htons(ETH_P_ARP) ||
e->invflags & EBT_IPROTO) e->invflags & EBT_IPROTO)
return false; return false;
CLEAR_BASE_CHAIN_BIT;
return true; return true;
} }
......
...@@ -26,19 +26,20 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -26,19 +26,20 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_target_param *par)
return info->target; return info->target;
} }
static bool static bool ebt_dnat_tg_check(const struct xt_tgchk_param *par)
ebt_dnat_tg_check(const char *tablename, const void *entry,
const struct xt_target *target, void *data,
unsigned int hookmask)
{ {
const struct ebt_nat_info *info = data; const struct ebt_nat_info *info = par->targinfo;
unsigned int hook_mask;
if (BASE_CHAIN && info->target == EBT_RETURN) if (BASE_CHAIN && info->target == EBT_RETURN)
return false; return false;
CLEAR_BASE_CHAIN_BIT;
if ( (strcmp(tablename, "nat") || hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
(hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) && if ((strcmp(par->table, "nat") != 0 ||
(strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) (hook_mask & ~((1 << NF_BR_PRE_ROUTING) |
(1 << NF_BR_LOCAL_OUT)))) &&
(strcmp(par->table, "broute") != 0 ||
hook_mask & ~(1 << NF_BR_BROUTING)))
return false; return false;
if (INVALID_TARGET) if (INVALID_TARGET)
return false; return false;
......
...@@ -24,12 +24,9 @@ ...@@ -24,12 +24,9 @@
static DEFINE_SPINLOCK(ebt_log_lock); static DEFINE_SPINLOCK(ebt_log_lock);
static bool static bool ebt_log_tg_check(const struct xt_tgchk_param *par)
ebt_log_tg_check(const char *table, const void *entry,
const struct xt_target *target, void *data,
unsigned int hook_mask)
{ {
struct ebt_log_info *info = data; struct ebt_log_info *info = par->targinfo;
if (info->bitmask & ~EBT_LOG_MASK) if (info->bitmask & ~EBT_LOG_MASK)
return false; return false;
......
...@@ -36,18 +36,14 @@ ebt_mark_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -36,18 +36,14 @@ ebt_mark_tg(struct sk_buff *skb, const struct xt_target_param *par)
return info->target | ~EBT_VERDICT_BITS; return info->target | ~EBT_VERDICT_BITS;
} }
static bool static bool ebt_mark_tg_check(const struct xt_tgchk_param *par)
ebt_mark_tg_check(const char *table, const void *e,
const struct xt_target *target, void *data,
unsigned int hookmask)
{ {
const struct ebt_mark_t_info *info = data; const struct ebt_mark_t_info *info = par->targinfo;
int tmp; int tmp;
tmp = info->target | ~EBT_VERDICT_BITS; tmp = info->target | ~EBT_VERDICT_BITS;
if (BASE_CHAIN && tmp == EBT_RETURN) if (BASE_CHAIN && tmp == EBT_RETURN)
return false; return false;
CLEAR_BASE_CHAIN_BIT;
if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
return false; return false;
tmp = info->target & ~EBT_VERDICT_BITS; tmp = info->target & ~EBT_VERDICT_BITS;
......
...@@ -35,12 +35,9 @@ ebt_nflog_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -35,12 +35,9 @@ ebt_nflog_tg(struct sk_buff *skb, const struct xt_target_param *par)
return EBT_CONTINUE; return EBT_CONTINUE;
} }
static bool static bool ebt_nflog_tg_check(const struct xt_tgchk_param *par)
ebt_nflog_tg_check(const char *table, const void *e,
const struct xt_target *target, void *data,
unsigned int hookmask)
{ {
struct ebt_nflog_info *info = data; struct ebt_nflog_info *info = par->targinfo;
if (info->flags & ~EBT_NFLOG_MASK) if (info->flags & ~EBT_NFLOG_MASK)
return false; return false;
......
...@@ -32,18 +32,19 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -32,18 +32,19 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_target_param *par)
return info->target; return info->target;
} }
static bool static bool ebt_redirect_tg_check(const struct xt_tgchk_param *par)
ebt_redirect_tg_check(const char *tablename, const void *e,
const struct xt_target *target, void *data,
unsigned int hookmask)
{ {
const struct ebt_redirect_info *info = data; const struct ebt_redirect_info *info = par->targinfo;
unsigned int hook_mask;
if (BASE_CHAIN && info->target == EBT_RETURN) if (BASE_CHAIN && info->target == EBT_RETURN)
return false; return false;
CLEAR_BASE_CHAIN_BIT;
if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) && hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
(strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) if ((strcmp(par->table, "nat") != 0 ||
hook_mask & ~(1 << NF_BR_PRE_ROUTING)) &&
(strcmp(par->table, "broute") != 0 ||
hook_mask & ~(1 << NF_BR_BROUTING)))
return false; return false;
if (INVALID_TARGET) if (INVALID_TARGET)
return false; return false;
......
...@@ -42,18 +42,14 @@ out: ...@@ -42,18 +42,14 @@ out:
return info->target | ~EBT_VERDICT_BITS; return info->target | ~EBT_VERDICT_BITS;
} }
static bool static bool ebt_snat_tg_check(const struct xt_tgchk_param *par)
ebt_snat_tg_check(const char *tablename, const void *e,
const struct xt_target *target, void *data,
unsigned int hookmask)
{ {
const struct ebt_nat_info *info = data; const struct ebt_nat_info *info = par->targinfo;
int tmp; int tmp;
tmp = info->target | ~EBT_VERDICT_BITS; tmp = info->target | ~EBT_VERDICT_BITS;
if (BASE_CHAIN && tmp == EBT_RETURN) if (BASE_CHAIN && tmp == EBT_RETURN)
return false; return false;
CLEAR_BASE_CHAIN_BIT;
if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
return false; return false;
......
...@@ -254,12 +254,9 @@ ebt_ulog_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -254,12 +254,9 @@ ebt_ulog_tg(struct sk_buff *skb, const struct xt_target_param *par)
return EBT_CONTINUE; return EBT_CONTINUE;
} }
static bool static bool ebt_ulog_tg_check(const struct xt_tgchk_param *par)
ebt_ulog_tg_check(const char *table, const void *entry,
const struct xt_target *target, void *data,
unsigned int hookmask)
{ {
struct ebt_ulog_info *uloginfo = data; struct ebt_ulog_info *uloginfo = par->targinfo;
if (uloginfo->nlgroup > 31) if (uloginfo->nlgroup > 31)
return false; return false;
......
...@@ -363,9 +363,10 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par, ...@@ -363,9 +363,10 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par,
} }
static inline int static inline int
ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
const char *name, unsigned int hookmask, unsigned int *cnt) unsigned int *cnt)
{ {
const struct ebt_entry *e = par->entryinfo;
struct xt_target *watcher; struct xt_target *watcher;
size_t left = ((char *)e + e->target_offset) - (char *)w; size_t left = ((char *)e + e->target_offset) - (char *)w;
int ret; int ret;
...@@ -383,9 +384,10 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, ...@@ -383,9 +384,10 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
return -ENOENT; return -ENOENT;
w->u.watcher = watcher; w->u.watcher = watcher;
ret = xt_check_target(watcher, NFPROTO_BRIDGE, w->watcher_size, par->target = watcher;
name, hookmask, e->ethproto, e->invflags & EBT_IPROTO, par->targinfo = w->data;
e, w->data); ret = xt_check_target(par, NFPROTO_BRIDGE, w->watcher_size,
e->ethproto, e->invflags & EBT_IPROTO);
if (ret < 0) { if (ret < 0) {
module_put(watcher->me); module_put(watcher->me);
return ret; return ret;
...@@ -619,6 +621,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -619,6 +621,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
size_t gap; size_t gap;
int ret; int ret;
struct xt_mtchk_param mtpar; struct xt_mtchk_param mtpar;
struct xt_tgchk_param tgpar;
/* don't mess with the struct ebt_entries */ /* don't mess with the struct ebt_entries */
if (e->bitmask == 0) if (e->bitmask == 0)
...@@ -660,14 +663,14 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -660,14 +663,14 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
} }
i = 0; i = 0;
mtpar.table = name; mtpar.table = tgpar.table = name;
mtpar.entryinfo = e; mtpar.entryinfo = tgpar.entryinfo = e;
mtpar.hook_mask = hookmask; mtpar.hook_mask = tgpar.hook_mask = hookmask;
ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i); ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i);
if (ret != 0) if (ret != 0)
goto cleanup_matches; goto cleanup_matches;
j = 0; j = 0;
ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j); ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, &tgpar, &j);
if (ret != 0) if (ret != 0)
goto cleanup_watchers; goto cleanup_watchers;
t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); 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,9 +706,10 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
goto cleanup_watchers; goto cleanup_watchers;
} }
ret = xt_check_target(target, NFPROTO_BRIDGE, t->target_size, tgpar.target = target;
name, hookmask, e->ethproto, e->invflags & EBT_IPROTO, tgpar.targinfo = t->data;
e, t->data); ret = xt_check_target(&tgpar, NFPROTO_BRIDGE, t->target_size,
e->ethproto, e->invflags & EBT_IPROTO);
if (ret < 0) { if (ret < 0) {
module_put(target->me); module_put(target->me);
goto cleanup_watchers; goto cleanup_watchers;
......
...@@ -457,16 +457,18 @@ static inline int check_entry(struct arpt_entry *e, const char *name) ...@@ -457,16 +457,18 @@ static inline int check_entry(struct arpt_entry *e, const char *name)
static inline int check_target(struct arpt_entry *e, const char *name) static inline int check_target(struct arpt_entry *e, const char *name)
{ {
struct arpt_entry_target *t; struct arpt_entry_target *t = arpt_get_target(e);
struct xt_target *target;
int ret; int ret;
struct xt_tgchk_param par = {
t = arpt_get_target(e); .table = name,
target = t->u.kernel.target; .entryinfo = e,
.target = t->u.kernel.target,
ret = xt_check_target(target, NFPROTO_ARP, .targinfo = t->data,
t->u.target_size - sizeof(*t), .hook_mask = e->comefrom,
name, e->comefrom, 0, 0, e, t->data); };
ret = xt_check_target(&par, NFPROTO_ARP,
t->u.target_size - sizeof(*t), 0, false);
if (ret < 0) { if (ret < 0) {
duprintf("arp_tables: check failed for `%s'.\n", duprintf("arp_tables: check failed for `%s'.\n",
t->u.kernel.target->name); t->u.kernel.target->name);
......
...@@ -54,11 +54,9 @@ target(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -54,11 +54,9 @@ target(struct sk_buff *skb, const struct xt_target_param *par)
return mangle->target; return mangle->target;
} }
static bool static bool checkentry(const struct xt_tgchk_param *par)
checkentry(const char *tablename, const void *e, const struct xt_target *target,
void *targinfo, unsigned int hook_mask)
{ {
const struct arpt_mangle *mangle = targinfo; const struct arpt_mangle *mangle = par->targinfo;
if (mangle->flags & ~ARPT_MANGLE_MASK || if (mangle->flags & ~ARPT_MANGLE_MASK ||
!(mangle->flags & ARPT_MANGLE_MASK)) !(mangle->flags & ARPT_MANGLE_MASK))
......
...@@ -655,15 +655,18 @@ err: ...@@ -655,15 +655,18 @@ err:
static int check_target(struct ipt_entry *e, const char *name) static int check_target(struct ipt_entry *e, const char *name)
{ {
struct ipt_entry_target *t; struct ipt_entry_target *t = ipt_get_target(e);
struct xt_target *target; struct xt_tgchk_param par = {
.table = name,
.entryinfo = e,
.target = t->u.kernel.target,
.targinfo = t->data,
.hook_mask = e->comefrom,
};
int ret; int ret;
t = ipt_get_target(e); ret = xt_check_target(&par, NFPROTO_IPV4, t->u.target_size - sizeof(*t),
target = t->u.kernel.target; e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
name, e->comefrom, e->ip.proto,
e->ip.invflags & IPT_INV_PROTO, e, t->data);
if (ret < 0) { if (ret < 0) {
duprintf("ip_tables: check failed for `%s'.\n", duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name); t->u.kernel.target->name);
......
...@@ -347,13 +347,10 @@ clusterip_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -347,13 +347,10 @@ clusterip_tg(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool clusterip_tg_check(const struct xt_tgchk_param *par)
clusterip_tg_check(const char *tablename, const void *e_void,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
struct ipt_clusterip_tgt_info *cipinfo = targinfo; struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
const struct ipt_entry *e = e_void; const struct ipt_entry *e = par->entryinfo;
struct clusterip_config *config; struct clusterip_config *config;
...@@ -404,9 +401,9 @@ clusterip_tg_check(const char *tablename, const void *e_void, ...@@ -404,9 +401,9 @@ clusterip_tg_check(const char *tablename, const void *e_void,
} }
cipinfo->config = config; cipinfo->config = config;
if (nf_ct_l3proto_try_module_get(target->family) < 0) { if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for " printk(KERN_WARNING "can't load conntrack support for "
"proto=%u\n", target->family); "proto=%u\n", par->target->family);
return false; return false;
} }
......
...@@ -93,13 +93,10 @@ ecn_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -93,13 +93,10 @@ ecn_tg(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool ecn_tg_check(const struct xt_tgchk_param *par)
ecn_tg_check(const char *tablename, const void *e_void,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct ipt_ECN_info *einfo = targinfo; const struct ipt_ECN_info *einfo = par->targinfo;
const struct ipt_entry *e = e_void; const struct ipt_entry *e = par->entryinfo;
if (einfo->operation & IPT_ECN_OP_MASK) { if (einfo->operation & IPT_ECN_OP_MASK) {
printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
......
...@@ -440,12 +440,9 @@ log_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -440,12 +440,9 @@ log_tg(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool log_tg_check(const struct xt_tgchk_param *par)
log_tg_check(const char *tablename, const void *e,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct ipt_log_info *loginfo = targinfo; const struct ipt_log_info *loginfo = par->targinfo;
if (loginfo->level >= 8) { if (loginfo->level >= 8) {
pr_debug("LOG: level %u >= 8\n", loginfo->level); pr_debug("LOG: level %u >= 8\n", loginfo->level);
......
...@@ -31,12 +31,9 @@ MODULE_DESCRIPTION("Xtables: automatic-address SNAT"); ...@@ -31,12 +31,9 @@ MODULE_DESCRIPTION("Xtables: automatic-address SNAT");
static DEFINE_RWLOCK(masq_lock); static DEFINE_RWLOCK(masq_lock);
/* FIXME: Multiple targets. --RR */ /* FIXME: Multiple targets. --RR */
static bool static bool masquerade_tg_check(const struct xt_tgchk_param *par)
masquerade_tg_check(const char *tablename, const void *e,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct nf_nat_multi_range_compat *mr = targinfo; const struct nf_nat_multi_range_compat *mr = par->targinfo;
if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
pr_debug("masquerade_check: bad MAP_IPS.\n"); pr_debug("masquerade_check: bad MAP_IPS.\n");
......
...@@ -22,12 +22,9 @@ MODULE_LICENSE("GPL"); ...@@ -22,12 +22,9 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets"); MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets");
static bool static bool netmap_tg_check(const struct xt_tgchk_param *par)
netmap_tg_check(const char *tablename, const void *e,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct nf_nat_multi_range_compat *mr = targinfo; const struct nf_nat_multi_range_compat *mr = par->targinfo;
if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
pr_debug("NETMAP:check: bad MAP_IPS.\n"); pr_debug("NETMAP:check: bad MAP_IPS.\n");
......
...@@ -26,12 +26,9 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); ...@@ -26,12 +26,9 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
/* FIXME: Take multiple ranges --RR */ /* FIXME: Take multiple ranges --RR */
static bool static bool redirect_tg_check(const struct xt_tgchk_param *par)
redirect_tg_check(const char *tablename, const void *e,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct nf_nat_multi_range_compat *mr = targinfo; const struct nf_nat_multi_range_compat *mr = par->targinfo;
if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
pr_debug("redirect_check: bad MAP_IPS.\n"); pr_debug("redirect_check: bad MAP_IPS.\n");
......
...@@ -175,13 +175,10 @@ reject_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -175,13 +175,10 @@ reject_tg(struct sk_buff *skb, const struct xt_target_param *par)
return NF_DROP; return NF_DROP;
} }
static bool static bool reject_tg_check(const struct xt_tgchk_param *par)
reject_tg_check(const char *tablename, const void *e_void,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct ipt_reject_info *rejinfo = targinfo; const struct ipt_reject_info *rejinfo = par->targinfo;
const struct ipt_entry *e = e_void; const struct ipt_entry *e = par->entryinfo;
if (rejinfo->with == IPT_ICMP_ECHOREPLY) { if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
printk("ipt_REJECT: ECHOREPLY no longer supported.\n"); printk("ipt_REJECT: ECHOREPLY no longer supported.\n");
......
...@@ -59,12 +59,9 @@ ttl_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -59,12 +59,9 @@ ttl_tg(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool ttl_tg_check(const struct xt_tgchk_param *par)
ttl_tg_check(const char *tablename, const void *e,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct ipt_TTL_info *info = targinfo; const struct ipt_TTL_info *info = par->targinfo;
if (info->mode > IPT_TTL_MAXMODE) { if (info->mode > IPT_TTL_MAXMODE) {
printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
......
...@@ -313,12 +313,9 @@ static void ipt_logfn(u_int8_t pf, ...@@ -313,12 +313,9 @@ static void ipt_logfn(u_int8_t pf,
ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
} }
static bool static bool ulog_tg_check(const struct xt_tgchk_param *par)
ulog_tg_check(const char *tablename, const void *e,
const struct xt_target *target, void *targinfo,
unsigned int hookmask)
{ {
const struct ipt_ulog_info *loginfo = targinfo; const struct ipt_ulog_info *loginfo = par->targinfo;
if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
pr_debug("ipt_ULOG: prefix term %i\n", pr_debug("ipt_ULOG: prefix term %i\n",
......
...@@ -128,13 +128,9 @@ ipt_dnat_target(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -128,13 +128,9 @@ ipt_dnat_target(struct sk_buff *skb, const struct xt_target_param *par)
return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST);
} }
static bool ipt_snat_checkentry(const char *tablename, static bool ipt_snat_checkentry(const struct xt_tgchk_param *par)
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int hook_mask)
{ {
const struct nf_nat_multi_range_compat *mr = targinfo; const struct nf_nat_multi_range_compat *mr = par->targinfo;
/* Must be a valid range */ /* Must be a valid range */
if (mr->rangesize != 1) { if (mr->rangesize != 1) {
...@@ -144,13 +140,9 @@ static bool ipt_snat_checkentry(const char *tablename, ...@@ -144,13 +140,9 @@ static bool ipt_snat_checkentry(const char *tablename,
return true; return true;
} }
static bool ipt_dnat_checkentry(const char *tablename, static bool ipt_dnat_checkentry(const struct xt_tgchk_param *par)
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int hook_mask)
{ {
const struct nf_nat_multi_range_compat *mr = targinfo; const struct nf_nat_multi_range_compat *mr = par->targinfo;
/* Must be a valid range */ /* Must be a valid range */
if (mr->rangesize != 1) { if (mr->rangesize != 1) {
......
...@@ -679,15 +679,19 @@ err: ...@@ -679,15 +679,19 @@ err:
static int check_target(struct ip6t_entry *e, const char *name) static int check_target(struct ip6t_entry *e, const char *name)
{ {
struct ip6t_entry_target *t; struct ip6t_entry_target *t = ip6t_get_target(e);
struct xt_target *target; struct xt_tgchk_param par = {
.table = name,
.entryinfo = e,
.target = t->u.kernel.target,
.targinfo = t->data,
.hook_mask = e->comefrom,
};
int ret; int ret;
t = ip6t_get_target(e); t = ip6t_get_target(e);
target = t->u.kernel.target; ret = xt_check_target(&par, NFPROTO_IPV6, t->u.target_size - sizeof(*t),
ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t), e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO);
name, e->comefrom, e->ipv6.proto,
e->ipv6.invflags & IP6T_INV_PROTO, e, t->data);
if (ret < 0) { if (ret < 0) {
duprintf("ip_tables: check failed for `%s'.\n", duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name); t->u.kernel.target->name);
......
...@@ -54,12 +54,9 @@ hl_tg6(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -54,12 +54,9 @@ hl_tg6(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool hl_tg6_check(const struct xt_tgchk_param *par)
hl_tg6_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct ip6t_HL_info *info = targinfo; const struct ip6t_HL_info *info = par->targinfo;
if (info->mode > IP6T_HL_MAXMODE) { if (info->mode > IP6T_HL_MAXMODE) {
printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
......
...@@ -453,12 +453,9 @@ log_tg6(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -453,12 +453,9 @@ log_tg6(struct sk_buff *skb, const struct xt_target_param *par)
} }
static bool static bool log_tg6_check(const struct xt_tgchk_param *par)
log_tg6_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct ip6t_log_info *loginfo = targinfo; const struct ip6t_log_info *loginfo = par->targinfo;
if (loginfo->level >= 8) { if (loginfo->level >= 8) {
pr_debug("LOG: level %u >= 8\n", loginfo->level); pr_debug("LOG: level %u >= 8\n", loginfo->level);
......
...@@ -213,13 +213,10 @@ reject_tg6(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -213,13 +213,10 @@ reject_tg6(struct sk_buff *skb, const struct xt_target_param *par)
return NF_DROP; return NF_DROP;
} }
static bool static bool reject_tg6_check(const struct xt_tgchk_param *par)
reject_tg6_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct ip6t_reject_info *rejinfo = targinfo; const struct ip6t_reject_info *rejinfo = par->targinfo;
const struct ip6t_entry *e = entry; const struct ip6t_entry *e = par->entryinfo;
if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
printk("ip6t_REJECT: ECHOREPLY is not supported.\n"); printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
......
...@@ -471,35 +471,35 @@ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr, ...@@ -471,35 +471,35 @@ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
EXPORT_SYMBOL_GPL(xt_compat_match_to_user); EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
int xt_check_target(const struct xt_target *target, unsigned short family, int xt_check_target(struct xt_tgchk_param *par, u_int8_t family,
unsigned int size, const char *table, unsigned int hook_mask, unsigned int size, u_int8_t proto, bool inv_proto)
unsigned short proto, int inv_proto, const void *entry,
void *targinfo)
{ {
if (XT_ALIGN(target->targetsize) != size) { if (XT_ALIGN(par->target->targetsize) != size) {
printk("%s_tables: %s target: invalid size %Zu != %u\n", printk("%s_tables: %s target: invalid size %Zu != %u\n",
xt_prefix[family], target->name, xt_prefix[family], par->target->name,
XT_ALIGN(target->targetsize), size); XT_ALIGN(par->target->targetsize), size);
return -EINVAL; return -EINVAL;
} }
if (target->table && strcmp(target->table, table)) { if (par->target->table != NULL &&
strcmp(par->target->table, par->table) != 0) {
printk("%s_tables: %s target: only valid in %s table, not %s\n", printk("%s_tables: %s target: only valid in %s table, not %s\n",
xt_prefix[family], target->name, target->table, table); xt_prefix[family], par->target->name,
par->target->table, par->table);
return -EINVAL; return -EINVAL;
} }
if (target->hooks && (hook_mask & ~target->hooks) != 0) { if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) {
printk("%s_tables: %s target: bad hook_mask %#x/%#x\n", printk("%s_tables: %s target: bad hook_mask %#x/%#x\n",
xt_prefix[family], target->name, hook_mask, xt_prefix[family], par->target->name, par->hook_mask,
target->hooks); par->target->hooks);
return -EINVAL; return -EINVAL;
} }
if (target->proto && (target->proto != proto || inv_proto)) { if (par->target->proto && (par->target->proto != proto || inv_proto)) {
printk("%s_tables: %s target: only valid for protocol %u\n", printk("%s_tables: %s target: only valid for protocol %u\n",
xt_prefix[family], target->name, target->proto); xt_prefix[family], par->target->name,
par->target->proto);
return -EINVAL; return -EINVAL;
} }
if (target->checkentry != NULL && if (par->target->checkentry != NULL && !par->target->checkentry(par))
!target->checkentry(table, entry, target, targinfo, hook_mask))
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
......
...@@ -112,18 +112,15 @@ connmark_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -112,18 +112,15 @@ connmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool connmark_tg_check_v0(const struct xt_tgchk_param *par)
connmark_tg_check_v0(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct xt_connmark_target_info *matchinfo = targinfo; const struct xt_connmark_target_info *matchinfo = par->targinfo;
if (matchinfo->mode == XT_CONNMARK_RESTORE) { if (matchinfo->mode == XT_CONNMARK_RESTORE) {
if (strcmp(tablename, "mangle") != 0) { if (strcmp(par->table, "mangle") != 0) {
printk(KERN_WARNING "CONNMARK: restore can only be " printk(KERN_WARNING "CONNMARK: restore can only be "
"called from \"mangle\" table, not \"%s\"\n", "called from \"mangle\" table, not \"%s\"\n",
tablename); par->table);
return false; return false;
} }
} }
...@@ -131,22 +128,19 @@ connmark_tg_check_v0(const char *tablename, const void *entry, ...@@ -131,22 +128,19 @@ connmark_tg_check_v0(const char *tablename, const void *entry,
printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
return false; return false;
} }
if (nf_ct_l3proto_try_module_get(target->family) < 0) { if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for " printk(KERN_WARNING "can't load conntrack support for "
"proto=%u\n", target->family); "proto=%u\n", par->target->family);
return false; return false;
} }
return true; return true;
} }
static bool static bool connmark_tg_check(const struct xt_tgchk_param *par)
connmark_tg_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
if (nf_ct_l3proto_try_module_get(target->family) < 0) { if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
printk(KERN_WARNING "cannot load conntrack support for " printk(KERN_WARNING "cannot load conntrack support for "
"proto=%u\n", target->family); "proto=%u\n", par->target->family);
return false; return false;
} }
return true; return true;
......
...@@ -85,16 +85,14 @@ connsecmark_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -85,16 +85,14 @@ connsecmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool connsecmark_tg_check(const struct xt_tgchk_param *par)
connsecmark_tg_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct xt_connsecmark_target_info *info = targinfo; const struct xt_connsecmark_target_info *info = par->targinfo;
if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) { if (strcmp(par->table, "mangle") != 0 &&
strcmp(par->table, "security") != 0) {
printk(KERN_INFO PFX "target only valid in the \'mangle\' " printk(KERN_INFO PFX "target only valid in the \'mangle\' "
"or \'security\' tables, not \'%s\'.\n", tablename); "or \'security\' tables, not \'%s\'.\n", par->table);
return false; return false;
} }
...@@ -108,9 +106,9 @@ connsecmark_tg_check(const char *tablename, const void *entry, ...@@ -108,9 +106,9 @@ connsecmark_tg_check(const char *tablename, const void *entry,
return false; return false;
} }
if (nf_ct_l3proto_try_module_get(target->family) < 0) { if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for " printk(KERN_WARNING "can't load conntrack support for "
"proto=%u\n", target->family); "proto=%u\n", par->target->family);
return false; return false;
} }
return true; return true;
......
...@@ -61,15 +61,12 @@ dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -61,15 +61,12 @@ dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool dscp_tg_check(const struct xt_tgchk_param *par)
dscp_tg_check(const char *tablename, const void *e_void,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp; const struct xt_DSCP_info *info = par->targinfo;
if (dscp > XT_DSCP_MAX) { if (info->dscp > XT_DSCP_MAX) {
printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); printk(KERN_WARNING "DSCP: dscp %x out of range\n", info->dscp);
return false; return false;
} }
return true; return true;
...@@ -95,12 +92,10 @@ tos_tg_v0(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -95,12 +92,10 @@ tos_tg_v0(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool tos_tg_check_v0(const struct xt_tgchk_param *par)
tos_tg_check_v0(const char *tablename, const void *e_void,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos; const struct ipt_tos_target_info *info = par->targinfo;
const uint8_t tos = info->tos;
if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT && if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT &&
tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST && tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST &&
......
...@@ -66,12 +66,9 @@ mark_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -66,12 +66,9 @@ mark_tg(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool mark_tg_check_v0(const struct xt_tgchk_param *par)
mark_tg_check_v0(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct xt_mark_target_info *markinfo = targinfo; const struct xt_mark_target_info *markinfo = par->targinfo;
if (markinfo->mark > 0xffffffff) { if (markinfo->mark > 0xffffffff) {
printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); 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,12 +77,9 @@ mark_tg_check_v0(const char *tablename, const void *entry,
return true; return true;
} }
static bool static bool mark_tg_check_v1(const struct xt_tgchk_param *par)
mark_tg_check_v1(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct xt_mark_target_info_v1 *markinfo = targinfo; const struct xt_mark_target_info_v1 *markinfo = par->targinfo;
if (markinfo->mode != XT_MARK_SET if (markinfo->mode != XT_MARK_SET
&& markinfo->mode != XT_MARK_AND && markinfo->mode != XT_MARK_AND
......
...@@ -36,12 +36,9 @@ nflog_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -36,12 +36,9 @@ nflog_tg(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool nflog_tg_check(const struct xt_tgchk_param *par)
nflog_tg_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targetinfo,
unsigned int hookmask)
{ {
const struct xt_nflog_info *info = targetinfo; const struct xt_nflog_info *info = par->targinfo;
if (info->flags & ~XT_NFLOG_MASK) if (info->flags & ~XT_NFLOG_MASK)
return false; return false;
......
...@@ -84,14 +84,9 @@ xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -84,14 +84,9 @@ xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static bool static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
xt_rateest_tg_checkentry(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int hook_mask)
{ {
struct xt_rateest_target_info *info = targinfo; struct xt_rateest_target_info *info = par->targinfo;
struct xt_rateest *est; struct xt_rateest *est;
struct { struct {
struct nlattr opt; struct nlattr opt;
......
...@@ -80,16 +80,14 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info) ...@@ -80,16 +80,14 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
return true; return true;
} }
static bool static bool secmark_tg_check(const struct xt_tgchk_param *par)
secmark_tg_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
struct xt_secmark_target_info *info = targinfo; struct xt_secmark_target_info *info = par->targinfo;
if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) { if (strcmp(par->table, "mangle") != 0 &&
strcmp(par->table, "security") != 0) {
printk(KERN_INFO PFX "target only valid in the \'mangle\' " printk(KERN_INFO PFX "target only valid in the \'mangle\' "
"or \'security\' tables, not \'%s\'.\n", tablename); "or \'security\' tables, not \'%s\'.\n", par->table);
return false; return false;
} }
......
...@@ -237,16 +237,13 @@ static inline bool find_syn_match(const struct xt_entry_match *m) ...@@ -237,16 +237,13 @@ static inline bool find_syn_match(const struct xt_entry_match *m)
return false; return false;
} }
static bool static bool tcpmss_tg4_check(const struct xt_tgchk_param *par)
tcpmss_tg4_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct xt_tcpmss_info *info = targinfo; const struct xt_tcpmss_info *info = par->targinfo;
const struct ipt_entry *e = entry; const struct ipt_entry *e = par->entryinfo;
if (info->mss == XT_TCPMSS_CLAMP_PMTU && if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
(hook_mask & ~((1 << NF_INET_FORWARD) | (par->hook_mask & ~((1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING))) != 0) { (1 << NF_INET_POST_ROUTING))) != 0) {
printk("xt_TCPMSS: path-MTU clamping only supported in " printk("xt_TCPMSS: path-MTU clamping only supported in "
...@@ -260,16 +257,13 @@ tcpmss_tg4_check(const char *tablename, const void *entry, ...@@ -260,16 +257,13 @@ tcpmss_tg4_check(const char *tablename, const void *entry,
} }
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
static bool static bool tcpmss_tg6_check(const struct xt_tgchk_param *par)
tcpmss_tg6_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
unsigned int hook_mask)
{ {
const struct xt_tcpmss_info *info = targinfo; const struct xt_tcpmss_info *info = par->targinfo;
const struct ip6t_entry *e = entry; const struct ip6t_entry *e = par->entryinfo;
if (info->mss == XT_TCPMSS_CLAMP_PMTU && if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
(hook_mask & ~((1 << NF_INET_FORWARD) | (par->hook_mask & ~((1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING))) != 0) { (1 << NF_INET_POST_ROUTING))) != 0) {
printk("xt_TCPMSS: path-MTU clamping only supported in " printk("xt_TCPMSS: path-MTU clamping only supported in "
......
...@@ -59,14 +59,9 @@ tproxy_tg(struct sk_buff *skb, const struct xt_target_param *par) ...@@ -59,14 +59,9 @@ tproxy_tg(struct sk_buff *skb, const struct xt_target_param *par)
return NF_DROP; return NF_DROP;
} }
static bool static bool tproxy_tg_check(const struct xt_tgchk_param *par)
tproxy_tg_check(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targetinfo,
unsigned int hook_mask)
{ {
const struct ipt_ip *i = entry; const struct ipt_ip *i = par->entryinfo;
if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
&& !(i->invflags & IPT_INV_PROTO)) && !(i->invflags & IPT_INV_PROTO))
......
...@@ -40,6 +40,7 @@ static struct tcf_hashinfo ipt_hash_info = { ...@@ -40,6 +40,7 @@ static struct tcf_hashinfo ipt_hash_info = {
static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
{ {
struct xt_tgchk_param par;
struct xt_target *target; struct xt_target *target;
int ret = 0; int ret = 0;
...@@ -49,9 +50,14 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int ...@@ -49,9 +50,14 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int
return -ENOENT; return -ENOENT;
t->u.kernel.target = target; t->u.kernel.target = target;
par.table = table;
ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), par.entryinfo = NULL;
table, hook, 0, 0, NULL, t->data); par.target = target;
par.targinfo = t->data;
par.hook_mask = hook;
ret = xt_check_target(&par, NFPROTO_IPV4,
t->u.target_size - sizeof(*t), 0, false);
if (ret < 0) { if (ret < 0) {
module_put(t->u.kernel.target->me); module_put(t->u.kernel.target->me);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment