1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <netinet/in.h>
4 #include <linux/fou.h>
5 #include <linux/if_arp.h>
6 #include <linux/if_tunnel.h>
7 #include <linux/ip.h>
8 #include <linux/ip6_tunnel.h>
9
10 #include "af-list.h"
11 #include "conf-parser.h"
12 #include "hexdecoct.h"
13 #include "missing_network.h"
14 #include "netlink-util.h"
15 #include "networkd-manager.h"
16 #include "parse-util.h"
17 #include "siphash24.h"
18 #include "string-table.h"
19 #include "string-util.h"
20 #include "tunnel.h"
21 #include "util.h"
22
23 #define DEFAULT_IPV6_TTL 64
24 #define IP6_FLOWINFO_FLOWLABEL htobe32(0x000FFFFF)
25 #define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0x40
26
27 static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
28 [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
29 [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6",
30 [NETDEV_IP6_TNL_MODE_ANYIP6] = "any",
31 };
32
33 DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
34 DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
35
36 #define HASH_KEY SD_ID128_MAKE(74,c4,de,12,f3,d9,41,34,bb,3d,c1,a4,42,93,50,87)
37
dhcp4_pd_create_6rd_tunnel_name(Link * link,char ** ret)38 int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret) {
39 _cleanup_free_ char *ifname_alloc = NULL;
40 uint8_t ipv4masklen, sixrd_prefixlen, *buf, *p;
41 struct in_addr ipv4address;
42 struct in6_addr sixrd_prefix;
43 char ifname[IFNAMSIZ];
44 uint64_t result;
45 size_t sz;
46 int r;
47
48 assert(link);
49 assert(link->dhcp_lease);
50
51 r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
52 if (r < 0)
53 return log_link_debug_errno(link, r, "Failed to get DHCPv4 address: %m");
54
55 r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
56 if (r < 0)
57 return log_link_debug_errno(link, r, "Failed to get 6rd option: %m");
58
59 sz = sizeof(uint8_t) * 2 + sizeof(struct in6_addr) + sizeof(struct in_addr);
60 buf = newa(uint8_t, sz);
61 p = buf;
62 p = mempcpy(p, &ipv4masklen, sizeof(uint8_t));
63 p = mempcpy(p, &ipv4address, sizeof(struct in_addr));
64 p = mempcpy(p, &sixrd_prefixlen, sizeof(uint8_t));
65 p = mempcpy(p, &sixrd_prefix, sizeof(struct in6_addr));
66
67 result = siphash24(buf, sz, HASH_KEY.bytes);
68 memcpy(ifname, "6rd-", STRLEN("6rd-"));
69 ifname[STRLEN("6rd-") ] = urlsafe_base64char(result >> 54);
70 ifname[STRLEN("6rd-") + 1] = urlsafe_base64char(result >> 48);
71 ifname[STRLEN("6rd-") + 2] = urlsafe_base64char(result >> 42);
72 ifname[STRLEN("6rd-") + 3] = urlsafe_base64char(result >> 36);
73 ifname[STRLEN("6rd-") + 4] = urlsafe_base64char(result >> 30);
74 ifname[STRLEN("6rd-") + 5] = urlsafe_base64char(result >> 24);
75 ifname[STRLEN("6rd-") + 6] = urlsafe_base64char(result >> 18);
76 ifname[STRLEN("6rd-") + 7] = urlsafe_base64char(result >> 12);
77 ifname[STRLEN("6rd-") + 8] = urlsafe_base64char(result >> 6);
78 ifname[STRLEN("6rd-") + 9] = urlsafe_base64char(result);
79 ifname[STRLEN("6rd-") + 10] = '\0';
80 assert_cc(STRLEN("6rd-") + 10 <= IFNAMSIZ);
81
82 ifname_alloc = strdup(ifname);
83 if (!ifname_alloc)
84 return log_oom_debug();
85
86 *ret = TAKE_PTR(ifname_alloc);
87 return 0;
88 }
89
dhcp4_pd_create_6rd_tunnel_message(Link * link,sd_netlink_message * m,const struct in_addr * ipv4address,uint8_t ipv4masklen,const struct in6_addr * sixrd_prefix,uint8_t sixrd_prefixlen)90 static int dhcp4_pd_create_6rd_tunnel_message(
91 Link *link,
92 sd_netlink_message *m,
93 const struct in_addr *ipv4address,
94 uint8_t ipv4masklen,
95 const struct in6_addr *sixrd_prefix,
96 uint8_t sixrd_prefixlen) {
97 int r;
98
99 r = sd_netlink_message_append_string(m, IFLA_IFNAME, link->dhcp4_6rd_tunnel_name);
100 if (r < 0)
101 return r;
102
103 r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
104 if (r < 0)
105 return r;
106
107 r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "sit");
108 if (r < 0)
109 return r;
110
111 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, ipv4address);
112 if (r < 0)
113 return r;
114
115 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, 64);
116 if (r < 0)
117 return r;
118
119 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, sixrd_prefix);
120 if (r < 0)
121 return r;
122
123 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_PREFIXLEN, sixrd_prefixlen);
124 if (r < 0)
125 return r;
126
127 struct in_addr relay_prefix = *ipv4address;
128 (void) in4_addr_mask(&relay_prefix, ipv4masklen);
129 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_6RD_RELAY_PREFIX, relay_prefix.s_addr);
130 if (r < 0)
131 return r;
132
133 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_RELAY_PREFIXLEN, ipv4masklen);
134 if (r < 0)
135 return r;
136
137 r = sd_netlink_message_close_container(m);
138 if (r < 0)
139 return r;
140
141 r = sd_netlink_message_close_container(m);
142 if (r < 0)
143 return r;
144
145 return 0;
146 }
147
dhcp4_pd_create_6rd_tunnel(Link * link,link_netlink_message_handler_t callback)148 int dhcp4_pd_create_6rd_tunnel(Link *link, link_netlink_message_handler_t callback) {
149 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
150 uint8_t ipv4masklen, sixrd_prefixlen;
151 struct in_addr ipv4address;
152 struct in6_addr sixrd_prefix;
153 int r;
154
155 assert(link);
156 assert(link->ifindex > 0);
157 assert(link->manager);
158 assert(link->dhcp_lease);
159 assert(link->dhcp4_6rd_tunnel_name);
160 assert(callback);
161
162 r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
163 if (r < 0)
164 return log_link_debug_errno(link, r, "Failed to get DHCPv4 address: %m");
165
166 r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
167 if (r < 0)
168 return log_link_debug_errno(link, r, "Failed to get 6rd option: %m");
169
170 r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, 0);
171 if (r < 0)
172 return log_link_debug_errno(link, r, "Failed to create netlink message: %m");
173
174 r = dhcp4_pd_create_6rd_tunnel_message(link, m,
175 &ipv4address, ipv4masklen,
176 &sixrd_prefix, sixrd_prefixlen);
177 if (r < 0)
178 return log_link_debug_errno(link, r, "Failed to fill netlink message: %m");
179
180 r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
181 link_netlink_destroy_callback, link);
182 if (r < 0)
183 return log_link_debug_errno(link, r, "Could not send netlink message: %m");
184
185 link_ref(link);
186
187 return 0;
188 }
189
tunnel_get_local_address(Tunnel * t,Link * link,union in_addr_union * ret)190 static int tunnel_get_local_address(Tunnel *t, Link *link, union in_addr_union *ret) {
191 assert(t);
192
193 if (t->local_type < 0) {
194 if (ret)
195 *ret = t->local;
196 return 0;
197 }
198
199 return link_get_local_address(link, t->local_type, t->family, NULL, ret);
200 }
201
netdev_ipip_sit_fill_message_create(NetDev * netdev,Link * link,sd_netlink_message * m)202 static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
203 union in_addr_union local;
204 Tunnel *t;
205 int r;
206
207 assert(netdev);
208 assert(m);
209
210 if (netdev->kind == NETDEV_KIND_IPIP)
211 t = IPIP(netdev);
212 else
213 t = SIT(netdev);
214
215 assert(t);
216
217 if (t->external) {
218 r = sd_netlink_message_append_flag(m, IFLA_IPTUN_COLLECT_METADATA);
219 if (r < 0)
220 return r;
221
222 /* If external mode is enabled, then the following settings should not be appended. */
223 return 0;
224 }
225
226 if (link || t->assign_to_loopback) {
227 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
228 if (r < 0)
229 return r;
230 }
231
232 r = tunnel_get_local_address(t, link, &local);
233 if (r < 0)
234 return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
235
236 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &local.in);
237 if (r < 0)
238 return r;
239
240 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
241 if (r < 0)
242 return r;
243
244 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
245 if (r < 0)
246 return r;
247
248 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
249 if (r < 0)
250 return r;
251
252 if (t->fou_tunnel) {
253 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_TYPE, t->fou_encap_type);
254 if (r < 0)
255 return r;
256
257 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_SPORT, htobe16(t->encap_src_port));
258 if (r < 0)
259 return r;
260
261 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_DPORT, htobe16(t->fou_destination_port));
262 if (r < 0)
263 return r;
264 }
265
266 if (netdev->kind == NETDEV_KIND_SIT) {
267 if (t->sixrd_prefixlen > 0) {
268 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &t->sixrd_prefix);
269 if (r < 0)
270 return r;
271
272 /* u16 is deliberate here, even though we're passing a netmask that can never be >128. The kernel is
273 * expecting to receive the prefixlen as a u16.
274 */
275 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_PREFIXLEN, t->sixrd_prefixlen);
276 if (r < 0)
277 return r;
278 }
279
280 if (t->isatap >= 0) {
281 uint16_t flags = 0;
282
283 SET_FLAG(flags, SIT_ISATAP, t->isatap);
284
285 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_FLAGS, flags);
286 if (r < 0)
287 return r;
288 }
289 }
290
291 return 0;
292 }
293
netdev_gre_erspan_fill_message_create(NetDev * netdev,Link * link,sd_netlink_message * m)294 static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
295 union in_addr_union local;
296 uint32_t ikey = 0;
297 uint32_t okey = 0;
298 uint16_t iflags = 0;
299 uint16_t oflags = 0;
300 Tunnel *t;
301 int r;
302
303 assert(netdev);
304 assert(m);
305
306 switch (netdev->kind) {
307 case NETDEV_KIND_GRE:
308 t = GRE(netdev);
309 break;
310 case NETDEV_KIND_ERSPAN:
311 t = ERSPAN(netdev);
312 break;
313 case NETDEV_KIND_GRETAP:
314 t = GRETAP(netdev);
315 break;
316 default:
317 assert_not_reached();
318 }
319
320 assert(t);
321
322 if (t->external) {
323 r = sd_netlink_message_append_flag(m, IFLA_GRE_COLLECT_METADATA);
324 if (r < 0)
325 return r;
326
327 /* If external mode is enabled, then the following settings should not be appended. */
328 return 0;
329 }
330
331 if (link || t->assign_to_loopback) {
332 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
333 if (r < 0)
334 return r;
335 }
336
337 if (netdev->kind == NETDEV_KIND_ERSPAN) {
338 r = sd_netlink_message_append_u32(m, IFLA_GRE_ERSPAN_INDEX, t->erspan_index);
339 if (r < 0)
340 return r;
341 }
342
343 r = tunnel_get_local_address(t, link, &local);
344 if (r < 0)
345 return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
346
347 r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &local.in);
348 if (r < 0)
349 return r;
350
351 r = sd_netlink_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
352 if (r < 0)
353 return r;
354
355 r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
356 if (r < 0)
357 return r;
358
359 r = sd_netlink_message_append_u8(m, IFLA_GRE_TOS, t->tos);
360 if (r < 0)
361 return r;
362
363 r = sd_netlink_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc);
364 if (r < 0)
365 return r;
366
367 if (t->key != 0) {
368 ikey = okey = htobe32(t->key);
369 iflags |= GRE_KEY;
370 oflags |= GRE_KEY;
371 }
372
373 if (t->ikey != 0) {
374 ikey = htobe32(t->ikey);
375 iflags |= GRE_KEY;
376 }
377
378 if (t->okey != 0) {
379 okey = htobe32(t->okey);
380 oflags |= GRE_KEY;
381 }
382
383 if (t->gre_erspan_sequence > 0) {
384 iflags |= GRE_SEQ;
385 oflags |= GRE_SEQ;
386 } else if (t->gre_erspan_sequence == 0) {
387 iflags &= ~GRE_SEQ;
388 oflags &= ~GRE_SEQ;
389 }
390
391 r = sd_netlink_message_append_u32(m, IFLA_GRE_IKEY, ikey);
392 if (r < 0)
393 return r;
394
395 r = sd_netlink_message_append_u32(m, IFLA_GRE_OKEY, okey);
396 if (r < 0)
397 return r;
398
399 r = sd_netlink_message_append_u16(m, IFLA_GRE_IFLAGS, iflags);
400 if (r < 0)
401 return r;
402
403 r = sd_netlink_message_append_u16(m, IFLA_GRE_OFLAGS, oflags);
404 if (r < 0)
405 return r;
406
407 if (t->fou_tunnel) {
408 r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_TYPE, t->fou_encap_type);
409 if (r < 0)
410 return r;
411
412 r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_SPORT, htobe16(t->encap_src_port));
413 if (r < 0)
414 return r;
415
416 r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_DPORT, htobe16(t->fou_destination_port));
417 if (r < 0)
418 return r;
419 }
420
421 return 0;
422 }
423
netdev_ip6gre_fill_message_create(NetDev * netdev,Link * link,sd_netlink_message * m)424 static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
425 union in_addr_union local;
426 uint32_t ikey = 0;
427 uint32_t okey = 0;
428 uint16_t iflags = 0;
429 uint16_t oflags = 0;
430 Tunnel *t;
431 int r;
432
433 assert(netdev);
434 assert(m);
435
436 if (netdev->kind == NETDEV_KIND_IP6GRE)
437 t = IP6GRE(netdev);
438 else
439 t = IP6GRETAP(netdev);
440
441 assert(t);
442
443 if (t->external) {
444 r = sd_netlink_message_append_flag(m, IFLA_GRE_COLLECT_METADATA);
445 if (r < 0)
446 return r;
447
448 /* If external mode is enabled, then the following settings should not be appended. */
449 return 0;
450 }
451
452 if (link || t->assign_to_loopback) {
453 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
454 if (r < 0)
455 return r;
456 }
457
458 r = tunnel_get_local_address(t, link, &local);
459 if (r < 0)
460 return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
461
462 r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &local.in6);
463 if (r < 0)
464 return r;
465
466 r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
467 if (r < 0)
468 return r;
469
470 r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
471 if (r < 0)
472 return r;
473
474 if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
475 r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel);
476 if (r < 0)
477 return r;
478 }
479
480 r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags);
481 if (r < 0)
482 return r;
483
484 if (t->key != 0) {
485 ikey = okey = htobe32(t->key);
486 iflags |= GRE_KEY;
487 oflags |= GRE_KEY;
488 }
489
490 if (t->ikey != 0) {
491 ikey = htobe32(t->ikey);
492 iflags |= GRE_KEY;
493 }
494
495 if (t->okey != 0) {
496 okey = htobe32(t->okey);
497 oflags |= GRE_KEY;
498 }
499
500 r = sd_netlink_message_append_u32(m, IFLA_GRE_IKEY, ikey);
501 if (r < 0)
502 return r;
503
504 r = sd_netlink_message_append_u32(m, IFLA_GRE_OKEY, okey);
505 if (r < 0)
506 return r;
507
508 r = sd_netlink_message_append_u16(m, IFLA_GRE_IFLAGS, iflags);
509 if (r < 0)
510 return r;
511
512 r = sd_netlink_message_append_u16(m, IFLA_GRE_OFLAGS, oflags);
513 if (r < 0)
514 return r;
515
516 return 0;
517 }
518
netdev_vti_fill_message_create(NetDev * netdev,Link * link,sd_netlink_message * m)519 static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
520 union in_addr_union local;
521 uint32_t ikey, okey;
522 Tunnel *t;
523 int r;
524
525 assert(netdev);
526 assert(m);
527
528 if (netdev->kind == NETDEV_KIND_VTI)
529 t = VTI(netdev);
530 else
531 t = VTI6(netdev);
532
533 assert(t);
534
535 if (link || t->assign_to_loopback) {
536 r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
537 if (r < 0)
538 return r;
539 }
540
541 if (t->key != 0)
542 ikey = okey = htobe32(t->key);
543 else {
544 ikey = htobe32(t->ikey);
545 okey = htobe32(t->okey);
546 }
547
548 r = sd_netlink_message_append_u32(m, IFLA_VTI_IKEY, ikey);
549 if (r < 0)
550 return r;
551
552 r = sd_netlink_message_append_u32(m, IFLA_VTI_OKEY, okey);
553 if (r < 0)
554 return r;
555
556 r = tunnel_get_local_address(t, link, &local);
557 if (r < 0)
558 return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
559
560 r = netlink_message_append_in_addr_union(m, IFLA_VTI_LOCAL, t->family, &local);
561 if (r < 0)
562 return r;
563
564 r = netlink_message_append_in_addr_union(m, IFLA_VTI_REMOTE, t->family, &t->remote);
565 if (r < 0)
566 return r;
567
568 return 0;
569 }
570
netdev_ip6tnl_fill_message_create(NetDev * netdev,Link * link,sd_netlink_message * m)571 static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
572 union in_addr_union local;
573 uint8_t proto;
574 Tunnel *t;
575 int r;
576
577 assert(netdev);
578 assert(m);
579
580 t = IP6TNL(netdev);
581
582 assert(t);
583
584 switch (t->ip6tnl_mode) {
585 case NETDEV_IP6_TNL_MODE_IP6IP6:
586 proto = IPPROTO_IPV6;
587 break;
588 case NETDEV_IP6_TNL_MODE_IPIP6:
589 proto = IPPROTO_IPIP;
590 break;
591 case NETDEV_IP6_TNL_MODE_ANYIP6:
592 default:
593 proto = 0;
594 break;
595 }
596
597 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
598 if (r < 0)
599 return r;
600
601 if (t->external) {
602 r = sd_netlink_message_append_flag(m, IFLA_IPTUN_COLLECT_METADATA);
603 if (r < 0)
604 return r;
605
606 /* If external mode is enabled, then the following settings should not be appended. */
607 return 0;
608 }
609
610 if (link || t->assign_to_loopback) {
611 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
612 if (r < 0)
613 return r;
614 }
615
616 r = tunnel_get_local_address(t, link, &local);
617 if (r < 0)
618 return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
619
620 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &local.in6);
621 if (r < 0)
622 return r;
623
624 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
625 if (r < 0)
626 return r;
627
628 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
629 if (r < 0)
630 return r;
631
632 if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
633 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
634 if (r < 0)
635 return r;
636 }
637
638 if (t->copy_dscp)
639 t->flags |= IP6_TNL_F_RCV_DSCP_COPY;
640
641 if (t->allow_localremote >= 0)
642 SET_FLAG(t->flags, IP6_TNL_F_ALLOW_LOCAL_REMOTE, t->allow_localremote);
643
644 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
645 if (r < 0)
646 return r;
647
648 if (t->encap_limit != 0) {
649 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_ENCAP_LIMIT, t->encap_limit);
650 if (r < 0)
651 return r;
652 }
653
654 return 0;
655 }
656
netdev_tunnel_is_ready_to_create(NetDev * netdev,Link * link)657 static int netdev_tunnel_is_ready_to_create(NetDev *netdev, Link *link) {
658 Tunnel *t;
659
660 assert(netdev);
661
662 t = TUNNEL(netdev);
663
664 assert(t);
665
666 if (t->independent)
667 return true;
668
669 return tunnel_get_local_address(t, link, NULL) >= 0;
670 }
671
netdev_tunnel_verify(NetDev * netdev,const char * filename)672 static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
673 Tunnel *t;
674
675 assert(netdev);
676 assert(filename);
677
678 t = TUNNEL(netdev);
679
680 assert(t);
681
682 if (netdev->kind == NETDEV_KIND_IP6TNL &&
683 t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID)
684 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
685 "ip6tnl without mode configured in %s. Ignoring", filename);
686
687 if (t->external) {
688 if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_VTI6))
689 log_netdev_debug(netdev, "vti/vti6 tunnel do not support external mode, ignoring.");
690 else {
691 /* tunnel with external mode does not require underlying interface. */
692 t->independent = true;
693
694 /* tunnel with external mode does not require any settings checked below. */
695 return 0;
696 }
697 }
698
699 if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_IPIP, NETDEV_KIND_SIT, NETDEV_KIND_GRE) &&
700 !IN_SET(t->family, AF_UNSPEC, AF_INET))
701 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
702 "vti/ipip/sit/gre tunnel without a local/remote IPv4 address configured in %s. Ignoring", filename);
703
704 if (IN_SET(netdev->kind, NETDEV_KIND_GRETAP, NETDEV_KIND_ERSPAN) &&
705 (t->family != AF_INET || !in_addr_is_set(t->family, &t->remote)))
706 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
707 "gretap/erspan tunnel without a remote IPv4 address configured in %s. Ignoring", filename);
708
709 if ((IN_SET(netdev->kind, NETDEV_KIND_VTI6, NETDEV_KIND_IP6TNL) && t->family != AF_INET6) ||
710 (netdev->kind == NETDEV_KIND_IP6GRE && !IN_SET(t->family, AF_UNSPEC, AF_INET6)))
711 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
712 "vti6/ip6tnl/ip6gre tunnel without a local/remote IPv6 address configured in %s. Ignoring", filename);
713
714 if (netdev->kind == NETDEV_KIND_IP6GRETAP &&
715 (t->family != AF_INET6 || !in_addr_is_set(t->family, &t->remote)))
716 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
717 "ip6gretap tunnel without a remote IPv6 address configured in %s. Ignoring", filename);
718
719 if (t->fou_tunnel && t->fou_destination_port <= 0)
720 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
721 "FooOverUDP missing port configured in %s. Ignoring", filename);
722
723 if (netdev->kind == NETDEV_KIND_ERSPAN && (t->erspan_index >= (1 << 20) || t->erspan_index == 0))
724 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Invalid erspan index %d. Ignoring", t->erspan_index);
725
726 /* netlink_message_append_in_addr_union() is used for vti/vti6. So, t->family cannot be AF_UNSPEC. */
727 if (netdev->kind == NETDEV_KIND_VTI)
728 t->family = AF_INET;
729
730 if (t->assign_to_loopback)
731 t->independent = true;
732
733 if (t->independent && t->local_type >= 0)
734 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
735 "The local address cannot be '%s' when Independent= or AssignToLoopback= is enabled, ignoring.",
736 strna(netdev_local_address_type_to_string(t->local_type)));
737
738 return 0;
739 }
740
unset_local(Tunnel * t)741 static int unset_local(Tunnel *t) {
742 assert(t);
743
744 /* Unset the previous assignment. */
745 t->local = IN_ADDR_NULL;
746 t->local_type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
747
748 /* If the remote address is not specified, also clear the address family. */
749 if (!in_addr_is_set(t->family, &t->remote))
750 t->family = AF_UNSPEC;
751
752 return 0;
753 }
754
config_parse_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)755 int config_parse_tunnel_local_address(
756 const char *unit,
757 const char *filename,
758 unsigned line,
759 const char *section,
760 unsigned section_line,
761 const char *lvalue,
762 int ltype,
763 const char *rvalue,
764 void *data,
765 void *userdata) {
766
767 union in_addr_union buffer = IN_ADDR_NULL;
768 NetDevLocalAddressType type;
769 Tunnel *t = userdata;
770 int r, f;
771
772 assert(filename);
773 assert(lvalue);
774 assert(rvalue);
775 assert(userdata);
776
777 if (isempty(rvalue) || streq(rvalue, "any"))
778 return unset_local(t);
779
780 type = netdev_local_address_type_from_string(rvalue);
781 if (IN_SET(type, NETDEV_LOCAL_ADDRESS_IPV4LL, NETDEV_LOCAL_ADDRESS_DHCP4))
782 f = AF_INET;
783 else if (IN_SET(type, NETDEV_LOCAL_ADDRESS_IPV6LL, NETDEV_LOCAL_ADDRESS_DHCP6, NETDEV_LOCAL_ADDRESS_SLAAC))
784 f = AF_INET6;
785 else {
786 type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
787 r = in_addr_from_string_auto(rvalue, &f, &buffer);
788 if (r < 0) {
789 log_syntax(unit, LOG_WARNING, filename, line, r,
790 "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue);
791 return 0;
792 }
793
794 if (in_addr_is_null(f, &buffer))
795 return unset_local(t);
796 }
797
798 if (t->family != AF_UNSPEC && t->family != f) {
799 log_syntax(unit, LOG_WARNING, filename, line, 0,
800 "Address family does not match the previous assignment, ignoring assignment: %s", rvalue);
801 return 0;
802 }
803
804 t->family = f;
805 t->local = buffer;
806 t->local_type = type;
807 return 0;
808 }
809
unset_remote(Tunnel * t)810 static int unset_remote(Tunnel *t) {
811 assert(t);
812
813 /* Unset the previous assignment. */
814 t->remote = IN_ADDR_NULL;
815
816 /* If the local address is not specified, also clear the address family. */
817 if (t->local_type == _NETDEV_LOCAL_ADDRESS_TYPE_INVALID &&
818 !in_addr_is_set(t->family, &t->local))
819 t->family = AF_UNSPEC;
820
821 return 0;
822 }
823
config_parse_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)824 int config_parse_tunnel_remote_address(
825 const char *unit,
826 const char *filename,
827 unsigned line,
828 const char *section,
829 unsigned section_line,
830 const char *lvalue,
831 int ltype,
832 const char *rvalue,
833 void *data,
834 void *userdata) {
835
836 union in_addr_union buffer;
837 Tunnel *t = userdata;
838 int r, f;
839
840 assert(filename);
841 assert(lvalue);
842 assert(rvalue);
843 assert(userdata);
844
845 if (isempty(rvalue) || streq(rvalue, "any"))
846 return unset_remote(t);
847
848 r = in_addr_from_string_auto(rvalue, &f, &buffer);
849 if (r < 0) {
850 log_syntax(unit, LOG_WARNING, filename, line, r,
851 "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue);
852 return 0;
853 }
854
855 if (in_addr_is_null(f, &buffer))
856 return unset_remote(t);
857
858 if (t->family != AF_UNSPEC && t->family != f) {
859 log_syntax(unit, LOG_WARNING, filename, line, 0,
860 "Address family does not match the previous assignment, ignoring assignment: %s", rvalue);
861 return 0;
862 }
863
864 t->family = f;
865 t->remote = buffer;
866 return 0;
867 }
868
config_parse_tunnel_key(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)869 int config_parse_tunnel_key(
870 const char *unit,
871 const char *filename,
872 unsigned line,
873 const char *section,
874 unsigned section_line,
875 const char *lvalue,
876 int ltype,
877 const char *rvalue,
878 void *data,
879 void *userdata) {
880
881 uint32_t *dest = ASSERT_PTR(data), k;
882 union in_addr_union buffer;
883 int r;
884
885 assert(filename);
886 assert(rvalue);
887
888 r = in_addr_from_string(AF_INET, rvalue, &buffer);
889 if (r < 0) {
890 r = safe_atou32(rvalue, &k);
891 if (r < 0) {
892 log_syntax(unit, LOG_WARNING, filename, line, r,
893 "Failed to parse tunnel key ignoring assignment: %s", rvalue);
894 return 0;
895 }
896 } else
897 k = be32toh(buffer.in.s_addr);
898
899 *dest = k;
900 return 0;
901 }
902
config_parse_ipv6_flowlabel(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)903 int config_parse_ipv6_flowlabel(
904 const char* unit,
905 const char *filename,
906 unsigned line,
907 const char *section,
908 unsigned section_line,
909 const char *lvalue,
910 int ltype,
911 const char *rvalue,
912 void *data,
913 void *userdata) {
914
915 Tunnel *t = ASSERT_PTR(userdata);
916 int k, r;
917
918 assert(filename);
919 assert(rvalue);
920
921 if (streq(rvalue, "inherit")) {
922 t->ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
923 t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
924 return 0;
925 }
926
927 r = safe_atoi(rvalue, &k);
928 if (r < 0) {
929 log_syntax(unit, LOG_WARNING, filename, line, r,
930 "Failed to parse tunnel IPv6 flowlabel, ignoring assignment: %s", rvalue);
931 return 0;
932 }
933
934 if (k > 0xFFFFF) {
935 log_syntax(unit, LOG_WARNING, filename, line, 0,
936 "Invalid tunnel IPv6 flowlabel, ignoring assignment: %s", rvalue);
937 return 0;
938 }
939
940 t->ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL;
941 t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
942 return 0;
943 }
944
config_parse_encap_limit(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)945 int config_parse_encap_limit(
946 const char* unit,
947 const char *filename,
948 unsigned line,
949 const char *section,
950 unsigned section_line,
951 const char *lvalue,
952 int ltype,
953 const char *rvalue,
954 void *data,
955 void *userdata) {
956
957 Tunnel *t = ASSERT_PTR(userdata);
958 int k, r;
959
960 assert(filename);
961 assert(rvalue);
962
963 if (streq(rvalue, "none")) {
964 t->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT;
965 t->encap_limit = 0;
966 return 0;
967 }
968
969 r = safe_atoi(rvalue, &k);
970 if (r < 0) {
971 log_syntax(unit, LOG_WARNING, filename, line, r,
972 "Failed to parse Tunnel Encapsulation Limit option, ignoring assignment: %s", rvalue);
973 return 0;
974 }
975
976 if (k > 255 || k < 0) {
977 log_syntax(unit, LOG_WARNING, filename, line, 0,
978 "Invalid Tunnel Encapsulation value, ignoring assignment: %d", k);
979 return 0;
980 }
981
982 t->encap_limit = k;
983 t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
984 return 0;
985 }
986
config_parse_6rd_prefix(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)987 int config_parse_6rd_prefix(
988 const char* unit,
989 const char *filename,
990 unsigned line,
991 const char *section,
992 unsigned section_line,
993 const char *lvalue,
994 int ltype,
995 const char *rvalue,
996 void *data,
997 void *userdata) {
998
999 Tunnel *t = userdata;
1000 union in_addr_union p;
1001 uint8_t l;
1002 int r;
1003
1004 assert(filename);
1005 assert(lvalue);
1006 assert(rvalue);
1007
1008 r = in_addr_prefix_from_string(rvalue, AF_INET6, &p, &l);
1009 if (r < 0) {
1010 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse 6rd prefix \"%s\", ignoring: %m", rvalue);
1011 return 0;
1012 }
1013 if (l == 0) {
1014 log_syntax(unit, LOG_WARNING, filename, line, 0, "6rd prefix length of \"%s\" must be greater than zero, ignoring", rvalue);
1015 return 0;
1016 }
1017
1018 t->sixrd_prefix = p.in6;
1019 t->sixrd_prefixlen = l;
1020
1021 return 0;
1022 }
1023
netdev_tunnel_init(NetDev * netdev)1024 static void netdev_tunnel_init(NetDev *netdev) {
1025 Tunnel *t;
1026
1027 assert(netdev);
1028
1029 t = TUNNEL(netdev);
1030
1031 assert(t);
1032
1033 t->local_type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
1034 t->pmtudisc = true;
1035 t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT;
1036 t->isatap = -1;
1037 t->gre_erspan_sequence = -1;
1038 t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
1039 t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
1040 t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
1041 t->allow_localremote = -1;
1042
1043 if (IN_SET(netdev->kind, NETDEV_KIND_IP6GRE, NETDEV_KIND_IP6GRETAP, NETDEV_KIND_IP6TNL))
1044 t->ttl = DEFAULT_IPV6_TTL;
1045 }
1046
1047 const NetDevVTable ipip_vtable = {
1048 .object_size = sizeof(Tunnel),
1049 .init = netdev_tunnel_init,
1050 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1051 .fill_message_create = netdev_ipip_sit_fill_message_create,
1052 .create_type = NETDEV_CREATE_STACKED,
1053 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1054 .config_verify = netdev_tunnel_verify,
1055 .iftype = ARPHRD_TUNNEL,
1056 };
1057
1058 const NetDevVTable sit_vtable = {
1059 .object_size = sizeof(Tunnel),
1060 .init = netdev_tunnel_init,
1061 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1062 .fill_message_create = netdev_ipip_sit_fill_message_create,
1063 .create_type = NETDEV_CREATE_STACKED,
1064 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1065 .config_verify = netdev_tunnel_verify,
1066 .iftype = ARPHRD_SIT,
1067 };
1068
1069 const NetDevVTable vti_vtable = {
1070 .object_size = sizeof(Tunnel),
1071 .init = netdev_tunnel_init,
1072 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1073 .fill_message_create = netdev_vti_fill_message_create,
1074 .create_type = NETDEV_CREATE_STACKED,
1075 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1076 .config_verify = netdev_tunnel_verify,
1077 .iftype = ARPHRD_TUNNEL,
1078 };
1079
1080 const NetDevVTable vti6_vtable = {
1081 .object_size = sizeof(Tunnel),
1082 .init = netdev_tunnel_init,
1083 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1084 .fill_message_create = netdev_vti_fill_message_create,
1085 .create_type = NETDEV_CREATE_STACKED,
1086 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1087 .config_verify = netdev_tunnel_verify,
1088 .iftype = ARPHRD_TUNNEL6,
1089 };
1090
1091 const NetDevVTable gre_vtable = {
1092 .object_size = sizeof(Tunnel),
1093 .init = netdev_tunnel_init,
1094 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1095 .fill_message_create = netdev_gre_erspan_fill_message_create,
1096 .create_type = NETDEV_CREATE_STACKED,
1097 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1098 .config_verify = netdev_tunnel_verify,
1099 .iftype = ARPHRD_IPGRE,
1100 };
1101
1102 const NetDevVTable gretap_vtable = {
1103 .object_size = sizeof(Tunnel),
1104 .init = netdev_tunnel_init,
1105 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1106 .fill_message_create = netdev_gre_erspan_fill_message_create,
1107 .create_type = NETDEV_CREATE_STACKED,
1108 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1109 .config_verify = netdev_tunnel_verify,
1110 .iftype = ARPHRD_ETHER,
1111 .generate_mac = true,
1112 };
1113
1114 const NetDevVTable ip6gre_vtable = {
1115 .object_size = sizeof(Tunnel),
1116 .init = netdev_tunnel_init,
1117 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1118 .fill_message_create = netdev_ip6gre_fill_message_create,
1119 .create_type = NETDEV_CREATE_STACKED,
1120 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1121 .config_verify = netdev_tunnel_verify,
1122 .iftype = ARPHRD_IP6GRE,
1123 };
1124
1125 const NetDevVTable ip6gretap_vtable = {
1126 .object_size = sizeof(Tunnel),
1127 .init = netdev_tunnel_init,
1128 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1129 .fill_message_create = netdev_ip6gre_fill_message_create,
1130 .create_type = NETDEV_CREATE_STACKED,
1131 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1132 .config_verify = netdev_tunnel_verify,
1133 .iftype = ARPHRD_ETHER,
1134 .generate_mac = true,
1135 };
1136
1137 const NetDevVTable ip6tnl_vtable = {
1138 .object_size = sizeof(Tunnel),
1139 .init = netdev_tunnel_init,
1140 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1141 .fill_message_create = netdev_ip6tnl_fill_message_create,
1142 .create_type = NETDEV_CREATE_STACKED,
1143 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1144 .config_verify = netdev_tunnel_verify,
1145 .iftype = ARPHRD_TUNNEL6,
1146 };
1147
1148 const NetDevVTable erspan_vtable = {
1149 .object_size = sizeof(Tunnel),
1150 .init = netdev_tunnel_init,
1151 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
1152 .fill_message_create = netdev_gre_erspan_fill_message_create,
1153 .create_type = NETDEV_CREATE_STACKED,
1154 .is_ready_to_create = netdev_tunnel_is_ready_to_create,
1155 .config_verify = netdev_tunnel_verify,
1156 .iftype = ARPHRD_ETHER,
1157 .generate_mac = true,
1158 };
1159