diff options
Diffstat (limited to 'net/netlink/genetlink.c')
| -rw-r--r-- | net/netlink/genetlink.c | 37 |
1 files changed, 13 insertions, 24 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 44ff3f3810fa..06438fa2b1e5 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
| 11 | #include <linux/slab.h> | ||
| 11 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| 12 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 13 | #include <linux/socket.h> | 14 | #include <linux/socket.h> |
| @@ -97,25 +98,17 @@ static struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family) | |||
| 97 | */ | 98 | */ |
| 98 | static inline u16 genl_generate_id(void) | 99 | static inline u16 genl_generate_id(void) |
| 99 | { | 100 | { |
| 100 | static u16 id_gen_idx; | 101 | static u16 id_gen_idx = GENL_MIN_ID; |
| 101 | int overflowed = 0; | 102 | int i; |
| 102 | 103 | ||
| 103 | do { | 104 | for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) { |
| 104 | if (id_gen_idx == 0) | 105 | if (!genl_family_find_byid(id_gen_idx)) |
| 106 | return id_gen_idx; | ||
| 107 | if (++id_gen_idx > GENL_MAX_ID) | ||
| 105 | id_gen_idx = GENL_MIN_ID; | 108 | id_gen_idx = GENL_MIN_ID; |
| 109 | } | ||
| 106 | 110 | ||
| 107 | if (++id_gen_idx > GENL_MAX_ID) { | 111 | return 0; |
| 108 | if (!overflowed) { | ||
| 109 | overflowed = 1; | ||
| 110 | id_gen_idx = 0; | ||
| 111 | continue; | ||
| 112 | } else | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | } while (genl_family_find_byid(id_gen_idx)); | ||
| 117 | |||
| 118 | return id_gen_idx; | ||
| 119 | } | 112 | } |
| 120 | 113 | ||
| 121 | static struct genl_multicast_group notify_grp; | 114 | static struct genl_multicast_group notify_grp; |
| @@ -374,11 +367,6 @@ int genl_register_family(struct genl_family *family) | |||
| 374 | goto errout_locked; | 367 | goto errout_locked; |
| 375 | } | 368 | } |
| 376 | 369 | ||
| 377 | if (genl_family_find_byid(family->id)) { | ||
| 378 | err = -EEXIST; | ||
| 379 | goto errout_locked; | ||
| 380 | } | ||
| 381 | |||
| 382 | if (family->id == GENL_ID_GENERATE) { | 370 | if (family->id == GENL_ID_GENERATE) { |
| 383 | u16 newid = genl_generate_id(); | 371 | u16 newid = genl_generate_id(); |
| 384 | 372 | ||
| @@ -388,6 +376,9 @@ int genl_register_family(struct genl_family *family) | |||
| 388 | } | 376 | } |
| 389 | 377 | ||
| 390 | family->id = newid; | 378 | family->id = newid; |
| 379 | } else if (genl_family_find_byid(family->id)) { | ||
| 380 | err = -EEXIST; | ||
| 381 | goto errout_locked; | ||
| 391 | } | 382 | } |
| 392 | 383 | ||
| 393 | if (family->maxattr) { | 384 | if (family->maxattr) { |
| @@ -691,9 +682,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 691 | int chains_to_skip = cb->args[0]; | 682 | int chains_to_skip = cb->args[0]; |
| 692 | int fams_to_skip = cb->args[1]; | 683 | int fams_to_skip = cb->args[1]; |
| 693 | 684 | ||
| 694 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | 685 | for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) { |
| 695 | if (i < chains_to_skip) | ||
| 696 | continue; | ||
| 697 | n = 0; | 686 | n = 0; |
| 698 | list_for_each_entry(rt, genl_family_chain(i), family_list) { | 687 | list_for_each_entry(rt, genl_family_chain(i), family_list) { |
| 699 | if (!rt->netnsok && !net_eq(net, &init_net)) | 688 | if (!rt->netnsok && !net_eq(net, &init_net)) |
