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"
30 int link_new(Manager *manager, struct udev_device *device, Link **ret) {
31 _cleanup_link_free_ Link *link = NULL;
33 struct ether_addr *mac_addr;
44 link->manager = manager;
45 link->state = _LINK_STATE_INVALID;
47 link->ifindex = udev_device_get_ifindex(device);
48 if (link->ifindex <= 0)
51 mac = udev_device_get_sysattr_value(device, "address");
53 mac_addr = ether_aton(mac);
55 memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
58 ifname = udev_device_get_sysname(device);
59 link->ifname = strdup(ifname);
61 r = hashmap_put(manager->links, &link->ifindex, link);
71 void link_free(Link *link) {
75 assert(link->manager);
78 sd_dhcp_client_free(link->dhcp);
80 route_free(link->dhcp_route);
81 link->dhcp_route = NULL;
83 address_free(link->dhcp_address);
84 link->dhcp_address = NULL;
86 hashmap_remove(link->manager->links, &link->ifindex);
93 int link_add(Manager *m, struct udev_device *device, Link **ret) {
103 ifindex = udev_device_get_ifindex(device);
104 link = hashmap_get(m->links, &ifindex);
110 r = link_new(m, device, &link);
116 devtype = udev_device_get_devtype(device);
117 if (streq_ptr(devtype, "bridge")) {
118 r = bridge_set_link(m, link);
119 if (r < 0 && r != -ENOENT)
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_warning_link(link, "could not set route: %s", strerror(-r));
171 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
173 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
174 log_debug_link(link, "routes set");
175 link_enter_configured(link);
181 static int link_enter_set_routes(Link *link) {
186 assert(link->network);
187 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
189 link->state = LINK_STATE_SETTING_ROUTES;
191 if (!link->network->static_routes && !link->dhcp_route)
192 return link_enter_configured(link);
194 log_debug_link(link, "setting routes");
196 LIST_FOREACH(static_routes, route, link->network->static_routes) {
197 r = route_configure(route, link, &route_handler);
199 log_warning_link(link,
200 "could not set routes: %s", strerror(-r));
201 link_enter_failed(link);
205 link->route_messages ++;
208 if (link->dhcp_route) {
209 r = route_configure(link->dhcp_route, link, &route_handler);
211 log_warning_link(link,
212 "could not set routes: %s", strerror(-r));
213 link_enter_failed(link);
217 link->route_messages ++;
223 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
224 Link *link = userdata;
229 assert(link->ifname);
230 assert(link->addr_messages > 0);
231 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
233 link->addr_messages --;
235 if (link->state == LINK_STATE_FAILED)
238 r = sd_rtnl_message_get_errno(m);
239 if (r < 0 && r != -EEXIST)
240 log_struct_link(LOG_ERR, link,
241 "MESSAGE=%s: could not set address: %s",
242 link->ifname, strerror(-r),
246 if (link->addr_messages == 0) {
247 log_debug_link(link, "addresses set");
248 link_enter_set_routes(link);
254 static int link_enter_set_addresses(Link *link) {
259 assert(link->network);
260 assert(link->state != _LINK_STATE_INVALID);
262 link->state = LINK_STATE_SETTING_ADDRESSES;
264 if (!link->network->static_addresses && !link->dhcp_address)
265 return link_enter_set_routes(link);
267 log_debug_link(link, "setting addresses");
269 LIST_FOREACH(static_addresses, address, link->network->static_addresses) {
270 r = address_configure(address, link, &address_handler);
272 log_warning_link(link,
273 "could not set addresses: %s", strerror(-r));
274 link_enter_failed(link);
278 link->addr_messages ++;
281 if (link->dhcp_address) {
282 r = address_configure(link->dhcp_address, link, &address_handler);
284 log_warning_link(link,
285 "could not set addresses: %s", strerror(-r));
286 link_enter_failed(link);
290 link->addr_messages ++;
296 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
297 Link *link = userdata;
302 assert(link->ifname);
304 if (link->state == LINK_STATE_FAILED)
307 r = sd_rtnl_message_get_errno(m);
308 if (r < 0 && r != -EEXIST)
309 log_warning_link(link, "could not drop address: %s", strerror(-r));
314 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
317 r = sd_bus_message_get_errno(m);
319 log_warning("Could not set hostname: %s", strerror(-r));
324 static int set_hostname(sd_bus *bus, const char *hostname) {
325 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
330 log_debug("Setting transient hostname: '%s'", hostname);
332 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
333 log_info("Not connected to system bus, ignoring transient hostname.");
337 r = sd_bus_message_new_method_call(
339 "org.freedesktop.hostname1",
340 "/org/freedesktop/hostname1",
341 "org.freedesktop.hostname1",
347 r = sd_bus_message_append(m, "sb", hostname, false);
351 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
353 log_error("Could not set transient hostname: %s", strerror(-r));
358 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
359 Link *link = userdata;
364 assert(link->ifname);
366 if (link->state == LINK_STATE_FAILED)
369 r = sd_rtnl_message_get_errno(m);
370 if (r < 0 && r != -EEXIST)
371 log_warning_link(link, "Could not set MTU: %s", strerror(-r));
376 static int link_set_mtu(Link *link, uint32_t mtu) {
377 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
381 assert(link->manager);
382 assert(link->manager->rtnl);
384 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
386 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
388 log_error_link(link, "Could not allocate RTM_SETLINK message");
392 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
394 log_error_link(link, "Could not append MTU: %s", strerror(-r));
398 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
401 "Could not send rtnetlink message: %s", strerror(-r));
408 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
409 Link *link = userdata;
410 struct in_addr address;
411 struct in_addr netmask;
412 struct in_addr gateway;
417 assert(link->network);
418 assert(link->manager);
420 if (link->state == LINK_STATE_FAILED)
424 log_warning_link(link, "DHCP error: %s", strerror(-event));
425 link_enter_failed(link);
429 if (event == DHCP_EVENT_NO_LEASE)
430 log_debug_link(link, "IP address in use.");
432 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
433 event == DHCP_EVENT_STOP) {
434 if (link->dhcp_address) {
435 address_drop(link->dhcp_address, link, address_drop_handler);
437 address_free(link->dhcp_address);
438 link->dhcp_address = NULL;
441 if (link->dhcp_route) {
442 route_free(link->dhcp_route);
443 link->dhcp_route = NULL;
446 if (link->network->dhcp_mtu) {
449 r = sd_dhcp_client_get_mtu(client, &mtu);
450 if (r >= 0 && link->original_mtu != mtu) {
451 r = link_set_mtu(link, link->original_mtu);
453 log_warning_link(link, "DHCP error: could not reset MTU");
454 link_enter_failed(link);
460 if (link->network->dhcp_hostname) {
461 r = set_hostname(link->manager->bus, "");
463 log_error("Failed to reset transient hostname");
467 r = sd_dhcp_client_get_address(client, &address);
469 log_warning_link(link, "DHCP error: no address");
470 link_enter_failed(link);
474 r = sd_dhcp_client_get_netmask(client, &netmask);
476 log_warning_link(link, "DHCP error: no netmask");
477 link_enter_failed(link);
481 prefixlen = sd_dhcp_client_prefixlen(&netmask);
483 log_warning_link(link, "DHCP error: no prefixlen");
484 link_enter_failed(link);
488 r = sd_dhcp_client_get_router(client, &gateway);
490 log_warning_link(link, "DHCP error: no router");
491 link_enter_failed(link);
495 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
496 _cleanup_address_free_ Address *addr = NULL;
497 _cleanup_route_free_ Route *rt = NULL;
498 struct in_addr *nameservers;
499 size_t nameservers_size;
501 log_struct_link(LOG_INFO, link,
502 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
504 ADDRESS_FMT_VAL(address),
506 ADDRESS_FMT_VAL(gateway),
507 "ADDRESS=%u.%u.%u.%u",
508 ADDRESS_FMT_VAL(address),
511 "GATEWAY=%u.%u.%u.%u",
512 ADDRESS_FMT_VAL(gateway),
515 r = address_new_dynamic(&addr);
517 log_error_link(link, "Could not allocate address");
518 link_enter_failed(link);
522 addr->family = AF_INET;
523 addr->in_addr.in = address;
524 addr->prefixlen = prefixlen;
525 addr->netmask = netmask;
527 r = route_new_dynamic(&rt);
529 log_error_link(link, "Could not allocate route");
530 link_enter_failed(link);
534 rt->family = AF_INET;
535 rt->in_addr.in = gateway;
537 link->dhcp_address = addr;
538 link->dhcp_route = rt;
542 if (link->network->dhcp_dns) {
543 r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
545 r = manager_update_resolv_conf(link->manager);
547 log_error("Failed to update resolv.conf");
551 if (link->network->dhcp_mtu) {
554 r = sd_dhcp_client_get_mtu(client, &mtu);
556 r = link_set_mtu(link, mtu);
558 log_error_link(link, "Failed to set MTU "
563 if (link->network->dhcp_hostname) {
564 const char *hostname;
566 r = sd_dhcp_client_get_hostname(client, &hostname);
568 r = set_hostname(link->manager->bus, hostname);
570 log_error("Failed to set transient hostname "
571 "to '%s'", hostname);
575 link_enter_set_addresses(link);
581 static int link_acquire_conf(Link *link) {
585 assert(link->network);
586 assert(link->network->dhcp);
587 assert(link->manager);
588 assert(link->manager->event);
591 link->dhcp = sd_dhcp_client_new(link->manager->event);
595 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
599 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
603 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
607 if (link->network->dhcp_mtu) {
608 r = sd_dhcp_client_set_request_option(link->dhcp, 26);
614 log_debug_link(link, "acquiring DHCPv4 lease");
616 r = sd_dhcp_client_start(link->dhcp);
623 static int link_update_flags(Link *link, unsigned flags) {
627 assert(link->network);
629 if (link->state == LINK_STATE_FAILED)
632 if (link->flags == flags) {
633 log_debug_link(link, "link status unchanged: %#.8x", flags);
637 if ((link->flags & IFF_UP) != (flags & IFF_UP))
639 "power %s", flags & IFF_UP ? "on": "off");
641 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
642 if (flags & IFF_LOWER_UP) {
643 log_info_link(link, "carrier on");
645 if (link->network->dhcp) {
646 r = link_acquire_conf(link);
648 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
649 link_enter_failed(link);
654 log_info_link(link, "carrier off");
656 if (link->network->dhcp) {
657 r = sd_dhcp_client_stop(link->dhcp);
659 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
660 link_enter_failed(link);
668 "link status updated: %#.8x -> %#.8x", link->flags, flags);
675 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
676 Link *link = userdata;
681 if (link->state == LINK_STATE_FAILED)
684 r = sd_rtnl_message_get_errno(m);
686 log_warning_link(link,
687 "could not bring up interface: %s", strerror(-r));
688 link_enter_failed(link);
691 link_update_flags(link, link->flags | IFF_UP);
696 static int link_up(Link *link) {
697 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
701 assert(link->manager);
702 assert(link->manager->rtnl);
704 log_debug_link(link, "bringing link up");
706 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
708 log_error_link(link, "Could not allocate RTM_SETLINK message");
712 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
714 log_error_link(link, "Could not set link flags: %s", strerror(-r));
718 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
721 "Could not send rtnetlink message: %s", strerror(-r));
728 static int link_bridge_joined(Link *link) {
732 assert(link->state == LINK_STATE_JOINING_BRIDGE);
733 assert(link->network);
737 link_enter_failed(link);
741 if (!link->network->dhcp)
742 return link_enter_set_addresses(link);
747 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
748 Link *link = userdata;
752 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
753 assert(link->network);
755 if (link->state == LINK_STATE_FAILED)
758 r = sd_rtnl_message_get_errno(m);
760 log_struct_link(LOG_ERR, link,
761 "MESSAGE=%s: could not join bridge '%s': %s",
762 link->ifname, link->network->bridge->name, strerror(-r),
763 BRIDGE(link->network->bridge),
765 link_enter_failed(link);
769 log_struct_link(LOG_DEBUG, link,
770 "MESSAGE=%s: joined bridge '%s'",
771 link->network->bridge->name,
772 BRIDGE(link->network->bridge),
775 link_bridge_joined(link);
780 static int link_enter_join_bridge(Link *link) {
784 assert(link->network);
785 assert(link->state == _LINK_STATE_INVALID);
787 link->state = LINK_STATE_JOINING_BRIDGE;
789 if (!link->network->bridge)
790 return link_bridge_joined(link);
792 log_struct_link(LOG_DEBUG, link,
793 "MESSAGE=%s: joining bridge '%s'",
794 link->network->bridge->name,
795 BRIDGE(link->network->bridge),
797 log_debug_link(link, "joining bridge");
799 r = bridge_join(link->network->bridge, link, &bridge_handler);
801 log_struct_link(LOG_WARNING, link,
802 "MESSAGE=%s: could not join bridge '%s': %s",
803 link->network->bridge->name, strerror(-r),
804 BRIDGE(link->network->bridge),
806 link_enter_failed(link);
813 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
814 Link *link = userdata;
819 if (link->state == LINK_STATE_FAILED)
822 r = sd_rtnl_message_get_errno(m);
824 log_warning_link(link, "could not get state: %s", strerror(-r));
825 link_enter_failed(link);
828 log_debug_link(link, "got link state");
830 link_update(link, m);
835 static int link_get(Link *link) {
836 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
840 assert(link->manager);
841 assert(link->manager->rtnl);
843 log_debug_link(link, "requesting link status");
845 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
847 log_error_link(link, "Could not allocate RTM_GETLINK message");
851 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
854 "Could not send rtnetlink message: %s", strerror(-r));
861 int link_configure(Link *link) {
865 assert(link->network);
866 assert(link->state == _LINK_STATE_INVALID);
870 link_enter_failed(link);
874 return link_enter_join_bridge(link);
877 int link_update(Link *link, sd_rtnl_message *m) {
886 if (link->state == LINK_STATE_FAILED)
889 r = sd_rtnl_message_link_get_flags(m, &flags);
891 log_warning_link(link, "Could not get link flags");
895 while (sd_rtnl_message_read(m, &type, &data) > 0) {
896 if (type == IFLA_MTU && link->network->dhcp &&
897 link->network->dhcp_mtu && !link->original_mtu) {
898 link->original_mtu = *(uint16_t *) data;
899 log_debug_link(link, "saved original MTU: %" PRIu16,
904 return link_update_flags(link, flags);