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)) |