diff options
Diffstat (limited to 'net/ipv4/datagram.c')
| -rw-r--r-- | net/ipv4/datagram.c | 25 | 
1 files changed, 25 insertions, 0 deletions
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 424fafbc8cb..b28e863fe0a 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -85,3 +85,28 @@ out:  	return err;  }  EXPORT_SYMBOL(ip4_datagram_connect); + +void ip4_datagram_release_cb(struct sock *sk) +{ +	const struct inet_sock *inet = inet_sk(sk); +	const struct ip_options_rcu *inet_opt; +	__be32 daddr = inet->inet_daddr; +	struct flowi4 fl4; +	struct rtable *rt; + +	if (! __sk_dst_get(sk) || __sk_dst_check(sk, 0)) +		return; + +	rcu_read_lock(); +	inet_opt = rcu_dereference(inet->inet_opt); +	if (inet_opt && inet_opt->opt.srr) +		daddr = inet_opt->opt.faddr; +	rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr, +				   inet->inet_saddr, inet->inet_dport, +				   inet->inet_sport, sk->sk_protocol, +				   RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); +	if (!IS_ERR(rt)) +		__sk_dst_set(sk, &rt->dst); +	rcu_read_unlock(); +} +EXPORT_SYMBOL_GPL(ip4_datagram_release_cb);  |