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_link_info(link, "link configured");
139 link->state = LINK_STATE_CONFIGURED;
144 static void link_enter_failed(Link *link) {
147 log_link_warning(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_link_debug(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_link_debug(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_link_debug(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_link_debug(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_link_debug(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_link_warning(link, "DHCP error: no address");
353 link_enter_failed(link);
357 r = sd_dhcp_client_get_netmask(client, &netmask);
359 log_link_warning(link, "DHCP error: no netmask");
360 link_enter_failed(link);
364 prefixlen = sd_dhcp_client_prefixlen(&netmask);
366 log_link_warning(link, "DHCP error: no prefixlen");
367 link_enter_failed(link);
371 r = sd_dhcp_client_get_router(client, &gateway);
373 log_link_warning(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_link_info(link, "received config over DHCPv4");
384 r = address_new_dynamic(&addr);
386 log_link_error(link, "Could not allocate address");
387 link_enter_failed(link);
391 addr->family = AF_INET;
392 addr->in_addr.in = address;
393 addr->prefixlen = prefixlen;
394 addr->netmask = netmask;
396 r = route_new_dynamic(&rt);
398 log_link_error(link, "Could not allocate route");
399 link_enter_failed(link);
403 rt->family = AF_INET;
404 rt->in_addr.in = gateway;
406 link->dhcp_address = addr;
407 link->dhcp_route = rt;
411 link_enter_set_addresses(link);
417 static int link_acquire_conf(Link *link) {
421 assert(link->network);
422 assert(link->network->dhcp);
423 assert(link->manager);
424 assert(link->manager->event);
427 link->dhcp = sd_dhcp_client_new(link->manager->event);
431 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
435 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
439 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
444 r = sd_dhcp_client_start(link->dhcp);
451 static int link_update_flags(Link *link, unsigned flags) {
455 assert(link->network);
457 if (link->state == LINK_STATE_FAILED)
460 if (link->flags == flags) {
461 log_debug_link(link, "link status unchanged: %#x", flags);
465 if ((link->flags & IFF_UP) != (flags & IFF_UP))
467 "power %s", flags & IFF_UP ? "on": "off");
469 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
470 if (flags & IFF_LOWER_UP) {
471 log_link_info(link, "carrier on");
473 if (link->network->dhcp) {
474 r = link_acquire_conf(link);
476 link_enter_failed(link);
481 log_link_info(link, "carrier off");
483 if (link->network->dhcp) {
484 r = sd_dhcp_client_stop(link->dhcp);
486 link_enter_failed(link);
494 "link status updated: %#x -> %#x", link->flags, flags);
501 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
502 Link *link = userdata;
507 if (link->state == LINK_STATE_FAILED)
510 r = sd_rtnl_message_get_errno(m);
512 log_warning_link(link,
513 "could not bring up interface: %s", strerror(-r));
514 link_enter_failed(link);
517 link_update_flags(link, link->flags | IFF_UP);
522 static int link_up(Link *link) {
523 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
527 assert(link->manager);
528 assert(link->manager->rtnl);
530 log_link_debug(link, "bringing link up");
532 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
534 log_link_error(link, "Could not allocate RTM_SETLINK message");
538 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
540 log_error_link(link, "Could not set link flags: %s", strerror(-r));
544 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
547 "Could not send rtnetlink message: %s", strerror(-r));
554 static int link_bridge_joined(Link *link) {
558 assert(link->state == LINK_STATE_JOINING_BRIDGE);
559 assert(link->network);
563 link_enter_failed(link);
567 if (!link->network->dhcp)
568 return link_enter_set_addresses(link);
573 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
574 Link *link = userdata;
578 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
579 assert(link->network);
581 if (link->state == LINK_STATE_FAILED)
584 r = sd_rtnl_message_get_errno(m);
586 log_struct_link(LOG_ERR, link,
587 "MESSAGE=%s: could not join bridge '%s': %s",
588 link->ifname, link->network->bridge->name, strerror(-r),
589 BRIDGE(link->network->bridge),
591 link_enter_failed(link);
595 log_struct_link(LOG_DEBUG, link,
596 "MESSAGE=%s: joined bridge '%s'",
597 link->network->bridge->name,
598 BRIDGE(link->network->bridge),
600 link_bridge_joined(link);
605 static int link_enter_join_bridge(Link *link) {
609 assert(link->network);
610 assert(link->state == _LINK_STATE_INVALID);
612 link->state = LINK_STATE_JOINING_BRIDGE;
614 if (!link->network->bridge)
615 return link_bridge_joined(link);
617 log_struct_link(LOG_DEBUG, link,
618 "MESSAGE=%s: joining bridge '%s'",
619 link->network->bridge->name,
620 BRIDGE(link->network->bridge),
622 log_link_debug(link, "joining bridge");
624 r = bridge_join(link->network->bridge, link, &bridge_handler);
626 log_struct_link(LOG_WARNING, link,
627 "MESSAGE=%s: could not join bridge '%s': %s",
628 link->network->bridge->name, strerror(-r),
629 BRIDGE(link->network->bridge),
631 link_enter_failed(link);
638 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
639 Link *link = userdata;
644 if (link->state == LINK_STATE_FAILED)
647 r = sd_rtnl_message_get_errno(m);
649 log_warning_link(link, "could not get state: %s", strerror(-r));
650 link_enter_failed(link);
653 log_link_debug(link, "got link state");
655 link_update(link, m);
660 static int link_get(Link *link) {
661 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
665 assert(link->manager);
666 assert(link->manager->rtnl);
668 log_link_debug(link, "requesting link status");
670 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
672 log_link_error(link, "Could not allocate RTM_GETLINK message");
676 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
679 "Could not send rtnetlink message: %s", strerror(-r));
686 int link_configure(Link *link) {
690 assert(link->network);
691 assert(link->state == _LINK_STATE_INVALID);
695 link_enter_failed(link);
699 return link_enter_join_bridge(link);
702 int link_update(Link *link, sd_rtnl_message *m) {
709 if (link->state == LINK_STATE_FAILED)
712 r = sd_rtnl_message_link_get_flags(m, &flags);
714 log_link_warning(link, "could not get link flags");
718 return link_update_flags(link, flags);