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_WARNING, link,
1061 "MESSAGE=%s: could not bring up interface: %s",
1062 link->ifname, strerror(-r),
1067 link_update_flags(link, link->flags | IFF_UP);
1072 static int link_up(Link *link) {
1073 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1077 assert(link->manager);
1078 assert(link->manager->rtnl);
1080 log_debug_link(link, "bringing link up");
1082 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1083 RTM_SETLINK, link->ifindex);
1085 log_error_link(link, "Could not allocate RTM_SETLINK message");
1089 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
1091 log_error_link(link, "Could not set link flags: %s", strerror(-r));
1095 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
1097 log_error_link(link,
1098 "Could not send rtnetlink message: %s", strerror(-r));
1105 static int link_enslaved(Link *link) {
1109 assert(link->state == LINK_STATE_ENSLAVING);
1110 assert(link->network);
1114 link_enter_failed(link);
1118 if (!link->network->dhcp && !link->network->ipv4ll)
1119 return link_enter_set_addresses(link);
1124 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1125 Link *link = userdata;
1129 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
1130 assert(link->network);
1134 if (link->state == LINK_STATE_FAILED)
1137 r = sd_rtnl_message_get_errno(m);
1139 log_struct_link(LOG_ERR, link,
1140 "MESSAGE=%s: could not enslave: %s",
1141 link->ifname, strerror(-r),
1144 link_enter_failed(link);
1148 log_debug_link(link, "enslaved");
1150 if (link->enslaving == 0)
1151 link_enslaved(link);
1156 static int link_enter_enslave(Link *link) {
1157 NetDev *vlan, *macvlan;
1162 assert(link->network);
1163 assert(link->state == _LINK_STATE_INVALID);
1165 link->state = LINK_STATE_ENSLAVING;
1169 if (!link->network->bridge && !link->network->bond &&
1170 hashmap_isempty(link->network->vlans) &&
1171 hashmap_isempty(link->network->macvlans))
1172 return link_enslaved(link);
1174 if (link->network->bridge) {
1175 log_struct_link(LOG_DEBUG, link,
1176 "MESSAGE=%s: enslaving by '%s'",
1177 link->ifname, link->network->bridge->name,
1178 NETDEV(link->network->bridge),
1181 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1183 log_struct_link(LOG_WARNING, link,
1184 "MESSAGE=%s: could not enslave by '%s': %s",
1185 link->ifname, link->network->bridge->name, strerror(-r),
1186 NETDEV(link->network->bridge),
1188 link_enter_failed(link);
1195 if (link->network->bond) {
1196 log_struct_link(LOG_DEBUG, link,
1197 "MESSAGE=%s: enslaving by '%s'",
1198 link->ifname, link->network->bond->name,
1199 NETDEV(link->network->bond),
1202 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1204 log_struct_link(LOG_WARNING, link,
1205 "MESSAGE=%s: could not enslave by '%s': %s",
1206 link->ifname, link->network->bond->name, strerror(-r),
1207 NETDEV(link->network->bond),
1209 link_enter_failed(link);
1216 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
1217 log_struct_link(LOG_DEBUG, link,
1218 "MESSAGE=%s: enslaving by '%s'",
1219 link->ifname, vlan->name, NETDEV(vlan), NULL);
1221 r = netdev_enslave(vlan, link, &enslave_handler);
1223 log_struct_link(LOG_WARNING, link,
1224 "MESSAGE=%s: could not enslave by '%s': %s",
1225 link->ifname, vlan->name, strerror(-r),
1226 NETDEV(vlan), NULL);
1227 link_enter_failed(link);
1234 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1235 log_struct_link(LOG_DEBUG, link,
1236 "MESSAGE=%s: enslaving by '%s'",
1237 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1239 r = netdev_enslave(macvlan, link, &enslave_handler);
1241 log_struct_link(LOG_WARNING, link,
1242 "MESSAGE=%s: could not enslave by '%s': %s",
1243 link->ifname, macvlan->name, strerror(-r),
1244 NETDEV(macvlan), NULL);
1245 link_enter_failed(link);
1255 static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1257 Link *link = userdata;
1262 if (link->state == LINK_STATE_FAILED)
1265 r = sd_rtnl_message_get_errno(m);
1267 log_struct_link(LOG_ERR, link,
1268 "MESSAGE=%s: could not get state: %s",
1269 link->ifname, strerror(-r),
1272 link_enter_failed(link);
1276 log_debug_link(link, "got link state");
1278 link_update(link, m);
1283 static int link_getlink(Link *link) {
1284 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1288 assert(link->manager);
1289 assert(link->manager->rtnl);
1291 log_debug_link(link, "requesting link status");
1293 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1294 RTM_GETLINK, link->ifindex);
1296 log_error_link(link, "Could not allocate RTM_GETLINK message");
1300 r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
1303 log_error_link(link,
1304 "Could not send rtnetlink message: %s", strerror(-r));
1311 int link_configure(Link *link) {
1315 assert(link->network);
1316 assert(link->state == _LINK_STATE_INVALID);
1318 r = link_getlink(link);
1320 link_enter_failed(link);
1324 return link_enter_enslave(link);
1327 int link_update(Link *link, sd_rtnl_message *m) {
1334 if (link->state == LINK_STATE_FAILED)
1337 r = sd_rtnl_message_link_get_flags(m, &flags);
1339 log_warning_link(link, "Could not get link flags");
1343 if (link->network->dhcp && link->network->dhcp_mtu &&
1344 !link->original_mtu) {
1345 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1347 log_debug_link(link, "saved original MTU: %"
1348 PRIu16, link->original_mtu);
1351 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &link->mac);
1353 log_debug_link(link, "MAC address: "
1354 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1355 link->mac.ether_addr_octet[0],
1356 link->mac.ether_addr_octet[1],
1357 link->mac.ether_addr_octet[2],
1358 link->mac.ether_addr_octet[3],
1359 link->mac.ether_addr_octet[4],
1360 link->mac.ether_addr_octet[5]);
1363 return link_update_flags(link, flags);
1366 int link_save(Link *link) {
1367 _cleanup_free_ char *temp_path = NULL;
1368 _cleanup_fclose_ FILE *f = NULL;
1372 assert(link->state_file);
1374 r = mkdir_safe_label("/run/systemd/network/links", 0755, 0, 0);
1378 r = fopen_temporary(link->state_file, &f, &temp_path);
1382 fchmod(fileno(f), 0644);
1385 "# This is private data. Do not parse.\n"
1387 link_state_to_string(link->state));
1389 if (link->dhcp_lease) {
1390 const char *lease_file = "/run/systemd/network/leases/test.lease";
1392 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1396 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1401 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1403 unlink(link->state_file);
1409 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1414 static const char* const link_state_table[_LINK_STATE_MAX] = {
1415 [LINK_STATE_ENSLAVING] = "configuring",
1416 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1417 [LINK_STATE_SETTING_ROUTES] = "configuring",
1418 [LINK_STATE_CONFIGURED] = "configured",
1419 [LINK_STATE_FAILED] = "failed",
1422 DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);