aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_proto.c37
1 files changed, 12 insertions, 25 deletions
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 509725412d3b..e4aad2087f4d 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -281,47 +281,34 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
281 return -EBUSY; 281 return -EBUSY;
282 282
283 mutex_lock(&nf_ct_proto_mutex); 283 mutex_lock(&nf_ct_proto_mutex);
284retry: 284 if (!nf_ct_protos[l4proto->l3proto]) {
285 if (nf_ct_protos[l4proto->l3proto]) {
286 if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
287 != &nf_conntrack_l4proto_generic) {
288 ret = -EBUSY;
289 goto out_unlock;
290 }
291 } else {
292 /* l3proto may be loaded latter. */ 285 /* l3proto may be loaded latter. */
293 struct nf_conntrack_l4proto **proto_array; 286 struct nf_conntrack_l4proto **proto_array;
294 int i; 287 int i;
295 288
296 proto_array = (struct nf_conntrack_l4proto **) 289 proto_array = kmalloc(MAX_NF_CT_PROTO *
297 kmalloc(MAX_NF_CT_PROTO * 290 sizeof(struct nf_conntrack_l4proto *),
298 sizeof(struct nf_conntrack_l4proto *), 291 GFP_KERNEL);
299 GFP_KERNEL);
300 if (proto_array == NULL) { 292 if (proto_array == NULL) {
301 ret = -ENOMEM; 293 ret = -ENOMEM;
302 goto out_unlock; 294 goto out_unlock;
303 } 295 }
296
304 for (i = 0; i < MAX_NF_CT_PROTO; i++) 297 for (i = 0; i < MAX_NF_CT_PROTO; i++)
305 proto_array[i] = &nf_conntrack_l4proto_generic; 298 proto_array[i] = &nf_conntrack_l4proto_generic;
306 299 nf_ct_protos[l4proto->l3proto] = proto_array;
307 if (nf_ct_protos[l4proto->l3proto]) 300 } else if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] !=
308 /* bad timing, but no problem */ 301 &nf_conntrack_l4proto_generic) {
309 kfree(proto_array); 302 ret = -EBUSY;
310 else 303 goto out_unlock;
311 nf_ct_protos[l4proto->l3proto] = proto_array;
312
313 /*
314 * Just once because array is never freed until unloading
315 * nf_conntrack.ko
316 */
317 goto retry;
318 } 304 }
319 305
320 ret = nf_ct_l4proto_register_sysctl(l4proto); 306 ret = nf_ct_l4proto_register_sysctl(l4proto);
321 if (ret < 0) 307 if (ret < 0)
322 goto out_unlock; 308 goto out_unlock;
323 309
324 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], l4proto); 310 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
311 l4proto);
325 312
326out_unlock: 313out_unlock:
327 mutex_unlock(&nf_ct_proto_mutex); 314 mutex_unlock(&nf_ct_proto_mutex);