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