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;
323 if (link->state == LINK_STATE_FAILED)
327 log_warning_link(link, "DHCP error: %s", strerror(-event));
328 link_enter_failed(link);
332 if (event == DHCP_EVENT_NO_LEASE)
333 log_debug_link(link, "IP address in use.");
335 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
336 event == DHCP_EVENT_STOP) {
337 if (link->dhcp_address) {
338 address_drop(link->dhcp_address, link, address_drop_handler);
340 address_free(link->dhcp_address);
341 link->dhcp_address = NULL;
344 if (link->dhcp_route) {
345 route_free(link->dhcp_route);
346 link->dhcp_route = NULL;
350 r = sd_dhcp_client_get_address(client, &address);
352 log_warning_link(link, "DHCP error: no address");
353 link_enter_failed(link);
357 r = sd_dhcp_client_get_netmask(client, &netmask);
359 log_warning_link(link, "DHCP error: no netmask");
360 link_enter_failed(link);
364 prefixlen = sd_dhcp_client_prefixlen(&netmask);
366 log_warning_link(link, "DHCP error: no prefixlen");
367 link_enter_failed(link);
371 r = sd_dhcp_client_get_router(client, &gateway);
373 log_warning_link(link, "DHCP error: no router");
374 link_enter_failed(link);
378 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
379 _cleanup_address_free_ Address *addr = NULL;
380 _cleanup_route_free_ Route *rt = NULL;
382 log_struct_link(LOG_INFO, link,
383 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
385 ADDRESS_FMT_VAL(address),
387 ADDRESS_FMT_VAL(gateway),
388 "ADDRESS=%u.%u.%u.%u",
389 ADDRESS_FMT_VAL(address),
392 "GATEWAY=%u.%u.%u.%u",
393 ADDRESS_FMT_VAL(gateway),
396 r = address_new_dynamic(&addr);
398 log_error_link(link, "Could not allocate address");
399 link_enter_failed(link);
403 addr->family = AF_INET;
404 addr->in_addr.in = address;
405 addr->prefixlen = prefixlen;
406 addr->netmask = netmask;
408 r = route_new_dynamic(&rt);
410 log_error_link(link, "Could not allocate route");
411 link_enter_failed(link);
415 rt->family = AF_INET;
416 rt->in_addr.in = gateway;
418 link->dhcp_address = addr;
419 link->dhcp_route = rt;
423 link_enter_set_addresses(link);
429 static int link_acquire_conf(Link *link) {
433 assert(link->network);
434 assert(link->network->dhcp);
435 assert(link->manager);
436 assert(link->manager->event);
439 link->dhcp = sd_dhcp_client_new(link->manager->event);
443 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
447 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
451 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
456 r = sd_dhcp_client_start(link->dhcp);
463 static int link_update_flags(Link *link, unsigned flags) {
467 assert(link->network);
469 if (link->state == LINK_STATE_FAILED)
472 if (link->flags == flags) {
473 log_debug_link(link, "link status unchanged: %#x", flags);
477 if ((link->flags & IFF_UP) != (flags & IFF_UP))
479 "power %s", flags & IFF_UP ? "on": "off");
481 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
482 if (flags & IFF_LOWER_UP) {
483 log_info_link(link, "carrier on");
485 if (link->network->dhcp) {
486 r = link_acquire_conf(link);
488 link_enter_failed(link);
493 log_info_link(link, "carrier off");
495 if (link->network->dhcp) {
496 r = sd_dhcp_client_stop(link->dhcp);
498 link_enter_failed(link);
506 "link status updated: %#x -> %#x", link->flags, flags);
513 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
514 Link *link = userdata;
519 if (link->state == LINK_STATE_FAILED)
522 r = sd_rtnl_message_get_errno(m);
524 log_warning_link(link,
525 "could not bring up interface: %s", strerror(-r));
526 link_enter_failed(link);
529 link_update_flags(link, link->flags | IFF_UP);
534 static int link_up(Link *link) {
535 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
539 assert(link->manager);
540 assert(link->manager->rtnl);
542 log_debug_link(link, "bringing link up");
544 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
546 log_error_link(link, "Could not allocate RTM_SETLINK message");
550 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
552 log_error_link(link, "Could not set link flags: %s", strerror(-r));
556 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
559 "Could not send rtnetlink message: %s", strerror(-r));
566 static int link_bridge_joined(Link *link) {
570 assert(link->state == LINK_STATE_JOINING_BRIDGE);
571 assert(link->network);
575 link_enter_failed(link);
579 if (!link->network->dhcp)
580 return link_enter_set_addresses(link);
585 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
586 Link *link = userdata;
590 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
591 assert(link->network);
593 if (link->state == LINK_STATE_FAILED)
596 r = sd_rtnl_message_get_errno(m);
598 log_struct_link(LOG_ERR, link,
599 "MESSAGE=%s: could not join bridge '%s': %s",
600 link->ifname, link->network->bridge->name, strerror(-r),
601 BRIDGE(link->network->bridge),
603 link_enter_failed(link);
607 log_struct_link(LOG_DEBUG, link,
608 "MESSAGE=%s: joined bridge '%s'",
609 link->network->bridge->name,
610 BRIDGE(link->network->bridge),
612 link_bridge_joined(link);
617 static int link_enter_join_bridge(Link *link) {
621 assert(link->network);
622 assert(link->state == _LINK_STATE_INVALID);
624 link->state = LINK_STATE_JOINING_BRIDGE;
626 if (!link->network->bridge)
627 return link_bridge_joined(link);
629 log_struct_link(LOG_DEBUG, link,
630 "MESSAGE=%s: joining bridge '%s'",
631 link->network->bridge->name,
632 BRIDGE(link->network->bridge),
634 log_debug_link(link, "joining bridge");
636 r = bridge_join(link->network->bridge, link, &bridge_handler);
638 log_struct_link(LOG_WARNING, link,
639 "MESSAGE=%s: could not join bridge '%s': %s",
640 link->network->bridge->name, strerror(-r),
641 BRIDGE(link->network->bridge),
643 link_enter_failed(link);
650 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
651 Link *link = userdata;
656 if (link->state == LINK_STATE_FAILED)
659 r = sd_rtnl_message_get_errno(m);
661 log_warning_link(link, "could not get state: %s", strerror(-r));
662 link_enter_failed(link);
665 log_debug_link(link, "got link state");
667 link_update(link, m);
672 static int link_get(Link *link) {
673 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
677 assert(link->manager);
678 assert(link->manager->rtnl);
680 log_debug_link(link, "requesting link status");
682 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
684 log_error_link(link, "Could not allocate RTM_GETLINK message");
688 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
691 "Could not send rtnetlink message: %s", strerror(-r));
698 int link_configure(Link *link) {
702 assert(link->network);
703 assert(link->state == _LINK_STATE_INVALID);
707 link_enter_failed(link);
711 return link_enter_join_bridge(link);
714 int link_update(Link *link, sd_rtnl_message *m) {
721 if (link->state == LINK_STATE_FAILED)
724 r = sd_rtnl_message_link_get_flags(m, &flags);
726 log_warning_link(link, "could not get link flags");
730 return link_update_flags(link, flags);