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