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