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_sd_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_link_new(RTM_SETLINK, link->ifindex, &req);
440 log_error_link(link, "Could not allocate RTM_SETLINK message");
444 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
446 log_error_link(link, "Could not append MTU: %s", strerror(-r));
450 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
453 "Could not send rtnetlink message: %s", strerror(-r));
460 static int dhcp_lease_lost(Link *link) {
461 _cleanup_address_free_ Address *address = NULL;
463 struct in_addr netmask;
468 assert(link->dhcp_lease);
470 r = address_new_dynamic(&address);
472 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
473 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
474 prefixlen = net_netmask_to_prefixlen(&netmask);
476 address->family = AF_INET;
477 address->in_addr.in = addr;
478 address->prefixlen = prefixlen;
480 address_drop(address, link, address_drop_handler);
483 if (link->network->dhcp_mtu) {
486 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
487 if (r >= 0 && link->original_mtu != mtu) {
488 r = link_set_mtu(link, link->original_mtu);
490 log_warning_link(link, "DHCP error: could not reset MTU");
491 link_enter_failed(link);
497 if (link->network->dhcp_hostname) {
498 r = set_hostname(link->manager->bus, "");
500 log_error("Failed to reset transient hostname");
503 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
508 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
509 sd_dhcp_lease *lease;
510 struct in_addr address;
511 struct in_addr netmask;
512 struct in_addr gateway;
514 struct in_addr *nameservers;
515 size_t nameservers_size;
521 r = sd_dhcp_client_get_lease(client, &lease);
523 log_warning_link(link, "DHCP error: no lease: %s",
528 r = sd_dhcp_lease_get_address(lease, &address);
530 log_warning_link(link, "DHCP error: no address: %s",
535 r = sd_dhcp_lease_get_netmask(lease, &netmask);
537 log_warning_link(link, "DHCP error: no netmask: %s",
542 prefixlen = net_netmask_to_prefixlen(&netmask);
544 r = sd_dhcp_lease_get_router(lease, &gateway);
546 log_warning_link(link, "DHCP error: no router: %s",
551 log_struct_link(LOG_INFO, link,
552 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
554 ADDRESS_FMT_VAL(address),
556 ADDRESS_FMT_VAL(gateway),
557 "ADDRESS=%u.%u.%u.%u",
558 ADDRESS_FMT_VAL(address),
561 "GATEWAY=%u.%u.%u.%u",
562 ADDRESS_FMT_VAL(gateway),
565 if (link->network->dhcp_dns) {
566 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
568 r = manager_update_resolv_conf(link->manager);
570 log_error("Failed to update resolv.conf");
574 if (link->network->dhcp_mtu) {
577 r = sd_dhcp_lease_get_mtu(lease, &mtu);
579 r = link_set_mtu(link, mtu);
581 log_error_link(link, "Failed to set MTU "
586 if (link->network->dhcp_hostname) {
587 const char *hostname;
589 r = sd_dhcp_lease_get_hostname(lease, &hostname);
591 r = set_hostname(link->manager->bus, hostname);
593 log_error("Failed to set transient hostname "
594 "to '%s'", hostname);
598 link->dhcp_lease = lease;
600 link_enter_set_addresses(link);
605 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
606 Link *link = userdata;
610 assert(link->network);
611 assert(link->manager);
613 if (link->state == LINK_STATE_FAILED)
617 case DHCP_EVENT_NO_LEASE:
618 log_debug_link(link, "IP address in use.");
620 case DHCP_EVENT_EXPIRED:
621 case DHCP_EVENT_STOP:
622 case DHCP_EVENT_IP_CHANGE:
623 if (link->network->dhcp_critical) {
624 log_error_link(link, "DHCPv4 connection considered system critical, "
625 "ignoring request to reconfigure it.");
629 r = dhcp_lease_lost(link);
631 link_enter_failed(link);
635 if (event == DHCP_EVENT_IP_CHANGE) {
636 r = dhcp_lease_acquired(client, link);
638 link_enter_failed(link);
644 case DHCP_EVENT_IP_ACQUIRE:
645 r = dhcp_lease_acquired(client, link);
647 link_enter_failed(link);
653 log_warning_link(link, "DHCP error: %s", strerror(-event));
655 log_warning_link(link, "DHCP unknown event: %d", event);
662 static int link_acquire_conf(Link *link) {
666 assert(link->network);
667 assert(link->network->dhcp);
668 assert(link->manager);
669 assert(link->manager->event);
671 if (!link->dhcp_client) {
672 r = sd_dhcp_client_new(&link->dhcp_client);
676 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
680 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
684 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
688 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
692 if (link->network->dhcp_mtu) {
693 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
699 log_debug_link(link, "acquiring DHCPv4 lease");
701 r = sd_dhcp_client_start(link->dhcp_client);
708 static int link_update_flags(Link *link, unsigned flags) {
712 assert(link->network);
714 if (link->state == LINK_STATE_FAILED)
717 if (link->flags == flags) {
718 log_debug_link(link, "link status unchanged: %#.8x", flags);
722 if ((link->flags & IFF_UP) != (flags & IFF_UP))
724 "link is %s", flags & IFF_UP ? "up": "down");
726 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
727 if (flags & IFF_LOWER_UP) {
728 log_info_link(link, "carrier on");
730 if (link->network->dhcp) {
731 r = link_acquire_conf(link);
733 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
734 link_enter_failed(link);
739 log_info_link(link, "carrier off");
741 if (link->network->dhcp) {
742 r = sd_dhcp_client_stop(link->dhcp_client);
744 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
745 link_enter_failed(link);
753 "link status updated: %#.8x -> %#.8x", link->flags, flags);
760 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
761 Link *link = userdata;
766 if (link->state == LINK_STATE_FAILED)
769 r = sd_rtnl_message_get_errno(m);
771 log_struct_link(LOG_ERR, link,
772 "MESSAGE=%s: could not bring up interface: %s",
773 link->ifname, strerror(-r),
776 link_enter_failed(link);
780 link_update_flags(link, link->flags | IFF_UP);
785 static int link_up(Link *link) {
786 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
790 assert(link->manager);
791 assert(link->manager->rtnl);
793 log_debug_link(link, "bringing link up");
795 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
797 log_error_link(link, "Could not allocate RTM_SETLINK message");
801 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
803 log_error_link(link, "Could not set link flags: %s", strerror(-r));
807 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
810 "Could not send rtnetlink message: %s", strerror(-r));
817 static int link_enslaved(Link *link) {
821 assert(link->state == LINK_STATE_ENSLAVING);
822 assert(link->network);
826 link_enter_failed(link);
830 if (!link->network->dhcp)
831 return link_enter_set_addresses(link);
836 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
837 Link *link = userdata;
841 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
842 assert(link->network);
846 if (link->state == LINK_STATE_FAILED)
849 r = sd_rtnl_message_get_errno(m);
851 log_struct_link(LOG_ERR, link,
852 "MESSAGE=%s: could not enslave: %s",
853 link->ifname, strerror(-r),
856 link_enter_failed(link);
860 log_debug_link(link, "enslaved");
862 if (link->enslaving == 0)
868 static int link_enter_enslave(Link *link) {
872 assert(link->network);
873 assert(link->state == _LINK_STATE_INVALID);
875 link->state = LINK_STATE_ENSLAVING;
877 if (!link->network->bridge && !link->network->bond && !link->network->vlan)
878 return link_enslaved(link);
880 if (link->network->bridge) {
881 log_struct_link(LOG_DEBUG, link,
882 "MESSAGE=%s: enslaving by '%s'",
883 link->ifname, link->network->bridge->name,
884 NETDEV(link->network->bridge),
887 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
889 log_struct_link(LOG_WARNING, link,
890 "MESSAGE=%s: could not enslave by '%s': %s",
891 link->ifname, link->network->bridge->name, strerror(-r),
892 NETDEV(link->network->bridge),
894 link_enter_failed(link);
901 if (link->network->vlan) {
902 log_struct_link(LOG_DEBUG, link,
903 "MESSAGE=%s: enslaving by '%s'",
904 link->ifname, link->network->vlan->name,
905 NETDEV(link->network->vlan),
908 r = netdev_enslave(link->network->vlan, link, &enslave_handler);
910 log_struct_link(LOG_WARNING, link,
911 "MESSAGE=%s: could not enslave by '%s': %s",
912 link->ifname, link->network->vlan->name,
913 strerror(-r), NETDEV(link->network->vlan),
915 link_enter_failed(link);
925 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
926 Link *link = userdata;
931 if (link->state == LINK_STATE_FAILED)
934 r = sd_rtnl_message_get_errno(m);
936 log_struct_link(LOG_ERR, link,
937 "MESSAGE=%s: could not get state: %s",
938 link->ifname, strerror(-r),
941 link_enter_failed(link);
945 log_debug_link(link, "got link state");
947 link_update(link, m);
952 static int link_get(Link *link) {
953 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
957 assert(link->manager);
958 assert(link->manager->rtnl);
960 log_debug_link(link, "requesting link status");
962 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
964 log_error_link(link, "Could not allocate RTM_GETLINK message");
968 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
971 "Could not send rtnetlink message: %s", strerror(-r));
978 int link_configure(Link *link) {
982 assert(link->network);
983 assert(link->state == _LINK_STATE_INVALID);
987 link_enter_failed(link);
991 return link_enter_enslave(link);
994 int link_update(Link *link, sd_rtnl_message *m) {
1003 if (link->state == LINK_STATE_FAILED)
1006 r = sd_rtnl_message_link_get_flags(m, &flags);
1008 log_warning_link(link, "Could not get link flags");
1012 while (sd_rtnl_message_read(m, &type, &data) > 0) {
1013 if (type == IFLA_MTU && link->network->dhcp &&
1014 link->network->dhcp_mtu && !link->original_mtu) {
1015 link->original_mtu = *(uint16_t *) data;
1016 log_debug_link(link, "saved original MTU: %" PRIu16,
1017 link->original_mtu);
1021 return link_update_flags(link, flags);