diff options
author | Johannes Berg <johannes.berg@intel.com> | 2014-12-23 14:54:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-12-27 02:20:23 -0500 |
commit | c380d9a7afff0e4c2e5f3c1c2dc7d2f4214dd962 (patch) | |
tree | adc927b4f3fb05268c6ca808aee5d0109351fec1 /net | |
parent | 7d68536bed72b09de03b07479dd707c5831b3b94 (diff) |
genetlink: pass multicast bind/unbind to families
In order to make the newly fixed multicast bind/unbind
functionality in generic netlink, pass them down to the
appropriate family.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netlink/genetlink.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 76393f2f4b22..05bf40bbd189 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -983,11 +983,70 @@ static struct genl_multicast_group genl_ctrl_groups[] = { | |||
983 | { .name = "notify", }, | 983 | { .name = "notify", }, |
984 | }; | 984 | }; |
985 | 985 | ||
986 | static int genl_bind(int group) | ||
987 | { | ||
988 | int i, err; | ||
989 | bool found = false; | ||
990 | |||
991 | down_read(&cb_lock); | ||
992 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | ||
993 | struct genl_family *f; | ||
994 | |||
995 | list_for_each_entry(f, genl_family_chain(i), family_list) { | ||
996 | if (group >= f->mcgrp_offset && | ||
997 | group < f->mcgrp_offset + f->n_mcgrps) { | ||
998 | int fam_grp = group - f->mcgrp_offset; | ||
999 | |||
1000 | if (f->mcast_bind) | ||
1001 | err = f->mcast_bind(fam_grp); | ||
1002 | else | ||
1003 | err = 0; | ||
1004 | found = true; | ||
1005 | break; | ||
1006 | } | ||
1007 | } | ||
1008 | } | ||
1009 | up_read(&cb_lock); | ||
1010 | |||
1011 | if (WARN_ON(!found)) | ||
1012 | err = 0; | ||
1013 | |||
1014 | return err; | ||
1015 | } | ||
1016 | |||
1017 | static void genl_unbind(int group) | ||
1018 | { | ||
1019 | int i; | ||
1020 | bool found = false; | ||
1021 | |||
1022 | down_read(&cb_lock); | ||
1023 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | ||
1024 | struct genl_family *f; | ||
1025 | |||
1026 | list_for_each_entry(f, genl_family_chain(i), family_list) { | ||
1027 | if (group >= f->mcgrp_offset && | ||
1028 | group < f->mcgrp_offset + f->n_mcgrps) { | ||
1029 | int fam_grp = group - f->mcgrp_offset; | ||
1030 | |||
1031 | if (f->mcast_unbind) | ||
1032 | f->mcast_unbind(fam_grp); | ||
1033 | found = true; | ||
1034 | break; | ||
1035 | } | ||
1036 | } | ||
1037 | } | ||
1038 | up_read(&cb_lock); | ||
1039 | |||
1040 | WARN_ON(!found); | ||
1041 | } | ||
1042 | |||
986 | static int __net_init genl_pernet_init(struct net *net) | 1043 | static int __net_init genl_pernet_init(struct net *net) |
987 | { | 1044 | { |
988 | struct netlink_kernel_cfg cfg = { | 1045 | struct netlink_kernel_cfg cfg = { |
989 | .input = genl_rcv, | 1046 | .input = genl_rcv, |
990 | .flags = NL_CFG_F_NONROOT_RECV, | 1047 | .flags = NL_CFG_F_NONROOT_RECV, |
1048 | .bind = genl_bind, | ||
1049 | .unbind = genl_unbind, | ||
991 | }; | 1050 | }; |
992 | 1051 | ||
993 | /* we'll bump the group number right afterwards */ | 1052 | /* we'll bump the group number right afterwards */ |