Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3840a06e authored by Neal Cardwell's avatar Neal Cardwell Committed by David S. Miller
Browse files

tcp: pass fl6 to inet6_csk_route_req()



This commit changes inet_csk_route_req() so that it uses a pointer to
a struct flowi6, rather than allocating its own on the stack. This
brings its behavior in line with its IPv4 cousin,
inet_csk_route_req(), and allows a follow-on patch to fix a dst leak.

Signed-off-by: default avatarNeal Cardwell <ncardwell@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9247869e
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ extern int inet6_csk_bind_conflict(const struct sock *sk,
				   const struct inet_bind_bucket *tb, bool relax);
				   const struct inet_bind_bucket *tb, bool relax);


extern struct dst_entry* inet6_csk_route_req(struct sock *sk,
extern struct dst_entry* inet6_csk_route_req(struct sock *sk,
					     struct flowi6 *fl6,
					     const struct request_sock *req);
					     const struct request_sock *req);


extern struct request_sock *inet6_csk_search_req(const struct sock *sk,
extern struct request_sock *inet6_csk_search_req(const struct sock *sk,
+13 −13
Original line number Original line Diff line number Diff line
@@ -55,26 +55,26 @@ int inet6_csk_bind_conflict(const struct sock *sk,
EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict);
EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict);


struct dst_entry *inet6_csk_route_req(struct sock *sk,
struct dst_entry *inet6_csk_route_req(struct sock *sk,
				      struct flowi6 *fl6,
				      const struct request_sock *req)
				      const struct request_sock *req)
{
{
	struct inet6_request_sock *treq = inet6_rsk(req);
	struct inet6_request_sock *treq = inet6_rsk(req);
	struct ipv6_pinfo *np = inet6_sk(sk);
	struct ipv6_pinfo *np = inet6_sk(sk);
	struct in6_addr *final_p, final;
	struct in6_addr *final_p, final;
	struct dst_entry *dst;
	struct dst_entry *dst;
	struct flowi6 fl6;

	memset(&fl6, 0, sizeof(fl6));
	fl6.flowi6_proto = IPPROTO_TCP;
	fl6.daddr = treq->rmt_addr;
	final_p = fl6_update_dst(&fl6, np->opt, &final);
	fl6.saddr = treq->loc_addr;
	fl6.flowi6_oif = treq->iif;
	fl6.flowi6_mark = sk->sk_mark;
	fl6.fl6_dport = inet_rsk(req)->rmt_port;
	fl6.fl6_sport = inet_rsk(req)->loc_port;
	security_req_classify_flow(req, flowi6_to_flowi(&fl6));


	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
	memset(fl6, 0, sizeof(*fl6));
	fl6->flowi6_proto = IPPROTO_TCP;
	fl6->daddr = treq->rmt_addr;
	final_p = fl6_update_dst(fl6, np->opt, &final);
	fl6->saddr = treq->loc_addr;
	fl6->flowi6_oif = treq->iif;
	fl6->flowi6_mark = sk->sk_mark;
	fl6->fl6_dport = inet_rsk(req)->rmt_port;
	fl6->fl6_sport = inet_rsk(req)->loc_port;
	security_req_classify_flow(req, flowi6_to_flowi(fl6));

	dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
	if (IS_ERR(dst))
	if (IS_ERR(dst))
		return NULL;
		return NULL;


+6 −3
Original line number Original line Diff line number Diff line
@@ -477,7 +477,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
}




static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
static int tcp_v6_send_synack(struct sock *sk,
			      struct request_sock *req,
			      struct request_values *rvp,
			      struct request_values *rvp,
			      u16 queue_mapping)
			      u16 queue_mapping)
{
{
@@ -1058,6 +1059,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
	struct tcp_sock *tp = tcp_sk(sk);
	struct tcp_sock *tp = tcp_sk(sk);
	__u32 isn = TCP_SKB_CB(skb)->when;
	__u32 isn = TCP_SKB_CB(skb)->when;
	struct dst_entry *dst = NULL;
	struct dst_entry *dst = NULL;
	struct flowi6 fl6;
	bool want_cookie = false;
	bool want_cookie = false;


	if (skb->protocol == htons(ETH_P_IP))
	if (skb->protocol == htons(ETH_P_IP))
@@ -1177,7 +1179,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
		 */
		 */
		if (tmp_opt.saw_tstamp &&
		if (tmp_opt.saw_tstamp &&
		    tcp_death_row.sysctl_tw_recycle &&
		    tcp_death_row.sysctl_tw_recycle &&
		    (dst = inet6_csk_route_req(sk, req)) != NULL &&
		    (dst = inet6_csk_route_req(sk, &fl6, req)) != NULL &&
		    (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL &&
		    (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL &&
		    ipv6_addr_equal((struct in6_addr *)peer->daddr.addr.a6,
		    ipv6_addr_equal((struct in6_addr *)peer->daddr.addr.a6,
				    &treq->rmt_addr)) {
				    &treq->rmt_addr)) {
@@ -1247,6 +1249,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
#ifdef CONFIG_TCP_MD5SIG
#ifdef CONFIG_TCP_MD5SIG
	struct tcp_md5sig_key *key;
	struct tcp_md5sig_key *key;
#endif
#endif
	struct flowi6 fl6;


	if (skb->protocol == htons(ETH_P_IP)) {
	if (skb->protocol == htons(ETH_P_IP)) {
		/*
		/*
@@ -1309,7 +1312,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
		goto out_overflow;
		goto out_overflow;


	if (!dst) {
	if (!dst) {
		dst = inet6_csk_route_req(sk, req);
		dst = inet6_csk_route_req(sk, &fl6, req);
		if (!dst)
		if (!dst)
			goto out;
			goto out;
	}
	}