/* * 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 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #ifndef _INET_HASHTABLES_H #define _INET_HASHTABLES_H #include <linux/interrupt.h> #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/list.h> #include <linux/slab.h> #include <linux/socket.h> #include <linux/spinlock.h> #include <linux/types.h> #include <linux/wait.h> #include <net/inet_connection_sock.h> #include <net/inet_sock.h> #include <net/sock.h> #include <net/route.h> #include <net/tcp_states.h> #include <net/netns/hash.h> #include <linux/refcount.h> #include <asm/byteorder.h> /* This is for all connections with a full identity, no wildcards. * The 'e' prefix stands for Establish, but we really put all sockets * but LISTEN ones. */ struct inet_ehash_bucket { struct hlist_nulls_head chain; }; /* There are a few simple rules, which allow for local port reuse by * an application. In essence: * * 1) Sockets bound to different interfaces may share a local port. * Failing that, goto test 2. * 2) If all sockets have sk->sk_reuse set, and none of them are in * TCP_LISTEN state, the port may be shared. * Failing that, goto test 3. * 3) If all sockets are bound to a specific inet_sk(sk)->rcv_saddr local * address, and none of them are the same, the port may be * shared. * Failing this, the port cannot be shared. * * The interesting point, is test #2. This is what an FTP server does * all day. To optimize this case we use a specific flag bit defined * below. As we add sockets to a bind bucket list, we perform a * check of: (newsk->sk_reuse && (newsk->sk_state != TCP_LISTEN)) * As long as all sockets added to a bind bucket pass this test, * the flag bit will be set. * The resulting situation is that tcp_v[46]_verify_bind() can just check * for this flag bit, if it is set and the socket trying to bind has * sk->sk_reuse set, we don't even have to walk the owners list at all, * we return that it is ok to bind this socket to the requested local port. * * Sounds like a lot of work, but it is worth it. In a more naive * implementation (ie. current FreeBSD etc.) the entire list of ports * must be walked for each data port opened by an ftp server. Needless * to say, this does not scale at all. With a couple thousand FTP * users logged onto your box, isn't it nice to know that new data * ports are created in O(1) time? I thought so. ;-) -DaveM */ #define FASTREUSEPORT_ANY 1 #define FASTREUSEPORT_STRICT 2 struct inet_bind_bucket { possible_net_t ib_net; unsigned short port; signed char fastreuse; signed char fastreuseport; kuid_t fastuid; #if IS_ENABLED(CONFIG_IPV6) struct in6_addr fast_v6_rcv_saddr; #endif __be32 fast_rcv_saddr; unsigned short fast_sk_family; bool fast_ipv6_only; struct hlist_node node; struct hlist_head owners; }; static inline struct net *ib_net(struct inet_bind_bucket *ib) { return read_pnet(&ib->ib_net); } #define inet_bind_bucket_for_each(tb, head) \ hlist_for_each_entry(tb, head, node) struct inet_bind_hashbucket { spinlock_t lock; struct hlist_head chain; }; /* Sockets can be hashed in established or listening table. * We must use different 'nulls' end-of-chain value for all hash buckets : * A socket might transition from ESTABLISH to LISTEN state without * RCU grace period. A lookup in ehash table needs to handle this case. */ #define LISTENING_NULLS_BASE (1U << 29) struct inet_listen_hashbucket { spinlock_t lock; union { struct hlist_head head; struct hlist_nulls_head nulls_head; }; }; /* This is for listening sockets, thus all sockets which possess wildcards. */ #define INET_LHTABLE_SIZE 32 /* Yes, really, this is all you need. */ struct inet_hashinfo { /* This is for sockets with full identity only. Sockets here will * always be without wildcards and will have the following invariant: * * TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE * */ struct inet_ehash_bucket *ehash; spinlock_t *ehash_locks; unsigned int ehash_mask; unsigned int ehash_locks_mask; /* Ok, let's try this, I give up, we do need a local binding * TCP hash as well as the others for fast bind/connect. */ struct inet_bind_hashbucket *bhash; unsigned int bhash_size; /* 4 bytes hole on 64 bit */ struct kmem_cache *bind_bucket_cachep; /* All the above members are written once at bootup and * never written again _or_ are predominantly read-access. * * Now align to a new cache line as all the following members * might be often dirty. */ /* All sockets in TCP_LISTEN state will be in here. This is the only * table where wildcard'd TCP sockets can exist. Hash function here * is just local port number. */ struct inet_listen_hashbucket listening_hash[INET_LHTABLE_SIZE] ____cacheline_aligned_in_smp; }; static inline struct inet_ehash_bucket *inet_ehash_bucket( struct inet_hashinfo *hashinfo, unsigned int hash) { return &hashinfo->ehash[hash & hashinfo->ehash_mask]; } static inline spinlock_t *inet_ehash_lockp( struct inet_hashinfo *hashinfo, unsigned int hash) { return &hashinfo->ehash_locks[hash & hashinfo->ehash_locks_mask]; } int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo); static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo) { kvfree(hashinfo->ehash_locks); hashinfo->ehash_locks = NULL; } struct inet_bind_bucket * inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net, struct inet_bind_hashbucket *head, const unsigned short snum); void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket *tb); static inline u32 inet_bhashfn(const struct net *net, const __u16 lport, const u32 bhash_size) { return (lport + net_hash_mix(net)) & (bhash_size - 1); } void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, const unsigned short snum); /* These can have wildcards, don't try too hard. */ static inline u32 inet_lhashfn(const struct net *net, const unsigned short num) { return (num + net_hash_mix(net)) & (INET_LHTABLE_SIZE - 1); } static inline int inet_sk_listen_hashfn(const struct sock *sk) { return inet_lhashfn(sock_net(sk), inet_sk(sk)->inet_num); } /* Caller must disable local BH processing. */ int __inet_inherit_port(const struct sock *sk, struct sock *child); void inet_put_port(struct sock *sk); void inet_hashinfo_init(struct inet_hashinfo *h); bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk); bool inet_ehash_nolisten(struct sock *sk, struct sock *osk, bool *found_dup_sk); int __inet_hash(struct sock *sk, struct sock *osk); int inet_hash(struct sock *sk); void inet_unhash(struct sock *sk); struct sock *__inet_lookup_listener(struct net *net, struct inet_hashinfo *hashinfo, struct sk_buff *skb, int doff, const __be32 saddr, const __be16 sport, const __be32 daddr, const unsigned short hnum, const int dif, const int sdif); static inline struct sock *inet_lookup_listener(struct net *net, struct inet_hashinfo *hashinfo, struct sk_buff *skb, int doff, __be32 saddr, __be16 sport, __be32 daddr, __be16 dport, int dif, int sdif) { return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, sport, daddr, ntohs(dport), dif, sdif); } /* Socket demux engine toys. */ /* What happens here is ugly; there's a pair of adjacent fields in struct inet_sock; __be16 dport followed by __u16 num. We want to search by pair, so we combine the keys into a single 32bit value and compare with 32bit value read from &...->dport. Let's at least make sure that it's not mixed with anything else... On 64bit targets we combine comparisons with pair of adjacent __be32 fields in the same way. */ #ifdef __BIG_ENDIAN #define INET_COMBINED_PORTS(__sport, __dport) \ ((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport))) #else /* __LITTLE_ENDIAN */ #define INET_COMBINED_PORTS(__sport, __dport) \ ((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport))) #endif #if (BITS_PER_LONG == 64) #ifdef __BIG_ENDIAN #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ const __addrpair __name = (__force __addrpair) ( \ (((__force __u64)(__be32)(__saddr)) << 32) | \ ((__force __u64)(__be32)(__daddr))) #else /* __LITTLE_ENDIAN */ #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ const __addrpair __name = (__force __addrpair) ( \ (((__force __u64)(__be32)(__daddr)) << 32) | \ ((__force __u64)(__be32)(__saddr))) #endif /* __BIG_ENDIAN */ #define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \ (((__sk)->sk_portpair == (__ports)) && \ ((__sk)->sk_addrpair == (__cookie)) && \ (!(__sk)->sk_bound_dev_if || \ ((__sk)->sk_bound_dev_if == (__dif)) || \ ((__sk)->sk_bound_dev_if == (__sdif))) && \ net_eq(sock_net(__sk), (__net))) #else /* 32-bit arch */ #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ const int __name __deprecated __attribute__((unused)) #define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \ (((__sk)->sk_portpair == (__ports)) && \ ((__sk)->sk_daddr == (__saddr)) && \ ((__sk)->sk_rcv_saddr == (__daddr)) && \ (!(__sk)->sk_bound_dev_if || \ ((__sk)->sk_bound_dev_if == (__dif)) || \ ((__sk)->sk_bound_dev_if == (__sdif))) && \ net_eq(sock_net(__sk), (__net))) #endif /* 64-bit arch */ /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need * not check it for lookups anymore, thanks Alexey. -DaveM */ struct sock *__inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo, const __be32 saddr, const __be16 sport, const __be32 daddr, const u16 hnum, const int dif, const int sdif); static inline struct sock * inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo, const __be32 saddr, const __be16 sport, const __be32 daddr, const __be16 dport, const int dif) { return __inet_lookup_established(net, hashinfo, saddr, sport, daddr, ntohs(dport), dif, 0); } static inline struct sock *__inet_lookup(struct net *net, struct inet_hashinfo *hashinfo, struct sk_buff *skb, int doff, const __be32 saddr, const __be16 sport, const __be32 daddr, const __be16 dport, const int dif, const int sdif, bool *refcounted) { u16 hnum = ntohs(dport); struct sock *sk; sk = __inet_lookup_established(net, hashinfo, saddr, sport, daddr, hnum, dif, sdif); *refcounted = true; if (sk) return sk; *refcounted = false; return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, sport, daddr, hnum, dif, sdif); } static inline struct sock *inet_lookup(struct net *net, struct inet_hashinfo *hashinfo, struct sk_buff *skb, int doff, const __be32 saddr, const __be16 sport, const __be32 daddr, const __be16 dport, const int dif) { struct sock *sk; bool refcounted; sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, dport, dif, 0, &refcounted); if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt)) sk = NULL; return sk; } static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo, struct sk_buff *skb, int doff, const __be16 sport, const __be16 dport, const int sdif, bool *refcounted) { struct sock *sk = skb_steal_sock(skb); const struct iphdr *iph = ip_hdr(skb); *refcounted = true; if (sk) return sk; return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb, doff, iph->saddr, sport, iph->daddr, dport, inet_iif(skb), sdif, refcounted); } u32 inet6_ehashfn(const struct net *net, const struct in6_addr *laddr, const u16 lport, const struct in6_addr *faddr, const __be16 fport); static inline void sk_daddr_set(struct sock *sk, __be32 addr) { sk->sk_daddr = addr; /* alias of inet_daddr */ #if IS_ENABLED(CONFIG_IPV6) ipv6_addr_set_v4mapped(addr, &sk->sk_v6_daddr); #endif } static inline void sk_rcv_saddr_set(struct sock *sk, __be32 addr) { sk->sk_rcv_saddr = addr; /* alias of inet_rcv_saddr */ #if IS_ENABLED(CONFIG_IPV6) ipv6_addr_set_v4mapped(addr, &sk->sk_v6_rcv_saddr); #endif } int __inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk, u64 port_offset, int (*check_established)(struct inet_timewait_death_row *, struct sock *, __u16, struct inet_timewait_sock **)); int inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk); #endif /* _INET_HASHTABLES_H */
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
9p | Folder | 0755 |
|
|
bluetooth | Folder | 0755 |
|
|
caif | Folder | 0755 |
|
|
iucv | Folder | 0755 |
|
|
netfilter | Folder | 0755 |
|
|
netns | Folder | 0755 |
|
|
nfc | Folder | 0755 |
|
|
phonet | Folder | 0755 |
|
|
sctp | Folder | 0755 |
|
|
tc_act | Folder | 0755 |
|
|
6lowpan.h | File | 10.03 KB | 0644 |
|
Space.h | File | 1.15 KB | 0644 |
|
act_api.h | File | 6.38 KB | 0644 |
|
addrconf.h | File | 12.63 KB | 0644 |
|
af_ieee802154.h | File | 1.55 KB | 0644 |
|
af_rxrpc.h | File | 2.79 KB | 0644 |
|
af_unix.h | File | 2.22 KB | 0644 |
|
af_vsock.h | File | 7.21 KB | 0644 |
|
ah.h | File | 382 B | 0644 |
|
arp.h | File | 2 KB | 0644 |
|
atmclip.h | File | 1.48 KB | 0644 |
|
ax25.h | File | 15.02 KB | 0644 |
|
ax88796.h | File | 998 B | 0644 |
|
bond_3ad.h | File | 9.79 KB | 0644 |
|
bond_alb.h | File | 6.6 KB | 0644 |
|
bond_options.h | File | 3.92 KB | 0644 |
|
bonding.h | File | 19.1 KB | 0644 |
|
busy_poll.h | File | 3.8 KB | 0644 |
|
calipso.h | File | 2.15 KB | 0644 |
|
cfg80211-wext.h | File | 1.95 KB | 0644 |
|
cfg80211.h | File | 221.24 KB | 0644 |
|
cfg802154.h | File | 10.89 KB | 0644 |
|
checksum.h | File | 4.76 KB | 0644 |
|
cipso_ipv4.h | File | 8.2 KB | 0644 |
|
cls_cgroup.h | File | 2.15 KB | 0644 |
|
codel.h | File | 5.65 KB | 0644 |
|
codel_impl.h | File | 7.98 KB | 0644 |
|
codel_qdisc.h | File | 2.9 KB | 0644 |
|
compat.h | File | 2.11 KB | 0644 |
|
datalink.h | File | 619 B | 0644 |
|
dcbevent.h | File | 1.26 KB | 0644 |
|
dcbnl.h | File | 4.2 KB | 0644 |
|
devlink.h | File | 13.25 KB | 0644 |
|
dn.h | File | 6.88 KB | 0644 |
|
dn_dev.h | File | 5.36 KB | 0644 |
|
dn_fib.h | File | 3.98 KB | 0644 |
|
dn_neigh.h | File | 968 B | 0644 |
|
dn_nsp.h | File | 5.83 KB | 0644 |
|
dn_route.h | File | 4.36 KB | 0644 |
|
dsa.h | File | 13.94 KB | 0644 |
|
dsfield.h | File | 1.11 KB | 0644 |
|
dst.h | File | 13.48 KB | 0644 |
|
dst_cache.h | File | 2.53 KB | 0644 |
|
dst_metadata.h | File | 5.39 KB | 0644 |
|
dst_ops.h | File | 2 KB | 0644 |
|
erspan.h | File | 2.11 KB | 0644 |
|
esp.h | File | 877 B | 0644 |
|
ethoc.h | File | 538 B | 0644 |
|
fib_notifier.h | File | 1.29 KB | 0644 |
|
fib_rules.h | File | 4.18 KB | 0644 |
|
firewire.h | File | 636 B | 0644 |
|
flow.h | File | 6.16 KB | 0644 |
|
flow_dissector.h | File | 7.55 KB | 0644 |
|
fou.h | File | 549 B | 0644 |
|
fq.h | File | 2.67 KB | 0644 |
|
fq_impl.h | File | 6.9 KB | 0644 |
|
garp.h | File | 2.62 KB | 0644 |
|
gen_stats.h | File | 2.34 KB | 0644 |
|
genetlink.h | File | 11.3 KB | 0644 |
|
geneve.h | File | 1.67 KB | 0644 |
|
gre.h | File | 2.99 KB | 0644 |
|
gro_cells.h | File | 443 B | 0644 |
|
gtp.h | File | 633 B | 0644 |
|
gue.h | File | 3.23 KB | 0644 |
|
hwbm.h | File | 937 B | 0644 |
|
icmp.h | File | 2.01 KB | 0644 |
|
ieee80211_radiotap.h | File | 6.63 KB | 0644 |
|
ieee802154_netdev.h | File | 9.14 KB | 0644 |
|
if_inet6.h | File | 6.13 KB | 0644 |
|
ife.h | File | 1.06 KB | 0644 |
|
ila.h | File | 498 B | 0644 |
|
inet6_connection_sock.h | File | 976 B | 0644 |
|
inet6_hashtables.h | File | 3.7 KB | 0644 |
|
inet_common.h | File | 1.89 KB | 0644 |
|
inet_connection_sock.h | File | 10.48 KB | 0644 |
|
inet_ecn.h | File | 6.02 KB | 0644 |
|
inet_frag.h | File | 4.51 KB | 0644 |
|
inet_hashtables.h | File | 12.91 KB | 0644 |
|
inet_sock.h | File | 8.25 KB | 0644 |
|
inet_timewait_sock.h | File | 3.82 KB | 0644 |
|
inetpeer.h | File | 3.29 KB | 0644 |
|
ip.h | File | 18.51 KB | 0644 |
|
ip6_checksum.h | File | 2.89 KB | 0644 |
|
ip6_fib.h | File | 10.04 KB | 0644 |
|
ip6_route.h | File | 7.63 KB | 0644 |
|
ip6_tunnel.h | File | 4.72 KB | 0644 |
|
ip_fib.h | File | 10.72 KB | 0644 |
|
ip_tunnels.h | File | 13.61 KB | 0644 |
|
ip_vs.h | File | 46.78 KB | 0644 |
|
ipcomp.h | File | 659 B | 0644 |
|
ipconfig.h | File | 811 B | 0644 |
|
ipv6.h | File | 29.97 KB | 0644 |
|
ipv6_frag.h | File | 2.54 KB | 0644 |
|
ipx.h | File | 4.4 KB | 0644 |
|
iw_handler.h | File | 20.91 KB | 0644 |
|
kcm.h | File | 4.96 KB | 0644 |
|
l3mdev.h | File | 5.86 KB | 0644 |
|
lapb.h | File | 4.75 KB | 0644 |
|
lib80211.h | File | 3.92 KB | 0644 |
|
llc.h | File | 4.41 KB | 0644 |
|
llc_c_ac.h | File | 9.31 KB | 0644 |
|
llc_c_ev.h | File | 10.68 KB | 0644 |
|
llc_c_st.h | File | 1.72 KB | 0644 |
|
llc_conn.h | File | 4.06 KB | 0644 |
|
llc_if.h | File | 2.16 KB | 0644 |
|
llc_pdu.h | File | 14.44 KB | 0644 |
|
llc_s_ac.h | File | 1.55 KB | 0644 |
|
llc_s_ev.h | File | 2.2 KB | 0644 |
|
llc_s_st.h | File | 947 B | 0644 |
|
llc_sap.h | File | 1.08 KB | 0644 |
|
lwtunnel.h | File | 5.84 KB | 0644 |
|
mac80211.h | File | 230.36 KB | 0644 |
|
mac802154.h | File | 15.27 KB | 0644 |
|
mip6.h | File | 1.58 KB | 0644 |
|
mld.h | File | 2.8 KB | 0644 |
|
mpls.h | File | 932 B | 0644 |
|
mpls_iptunnel.h | File | 827 B | 0644 |
|
mrp.h | File | 3.03 KB | 0644 |
|
ncsi.h | File | 1.92 KB | 0644 |
|
ndisc.h | File | 13.77 KB | 0644 |
|
neighbour.h | File | 15.06 KB | 0644 |
|
net_namespace.h | File | 10.08 KB | 0644 |
|
net_ratelimit.h | File | 220 B | 0644 |
|
netevent.h | File | 910 B | 0644 |
|
netlabel.h | File | 20.74 KB | 0644 |
|
netlink.h | File | 40.39 KB | 0644 |
|
netprio_cgroup.h | File | 1.24 KB | 0644 |
|
netrom.h | File | 7.68 KB | 0644 |
|
nexthop.h | File | 865 B | 0644 |
|
nl802154.h | File | 12.09 KB | 0644 |
|
nsh.h | File | 12.31 KB | 0644 |
|
p8022.h | File | 447 B | 0644 |
|
ping.h | File | 3.45 KB | 0644 |
|
pkt_cls.h | File | 17.34 KB | 0644 |
|
pkt_sched.h | File | 4.05 KB | 0644 |
|
pptp.h | File | 557 B | 0644 |
|
protocol.h | File | 4.08 KB | 0644 |
|
psample.h | File | 860 B | 0644 |
|
psnap.h | File | 351 B | 0644 |
|
raw.h | File | 2.07 KB | 0644 |
|
rawv6.h | File | 854 B | 0644 |
|
red.h | File | 10.45 KB | 0644 |
|
regulatory.h | File | 10.12 KB | 0644 |
|
request_sock.h | File | 6.46 KB | 0644 |
|
rose.h | File | 7.62 KB | 0644 |
|
route.h | File | 10.02 KB | 0644 |
|
rtnetlink.h | File | 6.13 KB | 0644 |
|
sch_generic.h | File | 23.3 KB | 0644 |
|
scm.h | File | 3.5 KB | 0644 |
|
secure_seq.h | File | 855 B | 0644 |
|
seg6.h | File | 1.66 KB | 0644 |
|
seg6_hmac.h | File | 1.65 KB | 0644 |
|
slhc_vj.h | File | 6.67 KB | 0644 |
|
smc.h | File | 440 B | 0644 |
|
snmp.h | File | 5.23 KB | 0644 |
|
sock.h | File | 69.75 KB | 0644 |
|
sock_reuseport.h | File | 863 B | 0644 |
|
stp.h | File | 383 B | 0644 |
|
strparser.h | File | 3.75 KB | 0644 |
|
switchdev.h | File | 6.52 KB | 0644 |
|
tcp.h | File | 62.8 KB | 0644 |
|
tcp_states.h | File | 1.26 KB | 0644 |
|
timewait_sock.h | File | 1.11 KB | 0644 |
|
tipc.h | File | 2.34 KB | 0644 |
|
tls.h | File | 7.12 KB | 0644 |
|
transp_v6.h | File | 2.08 KB | 0644 |
|
tso.h | File | 515 B | 0644 |
|
tun_proto.h | File | 988 B | 0644 |
|
udp.h | File | 12.82 KB | 0644 |
|
udp_tunnel.h | File | 5.12 KB | 0644 |
|
udplite.h | File | 3.83 KB | 0644 |
|
vsock_addr.h | File | 1.05 KB | 0644 |
|
vxlan.h | File | 10.43 KB | 0644 |
|
wext.h | File | 1.51 KB | 0644 |
|
wimax.h | File | 19.97 KB | 0644 |
|
x25.h | File | 9.43 KB | 0644 |
|
x25device.h | File | 387 B | 0644 |
|
xfrm.h | File | 53.72 KB | 0644 |
|