LCOV - code coverage report
Current view: top level - network - networkd-network.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 163 539 30.2 %
Date: 2019-08-23 13:36:53 Functions: 11 28 39.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 99 559 17.7 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <net/if.h>
       4                 :            : #include <netinet/in.h>
       5                 :            : #include <linux/netdevice.h>
       6                 :            : 
       7                 :            : #include "alloc-util.h"
       8                 :            : #include "conf-files.h"
       9                 :            : #include "conf-parser.h"
      10                 :            : #include "dns-domain.h"
      11                 :            : #include "fd-util.h"
      12                 :            : #include "hostname-util.h"
      13                 :            : #include "in-addr-util.h"
      14                 :            : #include "network-internal.h"
      15                 :            : #include "networkd-manager.h"
      16                 :            : #include "networkd-network.h"
      17                 :            : #include "parse-util.h"
      18                 :            : #include "set.h"
      19                 :            : #include "socket-util.h"
      20                 :            : #include "stat-util.h"
      21                 :            : #include "string-table.h"
      22                 :            : #include "string-util.h"
      23                 :            : #include "strv.h"
      24                 :            : #include "util.h"
      25                 :            : 
      26                 :            : /* Let's assume that anything above this number is a user misconfiguration. */
      27                 :            : #define MAX_NTP_SERVERS 128
      28                 :            : 
      29                 :            : /* Set defaults following RFC7844 */
      30                 :         12 : void network_apply_anonymize_if_set(Network *network) {
      31         [ +  - ]:         12 :         if (!network->dhcp_anonymize)
      32                 :         12 :                 return;
      33                 :            :         /* RFC7844 3.7
      34                 :            :          SHOULD NOT send the Host Name option */
      35                 :          0 :         network->dhcp_send_hostname = false;
      36                 :            :         /* RFC7844 section 3.:
      37                 :            :          MAY contain the Client Identifier option
      38                 :            :          Section 3.5:
      39                 :            :          clients MUST use client identifiers based solely
      40                 :            :          on the link-layer address */
      41                 :            :         /* NOTE: Using MAC, as it does not reveal extra information,
      42                 :            :         * and some servers might not answer if this option is not sent */
      43                 :          0 :         network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
      44                 :            :         /* RFC 7844 3.10:
      45                 :            :          SHOULD NOT use the Vendor Class Identifier option */
      46                 :          0 :         network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier);
      47                 :            :         /* RFC7844 section 3.6.:
      48                 :            :          The client intending to protect its privacy SHOULD only request a
      49                 :            :          minimal number of options in the PRL and SHOULD also randomly shuffle
      50                 :            :          the ordering of option codes in the PRL.  If this random ordering
      51                 :            :          cannot be implemented, the client MAY order the option codes in the
      52                 :            :          PRL by option code number (lowest to highest).
      53                 :            :         */
      54                 :            :         /* NOTE: dhcp_use_mtu is false by default,
      55                 :            :         * though it was not initiallized to any value in network_load_one.
      56                 :            :         * Maybe there should be another var called *send*?
      57                 :            :         * (to use the MTU sent by the server but to do not send
      58                 :            :         * the option in the PRL). */
      59                 :          0 :         network->dhcp_use_mtu = false;
      60                 :            :         /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
      61                 :            :          * but this is needed to use them. */
      62                 :          0 :         network->dhcp_use_routes = true;
      63                 :            :         /* RFC7844 section 3.6.
      64                 :            :         * same comments as previous option */
      65                 :          0 :         network->dhcp_use_timezone = false;
      66                 :            : }
      67                 :            : 
      68                 :        300 : static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
      69                 :            :         const char *kind_string;
      70                 :            :         NetDev *netdev;
      71                 :            :         int r;
      72                 :            : 
      73                 :            :         /* For test-networkd-conf, the check must be earlier than the assertions. */
      74         [ +  - ]:        300 :         if (!name)
      75                 :        300 :                 return 0;
      76                 :            : 
      77         [ #  # ]:          0 :         assert(network);
      78         [ #  # ]:          0 :         assert(network->manager);
      79         [ #  # ]:          0 :         assert(network->filename);
      80         [ #  # ]:          0 :         assert(ret_netdev);
      81                 :            : 
      82         [ #  # ]:          0 :         if (kind == _NETDEV_KIND_TUNNEL)
      83                 :          0 :                 kind_string = "tunnel";
      84                 :            :         else {
      85                 :          0 :                 kind_string = netdev_kind_to_string(kind);
      86         [ #  # ]:          0 :                 if (!kind_string)
      87         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
      88                 :            :                                                "%s: Invalid NetDev kind of %s, ignoring assignment.",
      89                 :            :                                                network->filename, name);
      90                 :            :         }
      91                 :            : 
      92                 :          0 :         r = netdev_get(network->manager, name, &netdev);
      93         [ #  # ]:          0 :         if (r < 0)
      94         [ #  # ]:          0 :                 return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
      95                 :            :                                        network->filename, name);
      96                 :            : 
      97   [ #  #  #  # ]:          0 :         if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
      98   [ #  #  #  # ]:          0 :                                       IN_SET(netdev->kind,
      99                 :            :                                              NETDEV_KIND_IPIP,
     100                 :            :                                              NETDEV_KIND_SIT,
     101                 :            :                                              NETDEV_KIND_GRE,
     102                 :            :                                              NETDEV_KIND_GRETAP,
     103                 :            :                                              NETDEV_KIND_IP6GRE,
     104                 :            :                                              NETDEV_KIND_IP6GRETAP,
     105                 :            :                                              NETDEV_KIND_VTI,
     106                 :            :                                              NETDEV_KIND_VTI6,
     107                 :            :                                              NETDEV_KIND_IP6TNL,
     108                 :            :                                              NETDEV_KIND_ERSPAN)))
     109         [ #  # ]:          0 :                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     110                 :            :                                        "%s: NetDev %s is not a %s, ignoring assignment",
     111                 :            :                                        network->filename, name, kind_string);
     112                 :            : 
     113                 :          0 :         *ret_netdev = netdev_ref(netdev);
     114                 :          0 :         return 1;
     115                 :            : }
     116                 :            : 
     117                 :        100 : static int network_resolve_stacked_netdevs(Network *network) {
     118                 :            :         void *name, *kind;
     119                 :            :         Iterator i;
     120                 :            :         int r;
     121                 :            : 
     122         [ -  + ]:        100 :         assert(network);
     123                 :            : 
     124         [ -  + ]:        100 :         HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names, i) {
     125      [ #  #  # ]:          0 :                 _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
     126                 :            : 
     127                 :          0 :                 r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
     128         [ #  # ]:          0 :                 if (r <= 0)
     129                 :          0 :                         continue;
     130                 :            : 
     131                 :          0 :                 r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
     132         [ #  # ]:          0 :                 if (r < 0)
     133                 :          0 :                         return log_oom();
     134                 :            : 
     135                 :          0 :                 r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
     136         [ #  # ]:          0 :                 if (r < 0)
     137         [ #  # ]:          0 :                         return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
     138                 :            :                                                network->filename, (const char *) name);
     139                 :            : 
     140                 :          0 :                 netdev = NULL;
     141                 :            :         }
     142                 :            : 
     143                 :        100 :         return 0;
     144                 :            : }
     145                 :            : 
     146                 :        104 : int network_verify(Network *network) {
     147                 :            :         Address *address, *address_next;
     148                 :            :         Route *route, *route_next;
     149                 :            :         FdbEntry *fdb, *fdb_next;
     150                 :            :         Neighbor *neighbor, *neighbor_next;
     151                 :            :         AddressLabel *label, *label_next;
     152                 :            :         Prefix *prefix, *prefix_next;
     153                 :            :         RoutingPolicyRule *rule, *rule_next;
     154                 :            : 
     155         [ -  + ]:        104 :         assert(network);
     156         [ -  + ]:        104 :         assert(network->filename);
     157                 :            : 
     158   [ +  -  +  -  :        208 :         if (set_isempty(network->match_mac) && strv_isempty(network->match_path) &&
                   +  + ]
     159   [ +  -  -  + ]:        296 :             strv_isempty(network->match_driver) && strv_isempty(network->match_type) &&
     160         [ #  # ]:         96 :             strv_isempty(network->match_name) && strv_isempty(network->match_property) &&
     161         [ #  # ]:          0 :             !network->conditions)
     162         [ #  # ]:          0 :                 log_warning("%s: No valid settings found in the [Match] section. "
     163                 :            :                             "The file will match all interfaces. "
     164                 :            :                             "If that is intended, please add Name=* in the [Match] section.",
     165                 :            :                             network->filename);
     166                 :            : 
     167                 :            :         /* skip out early if configuration does not match the environment */
     168         [ +  + ]:        104 :         if (!condition_test_list(network->conditions, NULL, NULL, NULL))
     169         [ -  + ]:          4 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
     170                 :            :                                        "%s: Conditions in the file do not match the system environment, skipping.",
     171                 :            :                                        network->filename);
     172                 :            : 
     173                 :        100 :         (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
     174                 :        100 :         (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
     175                 :        100 :         (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
     176                 :        100 :         (void) network_resolve_stacked_netdevs(network);
     177                 :            : 
     178                 :            :         /* Free unnecessary entries. */
     179                 :        100 :         network->bond_name = mfree(network->bond_name);
     180                 :        100 :         network->bridge_name = mfree(network->bridge_name);
     181                 :        100 :         network->vrf_name = mfree(network->vrf_name);
     182                 :        100 :         network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
     183                 :            : 
     184         [ -  + ]:        100 :         if (network->bond) {
     185                 :            :                 /* Bonding slave does not support addressing. */
     186         [ #  # ]:          0 :                 if (network->ipv6_accept_ra > 0) {
     187         [ #  # ]:          0 :                         log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
     188                 :            :                                     network->filename);
     189                 :          0 :                         network->ipv6_accept_ra = 0;
     190                 :            :                 }
     191   [ #  #  #  # ]:          0 :                 if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
     192         [ #  # ]:          0 :                         log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
     193                 :            :                                     network->filename);
     194                 :          0 :                         network->link_local = ADDRESS_FAMILY_NO;
     195                 :            :                 }
     196         [ #  # ]:          0 :                 if (network->dhcp != ADDRESS_FAMILY_NO) {
     197         [ #  # ]:          0 :                         log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
     198                 :            :                                     network->filename);
     199                 :          0 :                         network->dhcp = ADDRESS_FAMILY_NO;
     200                 :            :                 }
     201         [ #  # ]:          0 :                 if (network->dhcp_server) {
     202         [ #  # ]:          0 :                         log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
     203                 :            :                                     network->filename);
     204                 :          0 :                         network->dhcp_server = false;
     205                 :            :                 }
     206         [ #  # ]:          0 :                 if (network->n_static_addresses > 0) {
     207         [ #  # ]:          0 :                         log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
     208                 :            :                                     network->filename);
     209         [ #  # ]:          0 :                         while ((address = network->static_addresses))
     210                 :          0 :                                 address_free(address);
     211                 :            :                 }
     212         [ #  # ]:          0 :                 if (network->n_static_routes > 0) {
     213         [ #  # ]:          0 :                         log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
     214                 :            :                                     network->filename);
     215         [ #  # ]:          0 :                         while ((route = network->static_routes))
     216                 :          0 :                                 route_free(route);
     217                 :            :                 }
     218                 :            :         }
     219                 :            : 
     220         [ -  + ]:        100 :         if (network->link_local < 0)
     221         [ #  # ]:          0 :                 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
     222                 :            : 
     223         [ -  + ]:        100 :         if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
     224         [ #  # ]:          0 :             !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
     225         [ #  # ]:          0 :                 log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
     226                 :            :                             "Disabling the fallback assignment.", network->filename);
     227                 :          0 :                 SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
     228                 :            :         }
     229                 :            : 
     230   [ +  +  -  + ]:        100 :         if (network->ipv6_accept_ra < 0 && network->bridge)
     231                 :          0 :                 network->ipv6_accept_ra = false;
     232                 :            : 
     233                 :            :         /* IPMasquerade=yes implies IPForward=yes */
     234         [ +  + ]:        100 :         if (network->ip_masquerade)
     235                 :          8 :                 network->ip_forward |= ADDRESS_FAMILY_IPV4;
     236                 :            : 
     237   [ -  +  #  # ]:        100 :         if (network->mtu > 0 && network->dhcp_use_mtu) {
     238         [ #  # ]:          0 :                 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
     239                 :            :                             "Disabling UseMTU=.", network->filename);
     240                 :          0 :                 network->dhcp_use_mtu = false;
     241                 :            :         }
     242                 :            : 
     243         [ +  + ]:        100 :         if (network->dhcp_critical >= 0) {
     244         [ +  - ]:         92 :                 if (network->keep_configuration >= 0)
     245         [ +  - ]:         92 :                         log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
     246                 :            :                                     "Ignoring CriticalConnection=.", network->filename);
     247         [ #  # ]:          0 :                 else if (network->dhcp_critical)
     248                 :            :                         /* CriticalConnection=yes also preserve foreign static configurations. */
     249                 :          0 :                         network->keep_configuration = KEEP_CONFIGURATION_YES;
     250                 :            :                 else
     251                 :            :                         /* For backward compatibility, we do not release DHCP addresses on manager stop. */
     252                 :          0 :                         network->keep_configuration = KEEP_CONFIGURATION_DHCP_ON_STOP;
     253                 :            :         }
     254                 :            : 
     255         [ +  + ]:        100 :         if (network->keep_configuration < 0)
     256                 :            :                 /* For backward compatibility, we do not release DHCP addresses on manager stop. */
     257                 :          8 :                 network->keep_configuration = KEEP_CONFIGURATION_DHCP_ON_STOP;
     258                 :            : 
     259         [ +  + ]:        200 :         LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
     260         [ +  + ]:        100 :                 if (address_section_verify(address) < 0)
     261                 :         40 :                         address_free(address);
     262                 :            : 
     263         [ -  + ]:        100 :         LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes)
     264         [ #  # ]:          0 :                 if (route_section_verify(route, network) < 0)
     265                 :          0 :                         route_free(route);
     266                 :            : 
     267         [ -  + ]:        100 :         LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries)
     268         [ #  # ]:          0 :                 if (section_is_invalid(fdb->section))
     269                 :          0 :                         fdb_entry_free(fdb);
     270                 :            : 
     271         [ -  + ]:        100 :         LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
     272         [ #  # ]:          0 :                 if (neighbor_section_verify(neighbor) < 0)
     273                 :          0 :                         neighbor_free(neighbor);
     274                 :            : 
     275         [ -  + ]:        100 :         LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
     276         [ #  # ]:          0 :                 if (section_is_invalid(label->section))
     277                 :          0 :                         address_label_free(label);
     278                 :            : 
     279         [ -  + ]:        100 :         LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes)
     280         [ #  # ]:          0 :                 if (section_is_invalid(prefix->section))
     281                 :          0 :                         prefix_free(prefix);
     282                 :            : 
     283         [ -  + ]:        100 :         LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules)
     284         [ #  # ]:          0 :                 if (routing_policy_rule_section_verify(rule) < 0)
     285                 :          0 :                         routing_policy_rule_free(rule);
     286                 :            : 
     287                 :        100 :         return 0;
     288                 :            : }
     289                 :            : 
     290                 :         12 : int network_load_one(Manager *manager, const char *filename) {
     291                 :         12 :         _cleanup_free_ char *fname = NULL, *name = NULL;
     292                 :         12 :         _cleanup_(network_unrefp) Network *network = NULL;
     293                 :         12 :         _cleanup_fclose_ FILE *file = NULL;
     294                 :            :         const char *dropin_dirname;
     295                 :            :         char *d;
     296                 :            :         int r;
     297                 :            : 
     298         [ -  + ]:         12 :         assert(manager);
     299         [ -  + ]:         12 :         assert(filename);
     300                 :            : 
     301                 :         12 :         file = fopen(filename, "re");
     302         [ -  + ]:         12 :         if (!file) {
     303         [ #  # ]:          0 :                 if (errno == ENOENT)
     304                 :          0 :                         return 0;
     305                 :            : 
     306                 :          0 :                 return -errno;
     307                 :            :         }
     308                 :            : 
     309         [ -  + ]:         12 :         if (null_or_empty_fd(fileno(file))) {
     310         [ #  # ]:          0 :                 log_debug("Skipping empty file: %s", filename);
     311                 :          0 :                 return 0;
     312                 :            :         }
     313                 :            : 
     314                 :         12 :         fname = strdup(filename);
     315         [ -  + ]:         12 :         if (!fname)
     316                 :          0 :                 return log_oom();
     317                 :            : 
     318                 :         12 :         name = strdup(basename(filename));
     319         [ -  + ]:         12 :         if (!name)
     320                 :          0 :                 return log_oom();
     321                 :            : 
     322                 :         12 :         d = strrchr(name, '.');
     323         [ -  + ]:         12 :         if (!d)
     324                 :          0 :                 return -EINVAL;
     325                 :            : 
     326                 :         12 :         *d = '\0';
     327                 :            : 
     328   [ +  +  +  -  :         60 :         dropin_dirname = strjoina(name, ".network.d");
          -  +  -  +  +  
                +  +  - ]
     329                 :            : 
     330                 :         12 :         network = new(Network, 1);
     331         [ -  + ]:         12 :         if (!network)
     332                 :          0 :                 return log_oom();
     333                 :            : 
     334                 :         24 :         *network = (Network) {
     335                 :         12 :                 .filename = TAKE_PTR(fname),
     336                 :         12 :                 .name = TAKE_PTR(name),
     337                 :            : 
     338                 :            :                 .manager = manager,
     339                 :            :                 .n_ref = 1,
     340                 :            : 
     341                 :            :                 .required_for_online = true,
     342                 :            :                 .required_operstate_for_online = LINK_OPERSTATE_DEGRADED,
     343                 :            :                 .dhcp = ADDRESS_FAMILY_NO,
     344                 :            :                 .dhcp_critical = -1,
     345                 :            :                 .dhcp_use_ntp = true,
     346                 :            :                 .dhcp_use_dns = true,
     347                 :            :                 .dhcp_use_hostname = true,
     348                 :            :                 .dhcp_use_routes = true,
     349                 :            :                 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
     350                 :            :                 .dhcp_send_hostname = true,
     351                 :            :                 /* To enable/disable RFC7844 Anonymity Profiles */
     352                 :            :                 .dhcp_anonymize = false,
     353                 :            :                 .dhcp_route_metric = DHCP_ROUTE_METRIC,
     354                 :            :                 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
     355                 :            :                 .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
     356                 :            :                 .dhcp_route_table = RT_TABLE_MAIN,
     357                 :            :                 .dhcp_route_table_set = false,
     358                 :            :                 /* NOTE: from man: UseMTU=... Defaults to false*/
     359                 :            :                 .dhcp_use_mtu = false,
     360                 :            :                 /* NOTE: from man: UseTimezone=... Defaults to "no".*/
     361                 :            :                 .dhcp_use_timezone = false,
     362                 :            :                 .rapid_commit = true,
     363                 :            : 
     364                 :            :                 .dhcp6_use_ntp = true,
     365                 :            :                 .dhcp6_use_dns = true,
     366                 :            : 
     367                 :            :                 .dhcp_server_emit_dns = true,
     368                 :            :                 .dhcp_server_emit_ntp = true,
     369                 :            :                 .dhcp_server_emit_router = true,
     370                 :            :                 .dhcp_server_emit_timezone = true,
     371                 :            : 
     372                 :            :                 .router_emit_dns = true,
     373                 :            :                 .router_emit_domains = true,
     374                 :            : 
     375                 :            :                 .use_bpdu = -1,
     376                 :            :                 .hairpin = -1,
     377                 :            :                 .fast_leave = -1,
     378                 :            :                 .allow_port_to_be_root = -1,
     379                 :            :                 .unicast_flood = -1,
     380                 :            :                 .multicast_flood = -1,
     381                 :            :                 .multicast_to_unicast = -1,
     382                 :            :                 .neighbor_suppression = -1,
     383                 :            :                 .learning = -1,
     384                 :            :                 .bridge_proxy_arp = -1,
     385                 :            :                 .bridge_proxy_arp_wifi = -1,
     386                 :            :                 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
     387                 :            :                 .multicast_router = _MULTICAST_ROUTER_INVALID,
     388                 :            : 
     389                 :            :                 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
     390                 :            : 
     391                 :            :                 .dns_default_route = -1,
     392                 :            :                 .llmnr = RESOLVE_SUPPORT_YES,
     393                 :            :                 .mdns = RESOLVE_SUPPORT_NO,
     394                 :            :                 .dnssec_mode = _DNSSEC_MODE_INVALID,
     395                 :            :                 .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
     396                 :            : 
     397                 :            :                 /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
     398                 :            :                 .link_local = _ADDRESS_FAMILY_INVALID,
     399                 :            : 
     400                 :            :                 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
     401                 :            :                 .ipv6_accept_ra = -1,
     402                 :            :                 .ipv6_dad_transmits = -1,
     403                 :            :                 .ipv6_hop_limit = -1,
     404                 :            :                 .ipv6_proxy_ndp = -1,
     405                 :            :                 .duid.type = _DUID_TYPE_INVALID,
     406                 :            :                 .proxy_arp = -1,
     407                 :            :                 .arp = -1,
     408                 :            :                 .multicast = -1,
     409                 :            :                 .allmulticast = -1,
     410                 :            :                 .ipv6_accept_ra_use_dns = true,
     411                 :            :                 .ipv6_accept_ra_use_autonomous_prefix = true,
     412                 :            :                 .ipv6_accept_ra_use_onlink_prefix = true,
     413                 :            :                 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
     414                 :            :                 .ipv6_accept_ra_route_table_set = false,
     415                 :            : 
     416                 :            :                 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
     417                 :            : 
     418                 :            :                 .can_triple_sampling = -1,
     419                 :            :         };
     420                 :            : 
     421                 :         12 :         r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
     422                 :            :                               "Match\0"
     423                 :            :                               "Link\0"
     424                 :            :                               "Network\0"
     425                 :            :                               "Address\0"
     426                 :            :                               "Neighbor\0"
     427                 :            :                               "IPv6AddressLabel\0"
     428                 :            :                               "RoutingPolicyRule\0"
     429                 :            :                               "Route\0"
     430                 :            :                               "DHCP\0"
     431                 :            :                               "DHCPv4\0" /* compat */
     432                 :            :                               "DHCPv6\0"
     433                 :            :                               "DHCPServer\0"
     434                 :            :                               "IPv6AcceptRA\0"
     435                 :            :                               "IPv6NDPProxyAddress\0"
     436                 :            :                               "Bridge\0"
     437                 :            :                               "BridgeFDB\0"
     438                 :            :                               "BridgeVLAN\0"
     439                 :            :                               "IPv6PrefixDelegation\0"
     440                 :            :                               "IPv6Prefix\0"
     441                 :            :                               "CAN\0",
     442                 :            :                               config_item_perf_lookup, network_network_gperf_lookup,
     443                 :            :                               CONFIG_PARSE_WARN, network);
     444         [ -  + ]:         12 :         if (r < 0)
     445                 :          0 :                 return r;
     446                 :            : 
     447                 :         12 :         network_apply_anonymize_if_set(network);
     448                 :            : 
     449                 :         12 :         r = network_add_ipv4ll_route(network);
     450         [ -  + ]:         12 :         if (r < 0)
     451         [ #  # ]:          0 :                 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
     452                 :            : 
     453                 :         12 :         r = network_add_default_route_on_device(network);
     454         [ -  + ]:         12 :         if (r < 0)
     455         [ #  # ]:          0 :                 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
     456                 :            :                                   network->filename);
     457                 :            : 
     458                 :         12 :         r = ordered_hashmap_ensure_allocated(&manager->networks, &string_hash_ops);
     459         [ -  + ]:         12 :         if (r < 0)
     460                 :          0 :                 return r;
     461                 :            : 
     462                 :         12 :         r = ordered_hashmap_put(manager->networks, network->name, network);
     463         [ -  + ]:         12 :         if (r < 0)
     464                 :          0 :                 return r;
     465                 :            : 
     466         [ +  + ]:         12 :         if (network_verify(network) < 0)
     467                 :          4 :                 return 0;
     468                 :            : 
     469                 :          8 :         network = NULL;
     470                 :          8 :         return 0;
     471                 :            : }
     472                 :            : 
     473                 :          4 : int network_load(Manager *manager) {
     474                 :          4 :         _cleanup_strv_free_ char **files = NULL;
     475                 :            :         char **f;
     476                 :            :         int r;
     477                 :            : 
     478         [ -  + ]:          4 :         assert(manager);
     479                 :            : 
     480         [ -  + ]:          4 :         ordered_hashmap_clear_with_destructor(manager->networks, network_unref);
     481                 :            : 
     482                 :          4 :         r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
     483         [ -  + ]:          4 :         if (r < 0)
     484         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to enumerate network files: %m");
     485                 :            : 
     486   [ +  -  +  + ]:         16 :         STRV_FOREACH(f, files) {
     487                 :         12 :                 r = network_load_one(manager, *f);
     488         [ -  + ]:         12 :                 if (r < 0)
     489                 :          0 :                         return r;
     490                 :            :         }
     491                 :            : 
     492                 :          4 :         return 0;
     493                 :            : }
     494                 :            : 
     495                 :        104 : static Network *network_free(Network *network) {
     496                 :            :         IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
     497                 :            :         RoutingPolicyRule *rule;
     498                 :            :         FdbEntry *fdb_entry;
     499                 :            :         Neighbor *neighbor;
     500                 :            :         AddressLabel *label;
     501                 :            :         Prefix *prefix;
     502                 :            :         Address *address;
     503                 :            :         Route *route;
     504                 :            : 
     505         [ -  + ]:        104 :         if (!network)
     506                 :          0 :                 return NULL;
     507                 :            : 
     508                 :        104 :         free(network->filename);
     509                 :            : 
     510                 :        104 :         set_free_free(network->match_mac);
     511                 :        104 :         strv_free(network->match_path);
     512                 :        104 :         strv_free(network->match_driver);
     513                 :        104 :         strv_free(network->match_type);
     514                 :        104 :         strv_free(network->match_name);
     515                 :        104 :         strv_free(network->match_property);
     516                 :        104 :         condition_free_list(network->conditions);
     517                 :            : 
     518                 :        104 :         free(network->description);
     519                 :        104 :         free(network->dhcp_vendor_class_identifier);
     520                 :        104 :         strv_free(network->dhcp_user_class);
     521                 :        104 :         free(network->dhcp_hostname);
     522                 :        104 :         set_free(network->dhcp_black_listed_ip);
     523                 :        104 :         free(network->mac);
     524                 :            : 
     525                 :        104 :         strv_free(network->ntp);
     526                 :        104 :         free(network->dns);
     527                 :        104 :         ordered_set_free_free(network->search_domains);
     528                 :        104 :         ordered_set_free_free(network->route_domains);
     529                 :        104 :         strv_free(network->bind_carrier);
     530                 :            : 
     531                 :        104 :         ordered_set_free_free(network->router_search_domains);
     532                 :        104 :         free(network->router_dns);
     533                 :        104 :         set_free_free(network->ndisc_black_listed_prefix);
     534                 :            : 
     535                 :        104 :         free(network->bridge_name);
     536                 :        104 :         free(network->bond_name);
     537                 :        104 :         free(network->vrf_name);
     538                 :        104 :         hashmap_free_free_key(network->stacked_netdev_names);
     539                 :        104 :         netdev_unref(network->bridge);
     540                 :        104 :         netdev_unref(network->bond);
     541                 :        104 :         netdev_unref(network->vrf);
     542         [ -  + ]:        104 :         hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
     543                 :            : 
     544         [ -  + ]:        104 :         while ((route = network->static_routes))
     545                 :          0 :                 route_free(route);
     546                 :            : 
     547         [ +  + ]:        164 :         while ((address = network->static_addresses))
     548                 :         60 :                 address_free(address);
     549                 :            : 
     550         [ -  + ]:        104 :         while ((fdb_entry = network->static_fdb_entries))
     551                 :          0 :                 fdb_entry_free(fdb_entry);
     552                 :            : 
     553         [ -  + ]:        104 :         while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
     554                 :          0 :                 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
     555                 :            : 
     556         [ -  + ]:        104 :         while ((neighbor = network->neighbors))
     557                 :          0 :                 neighbor_free(neighbor);
     558                 :            : 
     559         [ -  + ]:        104 :         while ((label = network->address_labels))
     560                 :          0 :                 address_label_free(label);
     561                 :            : 
     562         [ -  + ]:        104 :         while ((prefix = network->static_prefixes))
     563                 :          0 :                 prefix_free(prefix);
     564                 :            : 
     565         [ -  + ]:        104 :         while ((rule = network->rules))
     566                 :          0 :                 routing_policy_rule_free(rule);
     567                 :            : 
     568                 :        104 :         hashmap_free(network->addresses_by_section);
     569                 :        104 :         hashmap_free(network->routes_by_section);
     570                 :        104 :         hashmap_free(network->fdb_entries_by_section);
     571                 :        104 :         hashmap_free(network->neighbors_by_section);
     572                 :        104 :         hashmap_free(network->address_labels_by_section);
     573                 :        104 :         hashmap_free(network->prefixes_by_section);
     574                 :        104 :         hashmap_free(network->rules_by_section);
     575                 :            : 
     576         [ +  + ]:        104 :         if (network->manager) {
     577   [ +  -  +  - ]:         12 :                 if (network->manager->networks && network->name)
     578                 :         12 :                         ordered_hashmap_remove(network->manager->networks, network->name);
     579                 :            : 
     580         [ -  + ]:         12 :                 if (network->manager->duids_requesting_uuid)
     581                 :          0 :                         set_remove(network->manager->duids_requesting_uuid, &network->duid);
     582                 :            :         }
     583                 :            : 
     584                 :        104 :         free(network->name);
     585                 :            : 
     586                 :        104 :         free(network->dhcp_server_timezone);
     587                 :        104 :         free(network->dhcp_server_dns);
     588                 :        104 :         free(network->dhcp_server_ntp);
     589                 :            : 
     590                 :        104 :         set_free_free(network->dnssec_negative_trust_anchors);
     591                 :            : 
     592                 :        104 :         return mfree(network);
     593                 :            : }
     594                 :            : 
     595   [ +  +  -  +  :        132 : DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
                   -  + ]
     596                 :            : 
     597                 :          0 : int network_get_by_name(Manager *manager, const char *name, Network **ret) {
     598                 :            :         Network *network;
     599                 :            : 
     600         [ #  # ]:          0 :         assert(manager);
     601         [ #  # ]:          0 :         assert(name);
     602         [ #  # ]:          0 :         assert(ret);
     603                 :            : 
     604                 :          0 :         network = ordered_hashmap_get(manager->networks, name);
     605         [ #  # ]:          0 :         if (!network)
     606                 :          0 :                 return -ENOENT;
     607                 :            : 
     608                 :          0 :         *ret = network;
     609                 :            : 
     610                 :          0 :         return 0;
     611                 :            : }
     612                 :            : 
     613                 :          4 : int network_get(Manager *manager, sd_device *device,
     614                 :            :                 const char *ifname, const struct ether_addr *address,
     615                 :            :                 Network **ret) {
     616                 :            :         Network *network;
     617                 :            :         Iterator i;
     618                 :            : 
     619         [ -  + ]:          4 :         assert(manager);
     620         [ -  + ]:          4 :         assert(ret);
     621                 :            : 
     622         [ +  + ]:         12 :         ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
     623         [ -  + ]:          8 :                 if (net_match_config(network->match_mac, network->match_path, network->match_driver,
     624                 :          8 :                                      network->match_type, network->match_name, network->match_property,
     625                 :            :                                      device, address, ifname)) {
     626   [ #  #  #  # ]:          0 :                         if (network->match_name && device) {
     627                 :            :                                 const char *attr;
     628                 :          0 :                                 uint8_t name_assign_type = NET_NAME_UNKNOWN;
     629                 :            : 
     630         [ #  # ]:          0 :                                 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
     631                 :          0 :                                         (void) safe_atou8(attr, &name_assign_type);
     632                 :            : 
     633         [ #  # ]:          0 :                                 if (name_assign_type == NET_NAME_ENUM)
     634         [ #  # ]:          0 :                                         log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
     635                 :            :                                                     ifname, network->filename);
     636                 :            :                                 else
     637         [ #  # ]:          0 :                                         log_debug("%s: found matching network '%s'", ifname, network->filename);
     638                 :            :                         } else
     639         [ #  # ]:          0 :                                 log_debug("%s: found matching network '%s'", ifname, network->filename);
     640                 :            : 
     641                 :          0 :                         *ret = network;
     642                 :          0 :                         return 0;
     643                 :            :                 }
     644                 :            : 
     645                 :          4 :         *ret = NULL;
     646                 :            : 
     647                 :          4 :         return -ENOENT;
     648                 :            : }
     649                 :            : 
     650                 :          0 : int network_apply(Network *network, Link *link) {
     651         [ #  # ]:          0 :         assert(network);
     652         [ #  # ]:          0 :         assert(link);
     653                 :            : 
     654                 :          0 :         link->network = network_ref(network);
     655                 :            : 
     656         [ #  # ]:          0 :         if (network->n_dns > 0 ||
     657         [ #  # ]:          0 :             !strv_isempty(network->ntp) ||
     658         [ #  # ]:          0 :             !ordered_set_isempty(network->search_domains) ||
     659         [ #  # ]:          0 :             !ordered_set_isempty(network->route_domains))
     660                 :          0 :                 link_dirty(link);
     661                 :            : 
     662                 :          0 :         return 0;
     663                 :            : }
     664                 :            : 
     665                 :          0 : bool network_has_static_ipv6_addresses(Network *network) {
     666                 :            :         Address *address;
     667                 :            : 
     668         [ #  # ]:          0 :         assert(network);
     669                 :            : 
     670         [ #  # ]:          0 :         LIST_FOREACH(addresses, address, network->static_addresses) {
     671         [ #  # ]:          0 :                 if (address->family == AF_INET6)
     672                 :          0 :                         return true;
     673                 :            :         }
     674                 :            : 
     675                 :          0 :         return false;
     676                 :            : }
     677                 :            : 
     678                 :          0 : int config_parse_stacked_netdev(const char *unit,
     679                 :            :                 const char *filename,
     680                 :            :                 unsigned line,
     681                 :            :                 const char *section,
     682                 :            :                 unsigned section_line,
     683                 :            :                 const char *lvalue,
     684                 :            :                 int ltype,
     685                 :            :                 const char *rvalue,
     686                 :            :                 void *data,
     687                 :            :                 void *userdata) {
     688                 :          0 :         _cleanup_free_ char *name = NULL;
     689                 :          0 :         NetDevKind kind = ltype;
     690                 :          0 :         Hashmap **h = data;
     691                 :            :         int r;
     692                 :            : 
     693         [ #  # ]:          0 :         assert(filename);
     694         [ #  # ]:          0 :         assert(lvalue);
     695         [ #  # ]:          0 :         assert(rvalue);
     696         [ #  # ]:          0 :         assert(data);
     697   [ #  #  #  # ]:          0 :         assert(IN_SET(kind,
     698                 :            :                       NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
     699                 :            :                       NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
     700                 :            :                       NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
     701                 :            :                       NETDEV_KIND_XFRM));
     702                 :            : 
     703         [ #  # ]:          0 :         if (!ifname_valid(rvalue)) {
     704         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     705                 :            :                            "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
     706                 :          0 :                 return 0;
     707                 :            :         }
     708                 :            : 
     709                 :          0 :         name = strdup(rvalue);
     710         [ #  # ]:          0 :         if (!name)
     711                 :          0 :                 return log_oom();
     712                 :            : 
     713                 :          0 :         r = hashmap_ensure_allocated(h, &string_hash_ops);
     714         [ #  # ]:          0 :         if (r < 0)
     715                 :          0 :                 return log_oom();
     716                 :            : 
     717                 :          0 :         r = hashmap_put(*h, name, INT_TO_PTR(kind));
     718         [ #  # ]:          0 :         if (r < 0)
     719         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     720                 :            :                            "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
     721         [ #  # ]:          0 :         else if (r == 0)
     722         [ #  # ]:          0 :                 log_syntax(unit, LOG_DEBUG, filename, line, r,
     723                 :            :                            "NetDev '%s' specified twice, ignoring.", name);
     724                 :            :         else
     725                 :          0 :                 name = NULL;
     726                 :            : 
     727                 :          0 :         return 0;
     728                 :            : }
     729                 :            : 
     730                 :          0 : int config_parse_domains(
     731                 :            :                 const char *unit,
     732                 :            :                 const char *filename,
     733                 :            :                 unsigned line,
     734                 :            :                 const char *section,
     735                 :            :                 unsigned section_line,
     736                 :            :                 const char *lvalue,
     737                 :            :                 int ltype,
     738                 :            :                 const char *rvalue,
     739                 :            :                 void *data,
     740                 :            :                 void *userdata) {
     741                 :            : 
     742                 :            :         const char *p;
     743                 :          0 :         Network *n = data;
     744                 :            :         int r;
     745                 :            : 
     746         [ #  # ]:          0 :         assert(n);
     747         [ #  # ]:          0 :         assert(lvalue);
     748         [ #  # ]:          0 :         assert(rvalue);
     749                 :            : 
     750         [ #  # ]:          0 :         if (isempty(rvalue)) {
     751                 :          0 :                 n->search_domains = ordered_set_free_free(n->search_domains);
     752                 :          0 :                 n->route_domains = ordered_set_free_free(n->route_domains);
     753                 :          0 :                 return 0;
     754                 :            :         }
     755                 :            : 
     756                 :          0 :         p = rvalue;
     757                 :          0 :         for (;;) {
     758   [ #  #  #  #  :          0 :                 _cleanup_free_ char *w = NULL, *normalized = NULL;
             #  #  #  # ]
     759                 :            :                 const char *domain;
     760                 :            :                 bool is_route;
     761                 :            : 
     762                 :          0 :                 r = extract_first_word(&p, &w, NULL, 0);
     763         [ #  # ]:          0 :                 if (r < 0) {
     764         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
     765                 :            :                                    "Failed to extract search or route domain, ignoring: %s", rvalue);
     766                 :          0 :                         break;
     767                 :            :                 }
     768         [ #  # ]:          0 :                 if (r == 0)
     769                 :          0 :                         break;
     770                 :            : 
     771                 :          0 :                 is_route = w[0] == '~';
     772         [ #  # ]:          0 :                 domain = is_route ? w + 1 : w;
     773                 :            : 
     774   [ #  #  #  # ]:          0 :                 if (dns_name_is_root(domain) || streq(domain, "*")) {
     775                 :            :                         /* If the root domain appears as is, or the special token "*" is found, we'll
     776                 :            :                          * consider this as routing domain, unconditionally. */
     777                 :          0 :                         is_route = true;
     778                 :          0 :                         domain = "."; /* make sure we don't allow empty strings, thus write the root
     779                 :            :                                        * domain as "." */
     780                 :            :                 } else {
     781                 :          0 :                         r = dns_name_normalize(domain, 0, &normalized);
     782         [ #  # ]:          0 :                         if (r < 0) {
     783         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, r,
     784                 :            :                                            "'%s' is not a valid domain name, ignoring.", domain);
     785                 :          0 :                                 continue;
     786                 :            :                         }
     787                 :            : 
     788                 :          0 :                         domain = normalized;
     789                 :            : 
     790         [ #  # ]:          0 :                         if (is_localhost(domain)) {
     791         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, 0,
     792                 :            :                                            "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
     793                 :            :                                            domain);
     794                 :          0 :                                 continue;
     795                 :            :                         }
     796                 :            :                 }
     797                 :            : 
     798         [ #  # ]:          0 :                 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
     799                 :          0 :                 r = ordered_set_ensure_allocated(set, &string_hash_ops);
     800         [ #  # ]:          0 :                 if (r < 0)
     801                 :          0 :                         return r;
     802                 :            : 
     803                 :          0 :                 r = ordered_set_put_strdup(*set, domain);
     804         [ #  # ]:          0 :                 if (r < 0)
     805                 :          0 :                         return log_oom();
     806                 :            :         }
     807                 :            : 
     808                 :          0 :         return 0;
     809                 :            : }
     810                 :            : 
     811                 :          0 : int config_parse_ipv6token(
     812                 :            :                 const char* unit,
     813                 :            :                 const char *filename,
     814                 :            :                 unsigned line,
     815                 :            :                 const char *section,
     816                 :            :                 unsigned section_line,
     817                 :            :                 const char *lvalue,
     818                 :            :                 int ltype,
     819                 :            :                 const char *rvalue,
     820                 :            :                 void *data,
     821                 :            :                 void *userdata) {
     822                 :            : 
     823                 :            :         union in_addr_union buffer;
     824                 :          0 :         struct in6_addr *token = data;
     825                 :            :         int r;
     826                 :            : 
     827         [ #  # ]:          0 :         assert(filename);
     828         [ #  # ]:          0 :         assert(lvalue);
     829         [ #  # ]:          0 :         assert(rvalue);
     830         [ #  # ]:          0 :         assert(token);
     831                 :            : 
     832                 :          0 :         r = in_addr_from_string(AF_INET6, rvalue, &buffer);
     833         [ #  # ]:          0 :         if (r < 0) {
     834         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     835                 :            :                            "Failed to parse IPv6 token, ignoring: %s", rvalue);
     836                 :          0 :                 return 0;
     837                 :            :         }
     838                 :            : 
     839         [ #  # ]:          0 :         if (in_addr_is_null(AF_INET6, &buffer)) {
     840         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     841                 :            :                            "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
     842                 :          0 :                 return 0;
     843                 :            :         }
     844                 :            : 
     845         [ #  # ]:          0 :         if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
     846         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     847                 :            :                            "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
     848                 :          0 :                 return 0;
     849                 :            :         }
     850                 :            : 
     851                 :          0 :         *token = buffer.in6;
     852                 :            : 
     853                 :          0 :         return 0;
     854                 :            : }
     855                 :            : 
     856                 :            : static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
     857                 :            :         [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
     858                 :            :         [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
     859                 :            :         [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
     860                 :            : };
     861                 :            : 
     862   [ +  +  +  + ]:         40 : DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
     863                 :            : 
     864                 :          0 : int config_parse_ipv6_privacy_extensions(
     865                 :            :                 const char* unit,
     866                 :            :                 const char *filename,
     867                 :            :                 unsigned line,
     868                 :            :                 const char *section,
     869                 :            :                 unsigned section_line,
     870                 :            :                 const char *lvalue,
     871                 :            :                 int ltype,
     872                 :            :                 const char *rvalue,
     873                 :            :                 void *data,
     874                 :            :                 void *userdata) {
     875                 :            : 
     876                 :          0 :         IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
     877                 :            :         int k;
     878                 :            : 
     879         [ #  # ]:          0 :         assert(filename);
     880         [ #  # ]:          0 :         assert(lvalue);
     881         [ #  # ]:          0 :         assert(rvalue);
     882         [ #  # ]:          0 :         assert(ipv6_privacy_extensions);
     883                 :            : 
     884                 :            :         /* Our enum shall be a superset of booleans, hence first try
     885                 :            :          * to parse as boolean, and then as enum */
     886                 :            : 
     887                 :          0 :         k = parse_boolean(rvalue);
     888         [ #  # ]:          0 :         if (k > 0)
     889                 :          0 :                 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
     890         [ #  # ]:          0 :         else if (k == 0)
     891                 :          0 :                 *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
     892                 :            :         else {
     893                 :            :                 IPv6PrivacyExtensions s;
     894                 :            : 
     895                 :          0 :                 s = ipv6_privacy_extensions_from_string(rvalue);
     896         [ #  # ]:          0 :                 if (s < 0) {
     897                 :            : 
     898         [ #  # ]:          0 :                         if (streq(rvalue, "kernel"))
     899                 :          0 :                                 s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
     900                 :            :                         else {
     901         [ #  # ]:          0 :                                 log_syntax(unit, LOG_ERR, filename, line, 0,
     902                 :            :                                            "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
     903                 :          0 :                                 return 0;
     904                 :            :                         }
     905                 :            :                 }
     906                 :            : 
     907                 :          0 :                 *ipv6_privacy_extensions = s;
     908                 :            :         }
     909                 :            : 
     910                 :          0 :         return 0;
     911                 :            : }
     912                 :            : 
     913                 :          0 : int config_parse_hostname(
     914                 :            :                 const char *unit,
     915                 :            :                 const char *filename,
     916                 :            :                 unsigned line,
     917                 :            :                 const char *section,
     918                 :            :                 unsigned section_line,
     919                 :            :                 const char *lvalue,
     920                 :            :                 int ltype,
     921                 :            :                 const char *rvalue,
     922                 :            :                 void *data,
     923                 :            :                 void *userdata) {
     924                 :            : 
     925                 :          0 :         _cleanup_free_ char *hn = NULL;
     926                 :          0 :         char **hostname = data;
     927                 :            :         int r;
     928                 :            : 
     929         [ #  # ]:          0 :         assert(filename);
     930         [ #  # ]:          0 :         assert(lvalue);
     931         [ #  # ]:          0 :         assert(rvalue);
     932                 :            : 
     933                 :          0 :         r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
     934         [ #  # ]:          0 :         if (r < 0)
     935                 :          0 :                 return r;
     936                 :            : 
     937         [ #  # ]:          0 :         if (!hostname_is_valid(hn, false)) {
     938         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     939                 :            :                            "Hostname is not valid, ignoring assignment: %s", rvalue);
     940                 :          0 :                 return 0;
     941                 :            :         }
     942                 :            : 
     943                 :          0 :         r = dns_name_is_valid(hn);
     944         [ #  # ]:          0 :         if (r < 0) {
     945         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     946                 :            :                            "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
     947                 :          0 :                 return 0;
     948                 :            :         }
     949         [ #  # ]:          0 :         if (r == 0) {
     950         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     951                 :            :                            "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
     952                 :          0 :                 return 0;
     953                 :            :         }
     954                 :            : 
     955                 :          0 :         return free_and_replace(*hostname, hn);
     956                 :            : }
     957                 :            : 
     958                 :          0 : int config_parse_timezone(
     959                 :            :                 const char *unit,
     960                 :            :                 const char *filename,
     961                 :            :                 unsigned line,
     962                 :            :                 const char *section,
     963                 :            :                 unsigned section_line,
     964                 :            :                 const char *lvalue,
     965                 :            :                 int ltype,
     966                 :            :                 const char *rvalue,
     967                 :            :                 void *data,
     968                 :            :                 void *userdata) {
     969                 :            : 
     970                 :          0 :         _cleanup_free_ char *tz = NULL;
     971                 :          0 :         char **datap = data;
     972                 :            :         int r;
     973                 :            : 
     974         [ #  # ]:          0 :         assert(filename);
     975         [ #  # ]:          0 :         assert(lvalue);
     976         [ #  # ]:          0 :         assert(rvalue);
     977                 :            : 
     978                 :          0 :         r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
     979         [ #  # ]:          0 :         if (r < 0)
     980                 :          0 :                 return r;
     981                 :            : 
     982         [ #  # ]:          0 :         if (!timezone_is_valid(tz, LOG_ERR)) {
     983         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     984                 :            :                            "Timezone is not valid, ignoring assignment: %s", rvalue);
     985                 :          0 :                 return 0;
     986                 :            :         }
     987                 :            : 
     988                 :          0 :         return free_and_replace(*datap, tz);
     989                 :            : }
     990                 :            : 
     991                 :          0 : int config_parse_dns(
     992                 :            :                 const char *unit,
     993                 :            :                 const char *filename,
     994                 :            :                 unsigned line,
     995                 :            :                 const char *section,
     996                 :            :                 unsigned section_line,
     997                 :            :                 const char *lvalue,
     998                 :            :                 int ltype,
     999                 :            :                 const char *rvalue,
    1000                 :            :                 void *data,
    1001                 :            :                 void *userdata) {
    1002                 :            : 
    1003                 :          0 :         Network *n = userdata;
    1004                 :            :         int r;
    1005                 :            : 
    1006         [ #  # ]:          0 :         assert(filename);
    1007         [ #  # ]:          0 :         assert(lvalue);
    1008         [ #  # ]:          0 :         assert(rvalue);
    1009                 :            : 
    1010                 :          0 :         for (;;) {
    1011   [ #  #  #  # ]:          0 :                 _cleanup_free_ char *w = NULL;
    1012                 :            :                 union in_addr_union a;
    1013                 :            :                 struct in_addr_data *m;
    1014                 :            :                 int family;
    1015                 :            : 
    1016                 :          0 :                 r = extract_first_word(&rvalue, &w, NULL, 0);
    1017         [ #  # ]:          0 :                 if (r == -ENOMEM)
    1018                 :          0 :                         return log_oom();
    1019         [ #  # ]:          0 :                 if (r < 0) {
    1020         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1021                 :            :                                    "Invalid syntax, ignoring: %s", rvalue);
    1022                 :          0 :                         break;
    1023                 :            :                 }
    1024         [ #  # ]:          0 :                 if (r == 0)
    1025                 :          0 :                         break;
    1026                 :            : 
    1027                 :          0 :                 r = in_addr_from_string_auto(w, &family, &a);
    1028         [ #  # ]:          0 :                 if (r < 0) {
    1029         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1030                 :            :                                    "Failed to parse dns server address, ignoring: %s", w);
    1031                 :          0 :                         continue;
    1032                 :            :                 }
    1033                 :            : 
    1034                 :          0 :                 m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
    1035         [ #  # ]:          0 :                 if (!m)
    1036                 :          0 :                         return log_oom();
    1037                 :            : 
    1038                 :          0 :                 m[n->n_dns++] = (struct in_addr_data) {
    1039                 :            :                         .family = family,
    1040                 :            :                         .address = a,
    1041                 :            :                 };
    1042                 :            : 
    1043                 :          0 :                 n->dns = m;
    1044                 :            :         }
    1045                 :            : 
    1046                 :          0 :         return 0;
    1047                 :            : }
    1048                 :            : 
    1049                 :          0 : int config_parse_dnssec_negative_trust_anchors(
    1050                 :            :                 const char *unit,
    1051                 :            :                 const char *filename,
    1052                 :            :                 unsigned line,
    1053                 :            :                 const char *section,
    1054                 :            :                 unsigned section_line,
    1055                 :            :                 const char *lvalue,
    1056                 :            :                 int ltype,
    1057                 :            :                 const char *rvalue,
    1058                 :            :                 void *data,
    1059                 :            :                 void *userdata) {
    1060                 :            : 
    1061                 :          0 :         const char *p = rvalue;
    1062                 :          0 :         Network *n = data;
    1063                 :            :         int r;
    1064                 :            : 
    1065         [ #  # ]:          0 :         assert(n);
    1066         [ #  # ]:          0 :         assert(lvalue);
    1067         [ #  # ]:          0 :         assert(rvalue);
    1068                 :            : 
    1069         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1070                 :          0 :                 n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
    1071                 :          0 :                 return 0;
    1072                 :            :         }
    1073                 :            : 
    1074                 :          0 :         for (;;) {
    1075   [ #  #  #  # ]:          0 :                 _cleanup_free_ char *w = NULL;
    1076                 :            : 
    1077                 :          0 :                 r = extract_first_word(&p, &w, NULL, 0);
    1078         [ #  # ]:          0 :                 if (r < 0) {
    1079         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1080                 :            :                                    "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
    1081                 :          0 :                         break;
    1082                 :            :                 }
    1083         [ #  # ]:          0 :                 if (r == 0)
    1084                 :          0 :                         break;
    1085                 :            : 
    1086                 :          0 :                 r = dns_name_is_valid(w);
    1087         [ #  # ]:          0 :                 if (r <= 0) {
    1088         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1089                 :            :                                    "%s is not a valid domain name, ignoring.", w);
    1090                 :          0 :                         continue;
    1091                 :            :                 }
    1092                 :            : 
    1093                 :          0 :                 r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
    1094         [ #  # ]:          0 :                 if (r < 0)
    1095                 :          0 :                         return log_oom();
    1096                 :            : 
    1097                 :          0 :                 r = set_put(n->dnssec_negative_trust_anchors, w);
    1098         [ #  # ]:          0 :                 if (r < 0)
    1099                 :          0 :                         return log_oom();
    1100         [ #  # ]:          0 :                 if (r > 0)
    1101                 :          0 :                         w = NULL;
    1102                 :            :         }
    1103                 :            : 
    1104                 :          0 :         return 0;
    1105                 :            : }
    1106                 :            : 
    1107                 :          0 : int config_parse_ntp(
    1108                 :            :                 const char *unit,
    1109                 :            :                 const char *filename,
    1110                 :            :                 unsigned line,
    1111                 :            :                 const char *section,
    1112                 :            :                 unsigned section_line,
    1113                 :            :                 const char *lvalue,
    1114                 :            :                 int ltype,
    1115                 :            :                 const char *rvalue,
    1116                 :            :                 void *data,
    1117                 :            :                 void *userdata) {
    1118                 :            : 
    1119                 :          0 :         char ***l = data;
    1120                 :            :         int r;
    1121                 :            : 
    1122         [ #  # ]:          0 :         assert(l);
    1123         [ #  # ]:          0 :         assert(lvalue);
    1124         [ #  # ]:          0 :         assert(rvalue);
    1125                 :            : 
    1126         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1127                 :          0 :                 *l = strv_free(*l);
    1128                 :          0 :                 return 0;
    1129                 :            :         }
    1130                 :            : 
    1131                 :          0 :         for (;;) {
    1132   [ #  #  #  # ]:          0 :                 _cleanup_free_ char *w = NULL;
    1133                 :            : 
    1134                 :          0 :                 r = extract_first_word(&rvalue, &w, NULL, 0);
    1135         [ #  # ]:          0 :                 if (r == -ENOMEM)
    1136                 :          0 :                         return log_oom();
    1137         [ #  # ]:          0 :                 if (r < 0) {
    1138         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1139                 :            :                                    "Failed to extract NTP server name, ignoring: %s", rvalue);
    1140                 :          0 :                         break;
    1141                 :            :                 }
    1142         [ #  # ]:          0 :                 if (r == 0)
    1143                 :          0 :                         break;
    1144                 :            : 
    1145                 :          0 :                 r = dns_name_is_valid_or_address(w);
    1146         [ #  # ]:          0 :                 if (r <= 0) {
    1147         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1148                 :            :                                    "%s is not a valid domain name or IP address, ignoring.", w);
    1149                 :          0 :                         continue;
    1150                 :            :                 }
    1151                 :            : 
    1152         [ #  # ]:          0 :                 if (strv_length(*l) > MAX_NTP_SERVERS) {
    1153         [ #  # ]:          0 :                         log_syntax(unit, LOG_WARNING, filename, line, 0,
    1154                 :            :                                    "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
    1155                 :            :                                    MAX_NTP_SERVERS, w);
    1156                 :          0 :                         break;
    1157                 :            :                 }
    1158                 :            : 
    1159                 :          0 :                 r = strv_consume(l, TAKE_PTR(w));
    1160         [ #  # ]:          0 :                 if (r < 0)
    1161                 :          0 :                         return log_oom();
    1162                 :            :         }
    1163                 :            : 
    1164                 :          0 :         return 0;
    1165                 :            : }
    1166                 :            : 
    1167                 :          0 : int config_parse_required_for_online(
    1168                 :            :                 const char *unit,
    1169                 :            :                 const char *filename,
    1170                 :            :                 unsigned line,
    1171                 :            :                 const char *section,
    1172                 :            :                 unsigned section_line,
    1173                 :            :                 const char *lvalue,
    1174                 :            :                 int ltype,
    1175                 :            :                 const char *rvalue,
    1176                 :            :                 void *data,
    1177                 :            :                 void *userdata) {
    1178                 :            : 
    1179                 :          0 :         Network *network = data;
    1180                 :            :         LinkOperationalState s;
    1181                 :          0 :         bool required = true;
    1182                 :            :         int r;
    1183                 :            : 
    1184         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1185                 :          0 :                 network->required_for_online = true;
    1186                 :          0 :                 network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED;
    1187                 :          0 :                 return 0;
    1188                 :            :         }
    1189                 :            : 
    1190                 :          0 :         s = link_operstate_from_string(rvalue);
    1191         [ #  # ]:          0 :         if (s < 0) {
    1192                 :          0 :                 r = parse_boolean(rvalue);
    1193         [ #  # ]:          0 :                 if (r < 0) {
    1194         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1195                 :            :                                    "Failed to parse %s= setting, ignoring assignment: %s",
    1196                 :            :                                    lvalue, rvalue);
    1197                 :          0 :                         return 0;
    1198                 :            :                 }
    1199                 :            : 
    1200                 :          0 :                 required = r;
    1201                 :          0 :                 s = LINK_OPERSTATE_DEGRADED;
    1202                 :            :         }
    1203                 :            : 
    1204                 :          0 :         network->required_for_online = required;
    1205                 :          0 :         network->required_operstate_for_online = s;
    1206                 :            : 
    1207                 :          0 :         return 0;
    1208                 :            : }
    1209                 :            : 
    1210   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
          #  #  #  #  #  
                #  #  # ]
    1211                 :            :                          "Failed to parse KeepConfiguration= setting");
    1212                 :            : 
    1213                 :            : static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
    1214                 :            :         [KEEP_CONFIGURATION_NO]           = "no",
    1215                 :            :         [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop",
    1216                 :            :         [KEEP_CONFIGURATION_DHCP]         = "dhcp",
    1217                 :            :         [KEEP_CONFIGURATION_STATIC]       = "static",
    1218                 :            :         [KEEP_CONFIGURATION_YES]          = "yes",
    1219                 :            : };
    1220                 :            : 
    1221   [ #  #  #  #  :          0 : DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
                   #  # ]

Generated by: LCOV version 1.14