diff options
Diffstat (limited to 'net/ipv6/inet6_connection_sock.c')
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 93 |
1 files changed, 55 insertions, 38 deletions
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 8a1628023bd1..8a58e8cf6646 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -54,24 +54,49 @@ int inet6_csk_bind_conflict(const struct sock *sk, | |||
54 | 54 | ||
55 | EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); | 55 | EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); |
56 | 56 | ||
57 | struct dst_entry *inet6_csk_route_req(struct sock *sk, | ||
58 | const struct request_sock *req) | ||
59 | { | ||
60 | struct inet6_request_sock *treq = inet6_rsk(req); | ||
61 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
62 | struct in6_addr *final_p, final; | ||
63 | struct dst_entry *dst; | ||
64 | struct flowi6 fl6; | ||
65 | |||
66 | memset(&fl6, 0, sizeof(fl6)); | ||
67 | fl6.flowi6_proto = IPPROTO_TCP; | ||
68 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); | ||
69 | final_p = fl6_update_dst(&fl6, np->opt, &final); | ||
70 | ipv6_addr_copy(&fl6.saddr, &treq->loc_addr); | ||
71 | fl6.flowi6_oif = sk->sk_bound_dev_if; | ||
72 | fl6.flowi6_mark = sk->sk_mark; | ||
73 | fl6.fl6_dport = inet_rsk(req)->rmt_port; | ||
74 | fl6.fl6_sport = inet_rsk(req)->loc_port; | ||
75 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); | ||
76 | |||
77 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); | ||
78 | if (IS_ERR(dst)) | ||
79 | return NULL; | ||
80 | |||
81 | return dst; | ||
82 | } | ||
83 | |||
57 | /* | 84 | /* |
58 | * request_sock (formerly open request) hash tables. | 85 | * request_sock (formerly open request) hash tables. |
59 | */ | 86 | */ |
60 | static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport, | 87 | static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport, |
61 | const u32 rnd, const u16 synq_hsize) | 88 | const u32 rnd, const u16 synq_hsize) |
62 | { | 89 | { |
63 | u32 a = (__force u32)raddr->s6_addr32[0]; | 90 | u32 c; |
64 | u32 b = (__force u32)raddr->s6_addr32[1]; | ||
65 | u32 c = (__force u32)raddr->s6_addr32[2]; | ||
66 | 91 | ||
67 | a += JHASH_GOLDEN_RATIO; | 92 | c = jhash_3words((__force u32)raddr->s6_addr32[0], |
68 | b += JHASH_GOLDEN_RATIO; | 93 | (__force u32)raddr->s6_addr32[1], |
69 | c += rnd; | 94 | (__force u32)raddr->s6_addr32[2], |
70 | __jhash_mix(a, b, c); | 95 | rnd); |
71 | 96 | ||
72 | a += (__force u32)raddr->s6_addr32[3]; | 97 | c = jhash_2words((__force u32)raddr->s6_addr32[3], |
73 | b += (__force u32)rport; | 98 | (__force u32)rport, |
74 | __jhash_mix(a, b, c); | 99 | c); |
75 | 100 | ||
76 | return c & (synq_hsize - 1); | 101 | return c & (synq_hsize - 1); |
77 | } | 102 | } |
@@ -178,47 +203,39 @@ struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) | |||
178 | return dst; | 203 | return dst; |
179 | } | 204 | } |
180 | 205 | ||
181 | int inet6_csk_xmit(struct sk_buff *skb) | 206 | int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) |
182 | { | 207 | { |
183 | struct sock *sk = skb->sk; | 208 | struct sock *sk = skb->sk; |
184 | struct inet_sock *inet = inet_sk(sk); | 209 | struct inet_sock *inet = inet_sk(sk); |
185 | struct ipv6_pinfo *np = inet6_sk(sk); | 210 | struct ipv6_pinfo *np = inet6_sk(sk); |
186 | struct flowi fl; | 211 | struct flowi6 fl6; |
187 | struct dst_entry *dst; | 212 | struct dst_entry *dst; |
188 | struct in6_addr *final_p, final; | 213 | struct in6_addr *final_p, final; |
189 | 214 | ||
190 | memset(&fl, 0, sizeof(fl)); | 215 | memset(&fl6, 0, sizeof(fl6)); |
191 | fl.proto = sk->sk_protocol; | 216 | fl6.flowi6_proto = sk->sk_protocol; |
192 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 217 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
193 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 218 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
194 | fl.fl6_flowlabel = np->flow_label; | 219 | fl6.flowlabel = np->flow_label; |
195 | IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel); | 220 | IP6_ECN_flow_xmit(sk, fl6.flowlabel); |
196 | fl.oif = sk->sk_bound_dev_if; | 221 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
197 | fl.mark = sk->sk_mark; | 222 | fl6.flowi6_mark = sk->sk_mark; |
198 | fl.fl_ip_sport = inet->inet_sport; | 223 | fl6.fl6_sport = inet->inet_sport; |
199 | fl.fl_ip_dport = inet->inet_dport; | 224 | fl6.fl6_dport = inet->inet_dport; |
200 | security_sk_classify_flow(sk, &fl); | 225 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
201 | 226 | ||
202 | final_p = fl6_update_dst(&fl, np->opt, &final); | 227 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
203 | 228 | ||
204 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); | 229 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
205 | 230 | ||
206 | if (dst == NULL) { | 231 | if (dst == NULL) { |
207 | int err = ip6_dst_lookup(sk, &dst, &fl); | 232 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
208 | |||
209 | if (err) { | ||
210 | sk->sk_err_soft = -err; | ||
211 | kfree_skb(skb); | ||
212 | return err; | ||
213 | } | ||
214 | |||
215 | if (final_p) | ||
216 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
217 | 233 | ||
218 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) { | 234 | if (IS_ERR(dst)) { |
235 | sk->sk_err_soft = -PTR_ERR(dst); | ||
219 | sk->sk_route_caps = 0; | 236 | sk->sk_route_caps = 0; |
220 | kfree_skb(skb); | 237 | kfree_skb(skb); |
221 | return err; | 238 | return PTR_ERR(dst); |
222 | } | 239 | } |
223 | 240 | ||
224 | __inet6_csk_dst_store(sk, dst, NULL, NULL); | 241 | __inet6_csk_dst_store(sk, dst, NULL, NULL); |
@@ -227,9 +244,9 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
227 | skb_dst_set(skb, dst_clone(dst)); | 244 | skb_dst_set(skb, dst_clone(dst)); |
228 | 245 | ||
229 | /* Restore final destination back after routing done */ | 246 | /* Restore final destination back after routing done */ |
230 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 247 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
231 | 248 | ||
232 | return ip6_xmit(sk, skb, &fl, np->opt); | 249 | return ip6_xmit(sk, skb, &fl6, np->opt); |
233 | } | 250 | } |
234 | 251 | ||
235 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); | 252 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); |