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;
582 _cleanup_route_free_ Route *route_gw = NULL;
583 _cleanup_route_free_ Route *route = NULL;
585 struct in_addr netmask;
586 struct in_addr gateway;
591 assert(link->dhcp_lease);
593 log_warning_link(link, "DHCP lease lost");
595 r = address_new_dynamic(&address);
597 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
598 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
599 sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
600 prefixlen = net_netmask_to_prefixlen(&netmask);
602 r = route_new_dynamic(&route_gw);
604 route_gw->family = AF_INET;
605 route_gw->dst_addr.in = gateway;
606 route_gw->dst_prefixlen = 32;
607 route_gw->scope = RT_SCOPE_LINK;
609 route_drop(route_gw, link, &route_drop_handler);
612 r = route_new_dynamic(&route);
614 route->family = AF_INET;
615 route->in_addr.in = gateway;
617 route_drop(route, link, &route_drop_handler);
620 address->family = AF_INET;
621 address->in_addr.in = addr;
622 address->prefixlen = prefixlen;
624 address_drop(address, link, &address_drop_handler);
627 if (link->network->dhcp_mtu) {
630 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
631 if (r >= 0 && link->original_mtu != mtu) {
632 r = link_set_mtu(link, link->original_mtu);
634 log_warning_link(link, "DHCP error: could not reset MTU");
635 link_enter_failed(link);
641 if (link->network->dhcp_hostname) {
642 const char *hostname = NULL;
644 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
645 if (r >= 0 && hostname) {
646 r = set_hostname(link->manager->bus, "");
648 log_error("Failed to reset transient hostname");
652 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
657 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
658 sd_dhcp_lease *lease;
659 struct in_addr address;
660 struct in_addr netmask;
661 struct in_addr gateway;
663 struct in_addr *nameservers;
664 size_t nameservers_size;
670 r = sd_dhcp_client_get_lease(client, &lease);
672 log_warning_link(link, "DHCP error: no lease: %s",
677 r = sd_dhcp_lease_get_address(lease, &address);
679 log_warning_link(link, "DHCP error: no address: %s",
684 r = sd_dhcp_lease_get_netmask(lease, &netmask);
686 log_warning_link(link, "DHCP error: no netmask: %s",
691 prefixlen = net_netmask_to_prefixlen(&netmask);
693 r = sd_dhcp_lease_get_router(lease, &gateway);
695 log_warning_link(link, "DHCP error: no router: %s",
700 log_struct_link(LOG_INFO, link,
701 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
703 ADDRESS_FMT_VAL(address),
705 ADDRESS_FMT_VAL(gateway),
706 "ADDRESS=%u.%u.%u.%u",
707 ADDRESS_FMT_VAL(address),
710 "GATEWAY=%u.%u.%u.%u",
711 ADDRESS_FMT_VAL(gateway),
714 link->dhcp_lease = lease;
716 if (link->network->dhcp_dns) {
717 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
719 r = manager_update_resolv_conf(link->manager);
721 log_error("Failed to update resolv.conf");
725 if (link->network->dhcp_mtu) {
728 r = sd_dhcp_lease_get_mtu(lease, &mtu);
730 r = link_set_mtu(link, mtu);
732 log_error_link(link, "Failed to set MTU "
737 if (link->network->dhcp_hostname) {
738 const char *hostname;
740 r = sd_dhcp_lease_get_hostname(lease, &hostname);
742 r = set_hostname(link->manager->bus, hostname);
744 log_error("Failed to set transient hostname "
745 "to '%s'", hostname);
749 link_enter_set_addresses(link);
754 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
755 Link *link = userdata;
759 assert(link->network);
760 assert(link->manager);
762 if (link->state == LINK_STATE_FAILED)
766 case DHCP_EVENT_NO_LEASE:
767 log_debug_link(link, "IP address in use.");
769 case DHCP_EVENT_EXPIRED:
770 case DHCP_EVENT_STOP:
771 case DHCP_EVENT_IP_CHANGE:
772 if (link->network->dhcp_critical) {
773 log_error_link(link, "DHCPv4 connection considered system critical, "
774 "ignoring request to reconfigure it.");
778 if (link->dhcp_lease) {
779 r = dhcp_lease_lost(link);
781 link_enter_failed(link);
786 if (event == DHCP_EVENT_IP_CHANGE) {
787 r = dhcp_lease_acquired(client, link);
789 link_enter_failed(link);
794 if (event == DHCP_EVENT_EXPIRED && link->network->ipv4ll) {
795 r = sd_ipv4ll_start (link->ipv4ll);
797 link_enter_failed(link);
803 case DHCP_EVENT_IP_ACQUIRE:
804 r = dhcp_lease_acquired(client, link);
806 link_enter_failed(link);
810 r = sd_ipv4ll_stop(link->ipv4ll);
812 link_enter_failed(link);
819 log_warning_link(link, "DHCP error: %s", strerror(-event));
821 log_warning_link(link, "DHCP unknown event: %d", event);
828 static int ipv4ll_address_lost(sd_ipv4ll *ll, Link *link) {
835 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
837 _cleanup_address_free_ Address *address = NULL;
838 _cleanup_route_free_ Route *route = NULL;
840 log_debug_link(link, "IPv4 link-local release %u.%u.%u.%u",
841 ADDRESS_FMT_VAL(addr));
843 r = address_new_dynamic(&address);
845 log_error_link(link, "Could not allocate address: %s", strerror(-r));
849 address->family = AF_INET;
850 address->in_addr.in = addr;
851 address->prefixlen = 16;
852 address->scope = RT_SCOPE_LINK;
854 address_drop(address, link, &address_drop_handler);
856 r = route_new_dynamic(&route);
858 log_error_link(link, "Could not allocate route: %s",
863 route->family = AF_INET;
864 route->scope = RT_SCOPE_LINK;
867 route_drop(route, link, &route_drop_handler);
873 static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
874 struct in_addr address;
880 r = sd_ipv4ll_get_address(ll, &address);
884 log_struct_link(LOG_INFO, link,
885 "MESSAGE=%s: IPv4 link-local address %u.%u.%u.%u",
887 ADDRESS_FMT_VAL(address),
890 link_enter_set_addresses(link);
895 static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
896 Link *link = userdata;
900 assert(link->network);
901 assert(link->manager);
904 case IPV4LL_EVENT_STOP:
905 case IPV4LL_EVENT_CONFLICT:
906 r = ipv4ll_address_lost(ll, link);
908 link_enter_failed(link);
912 case IPV4LL_EVENT_BIND:
913 r = ipv4ll_address_claimed(ll, link);
915 link_enter_failed(link);
921 log_warning_link(link, "IPv4 link-local error: %s", strerror(-event));
923 log_warning_link(link, "IPv4 link-local unknown event: %d", event);
928 static int link_acquire_conf(Link *link) {
932 assert(link->network);
933 assert(link->manager);
934 assert(link->manager->event);
936 if (link->network->ipv4ll) {
937 assert(link->ipv4ll);
939 log_debug_link(link, "acquiring IPv4 link-local address");
941 r = sd_ipv4ll_start(link->ipv4ll);
946 if (link->network->dhcp) {
947 assert(link->dhcp_client);
949 log_debug_link(link, "acquiring DHCPv4 lease");
951 r = sd_dhcp_client_start(link->dhcp_client);
959 static int link_update_flags(Link *link, unsigned flags) {
963 assert(link->network);
965 if (link->state == LINK_STATE_FAILED)
968 if (link->flags == flags)
971 log_debug_link(link, "link status updated: %#.8x -> %#.8x",
974 if ((link->flags & IFF_UP) != (flags & IFF_UP))
976 "link is %s", flags & IFF_UP ? "up": "down");
978 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
979 if (flags & IFF_LOWER_UP) {
980 log_info_link(link, "carrier on");
982 if (link->network->dhcp || link->network->ipv4ll) {
983 r = link_acquire_conf(link);
985 log_warning_link(link, "Could not acquire configuration: %s", strerror(-r));
986 link_enter_failed(link);
991 log_info_link(link, "carrier off");
993 if (link->network->dhcp) {
994 r = sd_dhcp_client_stop(link->dhcp_client);
996 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
997 link_enter_failed(link);
1002 if (link->network->ipv4ll) {
1003 r = sd_ipv4ll_stop(link->ipv4ll);
1005 log_warning_link(link, "Could not stop IPv4 link-local: %s", strerror(-r));
1006 link_enter_failed(link);
1013 link->flags = flags;
1018 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1019 Link *link = userdata;
1024 if (link->state == LINK_STATE_FAILED)
1027 r = sd_rtnl_message_get_errno(m);
1029 link_update_flags(link, link->flags | IFF_UP);
1031 log_struct_link(LOG_WARNING, link,
1032 "MESSAGE=%s: could not bring up interface: %s",
1033 link->ifname, strerror(-r),
1039 static int link_up(Link *link) {
1040 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1044 assert(link->manager);
1045 assert(link->manager->rtnl);
1047 log_debug_link(link, "bringing link up");
1049 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1050 RTM_SETLINK, link->ifindex);
1052 log_error_link(link, "Could not allocate RTM_SETLINK message");
1056 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
1058 log_error_link(link, "Could not set link flags: %s", strerror(-r));
1062 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
1064 log_error_link(link,
1065 "Could not send rtnetlink message: %s", strerror(-r));
1072 static int link_enslaved(Link *link) {
1076 assert(link->state == LINK_STATE_ENSLAVING);
1077 assert(link->network);
1081 link_enter_failed(link);
1085 if (!link->network->dhcp && !link->network->ipv4ll)
1086 return link_enter_set_addresses(link);
1091 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1092 Link *link = userdata;
1096 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
1097 assert(link->network);
1101 if (link->state == LINK_STATE_FAILED)
1104 r = sd_rtnl_message_get_errno(m);
1106 log_struct_link(LOG_ERR, link,
1107 "MESSAGE=%s: could not enslave: %s",
1108 link->ifname, strerror(-r),
1111 link_enter_failed(link);
1115 log_debug_link(link, "enslaved");
1117 if (link->enslaving == 0)
1118 link_enslaved(link);
1123 static int link_enter_enslave(Link *link) {
1124 NetDev *vlan, *macvlan;
1129 assert(link->network);
1130 assert(link->state == _LINK_STATE_INVALID);
1132 link->state = LINK_STATE_ENSLAVING;
1136 if (!link->network->bridge && !link->network->bond &&
1137 hashmap_isempty(link->network->vlans) &&
1138 hashmap_isempty(link->network->macvlans))
1139 return link_enslaved(link);
1141 if (link->network->bridge) {
1142 log_struct_link(LOG_DEBUG, link,
1143 "MESSAGE=%s: enslaving by '%s'",
1144 link->ifname, link->network->bridge->name,
1145 NETDEV(link->network->bridge),
1148 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1150 log_struct_link(LOG_WARNING, link,
1151 "MESSAGE=%s: could not enslave by '%s': %s",
1152 link->ifname, link->network->bridge->name, strerror(-r),
1153 NETDEV(link->network->bridge),
1155 link_enter_failed(link);
1162 if (link->network->bond) {
1163 log_struct_link(LOG_DEBUG, link,
1164 "MESSAGE=%s: enslaving by '%s'",
1165 link->ifname, link->network->bond->name,
1166 NETDEV(link->network->bond),
1169 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1171 log_struct_link(LOG_WARNING, link,
1172 "MESSAGE=%s: could not enslave by '%s': %s",
1173 link->ifname, link->network->bond->name, strerror(-r),
1174 NETDEV(link->network->bond),
1176 link_enter_failed(link);
1183 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
1184 log_struct_link(LOG_DEBUG, link,
1185 "MESSAGE=%s: enslaving by '%s'",
1186 link->ifname, vlan->name, NETDEV(vlan), NULL);
1188 r = netdev_enslave(vlan, link, &enslave_handler);
1190 log_struct_link(LOG_WARNING, link,
1191 "MESSAGE=%s: could not enslave by '%s': %s",
1192 link->ifname, vlan->name, strerror(-r),
1193 NETDEV(vlan), NULL);
1194 link_enter_failed(link);
1201 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1202 log_struct_link(LOG_DEBUG, link,
1203 "MESSAGE=%s: enslaving by '%s'",
1204 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1206 r = netdev_enslave(macvlan, link, &enslave_handler);
1208 log_struct_link(LOG_WARNING, link,
1209 "MESSAGE=%s: could not enslave by '%s': %s",
1210 link->ifname, macvlan->name, strerror(-r),
1211 NETDEV(macvlan), NULL);
1212 link_enter_failed(link);
1222 static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1224 Link *link = userdata;
1229 if (link->state == LINK_STATE_FAILED)
1232 r = sd_rtnl_message_get_errno(m);
1234 log_struct_link(LOG_ERR, link,
1235 "MESSAGE=%s: could not get state: %s",
1236 link->ifname, strerror(-r),
1239 link_enter_failed(link);
1243 link_update(link, m);
1248 static int link_getlink(Link *link) {
1249 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1253 assert(link->manager);
1254 assert(link->manager->rtnl);
1256 log_debug_link(link, "requesting link status");
1258 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1259 RTM_GETLINK, link->ifindex);
1261 log_error_link(link, "Could not allocate RTM_GETLINK message");
1265 r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
1268 log_error_link(link,
1269 "Could not send rtnetlink message: %s", strerror(-r));
1276 static int link_configure(Link *link) {
1280 assert(link->state == _LINK_STATE_INVALID);
1282 r = link_getlink(link);
1286 return link_enter_enslave(link);
1289 int link_add(Manager *m, struct udev_device *device, Link **ret) {
1297 r = link_new(m, device, &link);
1303 r = network_get(m, device, &network);
1305 return r == -ENOENT ? 0 : r;
1307 r = network_apply(m, network, link);
1311 if (link->network->ipv4ll) {
1313 r = sd_ipv4ll_new(&link->ipv4ll);
1317 r = net_get_unique_predictable_data(link->udev_device, seed);
1319 r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
1324 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
1328 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
1332 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
1337 if (link->network->dhcp) {
1338 r = sd_dhcp_client_new(&link->dhcp_client);
1342 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
1346 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
1350 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
1354 if (link->network->dhcp_mtu) {
1355 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
1361 r = link_configure(link);
1368 int link_update(Link *link, sd_rtnl_message *m) {
1370 struct ether_addr mac;
1374 assert(link->network);
1377 if (link->state == LINK_STATE_FAILED)
1380 if (link->network->dhcp && link->network->dhcp_mtu &&
1381 !link->original_mtu) {
1382 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1384 log_debug_link(link, "saved original MTU: %"
1385 PRIu16, link->original_mtu);
1388 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
1390 log_debug_link(link, "Could not get MAC address: %s", strerror(-r));
1392 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) {
1394 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
1396 log_debug_link(link, "MAC address: "
1397 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1398 mac.ether_addr_octet[0],
1399 mac.ether_addr_octet[1],
1400 mac.ether_addr_octet[2],
1401 mac.ether_addr_octet[3],
1402 mac.ether_addr_octet[4],
1403 mac.ether_addr_octet[5]);
1406 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1408 log_warning_link(link, "Could not update MAC "
1409 "address in IPv4LL client: %s",
1415 if (link->dhcp_client) {
1416 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1418 log_warning_link(link, "Could not update MAC "
1419 "address in DHCP client: %s",
1427 r = sd_rtnl_message_link_get_flags(m, &flags);
1429 log_warning_link(link, "Could not get link flags");
1433 return link_update_flags(link, flags);
1436 int link_save(Link *link) {
1437 _cleanup_free_ char *temp_path = NULL;
1438 _cleanup_fclose_ FILE *f = NULL;
1442 assert(link->state_file);
1444 r = fopen_temporary(link->state_file, &f, &temp_path);
1448 fchmod(fileno(f), 0644);
1451 "# This is private data. Do not parse.\n"
1453 link_state_to_string(link->state));
1455 if (link->dhcp_lease) {
1456 _cleanup_free_ char *lease_file = NULL;
1458 r = asprintf(&lease_file, "/run/systemd/network/leases/%"PRIu64,
1463 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1467 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1472 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1474 unlink(link->state_file);
1480 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1485 static const char* const link_state_table[_LINK_STATE_MAX] = {
1486 [LINK_STATE_ENSLAVING] = "configuring",
1487 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1488 [LINK_STATE_SETTING_ROUTES] = "configuring",
1489 [LINK_STATE_CONFIGURED] = "configured",
1490 [LINK_STATE_FAILED] = "failed",
1493 DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);