1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <netinet/in.h>
5 #include <linux/if_arp.h>
6 #include <linux/if_tunnel.h>
8 #include <linux/ip6_tunnel.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"
23 #define DEFAULT_IPV6_TTL 64
24 #define IP6_FLOWINFO_FLOWLABEL htobe32(0x000FFFFF)
25 #define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0x40
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",
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");
36 #define HASH_KEY SD_ID128_MAKE(74,c4,de,12,f3,d9,41,34,bb,3d,c1,a4,42,93,50,87)
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
];
49 assert(link
->dhcp_lease
);
51 r
= sd_dhcp_lease_get_address(link
->dhcp_lease
, &ipv4address
);
53 return log_link_debug_errno(link
, r
, "Failed to get DHCPv4 address: %m");
55 r
= sd_dhcp_lease_get_6rd(link
->dhcp_lease
, &ipv4masklen
, &sixrd_prefixlen
, &sixrd_prefix
, NULL
, NULL
);
57 return log_link_debug_errno(link
, r
, "Failed to get 6rd option: %m");
59 sz
= sizeof(uint8_t) * 2 + sizeof(struct in6_addr
) + sizeof(struct in_addr
);
60 buf
= newa(uint8_t, sz
);
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
));
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
);
82 ifname_alloc
= strdup(ifname
);
84 return log_oom_debug();
86 *ret
= TAKE_PTR(ifname_alloc
);
90 static int dhcp4_pd_create_6rd_tunnel_message(
92 sd_netlink_message
*m
,
93 const struct in_addr
*ipv4address
,
95 const struct in6_addr
*sixrd_prefix
,
96 uint8_t sixrd_prefixlen
) {
99 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, link
->dhcp4_6rd_tunnel_name
);
103 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
107 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "sit");
111 r
= sd_netlink_message_append_in_addr(m
, IFLA_IPTUN_LOCAL
, ipv4address
);
115 r
= sd_netlink_message_append_u8(m
, IFLA_IPTUN_TTL
, 64);
119 r
= sd_netlink_message_append_in6_addr(m
, IFLA_IPTUN_6RD_PREFIX
, sixrd_prefix
);
123 r
= sd_netlink_message_append_u16(m
, IFLA_IPTUN_6RD_PREFIXLEN
, sixrd_prefixlen
);
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
);
133 r
= sd_netlink_message_append_u16(m
, IFLA_IPTUN_6RD_RELAY_PREFIXLEN
, ipv4masklen
);
137 r
= sd_netlink_message_close_container(m
);
141 r
= sd_netlink_message_close_container(m
);
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
;
156 assert(link
->ifindex
> 0);
157 assert(link
->manager
);
158 assert(link
->dhcp_lease
);
159 assert(link
->dhcp4_6rd_tunnel_name
);
162 r
= sd_dhcp_lease_get_address(link
->dhcp_lease
, &ipv4address
);
164 return log_link_debug_errno(link
, r
, "Failed to get DHCPv4 address: %m");
166 r
= sd_dhcp_lease_get_6rd(link
->dhcp_lease
, &ipv4masklen
, &sixrd_prefixlen
, &sixrd_prefix
, NULL
, NULL
);
168 return log_link_debug_errno(link
, r
, "Failed to get 6rd option: %m");
170 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &m
, RTM_NEWLINK
, 0);
172 return log_link_debug_errno(link
, r
, "Failed to create netlink message: %m");
174 r
= dhcp4_pd_create_6rd_tunnel_message(link
, m
,
175 &ipv4address
, ipv4masklen
,
176 &sixrd_prefix
, sixrd_prefixlen
);
178 return log_link_debug_errno(link
, r
, "Failed to fill netlink message: %m");
180 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
, callback
,
181 link_netlink_destroy_callback
, link
);
183 return log_link_debug_errno(link
, r
, "Could not send netlink message: %m");
190 static int tunnel_get_local_address(Tunnel
*t
, Link
*link
, union in_addr_union
*ret
) {
193 if (t
->local_type
< 0) {
199 return link_get_local_address(link
, t
->local_type
, t
->family
, NULL
, ret
);
202 static int netdev_ipip_sit_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
203 union in_addr_union local
;
210 if (netdev
->kind
== NETDEV_KIND_IPIP
)
218 r
= sd_netlink_message_append_flag(m
, IFLA_IPTUN_COLLECT_METADATA
);
222 /* If external mode is enabled, then the following settings should not be appended. */
226 if (link
|| t
->assign_to_loopback
) {
227 r
= sd_netlink_message_append_u32(m
, IFLA_IPTUN_LINK
, link
? link
->ifindex
: LOOPBACK_IFINDEX
);
232 r
= tunnel_get_local_address(t
, link
, &local
);
234 return log_netdev_error_errno(netdev
, r
, "Could not find local address: %m");
236 r
= sd_netlink_message_append_in_addr(m
, IFLA_IPTUN_LOCAL
, &local
.in
);
240 r
= sd_netlink_message_append_in_addr(m
, IFLA_IPTUN_REMOTE
, &t
->remote
.in
);
244 r
= sd_netlink_message_append_u8(m
, IFLA_IPTUN_TTL
, t
->ttl
);
248 r
= sd_netlink_message_append_u8(m
, IFLA_IPTUN_PMTUDISC
, t
->pmtudisc
);
253 r
= sd_netlink_message_append_u16(m
, IFLA_IPTUN_ENCAP_TYPE
, t
->fou_encap_type
);
257 r
= sd_netlink_message_append_u16(m
, IFLA_IPTUN_ENCAP_SPORT
, htobe16(t
->encap_src_port
));
261 r
= sd_netlink_message_append_u16(m
, IFLA_IPTUN_ENCAP_DPORT
, htobe16(t
->fou_destination_port
));
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
);
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.
275 r
= sd_netlink_message_append_u16(m
, IFLA_IPTUN_6RD_PREFIXLEN
, t
->sixrd_prefixlen
);
280 if (t
->isatap
>= 0) {
283 SET_FLAG(flags
, SIT_ISATAP
, t
->isatap
);
285 r
= sd_netlink_message_append_u16(m
, IFLA_IPTUN_FLAGS
, flags
);
294 static int netdev_gre_erspan_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
295 union in_addr_union local
;
306 switch (netdev
->kind
) {
307 case NETDEV_KIND_GRE
:
310 case NETDEV_KIND_ERSPAN
:
313 case NETDEV_KIND_GRETAP
:
317 assert_not_reached();
323 r
= sd_netlink_message_append_flag(m
, IFLA_GRE_COLLECT_METADATA
);
327 /* If external mode is enabled, then the following settings should not be appended. */
331 if (link
|| t
->assign_to_loopback
) {
332 r
= sd_netlink_message_append_u32(m
, IFLA_GRE_LINK
, link
? link
->ifindex
: LOOPBACK_IFINDEX
);
337 if (netdev
->kind
== NETDEV_KIND_ERSPAN
) {
338 r
= sd_netlink_message_append_u8(m
, IFLA_GRE_ERSPAN_VER
, t
->erspan_version
);
342 if (t
->erspan_version
== 1) {
343 r
= sd_netlink_message_append_u32(m
, IFLA_GRE_ERSPAN_INDEX
, t
->erspan_index
);
347 } else if (t
->erspan_version
== 2) {
348 r
= sd_netlink_message_append_u8(m
, IFLA_GRE_ERSPAN_DIR
, t
->erspan_direction
);
352 r
= sd_netlink_message_append_u16(m
, IFLA_GRE_ERSPAN_HWID
, t
->erspan_hwid
);
358 r
= tunnel_get_local_address(t
, link
, &local
);
360 return log_netdev_error_errno(netdev
, r
, "Could not find local address: %m");
362 r
= sd_netlink_message_append_in_addr(m
, IFLA_GRE_LOCAL
, &local
.in
);
366 r
= sd_netlink_message_append_in_addr(m
, IFLA_GRE_REMOTE
, &t
->remote
.in
);
370 r
= sd_netlink_message_append_u8(m
, IFLA_GRE_TTL
, t
->ttl
);
374 r
= sd_netlink_message_append_u8(m
, IFLA_GRE_TOS
, t
->tos
);
378 r
= sd_netlink_message_append_u8(m
, IFLA_GRE_PMTUDISC
, t
->pmtudisc
);
383 ikey
= okey
= htobe32(t
->key
);
389 ikey
= htobe32(t
->ikey
);
394 okey
= htobe32(t
->okey
);
398 if (t
->gre_erspan_sequence
> 0) {
401 } else if (t
->gre_erspan_sequence
== 0) {
406 r
= sd_netlink_message_append_u32(m
, IFLA_GRE_IKEY
, ikey
);
410 r
= sd_netlink_message_append_u32(m
, IFLA_GRE_OKEY
, okey
);
414 r
= sd_netlink_message_append_u16(m
, IFLA_GRE_IFLAGS
, iflags
);
418 r
= sd_netlink_message_append_u16(m
, IFLA_GRE_OFLAGS
, oflags
);
423 r
= sd_netlink_message_append_u16(m
, IFLA_GRE_ENCAP_TYPE
, t
->fou_encap_type
);
427 r
= sd_netlink_message_append_u16(m
, IFLA_GRE_ENCAP_SPORT
, htobe16(t
->encap_src_port
));
431 r
= sd_netlink_message_append_u16(m
, IFLA_GRE_ENCAP_DPORT
, htobe16(t
->fou_destination_port
));
439 static int netdev_ip6gre_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
440 union in_addr_union local
;
451 if (netdev
->kind
== NETDEV_KIND_IP6GRE
)
454 t
= IP6GRETAP(netdev
);
459 r
= sd_netlink_message_append_flag(m
, IFLA_GRE_COLLECT_METADATA
);
463 /* If external mode is enabled, then the following settings should not be appended. */
467 if (link
|| t
->assign_to_loopback
) {
468 r
= sd_netlink_message_append_u32(m
, IFLA_GRE_LINK
, link
? link
->ifindex
: LOOPBACK_IFINDEX
);
473 r
= tunnel_get_local_address(t
, link
, &local
);
475 return log_netdev_error_errno(netdev
, r
, "Could not find local address: %m");
477 r
= sd_netlink_message_append_in6_addr(m
, IFLA_GRE_LOCAL
, &local
.in6
);
481 r
= sd_netlink_message_append_in6_addr(m
, IFLA_GRE_REMOTE
, &t
->remote
.in6
);
485 r
= sd_netlink_message_append_u8(m
, IFLA_GRE_TTL
, t
->ttl
);
489 if (t
->ipv6_flowlabel
!= _NETDEV_IPV6_FLOWLABEL_INVALID
) {
490 r
= sd_netlink_message_append_u32(m
, IFLA_GRE_FLOWINFO
, t
->ipv6_flowlabel
);
495 r
= sd_netlink_message_append_u32(m
, IFLA_GRE_FLAGS
, t
->flags
);
500 ikey
= okey
= htobe32(t
->key
);
506 ikey
= htobe32(t
->ikey
);
511 okey
= htobe32(t
->okey
);
515 r
= sd_netlink_message_append_u32(m
, IFLA_GRE_IKEY
, ikey
);
519 r
= sd_netlink_message_append_u32(m
, IFLA_GRE_OKEY
, okey
);
523 r
= sd_netlink_message_append_u16(m
, IFLA_GRE_IFLAGS
, iflags
);
527 r
= sd_netlink_message_append_u16(m
, IFLA_GRE_OFLAGS
, oflags
);
534 static int netdev_vti_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
535 union in_addr_union local
;
543 if (netdev
->kind
== NETDEV_KIND_VTI
)
550 if (link
|| t
->assign_to_loopback
) {
551 r
= sd_netlink_message_append_u32(m
, IFLA_VTI_LINK
, link
? link
->ifindex
: LOOPBACK_IFINDEX
);
557 ikey
= okey
= htobe32(t
->key
);
559 ikey
= htobe32(t
->ikey
);
560 okey
= htobe32(t
->okey
);
563 r
= sd_netlink_message_append_u32(m
, IFLA_VTI_IKEY
, ikey
);
567 r
= sd_netlink_message_append_u32(m
, IFLA_VTI_OKEY
, okey
);
571 r
= tunnel_get_local_address(t
, link
, &local
);
573 return log_netdev_error_errno(netdev
, r
, "Could not find local address: %m");
575 r
= netlink_message_append_in_addr_union(m
, IFLA_VTI_LOCAL
, t
->family
, &local
);
579 r
= netlink_message_append_in_addr_union(m
, IFLA_VTI_REMOTE
, t
->family
, &t
->remote
);
586 static int netdev_ip6tnl_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
587 union in_addr_union local
;
599 switch (t
->ip6tnl_mode
) {
600 case NETDEV_IP6_TNL_MODE_IP6IP6
:
601 proto
= IPPROTO_IPV6
;
603 case NETDEV_IP6_TNL_MODE_IPIP6
:
604 proto
= IPPROTO_IPIP
;
606 case NETDEV_IP6_TNL_MODE_ANYIP6
:
612 r
= sd_netlink_message_append_u8(m
, IFLA_IPTUN_PROTO
, proto
);
617 r
= sd_netlink_message_append_flag(m
, IFLA_IPTUN_COLLECT_METADATA
);
621 /* If external mode is enabled, then the following settings should not be appended. */
625 if (link
|| t
->assign_to_loopback
) {
626 r
= sd_netlink_message_append_u32(m
, IFLA_IPTUN_LINK
, link
? link
->ifindex
: LOOPBACK_IFINDEX
);
631 r
= tunnel_get_local_address(t
, link
, &local
);
633 return log_netdev_error_errno(netdev
, r
, "Could not find local address: %m");
635 r
= sd_netlink_message_append_in6_addr(m
, IFLA_IPTUN_LOCAL
, &local
.in6
);
639 r
= sd_netlink_message_append_in6_addr(m
, IFLA_IPTUN_REMOTE
, &t
->remote
.in6
);
643 r
= sd_netlink_message_append_u8(m
, IFLA_IPTUN_TTL
, t
->ttl
);
647 if (t
->ipv6_flowlabel
!= _NETDEV_IPV6_FLOWLABEL_INVALID
) {
648 r
= sd_netlink_message_append_u32(m
, IFLA_IPTUN_FLOWINFO
, t
->ipv6_flowlabel
);
654 t
->flags
|= IP6_TNL_F_RCV_DSCP_COPY
;
656 if (t
->allow_localremote
>= 0)
657 SET_FLAG(t
->flags
, IP6_TNL_F_ALLOW_LOCAL_REMOTE
, t
->allow_localremote
);
659 r
= sd_netlink_message_append_u32(m
, IFLA_IPTUN_FLAGS
, t
->flags
);
663 if (t
->encap_limit
!= 0) {
664 r
= sd_netlink_message_append_u8(m
, IFLA_IPTUN_ENCAP_LIMIT
, t
->encap_limit
);
672 static int netdev_tunnel_is_ready_to_create(NetDev
*netdev
, Link
*link
) {
684 return tunnel_get_local_address(t
, link
, NULL
) >= 0;
687 static int netdev_tunnel_verify(NetDev
*netdev
, const char *filename
) {
697 if (netdev
->kind
== NETDEV_KIND_IP6TNL
&&
698 t
->ip6tnl_mode
== _NETDEV_IP6_TNL_MODE_INVALID
)
699 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
700 "ip6tnl without mode configured in %s. Ignoring", filename
);
703 if (IN_SET(netdev
->kind
, NETDEV_KIND_VTI
, NETDEV_KIND_VTI6
))
704 log_netdev_debug(netdev
, "vti/vti6 tunnel do not support external mode, ignoring.");
706 /* tunnel with external mode does not require underlying interface. */
707 t
->independent
= true;
709 /* tunnel with external mode does not require any settings checked below. */
714 if (IN_SET(netdev
->kind
, NETDEV_KIND_VTI
, NETDEV_KIND_IPIP
, NETDEV_KIND_SIT
, NETDEV_KIND_GRE
) &&
715 !IN_SET(t
->family
, AF_UNSPEC
, AF_INET
))
716 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
717 "vti/ipip/sit/gre tunnel without a local/remote IPv4 address configured in %s. Ignoring", filename
);
719 if (IN_SET(netdev
->kind
, NETDEV_KIND_GRETAP
, NETDEV_KIND_ERSPAN
) &&
720 (t
->family
!= AF_INET
|| !in_addr_is_set(t
->family
, &t
->remote
)))
721 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
722 "gretap/erspan tunnel without a remote IPv4 address configured in %s. Ignoring", filename
);
724 if ((IN_SET(netdev
->kind
, NETDEV_KIND_VTI6
, NETDEV_KIND_IP6TNL
) && t
->family
!= AF_INET6
) ||
725 (netdev
->kind
== NETDEV_KIND_IP6GRE
&& !IN_SET(t
->family
, AF_UNSPEC
, AF_INET6
)))
726 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
727 "vti6/ip6tnl/ip6gre tunnel without a local/remote IPv6 address configured in %s. Ignoring", filename
);
729 if (netdev
->kind
== NETDEV_KIND_IP6GRETAP
&&
730 (t
->family
!= AF_INET6
|| !in_addr_is_set(t
->family
, &t
->remote
)))
731 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
732 "ip6gretap tunnel without a remote IPv6 address configured in %s. Ignoring", filename
);
734 if (t
->fou_tunnel
&& t
->fou_destination_port
<= 0)
735 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
736 "FooOverUDP missing port configured in %s. Ignoring", filename
);
738 /* netlink_message_append_in_addr_union() is used for vti/vti6. So, t->family cannot be AF_UNSPEC. */
739 if (netdev
->kind
== NETDEV_KIND_VTI
)
742 if (t
->assign_to_loopback
)
743 t
->independent
= true;
745 if (t
->independent
&& t
->local_type
>= 0)
746 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
747 "The local address cannot be '%s' when Independent= or AssignToLoopback= is enabled, ignoring.",
748 strna(netdev_local_address_type_to_string(t
->local_type
)));
753 static int unset_local(Tunnel
*t
) {
756 /* Unset the previous assignment. */
757 t
->local
= IN_ADDR_NULL
;
758 t
->local_type
= _NETDEV_LOCAL_ADDRESS_TYPE_INVALID
;
760 /* If the remote address is not specified, also clear the address family. */
761 if (!in_addr_is_set(t
->family
, &t
->remote
))
762 t
->family
= AF_UNSPEC
;
767 int config_parse_tunnel_local_address(
769 const char *filename
,
772 unsigned section_line
,
779 union in_addr_union buffer
= IN_ADDR_NULL
;
780 NetDevLocalAddressType type
;
781 Tunnel
*t
= userdata
;
789 if (isempty(rvalue
) || streq(rvalue
, "any"))
790 return unset_local(t
);
792 type
= netdev_local_address_type_from_string(rvalue
);
793 if (IN_SET(type
, NETDEV_LOCAL_ADDRESS_IPV4LL
, NETDEV_LOCAL_ADDRESS_DHCP4
))
795 else if (IN_SET(type
, NETDEV_LOCAL_ADDRESS_IPV6LL
, NETDEV_LOCAL_ADDRESS_DHCP6
, NETDEV_LOCAL_ADDRESS_SLAAC
))
798 type
= _NETDEV_LOCAL_ADDRESS_TYPE_INVALID
;
799 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
801 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
802 "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue
);
806 if (in_addr_is_null(f
, &buffer
))
807 return unset_local(t
);
810 if (t
->family
!= AF_UNSPEC
&& t
->family
!= f
) {
811 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
812 "Address family does not match the previous assignment, ignoring assignment: %s", rvalue
);
818 t
->local_type
= type
;
822 static int unset_remote(Tunnel
*t
) {
825 /* Unset the previous assignment. */
826 t
->remote
= IN_ADDR_NULL
;
828 /* If the local address is not specified, also clear the address family. */
829 if (t
->local_type
== _NETDEV_LOCAL_ADDRESS_TYPE_INVALID
&&
830 !in_addr_is_set(t
->family
, &t
->local
))
831 t
->family
= AF_UNSPEC
;
836 int config_parse_tunnel_remote_address(
838 const char *filename
,
841 unsigned section_line
,
848 union in_addr_union buffer
;
849 Tunnel
*t
= userdata
;
857 if (isempty(rvalue
) || streq(rvalue
, "any"))
858 return unset_remote(t
);
860 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
862 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
863 "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue
);
867 if (in_addr_is_null(f
, &buffer
))
868 return unset_remote(t
);
870 if (t
->family
!= AF_UNSPEC
&& t
->family
!= f
) {
871 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
872 "Address family does not match the previous assignment, ignoring assignment: %s", rvalue
);
881 int config_parse_tunnel_key(
883 const char *filename
,
886 unsigned section_line
,
893 uint32_t *dest
= ASSERT_PTR(data
), k
;
894 union in_addr_union buffer
;
900 r
= in_addr_from_string(AF_INET
, rvalue
, &buffer
);
902 r
= safe_atou32(rvalue
, &k
);
904 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
905 "Failed to parse tunnel key ignoring assignment: %s", rvalue
);
909 k
= be32toh(buffer
.in
.s_addr
);
915 int config_parse_ipv6_flowlabel(
917 const char *filename
,
920 unsigned section_line
,
927 Tunnel
*t
= ASSERT_PTR(userdata
);
933 if (streq(rvalue
, "inherit")) {
934 t
->ipv6_flowlabel
= IP6_FLOWINFO_FLOWLABEL
;
935 t
->flags
|= IP6_TNL_F_USE_ORIG_FLOWLABEL
;
939 r
= safe_atoi(rvalue
, &k
);
941 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
942 "Failed to parse tunnel IPv6 flowlabel, ignoring assignment: %s", rvalue
);
947 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
948 "Invalid tunnel IPv6 flowlabel, ignoring assignment: %s", rvalue
);
952 t
->ipv6_flowlabel
= htobe32(k
) & IP6_FLOWINFO_FLOWLABEL
;
953 t
->flags
&= ~IP6_TNL_F_USE_ORIG_FLOWLABEL
;
957 int config_parse_encap_limit(
959 const char *filename
,
962 unsigned section_line
,
969 Tunnel
*t
= ASSERT_PTR(userdata
);
975 if (streq(rvalue
, "none")) {
976 t
->flags
|= IP6_TNL_F_IGN_ENCAP_LIMIT
;
981 r
= safe_atoi(rvalue
, &k
);
983 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
984 "Failed to parse Tunnel Encapsulation Limit option, ignoring assignment: %s", rvalue
);
988 if (k
> 255 || k
< 0) {
989 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
990 "Invalid Tunnel Encapsulation value, ignoring assignment: %d", k
);
995 t
->flags
&= ~IP6_TNL_F_IGN_ENCAP_LIMIT
;
999 int config_parse_6rd_prefix(
1001 const char *filename
,
1003 const char *section
,
1004 unsigned section_line
,
1011 Tunnel
*t
= userdata
;
1012 union in_addr_union p
;
1020 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &p
, &l
);
1022 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse 6rd prefix \"%s\", ignoring: %m", rvalue
);
1026 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "6rd prefix length of \"%s\" must be greater than zero, ignoring", rvalue
);
1030 t
->sixrd_prefix
= p
.in6
;
1031 t
->sixrd_prefixlen
= l
;
1036 int config_parse_erspan_version(
1038 const char *filename
,
1040 const char *section
,
1041 unsigned section_line
,
1048 uint8_t n
, *v
= ASSERT_PTR(data
);
1055 if (isempty(rvalue
)) {
1056 *v
= 1; /* defaults to 1 */
1060 r
= safe_atou8(rvalue
, &n
);
1062 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1063 "Failed to parse erspan version \"%s\", ignoring: %m", rvalue
);
1066 if (!IN_SET(n
, 0, 1, 2)) {
1067 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1068 "Invalid erspan version \"%s\", which must be 0, 1 or 2, ignoring.", rvalue
);
1076 int config_parse_erspan_index(
1078 const char *filename
,
1080 const char *section
,
1081 unsigned section_line
,
1088 uint32_t n
, *v
= ASSERT_PTR(data
);
1095 if (isempty(rvalue
)) {
1096 *v
= 0; /* defaults to 0 */
1100 r
= safe_atou32(rvalue
, &n
);
1102 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1103 "Failed to parse erspan index \"%s\", ignoring: %m", rvalue
);
1106 if (n
>= 0x100000) {
1107 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1108 "Invalid erspan index \"%s\", which must be less than 0x100000, ignoring.", rvalue
);
1116 int config_parse_erspan_direction(
1118 const char *filename
,
1120 const char *section
,
1121 unsigned section_line
,
1128 uint8_t *v
= ASSERT_PTR(data
);
1134 if (isempty(rvalue
) || streq(rvalue
, "ingress"))
1135 *v
= 0; /* defaults to ingress */
1136 else if (streq(rvalue
, "egress"))
1139 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1140 "Invalid erspan direction \"%s\", which must be \"ingress\" or \"egress\", ignoring.", rvalue
);
1145 int config_parse_erspan_hwid(
1147 const char *filename
,
1149 const char *section
,
1150 unsigned section_line
,
1157 uint16_t n
, *v
= ASSERT_PTR(data
);
1164 if (isempty(rvalue
)) {
1165 *v
= 0; /* defaults to 0 */
1169 r
= safe_atou16(rvalue
, &n
);
1171 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1172 "Failed to parse erspan hwid \"%s\", ignoring: %m", rvalue
);
1176 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1177 "Invalid erspan index \"%s\", which must be less than 64, ignoring.", rvalue
);
1185 static void netdev_tunnel_init(NetDev
*netdev
) {
1194 t
->local_type
= _NETDEV_LOCAL_ADDRESS_TYPE_INVALID
;
1196 t
->fou_encap_type
= NETDEV_FOO_OVER_UDP_ENCAP_DIRECT
;
1198 t
->gre_erspan_sequence
= -1;
1199 t
->encap_limit
= IPV6_DEFAULT_TNL_ENCAP_LIMIT
;
1200 t
->ip6tnl_mode
= _NETDEV_IP6_TNL_MODE_INVALID
;
1201 t
->ipv6_flowlabel
= _NETDEV_IPV6_FLOWLABEL_INVALID
;
1202 t
->allow_localremote
= -1;
1203 t
->erspan_version
= 1;
1205 if (IN_SET(netdev
->kind
, NETDEV_KIND_IP6GRE
, NETDEV_KIND_IP6GRETAP
, NETDEV_KIND_IP6TNL
))
1206 t
->ttl
= DEFAULT_IPV6_TTL
;
1209 const NetDevVTable ipip_vtable
= {
1210 .object_size
= sizeof(Tunnel
),
1211 .init
= netdev_tunnel_init
,
1212 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1213 .fill_message_create
= netdev_ipip_sit_fill_message_create
,
1214 .create_type
= NETDEV_CREATE_STACKED
,
1215 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1216 .config_verify
= netdev_tunnel_verify
,
1217 .iftype
= ARPHRD_TUNNEL
,
1220 const NetDevVTable sit_vtable
= {
1221 .object_size
= sizeof(Tunnel
),
1222 .init
= netdev_tunnel_init
,
1223 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1224 .fill_message_create
= netdev_ipip_sit_fill_message_create
,
1225 .create_type
= NETDEV_CREATE_STACKED
,
1226 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1227 .config_verify
= netdev_tunnel_verify
,
1228 .iftype
= ARPHRD_SIT
,
1231 const NetDevVTable vti_vtable
= {
1232 .object_size
= sizeof(Tunnel
),
1233 .init
= netdev_tunnel_init
,
1234 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1235 .fill_message_create
= netdev_vti_fill_message_create
,
1236 .create_type
= NETDEV_CREATE_STACKED
,
1237 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1238 .config_verify
= netdev_tunnel_verify
,
1239 .iftype
= ARPHRD_TUNNEL
,
1242 const NetDevVTable vti6_vtable
= {
1243 .object_size
= sizeof(Tunnel
),
1244 .init
= netdev_tunnel_init
,
1245 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1246 .fill_message_create
= netdev_vti_fill_message_create
,
1247 .create_type
= NETDEV_CREATE_STACKED
,
1248 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1249 .config_verify
= netdev_tunnel_verify
,
1250 .iftype
= ARPHRD_TUNNEL6
,
1253 const NetDevVTable gre_vtable
= {
1254 .object_size
= sizeof(Tunnel
),
1255 .init
= netdev_tunnel_init
,
1256 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1257 .fill_message_create
= netdev_gre_erspan_fill_message_create
,
1258 .create_type
= NETDEV_CREATE_STACKED
,
1259 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1260 .config_verify
= netdev_tunnel_verify
,
1261 .iftype
= ARPHRD_IPGRE
,
1264 const NetDevVTable gretap_vtable
= {
1265 .object_size
= sizeof(Tunnel
),
1266 .init
= netdev_tunnel_init
,
1267 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1268 .fill_message_create
= netdev_gre_erspan_fill_message_create
,
1269 .create_type
= NETDEV_CREATE_STACKED
,
1270 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1271 .config_verify
= netdev_tunnel_verify
,
1272 .iftype
= ARPHRD_ETHER
,
1273 .generate_mac
= true,
1276 const NetDevVTable ip6gre_vtable
= {
1277 .object_size
= sizeof(Tunnel
),
1278 .init
= netdev_tunnel_init
,
1279 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1280 .fill_message_create
= netdev_ip6gre_fill_message_create
,
1281 .create_type
= NETDEV_CREATE_STACKED
,
1282 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1283 .config_verify
= netdev_tunnel_verify
,
1284 .iftype
= ARPHRD_IP6GRE
,
1287 const NetDevVTable ip6gretap_vtable
= {
1288 .object_size
= sizeof(Tunnel
),
1289 .init
= netdev_tunnel_init
,
1290 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1291 .fill_message_create
= netdev_ip6gre_fill_message_create
,
1292 .create_type
= NETDEV_CREATE_STACKED
,
1293 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1294 .config_verify
= netdev_tunnel_verify
,
1295 .iftype
= ARPHRD_ETHER
,
1296 .generate_mac
= true,
1299 const NetDevVTable ip6tnl_vtable
= {
1300 .object_size
= sizeof(Tunnel
),
1301 .init
= netdev_tunnel_init
,
1302 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1303 .fill_message_create
= netdev_ip6tnl_fill_message_create
,
1304 .create_type
= NETDEV_CREATE_STACKED
,
1305 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1306 .config_verify
= netdev_tunnel_verify
,
1307 .iftype
= ARPHRD_TUNNEL6
,
1310 const NetDevVTable erspan_vtable
= {
1311 .object_size
= sizeof(Tunnel
),
1312 .init
= netdev_tunnel_init
,
1313 .sections
= NETDEV_COMMON_SECTIONS
"Tunnel\0",
1314 .fill_message_create
= netdev_gre_erspan_fill_message_create
,
1315 .create_type
= NETDEV_CREATE_STACKED
,
1316 .is_ready_to_create
= netdev_tunnel_is_ready_to_create
,
1317 .config_verify
= netdev_tunnel_verify
,
1318 .iftype
= ARPHRD_ETHER
,
1319 .generate_mac
= true,