Commit d0dba725 authored by Holger Eitzenberger's avatar Holger Eitzenberger Committed by Patrick McHardy

netfilter: ctnetlink: add callbacks to the per-proto nlattrs

There is added a single callback for the l3 proto helper.  The two
callbacks for the l4 protos are necessary because of the general
structure of a ctnetlink event, which is in short:

 CTA_TUPLE_ORIG
   <l3/l4-proto-attributes>
 CTA_TUPLE_REPLY
   <l3/l4-proto-attributes>
 CTA_ID
 ...
 CTA_PROTOINFO
   <l4-proto-attributes>
 CTA_TUPLE_MASTER
   <l3/l4-proto-attributes>

Therefore the formular is

 size := sizeof(generic-nlas) + 3 * sizeof(tuple_nlas) + sizeof(protoinfo_nlas)

Some of the NLAs are optional, e. g. CTA_TUPLE_MASTER, which is only
set if it's an expected connection.  But the number of optional NLAs is
small enough to prevent netlink_trim() from reallocating if calculated
properly.
Signed-off-by: default avatarHolger Eitzenberger <holger@eitzenberger.org>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent b8dfe498
...@@ -53,10 +53,17 @@ struct nf_conntrack_l3proto ...@@ -53,10 +53,17 @@ struct nf_conntrack_l3proto
int (*tuple_to_nlattr)(struct sk_buff *skb, int (*tuple_to_nlattr)(struct sk_buff *skb,
const struct nf_conntrack_tuple *t); const struct nf_conntrack_tuple *t);
/*
* Calculate size of tuple nlattr
*/
int (*nlattr_tuple_size)(void);
int (*nlattr_to_tuple)(struct nlattr *tb[], int (*nlattr_to_tuple)(struct nlattr *tb[],
struct nf_conntrack_tuple *t); struct nf_conntrack_tuple *t);
const struct nla_policy *nla_policy; const struct nla_policy *nla_policy;
size_t nla_size;
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
struct ctl_table_header *ctl_table_header; struct ctl_table_header *ctl_table_header;
struct ctl_path *ctl_table_path; struct ctl_path *ctl_table_path;
......
...@@ -64,16 +64,22 @@ struct nf_conntrack_l4proto ...@@ -64,16 +64,22 @@ struct nf_conntrack_l4proto
/* convert protoinfo to nfnetink attributes */ /* convert protoinfo to nfnetink attributes */
int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla, int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla,
const struct nf_conn *ct); const struct nf_conn *ct);
/* Calculate protoinfo nlattr size */
int (*nlattr_size)(void);
/* convert nfnetlink attributes to protoinfo */ /* convert nfnetlink attributes to protoinfo */
int (*from_nlattr)(struct nlattr *tb[], struct nf_conn *ct); int (*from_nlattr)(struct nlattr *tb[], struct nf_conn *ct);
int (*tuple_to_nlattr)(struct sk_buff *skb, int (*tuple_to_nlattr)(struct sk_buff *skb,
const struct nf_conntrack_tuple *t); const struct nf_conntrack_tuple *t);
/* Calculate tuple nlattr size */
int (*nlattr_tuple_size)(void);
int (*nlattr_to_tuple)(struct nlattr *tb[], int (*nlattr_to_tuple)(struct nlattr *tb[],
struct nf_conntrack_tuple *t); struct nf_conntrack_tuple *t);
const struct nla_policy *nla_policy; const struct nla_policy *nla_policy;
size_t nla_size;
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
struct ctl_table_header **ctl_table_header; struct ctl_table_header **ctl_table_header;
struct ctl_table *ctl_table; struct ctl_table *ctl_table;
......
...@@ -167,6 +167,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) ...@@ -167,6 +167,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
if (proto->l3proto >= AF_MAX) if (proto->l3proto >= AF_MAX)
return -EBUSY; return -EBUSY;
if (proto->tuple_to_nlattr && !proto->nlattr_tuple_size)
return -EINVAL;
mutex_lock(&nf_ct_proto_mutex); mutex_lock(&nf_ct_proto_mutex);
if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) {
ret = -EBUSY; ret = -EBUSY;
...@@ -177,6 +180,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) ...@@ -177,6 +180,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
if (ret < 0) if (ret < 0)
goto out_unlock; goto out_unlock;
if (proto->nlattr_tuple_size)
proto->nla_size = 3 * proto->nlattr_tuple_size();
rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto); rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto);
out_unlock: out_unlock:
...@@ -263,6 +269,10 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) ...@@ -263,6 +269,10 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
if (l4proto->l3proto >= PF_MAX) if (l4proto->l3proto >= PF_MAX)
return -EBUSY; return -EBUSY;
if ((l4proto->to_nlattr && !l4proto->nlattr_size)
|| (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size))
return -EINVAL;
mutex_lock(&nf_ct_proto_mutex); mutex_lock(&nf_ct_proto_mutex);
if (!nf_ct_protos[l4proto->l3proto]) { if (!nf_ct_protos[l4proto->l3proto]) {
/* l3proto may be loaded latter. */ /* l3proto may be loaded latter. */
...@@ -290,6 +300,12 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) ...@@ -290,6 +300,12 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
if (ret < 0) if (ret < 0)
goto out_unlock; goto out_unlock;
l4proto->nla_size = 0;
if (l4proto->nlattr_size)
l4proto->nla_size += l4proto->nlattr_size();
if (l4proto->nlattr_tuple_size)
l4proto->nla_size += 3 * l4proto->nlattr_tuple_size();
rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
l4proto); l4proto);
......
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