// SPDX-License-Identifier: GPL-2.0
/* OpenVPN data channel offload
*
* Copyright (C) 2020-2025 OpenVPN, Inc.
*
* Author: James Yonan <james@openvpn.net>
* Antonio Quartulli <antonio@openvpn.net>
*/
#include <linux/skbuff.h>
#include <linux/list.h>
#include <linux/hashtable.h>
#include <net/ip6_route.h>
#include "ovpnpriv.h"
#include "bind.h"
#include "pktid.h"
#include "crypto.h"
#include "io.h"
#include "main.h"
#include "netlink.h"
#include "peer.h"
#include "socket.h"
static void unlock_ovpn(struct ovpn_priv *ovpn,
struct llist_head *release_list)
__releases(&ovpn->lock)
{
struct ovpn_peer *peer;
spin_unlock_bh(&ovpn->lock);
llist_for_each_entry(peer, release_list->first, release_entry) {
ovpn_socket_release(peer);
ovpn_peer_put(peer);
}
}
/**
* ovpn_peer_keepalive_set - configure keepalive values for peer
* @peer: the peer to configure
* @interval: outgoing keepalive interval
* @timeout: incoming keepalive timeout
*/
void ovpn_peer_keepalive_set(struct ovpn_peer *peer, u32 interval, u32 timeout)
{
time64_t now = ktime_get_real_seconds();
netdev_dbg(peer->ovpn->dev,
"scheduling keepalive for peer %u: interval=%u timeout=%u\n",
peer->id, interval, timeout);
peer->keepalive_interval = interval;
WRITE_ONCE(peer->last_sent, now);
peer->keepalive_xmit_exp = now + interval;
peer->keepalive_timeout = timeout;
WRITE_ONCE(peer->last_recv, now);
peer->keepalive_recv_exp = now + timeout;
/* now that interval and timeout have been changed, kick
* off the worker so that the next delay can be recomputed
*/
mod_delayed_work(system_wq, &peer->ovpn->keepalive_work, 0);
}
/**
* ovpn_peer_keepalive_send - periodic worker sending keepalive packets
* @work: pointer to the work member of the related peer object
*
* NOTE: the reference to peer is not dropped because it gets inherited
* by ovpn_xmit_special()
*/
static void ovpn_peer_keepalive_send(struct work_struct *work)
{
struct