aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ipvlan/ipvlan_main.c
diff options
context:
space:
mode:
authorKrister Johansen <kjlx@templeofstupid.com>2017-06-08 16:12:14 -0400
committerDavid S. Miller <davem@davemloft.net>2017-06-09 12:26:07 -0400
commit3ad7d2468f79fc13215eb941f766a692d34b1381 (patch)
tree5a742b551c95c8587e40bb5421c214e76d78c5d8 /drivers/net/ipvlan/ipvlan_main.c
parent2b3a9afc63ab6af58417b3aaca2746dee2fbdc86 (diff)
Ipvlan should return an error when an address is already in use.
The ipvlan code already knows how to detect when a duplicate address is about to be assigned to an ipvlan device. However, that failure is not propogated outward and leads to a silent failure. Introduce a validation step at ip address creation time and allow device drivers to register to validate the incoming ip addresses. The ipvlan code is the first consumer. If it detects an address in use, we can return an error to the user before beginning to commit the new ifa in the networking code. This can be especially useful if it is necessary to provision many ipvlans in containers. The provisioning software (or operator) can use this to detect situations where an ip address is unexpectedly in use. Signed-off-by: Krister Johansen <kjlx@templeofstupid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ipvlan/ipvlan_main.c')
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c69
1 files changed, 69 insertions, 0 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);