networkd-dhcp4.c revision 0bc70f1d9c5453ba614ec0ed041dc30b9cd52071
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering This file is part of systemd.
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering Copyright 2013-2014 Tom Gundersen <teg@jklm.no>
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering systemd is free software; you can redistribute it and/or modify it
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering (at your option) any later version.
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering systemd is distributed in the hope that it will be useful, but
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering Lesser General Public License for more details.
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
522d4a495af3a615526fccdf038d2d68f41a73c8Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _cleanup_link_unref_ Link *link = userdata;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_netlink_message_get_errno(m);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0 && r != -EEXIST) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_link_error_errno(link, r, "Could not set DHCPv4 route: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int link_set_dhcp_routes(Link *link) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek struct sd_dhcp_route *static_routes;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0 && r != -ENODATA)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _cleanup_route_free_ Route *route = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _cleanup_route_free_ Route *route_gw = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_link_error_errno(link, r, "Could not allocate route: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_link_error_errno(link, r, "Could not allocate route: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* The dhcp netmask may mask out the gateway. Add an explicit
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * route for the gw host so that we can route no matter the
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * netmask or existing kernel route tables. */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route_gw->scope = RT_SCOPE_LINK;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route_gw->protocol = RTPROT_DHCP;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route_gw->priority = link->network->dhcp_route_metric;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = route_configure(route_gw, link, &dhcp4_route_handler);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_link_warning_errno(link, r, "Could not set host route: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route->priority = link->network->dhcp_route_metric;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = route_configure(route, link, &dhcp4_route_handler);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_link_warning_errno(link, r, "Could not set routes: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_link_warning_errno(link, n, "DHCP error: could not get routes: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek for (i = 0; i < n; i++) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _cleanup_route_free_ Route *route = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_link_error_errno(link, r, "Could not allocate route: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route->gw.in = static_routes[i].gw_addr;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route->dst.in = static_routes[i].dst_addr;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route->dst_prefixlen = static_routes[i].dst_prefixlen;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route->priority = link->network->dhcp_route_metric;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = route_configure(route, link, &dhcp4_route_handler);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_link_warning_errno(link, r, "Could not set host route: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int dhcp_lease_lost(Link *link) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _cleanup_address_free_ Address *address = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_link_warning(link, "DHCP lease lost");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (link->network->dhcp_routes) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek for (i = 0; i < n; i++) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _cleanup_route_free_ Route *route = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route->gw.in = routes[i].gw_addr;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route->dst.in = routes[i].dst_addr;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route->dst_prefixlen = routes[i].dst_prefixlen;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _cleanup_route_free_ Route *route_gw = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _cleanup_route_free_ Route *route = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek route_gw->scope = RT_SCOPE_LINK;
if (hostname) {
void *userdata) {
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
unsigned prefixlen;
unsigned prefixlen;
if (r < 0 && r != -ENODATA)
NULL);
NULL);
if (hostname) {
if (tz) {
switch (event) {
log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
if (event < 0)
if (!hostname)
return -ENOMEM;
case DHCP_CLIENT_ID_DUID:
case DHCP_CLIENT_ID_MAC: