networkd-dhcp4.c revision 4b7b5abb785c03cb880e3a8a7a724d7de6e9cf3b
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/***
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering This file is part of systemd.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Copyright 2013-2014 Tom Gundersen <teg@jklm.no>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is free software; you can redistribute it and/or modify it
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering under the terms of the GNU Lesser General Public License as published by
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (at your option) any later version.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is distributed in the hope that it will be useful, but
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Lesser General Public License for more details.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering You should have received a copy of the GNU Lesser General Public License
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering***/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <netinet/ether.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <linux/if.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "hostname-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "networkd-link.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "network-internal.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "dhcp-lease-internal.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering void *userdata) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_link_unref_ Link *link = userdata;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link->dhcp4_messages);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link->dhcp4_messages --;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_netlink_message_get_errno(m);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0 && r != -EEXIST) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_error(link, "could not set DHCPv4 route: %s",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link_enter_failed(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!link->dhcp4_messages) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link->dhcp4_configured = true;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link_client_handler(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 1;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int link_set_dhcp_routes(Link *link) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering struct in_addr gateway;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering struct sd_dhcp_route *static_routes;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r, n, i;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link->dhcp_lease);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0 && r != -ENOENT) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning(link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "DHCP error: could not get gateway: %s",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering struct in_addr address;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_route_free_ Route *route = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_route_free_ Route *route_gw = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning(link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "DHCP error: could not get address: %s",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = route_new_dynamic(&route, RTPROT_DHCP);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_error(link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "Could not allocate route: %s",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = route_new_dynamic(&route_gw, RTPROT_DHCP);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_link_error(link,
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering "Could not allocate route: %s",
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering strerror(-r));
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering /* The dhcp netmask may mask out the gateway. Add an explicit
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering * route for the gw host so that we can route no matter the
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering * netmask or existing kernel route tables. */
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route_gw->family = AF_INET;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route_gw->dst_addr.in = gateway;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route_gw->dst_prefixlen = 32;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route_gw->prefsrc_addr.in = address;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route_gw->scope = RT_SCOPE_LINK;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route_gw->metrics = link->network->dhcp_route_metric;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = route_configure(route_gw, link, &dhcp4_route_handler);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_link_warning(link,
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering "could not set host route: %s",
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering strerror(-r));
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering link->dhcp4_messages ++;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->family = AF_INET;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->in_addr.in = gateway;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->prefsrc_addr.in = address;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->metrics = link->network->dhcp_route_metric;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = route_configure(route, link, &dhcp4_route_handler);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_link_warning(link,
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering "could not set routes: %s",
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering strerror(-r));
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering link_enter_failed(link);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering link->dhcp4_messages ++;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (n == -ENOENT)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return 0;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (n < 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_link_warning(link,
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering "DHCP error: could not get routes: %s",
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering strerror(-n));
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return n;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering for (i = 0; i < n; i++) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering _cleanup_route_free_ Route *route = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = route_new_dynamic(&route, RTPROT_DHCP);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_error(link, "Could not allocate route: %s",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->family = AF_INET;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->in_addr.in = static_routes[i].gw_addr;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->dst_addr.in = static_routes[i].dst_addr;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->dst_prefixlen = static_routes[i].dst_prefixlen;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->metrics = link->network->dhcp_route_metric;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = route_configure(route, link, &dhcp4_route_handler);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning(link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "could not set host route: %s",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link->dhcp4_messages ++;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int dhcp_lease_lost(Link *link) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_address_free_ Address *address = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering struct in_addr addr;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering struct in_addr netmask;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering struct in_addr gateway;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering unsigned prefixlen = 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link->dhcp_lease);
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning(link, "DHCP lease lost");
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (link->network->dhcp_routes) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering struct sd_dhcp_route *routes;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering int n, i;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (n >= 0) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering for (i = 0; i < n; i++) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering _cleanup_route_free_ Route *route = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = route_new_dynamic(&route, RTPROT_UNSPEC);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r >= 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->family = AF_INET;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->in_addr.in = routes[i].gw_addr;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->dst_addr.in = routes[i].dst_addr;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->dst_prefixlen = routes[i].dst_prefixlen;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route_drop(route, link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering &link_route_drop_handler);
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering }
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering }
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering }
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering }
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering r = address_new_dynamic(&address);
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering if (r >= 0) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_route_free_ Route *route_gw = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_route_free_ Route *route = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = route_new_dynamic(&route_gw, RTPROT_UNSPEC);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route_gw->family = AF_INET;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route_gw->dst_addr.in = gateway;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route_gw->dst_prefixlen = 32;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route_gw->scope = RT_SCOPE_LINK;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route_drop(route_gw, link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering &link_route_drop_handler);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = route_new_dynamic(&route, RTPROT_UNSPEC);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->family = AF_INET;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->in_addr.in = gateway;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route_drop(route, link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering &link_route_drop_handler);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering prefixlen = in_addr_netmask_to_prefixlen(&netmask);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering address->family = AF_INET;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering address->in_addr.in = addr;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering address->prefixlen = prefixlen;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering address_drop(address, link, &link_address_drop_handler);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->network->dhcp_mtu) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering uint16_t mtu;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0 && link->original_mtu != mtu) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = link_set_mtu(link, link->original_mtu);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_warning(link,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering "DHCP error: could not reset MTU");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_enter_failed(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (link->network->dhcp_hostname) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering const char *hostname = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (!link->network->hostname)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering else
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering hostname = link->network->hostname;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r >= 0 || hostname) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = link_set_hostname(link, hostname);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_error_errno(link, r,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering "Failed to set transient hostname to '%s': %m",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering hostname);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link->dhcp4_configured = false;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return 0;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering}
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringstatic int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering void *userdata) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_link_unref_ Link *link = userdata;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering int r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_netlink_message_get_errno(m);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0 && r != -EEXIST) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_error(link, "could not set DHCPv4 address: %s",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering strerror(-r));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_enter_failed(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering } else if (r >= 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_rtnl_process_address(rtnl, m, link->manager);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_set_dhcp_routes(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return 1;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering}
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringstatic int dhcp4_update_address(Link *link,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering struct in_addr *address,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering struct in_addr *netmask,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering uint32_t lifetime) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_address_free_ Address *addr = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering unsigned prefixlen;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering int r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(address);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(netmask);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(lifetime);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering prefixlen = in_addr_netmask_to_prefixlen(netmask);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = address_new_dynamic(&addr);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering addr->family = AF_INET;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering addr->in_addr.in.s_addr = address->s_addr;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering addr->cinfo.ifa_prefered = lifetime;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering addr->cinfo.ifa_valid = lifetime;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering addr->prefixlen = prefixlen;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering /* use update rather than configure so that we will update the
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering * lifetime of an existing address if it has already been configured */
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = address_update(addr, link, &dhcp4_address_handler);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return 0;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering}
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringstatic int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sd_dhcp_lease *lease;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering struct in_addr address;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering struct in_addr netmask;
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering int r;
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering assert(link);
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering assert(client);
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering assert(link->network);
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering r = sd_dhcp_client_get_lease(client, &lease);
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_warning(link, "DHCP error: no lease %s",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering strerror(-r));
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sd_dhcp_lease_unref(link->dhcp_lease);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link->dhcp4_configured = false;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link->dhcp_lease = sd_dhcp_lease_ref(lease);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_dhcp_lease_get_address(lease, &address);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_warning(link, "DHCP error: no address: %s",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering strerror(-r));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_dhcp_lease_get_netmask(lease, &netmask);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_warning(link, "DHCP error: no netmask: %s",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering strerror(-r));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (!link->network->dhcp_critical) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_dhcp_lease_get_lifetime(link->dhcp_lease,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering &lifetime);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_warning(link,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering "DHCP error: no lifetime: %s",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering strerror(-r));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = dhcp4_update_address(link, &address, &netmask, lifetime);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning(link, "could not update IP address: %s",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering strerror(-r));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_enter_failed(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering return 0;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering}
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poetteringstatic int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering sd_dhcp_lease *lease;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering struct in_addr address;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering struct in_addr netmask;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering struct in_addr gateway;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering unsigned prefixlen;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering int r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(client);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_get_lease(client, &lease);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return log_link_error_errno(link, r, "DHCP error: no lease: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_address(lease, &address);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return log_link_error_errno(link, r, "DHCP error: no address: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_netmask(lease, &netmask);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return log_link_error_errno(link, r, "DHCP error: no netmask: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering prefixlen = in_addr_netmask_to_prefixlen(&netmask);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_dhcp_lease_get_router(lease, &gateway);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0 && r != -ENOENT)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_struct(LOG_INFO,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering LOG_LINK_INTERFACE(link),
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ADDRESS_FMT_VAL(address),
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering prefixlen,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ADDRESS_FMT_VAL(gateway)),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "PREFIXLEN=%u", prefixlen,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering NULL);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering else
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_struct(LOG_INFO,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering LOG_LINK_INTERFACE(link),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering ADDRESS_FMT_VAL(address),
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering prefixlen),
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "PREFIXLEN=%u", prefixlen,
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering NULL);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link->dhcp_lease = sd_dhcp_lease_ref(lease);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (link->network->dhcp_mtu) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering uint16_t mtu;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_mtu(lease, &mtu);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r >= 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = link_set_mtu(link, mtu);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->network->dhcp_hostname) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *hostname = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!link->network->hostname)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_hostname(lease, &hostname);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering else
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering hostname = link->network->hostname;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r >= 0 || hostname) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = link_set_hostname(link, hostname);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!link->network->dhcp_critical) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = dhcp4_update_address(link, &address, &netmask, lifetime);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning_errno(link, r, "Could not update IP address: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link_enter_failed(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Link *link = userdata;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r = 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link->network);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link->manager);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering switch (event) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case DHCP_EVENT_EXPIRED:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case DHCP_EVENT_STOP:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case DHCP_EVENT_IP_CHANGE:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->network->dhcp_critical) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_error(link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->dhcp_lease) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = dhcp_lease_lost(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link_enter_failed(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (event == DHCP_EVENT_IP_CHANGE) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = dhcp_lease_acquired(client, link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link_enter_failed(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case DHCP_EVENT_RENEW:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = dhcp_lease_renew(client, link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link_enter_failed(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case DHCP_EVENT_IP_ACQUIRE:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = dhcp_lease_acquired(client, link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link_enter_failed(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering default:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (event < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning(link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "DHCP error: client failed: %s",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering strerror(-event));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering else
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning(link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "DHCP unknown event: %d",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering event);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringint dhcp4_configure(Link *link) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link->network);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_new(&link->dhcp_client);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_mac(link->dhcp_client,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (const uint8_t *) &link->mac,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sizeof (link->mac), ARPHRD_ETHER);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_request_broadcast(link->dhcp_client,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link->network->dhcp_broadcast);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->mtu) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->network->dhcp_mtu) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_request_option(link->dhcp_client,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering DHCP_OPTION_INTERFACE_MTU);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->network->dhcp_routes) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_request_option(link->dhcp_client,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering DHCP_OPTION_STATIC_ROUTE);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_request_option(link->dhcp_client,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Always acquire the timezone and NTP*/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NTP_SERVER);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NEW_TZDB_TIMEZONE);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->network->dhcp_sendhost) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *hostname = NULL;
const char *hn = NULL;
if (!link->network->hostname) {
hostname = gethostname_malloc();
if (!hostname)
return -ENOMEM;
hn = hostname;
} else
hn = link->network->hostname;
if (!is_localhost(hn)) {
r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
if (r < 0)
return r;
}
}
if (link->network->dhcp_vendor_class_identifier) {
r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
link->network->dhcp_vendor_class_identifier);
if (r < 0)
return r;
}
switch (link->network->dhcp_client_identifier) {
case DHCP_CLIENT_ID_DUID:
/* Library defaults to this. */
break;
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,
ARPHRD_ETHER,
(const uint8_t *) &link->mac,
sizeof (link->mac));
if (r < 0)
return r;
break;
default:
assert_not_reached("Unknown client identifier type.");
}
return 0;
}