]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/netdev/l2tp-tunnel.c
Merge pull request #12390 from poettering/string-file-mkdir
[thirdparty/systemd.git] / src / network / netdev / l2tp-tunnel.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <netinet/in.h>
4 #include <linux/l2tp.h>
5 #include <linux/genetlink.h>
6
7 #include "sd-netlink.h"
8
9 #include "conf-parser.h"
10 #include "hashmap.h"
11 #include "l2tp-tunnel.h"
12 #include "missing.h"
13 #include "netlink-util.h"
14 #include "networkd-address.h"
15 #include "networkd-manager.h"
16 #include "parse-util.h"
17 #include "socket-util.h"
18 #include "string-table.h"
19 #include "string-util.h"
20 #include "util.h"
21
22 static const char* const l2tp_l2spec_type_table[_NETDEV_L2TP_L2SPECTYPE_MAX] = {
23 [NETDEV_L2TP_L2SPECTYPE_NONE] = "none",
24 [NETDEV_L2TP_L2SPECTYPE_DEFAULT] = "default",
25 };
26
27 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_l2spec_type, L2tpL2specType);
28
29 static const char* const l2tp_encap_type_table[_NETDEV_L2TP_ENCAPTYPE_MAX] = {
30 [NETDEV_L2TP_ENCAPTYPE_UDP] = "udp",
31 [NETDEV_L2TP_ENCAPTYPE_IP] = "ip",
32 };
33
34 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_encap_type, L2tpEncapType);
35 DEFINE_CONFIG_PARSE_ENUM(config_parse_l2tp_encap_type, l2tp_encap_type, L2tpEncapType, "Failed to parse L2TP Encapsulation Type");
36
37 static const char* const l2tp_local_address_type_table[_NETDEV_L2TP_LOCAL_ADDRESS_MAX] = {
38 [NETDEV_L2TP_LOCAL_ADDRESS_AUTO] = "auto",
39 [NETDEV_L2TP_LOCAL_ADDRESS_STATIC] = "static",
40 [NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC] = "dynamic",
41 };
42
43 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_local_address_type, L2tpLocalAddressType);
44
45 static void l2tp_session_free(L2tpSession *s) {
46 if (!s)
47 return;
48
49 if (s->tunnel && s->section)
50 ordered_hashmap_remove(s->tunnel->sessions_by_section, s);
51
52 network_config_section_free(s->section);
53
54 free(s->name);
55
56 free(s);
57 }
58
59 DEFINE_NETWORK_SECTION_FUNCTIONS(L2tpSession, l2tp_session_free);
60
61 static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned section_line, L2tpSession **ret) {
62 _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
63 _cleanup_(l2tp_session_freep) L2tpSession *s = NULL;
64 int r;
65
66 assert(t);
67 assert(ret);
68 assert(filename);
69 assert(section_line > 0);
70
71 r = network_config_section_new(filename, section_line, &n);
72 if (r < 0)
73 return r;
74
75 s = ordered_hashmap_get(t->sessions_by_section, n);
76 if (s) {
77 *ret = TAKE_PTR(s);
78 return 0;
79 }
80
81 s = new(L2tpSession, 1);
82 if (!s)
83 return -ENOMEM;
84
85 *s = (L2tpSession) {
86 .l2tp_l2spec_type = NETDEV_L2TP_L2SPECTYPE_DEFAULT,
87 .tunnel = t,
88 .section = TAKE_PTR(n),
89 };
90
91 r = ordered_hashmap_ensure_allocated(&t->sessions_by_section, &network_config_hash_ops);
92 if (r < 0)
93 return r;
94
95 r = ordered_hashmap_put(t->sessions_by_section, s->section, s);
96 if (r < 0)
97 return r;
98
99 *ret = TAKE_PTR(s);
100 return 0;
101 }
102
103 static int netdev_l2tp_fill_message_tunnel(NetDev *netdev, union in_addr_union *local_address, sd_netlink_message **ret) {
104 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
105 uint16_t encap_type;
106 L2tpTunnel *t;
107 int r;
108
109 assert(netdev);
110 assert(local_address);
111
112 t = L2TP(netdev);
113
114 assert(t);
115
116 r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_TUNNEL_CREATE, &m);
117 if (r < 0)
118 return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
119
120 r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, t->tunnel_id);
121 if (r < 0)
122 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_CONN_ID attribute: %m");
123
124 r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, t->peer_tunnel_id);
125 if (r < 0)
126 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_CONN_ID attribute: %m");
127
128 r = sd_netlink_message_append_u8(m, L2TP_ATTR_PROTO_VERSION, 3);
129 if (r < 0)
130 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PROTO_VERSION attribute: %m");
131
132 switch(t->l2tp_encap_type) {
133 case NETDEV_L2TP_ENCAPTYPE_IP:
134 encap_type = L2TP_ENCAPTYPE_IP;
135 break;
136 case NETDEV_L2TP_ENCAPTYPE_UDP:
137 default:
138 encap_type = L2TP_ENCAPTYPE_UDP;
139 break;
140 }
141
142 r = sd_netlink_message_append_u16(m, L2TP_ATTR_ENCAP_TYPE, encap_type);
143 if (r < 0)
144 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_ENCAP_TYPE attribute: %m");
145
146 if (t->family == AF_INET) {
147 r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_SADDR, &local_address->in);
148 if (r < 0)
149 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP_SADDR attribute: %m");
150
151 r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_DADDR, &t->remote.in);
152 if (r < 0)
153 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP_DADDR attribute: %m");
154 } else {
155 r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_SADDR, &local_address->in6);
156 if (r < 0)
157 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP6_SADDR attribute: %m");
158
159 r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_DADDR, &t->remote.in6);
160 if (r < 0)
161 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP6_DADDR attribute: %m");
162 }
163
164 if (encap_type == L2TP_ENCAPTYPE_UDP) {
165 r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_SPORT, t->l2tp_udp_sport);
166 if (r < 0)
167 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_SPORT, attribute: %m");
168
169 r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_DPORT, t->l2tp_udp_dport);
170 if (r < 0)
171 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_DPORT attribute: %m");
172
173 if (t->udp_csum) {
174 r = sd_netlink_message_append_u8(m, L2TP_ATTR_UDP_CSUM, t->udp_csum);
175 if (r < 0)
176 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_CSUM attribute: %m");
177 }
178
179 if (t->udp6_csum_tx) {
180 r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_TX);
181 if (r < 0)
182 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_ZERO_CSUM6_TX attribute: %m");
183 }
184
185 if (t->udp6_csum_rx) {
186 r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_RX);
187 if (r < 0)
188 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_ZERO_CSUM6_RX attribute: %m");
189 }
190 }
191
192 *ret = TAKE_PTR(m);
193
194 return 0;
195 }
196
197 static int netdev_l2tp_fill_message_session(NetDev *netdev, L2tpSession *session, sd_netlink_message **ret) {
198 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
199 uint16_t l2_spec_len;
200 uint8_t l2_spec_type;
201 int r;
202
203 assert(netdev);
204 assert(session);
205 assert(session->tunnel);
206
207 r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_SESSION_CREATE, &m);
208 if (r < 0)
209 return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
210
211 r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, session->tunnel->tunnel_id);
212 if (r < 0)
213 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_CONN_ID attribute: %m");
214
215 r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, session->tunnel->peer_tunnel_id);
216 if (r < 0)
217 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_CONN_ID attribute: %m");
218
219 r = sd_netlink_message_append_u32(m, L2TP_ATTR_SESSION_ID, session->session_id);
220 if (r < 0)
221 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_SESSION_ID attribute: %m");
222
223 r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_SESSION_ID, session->peer_session_id);
224 if (r < 0)
225 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_SESSION_ID attribute: %m");
226
227 r = sd_netlink_message_append_u16(m, L2TP_ATTR_PW_TYPE, L2TP_PWTYPE_ETH);
228 if (r < 0)
229 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PW_TYPE attribute: %m");
230
231 switch (session->l2tp_l2spec_type) {
232 case NETDEV_L2TP_L2SPECTYPE_NONE:
233 l2_spec_type = L2TP_L2SPECTYPE_NONE;
234 l2_spec_len = 0;
235 break;
236 case NETDEV_L2TP_L2SPECTYPE_DEFAULT:
237 default:
238 l2_spec_type = L2TP_L2SPECTYPE_DEFAULT;
239 l2_spec_len = 4;
240 break;
241 }
242
243 r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_TYPE, l2_spec_type);
244 if (r < 0)
245 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_L2SPEC_TYPE attribute: %m");
246
247 r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_LEN, l2_spec_len);
248 if (r < 0)
249 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_L2SPEC_LEN attribute: %m");
250
251 r = sd_netlink_message_append_string(m, L2TP_ATTR_IFNAME, session->name);
252 if (r < 0)
253 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IFNAME attribute: %m");
254
255 *ret = TAKE_PTR(m);
256
257 return 0;
258 }
259
260 static int l2tp_acquire_local_address_one(L2tpTunnel *t, Address *a, union in_addr_union *ret) {
261 if (a->family != t->family)
262 return -EINVAL;
263
264 if (in_addr_is_null(a->family, &a->in_addr_peer) <= 0)
265 return -EINVAL;
266
267 if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_STATIC &&
268 !FLAGS_SET(a->flags, IFA_F_PERMANENT))
269 return -EINVAL;
270
271 if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC &&
272 FLAGS_SET(a->flags, IFA_F_PERMANENT))
273 return -EINVAL;
274
275 *ret = a->in_addr;
276 return 0;
277 }
278
279 static int l2tp_acquire_local_address(L2tpTunnel *t, Link *link, union in_addr_union *ret) {
280 Address *a;
281 Iterator i;
282
283 assert(t);
284 assert(link);
285 assert(ret);
286 assert(IN_SET(t->family, AF_INET, AF_INET6));
287
288 if (!in_addr_is_null(t->family, &t->local)) {
289 /* local address is explicitly specified. */
290 *ret = t->local;
291 return 0;
292 }
293
294 SET_FOREACH(a, link->addresses, i)
295 if (l2tp_acquire_local_address_one(t, a, ret) >= 0)
296 return 1;
297
298 SET_FOREACH(a, link->addresses_foreign, i)
299 if (l2tp_acquire_local_address_one(t, a, ret) >= 0)
300 return 1;
301
302 return -ENODATA;
303 }
304
305 static void l2tp_session_destroy_callback(L2tpSession *session) {
306 if (!session)
307 return;
308
309 netdev_unref(NETDEV(session->tunnel));
310 }
311
312 static int l2tp_create_session_handler(sd_netlink *rtnl, sd_netlink_message *m, L2tpSession *session) {
313 NetDev *netdev;
314 int r;
315
316 assert(session);
317 assert(session->tunnel);
318
319 netdev = NETDEV(session->tunnel);
320
321 r = sd_netlink_message_get_errno(m);
322 if (r == -EEXIST)
323 log_netdev_info(netdev, "L2TP session %s exists, using existing without changing its parameters",
324 session->name);
325 else if (r < 0) {
326 log_netdev_warning_errno(netdev, r, "L2TP session %s could not be created: %m", session->name);
327 return 1;
328 }
329
330 log_netdev_debug(netdev, "L2TP session %s created", session->name);
331 return 1;
332 }
333
334 static int l2tp_create_session(NetDev *netdev, L2tpSession *session) {
335 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *n = NULL;
336 int r;
337
338 r = netdev_l2tp_fill_message_session(netdev, session, &n);
339 if (r < 0)
340 return r;
341
342 r = netlink_call_async(netdev->manager->genl, NULL, n, l2tp_create_session_handler,
343 l2tp_session_destroy_callback, session);
344 if (r < 0)
345 return log_netdev_error_errno(netdev, r, "Failed to create L2TP session %s: %m", session->name);
346
347 netdev_ref(netdev);
348 return 0;
349 }
350
351 static int l2tp_create_tunnel_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
352 L2tpSession *session;
353 L2tpTunnel *t;
354 Iterator i;
355 int r;
356
357 assert(netdev);
358 assert(netdev->state != _NETDEV_STATE_INVALID);
359
360 t = L2TP(netdev);
361
362 assert(t);
363
364 r = sd_netlink_message_get_errno(m);
365 if (r == -EEXIST)
366 log_netdev_info(netdev, "netdev exists, using existing without changing its parameters");
367 else if (r < 0) {
368 log_netdev_warning_errno(netdev, r, "netdev could not be created: %m");
369 netdev_drop(netdev);
370
371 return 1;
372 }
373
374 log_netdev_debug(netdev, "L2TP tunnel is created");
375
376 ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i)
377 (void) l2tp_create_session(netdev, session);
378
379 return 1;
380 }
381
382 static int l2tp_create_tunnel(NetDev *netdev, Link *link) {
383 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
384 union in_addr_union local_address;
385 L2tpTunnel *t;
386 int r;
387
388 assert(netdev);
389
390 t = L2TP(netdev);
391
392 assert(t);
393
394 r = l2tp_acquire_local_address(t, link, &local_address);
395 if (r < 0)
396 return log_netdev_error_errno(netdev, r, "Could not find local address.");
397
398 if (r > 0 && DEBUG_LOGGING) {
399 _cleanup_free_ char *str = NULL;
400
401 (void) in_addr_to_string(t->family, &local_address, &str);
402 log_netdev_debug(netdev, "Local address %s acquired.", strna(str));
403 }
404
405 r = netdev_l2tp_fill_message_tunnel(netdev, &local_address, &m);
406 if (r < 0)
407 return r;
408
409 r = netlink_call_async(netdev->manager->genl, NULL, m, l2tp_create_tunnel_handler,
410 netdev_destroy_callback, netdev);
411 if (r < 0)
412 return log_netdev_error_errno(netdev, r, "Failed to create L2TP tunnel: %m");
413
414 netdev_ref(netdev);
415
416 return 0;
417 }
418
419 int config_parse_l2tp_tunnel_address(
420 const char *unit,
421 const char *filename,
422 unsigned line,
423 const char *section,
424 unsigned section_line,
425 const char *lvalue,
426 int ltype,
427 const char *rvalue,
428 void *data,
429 void *userdata) {
430
431 L2tpTunnel *t = userdata;
432 union in_addr_union *addr = data;
433 int r;
434
435 assert(filename);
436 assert(lvalue);
437 assert(rvalue);
438 assert(data);
439
440 if (streq(lvalue, "Local")) {
441 L2tpLocalAddressType addr_type;
442
443 if (isempty(rvalue))
444 addr_type = NETDEV_L2TP_LOCAL_ADDRESS_AUTO;
445 else
446 addr_type = l2tp_local_address_type_from_string(rvalue);
447
448 if (addr_type >= 0) {
449 if (in_addr_is_null(t->family, &t->remote) != 0)
450 /* If Remote= is not specified yet, then also clear family. */
451 t->family = AF_UNSPEC;
452
453 t->local = IN_ADDR_NULL;
454 t->local_address_type = addr_type;
455
456 return 0;
457 }
458 }
459
460 if (t->family == AF_UNSPEC)
461 r = in_addr_from_string_auto(rvalue, &t->family, addr);
462 else
463 r = in_addr_from_string(t->family, rvalue, addr);
464 if (r < 0) {
465 log_syntax(unit, LOG_ERR, filename, line, r,
466 "Invalid L2TP Tunnel address specified in %s='%s', ignoring assignment: %m", lvalue, rvalue);
467 return 0;
468 }
469
470 return 0;
471 }
472
473 int config_parse_l2tp_tunnel_id(
474 const char *unit,
475 const char *filename,
476 unsigned line,
477 const char *section,
478 unsigned section_line,
479 const char *lvalue,
480 int ltype,
481 const char *rvalue,
482 void *data,
483 void *userdata) {
484
485 uint32_t *id = data, k;
486 int r;
487
488 assert(filename);
489 assert(lvalue);
490 assert(rvalue);
491 assert(data);
492
493 r = safe_atou32(rvalue, &k);
494 if (r < 0) {
495 log_syntax(unit, LOG_ERR, filename, line, r,
496 "Failed to parse L2TP tunnel id. Ignoring assignment: %s", rvalue);
497 return 0;
498 }
499
500 if (k == 0) {
501 log_syntax(unit, LOG_ERR, filename, line, r,
502 "Invalid L2TP tunnel id. Ignoring assignment: %s", rvalue);
503 return 0;
504 }
505
506 *id = k;
507
508 return 0;
509 }
510
511 int config_parse_l2tp_session_id(
512 const char *unit,
513 const char *filename,
514 unsigned line,
515 const char *section,
516 unsigned section_line,
517 const char *lvalue,
518 int ltype,
519 const char *rvalue,
520 void *data,
521 void *userdata) {
522
523 _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
524 L2tpTunnel *t = userdata;
525 uint32_t k;
526 int r;
527
528 assert(filename);
529 assert(section);
530 assert(lvalue);
531 assert(rvalue);
532 assert(data);
533
534 r = l2tp_session_new_static(t, filename, section_line, &session);
535 if (r < 0)
536 return r;
537
538 r = safe_atou32(rvalue, &k);
539 if (r < 0) {
540 log_syntax(unit, LOG_ERR, filename, line, r,
541 "Failed to parse L2TP session id. Ignoring assignment: %s", rvalue);
542 return 0;
543 }
544
545 if (k == 0) {
546 log_syntax(unit, LOG_ERR, filename, line, r,
547 "Invalid L2TP session id. Ignoring assignment: %s", rvalue);
548 return 0;
549 }
550
551 if (streq(lvalue, "SessionId"))
552 session->session_id = k;
553 else
554 session->peer_session_id = k;
555
556 session = NULL;
557 return 0;
558 }
559
560 int config_parse_l2tp_session_l2spec(
561 const char *unit,
562 const char *filename,
563 unsigned line,
564 const char *section,
565 unsigned section_line,
566 const char *lvalue,
567 int ltype,
568 const char *rvalue,
569 void *data,
570 void *userdata) {
571
572 _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
573 L2tpTunnel *t = userdata;
574 L2tpL2specType spec;
575 int r;
576
577 assert(filename);
578 assert(section);
579 assert(lvalue);
580 assert(rvalue);
581 assert(data);
582
583 r = l2tp_session_new_static(t, filename, section_line, &session);
584 if (r < 0)
585 return r;
586
587 spec = l2tp_l2spec_type_from_string(rvalue);
588 if (spec < 0) {
589 log_syntax(unit, LOG_ERR, filename, line, 0,
590 "Failed to parse layer2 specific header type. Ignoring assignment: %s", rvalue);
591 return 0;
592 }
593
594 session->l2tp_l2spec_type = spec;
595
596 session = NULL;
597 return 0;
598 }
599
600 int config_parse_l2tp_session_name(
601 const char *unit,
602 const char *filename,
603 unsigned line,
604 const char *section,
605 unsigned section_line,
606 const char *lvalue,
607 int ltype,
608 const char *rvalue,
609 void *data,
610 void *userdata) {
611
612 _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
613 L2tpTunnel *t = userdata;
614 int r;
615
616 assert(filename);
617 assert(section);
618 assert(lvalue);
619 assert(rvalue);
620 assert(data);
621
622 r = l2tp_session_new_static(t, filename, section_line, &session);
623 if (r < 0)
624 return r;
625
626 if (!ifname_valid(rvalue)) {
627 log_syntax(unit, LOG_ERR, filename, line, 0,
628 "Failed to parse L2TP tunnel session name. Ignoring assignment: %s", rvalue);
629 return 0;
630 }
631
632 r = free_and_strdup(&session->name, rvalue);
633 if (r < 0)
634 return log_oom();
635
636 session = NULL;
637 return 0;
638 }
639
640 static void l2tp_tunnel_init(NetDev *netdev) {
641 L2tpTunnel *t;
642
643 assert(netdev);
644
645 t = L2TP(netdev);
646
647 assert(t);
648
649 t->l2tp_encap_type = NETDEV_L2TP_ENCAPTYPE_UDP;
650 t->udp6_csum_rx = true;
651 t->udp6_csum_tx = true;
652 }
653
654 static int l2tp_session_verify(L2tpSession *session) {
655 NetDev *netdev;
656
657 assert(session);
658 assert(session->tunnel);
659
660 netdev = NETDEV(session->tunnel);
661
662 if (section_is_invalid(session->section))
663 return -EINVAL;
664
665 if (!session->name)
666 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
667 "%s: L2TP session without name configured. "
668 "Ignoring [L2TPSession] section from line %u",
669 session->section->filename, session->section->line);
670
671 if (session->session_id == 0 || session->peer_session_id == 0)
672 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
673 "%s: L2TP session without session IDs configured. "
674 "Ignoring [L2TPSession] section from line %u",
675 session->section->filename, session->section->line);
676
677 return 0;
678 }
679
680 static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) {
681 L2tpTunnel *t;
682 L2tpSession *session;
683 Iterator i;
684
685 assert(netdev);
686 assert(filename);
687
688 t = L2TP(netdev);
689
690 assert(t);
691
692 if (!IN_SET(t->family, AF_INET, AF_INET6))
693 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
694 "%s: L2TP tunnel with invalid address family configured. Ignoring",
695 filename);
696
697 if (in_addr_is_null(t->family, &t->remote))
698 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
699 "%s: L2TP tunnel without a remote address configured. Ignoring",
700 filename);
701
702 if (t->tunnel_id == 0 || t->peer_tunnel_id == 0)
703 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
704 "%s: L2TP tunnel without tunnel IDs configured. Ignoring",
705 filename);
706
707 ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i)
708 if (l2tp_session_verify(session) < 0)
709 l2tp_session_free(session);
710
711 return 0;
712 }
713
714 static void l2tp_tunnel_done(NetDev *netdev) {
715 L2tpTunnel *t;
716
717 assert(netdev);
718
719 t = L2TP(netdev);
720
721 assert(t);
722
723 ordered_hashmap_free_with_destructor(t->sessions_by_section, l2tp_session_free);
724 }
725
726 const NetDevVTable l2tptnl_vtable = {
727 .object_size = sizeof(L2tpTunnel),
728 .init = l2tp_tunnel_init,
729 .sections = "Match\0NetDev\0L2TP\0L2TPSession\0",
730 .create_after_configured = l2tp_create_tunnel,
731 .done = l2tp_tunnel_done,
732 .create_type = NETDEV_CREATE_AFTER_CONFIGURED,
733 .config_verify = netdev_l2tp_tunnel_verify,
734 };