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 log_netdev_error(netdev,
59 "Could not append IFLA_IPTUN_LINK attribute: %s",
64 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
66 log_netdev_error(netdev,
67 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
72 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
74 log_netdev_error(netdev,
75 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
80 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
82 log_netdev_error(netdev,
83 "Could not append IFLA_IPTUN_TTL attribute: %s",
88 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
90 log_netdev_error(netdev,
91 "Could not append IFLA_IPTUN_PMTUDISC attribute: %s",
99 static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
100 Tunnel *t = SIT(netdev);
107 assert(t->family == AF_INET);
109 r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
111 log_netdev_error(netdev,
112 "Could not append IFLA_IPTUN_LINK attribute: %s",
117 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
119 log_netdev_error(netdev,
120 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
125 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
127 log_netdev_error(netdev,
128 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
133 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
135 log_netdev_error(netdev,
136 "Could not append IFLA_IPTUN_TTL attribute: %s",
141 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
143 log_netdev_error(netdev,
144 "Could not append IFLA_IPTUN_PMTUDISC attribute: %s",
152 static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
158 if (netdev->kind == NETDEV_KIND_GRE)
164 assert(t->family == AF_INET);
168 r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
170 log_netdev_error(netdev,
171 "Could not append IFLA_GRE_LINK attribute: %s",
176 r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
178 log_netdev_error(netdev,
179 "Could not append IFLA_GRE_LOCAL attribute: %s",
184 r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
186 log_netdev_error(netdev,
187 "Could not append IFLA_GRE_REMOTE attribute: %s",
192 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
194 log_netdev_error(netdev,
195 "Could not append IFLA_GRE_TTL attribute: %s",
200 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, t->tos);
202 log_netdev_error(netdev,
203 "Could not append IFLA_GRE_TOS attribute: %s",
208 r = sd_rtnl_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc);
210 log_netdev_error(netdev,
211 "Could not append IFLA_GRE_PMTUDISC attribute: %s",
219 static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
225 if (netdev->kind == NETDEV_KIND_IP6GRE)
228 t = IP6GRETAP(netdev);
231 assert(t->family == AF_INET6);
235 r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
237 log_netdev_error(netdev,
238 "Could not append IFLA_GRE_LINK attribute: %s",
243 r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
245 log_netdev_error(netdev,
246 "Could not append IFLA_GRE_LOCAL attribute: %s",
251 r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
253 log_netdev_error(netdev,
254 "Could not append IFLA_GRE_REMOTE attribute: %s",
259 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
261 log_netdev_error(netdev,
262 "Could not append IFLA_GRE_TTL attribute: %s",
270 static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
271 Tunnel *t = VTI(netdev);
278 assert(t->family == AF_INET);
280 r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
282 log_netdev_error(netdev,
283 "Could not append IFLA_IPTUN_LINK attribute: %s",
288 r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in);
290 log_netdev_error(netdev,
291 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
296 r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in);
298 log_netdev_error(netdev,
299 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
307 static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
308 Tunnel *t = IP6TNL(netdev);
316 assert(t->family == AF_INET6);
318 r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
320 log_netdev_error(netdev,
321 "Could not append IFLA_IPTUN_LINK attribute: %s",
326 r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
328 log_netdev_error(netdev,
329 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
334 r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
336 log_netdev_error(netdev,
337 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
342 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
344 log_netdev_error(netdev,
345 "Could not append IFLA_IPTUN_TTL attribute: %s",
350 switch (t->ip6tnl_mode) {
351 case NETDEV_IP6_TNL_MODE_IP6IP6:
352 proto = IPPROTO_IPV6;
354 case NETDEV_IP6_TNL_MODE_IPIP6:
355 proto = IPPROTO_IPIP;
357 case NETDEV_IP6_TNL_MODE_ANYIP6:
363 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
365 log_netdev_error(netdev,
366 "Could not append IFLA_IPTUN_MODE attribute: %s",
374 static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
380 switch (netdev->kind) {
381 case NETDEV_KIND_IPIP:
384 case NETDEV_KIND_SIT:
387 case NETDEV_KIND_GRE:
390 case NETDEV_KIND_GRETAP:
393 case NETDEV_KIND_IP6GRE:
396 case NETDEV_KIND_IP6GRETAP:
397 t = IP6GRETAP(netdev);
399 case NETDEV_KIND_VTI:
402 case NETDEV_KIND_IP6TNL:
406 assert_not_reached("Invalid tunnel kind");
411 if (t->remote.in.s_addr == INADDR_ANY) {
412 log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
416 if (t->family != AF_INET && t->family != AF_INET6) {
417 log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
421 if (netdev->kind == NETDEV_KIND_IP6TNL) {
422 if (t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) {
423 log_warning("IP6 Tunnel without mode configured in %s. Ignoring", filename);
431 int config_parse_tunnel_address(const char *unit,
432 const char *filename,
435 unsigned section_line,
441 Tunnel *t = userdata;
442 union in_addr_union *addr = data, buffer;
450 r = in_addr_from_string_auto(rvalue, &f, &buffer);
452 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel address is invalid, ignoring assignment: %s", rvalue);
456 if (t->family != AF_UNSPEC && t->family != f) {
457 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
467 static void ipip_init(NetDev *n) {
476 static void sit_init(NetDev *n) {
485 static void vti_init(NetDev *n) {
494 static void gre_init(NetDev *n) {
499 if (n->kind == NETDEV_KIND_GRE)
509 static void ip6gre_init(NetDev *n) {
514 if (n->kind == NETDEV_KIND_IP6GRE)
521 t->ttl = DEFAULT_TNL_HOP_LIMIT;
524 static void ip6tnl_init(NetDev *n) {
525 Tunnel *t = IP6TNL(n);
530 t->ttl = DEFAULT_TNL_HOP_LIMIT;
531 t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
532 t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
535 const NetDevVTable ipip_vtable = {
536 .object_size = sizeof(Tunnel),
538 .sections = "Match\0NetDev\0Tunnel\0",
539 .fill_message_create = netdev_ipip_fill_message_create,
540 .create_type = NETDEV_CREATE_STACKED,
541 .config_verify = netdev_tunnel_verify,
544 const NetDevVTable sit_vtable = {
545 .object_size = sizeof(Tunnel),
547 .sections = "Match\0NetDev\0Tunnel\0",
548 .fill_message_create = netdev_sit_fill_message_create,
549 .create_type = NETDEV_CREATE_STACKED,
550 .config_verify = netdev_tunnel_verify,
553 const NetDevVTable vti_vtable = {
554 .object_size = sizeof(Tunnel),
556 .sections = "Match\0NetDev\0Tunnel\0",
557 .fill_message_create = netdev_vti_fill_message_create,
558 .create_type = NETDEV_CREATE_STACKED,
559 .config_verify = netdev_tunnel_verify,
562 const NetDevVTable gre_vtable = {
563 .object_size = sizeof(Tunnel),
565 .sections = "Match\0NetDev\0Tunnel\0",
566 .fill_message_create = netdev_gre_fill_message_create,
567 .create_type = NETDEV_CREATE_STACKED,
568 .config_verify = netdev_tunnel_verify,
571 const NetDevVTable gretap_vtable = {
572 .object_size = sizeof(Tunnel),
574 .sections = "Match\0NetDev\0Tunnel\0",
575 .fill_message_create = netdev_gre_fill_message_create,
576 .create_type = NETDEV_CREATE_STACKED,
577 .config_verify = netdev_tunnel_verify,
580 const NetDevVTable ip6gre_vtable = {
581 .object_size = sizeof(Tunnel),
583 .sections = "Match\0NetDev\0Tunnel\0",
584 .fill_message_create = netdev_ip6gre_fill_message_create,
585 .create_type = NETDEV_CREATE_STACKED,
586 .config_verify = netdev_tunnel_verify,
589 const NetDevVTable ip6gretap_vtable = {
590 .object_size = sizeof(Tunnel),
592 .sections = "Match\0NetDev\0Tunnel\0",
593 .fill_message_create = netdev_ip6gre_fill_message_create,
594 .create_type = NETDEV_CREATE_STACKED,
595 .config_verify = netdev_tunnel_verify,
598 const NetDevVTable ip6tnl_vtable = {
599 .object_size = sizeof(Tunnel),
601 .sections = "Match\0NetDev\0Tunnel\0",
602 .fill_message_create = netdev_ip6tnl_fill_message_create,
603 .create_type = NETDEV_CREATE_STACKED,
604 .config_verify = netdev_tunnel_verify,