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"
29 int link_new(Manager *manager, struct udev_device *device, Link **ret) {
30 _cleanup_link_free_ Link *link = NULL;
32 struct ether_addr *mac_addr;
43 link->manager = manager;
44 link->state = _LINK_STATE_INVALID;
46 link->ifindex = udev_device_get_ifindex(device);
47 if (link->ifindex <= 0)
50 mac = udev_device_get_sysattr_value(device, "address");
52 mac_addr = ether_aton(mac);
54 memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
57 ifname = udev_device_get_sysname(device);
58 link->ifname = strdup(ifname);
60 r = hashmap_put(manager->links, &link->ifindex, link);
70 void link_free(Link *link) {
74 assert(link->manager);
77 sd_dhcp_client_free(link->dhcp);
79 route_free(link->dhcp_route);
80 link->dhcp_route = NULL;
82 address_free(link->dhcp_address);
83 link->dhcp_address = NULL;
85 hashmap_remove(link->manager->links, &link->ifindex);
92 int link_add(Manager *m, struct udev_device *device, Link **ret) {
102 ifindex = udev_device_get_ifindex(device);
103 link = hashmap_get(m->links, &ifindex);
109 r = link_new(m, device, &link);
115 devtype = udev_device_get_devtype(device);
116 if (streq_ptr(devtype, "bridge")) {
117 r = bridge_set_link(m, link);
118 if (r < 0 && r != -ENOENT)
122 r = network_get(m, device, &network);
124 return r == -ENOENT ? 0 : r;
126 r = network_apply(m, network, link);
133 static int link_enter_configured(Link *link) {
135 assert(link->state == LINK_STATE_SETTING_ROUTES);
137 log_info_link(link, "link configured");
139 link->state = LINK_STATE_CONFIGURED;
144 static void link_enter_failed(Link *link) {
147 log_warning_link(link, "failed");
149 link->state = LINK_STATE_FAILED;
152 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
153 Link *link = userdata;
156 assert(link->route_messages > 0);
157 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
158 link->state == LINK_STATE_SETTING_ROUTES ||
159 link->state == LINK_STATE_FAILED);
161 link->route_messages --;
163 if (link->state == LINK_STATE_FAILED)
166 r = sd_rtnl_message_get_errno(m);
167 if (r < 0 && r != -EEXIST)
168 log_warning_link(link, "could not set route: %s", strerror(-r));
170 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
172 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
173 log_debug_link(link, "routes set");
174 link_enter_configured(link);
180 static int link_enter_set_routes(Link *link) {
185 assert(link->network);
186 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
188 link->state = LINK_STATE_SETTING_ROUTES;
190 if (!link->network->static_routes && !link->dhcp_route)
191 return link_enter_configured(link);
193 log_debug_link(link, "setting routes");
195 LIST_FOREACH(static_routes, route, link->network->static_routes) {
196 r = route_configure(route, link, &route_handler);
198 log_warning_link(link,
199 "could not set routes: %s", strerror(-r));
200 link_enter_failed(link);
204 link->route_messages ++;
207 if (link->dhcp_route) {
208 r = route_configure(link->dhcp_route, link, &route_handler);
210 log_warning_link(link,
211 "could not set routes: %s", strerror(-r));
212 link_enter_failed(link);
216 link->route_messages ++;
222 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
223 Link *link = userdata;
228 assert(link->ifname);
229 assert(link->addr_messages > 0);
230 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
232 link->addr_messages --;
234 if (link->state == LINK_STATE_FAILED)
237 r = sd_rtnl_message_get_errno(m);
238 if (r < 0 && r != -EEXIST)
239 log_struct_link(LOG_ERR, link,
240 "MESSAGE=%s: could not set address: %s",
241 link->ifname, strerror(-r),
245 if (link->addr_messages == 0) {
246 log_debug_link(link, "addresses set");
247 link_enter_set_routes(link);
253 static int link_enter_set_addresses(Link *link) {
258 assert(link->network);
259 assert(link->state != _LINK_STATE_INVALID);
261 link->state = LINK_STATE_SETTING_ADDRESSES;
263 if (!link->network->static_addresses && !link->dhcp_address)
264 return link_enter_set_routes(link);
266 log_debug_link(link, "setting addresses");
268 LIST_FOREACH(static_addresses, address, link->network->static_addresses) {
269 r = address_configure(address, link, &address_handler);
271 log_warning_link(link,
272 "could not set addresses: %s", strerror(-r));
273 link_enter_failed(link);
277 link->addr_messages ++;
280 if (link->dhcp_address) {
281 r = address_configure(link->dhcp_address, link, &address_handler);
283 log_warning_link(link,
284 "could not set addresses: %s", strerror(-r));
285 link_enter_failed(link);
289 link->addr_messages ++;
295 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
296 Link *link = userdata;
301 assert(link->ifname);
303 if (link->state == LINK_STATE_FAILED)
306 r = sd_rtnl_message_get_errno(m);
307 if (r < 0 && r != -EEXIST)
308 log_warning_link(link, "could not drop address: %s", strerror(-r));
313 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
314 Link *link = userdata;
319 assert(link->ifname);
321 if (link->state == LINK_STATE_FAILED)
324 r = sd_rtnl_message_get_errno(m);
325 if (r < 0 && r != -EEXIST)
326 log_warning_link(link, "Could not set MTU: %s", strerror(-r));
331 static int link_set_mtu(Link *link, uint32_t mtu) {
332 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
336 assert(link->manager);
337 assert(link->manager->rtnl);
339 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
341 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
343 log_error_link(link, "Could not allocate RTM_SETLINK message");
347 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
349 log_error_link(link, "Could not append MTU: %s", strerror(-r));
353 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
356 "Could not send rtnetlink message: %s", strerror(-r));
363 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
364 Link *link = userdata;
365 struct in_addr address;
366 struct in_addr netmask;
367 struct in_addr gateway;
372 assert(link->network);
374 if (link->state == LINK_STATE_FAILED)
378 log_warning_link(link, "DHCP error: %s", strerror(-event));
379 link_enter_failed(link);
383 if (event == DHCP_EVENT_NO_LEASE)
384 log_debug_link(link, "IP address in use.");
386 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
387 event == DHCP_EVENT_STOP) {
388 if (link->dhcp_address) {
389 address_drop(link->dhcp_address, link, address_drop_handler);
391 address_free(link->dhcp_address);
392 link->dhcp_address = NULL;
395 if (link->dhcp_route) {
396 route_free(link->dhcp_route);
397 link->dhcp_route = NULL;
400 if (link->network->dhcp_mtu) {
403 r = sd_dhcp_client_get_mtu(client, &mtu);
404 if (r >= 0 && link->original_mtu != mtu) {
405 r = link_set_mtu(link, link->original_mtu);
407 log_warning_link(link, "DHCP error: could not reset MTU");
408 link_enter_failed(link);
415 r = sd_dhcp_client_get_address(client, &address);
417 log_warning_link(link, "DHCP error: no address");
418 link_enter_failed(link);
422 r = sd_dhcp_client_get_netmask(client, &netmask);
424 log_warning_link(link, "DHCP error: no netmask");
425 link_enter_failed(link);
429 prefixlen = sd_dhcp_client_prefixlen(&netmask);
431 log_warning_link(link, "DHCP error: no prefixlen");
432 link_enter_failed(link);
436 r = sd_dhcp_client_get_router(client, &gateway);
438 log_warning_link(link, "DHCP error: no router");
439 link_enter_failed(link);
443 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
444 _cleanup_address_free_ Address *addr = NULL;
445 _cleanup_route_free_ Route *rt = NULL;
446 struct in_addr **nameservers;
448 log_struct_link(LOG_INFO, link,
449 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
451 ADDRESS_FMT_VAL(address),
453 ADDRESS_FMT_VAL(gateway),
454 "ADDRESS=%u.%u.%u.%u",
455 ADDRESS_FMT_VAL(address),
458 "GATEWAY=%u.%u.%u.%u",
459 ADDRESS_FMT_VAL(gateway),
462 r = address_new_dynamic(&addr);
464 log_error_link(link, "Could not allocate address");
465 link_enter_failed(link);
469 addr->family = AF_INET;
470 addr->in_addr.in = address;
471 addr->prefixlen = prefixlen;
472 addr->netmask = netmask;
474 r = route_new_dynamic(&rt);
476 log_error_link(link, "Could not allocate route");
477 link_enter_failed(link);
481 rt->family = AF_INET;
482 rt->in_addr.in = gateway;
484 link->dhcp_address = addr;
485 link->dhcp_route = rt;
489 if (link->network->dhcp_dns) {
490 r = sd_dhcp_client_get_dns(client, &nameservers);
492 r = manager_update_resolv_conf(link->manager);
494 log_error("Failed to update resolv.conf");
498 if (link->network->dhcp_mtu) {
501 r = sd_dhcp_client_get_mtu(client, &mtu);
503 r = link_set_mtu(link, mtu);
505 log_error_link(link, "Failed to set MTU "
510 link_enter_set_addresses(link);
516 static int link_acquire_conf(Link *link) {
520 assert(link->network);
521 assert(link->network->dhcp);
522 assert(link->manager);
523 assert(link->manager->event);
526 link->dhcp = sd_dhcp_client_new(link->manager->event);
530 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
534 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
538 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
543 log_debug_link(link, "acquiring DHCPv4 lease");
545 if (link->network->dhcp_mtu) {
546 r = sd_dhcp_client_set_request_option(link->dhcp, 26);
551 r = sd_dhcp_client_start(link->dhcp);
558 static int link_update_flags(Link *link, unsigned flags) {
562 assert(link->network);
564 if (link->state == LINK_STATE_FAILED)
567 if (link->flags == flags) {
568 log_debug_link(link, "link status unchanged: %#.8x", flags);
572 if ((link->flags & IFF_UP) != (flags & IFF_UP))
574 "power %s", flags & IFF_UP ? "on": "off");
576 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
577 if (flags & IFF_LOWER_UP) {
578 log_info_link(link, "carrier on");
580 if (link->network->dhcp) {
581 r = link_acquire_conf(link);
583 link_enter_failed(link);
588 log_info_link(link, "carrier off");
590 if (link->network->dhcp) {
591 r = sd_dhcp_client_stop(link->dhcp);
593 link_enter_failed(link);
601 "link status updated: %#.8x -> %#.8x", link->flags, flags);
608 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
609 Link *link = userdata;
614 if (link->state == LINK_STATE_FAILED)
617 r = sd_rtnl_message_get_errno(m);
619 log_warning_link(link,
620 "could not bring up interface: %s", strerror(-r));
621 link_enter_failed(link);
624 link_update_flags(link, link->flags | IFF_UP);
629 static int link_up(Link *link) {
630 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
634 assert(link->manager);
635 assert(link->manager->rtnl);
637 log_debug_link(link, "bringing link up");
639 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
641 log_error_link(link, "Could not allocate RTM_SETLINK message");
645 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
647 log_error_link(link, "Could not set link flags: %s", strerror(-r));
651 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
654 "Could not send rtnetlink message: %s", strerror(-r));
661 static int link_bridge_joined(Link *link) {
665 assert(link->state == LINK_STATE_JOINING_BRIDGE);
666 assert(link->network);
670 link_enter_failed(link);
674 if (!link->network->dhcp)
675 return link_enter_set_addresses(link);
680 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
681 Link *link = userdata;
685 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
686 assert(link->network);
688 if (link->state == LINK_STATE_FAILED)
691 r = sd_rtnl_message_get_errno(m);
693 log_struct_link(LOG_ERR, link,
694 "MESSAGE=%s: could not join bridge '%s': %s",
695 link->ifname, link->network->bridge->name, strerror(-r),
696 BRIDGE(link->network->bridge),
698 link_enter_failed(link);
702 log_struct_link(LOG_DEBUG, link,
703 "MESSAGE=%s: joined bridge '%s'",
704 link->network->bridge->name,
705 BRIDGE(link->network->bridge),
708 link_bridge_joined(link);
713 static int link_enter_join_bridge(Link *link) {
717 assert(link->network);
718 assert(link->state == _LINK_STATE_INVALID);
720 link->state = LINK_STATE_JOINING_BRIDGE;
722 if (!link->network->bridge)
723 return link_bridge_joined(link);
725 log_struct_link(LOG_DEBUG, link,
726 "MESSAGE=%s: joining bridge '%s'",
727 link->network->bridge->name,
728 BRIDGE(link->network->bridge),
730 log_debug_link(link, "joining bridge");
732 r = bridge_join(link->network->bridge, link, &bridge_handler);
734 log_struct_link(LOG_WARNING, link,
735 "MESSAGE=%s: could not join bridge '%s': %s",
736 link->network->bridge->name, strerror(-r),
737 BRIDGE(link->network->bridge),
739 link_enter_failed(link);
746 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
747 Link *link = userdata;
752 if (link->state == LINK_STATE_FAILED)
755 r = sd_rtnl_message_get_errno(m);
757 log_warning_link(link, "could not get state: %s", strerror(-r));
758 link_enter_failed(link);
761 log_debug_link(link, "got link state");
763 link_update(link, m);
768 static int link_get(Link *link) {
769 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
773 assert(link->manager);
774 assert(link->manager->rtnl);
776 log_debug_link(link, "requesting link status");
778 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
780 log_error_link(link, "Could not allocate RTM_GETLINK message");
784 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
787 "Could not send rtnetlink message: %s", strerror(-r));
794 int link_configure(Link *link) {
798 assert(link->network);
799 assert(link->state == _LINK_STATE_INVALID);
803 link_enter_failed(link);
807 return link_enter_join_bridge(link);
810 int link_update(Link *link, sd_rtnl_message *m) {
819 if (link->state == LINK_STATE_FAILED)
822 r = sd_rtnl_message_link_get_flags(m, &flags);
824 log_warning_link(link, "Could not get link flags");
828 while (sd_rtnl_message_read(m, &type, &data) > 0) {
829 if (type == IFLA_MTU && link->network->dhcp_mtu && !link->original_mtu) {
830 link->original_mtu = *(uint16_t *) data;
831 log_debug_link(link, "saved original MTU: %" PRIu16, link->original_mtu);
835 return link_update_flags(link, flags);