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