diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_conntrack_proto.c | 37 |
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); |
284 | retry: | 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 | ||
326 | out_unlock: | 313 | out_unlock: |
327 | mutex_unlock(&nf_ct_proto_mutex); | 314 | mutex_unlock(&nf_ct_proto_mutex); |