From nobody Mon Nov 25 21:37:06 2024 Received: from mail-lj1-f170.google.com (mail-lj1-f170.google.com [209.85.208.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC9711DF264 for ; Fri, 25 Oct 2024 09:15:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729847712; cv=none; b=CnS7JiXlerlhrLOZvRDyFsR5A8EN3WDRwhQU0gRMbq6YhrJPN6fmeNN19QYuzhJQBqigHLXSiL0DxrnJk6UY8YF9bAX5eqqfzcvGMjAL3QWSIeXWALO4JWAaQZsxQOyaXOM6tP3ZWSVUWGdmx14RrDqC3h5RogC+zEoAr7l5ijk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729847712; c=relaxed/simple; bh=+ny/7Z1DJ7DqzyniBgVi2YmSRZmW82vQ4lKLHp8YpkU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iZmXBxey5nTcG2KtYQWBpsw10kWsSy4fWYQRQcPUndd6u4ozi2U66XxYhKv+i6qutpiT0tShNQmVk1LdMBzumy/45hHGIejkfG7W4wHdUfuiL+kTQ5PcMsntQd535/zNJ4PfpJicbR0rp40+TsVLNLfW0R88RDOsdS/pNtQXaxw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=openvpn.net; spf=pass smtp.mailfrom=openvpn.com; dkim=pass (2048-bit key) header.d=openvpn.net header.i=@openvpn.net header.b=dQwIgkR1; arc=none smtp.client-ip=209.85.208.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=openvpn.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=openvpn.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=openvpn.net header.i=@openvpn.net header.b="dQwIgkR1" Received: by mail-lj1-f170.google.com with SMTP id 38308e7fff4ca-2fb4ec17f5cso16877881fa.3 for ; Fri, 25 Oct 2024 02:15:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvpn.net; s=google; t=1729847705; x=1730452505; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=7Sqn5jbXzCasokH7RmP7q0PQ4Qz9mfONmQaHn1pOoZY=; b=dQwIgkR1iYLP3knj3tFmPFlilBvz83isOy0Pze9YFiZFmHvRajKMj99Josdq3N9RGn IkARifblp+j9keYGNYKCjwy0YUNR/TgM+e4hk0PgmIWrNj8jO+8HbpuQ1sMtBrV0fPax GeaNquEW3VT4OqTKphc37d360hFcH6NdKel/xIWwIiTWI1gP7z4MUnkcMc5MoTk/cF5B R+QFEvAy2NOYq7mht4Tfpp8f2sjmue01xjAxo+DhpJiEfa4HmsMrJgbNc42zTeFkxx2G jwm9IQDie5eUB0T0srKn9A6Rih2Y6cVIyTBxQlBc/0HIxiGV2Gx3npYCD1HwUn7X+tVQ FHXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729847705; x=1730452505; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7Sqn5jbXzCasokH7RmP7q0PQ4Qz9mfONmQaHn1pOoZY=; b=C3B1PgBolptUYdoQek5fSttlc1m1zLyG/I7OzxZlunGLGdLbRRInMAoywPOtinM9Gg GA0oXy0qGYZkJpkFx2a9x5i0fj0ulEl96Hm775DGxka4Ga3r1uAaKQJpSsSEicEWPL7s d012+2D97VwvLqCCGXiT6Gebi30auKElCSMNTWlua3wmz7Z/MkXT18QjWMmVOa3s9tmk EHvf2LV62x5VOcdeEzrBv1GFyLfbiVMeVPSaVYMcdiNxDSpVuvMJM+brA7pkKWGqwe5U 4mA9xpQ/7BZXdMl1qm9aZ3r8ugwulDS+zqf7DS/rqOGyMnm/hXh/XjFLzIXJidXa6ylY djMA== X-Forwarded-Encrypted: i=1; AJvYcCWhcSWihU+f9Q/x/TVD6SH17EyP7LJLoRHivE0xA4DocB6r70zBthYIw1HhKLDmFf6Xt9T5cmj38DstMqs=@vger.kernel.org X-Gm-Message-State: AOJu0Yxoyy6HrT/GU6d9izW4F+hM7xBjD31DERjZw+yTc64oBbxFvUae QTmlO7Aci6wtA8028UztndkCVqps8z9j+EvLRgv1k0qDsPgKNgAmimtamRthWwg= X-Google-Smtp-Source: AGHT+IFEParryooUY3R7NCbpQz12B33gL5/mpnX4Peg74UEk7rba6gnJPFq9WQqNHBtdW/D8d15I/g== X-Received: by 2002:a2e:b88d:0:b0:2fb:569a:553d with SMTP id 38308e7fff4ca-2fc9d61c54amr50912251fa.42.1729847704771; Fri, 25 Oct 2024 02:15:04 -0700 (PDT) Received: from serenity.mandelbit.com ([2001:67c:2fbc:1:676b:7d84:55a4:bea5]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4318b55f484sm41981485e9.13.2024.10.25.02.15.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Oct 2024 02:15:04 -0700 (PDT) From: Antonio Quartulli Date: Fri, 25 Oct 2024 11:14:08 +0200 Subject: [PATCH net-next v10 09/23] ovpn: implement basic RX path (UDP) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241025-b4-ovpn-v10-9-b87530777be7@openvpn.net> References: <20241025-b4-ovpn-v10-0-b87530777be7@openvpn.net> In-Reply-To: <20241025-b4-ovpn-v10-0-b87530777be7@openvpn.net> To: Eric Dumazet , Jakub Kicinski , Paolo Abeni , Donald Hunter , Antonio Quartulli , Shuah Khan , donald.hunter@gmail.com, sd@queasysnail.net, ryazanov.s.a@gmail.com, Andrew Lunn Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=14461; i=antonio@openvpn.net; h=from:subject:message-id; bh=+ny/7Z1DJ7DqzyniBgVi2YmSRZmW82vQ4lKLHp8YpkU=; b=owEBbQGS/pANAwAIAQtw5TqgONWHAcsmYgBnG2GZZjGWz6/aXr8jW+juM2OEM926i9sTqqr0N SSJ3Jr0C7yJATMEAAEIAB0WIQSZq9xs+NQS5N5fwPwLcOU6oDjVhwUCZxthmQAKCRALcOU6oDjV h0ENB/sFPD9Bw9LKhlm+pS6DwuahLegjak/zzBTqVhO8y5V8+X9J+c9F29jXVcQ5JFVb3yk/0PF S5oBGtoSJHbm7lQQVZYppvktaHkMvYmci0JRBLsIigcwsIXLWYXwUgulSVVoEVcdQXuS8GvvHNV 7DvpgwZnzBQ4hrZ97i7pIjUqkwZKDtCaAYfLGRbX9pOd1JIN96gWCD+xP4KdEkmPJqX/NY0ofw3 41hkz98umcZQndxwNryHh5KJGqG3pgzRFeQhCEZVp5qeWQSoJ5fFL/QPR0jTS9+C/hvcjKkNCtR ywtrAoJJ1Of0XNtveFQ+U8NeoN1xZbakXB0G30SO/WGNx7FA X-Developer-Key: i=antonio@openvpn.net; a=openpgp; fpr=CABDA1282017C267219885C748F0CCB68F59D14C Packets received over the socket are forwarded to the user device. Implementation is UDP only. TCP will be added by a later patch. Note: no decryption/decapsulation exists yet, packets are forwarded as they arrive without much processing. Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/io.c | 66 ++++++++++++++++++++++++++- drivers/net/ovpn/io.h | 2 + drivers/net/ovpn/main.c | 13 +++++- drivers/net/ovpn/ovpnstruct.h | 3 ++ drivers/net/ovpn/proto.h | 75 ++++++++++++++++++++++++++++++ drivers/net/ovpn/socket.c | 24 ++++++++++ drivers/net/ovpn/udp.c | 104 ++++++++++++++++++++++++++++++++++++++= +++- drivers/net/ovpn/udp.h | 3 +- 8 files changed, 286 insertions(+), 4 deletions(-) diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c index 77ba4d33ae0bd2f52e8bd1c06a182d24285297b4..791a1b117125118b179cb13cdfd= 5fbab6523a360 100644 --- a/drivers/net/ovpn/io.c +++ b/drivers/net/ovpn/io.c @@ -9,15 +9,79 @@ =20 #include #include +#include #include =20 -#include "io.h" #include "ovpnstruct.h" #include "peer.h" +#include "io.h" +#include "netlink.h" +#include "proto.h" #include "udp.h" #include "skb.h" #include "socket.h" =20 +/* Called after decrypt to write the IP packet to the device. + * This method is expected to manage/free the skb. + */ +static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb) +{ + unsigned int pkt_len; + + /* we can't guarantee the packet wasn't corrupted before entering the + * VPN, therefore we give other layers a chance to check that + */ + skb->ip_summed =3D CHECKSUM_NONE; + + /* skb hash for transport packet no longer valid after decapsulation */ + skb_clear_hash(skb); + + /* post-decrypt scrub -- prepare to inject encapsulated packet onto the + * interface, based on __skb_tunnel_rx() in dst.h + */ + skb->dev =3D peer->ovpn->dev; + skb_set_queue_mapping(skb, 0); + skb_scrub_packet(skb, true); + + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + skb_probe_transport_header(skb); + skb_reset_inner_headers(skb); + + memset(skb->cb, 0, sizeof(skb->cb)); + + /* cause packet to be "received" by the interface */ + pkt_len =3D skb->len; + if (likely(gro_cells_receive(&peer->ovpn->gro_cells, + skb) =3D=3D NET_RX_SUCCESS)) + /* update RX stats with the size of decrypted packet */ + dev_sw_netstats_rx_add(peer->ovpn->dev, pkt_len); +} + +static void ovpn_decrypt_post(struct sk_buff *skb, int ret) +{ + struct ovpn_peer *peer =3D ovpn_skb_cb(skb)->peer; + + if (unlikely(ret < 0)) + goto drop; + + ovpn_netdev_write(peer, skb); + /* skb is passed to upper layer - don't free it */ + skb =3D NULL; +drop: + if (unlikely(skb)) + dev_core_stats_rx_dropped_inc(peer->ovpn->dev); + ovpn_peer_put(peer); + kfree_skb(skb); +} + +/* pick next packet from RX queue, decrypt and forward it to the device */ +void ovpn_recv(struct ovpn_peer *peer, struct sk_buff *skb) +{ + ovpn_skb_cb(skb)->peer =3D peer; + ovpn_decrypt_post(skb, 0); +} + static void ovpn_encrypt_post(struct sk_buff *skb, int ret) { struct ovpn_peer *peer =3D ovpn_skb_cb(skb)->peer; diff --git a/drivers/net/ovpn/io.h b/drivers/net/ovpn/io.h index aa259be66441f7b0262f39da12d6c3dce0a9b24c..9667a0a470e0b4b427524fffb5b= 9b395007e5a2f 100644 --- a/drivers/net/ovpn/io.h +++ b/drivers/net/ovpn/io.h @@ -12,4 +12,6 @@ =20 netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev); =20 +void ovpn_recv(struct ovpn_peer *peer, struct sk_buff *skb); + #endif /* _NET_OVPN_OVPN_H_ */ diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c index 5492ce07751d135c1484fe1ed8227c646df94969..73348765a8cf24321aa6be78e75= f607d6dbffb1d 100644 --- a/drivers/net/ovpn/main.c +++ b/drivers/net/ovpn/main.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,16 @@ static void ovpn_struct_free(struct net_device *net) =20 static int ovpn_net_init(struct net_device *dev) { - return 0; + struct ovpn_struct *ovpn =3D netdev_priv(dev); + + return gro_cells_init(&ovpn->gro_cells, dev); +} + +static void ovpn_net_uninit(struct net_device *dev) +{ + struct ovpn_struct *ovpn =3D netdev_priv(dev); + + gro_cells_destroy(&ovpn->gro_cells); } =20 static int ovpn_net_open(struct net_device *dev) @@ -56,6 +66,7 @@ static int ovpn_net_stop(struct net_device *dev) =20 static const struct net_device_ops ovpn_netdev_ops =3D { .ndo_init =3D ovpn_net_init, + .ndo_uninit =3D ovpn_net_uninit, .ndo_open =3D ovpn_net_open, .ndo_stop =3D ovpn_net_stop, .ndo_start_xmit =3D ovpn_net_xmit, diff --git a/drivers/net/ovpn/ovpnstruct.h b/drivers/net/ovpn/ovpnstruct.h index a22c5083381c131db01a28c0f51e661d690d4998..4a48fc048890ab1cda78bc104fe= 3034b4a49d226 100644 --- a/drivers/net/ovpn/ovpnstruct.h +++ b/drivers/net/ovpn/ovpnstruct.h @@ -10,6 +10,7 @@ #ifndef _NET_OVPN_OVPNSTRUCT_H_ #define _NET_OVPN_OVPNSTRUCT_H_ =20 +#include #include #include #include @@ -23,6 +24,7 @@ * @lock: protect this object * @peer: in P2P mode, this is the only remote peer * @dev_list: entry for the module wide device list + * @gro_cells: pointer to the Generic Receive Offload cell */ struct ovpn_struct { struct net_device *dev; @@ -32,6 +34,7 @@ struct ovpn_struct { spinlock_t lock; /* protect writing to the ovpn_struct object */ struct ovpn_peer __rcu *peer; struct list_head dev_list; + struct gro_cells gro_cells; }; =20 #endif /* _NET_OVPN_OVPNSTRUCT_H_ */ diff --git a/drivers/net/ovpn/proto.h b/drivers/net/ovpn/proto.h new file mode 100644 index 0000000000000000000000000000000000000000..69604cf26bbf82539ee5cd5a7ac= 9c23920f555de --- /dev/null +++ b/drivers/net/ovpn/proto.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* OpenVPN data channel offload + * + * Copyright (C) 2020-2024 OpenVPN, Inc. + * + * Author: Antonio Quartulli + * James Yonan + */ + +#ifndef _NET_OVPN_OVPNPROTO_H_ +#define _NET_OVPN_OVPNPROTO_H_ + +#include "main.h" + +#include + +/* Methods for operating on the initial command + * byte of the OpenVPN protocol. + */ + +/* packet opcode (high 5 bits) and key-id (low 3 bits) are combined in + * one byte + */ +#define OVPN_KEY_ID_MASK 0x07 +#define OVPN_OPCODE_SHIFT 3 +#define OVPN_OPCODE_MASK 0x1F +/* upper bounds on opcode and key ID */ +#define OVPN_KEY_ID_MAX (OVPN_KEY_ID_MASK + 1) +#define OVPN_OPCODE_MAX (OVPN_OPCODE_MASK + 1) +/* packet opcodes of interest to us */ +#define OVPN_DATA_V1 6 /* data channel V1 packet */ +#define OVPN_DATA_V2 9 /* data channel V2 packet */ +/* size of initial packet opcode */ +#define OVPN_OP_SIZE_V1 1 +#define OVPN_OP_SIZE_V2 4 +#define OVPN_PEER_ID_MASK 0x00FFFFFF +#define OVPN_PEER_ID_UNDEF 0x00FFFFFF +/* first byte of keepalive message */ +#define OVPN_KEEPALIVE_FIRST_BYTE 0x2a +/* first byte of exit message */ +#define OVPN_EXPLICIT_EXIT_NOTIFY_FIRST_BYTE 0x28 + +/** + * ovpn_opcode_from_skb - extract OP code from skb at specified offset + * @skb: the packet to extract the OP code from + * @offset: the offset in the data buffer where the OP code is located + * + * Note: this function assumes that the skb head was pulled enough + * to access the first byte. + * + * Return: the OP code + */ +static inline u8 ovpn_opcode_from_skb(const struct sk_buff *skb, u16 offse= t) +{ + u8 byte =3D *(skb->data + offset); + + return byte >> OVPN_OPCODE_SHIFT; +} + +/** + * ovpn_peer_id_from_skb - extract peer ID from skb at specified offset + * @skb: the packet to extract the OP code from + * @offset: the offset in the data buffer where the OP code is located + * + * Note: this function assumes that the skb head was pulled enough + * to access the first 4 bytes. + * + * Return: the peer ID. + */ +static inline u32 ovpn_peer_id_from_skb(const struct sk_buff *skb, u16 off= set) +{ + return ntohl(*(__be32 *)(skb->data + offset)) & OVPN_PEER_ID_MASK; +} + +#endif /* _NET_OVPN_OVPNPROTO_H_ */ diff --git a/drivers/net/ovpn/socket.c b/drivers/net/ovpn/socket.c index 090a3232ab0ec19702110f1a90f45c7f10889f6f..964b566de69f4132806a969a455= cec7f6059a0bd 100644 --- a/drivers/net/ovpn/socket.c +++ b/drivers/net/ovpn/socket.c @@ -22,6 +22,9 @@ static void ovpn_socket_detach(struct socket *sock) if (!sock) return; =20 + if (sock->sk->sk_protocol =3D=3D IPPROTO_UDP) + ovpn_udp_socket_detach(sock); + sockfd_put(sock); } =20 @@ -71,6 +74,27 @@ static int ovpn_socket_attach(struct socket *sock, struc= t ovpn_peer *peer) return ret; } =20 +/* Retrieve the corresponding ovpn object from a UDP socket + * rcu_read_lock must be held on entry + */ +struct ovpn_struct *ovpn_from_udp_sock(struct sock *sk) +{ + struct ovpn_socket *ovpn_sock; + + if (unlikely(READ_ONCE(udp_sk(sk)->encap_type) !=3D UDP_ENCAP_OVPNINUDP)) + return NULL; + + ovpn_sock =3D rcu_dereference_sk_user_data(sk); + if (unlikely(!ovpn_sock)) + return NULL; + + /* make sure that sk matches our stored transport socket */ + if (unlikely(!ovpn_sock->sock || sk !=3D ovpn_sock->sock->sk)) + return NULL; + + return ovpn_sock->ovpn; +} + /** * ovpn_socket_new - create a new socket and initialize it * @sock: the kernel socket to embed diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c index d26d7566e9c8dfe91fa77f49c34fb179a9fb2239..d1e88ae83843f02d591e67a7995= f2d6868720695 100644 --- a/drivers/net/ovpn/udp.c +++ b/drivers/net/ovpn/udp.c @@ -21,9 +21,95 @@ #include "bind.h" #include "io.h" #include "peer.h" +#include "proto.h" #include "socket.h" #include "udp.h" =20 +/** + * ovpn_udp_encap_recv - Start processing a received UDP packet. + * @sk: socket over which the packet was received + * @skb: the received packet + * + * If the first byte of the payload is DATA_V2, the packet is further proc= essed, + * otherwise it is forwarded to the UDP stack for delivery to user space. + * + * Return: + * 0 if skb was consumed or dropped + * >0 if skb should be passed up to userspace as UDP (packet not consumed) + * <0 if skb should be resubmitted as proto -N (packet not consumed) + */ +static int ovpn_udp_encap_recv(struct sock *sk, struct sk_buff *skb) +{ + struct ovpn_peer *peer =3D NULL; + struct ovpn_struct *ovpn; + u32 peer_id; + u8 opcode; + + ovpn =3D ovpn_from_udp_sock(sk); + if (unlikely(!ovpn)) { + net_err_ratelimited("%s: cannot obtain ovpn object from UDP socket\n", + __func__); + goto drop_noovpn; + } + + /* Make sure the first 4 bytes of the skb data buffer after the UDP + * header are accessible. + * They are required to fetch the OP code, the key ID and the peer ID. + */ + if (unlikely(!pskb_may_pull(skb, sizeof(struct udphdr) + + OVPN_OP_SIZE_V2))) { + net_dbg_ratelimited("%s: packet too small\n", __func__); + goto drop; + } + + opcode =3D ovpn_opcode_from_skb(skb, sizeof(struct udphdr)); + if (unlikely(opcode !=3D OVPN_DATA_V2)) { + /* DATA_V1 is not supported */ + if (opcode =3D=3D OVPN_DATA_V1) + goto drop; + + /* unknown or control packet: let it bubble up to userspace */ + return 1; + } + + peer_id =3D ovpn_peer_id_from_skb(skb, sizeof(struct udphdr)); + /* some OpenVPN server implementations send data packets with the + * peer-id set to undef. In this case we skip the peer lookup by peer-id + * and we try with the transport address + */ + if (peer_id !=3D OVPN_PEER_ID_UNDEF) { + peer =3D ovpn_peer_get_by_id(ovpn, peer_id); + if (!peer) { + net_err_ratelimited("%s: received data from unknown peer (id: %d)\n", + __func__, peer_id); + goto drop; + } + } + + if (!peer) { + /* data packet with undef peer-id */ + peer =3D ovpn_peer_get_by_transp_addr(ovpn, skb); + if (unlikely(!peer)) { + net_dbg_ratelimited("%s: received data with undef peer-id from unknown = source\n", + __func__); + goto drop; + } + } + + /* pop off outer UDP header */ + __skb_pull(skb, sizeof(struct udphdr)); + ovpn_recv(peer, skb); + return 0; + +drop: + if (peer) + ovpn_peer_put(peer); + dev_core_stats_rx_dropped_inc(ovpn->dev); +drop_noovpn: + kfree_skb(skb); + return 0; +} + /** * ovpn_udp4_output - send IPv4 packet over udp socket * @ovpn: the openvpn instance @@ -259,8 +345,12 @@ void ovpn_udp_send_skb(struct ovpn_struct *ovpn, struc= t ovpn_peer *peer, */ int ovpn_udp_socket_attach(struct socket *sock, struct ovpn_struct *ovpn) { + struct udp_tunnel_sock_cfg cfg =3D { + .encap_type =3D UDP_ENCAP_OVPNINUDP, + .encap_rcv =3D ovpn_udp_encap_recv, + }; struct ovpn_socket *old_data; - int ret =3D 0; + int ret; =20 /* sanity check */ if (sock->sk->sk_protocol !=3D IPPROTO_UDP) { @@ -274,6 +364,7 @@ int ovpn_udp_socket_attach(struct socket *sock, struct = ovpn_struct *ovpn) if (!old_data) { /* socket is currently unused - we can take it */ rcu_read_unlock(); + setup_udp_tunnel_sock(sock_net(sock->sk), sock, &cfg); return 0; } =20 @@ -302,3 +393,14 @@ int ovpn_udp_socket_attach(struct socket *sock, struct= ovpn_struct *ovpn) =20 return ret; } + +/** + * ovpn_udp_socket_detach - clean udp-tunnel status for this socket + * @sock: the socket to clean + */ +void ovpn_udp_socket_detach(struct socket *sock) +{ + struct udp_tunnel_sock_cfg cfg =3D { }; + + setup_udp_tunnel_sock(sock_net(sock->sk), sock, &cfg); +} diff --git a/drivers/net/ovpn/udp.h b/drivers/net/ovpn/udp.h index e60f8cd2b4ac8f910aabcf8ed546af59d6ca4be4..fecb68464896bc1228315faf268= 453f9005e693d 100644 --- a/drivers/net/ovpn/udp.h +++ b/drivers/net/ovpn/udp.h @@ -18,8 +18,9 @@ struct sk_buff; struct socket; =20 int ovpn_udp_socket_attach(struct socket *sock, struct ovpn_struct *ovpn); - +void ovpn_udp_socket_detach(struct socket *sock); void ovpn_udp_send_skb(struct ovpn_struct *ovpn, struct ovpn_peer *peer, struct sk_buff *skb); +struct ovpn_struct *ovpn_from_udp_sock(struct sock *sk); =20 #endif /* _NET_OVPN_UDP_H_ */ --=20 2.45.2