aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inet_hashtables.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@ghostprotocols.net>2005-08-09 23:09:06 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:42:08 -0400
commit33b62231908c58ae04185e4f1063d1e35a7c8576 (patch)
tree502ba8c1c445d0b0f4c19d1aa3b86b01ea88478d /net/ipv4/inet_hashtables.c
parent81849d106b1fb97f8e2d311c0c4d36347def55b8 (diff)
[INET]: Generalise tcp_v4_lookup_listener
[acme@toy net-2.6.14]$ grep built-in /tmp/before /tmp/after /tmp/before: 282560 13122 9312 304994 4a762 net/ipv4/built-in.o /tmp/after: 282560 13122 9312 304994 4a762 net/ipv4/built-in.o Will be used in DCCP, not exporting it right now not to get in Adrian Bunk's exported-but-not-used-on-modules radar 8) Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/inet_hashtables.c')
-rw-r--r--net/ipv4/inet_hashtables.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 06cbc6f689c5..88fcba05b7d6 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -121,3 +121,44 @@ void inet_listen_wlock(struct inet_hashinfo *hashinfo)
121} 121}
122 122
123EXPORT_SYMBOL(inet_listen_wlock); 123EXPORT_SYMBOL(inet_listen_wlock);
124
125/*
126 * Don't inline this cruft. Here are some nice properties to exploit here. The
127 * BSD API does not allow a listening sock to specify the remote port nor the
128 * remote address for the connection. So always assume those are both
129 * wildcarded during the search since they can never be otherwise.
130 */
131struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 daddr,
132 const unsigned short hnum, const int dif)
133{
134 struct sock *result = NULL, *sk;
135 const struct hlist_node *node;
136 int hiscore = -1;
137
138 sk_for_each(sk, node, head) {
139 const struct inet_sock *inet = inet_sk(sk);
140
141 if (inet->num == hnum && !ipv6_only_sock(sk)) {
142 const __u32 rcv_saddr = inet->rcv_saddr;
143 int score = sk->sk_family == PF_INET ? 1 : 0;
144
145 if (rcv_saddr) {
146 if (rcv_saddr != daddr)
147 continue;
148 score += 2;
149 }
150 if (sk->sk_bound_dev_if) {
151 if (sk->sk_bound_dev_if != dif)
152 continue;
153 score += 2;
154 }
155 if (score == 5)
156 return sk;
157 if (score > hiscore) {
158 hiscore = score;
159 result = sk;
160 }
161 }
162 }
163 return result;
164}