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 void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
314 Link *link = userdata;
315 struct in_addr address;
316 struct in_addr netmask;
317 struct in_addr gateway;
322 assert(link->network);
324 if (link->state == LINK_STATE_FAILED)
328 log_warning_link(link, "DHCP error: %s", strerror(-event));
329 link_enter_failed(link);
333 if (event == DHCP_EVENT_NO_LEASE)
334 log_debug_link(link, "IP address in use.");
336 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
337 event == DHCP_EVENT_STOP) {
338 if (link->dhcp_address) {
339 address_drop(link->dhcp_address, link, address_drop_handler);
341 address_free(link->dhcp_address);
342 link->dhcp_address = NULL;
345 if (link->dhcp_route) {
346 route_free(link->dhcp_route);
347 link->dhcp_route = NULL;
351 r = sd_dhcp_client_get_address(client, &address);
353 log_warning_link(link, "DHCP error: no address");
354 link_enter_failed(link);
358 r = sd_dhcp_client_get_netmask(client, &netmask);
360 log_warning_link(link, "DHCP error: no netmask");
361 link_enter_failed(link);
365 prefixlen = sd_dhcp_client_prefixlen(&netmask);
367 log_warning_link(link, "DHCP error: no prefixlen");
368 link_enter_failed(link);
372 r = sd_dhcp_client_get_router(client, &gateway);
374 log_warning_link(link, "DHCP error: no router");
375 link_enter_failed(link);
379 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
380 _cleanup_address_free_ Address *addr = NULL;
381 _cleanup_route_free_ Route *rt = NULL;
382 struct in_addr **nameservers;
384 log_struct_link(LOG_INFO, link,
385 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
387 ADDRESS_FMT_VAL(address),
389 ADDRESS_FMT_VAL(gateway),
390 "ADDRESS=%u.%u.%u.%u",
391 ADDRESS_FMT_VAL(address),
394 "GATEWAY=%u.%u.%u.%u",
395 ADDRESS_FMT_VAL(gateway),
398 r = address_new_dynamic(&addr);
400 log_error_link(link, "Could not allocate address");
401 link_enter_failed(link);
405 addr->family = AF_INET;
406 addr->in_addr.in = address;
407 addr->prefixlen = prefixlen;
408 addr->netmask = netmask;
410 r = route_new_dynamic(&rt);
412 log_error_link(link, "Could not allocate route");
413 link_enter_failed(link);
417 rt->family = AF_INET;
418 rt->in_addr.in = gateway;
420 link->dhcp_address = addr;
421 link->dhcp_route = rt;
425 if (link->network->dhcp_dns) {
426 r = sd_dhcp_client_get_dns(client, &nameservers);
428 r = manager_update_resolv_conf(link->manager);
430 log_error("Failed to update resolv.conf");
434 link_enter_set_addresses(link);
440 static int link_acquire_conf(Link *link) {
444 assert(link->network);
445 assert(link->network->dhcp);
446 assert(link->manager);
447 assert(link->manager->event);
450 link->dhcp = sd_dhcp_client_new(link->manager->event);
454 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
458 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
462 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
467 log_debug_link(link, "acquiring DHCPv4 lease");
469 r = sd_dhcp_client_start(link->dhcp);
476 static int link_update_flags(Link *link, unsigned flags) {
480 assert(link->network);
482 if (link->state == LINK_STATE_FAILED)
485 if (link->flags == flags) {
486 log_debug_link(link, "link status unchanged: %#.8x", flags);
490 if ((link->flags & IFF_UP) != (flags & IFF_UP))
492 "power %s", flags & IFF_UP ? "on": "off");
494 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
495 if (flags & IFF_LOWER_UP) {
496 log_info_link(link, "carrier on");
498 if (link->network->dhcp) {
499 r = link_acquire_conf(link);
501 link_enter_failed(link);
506 log_info_link(link, "carrier off");
508 if (link->network->dhcp) {
509 r = sd_dhcp_client_stop(link->dhcp);
511 link_enter_failed(link);
519 "link status updated: %#.8x -> %#.8x", link->flags, flags);
526 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
527 Link *link = userdata;
532 if (link->state == LINK_STATE_FAILED)
535 r = sd_rtnl_message_get_errno(m);
537 log_warning_link(link,
538 "could not bring up interface: %s", strerror(-r));
539 link_enter_failed(link);
542 link_update_flags(link, link->flags | IFF_UP);
547 static int link_up(Link *link) {
548 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
552 assert(link->manager);
553 assert(link->manager->rtnl);
555 log_debug_link(link, "bringing link up");
557 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
559 log_error_link(link, "Could not allocate RTM_SETLINK message");
563 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
565 log_error_link(link, "Could not set link flags: %s", strerror(-r));
569 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
572 "Could not send rtnetlink message: %s", strerror(-r));
579 static int link_bridge_joined(Link *link) {
583 assert(link->state == LINK_STATE_JOINING_BRIDGE);
584 assert(link->network);
588 link_enter_failed(link);
592 if (!link->network->dhcp)
593 return link_enter_set_addresses(link);
598 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
599 Link *link = userdata;
603 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
604 assert(link->network);
606 if (link->state == LINK_STATE_FAILED)
609 r = sd_rtnl_message_get_errno(m);
611 log_struct_link(LOG_ERR, link,
612 "MESSAGE=%s: could not join bridge '%s': %s",
613 link->ifname, link->network->bridge->name, strerror(-r),
614 BRIDGE(link->network->bridge),
616 link_enter_failed(link);
620 log_struct_link(LOG_DEBUG, link,
621 "MESSAGE=%s: joined bridge '%s'",
622 link->network->bridge->name,
623 BRIDGE(link->network->bridge),
626 link_bridge_joined(link);
631 static int link_enter_join_bridge(Link *link) {
635 assert(link->network);
636 assert(link->state == _LINK_STATE_INVALID);
638 link->state = LINK_STATE_JOINING_BRIDGE;
640 if (!link->network->bridge)
641 return link_bridge_joined(link);
643 log_struct_link(LOG_DEBUG, link,
644 "MESSAGE=%s: joining bridge '%s'",
645 link->network->bridge->name,
646 BRIDGE(link->network->bridge),
648 log_debug_link(link, "joining bridge");
650 r = bridge_join(link->network->bridge, link, &bridge_handler);
652 log_struct_link(LOG_WARNING, link,
653 "MESSAGE=%s: could not join bridge '%s': %s",
654 link->network->bridge->name, strerror(-r),
655 BRIDGE(link->network->bridge),
657 link_enter_failed(link);
664 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
665 Link *link = userdata;
670 if (link->state == LINK_STATE_FAILED)
673 r = sd_rtnl_message_get_errno(m);
675 log_warning_link(link, "could not get state: %s", strerror(-r));
676 link_enter_failed(link);
679 log_debug_link(link, "got link state");
681 link_update(link, m);
686 static int link_get(Link *link) {
687 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
691 assert(link->manager);
692 assert(link->manager->rtnl);
694 log_debug_link(link, "requesting link status");
696 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
698 log_error_link(link, "Could not allocate RTM_GETLINK message");
702 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
705 "Could not send rtnetlink message: %s", strerror(-r));
712 int link_configure(Link *link) {
716 assert(link->network);
717 assert(link->state == _LINK_STATE_INVALID);
721 link_enter_failed(link);
725 return link_enter_join_bridge(link);
728 int link_update(Link *link, sd_rtnl_message *m) {
735 if (link->state == LINK_STATE_FAILED)
738 r = sd_rtnl_message_link_get_flags(m, &flags);
740 log_warning_link(link, "could not get link flags");
744 return link_update_flags(link, flags);