1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <netinet/in.h>
4 #include <linux/l2tp.h>
5 #include <linux/genetlink.h>
6 
7 #include "conf-parser.h"
8 #include "hashmap.h"
9 #include "l2tp-tunnel.h"
10 #include "netlink-util.h"
11 #include "networkd-address.h"
12 #include "networkd-manager.h"
13 #include "networkd-route-util.h"
14 #include "parse-util.h"
15 #include "socket-util.h"
16 #include "string-table.h"
17 #include "string-util.h"
18 #include "util.h"
19 
20 static const char* const l2tp_l2spec_type_table[_NETDEV_L2TP_L2SPECTYPE_MAX] = {
21         [NETDEV_L2TP_L2SPECTYPE_NONE]    = "none",
22         [NETDEV_L2TP_L2SPECTYPE_DEFAULT] = "default",
23 };
24 
25 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_l2spec_type, L2tpL2specType);
26 
27 static const char* const l2tp_encap_type_table[_NETDEV_L2TP_ENCAPTYPE_MAX] = {
28         [NETDEV_L2TP_ENCAPTYPE_UDP] = "udp",
29         [NETDEV_L2TP_ENCAPTYPE_IP]  = "ip",
30 };
31 
32 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_encap_type, L2tpEncapType);
33 DEFINE_CONFIG_PARSE_ENUM(config_parse_l2tp_encap_type, l2tp_encap_type, L2tpEncapType, "Failed to parse L2TP Encapsulation Type");
34 
35 static const char* const l2tp_local_address_type_table[_NETDEV_L2TP_LOCAL_ADDRESS_MAX] = {
36          [NETDEV_L2TP_LOCAL_ADDRESS_AUTO]    = "auto",
37          [NETDEV_L2TP_LOCAL_ADDRESS_STATIC]  = "static",
38          [NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC] = "dynamic",
39 };
40 
41 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_local_address_type, L2tpLocalAddressType);
42 
l2tp_session_free(L2tpSession * s)43 static L2tpSession* l2tp_session_free(L2tpSession *s) {
44         if (!s)
45                 return NULL;
46 
47         if (s->tunnel && s->section)
48                 ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section);
49 
50         config_section_free(s->section);
51         free(s->name);
52         return mfree(s);
53 }
54 
55 DEFINE_SECTION_CLEANUP_FUNCTIONS(L2tpSession, l2tp_session_free);
56 
l2tp_session_new_static(L2tpTunnel * t,const char * filename,unsigned section_line,L2tpSession ** ret)57 static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned section_line, L2tpSession **ret) {
58         _cleanup_(config_section_freep) ConfigSection *n = NULL;
59         _cleanup_(l2tp_session_freep) L2tpSession *s = NULL;
60         int r;
61 
62         assert(t);
63         assert(ret);
64         assert(filename);
65         assert(section_line > 0);
66 
67         r = config_section_new(filename, section_line, &n);
68         if (r < 0)
69                 return r;
70 
71         s = ordered_hashmap_get(t->sessions_by_section, n);
72         if (s) {
73                 *ret = TAKE_PTR(s);
74                 return 0;
75         }
76 
77         s = new(L2tpSession, 1);
78         if (!s)
79                 return -ENOMEM;
80 
81         *s = (L2tpSession) {
82                 .l2tp_l2spec_type = NETDEV_L2TP_L2SPECTYPE_DEFAULT,
83                 .tunnel = t,
84                 .section = TAKE_PTR(n),
85         };
86 
87         r = ordered_hashmap_ensure_put(&t->sessions_by_section, &config_section_hash_ops, s->section, s);
88         if (r < 0)
89                 return r;
90 
91         *ret = TAKE_PTR(s);
92         return 0;
93 }
94 
netdev_l2tp_create_message_tunnel(NetDev * netdev,union in_addr_union * local_address,sd_netlink_message ** ret)95 static int netdev_l2tp_create_message_tunnel(NetDev *netdev, union in_addr_union *local_address, sd_netlink_message **ret) {
96         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
97         uint16_t encap_type;
98         L2tpTunnel *t;
99         int r;
100 
101         assert(netdev);
102         assert(local_address);
103         assert_se(t = L2TP(netdev));
104 
105         r = sd_genl_message_new(netdev->manager->genl, L2TP_GENL_NAME, L2TP_CMD_TUNNEL_CREATE, &m);
106         if (r < 0)
107                 return r;
108 
109         r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, t->tunnel_id);
110         if (r < 0)
111                 return r;
112 
113         r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, t->peer_tunnel_id);
114         if (r < 0)
115                 return r;
116 
117         r = sd_netlink_message_append_u8(m, L2TP_ATTR_PROTO_VERSION, 3);
118         if (r < 0)
119                 return r;
120 
121         switch (t->l2tp_encap_type) {
122         case NETDEV_L2TP_ENCAPTYPE_IP:
123                 encap_type = L2TP_ENCAPTYPE_IP;
124                 break;
125         case NETDEV_L2TP_ENCAPTYPE_UDP:
126         default:
127                 encap_type = L2TP_ENCAPTYPE_UDP;
128                 break;
129         }
130 
131         r = sd_netlink_message_append_u16(m, L2TP_ATTR_ENCAP_TYPE, encap_type);
132         if (r < 0)
133                 return r;
134 
135         if (t->family == AF_INET) {
136                 r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_SADDR, &local_address->in);
137                 if (r < 0)
138                         return r;
139 
140                 r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_DADDR, &t->remote.in);
141                 if (r < 0)
142                         return r;
143         } else {
144                 r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_SADDR, &local_address->in6);
145                 if (r < 0)
146                         return r;
147 
148                 r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_DADDR, &t->remote.in6);
149                 if (r < 0)
150                         return r;
151         }
152 
153         if (encap_type == L2TP_ENCAPTYPE_UDP) {
154                 r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_SPORT, t->l2tp_udp_sport);
155                 if (r < 0)
156                         return r;
157 
158                 r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_DPORT, t->l2tp_udp_dport);
159                 if (r < 0)
160                         return r;
161 
162                 if (t->udp_csum) {
163                         r = sd_netlink_message_append_u8(m, L2TP_ATTR_UDP_CSUM, t->udp_csum);
164                         if (r < 0)
165                                 return r;
166                 }
167 
168                 if (t->udp6_csum_tx) {
169                         r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_TX);
170                         if (r < 0)
171                                 return r;
172                 }
173 
174                 if (t->udp6_csum_rx) {
175                         r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_RX);
176                         if (r < 0)
177                                 return r;
178                 }
179         }
180 
181         *ret = TAKE_PTR(m);
182 
183         return 0;
184 }
185 
netdev_l2tp_create_message_session(NetDev * netdev,L2tpSession * session,sd_netlink_message ** ret)186 static int netdev_l2tp_create_message_session(NetDev *netdev, L2tpSession *session, sd_netlink_message **ret) {
187         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
188         uint16_t l2_spec_len;
189         uint8_t l2_spec_type;
190         int r;
191 
192         assert(netdev);
193         assert(session);
194         assert(session->tunnel);
195 
196         r = sd_genl_message_new(netdev->manager->genl, L2TP_GENL_NAME, L2TP_CMD_SESSION_CREATE, &m);
197         if (r < 0)
198                 return r;
199 
200         r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, session->tunnel->tunnel_id);
201         if (r < 0)
202                 return r;
203 
204         r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, session->tunnel->peer_tunnel_id);
205         if (r < 0)
206                 return r;
207 
208         r = sd_netlink_message_append_u32(m, L2TP_ATTR_SESSION_ID, session->session_id);
209         if (r < 0)
210                 return r;
211 
212         r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_SESSION_ID, session->peer_session_id);
213         if (r < 0)
214                 return r;
215 
216         r = sd_netlink_message_append_u16(m, L2TP_ATTR_PW_TYPE, L2TP_PWTYPE_ETH);
217         if (r < 0)
218                 return r;
219 
220         switch (session->l2tp_l2spec_type) {
221         case NETDEV_L2TP_L2SPECTYPE_NONE:
222                 l2_spec_type = L2TP_L2SPECTYPE_NONE;
223                 l2_spec_len = 0;
224                 break;
225         case NETDEV_L2TP_L2SPECTYPE_DEFAULT:
226         default:
227                 l2_spec_type = L2TP_L2SPECTYPE_DEFAULT;
228                 l2_spec_len = 4;
229                 break;
230         }
231 
232         r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_TYPE, l2_spec_type);
233         if (r < 0)
234                 return r;
235 
236         r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_LEN, l2_spec_len);
237         if (r < 0)
238                 return r;
239 
240         r = sd_netlink_message_append_string(m, L2TP_ATTR_IFNAME, session->name);
241         if (r < 0)
242                 return r;
243 
244         *ret = TAKE_PTR(m);
245 
246         return 0;
247 }
248 
link_get_l2tp_local_address(Link * link,L2tpTunnel * t,union in_addr_union * ret)249 static int link_get_l2tp_local_address(Link *link, L2tpTunnel *t, union in_addr_union *ret) {
250         Address *a;
251 
252         assert(link);
253         assert(t);
254 
255         SET_FOREACH(a, link->addresses) {
256                 if (!address_is_ready(a))
257                         continue;
258 
259                 if (a->family != t->family)
260                         continue;
261 
262                 if (in_addr_is_set(a->family, &a->in_addr_peer))
263                         continue;
264 
265                 if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_STATIC &&
266                     !FLAGS_SET(a->flags, IFA_F_PERMANENT))
267                         continue;
268 
269                 if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC &&
270                     FLAGS_SET(a->flags, IFA_F_PERMANENT))
271                         continue;
272 
273                 if (ret)
274                         *ret = a->in_addr;
275         }
276 
277         return -ENOENT;
278 }
279 
l2tp_get_local_address(NetDev * netdev,union in_addr_union * ret)280 static int l2tp_get_local_address(NetDev *netdev, union in_addr_union *ret) {
281         Link *link = NULL;
282         L2tpTunnel *t;
283         Address *a;
284         int r;
285 
286         assert(netdev);
287         assert(netdev->manager);
288         assert_se(t = L2TP(netdev));
289 
290         if (t->local_ifname) {
291                 r = link_get_by_name(netdev->manager, t->local_ifname, &link);
292                 if (r < 0)
293                         return r;
294 
295                 if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
296                         return -EBUSY;
297         }
298 
299         if (netdev->manager->manage_foreign_routes) {
300                 /* First, check if the remote address is accessible. */
301                 if (link)
302                         r = link_address_is_reachable(link, t->family, &t->remote, &t->local, &a);
303                 else
304                         r = manager_address_is_reachable(netdev->manager, t->family, &t->remote, &t->local, &a);
305                 if (r < 0)
306                         return r;
307         }
308 
309         if (in_addr_is_set(t->family, &t->local)) {
310                 /* local address is explicitly specified. */
311 
312                 if (!a) {
313                         if (link)
314                                 r = link_get_address(link, t->family, &t->local, 0, &a);
315                         else
316                                 r = manager_get_address(netdev->manager, t->family, &t->local, 0, &a);
317                         if (r < 0)
318                                 return r;
319 
320                         if (!address_is_ready(a))
321                                 return -EBUSY;
322                 }
323 
324                 if (ret)
325                         *ret = a->in_addr;
326 
327                 return 0;
328         }
329 
330         if (a) {
331                 if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_STATIC &&
332                     !FLAGS_SET(a->flags, IFA_F_PERMANENT))
333                         return -EINVAL;
334 
335                 if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC &&
336                     FLAGS_SET(a->flags, IFA_F_PERMANENT))
337                         return -EINVAL;
338 
339                 if (ret)
340                         *ret = a->in_addr;
341 
342                 return 0;
343         }
344 
345         if (link)
346                 return link_get_l2tp_local_address(link, t, ret);
347 
348         HASHMAP_FOREACH(link, netdev->manager->links_by_index) {
349                 if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
350                         continue;
351 
352                 if (link_get_l2tp_local_address(link, t, ret) >= 0)
353                         return 0;
354         }
355 
356         return -ENOENT;
357 }
358 
l2tp_session_destroy_callback(L2tpSession * session)359 static void l2tp_session_destroy_callback(L2tpSession *session) {
360         if (!session)
361                 return;
362 
363         netdev_unref(NETDEV(session->tunnel));
364 }
365 
l2tp_create_session_handler(sd_netlink * rtnl,sd_netlink_message * m,L2tpSession * session)366 static int l2tp_create_session_handler(sd_netlink *rtnl, sd_netlink_message *m, L2tpSession *session) {
367         NetDev *netdev;
368         int r;
369 
370         assert(session);
371         assert(session->tunnel);
372 
373         netdev = NETDEV(session->tunnel);
374 
375         r = sd_netlink_message_get_errno(m);
376         if (r == -EEXIST)
377                 log_netdev_info(netdev, "L2TP session %s exists, using existing without changing its parameters",
378                                 session->name);
379         else if (r < 0) {
380                 log_netdev_warning_errno(netdev, r, "L2TP session %s could not be created: %m", session->name);
381                 return 1;
382         }
383 
384         log_netdev_debug(netdev, "L2TP session %s created", session->name);
385         return 1;
386 }
387 
l2tp_create_session(NetDev * netdev,L2tpSession * session)388 static int l2tp_create_session(NetDev *netdev, L2tpSession *session) {
389         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *n = NULL;
390         int r;
391 
392         r = netdev_l2tp_create_message_session(netdev, session, &n);
393         if (r < 0)
394                 return log_netdev_error_errno(netdev, r, "Failed to create netlink message: %m");
395 
396         r = netlink_call_async(netdev->manager->genl, NULL, n, l2tp_create_session_handler,
397                                l2tp_session_destroy_callback, session);
398         if (r < 0)
399                 return log_netdev_error_errno(netdev, r, "Failed to create L2TP session %s: %m", session->name);
400 
401         netdev_ref(netdev);
402         return 0;
403 }
404 
l2tp_create_tunnel_handler(sd_netlink * rtnl,sd_netlink_message * m,NetDev * netdev)405 static int l2tp_create_tunnel_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
406         L2tpSession *session;
407         L2tpTunnel *t;
408         int r;
409 
410         assert(netdev);
411         assert(netdev->state != _NETDEV_STATE_INVALID);
412 
413         t = L2TP(netdev);
414 
415         assert(t);
416 
417         r = sd_netlink_message_get_errno(m);
418         if (r == -EEXIST)
419                 log_netdev_info(netdev, "netdev exists, using existing without changing its parameters");
420         else if (r < 0) {
421                 log_netdev_warning_errno(netdev, r, "netdev could not be created: %m");
422                 netdev_enter_failed(netdev);
423 
424                 return 1;
425         }
426 
427         log_netdev_debug(netdev, "L2TP tunnel is created");
428 
429         ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section)
430                 (void) l2tp_create_session(netdev, session);
431 
432         return 1;
433 }
434 
l2tp_create_tunnel(NetDev * netdev)435 static int l2tp_create_tunnel(NetDev *netdev) {
436         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
437         union in_addr_union local_address;
438         L2tpTunnel *t;
439         int r;
440 
441         assert(netdev);
442         assert_se(t = L2TP(netdev));
443 
444         r = l2tp_get_local_address(netdev, &local_address);
445         if (r < 0)
446                 return log_netdev_error_errno(netdev, r, "Could not find local address.");
447 
448         if (t->local_address_type >= 0 && DEBUG_LOGGING) {
449                 _cleanup_free_ char *str = NULL;
450 
451                 (void) in_addr_to_string(t->family, &local_address, &str);
452                 log_netdev_debug(netdev, "Local address %s acquired.", strna(str));
453         }
454 
455         r = netdev_l2tp_create_message_tunnel(netdev, &local_address, &m);
456         if (r < 0)
457                 return log_netdev_error_errno(netdev, r, "Failed to create netlink message: %m");
458 
459         r = netlink_call_async(netdev->manager->genl, NULL, m, l2tp_create_tunnel_handler,
460                                netdev_destroy_callback, netdev);
461         if (r < 0)
462                 return log_netdev_error_errno(netdev, r, "Failed to create L2TP tunnel: %m");
463 
464         netdev_ref(netdev);
465 
466         return 0;
467 }
468 
netdev_l2tp_is_ready_to_create(NetDev * netdev,Link * link)469 static int netdev_l2tp_is_ready_to_create(NetDev *netdev, Link *link) {
470         return l2tp_get_local_address(netdev, NULL) >= 0;
471 }
472 
config_parse_l2tp_tunnel_local_address(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)473 int config_parse_l2tp_tunnel_local_address(
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         _cleanup_free_ char *addr_or_type = NULL, *ifname = NULL;
486         L2tpLocalAddressType type;
487         L2tpTunnel *t = userdata;
488         const char *p = rvalue;
489         union in_addr_union a;
490         int r, f;
491 
492         assert(filename);
493         assert(lvalue);
494         assert(rvalue);
495         assert(t);
496 
497         if (isempty(rvalue)) {
498                 t->local_ifname = mfree(t->local_ifname);
499                 t->local_address_type = NETDEV_L2TP_LOCAL_ADDRESS_AUTO;
500                 t->local = IN_ADDR_NULL;
501 
502                 if (!in_addr_is_set(t->family, &t->remote))
503                         /* If Remote= is not specified yet, then also clear family. */
504                         t->family = AF_UNSPEC;
505 
506                 return 0;
507         }
508 
509         r = extract_first_word(&p, &addr_or_type, "@", 0);
510         if (r < 0)
511                 return log_oom();
512         if (r == 0) {
513                 log_syntax(unit, LOG_WARNING, filename, line, 0,
514                            "Invalid L2TP Tunnel address specified in %s=, ignoring assignment: %s", lvalue, rvalue);
515                 return 0;
516         }
517 
518         if (!isempty(p)) {
519                 if (!ifname_valid_full(p, IFNAME_VALID_ALTERNATIVE)) {
520                         log_syntax(unit, LOG_WARNING, filename, line, 0,
521                                    "Invalid interface name specified in %s=, ignoring assignment: %s", lvalue, rvalue);
522                         return 0;
523                 }
524 
525                 ifname = strdup(p);
526                 if (!ifname)
527                         return log_oom();
528         }
529 
530         type = l2tp_local_address_type_from_string(rvalue);
531         if (type >= 0) {
532                 free_and_replace(t->local_ifname, ifname);
533                 t->local_address_type = type;
534                 t->local = IN_ADDR_NULL;
535 
536                 if (!in_addr_is_set(t->family, &t->remote))
537                         /* If Remote= is not specified yet, then also clear family. */
538                         t->family = AF_UNSPEC;
539 
540                 return 0;
541         }
542 
543         r = in_addr_from_string_auto(rvalue, &f, &a);
544         if (r < 0) {
545                 log_syntax(unit, LOG_WARNING, filename, line, r,
546                            "Invalid L2TP Tunnel local address specified, ignoring assignment: %s", rvalue);
547                 return 0;
548         }
549 
550         if (in_addr_is_null(f, &a)) {
551                 log_syntax(unit, LOG_WARNING, filename, line, r,
552                            "L2TP Tunnel local address cannot be null, ignoring assignment: %s", rvalue);
553                 return 0;
554         }
555 
556         if (t->family != AF_UNSPEC && t->family != f) {
557                 log_syntax(unit, LOG_WARNING, filename, line, 0,
558                            "Address family does not match the previous assignment, ignoring assignment: %s", rvalue);
559                 return 0;
560         }
561 
562         t->family = f;
563         t->local = a;
564         free_and_replace(t->local_ifname, ifname);
565         t->local_address_type = _NETDEV_L2TP_LOCAL_ADDRESS_INVALID;
566         return 0;
567 }
568 
config_parse_l2tp_tunnel_remote_address(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)569 int config_parse_l2tp_tunnel_remote_address(
570                 const char *unit,
571                 const char *filename,
572                 unsigned line,
573                 const char *section,
574                 unsigned section_line,
575                 const char *lvalue,
576                 int ltype,
577                 const char *rvalue,
578                 void *data,
579                 void *userdata) {
580 
581         L2tpTunnel *t = userdata;
582         union in_addr_union a;
583         int r, f;
584 
585         assert(filename);
586         assert(lvalue);
587         assert(rvalue);
588         assert(t);
589 
590         if (isempty(rvalue)) {
591                 t->remote = IN_ADDR_NULL;
592 
593                 if (!in_addr_is_set(t->family, &t->local))
594                         /* If Local= is not specified yet, then also clear family. */
595                         t->family = AF_UNSPEC;
596 
597                 return 0;
598         }
599 
600         r = in_addr_from_string_auto(rvalue, &f, &a);
601         if (r < 0) {
602                 log_syntax(unit, LOG_WARNING, filename, line, r,
603                            "Invalid L2TP Tunnel remote address specified, ignoring assignment: %s", rvalue);
604                 return 0;
605         }
606 
607         if (in_addr_is_null(f, &a)) {
608                 log_syntax(unit, LOG_WARNING, filename, line, r,
609                            "L2TP Tunnel remote address cannot be null, ignoring assignment: %s", rvalue);
610                 return 0;
611         }
612 
613         if (t->family != AF_UNSPEC && t->family != f) {
614                 log_syntax(unit, LOG_WARNING, filename, line, 0,
615                            "Address family does not match the previous assignment, ignoring assignment: %s", rvalue);
616                 return 0;
617         }
618 
619         t->family = f;
620         t->remote = a;
621         return 0;
622 }
623 
config_parse_l2tp_tunnel_id(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)624 int config_parse_l2tp_tunnel_id(
625                 const char *unit,
626                 const char *filename,
627                 unsigned line,
628                 const char *section,
629                 unsigned section_line,
630                 const char *lvalue,
631                 int ltype,
632                 const char *rvalue,
633                 void *data,
634                 void *userdata) {
635 
636         uint32_t *id = data, k;
637         int r;
638 
639         assert(filename);
640         assert(lvalue);
641         assert(rvalue);
642         assert(data);
643 
644         r = safe_atou32(rvalue, &k);
645         if (r < 0) {
646                 log_syntax(unit, LOG_WARNING, filename, line, r,
647                            "Failed to parse L2TP tunnel id. Ignoring assignment: %s", rvalue);
648                 return 0;
649         }
650 
651         if (k == 0) {
652                 log_syntax(unit, LOG_WARNING, filename, line, 0,
653                            "Invalid L2TP tunnel id. Ignoring assignment: %s", rvalue);
654                 return 0;
655         }
656 
657         *id = k;
658 
659         return 0;
660 }
661 
config_parse_l2tp_session_id(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)662 int config_parse_l2tp_session_id(
663                 const char *unit,
664                 const char *filename,
665                 unsigned line,
666                 const char *section,
667                 unsigned section_line,
668                 const char *lvalue,
669                 int ltype,
670                 const char *rvalue,
671                 void *data,
672                 void *userdata) {
673 
674         _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
675         L2tpTunnel *t = userdata;
676         uint32_t k;
677         int r;
678 
679         assert(filename);
680         assert(section);
681         assert(lvalue);
682         assert(rvalue);
683         assert(data);
684 
685         r = l2tp_session_new_static(t, filename, section_line, &session);
686         if (r < 0)
687                 return log_oom();
688 
689         r = safe_atou32(rvalue, &k);
690         if (r < 0) {
691                 log_syntax(unit, LOG_WARNING, filename, line, r,
692                            "Failed to parse L2TP session id. Ignoring assignment: %s", rvalue);
693                 return 0;
694         }
695 
696         if (k == 0) {
697                 log_syntax(unit, LOG_WARNING, filename, line, 0,
698                            "Invalid L2TP session id. Ignoring assignment: %s", rvalue);
699                 return 0;
700         }
701 
702         if (streq(lvalue, "SessionId"))
703                 session->session_id = k;
704         else
705                 session->peer_session_id = k;
706 
707         session = NULL;
708         return 0;
709 }
710 
config_parse_l2tp_session_l2spec(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)711 int config_parse_l2tp_session_l2spec(
712                 const char *unit,
713                 const char *filename,
714                 unsigned line,
715                 const char *section,
716                 unsigned section_line,
717                 const char *lvalue,
718                 int ltype,
719                 const char *rvalue,
720                 void *data,
721                 void *userdata) {
722 
723         _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
724         L2tpTunnel *t = userdata;
725         L2tpL2specType spec;
726         int r;
727 
728         assert(filename);
729         assert(section);
730         assert(lvalue);
731         assert(rvalue);
732         assert(data);
733 
734         r = l2tp_session_new_static(t, filename, section_line, &session);
735         if (r < 0)
736                 return log_oom();
737 
738         spec = l2tp_l2spec_type_from_string(rvalue);
739         if (spec < 0) {
740                 log_syntax(unit, LOG_WARNING, filename, line, spec,
741                            "Failed to parse layer2 specific header type. Ignoring assignment: %s", rvalue);
742                 return 0;
743         }
744 
745         session->l2tp_l2spec_type = spec;
746 
747         session = NULL;
748         return 0;
749 }
750 
config_parse_l2tp_session_name(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)751 int config_parse_l2tp_session_name(
752                 const char *unit,
753                 const char *filename,
754                 unsigned line,
755                 const char *section,
756                 unsigned section_line,
757                 const char *lvalue,
758                 int ltype,
759                 const char *rvalue,
760                 void *data,
761                 void *userdata) {
762 
763         _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
764         L2tpTunnel *t = userdata;
765         int r;
766 
767         assert(filename);
768         assert(section);
769         assert(lvalue);
770         assert(rvalue);
771         assert(data);
772 
773         r = l2tp_session_new_static(t, filename, section_line, &session);
774         if (r < 0)
775                 return log_oom();
776 
777         if (!ifname_valid(rvalue)) {
778                 log_syntax(unit, LOG_WARNING, filename, line, 0,
779                            "Failed to parse L2TP tunnel session name. Ignoring assignment: %s", rvalue);
780                 return 0;
781         }
782 
783         r = free_and_strdup(&session->name, rvalue);
784         if (r < 0)
785                 return log_oom();
786 
787         session = NULL;
788         return 0;
789 }
790 
l2tp_tunnel_init(NetDev * netdev)791 static void l2tp_tunnel_init(NetDev *netdev) {
792         L2tpTunnel *t;
793 
794         assert(netdev);
795 
796         t = L2TP(netdev);
797 
798         assert(t);
799 
800         t->l2tp_encap_type = NETDEV_L2TP_ENCAPTYPE_UDP;
801         t->udp6_csum_rx = true;
802         t->udp6_csum_tx = true;
803 }
804 
l2tp_session_verify(L2tpSession * session)805 static int l2tp_session_verify(L2tpSession *session) {
806         NetDev *netdev;
807 
808         assert(session);
809         assert(session->tunnel);
810 
811         netdev = NETDEV(session->tunnel);
812 
813         if (section_is_invalid(session->section))
814                 return -EINVAL;
815 
816         if (!session->name)
817                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
818                                               "%s: L2TP session without name configured. "
819                                               "Ignoring [L2TPSession] section from line %u",
820                                               session->section->filename, session->section->line);
821 
822         if (session->session_id == 0 || session->peer_session_id == 0)
823                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
824                                               "%s: L2TP session without session IDs configured. "
825                                               "Ignoring [L2TPSession] section from line %u",
826                                               session->section->filename, session->section->line);
827 
828         return 0;
829 }
830 
netdev_l2tp_tunnel_verify(NetDev * netdev,const char * filename)831 static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) {
832         L2tpTunnel *t;
833         L2tpSession *session;
834 
835         assert(netdev);
836         assert(filename);
837 
838         t = L2TP(netdev);
839 
840         assert(t);
841 
842         if (!IN_SET(t->family, AF_INET, AF_INET6))
843                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
844                                               "%s: L2TP tunnel with invalid address family configured. Ignoring",
845                                               filename);
846 
847         if (!in_addr_is_set(t->family, &t->remote))
848                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
849                                               "%s: L2TP tunnel without a remote address configured. Ignoring",
850                                               filename);
851 
852         if (t->tunnel_id == 0 || t->peer_tunnel_id == 0)
853                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
854                                               "%s: L2TP tunnel without tunnel IDs configured. Ignoring",
855                                               filename);
856 
857         ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section)
858                 if (l2tp_session_verify(session) < 0)
859                         l2tp_session_free(session);
860 
861         return 0;
862 }
863 
l2tp_tunnel_done(NetDev * netdev)864 static void l2tp_tunnel_done(NetDev *netdev) {
865         L2tpTunnel *t;
866 
867         assert(netdev);
868 
869         t = L2TP(netdev);
870 
871         assert(t);
872 
873         ordered_hashmap_free_with_destructor(t->sessions_by_section, l2tp_session_free);
874         free(t->local_ifname);
875 }
876 
877 const NetDevVTable l2tptnl_vtable = {
878         .object_size = sizeof(L2tpTunnel),
879         .init = l2tp_tunnel_init,
880         .sections = NETDEV_COMMON_SECTIONS "L2TP\0L2TPSession\0",
881         .create = l2tp_create_tunnel,
882         .done = l2tp_tunnel_done,
883         .create_type = NETDEV_CREATE_INDEPENDENT,
884         .is_ready_to_create = netdev_l2tp_is_ready_to_create,
885         .config_verify = netdev_l2tp_tunnel_verify,
886 };
887