Line data Source code
1 : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2 :
3 : /***
4 : This file is part of systemd.
5 :
6 : Copyright 2014 Susant Sahani
7 :
8 : systemd is free software; you can redistribute it and/or modify it
9 : under the terms of the GNU Lesser General Public License as published by
10 : the Free Software Foundation; either version 2.1 of the License, or
11 : (at your option) any later version.
12 :
13 : systemd is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : Lesser General Public License for more details.
17 :
18 : You should have received a copy of the GNU Lesser General Public License
19 : along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 : ***/
21 :
22 : #include <arpa/inet.h>
23 : #include <net/if.h>
24 : #include <linux/ip.h>
25 : #include <linux/if_tunnel.h>
26 : #include <linux/ip6_tunnel.h>
27 :
28 : #include "sd-netlink.h"
29 : #include "networkd-netdev-tunnel.h"
30 : #include "networkd-link.h"
31 : #include "util.h"
32 : #include "missing.h"
33 : #include "conf-parser.h"
34 :
35 : #define DEFAULT_TNL_HOP_LIMIT 64
36 : #define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF)
37 :
38 : static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
39 : [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
40 : [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6",
41 : [NETDEV_IP6_TNL_MODE_ANYIP6] = "any",
42 : };
43 :
44 0 : DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
45 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
46 :
47 0 : static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
48 0 : Tunnel *t = IPIP(netdev);
49 : int r;
50 :
51 0 : assert(netdev);
52 0 : assert(link);
53 0 : assert(m);
54 0 : assert(t);
55 0 : assert(t->family == AF_INET);
56 :
57 0 : r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
58 0 : if (r < 0)
59 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
60 :
61 0 : r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
62 0 : if (r < 0)
63 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
64 :
65 0 : r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
66 0 : if (r < 0)
67 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
68 :
69 0 : r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
70 0 : if (r < 0)
71 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
72 :
73 0 : r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
74 0 : if (r < 0)
75 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
76 :
77 0 : return r;
78 : }
79 :
80 0 : static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
81 0 : Tunnel *t = SIT(netdev);
82 : int r;
83 :
84 0 : assert(netdev);
85 0 : assert(link);
86 0 : assert(m);
87 0 : assert(t);
88 0 : assert(t->family == AF_INET);
89 :
90 0 : r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
91 0 : if (r < 0)
92 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
93 :
94 0 : r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
95 0 : if (r < 0)
96 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
97 :
98 0 : r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
99 0 : if (r < 0)
100 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
101 :
102 0 : r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
103 0 : if (r < 0)
104 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
105 :
106 0 : r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
107 0 : if (r < 0)
108 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
109 :
110 0 : return r;
111 : }
112 :
113 0 : static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
114 : Tunnel *t;
115 : int r;
116 :
117 0 : assert(netdev);
118 :
119 0 : if (netdev->kind == NETDEV_KIND_GRE)
120 0 : t = GRE(netdev);
121 : else
122 0 : t = GRETAP(netdev);
123 :
124 0 : assert(t);
125 0 : assert(t->family == AF_INET);
126 0 : assert(link);
127 0 : assert(m);
128 :
129 0 : r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
130 0 : if (r < 0)
131 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
132 :
133 0 : r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
134 0 : if (r < 0)
135 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
136 :
137 0 : r = sd_netlink_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
138 0 : if (r < 0)
139 0 : log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
140 :
141 0 : r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
142 0 : if (r < 0)
143 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
144 :
145 0 : r = sd_netlink_message_append_u8(m, IFLA_GRE_TOS, t->tos);
146 0 : if (r < 0)
147 0 : log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m");
148 :
149 0 : r = sd_netlink_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc);
150 0 : if (r < 0)
151 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m");
152 :
153 0 : return r;
154 : }
155 :
156 0 : static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
157 : Tunnel *t;
158 : int r;
159 :
160 0 : assert(netdev);
161 :
162 0 : if (netdev->kind == NETDEV_KIND_IP6GRE)
163 0 : t = IP6GRE(netdev);
164 : else
165 0 : t = IP6GRETAP(netdev);
166 :
167 0 : assert(t);
168 0 : assert(t->family == AF_INET6);
169 0 : assert(link);
170 0 : assert(m);
171 :
172 0 : r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
173 0 : if (r < 0)
174 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
175 :
176 0 : r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
177 0 : if (r < 0)
178 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
179 :
180 0 : r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
181 0 : if (r < 0)
182 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
183 :
184 0 : r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
185 0 : if (r < 0)
186 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
187 :
188 0 : if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
189 0 : r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel);
190 0 : if (r < 0)
191 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m");
192 : }
193 :
194 0 : r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags);
195 0 : if (r < 0)
196 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m");
197 :
198 0 : return r;
199 : }
200 :
201 0 : static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
202 0 : Tunnel *t = VTI(netdev);
203 : int r;
204 :
205 0 : assert(netdev);
206 0 : assert(link);
207 0 : assert(m);
208 0 : assert(t);
209 0 : assert(t->family == AF_INET);
210 :
211 0 : r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
212 0 : if (r < 0)
213 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
214 :
215 0 : r = sd_netlink_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in);
216 0 : if (r < 0)
217 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
218 :
219 0 : r = sd_netlink_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in);
220 0 : if (r < 0)
221 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
222 :
223 0 : return r;
224 : }
225 :
226 0 : static int netdev_vti6_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
227 0 : Tunnel *t = VTI6(netdev);
228 : int r;
229 :
230 0 : assert(netdev);
231 0 : assert(link);
232 0 : assert(m);
233 0 : assert(t);
234 0 : assert(t->family == AF_INET6);
235 :
236 0 : r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
237 0 : if (r < 0)
238 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
239 :
240 0 : r = sd_netlink_message_append_in6_addr(m, IFLA_VTI_LOCAL, &t->local.in6);
241 0 : if (r < 0)
242 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
243 :
244 0 : r = sd_netlink_message_append_in6_addr(m, IFLA_VTI_REMOTE, &t->remote.in6);
245 0 : if (r < 0)
246 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
247 :
248 0 : return r;
249 : }
250 :
251 0 : static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
252 0 : Tunnel *t = IP6TNL(netdev);
253 : uint8_t proto;
254 : int r;
255 :
256 0 : assert(netdev);
257 0 : assert(link);
258 0 : assert(m);
259 0 : assert(t);
260 0 : assert(t->family == AF_INET6);
261 :
262 0 : r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
263 0 : if (r < 0)
264 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
265 :
266 0 : r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
267 0 : if (r < 0)
268 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
269 :
270 0 : r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
271 0 : if (r < 0)
272 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
273 :
274 0 : r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
275 0 : if (r < 0)
276 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
277 :
278 0 : if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
279 0 : r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
280 0 : if (r < 0)
281 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m");
282 : }
283 :
284 0 : if (t->copy_dscp)
285 0 : t->flags |= IP6_TNL_F_RCV_DSCP_COPY;
286 :
287 0 : r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
288 0 : if (r < 0)
289 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
290 :
291 0 : switch (t->ip6tnl_mode) {
292 : case NETDEV_IP6_TNL_MODE_IP6IP6:
293 0 : proto = IPPROTO_IPV6;
294 0 : break;
295 : case NETDEV_IP6_TNL_MODE_IPIP6:
296 0 : proto = IPPROTO_IPIP;
297 0 : break;
298 : case NETDEV_IP6_TNL_MODE_ANYIP6:
299 : default:
300 0 : proto = 0;
301 0 : break;
302 : }
303 :
304 0 : r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
305 0 : if (r < 0)
306 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_MODE attribute: %m");
307 :
308 0 : return r;
309 : }
310 :
311 0 : static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
312 0 : Tunnel *t = NULL;
313 :
314 0 : assert(netdev);
315 0 : assert(filename);
316 :
317 0 : switch (netdev->kind) {
318 : case NETDEV_KIND_IPIP:
319 0 : t = IPIP(netdev);
320 0 : break;
321 : case NETDEV_KIND_SIT:
322 0 : t = SIT(netdev);
323 0 : break;
324 : case NETDEV_KIND_GRE:
325 0 : t = GRE(netdev);
326 0 : break;
327 : case NETDEV_KIND_GRETAP:
328 0 : t = GRETAP(netdev);
329 0 : break;
330 : case NETDEV_KIND_IP6GRE:
331 0 : t = IP6GRE(netdev);
332 0 : break;
333 : case NETDEV_KIND_IP6GRETAP:
334 0 : t = IP6GRETAP(netdev);
335 0 : break;
336 : case NETDEV_KIND_VTI:
337 0 : t = VTI(netdev);
338 0 : break;
339 : case NETDEV_KIND_VTI6:
340 0 : t = VTI6(netdev);
341 0 : break;
342 : case NETDEV_KIND_IP6TNL:
343 0 : t = IP6TNL(netdev);
344 0 : break;
345 : default:
346 0 : assert_not_reached("Invalid tunnel kind");
347 : }
348 :
349 0 : assert(t);
350 :
351 0 : if (t->remote.in.s_addr == INADDR_ANY) {
352 0 : log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
353 0 : return -EINVAL;
354 : }
355 :
356 0 : if (t->family != AF_INET && t->family != AF_INET6) {
357 0 : log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
358 0 : return -EINVAL;
359 : }
360 :
361 0 : if (netdev->kind == NETDEV_KIND_IP6TNL) {
362 0 : if (t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) {
363 0 : log_warning("IP6 Tunnel without mode configured in %s. Ignoring", filename);
364 0 : return -EINVAL;
365 : }
366 : }
367 :
368 0 : return 0;
369 : }
370 :
371 0 : int config_parse_tunnel_address(const char *unit,
372 : const char *filename,
373 : unsigned line,
374 : const char *section,
375 : unsigned section_line,
376 : const char *lvalue,
377 : int ltype,
378 : const char *rvalue,
379 : void *data,
380 : void *userdata) {
381 0 : Tunnel *t = userdata;
382 0 : union in_addr_union *addr = data, buffer;
383 : int r, f;
384 :
385 0 : assert(filename);
386 0 : assert(lvalue);
387 0 : assert(rvalue);
388 0 : assert(data);
389 :
390 0 : r = in_addr_from_string_auto(rvalue, &f, &buffer);
391 0 : if (r < 0) {
392 0 : log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel address is invalid, ignoring assignment: %s", rvalue);
393 0 : return 0;
394 : }
395 :
396 0 : if (t->family != AF_UNSPEC && t->family != f) {
397 0 : log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
398 0 : return 0;
399 : }
400 :
401 0 : t->family = f;
402 0 : *addr = buffer;
403 :
404 0 : return 0;
405 : }
406 :
407 : static const char* const ipv6_flowlabel_table[_NETDEV_IPV6_FLOWLABEL_MAX] = {
408 : [NETDEV_IPV6_FLOWLABEL_INHERIT] = "inherit",
409 : };
410 :
411 0 : DEFINE_STRING_TABLE_LOOKUP(ipv6_flowlabel, IPv6FlowLabel);
412 :
413 0 : int config_parse_ipv6_flowlabel(const char* unit,
414 : const char *filename,
415 : unsigned line,
416 : const char *section,
417 : unsigned section_line,
418 : const char *lvalue,
419 : int ltype,
420 : const char *rvalue,
421 : void *data,
422 : void *userdata) {
423 0 : IPv6FlowLabel *ipv6_flowlabel = data;
424 0 : Tunnel *t = userdata;
425 : IPv6FlowLabel s;
426 0 : int k = 0;
427 : int r;
428 :
429 0 : assert(filename);
430 0 : assert(lvalue);
431 0 : assert(rvalue);
432 0 : assert(ipv6_flowlabel);
433 :
434 0 : s = ipv6_flowlabel_from_string(rvalue);
435 0 : if (s != _NETDEV_IPV6_FLOWLABEL_INVALID) {
436 0 : *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
437 0 : t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
438 : } else {
439 0 : r = config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);
440 0 : if (r >= 0) {
441 0 : if (k > 0xFFFFF)
442 0 : log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
443 : else {
444 0 : *ipv6_flowlabel = htonl(k) & IP6_FLOWINFO_FLOWLABEL;
445 0 : t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
446 : }
447 : }
448 : }
449 :
450 0 : return 0;
451 : }
452 :
453 0 : static void ipip_init(NetDev *n) {
454 0 : Tunnel *t = IPIP(n);
455 :
456 0 : assert(n);
457 0 : assert(t);
458 :
459 0 : t->pmtudisc = true;
460 0 : }
461 :
462 0 : static void sit_init(NetDev *n) {
463 0 : Tunnel *t = SIT(n);
464 :
465 0 : assert(n);
466 0 : assert(t);
467 :
468 0 : t->pmtudisc = true;
469 0 : }
470 :
471 0 : static void vti_init(NetDev *n) {
472 : Tunnel *t;
473 :
474 0 : assert(n);
475 :
476 0 : if (n->kind == NETDEV_KIND_VTI)
477 0 : t = VTI(n);
478 : else
479 0 : t = VTI6(n);
480 :
481 0 : assert(t);
482 :
483 0 : t->pmtudisc = true;
484 0 : }
485 :
486 0 : static void gre_init(NetDev *n) {
487 : Tunnel *t;
488 :
489 0 : assert(n);
490 :
491 0 : if (n->kind == NETDEV_KIND_GRE)
492 0 : t = GRE(n);
493 : else
494 0 : t = GRETAP(n);
495 :
496 0 : assert(t);
497 :
498 0 : t->pmtudisc = true;
499 0 : }
500 :
501 0 : static void ip6gre_init(NetDev *n) {
502 : Tunnel *t;
503 :
504 0 : assert(n);
505 :
506 0 : if (n->kind == NETDEV_KIND_IP6GRE)
507 0 : t = IP6GRE(n);
508 : else
509 0 : t = IP6GRETAP(n);
510 :
511 0 : assert(t);
512 :
513 0 : t->ttl = DEFAULT_TNL_HOP_LIMIT;
514 0 : }
515 :
516 0 : static void ip6tnl_init(NetDev *n) {
517 0 : Tunnel *t = IP6TNL(n);
518 :
519 0 : assert(n);
520 0 : assert(t);
521 :
522 0 : t->ttl = DEFAULT_TNL_HOP_LIMIT;
523 0 : t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
524 0 : t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
525 0 : t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
526 0 : }
527 :
528 : const NetDevVTable ipip_vtable = {
529 : .object_size = sizeof(Tunnel),
530 : .init = ipip_init,
531 : .sections = "Match\0NetDev\0Tunnel\0",
532 : .fill_message_create = netdev_ipip_fill_message_create,
533 : .create_type = NETDEV_CREATE_STACKED,
534 : .config_verify = netdev_tunnel_verify,
535 : };
536 :
537 : const NetDevVTable sit_vtable = {
538 : .object_size = sizeof(Tunnel),
539 : .init = sit_init,
540 : .sections = "Match\0NetDev\0Tunnel\0",
541 : .fill_message_create = netdev_sit_fill_message_create,
542 : .create_type = NETDEV_CREATE_STACKED,
543 : .config_verify = netdev_tunnel_verify,
544 : };
545 :
546 : const NetDevVTable vti_vtable = {
547 : .object_size = sizeof(Tunnel),
548 : .init = vti_init,
549 : .sections = "Match\0NetDev\0Tunnel\0",
550 : .fill_message_create = netdev_vti_fill_message_create,
551 : .create_type = NETDEV_CREATE_STACKED,
552 : .config_verify = netdev_tunnel_verify,
553 : };
554 :
555 : const NetDevVTable vti6_vtable = {
556 : .object_size = sizeof(Tunnel),
557 : .init = vti_init,
558 : .sections = "Match\0NetDev\0Tunnel\0",
559 : .fill_message_create = netdev_vti6_fill_message_create,
560 : .create_type = NETDEV_CREATE_STACKED,
561 : .config_verify = netdev_tunnel_verify,
562 : };
563 :
564 : const NetDevVTable gre_vtable = {
565 : .object_size = sizeof(Tunnel),
566 : .init = gre_init,
567 : .sections = "Match\0NetDev\0Tunnel\0",
568 : .fill_message_create = netdev_gre_fill_message_create,
569 : .create_type = NETDEV_CREATE_STACKED,
570 : .config_verify = netdev_tunnel_verify,
571 : };
572 :
573 : const NetDevVTable gretap_vtable = {
574 : .object_size = sizeof(Tunnel),
575 : .init = gre_init,
576 : .sections = "Match\0NetDev\0Tunnel\0",
577 : .fill_message_create = netdev_gre_fill_message_create,
578 : .create_type = NETDEV_CREATE_STACKED,
579 : .config_verify = netdev_tunnel_verify,
580 : };
581 :
582 : const NetDevVTable ip6gre_vtable = {
583 : .object_size = sizeof(Tunnel),
584 : .init = ip6gre_init,
585 : .sections = "Match\0NetDev\0Tunnel\0",
586 : .fill_message_create = netdev_ip6gre_fill_message_create,
587 : .create_type = NETDEV_CREATE_STACKED,
588 : .config_verify = netdev_tunnel_verify,
589 : };
590 :
591 : const NetDevVTable ip6gretap_vtable = {
592 : .object_size = sizeof(Tunnel),
593 : .init = ip6gre_init,
594 : .sections = "Match\0NetDev\0Tunnel\0",
595 : .fill_message_create = netdev_ip6gre_fill_message_create,
596 : .create_type = NETDEV_CREATE_STACKED,
597 : .config_verify = netdev_tunnel_verify,
598 : };
599 :
600 : const NetDevVTable ip6tnl_vtable = {
601 : .object_size = sizeof(Tunnel),
602 : .init = ip6tnl_init,
603 : .sections = "Match\0NetDev\0Tunnel\0",
604 : .fill_message_create = netdev_ip6tnl_fill_message_create,
605 : .create_type = NETDEV_CREATE_STACKED,
606 : .config_verify = netdev_tunnel_verify,
607 : };
|