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;
45 link->manager = manager;
46 link->state = _LINK_STATE_INVALID;
48 link->ifindex = udev_device_get_ifindex(device);
49 if (link->ifindex <= 0)
52 mac = udev_device_get_sysattr_value(device, "address");
54 mac_addr = ether_aton(mac);
56 memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
59 ifname = udev_device_get_sysname(device);
60 link->ifname = strdup(ifname);
62 r = hashmap_put(manager->links, &link->ifindex, link);
72 void link_free(Link *link) {
76 assert(link->manager);
78 sd_dhcp_client_free(link->dhcp_client);
79 sd_dhcp_lease_unref(link->dhcp_lease);
81 hashmap_remove(link->manager->links, &link->ifindex);
88 int link_add(Manager *m, struct udev_device *device, Link **ret) {
97 ifindex = udev_device_get_ifindex(device);
98 link = hashmap_get(m->links, &ifindex);
104 r = link_new(m, device, &link);
110 r = network_get(m, device, &network);
112 return r == -ENOENT ? 0 : r;
114 r = network_apply(m, network, link);
121 static int link_enter_configured(Link *link) {
123 assert(link->state == LINK_STATE_SETTING_ROUTES);
125 log_info_link(link, "link configured");
127 link->state = LINK_STATE_CONFIGURED;
132 static void link_enter_failed(Link *link) {
135 log_warning_link(link, "failed");
137 link->state = LINK_STATE_FAILED;
140 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
141 Link *link = userdata;
144 assert(link->route_messages > 0);
145 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
146 link->state == LINK_STATE_SETTING_ROUTES ||
147 link->state == LINK_STATE_FAILED);
149 link->route_messages --;
151 if (link->state == LINK_STATE_FAILED)
154 r = sd_rtnl_message_get_errno(m);
155 if (r < 0 && r != -EEXIST)
156 log_struct_link(LOG_WARNING, link,
157 "MESSAGE=%s: could not set route: %s",
158 link->ifname, strerror(-r),
162 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
164 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
165 log_debug_link(link, "routes set");
166 link_enter_configured(link);
172 static int link_enter_set_routes(Link *link) {
177 assert(link->network);
178 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
180 link->state = LINK_STATE_SETTING_ROUTES;
182 if (!link->network->static_routes && !link->dhcp_lease)
183 return link_enter_configured(link);
185 log_debug_link(link, "setting routes");
187 LIST_FOREACH(static_routes, rt, link->network->static_routes) {
188 r = route_configure(rt, link, &route_handler);
190 log_warning_link(link,
191 "could not set routes: %s", strerror(-r));
192 link_enter_failed(link);
196 link->route_messages ++;
199 if (link->dhcp_lease) {
200 _cleanup_route_free_ Route *route = NULL;
201 struct in_addr gateway;
203 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
205 log_warning_link(link, "DHCP error: no router: %s",
210 r = route_new_dynamic(&route);
212 log_error_link(link, "Could not allocate route: %s",
217 route->family = AF_INET;
218 route->in_addr.in = gateway;
220 r = route_configure(route, link, &route_handler);
222 log_warning_link(link,
223 "could not set routes: %s", strerror(-r));
224 link_enter_failed(link);
228 link->route_messages ++;
234 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
235 Link *link = userdata;
240 assert(link->ifname);
241 assert(link->addr_messages > 0);
242 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
244 link->addr_messages --;
246 if (link->state == LINK_STATE_FAILED)
249 r = sd_rtnl_message_get_errno(m);
250 if (r < 0 && r != -EEXIST)
251 log_struct_link(LOG_WARNING, link,
252 "MESSAGE=%s: could not set address: %s",
253 link->ifname, strerror(-r),
257 if (link->addr_messages == 0) {
258 log_debug_link(link, "addresses set");
259 link_enter_set_routes(link);
265 static int link_enter_set_addresses(Link *link) {
270 assert(link->network);
271 assert(link->state != _LINK_STATE_INVALID);
273 link->state = LINK_STATE_SETTING_ADDRESSES;
275 if (!link->network->static_addresses && !link->dhcp_lease)
276 return link_enter_set_routes(link);
278 log_debug_link(link, "setting addresses");
280 LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
281 r = address_configure(ad, link, &address_handler);
283 log_warning_link(link,
284 "could not set addresses: %s", strerror(-r));
285 link_enter_failed(link);
289 link->addr_messages ++;
292 if (link->dhcp_lease) {
293 _cleanup_address_free_ Address *address = NULL;
295 struct in_addr netmask;
298 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
300 log_warning_link(link, "DHCP error: no address: %s",
305 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
307 log_warning_link(link, "DHCP error: no netmask: %s",
312 prefixlen = net_netmask_to_prefixlen(&netmask);
314 r = address_new_dynamic(&address);
316 log_error_link(link, "Could not allocate address: %s",
321 address->family = AF_INET;
322 address->in_addr.in = addr;
323 address->prefixlen = prefixlen;
324 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
326 r = address_configure(address, link, &address_handler);
328 log_warning_link(link,
329 "could not set addresses: %s", strerror(-r));
330 link_enter_failed(link);
334 link->addr_messages ++;
340 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
341 Link *link = userdata;
346 assert(link->ifname);
348 if (link->state == LINK_STATE_FAILED)
351 r = sd_rtnl_message_get_errno(m);
352 if (r < 0 && r != -ENOENT)
353 log_struct_link(LOG_WARNING, link,
354 "MESSAGE=%s: could not drop address: %s",
355 link->ifname, strerror(-r),
362 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
365 r = sd_bus_message_get_errno(m);
367 log_warning("Could not set hostname: %s", strerror(-r));
372 static int set_hostname(sd_bus *bus, const char *hostname) {
373 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
378 log_debug("Setting transient hostname: '%s'", hostname);
380 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
381 log_info("Not connected to system bus, ignoring transient hostname.");
385 r = sd_bus_message_new_method_call(
387 "org.freedesktop.hostname1",
388 "/org/freedesktop/hostname1",
389 "org.freedesktop.hostname1",
395 r = sd_bus_message_append(m, "sb", hostname, false);
399 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
401 log_error("Could not set transient hostname: %s", strerror(-r));
406 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
407 Link *link = userdata;
412 assert(link->ifname);
414 if (link->state == LINK_STATE_FAILED)
417 r = sd_rtnl_message_get_errno(m);
419 log_struct_link(LOG_WARNING, link,
420 "MESSAGE=%s: could not set MTU: %s",
421 link->ifname, strerror(-r),
428 static int link_set_mtu(Link *link, uint32_t mtu) {
429 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
433 assert(link->manager);
434 assert(link->manager->rtnl);
436 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
438 r = sd_rtnl_message_new_link(link->manager->rtnl, RTM_SETLINK,
439 link->ifindex, &req);
441 log_error_link(link, "Could not allocate RTM_SETLINK message");
445 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
447 log_error_link(link, "Could not append MTU: %s", strerror(-r));
451 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
454 "Could not send rtnetlink message: %s", strerror(-r));
461 static int dhcp_lease_lost(Link *link) {
462 _cleanup_address_free_ Address *address = NULL;
464 struct in_addr netmask;
469 assert(link->dhcp_lease);
471 r = address_new_dynamic(&address);
473 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
474 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
475 prefixlen = net_netmask_to_prefixlen(&netmask);
477 address->family = AF_INET;
478 address->in_addr.in = addr;
479 address->prefixlen = prefixlen;
481 address_drop(address, link, address_drop_handler);
484 if (link->network->dhcp_mtu) {
487 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
488 if (r >= 0 && link->original_mtu != mtu) {
489 r = link_set_mtu(link, link->original_mtu);
491 log_warning_link(link, "DHCP error: could not reset MTU");
492 link_enter_failed(link);
498 if (link->network->dhcp_hostname) {
499 r = set_hostname(link->manager->bus, "");
501 log_error("Failed to reset transient hostname");
504 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
509 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
510 sd_dhcp_lease *lease;
511 struct in_addr address;
512 struct in_addr netmask;
513 struct in_addr gateway;
515 struct in_addr *nameservers;
516 size_t nameservers_size;
522 r = sd_dhcp_client_get_lease(client, &lease);
524 log_warning_link(link, "DHCP error: no lease: %s",
529 r = sd_dhcp_lease_get_address(lease, &address);
531 log_warning_link(link, "DHCP error: no address: %s",
536 r = sd_dhcp_lease_get_netmask(lease, &netmask);
538 log_warning_link(link, "DHCP error: no netmask: %s",
543 prefixlen = net_netmask_to_prefixlen(&netmask);
545 r = sd_dhcp_lease_get_router(lease, &gateway);
547 log_warning_link(link, "DHCP error: no router: %s",
552 log_struct_link(LOG_INFO, link,
553 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
555 ADDRESS_FMT_VAL(address),
557 ADDRESS_FMT_VAL(gateway),
558 "ADDRESS=%u.%u.%u.%u",
559 ADDRESS_FMT_VAL(address),
562 "GATEWAY=%u.%u.%u.%u",
563 ADDRESS_FMT_VAL(gateway),
566 link->dhcp_lease = lease;
568 if (link->network->dhcp_dns) {
569 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
571 r = manager_update_resolv_conf(link->manager);
573 log_error("Failed to update resolv.conf");
577 if (link->network->dhcp_mtu) {
580 r = sd_dhcp_lease_get_mtu(lease, &mtu);
582 r = link_set_mtu(link, mtu);
584 log_error_link(link, "Failed to set MTU "
589 if (link->network->dhcp_hostname) {
590 const char *hostname;
592 r = sd_dhcp_lease_get_hostname(lease, &hostname);
594 r = set_hostname(link->manager->bus, hostname);
596 log_error("Failed to set transient hostname "
597 "to '%s'", hostname);
601 link_enter_set_addresses(link);
606 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
607 Link *link = userdata;
611 assert(link->network);
612 assert(link->manager);
614 if (link->state == LINK_STATE_FAILED)
618 case DHCP_EVENT_NO_LEASE:
619 log_debug_link(link, "IP address in use.");
621 case DHCP_EVENT_EXPIRED:
622 case DHCP_EVENT_STOP:
623 case DHCP_EVENT_IP_CHANGE:
624 if (link->network->dhcp_critical) {
625 log_error_link(link, "DHCPv4 connection considered system critical, "
626 "ignoring request to reconfigure it.");
630 if (link->dhcp_lease) {
631 r = dhcp_lease_lost(link);
633 link_enter_failed(link);
638 if (event == DHCP_EVENT_IP_CHANGE) {
639 r = dhcp_lease_acquired(client, link);
641 link_enter_failed(link);
647 case DHCP_EVENT_IP_ACQUIRE:
648 r = dhcp_lease_acquired(client, link);
650 link_enter_failed(link);
656 log_warning_link(link, "DHCP error: %s", strerror(-event));
658 log_warning_link(link, "DHCP unknown event: %d", event);
665 static int link_acquire_conf(Link *link) {
669 assert(link->network);
670 assert(link->network->dhcp);
671 assert(link->manager);
672 assert(link->manager->event);
674 if (!link->dhcp_client) {
675 r = sd_dhcp_client_new(&link->dhcp_client);
679 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
683 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
687 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
691 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
695 if (link->network->dhcp_mtu) {
696 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
702 log_debug_link(link, "acquiring DHCPv4 lease");
704 r = sd_dhcp_client_start(link->dhcp_client);
711 static int link_update_flags(Link *link, unsigned flags) {
715 assert(link->network);
717 if (link->state == LINK_STATE_FAILED)
720 if (link->flags == flags) {
721 log_debug_link(link, "link status unchanged: %#.8x", flags);
725 if ((link->flags & IFF_UP) != (flags & IFF_UP))
727 "link is %s", flags & IFF_UP ? "up": "down");
729 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
730 if (flags & IFF_LOWER_UP) {
731 log_info_link(link, "carrier on");
733 if (link->network->dhcp) {
734 r = link_acquire_conf(link);
736 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
737 link_enter_failed(link);
742 log_info_link(link, "carrier off");
744 if (link->network->dhcp) {
745 r = sd_dhcp_client_stop(link->dhcp_client);
747 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
748 link_enter_failed(link);
756 "link status updated: %#.8x -> %#.8x", link->flags, flags);
763 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
764 Link *link = userdata;
769 if (link->state == LINK_STATE_FAILED)
772 r = sd_rtnl_message_get_errno(m);
774 log_struct_link(LOG_ERR, link,
775 "MESSAGE=%s: could not bring up interface: %s",
776 link->ifname, strerror(-r),
779 link_enter_failed(link);
783 link_update_flags(link, link->flags | IFF_UP);
788 static int link_up(Link *link) {
789 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
793 assert(link->manager);
794 assert(link->manager->rtnl);
796 log_debug_link(link, "bringing link up");
798 r = sd_rtnl_message_new_link(link->manager->rtnl, RTM_SETLINK,
799 link->ifindex, &req);
801 log_error_link(link, "Could not allocate RTM_SETLINK message");
805 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
807 log_error_link(link, "Could not set link flags: %s", strerror(-r));
811 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
814 "Could not send rtnetlink message: %s", strerror(-r));
821 static int link_enslaved(Link *link) {
825 assert(link->state == LINK_STATE_ENSLAVING);
826 assert(link->network);
830 link_enter_failed(link);
834 if (!link->network->dhcp)
835 return link_enter_set_addresses(link);
840 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
841 Link *link = userdata;
845 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
846 assert(link->network);
850 if (link->state == LINK_STATE_FAILED)
853 r = sd_rtnl_message_get_errno(m);
855 log_struct_link(LOG_ERR, link,
856 "MESSAGE=%s: could not enslave: %s",
857 link->ifname, strerror(-r),
860 link_enter_failed(link);
864 log_debug_link(link, "enslaved");
866 if (link->enslaving == 0)
872 static int link_enter_enslave(Link *link) {
878 assert(link->network);
879 assert(link->state == _LINK_STATE_INVALID);
881 link->state = LINK_STATE_ENSLAVING;
883 if (!link->network->bridge && !link->network->bond &&
884 hashmap_isempty(link->network->vlans))
885 return link_enslaved(link);
887 if (link->network->bridge) {
888 log_struct_link(LOG_DEBUG, link,
889 "MESSAGE=%s: enslaving by '%s'",
890 link->ifname, link->network->bridge->name,
891 NETDEV(link->network->bridge),
894 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
896 log_struct_link(LOG_WARNING, link,
897 "MESSAGE=%s: could not enslave by '%s': %s",
898 link->ifname, link->network->bridge->name, strerror(-r),
899 NETDEV(link->network->bridge),
901 link_enter_failed(link);
908 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
909 log_struct_link(LOG_DEBUG, link,
910 "MESSAGE=%s: enslaving by '%s'",
911 link->ifname, vlan->name, NETDEV(vlan), NULL);
913 r = netdev_enslave(vlan, link, &enslave_handler);
915 log_struct_link(LOG_WARNING, link,
916 "MESSAGE=%s: could not enslave by '%s': %s",
917 link->ifname, vlan->name, strerror(-r),
919 link_enter_failed(link);
929 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
930 Link *link = userdata;
935 if (link->state == LINK_STATE_FAILED)
938 r = sd_rtnl_message_get_errno(m);
940 log_struct_link(LOG_ERR, link,
941 "MESSAGE=%s: could not get state: %s",
942 link->ifname, strerror(-r),
945 link_enter_failed(link);
949 log_debug_link(link, "got link state");
951 link_update(link, m);
956 static int link_get(Link *link) {
957 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
961 assert(link->manager);
962 assert(link->manager->rtnl);
964 log_debug_link(link, "requesting link status");
966 r = sd_rtnl_message_new_link(link->manager->rtnl, RTM_GETLINK,
967 link->ifindex, &req);
969 log_error_link(link, "Could not allocate RTM_GETLINK message");
973 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
976 "Could not send rtnetlink message: %s", strerror(-r));
983 int link_configure(Link *link) {
987 assert(link->network);
988 assert(link->state == _LINK_STATE_INVALID);
992 link_enter_failed(link);
996 return link_enter_enslave(link);
999 int link_update(Link *link, sd_rtnl_message *m) {
1008 if (link->state == LINK_STATE_FAILED)
1011 r = sd_rtnl_message_link_get_flags(m, &flags);
1013 log_warning_link(link, "Could not get link flags");
1017 while (sd_rtnl_message_read(m, &type, &data) > 0) {
1018 if (type == IFLA_MTU && link->network->dhcp &&
1019 link->network->dhcp_mtu && !link->original_mtu) {
1020 link->original_mtu = *(uint16_t *) data;
1021 log_debug_link(link, "saved original MTU: %" PRIu16,
1022 link->original_mtu);
1026 return link_update_flags(link, flags);