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