LCOV - code coverage report
Current view: top level - network - networkd-network.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 163 539 30.2 %
Date: 2019-08-22 15:41:25 Functions: 11 28 39.3 %

          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           3 : void network_apply_anonymize_if_set(Network *network) {
      31           3 :         if (!network->dhcp_anonymize)
      32           3 :                 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          75 : 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          75 :         if (!name)
      75          75 :                 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          25 : static int network_resolve_stacked_netdevs(Network *network) {
     118             :         void *name, *kind;
     119             :         Iterator i;
     120             :         int r;
     121             : 
     122          25 :         assert(network);
     123             : 
     124          25 :         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          25 :         return 0;
     144             : }
     145             : 
     146          26 : 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          26 :         assert(network);
     156          26 :         assert(network->filename);
     157             : 
     158          52 :         if (set_isempty(network->match_mac) && strv_isempty(network->match_path) &&
     159          74 :             strv_isempty(network->match_driver) && strv_isempty(network->match_type) &&
     160          24 :             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          26 :         if (!condition_test_list(network->conditions, NULL, NULL, NULL))
     169           1 :                 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          25 :         (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
     174          25 :         (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
     175          25 :         (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
     176          25 :         (void) network_resolve_stacked_netdevs(network);
     177             : 
     178             :         /* Free unnecessary entries. */
     179          25 :         network->bond_name = mfree(network->bond_name);
     180          25 :         network->bridge_name = mfree(network->bridge_name);
     181          25 :         network->vrf_name = mfree(network->vrf_name);
     182          25 :         network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
     183             : 
     184          25 :         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          25 :         if (network->link_local < 0)
     221           0 :                 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
     222             : 
     223          25 :         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          25 :         if (network->ipv6_accept_ra < 0 && network->bridge)
     231           0 :                 network->ipv6_accept_ra = false;
     232             : 
     233             :         /* IPMasquerade=yes implies IPForward=yes */
     234          25 :         if (network->ip_masquerade)
     235           2 :                 network->ip_forward |= ADDRESS_FAMILY_IPV4;
     236             : 
     237          25 :         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          25 :         if (network->dhcp_critical >= 0) {
     244          23 :                 if (network->keep_configuration >= 0)
     245          23 :                         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          25 :         if (network->keep_configuration < 0)
     256             :                 /* For backward compatibility, we do not release DHCP addresses on manager stop. */
     257           2 :                 network->keep_configuration = KEEP_CONFIGURATION_DHCP_ON_STOP;
     258             : 
     259          50 :         LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
     260          25 :                 if (address_section_verify(address) < 0)
     261          10 :                         address_free(address);
     262             : 
     263          25 :         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          25 :         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          25 :         LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
     272           0 :                 if (neighbor_section_verify(neighbor) < 0)
     273           0 :                         neighbor_free(neighbor);
     274             : 
     275          25 :         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          25 :         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          25 :         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          25 :         return 0;
     288             : }
     289             : 
     290           3 : int network_load_one(Manager *manager, const char *filename) {
     291           3 :         _cleanup_free_ char *fname = NULL, *name = NULL;
     292           3 :         _cleanup_(network_unrefp) Network *network = NULL;
     293           3 :         _cleanup_fclose_ FILE *file = NULL;
     294             :         const char *dropin_dirname;
     295             :         char *d;
     296             :         int r;
     297             : 
     298           3 :         assert(manager);
     299           3 :         assert(filename);
     300             : 
     301           3 :         file = fopen(filename, "re");
     302           3 :         if (!file) {
     303           0 :                 if (errno == ENOENT)
     304           0 :                         return 0;
     305             : 
     306           0 :                 return -errno;
     307             :         }
     308             : 
     309           3 :         if (null_or_empty_fd(fileno(file))) {
     310           0 :                 log_debug("Skipping empty file: %s", filename);
     311           0 :                 return 0;
     312             :         }
     313             : 
     314           3 :         fname = strdup(filename);
     315           3 :         if (!fname)
     316           0 :                 return log_oom();
     317             : 
     318           3 :         name = strdup(basename(filename));
     319           3 :         if (!name)
     320           0 :                 return log_oom();
     321             : 
     322           3 :         d = strrchr(name, '.');
     323           3 :         if (!d)
     324           0 :                 return -EINVAL;
     325             : 
     326           3 :         *d = '\0';
     327             : 
     328          15 :         dropin_dirname = strjoina(name, ".network.d");
     329             : 
     330           3 :         network = new(Network, 1);
     331           3 :         if (!network)
     332           0 :                 return log_oom();
     333             : 
     334           6 :         *network = (Network) {
     335           3 :                 .filename = TAKE_PTR(fname),
     336           3 :                 .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           3 :         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           3 :         if (r < 0)
     445           0 :                 return r;
     446             : 
     447           3 :         network_apply_anonymize_if_set(network);
     448             : 
     449           3 :         r = network_add_ipv4ll_route(network);
     450           3 :         if (r < 0)
     451           0 :                 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
     452             : 
     453           3 :         r = network_add_default_route_on_device(network);
     454           3 :         if (r < 0)
     455           0 :                 log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
     456             :                                   network->filename);
     457             : 
     458           3 :         r = ordered_hashmap_ensure_allocated(&manager->networks, &string_hash_ops);
     459           3 :         if (r < 0)
     460           0 :                 return r;
     461             : 
     462           3 :         r = ordered_hashmap_put(manager->networks, network->name, network);
     463           3 :         if (r < 0)
     464           0 :                 return r;
     465             : 
     466           3 :         if (network_verify(network) < 0)
     467           1 :                 return 0;
     468             : 
     469           2 :         network = NULL;
     470           2 :         return 0;
     471             : }
     472             : 
     473           1 : int network_load(Manager *manager) {
     474           1 :         _cleanup_strv_free_ char **files = NULL;
     475             :         char **f;
     476             :         int r;
     477             : 
     478           1 :         assert(manager);
     479             : 
     480           1 :         ordered_hashmap_clear_with_destructor(manager->networks, network_unref);
     481             : 
     482           1 :         r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
     483           1 :         if (r < 0)
     484           0 :                 return log_error_errno(r, "Failed to enumerate network files: %m");
     485             : 
     486           4 :         STRV_FOREACH(f, files) {
     487           3 :                 r = network_load_one(manager, *f);
     488           3 :                 if (r < 0)
     489           0 :                         return r;
     490             :         }
     491             : 
     492           1 :         return 0;
     493             : }
     494             : 
     495          26 : 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          26 :         if (!network)
     506           0 :                 return NULL;
     507             : 
     508          26 :         free(network->filename);
     509             : 
     510          26 :         set_free_free(network->match_mac);
     511          26 :         strv_free(network->match_path);
     512          26 :         strv_free(network->match_driver);
     513          26 :         strv_free(network->match_type);
     514          26 :         strv_free(network->match_name);
     515          26 :         strv_free(network->match_property);
     516          26 :         condition_free_list(network->conditions);
     517             : 
     518          26 :         free(network->description);
     519          26 :         free(network->dhcp_vendor_class_identifier);
     520          26 :         strv_free(network->dhcp_user_class);
     521          26 :         free(network->dhcp_hostname);
     522          26 :         set_free(network->dhcp_black_listed_ip);
     523          26 :         free(network->mac);
     524             : 
     525          26 :         strv_free(network->ntp);
     526          26 :         free(network->dns);
     527          26 :         ordered_set_free_free(network->search_domains);
     528          26 :         ordered_set_free_free(network->route_domains);
     529          26 :         strv_free(network->bind_carrier);
     530             : 
     531          26 :         ordered_set_free_free(network->router_search_domains);
     532          26 :         free(network->router_dns);
     533          26 :         set_free_free(network->ndisc_black_listed_prefix);
     534             : 
     535          26 :         free(network->bridge_name);
     536          26 :         free(network->bond_name);
     537          26 :         free(network->vrf_name);
     538          26 :         hashmap_free_free_key(network->stacked_netdev_names);
     539          26 :         netdev_unref(network->bridge);
     540          26 :         netdev_unref(network->bond);
     541          26 :         netdev_unref(network->vrf);
     542          26 :         hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
     543             : 
     544          26 :         while ((route = network->static_routes))
     545           0 :                 route_free(route);
     546             : 
     547          41 :         while ((address = network->static_addresses))
     548          15 :                 address_free(address);
     549             : 
     550          26 :         while ((fdb_entry = network->static_fdb_entries))
     551           0 :                 fdb_entry_free(fdb_entry);
     552             : 
     553          26 :         while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
     554           0 :                 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
     555             : 
     556          26 :         while ((neighbor = network->neighbors))
     557           0 :                 neighbor_free(neighbor);
     558             : 
     559          26 :         while ((label = network->address_labels))
     560           0 :                 address_label_free(label);
     561             : 
     562          26 :         while ((prefix = network->static_prefixes))
     563           0 :                 prefix_free(prefix);
     564             : 
     565          26 :         while ((rule = network->rules))
     566           0 :                 routing_policy_rule_free(rule);
     567             : 
     568          26 :         hashmap_free(network->addresses_by_section);
     569          26 :         hashmap_free(network->routes_by_section);
     570          26 :         hashmap_free(network->fdb_entries_by_section);
     571          26 :         hashmap_free(network->neighbors_by_section);
     572          26 :         hashmap_free(network->address_labels_by_section);
     573          26 :         hashmap_free(network->prefixes_by_section);
     574          26 :         hashmap_free(network->rules_by_section);
     575             : 
     576          26 :         if (network->manager) {
     577           3 :                 if (network->manager->networks && network->name)
     578           3 :                         ordered_hashmap_remove(network->manager->networks, network->name);
     579             : 
     580           3 :                 if (network->manager->duids_requesting_uuid)
     581           0 :                         set_remove(network->manager->duids_requesting_uuid, &network->duid);
     582             :         }
     583             : 
     584          26 :         free(network->name);
     585             : 
     586          26 :         free(network->dhcp_server_timezone);
     587          26 :         free(network->dhcp_server_dns);
     588          26 :         free(network->dhcp_server_ntp);
     589             : 
     590          26 :         set_free_free(network->dnssec_negative_trust_anchors);
     591             : 
     592          26 :         return mfree(network);
     593             : }
     594             : 
     595          32 : 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           1 : 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           1 :         assert(manager);
     620           1 :         assert(ret);
     621             : 
     622           3 :         ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
     623           2 :                 if (net_match_config(network->match_mac, network->match_path, network->match_driver,
     624           2 :                                      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           1 :         *ret = NULL;
     646             : 
     647           1 :         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          10 : 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