diff options
Diffstat (limited to 'net/ipv6/inet6_connection_sock.c')
| -rw-r--r-- | net/ipv6/inet6_connection_sock.c | 101 | 
1 files changed, 62 insertions, 39 deletions
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index e6cee5292a0..0251a6005be 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -55,26 +55,26 @@ int inet6_csk_bind_conflict(const struct sock *sk,  EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict);  struct dst_entry *inet6_csk_route_req(struct sock *sk, +				      struct flowi6 *fl6,  				      const struct request_sock *req)  {  	struct inet6_request_sock *treq = inet6_rsk(req);  	struct ipv6_pinfo *np = inet6_sk(sk);  	struct in6_addr *final_p, final;  	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 = sk->sk_bound_dev_if; -	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)); +	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); +	dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);  	if (IS_ERR(dst))  		return NULL; @@ -171,7 +171,8 @@ EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);  static inline  void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, -			   struct in6_addr *daddr, struct in6_addr *saddr) +			   const struct in6_addr *daddr, +			   const struct in6_addr *saddr)  {  	__ip6_dst_store(sk, dst, daddr, saddr); @@ -203,43 +204,52 @@ struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)  	return dst;  } -int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) +static struct dst_entry *inet6_csk_route_socket(struct sock *sk, +						struct flowi6 *fl6)  { -	struct sock *sk = skb->sk;  	struct inet_sock *inet = inet_sk(sk);  	struct ipv6_pinfo *np = inet6_sk(sk); -	struct flowi6 fl6; -	struct dst_entry *dst;  	struct in6_addr *final_p, final; -	int res; +	struct dst_entry *dst; -	memset(&fl6, 0, sizeof(fl6)); -	fl6.flowi6_proto = sk->sk_protocol; -	fl6.daddr = np->daddr; -	fl6.saddr = np->saddr; -	fl6.flowlabel = np->flow_label; -	IP6_ECN_flow_xmit(sk, fl6.flowlabel); -	fl6.flowi6_oif = sk->sk_bound_dev_if; -	fl6.flowi6_mark = sk->sk_mark; -	fl6.fl6_sport = inet->inet_sport; -	fl6.fl6_dport = inet->inet_dport; -	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); +	memset(fl6, 0, sizeof(*fl6)); +	fl6->flowi6_proto = sk->sk_protocol; +	fl6->daddr = np->daddr; +	fl6->saddr = np->saddr; +	fl6->flowlabel = np->flow_label; +	IP6_ECN_flow_xmit(sk, fl6->flowlabel); +	fl6->flowi6_oif = sk->sk_bound_dev_if; +	fl6->flowi6_mark = sk->sk_mark; +	fl6->fl6_sport = inet->inet_sport; +	fl6->fl6_dport = inet->inet_dport; +	security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); -	final_p = fl6_update_dst(&fl6, np->opt, &final); +	final_p = fl6_update_dst(fl6, np->opt, &final);  	dst = __inet6_csk_dst_check(sk, np->dst_cookie); +	if (!dst) { +		dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); -	if (dst == NULL) { -		dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); +		if (!IS_ERR(dst)) +			__inet6_csk_dst_store(sk, dst, NULL, NULL); +	} +	return dst; +} -		if (IS_ERR(dst)) { -			sk->sk_err_soft = -PTR_ERR(dst); -			sk->sk_route_caps = 0; -			kfree_skb(skb); -			return PTR_ERR(dst); -		} +int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) +{ +	struct sock *sk = skb->sk; +	struct ipv6_pinfo *np = inet6_sk(sk); +	struct flowi6 fl6; +	struct dst_entry *dst; +	int res; -		__inet6_csk_dst_store(sk, dst, NULL, NULL); +	dst = inet6_csk_route_socket(sk, &fl6); +	if (IS_ERR(dst)) { +		sk->sk_err_soft = -PTR_ERR(dst); +		sk->sk_route_caps = 0; +		kfree_skb(skb); +		return PTR_ERR(dst);  	}  	rcu_read_lock(); @@ -253,3 +263,16 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused)  	return res;  }  EXPORT_SYMBOL_GPL(inet6_csk_xmit); + +struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu) +{ +	struct flowi6 fl6; +	struct dst_entry *dst = inet6_csk_route_socket(sk, &fl6); + +	if (IS_ERR(dst)) +		return NULL; +	dst->ops->update_pmtu(dst, sk, NULL, mtu); + +	return inet6_csk_route_socket(sk, &fl6); +} +EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu);  |