From nobody Tue Feb 10 07:01:46 2026 Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) (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 8C2101F37CF for ; Wed, 11 Dec 2024 21:32:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733952780; cv=none; b=Q9+b3y1ijBqD23O+UTJIHOUZqKB8vY9wde530eH2XDunM9GaiczeMUEtQBiSBfph+iv5AlP4Hg0cl25jN3DG/SKPNyyVM0E+aX7foSBz1exLdd0V6vz0OHErNHjkLwcn8Ka0qQwEHN8Gw4tKB3T6DC8addC29kx5x9SbJVBFZgE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733952780; c=relaxed/simple; bh=Wd8BbIdktli1TBn9FuD7TQ7L0jfWUlgOHnnZ4QoTlAY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Y5fpHtpyOuGkDqQP4pkBOGX5snGtAFArZ1Ng89VfvTVqIN9KfgFbVZ4LgI4AJngljuKh6dpozJ9WMk8OpTn6QnF99CUqCDyCfuzYvGn30nsBI9MS6NnC1wQ7NeDrT+KUcxNKTxBAuol4hmMYmunYWB+ZRPeyusxurnUxPmT1k/c= 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=OqD/HJGe; arc=none smtp.client-ip=209.85.221.43 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="OqD/HJGe" Received: by mail-wr1-f43.google.com with SMTP id ffacd0b85a97d-3862d161947so3532532f8f.3 for ; Wed, 11 Dec 2024 13:32:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvpn.net; s=google; t=1733952776; x=1734557576; 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=3mhISHWiGrJ1H4XzmBSHzyqz1eQXRXC1OYV4lhTAVkM=; b=OqD/HJGeqKNHXSFRaKJV6H/iHT05YsMBCLJjs2hZqMTfFCH+72gHaaG6NfXBS+9v3w FWItID/xcynbsErYMCuqSua7MHe1xa4hFIDJcuE+Di8KL1LBpH557gWW6F+b7qyXM/0t mkzdmDyGclO/g586FhCen4PkA6dxDK/vNsH/QIkhX+clyzzhCNpptgNLDF9YzEhflXAx wFvhWVsVBhDIoZNNVp1GzRf06T6jm45RhTrlOpizAe21GKHYObxMXAyP59U7M8+QVC3g G+1CDXhh/u4tAk/HuPMSGoZKxtNjlF6jzFD9OQ+PMlrBLYMzGCdOJ3smitsE85r8/mds qvtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733952776; x=1734557576; 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=3mhISHWiGrJ1H4XzmBSHzyqz1eQXRXC1OYV4lhTAVkM=; b=KL3tI2/96W2J9mX9ctT2/8mywLWLrPrc/YvPCybkunkFVRM7xacYzVNA+Xs6KkYW/u nKgP5vjvTcrnHoMLfLYiinsW8o48ZKFqDYauM/jQd3LudvsFwdyTpwummC6a53cL23wx oEwoHokolfQ7Z1JGkooU00c2hu5IElO6vCgyVBMxHaA8ILujl4uEzBmue31dNJUWc8Rv fs1M6r6/vqueqbsj2kNG/YJRfH7twXVkchbUD9f2DO4CEeA0QgJMEzKQ5NpLCjOI5/pS UQ45kvLoPsyCEjX5RteoYrHrNa6ry+3u+bM92MqU3qpEZS99MJdmVJVbZHp76JnuNEEU E8Bw== X-Forwarded-Encrypted: i=1; AJvYcCUPErbfcQYZkfaP69pzeWPylpsKPGAhP+yrnEGx6EIrvTukkXl+BWq3ar/F+dWISHtFBAauWcAzkwu0Ij8=@vger.kernel.org X-Gm-Message-State: AOJu0YxX8laCDHDUDcu0BTYzngedy24KTG/3+FZXiiQYv+0ySsCN5Q85 /C7MbCXxT9g8pqMW6yplKqZmV80aBjvTUNYxC4WSAqnjSMmdftOMFRgFUIAu1sE= X-Gm-Gg: ASbGncs1M1KQefOFWwJBAe+rtzCbf9oq9TI5UUyifozAzYML5g9Re8eD0e0/Se1a6sl NZCrOLjys3nMtO86pykIMsP0gnqQJidAvi+VrGJO+6jiYvIzxB+bmqh8ATxGLXBtWGKnOnVMlfP F9DpaylezHPFvlFUoif2x4m6vCTvtwhmBB7vPQfx3Ww76NT4yXkiR0U2x0HDX5wNJlfKrxlM4xZ fo38G0um6PILwjx/LpfB2wCUr3lNxeeXCGgOm06i4s0mRavWORRlLe79bUmjqDNhg== X-Google-Smtp-Source: AGHT+IFnpfgjq2gkfvXF4DwaLaAM0GmRFqQ8cwz5zIOcxYm9XbK0VWa++1ZB8mVZzvLF0PsvBAnMhQ== X-Received: by 2002:a05:6000:71e:b0:385:f631:612 with SMTP id ffacd0b85a97d-3878768e1eamr879685f8f.17.1733952775874; Wed, 11 Dec 2024 13:32:55 -0800 (PST) Received: from serenity.mandelbit.com ([2001:67c:2fbc:1:3115:252a:3e6f:da41]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3878248f5a0sm2136252f8f.13.2024.12.11.13.32.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Dec 2024 13:32:55 -0800 (PST) From: Antonio Quartulli Date: Wed, 11 Dec 2024 22:15:12 +0100 Subject: [PATCH net-next v15 08/22] 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: <20241211-b4-ovpn-v15-8-314e2cad0618@openvpn.net> References: <20241211-b4-ovpn-v15-0-314e2cad0618@openvpn.net> In-Reply-To: <20241211-b4-ovpn-v15-0-314e2cad0618@openvpn.net> To: netdev@vger.kernel.org, Eric Dumazet , Jakub Kicinski , Paolo Abeni , Donald Hunter , Antonio Quartulli , Shuah Khan , sd@queasysnail.net, ryazanov.s.a@gmail.com, Andrew Lunn Cc: Simon Horman , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Xiao Liang X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=13530; i=antonio@openvpn.net; h=from:subject:message-id; bh=Wd8BbIdktli1TBn9FuD7TQ7L0jfWUlgOHnnZ4QoTlAY=; b=owEBbQGS/pANAwAIAQtw5TqgONWHAcsmYgBnWgUlYW0fHpJLKp/SJxisevpZWCyD2769ndSPg ilYDDQecIGJATMEAAEIAB0WIQSZq9xs+NQS5N5fwPwLcOU6oDjVhwUCZ1oFJQAKCRALcOU6oDjV h3n8B/969jQPl2LUcxguV7KNtouLg6MXO765JSH7VZkh+AcSOncJSYQgyizBnt7c0tdPnj3nKhl O1mO+w8O+/9lbA63AdiZWWOVlgH0g7TObBDZWmFhfg7nhKR9aBxZR/AqJtkf9UbPwRUqxjdRl6Z yDq5cHq9WjlLZFgmyISzmp2nHh4aAwD+7Dmw2kFaItdWryCDDqjjHLdgl+PxMyz1tkuUjk/6XSz qqS5htduervij3WB7GuSFRRRSkXdt7ekG36wYQeiZDoU+Hm1hOurqhLRaZmET/B8G8yVuv8qvLS 69daAbQI4RT1e5+l6v4RT+GNRP94rlHEktP8wo2wOPmkGxxj 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 | 64 +++++++++++++++++++++++++++++- drivers/net/ovpn/io.h | 2 + drivers/net/ovpn/main.c | 13 ++++++- drivers/net/ovpn/ovpnstruct.h | 3 ++ drivers/net/ovpn/proto.h | 50 +++++++++++++++++++++++- drivers/net/ovpn/socket.c | 24 ++++++++++++ drivers/net/ovpn/udp.c | 91 +++++++++++++++++++++++++++++++++++++++= +++- drivers/net/ovpn/udp.h | 3 +- 8 files changed, 245 insertions(+), 5 deletions(-) diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c index 2a3dbc723813a14070159318097755cc7ea3f216..9f5c6b06c79681048f750fce89e= 9683da41ea642 100644 --- a/drivers/net/ovpn/io.c +++ b/drivers/net/ovpn/io.c @@ -9,15 +9,77 @@ =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; + int ret; + + /* 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_reset_inner_headers(skb); + + /* cause packet to be "received" by the interface */ + pkt_len =3D skb->len; + ret =3D gro_cells_receive(&peer->ovpn->gro_cells, skb); + if (likely(ret =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); +} + +/* RX path entry point: decrypt packet 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 a90537e9af6c0d2f38da229bdc2d8c639f2d11d1..b3830b787e16f3bdcaaff94e5bb= e89be3e1006fe 100644 --- a/drivers/net/ovpn/io.h +++ b/drivers/net/ovpn/io.h @@ -21,4 +21,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 c37cb47495f04bb7a6facdf30e5877ddef0ddb29..c27e4c190f5bdf061a71c516344= 551ef7cd31496 100644 --- a/drivers/net/ovpn/main.c +++ b/drivers/net/ovpn/main.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -24,7 +25,16 @@ =20 static int ovpn_net_init(struct net_device *dev) { - return 0; + struct ovpn_priv *ovpn =3D netdev_priv(dev); + + return gro_cells_init(&ovpn->gro_cells, dev); +} + +static void ovpn_net_uninit(struct net_device *dev) +{ + struct ovpn_priv *ovpn =3D netdev_priv(dev); + + gro_cells_destroy(&ovpn->gro_cells); } =20 static int ovpn_net_open(struct net_device *dev) @@ -50,6 +60,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 a6cfb436f3d0d79a0c438e647f8652021119b0ed..1cca91d869d9e3c722a0933a426= 255f05daf8097 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 @@ -22,6 +23,7 @@ * @mode: device operation mode (i.e. p2p, mp, ..) * @lock: protect this object * @peer: in P2P mode, this is the only remote peer + * @gro_cells: pointer to the Generic Receive Offload cell */ struct ovpn_priv { struct net_device *dev; @@ -30,6 +32,7 @@ struct ovpn_priv { enum ovpn_mode mode; spinlock_t lock; /* protect writing to the ovpn_priv object */ struct ovpn_peer __rcu *peer; + 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 index 00bb3725ac7ab7040c97eb012c2639b2d6967de1..34a812869b2e92e8bab0ebb87d4= 6b67c3bbccf9f 100644 --- a/drivers/net/ovpn/proto.h +++ b/drivers/net/ovpn/proto.h @@ -10,6 +10,11 @@ #ifndef _NET_OVPN_PROTO_H_ #define _NET_OVPN_PROTO_H_ =20 +#include "main.h" + +#include +#include + /* When the OpenVPN protocol is ran in AEAD mode, use * the OpenVPN packet ID as the AEAD nonce: * @@ -34,5 +39,48 @@ #define OVPN_NONCE_WIRE_SIZE (OVPN_NONCE_SIZE - OVPN_NONCE_TAIL_SIZE) =20 #define OVPN_OPCODE_SIZE 4 /* DATA_V2 opcode size */ +#define OVPN_OPCODE_KEYID_MASK 0x07000000 +#define OVPN_OPCODE_PKTTYPE_MASK 0xF8000000 +#define OVPN_OPCODE_PEERID_MASK 0x00FFFFFF + +/* packet opcodes of interest to us */ +#define OVPN_DATA_V1 6 /* data channel v1 packet */ +#define OVPN_DATA_V2 9 /* data channel v2 packet */ + +#define OVPN_PEER_ID_UNDEF 0x00FFFFFF + +/** + * 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) +{ + u32 opcode =3D be32_to_cpu(*(__be32 *)(skb->data + offset)); + + return FIELD_GET(OVPN_OPCODE_PKTTYPE_MASK, opcode); +} + +/** + * 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) +{ + u32 opcode =3D be32_to_cpu(*(__be32 *)(skb->data + offset)); + + return FIELD_GET(OVPN_OPCODE_PEERID_MASK, opcode); +} =20 -#endif /* _NET_OVPN_PROTO_H_ */ +#endif /* _NET_OVPN_OVPNPROTO_H_ */ diff --git a/drivers/net/ovpn/socket.c b/drivers/net/ovpn/socket.c index 0abac02e13fb4ef1e212dacae075d5b58e872d34..e10590924e3f9fe605309989be8= 4866e2e508944 100644 --- a/drivers/net/ovpn/socket.c +++ b/drivers/net/ovpn/socket.c @@ -23,6 +23,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 @@ -70,6 +73,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_priv *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 c0e7aa289ad3345fcd91e7c890f70961300c356f..5932f8b5dfad1004e9e76e5fabf= bb71bd9a94d4d 100644 --- a/drivers/net/ovpn/udp.c +++ b/drivers/net/ovpn/udp.c @@ -23,9 +23,82 @@ #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_priv *ovpn; + struct ovpn_peer *peer; + u32 peer_id; + u8 opcode; + + ovpn =3D ovpn_from_udp_sock(sk); + if (unlikely(!ovpn)) { + net_err_ratelimited("ovpn: cannot obtain ovpn object from UDP socket\n"); + 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_OPCODE_SIZE))) { + net_dbg_ratelimited("%s: packet too small from UDP socket\n", + netdev_name(ovpn->dev)); + 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=3D OVPN_PEER_ID_UNDEF) + peer =3D ovpn_peer_get_by_transp_addr(ovpn, skb); + else + peer =3D ovpn_peer_get_by_id(ovpn, peer_id); + + if (unlikely(!peer)) + goto drop; + + /* pop off outer UDP header */ + __skb_pull(skb, sizeof(struct udphdr)); + ovpn_recv(peer, skb); + return 0; + +drop: + dev_core_stats_rx_dropped_inc(ovpn->dev); +drop_noovpn: + kfree_skb(skb); + return 0; +} + /** * ovpn_udp4_output - send IPv4 packet over udp socket * @peer: the destination peer @@ -262,8 +335,12 @@ void ovpn_udp_send_skb(struct ovpn_peer *peer, struct = sk_buff *skb) */ int ovpn_udp_socket_attach(struct socket *sock, struct ovpn_priv *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 /* make sure no pre-existing encapsulation handler exists */ rcu_read_lock(); @@ -271,6 +348,7 @@ int ovpn_udp_socket_attach(struct socket *sock, struct = ovpn_priv *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 @@ -297,3 +375,14 @@ int ovpn_udp_socket_attach(struct socket *sock, struct= ovpn_priv *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 44ebeb82325dc4d172da7e29fb36f21a5609ea8d..90a46821d1e999fea0e1aa0f7de= 9db65decf71d5 100644 --- a/drivers/net/ovpn/udp.h +++ b/drivers/net/ovpn/udp.h @@ -16,7 +16,8 @@ struct ovpn_priv; struct socket; =20 int ovpn_udp_socket_attach(struct socket *sock, struct ovpn_priv *ovpn); - +void ovpn_udp_socket_detach(struct socket *sock); void ovpn_udp_send_skb(struct ovpn_peer *peer, struct sk_buff *skb); +struct ovpn_priv *ovpn_from_udp_sock(struct sock *sk); =20 #endif /* _NET_OVPN_UDP_H_ */ --=20 2.45.2