aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/inet6_connection_sock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/inet6_connection_sock.c')
-rw-r--r--net/ipv6/inet6_connection_sock.c93
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
55EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); 55EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict);
56 56
57struct 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 */
60static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport, 87static 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
181int inet6_csk_xmit(struct sk_buff *skb) 206int 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
235EXPORT_SYMBOL_GPL(inet6_csk_xmit); 252EXPORT_SYMBOL_GPL(inet6_csk_xmit);