mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
102 lines
2.3 KiB
C
102 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_ */
|