aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-09-17 14:56:21 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:49:10 -0400
commit881d966b48b035ab3f3aeaae0f3d3f9b584f45b2 (patch)
treec579d59a4107cbbe9e2b85939bc0d496b815c887 /net/core/rtnetlink.c
parentb4b510290b056b86611757ce1175a230f1080f53 (diff)
[NET]: Make the device list and device lookups per namespace.
This patch makes most of the generic device layer network namespace safe. This patch makes dev_base_head a network namespace variable, and then it picks up a few associated variables. The functions: dev_getbyhwaddr dev_getfirsthwbytype dev_get_by_flags dev_get_by_name __dev_get_by_name dev_get_by_index __dev_get_by_index dev_ioctl dev_ethtool dev_load wireless_process_ioctl were modified to take a network namespace argument, and deal with it. vlan_ioctl_set and brioctl_set were modified so their hooks will receive a network namespace argument. So basically anthing in the core of the network stack that was affected to by the change of dev_base was modified to handle multiple network namespaces. The rest of the network stack was simply modified to explicitly use &init_net the initial network namespace. This can be fixed when those components of the network stack are modified to handle multiple network namespaces. For now the ifindex generator is left global. Fundametally ifindex numbers are per namespace, or else we will have corner case problems with migration when we get that far. At the same time there are assumptions in the network stack that the ifindex of a network device won't change. Making the ifindex number global seems a good compromise until the network stack can cope with ifindex changes when you change namespaces, and the like. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 416768d1e0cd..44f91bb1ae8d 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -306,10 +306,13 @@ EXPORT_SYMBOL_GPL(rtnl_link_register);
306void __rtnl_link_unregister(struct rtnl_link_ops *ops) 306void __rtnl_link_unregister(struct rtnl_link_ops *ops)
307{ 307{
308 struct net_device *dev, *n; 308 struct net_device *dev, *n;
309 struct net *net;
309 310
310 for_each_netdev_safe(dev, n) { 311 for_each_net(net) {
311 if (dev->rtnl_link_ops == ops) 312 for_each_netdev_safe(net, dev, n) {
312 ops->dellink(dev); 313 if (dev->rtnl_link_ops == ops)
314 ops->dellink(dev);
315 }
313 } 316 }
314 list_del(&ops->list); 317 list_del(&ops->list);
315} 318}
@@ -693,12 +696,13 @@ nla_put_failure:
693 696
694static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) 697static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
695{ 698{
699 struct net *net = skb->sk->sk_net;
696 int idx; 700 int idx;
697 int s_idx = cb->args[0]; 701 int s_idx = cb->args[0];
698 struct net_device *dev; 702 struct net_device *dev;
699 703
700 idx = 0; 704 idx = 0;
701 for_each_netdev(dev) { 705 for_each_netdev(net, dev) {
702 if (idx < s_idx) 706 if (idx < s_idx)
703 goto cont; 707 goto cont;
704 if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, 708 if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
@@ -858,6 +862,7 @@ errout:
858 862
859static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 863static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
860{ 864{
865 struct net *net = skb->sk->sk_net;
861 struct ifinfomsg *ifm; 866 struct ifinfomsg *ifm;
862 struct net_device *dev; 867 struct net_device *dev;
863 int err; 868 int err;
@@ -876,9 +881,9 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
876 err = -EINVAL; 881 err = -EINVAL;
877 ifm = nlmsg_data(nlh); 882 ifm = nlmsg_data(nlh);
878 if (ifm->ifi_index > 0) 883 if (ifm->ifi_index > 0)
879 dev = dev_get_by_index(ifm->ifi_index); 884 dev = dev_get_by_index(net, ifm->ifi_index);
880 else if (tb[IFLA_IFNAME]) 885 else if (tb[IFLA_IFNAME])
881 dev = dev_get_by_name(ifname); 886 dev = dev_get_by_name(net, ifname);
882 else 887 else
883 goto errout; 888 goto errout;
884 889
@@ -904,6 +909,7 @@ errout:
904 909
905static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 910static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
906{ 911{
912 struct net *net = skb->sk->sk_net;
907 const struct rtnl_link_ops *ops; 913 const struct rtnl_link_ops *ops;
908 struct net_device *dev; 914 struct net_device *dev;
909 struct ifinfomsg *ifm; 915 struct ifinfomsg *ifm;
@@ -920,9 +926,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
920 926
921 ifm = nlmsg_data(nlh); 927 ifm = nlmsg_data(nlh);
922 if (ifm->ifi_index > 0) 928 if (ifm->ifi_index > 0)
923 dev = __dev_get_by_index(ifm->ifi_index); 929 dev = __dev_get_by_index(net, ifm->ifi_index);
924 else if (tb[IFLA_IFNAME]) 930 else if (tb[IFLA_IFNAME])
925 dev = __dev_get_by_name(ifname); 931 dev = __dev_get_by_name(net, ifname);
926 else 932 else
927 return -EINVAL; 933 return -EINVAL;
928 934
@@ -937,7 +943,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
937 return 0; 943 return 0;
938} 944}
939 945
940struct net_device *rtnl_create_link(char *ifname, 946struct net_device *rtnl_create_link(struct net *net, char *ifname,
941 const struct rtnl_link_ops *ops, struct nlattr *tb[]) 947 const struct rtnl_link_ops *ops, struct nlattr *tb[])
942{ 948{
943 int err; 949 int err;
@@ -954,6 +960,7 @@ struct net_device *rtnl_create_link(char *ifname,
954 goto err_free; 960 goto err_free;
955 } 961 }
956 962
963 dev->nd_net = net;
957 dev->rtnl_link_ops = ops; 964 dev->rtnl_link_ops = ops;
958 965
959 if (tb[IFLA_MTU]) 966 if (tb[IFLA_MTU])
@@ -981,6 +988,7 @@ err:
981 988
982static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 989static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
983{ 990{
991 struct net *net = skb->sk->sk_net;
984 const struct rtnl_link_ops *ops; 992 const struct rtnl_link_ops *ops;
985 struct net_device *dev; 993 struct net_device *dev;
986 struct ifinfomsg *ifm; 994 struct ifinfomsg *ifm;
@@ -1004,9 +1012,9 @@ replay:
1004 1012
1005 ifm = nlmsg_data(nlh); 1013 ifm = nlmsg_data(nlh);
1006 if (ifm->ifi_index > 0) 1014 if (ifm->ifi_index > 0)
1007 dev = __dev_get_by_index(ifm->ifi_index); 1015 dev = __dev_get_by_index(net, ifm->ifi_index);
1008 else if (ifname[0]) 1016 else if (ifname[0])
1009 dev = __dev_get_by_name(ifname); 1017 dev = __dev_get_by_name(net, ifname);
1010 else 1018 else
1011 dev = NULL; 1019 dev = NULL;
1012 1020
@@ -1092,7 +1100,7 @@ replay:
1092 if (!ifname[0]) 1100 if (!ifname[0])
1093 snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); 1101 snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
1094 1102
1095 dev = rtnl_create_link(ifname, ops, tb); 1103 dev = rtnl_create_link(net, ifname, ops, tb);
1096 1104
1097 if (IS_ERR(dev)) 1105 if (IS_ERR(dev))
1098 err = PTR_ERR(dev); 1106 err = PTR_ERR(dev);
@@ -1109,6 +1117,7 @@ replay:
1109 1117
1110static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 1118static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1111{ 1119{
1120 struct net *net = skb->sk->sk_net;
1112 struct ifinfomsg *ifm; 1121 struct ifinfomsg *ifm;
1113 struct nlattr *tb[IFLA_MAX+1]; 1122 struct nlattr *tb[IFLA_MAX+1];
1114 struct net_device *dev = NULL; 1123 struct net_device *dev = NULL;
@@ -1121,7 +1130,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1121 1130
1122 ifm = nlmsg_data(nlh); 1131 ifm = nlmsg_data(nlh);
1123 if (ifm->ifi_index > 0) { 1132 if (ifm->ifi_index > 0) {
1124 dev = dev_get_by_index(ifm->ifi_index); 1133 dev = dev_get_by_index(net, ifm->ifi_index);
1125 if (dev == NULL) 1134 if (dev == NULL)
1126 return -ENODEV; 1135 return -ENODEV;
1127 } else 1136 } else