summaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c17
1 files changed, 16 insertions, 1 deletions
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