xref: /linux/drivers/net/ovpn/bind.c (revision fcab107abe1ab5be9dbe874baa722372da8f4f73)
1 // SPDX-License-Identifier: GPL-2.0
2 /*  OpenVPN data channel offload
3  *
4  *  Copyright (C) 2012-2025 OpenVPN, Inc.
5  *
6  *  Author:	James Yonan <james@openvpn.net>
7  *		Antonio Quartulli <antonio@openvpn.net>
8  */
9 
10 #include <linux/netdevice.h>
11 #include <linux/socket.h>
12 
13 #include "ovpnpriv.h"
14 #include "bind.h"
15 #include "peer.h"
16 
17 /**
18  * ovpn_bind_from_sockaddr - retrieve binding matching sockaddr
19  * @ss: the sockaddr to match
20  *
21  * Return: the bind matching the passed sockaddr if found, NULL otherwise
22  */
23 struct ovpn_bind *ovpn_bind_from_sockaddr(const struct sockaddr_storage *ss)
24 {
25 	struct ovpn_bind *bind;
26 	size_t sa_len;
27 
28 	if (ss->ss_family == AF_INET)
29 		sa_len = sizeof(struct sockaddr_in);
30 	else if (ss->ss_family == AF_INET6)
31 		sa_len = sizeof(struct sockaddr_in6);
32 	else
33 		return ERR_PTR(-EAFNOSUPPORT);
34 
35 	bind = kzalloc(sizeof(*bind), GFP_ATOMIC);
36 	if (unlikely(!bind))
37 		return ERR_PTR(-ENOMEM);
38 
39 	memcpy(&bind->remote, ss, sa_len);
40 
41 	return bind;
42 }
43 
44 /**
45  * ovpn_bind_reset - assign new binding to peer
46  * @peer: the peer whose binding has to be replaced
47  * @new: the new bind to assign
48  */
49 void ovpn_bind_reset(struct ovpn_peer *peer, struct ovpn_bind *new)
50 {
51 	lockdep_assert_held(&peer->lock);
52 
53 	kfree_rcu(rcu_replace_pointer(peer->bind, new,
54 				      lockdep_is_held(&peer->lock)), rcu);
55 }
56