Skip to content

Commit 2395e4f

Browse files
committed
Kernel: T8605: net/l2tp: allow unmanaged tunnel setup without route to peer
Kernel-created L2TPv3 tunnels (genetlink L2TP_CMD_TUNNEL_CREATE without L2TP_ATTR_FD) used udp_sock_create() and kernel_connect(), which invoke __ip4_datagram_connect() / __ip6_datagram_connect(). Those paths insist on a successful FIB lookup at connect time. If no route to the configured remote existed yet, tunnel and interface creation failed. The data path already resolves routes on transmit (e.g. __ip_queue_xmit(), inet6_csk_route_socket()). This change defers requiring a route until packets are sent. Details: - UDP encapsulation: bind with udp_sock_create() after zeroing peer_udp_port, then l2tp_udp_sk_set_peer() sets daddr/dport and socket "connected" state without caching sk_dst from connect. - IPv4 L2TP/IP (l2tp_ip): on -ENETUNREACH / -EHOSTUNREACH from __ip4_datagram_connect(), l2tp_ip_connect_deferred() installs peer and bind-table updates without a connect-time route. - IPv6 L2TP/IP (l2tp_ip6): same for __ip6_datagram_connect(), including IPv4-mapped peers and scope / bound-device checks aligned with the normal connect path. Forwarding still only happens once the FIB can reach the peer. Until then outgoing packets follow the existing no-route drop path.
1 parent f8ee384 commit 2395e4f

1 file changed

Lines changed: 355 additions & 0 deletions

