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;
331 log_debug("Setting transient hostname: '%s'", hostname);
333 r = sd_bus_message_new_method_call(
335 "org.freedesktop.hostname1",
336 "/org/freedesktop/hostname1",
337 "org.freedesktop.hostname1",
343 r = sd_bus_message_append(m, "sb", hostname, false);
347 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
349 log_error("Could not set transient hostname: %s", strerror(-r));
354 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
355 Link *link = userdata;
360 assert(link->ifname);
362 if (link->state == LINK_STATE_FAILED)
365 r = sd_rtnl_message_get_errno(m);
366 if (r < 0 && r != -EEXIST)
367 log_warning_link(link, "Could not set MTU: %s", strerror(-r));
372 static int link_set_mtu(Link *link, uint32_t mtu) {
373 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
377 assert(link->manager);
378 assert(link->manager->rtnl);
380 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
382 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
384 log_error_link(link, "Could not allocate RTM_SETLINK message");
388 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
390 log_error_link(link, "Could not append MTU: %s", strerror(-r));
394 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
397 "Could not send rtnetlink message: %s", strerror(-r));
404 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
405 Link *link = userdata;
406 struct in_addr address;
407 struct in_addr netmask;
408 struct in_addr gateway;
413 assert(link->network);
414 assert(link->manager);
416 if (link->state == LINK_STATE_FAILED)
420 log_warning_link(link, "DHCP error: %s", strerror(-event));
421 link_enter_failed(link);
425 if (event == DHCP_EVENT_NO_LEASE)
426 log_debug_link(link, "IP address in use.");
428 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
429 event == DHCP_EVENT_STOP) {
430 if (link->dhcp_address) {
431 address_drop(link->dhcp_address, link, address_drop_handler);
433 address_free(link->dhcp_address);
434 link->dhcp_address = NULL;
437 if (link->dhcp_route) {
438 route_free(link->dhcp_route);
439 link->dhcp_route = NULL;
442 if (link->network->dhcp_mtu) {
445 r = sd_dhcp_client_get_mtu(client, &mtu);
446 if (r >= 0 && link->original_mtu != mtu) {
447 r = link_set_mtu(link, link->original_mtu);
449 log_warning_link(link, "DHCP error: could not reset MTU");
450 link_enter_failed(link);
456 if (link->network->dhcp_hostname) {
457 r = set_hostname(link->manager->bus, "");
459 log_error("Failed to reset transient hostname");
463 r = sd_dhcp_client_get_address(client, &address);
465 log_warning_link(link, "DHCP error: no address");
466 link_enter_failed(link);
470 r = sd_dhcp_client_get_netmask(client, &netmask);
472 log_warning_link(link, "DHCP error: no netmask");
473 link_enter_failed(link);
477 prefixlen = sd_dhcp_client_prefixlen(&netmask);
479 log_warning_link(link, "DHCP error: no prefixlen");
480 link_enter_failed(link);
484 r = sd_dhcp_client_get_router(client, &gateway);
486 log_warning_link(link, "DHCP error: no router");
487 link_enter_failed(link);
491 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
492 _cleanup_address_free_ Address *addr = NULL;
493 _cleanup_route_free_ Route *rt = NULL;
494 struct in_addr **nameservers;
496 log_struct_link(LOG_INFO, link,
497 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
499 ADDRESS_FMT_VAL(address),
501 ADDRESS_FMT_VAL(gateway),
502 "ADDRESS=%u.%u.%u.%u",
503 ADDRESS_FMT_VAL(address),
506 "GATEWAY=%u.%u.%u.%u",
507 ADDRESS_FMT_VAL(gateway),
510 r = address_new_dynamic(&addr);
512 log_error_link(link, "Could not allocate address");
513 link_enter_failed(link);
517 addr->family = AF_INET;
518 addr->in_addr.in = address;
519 addr->prefixlen = prefixlen;
520 addr->netmask = netmask;
522 r = route_new_dynamic(&rt);
524 log_error_link(link, "Could not allocate route");
525 link_enter_failed(link);
529 rt->family = AF_INET;
530 rt->in_addr.in = gateway;
532 link->dhcp_address = addr;
533 link->dhcp_route = rt;
537 if (link->network->dhcp_dns) {
538 r = sd_dhcp_client_get_dns(client, &nameservers);
540 r = manager_update_resolv_conf(link->manager);
542 log_error("Failed to update resolv.conf");
546 if (link->network->dhcp_mtu) {
549 r = sd_dhcp_client_get_mtu(client, &mtu);
551 r = link_set_mtu(link, mtu);
553 log_error_link(link, "Failed to set MTU "
558 if (link->network->dhcp_hostname) {
559 const char *hostname;
561 r = sd_dhcp_client_get_hostname(client, &hostname);
563 r = set_hostname(link->manager->bus, hostname);
565 log_error("Failed to set transient hostname "
566 "to '%s'", hostname);
570 link_enter_set_addresses(link);
576 static int link_acquire_conf(Link *link) {
580 assert(link->network);
581 assert(link->network->dhcp);
582 assert(link->manager);
583 assert(link->manager->event);
586 link->dhcp = sd_dhcp_client_new(link->manager->event);
590 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
594 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
598 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
602 if (link->network->dhcp_mtu) {
603 r = sd_dhcp_client_set_request_option(link->dhcp, 26);
609 log_debug_link(link, "acquiring DHCPv4 lease");
611 r = sd_dhcp_client_start(link->dhcp);
618 static int link_update_flags(Link *link, unsigned flags) {
622 assert(link->network);
624 if (link->state == LINK_STATE_FAILED)
627 if (link->flags == flags) {
628 log_debug_link(link, "link status unchanged: %#.8x", flags);
632 if ((link->flags & IFF_UP) != (flags & IFF_UP))
634 "power %s", flags & IFF_UP ? "on": "off");
636 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
637 if (flags & IFF_LOWER_UP) {
638 log_info_link(link, "carrier on");
640 if (link->network->dhcp) {
641 r = link_acquire_conf(link);
643 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
644 link_enter_failed(link);
649 log_info_link(link, "carrier off");
651 if (link->network->dhcp) {
652 r = sd_dhcp_client_stop(link->dhcp);
654 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
655 link_enter_failed(link);
663 "link status updated: %#.8x -> %#.8x", link->flags, flags);
670 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
671 Link *link = userdata;
676 if (link->state == LINK_STATE_FAILED)
679 r = sd_rtnl_message_get_errno(m);
681 log_warning_link(link,
682 "could not bring up interface: %s", strerror(-r));
683 link_enter_failed(link);
686 link_update_flags(link, link->flags | IFF_UP);
691 static int link_up(Link *link) {
692 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
696 assert(link->manager);
697 assert(link->manager->rtnl);
699 log_debug_link(link, "bringing link up");
701 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
703 log_error_link(link, "Could not allocate RTM_SETLINK message");
707 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
709 log_error_link(link, "Could not set link flags: %s", strerror(-r));
713 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
716 "Could not send rtnetlink message: %s", strerror(-r));
723 static int link_bridge_joined(Link *link) {
727 assert(link->state == LINK_STATE_JOINING_BRIDGE);
728 assert(link->network);
732 link_enter_failed(link);
736 if (!link->network->dhcp)
737 return link_enter_set_addresses(link);
742 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
743 Link *link = userdata;
747 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
748 assert(link->network);
750 if (link->state == LINK_STATE_FAILED)
753 r = sd_rtnl_message_get_errno(m);
755 log_struct_link(LOG_ERR, link,
756 "MESSAGE=%s: could not join bridge '%s': %s",
757 link->ifname, link->network->bridge->name, strerror(-r),
758 BRIDGE(link->network->bridge),
760 link_enter_failed(link);
764 log_struct_link(LOG_DEBUG, link,
765 "MESSAGE=%s: joined bridge '%s'",
766 link->network->bridge->name,
767 BRIDGE(link->network->bridge),
770 link_bridge_joined(link);
775 static int link_enter_join_bridge(Link *link) {
779 assert(link->network);
780 assert(link->state == _LINK_STATE_INVALID);
782 link->state = LINK_STATE_JOINING_BRIDGE;
784 if (!link->network->bridge)
785 return link_bridge_joined(link);
787 log_struct_link(LOG_DEBUG, link,
788 "MESSAGE=%s: joining bridge '%s'",
789 link->network->bridge->name,
790 BRIDGE(link->network->bridge),
792 log_debug_link(link, "joining bridge");
794 r = bridge_join(link->network->bridge, link, &bridge_handler);
796 log_struct_link(LOG_WARNING, link,
797 "MESSAGE=%s: could not join bridge '%s': %s",
798 link->network->bridge->name, strerror(-r),
799 BRIDGE(link->network->bridge),
801 link_enter_failed(link);
808 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
809 Link *link = userdata;
814 if (link->state == LINK_STATE_FAILED)
817 r = sd_rtnl_message_get_errno(m);
819 log_warning_link(link, "could not get state: %s", strerror(-r));
820 link_enter_failed(link);
823 log_debug_link(link, "got link state");
825 link_update(link, m);
830 static int link_get(Link *link) {
831 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
835 assert(link->manager);
836 assert(link->manager->rtnl);
838 log_debug_link(link, "requesting link status");
840 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
842 log_error_link(link, "Could not allocate RTM_GETLINK message");
846 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
849 "Could not send rtnetlink message: %s", strerror(-r));
856 int link_configure(Link *link) {
860 assert(link->network);
861 assert(link->state == _LINK_STATE_INVALID);
865 link_enter_failed(link);
869 return link_enter_join_bridge(link);
872 int link_update(Link *link, sd_rtnl_message *m) {
881 if (link->state == LINK_STATE_FAILED)
884 r = sd_rtnl_message_link_get_flags(m, &flags);
886 log_warning_link(link, "Could not get link flags");
890 while (sd_rtnl_message_read(m, &type, &data) > 0) {
891 if (type == IFLA_MTU && link->network->dhcp &&
892 link->network->dhcp_mtu && !link->original_mtu) {
893 link->original_mtu = *(uint16_t *) data;
894 log_debug_link(link, "saved original MTU: %" PRIu16,
899 return link_update_flags(link, flags);