chiark / gitweb /
networkd: add basic bonding support
[elogind.git] / src / network / networkd-link.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Tom Gundersen <teg@jklm.no>
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <netinet/ether.h>
23 #include <linux/if.h>
24
25 #include "networkd.h"
26 #include "libudev-private.h"
27 #include "util.h"
28 #include "bus-util.h"
29
30 int link_new(Manager *manager, struct udev_device *device, Link **ret) {
31         _cleanup_link_free_ Link *link = NULL;
32         const char *mac;
33         struct ether_addr *mac_addr;
34         const char *ifname;
35         int r;
36
37         assert(device);
38         assert(ret);
39
40         link = new0(Link, 1);
41         if (!link)
42                 return -ENOMEM;
43
44         link->manager = manager;
45         link->state = _LINK_STATE_INVALID;
46
47         link->ifindex = udev_device_get_ifindex(device);
48         if (link->ifindex <= 0)
49                 return -EINVAL;
50
51         mac = udev_device_get_sysattr_value(device, "address");
52         if (mac) {
53                 mac_addr = ether_aton(mac);
54                 if (mac_addr)
55                         memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
56         }
57
58         ifname = udev_device_get_sysname(device);
59         link->ifname = strdup(ifname);
60
61         r = hashmap_put(manager->links, &link->ifindex, link);
62         if (r < 0)
63                 return r;
64
65         *ret = link;
66         link = NULL;
67
68         return 0;
69 }
70
71 void link_free(Link *link) {
72         if (!link)
73                 return;
74
75         assert(link->manager);
76
77         if (link->dhcp)
78                 sd_dhcp_client_free(link->dhcp);
79
80         route_free(link->dhcp_route);
81         link->dhcp_route = NULL;
82
83         address_free(link->dhcp_address);
84         link->dhcp_address = NULL;
85
86         hashmap_remove(link->manager->links, &link->ifindex);
87
88         free(link->ifname);
89
90         free(link);
91 }
92
93 int link_add(Manager *m, struct udev_device *device, Link **ret) {
94         Link *link;
95         Network *network;
96         int r;
97         uint64_t ifindex;
98         NetdevKind kind;
99
100         assert(m);
101         assert(device);
102
103         ifindex = udev_device_get_ifindex(device);
104         link = hashmap_get(m->links, &ifindex);
105         if (link) {
106                 *ret = link;
107                 return -EEXIST;
108         }
109
110         r = link_new(m, device, &link);
111         if (r < 0)
112                 return r;
113
114         *ret = link;
115
116         kind = netdev_kind_from_string(udev_device_get_devtype(device));
117         if (kind != _NETDEV_KIND_INVALID) {
118                 r = netdev_set_link(m, kind, link);
119                 if (r < 0 && r != -ENOENT)
120                         return r;
121         }
122
123         r = network_get(m, device, &network);
124         if (r < 0)
125                 return r == -ENOENT ? 0 : r;
126
127         r = network_apply(m, network, link);
128         if (r < 0)
129                 return r;
130
131         return 0;
132 }
133
134 static int link_enter_configured(Link *link) {
135         assert(link);
136         assert(link->state == LINK_STATE_SETTING_ROUTES);
137
138         log_info_link(link, "link configured");
139
140         link->state = LINK_STATE_CONFIGURED;
141
142         return 0;
143 }
144
145 static void link_enter_failed(Link *link) {
146         assert(link);
147
148         log_warning_link(link, "failed");
149
150         link->state = LINK_STATE_FAILED;
151 }
152
153 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
154         Link *link = userdata;
155         int r;
156
157         assert(link->route_messages > 0);
158         assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
159                link->state == LINK_STATE_SETTING_ROUTES ||
160                link->state == LINK_STATE_FAILED);
161
162         link->route_messages --;
163
164         if (link->state == LINK_STATE_FAILED)
165                 return 1;
166
167         r = sd_rtnl_message_get_errno(m);
168         if (r < 0 && r != -EEXIST)
169                 log_warning_link(link, "could not set route: %s", strerror(-r));
170
171         /* we might have received an old reply after moving back to SETTING_ADDRESSES,
172          * ignore it */
173         if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
174                 log_debug_link(link, "routes set");
175                 link_enter_configured(link);
176         }
177
178         return 1;
179 }
180
181 static int link_enter_set_routes(Link *link) {
182         Route *route;
183         int r;
184
185         assert(link);
186         assert(link->network);
187         assert(link->state == LINK_STATE_SETTING_ADDRESSES);
188
189         link->state = LINK_STATE_SETTING_ROUTES;
190
191         if (!link->network->static_routes && !link->dhcp_route)
192                 return link_enter_configured(link);
193
194         log_debug_link(link, "setting routes");
195
196         LIST_FOREACH(static_routes, route, link->network->static_routes) {
197                 r = route_configure(route, link, &route_handler);
198                 if (r < 0) {
199                         log_warning_link(link,
200                                          "could not set routes: %s", strerror(-r));
201                         link_enter_failed(link);
202                         return r;
203                 }
204
205                 link->route_messages ++;
206         }
207
208         if (link->dhcp_route) {
209                 r = route_configure(link->dhcp_route, link, &route_handler);
210                 if (r < 0) {
211                         log_warning_link(link,
212                                          "could not set routes: %s", strerror(-r));
213                         link_enter_failed(link);
214                         return r;
215                 }
216
217                 link->route_messages ++;
218         }
219
220         return 0;
221 }
222
223 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
224         Link *link = userdata;
225         int r;
226
227         assert(m);
228         assert(link);
229         assert(link->ifname);
230         assert(link->addr_messages > 0);
231         assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
232
233         link->addr_messages --;
234
235         if (link->state == LINK_STATE_FAILED)
236                 return 1;
237
238         r = sd_rtnl_message_get_errno(m);
239         if (r < 0 && r != -EEXIST)
240                 log_struct_link(LOG_ERR, link,
241                                 "MESSAGE=%s: could not set address: %s",
242                                 link->ifname, strerror(-r),
243                                 "ERRNO=%d", -r,
244                                 NULL);
245
246         if (link->addr_messages == 0) {
247                 log_debug_link(link, "addresses set");
248                 link_enter_set_routes(link);
249         }
250
251         return 1;
252 }
253
254 static int link_enter_set_addresses(Link *link) {
255         Address *address;
256         int r;
257
258         assert(link);
259         assert(link->network);
260         assert(link->state != _LINK_STATE_INVALID);
261
262         link->state = LINK_STATE_SETTING_ADDRESSES;
263
264         if (!link->network->static_addresses && !link->dhcp_address)
265                 return link_enter_set_routes(link);
266
267         log_debug_link(link, "setting addresses");
268
269         LIST_FOREACH(static_addresses, address, link->network->static_addresses) {
270                 r = address_configure(address, link, &address_handler);
271                 if (r < 0) {
272                         log_warning_link(link,
273                                          "could not set addresses: %s", strerror(-r));
274                         link_enter_failed(link);
275                         return r;
276                 }
277
278                 link->addr_messages ++;
279         }
280
281         if (link->dhcp_address) {
282                 r = address_configure(link->dhcp_address, link, &address_handler);
283                 if (r < 0) {
284                         log_warning_link(link,
285                                          "could not set addresses: %s", strerror(-r));
286                         link_enter_failed(link);
287                         return r;
288                 }
289
290                 link->addr_messages ++;
291         }
292
293         return 0;
294 }
295
296 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
297         Link *link = userdata;
298         int r;
299
300         assert(m);
301         assert(link);
302         assert(link->ifname);
303
304         if (link->state == LINK_STATE_FAILED)
305                 return 1;
306
307         r = sd_rtnl_message_get_errno(m);
308         if (r < 0 && r != -EEXIST)
309                 log_warning_link(link, "could not drop address: %s", strerror(-r));
310
311         return 1;
312 }
313
314 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
315         int r;
316
317         r = sd_bus_message_get_errno(m);
318         if (r < 0)
319                 log_warning("Could not set hostname: %s", strerror(-r));
320
321         return 1;
322 }
323
324 static int set_hostname(sd_bus *bus, const char *hostname) {
325         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
326         int r = 0;
327
328         assert(hostname);
329
330         log_debug("Setting transient hostname: '%s'", hostname);
331
332         if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
333                 log_info("Not connected to system bus, ignoring transient hostname.");
334                 return 0;
335         }
336
337         r = sd_bus_message_new_method_call(
338                         bus,
339                         "org.freedesktop.hostname1",
340                         "/org/freedesktop/hostname1",
341                         "org.freedesktop.hostname1",
342                         "SetHostname",
343                         &m);
344         if (r < 0)
345                 return r;
346
347         r = sd_bus_message_append(m, "sb", hostname, false);
348         if (r < 0)
349                 return r;
350
351         r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
352         if (r < 0)
353                 log_error("Could not set transient hostname: %s", strerror(-r));
354
355         return r;
356 }
357
358 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
359         Link *link = userdata;
360         int r;
361
362         assert(m);
363         assert(link);
364         assert(link->ifname);
365
366         if (link->state == LINK_STATE_FAILED)
367                 return 1;
368
369         r = sd_rtnl_message_get_errno(m);
370         if (r < 0 && r != -EEXIST)
371                 log_warning_link(link, "Could not set MTU: %s", strerror(-r));
372
373         return 1;
374 }
375
376 static int link_set_mtu(Link *link, uint32_t mtu) {
377         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
378         int r;
379
380         assert(link);
381         assert(link->manager);
382         assert(link->manager->rtnl);
383
384         log_debug_link(link, "setting MTU: %" PRIu32, mtu);
385
386         r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
387         if (r < 0) {
388                 log_error_link(link, "Could not allocate RTM_SETLINK message");
389                 return r;
390         }
391
392         r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
393         if (r < 0) {
394                 log_error_link(link, "Could not append MTU: %s", strerror(-r));
395                 return r;
396         }
397
398         r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
399         if (r < 0) {
400                 log_error_link(link,
401                                "Could not send rtnetlink message: %s", strerror(-r));
402                 return r;
403         }
404
405         return 0;
406 }
407
408 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
409         Link *link = userdata;
410         struct in_addr address;
411         struct in_addr netmask;
412         struct in_addr gateway;
413         int prefixlen;
414         int r;
415
416         assert(link);
417         assert(link->network);
418         assert(link->manager);
419
420         if (link->state == LINK_STATE_FAILED)
421                 return;
422
423         if (event < 0) {
424                 log_warning_link(link, "DHCP error: %s", strerror(-event));
425                 link_enter_failed(link);
426                 return;
427         }
428
429         if (event == DHCP_EVENT_NO_LEASE)
430                 log_debug_link(link, "IP address in use.");
431
432         if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
433             event == DHCP_EVENT_STOP) {
434                 if (link->dhcp_address) {
435                         address_drop(link->dhcp_address, link, address_drop_handler);
436
437                         address_free(link->dhcp_address);
438                         link->dhcp_address = NULL;
439                 }
440
441                 if (link->dhcp_route) {
442                         route_free(link->dhcp_route);
443                         link->dhcp_route = NULL;
444                 }
445
446                 if (link->network->dhcp_mtu) {
447                         uint16_t mtu;
448
449                         r = sd_dhcp_client_get_mtu(client, &mtu);
450                         if (r >= 0 && link->original_mtu != mtu) {
451                                 r = link_set_mtu(link, link->original_mtu);
452                                 if (r < 0) {
453                                         log_warning_link(link, "DHCP error: could not reset MTU");
454                                         link_enter_failed(link);
455                                         return;
456                                 }
457                         }
458                 }
459
460                 if (link->network->dhcp_hostname) {
461                         r = set_hostname(link->manager->bus, "");
462                         if (r < 0)
463                                 log_error("Failed to reset transient hostname");
464                 }
465         }
466
467         r = sd_dhcp_client_get_address(client, &address);
468         if (r < 0) {
469                 log_warning_link(link, "DHCP error: no address");
470                 link_enter_failed(link);
471                 return;
472         }
473
474         r = sd_dhcp_client_get_netmask(client, &netmask);
475         if (r < 0) {
476                 log_warning_link(link, "DHCP error: no netmask");
477                 link_enter_failed(link);
478                 return;
479         }
480
481         prefixlen = sd_dhcp_client_prefixlen(&netmask);
482         if (prefixlen < 0) {
483                 log_warning_link(link, "DHCP error: no prefixlen");
484                 link_enter_failed(link);
485                 return;
486         }
487
488         r = sd_dhcp_client_get_router(client, &gateway);
489         if (r < 0) {
490                 log_warning_link(link, "DHCP error: no router");
491                 link_enter_failed(link);
492                 return;
493         }
494
495         if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
496                 _cleanup_address_free_ Address *addr = NULL;
497                 _cleanup_route_free_ Route *rt = NULL;
498                 struct in_addr *nameservers;
499                 size_t nameservers_size;
500
501                 log_struct_link(LOG_INFO, link,
502                                 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
503                                 link->ifname,
504                                 ADDRESS_FMT_VAL(address),
505                                 prefixlen,
506                                 ADDRESS_FMT_VAL(gateway),
507                                 "ADDRESS=%u.%u.%u.%u",
508                                 ADDRESS_FMT_VAL(address),
509                                 "PREFIXLEN=%u",
510                                 prefixlen,
511                                 "GATEWAY=%u.%u.%u.%u",
512                                 ADDRESS_FMT_VAL(gateway),
513                                 NULL);
514
515                 r = address_new_dynamic(&addr);
516                 if (r < 0) {
517                         log_error_link(link, "Could not allocate address");
518                         link_enter_failed(link);
519                         return;
520                 }
521
522                 addr->family = AF_INET;
523                 addr->in_addr.in = address;
524                 addr->prefixlen = prefixlen;
525                 addr->netmask = netmask;
526
527                 r = route_new_dynamic(&rt);
528                 if (r < 0) {
529                         log_error_link(link, "Could not allocate route");
530                         link_enter_failed(link);
531                         return;
532                 }
533
534                 rt->family = AF_INET;
535                 rt->in_addr.in = gateway;
536
537                 link->dhcp_address = addr;
538                 link->dhcp_route = rt;
539                 addr = NULL;
540                 rt = NULL;
541
542                 if (link->network->dhcp_dns) {
543                         r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
544                         if (r >= 0) {
545                                 r = manager_update_resolv_conf(link->manager);
546                                 if (r < 0)
547                                         log_error("Failed to update resolv.conf");
548                         }
549                 }
550
551                 if (link->network->dhcp_mtu) {
552                         uint16_t mtu;
553
554                         r = sd_dhcp_client_get_mtu(client, &mtu);
555                         if (r >= 0) {
556                                 r = link_set_mtu(link, mtu);
557                                 if (r < 0)
558                                         log_error_link(link, "Failed to set MTU "
559                                                              "to %" PRIu16, mtu);
560                         }
561                 }
562
563                 if (link->network->dhcp_hostname) {
564                         const char *hostname;
565
566                         r = sd_dhcp_client_get_hostname(client, &hostname);
567                         if (r >= 0) {
568                                 r = set_hostname(link->manager->bus, hostname);
569                                 if (r < 0)
570                                         log_error("Failed to set transient hostname "
571                                                   "to '%s'", hostname);
572                         }
573                 }
574
575                 link_enter_set_addresses(link);
576         }
577
578         return;
579 }
580
581 static int link_acquire_conf(Link *link) {
582         int r;
583
584         assert(link);
585         assert(link->network);
586         assert(link->network->dhcp);
587         assert(link->manager);
588         assert(link->manager->event);
589
590         if (!link->dhcp) {
591                 r = sd_dhcp_client_new(&link->dhcp);
592                 if (r < 0)
593                         return r;
594
595                 r = sd_dhcp_client_attach_event(link->dhcp, NULL, 0);
596                 if (r < 0)
597                         return r;
598
599                 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
600                 if (r < 0)
601                         return r;
602
603                 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
604                 if (r < 0)
605                         return r;
606
607                 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
608                 if (r < 0)
609                         return r;
610
611                 if (link->network->dhcp_mtu) {
612                         r = sd_dhcp_client_set_request_option(link->dhcp, 26);
613                         if (r < 0)
614                                 return r;
615                 }
616         }
617
618         log_debug_link(link, "acquiring DHCPv4 lease");
619
620         r = sd_dhcp_client_start(link->dhcp);
621         if (r < 0)
622                 return r;
623
624         return 0;
625 }
626
627 static int link_update_flags(Link *link, unsigned flags) {
628         int r;
629
630         assert(link);
631         assert(link->network);
632
633         if (link->state == LINK_STATE_FAILED)
634                 return 0;
635
636         if (link->flags == flags) {
637                 log_debug_link(link, "link status unchanged: %#.8x", flags);
638                 return 0;
639         }
640
641         if ((link->flags & IFF_UP) != (flags & IFF_UP))
642                 log_info_link(link,
643                               "link is %s", flags & IFF_UP ? "up": "down");
644
645         if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
646                 if (flags & IFF_LOWER_UP) {
647                         log_info_link(link, "carrier on");
648
649                         if (link->network->dhcp) {
650                                 r = link_acquire_conf(link);
651                                 if (r < 0) {
652                                         log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
653                                         link_enter_failed(link);
654                                         return r;
655                                 }
656                         }
657                 } else {
658                         log_info_link(link, "carrier off");
659
660                         if (link->network->dhcp) {
661                                 r = sd_dhcp_client_stop(link->dhcp);
662                                 if (r < 0) {
663                                         log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
664                                         link_enter_failed(link);
665                                         return r;
666                                 }
667                         }
668                 }
669         }
670
671         log_debug_link(link,
672                        "link status updated: %#.8x -> %#.8x", link->flags, flags);
673
674         link->flags = flags;
675
676         return 0;
677 }
678
679 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
680         Link *link = userdata;
681         int r;
682
683         assert(link);
684
685         if (link->state == LINK_STATE_FAILED)
686                 return 1;
687
688         r = sd_rtnl_message_get_errno(m);
689         if (r < 0) {
690                 log_warning_link(link,
691                                  "could not bring up interface: %s", strerror(-r));
692                 link_enter_failed(link);
693         }
694
695         link_update_flags(link, link->flags | IFF_UP);
696
697         return 1;
698 }
699
700 static int link_up(Link *link) {
701         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
702         int r;
703
704         assert(link);
705         assert(link->manager);
706         assert(link->manager->rtnl);
707
708         log_debug_link(link, "bringing link up");
709
710         r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
711         if (r < 0) {
712                 log_error_link(link, "Could not allocate RTM_SETLINK message");
713                 return r;
714         }
715
716         r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
717         if (r < 0) {
718                 log_error_link(link, "Could not set link flags: %s", strerror(-r));
719                 return r;
720         }
721
722         r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
723         if (r < 0) {
724                 log_error_link(link,
725                                "Could not send rtnetlink message: %s", strerror(-r));
726                 return r;
727         }
728
729         return 0;
730 }
731
732 static int link_enslaved(Link *link) {
733         int r;
734
735         assert(link);
736         assert(link->state == LINK_STATE_ENSLAVING);
737         assert(link->network);
738
739         r = link_up(link);
740         if (r < 0) {
741                 link_enter_failed(link);
742                 return r;
743         }
744
745         if (!link->network->dhcp)
746                 return link_enter_set_addresses(link);
747
748         return 0;
749 }
750
751 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
752         Link *link = userdata;
753         int r;
754
755         assert(link);
756         assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
757         assert(link->network);
758
759         link->enslaving --;
760
761         if (link->state == LINK_STATE_FAILED)
762                 return 1;
763
764         r = sd_rtnl_message_get_errno(m);
765         if (r < 0) {
766                 log_error_link(link, "could not enslave: %s",
767                                strerror(-r));
768                 link_enter_failed(link);
769                 return 1;
770         }
771
772         log_debug_link(link, "enslaved");
773
774         if (link->enslaving == 0)
775                 link_enslaved(link);
776
777         return 1;
778 }
779
780 static int link_enter_enslave(Link *link) {
781         int r;
782
783         assert(link);
784         assert(link->network);
785         assert(link->state == _LINK_STATE_INVALID);
786
787         link->state = LINK_STATE_ENSLAVING;
788
789         if (!link->network->bridge && !link->network->bond)
790                 return link_enslaved(link);
791
792         if (link->network->bridge) {
793                 log_struct_link(LOG_DEBUG, link,
794                                 "MESSAGE=%s: enslaving by '%s'",
795                                 link->network->bridge->name,
796                                 NETDEV(link->network->bridge),
797                                 NULL);
798
799                 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
800                 if (r < 0) {
801                         log_struct_link(LOG_WARNING, link,
802                                         "MESSAGE=%s: could not enslave by '%s': %s",
803                                         link->network->bridge->name, strerror(-r),
804                                         NETDEV(link->network->bridge),
805                                         NULL);
806                         link_enter_failed(link);
807                         return r;
808                 }
809
810                 link->enslaving ++;
811         }
812
813         if (link->network->bond) {
814                 log_struct_link(LOG_DEBUG, link,
815                                 "MESSAGE=%s: enslaving by '%s'",
816                                 link->network->bond->name,
817                                 NETDEV(link->network->bond),
818                                 NULL);
819
820                 r = netdev_enslave(link->network->bond, link, &enslave_handler);
821                 if (r < 0) {
822                         log_struct_link(LOG_WARNING, link,
823                                         "MESSAGE=%s: could not enslave by '%s': %s",
824                                         link->network->bond->name, strerror(-r),
825                                         NETDEV(link->network->bond),
826                                         NULL);
827                         link_enter_failed(link);
828                         return r;
829                 }
830
831                 link->enslaving ++;
832         }
833
834         return 0;
835 }
836
837 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
838         Link *link = userdata;
839         int r;
840
841         assert(link);
842
843         if (link->state == LINK_STATE_FAILED)
844                 return 1;
845
846         r = sd_rtnl_message_get_errno(m);
847         if (r < 0) {
848                 log_warning_link(link, "could not get state: %s", strerror(-r));
849                 link_enter_failed(link);
850         }
851
852         log_debug_link(link, "got link state");
853
854         link_update(link, m);
855
856         return 1;
857 }
858
859 static int link_get(Link *link) {
860         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
861         int r;
862
863         assert(link);
864         assert(link->manager);
865         assert(link->manager->rtnl);
866
867         log_debug_link(link, "requesting link status");
868
869         r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
870         if (r < 0) {
871                 log_error_link(link, "Could not allocate RTM_GETLINK message");
872                 return r;
873         }
874
875         r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
876         if (r < 0) {
877                 log_error_link(link,
878                                "Could not send rtnetlink message: %s", strerror(-r));
879                 return r;
880         }
881
882         return 0;
883 }
884
885 int link_configure(Link *link) {
886         int r;
887
888         assert(link);
889         assert(link->network);
890         assert(link->state == _LINK_STATE_INVALID);
891
892         r = link_get(link);
893         if (r < 0) {
894                 link_enter_failed(link);
895                 return r;
896         }
897
898         return link_enter_enslave(link);
899 }
900
901 int link_update(Link *link, sd_rtnl_message *m) {
902         unsigned flags;
903         void *data;
904         uint16_t type;
905         int r;
906
907         assert(link);
908         assert(m);
909
910         if (link->state == LINK_STATE_FAILED)
911                 return 0;
912
913         r = sd_rtnl_message_link_get_flags(m, &flags);
914         if (r < 0) {
915                 log_warning_link(link, "Could not get link flags");
916                 return r;
917         }
918
919         while (sd_rtnl_message_read(m, &type, &data) > 0) {
920                 if (type == IFLA_MTU && link->network->dhcp &&
921                     link->network->dhcp_mtu && !link->original_mtu) {
922                         link->original_mtu = *(uint16_t *) data;
923                         log_debug_link(link, "saved original MTU: %" PRIu16,
924                                        link->original_mtu);
925                 }
926         }
927
928         return link_update_flags(link, flags);
929 }