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