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