aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2010-05-18 01:27:12 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-18 01:27:12 -0400
commiteedf042a63ffef050ebc015de19b52dc065e830b (patch)
treefe8a31b4ca2e36de74ce8c6b4ee66ac66deac6da /net/ipv6/addrconf.c
parent820ae8a80eb59962aefbbd4908dfe144ec0f9edb (diff)
ipv6: fix the bug of address check
The duplicate address check code got broken in the conversion to hlist (2.6.35). The earlier patch did not fix the case where two addresses match same hash value. Use two exit paths, rather than depending on state of loop variables (from macro). Based on earlier fix by Shan Wei. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Reviewed-by: Shan Wei <shanwei@cn.fujitsu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3984f52181f4..75d3b8c1e856 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1274,7 +1274,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev)
1274int ipv6_chk_addr(struct net *net, struct in6_addr *addr, 1274int ipv6_chk_addr(struct net *net, struct in6_addr *addr,
1275 struct net_device *dev, int strict) 1275 struct net_device *dev, int strict)
1276{ 1276{
1277 struct inet6_ifaddr *ifp = NULL; 1277 struct inet6_ifaddr *ifp;
1278 struct hlist_node *node; 1278 struct hlist_node *node;
1279 unsigned int hash = ipv6_addr_hash(addr); 1279 unsigned int hash = ipv6_addr_hash(addr);
1280 1280
@@ -1283,15 +1283,16 @@ int ipv6_chk_addr(struct net *net, struct in6_addr *addr,
1283 if (!net_eq(dev_net(ifp->idev->dev), net)) 1283 if (!net_eq(dev_net(ifp->idev->dev), net))
1284 continue; 1284 continue;
1285 if (ipv6_addr_equal(&ifp->addr, addr) && 1285 if (ipv6_addr_equal(&ifp->addr, addr) &&
1286 !(ifp->flags&IFA_F_TENTATIVE)) { 1286 !(ifp->flags&IFA_F_TENTATIVE) &&
1287 if (dev == NULL || ifp->idev->dev == dev || 1287 (dev == NULL || ifp->idev->dev == dev ||
1288 !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) 1288 !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))) {
1289 break; 1289 rcu_read_unlock_bh();
1290 return 1;
1290 } 1291 }
1291 } 1292 }
1292 rcu_read_unlock_bh();
1293 1293
1294 return ifp != NULL; 1294 rcu_read_unlock_bh();
1295 return 0;
1295} 1296}
1296EXPORT_SYMBOL(ipv6_chk_addr); 1297EXPORT_SYMBOL(ipv6_chk_addr);
1297 1298