LCOV - code coverage report
Current view: top level - network/netdev - tunnel.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 1 450 0.2 %
Date: 2019-08-22 15:41:25 Functions: 2 19 10.5 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <netinet/in.h>
       4             : #include <linux/fou.h>
       5             : #include <linux/ip.h>
       6             : #include <linux/if_tunnel.h>
       7             : #include <linux/ip6_tunnel.h>
       8             : 
       9             : #include "sd-netlink.h"
      10             : 
      11             : #include "conf-parser.h"
      12             : #include "missing.h"
      13             : #include "netlink-util.h"
      14             : #include "networkd-link.h"
      15             : #include "netdev/tunnel.h"
      16             : #include "parse-util.h"
      17             : #include "string-table.h"
      18             : #include "string-util.h"
      19             : #include "util.h"
      20             : 
      21             : #define DEFAULT_TNL_HOP_LIMIT   64
      22             : #define IP6_FLOWINFO_FLOWLABEL  htobe32(0x000FFFFF)
      23             : #define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0x40
      24             : 
      25             : static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
      26             :         [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
      27             :         [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6",
      28             :         [NETDEV_IP6_TNL_MODE_ANYIP6] = "any",
      29             : };
      30             : 
      31          10 : DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
      32           0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
      33             : 
      34           0 : static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
      35             :         Tunnel *t;
      36             :         int r;
      37             : 
      38           0 :         assert(netdev);
      39             : 
      40           0 :         if (netdev->kind == NETDEV_KIND_IPIP)
      41           0 :                 t = IPIP(netdev);
      42             :         else
      43           0 :                 t = SIT(netdev);
      44             : 
      45           0 :         assert(m);
      46           0 :         assert(t);
      47             : 
      48           0 :         if (link || t->assign_to_loopback) {
      49           0 :                 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
      50           0 :                 if (r < 0)
      51           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
      52             :         }
      53             : 
      54           0 :         r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
      55           0 :         if (r < 0)
      56           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
      57             : 
      58           0 :         r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
      59           0 :         if (r < 0)
      60           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
      61             : 
      62           0 :         r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
      63           0 :         if (r < 0)
      64           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
      65             : 
      66           0 :         r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
      67           0 :         if (r < 0)
      68           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
      69             : 
      70           0 :         if (t->fou_tunnel) {
      71           0 :                 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_TYPE, t->fou_encap_type);
      72           0 :                 if (r < 0)
      73           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_TYPE attribute: %m");
      74             : 
      75           0 :                 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_SPORT, htobe16(t->encap_src_port));
      76           0 :                 if (r < 0)
      77           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_SPORT attribute: %m");
      78             : 
      79           0 :                 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_DPORT, htobe16(t->fou_destination_port));
      80           0 :                 if (r < 0)
      81           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_DPORT attribute: %m");
      82             :         }
      83             : 
      84           0 :         if (netdev->kind == NETDEV_KIND_SIT) {
      85           0 :                 if (t->sixrd_prefixlen > 0) {
      86           0 :                         r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &t->sixrd_prefix);
      87           0 :                         if (r < 0)
      88           0 :                                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIX attribute: %m");
      89             : 
      90             :                         /* u16 is deliberate here, even though we're passing a netmask that can never be >128. The kernel is
      91             :                          * expecting to receive the prefixlen as a u16.
      92             :                          */
      93           0 :                         r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_PREFIXLEN, t->sixrd_prefixlen);
      94           0 :                         if (r < 0)
      95           0 :                                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIXLEN attribute: %m");
      96             :                 }
      97             : 
      98           0 :                 if (t->isatap >= 0) {
      99           0 :                         uint16_t flags = 0;
     100             : 
     101           0 :                         SET_FLAG(flags, SIT_ISATAP, t->isatap);
     102             : 
     103           0 :                         r = sd_netlink_message_append_u16(m, IFLA_IPTUN_FLAGS, flags);
     104           0 :                         if (r < 0)
     105           0 :                                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
     106             :                 }
     107             :         }
     108             : 
     109           0 :         return r;
     110             : }
     111             : 
     112           0 : static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
     113           0 :         uint32_t ikey = 0;
     114           0 :         uint32_t okey = 0;
     115           0 :         uint16_t iflags = 0;
     116           0 :         uint16_t oflags = 0;
     117             :         Tunnel *t;
     118             :         int r;
     119             : 
     120           0 :         assert(netdev);
     121           0 :         assert(m);
     122             : 
     123           0 :         switch (netdev->kind) {
     124           0 :         case NETDEV_KIND_GRE:
     125           0 :                 t = GRE(netdev);
     126           0 :                 break;
     127           0 :         case NETDEV_KIND_ERSPAN:
     128           0 :                 t = ERSPAN(netdev);
     129           0 :                 break;
     130           0 :         case NETDEV_KIND_GRETAP:
     131           0 :                 t = GRETAP(netdev);
     132           0 :                 break;
     133           0 :         default:
     134           0 :                 assert_not_reached("invalid netdev kind");
     135             :         }
     136             : 
     137           0 :         assert(t);
     138             : 
     139           0 :         if (link || t->assign_to_loopback) {
     140           0 :                 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
     141           0 :                 if (r < 0)
     142           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
     143             :         }
     144             : 
     145           0 :         if (netdev->kind == NETDEV_KIND_ERSPAN) {
     146           0 :                 r = sd_netlink_message_append_u32(m, IFLA_GRE_ERSPAN_INDEX, t->erspan_index);
     147           0 :                 if (r < 0)
     148           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ERSPAN_INDEX attribute: %m");
     149             :         }
     150             : 
     151           0 :         r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
     152           0 :         if (r < 0)
     153           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
     154             : 
     155           0 :         r = sd_netlink_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
     156           0 :         if (r < 0)
     157           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
     158             : 
     159           0 :         r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
     160           0 :         if (r < 0)
     161           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
     162             : 
     163           0 :         r = sd_netlink_message_append_u8(m, IFLA_GRE_TOS, t->tos);
     164           0 :         if (r < 0)
     165           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m");
     166             : 
     167           0 :         r = sd_netlink_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc);
     168           0 :         if (r < 0)
     169           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m");
     170             : 
     171           0 :         if (t->key != 0) {
     172           0 :                 ikey = okey = htobe32(t->key);
     173           0 :                 iflags |= GRE_KEY;
     174           0 :                 oflags |= GRE_KEY;
     175             :         }
     176             : 
     177           0 :         if (t->ikey != 0) {
     178           0 :                 ikey = htobe32(t->ikey);
     179           0 :                 iflags |= GRE_KEY;
     180             :         }
     181             : 
     182           0 :         if (t->okey != 0) {
     183           0 :                 okey = htobe32(t->okey);
     184           0 :                 oflags |= GRE_KEY;
     185             :         }
     186             : 
     187           0 :         if (t->gre_erspan_sequence > 0) {
     188           0 :                 iflags |= GRE_SEQ;
     189           0 :                 oflags |= GRE_SEQ;
     190           0 :         } else if (t->gre_erspan_sequence == 0) {
     191           0 :                 iflags &= ~GRE_SEQ;
     192           0 :                 oflags &= ~GRE_SEQ;
     193             :         }
     194             : 
     195           0 :         r = sd_netlink_message_append_u32(m, IFLA_GRE_IKEY, ikey);
     196           0 :         if (r < 0)
     197           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IKEY attribute: %m");
     198             : 
     199           0 :         r = sd_netlink_message_append_u32(m, IFLA_GRE_OKEY, okey);
     200           0 :         if (r < 0)
     201           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OKEY attribute: %m");
     202             : 
     203           0 :         r = sd_netlink_message_append_u16(m, IFLA_GRE_IFLAGS, iflags);
     204           0 :         if (r < 0)
     205           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IFLAGS attribute: %m");
     206             : 
     207           0 :         r = sd_netlink_message_append_u16(m, IFLA_GRE_OFLAGS, oflags);
     208           0 :         if (r < 0)
     209           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OFLAGS, attribute: %m");
     210             : 
     211           0 :         if (t->fou_tunnel) {
     212           0 :                 r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_TYPE, t->fou_encap_type);
     213           0 :                 if (r < 0)
     214           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_TYPE attribute: %m");
     215             : 
     216           0 :                 r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_SPORT, htobe16(t->encap_src_port));
     217           0 :                 if (r < 0)
     218           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_SPORT attribute: %m");
     219             : 
     220           0 :                 r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_DPORT, htobe16(t->fou_destination_port));
     221           0 :                 if (r < 0)
     222           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_DPORT attribute: %m");
     223             :         }
     224             : 
     225           0 :         return r;
     226             : }
     227             : 
     228           0 : static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
     229             :         Tunnel *t;
     230             :         int r;
     231             : 
     232           0 :         assert(netdev);
     233             : 
     234           0 :         if (netdev->kind == NETDEV_KIND_IP6GRE)
     235           0 :                 t = IP6GRE(netdev);
     236             :         else
     237           0 :                 t = IP6GRETAP(netdev);
     238             : 
     239           0 :         assert(t);
     240           0 :         assert(m);
     241             : 
     242           0 :         if (link || t->assign_to_loopback) {
     243           0 :                 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
     244           0 :                 if (r < 0)
     245           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
     246             :         }
     247             : 
     248           0 :         r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
     249           0 :         if (r < 0)
     250           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
     251             : 
     252           0 :         r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
     253           0 :         if (r < 0)
     254           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
     255             : 
     256           0 :         r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
     257           0 :         if (r < 0)
     258           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
     259             : 
     260           0 :         if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
     261           0 :                 r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel);
     262           0 :                 if (r < 0)
     263           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m");
     264             :         }
     265             : 
     266           0 :         r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags);
     267           0 :         if (r < 0)
     268           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m");
     269             : 
     270           0 :         return r;
     271             : }
     272             : 
     273           0 : static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
     274             :         uint32_t ikey, okey;
     275             :         Tunnel *t;
     276             :         int r;
     277             : 
     278           0 :         assert(netdev);
     279           0 :         assert(m);
     280             : 
     281           0 :         if (netdev->kind == NETDEV_KIND_VTI)
     282           0 :                 t = VTI(netdev);
     283             :         else
     284           0 :                 t = VTI6(netdev);
     285             : 
     286           0 :         assert(t);
     287             : 
     288           0 :         if (link || t->assign_to_loopback) {
     289           0 :                 r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
     290           0 :                 if (r < 0)
     291           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_LINK attribute: %m");
     292             :         }
     293             : 
     294           0 :         if (t->key != 0)
     295           0 :                 ikey = okey = htobe32(t->key);
     296             :         else {
     297           0 :                 ikey = htobe32(t->ikey);
     298           0 :                 okey = htobe32(t->okey);
     299             :         }
     300             : 
     301           0 :         r = sd_netlink_message_append_u32(m, IFLA_VTI_IKEY, ikey);
     302           0 :         if (r < 0)
     303           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_IKEY attribute: %m");
     304             : 
     305           0 :         r = sd_netlink_message_append_u32(m, IFLA_VTI_OKEY, okey);
     306           0 :         if (r < 0)
     307           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_OKEY attribute: %m");
     308             : 
     309           0 :         r = netlink_message_append_in_addr_union(m, IFLA_VTI_LOCAL, t->family, &t->local);
     310           0 :         if (r < 0)
     311           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_LOCAL attribute: %m");
     312             : 
     313           0 :         r = netlink_message_append_in_addr_union(m, IFLA_VTI_REMOTE, t->family, &t->remote);
     314           0 :         if (r < 0)
     315           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_REMOTE attribute: %m");
     316             : 
     317           0 :         return r;
     318             : }
     319             : 
     320           0 : static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
     321           0 :         Tunnel *t = IP6TNL(netdev);
     322             :         uint8_t proto;
     323             :         int r;
     324             : 
     325           0 :         assert(netdev);
     326           0 :         assert(m);
     327           0 :         assert(t);
     328             : 
     329           0 :         if (link || t->assign_to_loopback) {
     330           0 :                 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
     331           0 :                 if (r < 0)
     332           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
     333             :         }
     334             : 
     335           0 :         r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
     336           0 :         if (r < 0)
     337           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
     338             : 
     339           0 :         r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
     340           0 :         if (r < 0)
     341           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
     342             : 
     343           0 :         r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
     344           0 :         if (r < 0)
     345           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
     346             : 
     347           0 :         if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
     348           0 :                 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
     349           0 :                 if (r < 0)
     350           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m");
     351             :         }
     352             : 
     353           0 :         if (t->copy_dscp)
     354           0 :                 t->flags |= IP6_TNL_F_RCV_DSCP_COPY;
     355             : 
     356           0 :         if (t->allow_localremote >= 0)
     357           0 :                 SET_FLAG(t->flags, IP6_TNL_F_ALLOW_LOCAL_REMOTE, t->allow_localremote);
     358             : 
     359           0 :         if (t->encap_limit != IPV6_DEFAULT_TNL_ENCAP_LIMIT) {
     360           0 :                 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_ENCAP_LIMIT, t->encap_limit);
     361           0 :                 if (r < 0)
     362           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_LIMIT attribute: %m");
     363             :         }
     364             : 
     365           0 :         r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
     366           0 :         if (r < 0)
     367           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
     368             : 
     369           0 :         switch (t->ip6tnl_mode) {
     370           0 :         case NETDEV_IP6_TNL_MODE_IP6IP6:
     371           0 :                 proto = IPPROTO_IPV6;
     372           0 :                 break;
     373           0 :         case NETDEV_IP6_TNL_MODE_IPIP6:
     374           0 :                 proto = IPPROTO_IPIP;
     375           0 :                 break;
     376           0 :         case NETDEV_IP6_TNL_MODE_ANYIP6:
     377             :         default:
     378           0 :                 proto = 0;
     379           0 :                 break;
     380             :         }
     381             : 
     382           0 :         r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
     383           0 :         if (r < 0)
     384           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PROTO attribute: %m");
     385             : 
     386           0 :         return r;
     387             : }
     388             : 
     389           0 : static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
     390           0 :         Tunnel *t = NULL;
     391             : 
     392           0 :         assert(netdev);
     393           0 :         assert(filename);
     394             : 
     395           0 :         switch (netdev->kind) {
     396           0 :         case NETDEV_KIND_IPIP:
     397           0 :                 t = IPIP(netdev);
     398           0 :                 break;
     399           0 :         case NETDEV_KIND_SIT:
     400           0 :                 t = SIT(netdev);
     401           0 :                 break;
     402           0 :         case NETDEV_KIND_GRE:
     403           0 :                 t = GRE(netdev);
     404           0 :                 break;
     405           0 :         case NETDEV_KIND_GRETAP:
     406           0 :                 t = GRETAP(netdev);
     407           0 :                 break;
     408           0 :         case NETDEV_KIND_IP6GRE:
     409           0 :                 t = IP6GRE(netdev);
     410           0 :                 break;
     411           0 :         case NETDEV_KIND_IP6GRETAP:
     412           0 :                 t = IP6GRETAP(netdev);
     413           0 :                 break;
     414           0 :         case NETDEV_KIND_VTI:
     415           0 :                 t = VTI(netdev);
     416           0 :                 break;
     417           0 :         case NETDEV_KIND_VTI6:
     418           0 :                 t = VTI6(netdev);
     419           0 :                 break;
     420           0 :         case NETDEV_KIND_IP6TNL:
     421           0 :                 t = IP6TNL(netdev);
     422           0 :                 break;
     423           0 :         case NETDEV_KIND_ERSPAN:
     424           0 :                 t = ERSPAN(netdev);
     425           0 :                 break;
     426           0 :         default:
     427           0 :                 assert_not_reached("Invalid tunnel kind");
     428             :         }
     429             : 
     430           0 :         assert(t);
     431             : 
     432           0 :         if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_IPIP, NETDEV_KIND_SIT, NETDEV_KIND_GRE) &&
     433           0 :             !IN_SET(t->family, AF_UNSPEC, AF_INET))
     434           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     435             :                                               "vti/ipip/sit/gre tunnel without a local/remote IPv4 address configured in %s. Ignoring", filename);
     436             : 
     437           0 :         if (IN_SET(netdev->kind, NETDEV_KIND_GRETAP, NETDEV_KIND_ERSPAN) &&
     438           0 :             (t->family != AF_INET || in_addr_is_null(t->family, &t->remote)))
     439           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     440             :                                               "gretap/erspan tunnel without a remote IPv4 address configured in %s. Ignoring", filename);
     441             : 
     442           0 :         if ((IN_SET(netdev->kind, NETDEV_KIND_VTI6, NETDEV_KIND_IP6TNL) && t->family != AF_INET6) ||
     443           0 :             (netdev->kind == NETDEV_KIND_IP6GRE && !IN_SET(t->family, AF_UNSPEC, AF_INET6)))
     444           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     445             :                                               "vti6/ip6tnl/ip6gre tunnel without a local/remote IPv6 address configured in %s. Ignoring", filename);
     446             : 
     447           0 :         if (netdev->kind == NETDEV_KIND_IP6GRETAP &&
     448           0 :             (t->family != AF_INET6 || in_addr_is_null(t->family, &t->remote)))
     449           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     450             :                                               "ip6gretap tunnel without a remote IPv6 address configured in %s. Ignoring", filename);
     451             : 
     452           0 :         if (netdev->kind == NETDEV_KIND_IP6TNL &&
     453           0 :             t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID)
     454           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     455             :                                               "ip6tnl without mode configured in %s. Ignoring", filename);
     456             : 
     457           0 :         if (t->fou_tunnel && t->fou_destination_port <= 0)
     458           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     459             :                                               "FooOverUDP missing port configured in %s. Ignoring", filename);
     460             : 
     461           0 :         if (netdev->kind == NETDEV_KIND_ERSPAN && (t->erspan_index >= (1 << 20) || t->erspan_index == 0))
     462           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Invalid erspan index %d. Ignoring", t->erspan_index);
     463             : 
     464             :         /* netlink_message_append_in_addr_union() is used for vti/vti6. So, t->family cannot be AF_UNSPEC. */
     465           0 :         if (netdev->kind == NETDEV_KIND_VTI)
     466           0 :                 t->family = AF_INET;
     467             : 
     468           0 :         return 0;
     469             : }
     470             : 
     471           0 : int config_parse_tunnel_address(const char *unit,
     472             :                                 const char *filename,
     473             :                                 unsigned line,
     474             :                                 const char *section,
     475             :                                 unsigned section_line,
     476             :                                 const char *lvalue,
     477             :                                 int ltype,
     478             :                                 const char *rvalue,
     479             :                                 void *data,
     480             :                                 void *userdata) {
     481           0 :         Tunnel *t = userdata;
     482           0 :         union in_addr_union *addr = data, buffer;
     483             :         int r, f;
     484             : 
     485           0 :         assert(filename);
     486           0 :         assert(lvalue);
     487           0 :         assert(rvalue);
     488           0 :         assert(data);
     489             : 
     490             :         /* This is used to parse addresses on both local and remote ends of the tunnel.
     491             :          * Address families must match.
     492             :          *
     493             :          * "any" is a special value which means that the address is unspecified.
     494             :          */
     495             : 
     496           0 :         if (streq(rvalue, "any")) {
     497           0 :                 *addr = IN_ADDR_NULL;
     498             : 
     499             :                 /* As a special case, if both the local and remote addresses are
     500             :                  * unspecified, also clear the address family.
     501             :                  */
     502           0 :                 if (t->family != AF_UNSPEC &&
     503           0 :                     in_addr_is_null(t->family, &t->local) != 0 &&
     504           0 :                     in_addr_is_null(t->family, &t->remote) != 0)
     505           0 :                         t->family = AF_UNSPEC;
     506           0 :                 return 0;
     507             :         }
     508             : 
     509           0 :         r = in_addr_from_string_auto(rvalue, &f, &buffer);
     510           0 :         if (r < 0) {
     511           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     512             :                            "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue);
     513           0 :                 return 0;
     514             :         }
     515             : 
     516           0 :         if (t->family != AF_UNSPEC && t->family != f) {
     517           0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     518             :                            "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
     519           0 :                 return 0;
     520             :         }
     521             : 
     522           0 :         t->family = f;
     523           0 :         *addr = buffer;
     524           0 :         return 0;
     525             : }
     526             : 
     527           0 : int config_parse_tunnel_key(const char *unit,
     528             :                             const char *filename,
     529             :                             unsigned line,
     530             :                             const char *section,
     531             :                             unsigned section_line,
     532             :                             const char *lvalue,
     533             :                             int ltype,
     534             :                             const char *rvalue,
     535             :                             void *data,
     536             :                             void *userdata) {
     537             :         union in_addr_union buffer;
     538           0 :         Tunnel *t = userdata;
     539             :         uint32_t k;
     540             :         int r;
     541             : 
     542           0 :         assert(filename);
     543           0 :         assert(lvalue);
     544           0 :         assert(rvalue);
     545           0 :         assert(data);
     546             : 
     547           0 :         r = in_addr_from_string(AF_INET, rvalue, &buffer);
     548           0 :         if (r < 0) {
     549           0 :                 r = safe_atou32(rvalue, &k);
     550           0 :                 if (r < 0) {
     551           0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse tunnel key ignoring assignment: %s", rvalue);
     552           0 :                         return 0;
     553             :                 }
     554             :         } else
     555           0 :                 k = be32toh(buffer.in.s_addr);
     556             : 
     557           0 :         if (streq(lvalue, "Key"))
     558           0 :                 t->key = k;
     559           0 :         else if (streq(lvalue, "InputKey"))
     560           0 :                 t->ikey = k;
     561             :         else
     562           0 :                 t->okey = k;
     563             : 
     564           0 :         return 0;
     565             : }
     566             : 
     567           0 : int config_parse_ipv6_flowlabel(const char* unit,
     568             :                                 const char *filename,
     569             :                                 unsigned line,
     570             :                                 const char *section,
     571             :                                 unsigned section_line,
     572             :                                 const char *lvalue,
     573             :                                 int ltype,
     574             :                                 const char *rvalue,
     575             :                                 void *data,
     576             :                                 void *userdata) {
     577           0 :         IPv6FlowLabel *ipv6_flowlabel = data;
     578           0 :         Tunnel *t = userdata;
     579           0 :         int k = 0;
     580             :         int r;
     581             : 
     582           0 :         assert(filename);
     583           0 :         assert(lvalue);
     584           0 :         assert(rvalue);
     585           0 :         assert(ipv6_flowlabel);
     586             : 
     587           0 :         if (streq(rvalue, "inherit")) {
     588           0 :                 *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
     589           0 :                 t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
     590             :         } else {
     591           0 :                 r = config_parse_int(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);
     592           0 :                 if (r < 0)
     593           0 :                         return r;
     594             : 
     595           0 :                 if (k > 0xFFFFF)
     596           0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
     597             :                 else {
     598           0 :                         *ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL;
     599           0 :                         t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
     600             :                 }
     601             :         }
     602             : 
     603           0 :         return 0;
     604             : }
     605             : 
     606           0 : int config_parse_encap_limit(const char* unit,
     607             :                              const char *filename,
     608             :                              unsigned line,
     609             :                              const char *section,
     610             :                              unsigned section_line,
     611             :                              const char *lvalue,
     612             :                              int ltype,
     613             :                              const char *rvalue,
     614             :                              void *data,
     615             :                              void *userdata) {
     616           0 :         Tunnel *t = userdata;
     617           0 :         int k = 0;
     618             :         int r;
     619             : 
     620           0 :         assert(filename);
     621           0 :         assert(lvalue);
     622           0 :         assert(rvalue);
     623             : 
     624           0 :         if (streq(rvalue, "none"))
     625           0 :                 t->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT;
     626             :         else {
     627           0 :                 r = safe_atoi(rvalue, &k);
     628           0 :                 if (r < 0) {
     629           0 :                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Tunnel Encapsulation Limit option, ignoring: %s", rvalue);
     630           0 :                         return 0;
     631             :                 }
     632             : 
     633           0 :                 if (k > 255 || k < 0)
     634           0 :                         log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid Tunnel Encapsulation value, ignoring: %d", k);
     635             :                 else {
     636           0 :                         t->encap_limit = k;
     637           0 :                         t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
     638             :                 }
     639             :         }
     640             : 
     641           0 :         return 0;
     642             : }
     643             : 
     644           0 : int config_parse_6rd_prefix(const char* unit,
     645             :                             const char *filename,
     646             :                             unsigned line,
     647             :                             const char *section,
     648             :                             unsigned section_line,
     649             :                             const char *lvalue,
     650             :                             int ltype,
     651             :                             const char *rvalue,
     652             :                             void *data,
     653             :                             void *userdata) {
     654           0 :         Tunnel *t = userdata;
     655             : 
     656           0 :         assert(filename);
     657           0 :         assert(lvalue);
     658           0 :         assert(rvalue);
     659             : 
     660             :         union in_addr_union p;
     661             :         uint8_t l;
     662             :         int r;
     663             : 
     664           0 :         r = in_addr_prefix_from_string(rvalue, AF_INET6, &p, &l);
     665           0 :         if (r < 0) {
     666           0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse 6rd prefix \"%s\", ignoring: %m", rvalue);
     667           0 :                 return 0;
     668             :         }
     669           0 :         if (l == 0) {
     670           0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "6rd prefix length of \"%s\" must be greater than zero, ignoring", rvalue);
     671           0 :                 return 0;
     672             :         }
     673             : 
     674           0 :         t->sixrd_prefix = p.in6;
     675           0 :         t->sixrd_prefixlen = l;
     676             : 
     677           0 :         return 0;
     678             : }
     679             : 
     680           0 : static void ipip_sit_init(NetDev *n) {
     681             :         Tunnel *t;
     682             : 
     683           0 :         assert(n);
     684             : 
     685           0 :         switch (n->kind) {
     686           0 :         case NETDEV_KIND_IPIP:
     687           0 :                 t = IPIP(n);
     688           0 :                 break;
     689           0 :         case NETDEV_KIND_SIT:
     690           0 :                 t = SIT(n);
     691           0 :                 break;
     692           0 :         default:
     693           0 :                 assert_not_reached("invalid netdev kind");
     694             :         }
     695             : 
     696           0 :         assert(t);
     697             : 
     698           0 :         t->pmtudisc = true;
     699           0 :         t->fou_encap_type = FOU_ENCAP_DIRECT;
     700           0 :         t->isatap = -1;
     701           0 : }
     702             : 
     703           0 : static void vti_init(NetDev *n) {
     704             :         Tunnel *t;
     705             : 
     706           0 :         assert(n);
     707             : 
     708           0 :         if (n->kind == NETDEV_KIND_VTI)
     709           0 :                 t = VTI(n);
     710             :         else
     711           0 :                 t = VTI6(n);
     712             : 
     713           0 :         assert(t);
     714             : 
     715           0 :         t->pmtudisc = true;
     716           0 : }
     717             : 
     718           0 : static void gre_erspan_init(NetDev *n) {
     719             :         Tunnel *t;
     720             : 
     721           0 :         assert(n);
     722             : 
     723           0 :         switch (n->kind) {
     724           0 :         case NETDEV_KIND_GRE:
     725           0 :                 t = GRE(n);
     726           0 :                 break;
     727           0 :         case NETDEV_KIND_ERSPAN:
     728           0 :                 t = ERSPAN(n);
     729           0 :                 break;
     730           0 :         case NETDEV_KIND_GRETAP:
     731           0 :                 t = GRETAP(n);
     732           0 :                 break;
     733           0 :         default:
     734           0 :                 assert_not_reached("invalid netdev kind");
     735             :         }
     736             : 
     737           0 :         assert(t);
     738             : 
     739           0 :         t->pmtudisc = true;
     740           0 :         t->gre_erspan_sequence = -1;
     741           0 :         t->fou_encap_type = FOU_ENCAP_DIRECT;
     742           0 : }
     743             : 
     744           0 : static void ip6gre_init(NetDev *n) {
     745             :         Tunnel *t;
     746             : 
     747           0 :         assert(n);
     748             : 
     749           0 :         if (n->kind == NETDEV_KIND_IP6GRE)
     750           0 :                 t = IP6GRE(n);
     751             :         else
     752           0 :                 t = IP6GRETAP(n);
     753             : 
     754           0 :         assert(t);
     755             : 
     756           0 :         t->ttl = DEFAULT_TNL_HOP_LIMIT;
     757           0 : }
     758             : 
     759           0 : static void ip6tnl_init(NetDev *n) {
     760           0 :         Tunnel *t = IP6TNL(n);
     761             : 
     762           0 :         assert(n);
     763           0 :         assert(t);
     764             : 
     765           0 :         t->ttl = DEFAULT_TNL_HOP_LIMIT;
     766           0 :         t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
     767           0 :         t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
     768           0 :         t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
     769           0 :         t->allow_localremote = -1;
     770           0 : }
     771             : 
     772             : const NetDevVTable ipip_vtable = {
     773             :         .object_size = sizeof(Tunnel),
     774             :         .init = ipip_sit_init,
     775             :         .sections = "Match\0NetDev\0Tunnel\0",
     776             :         .fill_message_create = netdev_ipip_sit_fill_message_create,
     777             :         .create_type = NETDEV_CREATE_STACKED,
     778             :         .config_verify = netdev_tunnel_verify,
     779             :         .generate_mac = true,
     780             : };
     781             : 
     782             : const NetDevVTable sit_vtable = {
     783             :         .object_size = sizeof(Tunnel),
     784             :         .init = ipip_sit_init,
     785             :         .sections = "Match\0NetDev\0Tunnel\0",
     786             :         .fill_message_create = netdev_ipip_sit_fill_message_create,
     787             :         .create_type = NETDEV_CREATE_STACKED,
     788             :         .config_verify = netdev_tunnel_verify,
     789             :         .generate_mac = true,
     790             : };
     791             : 
     792             : const NetDevVTable vti_vtable = {
     793             :         .object_size = sizeof(Tunnel),
     794             :         .init = vti_init,
     795             :         .sections = "Match\0NetDev\0Tunnel\0",
     796             :         .fill_message_create = netdev_vti_fill_message_create,
     797             :         .create_type = NETDEV_CREATE_STACKED,
     798             :         .config_verify = netdev_tunnel_verify,
     799             :         .generate_mac = true,
     800             : };
     801             : 
     802             : const NetDevVTable vti6_vtable = {
     803             :         .object_size = sizeof(Tunnel),
     804             :         .init = vti_init,
     805             :         .sections = "Match\0NetDev\0Tunnel\0",
     806             :         .fill_message_create = netdev_vti_fill_message_create,
     807             :         .create_type = NETDEV_CREATE_STACKED,
     808             :         .config_verify = netdev_tunnel_verify,
     809             :         .generate_mac = true,
     810             : };
     811             : 
     812             : const NetDevVTable gre_vtable = {
     813             :         .object_size = sizeof(Tunnel),
     814             :         .init = gre_erspan_init,
     815             :         .sections = "Match\0NetDev\0Tunnel\0",
     816             :         .fill_message_create = netdev_gre_erspan_fill_message_create,
     817             :         .create_type = NETDEV_CREATE_STACKED,
     818             :         .config_verify = netdev_tunnel_verify,
     819             :         .generate_mac = true,
     820             : };
     821             : 
     822             : const NetDevVTable gretap_vtable = {
     823             :         .object_size = sizeof(Tunnel),
     824             :         .init = gre_erspan_init,
     825             :         .sections = "Match\0NetDev\0Tunnel\0",
     826             :         .fill_message_create = netdev_gre_erspan_fill_message_create,
     827             :         .create_type = NETDEV_CREATE_STACKED,
     828             :         .config_verify = netdev_tunnel_verify,
     829             :         .generate_mac = true,
     830             : };
     831             : 
     832             : const NetDevVTable ip6gre_vtable = {
     833             :         .object_size = sizeof(Tunnel),
     834             :         .init = ip6gre_init,
     835             :         .sections = "Match\0NetDev\0Tunnel\0",
     836             :         .fill_message_create = netdev_ip6gre_fill_message_create,
     837             :         .create_type = NETDEV_CREATE_STACKED,
     838             :         .config_verify = netdev_tunnel_verify,
     839             :         .generate_mac = true,
     840             : };
     841             : 
     842             : const NetDevVTable ip6gretap_vtable = {
     843             :         .object_size = sizeof(Tunnel),
     844             :         .init = ip6gre_init,
     845             :         .sections = "Match\0NetDev\0Tunnel\0",
     846             :         .fill_message_create = netdev_ip6gre_fill_message_create,
     847             :         .create_type = NETDEV_CREATE_STACKED,
     848             :         .config_verify = netdev_tunnel_verify,
     849             :         .generate_mac = true,
     850             : };
     851             : 
     852             : const NetDevVTable ip6tnl_vtable = {
     853             :         .object_size = sizeof(Tunnel),
     854             :         .init = ip6tnl_init,
     855             :         .sections = "Match\0NetDev\0Tunnel\0",
     856             :         .fill_message_create = netdev_ip6tnl_fill_message_create,
     857             :         .create_type = NETDEV_CREATE_STACKED,
     858             :         .config_verify = netdev_tunnel_verify,
     859             :         .generate_mac = true,
     860             : };
     861             : 
     862             : const NetDevVTable erspan_vtable = {
     863             :         .object_size = sizeof(Tunnel),
     864             :         .init = gre_erspan_init,
     865             :         .sections = "Match\0NetDev\0Tunnel\0",
     866             :         .fill_message_create = netdev_gre_erspan_fill_message_create,
     867             :         .create_type = NETDEV_CREATE_STACKED,
     868             :         .config_verify = netdev_tunnel_verify,
     869             :         .generate_mac = true,
     870             : };

Generated by: LCOV version 1.14