]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/netdev/tunnel.c
8d6d54d5679dc8bb074cc441fd6c1013d12bbf10
[thirdparty/systemd.git] / src / network / netdev / tunnel.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2014 Susant Sahani
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <arpa/inet.h>
22 #include <net/if.h>
23 #include <linux/ip.h>
24 #include <linux/if_tunnel.h>
25 #include <linux/ip6_tunnel.h>
26
27 #include "sd-netlink.h"
28
29 #include "conf-parser.h"
30 #include "missing.h"
31 #include "networkd-link.h"
32 #include "netdev/tunnel.h"
33 #include "parse-util.h"
34 #include "string-table.h"
35 #include "string-util.h"
36 #include "util.h"
37
38 #define DEFAULT_TNL_HOP_LIMIT 64
39 #define IP6_FLOWINFO_FLOWLABEL htobe32(0x000FFFFF)
40
41 static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
42 [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
43 [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6",
44 [NETDEV_IP6_TNL_MODE_ANYIP6] = "any",
45 };
46
47 DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
48 DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
49
50 static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
51 Tunnel *t = IPIP(netdev);
52 int r;
53
54 assert(netdev);
55 assert(m);
56 assert(t);
57 assert(IN_SET(t->family, AF_INET, AF_UNSPEC));
58
59 if (link) {
60 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
61 if (r < 0)
62 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
63
64 }
65
66 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
67 if (r < 0)
68 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
69
70 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
71 if (r < 0)
72 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
73
74 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
75 if (r < 0)
76 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
77
78 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
79 if (r < 0)
80 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
81
82 return r;
83 }
84
85 static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
86 Tunnel *t = SIT(netdev);
87 int r;
88
89 assert(netdev);
90 assert(m);
91 assert(t);
92 assert(IN_SET(t->family, AF_INET, AF_UNSPEC));
93
94 if (link) {
95 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
96 if (r < 0)
97 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
98
99 }
100
101 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
102 if (r < 0)
103 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
104
105 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
106 if (r < 0)
107 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
108
109 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
110 if (r < 0)
111 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
112
113 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
114 if (r < 0)
115 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
116
117 return r;
118 }
119
120 static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
121 Tunnel *t;
122 int r;
123
124 assert(netdev);
125
126 if (netdev->kind == NETDEV_KIND_GRE)
127 t = GRE(netdev);
128 else
129 t = GRETAP(netdev);
130
131 assert(t);
132 assert(IN_SET(t->family, AF_INET, AF_UNSPEC));
133 assert(m);
134
135 if (link) {
136 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
137 if (r < 0)
138 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
139 }
140
141 r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
142 if (r < 0)
143 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
144
145 r = sd_netlink_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
146 if (r < 0)
147 log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
148
149 r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
150 if (r < 0)
151 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
152
153 r = sd_netlink_message_append_u8(m, IFLA_GRE_TOS, t->tos);
154 if (r < 0)
155 log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m");
156
157 r = sd_netlink_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc);
158 if (r < 0)
159 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m");
160
161 return r;
162 }
163
164 static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
165 Tunnel *t;
166 int r;
167
168 assert(netdev);
169
170 if (netdev->kind == NETDEV_KIND_IP6GRE)
171 t = IP6GRE(netdev);
172 else
173 t = IP6GRETAP(netdev);
174
175 assert(t);
176 assert(t->family == AF_INET6);
177 assert(m);
178
179 if (link) {
180 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
181 if (r < 0)
182 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
183 }
184
185 r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
186 if (r < 0)
187 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
188
189 r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
190 if (r < 0)
191 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
192
193 r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
194 if (r < 0)
195 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
196
197 if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
198 r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel);
199 if (r < 0)
200 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m");
201 }
202
203 r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags);
204 if (r < 0)
205 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m");
206
207 return r;
208 }
209
210 static int netdev_vti_fill_message_key(NetDev *netdev, Link *link, sd_netlink_message *m) {
211 uint32_t ikey, okey;
212 Tunnel *t;
213 int r;
214
215 assert(m);
216
217 if (netdev->kind == NETDEV_KIND_VTI)
218 t = VTI(netdev);
219 else
220 t = VTI6(netdev);
221
222 assert(t);
223
224 if (t->key != 0)
225 ikey = okey = htobe32(t->key);
226 else {
227 ikey = htobe32(t->ikey);
228 okey = htobe32(t->okey);
229 }
230
231 r = sd_netlink_message_append_u32(m, IFLA_VTI_IKEY, ikey);
232 if (r < 0)
233 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_IKEY attribute: %m");
234
235 r = sd_netlink_message_append_u32(m, IFLA_VTI_OKEY, okey);
236 if (r < 0)
237 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_OKEY attribute: %m");
238
239 return 0;
240 }
241
242 static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
243 Tunnel *t = VTI(netdev);
244 int r;
245
246 assert(netdev);
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 };