diff options
author | Holger Eitzenberger <holger@eitzenberger.org> | 2009-03-25 13:24:48 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2009-03-25 13:24:48 -0400 |
commit | d0dba7255b541f1651a88e75ebdb20dd45509c2f (patch) | |
tree | db731388062d6b81e73bc9328fdd29e6eb81c509 | |
parent | b8dfe498775de912116f275680ddb57c8799d9ef (diff) |
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: Holger Eitzenberger <holger@eitzenberger.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/net/netfilter/nf_conntrack_l3proto.h | 7 | ||||
-rw-r--r-- | include/net/netfilter/nf_conntrack_l4proto.h | 6 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto.c | 16 |
3 files changed, 29 insertions, 0 deletions
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 0378676c3dd8..9f99d36d5de9 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h | |||
@@ -53,10 +53,17 @@ struct nf_conntrack_l3proto | |||
53 | int (*tuple_to_nlattr)(struct sk_buff *skb, | 53 | int (*tuple_to_nlattr)(struct sk_buff *skb, |
54 | const struct nf_conntrack_tuple *t); | 54 | const struct nf_conntrack_tuple *t); |
55 | 55 | ||
56 | /* | ||
57 | * Calculate size of tuple nlattr | ||
58 | */ | ||
59 | int (*nlattr_tuple_size)(void); | ||
60 | |||
56 | int (*nlattr_to_tuple)(struct nlattr *tb[], | 61 | int (*nlattr_to_tuple)(struct nlattr *tb[], |
57 | struct nf_conntrack_tuple *t); | 62 | struct nf_conntrack_tuple *t); |
58 | const struct nla_policy *nla_policy; | 63 | const struct nla_policy *nla_policy; |
59 | 64 | ||
65 | size_t nla_size; | ||
66 | |||
60 | #ifdef CONFIG_SYSCTL | 67 | #ifdef CONFIG_SYSCTL |
61 | struct ctl_table_header *ctl_table_header; | 68 | struct ctl_table_header *ctl_table_header; |
62 | struct ctl_path *ctl_table_path; | 69 | struct ctl_path *ctl_table_path; |
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index b01070bf2f84..a120990b3b2b 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h | |||
@@ -64,16 +64,22 @@ struct nf_conntrack_l4proto | |||
64 | /* convert protoinfo to nfnetink attributes */ | 64 | /* convert protoinfo to nfnetink attributes */ |
65 | int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla, | 65 | int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla, |
66 | const struct nf_conn *ct); | 66 | const struct nf_conn *ct); |
67 | /* Calculate protoinfo nlattr size */ | ||
68 | int (*nlattr_size)(void); | ||
67 | 69 | ||
68 | /* convert nfnetlink attributes to protoinfo */ | 70 | /* convert nfnetlink attributes to protoinfo */ |
69 | int (*from_nlattr)(struct nlattr *tb[], struct nf_conn *ct); | 71 | int (*from_nlattr)(struct nlattr *tb[], struct nf_conn *ct); |
70 | 72 | ||
71 | int (*tuple_to_nlattr)(struct sk_buff *skb, | 73 | int (*tuple_to_nlattr)(struct sk_buff *skb, |
72 | const struct nf_conntrack_tuple *t); | 74 | const struct nf_conntrack_tuple *t); |
75 | /* Calculate tuple nlattr size */ | ||
76 | int (*nlattr_tuple_size)(void); | ||
73 | int (*nlattr_to_tuple)(struct nlattr *tb[], | 77 | int (*nlattr_to_tuple)(struct nlattr *tb[], |
74 | struct nf_conntrack_tuple *t); | 78 | struct nf_conntrack_tuple *t); |
75 | const struct nla_policy *nla_policy; | 79 | const struct nla_policy *nla_policy; |
76 | 80 | ||
81 | size_t nla_size; | ||
82 | |||
77 | #ifdef CONFIG_SYSCTL | 83 | #ifdef CONFIG_SYSCTL |
78 | struct ctl_table_header **ctl_table_header; | 84 | struct ctl_table_header **ctl_table_header; |
79 | struct ctl_table *ctl_table; | 85 | struct ctl_table *ctl_table; |
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 9a62b4efa0e1..1a4568bf7ea5 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c | |||
@@ -167,6 +167,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) | |||
167 | if (proto->l3proto >= AF_MAX) | 167 | if (proto->l3proto >= AF_MAX) |
168 | return -EBUSY; | 168 | return -EBUSY; |
169 | 169 | ||
170 | if (proto->tuple_to_nlattr && !proto->nlattr_tuple_size) | ||
171 | return -EINVAL; | ||
172 | |||
170 | mutex_lock(&nf_ct_proto_mutex); | 173 | mutex_lock(&nf_ct_proto_mutex); |
171 | if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { | 174 | if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { |
172 | ret = -EBUSY; | 175 | ret = -EBUSY; |
@@ -177,6 +180,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) | |||
177 | if (ret < 0) | 180 | if (ret < 0) |
178 | goto out_unlock; | 181 | goto out_unlock; |
179 | 182 | ||
183 | if (proto->nlattr_tuple_size) | ||
184 | proto->nla_size = 3 * proto->nlattr_tuple_size(); | ||
185 | |||
180 | rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto); | 186 | rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto); |
181 | 187 | ||
182 | out_unlock: | 188 | out_unlock: |
@@ -263,6 +269,10 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) | |||
263 | if (l4proto->l3proto >= PF_MAX) | 269 | if (l4proto->l3proto >= PF_MAX) |
264 | return -EBUSY; | 270 | return -EBUSY; |
265 | 271 | ||
272 | if ((l4proto->to_nlattr && !l4proto->nlattr_size) | ||
273 | || (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size)) | ||
274 | return -EINVAL; | ||
275 | |||
266 | mutex_lock(&nf_ct_proto_mutex); | 276 | mutex_lock(&nf_ct_proto_mutex); |
267 | if (!nf_ct_protos[l4proto->l3proto]) { | 277 | if (!nf_ct_protos[l4proto->l3proto]) { |
268 | /* l3proto may be loaded latter. */ | 278 | /* l3proto may be loaded latter. */ |
@@ -290,6 +300,12 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) | |||
290 | if (ret < 0) | 300 | if (ret < 0) |
291 | goto out_unlock; | 301 | goto out_unlock; |
292 | 302 | ||
303 | l4proto->nla_size = 0; | ||
304 | if (l4proto->nlattr_size) | ||
305 | l4proto->nla_size += l4proto->nlattr_size(); | ||
306 | if (l4proto->nlattr_tuple_size) | ||
307 | l4proto->nla_size += 3 * l4proto->nlattr_tuple_size(); | ||
308 | |||
293 | rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], | 309 | rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], |
294 | l4proto); | 310 | l4proto); |
295 | 311 | ||