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