Commit 8141ed9fcedb278f4a3a78680591bef1e55f75fb

Authored by Steffen Klassert
Committed by David S. Miller
1 parent 9cb3a50c5f

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>

Showing 5 changed files with 30 additions and 0 deletions Side-by-side Diff

... ... @@ -143,6 +143,8 @@
143 143 extern int ip4_datagram_connect(struct sock *sk,
144 144 struct sockaddr *uaddr, int addr_len);
145 145  
  146 +extern void ip4_datagram_release_cb(struct sock *sk);
  147 +
146 148 struct ip_reply_arg {
147 149 struct kvec iov[1];
148 150 int flags;
... ... @@ -85,4 +85,29 @@
85 85 return err;
86 86 }
87 87 EXPORT_SYMBOL(ip4_datagram_connect);
  88 +
  89 +void ip4_datagram_release_cb(struct sock *sk)
  90 +{
  91 + const struct inet_sock *inet = inet_sk(sk);
  92 + const struct ip_options_rcu *inet_opt;
  93 + __be32 daddr = inet->inet_daddr;
  94 + struct flowi4 fl4;
  95 + struct rtable *rt;
  96 +
  97 + if (! __sk_dst_get(sk) || __sk_dst_check(sk, 0))
  98 + return;
  99 +
  100 + rcu_read_lock();
  101 + inet_opt = rcu_dereference(inet->inet_opt);
  102 + if (inet_opt && inet_opt->opt.srr)
  103 + daddr = inet_opt->opt.faddr;
  104 + rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr,
  105 + inet->inet_saddr, inet->inet_dport,
  106 + inet->inet_sport, sk->sk_protocol,
  107 + RT_CONN_FLAGS(sk), sk->sk_bound_dev_if);
  108 + if (!IS_ERR(rt))
  109 + __sk_dst_set(sk, &rt->dst);
  110 + rcu_read_unlock();
  111 +}
  112 +EXPORT_SYMBOL_GPL(ip4_datagram_release_cb);
... ... @@ -738,6 +738,7 @@
738 738 .recvmsg = ping_recvmsg,
739 739 .bind = ping_bind,
740 740 .backlog_rcv = ping_queue_rcv_skb,
  741 + .release_cb = ip4_datagram_release_cb,
741 742 .hash = ping_v4_hash,
742 743 .unhash = ping_v4_unhash,
743 744 .get_port = ping_v4_get_port,
... ... @@ -894,6 +894,7 @@
894 894 .recvmsg = raw_recvmsg,
895 895 .bind = raw_bind,
896 896 .backlog_rcv = raw_rcv_skb,
  897 + .release_cb = ip4_datagram_release_cb,
897 898 .hash = raw_hash_sk,
898 899 .unhash = raw_unhash_sk,
899 900 .obj_size = sizeof(struct raw_sock),
... ... @@ -1952,6 +1952,7 @@
1952 1952 .recvmsg = udp_recvmsg,
1953 1953 .sendpage = udp_sendpage,
1954 1954 .backlog_rcv = __udp_queue_rcv_skb,
  1955 + .release_cb = ip4_datagram_release_cb,
1955 1956 .hash = udp_lib_hash,
1956 1957 .unhash = udp_lib_unhash,
1957 1958 .rehash = udp_v4_rehash,