networkd-dhcp4.c revision b26fa1a2fbcfee7d03b0c8fd15ec3aa64ae70b9f
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen/***
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen This file is part of systemd.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen Copyright 2013-2014 Tom Gundersen <teg@jklm.no>
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen systemd is free software; you can redistribute it and/or modify it
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen under the terms of the GNU Lesser General Public License as published by
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen (at your option) any later version.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen systemd is distributed in the hope that it will be useful, but
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen Lesser General Public License for more details.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen You should have received a copy of the GNU Lesser General Public License
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen***/
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen#include <netinet/ether.h>
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen#include <linux/if.h>
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen#include "alloc-util.h"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen#include "dhcp-lease-internal.h"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen#include "hostname-util.h"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen#include "network-internal.h"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen#include "networkd-link.h"
1346b1f0388f4100bb3c2a2bb23bc881769c020cTom Gundersen
f5be560181d092c5f52a2b819aedcd48220f36abTom Gundersenstatic int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
dd43110f781a9245ec00531456fee68ed763a179Tom Gundersen void *userdata) {
5c1d3fc93d91384bbac29adf01074fa4375317eaUmut Tezduyar Lindskog _cleanup_link_unref_ Link *link = userdata;
4138fb2c7936758da709eaed3f6b4f3df1d04effPatrik Flykt int r;
4138fb2c7936758da709eaed3f6b4f3df1d04effPatrik Flykt
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen assert(link);
ce43e484465050c619ea9a1991d49b3d6215028bSusant Sahani assert(link->dhcp4_messages > 0);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen link->dhcp4_messages --;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = sd_netlink_message_get_errno(m);
06f021a8048583d66202e3ac5cd0a12386d33ac2Tom Gundersen if (r < 0 && r != -EEXIST) {
134e56dcc53970a20a858283650bb92cd5da1d17Lennart Poettering log_link_error_errno(link, r, "Could not set DHCPv4 route: %m");
3b653205cf7bd3851befd0a9f6a3ded6e267c173Lennart Poettering link_enter_failed(link);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen }
aba496a58acf9d9c61314de71353550e579f85eeUmut Tezduyar Lindskog
4faefc7ff884eae65a80e82313fd9f4bb859d6dbLennart Poettering if (link->dhcp4_messages == 0) {
4faefc7ff884eae65a80e82313fd9f4bb859d6dbLennart Poettering link->dhcp4_configured = true;
aba496a58acf9d9c61314de71353550e579f85eeUmut Tezduyar Lindskog link_check_ready(link);
1a436809498faf6486815baa0338fb6b8e5def07Tom Gundersen }
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen return 1;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen}
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic int link_set_dhcp_routes(Link *link) {
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering struct in_addr gateway;
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta _cleanup_free_ sd_dhcp_route **static_routes = NULL;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen int r, n, i;
cb9fc36a1211967e8c58b0502a26c42552ac8060Lennart Poettering
769d324c99aab129148bd25f5f663ef441287d86Lennart Poettering assert(link);
769d324c99aab129148bd25f5f663ef441287d86Lennart Poettering assert(link->dhcp_lease);
769d324c99aab129148bd25f5f663ef441287d86Lennart Poettering
769d324c99aab129148bd25f5f663ef441287d86Lennart Poettering r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
769d324c99aab129148bd25f5f663ef441287d86Lennart Poettering if (r < 0 && r != -ENODATA)
cb9fc36a1211967e8c58b0502a26c42552ac8060Lennart Poettering return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
cb9fc36a1211967e8c58b0502a26c42552ac8060Lennart Poettering
cb9fc36a1211967e8c58b0502a26c42552ac8060Lennart Poettering if (r >= 0) {
ed942a9eb22d50f667909ad6184b45015d28d054Tom Gundersen struct in_addr address;
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen _cleanup_route_free_ Route *route = NULL;
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen _cleanup_route_free_ Route *route_gw = NULL;
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen if (r < 0)
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen r = route_new(&route);
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen if (r < 0)
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen return log_link_error_errno(link, r, "Could not allocate route: %m");
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen route->protocol = RTPROT_DHCP;
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen r = route_new(&route_gw);
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen if (r < 0)
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen return log_link_error_errno(link, r, "Could not allocate route: %m");
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen /* The dhcp netmask may mask out the gateway. Add an explicit
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen * route for the gw host so that we can route no matter the
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta * netmask or existing kernel route tables. */
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta route_gw->family = AF_INET;
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta route_gw->dst.in = gateway;
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta route_gw->dst_prefixlen = 32;
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta route_gw->prefsrc.in = address;
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta route_gw->scope = RT_SCOPE_LINK;
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta route_gw->protocol = RTPROT_DHCP;
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta route_gw->priority = link->network->dhcp_route_metric;
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta r = route_configure(route_gw, link, &dhcp4_route_handler);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (r < 0)
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen return log_link_warning_errno(link, r, "Could not set host route: %m");
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen link->dhcp4_messages ++;
dbffab87f1504abc9f189dd253111693c99fbd9aTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen route->family = AF_INET;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen route->gw.in = gateway;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen route->prefsrc.in = address;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen route->priority = link->network->dhcp_route_metric;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = route_configure(route, link, &dhcp4_route_handler);
edb85f0d8d0a84f27308a3728f3fde3c52b9dce2Susant Sahani if (r < 0) {
edb85f0d8d0a84f27308a3728f3fde3c52b9dce2Susant Sahani log_link_warning_errno(link, r, "Could not set routes: %m");
2cc412b59353576cece2d5b30c6a39c70552f0a0Tom Gundersen link_enter_failed(link);
2cc412b59353576cece2d5b30c6a39c70552f0a0Tom Gundersen return r;
2cc412b59353576cece2d5b30c6a39c70552f0a0Tom Gundersen }
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen link->dhcp4_messages ++;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen }
1a436809498faf6486815baa0338fb6b8e5def07Tom Gundersen
1a436809498faf6486815baa0338fb6b8e5def07Tom Gundersen n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
6a0a2f860f1ca4a10932da3b41dbc3c0139757ccTom Gundersen if (n == -ENODATA)
cb9fc36a1211967e8c58b0502a26c42552ac8060Lennart Poettering return 0;
5be4d38e31281727b6f45ae869136bb01a1f7790Tom Gundersen if (n < 0)
bcb7a07e0a785bda1eed658e984ff6b4a11cba9aTom Gundersen return log_link_warning_errno(link, n, "DHCP error: could not get routes: %m");
4f882b2a5007e51032459e29d15a86df6b5ea9f4Tom Gundersen
1346b1f0388f4100bb3c2a2bb23bc881769c020cTom Gundersen for (i = 0; i < n; i++) {
ad0734e890b25751ef8229e47210ff11ae8fa3f3Tom Gundersen _cleanup_route_free_ Route *route = NULL;
4cc7a82c9490a3c5ae03b1d6d168ce40ba499e23Eugene Yakubovich
f5de5b00204f041aaec828d336c8afd9e860a5c3Tom Gundersen r = route_new(&route);
eb27aeca247a4cf8816fffc4c0dbcab55ead3864Tom Gundersen if (r < 0)
e1ea665edac17d75fce01b72dadfa3211b60df2cEugene Yakubovich return log_link_error_errno(link, r, "Could not allocate route: %m");
84b5b79a8f7b423c5b7cad4170eb68d57fe5e26cAngus Gibson
5c1d3fc93d91384bbac29adf01074fa4375317eaUmut Tezduyar Lindskog route->family = AF_INET;
bfa695b5cc37aeb78737c57c84e9e69ea08152c0Tom Gundersen route->protocol = RTPROT_DHCP;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
dd43110f781a9245ec00531456fee68ed763a179Tom Gundersen assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
dd43110f781a9245ec00531456fee68ed763a179Tom Gundersen assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
e1853b00ef7cb56cafd908327dd44b3ab48b402cSusant Sahani route->priority = link->network->dhcp_route_metric;
e1853b00ef7cb56cafd908327dd44b3ab48b402cSusant Sahani
769d324c99aab129148bd25f5f663ef441287d86Lennart Poettering r = route_configure(route, link, &dhcp4_route_handler);
5a8bcb674f71a20e95df55319b34c556638378ceLennart Poettering if (r < 0)
5a8bcb674f71a20e95df55319b34c556638378ceLennart Poettering return log_link_warning_errno(link, r, "Could not set host route: %m");
c106cc36b9b8e8998eb95299b02f1db9c1209122Tom Gundersen
c106cc36b9b8e8998eb95299b02f1db9c1209122Tom Gundersen link->dhcp4_messages ++;
c106cc36b9b8e8998eb95299b02f1db9c1209122Tom Gundersen }
ce43e484465050c619ea9a1991d49b3d6215028bSusant Sahani
ce43e484465050c619ea9a1991d49b3d6215028bSusant Sahani return 0;
f048a16b464295a4e0a4f4c1210f06343ad31231Tom Gundersen}
f048a16b464295a4e0a4f4c1210f06343ad31231Tom Gundersen
b98b483bac585af754e8a22ea890db8486905d8aAlin Rautastatic int dhcp_lease_lost(Link *link) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen _cleanup_address_free_ Address *address = NULL;
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen struct in_addr addr;
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen struct in_addr netmask;
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta struct in_addr gateway;
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen unsigned prefixlen = 0;
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen int r;
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen
06f021a8048583d66202e3ac5cd0a12386d33ac2Tom Gundersen assert(link);
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen assert(link->dhcp_lease);
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen log_link_warning(link, "DHCP lease lost");
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (link->network->dhcp_use_routes) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen _cleanup_free_ sd_dhcp_route **routes = NULL;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen int n, i;
16aa63a00b5b1db23a9c0b8de350ebf482d90cd0Tom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering if (n >= 0) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen for (i = 0; i < n; i++) {
5c1d3fc93d91384bbac29adf01074fa4375317eaUmut Tezduyar Lindskog _cleanup_route_free_ Route *route = NULL;
81163121e649523b4071f67ddc03c2db649036c5Tom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = route_new(&route);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (r >= 0) {
eb0ea358b688a6f83ff305c6b825c61f12b6dcb8Tom Gundersen route->family = AF_INET;
aba496a58acf9d9c61314de71353550e579f85eeUmut Tezduyar Lindskog assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
8cd11a0f0f4ca05199e1166f6a07472b296f7455Tom Gundersen assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
5d3de3fe9cc452f1bfe3c2dcafecbd7f904da4dcLennart Poettering assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
c081882f07617e56bcbce54105068137e4e0bb52Susant Sahani
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen route_remove(route, link,
fd6d906cf46ecef45ebbb5a361e1dc436f031d7aLennart Poettering &link_route_remove_handler);
5a8bcb674f71a20e95df55319b34c556638378ceLennart Poettering }
3d3d425547a3f38473fcf8737b85dfebb630479dTom Gundersen }
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen }
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen }
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = address_new(&address);
16aa63a00b5b1db23a9c0b8de350ebf482d90cd0Tom Gundersen if (r >= 0) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering if (r >= 0) {
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen _cleanup_route_free_ Route *route_gw = NULL;
9e7e440835c43d81ffdbc299d2c07daaa641ed50Tom Gundersen _cleanup_route_free_ Route *route = NULL;
5c1d3fc93d91384bbac29adf01074fa4375317eaUmut Tezduyar Lindskog
5c1d3fc93d91384bbac29adf01074fa4375317eaUmut Tezduyar Lindskog r = route_new(&route_gw);
28cc555d8504c9429776aedbbe1fee7101258578Dan Williams if (r >= 0) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen route_gw->family = AF_INET;
5d3de3fe9cc452f1bfe3c2dcafecbd7f904da4dcLennart Poettering route_gw->dst.in = gateway;
5d3de3fe9cc452f1bfe3c2dcafecbd7f904da4dcLennart Poettering route_gw->dst_prefixlen = 32;
9e7e440835c43d81ffdbc299d2c07daaa641ed50Tom Gundersen route_gw->scope = RT_SCOPE_LINK;
46b0c76e2c355c0d0cc4792abb98cde07b28bc53Emil Renner Berthing
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen route_remove(route_gw, link,
3d3d425547a3f38473fcf8737b85dfebb630479dTom Gundersen &link_route_remove_handler);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen }
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering r = route_new(&route);
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering if (r >= 0) {
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering route->family = AF_INET;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering route->gw.in = gateway;
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering route_remove(route, link,
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering &link_route_remove_handler);
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering }
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering }
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (r >= 0) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (r >= 0)
9c0a72f961e00b0447767973e7117e131bea5b5dTom Gundersen prefixlen = in_addr_netmask_to_prefixlen(&netmask);
1346b1f0388f4100bb3c2a2bb23bc881769c020cTom Gundersen
9c0a72f961e00b0447767973e7117e131bea5b5dTom Gundersen address->family = AF_INET;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen address->in_addr.in = addr;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen address->prefixlen = prefixlen;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen address_remove(address, link, &link_address_remove_handler);
6a24f1484fcc1f59f89617afbe4282667a358eabTom Gundersen }
6a24f1484fcc1f59f89617afbe4282667a358eabTom Gundersen }
bbf7c04821a71fec67eaf0e7a34d17afc5913c13Tom Gundersen
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen if (link->network->dhcp_use_mtu) {
bbf7c04821a71fec67eaf0e7a34d17afc5913c13Tom Gundersen uint16_t mtu;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
52433f6b65eccd1c54606dde999610640f3458acTom Gundersen r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
dbffab87f1504abc9f189dd253111693c99fbd9aTom Gundersen if (r >= 0 && link->original_mtu != mtu) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = link_set_mtu(link, link->original_mtu);
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering if (r < 0) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen log_link_warning(link,
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen "DHCP error: could not reset MTU");
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen link_enter_failed(link);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen return r;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek }
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek }
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen }
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen if (link->network->dhcp_use_hostname) {
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen const char *hostname = NULL;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (link->network->dhcp_hostname)
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen hostname = link->network->dhcp_hostname;
8f203c166ecb24f904a068f2d8f0c636c1511a8fTom Gundersen else
a97dcc12e486ecff531809802930a26c4da827f2Tom Gundersen (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
a97dcc12e486ecff531809802930a26c4da827f2Tom Gundersen
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen if (hostname) {
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen /* If a hostname was set due to the lease, then unset it now. */
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen r = link_set_hostname(link, NULL);
505f8da7325591defe5f751f328bd26915267602Tom Gundersen if (r < 0)
45af44d47da6933b260c734ad9ff721f63f80a4dTom Gundersen log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen }
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen }
bbf7c04821a71fec67eaf0e7a34d17afc5913c13Tom Gundersen
3bef724f7e7f7eaca69881548b06e221b77d7031Tom Gundersen link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering link_dirty(link);
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering link->dhcp4_configured = false;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen return 0;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen}
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen void *userdata) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen _cleanup_link_unref_ Link *link = userdata;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen int r;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen assert(link);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = sd_netlink_message_get_errno(m);
dbffab87f1504abc9f189dd253111693c99fbd9aTom Gundersen if (r < 0 && r != -EEXIST) {
505f8da7325591defe5f751f328bd26915267602Tom Gundersen log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
505f8da7325591defe5f751f328bd26915267602Tom Gundersen link_enter_failed(link);
505f8da7325591defe5f751f328bd26915267602Tom Gundersen } else if (r >= 0)
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen manager_rtnl_process_address(rtnl, m, link->manager);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
69a93e7db47addc4495a6ec9dc0fc74092a6ebeeTom Gundersen link_set_dhcp_routes(link);
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen return 1;
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen}
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersenstatic int dhcp4_update_address(Link *link,
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen struct in_addr *address,
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen struct in_addr *netmask,
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen uint32_t lifetime) {
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen _cleanup_address_free_ Address *addr = NULL;
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen unsigned prefixlen;
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen int r;
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen assert(address);
6192b846ca0d15602e94ddb5da4420b7c60d64a5Tom Gundersen assert(netmask);
7951dea20911969287878e6897b3eca348721adeSusant Sahani assert(lifetime);
7951dea20911969287878e6897b3eca348721adeSusant Sahani
7951dea20911969287878e6897b3eca348721adeSusant Sahani prefixlen = in_addr_netmask_to_prefixlen(netmask);
7951dea20911969287878e6897b3eca348721adeSusant Sahani
7951dea20911969287878e6897b3eca348721adeSusant Sahani r = address_new(&addr);
7951dea20911969287878e6897b3eca348721adeSusant Sahani if (r < 0)
7951dea20911969287878e6897b3eca348721adeSusant Sahani return r;
7951dea20911969287878e6897b3eca348721adeSusant Sahani
7951dea20911969287878e6897b3eca348721adeSusant Sahani addr->family = AF_INET;
7951dea20911969287878e6897b3eca348721adeSusant Sahani addr->in_addr.in.s_addr = address->s_addr;
7951dea20911969287878e6897b3eca348721adeSusant Sahani addr->cinfo.ifa_prefered = lifetime;
7951dea20911969287878e6897b3eca348721adeSusant Sahani addr->cinfo.ifa_valid = lifetime;
7951dea20911969287878e6897b3eca348721adeSusant Sahani addr->prefixlen = prefixlen;
7951dea20911969287878e6897b3eca348721adeSusant Sahani addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
7951dea20911969287878e6897b3eca348721adeSusant Sahani
7951dea20911969287878e6897b3eca348721adeSusant Sahani /* allow reusing an existing address and simply update its lifetime
7951dea20911969287878e6897b3eca348721adeSusant Sahani * in case it already exists */
7951dea20911969287878e6897b3eca348721adeSusant Sahani r = address_configure(addr, link, &dhcp4_address_handler, true);
7951dea20911969287878e6897b3eca348721adeSusant Sahani if (r < 0)
7951dea20911969287878e6897b3eca348721adeSusant Sahani return r;
7951dea20911969287878e6897b3eca348721adeSusant Sahani
7951dea20911969287878e6897b3eca348721adeSusant Sahani return 0;
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani}
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahanistatic int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani sd_dhcp_lease *lease;
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani struct in_addr address;
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani struct in_addr netmask;
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani int r;
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani assert(link);
85a8eeee36b57c1ab382b0225fa9a87525bbeee9Susant Sahani assert(client);
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen assert(link->network);
c0dda18697e0994272c0c9616d36f6777b60e2c7Tom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = sd_dhcp_client_get_lease(client, &lease);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (r < 0)
f048a16b464295a4e0a4f4c1210f06343ad31231Tom Gundersen return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
28cc555d8504c9429776aedbbe1fee7101258578Dan Williams
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen sd_dhcp_lease_unref(link->dhcp_lease);
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen link->dhcp4_configured = false;
5c1d3fc93d91384bbac29adf01074fa4375317eaUmut Tezduyar Lindskog link->dhcp_lease = sd_dhcp_lease_ref(lease);
5c1d3fc93d91384bbac29adf01074fa4375317eaUmut Tezduyar Lindskog link_dirty(link);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = sd_dhcp_lease_get_address(lease, &address);
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (r < 0)
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen return log_link_warning_errno(link, r, "DHCP error: no address: %m");
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen
71a6151083d842b2f5bf04e50239f0bf85d34d2eTom Gundersen r = sd_dhcp_lease_get_netmask(lease, &netmask);
71a6151083d842b2f5bf04e50239f0bf85d34d2eTom Gundersen if (r < 0)
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen if (!link->network->dhcp_critical) {
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen if (r < 0)
5d8e593dce074bff966fc0a46579c61b4f3bc33aSusant Sahani return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
5d8e593dce074bff966fc0a46579c61b4f3bc33aSusant Sahani }
5d8e593dce074bff966fc0a46579c61b4f3bc33aSusant Sahani
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen r = dhcp4_update_address(link, &address, &netmask, lifetime);
f048a16b464295a4e0a4f4c1210f06343ad31231Tom Gundersen if (r < 0) {
f048a16b464295a4e0a4f4c1210f06343ad31231Tom Gundersen log_link_warning_errno(link, r, "Could not update IP address: %m");
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen link_enter_failed(link);
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen return r;
aba496a58acf9d9c61314de71353550e579f85eeUmut Tezduyar Lindskog }
407fe036a24834203aca6c1eec7d74d9ad3e9ee0Tom Gundersen
5a8bcb674f71a20e95df55319b34c556638378ceLennart Poettering return 0;
5a8bcb674f71a20e95df55319b34c556638378ceLennart Poettering}
9505d3c6deda0452c22ab2ed47bca74b98d87a17Tom Gundersen
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen sd_dhcp_lease *lease;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen struct in_addr address;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen struct in_addr netmask;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen struct in_addr gateway;
71a6151083d842b2f5bf04e50239f0bf85d34d2eTom Gundersen unsigned prefixlen;
71a6151083d842b2f5bf04e50239f0bf85d34d2eTom Gundersen uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen int r;
eb0ea358b688a6f83ff305c6b825c61f12b6dcb8Tom Gundersen
eb0ea358b688a6f83ff305c6b825c61f12b6dcb8Tom Gundersen assert(client);
eb0ea358b688a6f83ff305c6b825c61f12b6dcb8Tom Gundersen assert(link);
eb0ea358b688a6f83ff305c6b825c61f12b6dcb8Tom Gundersen
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen r = sd_dhcp_client_get_lease(client, &lease);
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen if (r < 0)
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen return log_link_error_errno(link, r, "DHCP error: No lease: %m");
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta r = sd_dhcp_lease_get_address(lease, &address);
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta if (r < 0)
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta return log_link_error_errno(link, r, "DHCP error: No address: %m");
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta r = sd_dhcp_lease_get_netmask(lease, &netmask);
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta if (r < 0)
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta prefixlen = in_addr_netmask_to_prefixlen(&netmask);
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta r = sd_dhcp_lease_get_router(lease, &gateway);
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta if (r < 0 && r != -ENODATA)
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta if (r >= 0)
b98b483bac585af754e8a22ea890db8486905d8aAlin Rauta log_struct(LOG_INFO,
ed942a9eb22d50f667909ad6184b45015d28d054Tom Gundersen LOG_LINK_INTERFACE(link),
ed942a9eb22d50f667909ad6184b45015d28d054Tom Gundersen LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
ed942a9eb22d50f667909ad6184b45015d28d054Tom Gundersen ADDRESS_FMT_VAL(address),
ed942a9eb22d50f667909ad6184b45015d28d054Tom Gundersen prefixlen,
ed942a9eb22d50f667909ad6184b45015d28d054Tom Gundersen ADDRESS_FMT_VAL(gateway)),
ed942a9eb22d50f667909ad6184b45015d28d054Tom Gundersen "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen "PREFIXLEN=%u", prefixlen,
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway),
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen NULL);
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen else
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen log_struct(LOG_INFO,
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen LOG_LINK_INTERFACE(link),
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen ADDRESS_FMT_VAL(address),
bd8f65387673e29f46136a4ed172097035002c23Tom Gundersen prefixlen),
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering "PREFIXLEN=%u", prefixlen,
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering NULL);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering link->dhcp_lease = sd_dhcp_lease_ref(lease);
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering link_dirty(link);
11bf3cced13c885ca215c108cb0bdb7a148520d6Lennart Poettering
cb9fc36a1211967e8c58b0502a26c42552ac8060Lennart Poettering if (link->network->dhcp_use_mtu) {
cb9fc36a1211967e8c58b0502a26c42552ac8060Lennart Poettering uint16_t mtu;
cb9fc36a1211967e8c58b0502a26c42552ac8060Lennart Poettering
769d324c99aab129148bd25f5f663ef441287d86Lennart Poettering r = sd_dhcp_lease_get_mtu(lease, &mtu);
769d324c99aab129148bd25f5f663ef441287d86Lennart Poettering if (r >= 0) {
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen r = link_set_mtu(link, mtu);
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen if (r < 0)
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen }
e331e24649213f2e093e16e4d3d64ee823dfc375Tom Gundersen }
if (link->network->dhcp_use_hostname) {
const char *hostname = NULL;
if (link->network->dhcp_hostname)
hostname = link->network->dhcp_hostname;
else
(void) sd_dhcp_lease_get_hostname(lease, &hostname);
if (hostname) {
r = link_set_hostname(link, hostname);
if (r < 0)
log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
}
}
if (link->network->dhcp_use_timezone) {
const char *tz = NULL;
(void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
if (tz) {
r = link_set_timezone(link, tz);
if (r < 0)
log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz);
}
}
if (!link->network->dhcp_critical) {
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
if (r < 0) {
log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
return r;
}
}
r = dhcp4_update_address(link, &address, &netmask, lifetime);
if (r < 0) {
log_link_warning_errno(link, r, "Could not update IP address: %m");
link_enter_failed(link);
return r;
}
return 0;
}
static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
Link *link = userdata;
int r = 0;
assert(link);
assert(link->network);
assert(link->manager);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return;
switch (event) {
case SD_DHCP_CLIENT_EVENT_EXPIRED:
case SD_DHCP_CLIENT_EVENT_STOP:
case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
if (link->network->dhcp_critical) {
log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
return;
}
if (link->dhcp_lease) {
r = dhcp_lease_lost(link);
if (r < 0) {
link_enter_failed(link);
return;
}
}
if (event == SD_DHCP_CLIENT_EVENT_IP_CHANGE) {
r = dhcp_lease_acquired(client, link);
if (r < 0) {
link_enter_failed(link);
return;
}
}
break;
case SD_DHCP_CLIENT_EVENT_RENEW:
r = dhcp_lease_renew(client, link);
if (r < 0) {
link_enter_failed(link);
return;
}
break;
case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
r = dhcp_lease_acquired(client, link);
if (r < 0) {
link_enter_failed(link);
return;
}
break;
default:
if (event < 0)
log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
else
log_link_warning(link, "DHCP unknown event: %i", event);
break;
}
return;
}
int dhcp4_configure(Link *link) {
int r;
assert(link);
assert(link->network);
assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
if (!link->dhcp_client) {
r = sd_dhcp_client_new(&link->dhcp_client);
if (r < 0)
return r;
}
r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
if (r < 0)
return r;
r = sd_dhcp_client_set_mac(link->dhcp_client,
(const uint8_t *) &link->mac,
sizeof (link->mac), ARPHRD_ETHER);
if (r < 0)
return r;
r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
if (r < 0)
return r;
r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
if (r < 0)
return r;
r = sd_dhcp_client_set_request_broadcast(link->dhcp_client,
link->network->dhcp_broadcast);
if (r < 0)
return r;
if (link->mtu) {
r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
if (r < 0)
return r;
}
if (link->network->dhcp_use_mtu) {
r = sd_dhcp_client_set_request_option(link->dhcp_client,
SD_DHCP_OPTION_INTERFACE_MTU);
if (r < 0)
return r;
}
if (link->network->dhcp_use_routes) {
r = sd_dhcp_client_set_request_option(link->dhcp_client,
SD_DHCP_OPTION_STATIC_ROUTE);
if (r < 0)
return r;
r = sd_dhcp_client_set_request_option(link->dhcp_client,
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
if (r < 0)
return r;
}
/* Always acquire the timezone and NTP */
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
if (r < 0)
return r;
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
if (r < 0)
return r;
if (link->network->dhcp_send_hostname) {
_cleanup_free_ char *hostname = NULL;
const char *hn = NULL;
if (!link->network->dhcp_hostname) {
hostname = gethostname_malloc();
if (!hostname)
return -ENOMEM;
hn = hostname;
} else
hn = link->network->dhcp_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;
}