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) {
102 ifindex = udev_device_get_ifindex(device);
103 link = hashmap_get(m->links, &ifindex);
107 r = link_new(m, device, &link);
111 devtype = udev_device_get_devtype(device);
112 if (streq_ptr(devtype, "bridge")) {
113 r = bridge_set_link(m, link);
115 return r == -ENOENT ? 0 : r;
118 r = network_get(m, device, &network);
120 return r == -ENOENT ? 0 : r;
122 r = network_apply(m, network, link);
129 static int link_enter_configured(Link *link) {
131 assert(link->state == LINK_STATE_SETTING_ROUTES);
133 log_info("%s: link configured", link->ifname);
135 link->state = LINK_STATE_CONFIGURED;
140 static void link_enter_failed(Link *link) {
143 log_warning("%s: failed", link->ifname);
145 link->state = LINK_STATE_FAILED;
148 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
149 Link *link = userdata;
152 assert(link->route_messages > 0);
153 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
154 link->state == LINK_STATE_SETTING_ROUTES ||
155 link->state == LINK_STATE_FAILED);
157 link->route_messages --;
159 if (link->state == LINK_STATE_FAILED)
162 r = sd_rtnl_message_get_errno(m);
163 if (r < 0 && r != -EEXIST)
164 log_warning("%s: could not set route: %s",
165 link->ifname, strerror(-r));
167 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
169 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
170 log_debug("%s: routes set", link->ifname);
171 link_enter_configured(link);
177 static int link_enter_set_routes(Link *link) {
182 assert(link->network);
183 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
185 link->state = LINK_STATE_SETTING_ROUTES;
187 if (!link->network->static_routes && !link->dhcp_route)
188 return link_enter_configured(link);
190 log_debug("%s: setting routes", link->ifname);
192 LIST_FOREACH(static_routes, route, link->network->static_routes) {
193 r = route_configure(route, link, &route_handler);
195 log_warning("%s: could not set routes", link->ifname);
196 link_enter_failed(link);
200 link->route_messages ++;
203 if (link->dhcp_route) {
204 r = route_configure(link->dhcp_route, link, &route_handler);
206 log_warning("%s: could not set routes", link->ifname);
207 link_enter_failed(link);
211 link->route_messages ++;
217 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
218 Link *link = userdata;
223 assert(link->ifname);
224 assert(link->addr_messages > 0);
225 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
227 link->addr_messages --;
229 if (link->state == LINK_STATE_FAILED)
232 r = sd_rtnl_message_get_errno(m);
233 if (r < 0 && r != -EEXIST)
234 log_warning("%s: could not set address: %s",
235 link->ifname, strerror(-r));
237 if (link->addr_messages == 0) {
238 log_debug("%s: addresses set", link->ifname);
239 link_enter_set_routes(link);
245 static int link_enter_set_addresses(Link *link) {
250 assert(link->network);
251 assert(link->state != _LINK_STATE_INVALID);
253 link->state = LINK_STATE_SETTING_ADDRESSES;
255 if (!link->network->static_addresses && !link->dhcp_address)
256 return link_enter_set_routes(link);
258 log_debug("%s: setting addresses", link->ifname);
260 LIST_FOREACH(static_addresses, address, link->network->static_addresses) {
261 r = address_configure(address, link, &address_handler);
263 log_warning("%s: could not set addresses", link->ifname);
264 link_enter_failed(link);
268 link->addr_messages ++;
271 if (link->dhcp_address) {
272 r = address_configure(link->dhcp_address, link, &address_handler);
274 log_warning("%s: could not set addresses", link->ifname);
275 link_enter_failed(link);
279 link->addr_messages ++;
285 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
286 Link *link = userdata;
291 assert(link->ifname);
293 if (link->state == LINK_STATE_FAILED)
296 r = sd_rtnl_message_get_errno(m);
297 if (r < 0 && r != -EEXIST)
298 log_warning("%s: could not drop address: %s",
299 link->ifname, strerror(-r));
304 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
305 Link *link = userdata;
306 struct in_addr address;
307 struct in_addr netmask;
308 struct in_addr gateway;
314 if (link->state == LINK_STATE_FAILED)
318 log_warning("%s: DHCP error: %s", link->ifname, strerror(-event));
319 link_enter_failed(link);
323 if (event == DHCP_EVENT_NO_LEASE)
324 log_debug("%s: IP address in use.", link->ifname);
326 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
327 event == DHCP_EVENT_STOP) {
328 if (link->dhcp_address) {
329 address_drop(link->dhcp_address, link, address_drop_handler);
331 address_free(link->dhcp_address);
332 link->dhcp_address = NULL;
335 if (link->dhcp_route) {
336 route_free(link->dhcp_route);
337 link->dhcp_route = NULL;
341 r = sd_dhcp_client_get_address(client, &address);
343 log_warning("%s: DHCP error: no address", link->ifname);
344 link_enter_failed(link);
348 r = sd_dhcp_client_get_netmask(client, &netmask);
350 log_warning("%s: DHCP error: no netmask", link->ifname);
351 link_enter_failed(link);
355 prefixlen = sd_dhcp_client_prefixlen(&netmask);
357 log_warning("%s: DHCP error: no prefixlen", link->ifname);
358 link_enter_failed(link);
362 r = sd_dhcp_client_get_router(client, &gateway);
364 log_warning("%s: DHCP error: no router", link->ifname);
365 link_enter_failed(link);
369 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
370 _cleanup_address_free_ Address *addr = NULL;
371 _cleanup_route_free_ Route *rt = NULL;
373 log_info("%s: received config over DHCPv4", link->ifname);
375 r = address_new_dynamic(&addr);
377 log_error("Could not allocate address");
378 link_enter_failed(link);
382 addr->family = AF_INET;
383 addr->in_addr.in = address;
384 addr->prefixlen = prefixlen;
385 addr->netmask = netmask;
387 r = route_new_dynamic(&rt);
389 log_error("Could not allocate route");
390 link_enter_failed(link);
394 rt->family = AF_INET;
395 rt->in_addr.in = gateway;
397 link->dhcp_address = addr;
398 link->dhcp_route = rt;
402 link_enter_set_addresses(link);
408 static int link_acquire_conf(Link *link) {
412 assert(link->network);
413 assert(link->network->dhcp);
414 assert(link->manager);
415 assert(link->manager->event);
418 link->dhcp = sd_dhcp_client_new(link->manager->event);
422 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
426 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
430 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
435 r = sd_dhcp_client_start(link->dhcp);
442 static int link_update_flags(Link *link, unsigned flags) {
446 assert(link->network);
448 if (link->state == LINK_STATE_FAILED)
451 if (link->flags == flags) {
452 log_debug("%s: link status unchanged: %#x", link->ifname, flags);
456 if ((link->flags & IFF_UP) != (flags & IFF_UP)) {
458 log_info("%s: power on", link->ifname);
460 log_info("%s: power off", link->ifname);
463 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
464 if (flags & IFF_LOWER_UP) {
465 log_info("%s: carrier on", link->ifname);
467 if (link->network->dhcp) {
468 r = link_acquire_conf(link);
470 link_enter_failed(link);
475 log_info("%s: carrier off", link->ifname);
477 if (link->network->dhcp) {
478 r = sd_dhcp_client_stop(link->dhcp);
480 link_enter_failed(link);
487 log_debug("%s: link status updated: %#x -> %#x", link->ifname, link->flags, flags);
494 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
495 Link *link = userdata;
500 if (link->state == LINK_STATE_FAILED)
503 r = sd_rtnl_message_get_errno(m);
505 log_warning("%s: could not bring up interface: %s",
506 link->ifname, strerror(-r));
507 link_enter_failed(link);
510 link_update_flags(link, link->flags | IFF_UP);
515 static int link_up(Link *link) {
516 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
520 assert(link->manager);
521 assert(link->manager->rtnl);
523 log_debug("%s: bringing up link", link->ifname);
525 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
527 log_error("Could not allocate RTM_SETLINK message");
531 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
533 log_error("Could not set link flags");
537 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
539 log_error("Could not send rtnetlink message: %s", strerror(-r));
546 static int link_bridge_joined(Link *link) {
550 assert(link->state == LINK_STATE_JOINING_BRIDGE);
551 assert(link->network);
555 link_enter_failed(link);
559 if (!link->network->dhcp)
560 return link_enter_set_addresses(link);
565 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
566 Link *link = userdata;
570 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
571 assert(link->network);
573 if (link->state == LINK_STATE_FAILED)
576 r = sd_rtnl_message_get_errno(m);
578 log_warning("%s: could not join bridge '%s': %s",
579 link->ifname, link->network->bridge->name, strerror(-r));
580 link_enter_failed(link);
583 log_debug("%s: joined bridge '%s'",
584 link->ifname, link->network->bridge->name);
586 link_bridge_joined(link);
591 static int link_enter_join_bridge(Link *link) {
595 assert(link->network);
596 assert(link->state == _LINK_STATE_INVALID);
598 link->state = LINK_STATE_JOINING_BRIDGE;
600 if (!link->network->bridge)
601 return link_bridge_joined(link);
603 log_debug("%s: joining bridge", link->ifname);
605 r = bridge_join(link->network->bridge, link, &bridge_handler);
607 log_warning("%s: could not join bridge '%s'", link->ifname,
608 link->network->bridge->name);
609 link_enter_failed(link);
616 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
617 Link *link = userdata;
622 if (link->state == LINK_STATE_FAILED)
625 r = sd_rtnl_message_get_errno(m);
627 log_warning("%s: could not get state: %s",
628 link->ifname, strerror(-r));
629 link_enter_failed(link);
632 log_debug("%s: got link state", link->ifname);
634 link_update(link, m);
639 static int link_get(Link *link) {
640 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
644 assert(link->manager);
645 assert(link->manager->rtnl);
647 log_debug("%s: requesting link status", link->ifname);
649 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
651 log_error("Could not allocate RTM_GETLINK message");
655 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
657 log_error("Could not send rtnetlink message: %s", strerror(-r));
664 int link_configure(Link *link) {
668 assert(link->network);
669 assert(link->state == _LINK_STATE_INVALID);
673 link_enter_failed(link);
677 return link_enter_join_bridge(link);
680 int link_update(Link *link, sd_rtnl_message *m) {
687 if (link->state == LINK_STATE_FAILED)
690 r = sd_rtnl_message_link_get_flags(m, &flags);
692 log_warning("%s: could not get link flags", link->ifname);
696 return link_update_flags(link, flags);