Commit c2d950c4 authored by Antonio Quartulli's avatar Antonio Quartulli Committed by Paolo Abeni
Browse files

ovpn: add basic interface creation/destruction/management routines

parent b7a63391
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -938,6 +938,12 @@ definitions:
    entries:
      - name: none
      - name: default
  -
    name: ovpn-mode
    type: enum
    entries:
      - p2p
      - mp

attribute-sets:
  -
@@ -2272,6 +2278,13 @@ attribute-sets:
      -
        name: tailroom
        type: u16
  -
    name: linkinfo-ovpn-attrs
    attributes:
      -
        name: mode
        type: u8
        enum: ovpn-mode

sub-messages:
  -
@@ -2322,6 +2335,9 @@ sub-messages:
      -
        value: netkit
        attribute-set: linkinfo-netkit-attrs
      -
        value: ovpn
        attribute-set: linkinfo-ovpn-attrs
  -
    name: linkinfo-member-data-msg
    formats:
+1 −0
Original line number Diff line number Diff line
@@ -8,5 +8,6 @@

obj-$(CONFIG_OVPN) := ovpn.o
ovpn-y += main.o
ovpn-y += io.o
ovpn-y += netlink.o
ovpn-y += netlink-gen.o

drivers/net/ovpn/io.c

0 → 100644
+22 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*  OpenVPN data channel offload
 *
 *  Copyright (C) 2019-2025 OpenVPN, Inc.
 *
 *  Author:	James Yonan <james@openvpn.net>
 *		Antonio Quartulli <antonio@openvpn.net>
 */

#include <linux/netdevice.h>
#include <linux/skbuff.h>

#include "io.h"

/* Send user data to the network
 */
netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)
{
	skb_tx_error(skb);
	kfree_skb(skb);
	return NET_XMIT_DROP;
}

drivers/net/ovpn/io.h

0 → 100644
+24 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/* OpenVPN data channel offload
 *
 *  Copyright (C) 2019-2025 OpenVPN, Inc.
 *
 *  Author:	James Yonan <james@openvpn.net>
 *		Antonio Quartulli <antonio@openvpn.net>
 */

#ifndef _NET_OVPN_OVPN_H_
#define _NET_OVPN_OVPN_H_

/* DATA_V2 header size with AEAD encryption */
#define OVPN_HEAD_ROOM (OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE +	   \
			16 /* AEAD TAG length */ +			   \
			max(sizeof(struct udphdr), sizeof(struct tcphdr)) +\
			max(sizeof(struct ipv6hdr), sizeof(struct iphdr)))

/* max padding required by encryption */
#define OVPN_MAX_PADDING 16

netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev);

#endif /* _NET_OVPN_OVPN_H_ */
+80 −2
Original line number Diff line number Diff line
@@ -10,14 +10,28 @@
#include <linux/genetlink.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <net/ip.h>
#include <net/rtnetlink.h>
#include <uapi/linux/ovpn.h>
#include <uapi/linux/if_arp.h>

#include "ovpnpriv.h"
#include "main.h"
#include "netlink.h"
#include "io.h"
#include "proto.h"

static const struct net_device_ops ovpn_netdev_ops = {
	.ndo_start_xmit		= ovpn_net_xmit,
};

static const struct device_type ovpn_type = {
	.name = OVPN_FAMILY_NAME,
};

static const struct nla_policy ovpn_policy[IFLA_OVPN_MAX + 1] = {
	[IFLA_OVPN_MODE] = NLA_POLICY_RANGE(NLA_U8, OVPN_MODE_P2P,
					    OVPN_MODE_MP),
};

/**
@@ -31,18 +45,82 @@ bool ovpn_dev_is_valid(const struct net_device *dev)
	return dev->netdev_ops == &ovpn_netdev_ops;
}

static void ovpn_setup(struct net_device *dev)
{
	netdev_features_t feat = NETIF_F_SG | NETIF_F_GSO |
				 NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA;

	dev->needs_free_netdev = true;

	dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;

	dev->netdev_ops = &ovpn_netdev_ops;

	dev->hard_header_len = 0;
	dev->addr_len = 0;
	dev->mtu = ETH_DATA_LEN - OVPN_HEAD_ROOM;
	dev->min_mtu = IPV4_MIN_MTU;
	dev->max_mtu = IP_MAX_MTU - OVPN_HEAD_ROOM;

	dev->type = ARPHRD_NONE;
	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
	dev->priv_flags |= IFF_NO_QUEUE;

	dev->lltx = true;
	dev->features |= feat;
	dev->hw_features |= feat;
	dev->hw_enc_features |= feat;

	dev->needed_headroom = ALIGN(OVPN_HEAD_ROOM, 4);
	dev->needed_tailroom = OVPN_MAX_PADDING;

	SET_NETDEV_DEVTYPE(dev, &ovpn_type);
}

static int ovpn_newlink(struct net_device *dev,
			struct rtnl_newlink_params *params,
			struct netlink_ext_ack *extack)
{
	return -EOPNOTSUPP;
	struct ovpn_priv *ovpn = netdev_priv(dev);
	struct nlattr **data = params->data;
	enum ovpn_mode mode = OVPN_MODE_P2P;

	if (data && data[IFLA_OVPN_MODE]) {
		mode = nla_get_u8(data[IFLA_OVPN_MODE]);
		netdev_dbg(dev, "setting device mode: %u\n", mode);
	}

	ovpn->dev = dev;
	ovpn->mode = mode;

	/* turn carrier explicitly off after registration, this way state is
	 * clearly defined
	 */
	netif_carrier_off(dev);

	return register_netdevice(dev);
}

static int ovpn_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
	struct ovpn_priv *ovpn = netdev_priv(dev);

	if (nla_put_u8(skb, IFLA_OVPN_MODE, ovpn->mode))
		return -EMSGSIZE;

	return 0;
}

static struct rtnl_link_ops ovpn_link_ops = {
	.kind = "ovpn",
	.netns_refund = false,
	.priv_size = sizeof(struct ovpn_priv),
	.setup = ovpn_setup,
	.policy = ovpn_policy,
	.maxtype = IFLA_OVPN_MAX,
	.newlink = ovpn_newlink,
	.dellink = unregister_netdevice_queue,
	.fill_info = ovpn_fill_info,
};

static int __init ovpn_init(void)
Loading