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