netfilter: xtables: conntrack match revision 2
As reported by Philip, the UNTRACKED state bit does not fit within the 8-bit state_mask member. Enlarge state_mask and give status_mask a few more bits too. Reported-by: Philip Craig <philipc@snapgear.com> References: http://markmail.org/thread/b7eg6aovfh4agyz7 Signed-off-by: Jan Engelhardt <jengelh@medozas.de> Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
parent
8a3af79361
commit
d6d3f08b0f
|
@ -81,4 +81,17 @@ struct xt_conntrack_mtinfo1 {
|
||||||
__u8 state_mask, status_mask;
|
__u8 state_mask, status_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xt_conntrack_mtinfo2 {
|
||||||
|
union nf_inet_addr origsrc_addr, origsrc_mask;
|
||||||
|
union nf_inet_addr origdst_addr, origdst_mask;
|
||||||
|
union nf_inet_addr replsrc_addr, replsrc_mask;
|
||||||
|
union nf_inet_addr repldst_addr, repldst_mask;
|
||||||
|
__u32 expires_min, expires_max;
|
||||||
|
__u16 l4proto;
|
||||||
|
__be16 origsrc_port, origdst_port;
|
||||||
|
__be16 replsrc_port, repldst_port;
|
||||||
|
__u16 match_flags, invert_flags;
|
||||||
|
__u16 state_mask, status_mask;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /*_XT_CONNTRACK_H*/
|
#endif /*_XT_CONNTRACK_H*/
|
||||||
|
|
|
@ -129,7 +129,7 @@ conntrack_addrcmp(const union nf_inet_addr *kaddr,
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
conntrack_mt_origsrc(const struct nf_conn *ct,
|
conntrack_mt_origsrc(const struct nf_conn *ct,
|
||||||
const struct xt_conntrack_mtinfo1 *info,
|
const struct xt_conntrack_mtinfo2 *info,
|
||||||
u_int8_t family)
|
u_int8_t family)
|
||||||
{
|
{
|
||||||
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
|
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
|
||||||
|
@ -138,7 +138,7 @@ conntrack_mt_origsrc(const struct nf_conn *ct,
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
conntrack_mt_origdst(const struct nf_conn *ct,
|
conntrack_mt_origdst(const struct nf_conn *ct,
|
||||||
const struct xt_conntrack_mtinfo1 *info,
|
const struct xt_conntrack_mtinfo2 *info,
|
||||||
u_int8_t family)
|
u_int8_t family)
|
||||||
{
|
{
|
||||||
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3,
|
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3,
|
||||||
|
@ -147,7 +147,7 @@ conntrack_mt_origdst(const struct nf_conn *ct,
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
conntrack_mt_replsrc(const struct nf_conn *ct,
|
conntrack_mt_replsrc(const struct nf_conn *ct,
|
||||||
const struct xt_conntrack_mtinfo1 *info,
|
const struct xt_conntrack_mtinfo2 *info,
|
||||||
u_int8_t family)
|
u_int8_t family)
|
||||||
{
|
{
|
||||||
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3,
|
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3,
|
||||||
|
@ -156,7 +156,7 @@ conntrack_mt_replsrc(const struct nf_conn *ct,
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
conntrack_mt_repldst(const struct nf_conn *ct,
|
conntrack_mt_repldst(const struct nf_conn *ct,
|
||||||
const struct xt_conntrack_mtinfo1 *info,
|
const struct xt_conntrack_mtinfo2 *info,
|
||||||
u_int8_t family)
|
u_int8_t family)
|
||||||
{
|
{
|
||||||
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3,
|
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3,
|
||||||
|
@ -164,7 +164,7 @@ conntrack_mt_repldst(const struct nf_conn *ct,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
|
ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info,
|
||||||
const struct nf_conn *ct)
|
const struct nf_conn *ct)
|
||||||
{
|
{
|
||||||
const struct nf_conntrack_tuple *tuple;
|
const struct nf_conntrack_tuple *tuple;
|
||||||
|
@ -204,7 +204,7 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
|
||||||
static bool
|
static bool
|
||||||
conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||||
{
|
{
|
||||||
const struct xt_conntrack_mtinfo1 *info = par->matchinfo;
|
const struct xt_conntrack_mtinfo2 *info = par->matchinfo;
|
||||||
enum ip_conntrack_info ctinfo;
|
enum ip_conntrack_info ctinfo;
|
||||||
const struct nf_conn *ct;
|
const struct nf_conn *ct;
|
||||||
unsigned int statebit;
|
unsigned int statebit;
|
||||||
|
@ -278,6 +278,16 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||||
|
{
|
||||||
|
const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo;
|
||||||
|
struct xt_match_param newpar = *par;
|
||||||
|
|
||||||
|
newpar.matchinfo = *info;
|
||||||
|
return conntrack_mt(skb, &newpar);
|
||||||
|
}
|
||||||
|
|
||||||
static bool conntrack_mt_check(const struct xt_mtchk_param *par)
|
static bool conntrack_mt_check(const struct xt_mtchk_param *par)
|
||||||
{
|
{
|
||||||
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
if (nf_ct_l3proto_try_module_get(par->family) < 0) {
|
||||||
|
@ -288,11 +298,45 @@ static bool conntrack_mt_check(const struct xt_mtchk_param *par)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par)
|
||||||
|
{
|
||||||
|
struct xt_conntrack_mtinfo1 *info = par->matchinfo;
|
||||||
|
struct xt_conntrack_mtinfo2 *up;
|
||||||
|
int ret = conntrack_mt_check(par);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
up = kmalloc(sizeof(*up), GFP_KERNEL);
|
||||||
|
if (up == NULL) {
|
||||||
|
nf_ct_l3proto_module_put(par->family);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The strategy here is to minimize the overhead of v1 matching,
|
||||||
|
* by prebuilding a v2 struct and putting the pointer into the
|
||||||
|
* v1 dataspace.
|
||||||
|
*/
|
||||||
|
memcpy(up, info, offsetof(typeof(*info), state_mask));
|
||||||
|
up->state_mask = info->state_mask;
|
||||||
|
up->status_mask = info->status_mask;
|
||||||
|
*(void **)info = up;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)
|
static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)
|
||||||
{
|
{
|
||||||
nf_ct_l3proto_module_put(par->family);
|
nf_ct_l3proto_module_put(par->family);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par)
|
||||||
|
{
|
||||||
|
struct xt_conntrack_mtinfo2 **info = par->matchinfo;
|
||||||
|
kfree(*info);
|
||||||
|
conntrack_mt_destroy(par);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
struct compat_xt_conntrack_info
|
struct compat_xt_conntrack_info
|
||||||
{
|
{
|
||||||
|
@ -363,6 +407,16 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = {
|
||||||
.revision = 1,
|
.revision = 1,
|
||||||
.family = NFPROTO_UNSPEC,
|
.family = NFPROTO_UNSPEC,
|
||||||
.matchsize = sizeof(struct xt_conntrack_mtinfo1),
|
.matchsize = sizeof(struct xt_conntrack_mtinfo1),
|
||||||
|
.match = conntrack_mt_v1,
|
||||||
|
.checkentry = conntrack_mt_check_v1,
|
||||||
|
.destroy = conntrack_mt_destroy_v1,
|
||||||
|
.me = THIS_MODULE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "conntrack",
|
||||||
|
.revision = 2,
|
||||||
|
.family = NFPROTO_UNSPEC,
|
||||||
|
.matchsize = sizeof(struct xt_conntrack_mtinfo2),
|
||||||
.match = conntrack_mt,
|
.match = conntrack_mt,
|
||||||
.checkentry = conntrack_mt_check,
|
.checkentry = conntrack_mt_check,
|
||||||
.destroy = conntrack_mt_destroy,
|
.destroy = conntrack_mt_destroy,
|
||||||
|
|
Loading…
Reference in New Issue