networkd-link.c revision 5d4795f3722911ccd7953c0cf112c1f7624ea834
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/***
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen This file is part of systemd.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Copyright 2013 Tom Gundersen <teg@jklm.no>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is free software; you can redistribute it and/or modify it
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen under the terms of the GNU Lesser General Public License as published by
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen (at your option) any later version.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is distributed in the hope that it will be useful, but
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Lesser General Public License for more details.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen You should have received a copy of the GNU Lesser General Public License
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen***/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <netinet/ether.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <linux/if.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include "networkd.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "libudev-private.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "util.h"
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include "bus-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringint link_new(Manager *manager, struct udev_device *device, Link **ret) {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering _cleanup_link_free_ Link *link = NULL;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering const char *mac;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering struct ether_addr *mac_addr;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen const char *ifname;
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering int r;
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(device);
99634696183dfabae20104e58157c69029a11594Tom Gundersen assert(ret);
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen link = new0(Link, 1);
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (!link)
99634696183dfabae20104e58157c69029a11594Tom Gundersen return -ENOMEM;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen link->manager = manager;
99634696183dfabae20104e58157c69029a11594Tom Gundersen link->state = _LINK_STATE_INVALID;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen link->ifindex = udev_device_get_ifindex(device);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (link->ifindex <= 0)
99634696183dfabae20104e58157c69029a11594Tom Gundersen return -EINVAL;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen mac = udev_device_get_sysattr_value(device, "address");
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (mac) {
99634696183dfabae20104e58157c69029a11594Tom Gundersen mac_addr = ether_aton(mac);
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (mac_addr)
99634696183dfabae20104e58157c69029a11594Tom Gundersen memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
99634696183dfabae20104e58157c69029a11594Tom Gundersen }
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen ifname = udev_device_get_sysname(device);
99634696183dfabae20104e58157c69029a11594Tom Gundersen link->ifname = strdup(ifname);
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen r = hashmap_put(manager->links, &link->ifindex, link);
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (r < 0)
99634696183dfabae20104e58157c69029a11594Tom Gundersen return r;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen *ret = link;
99634696183dfabae20104e58157c69029a11594Tom Gundersen link = NULL;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen return 0;
99634696183dfabae20104e58157c69029a11594Tom Gundersen}
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersenvoid link_free(Link *link) {
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (!link)
99634696183dfabae20104e58157c69029a11594Tom Gundersen return;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen assert(link->manager);
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (link->dhcp)
99634696183dfabae20104e58157c69029a11594Tom Gundersen sd_dhcp_client_free(link->dhcp);
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen route_free(link->dhcp_route);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen link->dhcp_route = NULL;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen address_free(link->dhcp_address);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen link->dhcp_address = NULL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen hashmap_remove(link->manager->links, &link->ifindex);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen free(link->ifname);
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen free(link);
99634696183dfabae20104e58157c69029a11594Tom Gundersen}
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersenint link_add(Manager *m, struct udev_device *device, Link **ret) {
99634696183dfabae20104e58157c69029a11594Tom Gundersen Link *link;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen Network *network;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen int r;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen uint64_t ifindex;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen const char *devtype;
04c0136989b7eb896bfb0fb176e11233d69e1453Lennart Poettering
756775814cf69471f74ce853745bba69f2ba94efThomas Hindoe Paaboel Andersen assert(m);
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen assert(device);
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen ifindex = udev_device_get_ifindex(device);
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen link = hashmap_get(m->links, &ifindex);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (link) {
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering *ret = link;
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering return -EEXIST;
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering }
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering r = link_new(m, device, &link);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering if (r < 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen *ret = link;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen devtype = udev_device_get_devtype(device);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (streq_ptr(devtype, "bridge")) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = bridge_set_link(m, link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r < 0 && r != -ENOENT)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
1e2527a6fede996a429bd44b30a15e76ee293437Tom Gundersen r = network_get(m, device, &network);
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen if (r < 0)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return r == -ENOENT ? 0 : r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = network_apply(m, network, link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r < 0)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 0;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic int link_enter_configured(Link *link) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(link->state == LINK_STATE_SETTING_ROUTES);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen log_info_link(link, "link configured");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen link->state = LINK_STATE_CONFIGURED;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt return 0;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt}
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidtstatic void link_enter_failed(Link *link) {
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt assert(link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen log_warning_link(link, "failed");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen link->state = LINK_STATE_FAILED;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen Link *link = userdata;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen int r;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(link->route_messages > 0);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering link->state == LINK_STATE_SETTING_ROUTES ||
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen link->state == LINK_STATE_FAILED);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering link->route_messages --;
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering if (link->state == LINK_STATE_FAILED)
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering return 1;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering r = sd_rtnl_message_get_errno(m);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r < 0 && r != -EEXIST)
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering log_warning_link(link, "could not set route: %s", strerror(-r));
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering /* we might have received an old reply after moving back to SETTING_ADDRESSES,
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering * ignore it */
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering log_debug_link(link, "routes set");
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering link_enter_configured(link);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering }
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering return 1;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering}
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poetteringstatic int link_enter_set_routes(Link *link) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering Route *route;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen int r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(link);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(link->network);
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen assert(link->state == LINK_STATE_SETTING_ADDRESSES);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen link->state = LINK_STATE_SETTING_ROUTES;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen if (!link->network->static_routes && !link->dhcp_route)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return link_enter_configured(link);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen log_debug_link(link, "setting routes");
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen LIST_FOREACH(static_routes, route, link->network->static_routes) {
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering r = route_configure(route, link, &route_handler);
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen if (r < 0) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen log_warning_link(link,
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen "could not set routes: %s", strerror(-r));
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen link_enter_failed(link);
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering return r;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt }
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering link->route_messages ++;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (link->dhcp_route) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen r = route_configure(link->dhcp_route, link, &route_handler);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (r < 0) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen log_warning_link(link,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "could not set routes: %s", strerror(-r));
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen link_enter_failed(link);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen link->route_messages ++;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen}
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Link *link = userdata;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen int r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(m);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(link);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(link->ifname);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(link->addr_messages > 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen link->addr_messages --;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (link->state == LINK_STATE_FAILED)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 1;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen r = sd_rtnl_message_get_errno(m);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (r < 0 && r != -EEXIST)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen log_struct_link(LOG_ERR, link,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "MESSAGE=%s: could not set address: %s",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen link->ifname, strerror(-r),
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "ERRNO=%d", -r,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen NULL);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (link->addr_messages == 0) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen log_debug_link(link, "addresses set");
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen link_enter_set_routes(link);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen }
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return 1;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen}
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersenstatic int link_enter_set_addresses(Link *link) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen Address *address;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen int r;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert(link);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert(link->network);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert(link->state != _LINK_STATE_INVALID);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen link->state = LINK_STATE_SETTING_ADDRESSES;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!link->network->static_addresses && !link->dhcp_address)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return link_enter_set_routes(link);
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_debug_link(link, "setting addresses");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen LIST_FOREACH(static_addresses, address, link->network->static_addresses) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = address_configure(address, link, &address_handler);
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_warning_link(link,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "could not set addresses: %s", strerror(-r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen link_enter_failed(link);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen link->addr_messages ++;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (link->dhcp_address) {
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering r = address_configure(link->dhcp_address, link, &address_handler);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_warning_link(link,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "could not set addresses: %s", strerror(-r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen link_enter_failed(link);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen link->addr_messages ++;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen Link *link = userdata;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(m);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(link);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(link->ifname);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (link->state == LINK_STATE_FAILED)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_rtnl_message_get_errno(m);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0 && r != -EEXIST)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_warning_link(link, "could not drop address: %s", strerror(-r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_message_get_errno(m);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_warning("Could not set hostname: %s", strerror(-r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_hostname(sd_bus *bus, const char *hostname) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r = 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering assert(hostname);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_debug("Setting transient hostname: '%s'", hostname);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_info("Not connected to system bus, ignoring transient hostname.");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_message_new_method_call(
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen bus,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.hostname1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "/org/freedesktop/hostname1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.hostname1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "SetHostname",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &m);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_message_append(m, "sb", hostname, false);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Could not set transient hostname: %s", strerror(-r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen Link *link = userdata;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(m);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(link);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(link->ifname);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (link->state == LINK_STATE_FAILED)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_rtnl_message_get_errno(m);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0 && r != -EEXIST)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_warning_link(link, "Could not set MTU: %s", strerror(-r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int link_set_mtu(Link *link, uint32_t mtu) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(link);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(link->manager);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(link->manager->rtnl);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_debug_link(link, "setting MTU: %" PRIu32, mtu);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error_link(link, "Could not allocate RTM_SETLINK message");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error_link(link, "Could not append MTU: %s", strerror(-r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen log_error_link(link,
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen "Could not send rtnetlink message: %s", strerror(-r));
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return r;
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return 0;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen}
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen Link *link = userdata;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen struct in_addr address;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen struct in_addr netmask;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen struct in_addr gateway;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen int prefixlen;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen int r;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
1231c4d238844e77018caf5b5852f01d96373c47Tom Gundersen assert(link);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(link->network);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(link->manager);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (link->state == LINK_STATE_FAILED)
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (event < 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_warning_link(link, "DHCP error: %s", strerror(-event));
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen link_enter_failed(link);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (event == DHCP_EVENT_NO_LEASE)
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams log_debug_link(link, "IP address in use.");
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen event == DHCP_EVENT_STOP) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (link->dhcp_address) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen address_drop(link->dhcp_address, link, address_drop_handler);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen address_free(link->dhcp_address);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen link->dhcp_address = NULL;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (link->dhcp_route) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen route_free(link->dhcp_route);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen link->dhcp_route = NULL;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (link->network->dhcp_mtu) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen uint16_t mtu;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = sd_dhcp_client_get_mtu(client, &mtu);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (r >= 0 && link->original_mtu != mtu) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = link_set_mtu(link, link->original_mtu);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (r < 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_warning_link(link, "DHCP error: could not reset MTU");
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen link_enter_failed(link);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (link->network->dhcp_hostname) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen r = set_hostname(link->manager->bus, "");
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (r < 0)
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_error("Failed to reset transient hostname");
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen }
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen r = sd_dhcp_client_get_address(client, &address);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen if (r < 0) {
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen log_warning_link(link, "DHCP error: no address");
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen link_enter_failed(link);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen return;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen }
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen r = sd_dhcp_client_get_netmask(client, &netmask);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (r < 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_warning_link(link, "DHCP error: no netmask");
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen link_enter_failed(link);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen prefixlen = sd_dhcp_client_prefixlen(&netmask);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (prefixlen < 0) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen log_warning_link(link, "DHCP error: no prefixlen");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen link_enter_failed(link);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = sd_dhcp_client_get_router(client, &gateway);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_warning_link(link, "DHCP error: no router");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen link_enter_failed(link);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen _cleanup_address_free_ Address *addr = NULL;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen _cleanup_route_free_ Route *rt = NULL;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen struct in_addr *nameservers;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen size_t nameservers_size;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_struct_link(LOG_INFO, link,
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen link->ifname,
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen ADDRESS_FMT_VAL(address),
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen prefixlen,
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen ADDRESS_FMT_VAL(gateway),
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen "ADDRESS=%u.%u.%u.%u",
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen ADDRESS_FMT_VAL(address),
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen "PREFIXLEN=%u",
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen prefixlen,
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen "GATEWAY=%u.%u.%u.%u",
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering ADDRESS_FMT_VAL(gateway),
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering NULL);
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering r = address_new_dynamic(&addr);
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering if (r < 0) {
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering log_error_link(link, "Could not allocate address");
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering link_enter_failed(link);
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering return;
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering }
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering addr->family = AF_INET;
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering addr->in_addr.in = address;
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering addr->prefixlen = prefixlen;
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering addr->netmask = netmask;
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering r = route_new_dynamic(&rt);
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering if (r < 0) {
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering log_error_link(link, "Could not allocate route");
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering link_enter_failed(link);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering return;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering }
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering rt->family = AF_INET;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering rt->in_addr.in = gateway;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering link->dhcp_address = addr;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering link->dhcp_route = rt;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen addr = NULL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen rt = NULL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (link->network->dhcp_dns) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r >= 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = manager_update_resolv_conf(link->manager);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen if (r < 0)
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen log_error("Failed to update resolv.conf");
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen }
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen }
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen if (link->network->dhcp_mtu) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen uint16_t mtu;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen r = sd_dhcp_client_get_mtu(client, &mtu);
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering if (r >= 0) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen r = link_set_mtu(link, mtu);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen if (r < 0)
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen log_error_link(link, "Failed to set MTU "
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen "to %" PRIu16, mtu);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen }
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen }
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (link->network->dhcp_hostname) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen const char *hostname;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = sd_dhcp_client_get_hostname(client, &hostname);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (r >= 0) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = set_hostname(link->manager->bus, hostname);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (r < 0)
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen log_error("Failed to set transient hostname "
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen "to '%s'", hostname);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen }
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams }
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen link_enter_set_addresses(link);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen }
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen return;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen}
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersenstatic int link_acquire_conf(Link *link) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen int r;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen assert(link);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen assert(link->network);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen assert(link->network->dhcp);
c15fb62a731f1a457af94e60ac6a4d23f219a8f6Thomas Hindoe Paaboel Andersen assert(link->manager);
c15fb62a731f1a457af94e60ac6a4d23f219a8f6Thomas Hindoe Paaboel Andersen assert(link->manager->event);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (!link->dhcp) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = sd_dhcp_client_new(&link->dhcp);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (r < 0)
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering return r;
89ca10c6a61309d84d54c5dc5a295387ce39e610Lennart Poettering
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = sd_dhcp_client_attach_event(link->dhcp, NULL, 0);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r < 0)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen if (r < 0)
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen return r;
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return r;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (link->network->dhcp_mtu) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = sd_dhcp_client_set_request_option(link->dhcp, 26);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r < 0)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_debug_link(link, "acquiring DHCPv4 lease");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = sd_dhcp_client_start(link->dhcp);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r < 0)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return 0;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen}
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersenstatic int link_update_flags(Link *link, unsigned flags) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen int r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen assert(link);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen assert(link->network);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (link->state == LINK_STATE_FAILED)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return 0;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (link->flags == flags) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_debug_link(link, "link status unchanged: %#.8x", flags);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return 0;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if ((link->flags & IFF_UP) != (flags & IFF_UP))
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_info_link(link,
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen "link is %s", flags & IFF_UP ? "up": "down");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (flags & IFF_LOWER_UP) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_info_link(link, "carrier on");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (link->network->dhcp) {
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering r = link_acquire_conf(link);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r < 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen link_enter_failed(link);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
e2acdb6b0f68d9b4152708a9f21bf9e11f8b9e7eTorstein Husebø }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen } else {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_info_link(link, "carrier off");
9a0f246fcdb1238e6b3397169a10095f4df89210Lennart Poettering
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (link->network->dhcp) {
9a0f246fcdb1238e6b3397169a10095f4df89210Lennart Poettering r = sd_dhcp_client_stop(link->dhcp);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r < 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen link_enter_failed(link);
9a0f246fcdb1238e6b3397169a10095f4df89210Lennart Poettering return r;
9a0f246fcdb1238e6b3397169a10095f4df89210Lennart Poettering }
9a0f246fcdb1238e6b3397169a10095f4df89210Lennart Poettering }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_debug_link(link,
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen "link status updated: %#.8x -> %#.8x", link->flags, flags);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen link->flags = flags;
9a0f246fcdb1238e6b3397169a10095f4df89210Lennart Poettering
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering return 0;
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering}
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poetteringstatic int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen Link *link = userdata;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen int r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen assert(link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (link->state == LINK_STATE_FAILED)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 1;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = sd_rtnl_message_get_errno(m);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r < 0) {
99634696183dfabae20104e58157c69029a11594Tom Gundersen log_warning_link(link,
99634696183dfabae20104e58157c69029a11594Tom Gundersen "could not bring up interface: %s", strerror(-r));
99634696183dfabae20104e58157c69029a11594Tom Gundersen link_enter_failed(link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
99634696183dfabae20104e58157c69029a11594Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen link_update_flags(link, link->flags | IFF_UP);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersen return 1;
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersen}
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
be077570f779664ed87b50f60608df9fbe258821Tom Gundersenstatic int link_up(Link *link) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen assert(link);
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen assert(link->manager);
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen assert(link->manager->rtnl);
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen log_debug_link(link, "bringing link up");
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen if (r < 0) {
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen log_error_link(link, "Could not allocate RTM_SETLINK message");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r < 0) {
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen log_error_link(link, "Could not set link flags: %s", strerror(-r));
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen return r;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen }
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r < 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_error_link(link,
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen "Could not send rtnetlink message: %s", strerror(-r));
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return r;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return 0;
9a0f246fcdb1238e6b3397169a10095f4df89210Lennart Poettering}
9a0f246fcdb1238e6b3397169a10095f4df89210Lennart Poettering
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic int link_bridge_joined(Link *link) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int r;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(link);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(link->state == LINK_STATE_JOINING_BRIDGE);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(link->network);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = link_up(link);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen link_enter_failed(link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (!link->network->dhcp)
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen return link_enter_set_addresses(link);
0cb3c286883b694fc52a18a3b559ff98931641f3Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen return 0;
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersen}
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersen
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersenstatic int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersen Link *link = userdata;
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersen int r;
0cb3c286883b694fc52a18a3b559ff98931641f3Tom Gundersen
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen assert(link);
933f9caeeb2b3c1b951d330e04beb04226e5a890Daniel Mack assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
0cb3c286883b694fc52a18a3b559ff98931641f3Tom Gundersen assert(link->network);
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (link->state == LINK_STATE_FAILED)
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersen return 1;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = sd_rtnl_message_get_errno(m);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r < 0) {
83cedf7ae28925e37931e7e92d22be9c936a1defTom Gundersen log_struct_link(LOG_ERR, link,
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen "MESSAGE=%s: could not join bridge '%s': %s",
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen link->ifname, link->network->bridge->name, strerror(-r),
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen BRIDGE(link->network->bridge),
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen NULL);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen link_enter_failed(link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 1;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_struct_link(LOG_DEBUG, link,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "MESSAGE=%s: joined bridge '%s'",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen link->network->bridge->name,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen BRIDGE(link->network->bridge),
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen NULL);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen link_bridge_joined(link);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return 1;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen}
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersenstatic int link_enter_join_bridge(Link *link) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen int r;
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen assert(link);
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen assert(link->network);
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen assert(link->state == _LINK_STATE_INVALID);
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen link->state = LINK_STATE_JOINING_BRIDGE;
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen if (!link->network->bridge)
9a0f246fcdb1238e6b3397169a10095f4df89210Lennart Poettering return link_bridge_joined(link);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen log_struct_link(LOG_DEBUG, link,
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen "MESSAGE=%s: joining bridge '%s'",
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen link->network->bridge->name,
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen BRIDGE(link->network->bridge),
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen NULL);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_debug_link(link, "joining bridge");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = bridge_join(link->network->bridge, link, &bridge_handler);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_struct_link(LOG_WARNING, link,
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen "MESSAGE=%s: could not join bridge '%s': %s",
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen link->network->bridge->name, strerror(-r),
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen BRIDGE(link->network->bridge),
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen NULL);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen link_enter_failed(link);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return r;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return 0;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen}
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen Link *link = userdata;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen int r;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen assert(link);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (link->state == LINK_STATE_FAILED)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return 1;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = sd_rtnl_message_get_errno(m);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_warning_link(link, "could not get state: %s", strerror(-r));
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen link_enter_failed(link);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_debug_link(link, "got link state");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen link_update(link, m);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return 1;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen}
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic int link_get(Link *link) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen int r;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen assert(link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(link->manager);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(link->manager->rtnl);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen log_debug_link(link, "requesting link status");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r < 0) {
a7f7d1bde43fc825c49afea3f946f5b4b3d563e0Harald Hoyer log_error_link(link, "Could not allocate RTM_GETLINK message");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r < 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen log_error_link(link,
02557f973aed0fed7154fefe53d67e2935f918dcThomas Hindoe Paaboel Andersen "Could not send rtnetlink message: %s", strerror(-r));
02557f973aed0fed7154fefe53d67e2935f918dcThomas Hindoe Paaboel Andersen return r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
02557f973aed0fed7154fefe53d67e2935f918dcThomas Hindoe Paaboel Andersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 0;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen}
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersenint link_configure(Link *link) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(link);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen assert(link->network);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen assert(link->state == _LINK_STATE_INVALID);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani r = link_get(link);
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani if (r < 0) {
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani link_enter_failed(link);
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering return r;
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani }
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return link_enter_join_bridge(link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenint link_update(Link *link, sd_rtnl_message *m) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen unsigned flags;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen void *data;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen uint16_t type;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(link);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(m);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (link->state == LINK_STATE_FAILED)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return 0;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = sd_rtnl_message_link_get_flags(m, &flags);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r < 0) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen log_warning_link(link, "Could not get link flags");
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen while (sd_rtnl_message_read(m, &type, &data) > 0) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen if (type == IFLA_MTU && link->network->dhcp &&
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen link->network->dhcp_mtu && !link->original_mtu) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen link->original_mtu = *(uint16_t *) data;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen log_debug_link(link, "saved original MTU: %" PRIu16,
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen link->original_mtu);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen }
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen }
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen return link_update_flags(link, flags);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen}
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen