summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c69
-rw-r--r--include/linux/inetdevice.h7
-rw-r--r--include/net/addrconf.h10
-rw-r--r--net/ipv4/devinet.c33
-rw-r--r--net/ipv6/addrconf.c17
-rw-r--r--net/ipv6/addrconf_core.c19
6 files changed, 153 insertions, 2 deletions
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 618ed88fad0f..e4141d62b5c3 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -824,6 +824,33 @@ static int ipvlan_addr6_event(struct notifier_block *unused,
824 return NOTIFY_OK; 824 return NOTIFY_OK;
825} 825}
826 826
827static int ipvlan_addr6_validator_event(struct notifier_block *unused,
828 unsigned long event, void *ptr)
829{
830 struct in6_validator_info *i6vi = (struct in6_validator_info *)ptr;
831 struct net_device *dev = (struct net_device *)i6vi->i6vi_dev->dev;
832 struct ipvl_dev *ipvlan = netdev_priv(dev);
833
834 /* FIXME IPv6 autoconf calls us from bh without RTNL */
835 if (in_softirq())
836 return NOTIFY_DONE;
837
838 if (!netif_is_ipvlan(dev))
839 return NOTIFY_DONE;
840
841 if (!ipvlan || !ipvlan->port)
842 return NOTIFY_DONE;
843
844 switch (event) {
845 case NETDEV_UP:
846 if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true))
847 return notifier_from_errno(-EADDRINUSE);
848 break;
849 }
850
851 return NOTIFY_OK;
852}
853
827static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) 854static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
828{ 855{
829 if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) { 856 if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) {
@@ -871,10 +898,37 @@ static int ipvlan_addr4_event(struct notifier_block *unused,
871 return NOTIFY_OK; 898 return NOTIFY_OK;
872} 899}
873 900
901static int ipvlan_addr4_validator_event(struct notifier_block *unused,
902 unsigned long event, void *ptr)
903{
904 struct in_validator_info *ivi = (struct in_validator_info *)ptr;
905 struct net_device *dev = (struct net_device *)ivi->ivi_dev->dev;
906 struct ipvl_dev *ipvlan = netdev_priv(dev);
907
908 if (!netif_is_ipvlan(dev))
909 return NOTIFY_DONE;
910
911 if (!ipvlan || !ipvlan->port)
912 return NOTIFY_DONE;
913
914 switch (event) {
915 case NETDEV_UP:
916 if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false))
917 return notifier_from_errno(-EADDRINUSE);
918 break;
919 }
920
921 return NOTIFY_OK;
922}
923
874static struct notifier_block ipvlan_addr4_notifier_block __read_mostly = { 924static struct notifier_block ipvlan_addr4_notifier_block __read_mostly = {
875 .notifier_call = ipvlan_addr4_event, 925 .notifier_call = ipvlan_addr4_event,
876}; 926};
877 927
928static struct notifier_block ipvlan_addr4_vtor_notifier_block __read_mostly = {
929 .notifier_call = ipvlan_addr4_validator_event,
930};
931
878static struct notifier_block ipvlan_notifier_block __read_mostly = { 932static struct notifier_block ipvlan_notifier_block __read_mostly = {
879 .notifier_call = ipvlan_device_event, 933 .notifier_call = ipvlan_device_event,
880}; 934};
@@ -883,6 +937,10 @@ static struct notifier_block ipvlan_addr6_notifier_block __read_mostly = {
883 .notifier_call = ipvlan_addr6_event, 937 .notifier_call = ipvlan_addr6_event,
884}; 938};
885 939
940static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
941 .notifier_call = ipvlan_addr6_validator_event,
942};
943
886static void ipvlan_ns_exit(struct net *net) 944static void ipvlan_ns_exit(struct net *net)
887{ 945{
888 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); 946 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
@@ -907,7 +965,10 @@ static int __init ipvlan_init_module(void)
907 ipvlan_init_secret(); 965 ipvlan_init_secret();
908 register_netdevice_notifier(&ipvlan_notifier_block); 966 register_netdevice_notifier(&ipvlan_notifier_block);
909 register_inet6addr_notifier(&ipvlan_addr6_notifier_block); 967 register_inet6addr_notifier(&ipvlan_addr6_notifier_block);
968 register_inet6addr_validator_notifier(
969 &ipvlan_addr6_vtor_notifier_block);
910 register_inetaddr_notifier(&ipvlan_addr4_notifier_block); 970 register_inetaddr_notifier(&ipvlan_addr4_notifier_block);
971 register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block);
911 972
912 err = register_pernet_subsys(&ipvlan_net_ops); 973 err = register_pernet_subsys(&ipvlan_net_ops);
913 if (err < 0) 974 if (err < 0)
@@ -922,7 +983,11 @@ static int __init ipvlan_init_module(void)
922 return 0; 983 return 0;
923error: 984error:
924 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); 985 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
986 unregister_inetaddr_validator_notifier(
987 &ipvlan_addr4_vtor_notifier_block);
925 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block); 988 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
989 unregister_inet6addr_validator_notifier(
990 &ipvlan_addr6_vtor_notifier_block);
926 unregister_netdevice_notifier(&ipvlan_notifier_block); 991 unregister_netdevice_notifier(&ipvlan_notifier_block);
927 return err; 992 return err;
928} 993}
@@ -933,7 +998,11 @@ static void __exit ipvlan_cleanup_module(void)
933 unregister_pernet_subsys(&ipvlan_net_ops); 998 unregister_pernet_subsys(&ipvlan_net_ops);
934 unregister_netdevice_notifier(&ipvlan_notifier_block); 999 unregister_netdevice_notifier(&ipvlan_notifier_block);
935 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); 1000 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
1001 unregister_inetaddr_validator_notifier(
1002 &ipvlan_addr4_vtor_notifier_block);
936 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block); 1003 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
1004 unregister_inet6addr_validator_notifier(
1005 &ipvlan_addr6_vtor_notifier_block);
937} 1006}
938 1007
939module_init(ipvlan_init_module); 1008module_init(ipvlan_init_module);
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index a2e9d6ea1349..e7c04c4e4bcd 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -150,8 +150,15 @@ struct in_ifaddr {
150 unsigned long ifa_tstamp; /* updated timestamp */ 150 unsigned long ifa_tstamp; /* updated timestamp */
151}; 151};
152 152
153struct in_validator_info {
154 __be32 ivi_addr;
155 struct in_device *ivi_dev;
156};
157
153int register_inetaddr_notifier(struct notifier_block *nb); 158int register_inetaddr_notifier(struct notifier_block *nb);
154int unregister_inetaddr_notifier(struct notifier_block *nb); 159int unregister_inetaddr_notifier(struct notifier_block *nb);
160int register_inetaddr_validator_notifier(struct notifier_block *nb);
161int unregister_inetaddr_validator_notifier(struct notifier_block *nb);
155 162
156void inet_netconf_notify_devconf(struct net *net, int event, int type, 163void inet_netconf_notify_devconf(struct net *net, int event, int type,
157 int ifindex, struct ipv4_devconf *devconf); 164 int ifindex, struct ipv4_devconf *devconf);
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index b43a4eec3cec..d0889cb50172 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -48,11 +48,15 @@ struct prefix_info {
48 struct in6_addr prefix; 48 struct in6_addr prefix;
49}; 49};
50 50
51
52#include <linux/netdevice.h> 51#include <linux/netdevice.h>
53#include <net/if_inet6.h> 52#include <net/if_inet6.h>
54#include <net/ipv6.h> 53#include <net/ipv6.h>
55 54
55struct in6_validator_info {
56 struct in6_addr i6vi_addr;
57 struct inet6_dev *i6vi_dev;
58};
59
56#define IN6_ADDR_HSIZE_SHIFT 4 60#define IN6_ADDR_HSIZE_SHIFT 4
57#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT) 61#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT)
58 62
@@ -278,6 +282,10 @@ int register_inet6addr_notifier(struct notifier_block *nb);
278int unregister_inet6addr_notifier(struct notifier_block *nb); 282int unregister_inet6addr_notifier(struct notifier_block *nb);
279int inet6addr_notifier_call_chain(unsigned long val, void *v); 283int inet6addr_notifier_call_chain(unsigned long val, void *v);
280 284
285int register_inet6addr_validator_notifier(struct notifier_block *nb);
286int unregister_inet6addr_validator_notifier(struct notifier_block *nb);
287int inet6addr_validator_notifier_call_chain(unsigned long val, void *v);
288
281void inet6_netconf_notify_devconf(struct net *net, int event, int type, 289void inet6_netconf_notify_devconf(struct net *net, int event, int type,
282 int ifindex, struct ipv6_devconf *devconf); 290 int ifindex, struct ipv6_devconf *devconf);
283 291
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index df14815a3b8c..a7dd088d5fc9 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -176,6 +176,7 @@ EXPORT_SYMBOL(__ip_dev_find);
176static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32); 176static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
177 177
178static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); 178static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
179static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain);
179static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 180static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
180 int destroy); 181 int destroy);
181#ifdef CONFIG_SYSCTL 182#ifdef CONFIG_SYSCTL
@@ -441,6 +442,8 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
441{ 442{
442 struct in_device *in_dev = ifa->ifa_dev; 443 struct in_device *in_dev = ifa->ifa_dev;
443 struct in_ifaddr *ifa1, **ifap, **last_primary; 444 struct in_ifaddr *ifa1, **ifap, **last_primary;
445 struct in_validator_info ivi;
446 int ret;
444 447
445 ASSERT_RTNL(); 448 ASSERT_RTNL();
446 449
@@ -471,6 +474,23 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
471 } 474 }
472 } 475 }
473 476
477 /* Allow any devices that wish to register ifaddr validtors to weigh
478 * in now, before changes are committed. The rntl lock is serializing
479 * access here, so the state should not change between a validator call
480 * and a final notify on commit. This isn't invoked on promotion under
481 * the assumption that validators are checking the address itself, and
482 * not the flags.
483 */
484 ivi.ivi_addr = ifa->ifa_address;
485 ivi.ivi_dev = ifa->ifa_dev;
486 ret = blocking_notifier_call_chain(&inetaddr_validator_chain,
487 NETDEV_UP, &ivi);
488 ret = notifier_to_errno(ret);
489 if (ret) {
490 inet_free_ifa(ifa);
491 return ret;
492 }
493
474 if (!(ifa->ifa_flags & IFA_F_SECONDARY)) { 494 if (!(ifa->ifa_flags & IFA_F_SECONDARY)) {
475 prandom_seed((__force u32) ifa->ifa_local); 495 prandom_seed((__force u32) ifa->ifa_local);
476 ifap = last_primary; 496 ifap = last_primary;
@@ -1356,6 +1376,19 @@ int unregister_inetaddr_notifier(struct notifier_block *nb)
1356} 1376}
1357EXPORT_SYMBOL(unregister_inetaddr_notifier); 1377EXPORT_SYMBOL(unregister_inetaddr_notifier);
1358 1378
1379int register_inetaddr_validator_notifier(struct notifier_block *nb)
1380{
1381 return blocking_notifier_chain_register(&inetaddr_validator_chain, nb);
1382}
1383EXPORT_SYMBOL(register_inetaddr_validator_notifier);
1384
1385int unregister_inetaddr_validator_notifier(struct notifier_block *nb)
1386{
1387 return blocking_notifier_chain_unregister(&inetaddr_validator_chain,
1388 nb);
1389}
1390EXPORT_SYMBOL(unregister_inetaddr_validator_notifier);
1391
1359/* Rename ifa_labels for a device name change. Make some effort to preserve 1392/* Rename ifa_labels for a device name change. Make some effort to preserve
1360 * existing alias numbering and to create unique labels if possible. 1393 * existing alias numbering and to create unique labels if possible.
1361*/ 1394*/
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 25443fd946a8..0aa36b093013 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -963,6 +963,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
963 struct net *net = dev_net(idev->dev); 963 struct net *net = dev_net(idev->dev);
964 struct inet6_ifaddr *ifa = NULL; 964 struct inet6_ifaddr *ifa = NULL;
965 struct rt6_info *rt; 965 struct rt6_info *rt;
966 struct in6_validator_info i6vi;
966 unsigned int hash; 967 unsigned int hash;
967 int err = 0; 968 int err = 0;
968 int addr_type = ipv6_addr_type(addr); 969 int addr_type = ipv6_addr_type(addr);
@@ -974,6 +975,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
974 return ERR_PTR(-EADDRNOTAVAIL); 975 return ERR_PTR(-EADDRNOTAVAIL);
975 976
976 rcu_read_lock_bh(); 977 rcu_read_lock_bh();
978
979 in6_dev_hold(idev);
980
977 if (idev->dead) { 981 if (idev->dead) {
978 err = -ENODEV; /*XXX*/ 982 err = -ENODEV; /*XXX*/
979 goto out2; 983 goto out2;
@@ -984,6 +988,17 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
984 goto out2; 988 goto out2;
985 } 989 }
986 990
991 i6vi.i6vi_addr = *addr;
992 i6vi.i6vi_dev = idev;
993 rcu_read_unlock_bh();
994
995 err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi);
996
997 rcu_read_lock_bh();
998 err = notifier_to_errno(err);
999 if (err)
1000 goto out2;
1001
987 spin_lock(&addrconf_hash_lock); 1002 spin_lock(&addrconf_hash_lock);
988 1003
989 /* Ignore adding duplicate addresses on an interface */ 1004 /* Ignore adding duplicate addresses on an interface */
@@ -1034,7 +1049,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
1034 ifa->rt = rt; 1049 ifa->rt = rt;
1035 1050
1036 ifa->idev = idev; 1051 ifa->idev = idev;
1037 in6_dev_hold(idev);
1038 /* For caller */ 1052 /* For caller */
1039 in6_ifa_hold(ifa); 1053 in6_ifa_hold(ifa);
1040 1054
@@ -1062,6 +1076,7 @@ out2:
1062 inet6addr_notifier_call_chain(NETDEV_UP, ifa); 1076 inet6addr_notifier_call_chain(NETDEV_UP, ifa);
1063 else { 1077 else {
1064 kfree(ifa); 1078 kfree(ifa);
1079 in6_dev_put(idev);
1065 ifa = ERR_PTR(err); 1080 ifa = ERR_PTR(err);
1066 } 1081 }
1067 1082
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index bfa941fc1165..9e3488d50b15 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -88,6 +88,7 @@ int __ipv6_addr_type(const struct in6_addr *addr)
88EXPORT_SYMBOL(__ipv6_addr_type); 88EXPORT_SYMBOL(__ipv6_addr_type);
89 89
90static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); 90static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
91static ATOMIC_NOTIFIER_HEAD(inet6addr_validator_chain);
91 92
92int register_inet6addr_notifier(struct notifier_block *nb) 93int register_inet6addr_notifier(struct notifier_block *nb)
93{ 94{
@@ -107,6 +108,24 @@ int inet6addr_notifier_call_chain(unsigned long val, void *v)
107} 108}
108EXPORT_SYMBOL(inet6addr_notifier_call_chain); 109EXPORT_SYMBOL(inet6addr_notifier_call_chain);
109 110
111int register_inet6addr_validator_notifier(struct notifier_block *nb)
112{
113 return atomic_notifier_chain_register(&inet6addr_validator_chain, nb);
114}
115EXPORT_SYMBOL(register_inet6addr_validator_notifier);
116
117int unregister_inet6addr_validator_notifier(struct notifier_block *nb)
118{
119 return atomic_notifier_chain_unregister(&inet6addr_validator_chain, nb);
120}
121EXPORT_SYMBOL(unregister_inet6addr_validator_notifier);
122
123int inet6addr_validator_notifier_call_chain(unsigned long val, void *v)
124{
125 return atomic_notifier_call_chain(&inet6addr_validator_chain, val, v);
126}
127EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain);
128
110static int eafnosupport_ipv6_dst_lookup(struct net *net, struct sock *u1, 129static int eafnosupport_ipv6_dst_lookup(struct net *net, struct sock *u1,
111 struct dst_entry **u2, 130 struct dst_entry **u2,
112 struct flowi6 *u3) 131 struct flowi6 *u3)