drivers/net/ovpn/udp.c

Source file repositories/reference/linux-study-clean/drivers/net/ovpn/udp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ovpn/udp.c
Extension
.c
Size
12046 bytes
Lines
449
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*  OpenVPN data channel offload
 *
 *  Copyright (C) 2019-2025 OpenVPN, Inc.
 *
 *  Author:	Antonio Quartulli <antonio@openvpn.net>
 */

#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/skbuff.h>
#include <linux/socket.h>
#include <linux/udp.h>
#include <net/addrconf.h>
#include <net/dst_cache.h>
#include <net/route.h>
#include <net/transp_v6.h>
#include <net/udp.h>
#include <net/udp_tunnel.h>

#include "ovpnpriv.h"
#include "main.h"
#include "bind.h"
#include "io.h"
#include "peer.h"
#include "proto.h"
#include "socket.h"
#include "udp.h"

/* Retrieve the corresponding ovpn object from a UDP socket
 * rcu_read_lock must be held on entry
 */
static struct ovpn_socket *ovpn_socket_from_udp_sock(struct sock *sk)
{
	struct ovpn_socket *ovpn_sock;

	if (unlikely(READ_ONCE(udp_sk(sk)->encap_type) != UDP_ENCAP_OVPNINUDP))
		return NULL;

	ovpn_sock = rcu_dereference_sk_user_data(sk);
	if (unlikely(!ovpn_sock))
		return NULL;

	/* make sure that sk matches our stored transport socket */
	if (unlikely(!ovpn_sock->sk || sk != ovpn_sock->sk))
		return NULL;

	return ovpn_sock;
}

/**
 * ovpn_udp_encap_recv - Start processing a received UDP packet.
 * @sk: socket over which the packet was received
 * @skb: the received packet
 *
 * If the first byte of the payload is:
 * - DATA_V2 the packet is accepted for further processing,
 * - DATA_V1 the packet is dropped as not supported,
 * - anything else the packet is forwarded to the UDP stack for
 *   delivery to user space.
 *
 * Return:
 *  0 if skb was consumed or dropped
 * >0 if skb should be passed up to userspace as UDP (packet not consumed)
 * <0 if skb should be resubmitted as proto -N (packet not consumed)
 */
static int ovpn_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
{
	struct ovpn_socket *ovpn_sock;
	struct ovpn_priv *ovpn;
	struct ovpn_peer *peer;
	u32 peer_id;
	u8 opcode;

	ovpn_sock = ovpn_socket_from_udp_sock(sk);
	if (unlikely(!ovpn_sock)) {
		net_err_ratelimited("ovpn: %s invoked on non ovpn socket\n",
				    __func__);
		goto drop_noovpn;
	}

	ovpn = ovpn_sock->ovpn;
	if (unlikely(!ovpn)) {
		net_err_ratelimited("ovpn: cannot obtain ovpn object from UDP socket\n");
		goto drop_noovpn;
	}

	/* Make sure the first 4 bytes of the skb data buffer after the UDP
	 * header are accessible.
	 * They are required to fetch the OP code, the key ID and the peer ID.

Annotation

Implementation Notes