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 int link_new(Manager *manager, struct udev_device *device, Link **ret) {
32 _cleanup_link_free_ Link *link = NULL;
34 struct ether_addr *mac_addr;
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 mac = udev_device_get_sysattr_value(device, "address");
56 mac_addr = ether_aton(mac);
58 memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
61 ifname = udev_device_get_sysname(device);
62 link->ifname = strdup(ifname);
64 r = hashmap_put(manager->links, &link->ifindex, link);
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 hashmap_remove(link->manager->links, &link->ifindex);
90 int link_get(Manager *m, int ifindex, Link **ret) {
100 link = hashmap_get(m->links, &ifindex_64);
109 int link_add(Manager *m, struct udev_device *device, Link **ret) {
117 r = link_new(m, device, &link);
123 r = network_get(m, device, &network);
125 return r == -ENOENT ? 0 : r;
127 r = network_apply(m, network, link);
134 static int link_enter_configured(Link *link) {
136 assert(link->state == LINK_STATE_SETTING_ROUTES);
138 log_info_link(link, "link configured");
140 link->state = LINK_STATE_CONFIGURED;
145 static void link_enter_failed(Link *link) {
148 log_warning_link(link, "failed");
150 link->state = LINK_STATE_FAILED;
153 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
154 Link *link = userdata;
157 assert(link->route_messages > 0);
158 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
159 link->state == LINK_STATE_SETTING_ROUTES ||
160 link->state == LINK_STATE_FAILED);
162 link->route_messages --;
164 if (link->state == LINK_STATE_FAILED)
167 r = sd_rtnl_message_get_errno(m);
168 if (r < 0 && r != -EEXIST)
169 log_struct_link(LOG_WARNING, link,
170 "MESSAGE=%s: could not set route: %s",
171 link->ifname, strerror(-r),
175 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
177 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
178 log_debug_link(link, "routes set");
179 link_enter_configured(link);
185 static int link_enter_set_routes(Link *link) {
190 assert(link->network);
191 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
193 link->state = LINK_STATE_SETTING_ROUTES;
195 if (!link->network->static_routes && !link->dhcp_lease)
196 return link_enter_configured(link);
198 log_debug_link(link, "setting routes");
200 LIST_FOREACH(static_routes, rt, link->network->static_routes) {
201 r = route_configure(rt, link, &route_handler);
203 log_warning_link(link,
204 "could not set routes: %s", strerror(-r));
205 link_enter_failed(link);
209 link->route_messages ++;
212 if (link->dhcp_lease) {
213 _cleanup_route_free_ Route *route = NULL;
214 struct in_addr gateway;
216 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
218 log_warning_link(link, "DHCP error: no router: %s",
223 r = route_new_dynamic(&route);
225 log_error_link(link, "Could not allocate route: %s",
230 route->family = AF_INET;
231 route->in_addr.in = gateway;
233 r = route_configure(route, link, &route_handler);
235 log_warning_link(link,
236 "could not set routes: %s", strerror(-r));
237 link_enter_failed(link);
241 link->route_messages ++;
247 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
248 Link *link = userdata;
253 assert(link->ifname);
254 assert(link->addr_messages > 0);
255 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
257 link->addr_messages --;
259 if (link->state == LINK_STATE_FAILED)
262 r = sd_rtnl_message_get_errno(m);
263 if (r < 0 && r != -EEXIST)
264 log_struct_link(LOG_WARNING, link,
265 "MESSAGE=%s: could not set address: %s",
266 link->ifname, strerror(-r),
270 if (link->addr_messages == 0) {
271 log_debug_link(link, "addresses set");
272 link_enter_set_routes(link);
278 static int link_enter_set_addresses(Link *link) {
283 assert(link->network);
284 assert(link->state != _LINK_STATE_INVALID);
286 link->state = LINK_STATE_SETTING_ADDRESSES;
288 if (!link->network->static_addresses && !link->dhcp_lease)
289 return link_enter_set_routes(link);
291 log_debug_link(link, "setting addresses");
293 LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
294 r = address_configure(ad, link, &address_handler);
296 log_warning_link(link,
297 "could not set addresses: %s", strerror(-r));
298 link_enter_failed(link);
302 link->addr_messages ++;
305 if (link->dhcp_lease) {
306 _cleanup_address_free_ Address *address = NULL;
308 struct in_addr netmask;
311 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
313 log_warning_link(link, "DHCP error: no address: %s",
318 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
320 log_warning_link(link, "DHCP error: no netmask: %s",
325 prefixlen = net_netmask_to_prefixlen(&netmask);
327 r = address_new_dynamic(&address);
329 log_error_link(link, "Could not allocate address: %s",
334 address->family = AF_INET;
335 address->in_addr.in = addr;
336 address->prefixlen = prefixlen;
337 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
339 r = address_configure(address, link, &address_handler);
341 log_warning_link(link,
342 "could not set addresses: %s", strerror(-r));
343 link_enter_failed(link);
347 link->addr_messages ++;
353 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
354 Link *link = userdata;
359 assert(link->ifname);
361 if (link->state == LINK_STATE_FAILED)
364 r = sd_rtnl_message_get_errno(m);
365 if (r < 0 && r != -ENOENT)
366 log_struct_link(LOG_WARNING, link,
367 "MESSAGE=%s: could not drop address: %s",
368 link->ifname, strerror(-r),
375 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
378 r = sd_bus_message_get_errno(m);
380 log_warning("Could not set hostname: %s", strerror(-r));
385 static int set_hostname(sd_bus *bus, const char *hostname) {
386 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
391 log_debug("Setting transient hostname: '%s'", hostname);
393 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
394 log_info("Not connected to system bus, ignoring transient hostname.");
398 r = sd_bus_message_new_method_call(
401 "org.freedesktop.hostname1",
402 "/org/freedesktop/hostname1",
403 "org.freedesktop.hostname1",
408 r = sd_bus_message_append(m, "sb", hostname, false);
412 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
414 log_error("Could not set transient hostname: %s", strerror(-r));
419 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
420 Link *link = userdata;
425 assert(link->ifname);
427 if (link->state == LINK_STATE_FAILED)
430 r = sd_rtnl_message_get_errno(m);
432 log_struct_link(LOG_WARNING, link,
433 "MESSAGE=%s: could not set MTU: %s",
434 link->ifname, strerror(-r),
441 static int link_set_mtu(Link *link, uint32_t mtu) {
442 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
446 assert(link->manager);
447 assert(link->manager->rtnl);
449 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
451 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
452 RTM_SETLINK, link->ifindex);
454 log_error_link(link, "Could not allocate RTM_SETLINK message");
458 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
460 log_error_link(link, "Could not append MTU: %s", strerror(-r));
464 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
467 "Could not send rtnetlink message: %s", strerror(-r));
474 static int dhcp_lease_lost(Link *link) {
475 _cleanup_address_free_ Address *address = NULL;
477 struct in_addr netmask;
482 assert(link->dhcp_lease);
484 log_warning_link(link, "DHCP lease lost");
486 r = address_new_dynamic(&address);
488 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
489 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
490 prefixlen = net_netmask_to_prefixlen(&netmask);
492 address->family = AF_INET;
493 address->in_addr.in = addr;
494 address->prefixlen = prefixlen;
496 address_drop(address, link, address_drop_handler);
499 if (link->network->dhcp_mtu) {
502 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
503 if (r >= 0 && link->original_mtu != mtu) {
504 r = link_set_mtu(link, link->original_mtu);
506 log_warning_link(link, "DHCP error: could not reset MTU");
507 link_enter_failed(link);
513 if (link->network->dhcp_hostname) {
514 const char *hostname = NULL;
516 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
517 if (r >= 0 && hostname) {
518 r = set_hostname(link->manager->bus, "");
520 log_error("Failed to reset transient hostname");
524 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
529 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
530 sd_dhcp_lease *lease;
531 struct in_addr address;
532 struct in_addr netmask;
533 struct in_addr gateway;
535 struct in_addr *nameservers;
536 size_t nameservers_size;
542 r = sd_dhcp_client_get_lease(client, &lease);
544 log_warning_link(link, "DHCP error: no lease: %s",
549 r = sd_dhcp_lease_get_address(lease, &address);
551 log_warning_link(link, "DHCP error: no address: %s",
556 r = sd_dhcp_lease_get_netmask(lease, &netmask);
558 log_warning_link(link, "DHCP error: no netmask: %s",
563 prefixlen = net_netmask_to_prefixlen(&netmask);
565 r = sd_dhcp_lease_get_router(lease, &gateway);
567 log_warning_link(link, "DHCP error: no router: %s",
572 log_struct_link(LOG_INFO, link,
573 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
575 ADDRESS_FMT_VAL(address),
577 ADDRESS_FMT_VAL(gateway),
578 "ADDRESS=%u.%u.%u.%u",
579 ADDRESS_FMT_VAL(address),
582 "GATEWAY=%u.%u.%u.%u",
583 ADDRESS_FMT_VAL(gateway),
586 link->dhcp_lease = lease;
588 if (link->network->dhcp_dns) {
589 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
591 r = manager_update_resolv_conf(link->manager);
593 log_error("Failed to update resolv.conf");
597 if (link->network->dhcp_mtu) {
600 r = sd_dhcp_lease_get_mtu(lease, &mtu);
602 r = link_set_mtu(link, mtu);
604 log_error_link(link, "Failed to set MTU "
609 if (link->network->dhcp_hostname) {
610 const char *hostname;
612 r = sd_dhcp_lease_get_hostname(lease, &hostname);
614 r = set_hostname(link->manager->bus, hostname);
616 log_error("Failed to set transient hostname "
617 "to '%s'", hostname);
621 link_enter_set_addresses(link);
626 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
627 Link *link = userdata;
631 assert(link->network);
632 assert(link->manager);
634 if (link->state == LINK_STATE_FAILED)
638 case DHCP_EVENT_NO_LEASE:
639 log_debug_link(link, "IP address in use.");
641 case DHCP_EVENT_EXPIRED:
642 case DHCP_EVENT_STOP:
643 case DHCP_EVENT_IP_CHANGE:
644 if (link->network->dhcp_critical) {
645 log_error_link(link, "DHCPv4 connection considered system critical, "
646 "ignoring request to reconfigure it.");
650 if (link->dhcp_lease) {
651 r = dhcp_lease_lost(link);
653 link_enter_failed(link);
658 if (event == DHCP_EVENT_IP_CHANGE) {
659 r = dhcp_lease_acquired(client, link);
661 link_enter_failed(link);
667 case DHCP_EVENT_IP_ACQUIRE:
668 r = dhcp_lease_acquired(client, link);
670 link_enter_failed(link);
676 log_warning_link(link, "DHCP error: %s", strerror(-event));
678 log_warning_link(link, "DHCP unknown event: %d", event);
685 static int link_acquire_conf(Link *link) {
689 assert(link->network);
690 assert(link->network->dhcp);
691 assert(link->manager);
692 assert(link->manager->event);
694 if (!link->dhcp_client) {
695 r = sd_dhcp_client_new(&link->dhcp_client);
699 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
703 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
707 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
711 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
715 if (link->network->dhcp_mtu) {
716 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
722 log_debug_link(link, "acquiring DHCPv4 lease");
724 r = sd_dhcp_client_start(link->dhcp_client);
731 static int link_update_flags(Link *link, unsigned flags) {
735 assert(link->network);
737 if (link->state == LINK_STATE_FAILED)
740 if (link->flags == flags) {
741 log_debug_link(link, "link status unchanged: %#.8x", flags);
745 if ((link->flags & IFF_UP) != (flags & IFF_UP))
747 "link is %s", flags & IFF_UP ? "up": "down");
749 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
750 if (flags & IFF_LOWER_UP) {
751 log_info_link(link, "carrier on");
753 if (link->network->dhcp) {
754 r = link_acquire_conf(link);
756 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
757 link_enter_failed(link);
762 log_info_link(link, "carrier off");
764 if (link->network->dhcp) {
765 r = sd_dhcp_client_stop(link->dhcp_client);
767 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
768 link_enter_failed(link);
776 "link status updated: %#.8x -> %#.8x", link->flags, flags);
783 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
784 Link *link = userdata;
789 if (link->state == LINK_STATE_FAILED)
792 r = sd_rtnl_message_get_errno(m);
794 log_struct_link(LOG_ERR, link,
795 "MESSAGE=%s: could not bring up interface: %s",
796 link->ifname, strerror(-r),
799 link_enter_failed(link);
803 link_update_flags(link, link->flags | IFF_UP);
808 static int link_up(Link *link) {
809 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
813 assert(link->manager);
814 assert(link->manager->rtnl);
816 log_debug_link(link, "bringing link up");
818 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
819 RTM_SETLINK, link->ifindex);
821 log_error_link(link, "Could not allocate RTM_SETLINK message");
825 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
827 log_error_link(link, "Could not set link flags: %s", strerror(-r));
831 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
834 "Could not send rtnetlink message: %s", strerror(-r));
841 static int link_enslaved(Link *link) {
845 assert(link->state == LINK_STATE_ENSLAVING);
846 assert(link->network);
850 link_enter_failed(link);
854 if (!link->network->dhcp)
855 return link_enter_set_addresses(link);
860 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
861 Link *link = userdata;
865 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
866 assert(link->network);
870 if (link->state == LINK_STATE_FAILED)
873 r = sd_rtnl_message_get_errno(m);
875 log_struct_link(LOG_ERR, link,
876 "MESSAGE=%s: could not enslave: %s",
877 link->ifname, strerror(-r),
880 link_enter_failed(link);
884 log_debug_link(link, "enslaved");
886 if (link->enslaving == 0)
892 static int link_enter_enslave(Link *link) {
893 NetDev *vlan, *macvlan;
898 assert(link->network);
899 assert(link->state == _LINK_STATE_INVALID);
901 link->state = LINK_STATE_ENSLAVING;
903 if (!link->network->bridge && !link->network->bond &&
904 hashmap_isempty(link->network->vlans) &&
905 hashmap_isempty(link->network->macvlans))
906 return link_enslaved(link);
908 if (link->network->bridge) {
909 log_struct_link(LOG_DEBUG, link,
910 "MESSAGE=%s: enslaving by '%s'",
911 link->ifname, link->network->bridge->name,
912 NETDEV(link->network->bridge),
915 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
917 log_struct_link(LOG_WARNING, link,
918 "MESSAGE=%s: could not enslave by '%s': %s",
919 link->ifname, link->network->bridge->name, strerror(-r),
920 NETDEV(link->network->bridge),
922 link_enter_failed(link);
929 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
930 log_struct_link(LOG_DEBUG, link,
931 "MESSAGE=%s: enslaving by '%s'",
932 link->ifname, vlan->name, NETDEV(vlan), NULL);
934 r = netdev_enslave(vlan, link, &enslave_handler);
936 log_struct_link(LOG_WARNING, link,
937 "MESSAGE=%s: could not enslave by '%s': %s",
938 link->ifname, vlan->name, strerror(-r),
940 link_enter_failed(link);
947 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
948 log_struct_link(LOG_DEBUG, link,
949 "MESSAGE=%s: enslaving by '%s'",
950 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
952 r = netdev_enslave(macvlan, link, &enslave_handler);
954 log_struct_link(LOG_WARNING, link,
955 "MESSAGE=%s: could not enslave by '%s': %s",
956 link->ifname, macvlan->name, strerror(-r),
957 NETDEV(macvlan), NULL);
958 link_enter_failed(link);
968 static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
970 Link *link = userdata;
975 if (link->state == LINK_STATE_FAILED)
978 r = sd_rtnl_message_get_errno(m);
980 log_struct_link(LOG_ERR, link,
981 "MESSAGE=%s: could not get state: %s",
982 link->ifname, strerror(-r),
985 link_enter_failed(link);
989 log_debug_link(link, "got link state");
991 link_update(link, m);
996 static int link_getlink(Link *link) {
997 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1001 assert(link->manager);
1002 assert(link->manager->rtnl);
1004 log_debug_link(link, "requesting link status");
1006 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1007 RTM_GETLINK, link->ifindex);
1009 log_error_link(link, "Could not allocate RTM_GETLINK message");
1013 r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
1016 log_error_link(link,
1017 "Could not send rtnetlink message: %s", strerror(-r));
1024 int link_configure(Link *link) {
1028 assert(link->network);
1029 assert(link->state == _LINK_STATE_INVALID);
1031 r = link_getlink(link);
1033 link_enter_failed(link);
1037 return link_enter_enslave(link);
1040 int link_update(Link *link, sd_rtnl_message *m) {
1049 if (link->state == LINK_STATE_FAILED)
1052 r = sd_rtnl_message_link_get_flags(m, &flags);
1054 log_warning_link(link, "Could not get link flags");
1058 while (sd_rtnl_message_read(m, &type, &data) > 0) {
1059 if (type == IFLA_MTU && link->network->dhcp &&
1060 link->network->dhcp_mtu && !link->original_mtu) {
1061 link->original_mtu = *(uint16_t *) data;
1062 log_debug_link(link, "saved original MTU: %" PRIu16,
1063 link->original_mtu);
1067 return link_update_flags(link, flags);