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);
79 sd_dhcp_client_free(link->dhcp);
81 route_free(link->dhcp_route);
82 link->dhcp_route = NULL;
84 address_free(link->dhcp_address);
85 link->dhcp_address = NULL;
87 hashmap_remove(link->manager->links, &link->ifindex);
94 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 r = network_get(m, device, &network);
118 return r == -ENOENT ? 0 : r;
120 r = network_apply(m, network, link);
127 static int link_enter_configured(Link *link) {
129 assert(link->state == LINK_STATE_SETTING_ROUTES);
131 log_info_link(link, "link configured");
133 link->state = LINK_STATE_CONFIGURED;
138 static void link_enter_failed(Link *link) {
141 log_warning_link(link, "failed");
143 link->state = LINK_STATE_FAILED;
146 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
147 Link *link = userdata;
150 assert(link->route_messages > 0);
151 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
152 link->state == LINK_STATE_SETTING_ROUTES ||
153 link->state == LINK_STATE_FAILED);
155 link->route_messages --;
157 if (link->state == LINK_STATE_FAILED)
160 r = sd_rtnl_message_get_errno(m);
161 if (r < 0 && r != -EEXIST)
162 log_struct_link(LOG_WARNING, link,
163 "MESSAGE=%s: could not set route: %s",
164 link->ifname, strerror(-r),
168 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
170 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
171 log_debug_link(link, "routes set");
172 link_enter_configured(link);
178 static int link_enter_set_routes(Link *link) {
183 assert(link->network);
184 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
186 link->state = LINK_STATE_SETTING_ROUTES;
188 if (!link->network->static_routes && !link->dhcp_route)
189 return link_enter_configured(link);
191 log_debug_link(link, "setting routes");
193 LIST_FOREACH(static_routes, route, link->network->static_routes) {
194 r = route_configure(route, link, &route_handler);
196 log_warning_link(link,
197 "could not set routes: %s", strerror(-r));
198 link_enter_failed(link);
202 link->route_messages ++;
205 if (link->dhcp_route) {
206 r = route_configure(link->dhcp_route, link, &route_handler);
208 log_warning_link(link,
209 "could not set routes: %s", strerror(-r));
210 link_enter_failed(link);
214 link->route_messages ++;
220 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
221 Link *link = userdata;
226 assert(link->ifname);
227 assert(link->addr_messages > 0);
228 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
230 link->addr_messages --;
232 if (link->state == LINK_STATE_FAILED)
235 r = sd_rtnl_message_get_errno(m);
236 if (r < 0 && r != -EEXIST)
237 log_struct_link(LOG_WARNING, link,
238 "MESSAGE=%s: could not set address: %s",
239 link->ifname, strerror(-r),
243 if (link->addr_messages == 0) {
244 log_debug_link(link, "addresses set");
245 link_enter_set_routes(link);
251 static int link_enter_set_addresses(Link *link) {
256 assert(link->network);
257 assert(link->state != _LINK_STATE_INVALID);
259 link->state = LINK_STATE_SETTING_ADDRESSES;
261 if (!link->network->static_addresses && !link->dhcp_address)
262 return link_enter_set_routes(link);
264 log_debug_link(link, "setting addresses");
266 LIST_FOREACH(static_addresses, address, link->network->static_addresses) {
267 r = address_configure(address, link, &address_handler);
269 log_warning_link(link,
270 "could not set addresses: %s", strerror(-r));
271 link_enter_failed(link);
275 link->addr_messages ++;
278 if (link->dhcp_address) {
279 r = address_configure(link->dhcp_address, link, &address_handler);
281 log_warning_link(link,
282 "could not set addresses: %s", strerror(-r));
283 link_enter_failed(link);
287 link->addr_messages ++;
293 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
294 Link *link = userdata;
299 assert(link->ifname);
301 if (link->state == LINK_STATE_FAILED)
304 r = sd_rtnl_message_get_errno(m);
305 if (r < 0 && r != -ENOENT)
306 log_struct_link(LOG_WARNING, link,
307 "MESSAGE=%s: could not drop address: %s",
308 link->ifname, strerror(-r),
315 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
318 r = sd_bus_message_get_errno(m);
320 log_warning("Could not set hostname: %s", strerror(-r));
325 static int set_hostname(sd_bus *bus, const char *hostname) {
326 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
331 log_debug("Setting transient hostname: '%s'", hostname);
333 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
334 log_info("Not connected to system bus, ignoring transient hostname.");
338 r = sd_bus_message_new_method_call(
340 "org.freedesktop.hostname1",
341 "/org/freedesktop/hostname1",
342 "org.freedesktop.hostname1",
348 r = sd_bus_message_append(m, "sb", hostname, false);
352 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
354 log_error("Could not set transient hostname: %s", strerror(-r));
359 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
360 Link *link = userdata;
365 assert(link->ifname);
367 if (link->state == LINK_STATE_FAILED)
370 r = sd_rtnl_message_get_errno(m);
372 log_struct_link(LOG_WARNING, link,
373 "MESSAGE=%s: could not set MTU: %s",
374 link->ifname, strerror(-r),
381 static int link_set_mtu(Link *link, uint32_t mtu) {
382 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
386 assert(link->manager);
387 assert(link->manager->rtnl);
389 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
391 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
393 log_error_link(link, "Could not allocate RTM_SETLINK message");
397 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
399 log_error_link(link, "Could not append MTU: %s", strerror(-r));
403 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
406 "Could not send rtnetlink message: %s", strerror(-r));
413 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
414 Link *link = userdata;
415 struct in_addr address;
416 struct in_addr netmask;
417 struct in_addr gateway;
422 assert(link->network);
423 assert(link->manager);
425 if (link->state == LINK_STATE_FAILED)
429 log_warning_link(link, "DHCP error: %s", strerror(-event));
430 link_enter_failed(link);
434 if (event == DHCP_EVENT_NO_LEASE)
435 log_debug_link(link, "IP address in use.");
437 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
438 event == DHCP_EVENT_STOP) {
439 if (link->network->dhcp_critical) {
440 log_warning_link(link, "DHCPv4 connection considered system critical, "
441 "ignoring request to reconfigure it down.");
445 if (link->dhcp_address) {
446 address_drop(link->dhcp_address, link, address_drop_handler);
448 address_free(link->dhcp_address);
449 link->dhcp_address = NULL;
452 if (link->dhcp_route) {
453 route_free(link->dhcp_route);
454 link->dhcp_route = NULL;
457 if (link->network->dhcp_mtu) {
460 r = sd_dhcp_client_get_mtu(client, &mtu);
461 if (r >= 0 && link->original_mtu != mtu) {
462 r = link_set_mtu(link, link->original_mtu);
464 log_warning_link(link, "DHCP error: could not reset MTU");
465 link_enter_failed(link);
471 if (link->network->dhcp_hostname) {
472 r = set_hostname(link->manager->bus, "");
474 log_error("Failed to reset transient hostname");
478 r = sd_dhcp_client_get_address(client, &address);
480 log_warning_link(link, "DHCP error: no address");
481 link_enter_failed(link);
485 r = sd_dhcp_client_get_netmask(client, &netmask);
487 log_warning_link(link, "DHCP error: no netmask");
488 link_enter_failed(link);
492 prefixlen = net_netmask_to_prefixlen(&netmask);
494 r = sd_dhcp_client_get_router(client, &gateway);
496 log_warning_link(link, "DHCP error: no router");
497 link_enter_failed(link);
501 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
502 _cleanup_address_free_ Address *addr = NULL;
503 _cleanup_route_free_ Route *rt = NULL;
504 struct in_addr *nameservers;
505 size_t nameservers_size;
507 log_struct_link(LOG_INFO, link,
508 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
510 ADDRESS_FMT_VAL(address),
512 ADDRESS_FMT_VAL(gateway),
513 "ADDRESS=%u.%u.%u.%u",
514 ADDRESS_FMT_VAL(address),
517 "GATEWAY=%u.%u.%u.%u",
518 ADDRESS_FMT_VAL(gateway),
521 r = address_new_dynamic(&addr);
523 log_error_link(link, "Could not allocate address");
524 link_enter_failed(link);
528 addr->family = AF_INET;
529 addr->in_addr.in = address;
530 addr->prefixlen = prefixlen;
531 addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
533 r = route_new_dynamic(&rt);
535 log_error_link(link, "Could not allocate route");
536 link_enter_failed(link);
540 rt->family = AF_INET;
541 rt->in_addr.in = gateway;
543 link->dhcp_address = addr;
544 link->dhcp_route = rt;
548 if (link->network->dhcp_dns) {
549 r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
551 r = manager_update_resolv_conf(link->manager);
553 log_error("Failed to update resolv.conf");
557 if (link->network->dhcp_mtu) {
560 r = sd_dhcp_client_get_mtu(client, &mtu);
562 r = link_set_mtu(link, mtu);
564 log_error_link(link, "Failed to set MTU "
569 if (link->network->dhcp_hostname) {
570 const char *hostname;
572 r = sd_dhcp_client_get_hostname(client, &hostname);
574 r = set_hostname(link->manager->bus, hostname);
576 log_error("Failed to set transient hostname "
577 "to '%s'", hostname);
581 link_enter_set_addresses(link);
587 static int link_acquire_conf(Link *link) {
591 assert(link->network);
592 assert(link->network->dhcp);
593 assert(link->manager);
594 assert(link->manager->event);
597 r = sd_dhcp_client_new(&link->dhcp);
601 r = sd_dhcp_client_attach_event(link->dhcp, NULL, 0);
605 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
609 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
613 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
617 if (link->network->dhcp_mtu) {
618 r = sd_dhcp_client_set_request_option(link->dhcp, 26);
624 log_debug_link(link, "acquiring DHCPv4 lease");
626 r = sd_dhcp_client_start(link->dhcp);
633 static int link_update_flags(Link *link, unsigned flags) {
637 assert(link->network);
639 if (link->state == LINK_STATE_FAILED)
642 if (link->flags == flags) {
643 log_debug_link(link, "link status unchanged: %#.8x", flags);
647 if ((link->flags & IFF_UP) != (flags & IFF_UP))
649 "link is %s", flags & IFF_UP ? "up": "down");
651 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
652 if (flags & IFF_LOWER_UP) {
653 log_info_link(link, "carrier on");
655 if (link->network->dhcp) {
656 r = link_acquire_conf(link);
658 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
659 link_enter_failed(link);
664 log_info_link(link, "carrier off");
666 if (link->network->dhcp) {
667 r = sd_dhcp_client_stop(link->dhcp);
669 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
670 link_enter_failed(link);
678 "link status updated: %#.8x -> %#.8x", link->flags, flags);
685 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
686 Link *link = userdata;
691 if (link->state == LINK_STATE_FAILED)
694 r = sd_rtnl_message_get_errno(m);
696 log_struct_link(LOG_ERR, link,
697 "MESSAGE=%s: could not bring up interface: %s",
698 link->ifname, strerror(-r),
701 link_enter_failed(link);
705 link_update_flags(link, link->flags | IFF_UP);
710 static int link_up(Link *link) {
711 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
715 assert(link->manager);
716 assert(link->manager->rtnl);
718 log_debug_link(link, "bringing link up");
720 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
722 log_error_link(link, "Could not allocate RTM_SETLINK message");
726 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
728 log_error_link(link, "Could not set link flags: %s", strerror(-r));
732 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
735 "Could not send rtnetlink message: %s", strerror(-r));
742 static int link_enslaved(Link *link) {
746 assert(link->state == LINK_STATE_ENSLAVING);
747 assert(link->network);
751 link_enter_failed(link);
755 if (!link->network->dhcp)
756 return link_enter_set_addresses(link);
761 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
762 Link *link = userdata;
766 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
767 assert(link->network);
771 if (link->state == LINK_STATE_FAILED)
774 r = sd_rtnl_message_get_errno(m);
776 log_struct_link(LOG_ERR, link,
777 "MESSAGE=%s: could not enslave: %s",
778 link->ifname, strerror(-r),
781 link_enter_failed(link);
785 log_debug_link(link, "enslaved");
787 if (link->enslaving == 0)
793 static int link_enter_enslave(Link *link) {
797 assert(link->network);
798 assert(link->state == _LINK_STATE_INVALID);
800 link->state = LINK_STATE_ENSLAVING;
802 if (!link->network->bridge && !link->network->bond && !link->network->vlan)
803 return link_enslaved(link);
805 if (link->network->bridge) {
806 log_struct_link(LOG_DEBUG, link,
807 "MESSAGE=%s: enslaving by '%s'",
808 link->ifname, link->network->bridge->name,
809 NETDEV(link->network->bridge),
812 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
814 log_struct_link(LOG_WARNING, link,
815 "MESSAGE=%s: could not enslave by '%s': %s",
816 link->ifname, link->network->bridge->name, strerror(-r),
817 NETDEV(link->network->bridge),
819 link_enter_failed(link);
826 if (link->network->vlan) {
827 log_struct_link(LOG_DEBUG, link,
828 "MESSAGE=%s: enslaving by '%s'",
829 link->ifname, link->network->vlan->name,
830 NETDEV(link->network->vlan),
833 r = netdev_enslave(link->network->vlan, link, &enslave_handler);
835 log_struct_link(LOG_WARNING, link,
836 "MESSAGE=%s: could not enslave by '%s': %s",
837 link->ifname, link->network->vlan->name,
838 strerror(-r), NETDEV(link->network->vlan),
840 link_enter_failed(link);
850 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
851 Link *link = userdata;
856 if (link->state == LINK_STATE_FAILED)
859 r = sd_rtnl_message_get_errno(m);
861 log_struct_link(LOG_ERR, link,
862 "MESSAGE=%s: could not get state: %s",
863 link->ifname, strerror(-r),
866 link_enter_failed(link);
870 log_debug_link(link, "got link state");
872 link_update(link, m);
877 static int link_get(Link *link) {
878 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
882 assert(link->manager);
883 assert(link->manager->rtnl);
885 log_debug_link(link, "requesting link status");
887 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
889 log_error_link(link, "Could not allocate RTM_GETLINK message");
893 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
896 "Could not send rtnetlink message: %s", strerror(-r));
903 int link_configure(Link *link) {
907 assert(link->network);
908 assert(link->state == _LINK_STATE_INVALID);
912 link_enter_failed(link);
916 return link_enter_enslave(link);
919 int link_update(Link *link, sd_rtnl_message *m) {
928 if (link->state == LINK_STATE_FAILED)
931 r = sd_rtnl_message_link_get_flags(m, &flags);
933 log_warning_link(link, "Could not get link flags");
937 while (sd_rtnl_message_read(m, &type, &data) > 0) {
938 if (type == IFLA_MTU && link->network->dhcp &&
939 link->network->dhcp_mtu && !link->original_mtu) {
940 link->original_mtu = *(uint16_t *) data;
941 log_debug_link(link, "saved original MTU: %" PRIu16,
946 return link_update_flags(link, flags);