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 int dhcp_lease_lost(sd_dhcp_client *client, Link *link) {
419 if (link->dhcp_address) {
420 address_drop(link->dhcp_address, link, address_drop_handler);
422 address_free(link->dhcp_address);
423 link->dhcp_address = NULL;
426 if (link->dhcp_route) {
427 route_free(link->dhcp_route);
428 link->dhcp_route = NULL;
431 if (link->network->dhcp_mtu) {
434 r = sd_dhcp_client_get_mtu(client, &mtu);
435 if (r >= 0 && link->original_mtu != mtu) {
436 r = link_set_mtu(link, link->original_mtu);
438 log_warning_link(link, "DHCP error: could not reset MTU");
439 link_enter_failed(link);
445 if (link->network->dhcp_hostname) {
446 r = set_hostname(link->manager->bus, "");
448 log_error("Failed to reset transient hostname");
454 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
455 struct in_addr address;
456 struct in_addr netmask;
457 struct in_addr gateway;
459 _cleanup_address_free_ Address *addr = NULL;
460 _cleanup_route_free_ Route *rt = NULL;
461 struct in_addr *nameservers;
462 size_t nameservers_size;
468 r = sd_dhcp_client_get_address(client, &address);
470 log_warning_link(link, "DHCP error: no address: %s",
475 r = sd_dhcp_client_get_netmask(client, &netmask);
477 log_warning_link(link, "DHCP error: no netmask: %s",
482 prefixlen = net_netmask_to_prefixlen(&netmask);
484 r = sd_dhcp_client_get_router(client, &gateway);
486 log_warning_link(link, "DHCP error: no router: %s",
492 log_struct_link(LOG_INFO, link,
493 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
495 ADDRESS_FMT_VAL(address),
497 ADDRESS_FMT_VAL(gateway),
498 "ADDRESS=%u.%u.%u.%u",
499 ADDRESS_FMT_VAL(address),
502 "GATEWAY=%u.%u.%u.%u",
503 ADDRESS_FMT_VAL(gateway),
506 r = address_new_dynamic(&addr);
508 log_error_link(link, "Could not allocate address: %s",
513 addr->family = AF_INET;
514 addr->in_addr.in = address;
515 addr->prefixlen = prefixlen;
516 addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
518 r = route_new_dynamic(&rt);
520 log_error_link(link, "Could not allocate route: %s",
525 rt->family = AF_INET;
526 rt->in_addr.in = gateway;
528 link->dhcp_address = addr;
529 link->dhcp_route = rt;
533 if (link->network->dhcp_dns) {
534 r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
536 r = manager_update_resolv_conf(link->manager);
538 log_error("Failed to update resolv.conf");
542 if (link->network->dhcp_mtu) {
545 r = sd_dhcp_client_get_mtu(client, &mtu);
547 r = link_set_mtu(link, mtu);
549 log_error_link(link, "Failed to set MTU "
554 if (link->network->dhcp_hostname) {
555 const char *hostname;
557 r = sd_dhcp_client_get_hostname(client, &hostname);
559 r = set_hostname(link->manager->bus, hostname);
561 log_error("Failed to set transient hostname "
562 "to '%s'", hostname);
566 link_enter_set_addresses(link);
571 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
572 Link *link = userdata;
576 assert(link->network);
577 assert(link->manager);
579 if (link->state == LINK_STATE_FAILED)
583 case DHCP_EVENT_NO_LEASE:
584 log_debug_link(link, "IP address in use.");
586 case DHCP_EVENT_EXPIRED:
587 case DHCP_EVENT_STOP:
588 case DHCP_EVENT_IP_CHANGE:
589 if (link->network->dhcp_critical) {
590 log_error_link(link, "DHCPv4 connection considered system critical, "
591 "ignoring request to reconfigure it.");
595 r = dhcp_lease_lost(client, link);
597 link_enter_failed(link);
601 if (event == DHCP_EVENT_IP_CHANGE) {
602 r = dhcp_lease_acquired(client, link);
604 link_enter_failed(link);
610 case DHCP_EVENT_IP_ACQUIRE:
611 r = dhcp_lease_acquired(client, link);
613 link_enter_failed(link);
619 log_warning_link(link, "DHCP error: %s", strerror(-event));
621 log_warning_link(link, "DHCP unknown event: %d", event);
628 static int link_acquire_conf(Link *link) {
632 assert(link->network);
633 assert(link->network->dhcp);
634 assert(link->manager);
635 assert(link->manager->event);
638 r = sd_dhcp_client_new(&link->dhcp);
642 r = sd_dhcp_client_attach_event(link->dhcp, NULL, 0);
646 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
650 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
654 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
658 if (link->network->dhcp_mtu) {
659 r = sd_dhcp_client_set_request_option(link->dhcp, 26);
665 log_debug_link(link, "acquiring DHCPv4 lease");
667 r = sd_dhcp_client_start(link->dhcp);
674 static int link_update_flags(Link *link, unsigned flags) {
678 assert(link->network);
680 if (link->state == LINK_STATE_FAILED)
683 if (link->flags == flags) {
684 log_debug_link(link, "link status unchanged: %#.8x", flags);
688 if ((link->flags & IFF_UP) != (flags & IFF_UP))
690 "link is %s", flags & IFF_UP ? "up": "down");
692 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
693 if (flags & IFF_LOWER_UP) {
694 log_info_link(link, "carrier on");
696 if (link->network->dhcp) {
697 r = link_acquire_conf(link);
699 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
700 link_enter_failed(link);
705 log_info_link(link, "carrier off");
707 if (link->network->dhcp) {
708 r = sd_dhcp_client_stop(link->dhcp);
710 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
711 link_enter_failed(link);
719 "link status updated: %#.8x -> %#.8x", link->flags, flags);
726 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
727 Link *link = userdata;
732 if (link->state == LINK_STATE_FAILED)
735 r = sd_rtnl_message_get_errno(m);
737 log_struct_link(LOG_ERR, link,
738 "MESSAGE=%s: could not bring up interface: %s",
739 link->ifname, strerror(-r),
742 link_enter_failed(link);
746 link_update_flags(link, link->flags | IFF_UP);
751 static int link_up(Link *link) {
752 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
756 assert(link->manager);
757 assert(link->manager->rtnl);
759 log_debug_link(link, "bringing link up");
761 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
763 log_error_link(link, "Could not allocate RTM_SETLINK message");
767 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
769 log_error_link(link, "Could not set link flags: %s", strerror(-r));
773 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
776 "Could not send rtnetlink message: %s", strerror(-r));
783 static int link_enslaved(Link *link) {
787 assert(link->state == LINK_STATE_ENSLAVING);
788 assert(link->network);
792 link_enter_failed(link);
796 if (!link->network->dhcp)
797 return link_enter_set_addresses(link);
802 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
803 Link *link = userdata;
807 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
808 assert(link->network);
812 if (link->state == LINK_STATE_FAILED)
815 r = sd_rtnl_message_get_errno(m);
817 log_struct_link(LOG_ERR, link,
818 "MESSAGE=%s: could not enslave: %s",
819 link->ifname, strerror(-r),
822 link_enter_failed(link);
826 log_debug_link(link, "enslaved");
828 if (link->enslaving == 0)
834 static int link_enter_enslave(Link *link) {
838 assert(link->network);
839 assert(link->state == _LINK_STATE_INVALID);
841 link->state = LINK_STATE_ENSLAVING;
843 if (!link->network->bridge && !link->network->bond && !link->network->vlan)
844 return link_enslaved(link);
846 if (link->network->bridge) {
847 log_struct_link(LOG_DEBUG, link,
848 "MESSAGE=%s: enslaving by '%s'",
849 link->ifname, link->network->bridge->name,
850 NETDEV(link->network->bridge),
853 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
855 log_struct_link(LOG_WARNING, link,
856 "MESSAGE=%s: could not enslave by '%s': %s",
857 link->ifname, link->network->bridge->name, strerror(-r),
858 NETDEV(link->network->bridge),
860 link_enter_failed(link);
867 if (link->network->vlan) {
868 log_struct_link(LOG_DEBUG, link,
869 "MESSAGE=%s: enslaving by '%s'",
870 link->ifname, link->network->vlan->name,
871 NETDEV(link->network->vlan),
874 r = netdev_enslave(link->network->vlan, link, &enslave_handler);
876 log_struct_link(LOG_WARNING, link,
877 "MESSAGE=%s: could not enslave by '%s': %s",
878 link->ifname, link->network->vlan->name,
879 strerror(-r), NETDEV(link->network->vlan),
881 link_enter_failed(link);
891 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
892 Link *link = userdata;
897 if (link->state == LINK_STATE_FAILED)
900 r = sd_rtnl_message_get_errno(m);
902 log_struct_link(LOG_ERR, link,
903 "MESSAGE=%s: could not get state: %s",
904 link->ifname, strerror(-r),
907 link_enter_failed(link);
911 log_debug_link(link, "got link state");
913 link_update(link, m);
918 static int link_get(Link *link) {
919 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
923 assert(link->manager);
924 assert(link->manager->rtnl);
926 log_debug_link(link, "requesting link status");
928 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
930 log_error_link(link, "Could not allocate RTM_GETLINK message");
934 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
937 "Could not send rtnetlink message: %s", strerror(-r));
944 int link_configure(Link *link) {
948 assert(link->network);
949 assert(link->state == _LINK_STATE_INVALID);
953 link_enter_failed(link);
957 return link_enter_enslave(link);
960 int link_update(Link *link, sd_rtnl_message *m) {
969 if (link->state == LINK_STATE_FAILED)
972 r = sd_rtnl_message_link_get_flags(m, &flags);
974 log_warning_link(link, "Could not get link flags");
978 while (sd_rtnl_message_read(m, &type, &data) > 0) {
979 if (type == IFLA_MTU && link->network->dhcp &&
980 link->network->dhcp_mtu && !link->original_mtu) {
981 link->original_mtu = *(uint16_t *) data;
982 log_debug_link(link, "saved original MTU: %" PRIu16,
987 return link_update_flags(link, flags);