LCOV - code coverage report
Current view: top level - network/netdev - l2tp-tunnel.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 374 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 27 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <netinet/in.h>
       4             : #include <linux/l2tp.h>
       5             : #include <linux/genetlink.h>
       6             : 
       7             : #include "sd-netlink.h"
       8             : 
       9             : #include "conf-parser.h"
      10             : #include "hashmap.h"
      11             : #include "l2tp-tunnel.h"
      12             : #include "missing.h"
      13             : #include "netlink-util.h"
      14             : #include "networkd-address.h"
      15             : #include "networkd-manager.h"
      16             : #include "parse-util.h"
      17             : #include "socket-util.h"
      18             : #include "string-table.h"
      19             : #include "string-util.h"
      20             : #include "util.h"
      21             : 
      22             : static const char* const l2tp_l2spec_type_table[_NETDEV_L2TP_L2SPECTYPE_MAX] = {
      23             :         [NETDEV_L2TP_L2SPECTYPE_NONE]    = "none",
      24             :         [NETDEV_L2TP_L2SPECTYPE_DEFAULT] = "default",
      25             : };
      26             : 
      27           0 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_l2spec_type, L2tpL2specType);
      28             : 
      29             : static const char* const l2tp_encap_type_table[_NETDEV_L2TP_ENCAPTYPE_MAX] = {
      30             :         [NETDEV_L2TP_ENCAPTYPE_UDP] = "udp",
      31             :         [NETDEV_L2TP_ENCAPTYPE_IP]  = "ip",
      32             : };
      33             : 
      34           0 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_encap_type, L2tpEncapType);
      35           0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_l2tp_encap_type, l2tp_encap_type, L2tpEncapType, "Failed to parse L2TP Encapsulation Type");
      36             : 
      37             : static const char* const l2tp_local_address_type_table[_NETDEV_L2TP_LOCAL_ADDRESS_MAX] = {
      38             :          [NETDEV_L2TP_LOCAL_ADDRESS_AUTO]    = "auto",
      39             :          [NETDEV_L2TP_LOCAL_ADDRESS_STATIC]  = "static",
      40             :          [NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC] = "dynamic",
      41             : };
      42             : 
      43           0 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_local_address_type, L2tpLocalAddressType);
      44             : 
      45           0 : static void l2tp_session_free(L2tpSession *s) {
      46           0 :         if (!s)
      47           0 :                 return;
      48             : 
      49           0 :         if (s->tunnel && s->section)
      50           0 :                 ordered_hashmap_remove(s->tunnel->sessions_by_section, s);
      51             : 
      52           0 :         network_config_section_free(s->section);
      53             : 
      54           0 :         free(s->name);
      55             : 
      56           0 :         free(s);
      57             : }
      58             : 
      59           0 : DEFINE_NETWORK_SECTION_FUNCTIONS(L2tpSession, l2tp_session_free);
      60             : 
      61           0 : static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned section_line, L2tpSession **ret) {
      62           0 :         _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
      63           0 :         _cleanup_(l2tp_session_freep) L2tpSession *s = NULL;
      64             :         int r;
      65             : 
      66           0 :         assert(t);
      67           0 :         assert(ret);
      68           0 :         assert(filename);
      69           0 :         assert(section_line > 0);
      70             : 
      71           0 :         r = network_config_section_new(filename, section_line, &n);
      72           0 :         if (r < 0)
      73           0 :                 return r;
      74             : 
      75           0 :         s = ordered_hashmap_get(t->sessions_by_section, n);
      76           0 :         if (s) {
      77           0 :                 *ret = TAKE_PTR(s);
      78           0 :                 return 0;
      79             :         }
      80             : 
      81           0 :         s = new(L2tpSession, 1);
      82           0 :         if (!s)
      83           0 :                 return -ENOMEM;
      84             : 
      85           0 :         *s = (L2tpSession) {
      86             :                 .l2tp_l2spec_type = NETDEV_L2TP_L2SPECTYPE_DEFAULT,
      87             :                 .tunnel = t,
      88           0 :                 .section = TAKE_PTR(n),
      89             :         };
      90             : 
      91           0 :         r = ordered_hashmap_ensure_allocated(&t->sessions_by_section, &network_config_hash_ops);
      92           0 :         if (r < 0)
      93           0 :                 return r;
      94             : 
      95           0 :         r = ordered_hashmap_put(t->sessions_by_section, s->section, s);
      96           0 :         if (r < 0)
      97           0 :                 return r;
      98             : 
      99           0 :         *ret = TAKE_PTR(s);
     100           0 :         return 0;
     101             : }
     102             : 
     103           0 : static int netdev_l2tp_fill_message_tunnel(NetDev *netdev, union in_addr_union *local_address, sd_netlink_message **ret) {
     104           0 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
     105             :         uint16_t encap_type;
     106             :         L2tpTunnel *t;
     107             :         int r;
     108             : 
     109           0 :         assert(netdev);
     110           0 :         assert(local_address);
     111             : 
     112           0 :         t = L2TP(netdev);
     113             : 
     114           0 :         assert(t);
     115             : 
     116           0 :         r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_TUNNEL_CREATE, &m);
     117           0 :         if (r < 0)
     118           0 :                 return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
     119             : 
     120           0 :         r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, t->tunnel_id);
     121           0 :         if (r < 0)
     122           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_CONN_ID attribute: %m");
     123             : 
     124           0 :         r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, t->peer_tunnel_id);
     125           0 :         if (r < 0)
     126           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_CONN_ID attribute: %m");
     127             : 
     128           0 :         r = sd_netlink_message_append_u8(m, L2TP_ATTR_PROTO_VERSION, 3);
     129           0 :         if (r < 0)
     130           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PROTO_VERSION attribute: %m");
     131             : 
     132           0 :         switch(t->l2tp_encap_type) {
     133           0 :         case NETDEV_L2TP_ENCAPTYPE_IP:
     134           0 :                 encap_type = L2TP_ENCAPTYPE_IP;
     135           0 :                 break;
     136           0 :         case NETDEV_L2TP_ENCAPTYPE_UDP:
     137             :         default:
     138           0 :                 encap_type = L2TP_ENCAPTYPE_UDP;
     139           0 :                 break;
     140             :         }
     141             : 
     142           0 :         r = sd_netlink_message_append_u16(m, L2TP_ATTR_ENCAP_TYPE, encap_type);
     143           0 :         if (r < 0)
     144           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_ENCAP_TYPE attribute: %m");
     145             : 
     146           0 :         if (t->family == AF_INET) {
     147           0 :                 r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_SADDR, &local_address->in);
     148           0 :                 if (r < 0)
     149           0 :                         return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP_SADDR attribute: %m");
     150             : 
     151           0 :                 r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_DADDR, &t->remote.in);
     152           0 :                 if (r < 0)
     153           0 :                         return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP_DADDR attribute: %m");
     154             :         } else {
     155           0 :                 r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_SADDR, &local_address->in6);
     156           0 :                 if (r < 0)
     157           0 :                         return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP6_SADDR attribute: %m");
     158             : 
     159           0 :                 r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_DADDR, &t->remote.in6);
     160           0 :                 if (r < 0)
     161           0 :                         return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP6_DADDR attribute: %m");
     162             :         }
     163             : 
     164           0 :         if (encap_type == L2TP_ENCAPTYPE_UDP) {
     165           0 :                 r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_SPORT, t->l2tp_udp_sport);
     166           0 :                 if (r < 0)
     167           0 :                         return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_SPORT, attribute: %m");
     168             : 
     169           0 :                 r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_DPORT, t->l2tp_udp_dport);
     170           0 :                 if (r < 0)
     171           0 :                         return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_DPORT attribute: %m");
     172             : 
     173           0 :                 if (t->udp_csum) {
     174           0 :                         r = sd_netlink_message_append_u8(m, L2TP_ATTR_UDP_CSUM, t->udp_csum);
     175           0 :                         if (r < 0)
     176           0 :                                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_CSUM attribute: %m");
     177             :                 }
     178             : 
     179           0 :                 if (t->udp6_csum_tx) {
     180           0 :                         r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_TX);
     181           0 :                         if (r < 0)
     182           0 :                                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_ZERO_CSUM6_TX attribute: %m");
     183             :                 }
     184             : 
     185           0 :                 if (t->udp6_csum_rx) {
     186           0 :                         r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_RX);
     187           0 :                         if (r < 0)
     188           0 :                                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_ZERO_CSUM6_RX attribute: %m");
     189             :                 }
     190             :         }
     191             : 
     192           0 :         *ret = TAKE_PTR(m);
     193             : 
     194           0 :         return 0;
     195             : }
     196             : 
     197           0 : static int netdev_l2tp_fill_message_session(NetDev *netdev, L2tpSession *session, sd_netlink_message **ret) {
     198           0 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
     199             :         uint16_t l2_spec_len;
     200             :         uint8_t l2_spec_type;
     201             :         int r;
     202             : 
     203           0 :         assert(netdev);
     204           0 :         assert(session);
     205           0 :         assert(session->tunnel);
     206             : 
     207           0 :         r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_SESSION_CREATE, &m);
     208           0 :         if (r < 0)
     209           0 :                 return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
     210             : 
     211           0 :         r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, session->tunnel->tunnel_id);
     212           0 :         if (r < 0)
     213           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_CONN_ID attribute: %m");
     214             : 
     215           0 :         r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, session->tunnel->peer_tunnel_id);
     216           0 :         if (r < 0)
     217           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_CONN_ID attribute: %m");
     218             : 
     219           0 :         r = sd_netlink_message_append_u32(m, L2TP_ATTR_SESSION_ID, session->session_id);
     220           0 :         if (r < 0)
     221           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_SESSION_ID attribute: %m");
     222             : 
     223           0 :         r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_SESSION_ID, session->peer_session_id);
     224           0 :         if (r < 0)
     225           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_SESSION_ID attribute: %m");
     226             : 
     227           0 :         r = sd_netlink_message_append_u16(m, L2TP_ATTR_PW_TYPE, L2TP_PWTYPE_ETH);
     228           0 :         if (r < 0)
     229           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PW_TYPE attribute: %m");
     230             : 
     231           0 :         switch (session->l2tp_l2spec_type) {
     232           0 :         case NETDEV_L2TP_L2SPECTYPE_NONE:
     233           0 :                 l2_spec_type = L2TP_L2SPECTYPE_NONE;
     234           0 :                 l2_spec_len = 0;
     235           0 :                 break;
     236           0 :         case NETDEV_L2TP_L2SPECTYPE_DEFAULT:
     237             :         default:
     238           0 :                 l2_spec_type = L2TP_L2SPECTYPE_DEFAULT;
     239           0 :                 l2_spec_len = 4;
     240           0 :                 break;
     241             :         }
     242             : 
     243           0 :         r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_TYPE, l2_spec_type);
     244           0 :         if (r < 0)
     245           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_L2SPEC_TYPE attribute: %m");
     246             : 
     247           0 :         r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_LEN, l2_spec_len);
     248           0 :         if (r < 0)
     249           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_L2SPEC_LEN attribute: %m");
     250             : 
     251           0 :         r = sd_netlink_message_append_string(m, L2TP_ATTR_IFNAME, session->name);
     252           0 :         if (r < 0)
     253           0 :                 return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IFNAME attribute: %m");
     254             : 
     255           0 :         *ret = TAKE_PTR(m);
     256             : 
     257           0 :         return 0;
     258             : }
     259             : 
     260           0 : static int l2tp_acquire_local_address_one(L2tpTunnel *t, Address *a, union in_addr_union *ret) {
     261           0 :         if (a->family != t->family)
     262           0 :                 return -EINVAL;
     263             : 
     264           0 :         if (in_addr_is_null(a->family, &a->in_addr_peer) <= 0)
     265           0 :                 return -EINVAL;
     266             : 
     267           0 :         if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_STATIC &&
     268           0 :             !FLAGS_SET(a->flags, IFA_F_PERMANENT))
     269           0 :                 return -EINVAL;
     270             : 
     271           0 :         if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC &&
     272           0 :             FLAGS_SET(a->flags, IFA_F_PERMANENT))
     273           0 :                 return -EINVAL;
     274             : 
     275           0 :         *ret = a->in_addr;
     276           0 :         return 0;
     277             : }
     278             : 
     279           0 : static int l2tp_acquire_local_address(L2tpTunnel *t, Link *link, union in_addr_union *ret) {
     280             :         Address *a;
     281             :         Iterator i;
     282             : 
     283           0 :         assert(t);
     284           0 :         assert(link);
     285           0 :         assert(ret);
     286           0 :         assert(IN_SET(t->family, AF_INET, AF_INET6));
     287             : 
     288           0 :         if (!in_addr_is_null(t->family, &t->local)) {
     289             :                 /* local address is explicitly specified. */
     290           0 :                 *ret = t->local;
     291           0 :                 return 0;
     292             :         }
     293             : 
     294           0 :         SET_FOREACH(a, link->addresses, i)
     295           0 :                 if (l2tp_acquire_local_address_one(t, a, ret) >= 0)
     296           0 :                         return 1;
     297             : 
     298           0 :         SET_FOREACH(a, link->addresses_foreign, i)
     299           0 :                 if (l2tp_acquire_local_address_one(t, a, ret) >= 0)
     300           0 :                         return 1;
     301             : 
     302           0 :         return -ENODATA;
     303             : }
     304             : 
     305           0 : static void l2tp_session_destroy_callback(L2tpSession *session) {
     306           0 :         if (!session)
     307           0 :                 return;
     308             : 
     309           0 :         netdev_unref(NETDEV(session->tunnel));
     310             : }
     311             : 
     312           0 : static int l2tp_create_session_handler(sd_netlink *rtnl, sd_netlink_message *m, L2tpSession *session) {
     313             :         NetDev *netdev;
     314             :         int r;
     315             : 
     316           0 :         assert(session);
     317           0 :         assert(session->tunnel);
     318             : 
     319           0 :         netdev = NETDEV(session->tunnel);
     320             : 
     321           0 :         r = sd_netlink_message_get_errno(m);
     322           0 :         if (r == -EEXIST)
     323           0 :                 log_netdev_info(netdev, "L2TP session %s exists, using existing without changing its parameters",
     324             :                                 session->name);
     325           0 :         else if (r < 0) {
     326           0 :                 log_netdev_warning_errno(netdev, r, "L2TP session %s could not be created: %m", session->name);
     327           0 :                 return 1;
     328             :         }
     329             : 
     330           0 :         log_netdev_debug(netdev, "L2TP session %s created", session->name);
     331           0 :         return 1;
     332             : }
     333             : 
     334           0 : static int l2tp_create_session(NetDev *netdev, L2tpSession *session) {
     335           0 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *n = NULL;
     336             :         int r;
     337             : 
     338           0 :         r = netdev_l2tp_fill_message_session(netdev, session, &n);
     339           0 :         if (r < 0)
     340           0 :                 return r;
     341             : 
     342           0 :         r = netlink_call_async(netdev->manager->genl, NULL, n, l2tp_create_session_handler,
     343             :                                l2tp_session_destroy_callback, session);
     344           0 :         if (r < 0)
     345           0 :                 return log_netdev_error_errno(netdev, r, "Failed to create L2TP session %s: %m", session->name);
     346             : 
     347           0 :         netdev_ref(netdev);
     348           0 :         return 0;
     349             : }
     350             : 
     351           0 : static int l2tp_create_tunnel_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
     352             :         L2tpSession *session;
     353             :         L2tpTunnel *t;
     354             :         Iterator i;
     355             :         int r;
     356             : 
     357           0 :         assert(netdev);
     358           0 :         assert(netdev->state != _NETDEV_STATE_INVALID);
     359             : 
     360           0 :         t = L2TP(netdev);
     361             : 
     362           0 :         assert(t);
     363             : 
     364           0 :         r = sd_netlink_message_get_errno(m);
     365           0 :         if (r == -EEXIST)
     366           0 :                 log_netdev_info(netdev, "netdev exists, using existing without changing its parameters");
     367           0 :         else if (r < 0) {
     368           0 :                 log_netdev_warning_errno(netdev, r, "netdev could not be created: %m");
     369           0 :                 netdev_drop(netdev);
     370             : 
     371           0 :                 return 1;
     372             :         }
     373             : 
     374           0 :         log_netdev_debug(netdev, "L2TP tunnel is created");
     375             : 
     376           0 :         ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i)
     377           0 :                 (void) l2tp_create_session(netdev, session);
     378             : 
     379           0 :         return 1;
     380             : }
     381             : 
     382           0 : static int l2tp_create_tunnel(NetDev *netdev, Link *link) {
     383           0 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
     384             :         union in_addr_union local_address;
     385             :         L2tpTunnel *t;
     386             :         int r;
     387             : 
     388           0 :         assert(netdev);
     389             : 
     390           0 :         t = L2TP(netdev);
     391             : 
     392           0 :         assert(t);
     393             : 
     394           0 :         r = l2tp_acquire_local_address(t, link, &local_address);
     395           0 :         if (r < 0)
     396           0 :                 return log_netdev_error_errno(netdev, r, "Could not find local address.");
     397             : 
     398           0 :         if (r > 0 && DEBUG_LOGGING) {
     399           0 :                 _cleanup_free_ char *str = NULL;
     400             : 
     401           0 :                 (void) in_addr_to_string(t->family, &local_address, &str);
     402           0 :                 log_netdev_debug(netdev, "Local address %s acquired.", strna(str));
     403             :         }
     404             : 
     405           0 :         r = netdev_l2tp_fill_message_tunnel(netdev, &local_address, &m);
     406           0 :         if (r < 0)
     407           0 :                 return r;
     408             : 
     409           0 :         r = netlink_call_async(netdev->manager->genl, NULL, m, l2tp_create_tunnel_handler,
     410             :                                netdev_destroy_callback, netdev);
     411           0 :         if (r < 0)
     412           0 :                 return log_netdev_error_errno(netdev, r, "Failed to create L2TP tunnel: %m");
     413             : 
     414           0 :         netdev_ref(netdev);
     415             : 
     416           0 :         return 0;
     417             : }
     418             : 
     419           0 : int config_parse_l2tp_tunnel_address(
     420             :                 const char *unit,
     421             :                 const char *filename,
     422             :                 unsigned line,
     423             :                 const char *section,
     424             :                 unsigned section_line,
     425             :                 const char *lvalue,
     426             :                 int ltype,
     427             :                 const char *rvalue,
     428             :                 void *data,
     429             :                 void *userdata) {
     430             : 
     431           0 :         L2tpTunnel *t = userdata;
     432           0 :         union in_addr_union *addr = data;
     433             :         int r;
     434             : 
     435           0 :         assert(filename);
     436           0 :         assert(lvalue);
     437           0 :         assert(rvalue);
     438           0 :         assert(data);
     439             : 
     440           0 :         if (streq(lvalue, "Local")) {
     441             :                 L2tpLocalAddressType addr_type;
     442             : 
     443           0 :                 if (isempty(rvalue))
     444           0 :                         addr_type = NETDEV_L2TP_LOCAL_ADDRESS_AUTO;
     445             :                 else
     446           0 :                         addr_type = l2tp_local_address_type_from_string(rvalue);
     447             : 
     448           0 :                 if (addr_type >= 0) {
     449           0 :                         if (in_addr_is_null(t->family, &t->remote) != 0)
     450             :                                 /* If Remote= is not specified yet, then also clear family. */
     451           0 :                                 t->family = AF_UNSPEC;
     452             : 
     453           0 :                         t->local = IN_ADDR_NULL;
     454           0 :                         t->local_address_type = addr_type;
     455             : 
     456           0 :                         return 0;
     457             :                 }
     458             :         }
     459             : 
     460           0 :         if (t->family == AF_UNSPEC)
     461           0 :                 r = in_addr_from_string_auto(rvalue, &t->family, addr);
     462             :         else
     463           0 :                 r = in_addr_from_string(t->family, rvalue, addr);
     464           0 :         if (r < 0) {
     465           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     466             :                            "Invalid L2TP Tunnel address specified in %s='%s', ignoring assignment: %m", lvalue, rvalue);
     467           0 :                 return 0;
     468             :         }
     469             : 
     470           0 :         return 0;
     471             : }
     472             : 
     473           0 : int config_parse_l2tp_tunnel_id(
     474             :                 const char *unit,
     475             :                 const char *filename,
     476             :                 unsigned line,
     477             :                 const char *section,
     478             :                 unsigned section_line,
     479             :                 const char *lvalue,
     480             :                 int ltype,
     481             :                 const char *rvalue,
     482             :                 void *data,
     483             :                 void *userdata) {
     484             : 
     485           0 :         uint32_t *id = data, k;
     486             :         int r;
     487             : 
     488           0 :         assert(filename);
     489           0 :         assert(lvalue);
     490           0 :         assert(rvalue);
     491           0 :         assert(data);
     492             : 
     493           0 :         r = safe_atou32(rvalue, &k);
     494           0 :         if (r < 0) {
     495           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     496             :                            "Failed to parse L2TP tunnel id. Ignoring assignment: %s", rvalue);
     497           0 :                 return 0;
     498             :         }
     499             : 
     500           0 :         if (k == 0) {
     501           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     502             :                            "Invalid L2TP tunnel id. Ignoring assignment: %s", rvalue);
     503           0 :                 return 0;
     504             :         }
     505             : 
     506           0 :         *id = k;
     507             : 
     508           0 :         return 0;
     509             : }
     510             : 
     511           0 : int config_parse_l2tp_session_id(
     512             :                 const char *unit,
     513             :                 const char *filename,
     514             :                 unsigned line,
     515             :                 const char *section,
     516             :                 unsigned section_line,
     517             :                 const char *lvalue,
     518             :                 int ltype,
     519             :                 const char *rvalue,
     520             :                 void *data,
     521             :                 void *userdata) {
     522             : 
     523           0 :         _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
     524           0 :         L2tpTunnel *t = userdata;
     525             :         uint32_t k;
     526             :         int r;
     527             : 
     528           0 :         assert(filename);
     529           0 :         assert(section);
     530           0 :         assert(lvalue);
     531           0 :         assert(rvalue);
     532           0 :         assert(data);
     533             : 
     534           0 :         r = l2tp_session_new_static(t, filename, section_line, &session);
     535           0 :         if (r < 0)
     536           0 :                 return r;
     537             : 
     538           0 :         r = safe_atou32(rvalue, &k);
     539           0 :         if (r < 0) {
     540           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     541             :                            "Failed to parse L2TP session id. Ignoring assignment: %s", rvalue);
     542           0 :                 return 0;
     543             :         }
     544             : 
     545           0 :         if (k == 0) {
     546           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     547             :                            "Invalid L2TP session id. Ignoring assignment: %s", rvalue);
     548           0 :                 return 0;
     549             :         }
     550             : 
     551           0 :         if (streq(lvalue, "SessionId"))
     552           0 :                 session->session_id = k;
     553             :         else
     554           0 :                 session->peer_session_id = k;
     555             : 
     556           0 :         session = NULL;
     557           0 :         return 0;
     558             : }
     559             : 
     560           0 : int config_parse_l2tp_session_l2spec(
     561             :                 const char *unit,
     562             :                 const char *filename,
     563             :                 unsigned line,
     564             :                 const char *section,
     565             :                 unsigned section_line,
     566             :                 const char *lvalue,
     567             :                 int ltype,
     568             :                 const char *rvalue,
     569             :                 void *data,
     570             :                 void *userdata) {
     571             : 
     572           0 :         _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
     573           0 :         L2tpTunnel *t = userdata;
     574             :         L2tpL2specType spec;
     575             :         int r;
     576             : 
     577           0 :         assert(filename);
     578           0 :         assert(section);
     579           0 :         assert(lvalue);
     580           0 :         assert(rvalue);
     581           0 :         assert(data);
     582             : 
     583           0 :         r = l2tp_session_new_static(t, filename, section_line, &session);
     584           0 :         if (r < 0)
     585           0 :                 return r;
     586             : 
     587           0 :         spec = l2tp_l2spec_type_from_string(rvalue);
     588           0 :         if (spec < 0) {
     589           0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     590             :                            "Failed to parse layer2 specific header type. Ignoring assignment: %s", rvalue);
     591           0 :                 return 0;
     592             :         }
     593             : 
     594           0 :         session->l2tp_l2spec_type = spec;
     595             : 
     596           0 :         session = NULL;
     597           0 :         return 0;
     598             : }
     599             : 
     600           0 : int config_parse_l2tp_session_name(
     601             :                 const char *unit,
     602             :                 const char *filename,
     603             :                 unsigned line,
     604             :                 const char *section,
     605             :                 unsigned section_line,
     606             :                 const char *lvalue,
     607             :                 int ltype,
     608             :                 const char *rvalue,
     609             :                 void *data,
     610             :                 void *userdata) {
     611             : 
     612           0 :         _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL;
     613           0 :         L2tpTunnel *t = userdata;
     614             :         int r;
     615             : 
     616           0 :         assert(filename);
     617           0 :         assert(section);
     618           0 :         assert(lvalue);
     619           0 :         assert(rvalue);
     620           0 :         assert(data);
     621             : 
     622           0 :         r = l2tp_session_new_static(t, filename, section_line, &session);
     623           0 :         if (r < 0)
     624           0 :                 return r;
     625             : 
     626           0 :         if (!ifname_valid(rvalue)) {
     627           0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     628             :                            "Failed to parse L2TP tunnel session name. Ignoring assignment: %s", rvalue);
     629           0 :                 return 0;
     630             :         }
     631             : 
     632           0 :         r = free_and_strdup(&session->name, rvalue);
     633           0 :         if (r < 0)
     634           0 :                 return log_oom();
     635             : 
     636           0 :         session = NULL;
     637           0 :         return 0;
     638             : }
     639             : 
     640           0 : static void l2tp_tunnel_init(NetDev *netdev) {
     641             :         L2tpTunnel *t;
     642             : 
     643           0 :         assert(netdev);
     644             : 
     645           0 :         t = L2TP(netdev);
     646             : 
     647           0 :         assert(t);
     648             : 
     649           0 :         t->l2tp_encap_type = NETDEV_L2TP_ENCAPTYPE_UDP;
     650           0 :         t->udp6_csum_rx = true;
     651           0 :         t->udp6_csum_tx = true;
     652           0 : }
     653             : 
     654           0 : static int l2tp_session_verify(L2tpSession *session) {
     655             :         NetDev *netdev;
     656             : 
     657           0 :         assert(session);
     658           0 :         assert(session->tunnel);
     659             : 
     660           0 :         netdev = NETDEV(session->tunnel);
     661             : 
     662           0 :         if (section_is_invalid(session->section))
     663           0 :                 return -EINVAL;
     664             : 
     665           0 :         if (!session->name)
     666           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     667             :                                               "%s: L2TP session without name configured. "
     668             :                                               "Ignoring [L2TPSession] section from line %u",
     669             :                                               session->section->filename, session->section->line);
     670             : 
     671           0 :         if (session->session_id == 0 || session->peer_session_id == 0)
     672           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     673             :                                               "%s: L2TP session without session IDs configured. "
     674             :                                               "Ignoring [L2TPSession] section from line %u",
     675             :                                               session->section->filename, session->section->line);
     676             : 
     677           0 :         return 0;
     678             : }
     679             : 
     680           0 : static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) {
     681             :         L2tpTunnel *t;
     682             :         L2tpSession *session;
     683             :         Iterator i;
     684             : 
     685           0 :         assert(netdev);
     686           0 :         assert(filename);
     687             : 
     688           0 :         t = L2TP(netdev);
     689             : 
     690           0 :         assert(t);
     691             : 
     692           0 :         if (!IN_SET(t->family, AF_INET, AF_INET6))
     693           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     694             :                                               "%s: L2TP tunnel with invalid address family configured. Ignoring",
     695             :                                               filename);
     696             : 
     697           0 :         if (in_addr_is_null(t->family, &t->remote))
     698           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     699             :                                               "%s: L2TP tunnel without a remote address configured. Ignoring",
     700             :                                               filename);
     701             : 
     702           0 :         if (t->tunnel_id == 0 || t->peer_tunnel_id == 0)
     703           0 :                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     704             :                                               "%s: L2TP tunnel without tunnel IDs configured. Ignoring",
     705             :                                               filename);
     706             : 
     707           0 :         ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i)
     708           0 :                 if (l2tp_session_verify(session) < 0)
     709           0 :                         l2tp_session_free(session);
     710             : 
     711           0 :         return 0;
     712             : }
     713             : 
     714           0 : static void l2tp_tunnel_done(NetDev *netdev) {
     715             :         L2tpTunnel *t;
     716             : 
     717           0 :         assert(netdev);
     718             : 
     719           0 :         t = L2TP(netdev);
     720             : 
     721           0 :         assert(t);
     722             : 
     723           0 :         ordered_hashmap_free_with_destructor(t->sessions_by_section, l2tp_session_free);
     724           0 : }
     725             : 
     726             : const NetDevVTable l2tptnl_vtable = {
     727             :         .object_size = sizeof(L2tpTunnel),
     728             :         .init = l2tp_tunnel_init,
     729             :         .sections = "Match\0NetDev\0L2TP\0L2TPSession\0",
     730             :         .create_after_configured = l2tp_create_tunnel,
     731             :         .done = l2tp_tunnel_done,
     732             :         .create_type = NETDEV_CREATE_AFTER_CONFIGURED,
     733             :         .config_verify = netdev_l2tp_tunnel_verify,
     734             : };

Generated by: LCOV version 1.14