Line data Source code
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 0 : 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 0 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_encap_type, L2tpEncapType);
35 0 : 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 0 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_local_address_type, L2tpLocalAddressType);
44 :
45 0 : static void l2tp_session_free(L2tpSession *s) {
46 0 : if (!s)
47 0 : return;
48 :
49 0 : if (s->tunnel && s->section)
50 0 : ordered_hashmap_remove(s->tunnel->sessions_by_section, s);
51 :
52 0 : network_config_section_free(s->section);
53 :
54 0 : free(s->name);
55 :
56 0 : free(s);
57 : }
58 :
59 0 : DEFINE_NETWORK_SECTION_FUNCTIONS(L2tpSession, l2tp_session_free);
60 :
61 0 : static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned section_line, L2tpSession **ret) {
62 0 : _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
63 0 : _cleanup_(l2tp_session_freep) L2tpSession *s = NULL;
64 : int r;
65 :
66 0 : assert(t);
67 0 : assert(ret);
68 0 : assert(filename);
69 0 : assert(section_line > 0);
70 :
71 0 : r = network_config_section_new(filename, section_line, &n);
72 0 : if (r < 0)
73 0 : return r;
74 :
75 0 : s = ordered_hashmap_get(t->sessions_by_section, n);
76 0 : if (s) {
77 0 : *ret = TAKE_PTR(s);
78 0 : return 0;
79 : }
80 :
81 0 : s = new(L2tpSession, 1);
82 0 : if (!s)
83 0 : return -ENOMEM;
84 :
85 0 : *s = (L2tpSession) {
86 : .l2tp_l2spec_type = NETDEV_L2TP_L2SPECTYPE_DEFAULT,
87 : .tunnel = t,
88 0 : .section = TAKE_PTR(n),
89 : };
90 :
91 0 : r = ordered_hashmap_ensure_allocated(&t->sessions_by_section, &network_config_hash_ops);
92 0 : if (r < 0)
93 0 : return r;
94 :
95 0 : r = ordered_hashmap_put(t->sessions_by_section, s->section, s);
96 0 : if (r < 0)
97 0 : return r;
98 :
99 0 : *ret = TAKE_PTR(s);
100 0 : return 0;
101 : }
102 :
103 0 : static int netdev_l2tp_fill_message_tunnel(NetDev *netdev, union in_addr_union *local_address, sd_netlink_message **ret) {
104 0 : _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
105 : uint16_t encap_type;
106 : L2tpTunnel *t;
107 : int r;
108 :
109 0 : assert(netdev);
110 0 : assert(local_address);
111 :
112 0 : t = L2TP(netdev);
113 :
114 0 : assert(t);
115 :
116 0 : r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_TUNNEL_CREATE, &m);
117 0 : if (r < 0)
118 0 : return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
119 :
120 0 : r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, t->tunnel_id);
121 0 : if (r < 0)
122 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_CONN_ID attribute: %m");
123 :
124 0 : r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, t->peer_tunnel_id);
125 0 : if (r < 0)
126 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_CONN_ID attribute: %m");
127 :
128 0 : r = sd_netlink_message_append_u8(m, L2TP_ATTR_PROTO_VERSION, 3);
129 0 : if (r < 0)
130 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PROTO_VERSION attribute: %m");
131 :
132 0 : switch(t->l2tp_encap_type) {
133 0 : case NETDEV_L2TP_ENCAPTYPE_IP:
134 0 : encap_type = L2TP_ENCAPTYPE_IP;
135 0 : break;
136 0 : case NETDEV_L2TP_ENCAPTYPE_UDP:
137 : default:
138 0 : encap_type = L2TP_ENCAPTYPE_UDP;
139 0 : break;
140 : }
141 :
142 0 : r = sd_netlink_message_append_u16(m, L2TP_ATTR_ENCAP_TYPE, encap_type);
143 0 : if (r < 0)
144 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_ENCAP_TYPE attribute: %m");
145 :
146 0 : if (t->family == AF_INET) {
147 0 : r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_SADDR, &local_address->in);
148 0 : if (r < 0)
149 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP_SADDR attribute: %m");
150 :
151 0 : r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_DADDR, &t->remote.in);
152 0 : if (r < 0)
153 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP_DADDR attribute: %m");
154 : } else {
155 0 : r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_SADDR, &local_address->in6);
156 0 : if (r < 0)
157 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP6_SADDR attribute: %m");
158 :
159 0 : r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_DADDR, &t->remote.in6);
160 0 : if (r < 0)
161 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP6_DADDR attribute: %m");
162 : }
163 :
164 0 : if (encap_type == L2TP_ENCAPTYPE_UDP) {
165 0 : r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_SPORT, t->l2tp_udp_sport);
166 0 : if (r < 0)
167 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_SPORT, attribute: %m");
168 :
169 0 : r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_DPORT, t->l2tp_udp_dport);
170 0 : if (r < 0)
171 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_DPORT attribute: %m");
172 :
173 0 : if (t->udp_csum) {
174 0 : r = sd_netlink_message_append_u8(m, L2TP_ATTR_UDP_CSUM, t->udp_csum);
175 0 : if (r < 0)
176 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_CSUM attribute: %m");
177 : }
178 :
179 0 : if (t->udp6_csum_tx) {
180 0 : r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_TX);
181 0 : if (r < 0)
182 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_ZERO_CSUM6_TX attribute: %m");
183 : }
184 :
185 0 : if (t->udp6_csum_rx) {
186 0 : r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_RX);
187 0 : if (r < 0)
188 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_ZERO_CSUM6_RX attribute: %m");
189 : }
190 : }
191 :
192 0 : *ret = TAKE_PTR(m);
193 :
194 0 : return 0;
195 : }
196 :
197 0 : static int netdev_l2tp_fill_message_session(NetDev *netdev, L2tpSession *session, sd_netlink_message **ret) {
198 0 : _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 0 : assert(netdev);
204 0 : assert(session);
205 0 : assert(session->tunnel);
206 :
207 0 : r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_SESSION_CREATE, &m);
208 0 : if (r < 0)
209 0 : return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
210 :
211 0 : r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, session->tunnel->tunnel_id);
212 0 : if (r < 0)
213 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_CONN_ID attribute: %m");
214 :
215 0 : r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, session->tunnel->peer_tunnel_id);
216 0 : if (r < 0)
217 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_CONN_ID attribute: %m");
218 :
219 0 : r = sd_netlink_message_append_u32(m, L2TP_ATTR_SESSION_ID, session->session_id);
220 0 : if (r < 0)
221 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_SESSION_ID attribute: %m");
222 :
223 0 : r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_SESSION_ID, session->peer_session_id);
224 0 : if (r < 0)
225 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_SESSION_ID attribute: %m");
226 :
227 0 : r = sd_netlink_message_append_u16(m, L2TP_ATTR_PW_TYPE, L2TP_PWTYPE_ETH);
228 0 : if (r < 0)
229 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PW_TYPE attribute: %m");
230 :
231 0 : switch (session->l2tp_l2spec_type) {
232 0 : case NETDEV_L2TP_L2SPECTYPE_NONE:
233 0 : l2_spec_type = L2TP_L2SPECTYPE_NONE;
234 0 : l2_spec_len = 0;
235 0 : break;
236 0 : case NETDEV_L2TP_L2SPECTYPE_DEFAULT:
237 : default:
238 0 : l2_spec_type = L2TP_L2SPECTYPE_DEFAULT;
239 0 : l2_spec_len = 4;
240 0 : break;
241 : }
242 :
243 0 : r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_TYPE, l2_spec_type);
244 0 : if (r < 0)
245 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_L2SPEC_TYPE attribute: %m");
246 :
247 0 : r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_LEN, l2_spec_len);
248 0 : if (r < 0)
249 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_L2SPEC_LEN attribute: %m");
250 :
251 0 : r = sd_netlink_message_append_string(m, L2TP_ATTR_IFNAME, session->name);
252 0 : if (r < 0)
253 0 : return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IFNAME attribute: %m");
254 :
255 0 : *ret = TAKE_PTR(m);
256 :
257 0 : return 0;
258 : }
259 :
260 0 : static int l2tp_acquire_local_address_one(L2tpTunnel *t, Address *a, union in_addr_union *ret) {
261 0 : if (a->family != t->family)
262 0 : return -EINVAL;
263 :
264 0 : if (in_addr_is_null(a->family, &a->in_addr_peer) <= 0)
265 0 : return -EINVAL;
266 :
267 0 : if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_STATIC &&
268 0 : !FLAGS_SET(a->flags, IFA_F_PERMANENT))
269 0 : return -EINVAL;
270 :
271 0 : if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC &&
272 0 : FLAGS_SET(a->flags, IFA_F_PERMANENT))
273 0 : return -EINVAL;
274 :
275 0 : *ret = a->in_addr;
276 0 : return 0;
277 : }
278 :
279 0 : static int l2tp_acquire_local_address(L2tpTunnel *t, Link *link, union in_addr_union *ret) {
280 : Address *a;
281 : Iterator i;
282 :
283 0 : assert(t);
284 0 : assert(link);
285 0 : assert(ret);
286 0 : assert(IN_SET(t->family, AF_INET, AF_INET6));
287 :
288 0 : if (!in_addr_is_null(t->family, &t->local)) {
289 : /* local address is explicitly specified. */
290 0 : *ret = t->local;
291 0 : return 0;
292 : }
293 :
294 0 : SET_FOREACH(a, link->addresses, i)
295 0 : if (l2tp_acquire_local_address_one(t, a, ret) >= 0)
296 0 : return 1;
297 :
298 0 : SET_FOREACH(a, link->addresses_foreign, i)
299 0 : if (l2tp_acquire_local_address_one(t, a, ret) >= 0)
300 0 : return 1;
301 :
302 0 : return -ENODATA;
303 : }
304 :
305 0 : static void l2tp_session_destroy_callback(L2tpSession *session) {
306 0 : if (!session)
307 0 : return;
308 :
309 0 : netdev_unref(NETDEV(session->tunnel));
310 : }
311 :
312 0 : static int l2tp_create_session_handler(sd_netlink *rtnl, sd_netlink_message *m, L2tpSession *session) {
313 : NetDev *netdev;
314 : int r;
315 :
316 0 : assert(session);
317 0 : assert(session->tunnel);
318 :
319 0 : netdev = NETDEV(session->tunnel);
320 :
321 0 : r = sd_netlink_message_get_errno(m);
322 0 : if (r == -EEXIST)
323 0 : log_netdev_info(netdev, "L2TP session %s exists, using existing without changing its parameters",
324 : session->name);
325 0 : else if (r < 0) {
326 0 : log_netdev_warning_errno(netdev, r, "L2TP session %s could not be created: %m", session->name);
327 0 : return 1;
328 : }
329 :
330 0 : log_netdev_debug(netdev, "L2TP session %s created", session->name);
331 0 : return 1;
332 : }
333 :
334 0 : static int l2tp_create_session(NetDev *netdev, L2tpSession *session) {
335 0 : _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *n = NULL;
336 : int r;
337 :
338 0 : r = netdev_l2tp_fill_message_session(netdev, session, &n);
339 0 : if (r < 0)
340 0 : return r;
341 :
342 0 : r = netlink_call_async(netdev->manager->genl, NULL, n, l2tp_create_session_handler,
343 : l2tp_session_destroy_callback, session);
344 0 : if (r < 0)
345 0 : return log_netdev_error_errno(netdev, r, "Failed to create L2TP session %s: %m", session->name);
346 :
347 0 : netdev_ref(netdev);
348 0 : return 0;
349 : }
350 :
351 0 : 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 0 : assert(netdev);
358 0 : assert(netdev->state != _NETDEV_STATE_INVALID);
359 :
360 0 : t = L2TP(netdev);
361 :
362 0 : assert(t);
363 :
364 0 : r = sd_netlink_message_get_errno(m);
365 0 : if (r == -EEXIST)
366 0 : log_netdev_info(netdev, "netdev exists, using existing without changing its parameters");
367 0 : else if (r < 0) {
368 0 : log_netdev_warning_errno(netdev, r, "netdev could not be created: %m");
369 0 : netdev_drop(netdev);
370 :
371 0 : return 1;
372 : }
373 :
374 0 : log_netdev_debug(netdev, "L2TP tunnel is created");
375 :
376 0 : ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i)
377 0 : (void) l2tp_create_session(netdev, session);
378 :
379 0 : return 1;
380 : }
381 :
382 0 : static int l2tp_create_tunnel(NetDev *netdev, Link *link) {
383 0 : _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 0 : assert(netdev);
389 :
390 0 : t = L2TP(netdev);
391 :
392 0 : assert(t);
393 :
394 0 : r = l2tp_acquire_local_address(t, link, &local_address);
395 0 : if (r < 0)
396 0 : return log_netdev_error_errno(netdev, r, "Could not find local address.");
397 :
398 0 : if (r > 0 && DEBUG_LOGGING) {
399 0 : _cleanup_free_ char *str = NULL;
400 :
401 0 : (void) in_addr_to_string(t->family, &local_address, &str);
402 0 : log_netdev_debug(netdev, "Local address %s acquired.", strna(str));
403 : }
404 :
405 0 : r = netdev_l2tp_fill_message_tunnel(netdev, &local_address, &m);
406 0 : if (r < 0)
407 0 : return r;
408 :
409 0 : r = netlink_call_async(netdev->manager->genl, NULL, m, l2tp_create_tunnel_handler,
410 : netdev_destroy_callback, netdev);
411 0 : if (r < 0)
412 0 : return log_netdev_error_errno(netdev, r, "Failed to create L2TP tunnel: %m");
413 :
414 0 : netdev_ref(netdev);
415 :
416 0 : return 0;
417 : }
418 :
419 0 : 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 0 : L2tpTunnel *t = userdata;
432 0 : union in_addr_union *addr = data;
433 : int r;
434 :
435 0 : assert(filename);
436 0 : assert(lvalue);
437 0 : assert(rvalue);
438 0 : assert(data);
439 :
440 0 : if (streq(lvalue, "Local")) {
441 : L2tpLocalAddressType addr_type;
442 :
443 0 : if (isempty(rvalue))
444 0 : addr_type = NETDEV_L2TP_LOCAL_ADDRESS_AUTO;
445 : else
446 0 : addr_type = l2tp_local_address_type_from_string(rvalue);
447 :
448 0 : if (addr_type >= 0) {
449 0 : if (in_addr_is_null(t->family, &t->remote) != 0)
450 : /* If Remote= is not specified yet, then also clear family. */
451 0 : t->family = AF_UNSPEC;
452 :
453 0 : t->local = IN_ADDR_NULL;
454 0 : t->local_address_type = addr_type;
455 :
456 0 : return 0;
457 : }
458 : }
459 :
460 0 : if (t->family == AF_UNSPEC)
461 0 : r = in_addr_from_string_auto(rvalue, &t->family, addr);
462 : else
463 0 : r = in_addr_from_string(t->family, rvalue, addr);
464 0 : if (r < 0) {
465 0 : log_syntax(unit, LOG_ERR, filename, line, r,
466 : "Invalid L2TP Tunnel address specified in %s='%s', ignoring assignment: %m", lvalue, rvalue);
467 0 : return 0;
468 : }
469 :
470 0 : return 0;
471 : }
472 :
473 0 : 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 0 : uint32_t *id = data, k;
486 : int r;
487 :
488 0 : assert(filename);
489 0 : assert(lvalue);
490 0 : assert(rvalue);
491 0 : assert(data);
492 :
493 0 : r = safe_atou32(rvalue, &k);
494 0 : if (r < 0) {
495 0 : log_syntax(unit, LOG_ERR, filename, line, r,
496 : "Failed to parse L2TP tunnel id. Ignoring assignment: %s", rvalue);
497 0 : return 0;
498 : }
499 :
500 0 : if (k == 0) {
501 0 : log_syntax(unit, LOG_ERR, filename, line, r,
502 : "Invalid L2TP tunnel id. Ignoring assignment: %s", rvalue);
503 0 : return 0;
504 : }
505 :
506 0 : *id = k;
507 :
508 0 : return 0;
509 : }
510 :
511 0 : 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 0 : _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
524 0 : L2tpTunnel *t = userdata;
525 : uint32_t k;
526 : int r;
527 :
528 0 : assert(filename);
529 0 : assert(section);
530 0 : assert(lvalue);
531 0 : assert(rvalue);
532 0 : assert(data);
533 :
534 0 : r = l2tp_session_new_static(t, filename, section_line, &session);
535 0 : if (r < 0)
536 0 : return r;
537 :
538 0 : r = safe_atou32(rvalue, &k);
539 0 : if (r < 0) {
540 0 : log_syntax(unit, LOG_ERR, filename, line, r,
541 : "Failed to parse L2TP session id. Ignoring assignment: %s", rvalue);
542 0 : return 0;
543 : }
544 :
545 0 : if (k == 0) {
546 0 : log_syntax(unit, LOG_ERR, filename, line, r,
547 : "Invalid L2TP session id. Ignoring assignment: %s", rvalue);
548 0 : return 0;
549 : }
550 :
551 0 : if (streq(lvalue, "SessionId"))
552 0 : session->session_id = k;
553 : else
554 0 : session->peer_session_id = k;
555 :
556 0 : session = NULL;
557 0 : return 0;
558 : }
559 :
560 0 : 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 0 : _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
573 0 : L2tpTunnel *t = userdata;
574 : L2tpL2specType spec;
575 : int r;
576 :
577 0 : assert(filename);
578 0 : assert(section);
579 0 : assert(lvalue);
580 0 : assert(rvalue);
581 0 : assert(data);
582 :
583 0 : r = l2tp_session_new_static(t, filename, section_line, &session);
584 0 : if (r < 0)
585 0 : return r;
586 :
587 0 : spec = l2tp_l2spec_type_from_string(rvalue);
588 0 : if (spec < 0) {
589 0 : log_syntax(unit, LOG_ERR, filename, line, 0,
590 : "Failed to parse layer2 specific header type. Ignoring assignment: %s", rvalue);
591 0 : return 0;
592 : }
593 :
594 0 : session->l2tp_l2spec_type = spec;
595 :
596 0 : session = NULL;
597 0 : return 0;
598 : }
599 :
600 0 : 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 0 : _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
613 0 : L2tpTunnel *t = userdata;
614 : int r;
615 :
616 0 : assert(filename);
617 0 : assert(section);
618 0 : assert(lvalue);
619 0 : assert(rvalue);
620 0 : assert(data);
621 :
622 0 : r = l2tp_session_new_static(t, filename, section_line, &session);
623 0 : if (r < 0)
624 0 : return r;
625 :
626 0 : if (!ifname_valid(rvalue)) {
627 0 : log_syntax(unit, LOG_ERR, filename, line, 0,
628 : "Failed to parse L2TP tunnel session name. Ignoring assignment: %s", rvalue);
629 0 : return 0;
630 : }
631 :
632 0 : r = free_and_strdup(&session->name, rvalue);
633 0 : if (r < 0)
634 0 : return log_oom();
635 :
636 0 : session = NULL;
637 0 : return 0;
638 : }
639 :
640 0 : static void l2tp_tunnel_init(NetDev *netdev) {
641 : L2tpTunnel *t;
642 :
643 0 : assert(netdev);
644 :
645 0 : t = L2TP(netdev);
646 :
647 0 : assert(t);
648 :
649 0 : t->l2tp_encap_type = NETDEV_L2TP_ENCAPTYPE_UDP;
650 0 : t->udp6_csum_rx = true;
651 0 : t->udp6_csum_tx = true;
652 0 : }
653 :
654 0 : static int l2tp_session_verify(L2tpSession *session) {
655 : NetDev *netdev;
656 :
657 0 : assert(session);
658 0 : assert(session->tunnel);
659 :
660 0 : netdev = NETDEV(session->tunnel);
661 :
662 0 : if (section_is_invalid(session->section))
663 0 : return -EINVAL;
664 :
665 0 : if (!session->name)
666 0 : 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 0 : if (session->session_id == 0 || session->peer_session_id == 0)
672 0 : 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 0 : return 0;
678 : }
679 :
680 0 : static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) {
681 : L2tpTunnel *t;
682 : L2tpSession *session;
683 : Iterator i;
684 :
685 0 : assert(netdev);
686 0 : assert(filename);
687 :
688 0 : t = L2TP(netdev);
689 :
690 0 : assert(t);
691 :
692 0 : if (!IN_SET(t->family, AF_INET, AF_INET6))
693 0 : return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
694 : "%s: L2TP tunnel with invalid address family configured. Ignoring",
695 : filename);
696 :
697 0 : if (in_addr_is_null(t->family, &t->remote))
698 0 : return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
699 : "%s: L2TP tunnel without a remote address configured. Ignoring",
700 : filename);
701 :
702 0 : if (t->tunnel_id == 0 || t->peer_tunnel_id == 0)
703 0 : return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
704 : "%s: L2TP tunnel without tunnel IDs configured. Ignoring",
705 : filename);
706 :
707 0 : ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i)
708 0 : if (l2tp_session_verify(session) < 0)
709 0 : l2tp_session_free(session);
710 :
711 0 : return 0;
712 : }
713 :
714 0 : static void l2tp_tunnel_done(NetDev *netdev) {
715 : L2tpTunnel *t;
716 :
717 0 : assert(netdev);
718 :
719 0 : t = L2TP(netdev);
720 :
721 0 : assert(t);
722 :
723 0 : ordered_hashmap_free_with_destructor(t->sessions_by_section, l2tp_session_free);
724 0 : }
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 : };
|