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