Add basic infrastructure for handling ovpn interfaces.
Unified · Split
| @@ -938,6 +938,12 @@ definitions: · 937 unmodified lines | |||
| 938 | entries: | 938 | entries: |
| 939 | - name: none | 939 | - name: none |
| 940 | - name: default | 940 | - name: default |
| 941 | - | ||
| 942 | name: ovpn-mode | ||
| 943 | type: enum | ||
| 944 | entries: | ||
| 945 | - p2p | ||
| 946 | - mp | ||
| 941 | 947 | ||
| 942 | attribute-sets: | 948 | attribute-sets: |
| 943 | - | 949 | - |
| @@ -2272,6 +2278,13 @@ attribute-sets: · 1328 unmodified lines | |||
| 2272 | - | 2278 | - |
| 2273 | name: tailroom | 2279 | name: tailroom |
| 2274 | type: u16 | 2280 | type: u16 |
| 2281 | - | ||
| 2282 | name: linkinfo-ovpn-attrs | ||
| 2283 | attributes: | ||
| 2284 | - | ||
| 2285 | name: mode | ||
| 2286 | type: u8 | ||
| 2287 | enum: ovpn-mode | ||
| 2275 | 2288 | ||
| 2276 | sub-messages: | 2289 | sub-messages: |
| 2277 | - | 2290 | - |
| @@ -2322,6 +2335,9 @@ sub-messages: · 44 unmodified lines | |||
| 2322 | - | 2335 | - |
| 2323 | value: netkit | 2336 | value: netkit |
| 2324 | attribute-set: linkinfo-netkit-attrs | 2337 | attribute-set: linkinfo-netkit-attrs |
| 2338 | - | ||
| 2339 | value: ovpn | ||
| 2340 | attribute-set: linkinfo-ovpn-attrs | ||
| 2325 | - | 2341 | - |
| 2326 | name: linkinfo-member-data-msg | 2342 | name: linkinfo-member-data-msg |
| 2327 | formats: | 2343 | formats: |
| @@ -8,5 +8,6 @@ · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | obj-$(CONFIG_OVPN) := ovpn.o | 9 | obj-$(CONFIG_OVPN) := ovpn.o |
| 10 | ovpn-y += main.o | 10 | ovpn-y += main.o |
| 11 | ovpn-y += io.o | ||
| 11 | ovpn-y += netlink.o | 12 | ovpn-y += netlink.o |
| 12 | ovpn-y += netlink-gen.o | 13 | ovpn-y += netlink-gen.o |
| @@ -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 <james@openvpn.net> | ||
| 7 | * Antonio Quartulli <antonio@openvpn.net> | ||
| 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 | } | ||
| @@ -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 <james@openvpn.net> | ||
| 7 | * Antonio Quartulli <antonio@openvpn.net> | ||
| 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_ */ | ||
| @@ -10,14 +10,28 @@ · 9 unmodified lines | |||
| 10 | #include <linux/genetlink.h> | 10 | #include <linux/genetlink.h> |
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
| 13 | #include <linux/inetdevice.h> | ||
| 14 | #include <net/ip.h> | ||
| 13 | #include <net/rtnetlink.h> | 15 | #include <net/rtnetlink.h> |
| 14 | #include <uapi/linux/ovpn.h> | 16 | #include <uapi/linux/if_arp.h> |
| 15 | 17 | ||
| 16 | #include "ovpnpriv.h" | 18 | #include "ovpnpriv.h" |
| 17 | #include "main.h" | 19 | #include "main.h" |
| 18 | #include "netlink.h" | 20 | #include "netlink.h" |
| 21 | #include "io.h" | ||
| 22 | #include "proto.h" | ||
| 19 | 23 | ||
| 20 | static const struct net_device_ops ovpn_netdev_ops = { | 24 | 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), | ||
| 21 | }; | 35 | }; |
| 22 | 36 | ||
| 23 | /** | 37 | /** |
| @@ -31,18 +45,82 @@ bool ovpn_dev_is_valid(const struct net_device *dev) · 7 unmodified lines | |||
| 31 | return dev->netdev_ops == &ovpn_netdev_ops; | 45 | return dev->netdev_ops == &ovpn_netdev_ops; |
| 32 | } | 46 | } |
| 33 | 47 | ||
| 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 | |||
| 34 | static int ovpn_newlink(struct net_device *dev, | 80 | static int ovpn_newlink(struct net_device *dev, |
| 35 | struct rtnl_newlink_params *params, | 81 | struct rtnl_newlink_params *params, |
| 36 | struct netlink_ext_ack *extack) | 82 | struct netlink_ext_ack *extack) |
| 37 | { | 83 | { |
| 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; | ||
| 39 | } | 112 | } |
| 40 | 113 | ||
| 41 | static struct rtnl_link_ops ovpn_link_ops = { | 114 | static struct rtnl_link_ops ovpn_link_ops = { |
| 42 | .kind = "ovpn", | 115 | .kind = "ovpn", |
| 43 | .netns_refund = false, | 116 | .netns_refund = false, |
| 117 | .priv_size = sizeof(struct ovpn_priv), | ||
| 118 | .setup = ovpn_setup, | ||
| 119 | .policy = ovpn_policy, | ||
| 120 | .maxtype = IFLA_OVPN_MAX, | ||
| 44 | .newlink = ovpn_newlink, | 121 | .newlink = ovpn_newlink, |
| 45 | .dellink = unregister_netdevice_queue, | 122 | .dellink = unregister_netdevice_queue, |
| 123 | .fill_info = ovpn_fill_info, | ||
| 46 | }; | 124 | }; |
| 47 | 125 | ||
| 48 | static int __init ovpn_init(void) | 126 | static int __init ovpn_init(void) |
| @@ -10,12 +10,17 @@ · 9 unmodified lines | |||
| 10 | #ifndef _NET_OVPN_OVPNSTRUCT_H_ | 10 | #ifndef _NET_OVPN_OVPNSTRUCT_H_ |
| 11 | #define _NET_OVPN_OVPNSTRUCT_H_ | 11 | #define _NET_OVPN_OVPNSTRUCT_H_ |
| 12 | 12 | ||
| 13 | #include <uapi/linux/if_link.h> | ||
| 14 | #include <uapi/linux/ovpn.h> | ||
| 15 | |||
| 13 | /** | 16 | /** |
| 14 | * struct ovpn_priv - per ovpn interface state | 17 | * struct ovpn_priv - per ovpn interface state |
| 15 | * @dev: the actual netdev representing the tunnel | 18 | * @dev: the actual netdev representing the tunnel |
| 19 | * @mode: device operation mode (i.e. p2p, mp, ..) | ||
| 16 | */ | 20 | */ |
| 17 | struct ovpn_priv { | 21 | struct ovpn_priv { |
| 18 | struct net_device *dev; | 22 | struct net_device *dev; |
| 23 | enum ovpn_mode mode; | ||
| 19 | }; | 24 | }; |
| 20 | 25 | ||
| 21 | #endif /* _NET_OVPN_OVPNSTRUCT_H_ */ | 26 | #endif /* _NET_OVPN_OVPNSTRUCT_H_ */ |
| @@ -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 <antonio@openvpn.net> | ||
| 7 | * James Yonan <james@openvpn.net> | ||
| 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_ */ | ||
| @@ -1986,4 +1986,19 @@ enum { · 1985 unmodified lines | |||
| 1986 | 1986 | ||
| 1987 | #define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1) | 1987 | #define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1) |
| 1988 | 1988 | ||
| 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 | |||
| 1989 | #endif /* _UAPI_LINUX_IF_LINK_H */ | 2004 | #endif /* _UAPI_LINUX_IF_LINK_H */ |