aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-10 05:51:34 -0400
committerDavid S. Miller <davem@davemloft.net>2009-07-12 17:03:27 -0400
commit134e63756d5f3d0f7604dfcca847b09d1b14fd66 (patch)
treed2b5eab085d90cde0a4c0136a118800ca72b76ad /net/netlink/genetlink.c
parent11a28d373ed2539a110d56419457e2e7db221ac7 (diff)
genetlink: make netns aware
This makes generic netlink network namespace aware. No generic netlink families except for the controller family are made namespace aware, they need to be checked one by one and then set the family->netnsok member to true. A new function genlmsg_multicast_netns() is introduced to allow sending a multicast message in a given namespace, for example when it applies to an object that lives in that namespace, a new function genlmsg_multicast_allns() to send a message to all network namespaces (for objects that do not have an associated netns). The function genlmsg_multicast() is changed to multicast the message in just init_net, which is currently correct for all generic netlink families since they only work in init_net right now. Some will later want to work in all net namespaces because they do not care about the netns at all -- those will have to be converted to use one of the new functions genlmsg_multicast_allns() or genlmsg_multicast_netns() whenever they are made netns aware in some way. After this patch families can easily decide whether or not they should be available in all net namespaces. Many genl families us it for objects not related to networking and should therefore be available in all namespaces, but that will have to be done on a per family basis. Note that this doesn't touch on the checkpoint/restart problem where network namespaces could be used, genl families and multicast groups are numbered globally and I see no easy way of changing that, especially since it must be possible to multicast to all network namespaces for those families that do not care about netns. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r--net/netlink/genetlink.c186
1 files changed, 146 insertions, 40 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index eed4c6a8afc0..575c64341508 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -18,8 +18,6 @@
18#include <net/sock.h> 18#include <net/sock.h>
19#include <net/genetlink.h> 19#include <net/genetlink.h>
20 20
21struct sock *genl_sock = NULL;
22
23static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ 21static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
24 22
25static inline void genl_lock(void) 23static inline void genl_lock(void)
@@ -175,10 +173,31 @@ int genl_register_mc_group(struct genl_family *family,
175 mc_groups_longs++; 173 mc_groups_longs++;
176 } 174 }
177 175
178 err = netlink_change_ngroups(genl_sock, 176 if (family->netnsok) {
179 mc_groups_longs * BITS_PER_LONG); 177 struct net *net;
180 if (err) 178
181 goto out; 179 rcu_read_lock();
180 for_each_net_rcu(net) {
181 err = netlink_change_ngroups(net->genl_sock,
182 mc_groups_longs * BITS_PER_LONG);
183 if (err) {
184 /*
185 * No need to roll back, can only fail if
186 * memory allocation fails and then the
187 * number of _possible_ groups has been
188 * increased on some sockets which is ok.
189 */
190 rcu_read_unlock();
191 goto out;
192 }
193 }
194 rcu_read_unlock();
195 } else {
196 err = netlink_change_ngroups(init_net.genl_sock,
197 mc_groups_longs * BITS_PER_LONG);
198 if (err)
199 goto out;
200 }
182 201
183 grp->id = id; 202 grp->id = id;
184 set_bit(id, mc_groups); 203 set_bit(id, mc_groups);
@@ -195,8 +214,14 @@ EXPORT_SYMBOL(genl_register_mc_group);
195static void __genl_unregister_mc_group(struct genl_family *family, 214static void __genl_unregister_mc_group(struct genl_family *family,
196 struct genl_multicast_group *grp) 215 struct genl_multicast_group *grp)
197{ 216{
217 struct net *net;
198 BUG_ON(grp->family != family); 218 BUG_ON(grp->family != family);
199 netlink_clear_multicast_users(genl_sock, grp->id); 219
220 rcu_read_lock();
221 for_each_net_rcu(net)
222 netlink_clear_multicast_users(net->genl_sock, grp->id);
223 rcu_read_unlock();
224
200 clear_bit(grp->id, mc_groups); 225 clear_bit(grp->id, mc_groups);
201 list_del(&grp->list); 226 list_del(&grp->list);
202 genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp); 227 genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
@@ -467,6 +492,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
467{ 492{
468 struct genl_ops *ops; 493 struct genl_ops *ops;
469 struct genl_family *family; 494 struct genl_family *family;
495 struct net *net = sock_net(skb->sk);
470 struct genl_info info; 496 struct genl_info info;
471 struct genlmsghdr *hdr = nlmsg_data(nlh); 497 struct genlmsghdr *hdr = nlmsg_data(nlh);
472 int hdrlen, err; 498 int hdrlen, err;
@@ -475,6 +501,10 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
475 if (family == NULL) 501 if (family == NULL)
476 return -ENOENT; 502 return -ENOENT;
477 503
504 /* this family doesn't exist in this netns */
505 if (!family->netnsok && !net_eq(net, &init_net))
506 return -ENOENT;
507
478 hdrlen = GENL_HDRLEN + family->hdrsize; 508 hdrlen = GENL_HDRLEN + family->hdrsize;
479 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) 509 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
480 return -EINVAL; 510 return -EINVAL;
@@ -492,7 +522,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
492 return -EOPNOTSUPP; 522 return -EOPNOTSUPP;
493 523
494 genl_unlock(); 524 genl_unlock();
495 err = netlink_dump_start(genl_sock, skb, nlh, 525 err = netlink_dump_start(net->genl_sock, skb, nlh,
496 ops->dumpit, ops->done); 526 ops->dumpit, ops->done);
497 genl_lock(); 527 genl_lock();
498 return err; 528 return err;
@@ -514,6 +544,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
514 info.genlhdr = nlmsg_data(nlh); 544 info.genlhdr = nlmsg_data(nlh);
515 info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; 545 info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
516 info.attrs = family->attrbuf; 546 info.attrs = family->attrbuf;
547 genl_info_net_set(&info, net);
517 548
518 return ops->doit(skb, &info); 549 return ops->doit(skb, &info);
519} 550}
@@ -534,6 +565,7 @@ static struct genl_family genl_ctrl = {
534 .name = "nlctrl", 565 .name = "nlctrl",
535 .version = 0x2, 566 .version = 0x2,
536 .maxattr = CTRL_ATTR_MAX, 567 .maxattr = CTRL_ATTR_MAX,
568 .netnsok = true,
537}; 569};
538 570
539static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, 571static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
@@ -650,6 +682,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
650 682
651 int i, n = 0; 683 int i, n = 0;
652 struct genl_family *rt; 684 struct genl_family *rt;
685 struct net *net = sock_net(skb->sk);
653 int chains_to_skip = cb->args[0]; 686 int chains_to_skip = cb->args[0];
654 int fams_to_skip = cb->args[1]; 687 int fams_to_skip = cb->args[1];
655 688
@@ -658,6 +691,8 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
658 continue; 691 continue;
659 n = 0; 692 n = 0;
660 list_for_each_entry(rt, genl_family_chain(i), family_list) { 693 list_for_each_entry(rt, genl_family_chain(i), family_list) {
694 if (!rt->netnsok && !net_eq(net, &init_net))
695 continue;
661 if (++n < fams_to_skip) 696 if (++n < fams_to_skip)
662 continue; 697 continue;
663 if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).pid, 698 if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).pid,
@@ -729,6 +764,7 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
729 if (info->attrs[CTRL_ATTR_FAMILY_ID]) { 764 if (info->attrs[CTRL_ATTR_FAMILY_ID]) {
730 u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]); 765 u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]);
731 res = genl_family_find_byid(id); 766 res = genl_family_find_byid(id);
767 err = -ENOENT;
732 } 768 }
733 769
734 if (info->attrs[CTRL_ATTR_FAMILY_NAME]) { 770 if (info->attrs[CTRL_ATTR_FAMILY_NAME]) {
@@ -736,49 +772,61 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
736 772
737 name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]); 773 name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]);
738 res = genl_family_find_byname(name); 774 res = genl_family_find_byname(name);
775 err = -ENOENT;
739 } 776 }
740 777
741 if (res == NULL) { 778 if (res == NULL)
742 err = -ENOENT; 779 return err;
743 goto errout; 780
781 if (!res->netnsok && !net_eq(genl_info_net(info), &init_net)) {
782 /* family doesn't exist here */
783 return -ENOENT;
744 } 784 }
745 785
746 msg = ctrl_build_family_msg(res, info->snd_pid, info->snd_seq, 786 msg = ctrl_build_family_msg(res, info->snd_pid, info->snd_seq,
747 CTRL_CMD_NEWFAMILY); 787 CTRL_CMD_NEWFAMILY);
748 if (IS_ERR(msg)) { 788 if (IS_ERR(msg))
749 err = PTR_ERR(msg); 789 return PTR_ERR(msg);
750 goto errout;
751 }
752 790
753 err = genlmsg_reply(msg, info); 791 return genlmsg_reply(msg, info);
754errout:
755 return err;
756} 792}
757 793
758static int genl_ctrl_event(int event, void *data) 794static int genl_ctrl_event(int event, void *data)
759{ 795{
760 struct sk_buff *msg; 796 struct sk_buff *msg;
797 struct genl_family *family;
798 struct genl_multicast_group *grp;
761 799
762 if (genl_sock == NULL) 800 /* genl is still initialising */
801 if (!init_net.genl_sock)
763 return 0; 802 return 0;
764 803
765 switch (event) { 804 switch (event) {
766 case CTRL_CMD_NEWFAMILY: 805 case CTRL_CMD_NEWFAMILY:
767 case CTRL_CMD_DELFAMILY: 806 case CTRL_CMD_DELFAMILY:
768 msg = ctrl_build_family_msg(data, 0, 0, event); 807 family = data;
769 if (IS_ERR(msg)) 808 msg = ctrl_build_family_msg(family, 0, 0, event);
770 return PTR_ERR(msg);
771
772 genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
773 break; 809 break;
774 case CTRL_CMD_NEWMCAST_GRP: 810 case CTRL_CMD_NEWMCAST_GRP:
775 case CTRL_CMD_DELMCAST_GRP: 811 case CTRL_CMD_DELMCAST_GRP:
812 grp = data;
813 family = grp->family;
776 msg = ctrl_build_mcgrp_msg(data, 0, 0, event); 814 msg = ctrl_build_mcgrp_msg(data, 0, 0, event);
777 if (IS_ERR(msg))
778 return PTR_ERR(msg);
779
780 genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
781 break; 815 break;
816 default:
817 return -EINVAL;
818 }
819
820 if (IS_ERR(msg))
821 return PTR_ERR(msg);
822
823 if (!family->netnsok) {
824 genlmsg_multicast_netns(&init_net, msg, 0,
825 GENL_ID_CTRL, GFP_KERNEL);
826 } else {
827 rcu_read_lock();
828 genlmsg_multicast_allns(msg, 0, GENL_ID_CTRL, GFP_ATOMIC);
829 rcu_read_unlock();
782 } 830 }
783 831
784 return 0; 832 return 0;
@@ -795,6 +843,33 @@ static struct genl_multicast_group notify_grp = {
795 .name = "notify", 843 .name = "notify",
796}; 844};
797 845
846static int __net_init genl_pernet_init(struct net *net)
847{
848 /* we'll bump the group number right afterwards */
849 net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, 0,
850 genl_rcv, &genl_mutex,
851 THIS_MODULE);
852
853 if (!net->genl_sock && net_eq(net, &init_net))
854 panic("GENL: Cannot initialize generic netlink\n");
855
856 if (!net->genl_sock)
857 return -ENOMEM;
858
859 return 0;
860}
861
862static void __net_exit genl_pernet_exit(struct net *net)
863{
864 netlink_kernel_release(net->genl_sock);
865 net->genl_sock = NULL;
866}
867
868static struct pernet_operations genl_pernet_ops = {
869 .init = genl_pernet_init,
870 .exit = genl_pernet_exit,
871};
872
798static int __init genl_init(void) 873static int __init genl_init(void)
799{ 874{
800 int i, err; 875 int i, err;
@@ -804,36 +879,67 @@ static int __init genl_init(void)
804 879
805 err = genl_register_family(&genl_ctrl); 880 err = genl_register_family(&genl_ctrl);
806 if (err < 0) 881 if (err < 0)
807 goto errout; 882 goto problem;
808 883
809 err = genl_register_ops(&genl_ctrl, &genl_ctrl_ops); 884 err = genl_register_ops(&genl_ctrl, &genl_ctrl_ops);
810 if (err < 0) 885 if (err < 0)
811 goto errout_register; 886 goto problem;
812 887
813 netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV); 888 netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
814 889
815 /* we'll bump the group number right afterwards */ 890 err = register_pernet_subsys(&genl_pernet_ops);
816 genl_sock = netlink_kernel_create(&init_net, NETLINK_GENERIC, 0, 891 if (err)
817 genl_rcv, &genl_mutex, THIS_MODULE); 892 goto problem;
818 if (genl_sock == NULL)
819 panic("GENL: Cannot initialize generic netlink\n");
820 893
821 err = genl_register_mc_group(&genl_ctrl, &notify_grp); 894 err = genl_register_mc_group(&genl_ctrl, &notify_grp);
822 if (err < 0) 895 if (err < 0)
823 goto errout_register; 896 goto problem;
824 897
825 return 0; 898 return 0;
826 899
827errout_register: 900problem:
828 genl_unregister_family(&genl_ctrl);
829errout:
830 panic("GENL: Cannot register controller: %d\n", err); 901 panic("GENL: Cannot register controller: %d\n", err);
831} 902}
832 903
833subsys_initcall(genl_init); 904subsys_initcall(genl_init);
834 905
835EXPORT_SYMBOL(genl_sock);
836EXPORT_SYMBOL(genl_register_ops); 906EXPORT_SYMBOL(genl_register_ops);
837EXPORT_SYMBOL(genl_unregister_ops); 907EXPORT_SYMBOL(genl_unregister_ops);
838EXPORT_SYMBOL(genl_register_family); 908EXPORT_SYMBOL(genl_register_family);
839EXPORT_SYMBOL(genl_unregister_family); 909EXPORT_SYMBOL(genl_unregister_family);
910
911static int genlmsg_mcast(struct sk_buff *skb, u32 pid, unsigned long group,
912 gfp_t flags)
913{
914 struct sk_buff *tmp;
915 struct net *net, *prev = NULL;
916 int err;
917
918 for_each_net_rcu(net) {
919 if (prev) {
920 tmp = skb_clone(skb, flags);
921 if (!tmp) {
922 err = -ENOMEM;
923 goto error;
924 }
925 err = nlmsg_multicast(prev->genl_sock, tmp,
926 pid, group, flags);
927 if (err)
928 goto error;
929 }
930
931 prev = net;
932 }
933
934 return nlmsg_multicast(prev->genl_sock, skb, pid, group, flags);
935 error:
936 kfree_skb(skb);
937 return err;
938}
939
940int genlmsg_multicast_allns(struct sk_buff *skb, u32 pid, unsigned int group,
941 gfp_t flags)
942{
943 return genlmsg_mcast(skb, pid, group, flags);
944}
945EXPORT_SYMBOL(genlmsg_multicast_allns);