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 log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
584 link_enter_failed(link);
589 log_info_link(link, "carrier off");
591 if (link->network->dhcp) {
592 r = sd_dhcp_client_stop(link->dhcp);
594 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
595 link_enter_failed(link);
603 "link status updated: %#.8x -> %#.8x", link->flags, flags);
610 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
611 Link *link = userdata;
616 if (link->state == LINK_STATE_FAILED)
619 r = sd_rtnl_message_get_errno(m);
621 log_warning_link(link,
622 "could not bring up interface: %s", strerror(-r));
623 link_enter_failed(link);
626 link_update_flags(link, link->flags | IFF_UP);
631 static int link_up(Link *link) {
632 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
636 assert(link->manager);
637 assert(link->manager->rtnl);
639 log_debug_link(link, "bringing link up");
641 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
643 log_error_link(link, "Could not allocate RTM_SETLINK message");
647 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
649 log_error_link(link, "Could not set link flags: %s", strerror(-r));
653 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
656 "Could not send rtnetlink message: %s", strerror(-r));
663 static int link_bridge_joined(Link *link) {
667 assert(link->state == LINK_STATE_JOINING_BRIDGE);
668 assert(link->network);
672 link_enter_failed(link);
676 if (!link->network->dhcp)
677 return link_enter_set_addresses(link);
682 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
683 Link *link = userdata;
687 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
688 assert(link->network);
690 if (link->state == LINK_STATE_FAILED)
693 r = sd_rtnl_message_get_errno(m);
695 log_struct_link(LOG_ERR, link,
696 "MESSAGE=%s: could not join bridge '%s': %s",
697 link->ifname, link->network->bridge->name, strerror(-r),
698 BRIDGE(link->network->bridge),
700 link_enter_failed(link);
704 log_struct_link(LOG_DEBUG, link,
705 "MESSAGE=%s: joined bridge '%s'",
706 link->network->bridge->name,
707 BRIDGE(link->network->bridge),
710 link_bridge_joined(link);
715 static int link_enter_join_bridge(Link *link) {
719 assert(link->network);
720 assert(link->state == _LINK_STATE_INVALID);
722 link->state = LINK_STATE_JOINING_BRIDGE;
724 if (!link->network->bridge)
725 return link_bridge_joined(link);
727 log_struct_link(LOG_DEBUG, link,
728 "MESSAGE=%s: joining bridge '%s'",
729 link->network->bridge->name,
730 BRIDGE(link->network->bridge),
732 log_debug_link(link, "joining bridge");
734 r = bridge_join(link->network->bridge, link, &bridge_handler);
736 log_struct_link(LOG_WARNING, link,
737 "MESSAGE=%s: could not join bridge '%s': %s",
738 link->network->bridge->name, strerror(-r),
739 BRIDGE(link->network->bridge),
741 link_enter_failed(link);
748 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
749 Link *link = userdata;
754 if (link->state == LINK_STATE_FAILED)
757 r = sd_rtnl_message_get_errno(m);
759 log_warning_link(link, "could not get state: %s", strerror(-r));
760 link_enter_failed(link);
763 log_debug_link(link, "got link state");
765 link_update(link, m);
770 static int link_get(Link *link) {
771 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
775 assert(link->manager);
776 assert(link->manager->rtnl);
778 log_debug_link(link, "requesting link status");
780 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
782 log_error_link(link, "Could not allocate RTM_GETLINK message");
786 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
789 "Could not send rtnetlink message: %s", strerror(-r));
796 int link_configure(Link *link) {
800 assert(link->network);
801 assert(link->state == _LINK_STATE_INVALID);
805 link_enter_failed(link);
809 return link_enter_join_bridge(link);
812 int link_update(Link *link, sd_rtnl_message *m) {
821 if (link->state == LINK_STATE_FAILED)
824 r = sd_rtnl_message_link_get_flags(m, &flags);
826 log_warning_link(link, "Could not get link flags");
830 while (sd_rtnl_message_read(m, &type, &data) > 0) {
831 if (type == IFLA_MTU && link->network->dhcp_mtu && !link->original_mtu) {
832 link->original_mtu = *(uint16_t *) data;
833 log_debug_link(link, "saved original MTU: %" PRIu16, link->original_mtu);
837 return link_update_flags(link, flags);