Skip to content

Commit 6e828dc

Browse files
tomparkinkuba-moo
authored andcommitted
l2tp: fix ICMP error handling for UDP-encap sockets
Since commit a36e185 ("udp: Handle ICMP errors for tunnels with same destination port on both endpoints") UDP's handling of ICMP errors has allowed for UDP-encap tunnels to determine socket associations in scenarios where the UDP hash lookup could not. Subsequently, commit d26796a ("udp: check udp sock encap_type in __udp_lib_err") subtly tweaked the approach such that UDP ICMP error handling would be skipped for any UDP socket which has encapsulation enabled. In the case of L2TP tunnel sockets using UDP-encap, this latter modification effectively broke ICMP error reporting for the L2TP control plane. To a degree this isn't catastrophic inasmuch as the L2TP control protocol defines a reliable transport on top of the underlying packet switching network which will eventually detect errors and time out. However, paying attention to the ICMP error reporting allows for more timely detection of errors in L2TP userspace, and aids in debugging connectivity issues. Reinstate ICMP error handling for UDP encap L2TP tunnels: * implement struct udp_tunnel_sock_cfg .encap_err_rcv in order to allow the L2TP code to handle ICMP errors; * only implement error-handling for tunnels which have a managed socket: unmanaged tunnels using a kernel socket have no userspace to report errors back to; * flag the error on the socket, which allows for userspace to get an error such as -ECONNREFUSED back from sendmsg/recvmsg; * pass the error into ip[v6]_icmp_error() which allows for userspace to get extended error information via. MSG_ERRQUEUE. Fixes: d26796a ("udp: check udp sock encap_type in __udp_lib_err") Signed-off-by: Tom Parkin <tparkin@katalix.com> Link: https://lore.kernel.org/r/20240513172248.623261-1-tparkin@katalix.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent f6f25ee commit 6e828dc

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

net/l2tp/l2tp_core.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -910,22 +910,20 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
910910
return 1;
911911
}
912912

913-
/* UDP encapsulation receive handler. See net/ipv4/udp.c.
914-
* Return codes:
915-
* 0 : success.
916-
* <0: error
917-
* >0: skb should be passed up to userspace as UDP.
913+
/* UDP encapsulation receive and error receive handlers.
914+
* See net/ipv4/udp.c for details.
915+
*
916+
* Note that these functions are called from inside an
917+
* RCU-protected region, but without the socket being locked.
918+
*
919+
* Hence we use rcu_dereference_sk_user_data to access the
920+
* tunnel data structure rather the usual l2tp_sk_to_tunnel
921+
* accessor function.
918922
*/
919923
int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
920924
{
921925
struct l2tp_tunnel *tunnel;
922926

923-
/* Note that this is called from the encap_rcv hook inside an
924-
* RCU-protected region, but without the socket being locked.
925-
* Hence we use rcu_dereference_sk_user_data to access the
926-
* tunnel data structure rather the usual l2tp_sk_to_tunnel
927-
* accessor function.
928-
*/
929927
tunnel = rcu_dereference_sk_user_data(sk);
930928
if (!tunnel)
931929
goto pass_up;
@@ -942,6 +940,29 @@ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
942940
}
943941
EXPORT_SYMBOL_GPL(l2tp_udp_encap_recv);
944942

943+
static void l2tp_udp_encap_err_recv(struct sock *sk, struct sk_buff *skb, int err,
944+
__be16 port, u32 info, u8 *payload)
945+
{
946+
struct l2tp_tunnel *tunnel;
947+
948+
tunnel = rcu_dereference_sk_user_data(sk);
949+
if (!tunnel || tunnel->fd < 0)
950+
return;
951+
952+
sk->sk_err = err;
953+
sk_error_report(sk);
954+
955+
if (ip_hdr(skb)->version == IPVERSION) {
956+
if (inet_test_bit(RECVERR, sk))
957+
return ip_icmp_error(sk, skb, err, port, info, payload);
958+
#if IS_ENABLED(CONFIG_IPV6)
959+
} else {
960+
if (inet6_test_bit(RECVERR6, sk))
961+
return ipv6_icmp_error(sk, skb, err, port, info, payload);
962+
#endif
963+
}
964+
}
965+
945966
/************************************************************************
946967
* Transmit handling
947968
***********************************************************************/
@@ -1516,6 +1537,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
15161537
.sk_user_data = tunnel,
15171538
.encap_type = UDP_ENCAP_L2TPINUDP,
15181539
.encap_rcv = l2tp_udp_encap_recv,
1540+
.encap_err_rcv = l2tp_udp_encap_err_recv,
15191541
.encap_destroy = l2tp_udp_encap_destroy,
15201542
};
15211543

0 commit comments

Comments
 (0)