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"
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;
36 struct ether_addr *mac_addr;
41 assert(manager->links);
49 link->manager = manager;
50 link->state = _LINK_STATE_INVALID;
52 link->ifindex = udev_device_get_ifindex(device);
53 if (link->ifindex <= 0)
56 r = asprintf(&link->state_file, "/run/systemd/network/links/%u",
57 (unsigned) link->ifindex);
61 mac = udev_device_get_sysattr_value(device, "address");
63 mac_addr = ether_aton(mac);
65 memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
68 ifname = udev_device_get_sysname(device);
69 link->ifname = strdup(ifname);
71 r = hashmap_put(manager->links, &link->ifindex, link);
81 void link_free(Link *link) {
85 assert(link->manager);
87 sd_dhcp_client_free(link->dhcp_client);
88 sd_dhcp_lease_unref(link->dhcp_lease);
90 sd_ipv4ll_free(link->ipv4ll);
92 hashmap_remove(link->manager->links, &link->ifindex);
95 free(link->state_file);
100 int link_get(Manager *m, int ifindex, Link **ret) {
109 ifindex_64 = ifindex;
110 link = hashmap_get(m->links, &ifindex_64);
119 int link_add(Manager *m, struct udev_device *device, Link **ret) {
127 r = link_new(m, device, &link);
133 r = network_get(m, device, &network);
135 return r == -ENOENT ? 0 : r;
137 r = network_apply(m, network, link);
144 static int link_enter_configured(Link *link) {
146 assert(link->state == LINK_STATE_SETTING_ROUTES);
148 log_info_link(link, "link configured");
150 link->state = LINK_STATE_CONFIGURED;
157 static void link_enter_failed(Link *link) {
160 log_warning_link(link, "failed");
162 link->state = LINK_STATE_FAILED;
167 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
168 Link *link = userdata;
171 assert(link->route_messages > 0);
172 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
173 link->state == LINK_STATE_SETTING_ROUTES ||
174 link->state == LINK_STATE_FAILED);
176 link->route_messages --;
178 if (link->state == LINK_STATE_FAILED)
181 r = sd_rtnl_message_get_errno(m);
182 if (r < 0 && r != -EEXIST)
183 log_struct_link(LOG_WARNING, link,
184 "MESSAGE=%s: could not set route: %s",
185 link->ifname, strerror(-r),
189 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
191 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
192 log_debug_link(link, "routes set");
193 link_enter_configured(link);
199 static int link_enter_set_routes(Link *link) {
205 assert(link->network);
206 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
208 link->state = LINK_STATE_SETTING_ROUTES;
210 if (!link->network->static_routes && !link->dhcp_lease &&
211 (!link->ipv4ll || sd_ipv4ll_get_address(link->ipv4ll, &a) < 0))
212 return link_enter_configured(link);
214 log_debug_link(link, "setting routes");
216 LIST_FOREACH(static_routes, rt, link->network->static_routes) {
217 r = route_configure(rt, link, &route_handler);
219 log_warning_link(link,
220 "could not set routes: %s", strerror(-r));
221 link_enter_failed(link);
225 link->route_messages ++;
228 if (link->ipv4ll && !link->dhcp_lease) {
229 _cleanup_route_free_ Route *route = NULL;
232 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
233 if (r < 0 && r != -ENOENT) {
234 log_warning_link(link, "IPV4LL error: no address: %s",
240 r = route_new_dynamic(&route);
242 log_error_link(link, "Could not allocate route: %s",
247 route->family = AF_INET;
248 route->scope = RT_SCOPE_LINK;
251 r = route_configure(route, link, &route_handler);
253 log_warning_link(link,
254 "could not set routes: %s", strerror(-r));
255 link_enter_failed(link);
259 link->route_messages ++;
263 if (link->dhcp_lease) {
264 _cleanup_route_free_ Route *route = NULL;
265 struct in_addr gateway;
267 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
269 log_warning_link(link, "DHCP error: no router: %s",
274 r = route_new_dynamic(&route);
276 log_error_link(link, "Could not allocate route: %s",
281 route->family = AF_INET;
282 route->in_addr.in = gateway;
284 r = route_configure(route, link, &route_handler);
286 log_warning_link(link,
287 "could not set routes: %s", strerror(-r));
288 link_enter_failed(link);
292 link->route_messages ++;
298 static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
299 Link *link = userdata;
304 assert(link->ifname);
306 if (link->state == LINK_STATE_FAILED)
309 r = sd_rtnl_message_get_errno(m);
310 if (r < 0 && r != -ENOENT)
311 log_struct_link(LOG_WARNING, link,
312 "MESSAGE=%s: could not drop route: %s",
313 link->ifname, strerror(-r),
320 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
321 Link *link = userdata;
326 assert(link->ifname);
327 assert(link->addr_messages > 0);
328 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
330 link->addr_messages --;
332 if (link->state == LINK_STATE_FAILED)
335 r = sd_rtnl_message_get_errno(m);
336 if (r < 0 && r != -EEXIST)
337 log_struct_link(LOG_WARNING, link,
338 "MESSAGE=%s: could not set address: %s",
339 link->ifname, strerror(-r),
343 if (link->addr_messages == 0) {
344 log_debug_link(link, "addresses set");
345 link_enter_set_routes(link);
351 static int link_enter_set_addresses(Link *link) {
357 assert(link->network);
358 assert(link->state != _LINK_STATE_INVALID);
360 link->state = LINK_STATE_SETTING_ADDRESSES;
362 if (!link->network->static_addresses && !link->dhcp_lease &&
363 (!link->ipv4ll || sd_ipv4ll_get_address(link->ipv4ll, &a) < 0))
364 return link_enter_set_routes(link);
366 log_debug_link(link, "setting addresses");
368 LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
369 r = address_configure(ad, link, &address_handler);
371 log_warning_link(link,
372 "could not set addresses: %s", strerror(-r));
373 link_enter_failed(link);
377 link->addr_messages ++;
380 if (link->ipv4ll && !link->dhcp_lease) {
381 _cleanup_address_free_ Address *ll_addr = NULL;
384 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
385 if (r < 0 && r != -ENOENT) {
386 log_warning_link(link, "IPV4LL error: no address: %s",
392 r = address_new_dynamic(&ll_addr);
394 log_error_link(link, "Could not allocate address: %s", strerror(-r));
398 ll_addr->family = AF_INET;
399 ll_addr->in_addr.in = addr;
400 ll_addr->prefixlen = 16;
401 ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
402 ll_addr->scope = RT_SCOPE_LINK;
404 r = address_configure(ll_addr, link, &address_handler);
406 log_warning_link(link,
407 "could not set addresses: %s", strerror(-r));
408 link_enter_failed(link);
412 link->addr_messages ++;
416 if (link->dhcp_lease) {
417 _cleanup_address_free_ Address *address = NULL;
419 struct in_addr netmask;
422 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
424 log_warning_link(link, "DHCP error: no address: %s",
429 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
431 log_warning_link(link, "DHCP error: no netmask: %s",
436 prefixlen = net_netmask_to_prefixlen(&netmask);
438 r = address_new_dynamic(&address);
440 log_error_link(link, "Could not allocate address: %s",
445 address->family = AF_INET;
446 address->in_addr.in = addr;
447 address->prefixlen = prefixlen;
448 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
450 r = address_configure(address, link, &address_handler);
452 log_warning_link(link,
453 "could not set addresses: %s", strerror(-r));
454 link_enter_failed(link);
458 link->addr_messages ++;
464 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
465 Link *link = userdata;
470 assert(link->ifname);
472 if (link->state == LINK_STATE_FAILED)
475 r = sd_rtnl_message_get_errno(m);
476 if (r < 0 && r != -ENOENT)
477 log_struct_link(LOG_WARNING, link,
478 "MESSAGE=%s: could not drop address: %s",
479 link->ifname, strerror(-r),
486 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
489 r = sd_bus_message_get_errno(m);
491 log_warning("Could not set hostname: %s", strerror(-r));
496 static int set_hostname(sd_bus *bus, const char *hostname) {
497 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
502 log_debug("Setting transient hostname: '%s'", hostname);
504 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
505 log_info("Not connected to system bus, ignoring transient hostname.");
509 r = sd_bus_message_new_method_call(
512 "org.freedesktop.hostname1",
513 "/org/freedesktop/hostname1",
514 "org.freedesktop.hostname1",
519 r = sd_bus_message_append(m, "sb", hostname, false);
523 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
525 log_error("Could not set transient hostname: %s", strerror(-r));
530 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
531 Link *link = userdata;
536 assert(link->ifname);
538 if (link->state == LINK_STATE_FAILED)
541 r = sd_rtnl_message_get_errno(m);
543 log_struct_link(LOG_WARNING, link,
544 "MESSAGE=%s: could not set MTU: %s",
545 link->ifname, strerror(-r),
552 static int link_set_mtu(Link *link, uint32_t mtu) {
553 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
557 assert(link->manager);
558 assert(link->manager->rtnl);
560 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
562 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
563 RTM_SETLINK, link->ifindex);
565 log_error_link(link, "Could not allocate RTM_SETLINK message");
569 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
571 log_error_link(link, "Could not append MTU: %s", strerror(-r));
575 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
578 "Could not send rtnetlink message: %s", strerror(-r));
585 static int dhcp_lease_lost(Link *link) {
586 _cleanup_address_free_ Address *address = NULL;
588 struct in_addr netmask;
593 assert(link->dhcp_lease);
595 log_warning_link(link, "DHCP lease lost");
597 r = address_new_dynamic(&address);
599 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
600 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
601 prefixlen = net_netmask_to_prefixlen(&netmask);
603 address->family = AF_INET;
604 address->in_addr.in = addr;
605 address->prefixlen = prefixlen;
607 address_drop(address, link, &address_drop_handler);
610 if (link->network->dhcp_mtu) {
613 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
614 if (r >= 0 && link->original_mtu != mtu) {
615 r = link_set_mtu(link, link->original_mtu);
617 log_warning_link(link, "DHCP error: could not reset MTU");
618 link_enter_failed(link);
624 if (link->network->dhcp_hostname) {
625 const char *hostname = NULL;
627 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
628 if (r >= 0 && hostname) {
629 r = set_hostname(link->manager->bus, "");
631 log_error("Failed to reset transient hostname");
635 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
640 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
641 sd_dhcp_lease *lease;
642 struct in_addr address;
643 struct in_addr netmask;
644 struct in_addr gateway;
646 struct in_addr *nameservers;
647 size_t nameservers_size;
653 r = sd_dhcp_client_get_lease(client, &lease);
655 log_warning_link(link, "DHCP error: no lease: %s",
660 r = sd_dhcp_lease_get_address(lease, &address);
662 log_warning_link(link, "DHCP error: no address: %s",
667 r = sd_dhcp_lease_get_netmask(lease, &netmask);
669 log_warning_link(link, "DHCP error: no netmask: %s",
674 prefixlen = net_netmask_to_prefixlen(&netmask);
676 r = sd_dhcp_lease_get_router(lease, &gateway);
678 log_warning_link(link, "DHCP error: no router: %s",
683 log_struct_link(LOG_INFO, link,
684 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
686 ADDRESS_FMT_VAL(address),
688 ADDRESS_FMT_VAL(gateway),
689 "ADDRESS=%u.%u.%u.%u",
690 ADDRESS_FMT_VAL(address),
693 "GATEWAY=%u.%u.%u.%u",
694 ADDRESS_FMT_VAL(gateway),
697 link->dhcp_lease = lease;
699 if (link->network->dhcp_dns) {
700 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
702 r = manager_update_resolv_conf(link->manager);
704 log_error("Failed to update resolv.conf");
708 if (link->network->dhcp_mtu) {
711 r = sd_dhcp_lease_get_mtu(lease, &mtu);
713 r = link_set_mtu(link, mtu);
715 log_error_link(link, "Failed to set MTU "
720 if (link->network->dhcp_hostname) {
721 const char *hostname;
723 r = sd_dhcp_lease_get_hostname(lease, &hostname);
725 r = set_hostname(link->manager->bus, hostname);
727 log_error("Failed to set transient hostname "
728 "to '%s'", hostname);
732 link_enter_set_addresses(link);
737 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
738 Link *link = userdata;
742 assert(link->network);
743 assert(link->manager);
745 if (link->state == LINK_STATE_FAILED)
749 case DHCP_EVENT_NO_LEASE:
750 log_debug_link(link, "IP address in use.");
752 case DHCP_EVENT_EXPIRED:
753 case DHCP_EVENT_STOP:
754 case DHCP_EVENT_IP_CHANGE:
755 if (link->network->dhcp_critical) {
756 log_error_link(link, "DHCPv4 connection considered system critical, "
757 "ignoring request to reconfigure it.");
761 if (link->dhcp_lease) {
762 r = dhcp_lease_lost(link);
764 link_enter_failed(link);
769 if (event == DHCP_EVENT_IP_CHANGE) {
770 r = dhcp_lease_acquired(client, link);
772 link_enter_failed(link);
777 if (event == DHCP_EVENT_EXPIRED && link->network->ipv4ll) {
778 r = sd_ipv4ll_start (link->ipv4ll);
780 link_enter_failed(link);
786 case DHCP_EVENT_IP_ACQUIRE:
787 r = dhcp_lease_acquired(client, link);
789 link_enter_failed(link);
793 r = sd_ipv4ll_stop(link->ipv4ll);
795 link_enter_failed(link);
802 log_warning_link(link, "DHCP error: %s", strerror(-event));
804 log_warning_link(link, "DHCP unknown event: %d", event);
811 static int ipv4ll_address_lost(sd_ipv4ll *ll, Link *link) {
818 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
820 _cleanup_address_free_ Address *address = NULL;
821 _cleanup_route_free_ Route *route = NULL;
823 log_debug_link(link, "IPv4 link-local release %u.%u.%u.%u",
824 ADDRESS_FMT_VAL(addr));
826 r = address_new_dynamic(&address);
828 log_error_link(link, "Could not allocate address: %s", strerror(-r));
832 address->family = AF_INET;
833 address->in_addr.in = addr;
834 address->prefixlen = 16;
835 address->scope = RT_SCOPE_LINK;
837 address_drop(address, link, &address_drop_handler);
839 r = route_new_dynamic(&route);
841 log_error_link(link, "Could not allocate route: %s",
846 route->family = AF_INET;
847 route->scope = RT_SCOPE_LINK;
850 route_drop(route, link, &route_drop_handler);
856 static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
857 struct in_addr address;
863 r = sd_ipv4ll_get_address(ll, &address);
867 log_struct_link(LOG_INFO, link,
868 "MESSAGE=%s: IPv4 link-local address %u.%u.%u.%u",
870 ADDRESS_FMT_VAL(address),
873 link_enter_set_addresses(link);
878 static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
879 Link *link = userdata;
883 assert(link->network);
884 assert(link->manager);
887 case IPV4LL_EVENT_STOP:
888 case IPV4LL_EVENT_CONFLICT:
889 r = ipv4ll_address_lost(ll, link);
891 link_enter_failed(link);
895 case IPV4LL_EVENT_BIND:
896 r = ipv4ll_address_claimed(ll, link);
898 link_enter_failed(link);
904 log_warning_link(link, "IPv4 link-local error: %s", strerror(-event));
906 log_warning_link(link, "IPv4 link-local unknown event: %d", event);
911 static int link_acquire_conf(Link *link) {
915 assert(link->network);
916 assert(link->manager);
917 assert(link->manager->event);
919 if (link->network->ipv4ll) {
921 r = sd_ipv4ll_new(&link->ipv4ll);
925 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
929 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
933 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
937 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
942 log_debug_link(link, "acquiring IPv4 link-local address");
944 r = sd_ipv4ll_start(link->ipv4ll);
949 if (link->network->dhcp) {
950 if (!link->dhcp_client) {
951 r = sd_dhcp_client_new(&link->dhcp_client);
955 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
959 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
963 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
967 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
971 if (link->network->dhcp_mtu) {
972 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
978 log_debug_link(link, "acquiring DHCPv4 lease");
980 r = sd_dhcp_client_start(link->dhcp_client);
988 static int link_update_flags(Link *link, unsigned flags) {
992 assert(link->network);
994 if (link->state == LINK_STATE_FAILED)
997 if (link->flags == flags) {
998 log_debug_link(link, "link status unchanged: %#.8x", flags);
1002 if ((link->flags & IFF_UP) != (flags & IFF_UP))
1004 "link is %s", flags & IFF_UP ? "up": "down");
1006 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1007 if (flags & IFF_LOWER_UP) {
1008 log_info_link(link, "carrier on");
1010 if (link->network->dhcp || link->network->ipv4ll) {
1011 r = link_acquire_conf(link);
1013 log_warning_link(link, "Could not acquire configuration: %s", strerror(-r));
1014 link_enter_failed(link);
1019 log_info_link(link, "carrier off");
1021 if (link->network->dhcp) {
1022 r = sd_dhcp_client_stop(link->dhcp_client);
1024 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
1025 link_enter_failed(link);
1030 if (link->network->ipv4ll) {
1031 r = sd_ipv4ll_stop(link->ipv4ll);
1033 log_warning_link(link, "Could not stop IPv4 link-local: %s", strerror(-r));
1034 link_enter_failed(link);
1041 log_debug_link(link,
1042 "link status updated: %#.8x -> %#.8x", link->flags, flags);
1044 link->flags = flags;
1049 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1050 Link *link = userdata;
1055 if (link->state == LINK_STATE_FAILED)
1058 r = sd_rtnl_message_get_errno(m);
1060 log_struct_link(LOG_ERR, link,
1061 "MESSAGE=%s: could not bring up interface: %s",
1062 link->ifname, strerror(-r),
1065 link_enter_failed(link);
1069 link_update_flags(link, link->flags | IFF_UP);
1074 static int link_up(Link *link) {
1075 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1079 assert(link->manager);
1080 assert(link->manager->rtnl);
1082 log_debug_link(link, "bringing link up");
1084 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1085 RTM_SETLINK, link->ifindex);
1087 log_error_link(link, "Could not allocate RTM_SETLINK message");
1091 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
1093 log_error_link(link, "Could not set link flags: %s", strerror(-r));
1097 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
1099 log_error_link(link,
1100 "Could not send rtnetlink message: %s", strerror(-r));
1107 static int link_enslaved(Link *link) {
1111 assert(link->state == LINK_STATE_ENSLAVING);
1112 assert(link->network);
1116 link_enter_failed(link);
1120 if (!link->network->dhcp && !link->network->ipv4ll)
1121 return link_enter_set_addresses(link);
1126 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1127 Link *link = userdata;
1131 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
1132 assert(link->network);
1136 if (link->state == LINK_STATE_FAILED)
1139 r = sd_rtnl_message_get_errno(m);
1141 log_struct_link(LOG_ERR, link,
1142 "MESSAGE=%s: could not enslave: %s",
1143 link->ifname, strerror(-r),
1146 link_enter_failed(link);
1150 log_debug_link(link, "enslaved");
1152 if (link->enslaving == 0)
1153 link_enslaved(link);
1158 static int link_enter_enslave(Link *link) {
1159 NetDev *vlan, *macvlan;
1164 assert(link->network);
1165 assert(link->state == _LINK_STATE_INVALID);
1167 link->state = LINK_STATE_ENSLAVING;
1171 if (!link->network->bridge && !link->network->bond &&
1172 hashmap_isempty(link->network->vlans) &&
1173 hashmap_isempty(link->network->macvlans))
1174 return link_enslaved(link);
1176 if (link->network->bridge) {
1177 log_struct_link(LOG_DEBUG, link,
1178 "MESSAGE=%s: enslaving by '%s'",
1179 link->ifname, link->network->bridge->name,
1180 NETDEV(link->network->bridge),
1183 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1185 log_struct_link(LOG_WARNING, link,
1186 "MESSAGE=%s: could not enslave by '%s': %s",
1187 link->ifname, link->network->bridge->name, strerror(-r),
1188 NETDEV(link->network->bridge),
1190 link_enter_failed(link);
1197 if (link->network->bond) {
1198 log_struct_link(LOG_DEBUG, link,
1199 "MESSAGE=%s: enslaving by '%s'",
1200 link->ifname, link->network->bond->name,
1201 NETDEV(link->network->bond),
1204 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1206 log_struct_link(LOG_WARNING, link,
1207 "MESSAGE=%s: could not enslave by '%s': %s",
1208 link->ifname, link->network->bond->name, strerror(-r),
1209 NETDEV(link->network->bond),
1211 link_enter_failed(link);
1218 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
1219 log_struct_link(LOG_DEBUG, link,
1220 "MESSAGE=%s: enslaving by '%s'",
1221 link->ifname, vlan->name, NETDEV(vlan), NULL);
1223 r = netdev_enslave(vlan, link, &enslave_handler);
1225 log_struct_link(LOG_WARNING, link,
1226 "MESSAGE=%s: could not enslave by '%s': %s",
1227 link->ifname, vlan->name, strerror(-r),
1228 NETDEV(vlan), NULL);
1229 link_enter_failed(link);
1236 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1237 log_struct_link(LOG_DEBUG, link,
1238 "MESSAGE=%s: enslaving by '%s'",
1239 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1241 r = netdev_enslave(macvlan, link, &enslave_handler);
1243 log_struct_link(LOG_WARNING, link,
1244 "MESSAGE=%s: could not enslave by '%s': %s",
1245 link->ifname, macvlan->name, strerror(-r),
1246 NETDEV(macvlan), NULL);
1247 link_enter_failed(link);
1257 static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1259 Link *link = userdata;
1264 if (link->state == LINK_STATE_FAILED)
1267 r = sd_rtnl_message_get_errno(m);
1269 log_struct_link(LOG_ERR, link,
1270 "MESSAGE=%s: could not get state: %s",
1271 link->ifname, strerror(-r),
1274 link_enter_failed(link);
1278 log_debug_link(link, "got link state");
1280 link_update(link, m);
1285 static int link_getlink(Link *link) {
1286 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1290 assert(link->manager);
1291 assert(link->manager->rtnl);
1293 log_debug_link(link, "requesting link status");
1295 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1296 RTM_GETLINK, link->ifindex);
1298 log_error_link(link, "Could not allocate RTM_GETLINK message");
1302 r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
1305 log_error_link(link,
1306 "Could not send rtnetlink message: %s", strerror(-r));
1313 int link_configure(Link *link) {
1317 assert(link->network);
1318 assert(link->state == _LINK_STATE_INVALID);
1320 r = link_getlink(link);
1322 link_enter_failed(link);
1326 return link_enter_enslave(link);
1329 int link_update(Link *link, sd_rtnl_message *m) {
1338 if (link->state == LINK_STATE_FAILED)
1341 r = sd_rtnl_message_link_get_flags(m, &flags);
1343 log_warning_link(link, "Could not get link flags");
1347 while (sd_rtnl_message_read(m, &type, &data) > 0) {
1350 if (link->network->dhcp && link->network->dhcp_mtu &&
1351 !link->original_mtu) {
1352 link->original_mtu = *(uint16_t *) data;
1353 log_debug_link(link, "saved original MTU: %"
1354 PRIu16, link->original_mtu);
1359 if (memcmp(&link->mac.ether_addr_octet, &data,
1361 memcpy(&link->mac, data, ETH_ALEN);
1363 log_debug_link(link, "updated MAC address: "
1364 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1365 link->mac.ether_addr_octet[0],
1366 link->mac.ether_addr_octet[1],
1367 link->mac.ether_addr_octet[2],
1368 link->mac.ether_addr_octet[3],
1369 link->mac.ether_addr_octet[4],
1370 link->mac.ether_addr_octet[5]);
1377 return link_update_flags(link, flags);
1380 int link_save(Link *link) {
1381 _cleanup_free_ char *temp_path = NULL;
1382 _cleanup_fclose_ FILE *f = NULL;
1386 assert(link->state_file);
1388 r = mkdir_safe_label("/run/systemd/network/links", 0755, 0, 0);
1392 r = fopen_temporary(link->state_file, &f, &temp_path);
1396 fchmod(fileno(f), 0644);
1399 "# This is private data. Do not parse.\n"
1401 link_state_to_string(link->state));
1403 if (link->dhcp_lease) {
1404 const char *lease_file = "/run/systemd/network/leases/test.lease";
1406 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1410 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1415 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1417 unlink(link->state_file);
1423 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1428 static const char* const link_state_table[_LINK_STATE_MAX] = {
1429 [LINK_STATE_ENSLAVING] = "configuring",
1430 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1431 [LINK_STATE_SETTING_ROUTES] = "configuring",
1432 [LINK_STATE_CONFIGURED] = "configured",
1433 [LINK_STATE_FAILED] = "failed",
1436 DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);