File tree

Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
From: Christian Breunig <christian@breunig.cc>
2+
Date: Mon, 14 May 2026 13:11:00 +0200
3+
Subject: [PATCH] net/l2tp: allow unmanaged tunnel setup without route to peer
4+
5+
Kernel-created L2TPv3 tunnels (genetlink L2TP_CMD_TUNNEL_CREATE without
6+
L2TP_ATTR_FD) used udp_sock_create() and kernel_connect(), which invoke
7+
__ip4_datagram_connect() / __ip6_datagram_connect(). Those paths insist on
8+
a successful FIB lookup at connect time. If no route to the configured
9+
remote existed yet, tunnel and interface creation failed.
10+
11+
The data path already resolves routes on transmit (e.g. __ip_queue_xmit(),
12+
inet6_csk_route_socket()). This change defers requiring a route until
13+
packets are sent.
14+
15+
Details:
16+
- UDP encapsulation: bind with udp_sock_create() after zeroing peer_udp_port,
17+
then l2tp_udp_sk_set_peer() sets daddr/dport and socket "connected" state
18+
without caching sk_dst from connect.
19+
- IPv4 L2TP/IP (l2tp_ip): on -ENETUNREACH / -EHOSTUNREACH from
20+
__ip4_datagram_connect(), l2tp_ip_connect_deferred() installs peer and
21+
bind-table updates without a connect-time route.
22+
- IPv6 L2TP/IP (l2tp_ip6): same for __ip6_datagram_connect(), including
23+
IPv4-mapped peers and scope / bound-device checks aligned with the normal
24+
connect path.
25+
26+
Forwarding still only happens once the FIB can reach the peer. Until then
27+
outgoing packets follow the existing no-route drop path.
28+
29+
---
30+
diff --git i/net/l2tp/l2tp_core.c w/net/l2tp/l2tp_core.c
31+
index 9156a937334a..6fd9c1d89533 100644
32+
--- i/net/l2tp/l2tp_core.c
33+
+++ w/net/l2tp/l2tp_core.c
34+
@@ -55,6 +55,8 @@
35+
#include <net/inet_ecn.h>
36+
#include <net/ip6_route.h>
37+
#include <net/ip6_checksum.h>
38+
+#include <net/sock_reuseport.h>
39+
+#include <net/transp_v6.h>
40+
41+
#include <asm/byteorder.h>
42+
#include <linux/atomic.h>
43+
@@ -1453,6 +1455,67 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
44+
* These sockets are freed when the namespace exits using the pernet
45+
* exit hook.
46+
*/
47+
+
48+
+static int l2tp_udp_sk_set_peer(struct socket *sock, struct udp_port_cfg *cfg)
49+
+{
50+
+ struct sock *sk = sock->sk;
51+
+ struct inet_sock *inet;
52+
+
53+
+ lock_sock(sk);
54+
+ inet = inet_sk(sk);
55+
+ sk_dst_reset(sk);
56+
+
57+
+#if IS_ENABLED(CONFIG_IPV6)
58+
+ if (cfg->family == AF_INET6) {
59+
+ struct ipv6_pinfo *np = inet6_sk(sk);
60+
+
61+
+ sk->sk_v6_daddr = cfg->peer_ip6;
62+
+ np->flow_label = 0;
63+
+ inet->inet_dport = cfg->peer_udp_port;
64+
+ } else
65+
+#endif
66+
+ {
67+
+ inet->inet_daddr = cfg->peer_ip.s_addr;
68+
+ inet->inet_dport = cfg->peer_udp_port;
69+
+ }
70+
+
71+
+ reuseport_has_conns_set(sk);
72+
+ sk->sk_state = TCP_ESTABLISHED;
73+
+ sk_set_txhash(sk);
74+
+ atomic_set(&inet->inet_id, get_random_u16());
75+
+ release_sock(sk);
76+
+ return 0;
77+
+}
78+
+
79+
+static int l2tp_tunnel_udp_sock_create(struct net *net, struct udp_port_cfg *cfg,
80+
+ struct socket **sockp)
81+
+{
82+
+ struct udp_port_cfg cfg_bind = *cfg;
83+
+ int err;
84+
+ struct socket *sock;
85+
+
86+
+ cfg_bind.peer_udp_port = 0;
87+
+
88+
+ err = udp_sock_create(net, &cfg_bind, &sock);
89+
+ if (err < 0)
90+
+ return err;
91+
+
92+
+ if (!cfg->peer_udp_port) {
93+
+ *sockp = sock;
94+
+ return 0;
95+
+ }
96+
+
97+
+ err = l2tp_udp_sk_set_peer(sock, cfg);
98+
+ if (err < 0) {
99+
+ kernel_sock_shutdown(sock, SHUT_RDWR);
100+
+ sock_release(sock);
101+
+ return err;
102+
+ }
103+
+
104+
+ *sockp = sock;
105+
+ return 0;
106+
+}
107+
+
108+
static int l2tp_tunnel_sock_create(struct net *net,
109+
u32 tunnel_id,
110+
u32 peer_tunnel_id,
111+
@@ -1490,7 +1553,7 @@ static int l2tp_tunnel_sock_create(struct net *net,
112+
udp_conf.local_udp_port = htons(cfg->local_udp_port);
113+
udp_conf.peer_udp_port = htons(cfg->peer_udp_port);
114+
115+
- err = udp_sock_create(net, &udp_conf, &sock);
116+
+ err = l2tp_tunnel_udp_sock_create(net, &udp_conf, &sock);
117+
if (err < 0)
118+
goto out;
119+
120+
diff --git i/net/l2tp/l2tp_ip.c w/net/l2tp/l2tp_ip.c
121+
index 29795d2839e8..d63b00f09421 100644
122+
--- i/net/l2tp/l2tp_ip.c
123+
+++ w/net/l2tp/l2tp_ip.c
124+
@@ -24,6 +24,7 @@
125+
#include <net/xfrm.h>
126+
#include <net/net_namespace.h>
127+
#include <net/netns/generic.h>
128+
+#include <net/sock_reuseport.h>
129+
130+
#include "l2tp_core.h"
131+
132+
@@ -328,6 +329,37 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
133+
return ret;
134+
}
135+
136+
+/* Install peer address without capturing a route. Outgoing packets resolve
137+
+ * the path in __ip_queue_xmit(); this matches on-demand forwarding once the
138+
+ * FIB can reach the remote.
139+
+ */
140+
+static void __l2tp_ip4_sk_set_peer(struct sock *sk, __be32 daddr, __be16 dport)
141+
+{
142+
+ struct inet_sock *inet = inet_sk(sk);
143+
+
144+
+ sk_dst_reset(sk);
145+
+ inet->inet_daddr = daddr;
146+
+ inet->inet_dport = dport;
147+
+ reuseport_has_conns_set(sk);
148+
+ sk->sk_state = TCP_ESTABLISHED;
149+
+ sk_set_txhash(sk);
150+
+ atomic_set(&inet->inet_id, get_random_u16());
151+
+}
152+
+
153+
+static int l2tp_ip_connect_deferred(struct sock *sk, struct sockaddr_l2tpip *lsa)
154+
+{
155+
+ struct l2tp_ip_net *pn = l2tp_ip_pernet(sock_net(sk));
156+
+
157+
+ __l2tp_ip4_sk_set_peer(sk, lsa->l2tp_addr.s_addr, lsa->l2tp_unused);
158+
+ l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
159+
+
160+
+ write_lock_bh(&pn->l2tp_ip_lock);
161+
+ hlist_del_init(&sk->sk_bind_node);
162+
+ sk_add_bind_node(sk, &pn->l2tp_ip_bind_table);
163+
+ write_unlock_bh(&pn->l2tp_ip_lock);
164+
+ return 0;
165+
+}
166+
+
167+
static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
168+
{
169+
struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *)uaddr;
170+
@@ -349,15 +381,18 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
171+
}
172+
173+
rc = __ip4_datagram_connect(sk, uaddr, addr_len);
174+
- if (rc < 0)
175+
- goto out_sk;
176+
-
177+
- l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
178+
+ if (rc == -ENETUNREACH || rc == -EHOSTUNREACH)
179+
+ rc = l2tp_ip_connect_deferred(sk, lsa);
180+
+ else if (rc == 0) {
181+
+ l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
182+
183+
- write_lock_bh(&pn->l2tp_ip_lock);
184+
- hlist_del_init(&sk->sk_bind_node);
185+
- sk_add_bind_node(sk, &pn->l2tp_ip_bind_table);
186+
- write_unlock_bh(&pn->l2tp_ip_lock);
187+
+ write_lock_bh(&pn->l2tp_ip_lock);
188+
+ hlist_del_init(&sk->sk_bind_node);
189+
+ sk_add_bind_node(sk, &pn->l2tp_ip_bind_table);
190+
+ write_unlock_bh(&pn->l2tp_ip_lock);
191+
+ } else {
192+
+ goto out_sk;
193+
+ }
194+
195+
out_sk:
196+
release_sock(sk);
197+
diff --git i/net/l2tp/l2tp_ip6.c w/net/l2tp/l2tp_ip6.c
198+
index ea232f338dcb..610e666c0a58 100644
199+
--- i/net/l2tp/l2tp_ip6.c
200+
+++ w/net/l2tp/l2tp_ip6.c
201+
@@ -28,6 +28,8 @@
202+
#include <net/transp_v6.h>
203+
#include <net/addrconf.h>
204+
#include <net/ip6_route.h>
205+
+#include <net/l3mdev.h>
206+
+#include <net/sock_reuseport.h>
207+
208+
#include "l2tp_core.h"
209+
210+
@@ -383,6 +385,116 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
211+
return err;
212+
}
213+
214+
+static bool l2tp_ipv6_mapped_addr_any(const struct in6_addr *a)
215+
+{
216+
+ return ipv6_addr_v4mapped(a) && a->s6_addr32[3] == 0;
217+
+}
218+
+
219+
+/* Peer address without a cached dst; outbound path resolves the route. */
220+
+static void __l2tp_ip6_sk_set_peer(struct sock *sk, const struct in6_addr *daddr,
221+
+ __be16 dport, __be32 flowlabel)
222+
+{
223+
+ struct inet_sock *inet = inet_sk(sk);
224+
+ struct ipv6_pinfo *np = inet6_sk(sk);
225+
+
226+
+ sk_dst_reset(sk);
227+
+ sk->sk_v6_daddr = *daddr;
228+
+ np->flow_label = flowlabel;
229+
+ inet->inet_dport = dport;
230+
+ reuseport_has_conns_set(sk);
231+
+ sk->sk_state = TCP_ESTABLISHED;
232+
+ sk_set_txhash(sk);
233+
+}
234+
+
235+
+static int __l2tp_ip6_connect_deferred_mapped(struct sock *sk,
236+
+ struct sockaddr_l2tpip6 *lsa,
237+
+ struct sockaddr_in6 *usin)
238+
+{
239+
+ struct inet_sock *inet = inet_sk(sk);
240+
+ struct ipv6_pinfo *np = inet6_sk(sk);
241+
+ struct sockaddr_in sin;
242+
+ struct l2tp_ip6_net *pn;
243+
+ int err;
244+
+
245+
+ memset(&sin, 0, sizeof(sin));
246+
+ sin.sin_family = AF_INET;
247+
+ sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
248+
+ sin.sin_port = usin->sin6_port;
249+
+
250+
+ err = __ip4_datagram_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
251+
+ if (err == -ENETUNREACH || err == -EHOSTUNREACH) {
252+
+ sk_dst_reset(sk);
253+
+ inet->inet_daddr = sin.sin_addr.s_addr;
254+
+ inet->inet_dport = sin.sin_port;
255+
+ reuseport_has_conns_set(sk);
256+
+ sk->sk_state = TCP_ESTABLISHED;
257+
+ sk_set_txhash(sk);
258+
+ atomic_set(&inet->inet_id, get_random_u16());
259+
+ } else if (err) {
260+
+ return err;
261+
+ }
262+
+
263+
+ ipv6_addr_set_v4mapped(inet->inet_daddr, &sk->sk_v6_daddr);
264+
+ if (ipv6_addr_any(&np->saddr) || l2tp_ipv6_mapped_addr_any(&np->saddr))
265+
+ ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
266+
+ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr) ||
267+
+ l2tp_ipv6_mapped_addr_any(&sk->sk_v6_rcv_saddr)) {
268+
+ ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, &sk->sk_v6_rcv_saddr);
269+
+ if (sk->sk_prot->rehash)
270+
+ sk->sk_prot->rehash(sk);
271+
+ }
272+
+
273+
+ l2tp_ip6_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
274+
+ pn = l2tp_ip6_pernet(sock_net(sk));
275+
+ write_lock_bh(&pn->l2tp_ip6_lock);
276+
+ hlist_del_init(&sk->sk_bind_node);
277+
+ sk_add_bind_node(sk, &pn->l2tp_ip6_bind_table);
278+
+ write_unlock_bh(&pn->l2tp_ip6_lock);
279+
+ return 0;
280+
+}
281+
+
282+
+static int l2tp_ip6_connect_deferred(struct sock *sk, struct sockaddr_l2tpip6 *lsa,
283+
+ struct sockaddr_in6 *usin,
284+
+ int addr_len)
285+
+{
286+
+ struct ipv6_pinfo *np = inet6_sk(sk);
287+
+ struct l2tp_ip6_net *pn;
288+
+ int addr_type = ipv6_addr_type(&usin->sin6_addr);
289+
+ const struct in6_addr *daddr = &usin->sin6_addr;
290+
+ __be32 fl6_flowlabel = 0;
291+
+
292+
+ if (addr_type & IPV6_ADDR_MAPPED)
293+
+ return __l2tp_ip6_connect_deferred_mapped(sk, lsa, usin);
294+
+
295+
+ if (inet6_test_bit(SNDFLOW, sk))
296+
+ fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
297+
+
298+
+ if (__ipv6_addr_needs_scope_id(addr_type)) {
299+
+ if (addr_len >= sizeof(struct sockaddr_in6) &&
300+
+ usin->sin6_scope_id) {
301+
+ if (!sk_dev_equal_l3scope(sk, usin->sin6_scope_id))
302+
+ return -EINVAL;
303+
+ WRITE_ONCE(sk->sk_bound_dev_if, usin->sin6_scope_id);
304+
+ }
305+
+
306+
+ if (!sk->sk_bound_dev_if && (addr_type & IPV6_ADDR_MULTICAST))
307+
+ WRITE_ONCE(sk->sk_bound_dev_if, READ_ONCE(np->mcast_oif));
308+
+
309+
+ if (!sk->sk_bound_dev_if)
310+
+ return -EINVAL;
311+
+ }
312+
+
313+
+ __l2tp_ip6_sk_set_peer(sk, daddr, usin->sin6_port, fl6_flowlabel);
314+
+ l2tp_ip6_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
315+
+
316+
+ pn = l2tp_ip6_pernet(sock_net(sk));
317+
+ write_lock_bh(&pn->l2tp_ip6_lock);
318+
+ hlist_del_init(&sk->sk_bind_node);
319+
+ sk_add_bind_node(sk, &pn->l2tp_ip6_bind_table);
320+
+ write_unlock_bh(&pn->l2tp_ip6_lock);
321+
+ return 0;
322+
+}
323+
+
324+
static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr,
325+
int addr_len)
326+
{
327+
@@ -418,16 +530,19 @@ static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr,
328+
}
329+
330+
rc = __ip6_datagram_connect(sk, uaddr, addr_len);
331+
- if (rc < 0)
332+
- goto out_sk;
333+
+ if (rc == -ENETUNREACH || rc == -EHOSTUNREACH)
334+
+ rc = l2tp_ip6_connect_deferred(sk, lsa, usin, addr_len);
335+
+ else if (rc == 0) {
336+
+ l2tp_ip6_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
337+
338+
- l2tp_ip6_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
339+
-
340+
- pn = l2tp_ip6_pernet(sock_net(sk));
341+
- write_lock_bh(&pn->l2tp_ip6_lock);
342+
- hlist_del_init(&sk->sk_bind_node);
343+
- sk_add_bind_node(sk, &pn->l2tp_ip6_bind_table);
344+
- write_unlock_bh(&pn->l2tp_ip6_lock);
345+
+ pn = l2tp_ip6_pernet(sock_net(sk));
346+
+ write_lock_bh(&pn->l2tp_ip6_lock);
347+
+ hlist_del_init(&sk->sk_bind_node);
348+
+ sk_add_bind_node(sk, &pn->l2tp_ip6_bind_table);
349+
+ write_unlock_bh(&pn->l2tp_ip6_lock);
350+
+ } else {
351+
+ goto out_sk;
352+
+ }
353+
354+
out_sk:
355+
release_sock(sk);

0 commit comments

Comments
 (0)