1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/ether.h>
26 #include "libudev-private.h"
29 #include "network-internal.h"
31 #include "dhcp-lease-internal.h"
33 int link_new(Manager *manager, struct udev_device *device, Link **ret) {
34 _cleanup_link_free_ Link *link = NULL;
39 assert(manager->links);
47 link->manager = manager;
48 link->state = _LINK_STATE_INVALID;
50 link->ifindex = udev_device_get_ifindex(device);
51 if (link->ifindex <= 0)
54 r = asprintf(&link->state_file, "/run/systemd/network/links/%"PRIu64,
59 ifname = udev_device_get_sysname(device);
60 link->ifname = strdup(ifname);
62 r = hashmap_put(manager->links, &link->ifindex, link);
66 link->udev_device = udev_device_ref(device);
74 void link_free(Link *link) {
78 assert(link->manager);
80 sd_dhcp_client_free(link->dhcp_client);
81 sd_dhcp_lease_unref(link->dhcp_lease);
83 sd_ipv4ll_free(link->ipv4ll);
85 hashmap_remove(link->manager->links, &link->ifindex);
88 free(link->state_file);
90 udev_device_unref(link->udev_device);
95 int link_get(Manager *m, int ifindex, Link **ret) {
104 ifindex_64 = ifindex;
105 link = hashmap_get(m->links, &ifindex_64);
114 static int link_enter_configured(Link *link) {
116 assert(link->state == LINK_STATE_SETTING_ROUTES);
118 log_info_link(link, "link configured");
120 link->state = LINK_STATE_CONFIGURED;
127 static void link_enter_failed(Link *link) {
130 log_warning_link(link, "failed");
132 link->state = LINK_STATE_FAILED;
137 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
138 Link *link = userdata;
141 assert(link->route_messages > 0);
142 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
143 link->state == LINK_STATE_SETTING_ROUTES ||
144 link->state == LINK_STATE_FAILED);
146 link->route_messages --;
148 if (link->state == LINK_STATE_FAILED)
151 r = sd_rtnl_message_get_errno(m);
152 if (r < 0 && r != -EEXIST)
153 log_struct_link(LOG_WARNING, link,
154 "MESSAGE=%s: could not set route: %s",
155 link->ifname, strerror(-r),
159 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
161 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
162 log_debug_link(link, "routes set");
163 link_enter_configured(link);
169 static int link_enter_set_routes(Link *link) {
175 assert(link->network);
176 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
178 link->state = LINK_STATE_SETTING_ROUTES;
180 if (!link->network->static_routes && !link->dhcp_lease &&
181 (!link->ipv4ll || sd_ipv4ll_get_address(link->ipv4ll, &a) < 0))
182 return link_enter_configured(link);
184 log_debug_link(link, "setting routes");
186 LIST_FOREACH(static_routes, rt, link->network->static_routes) {
187 r = route_configure(rt, link, &route_handler);
189 log_warning_link(link,
190 "could not set routes: %s", strerror(-r));
191 link_enter_failed(link);
195 link->route_messages ++;
198 if (link->ipv4ll && !link->dhcp_lease) {
199 _cleanup_route_free_ Route *route = NULL;
202 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
203 if (r < 0 && r != -ENOENT) {
204 log_warning_link(link, "IPV4LL error: no address: %s",
210 r = route_new_dynamic(&route);
212 log_error_link(link, "Could not allocate route: %s",
217 route->family = AF_INET;
218 route->scope = RT_SCOPE_LINK;
221 r = route_configure(route, link, &route_handler);
223 log_warning_link(link,
224 "could not set routes: %s", strerror(-r));
225 link_enter_failed(link);
229 link->route_messages ++;
233 if (link->dhcp_lease) {
234 _cleanup_route_free_ Route *route = NULL;
235 _cleanup_route_free_ Route *route_gw = NULL;
236 struct in_addr gateway;
238 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
240 log_warning_link(link, "DHCP error: no router: %s",
245 r = route_new_dynamic(&route);
247 log_error_link(link, "Could not allocate route: %s",
252 r = route_new_dynamic(&route_gw);
254 log_error_link(link, "Could not allocate route: %s",
259 /* The dhcp netmask may mask out the gateway. Add an explicit
260 * route for the gw host so that we can route no matter the
261 * netmask or existing kernel route tables. */
262 route_gw->family = AF_INET;
263 route_gw->dst_addr.in = gateway;
264 route_gw->dst_prefixlen = 32;
265 route_gw->scope = RT_SCOPE_LINK;
267 r = route_configure(route_gw, link, &route_handler);
269 log_warning_link(link,
270 "could not set host route: %s", strerror(-r));
274 link->route_messages ++;
276 route->family = AF_INET;
277 route->in_addr.in = gateway;
279 r = route_configure(route, link, &route_handler);
281 log_warning_link(link,
282 "could not set routes: %s", strerror(-r));
283 link_enter_failed(link);
287 link->route_messages ++;
293 static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
294 Link *link = userdata;
299 assert(link->ifname);
301 if (link->state == LINK_STATE_FAILED)
304 r = sd_rtnl_message_get_errno(m);
305 if (r < 0 && r != -ENOENT)
306 log_struct_link(LOG_WARNING, link,
307 "MESSAGE=%s: could not drop route: %s",
308 link->ifname, strerror(-r),
315 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
316 Link *link = userdata;
321 assert(link->ifname);
322 assert(link->addr_messages > 0);
323 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
325 link->addr_messages --;
327 if (link->state == LINK_STATE_FAILED)
330 r = sd_rtnl_message_get_errno(m);
331 if (r < 0 && r != -EEXIST)
332 log_struct_link(LOG_WARNING, link,
333 "MESSAGE=%s: could not set address: %s",
334 link->ifname, strerror(-r),
338 if (link->addr_messages == 0) {
339 log_debug_link(link, "addresses set");
340 link_enter_set_routes(link);
346 static int link_enter_set_addresses(Link *link) {
352 assert(link->network);
353 assert(link->state != _LINK_STATE_INVALID);
355 link->state = LINK_STATE_SETTING_ADDRESSES;
357 if (!link->network->static_addresses && !link->dhcp_lease &&
358 (!link->ipv4ll || sd_ipv4ll_get_address(link->ipv4ll, &a) < 0))
359 return link_enter_set_routes(link);
361 log_debug_link(link, "setting addresses");
363 LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
364 r = address_configure(ad, link, &address_handler);
366 log_warning_link(link,
367 "could not set addresses: %s", strerror(-r));
368 link_enter_failed(link);
372 link->addr_messages ++;
375 if (link->ipv4ll && !link->dhcp_lease) {
376 _cleanup_address_free_ Address *ll_addr = NULL;
379 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
380 if (r < 0 && r != -ENOENT) {
381 log_warning_link(link, "IPV4LL error: no address: %s",
387 r = address_new_dynamic(&ll_addr);
389 log_error_link(link, "Could not allocate address: %s", strerror(-r));
393 ll_addr->family = AF_INET;
394 ll_addr->in_addr.in = addr;
395 ll_addr->prefixlen = 16;
396 ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
397 ll_addr->scope = RT_SCOPE_LINK;
399 r = address_configure(ll_addr, link, &address_handler);
401 log_warning_link(link,
402 "could not set addresses: %s", strerror(-r));
403 link_enter_failed(link);
407 link->addr_messages ++;
411 if (link->dhcp_lease) {
412 _cleanup_address_free_ Address *address = NULL;
414 struct in_addr netmask;
417 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
419 log_warning_link(link, "DHCP error: no address: %s",
424 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
426 log_warning_link(link, "DHCP error: no netmask: %s",
431 prefixlen = net_netmask_to_prefixlen(&netmask);
433 r = address_new_dynamic(&address);
435 log_error_link(link, "Could not allocate address: %s",
440 address->family = AF_INET;
441 address->in_addr.in = addr;
442 address->prefixlen = prefixlen;
443 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
445 r = address_configure(address, link, &address_handler);
447 log_warning_link(link,
448 "could not set addresses: %s", strerror(-r));
449 link_enter_failed(link);
453 link->addr_messages ++;
459 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
460 Link *link = userdata;
465 assert(link->ifname);
467 if (link->state == LINK_STATE_FAILED)
470 r = sd_rtnl_message_get_errno(m);
471 if (r < 0 && r != -ENOENT)
472 log_struct_link(LOG_WARNING, link,
473 "MESSAGE=%s: could not drop address: %s",
474 link->ifname, strerror(-r),
481 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
484 r = sd_bus_message_get_errno(m);
486 log_warning("Could not set hostname: %s", strerror(-r));
491 static int set_hostname(sd_bus *bus, const char *hostname) {
492 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
497 log_debug("Setting transient hostname: '%s'", hostname);
499 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
500 log_info("Not connected to system bus, ignoring transient hostname.");
504 r = sd_bus_message_new_method_call(
507 "org.freedesktop.hostname1",
508 "/org/freedesktop/hostname1",
509 "org.freedesktop.hostname1",
514 r = sd_bus_message_append(m, "sb", hostname, false);
518 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
520 log_error("Could not set transient hostname: %s", strerror(-r));
525 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
526 Link *link = userdata;
531 assert(link->ifname);
533 if (link->state == LINK_STATE_FAILED)
536 r = sd_rtnl_message_get_errno(m);
538 log_struct_link(LOG_WARNING, link,
539 "MESSAGE=%s: could not set MTU: %s",
540 link->ifname, strerror(-r),
547 static int link_set_mtu(Link *link, uint32_t mtu) {
548 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
552 assert(link->manager);
553 assert(link->manager->rtnl);
555 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
557 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
558 RTM_SETLINK, link->ifindex);
560 log_error_link(link, "Could not allocate RTM_SETLINK message");
564 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
566 log_error_link(link, "Could not append MTU: %s", strerror(-r));
570 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
573 "Could not send rtnetlink message: %s", strerror(-r));
580 static int dhcp_lease_lost(Link *link) {
581 _cleanup_address_free_ Address *address = NULL;
583 struct in_addr netmask;
588 assert(link->dhcp_lease);
590 log_warning_link(link, "DHCP lease lost");
592 r = address_new_dynamic(&address);
594 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
595 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
596 prefixlen = net_netmask_to_prefixlen(&netmask);
598 address->family = AF_INET;
599 address->in_addr.in = addr;
600 address->prefixlen = prefixlen;
602 address_drop(address, link, &address_drop_handler);
605 if (link->network->dhcp_mtu) {
608 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
609 if (r >= 0 && link->original_mtu != mtu) {
610 r = link_set_mtu(link, link->original_mtu);
612 log_warning_link(link, "DHCP error: could not reset MTU");
613 link_enter_failed(link);
619 if (link->network->dhcp_hostname) {
620 const char *hostname = NULL;
622 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
623 if (r >= 0 && hostname) {
624 r = set_hostname(link->manager->bus, "");
626 log_error("Failed to reset transient hostname");
630 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
635 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
636 sd_dhcp_lease *lease;
637 struct in_addr address;
638 struct in_addr netmask;
639 struct in_addr gateway;
641 struct in_addr *nameservers;
642 size_t nameservers_size;
648 r = sd_dhcp_client_get_lease(client, &lease);
650 log_warning_link(link, "DHCP error: no lease: %s",
655 r = sd_dhcp_lease_get_address(lease, &address);
657 log_warning_link(link, "DHCP error: no address: %s",
662 r = sd_dhcp_lease_get_netmask(lease, &netmask);
664 log_warning_link(link, "DHCP error: no netmask: %s",
669 prefixlen = net_netmask_to_prefixlen(&netmask);
671 r = sd_dhcp_lease_get_router(lease, &gateway);
673 log_warning_link(link, "DHCP error: no router: %s",
678 log_struct_link(LOG_INFO, link,
679 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
681 ADDRESS_FMT_VAL(address),
683 ADDRESS_FMT_VAL(gateway),
684 "ADDRESS=%u.%u.%u.%u",
685 ADDRESS_FMT_VAL(address),
688 "GATEWAY=%u.%u.%u.%u",
689 ADDRESS_FMT_VAL(gateway),
692 link->dhcp_lease = lease;
694 if (link->network->dhcp_dns) {
695 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
697 r = manager_update_resolv_conf(link->manager);
699 log_error("Failed to update resolv.conf");
703 if (link->network->dhcp_mtu) {
706 r = sd_dhcp_lease_get_mtu(lease, &mtu);
708 r = link_set_mtu(link, mtu);
710 log_error_link(link, "Failed to set MTU "
715 if (link->network->dhcp_hostname) {
716 const char *hostname;
718 r = sd_dhcp_lease_get_hostname(lease, &hostname);
720 r = set_hostname(link->manager->bus, hostname);
722 log_error("Failed to set transient hostname "
723 "to '%s'", hostname);
727 link_enter_set_addresses(link);
732 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
733 Link *link = userdata;
737 assert(link->network);
738 assert(link->manager);
740 if (link->state == LINK_STATE_FAILED)
744 case DHCP_EVENT_NO_LEASE:
745 log_debug_link(link, "IP address in use.");
747 case DHCP_EVENT_EXPIRED:
748 case DHCP_EVENT_STOP:
749 case DHCP_EVENT_IP_CHANGE:
750 if (link->network->dhcp_critical) {
751 log_error_link(link, "DHCPv4 connection considered system critical, "
752 "ignoring request to reconfigure it.");
756 if (link->dhcp_lease) {
757 r = dhcp_lease_lost(link);
759 link_enter_failed(link);
764 if (event == DHCP_EVENT_IP_CHANGE) {
765 r = dhcp_lease_acquired(client, link);
767 link_enter_failed(link);
772 if (event == DHCP_EVENT_EXPIRED && link->network->ipv4ll) {
773 r = sd_ipv4ll_start (link->ipv4ll);
775 link_enter_failed(link);
781 case DHCP_EVENT_IP_ACQUIRE:
782 r = dhcp_lease_acquired(client, link);
784 link_enter_failed(link);
788 r = sd_ipv4ll_stop(link->ipv4ll);
790 link_enter_failed(link);
797 log_warning_link(link, "DHCP error: %s", strerror(-event));
799 log_warning_link(link, "DHCP unknown event: %d", event);
806 static int ipv4ll_address_lost(sd_ipv4ll *ll, Link *link) {
813 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
815 _cleanup_address_free_ Address *address = NULL;
816 _cleanup_route_free_ Route *route = NULL;
818 log_debug_link(link, "IPv4 link-local release %u.%u.%u.%u",
819 ADDRESS_FMT_VAL(addr));
821 r = address_new_dynamic(&address);
823 log_error_link(link, "Could not allocate address: %s", strerror(-r));
827 address->family = AF_INET;
828 address->in_addr.in = addr;
829 address->prefixlen = 16;
830 address->scope = RT_SCOPE_LINK;
832 address_drop(address, link, &address_drop_handler);
834 r = route_new_dynamic(&route);
836 log_error_link(link, "Could not allocate route: %s",
841 route->family = AF_INET;
842 route->scope = RT_SCOPE_LINK;
845 route_drop(route, link, &route_drop_handler);
851 static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
852 struct in_addr address;
858 r = sd_ipv4ll_get_address(ll, &address);
862 log_struct_link(LOG_INFO, link,
863 "MESSAGE=%s: IPv4 link-local address %u.%u.%u.%u",
865 ADDRESS_FMT_VAL(address),
868 link_enter_set_addresses(link);
873 static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
874 Link *link = userdata;
878 assert(link->network);
879 assert(link->manager);
882 case IPV4LL_EVENT_STOP:
883 case IPV4LL_EVENT_CONFLICT:
884 r = ipv4ll_address_lost(ll, link);
886 link_enter_failed(link);
890 case IPV4LL_EVENT_BIND:
891 r = ipv4ll_address_claimed(ll, link);
893 link_enter_failed(link);
899 log_warning_link(link, "IPv4 link-local error: %s", strerror(-event));
901 log_warning_link(link, "IPv4 link-local unknown event: %d", event);
906 static int link_acquire_conf(Link *link) {
910 assert(link->network);
911 assert(link->manager);
912 assert(link->manager->event);
914 if (link->network->ipv4ll) {
915 assert(link->ipv4ll);
917 log_debug_link(link, "acquiring IPv4 link-local address");
919 r = sd_ipv4ll_start(link->ipv4ll);
924 if (link->network->dhcp) {
925 assert(link->dhcp_client);
927 log_debug_link(link, "acquiring DHCPv4 lease");
929 r = sd_dhcp_client_start(link->dhcp_client);
937 static int link_update_flags(Link *link, unsigned flags) {
941 assert(link->network);
943 if (link->state == LINK_STATE_FAILED)
946 if (link->flags == flags)
949 log_debug_link(link, "link status updated: %#.8x -> %#.8x",
952 if ((link->flags & IFF_UP) != (flags & IFF_UP))
954 "link is %s", flags & IFF_UP ? "up": "down");
956 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
957 if (flags & IFF_LOWER_UP) {
958 log_info_link(link, "carrier on");
960 if (link->network->dhcp || link->network->ipv4ll) {
961 r = link_acquire_conf(link);
963 log_warning_link(link, "Could not acquire configuration: %s", strerror(-r));
964 link_enter_failed(link);
969 log_info_link(link, "carrier off");
971 if (link->network->dhcp) {
972 r = sd_dhcp_client_stop(link->dhcp_client);
974 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
975 link_enter_failed(link);
980 if (link->network->ipv4ll) {
981 r = sd_ipv4ll_stop(link->ipv4ll);
983 log_warning_link(link, "Could not stop IPv4 link-local: %s", strerror(-r));
984 link_enter_failed(link);
996 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
997 Link *link = userdata;
1002 if (link->state == LINK_STATE_FAILED)
1005 r = sd_rtnl_message_get_errno(m);
1007 link_update_flags(link, link->flags | IFF_UP);
1009 log_struct_link(LOG_WARNING, link,
1010 "MESSAGE=%s: could not bring up interface: %s",
1011 link->ifname, strerror(-r),
1017 static int link_up(Link *link) {
1018 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1022 assert(link->manager);
1023 assert(link->manager->rtnl);
1025 log_debug_link(link, "bringing link up");
1027 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1028 RTM_SETLINK, link->ifindex);
1030 log_error_link(link, "Could not allocate RTM_SETLINK message");
1034 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
1036 log_error_link(link, "Could not set link flags: %s", strerror(-r));
1040 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
1042 log_error_link(link,
1043 "Could not send rtnetlink message: %s", strerror(-r));
1050 static int link_enslaved(Link *link) {
1054 assert(link->state == LINK_STATE_ENSLAVING);
1055 assert(link->network);
1059 link_enter_failed(link);
1063 if (!link->network->dhcp && !link->network->ipv4ll)
1064 return link_enter_set_addresses(link);
1069 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1070 Link *link = userdata;
1074 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
1075 assert(link->network);
1079 if (link->state == LINK_STATE_FAILED)
1082 r = sd_rtnl_message_get_errno(m);
1084 log_struct_link(LOG_ERR, link,
1085 "MESSAGE=%s: could not enslave: %s",
1086 link->ifname, strerror(-r),
1089 link_enter_failed(link);
1093 log_debug_link(link, "enslaved");
1095 if (link->enslaving == 0)
1096 link_enslaved(link);
1101 static int link_enter_enslave(Link *link) {
1102 NetDev *vlan, *macvlan;
1107 assert(link->network);
1108 assert(link->state == _LINK_STATE_INVALID);
1110 link->state = LINK_STATE_ENSLAVING;
1114 if (!link->network->bridge && !link->network->bond &&
1115 hashmap_isempty(link->network->vlans) &&
1116 hashmap_isempty(link->network->macvlans))
1117 return link_enslaved(link);
1119 if (link->network->bridge) {
1120 log_struct_link(LOG_DEBUG, link,
1121 "MESSAGE=%s: enslaving by '%s'",
1122 link->ifname, link->network->bridge->name,
1123 NETDEV(link->network->bridge),
1126 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1128 log_struct_link(LOG_WARNING, link,
1129 "MESSAGE=%s: could not enslave by '%s': %s",
1130 link->ifname, link->network->bridge->name, strerror(-r),
1131 NETDEV(link->network->bridge),
1133 link_enter_failed(link);
1140 if (link->network->bond) {
1141 log_struct_link(LOG_DEBUG, link,
1142 "MESSAGE=%s: enslaving by '%s'",
1143 link->ifname, link->network->bond->name,
1144 NETDEV(link->network->bond),
1147 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1149 log_struct_link(LOG_WARNING, link,
1150 "MESSAGE=%s: could not enslave by '%s': %s",
1151 link->ifname, link->network->bond->name, strerror(-r),
1152 NETDEV(link->network->bond),
1154 link_enter_failed(link);
1161 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
1162 log_struct_link(LOG_DEBUG, link,
1163 "MESSAGE=%s: enslaving by '%s'",
1164 link->ifname, vlan->name, NETDEV(vlan), NULL);
1166 r = netdev_enslave(vlan, link, &enslave_handler);
1168 log_struct_link(LOG_WARNING, link,
1169 "MESSAGE=%s: could not enslave by '%s': %s",
1170 link->ifname, vlan->name, strerror(-r),
1171 NETDEV(vlan), NULL);
1172 link_enter_failed(link);
1179 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1180 log_struct_link(LOG_DEBUG, link,
1181 "MESSAGE=%s: enslaving by '%s'",
1182 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1184 r = netdev_enslave(macvlan, link, &enslave_handler);
1186 log_struct_link(LOG_WARNING, link,
1187 "MESSAGE=%s: could not enslave by '%s': %s",
1188 link->ifname, macvlan->name, strerror(-r),
1189 NETDEV(macvlan), NULL);
1190 link_enter_failed(link);
1200 static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1202 Link *link = userdata;
1207 if (link->state == LINK_STATE_FAILED)
1210 r = sd_rtnl_message_get_errno(m);
1212 log_struct_link(LOG_ERR, link,
1213 "MESSAGE=%s: could not get state: %s",
1214 link->ifname, strerror(-r),
1217 link_enter_failed(link);
1221 link_update(link, m);
1226 static int link_getlink(Link *link) {
1227 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1231 assert(link->manager);
1232 assert(link->manager->rtnl);
1234 log_debug_link(link, "requesting link status");
1236 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1237 RTM_GETLINK, link->ifindex);
1239 log_error_link(link, "Could not allocate RTM_GETLINK message");
1243 r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
1246 log_error_link(link,
1247 "Could not send rtnetlink message: %s", strerror(-r));
1254 static int link_configure(Link *link) {
1258 assert(link->state == _LINK_STATE_INVALID);
1260 r = link_getlink(link);
1264 return link_enter_enslave(link);
1267 int link_add(Manager *m, struct udev_device *device, Link **ret) {
1275 r = link_new(m, device, &link);
1281 r = network_get(m, device, &network);
1283 return r == -ENOENT ? 0 : r;
1285 r = network_apply(m, network, link);
1289 if (link->network->ipv4ll) {
1291 r = sd_ipv4ll_new(&link->ipv4ll);
1295 r = net_get_unique_predictable_data(link->udev_device, seed);
1297 r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
1302 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
1306 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
1310 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
1315 if (link->network->dhcp) {
1316 r = sd_dhcp_client_new(&link->dhcp_client);
1320 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
1324 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
1328 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
1332 if (link->network->dhcp_mtu) {
1333 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
1339 r = link_configure(link);
1346 int link_update(Link *link, sd_rtnl_message *m) {
1348 struct ether_addr mac;
1352 assert(link->network);
1355 if (link->state == LINK_STATE_FAILED)
1358 if (link->network->dhcp && link->network->dhcp_mtu &&
1359 !link->original_mtu) {
1360 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1362 log_debug_link(link, "saved original MTU: %"
1363 PRIu16, link->original_mtu);
1366 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
1367 if (r >= 0 && memcmp(&link->mac.ether_addr_octet, &mac.ether_addr_octet, ETH_ALEN)) {
1369 memcpy(&link->mac.ether_addr_octet, &mac.ether_addr_octet, ETH_ALEN);
1371 log_debug_link(link, "MAC address: "
1372 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1373 mac.ether_addr_octet[0],
1374 mac.ether_addr_octet[1],
1375 mac.ether_addr_octet[2],
1376 mac.ether_addr_octet[3],
1377 mac.ether_addr_octet[4],
1378 mac.ether_addr_octet[5]);
1381 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1383 log_warning_link(link, "Could not update MAC "
1384 "address in IPv4LL client: %s",
1390 if (link->dhcp_client) {
1391 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1393 log_warning_link(link, "Could not update MAC "
1394 "address in DHCP client: %s",
1401 r = sd_rtnl_message_link_get_flags(m, &flags);
1403 log_warning_link(link, "Could not get link flags");
1407 return link_update_flags(link, flags);
1410 int link_save(Link *link) {
1411 _cleanup_free_ char *temp_path = NULL;
1412 _cleanup_fclose_ FILE *f = NULL;
1416 assert(link->state_file);
1418 r = fopen_temporary(link->state_file, &f, &temp_path);
1422 fchmod(fileno(f), 0644);
1425 "# This is private data. Do not parse.\n"
1427 link_state_to_string(link->state));
1429 if (link->dhcp_lease) {
1432 r = asprintf(&lease_file, "/run/systemd/network/leases/%"PRIu64,
1437 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1441 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1446 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1448 unlink(link->state_file);
1454 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1459 static const char* const link_state_table[_LINK_STATE_MAX] = {
1460 [LINK_STATE_ENSLAVING] = "configuring",
1461 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1462 [LINK_STATE_SETTING_ROUTES] = "configuring",
1463 [LINK_STATE_CONFIGURED] = "configured",
1464 [LINK_STATE_FAILED] = "failed",
1467 DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);