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 hashmap_remove(link->manager->links, &link->ifindex);
93 free(link->state_file);
98 int link_get(Manager *m, int ifindex, Link **ret) {
107 ifindex_64 = ifindex;
108 link = hashmap_get(m->links, &ifindex_64);
117 int link_add(Manager *m, struct udev_device *device, Link **ret) {
125 r = link_new(m, device, &link);
131 r = network_get(m, device, &network);
133 return r == -ENOENT ? 0 : r;
135 r = network_apply(m, network, link);
142 static int link_enter_configured(Link *link) {
144 assert(link->state == LINK_STATE_SETTING_ROUTES);
146 log_info_link(link, "link configured");
148 link->state = LINK_STATE_CONFIGURED;
155 static void link_enter_failed(Link *link) {
158 log_warning_link(link, "failed");
160 link->state = LINK_STATE_FAILED;
165 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
166 Link *link = userdata;
169 assert(link->route_messages > 0);
170 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
171 link->state == LINK_STATE_SETTING_ROUTES ||
172 link->state == LINK_STATE_FAILED);
174 link->route_messages --;
176 if (link->state == LINK_STATE_FAILED)
179 r = sd_rtnl_message_get_errno(m);
180 if (r < 0 && r != -EEXIST)
181 log_struct_link(LOG_WARNING, link,
182 "MESSAGE=%s: could not set route: %s",
183 link->ifname, strerror(-r),
187 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
189 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
190 log_debug_link(link, "routes set");
191 link_enter_configured(link);
197 static int link_enter_set_routes(Link *link) {
202 assert(link->network);
203 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
205 link->state = LINK_STATE_SETTING_ROUTES;
207 if (!link->network->static_routes && !link->dhcp_lease)
208 return link_enter_configured(link);
210 log_debug_link(link, "setting routes");
212 LIST_FOREACH(static_routes, rt, link->network->static_routes) {
213 r = route_configure(rt, link, &route_handler);
215 log_warning_link(link,
216 "could not set routes: %s", strerror(-r));
217 link_enter_failed(link);
221 link->route_messages ++;
224 if (link->dhcp_lease) {
225 _cleanup_route_free_ Route *route = NULL;
226 struct in_addr gateway;
228 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
230 log_warning_link(link, "DHCP error: no router: %s",
235 r = route_new_dynamic(&route);
237 log_error_link(link, "Could not allocate route: %s",
242 route->family = AF_INET;
243 route->in_addr.in = gateway;
245 r = route_configure(route, link, &route_handler);
247 log_warning_link(link,
248 "could not set routes: %s", strerror(-r));
249 link_enter_failed(link);
253 link->route_messages ++;
259 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
260 Link *link = userdata;
265 assert(link->ifname);
266 assert(link->addr_messages > 0);
267 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
269 link->addr_messages --;
271 if (link->state == LINK_STATE_FAILED)
274 r = sd_rtnl_message_get_errno(m);
275 if (r < 0 && r != -EEXIST)
276 log_struct_link(LOG_WARNING, link,
277 "MESSAGE=%s: could not set address: %s",
278 link->ifname, strerror(-r),
282 if (link->addr_messages == 0) {
283 log_debug_link(link, "addresses set");
284 link_enter_set_routes(link);
290 static int link_enter_set_addresses(Link *link) {
295 assert(link->network);
296 assert(link->state != _LINK_STATE_INVALID);
298 link->state = LINK_STATE_SETTING_ADDRESSES;
300 if (!link->network->static_addresses && !link->dhcp_lease)
301 return link_enter_set_routes(link);
303 log_debug_link(link, "setting addresses");
305 LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
306 r = address_configure(ad, link, &address_handler);
308 log_warning_link(link,
309 "could not set addresses: %s", strerror(-r));
310 link_enter_failed(link);
314 link->addr_messages ++;
317 if (link->dhcp_lease) {
318 _cleanup_address_free_ Address *address = NULL;
320 struct in_addr netmask;
323 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
325 log_warning_link(link, "DHCP error: no address: %s",
330 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
332 log_warning_link(link, "DHCP error: no netmask: %s",
337 prefixlen = net_netmask_to_prefixlen(&netmask);
339 r = address_new_dynamic(&address);
341 log_error_link(link, "Could not allocate address: %s",
346 address->family = AF_INET;
347 address->in_addr.in = addr;
348 address->prefixlen = prefixlen;
349 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
351 r = address_configure(address, link, &address_handler);
353 log_warning_link(link,
354 "could not set addresses: %s", strerror(-r));
355 link_enter_failed(link);
359 link->addr_messages ++;
365 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
366 Link *link = userdata;
371 assert(link->ifname);
373 if (link->state == LINK_STATE_FAILED)
376 r = sd_rtnl_message_get_errno(m);
377 if (r < 0 && r != -ENOENT)
378 log_struct_link(LOG_WARNING, link,
379 "MESSAGE=%s: could not drop address: %s",
380 link->ifname, strerror(-r),
387 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
390 r = sd_bus_message_get_errno(m);
392 log_warning("Could not set hostname: %s", strerror(-r));
397 static int set_hostname(sd_bus *bus, const char *hostname) {
398 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
403 log_debug("Setting transient hostname: '%s'", hostname);
405 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
406 log_info("Not connected to system bus, ignoring transient hostname.");
410 r = sd_bus_message_new_method_call(
413 "org.freedesktop.hostname1",
414 "/org/freedesktop/hostname1",
415 "org.freedesktop.hostname1",
420 r = sd_bus_message_append(m, "sb", hostname, false);
424 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
426 log_error("Could not set transient hostname: %s", strerror(-r));
431 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
432 Link *link = userdata;
437 assert(link->ifname);
439 if (link->state == LINK_STATE_FAILED)
442 r = sd_rtnl_message_get_errno(m);
444 log_struct_link(LOG_WARNING, link,
445 "MESSAGE=%s: could not set MTU: %s",
446 link->ifname, strerror(-r),
453 static int link_set_mtu(Link *link, uint32_t mtu) {
454 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
458 assert(link->manager);
459 assert(link->manager->rtnl);
461 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
463 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
464 RTM_SETLINK, link->ifindex);
466 log_error_link(link, "Could not allocate RTM_SETLINK message");
470 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
472 log_error_link(link, "Could not append MTU: %s", strerror(-r));
476 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
479 "Could not send rtnetlink message: %s", strerror(-r));
486 static int dhcp_lease_lost(Link *link) {
487 _cleanup_address_free_ Address *address = NULL;
489 struct in_addr netmask;
494 assert(link->dhcp_lease);
496 log_warning_link(link, "DHCP lease lost");
498 r = address_new_dynamic(&address);
500 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
501 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
502 prefixlen = net_netmask_to_prefixlen(&netmask);
504 address->family = AF_INET;
505 address->in_addr.in = addr;
506 address->prefixlen = prefixlen;
508 address_drop(address, link, address_drop_handler);
511 if (link->network->dhcp_mtu) {
514 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
515 if (r >= 0 && link->original_mtu != mtu) {
516 r = link_set_mtu(link, link->original_mtu);
518 log_warning_link(link, "DHCP error: could not reset MTU");
519 link_enter_failed(link);
525 if (link->network->dhcp_hostname) {
526 const char *hostname = NULL;
528 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
529 if (r >= 0 && hostname) {
530 r = set_hostname(link->manager->bus, "");
532 log_error("Failed to reset transient hostname");
536 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
541 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
542 sd_dhcp_lease *lease;
543 struct in_addr address;
544 struct in_addr netmask;
545 struct in_addr gateway;
547 struct in_addr *nameservers;
548 size_t nameservers_size;
554 r = sd_dhcp_client_get_lease(client, &lease);
556 log_warning_link(link, "DHCP error: no lease: %s",
561 r = sd_dhcp_lease_get_address(lease, &address);
563 log_warning_link(link, "DHCP error: no address: %s",
568 r = sd_dhcp_lease_get_netmask(lease, &netmask);
570 log_warning_link(link, "DHCP error: no netmask: %s",
575 prefixlen = net_netmask_to_prefixlen(&netmask);
577 r = sd_dhcp_lease_get_router(lease, &gateway);
579 log_warning_link(link, "DHCP error: no router: %s",
584 log_struct_link(LOG_INFO, link,
585 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
587 ADDRESS_FMT_VAL(address),
589 ADDRESS_FMT_VAL(gateway),
590 "ADDRESS=%u.%u.%u.%u",
591 ADDRESS_FMT_VAL(address),
594 "GATEWAY=%u.%u.%u.%u",
595 ADDRESS_FMT_VAL(gateway),
598 link->dhcp_lease = lease;
600 if (link->network->dhcp_dns) {
601 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
603 r = manager_update_resolv_conf(link->manager);
605 log_error("Failed to update resolv.conf");
609 if (link->network->dhcp_mtu) {
612 r = sd_dhcp_lease_get_mtu(lease, &mtu);
614 r = link_set_mtu(link, mtu);
616 log_error_link(link, "Failed to set MTU "
621 if (link->network->dhcp_hostname) {
622 const char *hostname;
624 r = sd_dhcp_lease_get_hostname(lease, &hostname);
626 r = set_hostname(link->manager->bus, hostname);
628 log_error("Failed to set transient hostname "
629 "to '%s'", hostname);
633 link_enter_set_addresses(link);
638 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
639 Link *link = userdata;
643 assert(link->network);
644 assert(link->manager);
646 if (link->state == LINK_STATE_FAILED)
650 case DHCP_EVENT_NO_LEASE:
651 log_debug_link(link, "IP address in use.");
653 case DHCP_EVENT_EXPIRED:
654 case DHCP_EVENT_STOP:
655 case DHCP_EVENT_IP_CHANGE:
656 if (link->network->dhcp_critical) {
657 log_error_link(link, "DHCPv4 connection considered system critical, "
658 "ignoring request to reconfigure it.");
662 if (link->dhcp_lease) {
663 r = dhcp_lease_lost(link);
665 link_enter_failed(link);
670 if (event == DHCP_EVENT_IP_CHANGE) {
671 r = dhcp_lease_acquired(client, link);
673 link_enter_failed(link);
679 case DHCP_EVENT_IP_ACQUIRE:
680 r = dhcp_lease_acquired(client, link);
682 link_enter_failed(link);
688 log_warning_link(link, "DHCP error: %s", strerror(-event));
690 log_warning_link(link, "DHCP unknown event: %d", event);
697 static int link_acquire_conf(Link *link) {
701 assert(link->network);
702 assert(link->network->dhcp);
703 assert(link->manager);
704 assert(link->manager->event);
706 if (!link->dhcp_client) {
707 r = sd_dhcp_client_new(&link->dhcp_client);
711 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
715 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
719 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
723 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
727 if (link->network->dhcp_mtu) {
728 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
734 log_debug_link(link, "acquiring DHCPv4 lease");
736 r = sd_dhcp_client_start(link->dhcp_client);
743 static int link_update_flags(Link *link, unsigned flags) {
747 assert(link->network);
749 if (link->state == LINK_STATE_FAILED)
752 if (link->flags == flags) {
753 log_debug_link(link, "link status unchanged: %#.8x", flags);
757 if ((link->flags & IFF_UP) != (flags & IFF_UP))
759 "link is %s", flags & IFF_UP ? "up": "down");
761 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
762 if (flags & IFF_LOWER_UP) {
763 log_info_link(link, "carrier on");
765 if (link->network->dhcp) {
766 r = link_acquire_conf(link);
768 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
769 link_enter_failed(link);
774 log_info_link(link, "carrier off");
776 if (link->network->dhcp) {
777 r = sd_dhcp_client_stop(link->dhcp_client);
779 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
780 link_enter_failed(link);
788 "link status updated: %#.8x -> %#.8x", link->flags, flags);
795 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
796 Link *link = userdata;
801 if (link->state == LINK_STATE_FAILED)
804 r = sd_rtnl_message_get_errno(m);
806 log_struct_link(LOG_ERR, link,
807 "MESSAGE=%s: could not bring up interface: %s",
808 link->ifname, strerror(-r),
811 link_enter_failed(link);
815 link_update_flags(link, link->flags | IFF_UP);
820 static int link_up(Link *link) {
821 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
825 assert(link->manager);
826 assert(link->manager->rtnl);
828 log_debug_link(link, "bringing link up");
830 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
831 RTM_SETLINK, link->ifindex);
833 log_error_link(link, "Could not allocate RTM_SETLINK message");
837 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
839 log_error_link(link, "Could not set link flags: %s", strerror(-r));
843 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
846 "Could not send rtnetlink message: %s", strerror(-r));
853 static int link_enslaved(Link *link) {
857 assert(link->state == LINK_STATE_ENSLAVING);
858 assert(link->network);
862 link_enter_failed(link);
866 if (!link->network->dhcp)
867 return link_enter_set_addresses(link);
872 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
873 Link *link = userdata;
877 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
878 assert(link->network);
882 if (link->state == LINK_STATE_FAILED)
885 r = sd_rtnl_message_get_errno(m);
887 log_struct_link(LOG_ERR, link,
888 "MESSAGE=%s: could not enslave: %s",
889 link->ifname, strerror(-r),
892 link_enter_failed(link);
896 log_debug_link(link, "enslaved");
898 if (link->enslaving == 0)
904 static int link_enter_enslave(Link *link) {
905 NetDev *vlan, *macvlan;
910 assert(link->network);
911 assert(link->state == _LINK_STATE_INVALID);
913 link->state = LINK_STATE_ENSLAVING;
917 if (!link->network->bridge && !link->network->bond &&
918 hashmap_isempty(link->network->vlans) &&
919 hashmap_isempty(link->network->macvlans))
920 return link_enslaved(link);
922 if (link->network->bridge) {
923 log_struct_link(LOG_DEBUG, link,
924 "MESSAGE=%s: enslaving by '%s'",
925 link->ifname, link->network->bridge->name,
926 NETDEV(link->network->bridge),
929 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
931 log_struct_link(LOG_WARNING, link,
932 "MESSAGE=%s: could not enslave by '%s': %s",
933 link->ifname, link->network->bridge->name, strerror(-r),
934 NETDEV(link->network->bridge),
936 link_enter_failed(link);
943 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
944 log_struct_link(LOG_DEBUG, link,
945 "MESSAGE=%s: enslaving by '%s'",
946 link->ifname, vlan->name, NETDEV(vlan), NULL);
948 r = netdev_enslave(vlan, link, &enslave_handler);
950 log_struct_link(LOG_WARNING, link,
951 "MESSAGE=%s: could not enslave by '%s': %s",
952 link->ifname, vlan->name, strerror(-r),
954 link_enter_failed(link);
961 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
962 log_struct_link(LOG_DEBUG, link,
963 "MESSAGE=%s: enslaving by '%s'",
964 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
966 r = netdev_enslave(macvlan, link, &enslave_handler);
968 log_struct_link(LOG_WARNING, link,
969 "MESSAGE=%s: could not enslave by '%s': %s",
970 link->ifname, macvlan->name, strerror(-r),
971 NETDEV(macvlan), NULL);
972 link_enter_failed(link);
982 static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
984 Link *link = userdata;
989 if (link->state == LINK_STATE_FAILED)
992 r = sd_rtnl_message_get_errno(m);
994 log_struct_link(LOG_ERR, link,
995 "MESSAGE=%s: could not get state: %s",
996 link->ifname, strerror(-r),
999 link_enter_failed(link);
1003 log_debug_link(link, "got link state");
1005 link_update(link, m);
1010 static int link_getlink(Link *link) {
1011 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1015 assert(link->manager);
1016 assert(link->manager->rtnl);
1018 log_debug_link(link, "requesting link status");
1020 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1021 RTM_GETLINK, link->ifindex);
1023 log_error_link(link, "Could not allocate RTM_GETLINK message");
1027 r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
1030 log_error_link(link,
1031 "Could not send rtnetlink message: %s", strerror(-r));
1038 int link_configure(Link *link) {
1042 assert(link->network);
1043 assert(link->state == _LINK_STATE_INVALID);
1045 r = link_getlink(link);
1047 link_enter_failed(link);
1051 return link_enter_enslave(link);
1054 int link_update(Link *link, sd_rtnl_message *m) {
1063 if (link->state == LINK_STATE_FAILED)
1066 r = sd_rtnl_message_link_get_flags(m, &flags);
1068 log_warning_link(link, "Could not get link flags");
1072 while (sd_rtnl_message_read(m, &type, &data) > 0) {
1073 if (type == IFLA_MTU && link->network->dhcp &&
1074 link->network->dhcp_mtu && !link->original_mtu) {
1075 link->original_mtu = *(uint16_t *) data;
1076 log_debug_link(link, "saved original MTU: %" PRIu16,
1077 link->original_mtu);
1081 return link_update_flags(link, flags);
1084 int link_save(Link *link) {
1085 _cleanup_free_ char *temp_path = NULL;
1086 _cleanup_fclose_ FILE *f = NULL;
1090 assert(link->state_file);
1092 r = mkdir_safe_label("/run/systemd/network/links", 0755, 0, 0);
1096 r = fopen_temporary(link->state_file, &f, &temp_path);
1100 fchmod(fileno(f), 0644);
1103 "# This is private data. Do not parse.\n"
1105 link_state_to_string(link->state));
1107 if (link->dhcp_lease) {
1108 const char *lease_file = "/run/systemd/network/leases/test.lease";
1110 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1114 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1119 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1121 unlink(link->state_file);
1127 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1132 static const char* const link_state_table[_LINK_STATE_MAX] = {
1133 [LINK_STATE_ENSLAVING] = "configuring",
1134 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1135 [LINK_STATE_SETTING_ROUTES] = "configuring",
1136 [LINK_STATE_CONFIGURED] = "configured",
1137 [LINK_STATE_FAILED] = "failed",
1140 DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);