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