LCOV - code coverage report
Current view: top level - network - networkd-dhcp4.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 5 794 0.6 %
Date: 2019-08-23 13:36:53 Functions: 1 30 3.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 978 0.2 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <netinet/in.h>
       4                 :            : #include <linux/if.h>
       5                 :            : #include <linux/if_arp.h>
       6                 :            : 
       7                 :            : #include "alloc-util.h"
       8                 :            : #include "hostname-util.h"
       9                 :            : #include "parse-util.h"
      10                 :            : #include "network-internal.h"
      11                 :            : #include "networkd-dhcp4.h"
      12                 :            : #include "networkd-link.h"
      13                 :            : #include "networkd-manager.h"
      14                 :            : #include "networkd-network.h"
      15                 :            : #include "string-table.h"
      16                 :            : #include "string-util.h"
      17                 :            : #include "sysctl-util.h"
      18                 :            : 
      19                 :            : static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all);
      20                 :            : static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all);
      21                 :            : static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all);
      22                 :            : static int dhcp_remove_address(Link *link, sd_dhcp_lease *lease, const struct in_addr *address);
      23                 :            : 
      24                 :         28 : void dhcp4_release_old_lease(Link *link) {
      25                 :         28 :         struct in_addr address = {}, address_old = {};
      26                 :            : 
      27         [ -  + ]:         28 :         assert(link);
      28                 :            : 
      29         [ +  - ]:         28 :         if (!link->dhcp_lease_old)
      30                 :         28 :                 return;
      31                 :            : 
      32         [ #  # ]:          0 :         assert(link->dhcp_lease);
      33                 :            : 
      34                 :          0 :         (void) sd_dhcp_lease_get_address(link->dhcp_lease_old, &address_old);
      35                 :          0 :         (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
      36                 :            : 
      37                 :          0 :         (void) dhcp_remove_routes(link, link->dhcp_lease_old, &address_old, false);
      38                 :          0 :         (void) dhcp_remove_router(link, link->dhcp_lease_old, &address_old, false);
      39                 :          0 :         (void) dhcp_remove_dns_routes(link, link->dhcp_lease_old, &address_old, false);
      40                 :            : 
      41         [ #  # ]:          0 :         if (!in4_addr_equal(&address_old, &address))
      42                 :          0 :                 (void) dhcp_remove_address(link, link->dhcp_lease_old, &address_old);
      43                 :            : 
      44                 :          0 :         link->dhcp_lease_old = sd_dhcp_lease_unref(link->dhcp_lease_old);
      45                 :          0 :         link_dirty(link);
      46                 :            : }
      47                 :            : 
      48                 :          0 : static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
      49                 :            :         int r;
      50                 :            : 
      51         [ #  # ]:          0 :         assert(link);
      52         [ #  # ]:          0 :         assert(link->dhcp4_messages > 0);
      53                 :            : 
      54                 :          0 :         link->dhcp4_messages--;
      55                 :            : 
      56   [ #  #  #  # ]:          0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
      57                 :          0 :                 return 1;
      58                 :            : 
      59                 :          0 :         r = sd_netlink_message_get_errno(m);
      60   [ #  #  #  # ]:          0 :         if (r < 0 && r != -EEXIST) {
      61   [ #  #  #  # ]:          0 :                 log_link_error_errno(link, r, "Could not set DHCPv4 route: %m");
      62                 :          0 :                 link_enter_failed(link);
      63                 :          0 :                 return 1;
      64                 :            :         }
      65                 :            : 
      66         [ #  # ]:          0 :         if (link->dhcp4_messages == 0) {
      67                 :          0 :                 link->dhcp4_configured = true;
      68                 :            :                 /* New address and routes are configured now. Let's release old lease. */
      69                 :          0 :                 dhcp4_release_old_lease(link);
      70                 :          0 :                 link_check_ready(link);
      71                 :            :         }
      72                 :            : 
      73                 :          0 :         return 1;
      74                 :            : }
      75                 :            : 
      76                 :          0 : static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
      77         [ #  # ]:          0 :         assert(route);
      78         [ #  # ]:          0 :         assert(self_addr);
      79                 :            : 
      80         [ #  # ]:          0 :         if (in4_addr_is_localhost(&route->dst.in) ||
      81   [ #  #  #  # ]:          0 :             (!in4_addr_is_null(self_addr) && in4_addr_equal(&route->dst.in, self_addr)))
      82                 :          0 :                 return RT_SCOPE_HOST;
      83         [ #  # ]:          0 :         else if (in4_addr_is_null(&route->gw.in))
      84                 :          0 :                 return RT_SCOPE_LINK;
      85                 :            :         else
      86                 :          0 :                 return RT_SCOPE_UNIVERSE;
      87                 :            : }
      88                 :            : 
      89                 :          0 : static int dhcp_route_configure(Route **route, Link *link) {
      90                 :            :         int r;
      91                 :            : 
      92         [ #  # ]:          0 :         assert(route);
      93         [ #  # ]:          0 :         assert(*route);
      94         [ #  # ]:          0 :         assert(link);
      95                 :            : 
      96         [ #  # ]:          0 :         if (set_contains(link->dhcp_routes, *route))
      97                 :          0 :                 return 0;
      98                 :            : 
      99                 :          0 :         r = route_configure(*route, link, dhcp4_route_handler);
     100         [ #  # ]:          0 :         if (r <= 0)
     101                 :          0 :                 return r;
     102                 :            : 
     103                 :          0 :         link->dhcp4_messages++;
     104                 :            : 
     105                 :          0 :         r = set_put(link->dhcp_routes, *route);
     106         [ #  # ]:          0 :         if (r < 0)
     107                 :          0 :                 return r;
     108                 :            : 
     109                 :          0 :         TAKE_PTR(*route);
     110                 :          0 :         return 0;
     111                 :            : }
     112                 :            : 
     113                 :          0 : static int link_set_dns_routes(Link *link, const struct in_addr *address) {
     114                 :            :         const struct in_addr *dns;
     115                 :            :         uint32_t table;
     116                 :            :         int i, n, r;
     117                 :            : 
     118         [ #  # ]:          0 :         assert(link);
     119         [ #  # ]:          0 :         assert(link->dhcp_lease);
     120         [ #  # ]:          0 :         assert(link->network);
     121                 :            : 
     122         [ #  # ]:          0 :         if (!link->network->dhcp_use_dns ||
     123         [ #  # ]:          0 :             !link->network->dhcp_routes_to_dns)
     124                 :          0 :                 return 0;
     125                 :            : 
     126                 :          0 :         n = sd_dhcp_lease_get_dns(link->dhcp_lease, &dns);
     127   [ #  #  #  # ]:          0 :         if (IN_SET(n, 0, -ENODATA))
     128                 :          0 :                 return 0;
     129         [ #  # ]:          0 :         if (n < 0)
     130   [ #  #  #  # ]:          0 :                 return log_link_warning_errno(link, n, "DHCP error: could not get DNS servers: %m");
     131                 :            : 
     132                 :          0 :         table = link_get_dhcp_route_table(link);
     133                 :            : 
     134         [ #  # ]:          0 :         for (i = 0; i < n; i ++) {
     135         [ #  # ]:          0 :                 _cleanup_(route_freep) Route *route = NULL;
     136                 :            : 
     137                 :          0 :                 r = route_new(&route);
     138         [ #  # ]:          0 :                 if (r < 0)
     139   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r,  "Could not allocate route: %m");
     140                 :            : 
     141                 :            :                 /* Set routes to DNS servers. */
     142                 :            : 
     143                 :          0 :                 route->family = AF_INET;
     144                 :          0 :                 route->dst.in = dns[i];
     145                 :          0 :                 route->dst_prefixlen = 32;
     146                 :          0 :                 route->prefsrc.in = *address;
     147                 :          0 :                 route->scope = RT_SCOPE_LINK;
     148                 :          0 :                 route->protocol = RTPROT_DHCP;
     149                 :          0 :                 route->priority = link->network->dhcp_route_metric;
     150                 :          0 :                 route->table = table;
     151                 :            : 
     152                 :          0 :                 r = dhcp_route_configure(&route, link);
     153         [ #  # ]:          0 :                 if (r < 0)
     154   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not set route to DNS server: %m");
     155                 :            :         }
     156                 :            : 
     157                 :          0 :         return 0;
     158                 :            : }
     159                 :            : 
     160                 :          0 : static int link_set_dhcp_routes(Link *link) {
     161                 :          0 :         _cleanup_free_ sd_dhcp_route **static_routes = NULL;
     162                 :          0 :         bool classless_route = false, static_route = false;
     163                 :            :         const struct in_addr *router;
     164                 :            :         struct in_addr address;
     165                 :            :         int r, n, i;
     166                 :            :         uint32_t table;
     167                 :            : 
     168         [ #  # ]:          0 :         assert(link);
     169                 :            : 
     170         [ #  # ]:          0 :         if (!link->dhcp_lease) /* link went down while we configured the IP addresses? */
     171                 :          0 :                 return 0;
     172                 :            : 
     173         [ #  # ]:          0 :         if (!link->network) /* link went down while we configured the IP addresses? */
     174                 :          0 :                 return 0;
     175                 :            : 
     176         [ #  # ]:          0 :         if (!link->network->dhcp_use_routes)
     177                 :          0 :                 return 0;
     178                 :            : 
     179   [ #  #  #  # ]:          0 :         if (!link_has_carrier(link) && !link->network->configure_without_carrier)
     180                 :            :                 /* During configuring addresses, the link lost its carrier. As networkd is dropping
     181                 :            :                  * the addresses now, let's not configure the routes either. */
     182                 :          0 :                 return 0;
     183                 :            : 
     184                 :          0 :         r = set_ensure_allocated(&link->dhcp_routes, &route_full_hash_ops);
     185         [ #  # ]:          0 :         if (r < 0)
     186                 :          0 :                 return log_oom();
     187                 :            : 
     188                 :            :         /* Clear old entries in case the set was already allocated */
     189                 :          0 :         set_clear(link->dhcp_routes);
     190                 :            : 
     191                 :          0 :         table = link_get_dhcp_route_table(link);
     192                 :            : 
     193                 :          0 :         r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
     194         [ #  # ]:          0 :         if (r < 0)
     195   [ #  #  #  # ]:          0 :                 return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
     196                 :            : 
     197                 :          0 :         n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
     198         [ #  # ]:          0 :         if (n == -ENODATA)
     199   [ #  #  #  # ]:          0 :                 log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m");
     200         [ #  # ]:          0 :         else if (n < 0)
     201   [ #  #  #  # ]:          0 :                 log_link_debug_errno(link, n, "DHCP error: could not get routes: %m");
     202                 :            : 
     203         [ #  # ]:          0 :         for (i = 0; i < n; i++) {
     204      [ #  #  # ]:          0 :                 switch (sd_dhcp_route_get_option(static_routes[i])) {
     205                 :          0 :                 case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
     206                 :          0 :                         classless_route = true;
     207                 :          0 :                         break;
     208                 :          0 :                 case SD_DHCP_OPTION_STATIC_ROUTE:
     209                 :          0 :                         static_route = true;
     210                 :          0 :                         break;
     211                 :            :                 }
     212                 :          0 :         }
     213                 :            : 
     214         [ #  # ]:          0 :         for (i = 0; i < n; i++) {
     215      [ #  #  # ]:          0 :                 _cleanup_(route_freep) Route *route = NULL;
     216                 :            : 
     217                 :            :                 /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option,
     218                 :            :                    the DHCP client MUST ignore the Static Routes option. */
     219   [ #  #  #  # ]:          0 :                 if (classless_route &&
     220                 :          0 :                     sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE)
     221                 :          0 :                         continue;
     222                 :            : 
     223                 :          0 :                 r = route_new(&route);
     224         [ #  # ]:          0 :                 if (r < 0)
     225   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not allocate route: %m");
     226                 :            : 
     227                 :          0 :                 route->family = AF_INET;
     228                 :          0 :                 route->protocol = RTPROT_DHCP;
     229         [ #  # ]:          0 :                 assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
     230         [ #  # ]:          0 :                 assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
     231         [ #  # ]:          0 :                 assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
     232                 :          0 :                 route->priority = link->network->dhcp_route_metric;
     233                 :          0 :                 route->table = table;
     234                 :          0 :                 route->scope = route_scope_from_address(route, &address);
     235   [ #  #  #  # ]:          0 :                 if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
     236                 :          0 :                         route->prefsrc.in = address;
     237                 :            : 
     238         [ #  # ]:          0 :                 if (set_contains(link->dhcp_routes, route))
     239                 :          0 :                         continue;
     240                 :            : 
     241                 :          0 :                 r = dhcp_route_configure(&route, link);
     242         [ #  # ]:          0 :                 if (r < 0)
     243   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not set route: %m");
     244                 :            :         }
     245                 :            : 
     246                 :          0 :         r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
     247   [ #  #  #  # ]:          0 :         if (IN_SET(r, 0, -ENODATA))
     248   [ #  #  #  # ]:          0 :                 log_link_info(link, "DHCP: No gateway received from DHCP server.");
     249         [ #  # ]:          0 :         else if (r < 0)
     250   [ #  #  #  # ]:          0 :                 log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
     251         [ #  # ]:          0 :         else if (in4_addr_is_null(&router[0]))
     252   [ #  #  #  # ]:          0 :                 log_link_info(link, "DHCP: Received gateway is null.");
     253                 :            : 
     254                 :            :         /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
     255                 :            :            a Router option, the DHCP client MUST ignore the Router option. */
     256   [ #  #  #  # ]:          0 :         if (classless_route && static_route)
     257   [ #  #  #  # ]:          0 :                 log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option");
     258                 :            : 
     259   [ #  #  #  #  :          0 :         if (r > 0 && !classless_route && !in4_addr_is_null(&router[0])) {
                   #  # ]
     260   [ #  #  #  # ]:          0 :                 _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL;
     261                 :            : 
     262                 :          0 :                 r = route_new(&route_gw);
     263         [ #  # ]:          0 :                 if (r < 0)
     264   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r,  "Could not allocate route: %m");
     265                 :            : 
     266                 :            :                 /* The dhcp netmask may mask out the gateway. Add an explicit
     267                 :            :                  * route for the gw host so that we can route no matter the
     268                 :            :                  * netmask or existing kernel route tables. */
     269                 :          0 :                 route_gw->family = AF_INET;
     270                 :          0 :                 route_gw->dst.in = router[0];
     271                 :          0 :                 route_gw->dst_prefixlen = 32;
     272                 :          0 :                 route_gw->prefsrc.in = address;
     273                 :          0 :                 route_gw->scope = RT_SCOPE_LINK;
     274                 :          0 :                 route_gw->protocol = RTPROT_DHCP;
     275                 :          0 :                 route_gw->priority = link->network->dhcp_route_metric;
     276                 :          0 :                 route_gw->table = table;
     277                 :            : 
     278                 :          0 :                 r = dhcp_route_configure(&route_gw, link);
     279         [ #  # ]:          0 :                 if (r < 0)
     280   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not set host route: %m");
     281                 :            : 
     282                 :          0 :                 r = route_new(&route);
     283         [ #  # ]:          0 :                 if (r < 0)
     284   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not allocate route: %m");
     285                 :            : 
     286                 :          0 :                 route->family = AF_INET;
     287                 :          0 :                 route->gw.in = router[0];
     288                 :          0 :                 route->prefsrc.in = address;
     289                 :          0 :                 route->protocol = RTPROT_DHCP;
     290                 :          0 :                 route->priority = link->network->dhcp_route_metric;
     291                 :          0 :                 route->table = table;
     292                 :            : 
     293                 :          0 :                 r = dhcp_route_configure(&route, link);
     294         [ #  # ]:          0 :                 if (r < 0)
     295   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not set router: %m");
     296                 :            :         }
     297                 :            : 
     298                 :          0 :         return link_set_dns_routes(link, &address);
     299                 :            : }
     300                 :            : 
     301                 :          0 : static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) {
     302                 :          0 :         _cleanup_free_ sd_dhcp_route **routes = NULL;
     303                 :            :         uint32_t table;
     304                 :            :         int n, i, r;
     305                 :            : 
     306         [ #  # ]:          0 :         assert(link);
     307         [ #  # ]:          0 :         assert(address);
     308                 :            : 
     309         [ #  # ]:          0 :         if (!link->network->dhcp_use_routes)
     310                 :          0 :                 return 0;
     311                 :            : 
     312                 :          0 :         n = sd_dhcp_lease_get_routes(lease, &routes);
     313   [ #  #  #  # ]:          0 :         if (IN_SET(n, 0, -ENODATA))
     314                 :          0 :                 return 0;
     315         [ #  # ]:          0 :         else if (n < 0)
     316   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, n, "DHCP error: Failed to get routes: %m");
     317                 :            : 
     318                 :          0 :         table = link_get_dhcp_route_table(link);
     319                 :            : 
     320         [ #  # ]:          0 :         for (i = 0; i < n; i++) {
     321      [ #  #  # ]:          0 :                 _cleanup_(route_freep) Route *route = NULL;
     322                 :            : 
     323                 :          0 :                 r = route_new(&route);
     324         [ #  # ]:          0 :                 if (r < 0)
     325                 :          0 :                         return log_oom();
     326                 :            : 
     327                 :          0 :                 route->family = AF_INET;
     328         [ #  # ]:          0 :                 assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
     329         [ #  # ]:          0 :                 assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
     330         [ #  # ]:          0 :                 assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
     331                 :          0 :                 route->priority = link->network->dhcp_route_metric;
     332                 :          0 :                 route->table = table;
     333                 :          0 :                 route->scope = route_scope_from_address(route, address);
     334   [ #  #  #  # ]:          0 :                 if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
     335                 :          0 :                         route->prefsrc.in = *address;
     336                 :            : 
     337   [ #  #  #  # ]:          0 :                 if (!remove_all && set_contains(link->dhcp_routes, route))
     338                 :          0 :                         continue;
     339                 :            : 
     340                 :          0 :                 (void) route_remove(route, link, NULL);
     341                 :            :         }
     342                 :            : 
     343                 :          0 :         return n;
     344                 :            : }
     345                 :            : 
     346                 :          0 : static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) {
     347                 :          0 :         _cleanup_(route_freep) Route *route_gw = NULL, *route = NULL;
     348                 :            :         const struct in_addr *router;
     349                 :            :         uint32_t table;
     350                 :            :         int r;
     351                 :            : 
     352         [ #  # ]:          0 :         assert(link);
     353         [ #  # ]:          0 :         assert(address);
     354                 :            : 
     355         [ #  # ]:          0 :         if (!link->network->dhcp_use_routes)
     356                 :          0 :                 return 0;
     357                 :            : 
     358                 :          0 :         r = sd_dhcp_lease_get_router(lease, &router);
     359   [ #  #  #  # ]:          0 :         if (IN_SET(r, 0, -ENODATA)) {
     360   [ #  #  #  # ]:          0 :                 log_link_debug(link, "DHCP: No gateway received from DHCP server.");
     361                 :          0 :                 return 0;
     362         [ #  # ]:          0 :         } else if (r < 0)
     363   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
     364         [ #  # ]:          0 :         else if (in4_addr_is_null(&router[0])) {
     365   [ #  #  #  # ]:          0 :                 log_link_info(link, "DHCP: Received gateway is null, ignoring.");
     366                 :          0 :                 return 0;
     367                 :            :         }
     368                 :            : 
     369                 :          0 :         table = link_get_dhcp_route_table(link);
     370                 :            : 
     371                 :          0 :         r = route_new(&route_gw);
     372         [ #  # ]:          0 :         if (r < 0)
     373                 :          0 :                 return log_oom();
     374                 :            : 
     375                 :          0 :         route_gw->family = AF_INET;
     376                 :          0 :         route_gw->dst.in = router[0];
     377                 :          0 :         route_gw->dst_prefixlen = 32;
     378                 :          0 :         route_gw->prefsrc.in = *address;
     379                 :          0 :         route_gw->scope = RT_SCOPE_LINK;
     380                 :          0 :         route_gw->protocol = RTPROT_DHCP;
     381                 :          0 :         route_gw->priority = link->network->dhcp_route_metric;
     382                 :          0 :         route_gw->table = table;
     383                 :            : 
     384   [ #  #  #  # ]:          0 :         if (remove_all || !set_contains(link->dhcp_routes, route_gw))
     385                 :          0 :                 (void) route_remove(route_gw, link, NULL);
     386                 :            : 
     387                 :          0 :         r = route_new(&route);
     388         [ #  # ]:          0 :         if (r < 0)
     389                 :          0 :                 return log_oom();
     390                 :            : 
     391                 :          0 :         route->family = AF_INET;
     392                 :          0 :         route->gw.in = router[0];
     393                 :          0 :         route->prefsrc.in = *address;
     394                 :          0 :         route->protocol = RTPROT_DHCP;
     395                 :          0 :         route->priority = link->network->dhcp_route_metric;
     396                 :          0 :         route->table = table;
     397                 :            : 
     398   [ #  #  #  # ]:          0 :         if (remove_all || !set_contains(link->dhcp_routes, route))
     399                 :          0 :                 (void) route_remove(route, link, NULL);
     400                 :            : 
     401                 :          0 :         return 0;
     402                 :            : }
     403                 :            : 
     404                 :          0 : static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) {
     405                 :            :         const struct in_addr *dns;
     406                 :            :         uint32_t table;
     407                 :            :         int i, n, r;
     408                 :            : 
     409         [ #  # ]:          0 :         assert(link);
     410         [ #  # ]:          0 :         assert(lease);
     411         [ #  # ]:          0 :         assert(link->network);
     412                 :            : 
     413         [ #  # ]:          0 :         if (!link->network->dhcp_use_dns ||
     414         [ #  # ]:          0 :             !link->network->dhcp_routes_to_dns)
     415                 :          0 :                 return 0;
     416                 :            : 
     417                 :          0 :         n = sd_dhcp_lease_get_dns(lease, &dns);
     418   [ #  #  #  # ]:          0 :         if (IN_SET(n, 0, -ENODATA))
     419                 :          0 :                 return 0;
     420         [ #  # ]:          0 :         if (n < 0)
     421   [ #  #  #  # ]:          0 :                 return log_link_warning_errno(link, n, "DHCP error: could not get DNS servers: %m");
     422                 :            : 
     423                 :          0 :         table = link_get_dhcp_route_table(link);
     424                 :            : 
     425         [ #  # ]:          0 :         for (i = 0; i < n; i ++) {
     426      [ #  #  # ]:          0 :                 _cleanup_(route_freep) Route *route = NULL;
     427                 :            : 
     428                 :          0 :                 r = route_new(&route);
     429         [ #  # ]:          0 :                 if (r < 0)
     430   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r,  "Could not allocate route: %m");
     431                 :            : 
     432                 :          0 :                 route->family = AF_INET;
     433                 :          0 :                 route->dst.in = dns[i];
     434                 :          0 :                 route->dst_prefixlen = 32;
     435                 :          0 :                 route->prefsrc.in = *address;
     436                 :          0 :                 route->scope = RT_SCOPE_LINK;
     437                 :          0 :                 route->protocol = RTPROT_DHCP;
     438                 :          0 :                 route->priority = link->network->dhcp_route_metric;
     439                 :          0 :                 route->table = table;
     440                 :            : 
     441   [ #  #  #  # ]:          0 :                 if (!remove_all && set_contains(link->dhcp_routes, route))
     442                 :          0 :                         continue;
     443                 :            : 
     444                 :          0 :                 (void) route_remove(route, link, NULL);
     445                 :            :         }
     446                 :            : 
     447                 :          0 :         return 0;
     448                 :            : }
     449                 :            : 
     450                 :          0 : static int dhcp_remove_address(Link *link, sd_dhcp_lease *lease, const struct in_addr *address) {
     451                 :          0 :         _cleanup_(address_freep) Address *a = NULL;
     452                 :            :         struct in_addr netmask;
     453                 :            :         int r;
     454                 :            : 
     455         [ #  # ]:          0 :         assert(link);
     456         [ #  # ]:          0 :         assert(address);
     457                 :            : 
     458         [ #  # ]:          0 :         if (in4_addr_is_null(address))
     459                 :          0 :                 return 0;
     460                 :            : 
     461                 :          0 :         r = address_new(&a);
     462         [ #  # ]:          0 :         if (r < 0)
     463                 :          0 :                 return log_oom();
     464                 :            : 
     465                 :          0 :         a->family = AF_INET;
     466                 :          0 :         a->in_addr.in = *address;
     467                 :            : 
     468         [ #  # ]:          0 :         if (sd_dhcp_lease_get_netmask(lease, &netmask) >= 0)
     469                 :          0 :                 a->prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
     470                 :            : 
     471                 :          0 :         (void) address_remove(a, link, NULL);
     472                 :            : 
     473                 :          0 :         return 0;
     474                 :            : }
     475                 :            : 
     476                 :          0 : static int dhcp_reset_mtu(Link *link) {
     477                 :            :         uint16_t mtu;
     478                 :            :         int r;
     479                 :            : 
     480         [ #  # ]:          0 :         assert(link);
     481                 :            : 
     482         [ #  # ]:          0 :         if (!link->network->dhcp_use_mtu)
     483                 :          0 :                 return 0;
     484                 :            : 
     485                 :          0 :         r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
     486         [ #  # ]:          0 :         if (r < 0)
     487                 :          0 :                 return r;
     488                 :            : 
     489         [ #  # ]:          0 :         if (link->original_mtu == mtu)
     490                 :          0 :                 return 0;
     491                 :            : 
     492                 :          0 :         r = link_set_mtu(link, link->original_mtu);
     493         [ #  # ]:          0 :         if (r < 0) {
     494   [ #  #  #  # ]:          0 :                 log_link_error_errno(link, r, "DHCP error: could not reset MTU: %m");
     495                 :          0 :                 link_enter_failed(link);
     496                 :          0 :                 return r;
     497                 :            :         }
     498                 :            : 
     499                 :          0 :         return 0;
     500                 :            : }
     501                 :            : 
     502                 :          0 : static int dhcp_reset_hostname(Link *link) {
     503                 :            :         const char *hostname;
     504                 :            :         int r;
     505                 :            : 
     506         [ #  # ]:          0 :         assert(link);
     507                 :            : 
     508         [ #  # ]:          0 :         if (!link->network->dhcp_use_hostname)
     509                 :          0 :                 return 0;
     510                 :            : 
     511                 :          0 :         hostname = link->network->dhcp_hostname;
     512         [ #  # ]:          0 :         if (!hostname)
     513                 :          0 :                 (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
     514                 :            : 
     515         [ #  # ]:          0 :         if (!hostname)
     516                 :          0 :                 return 0;
     517                 :            : 
     518                 :            :         /* If a hostname was set due to the lease, then unset it now. */
     519                 :          0 :         r = manager_set_hostname(link->manager, NULL);
     520         [ #  # ]:          0 :         if (r < 0)
     521   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP error: Failed to reset transient hostname: %m");
     522                 :            : 
     523                 :          0 :         return 0;
     524                 :            : }
     525                 :            : 
     526                 :          0 : static int dhcp_lease_lost(Link *link) {
     527                 :          0 :         struct in_addr address = {};
     528                 :            : 
     529         [ #  # ]:          0 :         assert(link);
     530         [ #  # ]:          0 :         assert(link->dhcp_lease);
     531                 :            : 
     532   [ #  #  #  # ]:          0 :         log_link_warning(link, "DHCP lease lost");
     533                 :            : 
     534                 :          0 :         link->dhcp4_configured = false;
     535                 :            : 
     536                 :          0 :         (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
     537                 :          0 :         (void) dhcp_remove_routes(link, link->dhcp_lease, &address, true);
     538                 :          0 :         (void) dhcp_remove_router(link, link->dhcp_lease, &address, true);
     539                 :          0 :         (void) dhcp_remove_dns_routes(link, link->dhcp_lease, &address, true);
     540                 :          0 :         (void) dhcp_remove_address(link, link->dhcp_lease, &address);
     541                 :          0 :         (void) dhcp_reset_mtu(link);
     542                 :          0 :         (void) dhcp_reset_hostname(link);
     543                 :            : 
     544                 :          0 :         link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
     545                 :          0 :         link_dirty(link);
     546                 :            : 
     547                 :          0 :         return 0;
     548                 :            : }
     549                 :            : 
     550                 :          0 : static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
     551                 :            :         int r;
     552                 :            : 
     553         [ #  # ]:          0 :         assert(link);
     554                 :            : 
     555   [ #  #  #  # ]:          0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     556                 :          0 :                 return 1;
     557                 :            : 
     558                 :          0 :         r = sd_netlink_message_get_errno(m);
     559   [ #  #  #  # ]:          0 :         if (r < 0 && r != -EEXIST) {
     560   [ #  #  #  # ]:          0 :                 log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
     561                 :          0 :                 link_enter_failed(link);
     562                 :          0 :                 return 1;
     563         [ #  # ]:          0 :         } else if (r >= 0)
     564                 :          0 :                 (void) manager_rtnl_process_address(rtnl, m, link->manager);
     565                 :            : 
     566                 :          0 :         r = link_set_dhcp_routes(link);
     567         [ #  # ]:          0 :         if (r < 0) {
     568                 :          0 :                 link_enter_failed(link);
     569                 :          0 :                 return 1;
     570                 :            :         }
     571                 :            : 
     572                 :            :         /* Add back static routes since kernel removes while DHCPv4 address is removed from when lease expires */
     573                 :          0 :         r = link_request_set_routes(link);
     574         [ #  # ]:          0 :         if (r < 0) {
     575                 :          0 :                 link_enter_failed(link);
     576                 :          0 :                 return 1;
     577                 :            :         }
     578                 :            : 
     579         [ #  # ]:          0 :         if (link->dhcp4_messages == 0) {
     580                 :          0 :                 link->dhcp4_configured = true;
     581                 :            :                 /* The new address is configured, and no route is requested.
     582                 :            :                  * Let's drop the old lease. */
     583                 :          0 :                 dhcp4_release_old_lease(link);
     584                 :          0 :                 link_check_ready(link);
     585                 :            :         }
     586                 :            : 
     587                 :          0 :         return 1;
     588                 :            : }
     589                 :            : 
     590                 :          0 : static int dhcp4_update_address(Link *link,
     591                 :            :                                 struct in_addr *address,
     592                 :            :                                 struct in_addr *netmask,
     593                 :            :                                 uint32_t lifetime) {
     594                 :          0 :         _cleanup_(address_freep) Address *addr = NULL;
     595                 :            :         unsigned prefixlen;
     596                 :            :         int r;
     597                 :            : 
     598         [ #  # ]:          0 :         assert(address);
     599         [ #  # ]:          0 :         assert(netmask);
     600         [ #  # ]:          0 :         assert(lifetime);
     601                 :            : 
     602                 :          0 :         prefixlen = in4_addr_netmask_to_prefixlen(netmask);
     603                 :            : 
     604                 :          0 :         r = address_new(&addr);
     605         [ #  # ]:          0 :         if (r < 0)
     606                 :          0 :                 return r;
     607                 :            : 
     608                 :          0 :         addr->family = AF_INET;
     609                 :          0 :         addr->in_addr.in.s_addr = address->s_addr;
     610                 :          0 :         addr->cinfo.ifa_prefered = lifetime;
     611                 :          0 :         addr->cinfo.ifa_valid = lifetime;
     612                 :          0 :         addr->prefixlen = prefixlen;
     613                 :          0 :         addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
     614                 :            : 
     615                 :            :         /* allow reusing an existing address and simply update its lifetime
     616                 :            :          * in case it already exists */
     617                 :          0 :         r = address_configure(addr, link, dhcp4_address_handler, true);
     618         [ #  # ]:          0 :         if (r < 0)
     619                 :          0 :                 return r;
     620                 :            : 
     621                 :          0 :         return 0;
     622                 :            : }
     623                 :            : 
     624                 :          0 : static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
     625                 :            :         sd_dhcp_lease *lease;
     626                 :            :         struct in_addr address;
     627                 :            :         struct in_addr netmask;
     628                 :          0 :         uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
     629                 :            :         int r;
     630                 :            : 
     631         [ #  # ]:          0 :         assert(link);
     632         [ #  # ]:          0 :         assert(client);
     633         [ #  # ]:          0 :         assert(link->network);
     634                 :            : 
     635                 :          0 :         r = sd_dhcp_client_get_lease(client, &lease);
     636         [ #  # ]:          0 :         if (r < 0)
     637   [ #  #  #  # ]:          0 :                 return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
     638                 :            : 
     639                 :          0 :         sd_dhcp_lease_unref(link->dhcp_lease);
     640                 :          0 :         link->dhcp4_configured = false;
     641                 :          0 :         link->dhcp_lease = sd_dhcp_lease_ref(lease);
     642                 :          0 :         link_dirty(link);
     643                 :            : 
     644                 :          0 :         r = sd_dhcp_lease_get_address(lease, &address);
     645         [ #  # ]:          0 :         if (r < 0)
     646   [ #  #  #  # ]:          0 :                 return log_link_warning_errno(link, r, "DHCP error: no address: %m");
     647                 :            : 
     648                 :          0 :         r = sd_dhcp_lease_get_netmask(lease, &netmask);
     649         [ #  # ]:          0 :         if (r < 0)
     650   [ #  #  #  # ]:          0 :                 return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
     651                 :            : 
     652         [ #  # ]:          0 :         if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
     653                 :          0 :                 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
     654         [ #  # ]:          0 :                 if (r < 0)
     655   [ #  #  #  # ]:          0 :                         return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
     656                 :            :         }
     657                 :            : 
     658                 :          0 :         r = dhcp4_update_address(link, &address, &netmask, lifetime);
     659         [ #  # ]:          0 :         if (r < 0)
     660   [ #  #  #  # ]:          0 :                 return log_link_warning_errno(link, r, "Could not update IP address: %m");
     661                 :            : 
     662                 :          0 :         return 0;
     663                 :            : }
     664                 :            : 
     665                 :          0 : static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
     666                 :            :         const struct in_addr *router;
     667                 :            :         sd_dhcp_lease *lease;
     668                 :            :         struct in_addr address;
     669                 :            :         struct in_addr netmask;
     670                 :            :         unsigned prefixlen;
     671                 :          0 :         uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
     672                 :            :         int r;
     673                 :            : 
     674         [ #  # ]:          0 :         assert(client);
     675         [ #  # ]:          0 :         assert(link);
     676                 :            : 
     677                 :          0 :         link->dhcp4_configured = false;
     678                 :            : 
     679                 :          0 :         r = sd_dhcp_client_get_lease(client, &lease);
     680         [ #  # ]:          0 :         if (r < 0)
     681   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP error: No lease: %m");
     682                 :            : 
     683                 :          0 :         r = sd_dhcp_lease_get_address(lease, &address);
     684         [ #  # ]:          0 :         if (r < 0)
     685   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP error: No address: %m");
     686                 :            : 
     687                 :          0 :         r = sd_dhcp_lease_get_netmask(lease, &netmask);
     688         [ #  # ]:          0 :         if (r < 0)
     689   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
     690                 :            : 
     691                 :          0 :         prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
     692                 :            : 
     693         [ #  # ]:          0 :         if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
     694                 :          0 :                 r = sd_dhcp_lease_get_lifetime(lease, &lifetime);
     695         [ #  # ]:          0 :                 if (r < 0)
     696   [ #  #  #  # ]:          0 :                         return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
     697                 :            :         }
     698                 :            : 
     699                 :          0 :         r = sd_dhcp_lease_get_router(lease, &router);
     700   [ #  #  #  # ]:          0 :         if (r < 0 && r != -ENODATA)
     701   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");
     702                 :            : 
     703   [ #  #  #  # ]:          0 :         if (r > 0 && !in4_addr_is_null(&router[0]))
     704                 :          0 :                 log_struct(LOG_INFO,
     705                 :            :                            LOG_LINK_INTERFACE(link),
     706                 :            :                            LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
     707                 :            :                                             ADDRESS_FMT_VAL(address),
     708                 :            :                                             prefixlen,
     709                 :            :                                             ADDRESS_FMT_VAL(router[0])),
     710                 :            :                            "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
     711                 :            :                            "PREFIXLEN=%u", prefixlen,
     712                 :            :                            "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(router[0]));
     713                 :            :         else
     714                 :          0 :                 log_struct(LOG_INFO,
     715                 :            :                            LOG_LINK_INTERFACE(link),
     716                 :            :                            LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
     717                 :            :                                             ADDRESS_FMT_VAL(address),
     718                 :            :                                             prefixlen),
     719                 :            :                            "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
     720                 :            :                            "PREFIXLEN=%u", prefixlen);
     721                 :            : 
     722                 :          0 :         link->dhcp_lease = sd_dhcp_lease_ref(lease);
     723                 :          0 :         link_dirty(link);
     724                 :            : 
     725         [ #  # ]:          0 :         if (link->network->dhcp_use_mtu) {
     726                 :            :                 uint16_t mtu;
     727                 :            : 
     728                 :          0 :                 r = sd_dhcp_lease_get_mtu(lease, &mtu);
     729         [ #  # ]:          0 :                 if (r >= 0) {
     730                 :          0 :                         r = link_set_mtu(link, mtu);
     731         [ #  # ]:          0 :                         if (r < 0)
     732   [ #  #  #  # ]:          0 :                                 log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
     733                 :            :                 }
     734                 :            :         }
     735                 :            : 
     736         [ #  # ]:          0 :         if (link->network->dhcp_use_hostname) {
     737                 :          0 :                 const char *dhcpname = NULL;
     738                 :          0 :                 _cleanup_free_ char *hostname = NULL;
     739                 :            : 
     740         [ #  # ]:          0 :                 if (link->network->dhcp_hostname)
     741                 :          0 :                         dhcpname = link->network->dhcp_hostname;
     742                 :            :                 else
     743                 :          0 :                         (void) sd_dhcp_lease_get_hostname(lease, &dhcpname);
     744                 :            : 
     745         [ #  # ]:          0 :                 if (dhcpname) {
     746                 :          0 :                         r = shorten_overlong(dhcpname, &hostname);
     747         [ #  # ]:          0 :                         if (r < 0)
     748   [ #  #  #  # ]:          0 :                                 log_link_warning_errno(link, r, "Unable to shorten overlong DHCP hostname '%s', ignoring: %m", dhcpname);
     749         [ #  # ]:          0 :                         if (r == 1)
     750   [ #  #  #  # ]:          0 :                                 log_link_notice(link, "Overlong DHCP hostname received, shortened from '%s' to '%s'", dhcpname, hostname);
     751                 :            :                 }
     752                 :            : 
     753         [ #  # ]:          0 :                 if (hostname) {
     754                 :          0 :                         r = manager_set_hostname(link->manager, hostname);
     755         [ #  # ]:          0 :                         if (r < 0)
     756   [ #  #  #  # ]:          0 :                                 log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
     757                 :            :                 }
     758                 :            :         }
     759                 :            : 
     760         [ #  # ]:          0 :         if (link->network->dhcp_use_timezone) {
     761                 :          0 :                 const char *tz = NULL;
     762                 :            : 
     763                 :          0 :                 (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
     764                 :            : 
     765         [ #  # ]:          0 :                 if (tz) {
     766                 :          0 :                         r = manager_set_timezone(link->manager, tz);
     767         [ #  # ]:          0 :                         if (r < 0)
     768   [ #  #  #  # ]:          0 :                                 log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz);
     769                 :            :                 }
     770                 :            :         }
     771                 :            : 
     772                 :          0 :         r = dhcp4_update_address(link, &address, &netmask, lifetime);
     773         [ #  # ]:          0 :         if (r < 0)
     774   [ #  #  #  # ]:          0 :                 return log_link_warning_errno(link, r, "Could not update IP address: %m");
     775                 :            : 
     776                 :          0 :         return 0;
     777                 :            : }
     778                 :            : 
     779                 :          0 : static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) {
     780                 :            :         int r;
     781                 :            : 
     782                 :          0 :         link->dhcp_lease_old = TAKE_PTR(link->dhcp_lease);
     783                 :            : 
     784                 :            :         /* On ip address change, to keep the connectability, we would like to assign new address and
     785                 :            :          * routes, and then release old lease. There are two possible success paths:
     786                 :            :          *
     787                 :            :          * 1. new address and routes are configured.
     788                 :            :          *    -> handled by dhcp_release_old_lease() in dhcp4_route_handler().
     789                 :            :          * 2. new address is configured and no route is requested.
     790                 :            :          *    -> handled by dhcp_release_old_lease() in dhcp4_address_handler().
     791                 :            :          *
     792                 :            :          * On error in assigning new address and routes, then the link always enters to the failed
     793                 :            :          * state. And link_enter_failed() leads to the DHCP client to be stopped. So,
     794                 :            :          * dhcp_release_old_lease() will be also called by link_stop_clients().
     795                 :            :          */
     796                 :            : 
     797                 :          0 :         r = dhcp_lease_acquired(client, link);
     798         [ #  # ]:          0 :         if (r < 0) {
     799                 :            :                 /* If it fails, then the new address is not configured yet.
     800                 :            :                  * So, let's simply drop the old lease. */
     801                 :          0 :                 sd_dhcp_lease_unref(link->dhcp_lease);
     802                 :          0 :                 link->dhcp_lease = TAKE_PTR(link->dhcp_lease_old);
     803                 :          0 :                 (void) dhcp_lease_lost(link);
     804                 :          0 :                 return r;
     805                 :            :         }
     806                 :            : 
     807                 :          0 :         return 0;
     808                 :            : }
     809                 :            : 
     810                 :          0 : static int dhcp_server_is_black_listed(Link *link, sd_dhcp_client *client) {
     811                 :            :         sd_dhcp_lease *lease;
     812                 :            :         struct in_addr addr;
     813                 :            :         int r;
     814                 :            : 
     815         [ #  # ]:          0 :         assert(link);
     816         [ #  # ]:          0 :         assert(link->network);
     817         [ #  # ]:          0 :         assert(client);
     818                 :            : 
     819                 :          0 :         r = sd_dhcp_client_get_lease(client, &lease);
     820         [ #  # ]:          0 :         if (r < 0)
     821   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Failed to get DHCP lease: %m");
     822                 :            : 
     823                 :          0 :         r = sd_dhcp_lease_get_server_identifier(lease, &addr);
     824         [ #  # ]:          0 :         if (r < 0)
     825   [ #  #  #  # ]:          0 :                 return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
     826                 :            : 
     827         [ #  # ]:          0 :         if (set_contains(link->network->dhcp_black_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
     828                 :          0 :                 log_struct(LOG_DEBUG,
     829                 :            :                            LOG_LINK_INTERFACE(link),
     830                 :            :                            LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in black listed ip addresses, ignoring offer",
     831                 :            :                                             ADDRESS_FMT_VAL(addr)));
     832                 :          0 :                 return true;
     833                 :            :         }
     834                 :            : 
     835                 :          0 :         return false;
     836                 :            : }
     837                 :            : 
     838                 :          0 : static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
     839                 :          0 :         Link *link = userdata;
     840                 :            :         int r;
     841                 :            : 
     842         [ #  # ]:          0 :         assert(link);
     843         [ #  # ]:          0 :         assert(link->network);
     844         [ #  # ]:          0 :         assert(link->manager);
     845                 :            : 
     846   [ #  #  #  # ]:          0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     847                 :          0 :                 return 0;
     848                 :            : 
     849   [ #  #  #  #  :          0 :         switch (event) {
                #  #  # ]
     850                 :          0 :                 case SD_DHCP_CLIENT_EVENT_STOP:
     851                 :            : 
     852         [ #  # ]:          0 :                         if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4)) {
     853         [ #  # ]:          0 :                                 assert(link->ipv4ll);
     854                 :            : 
     855   [ #  #  #  # ]:          0 :                                 log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
     856                 :            : 
     857                 :          0 :                                 r = sd_ipv4ll_start(link->ipv4ll);
     858         [ #  # ]:          0 :                                 if (r < 0)
     859   [ #  #  #  # ]:          0 :                                         return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
     860                 :            :                         }
     861                 :            : 
     862         [ #  # ]:          0 :                         if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
     863   [ #  #  #  # ]:          0 :                                 log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it.");
     864                 :          0 :                                 return 0;
     865                 :            :                         }
     866                 :            : 
     867         [ #  # ]:          0 :                         if (link->network->dhcp_send_release)
     868                 :          0 :                                 (void) sd_dhcp_client_send_release(client);
     869                 :            : 
     870         [ #  # ]:          0 :                         if (link->dhcp_lease) {
     871                 :          0 :                                 r = dhcp_lease_lost(link);
     872         [ #  # ]:          0 :                                 if (r < 0) {
     873                 :          0 :                                         link_enter_failed(link);
     874                 :          0 :                                         return r;
     875                 :            :                                 }
     876                 :            :                         }
     877                 :            : 
     878                 :          0 :                         break;
     879                 :          0 :                 case SD_DHCP_CLIENT_EVENT_EXPIRED:
     880         [ #  # ]:          0 :                         if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
     881   [ #  #  #  # ]:          0 :                                 log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it.");
     882                 :          0 :                                 return 0;
     883                 :            :                         }
     884                 :            : 
     885         [ #  # ]:          0 :                         if (link->dhcp_lease) {
     886                 :          0 :                                 r = dhcp_lease_lost(link);
     887         [ #  # ]:          0 :                                 if (r < 0) {
     888                 :          0 :                                         link_enter_failed(link);
     889                 :          0 :                                         return r;
     890                 :            :                                 }
     891                 :            :                         }
     892                 :            : 
     893                 :          0 :                         break;
     894                 :          0 :                 case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
     895         [ #  # ]:          0 :                         if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
     896   [ #  #  #  # ]:          0 :                                 log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it.");
     897                 :          0 :                                 return 0;
     898                 :            :                         }
     899                 :            : 
     900                 :          0 :                         r = dhcp_lease_ip_change(client, link);
     901         [ #  # ]:          0 :                         if (r < 0) {
     902                 :          0 :                                 link_enter_failed(link);
     903                 :          0 :                                 return r;
     904                 :            :                         }
     905                 :            : 
     906                 :          0 :                         break;
     907                 :          0 :                 case SD_DHCP_CLIENT_EVENT_RENEW:
     908                 :          0 :                         r = dhcp_lease_renew(client, link);
     909         [ #  # ]:          0 :                         if (r < 0) {
     910                 :          0 :                                 link_enter_failed(link);
     911                 :          0 :                                 return r;
     912                 :            :                         }
     913                 :          0 :                         break;
     914                 :          0 :                 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
     915                 :          0 :                         r = dhcp_lease_acquired(client, link);
     916         [ #  # ]:          0 :                         if (r < 0) {
     917                 :          0 :                                 link_enter_failed(link);
     918                 :          0 :                                 return r;
     919                 :            :                         }
     920                 :          0 :                         break;
     921                 :          0 :                 case SD_DHCP_CLIENT_EVENT_SELECTING:
     922                 :          0 :                         r = dhcp_server_is_black_listed(link, client);
     923         [ #  # ]:          0 :                         if (r < 0)
     924                 :          0 :                                 return r;
     925         [ #  # ]:          0 :                         if (r != 0)
     926                 :          0 :                                 return -ENOMSG;
     927                 :          0 :                         break;
     928                 :          0 :                 default:
     929         [ #  # ]:          0 :                         if (event < 0)
     930   [ #  #  #  # ]:          0 :                                 log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
     931                 :            :                         else
     932   [ #  #  #  # ]:          0 :                                 log_link_warning(link, "DHCP unknown event: %i", event);
     933                 :          0 :                         break;
     934                 :            :         }
     935                 :            : 
     936                 :          0 :         return 0;
     937                 :            : }
     938                 :            : 
     939                 :          0 : static int dhcp4_set_hostname(Link *link) {
     940                 :          0 :         _cleanup_free_ char *hostname = NULL;
     941                 :            :         const char *hn;
     942                 :            :         int r;
     943                 :            : 
     944         [ #  # ]:          0 :         assert(link);
     945                 :            : 
     946         [ #  # ]:          0 :         if (!link->network->dhcp_send_hostname)
     947                 :          0 :                 hn = NULL;
     948         [ #  # ]:          0 :         else if (link->network->dhcp_hostname)
     949                 :          0 :                 hn = link->network->dhcp_hostname;
     950                 :            :         else {
     951                 :          0 :                 r = gethostname_strict(&hostname);
     952   [ #  #  #  # ]:          0 :                 if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */
     953                 :          0 :                         return r;
     954                 :            : 
     955                 :          0 :                 hn = hostname;
     956                 :            :         }
     957                 :            : 
     958                 :          0 :         r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
     959   [ #  #  #  # ]:          0 :         if (r == -EINVAL && hostname)
     960                 :            :                 /* Ignore error when the machine's hostname is not suitable to send in DHCP packet. */
     961   [ #  #  #  # ]:          0 :                 log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set hostname from kernel hostname, ignoring: %m");
     962         [ #  # ]:          0 :         else if (r < 0)
     963   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set hostname: %m");
     964                 :            : 
     965                 :          0 :         return 0;
     966                 :            : }
     967                 :            : 
     968                 :          0 : static bool promote_secondaries_enabled(const char *ifname) {
     969                 :          0 :         _cleanup_free_ char *promote_secondaries_sysctl = NULL;
     970                 :            :         char *promote_secondaries_path;
     971                 :            :         int r;
     972                 :            : 
     973   [ #  #  #  #  :          0 :         promote_secondaries_path = strjoina("net/ipv4/conf/", ifname, "/promote_secondaries");
          #  #  #  #  #  
                #  #  # ]
     974                 :          0 :         r = sysctl_read(promote_secondaries_path, &promote_secondaries_sysctl);
     975         [ #  # ]:          0 :         if (r < 0) {
     976         [ #  # ]:          0 :                 log_debug_errno(r, "Cannot read sysctl %s", promote_secondaries_path);
     977                 :          0 :                 return false;
     978                 :            :         }
     979                 :            : 
     980                 :          0 :         truncate_nl(promote_secondaries_sysctl);
     981                 :          0 :         r = parse_boolean(promote_secondaries_sysctl);
     982         [ #  # ]:          0 :         if (r < 0)
     983         [ #  # ]:          0 :                 log_warning_errno(r, "Cannot parse sysctl %s with content %s as boolean", promote_secondaries_path, promote_secondaries_sysctl);
     984                 :          0 :         return r > 0;
     985                 :            : }
     986                 :            : 
     987                 :            : /* dhcp4_set_promote_secondaries will ensure this interface has
     988                 :            :  * the "promote_secondaries" option in the kernel set. If this sysctl
     989                 :            :  * is not set DHCP will work only as long as the IP address does not
     990                 :            :  * changes between leases. The kernel will remove all secondary IP
     991                 :            :  * addresses of an interface otherwise. The way systemd-network works
     992                 :            :  * is that the new IP of a lease is added as a secondary IP and when
     993                 :            :  * the primary one expires it relies on the kernel to promote the
     994                 :            :  * secondary IP. See also https://github.com/systemd/systemd/issues/7163
     995                 :            :  */
     996                 :          0 : int dhcp4_set_promote_secondaries(Link *link) {
     997                 :            :         int r;
     998                 :            : 
     999         [ #  # ]:          0 :         assert(link);
    1000         [ #  # ]:          0 :         assert(link->network);
    1001         [ #  # ]:          0 :         assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
    1002                 :            : 
    1003                 :            :         /* check if the kernel has promote_secondaries enabled for our
    1004                 :            :          * interface. If it is not globally enabled or enabled for the
    1005                 :            :          * specific interface we must either enable it.
    1006                 :            :          */
    1007   [ #  #  #  # ]:          0 :         if (!(promote_secondaries_enabled("all") || promote_secondaries_enabled(link->ifname))) {
    1008                 :          0 :                 char *promote_secondaries_path = NULL;
    1009                 :            : 
    1010   [ #  #  #  # ]:          0 :                 log_link_debug(link, "promote_secondaries is unset, setting it");
    1011   [ #  #  #  #  :          0 :                 promote_secondaries_path = strjoina("net/ipv4/conf/", link->ifname, "/promote_secondaries");
          #  #  #  #  #  
                #  #  # ]
    1012                 :          0 :                 r = sysctl_write(promote_secondaries_path, "1");
    1013         [ #  # ]:          0 :                 if (r < 0)
    1014   [ #  #  #  # ]:          0 :                         log_link_warning_errno(link, r, "cannot set sysctl %s to 1", promote_secondaries_path);
    1015                 :          0 :                 return r > 0;
    1016                 :            :         }
    1017                 :            : 
    1018                 :          0 :         return 0;
    1019                 :            : }
    1020                 :            : 
    1021                 :          0 : int dhcp4_set_client_identifier(Link *link) {
    1022                 :            :         int r;
    1023                 :            : 
    1024         [ #  # ]:          0 :         assert(link);
    1025         [ #  # ]:          0 :         assert(link->network);
    1026         [ #  # ]:          0 :         assert(link->dhcp_client);
    1027                 :            : 
    1028   [ #  #  #  # ]:          0 :         switch (link->network->dhcp_client_identifier) {
    1029                 :          0 :         case DHCP_CLIENT_ID_DUID: {
    1030                 :            :                 /* If configured, apply user specified DUID and IAID */
    1031                 :          0 :                 const DUID *duid = link_get_duid(link);
    1032                 :            : 
    1033   [ #  #  #  # ]:          0 :                 if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
    1034                 :          0 :                         r = sd_dhcp_client_set_iaid_duid_llt(link->dhcp_client,
    1035                 :          0 :                                                              link->network->iaid_set,
    1036                 :          0 :                                                              link->network->iaid,
    1037                 :            :                                                              duid->llt_time);
    1038                 :            :                 else
    1039                 :          0 :                         r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
    1040                 :          0 :                                                          link->network->iaid_set,
    1041                 :          0 :                                                          link->network->iaid,
    1042                 :          0 :                                                          duid->type,
    1043                 :          0 :                                                          duid->raw_data_len > 0 ? duid->raw_data : NULL,
    1044         [ #  # ]:          0 :                                                          duid->raw_data_len);
    1045         [ #  # ]:          0 :                 if (r < 0)
    1046   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IAID+DUID: %m");
    1047                 :          0 :                 break;
    1048                 :            :         }
    1049                 :          0 :         case DHCP_CLIENT_ID_DUID_ONLY: {
    1050                 :            :                 /* If configured, apply user specified DUID */
    1051                 :          0 :                 const DUID *duid = link_get_duid(link);
    1052                 :            : 
    1053   [ #  #  #  # ]:          0 :                 if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
    1054                 :          0 :                         r = sd_dhcp_client_set_duid_llt(link->dhcp_client,
    1055                 :            :                                                         duid->llt_time);
    1056                 :            :                 else
    1057                 :          0 :                         r = sd_dhcp_client_set_duid(link->dhcp_client,
    1058                 :          0 :                                                     duid->type,
    1059                 :          0 :                                                     duid->raw_data_len > 0 ? duid->raw_data : NULL,
    1060         [ #  # ]:          0 :                                                     duid->raw_data_len);
    1061         [ #  # ]:          0 :                 if (r < 0)
    1062   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m");
    1063                 :          0 :                 break;
    1064                 :            :         }
    1065                 :          0 :         case DHCP_CLIENT_ID_MAC:
    1066                 :          0 :                 r = sd_dhcp_client_set_client_id(link->dhcp_client,
    1067                 :            :                                                  ARPHRD_ETHER,
    1068                 :          0 :                                                  (const uint8_t *) &link->mac,
    1069                 :            :                                                  sizeof(link->mac));
    1070         [ #  # ]:          0 :                 if (r < 0)
    1071   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set client ID: %m");
    1072                 :          0 :                 break;
    1073                 :          0 :         default:
    1074                 :          0 :                 assert_not_reached("Unknown client identifier type.");
    1075                 :            :         }
    1076                 :            : 
    1077                 :          0 :         return 0;
    1078                 :            : }
    1079                 :            : 
    1080                 :          0 : int dhcp4_configure(Link *link) {
    1081                 :            :         int r;
    1082                 :            : 
    1083         [ #  # ]:          0 :         assert(link);
    1084         [ #  # ]:          0 :         assert(link->network);
    1085         [ #  # ]:          0 :         assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
    1086                 :            : 
    1087         [ #  # ]:          0 :         if (!link->dhcp_client) {
    1088                 :          0 :                 r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
    1089         [ #  # ]:          0 :                 if (r == -ENOMEM)
    1090                 :          0 :                         return log_oom();
    1091         [ #  # ]:          0 :                 if (r < 0)
    1092   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to create DHCP4 client: %m");
    1093                 :            :         }
    1094                 :            : 
    1095                 :          0 :         r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
    1096         [ #  # ]:          0 :         if (r < 0)
    1097   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to attach event: %m");
    1098                 :            : 
    1099                 :          0 :         r = sd_dhcp_client_set_mac(link->dhcp_client,
    1100                 :          0 :                                    (const uint8_t *) &link->mac,
    1101                 :            :                                    sizeof (link->mac), ARPHRD_ETHER);
    1102         [ #  # ]:          0 :         if (r < 0)
    1103   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MAC address: %m");
    1104                 :            : 
    1105                 :          0 :         r = sd_dhcp_client_set_ifindex(link->dhcp_client, link->ifindex);
    1106         [ #  # ]:          0 :         if (r < 0)
    1107   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ifindex: %m");
    1108                 :            : 
    1109                 :          0 :         r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
    1110         [ #  # ]:          0 :         if (r < 0)
    1111   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set callback: %m");
    1112                 :            : 
    1113                 :          0 :         r = sd_dhcp_client_set_request_broadcast(link->dhcp_client,
    1114                 :          0 :                                                  link->network->dhcp_broadcast);
    1115         [ #  # ]:          0 :         if (r < 0)
    1116   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for broadcast: %m");
    1117                 :            : 
    1118         [ #  # ]:          0 :         if (link->mtu) {
    1119                 :          0 :                 r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
    1120         [ #  # ]:          0 :                 if (r < 0)
    1121   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MTU: %m");
    1122                 :            :         }
    1123                 :            : 
    1124         [ #  # ]:          0 :         if (link->network->dhcp_use_mtu) {
    1125                 :          0 :                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
    1126                 :            :                                                       SD_DHCP_OPTION_INTERFACE_MTU);
    1127         [ #  # ]:          0 :                 if (r < 0)
    1128   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for MTU: %m");
    1129                 :            :         }
    1130                 :            : 
    1131                 :            :         /* NOTE: even if this variable is called "use", it also "sends" PRL
    1132                 :            :          * options, maybe there should be a different configuration variable
    1133                 :            :          * to send or not route options?. */
    1134                 :            :         /* NOTE: when using Anonymize=yes, routes PRL options are sent
    1135                 :            :          * by default, so they don't need to be added here. */
    1136   [ #  #  #  # ]:          0 :         if (link->network->dhcp_use_routes && !link->network->dhcp_anonymize) {
    1137                 :          0 :                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
    1138                 :            :                                                       SD_DHCP_OPTION_STATIC_ROUTE);
    1139         [ #  # ]:          0 :                 if (r < 0)
    1140   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for static route: %m");
    1141                 :            : 
    1142                 :          0 :                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
    1143                 :            :                                                       SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
    1144         [ #  # ]:          0 :                 if (r < 0)
    1145   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for classless static route: %m");
    1146                 :            :         }
    1147                 :            : 
    1148   [ #  #  #  # ]:          0 :         if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO && !link->network->dhcp_anonymize) {
    1149                 :          0 :                 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST);
    1150         [ #  # ]:          0 :                 if (r < 0)
    1151   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for domain search list: %m");
    1152                 :            :         }
    1153                 :            : 
    1154         [ #  # ]:          0 :         if (link->network->dhcp_use_ntp) {
    1155                 :          0 :                 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
    1156         [ #  # ]:          0 :                 if (r < 0)
    1157   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for NTP server: %m");
    1158                 :            :         }
    1159                 :            : 
    1160         [ #  # ]:          0 :         if (link->network->dhcp_use_timezone) {
    1161                 :          0 :                 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
    1162         [ #  # ]:          0 :                 if (r < 0)
    1163   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for timezone: %m");
    1164                 :            :         }
    1165                 :            : 
    1166                 :          0 :         r = dhcp4_set_hostname(link);
    1167         [ #  # ]:          0 :         if (r < 0)
    1168                 :          0 :                 return r;
    1169                 :            : 
    1170         [ #  # ]:          0 :         if (link->network->dhcp_vendor_class_identifier) {
    1171                 :          0 :                 r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
    1172                 :          0 :                                                                link->network->dhcp_vendor_class_identifier);
    1173         [ #  # ]:          0 :                 if (r < 0)
    1174   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set vendor class identifier: %m");
    1175                 :            :         }
    1176                 :            : 
    1177         [ #  # ]:          0 :         if (link->network->dhcp_user_class) {
    1178                 :          0 :                 r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
    1179         [ #  # ]:          0 :                 if (r < 0)
    1180   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m");
    1181                 :            :         }
    1182                 :            : 
    1183         [ #  # ]:          0 :         if (link->network->dhcp_client_port) {
    1184                 :          0 :                 r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
    1185         [ #  # ]:          0 :                 if (r < 0)
    1186   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m");
    1187                 :            :         }
    1188                 :            : 
    1189         [ #  # ]:          0 :         if (link->network->dhcp_max_attempts > 0) {
    1190                 :          0 :                 r = sd_dhcp_client_set_max_attempts(link->dhcp_client, link->network->dhcp_max_attempts);
    1191         [ #  # ]:          0 :                 if (r < 0)
    1192   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m");
    1193                 :            :         }
    1194                 :            : 
    1195                 :          0 :         return dhcp4_set_client_identifier(link);
    1196                 :            : }
    1197                 :            : 
    1198                 :          0 : int config_parse_dhcp_max_attempts(
    1199                 :            :                 const char *unit,
    1200                 :            :                 const char *filename,
    1201                 :            :                 unsigned line,
    1202                 :            :                 const char *section,
    1203                 :            :                 unsigned section_line,
    1204                 :            :                 const char *lvalue,
    1205                 :            :                 int ltype,
    1206                 :            :                 const char *rvalue,
    1207                 :            :                 void *data,
    1208                 :            :                 void *userdata) {
    1209                 :            : 
    1210                 :          0 :         Network *network = data;
    1211                 :            :         uint64_t a;
    1212                 :            :         int r;
    1213                 :            : 
    1214         [ #  # ]:          0 :         assert(network);
    1215         [ #  # ]:          0 :         assert(lvalue);
    1216         [ #  # ]:          0 :         assert(rvalue);
    1217                 :            : 
    1218         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1219                 :          0 :                 network->dhcp_max_attempts = 0;
    1220                 :          0 :                 return 0;
    1221                 :            :         }
    1222                 :            : 
    1223         [ #  # ]:          0 :         if (streq(rvalue, "infinity")) {
    1224                 :          0 :                 network->dhcp_max_attempts = (uint64_t) -1;
    1225                 :          0 :                 return 0;
    1226                 :            :         }
    1227                 :            : 
    1228                 :          0 :         r = safe_atou64(rvalue, &a);
    1229         [ #  # ]:          0 :         if (r < 0) {
    1230         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
    1231                 :            :                            "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
    1232                 :          0 :                 return 0;
    1233                 :            :         }
    1234                 :            : 
    1235         [ #  # ]:          0 :         if (a == 0) {
    1236         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
    1237                 :            :                            "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
    1238                 :          0 :                 return 0;
    1239                 :            :         }
    1240                 :            : 
    1241                 :          0 :         network->dhcp_max_attempts = a;
    1242                 :            : 
    1243                 :          0 :         return 0;
    1244                 :            : }
    1245                 :            : 
    1246                 :          0 : int config_parse_dhcp_black_listed_ip_address(
    1247                 :            :                 const char *unit,
    1248                 :            :                 const char *filename,
    1249                 :            :                 unsigned line,
    1250                 :            :                 const char *section,
    1251                 :            :                 unsigned section_line,
    1252                 :            :                 const char *lvalue,
    1253                 :            :                 int ltype,
    1254                 :            :                 const char *rvalue,
    1255                 :            :                 void *data,
    1256                 :            :                 void *userdata) {
    1257                 :            : 
    1258                 :          0 :         Network *network = data;
    1259                 :            :         const char *p;
    1260                 :            :         int r;
    1261                 :            : 
    1262         [ #  # ]:          0 :         assert(filename);
    1263         [ #  # ]:          0 :         assert(lvalue);
    1264         [ #  # ]:          0 :         assert(rvalue);
    1265         [ #  # ]:          0 :         assert(data);
    1266                 :            : 
    1267         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1268                 :          0 :                 network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
    1269                 :          0 :                 return 0;
    1270                 :            :         }
    1271                 :            : 
    1272                 :          0 :         for (p = rvalue;;) {
    1273      [ #  #  # ]:          0 :                 _cleanup_free_ char *n = NULL;
    1274                 :            :                 union in_addr_union ip;
    1275                 :            : 
    1276                 :          0 :                 r = extract_first_word(&p, &n, NULL, 0);
    1277         [ #  # ]:          0 :                 if (r < 0) {
    1278         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1279                 :            :                                    "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
    1280                 :            :                                    rvalue);
    1281                 :          0 :                         return 0;
    1282                 :            :                 }
    1283         [ #  # ]:          0 :                 if (r == 0)
    1284                 :          0 :                         return 0;
    1285                 :            : 
    1286                 :          0 :                 r = in_addr_from_string(AF_INET, n, &ip);
    1287         [ #  # ]:          0 :                 if (r < 0) {
    1288         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1289                 :            :                                    "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
    1290                 :          0 :                         continue;
    1291                 :            :                 }
    1292                 :            : 
    1293                 :          0 :                 r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
    1294         [ #  # ]:          0 :                 if (r < 0)
    1295                 :          0 :                         return log_oom();
    1296                 :            : 
    1297                 :          0 :                 r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
    1298         [ #  # ]:          0 :                 if (r < 0)
    1299         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1300                 :            :                                    "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
    1301                 :            :         }
    1302                 :            : 
    1303                 :            :         return 0;
    1304                 :            : }
    1305                 :            : 
    1306                 :          0 : int config_parse_dhcp_user_class(
    1307                 :            :                 const char *unit,
    1308                 :            :                 const char *filename,
    1309                 :            :                 unsigned line,
    1310                 :            :                 const char *section,
    1311                 :            :                 unsigned section_line,
    1312                 :            :                 const char *lvalue,
    1313                 :            :                 int ltype,
    1314                 :            :                 const char *rvalue,
    1315                 :            :                 void *data,
    1316                 :            :                 void *userdata) {
    1317                 :            : 
    1318                 :          0 :         char ***l = data;
    1319                 :            :         int r;
    1320                 :            : 
    1321         [ #  # ]:          0 :         assert(l);
    1322         [ #  # ]:          0 :         assert(lvalue);
    1323         [ #  # ]:          0 :         assert(rvalue);
    1324                 :            : 
    1325         [ #  # ]:          0 :         if (isempty(rvalue)) {
    1326                 :          0 :                 *l = strv_free(*l);
    1327                 :          0 :                 return 0;
    1328                 :            :         }
    1329                 :            : 
    1330                 :          0 :         for (;;) {
    1331   [ #  #  #  # ]:          0 :                 _cleanup_free_ char *w = NULL;
    1332                 :            : 
    1333                 :          0 :                 r = extract_first_word(&rvalue, &w, NULL, 0);
    1334         [ #  # ]:          0 :                 if (r == -ENOMEM)
    1335                 :          0 :                         return log_oom();
    1336         [ #  # ]:          0 :                 if (r < 0) {
    1337         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
    1338                 :            :                                    "Failed to split user classes option, ignoring: %s", rvalue);
    1339                 :          0 :                         break;
    1340                 :            :                 }
    1341         [ #  # ]:          0 :                 if (r == 0)
    1342                 :          0 :                         break;
    1343                 :            : 
    1344         [ #  # ]:          0 :                 if (strlen(w) > 255) {
    1345         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
    1346                 :            :                                    "%s length is not in the range 1-255, ignoring.", w);
    1347                 :          0 :                         continue;
    1348                 :            :                 }
    1349                 :            : 
    1350                 :          0 :                 r = strv_push(l, w);
    1351         [ #  # ]:          0 :                 if (r < 0)
    1352                 :          0 :                         return log_oom();
    1353                 :            : 
    1354                 :          0 :                 w = NULL;
    1355                 :            :         }
    1356                 :            : 
    1357                 :          0 :         return 0;
    1358                 :            : }
    1359                 :            : 
    1360                 :            : static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
    1361                 :            :         [DHCP_CLIENT_ID_MAC] = "mac",
    1362                 :            :         [DHCP_CLIENT_ID_DUID] = "duid",
    1363                 :            :         [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
    1364                 :            : };
    1365                 :            : 
    1366                 :          0 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
    1367   [ #  #  #  #  :          0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier,
          #  #  #  #  #  
                #  #  # ]
    1368                 :            :                          "Failed to parse client identifier type");

Generated by: LCOV version 1.14