]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/netdev/tunnel.c
Merge pull request #6715 from sourcejedi/kbrequest-jobmode2
[thirdparty/systemd.git] / src / network / netdev / tunnel.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2014 Susant Sahani
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <arpa/inet.h>
21 #include <net/if.h>
22 #include <linux/ip.h>
23 #include <linux/if_tunnel.h>
24 #include <linux/ip6_tunnel.h>
25
26 #include "sd-netlink.h"
27
28 #include "conf-parser.h"
29 #include "missing.h"
30 #include "networkd-link.h"
31 #include "netdev/tunnel.h"
32 #include "parse-util.h"
33 #include "string-table.h"
34 #include "string-util.h"
35 #include "util.h"
36
37 #define DEFAULT_TNL_HOP_LIMIT 64
38 #define IP6_FLOWINFO_FLOWLABEL htobe32(0x000FFFFF)
39
40 static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
41 [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
42 [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6",
43 [NETDEV_IP6_TNL_MODE_ANYIP6] = "any",
44 };
45
46 DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
47 DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
48
49 static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
50 Tunnel *t = IPIP(netdev);
51 int r;
52
53 assert(netdev);
54 assert(m);
55 assert(t);
56 assert(IN_SET(t->family, AF_INET, AF_UNSPEC));
57
58 if (link) {
59 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
60 if (r < 0)
61 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
62
63 }
64
65 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
66 if (r < 0)
67 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
68
69 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
70 if (r < 0)
71 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
72
73 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
74 if (r < 0)
75 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
76
77 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
78 if (r < 0)
79 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
80
81 return r;
82 }
83
84 static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
85 Tunnel *t = SIT(netdev);
86 int r;
87
88 assert(netdev);
89 assert(m);
90 assert(t);
91 assert(IN_SET(t->family, AF_INET, AF_UNSPEC));
92
93 if (link) {
94 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
95 if (r < 0)
96 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
97
98 }
99
100 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
101 if (r < 0)
102 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
103
104 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
105 if (r < 0)
106 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
107
108 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
109 if (r < 0)
110 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
111
112 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
113 if (r < 0)
114 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
115
116 return r;
117 }
118
119 static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
120 Tunnel *t;
121 int r;
122
123 assert(netdev);
124
125 if (netdev->kind == NETDEV_KIND_GRE)
126 t = GRE(netdev);
127 else
128 t = GRETAP(netdev);
129
130 assert(t);
131 assert(IN_SET(t->family, AF_INET, AF_UNSPEC));
132 assert(m);
133
134 if (link) {
135 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
136 if (r < 0)
137 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
138 }
139
140 r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
141 if (r < 0)
142 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
143
144 r = sd_netlink_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
145 if (r < 0)
146 log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
147
148 r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
149 if (r < 0)
150 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
151
152 r = sd_netlink_message_append_u8(m, IFLA_GRE_TOS, t->tos);
153 if (r < 0)
154 log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m");
155
156 r = sd_netlink_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc);
157 if (r < 0)
158 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m");
159
160 return r;
161 }
162
163 static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
164 Tunnel *t;
165 int r;
166
167 assert(netdev);
168
169 if (netdev->kind == NETDEV_KIND_IP6GRE)
170 t = IP6GRE(netdev);
171 else
172 t = IP6GRETAP(netdev);
173
174 assert(t);
175 assert(t->family == AF_INET6);
176 assert(m);
177
178 if (link) {
179 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
180 if (r < 0)
181 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
182 }
183
184 r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
185 if (r < 0)
186 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
187
188 r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
189 if (r < 0)
190 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
191
192 r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
193 if (r < 0)
194 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
195
196 if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
197 r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel);
198 if (r < 0)
199 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m");
200 }
201
202 r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags);
203 if (r < 0)
204 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m");
205
206 return r;
207 }
208
209 static int netdev_vti_fill_message_key(NetDev *netdev, Link *link, sd_netlink_message *m) {
210 uint32_t ikey, okey;
211 Tunnel *t;
212 int r;
213
214 assert(m);
215
216 if (netdev->kind == NETDEV_KIND_VTI)
217 t = VTI(netdev);
218 else
219 t = VTI6(netdev);
220
221 assert(t);
222
223 if (t->key != 0)
224 ikey = okey = htobe32(t->key);
225 else {
226 ikey = htobe32(t->ikey);
227 okey = htobe32(t->okey);
228 }
229
230 r = sd_netlink_message_append_u32(m, IFLA_VTI_IKEY, ikey);
231 if (r < 0)
232 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_IKEY attribute: %m");
233
234 r = sd_netlink_message_append_u32(m, IFLA_VTI_OKEY, okey);
235 if (r < 0)
236 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_OKEY attribute: %m");
237
238 return 0;
239 }
240
241 static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
242 Tunnel *t = VTI(netdev);
243 int r;
244
245 assert(netdev);
246 assert(link);
247 assert(m);
248 assert(t);
249 assert(t->family == AF_INET);
250
251 if (link) {
252 r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
253 if (r < 0)
254 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
255 }
256
257 r = netdev_vti_fill_message_key(netdev, link, m);
258 if (r < 0)
259 return r;
260
261 r = sd_netlink_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in);
262 if (r < 0)
263 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
264
265 r = sd_netlink_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in);
266 if (r < 0)
267 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
268
269 return r;
270 }
271
272 static int netdev_vti6_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
273 Tunnel *t = VTI6(netdev);
274 int r;
275
276 assert(netdev);
277 assert(m);
278 assert(t);
279 assert(t->family == AF_INET6);
280
281 if (link) {
282 r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
283 if (r < 0)
284 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
285 }
286
287 r = netdev_vti_fill_message_key(netdev, link, m);
288 if (r < 0)
289 return r;
290
291 r = sd_netlink_message_append_in6_addr(m, IFLA_VTI_LOCAL, &t->local.in6);
292 if (r < 0)
293 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
294
295 r = sd_netlink_message_append_in6_addr(m, IFLA_VTI_REMOTE, &t->remote.in6);
296 if (r < 0)
297 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
298
299 return r;
300 }
301
302 static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
303 Tunnel *t = IP6TNL(netdev);
304 uint8_t proto;
305 int r;
306
307 assert(netdev);
308 assert(m);
309 assert(t);
310 assert(t->family == AF_INET6);
311
312 if (link) {
313 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
314 if (r < 0)
315 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
316 }
317
318 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
319 if (r < 0)
320 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
321
322 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
323 if (r < 0)
324 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
325
326 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
327 if (r < 0)
328 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
329
330 if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
331 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
332 if (r < 0)
333 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m");
334 }
335
336 if (t->copy_dscp)
337 t->flags |= IP6_TNL_F_RCV_DSCP_COPY;
338
339 if (t->encap_limit != IPV6_DEFAULT_TNL_ENCAP_LIMIT) {
340 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_ENCAP_LIMIT, t->encap_limit);
341 if (r < 0)
342 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_LIMIT attribute: %m");
343 }
344
345 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
346 if (r < 0)
347 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
348
349 switch (t->ip6tnl_mode) {
350 case NETDEV_IP6_TNL_MODE_IP6IP6:
351 proto = IPPROTO_IPV6;
352 break;
353 case NETDEV_IP6_TNL_MODE_IPIP6:
354 proto = IPPROTO_IPIP;
355 break;
356 case NETDEV_IP6_TNL_MODE_ANYIP6:
357 default:
358 proto = 0;
359 break;
360 }
361
362 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
363 if (r < 0)
364 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_MODE attribute: %m");
365
366 return r;
367 }
368
369 static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
370 Tunnel *t = NULL;
371
372 assert(netdev);
373 assert(filename);
374
375 switch (netdev->kind) {
376 case NETDEV_KIND_IPIP:
377 t = IPIP(netdev);
378 break;
379 case NETDEV_KIND_SIT:
380 t = SIT(netdev);
381 break;
382 case NETDEV_KIND_GRE:
383 t = GRE(netdev);
384 break;
385 case NETDEV_KIND_GRETAP:
386 t = GRETAP(netdev);
387 break;
388 case NETDEV_KIND_IP6GRE:
389 t = IP6GRE(netdev);
390 break;
391 case NETDEV_KIND_IP6GRETAP:
392 t = IP6GRETAP(netdev);
393 break;
394 case NETDEV_KIND_VTI:
395 t = VTI(netdev);
396 break;
397 case NETDEV_KIND_VTI6:
398 t = VTI6(netdev);
399 break;
400 case NETDEV_KIND_IP6TNL:
401 t = IP6TNL(netdev);
402 break;
403 default:
404 assert_not_reached("Invalid tunnel kind");
405 }
406
407 assert(t);
408
409 if (!IN_SET(t->family, AF_INET, AF_INET6, AF_UNSPEC)) {
410 log_netdev_error(netdev,
411 "Tunnel with invalid address family configured in %s. Ignoring", filename);
412 return -EINVAL;
413 }
414
415 if (netdev->kind == NETDEV_KIND_VTI &&
416 (t->family != AF_INET || in_addr_is_null(t->family, &t->local))) {
417 log_netdev_error(netdev,
418 "vti tunnel without a local IPv4 address configured in %s. Ignoring", filename);
419 return -EINVAL;
420 }
421
422 if (IN_SET(netdev->kind, NETDEV_KIND_VTI6, NETDEV_KIND_IP6TNL, NETDEV_KIND_IP6GRE) &&
423 (t->family != AF_INET6 || in_addr_is_null(t->family, &t->local))) {
424 log_netdev_error(netdev,
425 "vti6/ip6tnl/ip6gre tunnel without a local IPv6 address configured in %s. Ignoring", filename);
426 return -EINVAL;
427 }
428
429 if (netdev->kind == NETDEV_KIND_IP6TNL &&
430 t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) {
431 log_netdev_error(netdev,
432 "ip6tnl without mode configured in %s. Ignoring", filename);
433 return -EINVAL;
434 }
435
436 return 0;
437 }
438
439 int config_parse_tunnel_address(const char *unit,
440 const char *filename,
441 unsigned line,
442 const char *section,
443 unsigned section_line,
444 const char *lvalue,
445 int ltype,
446 const char *rvalue,
447 void *data,
448 void *userdata) {
449 Tunnel *t = userdata;
450 union in_addr_union *addr = data, buffer;
451 int r, f;
452
453 assert(filename);
454 assert(lvalue);
455 assert(rvalue);
456 assert(data);
457
458 /* This is used to parse addresses on both local and remote ends of the tunnel.
459 * Address families must match.
460 *
461 * "any" is a special value which means that the address is unspecified.
462 */
463
464 if (streq(rvalue, "any")) {
465 *addr = IN_ADDR_NULL;
466
467 /* As a special case, if both the local and remote addresses are
468 * unspecified, also clear the address family.
469 */
470 if (t->family != AF_UNSPEC &&
471 in_addr_is_null(t->family, &t->local) &&
472 in_addr_is_null(t->family, &t->remote))
473 t->family = AF_UNSPEC;
474 return 0;
475 }
476
477 r = in_addr_from_string_auto(rvalue, &f, &buffer);
478 if (r < 0) {
479 log_syntax(unit, LOG_ERR, filename, line, r,
480 "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue);
481 return 0;
482 }
483
484 if (t->family != AF_UNSPEC && t->family != f) {
485 log_syntax(unit, LOG_ERR, filename, line, 0,
486 "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
487 return 0;
488 }
489
490 t->family = f;
491 *addr = buffer;
492 return 0;
493 }
494
495 int config_parse_tunnel_key(const char *unit,
496 const char *filename,
497 unsigned line,
498 const char *section,
499 unsigned section_line,
500 const char *lvalue,
501 int ltype,
502 const char *rvalue,
503 void *data,
504 void *userdata) {
505 union in_addr_union buffer;
506 Tunnel *t = userdata;
507 uint32_t k;
508 int r;
509
510 assert(filename);
511 assert(lvalue);
512 assert(rvalue);
513 assert(data);
514
515 r = in_addr_from_string(AF_INET, rvalue, &buffer);
516 if (r < 0) {
517 r = safe_atou32(rvalue, &k);
518 if (r < 0) {
519 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse tunnel key ignoring assignment: %s", rvalue);
520 return 0;
521 }
522 } else
523 k = be32toh(buffer.in.s_addr);
524
525 if (streq(lvalue, "Key"))
526 t->key = k;
527 else if (streq(lvalue, "InputKey"))
528 t->ikey = k;
529 else
530 t->okey = k;
531
532 return 0;
533 }
534
535 int config_parse_ipv6_flowlabel(const char* unit,
536 const char *filename,
537 unsigned line,
538 const char *section,
539 unsigned section_line,
540 const char *lvalue,
541 int ltype,
542 const char *rvalue,
543 void *data,
544 void *userdata) {
545 IPv6FlowLabel *ipv6_flowlabel = data;
546 Tunnel *t = userdata;
547 int k = 0;
548 int r;
549
550 assert(filename);
551 assert(lvalue);
552 assert(rvalue);
553 assert(ipv6_flowlabel);
554
555 if (streq(rvalue, "inherit")) {
556 *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
557 t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
558 } else {
559 r = config_parse_int(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);
560 if (r < 0)
561 return r;
562
563 if (k > 0xFFFFF)
564 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
565 else {
566 *ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL;
567 t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
568 }
569 }
570
571 return 0;
572 }
573
574 int config_parse_encap_limit(const char* unit,
575 const char *filename,
576 unsigned line,
577 const char *section,
578 unsigned section_line,
579 const char *lvalue,
580 int ltype,
581 const char *rvalue,
582 void *data,
583 void *userdata) {
584 Tunnel *t = userdata;
585 int k = 0;
586 int r;
587
588 assert(filename);
589 assert(lvalue);
590 assert(rvalue);
591
592 if (streq(rvalue, "none"))
593 t->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT;
594 else {
595 r = safe_atoi(rvalue, &k);
596 if (r < 0) {
597 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Tunnel Encapsulation Limit option, ignoring: %s", rvalue);
598 return 0;
599 }
600
601 if (k > 255 || k < 0)
602 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid Tunnel Encapsulation value, ignoring: %d", k);
603 else {
604 t->encap_limit = k;
605 t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
606 }
607 }
608
609 return 0;
610 }
611
612 static void ipip_init(NetDev *n) {
613 Tunnel *t = IPIP(n);
614
615 assert(n);
616 assert(t);
617
618 t->pmtudisc = true;
619 }
620
621 static void sit_init(NetDev *n) {
622 Tunnel *t = SIT(n);
623
624 assert(n);
625 assert(t);
626
627 t->pmtudisc = true;
628 }
629
630 static void vti_init(NetDev *n) {
631 Tunnel *t;
632
633 assert(n);
634
635 if (n->kind == NETDEV_KIND_VTI)
636 t = VTI(n);
637 else
638 t = VTI6(n);
639
640 assert(t);
641
642 t->pmtudisc = true;
643 }
644
645 static void gre_init(NetDev *n) {
646 Tunnel *t;
647
648 assert(n);
649
650 if (n->kind == NETDEV_KIND_GRE)
651 t = GRE(n);
652 else
653 t = GRETAP(n);
654
655 assert(t);
656
657 t->pmtudisc = true;
658 }
659
660 static void ip6gre_init(NetDev *n) {
661 Tunnel *t;
662
663 assert(n);
664
665 if (n->kind == NETDEV_KIND_IP6GRE)
666 t = IP6GRE(n);
667 else
668 t = IP6GRETAP(n);
669
670 assert(t);
671
672 t->ttl = DEFAULT_TNL_HOP_LIMIT;
673 }
674
675 static void ip6tnl_init(NetDev *n) {
676 Tunnel *t = IP6TNL(n);
677
678 assert(n);
679 assert(t);
680
681 t->ttl = DEFAULT_TNL_HOP_LIMIT;
682 t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
683 t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
684 t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
685 }
686
687 const NetDevVTable ipip_vtable = {
688 .object_size = sizeof(Tunnel),
689 .init = ipip_init,
690 .sections = "Match\0NetDev\0Tunnel\0",
691 .fill_message_create = netdev_ipip_fill_message_create,
692 .create_type = NETDEV_CREATE_STACKED,
693 .config_verify = netdev_tunnel_verify,
694 };
695
696 const NetDevVTable sit_vtable = {
697 .object_size = sizeof(Tunnel),
698 .init = sit_init,
699 .sections = "Match\0NetDev\0Tunnel\0",
700 .fill_message_create = netdev_sit_fill_message_create,
701 .create_type = NETDEV_CREATE_STACKED,
702 .config_verify = netdev_tunnel_verify,
703 };
704
705 const NetDevVTable vti_vtable = {
706 .object_size = sizeof(Tunnel),
707 .init = vti_init,
708 .sections = "Match\0NetDev\0Tunnel\0",
709 .fill_message_create = netdev_vti_fill_message_create,
710 .create_type = NETDEV_CREATE_STACKED,
711 .config_verify = netdev_tunnel_verify,
712 };
713
714 const NetDevVTable vti6_vtable = {
715 .object_size = sizeof(Tunnel),
716 .init = vti_init,
717 .sections = "Match\0NetDev\0Tunnel\0",
718 .fill_message_create = netdev_vti6_fill_message_create,
719 .create_type = NETDEV_CREATE_STACKED,
720 .config_verify = netdev_tunnel_verify,
721 };
722
723 const NetDevVTable gre_vtable = {
724 .object_size = sizeof(Tunnel),
725 .init = gre_init,
726 .sections = "Match\0NetDev\0Tunnel\0",
727 .fill_message_create = netdev_gre_fill_message_create,
728 .create_type = NETDEV_CREATE_STACKED,
729 .config_verify = netdev_tunnel_verify,
730 };
731
732 const NetDevVTable gretap_vtable = {
733 .object_size = sizeof(Tunnel),
734 .init = gre_init,
735 .sections = "Match\0NetDev\0Tunnel\0",
736 .fill_message_create = netdev_gre_fill_message_create,
737 .create_type = NETDEV_CREATE_STACKED,
738 .config_verify = netdev_tunnel_verify,
739 };
740
741 const NetDevVTable ip6gre_vtable = {
742 .object_size = sizeof(Tunnel),
743 .init = ip6gre_init,
744 .sections = "Match\0NetDev\0Tunnel\0",
745 .fill_message_create = netdev_ip6gre_fill_message_create,
746 .create_type = NETDEV_CREATE_STACKED,
747 .config_verify = netdev_tunnel_verify,
748 };
749
750 const NetDevVTable ip6gretap_vtable = {
751 .object_size = sizeof(Tunnel),
752 .init = ip6gre_init,
753 .sections = "Match\0NetDev\0Tunnel\0",
754 .fill_message_create = netdev_ip6gre_fill_message_create,
755 .create_type = NETDEV_CREATE_STACKED,
756 .config_verify = netdev_tunnel_verify,
757 };
758
759 const NetDevVTable ip6tnl_vtable = {
760 .object_size = sizeof(Tunnel),
761 .init = ip6tnl_init,
762 .sections = "Match\0NetDev\0Tunnel\0",
763 .fill_message_create = netdev_ip6tnl_fill_message_create,
764 .create_type = NETDEV_CREATE_STACKED,
765 .config_verify = netdev_tunnel_verify,
766 };