diff options
-rw-r--r-- | include/net/inet_connection_sock.h | 3 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 33 |
2 files changed, 36 insertions, 0 deletions
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 6ac4e3b5007f..4367d913c0e2 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h | |||
@@ -250,6 +250,9 @@ extern int inet_csk_get_port(struct sock *sk, unsigned short snum); | |||
250 | 250 | ||
251 | extern struct dst_entry* inet_csk_route_req(struct sock *sk, | 251 | extern struct dst_entry* inet_csk_route_req(struct sock *sk, |
252 | const struct request_sock *req); | 252 | const struct request_sock *req); |
253 | extern struct dst_entry* inet_csk_route_child_sock(struct sock *sk, | ||
254 | struct sock *newsk, | ||
255 | const struct request_sock *req); | ||
253 | 256 | ||
254 | static inline void inet_csk_reqsk_queue_add(struct sock *sk, | 257 | static inline void inet_csk_reqsk_queue_add(struct sock *sk, |
255 | struct request_sock *req, | 258 | struct request_sock *req, |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 54944da2f794..3a2ba5632dff 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -379,6 +379,39 @@ no_route: | |||
379 | } | 379 | } |
380 | EXPORT_SYMBOL_GPL(inet_csk_route_req); | 380 | EXPORT_SYMBOL_GPL(inet_csk_route_req); |
381 | 381 | ||
382 | struct dst_entry *inet_csk_route_child_sock(struct sock *sk, | ||
383 | struct sock *newsk, | ||
384 | const struct request_sock *req) | ||
385 | { | ||
386 | const struct inet_request_sock *ireq = inet_rsk(req); | ||
387 | struct inet_sock *newinet = inet_sk(newsk); | ||
388 | struct ip_options_rcu *opt = ireq->opt; | ||
389 | struct net *net = sock_net(sk); | ||
390 | struct flowi4 *fl4; | ||
391 | struct rtable *rt; | ||
392 | |||
393 | fl4 = &newinet->cork.fl.u.ip4; | ||
394 | flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, | ||
395 | RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, | ||
396 | sk->sk_protocol, inet_sk_flowi_flags(sk), | ||
397 | (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, | ||
398 | ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport); | ||
399 | security_req_classify_flow(req, flowi4_to_flowi(fl4)); | ||
400 | rt = ip_route_output_flow(net, fl4, sk); | ||
401 | if (IS_ERR(rt)) | ||
402 | goto no_route; | ||
403 | if (opt && opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) | ||
404 | goto route_err; | ||
405 | return &rt->dst; | ||
406 | |||
407 | route_err: | ||
408 | ip_rt_put(rt); | ||
409 | no_route: | ||
410 | IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); | ||
411 | return NULL; | ||
412 | } | ||
413 | EXPORT_SYMBOL_GPL(inet_csk_route_child_sock); | ||
414 | |||
382 | static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, | 415 | static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, |
383 | const u32 rnd, const u32 synq_hsize) | 416 | const u32 rnd, const u32 synq_hsize) |
384 | { | 417 | { |