Skip to content

Commit c2d950c

Browse files
ordexPaolo Abeni
authored andcommitted
ovpn: add basic interface creation/destruction/management routines
Add basic infrastructure for handling ovpn interfaces. Tested-by: Donald Hunter <[email protected]> Signed-off-by: Antonio Quartulli <[email protected]> Link: https://patch.msgid.link/[email protected] Reviewed-by: Sabrina Dubroca <[email protected]> Tested-by: Oleksandr Natalenko <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent b7a6339 commit c2d950c

File tree

8 files changed

+201
-2
lines changed

8 files changed

+201
-2
lines changed

Documentation/netlink/specs/rt-link.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,12 @@ definitions:
938938
entries:
939939
- name: none
940940
- name: default
941+
-
942+
name: ovpn-mode
943+
type: enum
944+
entries:
945+
- p2p
946+
- mp
941947

942948
attribute-sets:
943949
-
@@ -2272,6 +2278,13 @@ attribute-sets:
22722278
-
22732279
name: tailroom
22742280
type: u16
2281+
-
2282+
name: linkinfo-ovpn-attrs
2283+
attributes:
2284+
-
2285+
name: mode
2286+
type: u8
2287+
enum: ovpn-mode
22752288

22762289
sub-messages:
22772290
-
@@ -2322,6 +2335,9 @@ sub-messages:
23222335
-
23232336
value: netkit
23242337
attribute-set: linkinfo-netkit-attrs
2338+
-
2339+
value: ovpn
2340+
attribute-set: linkinfo-ovpn-attrs
23252341
-
23262342
name: linkinfo-member-data-msg
23272343
formats:

drivers/net/ovpn/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88

99
obj-$(CONFIG_OVPN) := ovpn.o
1010
ovpn-y += main.o
11+
ovpn-y += io.o
1112
ovpn-y += netlink.o
1213
ovpn-y += netlink-gen.o

drivers/net/ovpn/io.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* OpenVPN data channel offload
3+
*
4+
* Copyright (C) 2019-2025 OpenVPN, Inc.
5+
*
6+
* Author: James Yonan <[email protected]>
7+
* Antonio Quartulli <[email protected]>
8+
*/
9+
10+
#include <linux/netdevice.h>
11+
#include <linux/skbuff.h>
12+
13+
#include "io.h"
14+
15+
/* Send user data to the network
16+
*/
17+
netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)
18+
{
19+
skb_tx_error(skb);
20+
kfree_skb(skb);
21+
return NET_XMIT_DROP;
22+
}

drivers/net/ovpn/io.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/* OpenVPN data channel offload
3+
*
4+
* Copyright (C) 2019-2025 OpenVPN, Inc.
5+
*
6+
* Author: James Yonan <[email protected]>
7+
* Antonio Quartulli <[email protected]>
8+
*/
9+
10+
#ifndef _NET_OVPN_OVPN_H_
11+
#define _NET_OVPN_OVPN_H_
12+
13+
/* DATA_V2 header size with AEAD encryption */
14+
#define OVPN_HEAD_ROOM (OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE + \
15+
16 /* AEAD TAG length */ + \
16+
max(sizeof(struct udphdr), sizeof(struct tcphdr)) +\
17+
max(sizeof(struct ipv6hdr), sizeof(struct iphdr)))
18+
19+
/* max padding required by encryption */
20+
#define OVPN_MAX_PADDING 16
21+
22+
netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev);
23+
24+
#endif /* _NET_OVPN_OVPN_H_ */

drivers/net/ovpn/main.c

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,28 @@
1010
#include <linux/genetlink.h>
1111
#include <linux/module.h>
1212
#include <linux/netdevice.h>
13+
#include <linux/inetdevice.h>
14+
#include <net/ip.h>
1315
#include <net/rtnetlink.h>
14-
#include <uapi/linux/ovpn.h>
16+
#include <uapi/linux/if_arp.h>
1517

1618
#include "ovpnpriv.h"
1719
#include "main.h"
1820
#include "netlink.h"
21+
#include "io.h"
22+
#include "proto.h"
1923

2024
static const struct net_device_ops ovpn_netdev_ops = {
25+
.ndo_start_xmit = ovpn_net_xmit,
26+
};
27+
28+
static const struct device_type ovpn_type = {
29+
.name = OVPN_FAMILY_NAME,
30+
};
31+
32+
static const struct nla_policy ovpn_policy[IFLA_OVPN_MAX + 1] = {
33+
[IFLA_OVPN_MODE] = NLA_POLICY_RANGE(NLA_U8, OVPN_MODE_P2P,
34+
OVPN_MODE_MP),
2135
};
2236

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

