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