chiark / gitweb /
bus: add API calls for connecting to starter bus
[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->dhcp_address) {
447                         address_drop(link->dhcp_address, link, address_drop_handler);
448
449                         address_free(link->dhcp_address);
450                         link->dhcp_address = NULL;
451                 }
452
453                 if (link->dhcp_route) {
454                         route_free(link->dhcp_route);
455                         link->dhcp_route = NULL;
456                 }
457
458                 if (link->network->dhcp_mtu) {
459                         uint16_t mtu;
460
461                         r = sd_dhcp_client_get_mtu(client, &mtu);
462                         if (r >= 0 && link->original_mtu != mtu) {
463                                 r = link_set_mtu(link, link->original_mtu);
464                                 if (r < 0) {
465                                         log_warning_link(link, "DHCP error: could not reset MTU");
466                                         link_enter_failed(link);
467                                         return;
468                                 }
469                         }
470                 }
471
472                 if (link->network->dhcp_hostname) {
473                         r = set_hostname(link->manager->bus, "");
474                         if (r < 0)
475                                 log_error("Failed to reset transient hostname");
476                 }
477         }
478
479         r = sd_dhcp_client_get_address(client, &address);
480         if (r < 0) {
481                 log_warning_link(link, "DHCP error: no address");
482                 link_enter_failed(link);
483                 return;
484         }
485
486         r = sd_dhcp_client_get_netmask(client, &netmask);
487         if (r < 0) {
488                 log_warning_link(link, "DHCP error: no netmask");
489                 link_enter_failed(link);
490                 return;
491         }
492
493         prefixlen = sd_dhcp_client_prefixlen(&netmask);
494         if (prefixlen < 0) {
495                 log_warning_link(link, "DHCP error: no prefixlen");
496                 link_enter_failed(link);
497                 return;
498         }
499
500         r = sd_dhcp_client_get_router(client, &gateway);
501         if (r < 0) {
502                 log_warning_link(link, "DHCP error: no router");
503                 link_enter_failed(link);
504                 return;
505         }
506
507         if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
508                 _cleanup_address_free_ Address *addr = NULL;
509                 _cleanup_route_free_ Route *rt = NULL;
510                 struct in_addr *nameservers;
511                 size_t nameservers_size;
512
513                 log_struct_link(LOG_INFO, link,
514                                 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
515                                 link->ifname,
516                                 ADDRESS_FMT_VAL(address),
517                                 prefixlen,
518                                 ADDRESS_FMT_VAL(gateway),
519                                 "ADDRESS=%u.%u.%u.%u",
520                                 ADDRESS_FMT_VAL(address),
521                                 "PREFIXLEN=%u",
522                                 prefixlen,
523                                 "GATEWAY=%u.%u.%u.%u",
524                                 ADDRESS_FMT_VAL(gateway),
525                                 NULL);
526
527                 r = address_new_dynamic(&addr);
528                 if (r < 0) {
529                         log_error_link(link, "Could not allocate address");
530                         link_enter_failed(link);
531                         return;
532                 }
533
534                 addr->family = AF_INET;
535                 addr->in_addr.in = address;
536                 addr->prefixlen = prefixlen;
537                 addr->netmask = netmask;
538
539                 r = route_new_dynamic(&rt);
540                 if (r < 0) {
541                         log_error_link(link, "Could not allocate route");
542                         link_enter_failed(link);
543                         return;
544                 }
545
546                 rt->family = AF_INET;
547                 rt->in_addr.in = gateway;
548
549                 link->dhcp_address = addr;
550                 link->dhcp_route = rt;
551                 addr = NULL;
552                 rt = NULL;
553
554                 if (link->network->dhcp_dns) {
555                         r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
556                         if (r >= 0) {
557                                 r = manager_update_resolv_conf(link->manager);
558                                 if (r < 0)
559                                         log_error("Failed to update resolv.conf");
560                         }
561                 }
562
563                 if (link->network->dhcp_mtu) {
564                         uint16_t mtu;
565
566                         r = sd_dhcp_client_get_mtu(client, &mtu);
567                         if (r >= 0) {
568                                 r = link_set_mtu(link, mtu);
569                                 if (r < 0)
570                                         log_error_link(link, "Failed to set MTU "
571                                                              "to %" PRIu16, mtu);
572                         }
573                 }
574
575                 if (link->network->dhcp_hostname) {
576                         const char *hostname;
577
578                         r = sd_dhcp_client_get_hostname(client, &hostname);
579                         if (r >= 0) {
580                                 r = set_hostname(link->manager->bus, hostname);
581                                 if (r < 0)
582                                         log_error("Failed to set transient hostname "
583                                                   "to '%s'", hostname);
584                         }
585                 }
586
587                 link_enter_set_addresses(link);
588         }
589
590         return;
591 }
592
593 static int link_acquire_conf(Link *link) {
594         int r;
595
596         assert(link);
597         assert(link->network);
598         assert(link->network->dhcp);
599         assert(link->manager);
600         assert(link->manager->event);
601
602         if (!link->dhcp) {
603                 r = sd_dhcp_client_new(&link->dhcp);
604                 if (r < 0)
605                         return r;
606
607                 r = sd_dhcp_client_attach_event(link->dhcp, NULL, 0);
608                 if (r < 0)
609                         return r;
610
611                 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
612                 if (r < 0)
613                         return r;
614
615                 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
616                 if (r < 0)
617                         return r;
618
619                 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
620                 if (r < 0)
621                         return r;
622
623                 if (link->network->dhcp_mtu) {
624                         r = sd_dhcp_client_set_request_option(link->dhcp, 26);
625                         if (r < 0)
626                                 return r;
627                 }
628         }
629
630         log_debug_link(link, "acquiring DHCPv4 lease");
631
632         r = sd_dhcp_client_start(link->dhcp);
633         if (r < 0)
634                 return r;
635
636         return 0;
637 }
638
639 static int link_update_flags(Link *link, unsigned flags) {
640         int r;
641
642         assert(link);
643         assert(link->network);
644
645         if (link->state == LINK_STATE_FAILED)
646                 return 0;
647
648         if (link->flags == flags) {
649                 log_debug_link(link, "link status unchanged: %#.8x", flags);
650                 return 0;
651         }
652
653         if ((link->flags & IFF_UP) != (flags & IFF_UP))
654                 log_info_link(link,
655                               "link is %s", flags & IFF_UP ? "up": "down");
656
657         if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
658                 if (flags & IFF_LOWER_UP) {
659                         log_info_link(link, "carrier on");
660
661                         if (link->network->dhcp) {
662                                 r = link_acquire_conf(link);
663                                 if (r < 0) {
664                                         log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
665                                         link_enter_failed(link);
666                                         return r;
667                                 }
668                         }
669                 } else {
670                         log_info_link(link, "carrier off");
671
672                         if (link->network->dhcp) {
673                                 r = sd_dhcp_client_stop(link->dhcp);
674                                 if (r < 0) {
675                                         log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
676                                         link_enter_failed(link);
677                                         return r;
678                                 }
679                         }
680                 }
681         }
682
683         log_debug_link(link,
684                        "link status updated: %#.8x -> %#.8x", link->flags, flags);
685
686         link->flags = flags;
687
688         return 0;
689 }
690
691 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
692         Link *link = userdata;
693         int r;
694
695         assert(link);
696
697         if (link->state == LINK_STATE_FAILED)
698                 return 1;
699
700         r = sd_rtnl_message_get_errno(m);
701         if (r < 0) {
702                 log_struct_link(LOG_ERR, link,
703                                 "MESSAGE=%s: could not bring up interface: %s",
704                                 link->ifname, strerror(-r),
705                                 "ERRNO=%d", -r,
706                                 NULL);
707                 link_enter_failed(link);
708                 return 1;
709         }
710
711         link_update_flags(link, link->flags | IFF_UP);
712
713         return 1;
714 }
715
716 static int link_up(Link *link) {
717         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
718         int r;
719
720         assert(link);
721         assert(link->manager);
722         assert(link->manager->rtnl);
723
724         log_debug_link(link, "bringing link up");
725
726         r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
727         if (r < 0) {
728                 log_error_link(link, "Could not allocate RTM_SETLINK message");
729                 return r;
730         }
731
732         r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
733         if (r < 0) {
734                 log_error_link(link, "Could not set link flags: %s", strerror(-r));
735                 return r;
736         }
737
738         r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
739         if (r < 0) {
740                 log_error_link(link,
741                                "Could not send rtnetlink message: %s", strerror(-r));
742                 return r;
743         }
744
745         return 0;
746 }
747
748 static int link_enslaved(Link *link) {
749         int r;
750
751         assert(link);
752         assert(link->state == LINK_STATE_ENSLAVING);
753         assert(link->network);
754
755         r = link_up(link);
756         if (r < 0) {
757                 link_enter_failed(link);
758                 return r;
759         }
760
761         if (!link->network->dhcp)
762                 return link_enter_set_addresses(link);
763
764         return 0;
765 }
766
767 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
768         Link *link = userdata;
769         int r;
770
771         assert(link);
772         assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
773         assert(link->network);
774
775         link->enslaving --;
776
777         if (link->state == LINK_STATE_FAILED)
778                 return 1;
779
780         r = sd_rtnl_message_get_errno(m);
781         if (r < 0) {
782                 log_struct_link(LOG_ERR, link,
783                                 "MESSAGE=%s: could not enslave: %s",
784                                 link->ifname, strerror(-r),
785                                 "ERRNO=%d", -r,
786                                 NULL);
787                 link_enter_failed(link);
788                 return 1;
789         }
790
791         log_debug_link(link, "enslaved");
792
793         if (link->enslaving == 0)
794                 link_enslaved(link);
795
796         return 1;
797 }
798
799 static int link_enter_enslave(Link *link) {
800         int r;
801
802         assert(link);
803         assert(link->network);
804         assert(link->state == _LINK_STATE_INVALID);
805
806         link->state = LINK_STATE_ENSLAVING;
807
808         if (!link->network->bridge && !link->network->bond && !link->network->vlan)
809                 return link_enslaved(link);
810
811         if (link->network->bridge) {
812                 log_struct_link(LOG_DEBUG, link,
813                                 "MESSAGE=%s: enslaving by '%s'",
814                                 link->ifname, link->network->bridge->name,
815                                 NETDEV(link->network->bridge),
816                                 NULL);
817
818                 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
819                 if (r < 0) {
820                         log_struct_link(LOG_WARNING, link,
821                                         "MESSAGE=%s: could not enslave by '%s': %s",
822                                         link->ifname, link->network->bridge->name, strerror(-r),
823                                         NETDEV(link->network->bridge),
824                                         NULL);
825                         link_enter_failed(link);
826                         return r;
827                 }
828
829                 link->enslaving ++;
830         }
831
832         if (link->network->vlan) {
833                 log_struct_link(LOG_DEBUG, link,
834                                 "MESSAGE=%s: enslaving by '%s'",
835                                 link->ifname, link->network->vlan->name,
836                                 NETDEV(link->network->vlan),
837                                 NULL);
838
839                 r = netdev_enslave(link->network->vlan, link, &enslave_handler);
840                 if (r < 0) {
841                         log_struct_link(LOG_WARNING, link,
842                                         "MESSAGE=%s: could not enslave by '%s': %s",
843                                         link->ifname, link->network->vlan->name,
844                                         strerror(-r), NETDEV(link->network->vlan),
845                                         NULL);
846                         link_enter_failed(link);
847                         return r;
848                 }
849
850                 link->enslaving ++;
851         }
852
853         return 0;
854 }
855
856 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
857         Link *link = userdata;
858         int r;
859
860         assert(link);
861
862         if (link->state == LINK_STATE_FAILED)
863                 return 1;
864
865         r = sd_rtnl_message_get_errno(m);
866         if (r < 0) {
867                 log_struct_link(LOG_ERR, link,
868                                 "MESSAGE=%s: could not get state: %s",
869                                 link->ifname, strerror(-r),
870                                 "ERRNO=%d", -r,
871                                 NULL);
872                 link_enter_failed(link);
873                 return 1;
874         }
875
876         log_debug_link(link, "got link state");
877
878         link_update(link, m);
879
880         return 1;
881 }
882
883 static int link_get(Link *link) {
884         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
885         int r;
886
887         assert(link);
888         assert(link->manager);
889         assert(link->manager->rtnl);
890
891         log_debug_link(link, "requesting link status");
892
893         r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
894         if (r < 0) {
895                 log_error_link(link, "Could not allocate RTM_GETLINK message");
896                 return r;
897         }
898
899         r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
900         if (r < 0) {
901                 log_error_link(link,
902                                "Could not send rtnetlink message: %s", strerror(-r));
903                 return r;
904         }
905
906         return 0;
907 }
908
909 int link_configure(Link *link) {
910         int r;
911
912         assert(link);
913         assert(link->network);
914         assert(link->state == _LINK_STATE_INVALID);
915
916         r = link_get(link);
917         if (r < 0) {
918                 link_enter_failed(link);
919                 return r;
920         }
921
922         return link_enter_enslave(link);
923 }
924
925 int link_update(Link *link, sd_rtnl_message *m) {
926         unsigned flags;
927         void *data;
928         uint16_t type;
929         int r;
930
931         assert(link);
932         assert(m);
933
934         if (link->state == LINK_STATE_FAILED)
935                 return 0;
936
937         r = sd_rtnl_message_link_get_flags(m, &flags);
938         if (r < 0) {
939                 log_warning_link(link, "Could not get link flags");
940                 return r;
941         }
942
943         while (sd_rtnl_message_read(m, &type, &data) > 0) {
944                 if (type == IFLA_MTU && link->network->dhcp &&
945                     link->network->dhcp_mtu && !link->original_mtu) {
946                         link->original_mtu = *(uint16_t *) data;
947                         log_debug_link(link, "saved original MTU: %" PRIu16,
948                                        link->original_mtu);
949                 }
950         }
951
952         return link_update_flags(link, flags);
953 }