addrconf.c (56fc709b7a9fe191173dc772a881e180458db517) | addrconf.c (752a92927e97e88096394dac3f10d12a58555254) |
---|---|
1/* 2 * IPv6 Address [auto]configuration 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 8 * --- 942 unchanged lines hidden (view full) --- 951} 952 953static u32 inet6_addr_hash(const struct in6_addr *addr) 954{ 955 return hash_32(ipv6_addr_hash(addr), IN6_ADDR_HSIZE_SHIFT); 956} 957 958static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 1/* 2 * IPv6 Address [auto]configuration 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 8 * --- 942 unchanged lines hidden (view full) --- 951} 952 953static u32 inet6_addr_hash(const struct in6_addr *addr) 954{ 955 return hash_32(ipv6_addr_hash(addr), IN6_ADDR_HSIZE_SHIFT); 956} 957 958static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
959 struct net_device *dev) | 959 struct net_device *dev, unsigned int hash) |
960{ | 960{ |
961 unsigned int hash = inet6_addr_hash(addr); | |
962 struct inet6_ifaddr *ifp; 963 964 hlist_for_each_entry(ifp, &inet6_addr_lst[hash], addr_lst) { 965 if (!net_eq(dev_net(ifp->idev->dev), net)) 966 continue; 967 if (ipv6_addr_equal(&ifp->addr, addr)) { 968 if (!dev || ifp->idev->dev == dev) 969 return true; 970 } 971 } 972 return false; 973} 974 975static int ipv6_add_addr_hash(struct net_device *dev, struct inet6_ifaddr *ifa) 976{ | 961 struct inet6_ifaddr *ifp; 962 963 hlist_for_each_entry(ifp, &inet6_addr_lst[hash], addr_lst) { 964 if (!net_eq(dev_net(ifp->idev->dev), net)) 965 continue; 966 if (ipv6_addr_equal(&ifp->addr, addr)) { 967 if (!dev || ifp->idev->dev == dev) 968 return true; 969 } 970 } 971 return false; 972} 973 974static int ipv6_add_addr_hash(struct net_device *dev, struct inet6_ifaddr *ifa) 975{ |
977 unsigned int hash; | 976 unsigned int hash = inet6_addr_hash(&ifa->addr); |
978 int err = 0; 979 980 spin_lock(&addrconf_hash_lock); 981 982 /* Ignore adding duplicate addresses on an interface */ | 977 int err = 0; 978 979 spin_lock(&addrconf_hash_lock); 980 981 /* Ignore adding duplicate addresses on an interface */ |
983 if (ipv6_chk_same_addr(dev_net(dev), &ifa->addr, dev)) { | 982 if (ipv6_chk_same_addr(dev_net(dev), &ifa->addr, dev, hash)) { |
984 ADBG("ipv6_add_addr: already assigned\n"); 985 err = -EEXIST; | 983 ADBG("ipv6_add_addr: already assigned\n"); 984 err = -EEXIST; |
986 goto out; | 985 } else { 986 hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]); |
987 } 988 | 987 } 988 |
989 /* Add to big hash table */ 990 hash = inet6_addr_hash(&ifa->addr); 991 hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]); 992 993out: | |
994 spin_unlock(&addrconf_hash_lock); 995 996 return err; 997} 998 999/* On success it returns ifp with increased reference count */ 1000 1001static struct inet6_ifaddr * --- 5650 unchanged lines hidden --- | 989 spin_unlock(&addrconf_hash_lock); 990 991 return err; 992} 993 994/* On success it returns ifp with increased reference count */ 995 996static struct inet6_ifaddr * --- 5650 unchanged lines hidden --- |