forked from mirrors/linux
		
	RDMA/core Introduce and use rdma_find_ndev_for_src_ip_rcu
This fixes two issues: 1. When address family is other than IPv4 or v6, rdma_translate_ip() returns success which is incorrect. 2. When address familty is AF_INET6, and if the source address is not found, it returns success, which is also incorrect. Therefore, introduce and use rdma_find_ndev_for_src_ip_rcu() helper function which returns correct success or error status and is also useful for future code refactor in addr_resolve(). Signed-off-by: Parav Pandit <parav@mellanox.com> Reviewed-by: Daniel Jurgens <danielj@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
		
							parent
							
								
									99ed748e87
								
							
						
					
					
						commit
						caf1e3ae9f
					
				
					 1 changed files with 35 additions and 26 deletions
				
			
		| 
						 | 
					@ -232,6 +232,36 @@ void rdma_copy_addr(struct rdma_dev_addr *dev_addr,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(rdma_copy_addr);
 | 
					EXPORT_SYMBOL(rdma_copy_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct net_device *
 | 
				
			||||||
 | 
					rdma_find_ndev_for_src_ip_rcu(struct net *net, const struct sockaddr *src_in)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct net_device *dev = NULL;
 | 
				
			||||||
 | 
						int ret = -EADDRNOTAVAIL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (src_in->sa_family) {
 | 
				
			||||||
 | 
						case AF_INET:
 | 
				
			||||||
 | 
							dev = __ip_dev_find(net,
 | 
				
			||||||
 | 
									    ((const struct sockaddr_in *)src_in)->sin_addr.s_addr,
 | 
				
			||||||
 | 
									    false);
 | 
				
			||||||
 | 
							if (dev)
 | 
				
			||||||
 | 
								ret = 0;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					#if IS_ENABLED(CONFIG_IPV6)
 | 
				
			||||||
 | 
						case AF_INET6:
 | 
				
			||||||
 | 
							for_each_netdev_rcu(net, dev) {
 | 
				
			||||||
 | 
								if (ipv6_chk_addr(net,
 | 
				
			||||||
 | 
										  &((const struct sockaddr_in6 *)src_in)->sin6_addr,
 | 
				
			||||||
 | 
										  dev, 1)) {
 | 
				
			||||||
 | 
									ret = 0;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret ? ERR_PTR(ret) : dev;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int rdma_translate_ip(const struct sockaddr *addr,
 | 
					int rdma_translate_ip(const struct sockaddr *addr,
 | 
				
			||||||
		      struct rdma_dev_addr *dev_addr)
 | 
							      struct rdma_dev_addr *dev_addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -246,33 +276,12 @@ int rdma_translate_ip(const struct sockaddr *addr,
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (addr->sa_family) {
 | 
					 | 
				
			||||||
	case AF_INET:
 | 
					 | 
				
			||||||
		dev = ip_dev_find(dev_addr->net,
 | 
					 | 
				
			||||||
			((const struct sockaddr_in *)addr)->sin_addr.s_addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (!dev)
 | 
					 | 
				
			||||||
			return -EADDRNOTAVAIL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		rdma_copy_addr(dev_addr, dev, NULL);
 | 
					 | 
				
			||||||
		dev_put(dev);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#if IS_ENABLED(CONFIG_IPV6)
 | 
					 | 
				
			||||||
	case AF_INET6:
 | 
					 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
		for_each_netdev_rcu(dev_addr->net, dev) {
 | 
						dev = rdma_find_ndev_for_src_ip_rcu(dev_addr->net, addr);
 | 
				
			||||||
			if (ipv6_chk_addr(dev_addr->net,
 | 
						if (!IS_ERR(dev))
 | 
				
			||||||
					  &((const struct sockaddr_in6 *)addr)->sin6_addr,
 | 
					 | 
				
			||||||
					  dev, 1)) {
 | 
					 | 
				
			||||||
		rdma_copy_addr(dev_addr, dev, NULL);
 | 
							rdma_copy_addr(dev_addr, dev, NULL);
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
		break;
 | 
						return PTR_ERR_OR_ZERO(dev);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(rdma_translate_ip);
 | 
					EXPORT_SYMBOL(rdma_translate_ip);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue