1 /* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * Generic INET6 transport hashtables 7 * 8 * Authors: Lotsa people, from code originally in tcp 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 13 * 2 of the License, or (at your option) any later version. 14 */ 15 16 #include <linux/config.h> 17 18 #include <linux/module.h> 19 20 #include <net/inet_connection_sock.h> 21 #include <net/inet_hashtables.h> 22 #include <net/inet6_hashtables.h> 23 24 struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, 25 const struct in6_addr *daddr, 26 const unsigned short hnum, const int dif) 27 { 28 struct sock *sk; 29 const struct hlist_node *node; 30 struct sock *result = NULL; 31 int score, hiscore = 0; 32 33 read_lock(&hashinfo->lhash_lock); 34 sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) { 35 if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) { 36 const struct ipv6_pinfo *np = inet6_sk(sk); 37 38 score = 1; 39 if (!ipv6_addr_any(&np->rcv_saddr)) { 40 if (!ipv6_addr_equal(&np->rcv_saddr, daddr)) 41 continue; 42 score++; 43 } 44 if (sk->sk_bound_dev_if) { 45 if (sk->sk_bound_dev_if != dif) 46 continue; 47 score++; 48 } 49 if (score == 3) { 50 result = sk; 51 break; 52 } 53 if (score > hiscore) { 54 hiscore = score; 55 result = sk; 56 } 57 } 58 } 59 if (result) 60 sock_hold(result); 61 read_unlock(&hashinfo->lhash_lock); 62 return result; 63 } 64 65 EXPORT_SYMBOL_GPL(inet6_lookup_listener); 66 67 struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, 68 const struct in6_addr *saddr, const u16 sport, 69 const struct in6_addr *daddr, const u16 dport, 70 const int dif) 71 { 72 struct sock *sk; 73 74 local_bh_disable(); 75 sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif); 76 local_bh_enable(); 77 78 return sk; 79 } 80 81 EXPORT_SYMBOL_GPL(inet6_lookup); 82