summaryrefslogtreecommitdiffstats
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r--net/netlink/genetlink.c37
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 */
360int __genl_register_family(struct genl_family *family) 358int __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
420errout_locked: 428errout_locked:
421 genl_unlock_all(); 429 genl_unlock_all();
422errout:
423 return err; 430 return err;
424} 431}
425EXPORT_SYMBOL(__genl_register_family); 432EXPORT_SYMBOL(__genl_register_family);