xref: /openbmc/linux/net/ipv6/inet6_connection_sock.c (revision ca304b6104ffdd120bb6687a88a0625e58bc71cd)
18129765aSArnaldo Carvalho de Melo /*
28129765aSArnaldo Carvalho de Melo  * INET        An implementation of the TCP/IP protocol suite for the LINUX
38129765aSArnaldo Carvalho de Melo  *             operating system.  INET is implemented using the  BSD Socket
48129765aSArnaldo Carvalho de Melo  *             interface as the means of communication with the user level.
58129765aSArnaldo Carvalho de Melo  *
68129765aSArnaldo Carvalho de Melo  *             Support for INET6 connection oriented protocols.
78129765aSArnaldo Carvalho de Melo  *
88129765aSArnaldo Carvalho de Melo  * Authors:    See the TCPv6 sources
98129765aSArnaldo Carvalho de Melo  *
108129765aSArnaldo Carvalho de Melo  *             This program is free software; you can redistribute it and/or
118129765aSArnaldo Carvalho de Melo  *             modify it under the terms of the GNU General Public License
128129765aSArnaldo Carvalho de Melo  *             as published by the Free Software Foundation; either version
138129765aSArnaldo Carvalho de Melo  *             2 of the License, or(at your option) any later version.
148129765aSArnaldo Carvalho de Melo  */
158129765aSArnaldo Carvalho de Melo 
168129765aSArnaldo Carvalho de Melo #include <linux/config.h>
178129765aSArnaldo Carvalho de Melo #include <linux/module.h>
188129765aSArnaldo Carvalho de Melo #include <linux/in6.h>
198129765aSArnaldo Carvalho de Melo #include <linux/ipv6.h>
208129765aSArnaldo Carvalho de Melo #include <linux/jhash.h>
218129765aSArnaldo Carvalho de Melo 
228129765aSArnaldo Carvalho de Melo #include <net/addrconf.h>
238129765aSArnaldo Carvalho de Melo #include <net/inet_connection_sock.h>
248129765aSArnaldo Carvalho de Melo #include <net/sock.h>
258129765aSArnaldo Carvalho de Melo 
268129765aSArnaldo Carvalho de Melo /*
278129765aSArnaldo Carvalho de Melo  * request_sock (formerly open request) hash tables.
288129765aSArnaldo Carvalho de Melo  */
298129765aSArnaldo Carvalho de Melo static u32 inet6_synq_hash(const struct in6_addr *raddr, const u16 rport,
308129765aSArnaldo Carvalho de Melo 			   const u32 rnd, const u16 synq_hsize)
318129765aSArnaldo Carvalho de Melo {
328129765aSArnaldo Carvalho de Melo 	u32 a = raddr->s6_addr32[0];
338129765aSArnaldo Carvalho de Melo 	u32 b = raddr->s6_addr32[1];
348129765aSArnaldo Carvalho de Melo 	u32 c = raddr->s6_addr32[2];
358129765aSArnaldo Carvalho de Melo 
368129765aSArnaldo Carvalho de Melo 	a += JHASH_GOLDEN_RATIO;
378129765aSArnaldo Carvalho de Melo 	b += JHASH_GOLDEN_RATIO;
388129765aSArnaldo Carvalho de Melo 	c += rnd;
398129765aSArnaldo Carvalho de Melo 	__jhash_mix(a, b, c);
408129765aSArnaldo Carvalho de Melo 
418129765aSArnaldo Carvalho de Melo 	a += raddr->s6_addr32[3];
428129765aSArnaldo Carvalho de Melo 	b += (u32)rport;
438129765aSArnaldo Carvalho de Melo 	__jhash_mix(a, b, c);
448129765aSArnaldo Carvalho de Melo 
458129765aSArnaldo Carvalho de Melo 	return c & (synq_hsize - 1);
468129765aSArnaldo Carvalho de Melo }
478129765aSArnaldo Carvalho de Melo 
488129765aSArnaldo Carvalho de Melo struct request_sock *inet6_csk_search_req(const struct sock *sk,
498129765aSArnaldo Carvalho de Melo 					  struct request_sock ***prevp,
508129765aSArnaldo Carvalho de Melo 					  const __u16 rport,
518129765aSArnaldo Carvalho de Melo 					  const struct in6_addr *raddr,
528129765aSArnaldo Carvalho de Melo 					  const struct in6_addr *laddr,
538129765aSArnaldo Carvalho de Melo 					  const int iif)
548129765aSArnaldo Carvalho de Melo {
558129765aSArnaldo Carvalho de Melo 	const struct inet_connection_sock *icsk = inet_csk(sk);
568129765aSArnaldo Carvalho de Melo 	struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
578129765aSArnaldo Carvalho de Melo 	struct request_sock *req, **prev;
588129765aSArnaldo Carvalho de Melo 
598129765aSArnaldo Carvalho de Melo 	for (prev = &lopt->syn_table[inet6_synq_hash(raddr, rport,
608129765aSArnaldo Carvalho de Melo 						     lopt->hash_rnd,
618129765aSArnaldo Carvalho de Melo 						     lopt->nr_table_entries)];
628129765aSArnaldo Carvalho de Melo 	     (req = *prev) != NULL;
638129765aSArnaldo Carvalho de Melo 	     prev = &req->dl_next) {
64*ca304b61SArnaldo Carvalho de Melo 		const struct inet6_request_sock *treq = inet6_rsk(req);
658129765aSArnaldo Carvalho de Melo 
668129765aSArnaldo Carvalho de Melo 		if (inet_rsk(req)->rmt_port == rport &&
678129765aSArnaldo Carvalho de Melo 		    req->rsk_ops->family == AF_INET6 &&
688129765aSArnaldo Carvalho de Melo 		    ipv6_addr_equal(&treq->rmt_addr, raddr) &&
698129765aSArnaldo Carvalho de Melo 		    ipv6_addr_equal(&treq->loc_addr, laddr) &&
708129765aSArnaldo Carvalho de Melo 		    (!treq->iif || treq->iif == iif)) {
718129765aSArnaldo Carvalho de Melo 			BUG_TRAP(req->sk == NULL);
728129765aSArnaldo Carvalho de Melo 			*prevp = prev;
738129765aSArnaldo Carvalho de Melo 			return req;
748129765aSArnaldo Carvalho de Melo 		}
758129765aSArnaldo Carvalho de Melo 	}
768129765aSArnaldo Carvalho de Melo 
778129765aSArnaldo Carvalho de Melo 	return NULL;
788129765aSArnaldo Carvalho de Melo }
798129765aSArnaldo Carvalho de Melo 
808129765aSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet6_csk_search_req);
818129765aSArnaldo Carvalho de Melo 
828129765aSArnaldo Carvalho de Melo void inet6_csk_reqsk_queue_hash_add(struct sock *sk,
838129765aSArnaldo Carvalho de Melo 				    struct request_sock *req,
848129765aSArnaldo Carvalho de Melo 				    const unsigned long timeout)
858129765aSArnaldo Carvalho de Melo {
868129765aSArnaldo Carvalho de Melo 	struct inet_connection_sock *icsk = inet_csk(sk);
878129765aSArnaldo Carvalho de Melo 	struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
88*ca304b61SArnaldo Carvalho de Melo 	const u32 h = inet6_synq_hash(&inet6_rsk(req)->rmt_addr,
898129765aSArnaldo Carvalho de Melo 				      inet_rsk(req)->rmt_port,
908129765aSArnaldo Carvalho de Melo 				      lopt->hash_rnd, lopt->nr_table_entries);
918129765aSArnaldo Carvalho de Melo 
928129765aSArnaldo Carvalho de Melo 	reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, timeout);
938129765aSArnaldo Carvalho de Melo 	inet_csk_reqsk_queue_added(sk, timeout);
948129765aSArnaldo Carvalho de Melo }
958129765aSArnaldo Carvalho de Melo 
968129765aSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet6_csk_reqsk_queue_hash_add);
97