networkd-link.c revision eb27aeca247a4cf8816fffc4c0dbcab55ead3864
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2013 Tom Gundersen <teg@jklm.no>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringint link_new(Manager *manager, struct udev_device *device, Link **ret) {
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering link->ifindex = udev_device_get_ifindex(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mac = udev_device_get_sysattr_value(device, "address");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ifname = udev_device_get_sysname(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = hashmap_put(manager->links, &link->ifindex, link);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen hashmap_remove(link->manager->links, &link->ifindex);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_add(Manager *m, struct udev_device *device, Link **ret) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen r = link_new(m, device, &link);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering kind = netdev_kind_from_string(udev_device_get_devtype(device));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0 && r != -ENOENT)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return r == -ENOENT ? 0 : r;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringstatic int link_enter_configured(Link *link) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(link->state == LINK_STATE_SETTING_ROUTES);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic void link_enter_failed(Link *link) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poetteringstatic int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering link->state == LINK_STATE_SETTING_ROUTES ||
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (r < 0 && r != -EEXIST)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "MESSAGE=%s: could not set route: %s",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "ERRNO=%d", -r,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* we might have received an old reply after moving back to SETTING_ADDRESSES,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * ignore it */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int link_enter_set_routes(Link *link) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(link->state == LINK_STATE_SETTING_ADDRESSES);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (!link->network->static_routes && !link->dhcp_route)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LIST_FOREACH(static_routes, route, link->network->static_routes) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = route_configure(route, link, &route_handler);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering "could not set routes: %s", strerror(-r));
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = route_configure(link->dhcp_route, link, &route_handler);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering "could not set routes: %s", strerror(-r));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (r < 0 && r != -EEXIST)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "MESSAGE=%s: could not set address: %s",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "ERRNO=%d", -r,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int link_enter_set_addresses(Link *link) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(link->state != _LINK_STATE_INVALID);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering link->state = LINK_STATE_SETTING_ADDRESSES;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (!link->network->static_addresses && !link->dhcp_address)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering log_debug_link(link, "setting addresses");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering LIST_FOREACH(static_addresses, address, link->network->static_addresses) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = address_configure(address, link, &address_handler);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "could not set addresses: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = address_configure(link->dhcp_address, link, &address_handler);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "could not set addresses: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0 && r != -ENOENT)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "MESSAGE=%s: could not drop address: %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "ERRNO=%d", -r,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Could not set hostname: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int set_hostname(sd_bus *bus, const char *hostname) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_debug("Setting transient hostname: '%s'", hostname);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_info("Not connected to system bus, ignoring transient hostname.");
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "SetHostname",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = sd_bus_message_append(m, "sb", hostname, false);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_error("Could not set transient hostname: %s", strerror(-r));
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringstatic int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek "MESSAGE=%s: could not set MTU: %s",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "ERRNO=%d", -r,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic int link_set_mtu(Link *link, uint32_t mtu) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_debug_link(link, "setting MTU: %" PRIu32, mtu);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_error_link(link, "Could not allocate RTM_SETLINK message");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
a6c616024db23fef34152c1432892824a07799ccLennart Poettering log_error_link(link, "Could not append MTU: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "Could not send rtnetlink message: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers log_warning_link(link, "DHCP error: %s", strerror(-event));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_warning_link(link, "DHCPv4 connection considered system critical, "
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt "ignoring request to reconfigure it down.");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen address_drop(link->dhcp_address, link, address_drop_handler);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers log_warning_link(link, "DHCP error: could not reset MTU");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Failed to reset transient hostname");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_dhcp_client_get_address(client, &address);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_warning_link(link, "DHCP error: no address");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_dhcp_client_get_netmask(client, &netmask);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering log_warning_link(link, "DHCP error: no netmask");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning_link(link, "DHCP error: no prefixlen");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_dhcp_client_get_router(client, &gateway);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning_link(link, "DHCP error: no router");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_address_free_ Address *addr = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "ADDRESS=%u.%u.%u.%u",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "PREFIXLEN=%u",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "GATEWAY=%u.%u.%u.%u",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error_link(link, "Could not allocate address");
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_error_link(link, "Could not allocate route");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering r = manager_update_resolv_conf(link->manager);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering log_error("Failed to update resolv.conf");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering r = sd_dhcp_client_get_mtu(client, &mtu);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering log_error_link(link, "Failed to set MTU "
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek r = sd_dhcp_client_get_hostname(client, &hostname);
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek r = set_hostname(link->manager->bus, hostname);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Failed to set transient hostname "
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int link_acquire_conf(Link *link) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_dhcp_client_attach_event(link->dhcp, NULL, 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_dhcp_client_set_request_option(link->dhcp, 26);
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering log_debug_link(link, "acquiring DHCPv4 lease");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int link_update_flags(Link *link, unsigned flags) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug_link(link, "link status unchanged: %#.8x", flags);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if ((link->flags & IFF_UP) != (flags & IFF_UP))
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "link is %s", flags & IFF_UP ? "up": "down");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering "link status updated: %#.8x -> %#.8x", link->flags, flags);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "MESSAGE=%s: could not bring up interface: %s",
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering "ERRNO=%d", -r,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering link_update_flags(link, link->flags | IFF_UP);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug_link(link, "bringing link up");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error_link(link, "Could not allocate RTM_SETLINK message");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error_link(link, "Could not set link flags: %s", strerror(-r));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "Could not send rtnetlink message: %s", strerror(-r));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(link->state == LINK_STATE_ENSLAVING);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt "MESSAGE=%s: could not enslave: %s",
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering "ERRNO=%d", -r,
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poetteringstatic int link_enter_enslave(Link *link) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(link->state == _LINK_STATE_INVALID);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (!link->network->bridge && !link->network->bond && !link->network->vlan)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "MESSAGE=%s: enslaving by '%s'",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->ifname, link->network->bridge->name,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = netdev_enslave(link->network->bridge, link, &enslave_handler);
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek log_struct_link(LOG_WARNING, link,
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering "MESSAGE=%s: could not enslave by '%s': %s",
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering link->ifname, link->network->bridge->name, strerror(-r),
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen "MESSAGE=%s: enslaving by '%s'",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = netdev_enslave(link->network->vlan, link, &enslave_handler);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "MESSAGE=%s: could not enslave by '%s': %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering strerror(-r), NETDEV(link->network->vlan),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "MESSAGE=%s: could not get state: %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "ERRNO=%d", -r,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug_link(link, "requesting link status");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen log_error_link(link, "Could not allocate RTM_GETLINK message");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "Could not send rtnetlink message: %s", strerror(-r));
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(link->state == _LINK_STATE_INVALID);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_update(Link *link, sd_rtnl_message *m) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_rtnl_message_link_get_flags(m, &flags);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning_link(link, "Could not get link flags");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (sd_rtnl_message_read(m, &type, &data) > 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (type == IFLA_MTU && link->network->dhcp &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->network->dhcp_mtu && !link->original_mtu) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_debug_link(link, "saved original MTU: %" PRIu16,