LCOV - code coverage report
Current view: top level - network - networkd-dhcp4.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 0 355 0.0 %
Date: 2015-07-29 18:47:03 Functions: 0 9 0.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2013-2014 Tom Gundersen <teg@jklm.no>
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <netinet/ether.h>
      23             : #include <linux/if.h>
      24             : 
      25             : #include "hostname-util.h"
      26             : #include "networkd-link.h"
      27             : #include "network-internal.h"
      28             : #include "dhcp-lease-internal.h"
      29             : 
      30           0 : static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
      31             :                                void *userdata) {
      32           0 :         _cleanup_link_unref_ Link *link = userdata;
      33             :         int r;
      34             : 
      35           0 :         assert(link);
      36           0 :         assert(link->dhcp4_messages);
      37             : 
      38           0 :         link->dhcp4_messages --;
      39             : 
      40           0 :         r = sd_netlink_message_get_errno(m);
      41           0 :         if (r < 0 && r != -EEXIST) {
      42           0 :                 log_link_error(link, "could not set DHCPv4 route: %s",
      43             :                                strerror(-r));
      44           0 :                 link_enter_failed(link);
      45             :         }
      46             : 
      47           0 :         if (!link->dhcp4_messages) {
      48           0 :                 link->dhcp4_configured = true;
      49           0 :                 link_client_handler(link);
      50             :         }
      51             : 
      52           0 :         return 1;
      53             : }
      54             : 
      55           0 : static int link_set_dhcp_routes(Link *link) {
      56             :         struct in_addr gateway;
      57             :         struct sd_dhcp_route *static_routes;
      58             :         int r, n, i;
      59             : 
      60           0 :         assert(link);
      61           0 :         assert(link->dhcp_lease);
      62             : 
      63           0 :         r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
      64           0 :         if (r < 0 && r != -ENOENT) {
      65           0 :                 log_link_warning(link,
      66             :                                  "DHCP error: could not get gateway: %s",
      67             :                                  strerror(-r));
      68           0 :                 return r;
      69             :         }
      70           0 :         if (r >= 0) {
      71             :                 struct in_addr address;
      72           0 :                 _cleanup_route_free_ Route *route = NULL;
      73           0 :                 _cleanup_route_free_ Route *route_gw = NULL;
      74             : 
      75           0 :                 r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
      76           0 :                 if (r < 0) {
      77           0 :                         log_link_warning(link,
      78             :                                          "DHCP error: could not get address: %s",
      79             :                                          strerror(-r));
      80           0 :                         return r;
      81             :                 }
      82             : 
      83           0 :                 r = route_new_dynamic(&route, RTPROT_DHCP);
      84           0 :                 if (r < 0) {
      85           0 :                         log_link_error(link,
      86             :                                        "Could not allocate route: %s",
      87             :                                        strerror(-r));
      88           0 :                         return r;
      89             :                 }
      90             : 
      91           0 :                 r = route_new_dynamic(&route_gw, RTPROT_DHCP);
      92           0 :                 if (r < 0) {
      93           0 :                 log_link_error(link,
      94             :                                "Could not allocate route: %s",
      95             :                                strerror(-r));
      96           0 :                                return r;
      97             :                 }
      98             : 
      99             :                 /* The dhcp netmask may mask out the gateway. Add an explicit
     100             :                  * route for the gw host so that we can route no matter the
     101             :                  * netmask or existing kernel route tables. */
     102           0 :                 route_gw->family = AF_INET;
     103           0 :                 route_gw->dst_addr.in = gateway;
     104           0 :                 route_gw->dst_prefixlen = 32;
     105           0 :                 route_gw->prefsrc_addr.in = address;
     106           0 :                 route_gw->scope = RT_SCOPE_LINK;
     107           0 :                 route_gw->metrics = link->network->dhcp_route_metric;
     108             : 
     109           0 :                 r = route_configure(route_gw, link, &dhcp4_route_handler);
     110           0 :                 if (r < 0) {
     111           0 :                         log_link_warning(link,
     112             :                                          "could not set host route: %s",
     113             :                                          strerror(-r));
     114           0 :                         return r;
     115             :                 }
     116             : 
     117           0 :                 link->dhcp4_messages ++;
     118             : 
     119           0 :                 route->family = AF_INET;
     120           0 :                 route->in_addr.in = gateway;
     121           0 :                 route->prefsrc_addr.in = address;
     122           0 :                 route->metrics = link->network->dhcp_route_metric;
     123             : 
     124           0 :                 r = route_configure(route, link, &dhcp4_route_handler);
     125           0 :                 if (r < 0) {
     126           0 :                         log_link_warning(link,
     127             :                                          "could not set routes: %s",
     128             :                                          strerror(-r));
     129           0 :                         link_enter_failed(link);
     130           0 :                         return r;
     131             :                 }
     132             : 
     133           0 :                 link->dhcp4_messages ++;
     134             :         }
     135             : 
     136           0 :         n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
     137           0 :         if (n == -ENOENT)
     138           0 :                 return 0;
     139           0 :         if (n < 0) {
     140           0 :                 log_link_warning(link,
     141             :                                  "DHCP error: could not get routes: %s",
     142             :                                  strerror(-n));
     143             : 
     144           0 :                 return n;
     145             :         }
     146             : 
     147           0 :         for (i = 0; i < n; i++) {
     148           0 :                 _cleanup_route_free_ Route *route = NULL;
     149             : 
     150           0 :                 r = route_new_dynamic(&route, RTPROT_DHCP);
     151           0 :                 if (r < 0) {
     152           0 :                         log_link_error(link, "Could not allocate route: %s",
     153             :                                        strerror(-r));
     154           0 :                         return r;
     155             :                 }
     156             : 
     157           0 :                 route->family = AF_INET;
     158           0 :                 route->in_addr.in = static_routes[i].gw_addr;
     159           0 :                 route->dst_addr.in = static_routes[i].dst_addr;
     160           0 :                 route->dst_prefixlen = static_routes[i].dst_prefixlen;
     161           0 :                 route->metrics = link->network->dhcp_route_metric;
     162             : 
     163           0 :                 r = route_configure(route, link, &dhcp4_route_handler);
     164           0 :                 if (r < 0) {
     165           0 :                         log_link_warning(link,
     166             :                                          "could not set host route: %s",
     167             :                                          strerror(-r));
     168           0 :                         return r;
     169             :                 }
     170             : 
     171           0 :                 link->dhcp4_messages ++;
     172             :         }
     173             : 
     174           0 :         return 0;
     175             : }
     176             : 
     177           0 : static int dhcp_lease_lost(Link *link) {
     178           0 :         _cleanup_address_free_ Address *address = NULL;
     179             :         struct in_addr addr;
     180             :         struct in_addr netmask;
     181             :         struct in_addr gateway;
     182           0 :         unsigned prefixlen = 0;
     183             :         int r;
     184             : 
     185           0 :         assert(link);
     186           0 :         assert(link->dhcp_lease);
     187             : 
     188           0 :         log_link_warning(link, "DHCP lease lost");
     189             : 
     190           0 :         if (link->network->dhcp_routes) {
     191             :                 struct sd_dhcp_route *routes;
     192             :                 int n, i;
     193             : 
     194           0 :                 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
     195           0 :                 if (n >= 0) {
     196           0 :                         for (i = 0; i < n; i++) {
     197           0 :                                 _cleanup_route_free_ Route *route = NULL;
     198             : 
     199           0 :                                 r = route_new_dynamic(&route, RTPROT_UNSPEC);
     200           0 :                                 if (r >= 0) {
     201           0 :                                         route->family = AF_INET;
     202           0 :                                         route->in_addr.in = routes[i].gw_addr;
     203           0 :                                         route->dst_addr.in = routes[i].dst_addr;
     204           0 :                                         route->dst_prefixlen = routes[i].dst_prefixlen;
     205             : 
     206           0 :                                         route_drop(route, link,
     207             :                                                    &link_route_drop_handler);
     208             :                                 }
     209             :                         }
     210             :                 }
     211             :         }
     212             : 
     213           0 :         r = address_new_dynamic(&address);
     214           0 :         if (r >= 0) {
     215           0 :                 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
     216           0 :                 if (r >= 0) {
     217           0 :                         _cleanup_route_free_ Route *route_gw = NULL;
     218           0 :                         _cleanup_route_free_ Route *route = NULL;
     219             : 
     220           0 :                         r = route_new_dynamic(&route_gw, RTPROT_UNSPEC);
     221           0 :                         if (r >= 0) {
     222           0 :                                 route_gw->family = AF_INET;
     223           0 :                                 route_gw->dst_addr.in = gateway;
     224           0 :                                 route_gw->dst_prefixlen = 32;
     225           0 :                                 route_gw->scope = RT_SCOPE_LINK;
     226             : 
     227           0 :                                 route_drop(route_gw, link,
     228             :                                            &link_route_drop_handler);
     229             :                         }
     230             : 
     231           0 :                         r = route_new_dynamic(&route, RTPROT_UNSPEC);
     232           0 :                         if (r >= 0) {
     233           0 :                                 route->family = AF_INET;
     234           0 :                                 route->in_addr.in = gateway;
     235             : 
     236           0 :                                 route_drop(route, link,
     237             :                                            &link_route_drop_handler);
     238             :                         }
     239             :                 }
     240             : 
     241           0 :                 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
     242           0 :                 if (r >= 0) {
     243           0 :                         r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
     244           0 :                         if (r >= 0)
     245           0 :                                 prefixlen = in_addr_netmask_to_prefixlen(&netmask);
     246             : 
     247           0 :                         address->family = AF_INET;
     248           0 :                         address->in_addr.in = addr;
     249           0 :                         address->prefixlen = prefixlen;
     250             : 
     251           0 :                        address_drop(address, link, &link_address_drop_handler);
     252             :                 }
     253             :         }
     254             : 
     255           0 :         if (link->network->dhcp_mtu) {
     256             :                 uint16_t mtu;
     257             : 
     258           0 :                 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
     259           0 :                 if (r >= 0 && link->original_mtu != mtu) {
     260           0 :                         r = link_set_mtu(link, link->original_mtu);
     261           0 :                         if (r < 0) {
     262           0 :                                 log_link_warning(link,
     263             :                                                  "DHCP error: could not reset MTU");
     264           0 :                                 link_enter_failed(link);
     265           0 :                                 return r;
     266             :                         }
     267             :                 }
     268             :         }
     269             : 
     270           0 :         if (link->network->dhcp_hostname) {
     271           0 :                 const char *hostname = NULL;
     272             : 
     273           0 :                 if (!link->network->hostname)
     274           0 :                         r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
     275             :                 else
     276           0 :                         hostname = link->network->hostname;
     277             : 
     278           0 :                 if (r >= 0 || hostname) {
     279           0 :                         r = link_set_hostname(link, hostname);
     280           0 :                         if (r < 0)
     281           0 :                                 log_link_error_errno(link, r,
     282             :                                                      "Failed to set transient hostname to '%s': %m",
     283             :                                                      hostname);
     284             : 
     285             :                 }
     286             :         }
     287             : 
     288           0 :         link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
     289           0 :         link->dhcp4_configured = false;
     290             : 
     291           0 :         return 0;
     292             : }
     293             : 
     294           0 : static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
     295             :                                  void *userdata) {
     296           0 :         _cleanup_link_unref_ Link *link = userdata;
     297             :         int r;
     298             : 
     299           0 :         assert(link);
     300             : 
     301           0 :         r = sd_netlink_message_get_errno(m);
     302           0 :         if (r < 0 && r != -EEXIST) {
     303           0 :                 log_link_error(link, "could not set DHCPv4 address: %s",
     304             :                                strerror(-r));
     305           0 :                 link_enter_failed(link);
     306           0 :         } else if (r >= 0)
     307           0 :                 link_rtnl_process_address(rtnl, m, link->manager);
     308             : 
     309           0 :         link_set_dhcp_routes(link);
     310             : 
     311           0 :         return 1;
     312             : }
     313             : 
     314           0 : static int dhcp4_update_address(Link *link,
     315             :                                 struct in_addr *address,
     316             :                                 struct in_addr *netmask,
     317             :                                 uint32_t lifetime) {
     318           0 :         _cleanup_address_free_ Address *addr = NULL;
     319             :         unsigned prefixlen;
     320             :         int r;
     321             : 
     322           0 :         assert(address);
     323           0 :         assert(netmask);
     324           0 :         assert(lifetime);
     325             : 
     326           0 :         prefixlen = in_addr_netmask_to_prefixlen(netmask);
     327             : 
     328           0 :         r = address_new_dynamic(&addr);
     329           0 :         if (r < 0)
     330           0 :                 return r;
     331             : 
     332           0 :         addr->family = AF_INET;
     333           0 :         addr->in_addr.in.s_addr = address->s_addr;
     334           0 :         addr->cinfo.ifa_prefered = lifetime;
     335           0 :         addr->cinfo.ifa_valid = lifetime;
     336           0 :         addr->prefixlen = prefixlen;
     337           0 :         addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
     338             : 
     339             :         /* use update rather than configure so that we will update the
     340             :          * lifetime of an existing address if it has already been configured */
     341           0 :         r = address_update(addr, link, &dhcp4_address_handler);
     342           0 :         if (r < 0)
     343           0 :                 return r;
     344             : 
     345           0 :         return 0;
     346             : }
     347             : 
     348           0 : static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
     349             :         sd_dhcp_lease *lease;
     350             :         struct in_addr address;
     351             :         struct in_addr netmask;
     352           0 :         uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
     353             :         int r;
     354             : 
     355           0 :         assert(link);
     356           0 :         assert(client);
     357           0 :         assert(link->network);
     358             : 
     359           0 :         r = sd_dhcp_client_get_lease(client, &lease);
     360           0 :         if (r < 0) {
     361           0 :                 log_link_warning(link, "DHCP error: no lease %s",
     362             :                                  strerror(-r));
     363           0 :                 return r;
     364             :         }
     365             : 
     366           0 :         sd_dhcp_lease_unref(link->dhcp_lease);
     367           0 :         link->dhcp4_configured = false;
     368           0 :         link->dhcp_lease = lease;
     369             : 
     370           0 :         r = sd_dhcp_lease_get_address(lease, &address);
     371           0 :         if (r < 0) {
     372           0 :                 log_link_warning(link, "DHCP error: no address: %s",
     373             :                                  strerror(-r));
     374           0 :                 return r;
     375             :         }
     376             : 
     377           0 :         r = sd_dhcp_lease_get_netmask(lease, &netmask);
     378           0 :         if (r < 0) {
     379           0 :                 log_link_warning(link, "DHCP error: no netmask: %s",
     380             :                                  strerror(-r));
     381           0 :                 return r;
     382             :         }
     383             : 
     384           0 :         if (!link->network->dhcp_critical) {
     385           0 :                 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease,
     386             :                                                &lifetime);
     387           0 :                 if (r < 0) {
     388           0 :                         log_link_warning(link,
     389             :                                          "DHCP error: no lifetime: %s",
     390             :                                          strerror(-r));
     391           0 :                         return r;
     392             :                 }
     393             :         }
     394             : 
     395           0 :         r = dhcp4_update_address(link, &address, &netmask, lifetime);
     396           0 :         if (r < 0) {
     397           0 :                 log_link_warning(link, "could not update IP address: %s",
     398             :                                  strerror(-r));
     399           0 :                 link_enter_failed(link);
     400           0 :                 return r;
     401             :         }
     402             : 
     403           0 :         return 0;
     404             : }
     405             : 
     406           0 : static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
     407             :         sd_dhcp_lease *lease;
     408             :         struct in_addr address;
     409             :         struct in_addr netmask;
     410             :         struct in_addr gateway;
     411             :         unsigned prefixlen;
     412           0 :         uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
     413             :         int r;
     414             : 
     415           0 :         assert(client);
     416           0 :         assert(link);
     417             : 
     418           0 :         r = sd_dhcp_client_get_lease(client, &lease);
     419           0 :         if (r < 0)
     420           0 :                 return log_link_error_errno(link, r, "DHCP error: no lease: %m");
     421             : 
     422           0 :         r = sd_dhcp_lease_get_address(lease, &address);
     423           0 :         if (r < 0)
     424           0 :                 return log_link_error_errno(link, r, "DHCP error: no address: %m");
     425             : 
     426           0 :         r = sd_dhcp_lease_get_netmask(lease, &netmask);
     427           0 :         if (r < 0)
     428           0 :                 return log_link_error_errno(link, r, "DHCP error: no netmask: %m");
     429             : 
     430           0 :         prefixlen = in_addr_netmask_to_prefixlen(&netmask);
     431             : 
     432           0 :         r = sd_dhcp_lease_get_router(lease, &gateway);
     433           0 :         if (r < 0 && r != -ENOENT)
     434           0 :                 return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
     435             : 
     436           0 :         if (r >= 0)
     437           0 :                 log_struct(LOG_INFO,
     438             :                            LOG_LINK_INTERFACE(link),
     439             :                            LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
     440             :                                             ADDRESS_FMT_VAL(address),
     441             :                                             prefixlen,
     442             :                                             ADDRESS_FMT_VAL(gateway)),
     443             :                            "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
     444             :                            "PREFIXLEN=%u", prefixlen,
     445             :                            "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway),
     446             :                            NULL);
     447             :         else
     448           0 :                 log_struct(LOG_INFO,
     449             :                            LOG_LINK_INTERFACE(link),
     450             :                            LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
     451             :                                             ADDRESS_FMT_VAL(address),
     452             :                                             prefixlen),
     453             :                            "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
     454             :                            "PREFIXLEN=%u", prefixlen,
     455             :                            NULL);
     456             : 
     457           0 :         link->dhcp_lease = lease;
     458             : 
     459           0 :         if (link->network->dhcp_mtu) {
     460             :                 uint16_t mtu;
     461             : 
     462           0 :                 r = sd_dhcp_lease_get_mtu(lease, &mtu);
     463           0 :                 if (r >= 0) {
     464           0 :                         r = link_set_mtu(link, mtu);
     465           0 :                         if (r < 0)
     466           0 :                                 log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
     467             :                 }
     468             :         }
     469             : 
     470           0 :         if (link->network->dhcp_hostname) {
     471             :                 const char *hostname;
     472             : 
     473           0 :                 if (!link->network->hostname)
     474           0 :                         r = sd_dhcp_lease_get_hostname(lease, &hostname);
     475             :                 else
     476           0 :                         hostname = link->network->hostname;
     477             : 
     478           0 :                 if (r >= 0 || hostname) {
     479           0 :                         r = link_set_hostname(link, hostname);
     480           0 :                         if (r < 0)
     481           0 :                                 log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
     482             :                 }
     483             :         }
     484             : 
     485           0 :         if (!link->network->dhcp_critical) {
     486           0 :                 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
     487           0 :                 if (r < 0) {
     488           0 :                         log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
     489           0 :                         return r;
     490             :                 }
     491             :         }
     492             : 
     493           0 :         r = dhcp4_update_address(link, &address, &netmask, lifetime);
     494           0 :         if (r < 0) {
     495           0 :                 log_link_warning_errno(link, r, "Could not update IP address: %m");
     496           0 :                 link_enter_failed(link);
     497           0 :                 return r;
     498             :         }
     499             : 
     500           0 :         return 0;
     501             : }
     502           0 : static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
     503           0 :         Link *link = userdata;
     504           0 :         int r = 0;
     505             : 
     506           0 :         assert(link);
     507           0 :         assert(link->network);
     508           0 :         assert(link->manager);
     509             : 
     510           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     511           0 :                 return;
     512             : 
     513           0 :         switch (event) {
     514             :                 case DHCP_EVENT_EXPIRED:
     515             :                 case DHCP_EVENT_STOP:
     516             :                 case DHCP_EVENT_IP_CHANGE:
     517           0 :                         if (link->network->dhcp_critical) {
     518           0 :                                 log_link_error(link,
     519             :                                                "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
     520           0 :                                 return;
     521             :                         }
     522             : 
     523           0 :                         if (link->dhcp_lease) {
     524           0 :                                 r = dhcp_lease_lost(link);
     525           0 :                                 if (r < 0) {
     526           0 :                                         link_enter_failed(link);
     527           0 :                                         return;
     528             :                                 }
     529             :                         }
     530             : 
     531           0 :                         if (event == DHCP_EVENT_IP_CHANGE) {
     532           0 :                                 r = dhcp_lease_acquired(client, link);
     533           0 :                                 if (r < 0) {
     534           0 :                                         link_enter_failed(link);
     535           0 :                                         return;
     536             :                                 }
     537             :                         }
     538             : 
     539           0 :                         break;
     540             :                 case DHCP_EVENT_RENEW:
     541           0 :                         r = dhcp_lease_renew(client, link);
     542           0 :                         if (r < 0) {
     543           0 :                                 link_enter_failed(link);
     544           0 :                                 return;
     545             :                         }
     546           0 :                         break;
     547             :                 case DHCP_EVENT_IP_ACQUIRE:
     548           0 :                         r = dhcp_lease_acquired(client, link);
     549           0 :                         if (r < 0) {
     550           0 :                                 link_enter_failed(link);
     551           0 :                                 return;
     552             :                         }
     553           0 :                         break;
     554             :                 default:
     555           0 :                         if (event < 0)
     556           0 :                                 log_link_warning(link,
     557             :                                                  "DHCP error: client failed: %s",
     558             :                                                  strerror(-event));
     559             :                         else
     560           0 :                                 log_link_warning(link,
     561             :                                                  "DHCP unknown event: %d",
     562             :                                                  event);
     563           0 :                         break;
     564             :         }
     565             : 
     566           0 :         return;
     567             : }
     568             : 
     569           0 : int dhcp4_configure(Link *link) {
     570             :         int r;
     571             : 
     572           0 :         assert(link);
     573           0 :         assert(link->network);
     574           0 :         assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
     575             : 
     576           0 :         r = sd_dhcp_client_new(&link->dhcp_client);
     577           0 :         if (r < 0)
     578           0 :                 return r;
     579             : 
     580           0 :         r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
     581           0 :         if (r < 0)
     582           0 :                 return r;
     583             : 
     584           0 :         r = sd_dhcp_client_set_mac(link->dhcp_client,
     585           0 :                                    (const uint8_t *) &link->mac,
     586             :                                    sizeof (link->mac), ARPHRD_ETHER);
     587           0 :         if (r < 0)
     588           0 :                 return r;
     589             : 
     590           0 :         r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
     591           0 :         if (r < 0)
     592           0 :                 return r;
     593             : 
     594           0 :         r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
     595           0 :         if (r < 0)
     596           0 :                 return r;
     597             : 
     598           0 :         r = sd_dhcp_client_set_request_broadcast(link->dhcp_client,
     599           0 :                                                  link->network->dhcp_broadcast);
     600           0 :         if (r < 0)
     601           0 :                 return r;
     602             : 
     603           0 :         if (link->mtu) {
     604           0 :                 r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
     605           0 :                 if (r < 0)
     606           0 :                         return r;
     607             :         }
     608             : 
     609           0 :         if (link->network->dhcp_mtu) {
     610           0 :              r = sd_dhcp_client_set_request_option(link->dhcp_client,
     611             :                                                    DHCP_OPTION_INTERFACE_MTU);
     612           0 :              if (r < 0)
     613           0 :                 return r;
     614             :         }
     615             : 
     616           0 :         if (link->network->dhcp_routes) {
     617           0 :                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
     618             :                                                       DHCP_OPTION_STATIC_ROUTE);
     619           0 :                 if (r < 0)
     620           0 :                         return r;
     621           0 :                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
     622             :                                                       DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
     623           0 :                         if (r < 0)
     624           0 :                                 return r;
     625             :         }
     626             : 
     627           0 :         if (link->network->dhcp_sendhost) {
     628           0 :                 _cleanup_free_ char *hostname = NULL;
     629           0 :                 const char *hn = NULL;
     630             : 
     631           0 :                 if (!link->network->hostname)  {
     632           0 :                         hostname = gethostname_malloc();
     633           0 :                         if (!hostname)
     634           0 :                                 return -ENOMEM;
     635             : 
     636           0 :                         hn = hostname;
     637             :                 } else
     638           0 :                         hn = link->network->hostname;
     639             : 
     640           0 :                 if (!is_localhost(hn)) {
     641           0 :                         r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
     642           0 :                         if (r < 0)
     643           0 :                                 return r;
     644             :                 }
     645             :         }
     646             : 
     647           0 :         if (link->network->dhcp_vendor_class_identifier) {
     648           0 :                 r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
     649           0 :                                                                link->network->dhcp_vendor_class_identifier);
     650           0 :                 if (r < 0)
     651           0 :                         return r;
     652             :         }
     653             : 
     654           0 :         switch (link->network->dhcp_client_identifier) {
     655             :         case DHCP_CLIENT_ID_DUID:
     656             :                 /* Library defaults to this. */
     657           0 :                 break;
     658             :         case DHCP_CLIENT_ID_MAC:
     659           0 :                 r = sd_dhcp_client_set_client_id(link->dhcp_client,
     660             :                                                  ARPHRD_ETHER,
     661           0 :                                                  (const uint8_t *) &link->mac,
     662             :                                                  sizeof (link->mac));
     663           0 :                 if (r < 0)
     664           0 :                         return r;
     665           0 :                 break;
     666             :         default:
     667           0 :                 assert_not_reached("Unknown client identifier type.");
     668             :         }
     669             : 
     670           0 :         return 0;
     671             : }

Generated by: LCOV version 1.11