diff options
author | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2005-08-09 23:09:06 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:42:08 -0400 |
commit | 33b62231908c58ae04185e4f1063d1e35a7c8576 (patch) | |
tree | 502ba8c1c445d0b0f4c19d1aa3b86b01ea88478d /net/ipv4/inet_hashtables.c | |
parent | 81849d106b1fb97f8e2d311c0c4d36347def55b8 (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.c | 41 |
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 | ||
123 | EXPORT_SYMBOL(inet_listen_wlock); | 123 | EXPORT_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 | */ | ||
131 | struct 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 | } | ||