diff options
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r-- | net/netlink/genetlink.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 01291b7a27bb..f19ec969edee 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -349,8 +349,6 @@ static int genl_validate_ops(const struct genl_family *family) | |||
349 | * | 349 | * |
350 | * Registers the specified family after validating it first. Only one | 350 | * Registers the specified family after validating it first. Only one |
351 | * family may be registered with the same family name or identifier. | 351 | * family may be registered with the same family name or identifier. |
352 | * The family id may equal GENL_ID_GENERATE causing an unique id to | ||
353 | * be automatically generated and assigned. | ||
354 | * | 352 | * |
355 | * The family's ops array must already be assigned, you can use the | 353 | * The family's ops array must already be assigned, you can use the |
356 | * genl_register_family_with_ops() helper function. | 354 | * genl_register_family_with_ops() helper function. |
@@ -359,13 +357,7 @@ static int genl_validate_ops(const struct genl_family *family) | |||
359 | */ | 357 | */ |
360 | int __genl_register_family(struct genl_family *family) | 358 | int __genl_register_family(struct genl_family *family) |
361 | { | 359 | { |
362 | int err = -EINVAL, i; | 360 | int err, i; |
363 | |||
364 | if (family->id && family->id < GENL_MIN_ID) | ||
365 | goto errout; | ||
366 | |||
367 | if (family->id > GENL_MAX_ID) | ||
368 | goto errout; | ||
369 | 361 | ||
370 | err = genl_validate_ops(family); | 362 | err = genl_validate_ops(family); |
371 | if (err) | 363 | if (err) |
@@ -378,8 +370,27 @@ int __genl_register_family(struct genl_family *family) | |||
378 | goto errout_locked; | 370 | goto errout_locked; |
379 | } | 371 | } |
380 | 372 | ||
381 | if (family->id == GENL_ID_GENERATE) { | 373 | if (family == &genl_ctrl) { |
382 | u16 newid = genl_generate_id(); | 374 | family->id = GENL_ID_CTRL; |
375 | } else { | ||
376 | u16 newid; | ||
377 | |||
378 | /* this should be left zero in the struct */ | ||
379 | WARN_ON(family->id); | ||
380 | |||
381 | /* | ||
382 | * Sadly, a few cases need to be special-cased | ||
383 | * due to them having previously abused the API | ||
384 | * and having used their family ID also as their | ||
385 | * multicast group ID, so we use reserved IDs | ||
386 | * for both to be sure we can do that mapping. | ||
387 | */ | ||
388 | if (strcmp(family->name, "pmcraid") == 0) | ||
389 | newid = GENL_ID_PMCRAID; | ||
390 | else if (strcmp(family->name, "VFS_DQUOT") == 0) | ||
391 | newid = GENL_ID_VFS_DQUOT; | ||
392 | else | ||
393 | newid = genl_generate_id(); | ||
383 | 394 | ||
384 | if (!newid) { | 395 | if (!newid) { |
385 | err = -ENOMEM; | 396 | err = -ENOMEM; |
@@ -387,9 +398,6 @@ int __genl_register_family(struct genl_family *family) | |||
387 | } | 398 | } |
388 | 399 | ||
389 | family->id = newid; | 400 | family->id = newid; |
390 | } else if (genl_family_find_byid(family->id)) { | ||
391 | err = -EEXIST; | ||
392 | goto errout_locked; | ||
393 | } | 401 | } |
394 | 402 | ||
395 | if (family->maxattr && !family->parallel_ops) { | 403 | if (family->maxattr && !family->parallel_ops) { |
@@ -419,7 +427,6 @@ int __genl_register_family(struct genl_family *family) | |||
419 | 427 | ||
420 | errout_locked: | 428 | errout_locked: |
421 | genl_unlock_all(); | 429 | genl_unlock_all(); |
422 | errout: | ||
423 | return err; | 430 | return err; |
424 | } | 431 | } |
425 | EXPORT_SYMBOL(__genl_register_family); | 432 | EXPORT_SYMBOL(__genl_register_family); |