netfilter: ctnetlink: add NAT support for expectations

This patch adds the missing bits to create expectations that
are created in NAT setups.
This commit is contained in:
Pablo Neira Ayuso 2012-02-05 03:41:52 +01:00
Родитель b8c5e52c13
Коммит 076a0ca026
2 изменённых файлов: 75 добавлений и 2 удалений

Просмотреть файл

@ -174,10 +174,19 @@ enum ctattr_expect {
CTA_EXPECT_ZONE, CTA_EXPECT_ZONE,
CTA_EXPECT_FLAGS, CTA_EXPECT_FLAGS,
CTA_EXPECT_CLASS, CTA_EXPECT_CLASS,
CTA_EXPECT_NAT,
__CTA_EXPECT_MAX __CTA_EXPECT_MAX
}; };
#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
enum ctattr_expect_nat {
CTA_EXPECT_NAT_UNSPEC,
CTA_EXPECT_NAT_DIR,
CTA_EXPECT_NAT_TUPLE,
__CTA_EXPECT_NAT_MAX
};
#define CTA_EXPECT_NAT_MAX (__CTA_EXPECT_NAT_MAX - 1)
enum ctattr_help { enum ctattr_help {
CTA_HELP_UNSPEC, CTA_HELP_UNSPEC,
CTA_HELP_NAME, CTA_HELP_NAME,

Просмотреть файл

@ -1675,7 +1675,10 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
struct nf_conn *master = exp->master; struct nf_conn *master = exp->master;
long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ; long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ;
struct nf_conn_help *help; struct nf_conn_help *help;
#ifdef CONFIG_NF_NAT_NEEDED
struct nlattr *nest_parms;
struct nf_conntrack_tuple nat_tuple = {};
#endif
if (timeout < 0) if (timeout < 0)
timeout = 0; timeout = 0;
@ -1688,6 +1691,25 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
CTA_EXPECT_MASTER) < 0) CTA_EXPECT_MASTER) < 0)
goto nla_put_failure; goto nla_put_failure;
#ifdef CONFIG_NF_NAT_NEEDED
if (exp->saved_ip || exp->saved_proto.all) {
nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT | NLA_F_NESTED);
if (!nest_parms)
goto nla_put_failure;
NLA_PUT_BE32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir));
nat_tuple.src.l3num = nf_ct_l3num(master);
nat_tuple.src.u3.ip = exp->saved_ip;
nat_tuple.dst.protonum = nf_ct_protonum(master);
nat_tuple.src.u = exp->saved_proto;
if (ctnetlink_exp_dump_tuple(skb, &nat_tuple,
CTA_EXPECT_NAT_TUPLE) < 0)
goto nla_put_failure;
nla_nest_end(skb, nest_parms);
}
#endif
NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)); NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout));
NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)); NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp));
NLA_PUT_BE32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)); NLA_PUT_BE32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags));
@ -1858,6 +1880,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
[CTA_EXPECT_ZONE] = { .type = NLA_U16 }, [CTA_EXPECT_ZONE] = { .type = NLA_U16 },
[CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, [CTA_EXPECT_FLAGS] = { .type = NLA_U32 },
[CTA_EXPECT_CLASS] = { .type = NLA_U32 }, [CTA_EXPECT_CLASS] = { .type = NLA_U32 },
[CTA_EXPECT_NAT] = { .type = NLA_NESTED },
}; };
static int static int
@ -2033,6 +2056,41 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = {
[CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 },
[CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED },
};
static int
ctnetlink_parse_expect_nat(const struct nlattr *attr,
struct nf_conntrack_expect *exp,
u_int8_t u3)
{
#ifdef CONFIG_NF_NAT_NEEDED
struct nlattr *tb[CTA_EXPECT_NAT_MAX+1];
struct nf_conntrack_tuple nat_tuple = {};
int err;
nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy);
if (!tb[CTA_EXPECT_NAT_DIR] || !tb[CTA_EXPECT_NAT_TUPLE])
return -EINVAL;
err = ctnetlink_parse_tuple((const struct nlattr * const *)tb,
&nat_tuple, CTA_EXPECT_NAT_TUPLE, u3);
if (err < 0)
return err;
exp->saved_ip = nat_tuple.src.u3.ip;
exp->saved_proto = nat_tuple.src.u;
exp->dir = ntohl(nla_get_be32(tb[CTA_EXPECT_NAT_DIR]));
return 0;
#else
return -EOPNOTSUPP;
#endif
}
static int static int
ctnetlink_create_expect(struct net *net, u16 zone, ctnetlink_create_expect(struct net *net, u16 zone,
const struct nlattr * const cda[], const struct nlattr * const cda[],
@ -2133,9 +2191,15 @@ ctnetlink_create_expect(struct net *net, u16 zone,
memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3)); memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3));
exp->mask.src.u.all = mask.src.u.all; exp->mask.src.u.all = mask.src.u.all;
if (cda[CTA_EXPECT_NAT]) {
err = ctnetlink_parse_expect_nat(cda[CTA_EXPECT_NAT],
exp, u3);
if (err < 0)
goto err_out;
}
err = nf_ct_expect_related_report(exp, pid, report); err = nf_ct_expect_related_report(exp, pid, report);
err_out:
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
out: out:
nf_ct_put(nf_ct_tuplehash_to_ctrack(h)); nf_ct_put(nf_ct_tuplehash_to_ctrack(h));
return err; return err;