diff options
author | Steffen Klassert <steffen.klassert@secunet.com> | 2013-01-21 02:00:03 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-21 14:17:05 -0500 |
commit | 8141ed9fcedb278f4a3a78680591bef1e55f75fb (patch) | |
tree | d18c4a6ae41663fcb4ef4bc6e607b46aceaa5dbb /net/ipv4/datagram.c | |
parent | 9cb3a50c5f63ed745702972f66eaee8767659acd (diff) | |
download | talos-op-linux-8141ed9fcedb278f4a3a78680591bef1e55f75fb.tar.gz talos-op-linux-8141ed9fcedb278f4a3a78680591bef1e55f75fb.zip |
ipv4: Add a socket release callback for datagram sockets
This implements a socket release callback function to check
if the socket cached route got invalid during the time
we owned the socket. The function is used from udp, raw
and ping sockets.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
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 424fafbc8cb0..b28e863fe0a7 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); |