2019-05-27 09:55:01 +03:00
/* SPDX-License-Identifier: GPL-2.0-or-later */
2005-08-12 16:19:38 +04:00
/*
* INET An implementation of the TCP / IP protocol suite for the LINUX
* operating system . INET is implemented using the BSD Socket
* interface as the means of communication with the user level .
*
* Authors : Lotsa people , from code originally in tcp
*/
# ifndef _INET6_HASHTABLES_H
# define _INET6_HASHTABLES_H
2005-08-12 16:26:18 +04:00
2011-12-10 13:48:31 +04:00
# if IS_ENABLED(CONFIG_IPV6)
2005-08-12 16:26:18 +04:00
# include <linux/in6.h>
# include <linux/ipv6.h>
2005-08-12 16:19:38 +04:00
# include <linux/types.h>
2007-03-23 21:40:27 +03:00
# include <linux/jhash.h>
# include <net/inet_sock.h>
2005-08-12 16:19:38 +04:00
2005-08-12 16:26:18 +04:00
# include <net/ipv6.h>
2008-06-17 04:14:11 +04:00
# include <net/netns/hash.h>
2005-08-12 16:26:18 +04:00
2005-08-12 16:19:38 +04:00
struct inet_hashinfo ;
2013-10-19 23:48:52 +04:00
static inline unsigned int __inet6_ehashfn ( const u32 lhash ,
const u16 lport ,
const u32 fhash ,
const __be16 fport ,
const u32 initval )
2005-08-12 16:26:18 +04:00
{
2013-10-19 23:48:52 +04:00
const u32 ports = ( ( ( u32 ) lport ) < < 16 ) | ( __force u32 ) fport ;
return jhash_3words ( lhash , fhash , ports , initval ) ;
2005-08-12 16:26:18 +04:00
}
/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash , so
* we need not check it for TCP lookups anymore , thanks Alexey . - DaveM
*
* The sockhash lock must be held as a reader here .
*/
2013-09-21 21:22:41 +04:00
struct sock * __inet6_lookup_established ( struct net * net ,
struct inet_hashinfo * hashinfo ,
const struct in6_addr * saddr ,
const __be16 sport ,
const struct in6_addr * daddr ,
2017-08-07 18:44:21 +03:00
const u16 hnum , const int dif ,
const int sdif ) ;
2013-09-21 21:22:41 +04:00
struct sock * inet6_lookup_listener ( struct net * net ,
struct inet_hashinfo * hashinfo ,
2016-02-10 19:50:38 +03:00
struct sk_buff * skb , int doff ,
2013-09-21 21:22:41 +04:00
const struct in6_addr * saddr ,
const __be16 sport ,
const struct in6_addr * daddr ,
2017-08-07 18:44:21 +03:00
const unsigned short hnum ,
const int dif , const int sdif ) ;
2005-08-12 16:26:18 +04:00
2008-01-31 16:07:21 +03:00
static inline struct sock * __inet6_lookup ( struct net * net ,
struct inet_hashinfo * hashinfo ,
2016-02-10 19:50:38 +03:00
struct sk_buff * skb , int doff ,
2005-08-12 16:26:18 +04:00
const struct in6_addr * saddr ,
2006-11-08 11:20:00 +03:00
const __be16 sport ,
2005-08-12 16:26:18 +04:00
const struct in6_addr * daddr ,
const u16 hnum ,
2017-08-07 18:44:21 +03:00
const int dif , const int sdif ,
2016-04-01 18:52:17 +03:00
bool * refcounted )
2005-08-12 16:26:18 +04:00
{
2008-01-31 16:07:21 +03:00
struct sock * sk = __inet6_lookup_established ( net , hashinfo , saddr ,
2017-08-07 18:44:21 +03:00
sport , daddr , hnum ,
dif , sdif ) ;
2016-04-01 18:52:17 +03:00
* refcounted = true ;
2005-08-12 16:26:18 +04:00
if ( sk )
return sk ;
2016-04-01 18:52:17 +03:00
* refcounted = false ;
2016-02-10 19:50:38 +03:00
return inet6_lookup_listener ( net , hashinfo , skb , doff , saddr , sport ,
2017-08-07 18:44:21 +03:00
daddr , hnum , dif , sdif ) ;
2005-08-12 16:26:18 +04:00
}
2008-10-07 22:41:57 +04:00
static inline struct sock * __inet6_lookup_skb ( struct inet_hashinfo * hashinfo ,
2016-02-10 19:50:38 +03:00
struct sk_buff * skb , int doff ,
2008-10-07 22:41:57 +04:00
const __be16 sport ,
2014-10-17 20:17:20 +04:00
const __be16 dport ,
2017-08-07 18:44:21 +03:00
int iif , int sdif ,
2016-04-01 18:52:17 +03:00
bool * refcounted )
2008-10-07 22:41:57 +04:00
{
2020-03-30 01:53:39 +03:00
struct sock * sk = skb_steal_sock ( skb , refcounted ) ;
2008-10-07 23:41:01 +04:00
2012-07-26 16:18:11 +04:00
if ( sk )
2008-10-07 23:41:01 +04:00
return sk ;
2012-07-26 16:18:11 +04:00
2016-02-10 19:50:38 +03:00
return __inet6_lookup ( dev_net ( skb_dst ( skb ) - > dev ) , hashinfo , skb ,
doff , & ipv6_hdr ( skb ) - > saddr , sport ,
2012-07-26 16:18:11 +04:00
& ipv6_hdr ( skb ) - > daddr , ntohs ( dport ) ,
2017-08-07 18:44:21 +03:00
iif , sdif , refcounted ) ;
2008-10-07 22:41:57 +04:00
}
2013-09-21 21:22:41 +04:00
struct sock * inet6_lookup ( struct net * net , struct inet_hashinfo * hashinfo ,
2016-02-10 19:50:38 +03:00
struct sk_buff * skb , int doff ,
2013-09-21 21:22:41 +04:00
const struct in6_addr * saddr , const __be16 sport ,
const struct in6_addr * daddr , const __be16 dport ,
const int dif ) ;
2016-02-10 19:50:36 +03:00
int inet6_hash ( struct sock * sk ) ;
2014-11-04 21:59:47 +03:00
2022-05-13 21:55:49 +03:00
static inline bool inet6_match ( struct net * net , const struct sock * sk ,
const struct in6_addr * saddr ,
const struct in6_addr * daddr ,
const __portpair ports ,
const int dif , const int sdif )
{
int bound_dev_if ;
if ( ! net_eq ( sock_net ( sk ) , net ) | |
sk - > sk_family ! = AF_INET6 | |
sk - > sk_portpair ! = ports | |
! ipv6_addr_equal ( & sk - > sk_v6_daddr , saddr ) | |
! ipv6_addr_equal ( & sk - > sk_v6_rcv_saddr , daddr ) )
return false ;
bound_dev_if = READ_ONCE ( sk - > sk_bound_dev_if ) ;
return bound_dev_if = = dif | | bound_dev_if = = sdif ;
}
# endif /* IS_ENABLED(CONFIG_IPV6) */
2014-11-04 21:59:47 +03:00
2005-08-12 16:19:38 +04:00
# endif /* _INET6_HASHTABLES_H */