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 link_update_flags(link, link->flags | IFF_UP);
1062 log_struct_link(LOG_WARNING, link,
1063 "MESSAGE=%s: could not bring up interface: %s",
1064 link->ifname, strerror(-r),
1070 static int link_up(Link *link) {
1071 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1075 assert(link->manager);
1076 assert(link->manager->rtnl);
1078 log_debug_link(link, "bringing link up");
1080 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1081 RTM_SETLINK, link->ifindex);
1083 log_error_link(link, "Could not allocate RTM_SETLINK message");
1087 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
1089 log_error_link(link, "Could not set link flags: %s", strerror(-r));
1093 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
1095 log_error_link(link,
1096 "Could not send rtnetlink message: %s", strerror(-r));
1103 static int link_enslaved(Link *link) {
1107 assert(link->state == LINK_STATE_ENSLAVING);
1108 assert(link->network);
1112 link_enter_failed(link);
1116 if (!link->network->dhcp && !link->network->ipv4ll)
1117 return link_enter_set_addresses(link);
1122 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1123 Link *link = userdata;
1127 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
1128 assert(link->network);
1132 if (link->state == LINK_STATE_FAILED)
1135 r = sd_rtnl_message_get_errno(m);
1137 log_struct_link(LOG_ERR, link,
1138 "MESSAGE=%s: could not enslave: %s",
1139 link->ifname, strerror(-r),
1142 link_enter_failed(link);
1146 log_debug_link(link, "enslaved");
1148 if (link->enslaving == 0)
1149 link_enslaved(link);
1154 static int link_enter_enslave(Link *link) {
1155 NetDev *vlan, *macvlan;
1160 assert(link->network);
1161 assert(link->state == _LINK_STATE_INVALID);
1163 link->state = LINK_STATE_ENSLAVING;
1167 if (!link->network->bridge && !link->network->bond &&
1168 hashmap_isempty(link->network->vlans) &&
1169 hashmap_isempty(link->network->macvlans))
1170 return link_enslaved(link);
1172 if (link->network->bridge) {
1173 log_struct_link(LOG_DEBUG, link,
1174 "MESSAGE=%s: enslaving by '%s'",
1175 link->ifname, link->network->bridge->name,
1176 NETDEV(link->network->bridge),
1179 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1181 log_struct_link(LOG_WARNING, link,
1182 "MESSAGE=%s: could not enslave by '%s': %s",
1183 link->ifname, link->network->bridge->name, strerror(-r),
1184 NETDEV(link->network->bridge),
1186 link_enter_failed(link);
1193 if (link->network->bond) {
1194 log_struct_link(LOG_DEBUG, link,
1195 "MESSAGE=%s: enslaving by '%s'",
1196 link->ifname, link->network->bond->name,
1197 NETDEV(link->network->bond),
1200 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1202 log_struct_link(LOG_WARNING, link,
1203 "MESSAGE=%s: could not enslave by '%s': %s",
1204 link->ifname, link->network->bond->name, strerror(-r),
1205 NETDEV(link->network->bond),
1207 link_enter_failed(link);
1214 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
1215 log_struct_link(LOG_DEBUG, link,
1216 "MESSAGE=%s: enslaving by '%s'",
1217 link->ifname, vlan->name, NETDEV(vlan), NULL);
1219 r = netdev_enslave(vlan, link, &enslave_handler);
1221 log_struct_link(LOG_WARNING, link,
1222 "MESSAGE=%s: could not enslave by '%s': %s",
1223 link->ifname, vlan->name, strerror(-r),
1224 NETDEV(vlan), NULL);
1225 link_enter_failed(link);
1232 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1233 log_struct_link(LOG_DEBUG, link,
1234 "MESSAGE=%s: enslaving by '%s'",
1235 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1237 r = netdev_enslave(macvlan, link, &enslave_handler);
1239 log_struct_link(LOG_WARNING, link,
1240 "MESSAGE=%s: could not enslave by '%s': %s",
1241 link->ifname, macvlan->name, strerror(-r),
1242 NETDEV(macvlan), NULL);
1243 link_enter_failed(link);
1253 static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1255 Link *link = userdata;
1260 if (link->state == LINK_STATE_FAILED)
1263 r = sd_rtnl_message_get_errno(m);
1265 log_struct_link(LOG_ERR, link,
1266 "MESSAGE=%s: could not get state: %s",
1267 link->ifname, strerror(-r),
1270 link_enter_failed(link);
1274 log_debug_link(link, "got link state");
1276 link_update(link, m);
1281 static int link_getlink(Link *link) {
1282 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1286 assert(link->manager);
1287 assert(link->manager->rtnl);
1289 log_debug_link(link, "requesting link status");
1291 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1292 RTM_GETLINK, link->ifindex);
1294 log_error_link(link, "Could not allocate RTM_GETLINK message");
1298 r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
1301 log_error_link(link,
1302 "Could not send rtnetlink message: %s", strerror(-r));
1309 int link_configure(Link *link) {
1313 assert(link->network);
1314 assert(link->state == _LINK_STATE_INVALID);
1316 r = link_getlink(link);
1318 link_enter_failed(link);
1322 return link_enter_enslave(link);
1325 int link_update(Link *link, sd_rtnl_message *m) {
1332 if (link->state == LINK_STATE_FAILED)
1335 r = sd_rtnl_message_link_get_flags(m, &flags);
1337 log_warning_link(link, "Could not get link flags");
1341 if (link->network->dhcp && link->network->dhcp_mtu &&
1342 !link->original_mtu) {
1343 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1345 log_debug_link(link, "saved original MTU: %"
1346 PRIu16, link->original_mtu);
1349 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &link->mac);
1351 log_debug_link(link, "MAC address: "
1352 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1353 link->mac.ether_addr_octet[0],
1354 link->mac.ether_addr_octet[1],
1355 link->mac.ether_addr_octet[2],
1356 link->mac.ether_addr_octet[3],
1357 link->mac.ether_addr_octet[4],
1358 link->mac.ether_addr_octet[5]);
1361 return link_update_flags(link, flags);
1364 int link_save(Link *link) {
1365 _cleanup_free_ char *temp_path = NULL;
1366 _cleanup_fclose_ FILE *f = NULL;
1370 assert(link->state_file);
1372 r = mkdir_safe_label("/run/systemd/network/links", 0755, 0, 0);
1376 r = fopen_temporary(link->state_file, &f, &temp_path);
1380 fchmod(fileno(f), 0644);
1383 "# This is private data. Do not parse.\n"
1385 link_state_to_string(link->state));
1387 if (link->dhcp_lease) {
1388 const char *lease_file = "/run/systemd/network/leases/test.lease";
1390 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1394 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1399 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1401 unlink(link->state_file);
1407 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1412 static const char* const link_state_table[_LINK_STATE_MAX] = {
1413 [LINK_STATE_ENSLAVING] = "configuring",
1414 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1415 [LINK_STATE_SETTING_ROUTES] = "configuring",
1416 [LINK_STATE_CONFIGURED] = "configured",
1417 [LINK_STATE_FAILED] = "failed",
1420 DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);