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 | op-kernel-dev-8141ed9fcedb278f4a3a78680591bef1e55f75fb.zip op-kernel-dev-8141ed9fcedb278f4a3a78680591bef1e55f75fb.tar.gz |
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 424fafb..b28e863 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); |