mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

An ovpn_peer object holds the whole status of a remote peer (regardless whether it is a server or a client). This includes status for crypto, tx/rx buffers, napi, etc. Only support for one peer is introduced (P2P mode). Multi peer support is introduced with a later patch. Along with the ovpn_peer, also the ovpn_bind object is introcued as the two are strictly related. An ovpn_bind object wraps a sockaddr representing the local coordinates being used to talk to a specific peer. Signed-off-by: Antonio Quartulli <antonio@openvpn.net> Link: https://patch.msgid.link/20250415-b4-ovpn-v26-5-577f6097b964@openvpn.net Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
101 lines
2.3 KiB
C
101 lines
2.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/* OpenVPN data channel offload
|
|
*
|
|
* Copyright (C) 2012-2025 OpenVPN, Inc.
|
|
*
|
|
* Author: James Yonan <james@openvpn.net>
|
|
* Antonio Quartulli <antonio@openvpn.net>
|
|
*/
|
|
|
|
#ifndef _NET_OVPN_OVPNBIND_H_
|
|
#define _NET_OVPN_OVPNBIND_H_
|
|
|
|
#include <net/ip.h>
|
|
#include <linux/in.h>
|
|
#include <linux/in6.h>
|
|
#include <linux/rcupdate.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/spinlock.h>
|
|
|
|
struct ovpn_peer;
|
|
|
|
/**
|
|
* union ovpn_sockaddr - basic transport layer address
|
|
* @in4: IPv4 address
|
|
* @in6: IPv6 address
|
|
*/
|
|
union ovpn_sockaddr {
|
|
struct sockaddr_in in4;
|
|
struct sockaddr_in6 in6;
|
|
};
|
|
|
|
/**
|
|
* struct ovpn_bind - remote peer binding
|
|
* @remote: the remote peer sockaddress
|
|
* @local: local endpoint used to talk to the peer
|
|
* @local.ipv4: local IPv4 used to talk to the peer
|
|
* @local.ipv6: local IPv6 used to talk to the peer
|
|
* @rcu: used to schedule RCU cleanup job
|
|
*/
|
|
struct ovpn_bind {
|
|
union ovpn_sockaddr remote; /* remote sockaddr */
|
|
|
|
union {
|
|
struct in_addr ipv4;
|
|
struct in6_addr ipv6;
|
|
} local;
|
|
|
|
struct rcu_head rcu;
|
|
};
|
|
|
|
/**
|
|
* ovpn_bind_skb_src_match - match packet source with binding
|
|
* @bind: the binding to match
|
|
* @skb: the packet to match
|
|
*
|
|
* Return: true if the packet source matches the remote peer sockaddr
|
|
* in the binding
|
|
*/
|
|
static inline bool ovpn_bind_skb_src_match(const struct ovpn_bind *bind,
|
|
const struct sk_buff *skb)
|
|
{
|
|
const union ovpn_sockaddr *remote;
|
|
|
|
if (unlikely(!bind))
|
|
return false;
|
|
|
|
remote = &bind->remote;
|
|
|
|
switch (skb->protocol) {
|
|
case htons(ETH_P_IP):
|
|
if (unlikely(remote->in4.sin_family != AF_INET))
|
|
return false;
|
|
|
|
if (unlikely(remote->in4.sin_addr.s_addr != ip_hdr(skb)->saddr))
|
|
return false;
|
|
|
|
if (unlikely(remote->in4.sin_port != udp_hdr(skb)->source))
|
|
return false;
|
|
break;
|
|
case htons(ETH_P_IPV6):
|
|
if (unlikely(remote->in6.sin6_family != AF_INET6))
|
|
return false;
|
|
|
|
if (unlikely(!ipv6_addr_equal(&remote->in6.sin6_addr,
|
|
&ipv6_hdr(skb)->saddr)))
|
|
return false;
|
|
|
|
if (unlikely(remote->in6.sin6_port != udp_hdr(skb)->source))
|
|
return false;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
struct ovpn_bind *ovpn_bind_from_sockaddr(const struct sockaddr_storage *sa);
|
|
void ovpn_bind_reset(struct ovpn_peer *peer, struct ovpn_bind *bind);
|
|
|
|
#endif /* _NET_OVPN_OVPNBIND_H_ */
|