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;
495 size_t nameservers_size;
497 log_struct_link(LOG_INFO, link,
498 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
500 ADDRESS_FMT_VAL(address),
502 ADDRESS_FMT_VAL(gateway),
503 "ADDRESS=%u.%u.%u.%u",
504 ADDRESS_FMT_VAL(address),
507 "GATEWAY=%u.%u.%u.%u",
508 ADDRESS_FMT_VAL(gateway),
511 r = address_new_dynamic(&addr);
513 log_error_link(link, "Could not allocate address");
514 link_enter_failed(link);
518 addr->family = AF_INET;
519 addr->in_addr.in = address;
520 addr->prefixlen = prefixlen;
521 addr->netmask = netmask;
523 r = route_new_dynamic(&rt);
525 log_error_link(link, "Could not allocate route");
526 link_enter_failed(link);
530 rt->family = AF_INET;
531 rt->in_addr.in = gateway;
533 link->dhcp_address = addr;
534 link->dhcp_route = rt;
538 if (link->network->dhcp_dns) {
539 r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
541 r = manager_update_resolv_conf(link->manager);
543 log_error("Failed to update resolv.conf");
547 if (link->network->dhcp_mtu) {
550 r = sd_dhcp_client_get_mtu(client, &mtu);
552 r = link_set_mtu(link, mtu);
554 log_error_link(link, "Failed to set MTU "
559 if (link->network->dhcp_hostname) {
560 const char *hostname;
562 r = sd_dhcp_client_get_hostname(client, &hostname);
564 r = set_hostname(link->manager->bus, hostname);
566 log_error("Failed to set transient hostname "
567 "to '%s'", hostname);
571 link_enter_set_addresses(link);
577 static int link_acquire_conf(Link *link) {
581 assert(link->network);
582 assert(link->network->dhcp);
583 assert(link->manager);
584 assert(link->manager->event);
587 link->dhcp = sd_dhcp_client_new(link->manager->event);
591 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
595 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
599 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
603 if (link->network->dhcp_mtu) {
604 r = sd_dhcp_client_set_request_option(link->dhcp, 26);
610 log_debug_link(link, "acquiring DHCPv4 lease");
612 r = sd_dhcp_client_start(link->dhcp);
619 static int link_update_flags(Link *link, unsigned flags) {
623 assert(link->network);
625 if (link->state == LINK_STATE_FAILED)
628 if (link->flags == flags) {
629 log_debug_link(link, "link status unchanged: %#.8x", flags);
633 if ((link->flags & IFF_UP) != (flags & IFF_UP))
635 "power %s", flags & IFF_UP ? "on": "off");
637 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
638 if (flags & IFF_LOWER_UP) {
639 log_info_link(link, "carrier on");
641 if (link->network->dhcp) {
642 r = link_acquire_conf(link);
644 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
645 link_enter_failed(link);
650 log_info_link(link, "carrier off");
652 if (link->network->dhcp) {
653 r = sd_dhcp_client_stop(link->dhcp);
655 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
656 link_enter_failed(link);
664 "link status updated: %#.8x -> %#.8x", link->flags, flags);
671 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
672 Link *link = userdata;
677 if (link->state == LINK_STATE_FAILED)
680 r = sd_rtnl_message_get_errno(m);
682 log_warning_link(link,
683 "could not bring up interface: %s", strerror(-r));
684 link_enter_failed(link);
687 link_update_flags(link, link->flags | IFF_UP);
692 static int link_up(Link *link) {
693 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
697 assert(link->manager);
698 assert(link->manager->rtnl);
700 log_debug_link(link, "bringing link up");
702 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
704 log_error_link(link, "Could not allocate RTM_SETLINK message");
708 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
710 log_error_link(link, "Could not set link flags: %s", strerror(-r));
714 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
717 "Could not send rtnetlink message: %s", strerror(-r));
724 static int link_bridge_joined(Link *link) {
728 assert(link->state == LINK_STATE_JOINING_BRIDGE);
729 assert(link->network);
733 link_enter_failed(link);
737 if (!link->network->dhcp)
738 return link_enter_set_addresses(link);
743 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
744 Link *link = userdata;
748 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
749 assert(link->network);
751 if (link->state == LINK_STATE_FAILED)
754 r = sd_rtnl_message_get_errno(m);
756 log_struct_link(LOG_ERR, link,
757 "MESSAGE=%s: could not join bridge '%s': %s",
758 link->ifname, link->network->bridge->name, strerror(-r),
759 BRIDGE(link->network->bridge),
761 link_enter_failed(link);
765 log_struct_link(LOG_DEBUG, link,
766 "MESSAGE=%s: joined bridge '%s'",
767 link->network->bridge->name,
768 BRIDGE(link->network->bridge),
771 link_bridge_joined(link);
776 static int link_enter_join_bridge(Link *link) {
780 assert(link->network);
781 assert(link->state == _LINK_STATE_INVALID);
783 link->state = LINK_STATE_JOINING_BRIDGE;
785 if (!link->network->bridge)
786 return link_bridge_joined(link);
788 log_struct_link(LOG_DEBUG, link,
789 "MESSAGE=%s: joining bridge '%s'",
790 link->network->bridge->name,
791 BRIDGE(link->network->bridge),
793 log_debug_link(link, "joining bridge");
795 r = bridge_join(link->network->bridge, link, &bridge_handler);
797 log_struct_link(LOG_WARNING, link,
798 "MESSAGE=%s: could not join bridge '%s': %s",
799 link->network->bridge->name, strerror(-r),
800 BRIDGE(link->network->bridge),
802 link_enter_failed(link);
809 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
810 Link *link = userdata;
815 if (link->state == LINK_STATE_FAILED)
818 r = sd_rtnl_message_get_errno(m);
820 log_warning_link(link, "could not get state: %s", strerror(-r));
821 link_enter_failed(link);
824 log_debug_link(link, "got link state");
826 link_update(link, m);
831 static int link_get(Link *link) {
832 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
836 assert(link->manager);
837 assert(link->manager->rtnl);
839 log_debug_link(link, "requesting link status");
841 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
843 log_error_link(link, "Could not allocate RTM_GETLINK message");
847 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
850 "Could not send rtnetlink message: %s", strerror(-r));
857 int link_configure(Link *link) {
861 assert(link->network);
862 assert(link->state == _LINK_STATE_INVALID);
866 link_enter_failed(link);
870 return link_enter_join_bridge(link);
873 int link_update(Link *link, sd_rtnl_message *m) {
882 if (link->state == LINK_STATE_FAILED)
885 r = sd_rtnl_message_link_get_flags(m, &flags);
887 log_warning_link(link, "Could not get link flags");
891 while (sd_rtnl_message_read(m, &type, &data) > 0) {
892 if (type == IFLA_MTU && link->network->dhcp &&
893 link->network->dhcp_mtu && !link->original_mtu) {
894 link->original_mtu = *(uint16_t *) data;
895 log_debug_link(link, "saved original MTU: %" PRIu16,
900 return link_update_flags(link, flags);