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 _cleanup_address_free_ Address *addr = NULL;
515 _cleanup_route_free_ Route *rt = NULL;
516 struct in_addr *nameservers;
517 size_t nameservers_size;
523 r = sd_dhcp_client_get_lease(client, &lease);
525 log_warning_link(link, "DHCP error: no lease: %s",
530 r = sd_dhcp_lease_get_address(lease, &address);
532 log_warning_link(link, "DHCP error: no address: %s",
537 r = sd_dhcp_lease_get_netmask(lease, &netmask);
539 log_warning_link(link, "DHCP error: no netmask: %s",
544 prefixlen = net_netmask_to_prefixlen(&netmask);
546 r = sd_dhcp_lease_get_router(lease, &gateway);
548 log_warning_link(link, "DHCP error: no router: %s",
553 log_struct_link(LOG_INFO, link,
554 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
556 ADDRESS_FMT_VAL(address),
558 ADDRESS_FMT_VAL(gateway),
559 "ADDRESS=%u.%u.%u.%u",
560 ADDRESS_FMT_VAL(address),
563 "GATEWAY=%u.%u.%u.%u",
564 ADDRESS_FMT_VAL(gateway),
567 if (link->network->dhcp_dns) {
568 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
570 r = manager_update_resolv_conf(link->manager);
572 log_error("Failed to update resolv.conf");
576 if (link->network->dhcp_mtu) {
579 r = sd_dhcp_lease_get_mtu(lease, &mtu);
581 r = link_set_mtu(link, mtu);
583 log_error_link(link, "Failed to set MTU "
588 if (link->network->dhcp_hostname) {
589 const char *hostname;
591 r = sd_dhcp_lease_get_hostname(lease, &hostname);
593 r = set_hostname(link->manager->bus, hostname);
595 log_error("Failed to set transient hostname "
596 "to '%s'", hostname);
600 link->dhcp_lease = lease;
602 link_enter_set_addresses(link);
607 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
608 Link *link = userdata;
612 assert(link->network);
613 assert(link->manager);
615 if (link->state == LINK_STATE_FAILED)
619 case DHCP_EVENT_NO_LEASE:
620 log_debug_link(link, "IP address in use.");
622 case DHCP_EVENT_EXPIRED:
623 case DHCP_EVENT_STOP:
624 case DHCP_EVENT_IP_CHANGE:
625 if (link->network->dhcp_critical) {
626 log_error_link(link, "DHCPv4 connection considered system critical, "
627 "ignoring request to reconfigure it.");
631 r = dhcp_lease_lost(link);
633 link_enter_failed(link);
637 if (event == DHCP_EVENT_IP_CHANGE) {
638 r = dhcp_lease_acquired(client, link);
640 link_enter_failed(link);
646 case DHCP_EVENT_IP_ACQUIRE:
647 r = dhcp_lease_acquired(client, link);
649 link_enter_failed(link);
655 log_warning_link(link, "DHCP error: %s", strerror(-event));
657 log_warning_link(link, "DHCP unknown event: %d", event);
664 static int link_acquire_conf(Link *link) {
668 assert(link->network);
669 assert(link->network->dhcp);
670 assert(link->manager);
671 assert(link->manager->event);
673 if (!link->dhcp_client) {
674 r = sd_dhcp_client_new(&link->dhcp_client);
678 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
682 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
686 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
690 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
694 if (link->network->dhcp_mtu) {
695 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
701 log_debug_link(link, "acquiring DHCPv4 lease");
703 r = sd_dhcp_client_start(link->dhcp_client);
710 static int link_update_flags(Link *link, unsigned flags) {
714 assert(link->network);
716 if (link->state == LINK_STATE_FAILED)
719 if (link->flags == flags) {
720 log_debug_link(link, "link status unchanged: %#.8x", flags);
724 if ((link->flags & IFF_UP) != (flags & IFF_UP))
726 "link is %s", flags & IFF_UP ? "up": "down");
728 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
729 if (flags & IFF_LOWER_UP) {
730 log_info_link(link, "carrier on");
732 if (link->network->dhcp) {
733 r = link_acquire_conf(link);
735 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
736 link_enter_failed(link);
741 log_info_link(link, "carrier off");
743 if (link->network->dhcp) {
744 r = sd_dhcp_client_stop(link->dhcp_client);
746 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
747 link_enter_failed(link);
755 "link status updated: %#.8x -> %#.8x", link->flags, flags);
762 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
763 Link *link = userdata;
768 if (link->state == LINK_STATE_FAILED)
771 r = sd_rtnl_message_get_errno(m);
773 log_struct_link(LOG_ERR, link,
774 "MESSAGE=%s: could not bring up interface: %s",
775 link->ifname, strerror(-r),
778 link_enter_failed(link);
782 link_update_flags(link, link->flags | IFF_UP);
787 static int link_up(Link *link) {
788 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
792 assert(link->manager);
793 assert(link->manager->rtnl);
795 log_debug_link(link, "bringing link up");
797 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
799 log_error_link(link, "Could not allocate RTM_SETLINK message");
803 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
805 log_error_link(link, "Could not set link flags: %s", strerror(-r));
809 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
812 "Could not send rtnetlink message: %s", strerror(-r));
819 static int link_enslaved(Link *link) {
823 assert(link->state == LINK_STATE_ENSLAVING);
824 assert(link->network);
828 link_enter_failed(link);
832 if (!link->network->dhcp)
833 return link_enter_set_addresses(link);
838 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
839 Link *link = userdata;
843 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
844 assert(link->network);
848 if (link->state == LINK_STATE_FAILED)
851 r = sd_rtnl_message_get_errno(m);
853 log_struct_link(LOG_ERR, link,
854 "MESSAGE=%s: could not enslave: %s",
855 link->ifname, strerror(-r),
858 link_enter_failed(link);
862 log_debug_link(link, "enslaved");
864 if (link->enslaving == 0)
870 static int link_enter_enslave(Link *link) {
874 assert(link->network);
875 assert(link->state == _LINK_STATE_INVALID);
877 link->state = LINK_STATE_ENSLAVING;
879 if (!link->network->bridge && !link->network->bond && !link->network->vlan)
880 return link_enslaved(link);
882 if (link->network->bridge) {
883 log_struct_link(LOG_DEBUG, link,
884 "MESSAGE=%s: enslaving by '%s'",
885 link->ifname, link->network->bridge->name,
886 NETDEV(link->network->bridge),
889 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
891 log_struct_link(LOG_WARNING, link,
892 "MESSAGE=%s: could not enslave by '%s': %s",
893 link->ifname, link->network->bridge->name, strerror(-r),
894 NETDEV(link->network->bridge),
896 link_enter_failed(link);
903 if (link->network->vlan) {
904 log_struct_link(LOG_DEBUG, link,
905 "MESSAGE=%s: enslaving by '%s'",
906 link->ifname, link->network->vlan->name,
907 NETDEV(link->network->vlan),
910 r = netdev_enslave(link->network->vlan, link, &enslave_handler);
912 log_struct_link(LOG_WARNING, link,
913 "MESSAGE=%s: could not enslave by '%s': %s",
914 link->ifname, link->network->vlan->name,
915 strerror(-r), NETDEV(link->network->vlan),
917 link_enter_failed(link);
927 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
928 Link *link = userdata;
933 if (link->state == LINK_STATE_FAILED)
936 r = sd_rtnl_message_get_errno(m);
938 log_struct_link(LOG_ERR, link,
939 "MESSAGE=%s: could not get state: %s",
940 link->ifname, strerror(-r),
943 link_enter_failed(link);
947 log_debug_link(link, "got link state");
949 link_update(link, m);
954 static int link_get(Link *link) {
955 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
959 assert(link->manager);
960 assert(link->manager->rtnl);
962 log_debug_link(link, "requesting link status");
964 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
966 log_error_link(link, "Could not allocate RTM_GETLINK message");
970 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
973 "Could not send rtnetlink message: %s", strerror(-r));
980 int link_configure(Link *link) {
984 assert(link->network);
985 assert(link->state == _LINK_STATE_INVALID);
989 link_enter_failed(link);
993 return link_enter_enslave(link);
996 int link_update(Link *link, sd_rtnl_message *m) {
1005 if (link->state == LINK_STATE_FAILED)
1008 r = sd_rtnl_message_link_get_flags(m, &flags);
1010 log_warning_link(link, "Could not get link flags");
1014 while (sd_rtnl_message_read(m, &type, &data) > 0) {
1015 if (type == IFLA_MTU && link->network->dhcp &&
1016 link->network->dhcp_mtu && !link->original_mtu) {
1017 link->original_mtu = *(uint16_t *) data;
1018 log_debug_link(link, "saved original MTU: %" PRIu16,
1019 link->original_mtu);
1023 return link_update_flags(link, flags);