xref: /linux/drivers/net/ovpn/peer.c (revision 2c7e4a2663a1ab5a740c59c31991579b6b865a26)
180747caeSAntonio Quartulli // SPDX-License-Identifier: GPL-2.0
280747caeSAntonio Quartulli /*  OpenVPN data channel offload
380747caeSAntonio Quartulli  *
480747caeSAntonio Quartulli  *  Copyright (C) 2020-2025 OpenVPN, Inc.
580747caeSAntonio Quartulli  *
680747caeSAntonio Quartulli  *  Author:	James Yonan <james@openvpn.net>
780747caeSAntonio Quartulli  *		Antonio Quartulli <antonio@openvpn.net>
880747caeSAntonio Quartulli  */
980747caeSAntonio Quartulli 
1080747caeSAntonio Quartulli #include <linux/skbuff.h>
1180747caeSAntonio Quartulli #include <linux/list.h>
1205003b40SAntonio Quartulli #include <linux/hashtable.h>
13a3aaef8cSAntonio Quartulli #include <net/ip6_route.h>
1480747caeSAntonio Quartulli 
1580747caeSAntonio Quartulli #include "ovpnpriv.h"
1680747caeSAntonio Quartulli #include "bind.h"
178534731dSAntonio Quartulli #include "pktid.h"
188534731dSAntonio Quartulli #include "crypto.h"
1980747caeSAntonio Quartulli #include "io.h"
2080747caeSAntonio Quartulli #include "main.h"
2180747caeSAntonio Quartulli #include "netlink.h"
2280747caeSAntonio Quartulli #include "peer.h"
23f6226ae7SAntonio Quartulli #include "socket.h"
2480747caeSAntonio Quartulli 
unlock_ovpn(struct ovpn_priv * ovpn,struct llist_head * release_list)2580747caeSAntonio Quartulli static void unlock_ovpn(struct ovpn_priv *ovpn,
2680747caeSAntonio Quartulli 			 struct llist_head *release_list)
2780747caeSAntonio Quartulli 	__releases(&ovpn->lock)
2880747caeSAntonio Quartulli {
2980747caeSAntonio Quartulli 	struct ovpn_peer *peer;
3080747caeSAntonio Quartulli 
3180747caeSAntonio Quartulli 	spin_unlock_bh(&ovpn->lock);
3280747caeSAntonio Quartulli 
33f6226ae7SAntonio Quartulli 	llist_for_each_entry(peer, release_list->first, release_entry) {
34f6226ae7SAntonio Quartulli 		ovpn_socket_release(peer);
3580747caeSAntonio Quartulli 		ovpn_peer_put(peer);
3680747caeSAntonio Quartulli 	}
37f6226ae7SAntonio Quartulli }
3880747caeSAntonio Quartulli 
3980747caeSAntonio Quartulli /**
403ecfd934SAntonio Quartulli  * ovpn_peer_keepalive_set - configure keepalive values for peer
413ecfd934SAntonio Quartulli  * @peer: the peer to configure
423ecfd934SAntonio Quartulli  * @interval: outgoing keepalive interval
433ecfd934SAntonio Quartulli  * @timeout: incoming keepalive timeout
443ecfd934SAntonio Quartulli  */
ovpn_peer_keepalive_set(struct ovpn_peer * peer,u32 interval,u32 timeout)453ecfd934SAntonio Quartulli void ovpn_peer_keepalive_set(struct ovpn_peer *peer, u32 interval, u32 timeout)
463ecfd934SAntonio Quartulli {
473ecfd934SAntonio Quartulli 	time64_t now = ktime_get_real_seconds();
483ecfd934SAntonio Quartulli 
493ecfd934SAntonio Quartulli 	netdev_dbg(peer->ovpn->dev,
503ecfd934SAntonio Quartulli 		   "scheduling keepalive for peer %u: interval=%u timeout=%u\n",
513ecfd934SAntonio Quartulli 		   peer->id, interval, timeout);
523ecfd934SAntonio Quartulli 
533ecfd934SAntonio Quartulli 	peer->keepalive_interval = interval;
543ecfd934SAntonio Quartulli 	WRITE_ONCE(peer->last_sent, now);
553ecfd934SAntonio Quartulli 	peer->keepalive_xmit_exp = now + interval;
563ecfd934SAntonio Quartulli 
573ecfd934SAntonio Quartulli 	peer->keepalive_timeout = timeout;
583ecfd934SAntonio Quartulli 	WRITE_ONCE(peer->last_recv, now);
593ecfd934SAntonio Quartulli 	peer->keepalive_recv_exp = now + timeout;
603ecfd934SAntonio Quartulli 
613ecfd934SAntonio Quartulli 	/* now that interval and timeout have been changed, kick
623ecfd934SAntonio Quartulli 	 * off the worker so that the next delay can be recomputed
633ecfd934SAntonio Quartulli 	 */
643ecfd934SAntonio Quartulli 	mod_delayed_work(system_wq, &peer->ovpn->keepalive_work, 0);
653ecfd934SAntonio Quartulli }
663ecfd934SAntonio Quartulli 
673ecfd934SAntonio Quartulli /**
683ecfd934SAntonio Quartulli  * ovpn_peer_keepalive_send - periodic worker sending keepalive packets
693ecfd934SAntonio Quartulli  * @work: pointer to the work member of the related peer object
703ecfd934SAntonio Quartulli  *
713ecfd934SAntonio Quartulli  * NOTE: the reference to peer is not dropped because it gets inherited
723ecfd934SAntonio Quartulli  * by ovpn_xmit_special()
733ecfd934SAntonio Quartulli  */
ovpn_peer_keepalive_send(struct work_struct * work)743ecfd934SAntonio Quartulli static void ovpn_peer_keepalive_send(struct work_struct *work)
753ecfd934SAntonio Quartulli {
763ecfd934SAntonio Quartulli 	struct ovpn_peer *peer = container_of(work, struct ovpn_peer,
773ecfd934SAntonio Quartulli 					      keepalive_work);
783ecfd934SAntonio Quartulli 
793ecfd934SAntonio Quartulli 	local_bh_disable();
803ecfd934SAntonio Quartulli 	ovpn_xmit_special(peer, ovpn_keepalive_message,
813ecfd934SAntonio Quartulli 			  sizeof(ovpn_keepalive_message));
823ecfd934SAntonio Quartulli 	local_bh_enable();
833ecfd934SAntonio Quartulli }
843ecfd934SAntonio Quartulli 
853ecfd934SAntonio Quartulli /**
8680747caeSAntonio Quartulli  * ovpn_peer_new - allocate and initialize a new peer object
8780747caeSAntonio Quartulli  * @ovpn: the openvpn instance inside which the peer should be created
8880747caeSAntonio Quartulli  * @id: the ID assigned to this peer
8980747caeSAntonio Quartulli  *
9080747caeSAntonio Quartulli  * Return: a pointer to the new peer on success or an error code otherwise
9180747caeSAntonio Quartulli  */
ovpn_peer_new(struct ovpn_priv * ovpn,u32 id)9280747caeSAntonio Quartulli struct ovpn_peer *ovpn_peer_new(struct ovpn_priv *ovpn, u32 id)
9380747caeSAntonio Quartulli {
9480747caeSAntonio Quartulli 	struct ovpn_peer *peer;
9580747caeSAntonio Quartulli 	int ret;
9680747caeSAntonio Quartulli 
9780747caeSAntonio Quartulli 	/* alloc and init peer object */
9880747caeSAntonio Quartulli 	peer = kzalloc(sizeof(*peer), GFP_KERNEL);
9980747caeSAntonio Quartulli 	if (!peer)
10080747caeSAntonio Quartulli 		return ERR_PTR(-ENOMEM);
10180747caeSAntonio Quartulli 
10280747caeSAntonio Quartulli 	peer->id = id;
10380747caeSAntonio Quartulli 	peer->ovpn = ovpn;
10480747caeSAntonio Quartulli 
10580747caeSAntonio Quartulli 	peer->vpn_addrs.ipv4.s_addr = htonl(INADDR_ANY);
10680747caeSAntonio Quartulli 	peer->vpn_addrs.ipv6 = in6addr_any;
10780747caeSAntonio Quartulli 
10880747caeSAntonio Quartulli 	RCU_INIT_POINTER(peer->bind, NULL);
1098534731dSAntonio Quartulli 	ovpn_crypto_state_init(&peer->crypto);
11080747caeSAntonio Quartulli 	spin_lock_init(&peer->lock);
11180747caeSAntonio Quartulli 	kref_init(&peer->refcount);
11204ca1495SAntonio Quartulli 	ovpn_peer_stats_init(&peer->vpn_stats);
11304ca1495SAntonio Quartulli 	ovpn_peer_stats_init(&peer->link_stats);
1143ecfd934SAntonio Quartulli 	INIT_WORK(&peer->keepalive_work, ovpn_peer_keepalive_send);
11580747caeSAntonio Quartulli 
11680747caeSAntonio Quartulli 	ret = dst_cache_init(&peer->dst_cache, GFP_KERNEL);
11780747caeSAntonio Quartulli 	if (ret < 0) {
11880747caeSAntonio Quartulli 		netdev_err(ovpn->dev,
11980747caeSAntonio Quartulli 			   "cannot initialize dst cache for peer %u\n",
12080747caeSAntonio Quartulli 			   peer->id);
12180747caeSAntonio Quartulli 		kfree(peer);
12280747caeSAntonio Quartulli 		return ERR_PTR(ret);
12380747caeSAntonio Quartulli 	}
12480747caeSAntonio Quartulli 
12580747caeSAntonio Quartulli 	netdev_hold(ovpn->dev, &peer->dev_tracker, GFP_KERNEL);
12680747caeSAntonio Quartulli 
12780747caeSAntonio Quartulli 	return peer;
12880747caeSAntonio Quartulli }
12980747caeSAntonio Quartulli 
13080747caeSAntonio Quartulli /**
131f0281c1dSAntonio Quartulli  * ovpn_peer_reset_sockaddr - recreate binding for peer
132f0281c1dSAntonio Quartulli  * @peer: peer to recreate the binding for
133f0281c1dSAntonio Quartulli  * @ss: sockaddr to use as remote endpoint for the binding
134f0281c1dSAntonio Quartulli  * @local_ip: local IP for the binding
135f0281c1dSAntonio Quartulli  *
136f0281c1dSAntonio Quartulli  * Return: 0 on success or a negative error code otherwise
137f0281c1dSAntonio Quartulli  */
ovpn_peer_reset_sockaddr(struct ovpn_peer * peer,const struct sockaddr_storage * ss,const void * local_ip)1381d36a36fSAntonio Quartulli int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer,
139f0281c1dSAntonio Quartulli 			     const struct sockaddr_storage *ss,
140f0281c1dSAntonio Quartulli 			     const void *local_ip)
141f0281c1dSAntonio Quartulli {
142f0281c1dSAntonio Quartulli 	struct ovpn_bind *bind;
143f0281c1dSAntonio Quartulli 	size_t ip_len;
144f0281c1dSAntonio Quartulli 
145f0281c1dSAntonio Quartulli 	lockdep_assert_held(&peer->lock);
146f0281c1dSAntonio Quartulli 
147f0281c1dSAntonio Quartulli 	/* create new ovpn_bind object */
148f0281c1dSAntonio Quartulli 	bind = ovpn_bind_from_sockaddr(ss);
149f0281c1dSAntonio Quartulli 	if (IS_ERR(bind))
150f0281c1dSAntonio Quartulli 		return PTR_ERR(bind);
151f0281c1dSAntonio Quartulli 
1521d36a36fSAntonio Quartulli 	if (local_ip) {
153f0281c1dSAntonio Quartulli 		if (ss->ss_family == AF_INET) {
154f0281c1dSAntonio Quartulli 			ip_len = sizeof(struct in_addr);
155f0281c1dSAntonio Quartulli 		} else if (ss->ss_family == AF_INET6) {
156f0281c1dSAntonio Quartulli 			ip_len = sizeof(struct in6_addr);
157f0281c1dSAntonio Quartulli 		} else {
158f0281c1dSAntonio Quartulli 			net_dbg_ratelimited("%s: invalid family %u for remote endpoint for peer %u\n",
159f0281c1dSAntonio Quartulli 					    netdev_name(peer->ovpn->dev),
160f0281c1dSAntonio Quartulli 					    ss->ss_family, peer->id);
161f0281c1dSAntonio Quartulli 			kfree(bind);
162f0281c1dSAntonio Quartulli 			return -EINVAL;
163f0281c1dSAntonio Quartulli 		}
164f0281c1dSAntonio Quartulli 
165f0281c1dSAntonio Quartulli 		memcpy(&bind->local, local_ip, ip_len);
1661d36a36fSAntonio Quartulli 	}
167f0281c1dSAntonio Quartulli 
168f0281c1dSAntonio Quartulli 	/* set binding */
169f0281c1dSAntonio Quartulli 	ovpn_bind_reset(peer, bind);
170f0281c1dSAntonio Quartulli 
171f0281c1dSAntonio Quartulli 	return 0;
172f0281c1dSAntonio Quartulli }
173f0281c1dSAntonio Quartulli 
174f0281c1dSAntonio Quartulli /* variable name __tbl2 needs to be different from __tbl1
175f0281c1dSAntonio Quartulli  * in the macro below to avoid confusing clang
176f0281c1dSAntonio Quartulli  */
177f0281c1dSAntonio Quartulli #define ovpn_get_hash_slot(_tbl, _key, _key_len) ({	\
178f0281c1dSAntonio Quartulli 	typeof(_tbl) *__tbl2 = &(_tbl);			\
179f0281c1dSAntonio Quartulli 	jhash(_key, _key_len, 0) % HASH_SIZE(*__tbl2);	\
180f0281c1dSAntonio Quartulli })
181f0281c1dSAntonio Quartulli 
182f0281c1dSAntonio Quartulli #define ovpn_get_hash_head(_tbl, _key, _key_len) ({		\
183f0281c1dSAntonio Quartulli 	typeof(_tbl) *__tbl1 = &(_tbl);				\
184f0281c1dSAntonio Quartulli 	&(*__tbl1)[ovpn_get_hash_slot(*__tbl1, _key, _key_len)];\
185f0281c1dSAntonio Quartulli })
186f0281c1dSAntonio Quartulli 
187f0281c1dSAntonio Quartulli /**
188f0281c1dSAntonio Quartulli  * ovpn_peer_endpoints_update - update remote or local endpoint for peer
189f0281c1dSAntonio Quartulli  * @peer: peer to update the remote endpoint for
190f0281c1dSAntonio Quartulli  * @skb: incoming packet to retrieve the source/destination address from
191f0281c1dSAntonio Quartulli  */
ovpn_peer_endpoints_update(struct ovpn_peer * peer,struct sk_buff * skb)192f0281c1dSAntonio Quartulli void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
193f0281c1dSAntonio Quartulli {
194f0281c1dSAntonio Quartulli 	struct hlist_nulls_head *nhead;
195f0281c1dSAntonio Quartulli 	struct sockaddr_storage ss;
196f0281c1dSAntonio Quartulli 	struct sockaddr_in6 *sa6;
197f0281c1dSAntonio Quartulli 	bool reset_cache = false;
198f0281c1dSAntonio Quartulli 	struct sockaddr_in *sa;
199f0281c1dSAntonio Quartulli 	struct ovpn_bind *bind;
200f0281c1dSAntonio Quartulli 	const void *local_ip;
201f0281c1dSAntonio Quartulli 	size_t salen = 0;
202f0281c1dSAntonio Quartulli 
203f0281c1dSAntonio Quartulli 	spin_lock_bh(&peer->lock);
204f0281c1dSAntonio Quartulli 	bind = rcu_dereference_protected(peer->bind,
205f0281c1dSAntonio Quartulli 					 lockdep_is_held(&peer->lock));
206f0281c1dSAntonio Quartulli 	if (unlikely(!bind))
207f0281c1dSAntonio Quartulli 		goto unlock;
208f0281c1dSAntonio Quartulli 
209f0281c1dSAntonio Quartulli 	switch (skb->protocol) {
210f0281c1dSAntonio Quartulli 	case htons(ETH_P_IP):
211f0281c1dSAntonio Quartulli 		/* float check */
212f0281c1dSAntonio Quartulli 		if (unlikely(!ovpn_bind_skb_src_match(bind, skb))) {
213f0281c1dSAntonio Quartulli 			/* unconditionally save local endpoint in case
214f0281c1dSAntonio Quartulli 			 * of float, as it may have changed as well
215f0281c1dSAntonio Quartulli 			 */
216f0281c1dSAntonio Quartulli 			local_ip = &ip_hdr(skb)->daddr;
217f0281c1dSAntonio Quartulli 			sa = (struct sockaddr_in *)&ss;
218f0281c1dSAntonio Quartulli 			sa->sin_family = AF_INET;
219f0281c1dSAntonio Quartulli 			sa->sin_addr.s_addr = ip_hdr(skb)->saddr;
220f0281c1dSAntonio Quartulli 			sa->sin_port = udp_hdr(skb)->source;
221f0281c1dSAntonio Quartulli 			salen = sizeof(*sa);
222f0281c1dSAntonio Quartulli 			reset_cache = true;
223f0281c1dSAntonio Quartulli 			break;
224f0281c1dSAntonio Quartulli 		}
225f0281c1dSAntonio Quartulli 
226f0281c1dSAntonio Quartulli 		/* if no float happened, let's double check if the local endpoint
227f0281c1dSAntonio Quartulli 		 * has changed
228f0281c1dSAntonio Quartulli 		 */
229f0281c1dSAntonio Quartulli 		if (unlikely(bind->local.ipv4.s_addr != ip_hdr(skb)->daddr)) {
230f0281c1dSAntonio Quartulli 			net_dbg_ratelimited("%s: learning local IPv4 for peer %d (%pI4 -> %pI4)\n",
231f0281c1dSAntonio Quartulli 					    netdev_name(peer->ovpn->dev),
232f0281c1dSAntonio Quartulli 					    peer->id, &bind->local.ipv4.s_addr,
233f0281c1dSAntonio Quartulli 					    &ip_hdr(skb)->daddr);
234f0281c1dSAntonio Quartulli 			bind->local.ipv4.s_addr = ip_hdr(skb)->daddr;
235f0281c1dSAntonio Quartulli 			reset_cache = true;
236f0281c1dSAntonio Quartulli 		}
237f0281c1dSAntonio Quartulli 		break;
238f0281c1dSAntonio Quartulli 	case htons(ETH_P_IPV6):
239f0281c1dSAntonio Quartulli 		/* float check */
240f0281c1dSAntonio Quartulli 		if (unlikely(!ovpn_bind_skb_src_match(bind, skb))) {
241f0281c1dSAntonio Quartulli 			/* unconditionally save local endpoint in case
242f0281c1dSAntonio Quartulli 			 * of float, as it may have changed as well
243f0281c1dSAntonio Quartulli 			 */
244f0281c1dSAntonio Quartulli 			local_ip = &ipv6_hdr(skb)->daddr;
245f0281c1dSAntonio Quartulli 			sa6 = (struct sockaddr_in6 *)&ss;
246f0281c1dSAntonio Quartulli 			sa6->sin6_family = AF_INET6;
247f0281c1dSAntonio Quartulli 			sa6->sin6_addr = ipv6_hdr(skb)->saddr;
248f0281c1dSAntonio Quartulli 			sa6->sin6_port = udp_hdr(skb)->source;
249f0281c1dSAntonio Quartulli 			sa6->sin6_scope_id = ipv6_iface_scope_id(&ipv6_hdr(skb)->saddr,
250f0281c1dSAntonio Quartulli 								 skb->skb_iif);
251f0281c1dSAntonio Quartulli 			salen = sizeof(*sa6);
252f0281c1dSAntonio Quartulli 			reset_cache = true;
253f0281c1dSAntonio Quartulli 			break;
254f0281c1dSAntonio Quartulli 		}
255f0281c1dSAntonio Quartulli 
256f0281c1dSAntonio Quartulli 		/* if no float happened, let's double check if the local endpoint
257f0281c1dSAntonio Quartulli 		 * has changed
258f0281c1dSAntonio Quartulli 		 */
259f0281c1dSAntonio Quartulli 		if (unlikely(!ipv6_addr_equal(&bind->local.ipv6,
260f0281c1dSAntonio Quartulli 					      &ipv6_hdr(skb)->daddr))) {
2610ca74dfaSAntonio Quartulli 			net_dbg_ratelimited("%s: learning local IPv6 for peer %d (%pI6c -> %pI6c)\n",
262f0281c1dSAntonio Quartulli 					    netdev_name(peer->ovpn->dev),
263f0281c1dSAntonio Quartulli 					    peer->id, &bind->local.ipv6,
264f0281c1dSAntonio Quartulli 					    &ipv6_hdr(skb)->daddr);
265f0281c1dSAntonio Quartulli 			bind->local.ipv6 = ipv6_hdr(skb)->daddr;
266f0281c1dSAntonio Quartulli 			reset_cache = true;
267f0281c1dSAntonio Quartulli 		}
268f0281c1dSAntonio Quartulli 		break;
269f0281c1dSAntonio Quartulli 	default:
270f0281c1dSAntonio Quartulli 		goto unlock;
271f0281c1dSAntonio Quartulli 	}
272f0281c1dSAntonio Quartulli 
273f0281c1dSAntonio Quartulli 	if (unlikely(reset_cache))
274f0281c1dSAntonio Quartulli 		dst_cache_reset(&peer->dst_cache);
275f0281c1dSAntonio Quartulli 
276f0281c1dSAntonio Quartulli 	/* if the peer did not float, we can bail out now */
277f0281c1dSAntonio Quartulli 	if (likely(!salen))
278f0281c1dSAntonio Quartulli 		goto unlock;
279f0281c1dSAntonio Quartulli 
280f0281c1dSAntonio Quartulli 	if (unlikely(ovpn_peer_reset_sockaddr(peer,
281f0281c1dSAntonio Quartulli 					      (struct sockaddr_storage *)&ss,
282f0281c1dSAntonio Quartulli 					      local_ip) < 0))
283f0281c1dSAntonio Quartulli 		goto unlock;
284f0281c1dSAntonio Quartulli 
285f0281c1dSAntonio Quartulli 	net_dbg_ratelimited("%s: peer %d floated to %pIScp",
286f0281c1dSAntonio Quartulli 			    netdev_name(peer->ovpn->dev), peer->id, &ss);
287f0281c1dSAntonio Quartulli 
288f0281c1dSAntonio Quartulli 	spin_unlock_bh(&peer->lock);
289f0281c1dSAntonio Quartulli 
290f0281c1dSAntonio Quartulli 	/* rehashing is required only in MP mode as P2P has one peer
291f0281c1dSAntonio Quartulli 	 * only and thus there is no hashtable
292f0281c1dSAntonio Quartulli 	 */
293f0281c1dSAntonio Quartulli 	if (peer->ovpn->mode == OVPN_MODE_MP) {
294f0281c1dSAntonio Quartulli 		spin_lock_bh(&peer->ovpn->lock);
295f0281c1dSAntonio Quartulli 		spin_lock_bh(&peer->lock);
296f0281c1dSAntonio Quartulli 		bind = rcu_dereference_protected(peer->bind,
297f0281c1dSAntonio Quartulli 						 lockdep_is_held(&peer->lock));
298f0281c1dSAntonio Quartulli 		if (unlikely(!bind)) {
299f0281c1dSAntonio Quartulli 			spin_unlock_bh(&peer->lock);
300f0281c1dSAntonio Quartulli 			spin_unlock_bh(&peer->ovpn->lock);
301f0281c1dSAntonio Quartulli 			return;
302f0281c1dSAntonio Quartulli 		}
303f0281c1dSAntonio Quartulli 
304f0281c1dSAntonio Quartulli 		/* This function may be invoked concurrently, therefore another
305f0281c1dSAntonio Quartulli 		 * float may have happened in parallel: perform rehashing
306f0281c1dSAntonio Quartulli 		 * using the peer->bind->remote directly as key
307f0281c1dSAntonio Quartulli 		 */
308f0281c1dSAntonio Quartulli 
309f0281c1dSAntonio Quartulli 		switch (bind->remote.in4.sin_family) {
310f0281c1dSAntonio Quartulli 		case AF_INET:
311f0281c1dSAntonio Quartulli 			salen = sizeof(*sa);
312f0281c1dSAntonio Quartulli 			break;
313f0281c1dSAntonio Quartulli 		case AF_INET6:
314f0281c1dSAntonio Quartulli 			salen = sizeof(*sa6);
315f0281c1dSAntonio Quartulli 			break;
316f0281c1dSAntonio Quartulli 		}
317f0281c1dSAntonio Quartulli 
318f0281c1dSAntonio Quartulli 		/* remove old hashing */
319f0281c1dSAntonio Quartulli 		hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
320f0281c1dSAntonio Quartulli 		/* re-add with new transport address */
321f0281c1dSAntonio Quartulli 		nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr,
322f0281c1dSAntonio Quartulli 					   &bind->remote, salen);
323f0281c1dSAntonio Quartulli 		hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
324f0281c1dSAntonio Quartulli 		spin_unlock_bh(&peer->lock);
325f0281c1dSAntonio Quartulli 		spin_unlock_bh(&peer->ovpn->lock);
326f0281c1dSAntonio Quartulli 	}
327f0281c1dSAntonio Quartulli 	return;
328f0281c1dSAntonio Quartulli unlock:
329f0281c1dSAntonio Quartulli 	spin_unlock_bh(&peer->lock);
330f0281c1dSAntonio Quartulli }
331f0281c1dSAntonio Quartulli 
332f0281c1dSAntonio Quartulli /**
33380747caeSAntonio Quartulli  * ovpn_peer_release_rcu - RCU callback performing last peer release steps
33480747caeSAntonio Quartulli  * @head: RCU member of the ovpn_peer
33580747caeSAntonio Quartulli  */
ovpn_peer_release_rcu(struct rcu_head * head)33680747caeSAntonio Quartulli static void ovpn_peer_release_rcu(struct rcu_head *head)
33780747caeSAntonio Quartulli {
33880747caeSAntonio Quartulli 	struct ovpn_peer *peer = container_of(head, struct ovpn_peer, rcu);
33980747caeSAntonio Quartulli 
34080747caeSAntonio Quartulli 	/* this call will immediately free the dst_cache, therefore we
34180747caeSAntonio Quartulli 	 * perform it in the RCU callback, when all contexts are done
34280747caeSAntonio Quartulli 	 */
34380747caeSAntonio Quartulli 	dst_cache_destroy(&peer->dst_cache);
34480747caeSAntonio Quartulli 	kfree(peer);
34580747caeSAntonio Quartulli }
34680747caeSAntonio Quartulli 
34780747caeSAntonio Quartulli /**
34880747caeSAntonio Quartulli  * ovpn_peer_release - release peer private members
34980747caeSAntonio Quartulli  * @peer: the peer to release
35080747caeSAntonio Quartulli  */
ovpn_peer_release(struct ovpn_peer * peer)3511d36a36fSAntonio Quartulli void ovpn_peer_release(struct ovpn_peer *peer)
35280747caeSAntonio Quartulli {
3538534731dSAntonio Quartulli 	ovpn_crypto_state_release(&peer->crypto);
3548534731dSAntonio Quartulli 	spin_lock_bh(&peer->lock);
35580747caeSAntonio Quartulli 	ovpn_bind_reset(peer, NULL);
3568534731dSAntonio Quartulli 	spin_unlock_bh(&peer->lock);
35780747caeSAntonio Quartulli 	call_rcu(&peer->rcu, ovpn_peer_release_rcu);
35880747caeSAntonio Quartulli 	netdev_put(peer->ovpn->dev, &peer->dev_tracker);
35980747caeSAntonio Quartulli }
36080747caeSAntonio Quartulli 
36180747caeSAntonio Quartulli /**
36280747caeSAntonio Quartulli  * ovpn_peer_release_kref - callback for kref_put
36380747caeSAntonio Quartulli  * @kref: the kref object belonging to the peer
36480747caeSAntonio Quartulli  */
ovpn_peer_release_kref(struct kref * kref)36580747caeSAntonio Quartulli void ovpn_peer_release_kref(struct kref *kref)
36680747caeSAntonio Quartulli {
36780747caeSAntonio Quartulli 	struct ovpn_peer *peer = container_of(kref, struct ovpn_peer, refcount);
36880747caeSAntonio Quartulli 
36980747caeSAntonio Quartulli 	ovpn_peer_release(peer);
37080747caeSAntonio Quartulli }
37180747caeSAntonio Quartulli 
37280747caeSAntonio Quartulli /**
37380747caeSAntonio Quartulli  * ovpn_peer_skb_to_sockaddr - fill sockaddr with skb source address
37480747caeSAntonio Quartulli  * @skb: the packet to extract data from
37580747caeSAntonio Quartulli  * @ss: the sockaddr to fill
37680747caeSAntonio Quartulli  *
37780747caeSAntonio Quartulli  * Return: sockaddr length on success or -1 otherwise
37880747caeSAntonio Quartulli  */
ovpn_peer_skb_to_sockaddr(struct sk_buff * skb,struct sockaddr_storage * ss)37980747caeSAntonio Quartulli static int ovpn_peer_skb_to_sockaddr(struct sk_buff *skb,
38080747caeSAntonio Quartulli 				     struct sockaddr_storage *ss)
38180747caeSAntonio Quartulli {
38280747caeSAntonio Quartulli 	struct sockaddr_in6 *sa6;
38380747caeSAntonio Quartulli 	struct sockaddr_in *sa4;
38480747caeSAntonio Quartulli 
38580747caeSAntonio Quartulli 	switch (skb->protocol) {
38680747caeSAntonio Quartulli 	case htons(ETH_P_IP):
38780747caeSAntonio Quartulli 		sa4 = (struct sockaddr_in *)ss;
38880747caeSAntonio Quartulli 		sa4->sin_family = AF_INET;
38980747caeSAntonio Quartulli 		sa4->sin_addr.s_addr = ip_hdr(skb)->saddr;
39080747caeSAntonio Quartulli 		sa4->sin_port = udp_hdr(skb)->source;
39180747caeSAntonio Quartulli 		return sizeof(*sa4);
39280747caeSAntonio Quartulli 	case htons(ETH_P_IPV6):
39380747caeSAntonio Quartulli 		sa6 = (struct sockaddr_in6 *)ss;
39480747caeSAntonio Quartulli 		sa6->sin6_family = AF_INET6;
39580747caeSAntonio Quartulli 		sa6->sin6_addr = ipv6_hdr(skb)->saddr;
39680747caeSAntonio Quartulli 		sa6->sin6_port = udp_hdr(skb)->source;
39780747caeSAntonio Quartulli 		return sizeof(*sa6);
39880747caeSAntonio Quartulli 	}
39980747caeSAntonio Quartulli 
40080747caeSAntonio Quartulli 	return -1;
40180747caeSAntonio Quartulli }
40280747caeSAntonio Quartulli 
40380747caeSAntonio Quartulli /**
404a3aaef8cSAntonio Quartulli  * ovpn_nexthop_from_skb4 - retrieve IPv4 nexthop for outgoing skb
405a3aaef8cSAntonio Quartulli  * @skb: the outgoing packet
406a3aaef8cSAntonio Quartulli  *
407a3aaef8cSAntonio Quartulli  * Return: the IPv4 of the nexthop
408a3aaef8cSAntonio Quartulli  */
ovpn_nexthop_from_skb4(struct sk_buff * skb)409a3aaef8cSAntonio Quartulli static __be32 ovpn_nexthop_from_skb4(struct sk_buff *skb)
410a3aaef8cSAntonio Quartulli {
411a3aaef8cSAntonio Quartulli 	const struct rtable *rt = skb_rtable(skb);
412a3aaef8cSAntonio Quartulli 
413a3aaef8cSAntonio Quartulli 	if (rt && rt->rt_uses_gateway)
414a3aaef8cSAntonio Quartulli 		return rt->rt_gw4;
415a3aaef8cSAntonio Quartulli 
416a3aaef8cSAntonio Quartulli 	return ip_hdr(skb)->daddr;
417a3aaef8cSAntonio Quartulli }
418a3aaef8cSAntonio Quartulli 
419a3aaef8cSAntonio Quartulli /**
420a3aaef8cSAntonio Quartulli  * ovpn_nexthop_from_skb6 - retrieve IPv6 nexthop for outgoing skb
421a3aaef8cSAntonio Quartulli  * @skb: the outgoing packet
422a3aaef8cSAntonio Quartulli  *
423a3aaef8cSAntonio Quartulli  * Return: the IPv6 of the nexthop
424a3aaef8cSAntonio Quartulli  */
ovpn_nexthop_from_skb6(struct sk_buff * skb)425a3aaef8cSAntonio Quartulli static struct in6_addr ovpn_nexthop_from_skb6(struct sk_buff *skb)
426a3aaef8cSAntonio Quartulli {
427a3aaef8cSAntonio Quartulli 	const struct rt6_info *rt = skb_rt6_info(skb);
428a3aaef8cSAntonio Quartulli 
429a3aaef8cSAntonio Quartulli 	if (!rt || !(rt->rt6i_flags & RTF_GATEWAY))
430a3aaef8cSAntonio Quartulli 		return ipv6_hdr(skb)->daddr;
431a3aaef8cSAntonio Quartulli 
432a3aaef8cSAntonio Quartulli 	return rt->rt6i_gateway;
433a3aaef8cSAntonio Quartulli }
434a3aaef8cSAntonio Quartulli 
435a3aaef8cSAntonio Quartulli /**
436a3aaef8cSAntonio Quartulli  * ovpn_peer_get_by_vpn_addr4 - retrieve peer by its VPN IPv4 address
437a3aaef8cSAntonio Quartulli  * @ovpn: the openvpn instance to search
438a3aaef8cSAntonio Quartulli  * @addr: VPN IPv4 to use as search key
439a3aaef8cSAntonio Quartulli  *
440a3aaef8cSAntonio Quartulli  * Refcounter is not increased for the returned peer.
441a3aaef8cSAntonio Quartulli  *
442a3aaef8cSAntonio Quartulli  * Return: the peer if found or NULL otherwise
443a3aaef8cSAntonio Quartulli  */
ovpn_peer_get_by_vpn_addr4(struct ovpn_priv * ovpn,__be32 addr)444a3aaef8cSAntonio Quartulli static struct ovpn_peer *ovpn_peer_get_by_vpn_addr4(struct ovpn_priv *ovpn,
445a3aaef8cSAntonio Quartulli 						    __be32 addr)
446a3aaef8cSAntonio Quartulli {
447a3aaef8cSAntonio Quartulli 	struct hlist_nulls_head *nhead;
448a3aaef8cSAntonio Quartulli 	struct hlist_nulls_node *ntmp;
449a3aaef8cSAntonio Quartulli 	struct ovpn_peer *tmp;
450a3aaef8cSAntonio Quartulli 	unsigned int slot;
451a3aaef8cSAntonio Quartulli 
452a3aaef8cSAntonio Quartulli begin:
453a3aaef8cSAntonio Quartulli 	slot = ovpn_get_hash_slot(ovpn->peers->by_vpn_addr4, &addr,
454a3aaef8cSAntonio Quartulli 				  sizeof(addr));
455a3aaef8cSAntonio Quartulli 	nhead = &ovpn->peers->by_vpn_addr4[slot];
456a3aaef8cSAntonio Quartulli 
457a3aaef8cSAntonio Quartulli 	hlist_nulls_for_each_entry_rcu(tmp, ntmp, nhead, hash_entry_addr4)
458a3aaef8cSAntonio Quartulli 		if (addr == tmp->vpn_addrs.ipv4.s_addr)
459a3aaef8cSAntonio Quartulli 			return tmp;
460a3aaef8cSAntonio Quartulli 
461a3aaef8cSAntonio Quartulli 	/* item may have moved during lookup - check nulls and restart
462a3aaef8cSAntonio Quartulli 	 * if that's the case
463a3aaef8cSAntonio Quartulli 	 */
464a3aaef8cSAntonio Quartulli 	if (get_nulls_value(ntmp) != slot)
465a3aaef8cSAntonio Quartulli 		goto begin;
466a3aaef8cSAntonio Quartulli 
467a3aaef8cSAntonio Quartulli 	return NULL;
468a3aaef8cSAntonio Quartulli }
469a3aaef8cSAntonio Quartulli 
470a3aaef8cSAntonio Quartulli /**
471a3aaef8cSAntonio Quartulli  * ovpn_peer_get_by_vpn_addr6 - retrieve peer by its VPN IPv6 address
472a3aaef8cSAntonio Quartulli  * @ovpn: the openvpn instance to search
473a3aaef8cSAntonio Quartulli  * @addr: VPN IPv6 to use as search key
474a3aaef8cSAntonio Quartulli  *
475a3aaef8cSAntonio Quartulli  * Refcounter is not increased for the returned peer.
476a3aaef8cSAntonio Quartulli  *
477a3aaef8cSAntonio Quartulli  * Return: the peer if found or NULL otherwise
478a3aaef8cSAntonio Quartulli  */
ovpn_peer_get_by_vpn_addr6(struct ovpn_priv * ovpn,struct in6_addr * addr)479a3aaef8cSAntonio Quartulli static struct ovpn_peer *ovpn_peer_get_by_vpn_addr6(struct ovpn_priv *ovpn,
480a3aaef8cSAntonio Quartulli 						    struct in6_addr *addr)
481a3aaef8cSAntonio Quartulli {
482a3aaef8cSAntonio Quartulli 	struct hlist_nulls_head *nhead;
483a3aaef8cSAntonio Quartulli 	struct hlist_nulls_node *ntmp;
484a3aaef8cSAntonio Quartulli 	struct ovpn_peer *tmp;
485a3aaef8cSAntonio Quartulli 	unsigned int slot;
486a3aaef8cSAntonio Quartulli 
487a3aaef8cSAntonio Quartulli begin:
488a3aaef8cSAntonio Quartulli 	slot = ovpn_get_hash_slot(ovpn->peers->by_vpn_addr6, addr,
489a3aaef8cSAntonio Quartulli 				  sizeof(*addr));
490a3aaef8cSAntonio Quartulli 	nhead = &ovpn->peers->by_vpn_addr6[slot];
491a3aaef8cSAntonio Quartulli 
492a3aaef8cSAntonio Quartulli 	hlist_nulls_for_each_entry_rcu(tmp, ntmp, nhead, hash_entry_addr6)
493a3aaef8cSAntonio Quartulli 		if (ipv6_addr_equal(addr, &tmp->vpn_addrs.ipv6))
494a3aaef8cSAntonio Quartulli 			return tmp;
495a3aaef8cSAntonio Quartulli 
496a3aaef8cSAntonio Quartulli 	/* item may have moved during lookup - check nulls and restart
497a3aaef8cSAntonio Quartulli 	 * if that's the case
498a3aaef8cSAntonio Quartulli 	 */
499a3aaef8cSAntonio Quartulli 	if (get_nulls_value(ntmp) != slot)
500a3aaef8cSAntonio Quartulli 		goto begin;
501a3aaef8cSAntonio Quartulli 
502a3aaef8cSAntonio Quartulli 	return NULL;
503a3aaef8cSAntonio Quartulli }
504a3aaef8cSAntonio Quartulli 
505a3aaef8cSAntonio Quartulli /**
50680747caeSAntonio Quartulli  * ovpn_peer_transp_match - check if sockaddr and peer binding match
50780747caeSAntonio Quartulli  * @peer: the peer to get the binding from
50880747caeSAntonio Quartulli  * @ss: the sockaddr to match
50980747caeSAntonio Quartulli  *
51080747caeSAntonio Quartulli  * Return: true if sockaddr and binding match or false otherwise
51180747caeSAntonio Quartulli  */
ovpn_peer_transp_match(const struct ovpn_peer * peer,const struct sockaddr_storage * ss)51280747caeSAntonio Quartulli static bool ovpn_peer_transp_match(const struct ovpn_peer *peer,
51380747caeSAntonio Quartulli 				   const struct sockaddr_storage *ss)
51480747caeSAntonio Quartulli {
51580747caeSAntonio Quartulli 	struct ovpn_bind *bind = rcu_dereference(peer->bind);
51680747caeSAntonio Quartulli 	struct sockaddr_in6 *sa6;
51780747caeSAntonio Quartulli 	struct sockaddr_in *sa4;
51880747caeSAntonio Quartulli 
51980747caeSAntonio Quartulli 	if (unlikely(!bind))
52080747caeSAntonio Quartulli 		return false;
52180747caeSAntonio Quartulli 
52280747caeSAntonio Quartulli 	if (ss->ss_family != bind->remote.in4.sin_family)
52380747caeSAntonio Quartulli 		return false;
52480747caeSAntonio Quartulli 
52580747caeSAntonio Quartulli 	switch (ss->ss_family) {
52680747caeSAntonio Quartulli 	case AF_INET:
52780747caeSAntonio Quartulli 		sa4 = (struct sockaddr_in *)ss;
52880747caeSAntonio Quartulli 		if (sa4->sin_addr.s_addr != bind->remote.in4.sin_addr.s_addr)
52980747caeSAntonio Quartulli 			return false;
53080747caeSAntonio Quartulli 		if (sa4->sin_port != bind->remote.in4.sin_port)
53180747caeSAntonio Quartulli 			return false;
53280747caeSAntonio Quartulli 		break;
53380747caeSAntonio Quartulli 	case AF_INET6:
53480747caeSAntonio Quartulli 		sa6 = (struct sockaddr_in6 *)ss;
53580747caeSAntonio Quartulli 		if (!ipv6_addr_equal(&sa6->sin6_addr,
53680747caeSAntonio Quartulli 				     &bind->remote.in6.sin6_addr))
53780747caeSAntonio Quartulli 			return false;
53880747caeSAntonio Quartulli 		if (sa6->sin6_port != bind->remote.in6.sin6_port)
53980747caeSAntonio Quartulli 			return false;
54080747caeSAntonio Quartulli 		break;
54180747caeSAntonio Quartulli 	default:
54280747caeSAntonio Quartulli 		return false;
54380747caeSAntonio Quartulli 	}
54480747caeSAntonio Quartulli 
54580747caeSAntonio Quartulli 	return true;
54680747caeSAntonio Quartulli }
54780747caeSAntonio Quartulli 
54880747caeSAntonio Quartulli /**
54980747caeSAntonio Quartulli  * ovpn_peer_get_by_transp_addr_p2p - get peer by transport address in a P2P
55080747caeSAntonio Quartulli  *                                    instance
55180747caeSAntonio Quartulli  * @ovpn: the openvpn instance to search
55280747caeSAntonio Quartulli  * @ss: the transport socket address
55380747caeSAntonio Quartulli  *
55480747caeSAntonio Quartulli  * Return: the peer if found or NULL otherwise
55580747caeSAntonio Quartulli  */
55680747caeSAntonio Quartulli static struct ovpn_peer *
ovpn_peer_get_by_transp_addr_p2p(struct ovpn_priv * ovpn,struct sockaddr_storage * ss)55780747caeSAntonio Quartulli ovpn_peer_get_by_transp_addr_p2p(struct ovpn_priv *ovpn,
55880747caeSAntonio Quartulli 				 struct sockaddr_storage *ss)
55980747caeSAntonio Quartulli {
56080747caeSAntonio Quartulli 	struct ovpn_peer *tmp, *peer = NULL;
56180747caeSAntonio Quartulli 
56280747caeSAntonio Quartulli 	rcu_read_lock();
56380747caeSAntonio Quartulli 	tmp = rcu_dereference(ovpn->peer);
56480747caeSAntonio Quartulli 	if (likely(tmp && ovpn_peer_transp_match(tmp, ss) &&
56580747caeSAntonio Quartulli 		   ovpn_peer_hold(tmp)))
56680747caeSAntonio Quartulli 		peer = tmp;
56780747caeSAntonio Quartulli 	rcu_read_unlock();
56880747caeSAntonio Quartulli 
56980747caeSAntonio Quartulli 	return peer;
57080747caeSAntonio Quartulli }
57180747caeSAntonio Quartulli 
57280747caeSAntonio Quartulli /**
57380747caeSAntonio Quartulli  * ovpn_peer_get_by_transp_addr - retrieve peer by transport address
57480747caeSAntonio Quartulli  * @ovpn: the openvpn instance to search
57580747caeSAntonio Quartulli  * @skb: the skb to retrieve the source transport address from
57680747caeSAntonio Quartulli  *
57780747caeSAntonio Quartulli  * Return: a pointer to the peer if found or NULL otherwise
57880747caeSAntonio Quartulli  */
ovpn_peer_get_by_transp_addr(struct ovpn_priv * ovpn,struct sk_buff * skb)57980747caeSAntonio Quartulli struct ovpn_peer *ovpn_peer_get_by_transp_addr(struct ovpn_priv *ovpn,
58080747caeSAntonio Quartulli 					       struct sk_buff *skb)
58180747caeSAntonio Quartulli {
582a3aaef8cSAntonio Quartulli 	struct ovpn_peer *tmp, *peer = NULL;
58380747caeSAntonio Quartulli 	struct sockaddr_storage ss = { 0 };
584a3aaef8cSAntonio Quartulli 	struct hlist_nulls_head *nhead;
585a3aaef8cSAntonio Quartulli 	struct hlist_nulls_node *ntmp;
586a3aaef8cSAntonio Quartulli 	unsigned int slot;
587a3aaef8cSAntonio Quartulli 	ssize_t sa_len;
58880747caeSAntonio Quartulli 
589a3aaef8cSAntonio Quartulli 	sa_len = ovpn_peer_skb_to_sockaddr(skb, &ss);
590a3aaef8cSAntonio Quartulli 	if (unlikely(sa_len < 0))
59180747caeSAntonio Quartulli 		return NULL;
59280747caeSAntonio Quartulli 
59380747caeSAntonio Quartulli 	if (ovpn->mode == OVPN_MODE_P2P)
594a3aaef8cSAntonio Quartulli 		return ovpn_peer_get_by_transp_addr_p2p(ovpn, &ss);
595a3aaef8cSAntonio Quartulli 
596a3aaef8cSAntonio Quartulli 	rcu_read_lock();
597a3aaef8cSAntonio Quartulli begin:
598a3aaef8cSAntonio Quartulli 	slot = ovpn_get_hash_slot(ovpn->peers->by_transp_addr, &ss, sa_len);
599a3aaef8cSAntonio Quartulli 	nhead = &ovpn->peers->by_transp_addr[slot];
600a3aaef8cSAntonio Quartulli 
601a3aaef8cSAntonio Quartulli 	hlist_nulls_for_each_entry_rcu(tmp, ntmp, nhead,
602a3aaef8cSAntonio Quartulli 				       hash_entry_transp_addr) {
603a3aaef8cSAntonio Quartulli 		if (!ovpn_peer_transp_match(tmp, &ss))
604a3aaef8cSAntonio Quartulli 			continue;
605a3aaef8cSAntonio Quartulli 
606a3aaef8cSAntonio Quartulli 		if (!ovpn_peer_hold(tmp))
607a3aaef8cSAntonio Quartulli 			continue;
608a3aaef8cSAntonio Quartulli 
609a3aaef8cSAntonio Quartulli 		peer = tmp;
610a3aaef8cSAntonio Quartulli 		break;
611a3aaef8cSAntonio Quartulli 	}
612a3aaef8cSAntonio Quartulli 
613a3aaef8cSAntonio Quartulli 	/* item may have moved during lookup - check nulls and restart
614a3aaef8cSAntonio Quartulli 	 * if that's the case
615a3aaef8cSAntonio Quartulli 	 */
616a3aaef8cSAntonio Quartulli 	if (!peer && get_nulls_value(ntmp) != slot)
617a3aaef8cSAntonio Quartulli 		goto begin;
618a3aaef8cSAntonio Quartulli 	rcu_read_unlock();
61980747caeSAntonio Quartulli 
62080747caeSAntonio Quartulli 	return peer;
62180747caeSAntonio Quartulli }
62280747caeSAntonio Quartulli 
62380747caeSAntonio Quartulli /**
62480747caeSAntonio Quartulli  * ovpn_peer_get_by_id_p2p - get peer by ID in a P2P instance
62580747caeSAntonio Quartulli  * @ovpn: the openvpn instance to search
62680747caeSAntonio Quartulli  * @peer_id: the ID of the peer to find
62780747caeSAntonio Quartulli  *
62880747caeSAntonio Quartulli  * Return: the peer if found or NULL otherwise
62980747caeSAntonio Quartulli  */
ovpn_peer_get_by_id_p2p(struct ovpn_priv * ovpn,u32 peer_id)63080747caeSAntonio Quartulli static struct ovpn_peer *ovpn_peer_get_by_id_p2p(struct ovpn_priv *ovpn,
63180747caeSAntonio Quartulli 						 u32 peer_id)
63280747caeSAntonio Quartulli {
63380747caeSAntonio Quartulli 	struct ovpn_peer *tmp, *peer = NULL;
63480747caeSAntonio Quartulli 
63580747caeSAntonio Quartulli 	rcu_read_lock();
63680747caeSAntonio Quartulli 	tmp = rcu_dereference(ovpn->peer);
63780747caeSAntonio Quartulli 	if (likely(tmp && tmp->id == peer_id && ovpn_peer_hold(tmp)))
63880747caeSAntonio Quartulli 		peer = tmp;
63980747caeSAntonio Quartulli 	rcu_read_unlock();
64080747caeSAntonio Quartulli 
64180747caeSAntonio Quartulli 	return peer;
64280747caeSAntonio Quartulli }
64380747caeSAntonio Quartulli 
64480747caeSAntonio Quartulli /**
64580747caeSAntonio Quartulli  * ovpn_peer_get_by_id - retrieve peer by ID
64680747caeSAntonio Quartulli  * @ovpn: the openvpn instance to search
64780747caeSAntonio Quartulli  * @peer_id: the unique peer identifier to match
64880747caeSAntonio Quartulli  *
64980747caeSAntonio Quartulli  * Return: a pointer to the peer if found or NULL otherwise
65080747caeSAntonio Quartulli  */
ovpn_peer_get_by_id(struct ovpn_priv * ovpn,u32 peer_id)65180747caeSAntonio Quartulli struct ovpn_peer *ovpn_peer_get_by_id(struct ovpn_priv *ovpn, u32 peer_id)
65280747caeSAntonio Quartulli {
653a3aaef8cSAntonio Quartulli 	struct ovpn_peer *tmp, *peer = NULL;
654a3aaef8cSAntonio Quartulli 	struct hlist_head *head;
65580747caeSAntonio Quartulli 
65680747caeSAntonio Quartulli 	if (ovpn->mode == OVPN_MODE_P2P)
657a3aaef8cSAntonio Quartulli 		return ovpn_peer_get_by_id_p2p(ovpn, peer_id);
658a3aaef8cSAntonio Quartulli 
659a3aaef8cSAntonio Quartulli 	head = ovpn_get_hash_head(ovpn->peers->by_id, &peer_id,
660a3aaef8cSAntonio Quartulli 				  sizeof(peer_id));
661a3aaef8cSAntonio Quartulli 
662a3aaef8cSAntonio Quartulli 	rcu_read_lock();
663a3aaef8cSAntonio Quartulli 	hlist_for_each_entry_rcu(tmp, head, hash_entry_id) {
664a3aaef8cSAntonio Quartulli 		if (tmp->id != peer_id)
665a3aaef8cSAntonio Quartulli 			continue;
666a3aaef8cSAntonio Quartulli 
667a3aaef8cSAntonio Quartulli 		if (!ovpn_peer_hold(tmp))
668a3aaef8cSAntonio Quartulli 			continue;
669a3aaef8cSAntonio Quartulli 
670a3aaef8cSAntonio Quartulli 		peer = tmp;
671a3aaef8cSAntonio Quartulli 		break;
672a3aaef8cSAntonio Quartulli 	}
673a3aaef8cSAntonio Quartulli 	rcu_read_unlock();
67480747caeSAntonio Quartulli 
67580747caeSAntonio Quartulli 	return peer;
67680747caeSAntonio Quartulli }
67780747caeSAntonio Quartulli 
ovpn_peer_remove(struct ovpn_peer * peer,enum ovpn_del_peer_reason reason,struct llist_head * release_list)67880747caeSAntonio Quartulli static void ovpn_peer_remove(struct ovpn_peer *peer,
67980747caeSAntonio Quartulli 			     enum ovpn_del_peer_reason reason,
68080747caeSAntonio Quartulli 			     struct llist_head *release_list)
68180747caeSAntonio Quartulli {
68205003b40SAntonio Quartulli 	lockdep_assert_held(&peer->ovpn->lock);
68305003b40SAntonio Quartulli 
68480747caeSAntonio Quartulli 	switch (peer->ovpn->mode) {
68505003b40SAntonio Quartulli 	case OVPN_MODE_MP:
68605003b40SAntonio Quartulli 		/* prevent double remove */
68705003b40SAntonio Quartulli 		if (hlist_unhashed(&peer->hash_entry_id))
68805003b40SAntonio Quartulli 			return;
68905003b40SAntonio Quartulli 
69005003b40SAntonio Quartulli 		hlist_del_init_rcu(&peer->hash_entry_id);
69105003b40SAntonio Quartulli 		hlist_nulls_del_init_rcu(&peer->hash_entry_addr4);
69205003b40SAntonio Quartulli 		hlist_nulls_del_init_rcu(&peer->hash_entry_addr6);
69305003b40SAntonio Quartulli 		hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr);
69405003b40SAntonio Quartulli 		break;
69580747caeSAntonio Quartulli 	case OVPN_MODE_P2P:
69680747caeSAntonio Quartulli 		/* prevent double remove */
69780747caeSAntonio Quartulli 		if (peer != rcu_access_pointer(peer->ovpn->peer))
69880747caeSAntonio Quartulli 			return;
69980747caeSAntonio Quartulli 
70080747caeSAntonio Quartulli 		RCU_INIT_POINTER(peer->ovpn->peer, NULL);
70180747caeSAntonio Quartulli 		/* in P2P mode the carrier is switched off when the peer is
70280747caeSAntonio Quartulli 		 * deleted so that third party protocols can react accordingly
70380747caeSAntonio Quartulli 		 */
70480747caeSAntonio Quartulli 		netif_carrier_off(peer->ovpn->dev);
70580747caeSAntonio Quartulli 		break;
70680747caeSAntonio Quartulli 	}
70780747caeSAntonio Quartulli 
70880747caeSAntonio Quartulli 	peer->delete_reason = reason;
709a215d253SAntonio Quartulli 	ovpn_nl_peer_del_notify(peer);
71080747caeSAntonio Quartulli 
71180747caeSAntonio Quartulli 	/* append to provided list for later socket release and ref drop */
71280747caeSAntonio Quartulli 	llist_add(&peer->release_entry, release_list);
71380747caeSAntonio Quartulli }
71480747caeSAntonio Quartulli 
71580747caeSAntonio Quartulli /**
71608857b5eSAntonio Quartulli  * ovpn_peer_get_by_dst - Lookup peer to send skb to
71708857b5eSAntonio Quartulli  * @ovpn: the private data representing the current VPN session
71808857b5eSAntonio Quartulli  * @skb: the skb to extract the destination address from
71908857b5eSAntonio Quartulli  *
72008857b5eSAntonio Quartulli  * This function takes a tunnel packet and looks up the peer to send it to
72108857b5eSAntonio Quartulli  * after encapsulation. The skb is expected to be the in-tunnel packet, without
72208857b5eSAntonio Quartulli  * any OpenVPN related header.
72308857b5eSAntonio Quartulli  *
72408857b5eSAntonio Quartulli  * Assume that the IP header is accessible in the skb data.
72508857b5eSAntonio Quartulli  *
72608857b5eSAntonio Quartulli  * Return: the peer if found or NULL otherwise.
72708857b5eSAntonio Quartulli  */
ovpn_peer_get_by_dst(struct ovpn_priv * ovpn,struct sk_buff * skb)72808857b5eSAntonio Quartulli struct ovpn_peer *ovpn_peer_get_by_dst(struct ovpn_priv *ovpn,
72908857b5eSAntonio Quartulli 				       struct sk_buff *skb)
73008857b5eSAntonio Quartulli {
73108857b5eSAntonio Quartulli 	struct ovpn_peer *peer = NULL;
732a3aaef8cSAntonio Quartulli 	struct in6_addr addr6;
733a3aaef8cSAntonio Quartulli 	__be32 addr4;
73408857b5eSAntonio Quartulli 
73508857b5eSAntonio Quartulli 	/* in P2P mode, no matter the destination, packets are always sent to
73608857b5eSAntonio Quartulli 	 * the single peer listening on the other side
73708857b5eSAntonio Quartulli 	 */
73808857b5eSAntonio Quartulli 	if (ovpn->mode == OVPN_MODE_P2P) {
73908857b5eSAntonio Quartulli 		rcu_read_lock();
74008857b5eSAntonio Quartulli 		peer = rcu_dereference(ovpn->peer);
74108857b5eSAntonio Quartulli 		if (unlikely(peer && !ovpn_peer_hold(peer)))
74208857b5eSAntonio Quartulli 			peer = NULL;
74308857b5eSAntonio Quartulli 		rcu_read_unlock();
744a3aaef8cSAntonio Quartulli 		return peer;
74508857b5eSAntonio Quartulli 	}
74608857b5eSAntonio Quartulli 
747a3aaef8cSAntonio Quartulli 	rcu_read_lock();
748a3aaef8cSAntonio Quartulli 	switch (skb->protocol) {
749a3aaef8cSAntonio Quartulli 	case htons(ETH_P_IP):
750a3aaef8cSAntonio Quartulli 		addr4 = ovpn_nexthop_from_skb4(skb);
751a3aaef8cSAntonio Quartulli 		peer = ovpn_peer_get_by_vpn_addr4(ovpn, addr4);
752a3aaef8cSAntonio Quartulli 		break;
753a3aaef8cSAntonio Quartulli 	case htons(ETH_P_IPV6):
754a3aaef8cSAntonio Quartulli 		addr6 = ovpn_nexthop_from_skb6(skb);
755a3aaef8cSAntonio Quartulli 		peer = ovpn_peer_get_by_vpn_addr6(ovpn, &addr6);
756a3aaef8cSAntonio Quartulli 		break;
757a3aaef8cSAntonio Quartulli 	}
758a3aaef8cSAntonio Quartulli 
759a3aaef8cSAntonio Quartulli 	if (unlikely(peer && !ovpn_peer_hold(peer)))
760a3aaef8cSAntonio Quartulli 		peer = NULL;
761a3aaef8cSAntonio Quartulli 	rcu_read_unlock();
762a3aaef8cSAntonio Quartulli 
76308857b5eSAntonio Quartulli 	return peer;
76408857b5eSAntonio Quartulli }
76508857b5eSAntonio Quartulli 
76608857b5eSAntonio Quartulli /**
767a3aaef8cSAntonio Quartulli  * ovpn_nexthop_from_rt4 - look up the IPv4 nexthop for the given destination
768a3aaef8cSAntonio Quartulli  * @ovpn: the private data representing the current VPN session
769a3aaef8cSAntonio Quartulli  * @dest: the destination to be looked up
770a3aaef8cSAntonio Quartulli  *
771a3aaef8cSAntonio Quartulli  * Looks up in the IPv4 system routing table the IP of the nexthop to be used
772a3aaef8cSAntonio Quartulli  * to reach the destination passed as argument. If no nexthop can be found, the
773a3aaef8cSAntonio Quartulli  * destination itself is returned as it probably has to be used as nexthop.
774a3aaef8cSAntonio Quartulli  *
775a3aaef8cSAntonio Quartulli  * Return: the IP of the next hop if found or dest itself otherwise
776a3aaef8cSAntonio Quartulli  */
ovpn_nexthop_from_rt4(struct ovpn_priv * ovpn,__be32 dest)777a3aaef8cSAntonio Quartulli static __be32 ovpn_nexthop_from_rt4(struct ovpn_priv *ovpn, __be32 dest)
778a3aaef8cSAntonio Quartulli {
779a3aaef8cSAntonio Quartulli 	struct rtable *rt;
780a3aaef8cSAntonio Quartulli 	struct flowi4 fl = {
781a3aaef8cSAntonio Quartulli 		.daddr = dest
782a3aaef8cSAntonio Quartulli 	};
783a3aaef8cSAntonio Quartulli 
784a3aaef8cSAntonio Quartulli 	rt = ip_route_output_flow(dev_net(ovpn->dev), &fl, NULL);
785a3aaef8cSAntonio Quartulli 	if (IS_ERR(rt)) {
786a3aaef8cSAntonio Quartulli 		net_dbg_ratelimited("%s: no route to host %pI4\n",
787a3aaef8cSAntonio Quartulli 				    netdev_name(ovpn->dev), &dest);
788a3aaef8cSAntonio Quartulli 		/* if we end up here this packet is probably going to be
789a3aaef8cSAntonio Quartulli 		 * thrown away later
790a3aaef8cSAntonio Quartulli 		 */
791a3aaef8cSAntonio Quartulli 		return dest;
792a3aaef8cSAntonio Quartulli 	}
793a3aaef8cSAntonio Quartulli 
794a3aaef8cSAntonio Quartulli 	if (!rt->rt_uses_gateway)
795a3aaef8cSAntonio Quartulli 		goto out;
796a3aaef8cSAntonio Quartulli 
797a3aaef8cSAntonio Quartulli 	dest = rt->rt_gw4;
798a3aaef8cSAntonio Quartulli out:
799a3aaef8cSAntonio Quartulli 	ip_rt_put(rt);
800a3aaef8cSAntonio Quartulli 	return dest;
801a3aaef8cSAntonio Quartulli }
802a3aaef8cSAntonio Quartulli 
803a3aaef8cSAntonio Quartulli /**
804a3aaef8cSAntonio Quartulli  * ovpn_nexthop_from_rt6 - look up the IPv6 nexthop for the given destination
805a3aaef8cSAntonio Quartulli  * @ovpn: the private data representing the current VPN session
806a3aaef8cSAntonio Quartulli  * @dest: the destination to be looked up
807a3aaef8cSAntonio Quartulli  *
808a3aaef8cSAntonio Quartulli  * Looks up in the IPv6 system routing table the IP of the nexthop to be used
809a3aaef8cSAntonio Quartulli  * to reach the destination passed as argument. If no nexthop can be found, the
810a3aaef8cSAntonio Quartulli  * destination itself is returned as it probably has to be used as nexthop.
811a3aaef8cSAntonio Quartulli  *
812a3aaef8cSAntonio Quartulli  * Return: the IP of the next hop if found or dest itself otherwise
813a3aaef8cSAntonio Quartulli  */
ovpn_nexthop_from_rt6(struct ovpn_priv * ovpn,struct in6_addr dest)814a3aaef8cSAntonio Quartulli static struct in6_addr ovpn_nexthop_from_rt6(struct ovpn_priv *ovpn,
815a3aaef8cSAntonio Quartulli 					     struct in6_addr dest)
816a3aaef8cSAntonio Quartulli {
817a3aaef8cSAntonio Quartulli #if IS_ENABLED(CONFIG_IPV6)
818a3aaef8cSAntonio Quartulli 	struct dst_entry *entry;
819a3aaef8cSAntonio Quartulli 	struct rt6_info *rt;
820a3aaef8cSAntonio Quartulli 	struct flowi6 fl = {
821a3aaef8cSAntonio Quartulli 		.daddr = dest,
822a3aaef8cSAntonio Quartulli 	};
823a3aaef8cSAntonio Quartulli 
824a3aaef8cSAntonio Quartulli 	entry = ipv6_stub->ipv6_dst_lookup_flow(dev_net(ovpn->dev), NULL, &fl,
825a3aaef8cSAntonio Quartulli 						NULL);
826a3aaef8cSAntonio Quartulli 	if (IS_ERR(entry)) {
827a3aaef8cSAntonio Quartulli 		net_dbg_ratelimited("%s: no route to host %pI6c\n",
828a3aaef8cSAntonio Quartulli 				    netdev_name(ovpn->dev), &dest);
829a3aaef8cSAntonio Quartulli 		/* if we end up here this packet is probably going to be
830a3aaef8cSAntonio Quartulli 		 * thrown away later
831a3aaef8cSAntonio Quartulli 		 */
832a3aaef8cSAntonio Quartulli 		return dest;
833a3aaef8cSAntonio Quartulli 	}
834a3aaef8cSAntonio Quartulli 
835a3aaef8cSAntonio Quartulli 	rt = dst_rt6_info(entry);
836a3aaef8cSAntonio Quartulli 
837a3aaef8cSAntonio Quartulli 	if (!(rt->rt6i_flags & RTF_GATEWAY))
838a3aaef8cSAntonio Quartulli 		goto out;
839a3aaef8cSAntonio Quartulli 
840a3aaef8cSAntonio Quartulli 	dest = rt->rt6i_gateway;
841a3aaef8cSAntonio Quartulli out:
842a3aaef8cSAntonio Quartulli 	dst_release((struct dst_entry *)rt);
843a3aaef8cSAntonio Quartulli #endif
844a3aaef8cSAntonio Quartulli 	return dest;
845a3aaef8cSAntonio Quartulli }
846a3aaef8cSAntonio Quartulli 
847a3aaef8cSAntonio Quartulli /**
8488534731dSAntonio Quartulli  * ovpn_peer_check_by_src - check that skb source is routed via peer
8498534731dSAntonio Quartulli  * @ovpn: the openvpn instance to search
8508534731dSAntonio Quartulli  * @skb: the packet to extract source address from
8518534731dSAntonio Quartulli  * @peer: the peer to check against the source address
8528534731dSAntonio Quartulli  *
8538534731dSAntonio Quartulli  * Return: true if the peer is matching or false otherwise
8548534731dSAntonio Quartulli  */
ovpn_peer_check_by_src(struct ovpn_priv * ovpn,struct sk_buff * skb,struct ovpn_peer * peer)8558534731dSAntonio Quartulli bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb,
8568534731dSAntonio Quartulli 			    struct ovpn_peer *peer)
8578534731dSAntonio Quartulli {
8588534731dSAntonio Quartulli 	bool match = false;
859a3aaef8cSAntonio Quartulli 	struct in6_addr addr6;
860a3aaef8cSAntonio Quartulli 	__be32 addr4;
8618534731dSAntonio Quartulli 
8628534731dSAntonio Quartulli 	if (ovpn->mode == OVPN_MODE_P2P) {
8638534731dSAntonio Quartulli 		/* in P2P mode, no matter the destination, packets are always
8648534731dSAntonio Quartulli 		 * sent to the single peer listening on the other side
8658534731dSAntonio Quartulli 		 */
866a3aaef8cSAntonio Quartulli 		return peer == rcu_access_pointer(ovpn->peer);
867a3aaef8cSAntonio Quartulli 	}
868a3aaef8cSAntonio Quartulli 
869a3aaef8cSAntonio Quartulli 	/* This function performs a reverse path check, therefore we now
870a3aaef8cSAntonio Quartulli 	 * lookup the nexthop we would use if we wanted to route a packet
871a3aaef8cSAntonio Quartulli 	 * to the source IP. If the nexthop matches the sender we know the
872a3aaef8cSAntonio Quartulli 	 * latter is valid and we allow the packet to come in
873a3aaef8cSAntonio Quartulli 	 */
874a3aaef8cSAntonio Quartulli 
875a3aaef8cSAntonio Quartulli 	switch (skb->protocol) {
876a3aaef8cSAntonio Quartulli 	case htons(ETH_P_IP):
877a3aaef8cSAntonio Quartulli 		addr4 = ovpn_nexthop_from_rt4(ovpn, ip_hdr(skb)->saddr);
878a3aaef8cSAntonio Quartulli 		rcu_read_lock();
879a3aaef8cSAntonio Quartulli 		match = (peer == ovpn_peer_get_by_vpn_addr4(ovpn, addr4));
880a3aaef8cSAntonio Quartulli 		rcu_read_unlock();
881a3aaef8cSAntonio Quartulli 		break;
882a3aaef8cSAntonio Quartulli 	case htons(ETH_P_IPV6):
883a3aaef8cSAntonio Quartulli 		addr6 = ovpn_nexthop_from_rt6(ovpn, ipv6_hdr(skb)->saddr);
884a3aaef8cSAntonio Quartulli 		rcu_read_lock();
885a3aaef8cSAntonio Quartulli 		match = (peer == ovpn_peer_get_by_vpn_addr6(ovpn, &addr6));
886a3aaef8cSAntonio Quartulli 		rcu_read_unlock();
887a3aaef8cSAntonio Quartulli 		break;
8888534731dSAntonio Quartulli 	}
8898534731dSAntonio Quartulli 
8908534731dSAntonio Quartulli 	return match;
8918534731dSAntonio Quartulli }
8928534731dSAntonio Quartulli 
ovpn_peer_hash_vpn_ip(struct ovpn_peer * peer)8931d36a36fSAntonio Quartulli void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer)
8941d36a36fSAntonio Quartulli {
8951d36a36fSAntonio Quartulli 	struct hlist_nulls_head *nhead;
8961d36a36fSAntonio Quartulli 
8971d36a36fSAntonio Quartulli 	lockdep_assert_held(&peer->ovpn->lock);
8981d36a36fSAntonio Quartulli 
8991d36a36fSAntonio Quartulli 	/* rehashing makes sense only in multipeer mode */
9001d36a36fSAntonio Quartulli 	if (peer->ovpn->mode != OVPN_MODE_MP)
9011d36a36fSAntonio Quartulli 		return;
9021d36a36fSAntonio Quartulli 
9031d36a36fSAntonio Quartulli 	if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY)) {
9041d36a36fSAntonio Quartulli 		/* remove potential old hashing */
9051d36a36fSAntonio Quartulli 		hlist_nulls_del_init_rcu(&peer->hash_entry_addr4);
9061d36a36fSAntonio Quartulli 
9071d36a36fSAntonio Quartulli 		nhead = ovpn_get_hash_head(peer->ovpn->peers->by_vpn_addr4,
9081d36a36fSAntonio Quartulli 					   &peer->vpn_addrs.ipv4,
9091d36a36fSAntonio Quartulli 					   sizeof(peer->vpn_addrs.ipv4));
9101d36a36fSAntonio Quartulli 		hlist_nulls_add_head_rcu(&peer->hash_entry_addr4, nhead);
9111d36a36fSAntonio Quartulli 	}
9121d36a36fSAntonio Quartulli 
9131d36a36fSAntonio Quartulli 	if (!ipv6_addr_any(&peer->vpn_addrs.ipv6)) {
9141d36a36fSAntonio Quartulli 		/* remove potential old hashing */
9151d36a36fSAntonio Quartulli 		hlist_nulls_del_init_rcu(&peer->hash_entry_addr6);
9161d36a36fSAntonio Quartulli 
9171d36a36fSAntonio Quartulli 		nhead = ovpn_get_hash_head(peer->ovpn->peers->by_vpn_addr6,
9181d36a36fSAntonio Quartulli 					   &peer->vpn_addrs.ipv6,
9191d36a36fSAntonio Quartulli 					   sizeof(peer->vpn_addrs.ipv6));
9201d36a36fSAntonio Quartulli 		hlist_nulls_add_head_rcu(&peer->hash_entry_addr6, nhead);
9211d36a36fSAntonio Quartulli 	}
9221d36a36fSAntonio Quartulli }
9231d36a36fSAntonio Quartulli 
92405003b40SAntonio Quartulli /**
92505003b40SAntonio Quartulli  * ovpn_peer_add_mp - add peer to related tables in a MP instance
92605003b40SAntonio Quartulli  * @ovpn: the instance to add the peer to
92705003b40SAntonio Quartulli  * @peer: the peer to add
92805003b40SAntonio Quartulli  *
92905003b40SAntonio Quartulli  * Return: 0 on success or a negative error code otherwise
93005003b40SAntonio Quartulli  */
ovpn_peer_add_mp(struct ovpn_priv * ovpn,struct ovpn_peer * peer)93105003b40SAntonio Quartulli static int ovpn_peer_add_mp(struct ovpn_priv *ovpn, struct ovpn_peer *peer)
93205003b40SAntonio Quartulli {
93305003b40SAntonio Quartulli 	struct sockaddr_storage sa = { 0 };
93405003b40SAntonio Quartulli 	struct hlist_nulls_head *nhead;
93505003b40SAntonio Quartulli 	struct sockaddr_in6 *sa6;
93605003b40SAntonio Quartulli 	struct sockaddr_in *sa4;
93705003b40SAntonio Quartulli 	struct ovpn_bind *bind;
93805003b40SAntonio Quartulli 	struct ovpn_peer *tmp;
93905003b40SAntonio Quartulli 	size_t salen;
94005003b40SAntonio Quartulli 	int ret = 0;
94105003b40SAntonio Quartulli 
94205003b40SAntonio Quartulli 	spin_lock_bh(&ovpn->lock);
94305003b40SAntonio Quartulli 	/* do not add duplicates */
94405003b40SAntonio Quartulli 	tmp = ovpn_peer_get_by_id(ovpn, peer->id);
94505003b40SAntonio Quartulli 	if (tmp) {
94605003b40SAntonio Quartulli 		ovpn_peer_put(tmp);
94705003b40SAntonio Quartulli 		ret = -EEXIST;
94805003b40SAntonio Quartulli 		goto out;
94905003b40SAntonio Quartulli 	}
95005003b40SAntonio Quartulli 
95105003b40SAntonio Quartulli 	bind = rcu_dereference_protected(peer->bind, true);
95205003b40SAntonio Quartulli 	/* peers connected via TCP have bind == NULL */
95305003b40SAntonio Quartulli 	if (bind) {
95405003b40SAntonio Quartulli 		switch (bind->remote.in4.sin_family) {
95505003b40SAntonio Quartulli 		case AF_INET:
95605003b40SAntonio Quartulli 			sa4 = (struct sockaddr_in *)&sa;
95705003b40SAntonio Quartulli 
95805003b40SAntonio Quartulli 			sa4->sin_family = AF_INET;
95905003b40SAntonio Quartulli 			sa4->sin_addr.s_addr = bind->remote.in4.sin_addr.s_addr;
96005003b40SAntonio Quartulli 			sa4->sin_port = bind->remote.in4.sin_port;
96105003b40SAntonio Quartulli 			salen = sizeof(*sa4);
96205003b40SAntonio Quartulli 			break;
96305003b40SAntonio Quartulli 		case AF_INET6:
96405003b40SAntonio Quartulli 			sa6 = (struct sockaddr_in6 *)&sa;
96505003b40SAntonio Quartulli 
96605003b40SAntonio Quartulli 			sa6->sin6_family = AF_INET6;
96705003b40SAntonio Quartulli 			sa6->sin6_addr = bind->remote.in6.sin6_addr;
96805003b40SAntonio Quartulli 			sa6->sin6_port = bind->remote.in6.sin6_port;
96905003b40SAntonio Quartulli 			salen = sizeof(*sa6);
97005003b40SAntonio Quartulli 			break;
97105003b40SAntonio Quartulli 		default:
97205003b40SAntonio Quartulli 			ret = -EPROTONOSUPPORT;
97305003b40SAntonio Quartulli 			goto out;
97405003b40SAntonio Quartulli 		}
97505003b40SAntonio Quartulli 
97605003b40SAntonio Quartulli 		nhead = ovpn_get_hash_head(ovpn->peers->by_transp_addr, &sa,
97705003b40SAntonio Quartulli 					   salen);
97805003b40SAntonio Quartulli 		hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead);
97905003b40SAntonio Quartulli 	}
98005003b40SAntonio Quartulli 
98105003b40SAntonio Quartulli 	hlist_add_head_rcu(&peer->hash_entry_id,
98205003b40SAntonio Quartulli 			   ovpn_get_hash_head(ovpn->peers->by_id, &peer->id,
98305003b40SAntonio Quartulli 					      sizeof(peer->id)));
98405003b40SAntonio Quartulli 
9851d36a36fSAntonio Quartulli 	ovpn_peer_hash_vpn_ip(peer);
98605003b40SAntonio Quartulli out:
98705003b40SAntonio Quartulli 	spin_unlock_bh(&ovpn->lock);
98805003b40SAntonio Quartulli 	return ret;
98905003b40SAntonio Quartulli }
99005003b40SAntonio Quartulli 
9918534731dSAntonio Quartulli /**
99280747caeSAntonio Quartulli  * ovpn_peer_add_p2p - add peer to related tables in a P2P instance
99380747caeSAntonio Quartulli  * @ovpn: the instance to add the peer to
99480747caeSAntonio Quartulli  * @peer: the peer to add
99580747caeSAntonio Quartulli  *
99680747caeSAntonio Quartulli  * Return: 0 on success or a negative error code otherwise
99780747caeSAntonio Quartulli  */
ovpn_peer_add_p2p(struct ovpn_priv * ovpn,struct ovpn_peer * peer)99880747caeSAntonio Quartulli static int ovpn_peer_add_p2p(struct ovpn_priv *ovpn, struct ovpn_peer *peer)
99980747caeSAntonio Quartulli {
100080747caeSAntonio Quartulli 	LLIST_HEAD(release_list);
100180747caeSAntonio Quartulli 	struct ovpn_peer *tmp;
100280747caeSAntonio Quartulli 
100380747caeSAntonio Quartulli 	spin_lock_bh(&ovpn->lock);
100480747caeSAntonio Quartulli 	/* in p2p mode it is possible to have a single peer only, therefore the
100580747caeSAntonio Quartulli 	 * old one is released and substituted by the new one
100680747caeSAntonio Quartulli 	 */
100780747caeSAntonio Quartulli 	tmp = rcu_dereference_protected(ovpn->peer,
100880747caeSAntonio Quartulli 					lockdep_is_held(&ovpn->lock));
100980747caeSAntonio Quartulli 	if (tmp)
101080747caeSAntonio Quartulli 		ovpn_peer_remove(tmp, OVPN_DEL_PEER_REASON_TEARDOWN,
101180747caeSAntonio Quartulli 				 &release_list);
101280747caeSAntonio Quartulli 
101380747caeSAntonio Quartulli 	rcu_assign_pointer(ovpn->peer, peer);
101480747caeSAntonio Quartulli 	/* in P2P mode the carrier is switched on when the peer is added */
101580747caeSAntonio Quartulli 	netif_carrier_on(ovpn->dev);
101680747caeSAntonio Quartulli 	unlock_ovpn(ovpn, &release_list);
101780747caeSAntonio Quartulli 
101880747caeSAntonio Quartulli 	return 0;
101980747caeSAntonio Quartulli }
102080747caeSAntonio Quartulli 
102180747caeSAntonio Quartulli /**
102280747caeSAntonio Quartulli  * ovpn_peer_add - add peer to the related tables
102380747caeSAntonio Quartulli  * @ovpn: the openvpn instance the peer belongs to
102480747caeSAntonio Quartulli  * @peer: the peer object to add
102580747caeSAntonio Quartulli  *
102680747caeSAntonio Quartulli  * Assume refcounter was increased by caller
102780747caeSAntonio Quartulli  *
102880747caeSAntonio Quartulli  * Return: 0 on success or a negative error code otherwise
102980747caeSAntonio Quartulli  */
ovpn_peer_add(struct ovpn_priv * ovpn,struct ovpn_peer * peer)103080747caeSAntonio Quartulli int ovpn_peer_add(struct ovpn_priv *ovpn, struct ovpn_peer *peer)
103180747caeSAntonio Quartulli {
103280747caeSAntonio Quartulli 	switch (ovpn->mode) {
103305003b40SAntonio Quartulli 	case OVPN_MODE_MP:
103405003b40SAntonio Quartulli 		return ovpn_peer_add_mp(ovpn, peer);
103580747caeSAntonio Quartulli 	case OVPN_MODE_P2P:
103680747caeSAntonio Quartulli 		return ovpn_peer_add_p2p(ovpn, peer);
103705003b40SAntonio Quartulli 	}
103805003b40SAntonio Quartulli 
103980747caeSAntonio Quartulli 	return -EOPNOTSUPP;
104080747caeSAntonio Quartulli }
104105003b40SAntonio Quartulli 
104205003b40SAntonio Quartulli /**
104305003b40SAntonio Quartulli  * ovpn_peer_del_mp - delete peer from related tables in a MP instance
104405003b40SAntonio Quartulli  * @peer: the peer to delete
104505003b40SAntonio Quartulli  * @reason: reason why the peer was deleted (sent to userspace)
104605003b40SAntonio Quartulli  * @release_list: list where delete peer should be appended
104705003b40SAntonio Quartulli  *
104805003b40SAntonio Quartulli  * Return: 0 on success or a negative error code otherwise
104905003b40SAntonio Quartulli  */
ovpn_peer_del_mp(struct ovpn_peer * peer,enum ovpn_del_peer_reason reason,struct llist_head * release_list)105005003b40SAntonio Quartulli static int ovpn_peer_del_mp(struct ovpn_peer *peer,
105105003b40SAntonio Quartulli 			    enum ovpn_del_peer_reason reason,
105205003b40SAntonio Quartulli 			    struct llist_head *release_list)
105305003b40SAntonio Quartulli {
105405003b40SAntonio Quartulli 	struct ovpn_peer *tmp;
105505003b40SAntonio Quartulli 	int ret = -ENOENT;
105605003b40SAntonio Quartulli 
105705003b40SAntonio Quartulli 	lockdep_assert_held(&peer->ovpn->lock);
105805003b40SAntonio Quartulli 
105905003b40SAntonio Quartulli 	tmp = ovpn_peer_get_by_id(peer->ovpn, peer->id);
106005003b40SAntonio Quartulli 	if (tmp == peer) {
106105003b40SAntonio Quartulli 		ovpn_peer_remove(peer, reason, release_list);
106205003b40SAntonio Quartulli 		ret = 0;
106305003b40SAntonio Quartulli 	}
106405003b40SAntonio Quartulli 
106505003b40SAntonio Quartulli 	if (tmp)
106605003b40SAntonio Quartulli 		ovpn_peer_put(tmp);
106705003b40SAntonio Quartulli 
106805003b40SAntonio Quartulli 	return ret;
106980747caeSAntonio Quartulli }
107080747caeSAntonio Quartulli 
107180747caeSAntonio Quartulli /**
107280747caeSAntonio Quartulli  * ovpn_peer_del_p2p - delete peer from related tables in a P2P instance
107380747caeSAntonio Quartulli  * @peer: the peer to delete
107480747caeSAntonio Quartulli  * @reason: reason why the peer was deleted (sent to userspace)
107580747caeSAntonio Quartulli  * @release_list: list where delete peer should be appended
107680747caeSAntonio Quartulli  *
107780747caeSAntonio Quartulli  * Return: 0 on success or a negative error code otherwise
107880747caeSAntonio Quartulli  */
ovpn_peer_del_p2p(struct ovpn_peer * peer,enum ovpn_del_peer_reason reason,struct llist_head * release_list)107980747caeSAntonio Quartulli static int ovpn_peer_del_p2p(struct ovpn_peer *peer,
108080747caeSAntonio Quartulli 			     enum ovpn_del_peer_reason reason,
108180747caeSAntonio Quartulli 			     struct llist_head *release_list)
108280747caeSAntonio Quartulli {
108380747caeSAntonio Quartulli 	struct ovpn_peer *tmp;
108480747caeSAntonio Quartulli 
108580747caeSAntonio Quartulli 	lockdep_assert_held(&peer->ovpn->lock);
108680747caeSAntonio Quartulli 
108780747caeSAntonio Quartulli 	tmp = rcu_dereference_protected(peer->ovpn->peer,
108880747caeSAntonio Quartulli 					lockdep_is_held(&peer->ovpn->lock));
108980747caeSAntonio Quartulli 	if (tmp != peer)
109080747caeSAntonio Quartulli 		return -ENOENT;
109180747caeSAntonio Quartulli 
109280747caeSAntonio Quartulli 	ovpn_peer_remove(peer, reason, release_list);
109380747caeSAntonio Quartulli 
109480747caeSAntonio Quartulli 	return 0;
109580747caeSAntonio Quartulli }
109680747caeSAntonio Quartulli 
109780747caeSAntonio Quartulli /**
109880747caeSAntonio Quartulli  * ovpn_peer_del - delete peer from related tables
109980747caeSAntonio Quartulli  * @peer: the peer object to delete
110080747caeSAntonio Quartulli  * @reason: reason for deleting peer (will be sent to userspace)
110180747caeSAntonio Quartulli  *
110280747caeSAntonio Quartulli  * Return: 0 on success or a negative error code otherwise
110380747caeSAntonio Quartulli  */
ovpn_peer_del(struct ovpn_peer * peer,enum ovpn_del_peer_reason reason)110480747caeSAntonio Quartulli int ovpn_peer_del(struct ovpn_peer *peer, enum ovpn_del_peer_reason reason)
110580747caeSAntonio Quartulli {
110680747caeSAntonio Quartulli 	LLIST_HEAD(release_list);
110780747caeSAntonio Quartulli 	int ret = -EOPNOTSUPP;
110880747caeSAntonio Quartulli 
110980747caeSAntonio Quartulli 	spin_lock_bh(&peer->ovpn->lock);
111080747caeSAntonio Quartulli 	switch (peer->ovpn->mode) {
111105003b40SAntonio Quartulli 	case OVPN_MODE_MP:
111205003b40SAntonio Quartulli 		ret = ovpn_peer_del_mp(peer, reason, &release_list);
111305003b40SAntonio Quartulli 		break;
111480747caeSAntonio Quartulli 	case OVPN_MODE_P2P:
111580747caeSAntonio Quartulli 		ret = ovpn_peer_del_p2p(peer, reason, &release_list);
111680747caeSAntonio Quartulli 		break;
111780747caeSAntonio Quartulli 	default:
111880747caeSAntonio Quartulli 		break;
111980747caeSAntonio Quartulli 	}
112080747caeSAntonio Quartulli 	unlock_ovpn(peer->ovpn, &release_list);
112180747caeSAntonio Quartulli 
112280747caeSAntonio Quartulli 	return ret;
112380747caeSAntonio Quartulli }
112480747caeSAntonio Quartulli 
112580747caeSAntonio Quartulli /**
112680747caeSAntonio Quartulli  * ovpn_peer_release_p2p - release peer upon P2P device teardown
112780747caeSAntonio Quartulli  * @ovpn: the instance being torn down
1128f6226ae7SAntonio Quartulli  * @sk: if not NULL, release peer only if it's using this specific socket
112980747caeSAntonio Quartulli  * @reason: the reason for releasing the peer
113080747caeSAntonio Quartulli  */
ovpn_peer_release_p2p(struct ovpn_priv * ovpn,struct sock * sk,enum ovpn_del_peer_reason reason)113105003b40SAntonio Quartulli static void ovpn_peer_release_p2p(struct ovpn_priv *ovpn, struct sock *sk,
113280747caeSAntonio Quartulli 				  enum ovpn_del_peer_reason reason)
113380747caeSAntonio Quartulli {
1134f6226ae7SAntonio Quartulli 	struct ovpn_socket *ovpn_sock;
113580747caeSAntonio Quartulli 	LLIST_HEAD(release_list);
113680747caeSAntonio Quartulli 	struct ovpn_peer *peer;
113780747caeSAntonio Quartulli 
113880747caeSAntonio Quartulli 	spin_lock_bh(&ovpn->lock);
113980747caeSAntonio Quartulli 	peer = rcu_dereference_protected(ovpn->peer,
114080747caeSAntonio Quartulli 					 lockdep_is_held(&ovpn->lock));
1141f6226ae7SAntonio Quartulli 	if (!peer) {
1142f6226ae7SAntonio Quartulli 		spin_unlock_bh(&ovpn->lock);
1143f6226ae7SAntonio Quartulli 		return;
1144f6226ae7SAntonio Quartulli 	}
1145f6226ae7SAntonio Quartulli 
1146f6226ae7SAntonio Quartulli 	if (sk) {
1147f6226ae7SAntonio Quartulli 		ovpn_sock = rcu_access_pointer(peer->sock);
1148*ba499a07SAntonio Quartulli 		if (!ovpn_sock || ovpn_sock->sk != sk) {
1149f6226ae7SAntonio Quartulli 			spin_unlock_bh(&ovpn->lock);
1150f6226ae7SAntonio Quartulli 			ovpn_peer_put(peer);
1151f6226ae7SAntonio Quartulli 			return;
1152f6226ae7SAntonio Quartulli 		}
1153f6226ae7SAntonio Quartulli 	}
1154f6226ae7SAntonio Quartulli 
115580747caeSAntonio Quartulli 	ovpn_peer_remove(peer, reason, &release_list);
115680747caeSAntonio Quartulli 	unlock_ovpn(ovpn, &release_list);
115780747caeSAntonio Quartulli }
115805003b40SAntonio Quartulli 
ovpn_peers_release_mp(struct ovpn_priv * ovpn,struct sock * sk,enum ovpn_del_peer_reason reason)115905003b40SAntonio Quartulli static void ovpn_peers_release_mp(struct ovpn_priv *ovpn, struct sock *sk,
116005003b40SAntonio Quartulli 				  enum ovpn_del_peer_reason reason)
116105003b40SAntonio Quartulli {
116205003b40SAntonio Quartulli 	struct ovpn_socket *ovpn_sock;
116305003b40SAntonio Quartulli 	LLIST_HEAD(release_list);
116405003b40SAntonio Quartulli 	struct ovpn_peer *peer;
116505003b40SAntonio Quartulli 	struct hlist_node *tmp;
116605003b40SAntonio Quartulli 	int bkt;
116705003b40SAntonio Quartulli 
116805003b40SAntonio Quartulli 	spin_lock_bh(&ovpn->lock);
116905003b40SAntonio Quartulli 	hash_for_each_safe(ovpn->peers->by_id, bkt, tmp, peer, hash_entry_id) {
117005003b40SAntonio Quartulli 		bool remove = true;
117105003b40SAntonio Quartulli 
117205003b40SAntonio Quartulli 		/* if a socket was passed as argument, skip all peers except
117305003b40SAntonio Quartulli 		 * those using it
117405003b40SAntonio Quartulli 		 */
117505003b40SAntonio Quartulli 		if (sk) {
117605003b40SAntonio Quartulli 			rcu_read_lock();
117705003b40SAntonio Quartulli 			ovpn_sock = rcu_dereference(peer->sock);
1178*ba499a07SAntonio Quartulli 			remove = ovpn_sock && ovpn_sock->sk == sk;
117905003b40SAntonio Quartulli 			rcu_read_unlock();
118005003b40SAntonio Quartulli 		}
118105003b40SAntonio Quartulli 
118205003b40SAntonio Quartulli 		if (remove)
118305003b40SAntonio Quartulli 			ovpn_peer_remove(peer, reason, &release_list);
118405003b40SAntonio Quartulli 	}
118505003b40SAntonio Quartulli 	unlock_ovpn(ovpn, &release_list);
118605003b40SAntonio Quartulli }
118705003b40SAntonio Quartulli 
118805003b40SAntonio Quartulli /**
118905003b40SAntonio Quartulli  * ovpn_peers_free - free all peers in the instance
119005003b40SAntonio Quartulli  * @ovpn: the instance whose peers should be released
119105003b40SAntonio Quartulli  * @sk: if not NULL, only peers using this socket are removed and the socket
119205003b40SAntonio Quartulli  *      is released immediately
119305003b40SAntonio Quartulli  * @reason: the reason for releasing all peers
119405003b40SAntonio Quartulli  */
ovpn_peers_free(struct ovpn_priv * ovpn,struct sock * sk,enum ovpn_del_peer_reason reason)119505003b40SAntonio Quartulli void ovpn_peers_free(struct ovpn_priv *ovpn, struct sock *sk,
119605003b40SAntonio Quartulli 		     enum ovpn_del_peer_reason reason)
119705003b40SAntonio Quartulli {
119805003b40SAntonio Quartulli 	switch (ovpn->mode) {
119905003b40SAntonio Quartulli 	case OVPN_MODE_P2P:
120005003b40SAntonio Quartulli 		ovpn_peer_release_p2p(ovpn, sk, reason);
120105003b40SAntonio Quartulli 		break;
120205003b40SAntonio Quartulli 	case OVPN_MODE_MP:
120305003b40SAntonio Quartulli 		ovpn_peers_release_mp(ovpn, sk, reason);
120405003b40SAntonio Quartulli 		break;
120505003b40SAntonio Quartulli 	}
120605003b40SAntonio Quartulli }
12073ecfd934SAntonio Quartulli 
ovpn_peer_keepalive_work_single(struct ovpn_peer * peer,time64_t now,struct llist_head * release_list)12083ecfd934SAntonio Quartulli static time64_t ovpn_peer_keepalive_work_single(struct ovpn_peer *peer,
12093ecfd934SAntonio Quartulli 						time64_t now,
12103ecfd934SAntonio Quartulli 						struct llist_head *release_list)
12113ecfd934SAntonio Quartulli {
12123ecfd934SAntonio Quartulli 	time64_t last_recv, last_sent, next_run1, next_run2;
12133ecfd934SAntonio Quartulli 	unsigned long timeout, interval;
12143ecfd934SAntonio Quartulli 	bool expired;
12153ecfd934SAntonio Quartulli 
12163ecfd934SAntonio Quartulli 	spin_lock_bh(&peer->lock);
12173ecfd934SAntonio Quartulli 	/* we expect both timers to be configured at the same time,
12183ecfd934SAntonio Quartulli 	 * therefore bail out if either is not set
12193ecfd934SAntonio Quartulli 	 */
12203ecfd934SAntonio Quartulli 	if (!peer->keepalive_timeout || !peer->keepalive_interval) {
12213ecfd934SAntonio Quartulli 		spin_unlock_bh(&peer->lock);
12223ecfd934SAntonio Quartulli 		return 0;
12233ecfd934SAntonio Quartulli 	}
12243ecfd934SAntonio Quartulli 
12253ecfd934SAntonio Quartulli 	/* check for peer timeout */
12263ecfd934SAntonio Quartulli 	expired = false;
12273ecfd934SAntonio Quartulli 	timeout = peer->keepalive_timeout;
12283ecfd934SAntonio Quartulli 	last_recv = READ_ONCE(peer->last_recv);
12293ecfd934SAntonio Quartulli 	if (now < last_recv + timeout) {
12303ecfd934SAntonio Quartulli 		peer->keepalive_recv_exp = last_recv + timeout;
12313ecfd934SAntonio Quartulli 		next_run1 = peer->keepalive_recv_exp;
12323ecfd934SAntonio Quartulli 	} else if (peer->keepalive_recv_exp > now) {
12333ecfd934SAntonio Quartulli 		next_run1 = peer->keepalive_recv_exp;
12343ecfd934SAntonio Quartulli 	} else {
12353ecfd934SAntonio Quartulli 		expired = true;
12363ecfd934SAntonio Quartulli 	}
12373ecfd934SAntonio Quartulli 
12383ecfd934SAntonio Quartulli 	if (expired) {
12393ecfd934SAntonio Quartulli 		/* peer is dead -> kill it and move on */
12403ecfd934SAntonio Quartulli 		spin_unlock_bh(&peer->lock);
12413ecfd934SAntonio Quartulli 		netdev_dbg(peer->ovpn->dev, "peer %u expired\n",
12423ecfd934SAntonio Quartulli 			   peer->id);
12433ecfd934SAntonio Quartulli 		ovpn_peer_remove(peer, OVPN_DEL_PEER_REASON_EXPIRED,
12443ecfd934SAntonio Quartulli 				 release_list);
12453ecfd934SAntonio Quartulli 		return 0;
12463ecfd934SAntonio Quartulli 	}
12473ecfd934SAntonio Quartulli 
12483ecfd934SAntonio Quartulli 	/* check for peer keepalive */
12493ecfd934SAntonio Quartulli 	expired = false;
12503ecfd934SAntonio Quartulli 	interval = peer->keepalive_interval;
12513ecfd934SAntonio Quartulli 	last_sent = READ_ONCE(peer->last_sent);
12523ecfd934SAntonio Quartulli 	if (now < last_sent + interval) {
12533ecfd934SAntonio Quartulli 		peer->keepalive_xmit_exp = last_sent + interval;
12543ecfd934SAntonio Quartulli 		next_run2 = peer->keepalive_xmit_exp;
12553ecfd934SAntonio Quartulli 	} else if (peer->keepalive_xmit_exp > now) {
12563ecfd934SAntonio Quartulli 		next_run2 = peer->keepalive_xmit_exp;
12573ecfd934SAntonio Quartulli 	} else {
12583ecfd934SAntonio Quartulli 		expired = true;
12593ecfd934SAntonio Quartulli 		next_run2 = now + interval;
12603ecfd934SAntonio Quartulli 	}
12613ecfd934SAntonio Quartulli 	spin_unlock_bh(&peer->lock);
12623ecfd934SAntonio Quartulli 
12633ecfd934SAntonio Quartulli 	if (expired) {
12643ecfd934SAntonio Quartulli 		/* a keepalive packet is required */
12653ecfd934SAntonio Quartulli 		netdev_dbg(peer->ovpn->dev,
12663ecfd934SAntonio Quartulli 			   "sending keepalive to peer %u\n",
12673ecfd934SAntonio Quartulli 			   peer->id);
12683ecfd934SAntonio Quartulli 		if (schedule_work(&peer->keepalive_work))
12693ecfd934SAntonio Quartulli 			ovpn_peer_hold(peer);
12703ecfd934SAntonio Quartulli 	}
12713ecfd934SAntonio Quartulli 
12723ecfd934SAntonio Quartulli 	if (next_run1 < next_run2)
12733ecfd934SAntonio Quartulli 		return next_run1;
12743ecfd934SAntonio Quartulli 
12753ecfd934SAntonio Quartulli 	return next_run2;
12763ecfd934SAntonio Quartulli }
12773ecfd934SAntonio Quartulli 
ovpn_peer_keepalive_work_mp(struct ovpn_priv * ovpn,time64_t now,struct llist_head * release_list)12783ecfd934SAntonio Quartulli static time64_t ovpn_peer_keepalive_work_mp(struct ovpn_priv *ovpn,
12793ecfd934SAntonio Quartulli 					    time64_t now,
12803ecfd934SAntonio Quartulli 					    struct llist_head *release_list)
12813ecfd934SAntonio Quartulli {
12823ecfd934SAntonio Quartulli 	time64_t tmp_next_run, next_run = 0;
12833ecfd934SAntonio Quartulli 	struct hlist_node *tmp;
12843ecfd934SAntonio Quartulli 	struct ovpn_peer *peer;
12853ecfd934SAntonio Quartulli 	int bkt;
12863ecfd934SAntonio Quartulli 
12873ecfd934SAntonio Quartulli 	lockdep_assert_held(&ovpn->lock);
12883ecfd934SAntonio Quartulli 
12893ecfd934SAntonio Quartulli 	hash_for_each_safe(ovpn->peers->by_id, bkt, tmp, peer, hash_entry_id) {
12903ecfd934SAntonio Quartulli 		tmp_next_run = ovpn_peer_keepalive_work_single(peer, now,
12913ecfd934SAntonio Quartulli 							       release_list);
12923ecfd934SAntonio Quartulli 		if (!tmp_next_run)
12933ecfd934SAntonio Quartulli 			continue;
12943ecfd934SAntonio Quartulli 
12953ecfd934SAntonio Quartulli 		/* the next worker run will be scheduled based on the shortest
12963ecfd934SAntonio Quartulli 		 * required interval across all peers
12973ecfd934SAntonio Quartulli 		 */
12983ecfd934SAntonio Quartulli 		if (!next_run || tmp_next_run < next_run)
12993ecfd934SAntonio Quartulli 			next_run = tmp_next_run;
13003ecfd934SAntonio Quartulli 	}
13013ecfd934SAntonio Quartulli 
13023ecfd934SAntonio Quartulli 	return next_run;
13033ecfd934SAntonio Quartulli }
13043ecfd934SAntonio Quartulli 
ovpn_peer_keepalive_work_p2p(struct ovpn_priv * ovpn,time64_t now,struct llist_head * release_list)13053ecfd934SAntonio Quartulli static time64_t ovpn_peer_keepalive_work_p2p(struct ovpn_priv *ovpn,
13063ecfd934SAntonio Quartulli 					     time64_t now,
13073ecfd934SAntonio Quartulli 					     struct llist_head *release_list)
13083ecfd934SAntonio Quartulli {
13093ecfd934SAntonio Quartulli 	struct ovpn_peer *peer;
13103ecfd934SAntonio Quartulli 	time64_t next_run = 0;
13113ecfd934SAntonio Quartulli 
13123ecfd934SAntonio Quartulli 	lockdep_assert_held(&ovpn->lock);
13133ecfd934SAntonio Quartulli 
13143ecfd934SAntonio Quartulli 	peer = rcu_dereference_protected(ovpn->peer,
13153ecfd934SAntonio Quartulli 					 lockdep_is_held(&ovpn->lock));
13163ecfd934SAntonio Quartulli 	if (peer)
13173ecfd934SAntonio Quartulli 		next_run = ovpn_peer_keepalive_work_single(peer, now,
13183ecfd934SAntonio Quartulli 							   release_list);
13193ecfd934SAntonio Quartulli 
13203ecfd934SAntonio Quartulli 	return next_run;
13213ecfd934SAntonio Quartulli }
13223ecfd934SAntonio Quartulli 
13233ecfd934SAntonio Quartulli /**
13243ecfd934SAntonio Quartulli  * ovpn_peer_keepalive_work - run keepalive logic on each known peer
13253ecfd934SAntonio Quartulli  * @work: pointer to the work member of the related ovpn object
13263ecfd934SAntonio Quartulli  *
13273ecfd934SAntonio Quartulli  * Each peer has two timers (if configured):
13283ecfd934SAntonio Quartulli  * 1. peer timeout: when no data is received for a certain interval,
13293ecfd934SAntonio Quartulli  *    the peer is considered dead and it gets killed.
13303ecfd934SAntonio Quartulli  * 2. peer keepalive: when no data is sent to a certain peer for a
13313ecfd934SAntonio Quartulli  *    certain interval, a special 'keepalive' packet is explicitly sent.
13323ecfd934SAntonio Quartulli  *
13333ecfd934SAntonio Quartulli  * This function iterates across the whole peer collection while
13343ecfd934SAntonio Quartulli  * checking the timers described above.
13353ecfd934SAntonio Quartulli  */
ovpn_peer_keepalive_work(struct work_struct * work)13363ecfd934SAntonio Quartulli void ovpn_peer_keepalive_work(struct work_struct *work)
13373ecfd934SAntonio Quartulli {
13383ecfd934SAntonio Quartulli 	struct ovpn_priv *ovpn = container_of(work, struct ovpn_priv,
13393ecfd934SAntonio Quartulli 					      keepalive_work.work);
13403ecfd934SAntonio Quartulli 	time64_t next_run = 0, now = ktime_get_real_seconds();
13413ecfd934SAntonio Quartulli 	LLIST_HEAD(release_list);
13423ecfd934SAntonio Quartulli 
13433ecfd934SAntonio Quartulli 	spin_lock_bh(&ovpn->lock);
13443ecfd934SAntonio Quartulli 	switch (ovpn->mode) {
13453ecfd934SAntonio Quartulli 	case OVPN_MODE_MP:
13463ecfd934SAntonio Quartulli 		next_run = ovpn_peer_keepalive_work_mp(ovpn, now,
13473ecfd934SAntonio Quartulli 						       &release_list);
13483ecfd934SAntonio Quartulli 		break;
13493ecfd934SAntonio Quartulli 	case OVPN_MODE_P2P:
13503ecfd934SAntonio Quartulli 		next_run = ovpn_peer_keepalive_work_p2p(ovpn, now,
13513ecfd934SAntonio Quartulli 							&release_list);
13523ecfd934SAntonio Quartulli 		break;
13533ecfd934SAntonio Quartulli 	}
13543ecfd934SAntonio Quartulli 
13553ecfd934SAntonio Quartulli 	/* prevent rearming if the interface is being destroyed */
1356adcdaac5SAntonio Quartulli 	if (next_run > 0) {
13573ecfd934SAntonio Quartulli 		netdev_dbg(ovpn->dev,
13583ecfd934SAntonio Quartulli 			   "scheduling keepalive work: now=%llu next_run=%llu delta=%llu\n",
13593ecfd934SAntonio Quartulli 			   next_run, now, next_run - now);
13603ecfd934SAntonio Quartulli 		schedule_delayed_work(&ovpn->keepalive_work,
13613ecfd934SAntonio Quartulli 				      (next_run - now) * HZ);
13623ecfd934SAntonio Quartulli 	}
13633ecfd934SAntonio Quartulli 	unlock_ovpn(ovpn, &release_list);
13643ecfd934SAntonio Quartulli }
1365