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:
|
entries:
|
||||||
- name: none
|
- name: none
|
||||||
- name: default
|
- name: default
|
||||||
|
-
|
||||||
|
name: ovpn-mode
|
||||||
|
type: enum
|
||||||
|
entries:
|
||||||
|
- p2p
|
||||||
|
- mp
|
||||||
|
|
||||||
attribute-sets:
|
attribute-sets:
|
||||||
-
|
-
|
||||||
|
@ -2272,6 +2278,13 @@ attribute-sets:
|
||||||
-
|
-
|
||||||
name: tailroom
|
name: tailroom
|
||||||
type: u16
|
type: u16
|
||||||
|
-
|
||||||
|
name: linkinfo-ovpn-attrs
|
||||||
|
attributes:
|
||||||
|
-
|
||||||
|
name: mode
|
||||||
|
type: u8
|
||||||
|
enum: ovpn-mode
|
||||||
|
|
||||||
sub-messages:
|
sub-messages:
|
||||||
-
|
-
|
||||||
|
@ -2322,6 +2335,9 @@ sub-messages:
|
||||||
-
|
-
|
||||||
value: netkit
|
value: netkit
|
||||||
attribute-set: linkinfo-netkit-attrs
|
attribute-set: linkinfo-netkit-attrs
|
||||||
|
-
|
||||||
|
value: ovpn
|
||||||
|
attribute-set: linkinfo-ovpn-attrs
|
||||||
-
|
-
|
||||||
name: linkinfo-member-data-msg
|
name: linkinfo-member-data-msg
|
||||||
formats:
|
formats:
|
||||||
|
|
|
@ -8,5 +8,6 @@
|
||||||
|
|
||||||
obj-$(CONFIG_OVPN) := ovpn.o
|
obj-$(CONFIG_OVPN) := ovpn.o
|
||||||
ovpn-y += main.o
|
ovpn-y += main.o
|
||||||
|
ovpn-y += io.o
|
||||||
ovpn-y += netlink.o
|
ovpn-y += netlink.o
|
||||||
ovpn-y += netlink-gen.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/genetlink.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/inetdevice.h>
|
||||||
|
#include <net/ip.h>
|
||||||
#include <net/rtnetlink.h>
|
#include <net/rtnetlink.h>
|
||||||
#include <uapi/linux/ovpn.h>
|
#include <uapi/linux/if_arp.h>
|
||||||
|
|
||||||
#include "ovpnpriv.h"
|
#include "ovpnpriv.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "netlink.h"
|
#include "netlink.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "proto.h"
|
||||||
|
|
||||||
static const struct net_device_ops ovpn_netdev_ops = {
|
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;
|
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,
|
static int ovpn_newlink(struct net_device *dev,
|
||||||
struct rtnl_newlink_params *params,
|
struct rtnl_newlink_params *params,
|
||||||
struct netlink_ext_ack *extack)
|
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 = {
|
static struct rtnl_link_ops ovpn_link_ops = {
|
||||||
.kind = "ovpn",
|
.kind = "ovpn",
|
||||||
.netns_refund = false,
|
.netns_refund = false,
|
||||||
|
.priv_size = sizeof(struct ovpn_priv),
|
||||||
|
.setup = ovpn_setup,
|
||||||
|
.policy = ovpn_policy,
|
||||||
|
.maxtype = IFLA_OVPN_MAX,
|
||||||
.newlink = ovpn_newlink,
|
.newlink = ovpn_newlink,
|
||||||
.dellink = unregister_netdevice_queue,
|
.dellink = unregister_netdevice_queue,
|
||||||
|
.fill_info = ovpn_fill_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init ovpn_init(void)
|
static int __init ovpn_init(void)
|
||||||
|
|
|
@ -10,12 +10,17 @@
|
||||||
#ifndef _NET_OVPN_OVPNSTRUCT_H_
|
#ifndef _NET_OVPN_OVPNSTRUCT_H_
|
||||||
#define _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
|
* struct ovpn_priv - per ovpn interface state
|
||||||
* @dev: the actual netdev representing the tunnel
|
* @dev: the actual netdev representing the tunnel
|
||||||
|
* @mode: device operation mode (i.e. p2p, mp, ..)
|
||||||
*/
|
*/
|
||||||
struct ovpn_priv {
|
struct ovpn_priv {
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
|
enum ovpn_mode mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _NET_OVPN_OVPNSTRUCT_H_ */
|
#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)
|
#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 */
|
#endif /* _UAPI_LINUX_IF_LINK_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue