mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
ovpn: add basic interface creation/destruction/management routines
Add basic infrastructure for handling ovpn interfaces. Tested-by: Donald Hunter <donald.hunter@gmail.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net> Link: https://patch.msgid.link/20250415-b4-ovpn-v26-3-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>
This commit is contained in:
parent
b7a63391aa
commit
c2d950c467
8 changed files with 201 additions and 2 deletions
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
22
drivers/net/ovpn/io.c
Normal file
22
drivers/net/ovpn/io.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
// 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;
|
||||
}
|
24
drivers/net/ovpn/io.h
Normal file
24
drivers/net/ovpn/io.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* 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_ */
|
|
@ -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)
|
||||
|
|
|
@ -10,12 +10,17 @@
|
|||
#ifndef _NET_OVPN_OVPNSTRUCT_H_
|
||||
#define _NET_OVPN_OVPNSTRUCT_H_
|
||||
|
||||
#include <uapi/linux/if_link.h>
|
||||
#include <uapi/linux/ovpn.h>
|
||||
|
||||
/**
|
||||
* struct ovpn_priv - per ovpn interface state
|
||||
* @dev: the actual netdev representing the tunnel
|
||||
* @mode: device operation mode (i.e. p2p, mp, ..)
|
||||
*/
|
||||
struct ovpn_priv {
|
||||
struct net_device *dev;
|
||||
enum ovpn_mode mode;
|
||||
};
|
||||
|
||||
#endif /* _NET_OVPN_OVPNSTRUCT_H_ */
|
||||
|
|
38
drivers/net/ovpn/proto.h
Normal file
38
drivers/net/ovpn/proto.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* OpenVPN data channel offload
|
||||
*
|
||||
* Copyright (C) 2020-2025 OpenVPN, Inc.
|
||||
*
|
||||
* Author: Antonio Quartulli <antonio@openvpn.net>
|
||||
* James Yonan <james@openvpn.net>
|
||||
*/
|
||||
|
||||
#ifndef _NET_OVPN_PROTO_H_
|
||||
#define _NET_OVPN_PROTO_H_
|
||||
|
||||
/* When the OpenVPN protocol is ran in AEAD mode, use
|
||||
* the OpenVPN packet ID as the AEAD nonce:
|
||||
*
|
||||
* 00000005 521c3b01 4308c041
|
||||
* [seq # ] [ nonce_tail ]
|
||||
* [ 12-byte full IV ] -> OVPN_NONCE_SIZE
|
||||
* [4-bytes -> OVPN_NONCE_WIRE_SIZE
|
||||
* on wire]
|
||||
*/
|
||||
|
||||
/* nonce size (96bits) as required by AEAD ciphers */
|
||||
#define OVPN_NONCE_SIZE 12
|
||||
/* last 8 bytes of AEAD nonce: provided by userspace and usually derived
|
||||
* from key material generated during TLS handshake
|
||||
*/
|
||||
#define OVPN_NONCE_TAIL_SIZE 8
|
||||
|
||||
/* OpenVPN nonce size reduced by 8-byte nonce tail -- this is the
|
||||
* size of the AEAD Associated Data (AD) sent over the wire
|
||||
* and is normally the head of the IV
|
||||
*/
|
||||
#define OVPN_NONCE_WIRE_SIZE (OVPN_NONCE_SIZE - OVPN_NONCE_TAIL_SIZE)
|
||||
|
||||
#define OVPN_OPCODE_SIZE 4 /* DATA_V2 opcode size */
|
||||
|
||||
#endif /* _NET_OVPN_PROTO_H_ */
|
|
@ -1986,4 +1986,19 @@ enum {
|
|||
|
||||
#define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1)
|
||||
|
||||
/* OVPN section */
|
||||
|
||||
enum ovpn_mode {
|
||||
OVPN_MODE_P2P,
|
||||
OVPN_MODE_MP,
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_OVPN_UNSPEC,
|
||||
IFLA_OVPN_MODE,
|
||||
__IFLA_OVPN_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_OVPN_MAX (__IFLA_OVPN_MAX - 1)
|
||||
|
||||
#endif /* _UAPI_LINUX_IF_LINK_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue