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