Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8141ed9f authored by Steffen Klassert's avatar Steffen Klassert Committed by David S. Miller
Browse files

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: default avatarSteffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9cb3a50c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -143,6 +143,8 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
extern int		ip4_datagram_connect(struct sock *sk, 
					     struct sockaddr *uaddr, int addr_len);

extern void ip4_datagram_release_cb(struct sock *sk);

struct ip_reply_arg {
	struct kvec iov[1];   
	int	    flags;
+25 −0
Original line number Diff line number Diff line
@@ -85,3 +85,28 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
	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);
+1 −0
Original line number Diff line number Diff line
@@ -738,6 +738,7 @@ struct proto ping_prot = {
	.recvmsg =	ping_recvmsg,
	.bind =		ping_bind,
	.backlog_rcv =	ping_queue_rcv_skb,
	.release_cb =	ip4_datagram_release_cb,
	.hash =		ping_v4_hash,
	.unhash =	ping_v4_unhash,
	.get_port =	ping_v4_get_port,
+1 −0
Original line number Diff line number Diff line
@@ -894,6 +894,7 @@ struct proto raw_prot = {
	.recvmsg	   = raw_recvmsg,
	.bind		   = raw_bind,
	.backlog_rcv	   = raw_rcv_skb,
	.release_cb	   = ip4_datagram_release_cb,
	.hash		   = raw_hash_sk,
	.unhash		   = raw_unhash_sk,
	.obj_size	   = sizeof(struct raw_sock),
+1 −0
Original line number Diff line number Diff line
@@ -1952,6 +1952,7 @@ struct proto udp_prot = {
	.recvmsg	   = udp_recvmsg,
	.sendpage	   = udp_sendpage,
	.backlog_rcv	   = __udp_queue_rcv_skb,
	.release_cb	   = ip4_datagram_release_cb,
	.hash		   = udp_lib_hash,
	.unhash		   = udp_lib_unhash,
	.rehash		   = udp_v4_rehash,