48+
static void ovpn_setup(struct net_device *dev)
49+
{
50+
netdev_features_t feat = NETIF_F_SG | NETIF_F_GSO |
51+
NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA;
52+
53+
dev->needs_free_netdev = true;
54+
55+
dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
56+
57+
dev->netdev_ops = &ovpn_netdev_ops;
58+
59+
dev->hard_header_len = 0;
60+
dev->addr_len = 0;
61+
dev->mtu = ETH_DATA_LEN - OVPN_HEAD_ROOM;
62+
dev->min_mtu = IPV4_MIN_MTU;
63+
dev->max_mtu = IP_MAX_MTU - OVPN_HEAD_ROOM;
64+
65+
dev->type = ARPHRD_NONE;
66+
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
67+
dev->priv_flags |= IFF_NO_QUEUE;
68+
69+
dev->lltx = true;
70+
dev->features |= feat;
71+
dev->hw_features |= feat;
72+
dev->hw_enc_features |= feat;
73+
74+
dev->needed_headroom = ALIGN(OVPN_HEAD_ROOM, 4);
75+
dev->needed_tailroom = OVPN_MAX_PADDING;
76+
77+
SET_NETDEV_DEVTYPE(dev, &ovpn_type);
78+
}
79+
3480
static int ovpn_newlink(struct net_device *dev,
3581
struct rtnl_newlink_params *params,
3682
struct netlink_ext_ack *extack)
3783
{
38-
return -EOPNOTSUPP;
84+
struct ovpn_priv *ovpn = netdev_priv(dev);
85+
struct nlattr **data = params->data;
86+
enum ovpn_mode mode = OVPN_MODE_P2P;
87+
88+
if (data && data[IFLA_OVPN_MODE]) {
89+
mode = nla_get_u8(data[IFLA_OVPN_MODE]);
90+
netdev_dbg(dev, "setting device mode: %u\n", mode);
91+
}
92+
93+
ovpn->dev = dev;
94+
ovpn->mode = mode;
95+
96+
/* turn carrier explicitly off after registration, this way state is
97+
* clearly defined
98+
*/
99+
netif_carrier_off(dev);
100+
101+
return register_netdevice(dev);
102+
}
103+
104+
static int ovpn_fill_info(struct sk_buff *skb, const struct net_device *dev)
105+
{
106+
struct ovpn_priv *ovpn = netdev_priv(dev);
107+
108+
if (nla_put_u8(skb, IFLA_OVPN_MODE, ovpn->mode))
109+
return -EMSGSIZE;
110+
111+
return 0;
39112
}
40113

41114
static struct rtnl_link_ops ovpn_link_ops = {
42115
.kind = "ovpn",
43116
.netns_refund = false,
117+
.priv_size = sizeof(struct ovpn_priv),
118+
.setup = ovpn_setup,
119+
.policy = ovpn_policy,
120+
.maxtype = IFLA_OVPN_MAX,
44121
.newlink = ovpn_newlink,
45122
.dellink = unregister_netdevice_queue,
123+
.fill_info = ovpn_fill_info,
46124
};
47125

48126
static int __init ovpn_init(void)

drivers/net/ovpn/ovpnpriv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,17 @@
1010
#ifndef _NET_OVPN_OVPNSTRUCT_H_
1111
#define _NET_OVPN_OVPNSTRUCT_H_
1212

13+
#include <uapi/linux/if_link.h>
14+
#include <uapi/linux/ovpn.h>
15+
1316
/**
1417
* struct ovpn_priv - per ovpn interface state
1518
* @dev: the actual netdev representing the tunnel
19+
* @mode: device operation mode (i.e. p2p, mp, ..)
1620
*/
1721
struct ovpn_priv {
1822
struct net_device *dev;
23+
enum ovpn_mode mode;
1924
};
2025

2126
#endif /* _NET_OVPN_OVPNSTRUCT_H_ */

drivers/net/ovpn/proto.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/* OpenVPN data channel offload
3+
*
4+
* Copyright (C) 2020-2025 OpenVPN, Inc.
5+
*
6+
* Author: Antonio Quartulli <[email protected]>
7+
* James Yonan <[email protected]>
8+
*/
9+
10+
#ifndef _NET_OVPN_PROTO_H_
11+
#define _NET_OVPN_PROTO_H_
12+
13+
/* When the OpenVPN protocol is ran in AEAD mode, use
14+
* the OpenVPN packet ID as the AEAD nonce:
15+
*
16+
* 00000005 521c3b01 4308c041
17+
* [seq # ] [ nonce_tail ]
18+
* [ 12-byte full IV ] -> OVPN_NONCE_SIZE
19+
* [4-bytes -> OVPN_NONCE_WIRE_SIZE
20+
* on wire]
21+
*/
22+
23+
/* nonce size (96bits) as required by AEAD ciphers */
24+
#define OVPN_NONCE_SIZE 12
25+
/* last 8 bytes of AEAD nonce: provided by userspace and usually derived
26+
* from key material generated during TLS handshake
27+
*/
28+
#define OVPN_NONCE_TAIL_SIZE 8
29+
30+
/* OpenVPN nonce size reduced by 8-byte nonce tail -- this is the
31+
* size of the AEAD Associated Data (AD) sent over the wire
32+
* and is normally the head of the IV
33+
*/
34+
#define OVPN_NONCE_WIRE_SIZE (OVPN_NONCE_SIZE - OVPN_NONCE_TAIL_SIZE)
35+
36+
#define OVPN_OPCODE_SIZE 4 /* DATA_V2 opcode size */
37+
38+
#endif /* _NET_OVPN_PROTO_H_ */

include/uapi/linux/if_link.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,4 +1986,19 @@ enum {
19861986

19871987
#define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1)
19881988

1989+
/* OVPN section */
1990+
1991+
enum ovpn_mode {
1992+
OVPN_MODE_P2P,
1993+
OVPN_MODE_MP,
1994+
};
1995+
1996+
enum {
1997+
IFLA_OVPN_UNSPEC,
1998+
IFLA_OVPN_MODE,
1999+
__IFLA_OVPN_MAX,
2000+
};
2001+
2002+
#define IFLA_OVPN_MAX (__IFLA_OVPN_MAX - 1)
2003+
19892004
#endif /* _UAPI_LINUX_IF_LINK_H */

0 commit comments

Comments
 (0)