networkd-dhcp4.c revision 6c861f0aeff9449ee1201bb56f89861921e41c45
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>
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "networkd-link.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "network-internal.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "dhcp-lease-internal.h"
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersenstatic int dhcp4_route_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering void *userdata) {
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen _cleanup_link_unref_ Link *link = userdata;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani assert(link->dhcp4_messages);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen link->dhcp4_messages --;
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_get_errno(m);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0 && r != -EEXIST) {
db73295accbec0c6513817f0a64a92018592bb26Lennart Poettering log_link_error(link, "could not set DHCPv4 route: %s",
d8500c53789eafefe28d4ace088bf4b912280bf9Tom Gundersen strerror(-r));
266b538958932e6fc27dfce4917336e70e17e29eTom Gundersen link_enter_failed(link);
288a74cce597f81d3ba01d8a5ca7d2ba5b654b7eRonny Chevalier }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!link->dhcp4_messages) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link->dhcp4_configured = true;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart 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;
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(link->dhcp_lease);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen if (r < 0 && r != -ENOENT) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_warning(link,
732b7f39a2b3b1a2af90102c6262186ae71197acRonny Chevalier "DHCP error: could not get gateway: %s",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen struct in_addr address;
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen _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
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = route_new_dynamic(&route_gw, 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
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* The dhcp netmask may mask out the gateway. Add an explicit
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering * route for the gw host so that we can route no matter the
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering * netmask or existing kernel route tables. */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route_gw->family = AF_INET;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart 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);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_link_error(link, "Could not allocate route: %s",
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering strerror(-r));
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
a6a4f528899b1dab47408733b4a423c66ea40f7aThomas Hindoe Paaboel Andersen
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->family = AF_INET;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->in_addr.in = static_routes[i].gw_addr;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->dst_addr.in = static_routes[i].dst_addr;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->dst_prefixlen = static_routes[i].dst_prefixlen;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering route->metrics = link->network->dhcp_route_metric;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = route_configure(route, link, &dhcp4_route_handler);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering if (r < 0) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering log_link_warning(link,
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering "could not set host route: %s",
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering strerror(-r));
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering return r;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering }
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering link->dhcp4_messages ++;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering }
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering return 0;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering}
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poetteringstatic int dhcp_lease_lost(Link *link) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering _cleanup_address_free_ Address *address = NULL;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering struct in_addr addr;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering struct in_addr netmask;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering struct in_addr gateway;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering unsigned prefixlen = 0;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering int r;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering assert(link);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering assert(link->dhcp_lease);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering log_link_warning(link, "DHCP lease lost");
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering if (link->network->dhcp_routes) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering struct sd_dhcp_route *routes;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering int n, i;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
266b538958932e6fc27dfce4917336e70e17e29eTom Gundersen if (n >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering for (i = 0; i < n; i++) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_route_free_ Route *route = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart 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 = routes[i].gw_addr;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->dst_addr.in = routes[i].dst_addr;
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt route->dst_prefixlen = routes[i].dst_prefixlen;
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route_drop(route, link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering &link_route_drop_handler);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = address_new_dynamic(&address);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (r >= 0) {
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt _cleanup_route_free_ Route *route_gw = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_route_free_ Route *route = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
3e3db0ee860025ad663b13b0ace4e6d627611332Lennart Poettering r = route_new_dynamic(&route_gw, RTPROT_UNSPEC);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
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->scope = RT_SCOPE_LINK;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
ab1525bc2d92780b4dc64bc5b9cdb52594e2df7dLennart Poettering route_drop(route_gw, link,
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen &link_route_drop_handler);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering }
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering r = route_new_dynamic(&route, RTPROT_UNSPEC);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering route->family = AF_INET;
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen route->in_addr.in = gateway;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering route_drop(route, link,
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering &link_route_drop_handler);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0)
3e3db0ee860025ad663b13b0ace4e6d627611332Lennart Poettering prefixlen = in_addr_netmask_to_prefixlen(&netmask);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering address->family = AF_INET;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering address->in_addr.in = addr;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering address->prefixlen = prefixlen;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering address_drop(address, link, &link_address_drop_handler);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->network->dhcp_mtu) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering uint16_t mtu;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen if (r >= 0 && link->original_mtu != mtu) {
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen r = link_set_mtu(link, link->original_mtu);
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen if (r < 0) {
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen log_link_warning(link,
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen "DHCP error: could not reset MTU");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen link_enter_failed(link);
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering return r;
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering }
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering }
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen }
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen if (link->network->dhcp_hostname) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen const char *hostname = NULL;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r >= 0 && hostname) {
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen r = link_set_hostname(link, "");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0)
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen log_link_error(link,
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen "Failed to reset transient hostname");
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen link->dhcp4_configured = false;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen return 0;
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen}
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersenstatic int dhcp4_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen void *userdata) {
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering _cleanup_link_unref_ Link *link = userdata;
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering int r;
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering assert(link);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering r = sd_rtnl_message_get_errno(m);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (r < 0 && r != -EEXIST) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_link_error(link, "could not set DHCPv4 address: %s",
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen link_enter_failed(link);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen } else if (r >= 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen /* calling handler directly so take a ref */
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen link_ref(link);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen link_get_address_handler(rtnl, m, link);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen link_set_dhcp_routes(link);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return 1;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen}
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersenstatic int dhcp4_update_address(Link *link,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen struct in_addr *address,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen struct in_addr *netmask,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen uint32_t lifetime) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen _cleanup_address_free_ Address *addr = NULL;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen unsigned prefixlen;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen int r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(address);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(netmask);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(lifetime);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen prefixlen = in_addr_netmask_to_prefixlen(netmask);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = address_new_dynamic(&addr);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen addr->family = AF_INET;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen addr->in_addr.in.s_addr = address->s_addr;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen addr->cinfo.ifa_prefered = lifetime;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen addr->cinfo.ifa_valid = lifetime;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen addr->prefixlen = prefixlen;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen /* use update rather than configure so that we will update the
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen * lifetime of an existing address if it has already been configured */
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = address_update(addr, link, &dhcp4_address_handler);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return 0;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen}
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersenstatic int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen sd_dhcp_lease *lease;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen struct in_addr address;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen struct in_addr netmask;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen int r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(link);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(client);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(link->network);
144232a8e0ea77eed8c5a456832758681b5b3511Torstein Husebø
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_dhcp_client_get_lease(client, &lease);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_link_warning(link, "DHCP error: no lease %s",
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen sd_dhcp_lease_unref(link->dhcp_lease);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen link->dhcp4_configured = false;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen link->dhcp_lease = lease;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_dhcp_lease_get_address(lease, &address);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_link_warning(link, "DHCP error: no address: %s",
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_dhcp_lease_get_netmask(lease, &netmask);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_link_warning(link, "DHCP error: no netmask: %s",
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (!link->network->dhcp_critical) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_dhcp_lease_get_lifetime(link->dhcp_lease,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen &lifetime);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_link_warning(link,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen "DHCP error: no lifetime: %s",
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = dhcp4_update_address(link, &address, &netmask, lifetime);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_link_warning(link, "could not update IP address: %s",
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen strerror(-r));
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering link_enter_failed(link);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering return r;
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen }
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering return 0;
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen}
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersenstatic int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen sd_dhcp_lease *lease;
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen struct in_addr address;
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen struct in_addr netmask;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen struct in_addr gateway;
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen unsigned prefixlen;
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen int r;
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(client);
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen assert(link);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering r = sd_dhcp_client_get_lease(client, &lease);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen log_link_warning(link, "DHCP error: no lease: %s",
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen strerror(-r));
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering return r;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering }
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering r = sd_dhcp_lease_get_address(lease, &address);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering if (r < 0) {
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen log_link_warning(link, "DHCP error: no address: %s",
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering strerror(-r));
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering return r;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering }
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering r = sd_dhcp_lease_get_netmask(lease, &netmask);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering if (r < 0) {
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering log_link_warning(link, "DHCP error: no netmask: %s",
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering strerror(-r));
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering return r;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering }
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering prefixlen = in_addr_netmask_to_prefixlen(&netmask);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering r = sd_dhcp_lease_get_router(lease, &gateway);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering if (r < 0 && r != -ENOENT) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_link_warning(link, "DHCP error: could not get gateway: %s",
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (r >= 0)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering log_link_struct(link, LOG_INFO,
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering "MESSAGE=%-*s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering IFNAMSIZ,
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering link->ifname,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ADDRESS_FMT_VAL(address),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering prefixlen,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ADDRESS_FMT_VAL(gateway),
1d050e1e0a7082e23ee9b31fa0b819cb332b3444Lennart Poettering "ADDRESS=%u.%u.%u.%u",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ADDRESS_FMT_VAL(address),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "PREFIXLEN=%u",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering prefixlen,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "GATEWAY=%u.%u.%u.%u",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ADDRESS_FMT_VAL(gateway),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering else
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_struct(link, LOG_INFO,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "MESSAGE=%-*s: DHCPv4 address %u.%u.%u.%u/%u",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering IFNAMSIZ,
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering link->ifname,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ADDRESS_FMT_VAL(address),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering prefixlen,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "ADDRESS=%u.%u.%u.%u",
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering ADDRESS_FMT_VAL(address),
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering "PREFIXLEN=%u",
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering prefixlen,
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering NULL);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering link->dhcp_lease = lease;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering if (link->network->dhcp_mtu) {
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering uint16_t mtu;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering r = sd_dhcp_lease_get_mtu(lease, &mtu);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering if (r >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = link_set_mtu(link, mtu);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_error(link, "Failed to set MTU "
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "to %" PRIu16, mtu);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (link->network->dhcp_hostname) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *hostname;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_dhcp_lease_get_hostname(lease, &hostname);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = link_set_hostname(link, hostname);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_link_error(link,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "Failed to set transient hostname to '%s'",
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering hostname);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering }
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen }
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
2301cb9fdb774d0a1b3d8f5e95c5d358721ccacbLennart Poettering if (!link->network->dhcp_critical) {
6c03d27d9f7e831194dbd8bd6bcdeef9273edb6eThomas Hindoe Paaboel Andersen r = sd_dhcp_lease_get_lifetime(link->dhcp_lease,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering &lifetime);
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_warning(link,
373d9f173f910d547159917401c4b1f84af85736Tom Gundersen "DHCP error: no lifetime: %s",
af5effc4220dab6c4c87a130bae7be441f6967caTom Gundersen strerror(-r));
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering return r;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering }
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta }
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = dhcp4_update_address(link, &address, &netmask, lifetime);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_warning(link, "could not update IP address: %s",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering strerror(-r));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_enter_failed(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return 0;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering}
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringstatic void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering Link *link = userdata;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering int r = 0;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(link->network);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(link->manager);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering switch (event) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering case DHCP_EVENT_EXPIRED:
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt case DHCP_EVENT_STOP:
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt case DHCP_EVENT_IP_CHANGE:
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (link->network->dhcp_critical) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_link_error(link,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (link->dhcp_lease) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = dhcp_lease_lost(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_enter_failed(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (event == DHCP_EVENT_IP_CHANGE) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = dhcp_lease_acquired(client, link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_enter_failed(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering break;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering case DHCP_EVENT_RENEW:
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = dhcp_lease_renew(client, link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_enter_failed(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering break;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering case DHCP_EVENT_IP_ACQUIRE:
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen r = dhcp_lease_acquired(client, link);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering if (r < 0) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering link_enter_failed(link);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering return;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering break;
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen default:
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen if (event < 0)
2301cb9fdb774d0a1b3d8f5e95c5d358721ccacbLennart Poettering log_link_warning(link,
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen "DHCP error: client failed: %s",
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen strerror(-event));
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen else
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen log_link_warning(link,
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen "DHCP unknown event: %d",
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering event);
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering break;
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering }
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering return;
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen}
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringint dhcp4_configure(Link *link) {
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen int r;
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen assert(link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(link->network);
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen assert(IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V4));
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen r = sd_dhcp_client_new(&link->dhcp_client);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen return r;
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen return r;
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen
914d6c09f1a449c60c8495c179a8bbe012315ba2Tom Gundersen r = sd_dhcp_client_set_mac(link->dhcp_client,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering (const uint8_t *) &link->mac,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sizeof (link->mac), ARPHRD_ETHER);
b1acce80cd60fe95f16df2f1ad23ff2ad82d08e5Lennart Poettering if (r < 0)
b1acce80cd60fe95f16df2f1ad23ff2ad82d08e5Lennart Poettering return r;
373d9f173f910d547159917401c4b1f84af85736Tom Gundersen
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta if (r < 0)
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta return r;
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta return r;
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta r = sd_dhcp_client_set_request_broadcast(link->dhcp_client,
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta link->network->dhcp_broadcast);
af5effc4220dab6c4c87a130bae7be441f6967caTom Gundersen if (r < 0)
373d9f173f910d547159917401c4b1f84af85736Tom Gundersen return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering if (link->mtu) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta if (link->network->dhcp_mtu) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_dhcp_client_set_request_option(link->dhcp_client,
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta DHCP_OPTION_INTERFACE_MTU);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
db73295accbec0c6513817f0a64a92018592bb26Lennart Poettering
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering if (link->network->dhcp_routes) {
db73295accbec0c6513817f0a64a92018592bb26Lennart Poettering r = sd_dhcp_client_set_request_option(link->dhcp_client,
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering DHCP_OPTION_STATIC_ROUTE);
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering if (r < 0)
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering return r;
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering r = sd_dhcp_client_set_request_option(link->dhcp_client,
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering if (r < 0)
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta return r;
db73295accbec0c6513817f0a64a92018592bb26Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (link->network->dhcp_sendhost) {
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta _cleanup_free_ char *hostname = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta hostname = gethostname_malloc();
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta if (!hostname)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return -ENOMEM;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta if (!is_localhost(hostname)) {
2301cb9fdb774d0a1b3d8f5e95c5d358721ccacbLennart Poettering r = sd_dhcp_client_set_hostname(link->dhcp_client,
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta hostname);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta return r;
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta }
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta }
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta if (link->network->dhcp_vendor_class_identifier) {
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta link->network->dhcp_vendor_class_identifier);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
266b538958932e6fc27dfce4917336e70e17e29eTom Gundersen return 0;
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering