xref: /linux/drivers/net/ovpn/bind.h (revision 0ce92d548b44649a8de706f9bb9e74a4ed2f18a7)
1 /* SPDX-License-Identifier: GPL-2.0-only */
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 #ifndef _NET_OVPN_OVPNBIND_H_
11 #define _NET_OVPN_OVPNBIND_H_
12 
13 #include <net/ip.h>
14 #include <linux/in.h>
15 #include <linux/in6.h>
16 #include <linux/rcupdate.h>
17 #include <linux/skbuff.h>
18 #include <linux/spinlock.h>
19 
20 struct ovpn_peer;
21 
22 /**
23  * union ovpn_sockaddr - basic transport layer address
24  * @in4: IPv4 address
25  * @in6: IPv6 address
26  */
27 union ovpn_sockaddr {
28 	struct sockaddr_in in4;
29 	struct sockaddr_in6 in6;
30 };
31 
32 /**
33  * struct ovpn_bind - remote peer binding
34  * @remote: the remote peer sockaddress
35  * @local: local endpoint used to talk to the peer
36  * @local.ipv4: local IPv4 used to talk to the peer
37  * @local.ipv6: local IPv6 used to talk to the peer
38  * @rcu: used to schedule RCU cleanup job
39  */
40 struct ovpn_bind {
41 	union ovpn_sockaddr remote;  /* remote sockaddr */
42 
43 	union {
44 		struct in_addr ipv4;
45 		struct in6_addr ipv6;
46 	} local;
47 
48 	struct rcu_head rcu;
49 };
50 
51 /**
52  * ovpn_bind_skb_src_match - match packet source with binding
53  * @bind: the binding to match
54  * @skb: the packet to match
55  *
56  * Return: true if the packet source matches the remote peer sockaddr
57  * in the binding
58  */
59 static inline bool ovpn_bind_skb_src_match(const struct ovpn_bind *bind,
60 					   const struct sk_buff *skb)
61 {
62 	const union ovpn_sockaddr *remote;
63 
64 	if (unlikely(!bind))
65 		return false;
66 
67 	remote = &bind->remote;
68 
69 	switch (skb->protocol) {
70 	case htons(ETH_P_IP):
71 		if (unlikely(remote->in4.sin_family != AF_INET))
72 			return false;
73 
74 		if (unlikely(remote->in4.sin_addr.s_addr != ip_hdr(skb)->saddr))
75 			return false;
76 
77 		if (unlikely(remote->in4.sin_port != udp_hdr(skb)->source))
78 			return false;
79 		break;
80 	case htons(ETH_P_IPV6):
81 		if (unlikely(remote->in6.sin6_family != AF_INET6))
82 			return false;
83 
84 		if (unlikely(!ipv6_addr_equal(&remote->in6.sin6_addr,
85 					      &ipv6_hdr(skb)->saddr)))
86 			return false;
87 
88 		if (unlikely(remote->in6.sin6_port != udp_hdr(skb)->source))
89 			return false;
90 		break;
91 	default:
92 		return false;
93 	}
94 
95 	return true;
96 }
97 
98 struct ovpn_bind *ovpn_bind_from_sockaddr(const struct sockaddr_storage *sa);
99 void ovpn_bind_reset(struct ovpn_peer *peer, struct ovpn_bind *bind);
100 
101 #endif /* _NET_OVPN_OVPNBIND_H_ */
102