1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Susant Sahani
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.
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.
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/>.
22 #include <arpa/inet.h>
25 #include <linux/if_tunnel.h>
26 #include <linux/ip6_tunnel.h>
29 #include "networkd-netdev-tunnel.h"
30 #include "networkd-link.h"
33 #include "conf-parser.h"
35 #define DEFAULT_TNL_HOP_LIMIT 64
37 static const char* const ip6tnl_mode_table
[_NETDEV_IP6_TNL_MODE_MAX
] = {
38 [NETDEV_IP6_TNL_MODE_IP6IP6
] = "ip6ip6",
39 [NETDEV_IP6_TNL_MODE_IPIP6
] = "ipip6",
40 [NETDEV_IP6_TNL_MODE_ANYIP6
] = "any",
43 DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode
, Ip6TnlMode
);
44 DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode
, ip6tnl_mode
, Ip6TnlMode
, "Failed to parse ip6 tunnel Mode");
46 static int netdev_ipip_fill_message_create(NetDev
*netdev
, Link
*link
, sd_rtnl_message
*m
) {
47 Tunnel
*t
= IPIP(netdev
);
54 assert(t
->family
== AF_INET
);
56 r
= sd_rtnl_message_append_u32(m
, IFLA_IPTUN_LINK
, link
->ifindex
);
58 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LINK attribute: %m");
60 r
= sd_rtnl_message_append_in_addr(m
, IFLA_IPTUN_LOCAL
, &t
->local
.in
);
62 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
64 r
= sd_rtnl_message_append_in_addr(m
, IFLA_IPTUN_REMOTE
, &t
->remote
.in
);
66 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
68 r
= sd_rtnl_message_append_u8(m
, IFLA_IPTUN_TTL
, t
->ttl
);
70 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_TTL attribute: %m");
72 r
= sd_rtnl_message_append_u8(m
, IFLA_IPTUN_PMTUDISC
, t
->pmtudisc
);
74 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
79 static int netdev_sit_fill_message_create(NetDev
*netdev
, Link
*link
, sd_rtnl_message
*m
) {
80 Tunnel
*t
= SIT(netdev
);
87 assert(t
->family
== AF_INET
);
89 r
= sd_rtnl_message_append_u32(m
, IFLA_IPTUN_LINK
, link
->ifindex
);
91 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LINK attribute: %m");
93 r
= sd_rtnl_message_append_in_addr(m
, IFLA_IPTUN_LOCAL
, &t
->local
.in
);
95 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
97 r
= sd_rtnl_message_append_in_addr(m
, IFLA_IPTUN_REMOTE
, &t
->remote
.in
);
99 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
101 r
= sd_rtnl_message_append_u8(m
, IFLA_IPTUN_TTL
, t
->ttl
);
103 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_TTL attribute: %m");
105 r
= sd_rtnl_message_append_u8(m
, IFLA_IPTUN_PMTUDISC
, t
->pmtudisc
);
107 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
112 static int netdev_gre_fill_message_create(NetDev
*netdev
, Link
*link
, sd_rtnl_message
*m
) {
118 if (netdev
->kind
== NETDEV_KIND_GRE
)
124 assert(t
->family
== AF_INET
);
128 r
= sd_rtnl_message_append_u32(m
, IFLA_GRE_LINK
, link
->ifindex
);
130 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_LINK attribute: %m");
132 r
= sd_rtnl_message_append_in_addr(m
, IFLA_GRE_LOCAL
, &t
->local
.in
);
134 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_LOCAL attribute: %m");
136 r
= sd_rtnl_message_append_in_addr(m
, IFLA_GRE_REMOTE
, &t
->remote
.in
);
138 log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_REMOTE attribute: %m");
140 r
= sd_rtnl_message_append_u8(m
, IFLA_GRE_TTL
, t
->ttl
);
142 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_TTL attribute: %m");
144 r
= sd_rtnl_message_append_u8(m
, IFLA_GRE_TOS
, t
->tos
);
146 log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_TOS attribute: %m");
148 r
= sd_rtnl_message_append_u8(m
, IFLA_GRE_PMTUDISC
, t
->pmtudisc
);
150 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_PMTUDISC attribute: %m");
155 static int netdev_ip6gre_fill_message_create(NetDev
*netdev
, Link
*link
, sd_rtnl_message
*m
) {
161 if (netdev
->kind
== NETDEV_KIND_IP6GRE
)
164 t
= IP6GRETAP(netdev
);
167 assert(t
->family
== AF_INET6
);
171 r
= sd_rtnl_message_append_u32(m
, IFLA_GRE_LINK
, link
->ifindex
);
173 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_LINK attribute: %m");
175 r
= sd_rtnl_message_append_in6_addr(m
, IFLA_GRE_LOCAL
, &t
->local
.in6
);
177 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_LOCAL attribute: %m");
179 r
= sd_rtnl_message_append_in6_addr(m
, IFLA_GRE_REMOTE
, &t
->remote
.in6
);
181 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_REMOTE attribute: %m");
183 r
= sd_rtnl_message_append_u8(m
, IFLA_GRE_TTL
, t
->ttl
);
185 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GRE_TTL attribute: %m");
190 static int netdev_vti_fill_message_create(NetDev
*netdev
, Link
*link
, sd_rtnl_message
*m
) {
191 Tunnel
*t
= VTI(netdev
);
198 assert(t
->family
== AF_INET
);
200 r
= sd_rtnl_message_append_u32(m
, IFLA_VTI_LINK
, link
->ifindex
);
202 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LINK attribute: %m");
204 r
= sd_rtnl_message_append_in_addr(m
, IFLA_VTI_LOCAL
, &t
->local
.in
);
206 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
208 r
= sd_rtnl_message_append_in_addr(m
, IFLA_VTI_REMOTE
, &t
->remote
.in
);
210 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
215 static int netdev_vti6_fill_message_create(NetDev
*netdev
, Link
*link
, sd_rtnl_message
*m
) {
216 Tunnel
*t
= VTI6(netdev
);
223 assert(t
->family
== AF_INET6
);
225 r
= sd_rtnl_message_append_u32(m
, IFLA_VTI_LINK
, link
->ifindex
);
227 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LINK attribute: %m");
229 r
= sd_rtnl_message_append_in6_addr(m
, IFLA_VTI_LOCAL
, &t
->local
.in6
);
231 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
233 r
= sd_rtnl_message_append_in6_addr(m
, IFLA_VTI_REMOTE
, &t
->remote
.in6
);
235 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
240 static int netdev_ip6tnl_fill_message_create(NetDev
*netdev
, Link
*link
, sd_rtnl_message
*m
) {
241 Tunnel
*t
= IP6TNL(netdev
);
249 assert(t
->family
== AF_INET6
);
251 r
= sd_rtnl_message_append_u32(m
, IFLA_IPTUN_LINK
, link
->ifindex
);
253 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LINK attribute: %m");
255 r
= sd_rtnl_message_append_in6_addr(m
, IFLA_IPTUN_LOCAL
, &t
->local
.in6
);
257 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
259 r
= sd_rtnl_message_append_in6_addr(m
, IFLA_IPTUN_REMOTE
, &t
->remote
.in6
);
261 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
263 r
= sd_rtnl_message_append_u8(m
, IFLA_IPTUN_TTL
, t
->ttl
);
265 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_TTL attribute: %m");
267 switch (t
->ip6tnl_mode
) {
268 case NETDEV_IP6_TNL_MODE_IP6IP6
:
269 proto
= IPPROTO_IPV6
;
271 case NETDEV_IP6_TNL_MODE_IPIP6
:
272 proto
= IPPROTO_IPIP
;
274 case NETDEV_IP6_TNL_MODE_ANYIP6
:
280 r
= sd_rtnl_message_append_u8(m
, IFLA_IPTUN_PROTO
, proto
);
282 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IPTUN_MODE attribute: %m");
287 static int netdev_tunnel_verify(NetDev
*netdev
, const char *filename
) {
293 switch (netdev
->kind
) {
294 case NETDEV_KIND_IPIP
:
297 case NETDEV_KIND_SIT
:
300 case NETDEV_KIND_GRE
:
303 case NETDEV_KIND_GRETAP
:
306 case NETDEV_KIND_IP6GRE
:
309 case NETDEV_KIND_IP6GRETAP
:
310 t
= IP6GRETAP(netdev
);
312 case NETDEV_KIND_VTI
:
315 case NETDEV_KIND_VTI6
:
318 case NETDEV_KIND_IP6TNL
:
322 assert_not_reached("Invalid tunnel kind");
327 if (t
->remote
.in
.s_addr
== INADDR_ANY
) {
328 log_warning("Tunnel without remote address configured in %s. Ignoring", filename
);
332 if (t
->family
!= AF_INET
&& t
->family
!= AF_INET6
) {
333 log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename
);
337 if (netdev
->kind
== NETDEV_KIND_IP6TNL
) {
338 if (t
->ip6tnl_mode
== _NETDEV_IP6_TNL_MODE_INVALID
) {
339 log_warning("IP6 Tunnel without mode configured in %s. Ignoring", filename
);
347 int config_parse_tunnel_address(const char *unit
,
348 const char *filename
,
351 unsigned section_line
,
357 Tunnel
*t
= userdata
;
358 union in_addr_union
*addr
= data
, buffer
;
366 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
368 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
, "Tunnel address is invalid, ignoring assignment: %s", rvalue
);
372 if (t
->family
!= AF_UNSPEC
&& t
->family
!= f
) {
373 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue
);
383 static void ipip_init(NetDev
*n
) {
392 static void sit_init(NetDev
*n
) {
401 static void vti_init(NetDev
*n
) {
406 if (n
->kind
== NETDEV_KIND_VTI
)
416 static void gre_init(NetDev
*n
) {
421 if (n
->kind
== NETDEV_KIND_GRE
)
431 static void ip6gre_init(NetDev
*n
) {
436 if (n
->kind
== NETDEV_KIND_IP6GRE
)
443 t
->ttl
= DEFAULT_TNL_HOP_LIMIT
;
446 static void ip6tnl_init(NetDev
*n
) {
447 Tunnel
*t
= IP6TNL(n
);
452 t
->ttl
= DEFAULT_TNL_HOP_LIMIT
;
453 t
->encap_limit
= IPV6_DEFAULT_TNL_ENCAP_LIMIT
;
454 t
->ip6tnl_mode
= _NETDEV_IP6_TNL_MODE_INVALID
;
457 const NetDevVTable ipip_vtable
= {
458 .object_size
= sizeof(Tunnel
),
460 .sections
= "Match\0NetDev\0Tunnel\0",
461 .fill_message_create
= netdev_ipip_fill_message_create
,
462 .create_type
= NETDEV_CREATE_STACKED
,
463 .config_verify
= netdev_tunnel_verify
,
466 const NetDevVTable sit_vtable
= {
467 .object_size
= sizeof(Tunnel
),
469 .sections
= "Match\0NetDev\0Tunnel\0",
470 .fill_message_create
= netdev_sit_fill_message_create
,
471 .create_type
= NETDEV_CREATE_STACKED
,
472 .config_verify
= netdev_tunnel_verify
,
475 const NetDevVTable vti_vtable
= {
476 .object_size
= sizeof(Tunnel
),
478 .sections
= "Match\0NetDev\0Tunnel\0",
479 .fill_message_create
= netdev_vti_fill_message_create
,
480 .create_type
= NETDEV_CREATE_STACKED
,
481 .config_verify
= netdev_tunnel_verify
,
484 const NetDevVTable vti6_vtable
= {
485 .object_size
= sizeof(Tunnel
),
487 .sections
= "Match\0NetDev\0Tunnel\0",
488 .fill_message_create
= netdev_vti6_fill_message_create
,
489 .create_type
= NETDEV_CREATE_STACKED
,
490 .config_verify
= netdev_tunnel_verify
,
493 const NetDevVTable gre_vtable
= {
494 .object_size
= sizeof(Tunnel
),
496 .sections
= "Match\0NetDev\0Tunnel\0",
497 .fill_message_create
= netdev_gre_fill_message_create
,
498 .create_type
= NETDEV_CREATE_STACKED
,
499 .config_verify
= netdev_tunnel_verify
,
502 const NetDevVTable gretap_vtable
= {
503 .object_size
= sizeof(Tunnel
),
505 .sections
= "Match\0NetDev\0Tunnel\0",
506 .fill_message_create
= netdev_gre_fill_message_create
,
507 .create_type
= NETDEV_CREATE_STACKED
,
508 .config_verify
= netdev_tunnel_verify
,
511 const NetDevVTable ip6gre_vtable
= {
512 .object_size
= sizeof(Tunnel
),
514 .sections
= "Match\0NetDev\0Tunnel\0",
515 .fill_message_create
= netdev_ip6gre_fill_message_create
,
516 .create_type
= NETDEV_CREATE_STACKED
,
517 .config_verify
= netdev_tunnel_verify
,
520 const NetDevVTable ip6gretap_vtable
= {
521 .object_size
= sizeof(Tunnel
),
523 .sections
= "Match\0NetDev\0Tunnel\0",
524 .fill_message_create
= netdev_ip6gre_fill_message_create
,
525 .create_type
= NETDEV_CREATE_STACKED
,
526 .config_verify
= netdev_tunnel_verify
,
529 const NetDevVTable ip6tnl_vtable
= {
530 .object_size
= sizeof(Tunnel
),
532 .sections
= "Match\0NetDev\0Tunnel\0",
533 .fill_message_create
= netdev_ip6tnl_fill_message_create
,
534 .create_type
= NETDEV_CREATE_STACKED
,
535 .config_verify
= netdev_tunnel_verify
,