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