]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/netdev/tunnel.c
Merge pull request #6866 from sourcejedi/set-linger2
[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(m);
247 assert(t);
248 assert(t->family == AF_INET);
249
250 if (link) {
251 r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
252 if (r < 0)
253 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
254 }
255
256 r = netdev_vti_fill_message_key(netdev, link, m);
257 if (r < 0)
258 return r;
259
260 r = sd_netlink_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in);
261 if (r < 0)
262 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
263
264 r = sd_netlink_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in);
265 if (r < 0)
266 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
267
268 return r;
269 }
270
271 static int netdev_vti6_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
272 Tunnel *t = VTI6(netdev);
273 int r;
274
275 assert(netdev);
276 assert(m);
277 assert(t);
278 assert(t->family == AF_INET6);
279
280 if (link) {
281 r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
282 if (r < 0)
283 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
284 }
285
286 r = netdev_vti_fill_message_key(netdev, link, m);
287 if (r < 0)
288 return r;
289
290 r = sd_netlink_message_append_in6_addr(m, IFLA_VTI_LOCAL, &t->local.in6);
291 if (r < 0)
292 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
293
294 r = sd_netlink_message_append_in6_addr(m, IFLA_VTI_REMOTE, &t->remote.in6);
295 if (r < 0)
296 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
297
298 return r;
299 }
300
301 static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
302 Tunnel *t = IP6TNL(netdev);
303 uint8_t proto;
304 int r;
305
306 assert(netdev);
307 assert(m);
308 assert(t);
309 assert(t->family == AF_INET6);
310
311 if (link) {
312 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
313 if (r < 0)
314 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
315 }
316
317 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
318 if (r < 0)
319 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
320
321 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
322 if (r < 0)
323 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
324
325 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
326 if (r < 0)
327 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
328
329 if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
330 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
331 if (r < 0)
332 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m");
333 }
334
335 if (t->copy_dscp)
336 t->flags |= IP6_TNL_F_RCV_DSCP_COPY;
337
338 if (t->encap_limit != IPV6_DEFAULT_TNL_ENCAP_LIMIT) {
339 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_ENCAP_LIMIT, t->encap_limit);
340 if (r < 0)
341 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_LIMIT attribute: %m");
342 }
343
344 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
345 if (r < 0)
346 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
347
348 switch (t->ip6tnl_mode) {
349 case NETDEV_IP6_TNL_MODE_IP6IP6:
350 proto = IPPROTO_IPV6;
351 break;
352 case NETDEV_IP6_TNL_MODE_IPIP6:
353 proto = IPPROTO_IPIP;
354 break;
355 case NETDEV_IP6_TNL_MODE_ANYIP6:
356 default:
357 proto = 0;
358 break;
359 }
360
361 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
362 if (r < 0)
363 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_MODE attribute: %m");
364
365 return r;
366 }
367
368 static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
369 Tunnel *t = NULL;
370
371 assert(netdev);
372 assert(filename);
373
374 switch (netdev->kind) {
375 case NETDEV_KIND_IPIP:
376 t = IPIP(netdev);
377 break;
378 case NETDEV_KIND_SIT:
379 t = SIT(netdev);
380 break;
381 case NETDEV_KIND_GRE:
382 t = GRE(netdev);
383 break;
384 case NETDEV_KIND_GRETAP:
385 t = GRETAP(netdev);
386 break;
387 case NETDEV_KIND_IP6GRE:
388 t = IP6GRE(netdev);
389 break;
390 case NETDEV_KIND_IP6GRETAP:
391 t = IP6GRETAP(netdev);
392 break;
393 case NETDEV_KIND_VTI:
394 t = VTI(netdev);
395 break;
396 case NETDEV_KIND_VTI6:
397 t = VTI6(netdev);
398 break;
399 case NETDEV_KIND_IP6TNL:
400 t = IP6TNL(netdev);
401 break;
402 default:
403 assert_not_reached("Invalid tunnel kind");
404 }
405
406 assert(t);
407
408 if (!IN_SET(t->family, AF_INET, AF_INET6, AF_UNSPEC)) {
409 log_netdev_error(netdev,
410 "Tunnel with invalid address family configured in %s. Ignoring", filename);
411 return -EINVAL;
412 }
413
414 if (netdev->kind == NETDEV_KIND_VTI &&
415 (t->family != AF_INET || in_addr_is_null(t->family, &t->local))) {
416 log_netdev_error(netdev,
417 "vti tunnel without a local IPv4 address configured in %s. Ignoring", filename);
418 return -EINVAL;
419 }
420
421 if (IN_SET(netdev->kind, NETDEV_KIND_VTI6, NETDEV_KIND_IP6TNL, NETDEV_KIND_IP6GRE) &&
422 (t->family != AF_INET6 || in_addr_is_null(t->family, &t->local))) {
423 log_netdev_error(netdev,
424 "vti6/ip6tnl/ip6gre tunnel without a local IPv6 address configured in %s. Ignoring", filename);
425 return -EINVAL;
426 }
427
428 if (netdev->kind == NETDEV_KIND_IP6TNL &&
429 t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) {
430 log_netdev_error(netdev,
431 "ip6tnl without mode configured in %s. Ignoring", filename);
432 return -EINVAL;
433 }
434
435 return 0;
436 }
437
438 int config_parse_tunnel_address(const char *unit,
439 const char *filename,
440 unsigned line,
441 const char *section,
442 unsigned section_line,
443 const char *lvalue,
444 int ltype,
445 const char *rvalue,
446 void *data,
447 void *userdata) {
448 Tunnel *t = userdata;
449 union in_addr_union *addr = data, buffer;
450 int r, f;
451
452 assert(filename);
453 assert(lvalue);
454 assert(rvalue);
455 assert(data);
456
457 /* This is used to parse addresses on both local and remote ends of the tunnel.
458 * Address families must match.
459 *
460 * "any" is a special value which means that the address is unspecified.
461 */
462
463 if (streq(rvalue, "any")) {
464 *addr = IN_ADDR_NULL;
465
466 /* As a special case, if both the local and remote addresses are
467 * unspecified, also clear the address family.
468 */
469 if (t->family != AF_UNSPEC &&
470 in_addr_is_null(t->family, &t->local) &&
471 in_addr_is_null(t->family, &t->remote))
472 t->family = AF_UNSPEC;
473 return 0;
474 }
475
476 r = in_addr_from_string_auto(rvalue, &f, &buffer);
477 if (r < 0) {
478 log_syntax(unit, LOG_ERR, filename, line, r,
479 "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue);
480 return 0;
481 }
482
483 if (t->family != AF_UNSPEC && t->family != f) {
484 log_syntax(unit, LOG_ERR, filename, line, 0,
485 "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
486 return 0;
487 }
488
489 t->family = f;
490 *addr = buffer;
491 return 0;
492 }
493
494 int config_parse_tunnel_key(const char *unit,
495 const char *filename,
496 unsigned line,
497 const char *section,
498 unsigned section_line,
499 const char *lvalue,
500 int ltype,
501 const char *rvalue,
502 void *data,
503 void *userdata) {
504 union in_addr_union buffer;
505 Tunnel *t = userdata;
506 uint32_t k;
507 int r;
508
509 assert(filename);
510 assert(lvalue);
511 assert(rvalue);
512 assert(data);
513
514 r = in_addr_from_string(AF_INET, rvalue, &buffer);
515 if (r < 0) {
516 r = safe_atou32(rvalue, &k);
517 if (r < 0) {
518 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse tunnel key ignoring assignment: %s", rvalue);
519 return 0;
520 }
521 } else
522 k = be32toh(buffer.in.s_addr);
523
524 if (streq(lvalue, "Key"))
525 t->key = k;
526 else if (streq(lvalue, "InputKey"))
527 t->ikey = k;
528 else
529 t->okey = k;
530
531 return 0;
532 }
533
534 int config_parse_ipv6_flowlabel(const char* unit,
535 const char *filename,
536 unsigned line,
537 const char *section,
538 unsigned section_line,
539 const char *lvalue,
540 int ltype,
541 const char *rvalue,
542 void *data,
543 void *userdata) {
544 IPv6FlowLabel *ipv6_flowlabel = data;
545 Tunnel *t = userdata;
546 int k = 0;
547 int r;
548
549 assert(filename);
550 assert(lvalue);
551 assert(rvalue);
552 assert(ipv6_flowlabel);
553
554 if (streq(rvalue, "inherit")) {
555 *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
556 t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
557 } else {
558 r = config_parse_int(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);
559 if (r < 0)
560 return r;
561
562 if (k > 0xFFFFF)
563 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
564 else {
565 *ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL;
566 t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
567 }
568 }
569
570 return 0;
571 }
572
573 int config_parse_encap_limit(const char* unit,
574 const char *filename,
575 unsigned line,
576 const char *section,
577 unsigned section_line,
578 const char *lvalue,
579 int ltype,
580 const char *rvalue,
581 void *data,
582 void *userdata) {
583 Tunnel *t = userdata;
584 int k = 0;
585 int r;
586
587 assert(filename);
588 assert(lvalue);
589 assert(rvalue);
590
591 if (streq(rvalue, "none"))
592 t->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT;
593 else {
594 r = safe_atoi(rvalue, &k);
595 if (r < 0) {
596 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Tunnel Encapsulation Limit option, ignoring: %s", rvalue);
597 return 0;
598 }
599
600 if (k > 255 || k < 0)
601 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid Tunnel Encapsulation value, ignoring: %d", k);
602 else {
603 t->encap_limit = k;
604 t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
605 }
606 }
607
608 return 0;
609 }
610
611 static void ipip_init(NetDev *n) {
612 Tunnel *t = IPIP(n);
613
614 assert(n);
615 assert(t);
616
617 t->pmtudisc = true;
618 }
619
620 static void sit_init(NetDev *n) {
621 Tunnel *t = SIT(n);
622
623 assert(n);
624 assert(t);
625
626 t->pmtudisc = true;
627 }
628
629 static void vti_init(NetDev *n) {
630 Tunnel *t;
631
632 assert(n);
633
634 if (n->kind == NETDEV_KIND_VTI)
635 t = VTI(n);
636 else
637 t = VTI6(n);
638
639 assert(t);
640
641 t->pmtudisc = true;
642 }
643
644 static void gre_init(NetDev *n) {
645 Tunnel *t;
646
647 assert(n);
648
649 if (n->kind == NETDEV_KIND_GRE)
650 t = GRE(n);
651 else
652 t = GRETAP(n);
653
654 assert(t);
655
656 t->pmtudisc = true;
657 }
658
659 static void ip6gre_init(NetDev *n) {
660 Tunnel *t;
661
662 assert(n);
663
664 if (n->kind == NETDEV_KIND_IP6GRE)
665 t = IP6GRE(n);
666 else
667 t = IP6GRETAP(n);
668
669 assert(t);
670
671 t->ttl = DEFAULT_TNL_HOP_LIMIT;
672 }
673
674 static void ip6tnl_init(NetDev *n) {
675 Tunnel *t = IP6TNL(n);
676
677 assert(n);
678 assert(t);
679
680 t->ttl = DEFAULT_TNL_HOP_LIMIT;
681 t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
682 t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
683 t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
684 }
685
686 const NetDevVTable ipip_vtable = {
687 .object_size = sizeof(Tunnel),
688 .init = ipip_init,
689 .sections = "Match\0NetDev\0Tunnel\0",
690 .fill_message_create = netdev_ipip_fill_message_create,
691 .create_type = NETDEV_CREATE_STACKED,
692 .config_verify = netdev_tunnel_verify,
693 };
694
695 const NetDevVTable sit_vtable = {
696 .object_size = sizeof(Tunnel),
697 .init = sit_init,
698 .sections = "Match\0NetDev\0Tunnel\0",
699 .fill_message_create = netdev_sit_fill_message_create,
700 .create_type = NETDEV_CREATE_STACKED,
701 .config_verify = netdev_tunnel_verify,
702 };
703
704 const NetDevVTable vti_vtable = {
705 .object_size = sizeof(Tunnel),
706 .init = vti_init,
707 .sections = "Match\0NetDev\0Tunnel\0",
708 .fill_message_create = netdev_vti_fill_message_create,
709 .create_type = NETDEV_CREATE_STACKED,
710 .config_verify = netdev_tunnel_verify,
711 };
712
713 const NetDevVTable vti6_vtable = {
714 .object_size = sizeof(Tunnel),
715 .init = vti_init,
716 .sections = "Match\0NetDev\0Tunnel\0",
717 .fill_message_create = netdev_vti6_fill_message_create,
718 .create_type = NETDEV_CREATE_STACKED,
719 .config_verify = netdev_tunnel_verify,
720 };
721
722 const NetDevVTable gre_vtable = {
723 .object_size = sizeof(Tunnel),
724 .init = gre_init,
725 .sections = "Match\0NetDev\0Tunnel\0",
726 .fill_message_create = netdev_gre_fill_message_create,
727 .create_type = NETDEV_CREATE_STACKED,
728 .config_verify = netdev_tunnel_verify,
729 };
730
731 const NetDevVTable gretap_vtable = {
732 .object_size = sizeof(Tunnel),
733 .init = gre_init,
734 .sections = "Match\0NetDev\0Tunnel\0",
735 .fill_message_create = netdev_gre_fill_message_create,
736 .create_type = NETDEV_CREATE_STACKED,
737 .config_verify = netdev_tunnel_verify,
738 };
739
740 const NetDevVTable ip6gre_vtable = {
741 .object_size = sizeof(Tunnel),
742 .init = ip6gre_init,
743 .sections = "Match\0NetDev\0Tunnel\0",
744 .fill_message_create = netdev_ip6gre_fill_message_create,
745 .create_type = NETDEV_CREATE_STACKED,
746 .config_verify = netdev_tunnel_verify,
747 };
748
749 const NetDevVTable ip6gretap_vtable = {
750 .object_size = sizeof(Tunnel),
751 .init = ip6gre_init,
752 .sections = "Match\0NetDev\0Tunnel\0",
753 .fill_message_create = netdev_ip6gre_fill_message_create,
754 .create_type = NETDEV_CREATE_STACKED,
755 .config_verify = netdev_tunnel_verify,
756 };
757
758 const NetDevVTable ip6tnl_vtable = {
759 .object_size = sizeof(Tunnel),
760 .init = ip6tnl_init,
761 .sections = "Match\0NetDev\0Tunnel\0",
762 .fill_message_create = netdev_ip6tnl_fill_message_create,
763 .create_type = NETDEV_CREATE_STACKED,
764 .config_verify = netdev_tunnel_verify,
765 };