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;
381 struct in_addr **nameservers;
383 log_struct_link(LOG_INFO, link,
384 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
386 ADDRESS_FMT_VAL(address),
388 ADDRESS_FMT_VAL(gateway),
389 "ADDRESS=%u.%u.%u.%u",
390 ADDRESS_FMT_VAL(address),
393 "GATEWAY=%u.%u.%u.%u",
394 ADDRESS_FMT_VAL(gateway),
397 r = address_new_dynamic(&addr);
399 log_error_link(link, "Could not allocate address");
400 link_enter_failed(link);
404 addr->family = AF_INET;
405 addr->in_addr.in = address;
406 addr->prefixlen = prefixlen;
407 addr->netmask = netmask;
409 r = route_new_dynamic(&rt);
411 log_error_link(link, "Could not allocate route");
412 link_enter_failed(link);
416 rt->family = AF_INET;
417 rt->in_addr.in = gateway;
419 link->dhcp_address = addr;
420 link->dhcp_route = rt;
424 r = sd_dhcp_client_get_dns(client, &nameservers);
426 r = manager_update_resolv_conf(link->manager);
428 log_error("Failed to update resolv.conf");
431 link_enter_set_addresses(link);
437 static int link_acquire_conf(Link *link) {
441 assert(link->network);
442 assert(link->network->dhcp);
443 assert(link->manager);
444 assert(link->manager->event);
447 link->dhcp = sd_dhcp_client_new(link->manager->event);
451 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
455 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
459 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
464 log_debug_link(link, "acquiring DHCPv4 lease");
466 r = sd_dhcp_client_start(link->dhcp);
473 static int link_update_flags(Link *link, unsigned flags) {
477 assert(link->network);
479 if (link->state == LINK_STATE_FAILED)
482 if (link->flags == flags) {
483 log_debug_link(link, "link status unchanged: %#.8x", flags);
487 if ((link->flags & IFF_UP) != (flags & IFF_UP))
489 "power %s", flags & IFF_UP ? "on": "off");
491 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
492 if (flags & IFF_LOWER_UP) {
493 log_info_link(link, "carrier on");
495 if (link->network->dhcp) {
496 r = link_acquire_conf(link);
498 link_enter_failed(link);
503 log_info_link(link, "carrier off");
505 if (link->network->dhcp) {
506 r = sd_dhcp_client_stop(link->dhcp);
508 link_enter_failed(link);
516 "link status updated: %#.8x -> %#.8x", link->flags, flags);
523 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
524 Link *link = userdata;
529 if (link->state == LINK_STATE_FAILED)
532 r = sd_rtnl_message_get_errno(m);
534 log_warning_link(link,
535 "could not bring up interface: %s", strerror(-r));
536 link_enter_failed(link);
539 link_update_flags(link, link->flags | IFF_UP);
544 static int link_up(Link *link) {
545 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
549 assert(link->manager);
550 assert(link->manager->rtnl);
552 log_debug_link(link, "bringing link up");
554 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
556 log_error_link(link, "Could not allocate RTM_SETLINK message");
560 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
562 log_error_link(link, "Could not set link flags: %s", strerror(-r));
566 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
569 "Could not send rtnetlink message: %s", strerror(-r));
576 static int link_bridge_joined(Link *link) {
580 assert(link->state == LINK_STATE_JOINING_BRIDGE);
581 assert(link->network);
585 link_enter_failed(link);
589 if (!link->network->dhcp)
590 return link_enter_set_addresses(link);
595 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
596 Link *link = userdata;
600 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
601 assert(link->network);
603 if (link->state == LINK_STATE_FAILED)
606 r = sd_rtnl_message_get_errno(m);
608 log_struct_link(LOG_ERR, link,
609 "MESSAGE=%s: could not join bridge '%s': %s",
610 link->ifname, link->network->bridge->name, strerror(-r),
611 BRIDGE(link->network->bridge),
613 link_enter_failed(link);
617 log_struct_link(LOG_DEBUG, link,
618 "MESSAGE=%s: joined bridge '%s'",
619 link->network->bridge->name,
620 BRIDGE(link->network->bridge),
623 link_bridge_joined(link);
628 static int link_enter_join_bridge(Link *link) {
632 assert(link->network);
633 assert(link->state == _LINK_STATE_INVALID);
635 link->state = LINK_STATE_JOINING_BRIDGE;
637 if (!link->network->bridge)
638 return link_bridge_joined(link);
640 log_struct_link(LOG_DEBUG, link,
641 "MESSAGE=%s: joining bridge '%s'",
642 link->network->bridge->name,
643 BRIDGE(link->network->bridge),
645 log_debug_link(link, "joining bridge");
647 r = bridge_join(link->network->bridge, link, &bridge_handler);
649 log_struct_link(LOG_WARNING, link,
650 "MESSAGE=%s: could not join bridge '%s': %s",
651 link->network->bridge->name, strerror(-r),
652 BRIDGE(link->network->bridge),
654 link_enter_failed(link);
661 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
662 Link *link = userdata;
667 if (link->state == LINK_STATE_FAILED)
670 r = sd_rtnl_message_get_errno(m);
672 log_warning_link(link, "could not get state: %s", strerror(-r));
673 link_enter_failed(link);
676 log_debug_link(link, "got link state");
678 link_update(link, m);
683 static int link_get(Link *link) {
684 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
688 assert(link->manager);
689 assert(link->manager->rtnl);
691 log_debug_link(link, "requesting link status");
693 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
695 log_error_link(link, "Could not allocate RTM_GETLINK message");
699 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
702 "Could not send rtnetlink message: %s", strerror(-r));
709 int link_configure(Link *link) {
713 assert(link->network);
714 assert(link->state == _LINK_STATE_INVALID);
718 link_enter_failed(link);
722 return link_enter_join_bridge(link);
725 int link_update(Link *link, sd_rtnl_message *m) {
732 if (link->state == LINK_STATE_FAILED)
735 r = sd_rtnl_message_link_get_flags(m, &flags);
737 log_warning_link(link, "could not get link flags");
741 return link_update_flags(link, flags);