]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-link.c
networkd: rearrange checks when to write something into sysctl 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 #include <unistd.h>
25
26 #include "alloc-util.h"
27 #include "bus-util.h"
28 #include "dhcp-lease-internal.h"
29 #include "event-util.h"
30 #include "fd-util.h"
31 #include "fileio.h"
32 #include "netlink-util.h"
33 #include "network-internal.h"
34 #include "networkd-link.h"
35 #include "networkd-netdev.h"
36 #include "set.h"
37 #include "socket-util.h"
38 #include "stdio-util.h"
39 #include "string-table.h"
40 #include "udev-util.h"
41 #include "util.h"
42 #include "virt.h"
43
44 bool link_dhcp6_enabled(Link *link) {
45 if (link->flags & IFF_LOOPBACK)
46 return false;
47
48 if (!link->network)
49 return false;
50
51 return link->network->dhcp & ADDRESS_FAMILY_IPV6;
52 }
53
54 bool link_dhcp4_enabled(Link *link) {
55 if (link->flags & IFF_LOOPBACK)
56 return false;
57
58 if (!link->network)
59 return false;
60
61 return link->network->dhcp & ADDRESS_FAMILY_IPV4;
62 }
63
64 bool link_dhcp4_server_enabled(Link *link) {
65 if (link->flags & IFF_LOOPBACK)
66 return false;
67
68 if (!link->network)
69 return false;
70
71 return link->network->dhcp_server;
72 }
73
74 bool link_ipv4ll_enabled(Link *link) {
75 if (link->flags & IFF_LOOPBACK)
76 return false;
77
78 if (!link->network)
79 return false;
80
81 return link->network->link_local & ADDRESS_FAMILY_IPV4;
82 }
83
84 bool link_ipv6ll_enabled(Link *link) {
85 if (link->flags & IFF_LOOPBACK)
86 return false;
87
88 if (!link->network)
89 return false;
90
91 return link->network->link_local & ADDRESS_FAMILY_IPV6;
92 }
93
94 bool link_lldp_enabled(Link *link) {
95 if (link->flags & IFF_LOOPBACK)
96 return false;
97
98 if (!link->network)
99 return false;
100
101 if (link->network->bridge)
102 return false;
103
104 return link->network->lldp;
105 }
106
107 static bool link_ipv4_forward_enabled(Link *link) {
108 if (link->flags & IFF_LOOPBACK)
109 return false;
110
111 if (!link->network)
112 return false;
113
114 return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
115 }
116
117 static bool link_ipv6_forward_enabled(Link *link) {
118 if (link->flags & IFF_LOOPBACK)
119 return false;
120
121 if (!link->network)
122 return false;
123
124 return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
125 }
126
127 bool link_ipv6_accept_ra_enabled(Link *link) {
128 if (link->flags & IFF_LOOPBACK)
129 return false;
130
131 if (!link->network)
132 return false;
133
134 /* If unset use system default (enabled if local forwarding is disabled.
135 * disabled if local forwarding is enabled).
136 * If set, ignore or enforce RA independent of local forwarding state.
137 */
138 if (link->network->ipv6_accept_ra < 0)
139 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
140 return !link_ipv6_forward_enabled(link);
141 else if (link->network->ipv6_accept_ra > 0)
142 /* accept RA even if ip_forward is enabled */
143 return true;
144 else
145 /* ignore RA */
146 return false;
147 }
148
149 static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
150
151 if (!socket_ipv6_is_supported())
152 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
153
154 if (link->flags & IFF_LOOPBACK)
155 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
156
157 if (!link->network)
158 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
159
160 return link->network->ipv6_privacy_extensions;
161 }
162
163 void link_update_operstate(Link *link) {
164 LinkOperationalState operstate;
165 assert(link);
166
167 if (link->kernel_operstate == IF_OPER_DORMANT)
168 operstate = LINK_OPERSTATE_DORMANT;
169 else if (link_has_carrier(link)) {
170 Address *address;
171 uint8_t scope = RT_SCOPE_NOWHERE;
172 Iterator i;
173
174 /* if we have carrier, check what addresses we have */
175 SET_FOREACH(address, link->addresses, i) {
176 if (!address_is_ready(address))
177 continue;
178
179 if (address->scope < scope)
180 scope = address->scope;
181 }
182
183 /* for operstate we also take foreign addresses into account */
184 SET_FOREACH(address, link->addresses_foreign, i) {
185 if (!address_is_ready(address))
186 continue;
187
188 if (address->scope < scope)
189 scope = address->scope;
190 }
191
192 if (scope < RT_SCOPE_SITE)
193 /* universally accessible addresses found */
194 operstate = LINK_OPERSTATE_ROUTABLE;
195 else if (scope < RT_SCOPE_HOST)
196 /* only link or site local addresses found */
197 operstate = LINK_OPERSTATE_DEGRADED;
198 else
199 /* no useful addresses found */
200 operstate = LINK_OPERSTATE_CARRIER;
201 } else if (link->flags & IFF_UP)
202 operstate = LINK_OPERSTATE_NO_CARRIER;
203 else
204 operstate = LINK_OPERSTATE_OFF;
205
206 if (link->operstate != operstate) {
207 link->operstate = operstate;
208 link_send_changed(link, "OperationalState", NULL);
209 link_dirty(link);
210 manager_dirty(link->manager);
211 }
212 }
213
214 #define FLAG_STRING(string, flag, old, new) \
215 (((old ^ new) & flag) \
216 ? ((old & flag) ? (" -" string) : (" +" string)) \
217 : "")
218
219 static int link_update_flags(Link *link, sd_netlink_message *m) {
220 unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
221 uint8_t operstate;
222 int r;
223
224 assert(link);
225
226 r = sd_rtnl_message_link_get_flags(m, &flags);
227 if (r < 0)
228 return log_link_warning_errno(link, r, "Could not get link flags: %m");
229
230 r = sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &operstate);
231 if (r < 0)
232 /* if we got a message without operstate, take it to mean
233 the state was unchanged */
234 operstate = link->kernel_operstate;
235
236 if ((link->flags == flags) && (link->kernel_operstate == operstate))
237 return 0;
238
239 if (link->flags != flags) {
240 log_link_debug(link, "Flags change:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
241 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
242 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
243 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
244 FLAG_STRING("UP", IFF_UP, link->flags, flags),
245 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
246 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
247 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
248 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
249 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
250 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
251 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
252 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
253 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
254 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
255 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
256 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
257 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
258 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
259 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
260
261 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
262 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
263 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
264 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
265 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
266 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
267 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
268 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
269
270 /* link flags are currently at most 18 bits, let's align to
271 * printing 20 */
272 if (unknown_flags_added)
273 log_link_debug(link,
274 "Unknown link flags gained: %#.5x (ignoring)",
275 unknown_flags_added);
276
277 if (unknown_flags_removed)
278 log_link_debug(link,
279 "Unknown link flags lost: %#.5x (ignoring)",
280 unknown_flags_removed);
281 }
282
283 link->flags = flags;
284 link->kernel_operstate = operstate;
285
286 link_update_operstate(link);
287
288 return 0;
289 }
290
291 static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
292 _cleanup_link_unref_ Link *link = NULL;
293 uint16_t type;
294 const char *ifname;
295 int r, ifindex;
296
297 assert(manager);
298 assert(message);
299 assert(ret);
300
301 r = sd_netlink_message_get_type(message, &type);
302 if (r < 0)
303 return r;
304 else if (type != RTM_NEWLINK)
305 return -EINVAL;
306
307 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
308 if (r < 0)
309 return r;
310 else if (ifindex <= 0)
311 return -EINVAL;
312
313 r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
314 if (r < 0)
315 return r;
316
317 link = new0(Link, 1);
318 if (!link)
319 return -ENOMEM;
320
321 link->n_ref = 1;
322 link->manager = manager;
323 link->state = LINK_STATE_PENDING;
324 link->rtnl_extended_attrs = true;
325 link->ifindex = ifindex;
326 link->ifname = strdup(ifname);
327 if (!link->ifname)
328 return -ENOMEM;
329
330 r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
331 if (r < 0)
332 log_link_debug(link, "MAC address not found for new device, continuing without");
333
334 r = asprintf(&link->state_file, "/run/systemd/netif/links/%d",
335 link->ifindex);
336 if (r < 0)
337 return -ENOMEM;
338
339 r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d",
340 link->ifindex);
341 if (r < 0)
342 return -ENOMEM;
343
344 r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d",
345 link->ifindex);
346 if (r < 0)
347 return -ENOMEM;
348
349
350 r = hashmap_ensure_allocated(&manager->links, NULL);
351 if (r < 0)
352 return r;
353
354 r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
355 if (r < 0)
356 return r;
357
358 r = link_update_flags(link, message);
359 if (r < 0)
360 return r;
361
362 *ret = link;
363 link = NULL;
364
365 return 0;
366 }
367
368 static void link_free(Link *link) {
369 Address *address;
370 Iterator i;
371 Link *carrier;
372
373 if (!link)
374 return;
375
376 while (!set_isempty(link->addresses))
377 address_free(set_first(link->addresses));
378
379 while (!set_isempty(link->addresses_foreign))
380 address_free(set_first(link->addresses_foreign));
381
382 link->addresses = set_free(link->addresses);
383
384 link->addresses_foreign = set_free(link->addresses_foreign);
385
386 while ((address = link->pool_addresses)) {
387 LIST_REMOVE(addresses, link->pool_addresses, address);
388 address_free(address);
389 }
390
391 sd_dhcp_server_unref(link->dhcp_server);
392 sd_dhcp_client_unref(link->dhcp_client);
393 sd_dhcp_lease_unref(link->dhcp_lease);
394
395 free(link->lease_file);
396
397 sd_lldp_free(link->lldp);
398
399 free(link->lldp_file);
400
401 sd_ipv4ll_unref(link->ipv4ll);
402 sd_dhcp6_client_unref(link->dhcp6_client);
403 sd_ndisc_unref(link->ndisc_router_discovery);
404
405 if (link->manager)
406 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
407
408 free(link->ifname);
409
410 (void)unlink(link->state_file);
411 free(link->state_file);
412
413 udev_device_unref(link->udev_device);
414
415 HASHMAP_FOREACH (carrier, link->bound_to_links, i)
416 hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex));
417 hashmap_free(link->bound_to_links);
418
419 HASHMAP_FOREACH (carrier, link->bound_by_links, i)
420 hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
421 hashmap_free(link->bound_by_links);
422
423 free(link);
424 }
425
426 Link *link_unref(Link *link) {
427 if (!link)
428 return NULL;
429
430 assert(link->n_ref > 0);
431
432 link->n_ref --;
433
434 if (link->n_ref > 0)
435 return NULL;
436
437 link_free(link);
438
439 return NULL;
440 }
441
442 Link *link_ref(Link *link) {
443 if (!link)
444 return NULL;
445
446 assert(link->n_ref > 0);
447
448 link->n_ref ++;
449
450 return link;
451 }
452
453 int link_get(Manager *m, int ifindex, Link **ret) {
454 Link *link;
455
456 assert(m);
457 assert(ifindex);
458 assert(ret);
459
460 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
461 if (!link)
462 return -ENODEV;
463
464 *ret = link;
465
466 return 0;
467 }
468
469 static void link_set_state(Link *link, LinkState state) {
470 assert(link);
471
472 if (link->state == state)
473 return;
474
475 link->state = state;
476
477 link_send_changed(link, "AdministrativeState", NULL);
478
479 return;
480 }
481
482 static void link_enter_unmanaged(Link *link) {
483 assert(link);
484
485 log_link_debug(link, "Unmanaged");
486
487 link_set_state(link, LINK_STATE_UNMANAGED);
488
489 link_dirty(link);
490 }
491
492 static int link_stop_clients(Link *link) {
493 int r = 0, k;
494
495 assert(link);
496 assert(link->manager);
497 assert(link->manager->event);
498
499 if (!link->network)
500 return 0;
501
502 if (link->dhcp_client) {
503 k = sd_dhcp_client_stop(link->dhcp_client);
504 if (k < 0)
505 r = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m");
506 }
507
508 if (link->ipv4ll) {
509 k = sd_ipv4ll_stop(link->ipv4ll);
510 if (k < 0)
511 r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m");
512 }
513
514 if (link->dhcp6_client) {
515 k = sd_dhcp6_client_stop(link->dhcp6_client);
516 if (k < 0)
517 r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
518 }
519
520 if (link->ndisc_router_discovery) {
521 k = sd_ndisc_stop(link->ndisc_router_discovery);
522 if (k < 0)
523 r = log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m");
524 }
525
526 if (link->lldp) {
527 k = sd_lldp_stop(link->lldp);
528 if (k < 0)
529 r = log_link_warning_errno(link, r, "Could not stop LLDP: %m");
530 }
531
532 return r;
533 }
534
535 void link_enter_failed(Link *link) {
536 assert(link);
537
538 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
539 return;
540
541 log_link_warning(link, "Failed");
542
543 link_set_state(link, LINK_STATE_FAILED);
544
545 link_stop_clients(link);
546
547 link_dirty(link);
548 }
549
550 static Address* link_find_dhcp_server_address(Link *link) {
551 Address *address;
552
553 assert(link);
554 assert(link->network);
555
556 /* The first statically configured address if there is any */
557 LIST_FOREACH(addresses, address, link->network->static_addresses) {
558
559 if (address->family != AF_INET)
560 continue;
561
562 if (in_addr_is_null(address->family, &address->in_addr))
563 continue;
564
565 return address;
566 }
567
568 /* If that didn't work, find a suitable address we got from the pool */
569 LIST_FOREACH(addresses, address, link->pool_addresses) {
570 if (address->family != AF_INET)
571 continue;
572
573 return address;
574 }
575
576 return NULL;
577 }
578
579 static int link_enter_configured(Link *link) {
580 assert(link);
581 assert(link->network);
582 assert(link->state == LINK_STATE_SETTING_ROUTES);
583
584 log_link_info(link, "Configured");
585
586 link_set_state(link, LINK_STATE_CONFIGURED);
587
588 link_dirty(link);
589
590 return 0;
591 }
592
593 void link_check_ready(Link *link) {
594 Address *a;
595 Iterator i;
596
597 assert(link);
598
599 if (!link->network)
600 return;
601
602 if (!link->static_configured)
603 return;
604
605 if (link_ipv4ll_enabled(link))
606 if (!link->ipv4ll_address ||
607 !link->ipv4ll_route)
608 return;
609
610 if (link_ipv6ll_enabled(link))
611 if (!link->ipv6ll_address)
612 return;
613
614 if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
615 !link->dhcp4_configured) ||
616 (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
617 !link->dhcp6_configured) ||
618 (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) &&
619 !link->dhcp4_configured && !link->dhcp6_configured))
620 return;
621
622 if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
623 return;
624
625 SET_FOREACH(a, link->addresses, i)
626 if (!address_is_ready(a))
627 return;
628
629 if (link->state != LINK_STATE_CONFIGURED)
630 link_enter_configured(link);
631
632 return;
633 }
634
635 static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
636 _cleanup_link_unref_ Link *link = userdata;
637 int r;
638
639 assert(link->link_messages > 0);
640 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
641 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
642 LINK_STATE_LINGER));
643
644 link->link_messages --;
645
646 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
647 return 1;
648
649 r = sd_netlink_message_get_errno(m);
650 if (r < 0 && r != -EEXIST)
651 log_link_warning_errno(link, r, "Could not set route: %m");
652
653 if (link->link_messages == 0) {
654 log_link_debug(link, "Routes set");
655 link->static_configured = true;
656 link_check_ready(link);
657 }
658
659 return 1;
660 }
661
662 static int link_enter_set_routes(Link *link) {
663 Route *rt;
664 int r;
665
666 assert(link);
667 assert(link->network);
668 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
669
670 link_set_state(link, LINK_STATE_SETTING_ROUTES);
671
672 LIST_FOREACH(routes, rt, link->network->static_routes) {
673 r = route_configure(rt, link, &route_handler);
674 if (r < 0) {
675 log_link_warning_errno(link, r, "Could not set routes: %m");
676 link_enter_failed(link);
677 return r;
678 }
679
680 link->link_messages ++;
681 }
682
683 if (link->link_messages == 0) {
684 link->static_configured = true;
685 link_check_ready(link);
686 } else
687 log_link_debug(link, "Setting routes");
688
689 return 0;
690 }
691
692 int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
693 _cleanup_link_unref_ Link *link = userdata;
694 int r;
695
696 assert(m);
697 assert(link);
698 assert(link->ifname);
699
700 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
701 return 1;
702
703 r = sd_netlink_message_get_errno(m);
704 if (r < 0 && r != -ESRCH)
705 log_link_warning_errno(link, r, "Could not drop route: %m");
706
707 return 1;
708 }
709
710 static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
711 _cleanup_link_unref_ Link *link = userdata;
712 int r;
713
714 assert(rtnl);
715 assert(m);
716 assert(link);
717 assert(link->ifname);
718 assert(link->link_messages > 0);
719 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
720 LINK_STATE_FAILED, LINK_STATE_LINGER));
721
722 link->link_messages --;
723
724 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
725 return 1;
726
727 r = sd_netlink_message_get_errno(m);
728 if (r < 0 && r != -EEXIST)
729 log_link_warning_errno(link, r, "could not set address: %m");
730 else if (r >= 0)
731 manager_rtnl_process_address(rtnl, m, link->manager);
732
733 if (link->link_messages == 0) {
734 log_link_debug(link, "Addresses set");
735 link_enter_set_routes(link);
736 }
737
738 return 1;
739 }
740
741 static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
742 _cleanup_free_ struct in_addr *addresses = NULL;
743 size_t n_addresses = 0, n_allocated = 0;
744 char **a;
745
746 log_debug("Copying DNS server information from %s", link->ifname);
747
748 if (!link->network)
749 return 0;
750
751 STRV_FOREACH(a, link->network->dns) {
752 struct in_addr ia;
753
754 /* Only look for IPv4 addresses */
755 if (inet_pton(AF_INET, *a, &ia) <= 0)
756 continue;
757
758 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
759 return log_oom();
760
761 addresses[n_addresses++] = ia;
762 }
763
764 if (link->network->dhcp_dns &&
765 link->dhcp_lease) {
766 const struct in_addr *da = NULL;
767 int n;
768
769 n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
770 if (n > 0) {
771
772 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
773 return log_oom();
774
775 memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
776 n_addresses += n;
777 }
778 }
779
780 if (n_addresses <= 0)
781 return 0;
782
783 return sd_dhcp_server_set_dns(s, addresses, n_addresses);
784 }
785
786 static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
787 _cleanup_free_ struct in_addr *addresses = NULL;
788 size_t n_addresses = 0, n_allocated = 0;
789 char **a;
790
791 if (!link->network)
792 return 0;
793
794 log_debug("Copying NTP server information from %s", link->ifname);
795
796 STRV_FOREACH(a, link->network->ntp) {
797 struct in_addr ia;
798
799 /* Only look for IPv4 addresses */
800 if (inet_pton(AF_INET, *a, &ia) <= 0)
801 continue;
802
803 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
804 return log_oom();
805
806 addresses[n_addresses++] = ia;
807 }
808
809 if (link->network->dhcp_ntp &&
810 link->dhcp_lease) {
811 const struct in_addr *da = NULL;
812 int n;
813
814 n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
815 if (n > 0) {
816
817 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
818 return log_oom();
819
820 memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
821 n_addresses += n;
822 }
823 }
824
825 if (n_addresses <= 0)
826 return 0;
827
828 return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
829 }
830
831 static int link_enter_set_addresses(Link *link) {
832 Address *ad;
833 int r;
834
835 assert(link);
836 assert(link->network);
837 assert(link->state != _LINK_STATE_INVALID);
838
839 link_set_state(link, LINK_STATE_SETTING_ADDRESSES);
840
841 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
842 r = address_configure(ad, link, &address_handler, false);
843 if (r < 0) {
844 log_link_warning_errno(link, r, "Could not set addresses: %m");
845 link_enter_failed(link);
846 return r;
847 }
848
849 link->link_messages ++;
850 }
851
852 /* now that we can figure out a default address for the dhcp server,
853 start it */
854 if (link_dhcp4_server_enabled(link)) {
855 Address *address;
856 Link *uplink = NULL;
857 bool acquired_uplink = false;
858
859 address = link_find_dhcp_server_address(link);
860 if (!address) {
861 log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance.");
862 link_enter_failed(link);
863 return 0;
864 }
865
866 /* use the server address' subnet as the pool */
867 r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen,
868 link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size);
869 if (r < 0)
870 return r;
871
872 /* TODO:
873 r = sd_dhcp_server_set_router(link->dhcp_server,
874 &main_address->in_addr.in);
875 if (r < 0)
876 return r;
877 */
878
879 if (link->network->dhcp_server_max_lease_time_usec > 0) {
880 r = sd_dhcp_server_set_max_lease_time(
881 link->dhcp_server,
882 DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
883 if (r < 0)
884 return r;
885 }
886
887 if (link->network->dhcp_server_default_lease_time_usec > 0) {
888 r = sd_dhcp_server_set_default_lease_time(
889 link->dhcp_server,
890 DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
891 if (r < 0)
892 return r;
893 }
894
895 if (link->network->dhcp_server_emit_dns) {
896
897 if (link->network->n_dhcp_server_dns > 0)
898 r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
899 else {
900 uplink = manager_find_uplink(link->manager, link);
901 acquired_uplink = true;
902
903 if (!uplink) {
904 log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
905 r = 0;
906 } else
907 r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server);
908 }
909 if (r < 0)
910 log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
911 }
912
913
914 if (link->network->dhcp_server_emit_ntp) {
915
916 if (link->network->n_dhcp_server_ntp > 0)
917 r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
918 else {
919 if (!acquired_uplink)
920 uplink = manager_find_uplink(link->manager, link);
921
922 if (!uplink) {
923 log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
924 r = 0;
925 } else
926 r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server);
927
928 }
929 if (r < 0)
930 log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
931 }
932
933 if (link->network->dhcp_server_emit_timezone) {
934 _cleanup_free_ char *buffer = NULL;
935 const char *tz = NULL;
936
937 if (link->network->dhcp_server_timezone)
938 tz = link->network->dhcp_server_timezone;
939 else {
940 r = get_timezone(&buffer);
941 if (r < 0)
942 log_warning_errno(r, "Failed to determine timezone: %m");
943 else
944 tz = buffer;
945 }
946
947 if (tz) {
948 r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
949 if (r < 0)
950 return r;
951 }
952 }
953
954 r = sd_dhcp_server_start(link->dhcp_server);
955 if (r < 0) {
956 log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
957
958 link_enter_failed(link);
959
960 return 0;
961 }
962
963 log_link_debug(link, "Offering DHCPv4 leases");
964 }
965
966 if (link->link_messages == 0)
967 link_enter_set_routes(link);
968 else
969 log_link_debug(link, "Setting addresses");
970
971 return 0;
972 }
973
974 int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
975 _cleanup_link_unref_ Link *link = userdata;
976 int r;
977
978 assert(m);
979 assert(link);
980 assert(link->ifname);
981
982 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
983 return 1;
984
985 r = sd_netlink_message_get_errno(m);
986 if (r < 0 && r != -EADDRNOTAVAIL)
987 log_link_warning_errno(link, r, "Could not drop address: %m");
988
989 return 1;
990 }
991
992 static int link_set_bridge_fdb(Link *const link) {
993 FdbEntry *fdb_entry;
994 int r = 0;
995
996 LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
997 r = fdb_entry_configure(link, fdb_entry);
998 if(r < 0) {
999 log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
1000 break;
1001 }
1002 }
1003
1004 return r;
1005 }
1006
1007 static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
1008 _cleanup_link_unref_ Link *link = userdata;
1009 int r;
1010
1011 log_link_debug(link, "Set link");
1012
1013 r = sd_netlink_message_get_errno(m);
1014 if (r < 0 && r != -EEXIST) {
1015 log_link_error_errno(link, r, "Could not join netdev: %m");
1016 link_enter_failed(link);
1017 return 1;
1018 }
1019
1020 return 0;
1021 }
1022
1023 static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
1024 _cleanup_link_unref_ Link *link = userdata;
1025 const sd_bus_error *e;
1026
1027 assert(m);
1028 assert(link);
1029
1030 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1031 return 1;
1032
1033 e = sd_bus_message_get_error(m);
1034 if (e)
1035 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
1036
1037 return 1;
1038 }
1039
1040 int link_set_hostname(Link *link, const char *hostname) {
1041 int r;
1042
1043 assert(link);
1044 assert(link->manager);
1045
1046 log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname));
1047
1048 if (!link->manager->bus) {
1049 /* TODO: replace by assert when we can rely on kdbus */
1050 log_link_info(link, "Not connected to system bus, ignoring transient hostname.");
1051 return 0;
1052 }
1053
1054 r = sd_bus_call_method_async(
1055 link->manager->bus,
1056 NULL,
1057 "org.freedesktop.hostname1",
1058 "/org/freedesktop/hostname1",
1059 "org.freedesktop.hostname1",
1060 "SetHostname",
1061 set_hostname_handler,
1062 link,
1063 "sb",
1064 hostname,
1065 false);
1066
1067 if (r < 0)
1068 return log_link_error_errno(link, r, "Could not set transient hostname: %m");
1069
1070 link_ref(link);
1071
1072 return 0;
1073 }
1074
1075 static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
1076 _cleanup_link_unref_ Link *link = userdata;
1077 const sd_bus_error *e;
1078
1079 assert(m);
1080 assert(link);
1081
1082 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1083 return 1;
1084
1085 e = sd_bus_message_get_error(m);
1086 if (e)
1087 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
1088
1089 return 1;
1090 }
1091
1092 int link_set_timezone(Link *link, const char *tz) {
1093 int r;
1094
1095 assert(link);
1096 assert(link->manager);
1097 assert(tz);
1098
1099 log_link_debug(link, "Setting system timezone: '%s'", tz);
1100
1101 if (!link->manager->bus) {
1102 log_link_info(link, "Not connected to system bus, ignoring timezone.");
1103 return 0;
1104 }
1105
1106 r = sd_bus_call_method_async(
1107 link->manager->bus,
1108 NULL,
1109 "org.freedesktop.timedate1",
1110 "/org/freedesktop/timedate1",
1111 "org.freedesktop.timedate1",
1112 "SetTimezone",
1113 set_timezone_handler,
1114 link,
1115 "sb",
1116 tz,
1117 false);
1118 if (r < 0)
1119 return log_link_error_errno(link, r, "Could not set timezone: %m");
1120
1121 link_ref(link);
1122
1123 return 0;
1124 }
1125
1126 static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
1127 _cleanup_link_unref_ Link *link = userdata;
1128 int r;
1129
1130 assert(m);
1131 assert(link);
1132 assert(link->ifname);
1133
1134 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1135 return 1;
1136
1137 r = sd_netlink_message_get_errno(m);
1138 if (r < 0)
1139 log_link_warning_errno(link, r, "Could not set MTU: %m");
1140
1141 return 1;
1142 }
1143
1144 int link_set_mtu(Link *link, uint32_t mtu) {
1145 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
1146 int r;
1147
1148 assert(link);
1149 assert(link->manager);
1150 assert(link->manager->rtnl);
1151
1152 log_link_debug(link, "Setting MTU: %" PRIu32, mtu);
1153
1154 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1155 if (r < 0)
1156 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
1157
1158 r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu);
1159 if (r < 0)
1160 return log_link_error_errno(link, r, "Could not append MTU: %m");
1161
1162 r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
1163 if (r < 0)
1164 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
1165
1166 link_ref(link);
1167
1168 return 0;
1169 }
1170
1171 static int link_set_bridge(Link *link) {
1172 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
1173 int r;
1174
1175 assert(link);
1176 assert(link->network);
1177
1178 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1179 if (r < 0)
1180 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
1181
1182 r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
1183 if (r < 0)
1184 return log_link_error_errno(link, r, "Could not set message family: %m");
1185
1186 r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
1187 if (r < 0)
1188 return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
1189
1190 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
1191 if (r < 0)
1192 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
1193
1194 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
1195 if (r < 0)
1196 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
1197
1198 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
1199 if (r < 0)
1200 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
1201
1202 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
1203 if (r < 0)
1204 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
1205
1206 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
1207 if (r < 0)
1208 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
1209
1210 if(link->network->cost != 0) {
1211 r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
1212 if (r < 0)
1213 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
1214 }
1215
1216 r = sd_netlink_message_close_container(req);
1217 if (r < 0)
1218 return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
1219
1220 r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL);
1221 if (r < 0)
1222 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
1223
1224 link_ref(link);
1225
1226 return r;
1227 }
1228
1229 static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
1230 Link *link = userdata;
1231 int r;
1232
1233 assert(link);
1234 assert(link->network);
1235 assert(link->manager);
1236
1237 switch (event) {
1238 case SD_LLDP_EVENT_UPDATE_INFO:
1239 r = sd_lldp_save(link->lldp, link->lldp_file);
1240 if (r < 0)
1241 log_link_warning_errno(link, r, "Could not save LLDP: %m");
1242
1243 break;
1244 default:
1245 break;
1246 }
1247 }
1248
1249 static int link_acquire_ipv6_conf(Link *link) {
1250 int r;
1251
1252 assert(link);
1253
1254 if (link_dhcp6_enabled(link)) {
1255 assert(link->dhcp6_client);
1256
1257 log_link_debug(link, "Acquiring DHCPv6 lease");
1258
1259 r = sd_dhcp6_client_start(link->dhcp6_client);
1260 if (r < 0)
1261 return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
1262 }
1263
1264 if (link_ipv6_accept_ra_enabled(link)) {
1265 assert(link->ndisc_router_discovery);
1266
1267 log_link_debug(link, "Discovering IPv6 routers");
1268
1269 r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
1270 if (r < 0)
1271 return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
1272 }
1273
1274 return 0;
1275 }
1276
1277 static int link_acquire_conf(Link *link) {
1278 int r;
1279
1280 assert(link);
1281 assert(link->network);
1282 assert(link->manager);
1283 assert(link->manager->event);
1284
1285 if (link_ipv4ll_enabled(link)) {
1286 assert(link->ipv4ll);
1287
1288 log_link_debug(link, "Acquiring IPv4 link-local address");
1289
1290 r = sd_ipv4ll_start(link->ipv4ll);
1291 if (r < 0)
1292 return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
1293 }
1294
1295 if (link_dhcp4_enabled(link)) {
1296 assert(link->dhcp_client);
1297
1298 log_link_debug(link, "Acquiring DHCPv4 lease");
1299
1300 r = sd_dhcp_client_start(link->dhcp_client);
1301 if (r < 0)
1302 return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
1303 }
1304
1305 if (link_lldp_enabled(link)) {
1306 assert(link->lldp);
1307
1308 log_link_debug(link, "Starting LLDP");
1309
1310 r = sd_lldp_start(link->lldp);
1311 if (r < 0)
1312 return log_link_warning_errno(link, r, "Could not start LLDP: %m");
1313 }
1314
1315 return 0;
1316 }
1317
1318 bool link_has_carrier(Link *link) {
1319 /* see Documentation/networking/operstates.txt in the kernel sources */
1320
1321 if (link->kernel_operstate == IF_OPER_UP)
1322 return true;
1323
1324 if (link->kernel_operstate == IF_OPER_UNKNOWN)
1325 /* operstate may not be implemented, so fall back to flags */
1326 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
1327 return true;
1328
1329 return false;
1330 }
1331
1332 static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
1333 _cleanup_link_unref_ Link *link = userdata;
1334 int r;
1335
1336 assert(link);
1337
1338 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1339 return 1;
1340
1341 r = sd_netlink_message_get_errno(m);
1342 if (r < 0)
1343 /* we warn but don't fail the link, as it may be
1344 brought up later */
1345 log_link_warning_errno(link, r, "Could not bring up interface: %m");
1346
1347 return 1;
1348 }
1349
1350 static int link_up(Link *link) {
1351 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
1352 uint8_t ipv6ll_mode;
1353 int r;
1354
1355 assert(link);
1356 assert(link->network);
1357 assert(link->manager);
1358 assert(link->manager->rtnl);
1359
1360 log_link_debug(link, "Bringing link up");
1361
1362 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1363 if (r < 0)
1364 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
1365
1366 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
1367 if (r < 0)
1368 return log_link_error_errno(link, r, "Could not set link flags: %m");
1369
1370 if (link->network->mac) {
1371 r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
1372 if (r < 0)
1373 return log_link_error_errno(link, r, "Could not set MAC address: %m");
1374 }
1375
1376 if (link->network->mtu) {
1377 r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu);
1378 if (r < 0)
1379 return log_link_error_errno(link, r, "Could not set MTU: %m");
1380 }
1381
1382 r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
1383 if (r < 0)
1384 return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
1385
1386 if (socket_ipv6_is_supported()) {
1387 /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
1388 r = sd_netlink_message_open_container(req, AF_INET6);
1389 if (r < 0)
1390 return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
1391
1392 ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE;
1393 r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
1394 if (r < 0)
1395 return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
1396
1397 if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
1398 r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
1399 if (r < 0)
1400 return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
1401 }
1402
1403 r = sd_netlink_message_close_container(req);
1404 if (r < 0)
1405 return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
1406 }
1407
1408 r = sd_netlink_message_close_container(req);
1409 if (r < 0)
1410 return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
1411
1412 r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
1413 if (r < 0)
1414 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
1415
1416 link_ref(link);
1417
1418 return 0;
1419 }
1420
1421 static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
1422 _cleanup_link_unref_ Link *link = userdata;
1423 int r;
1424
1425 assert(link);
1426
1427 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1428 return 1;
1429
1430 r = sd_netlink_message_get_errno(m);
1431 if (r < 0)
1432 log_link_warning_errno(link, r, "Could not bring down interface: %m");
1433
1434 return 1;
1435 }
1436
1437 static int link_down(Link *link) {
1438 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
1439 int r;
1440
1441 assert(link);
1442 assert(link->manager);
1443 assert(link->manager->rtnl);
1444
1445 log_link_debug(link, "Bringing link down");
1446
1447 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1448 RTM_SETLINK, link->ifindex);
1449 if (r < 0)
1450 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
1451
1452 r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
1453 if (r < 0)
1454 return log_link_error_errno(link, r, "Could not set link flags: %m");
1455
1456 r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL);
1457 if (r < 0)
1458 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
1459
1460 link_ref(link);
1461
1462 return 0;
1463 }
1464
1465 static int link_handle_bound_to_list(Link *link) {
1466 Link *l;
1467 Iterator i;
1468 int r;
1469 bool required_up = false;
1470 bool link_is_up = false;
1471
1472 assert(link);
1473
1474 if (hashmap_isempty(link->bound_to_links))
1475 return 0;
1476
1477 if (link->flags & IFF_UP)
1478 link_is_up = true;
1479
1480 HASHMAP_FOREACH (l, link->bound_to_links, i)
1481 if (link_has_carrier(l)) {
1482 required_up = true;
1483 break;
1484 }
1485
1486 if (!required_up && link_is_up) {
1487 r = link_down(link);
1488 if (r < 0)
1489 return r;
1490 } else if (required_up && !link_is_up) {
1491 r = link_up(link);
1492 if (r < 0)
1493 return r;
1494 }
1495
1496 return 0;
1497 }
1498
1499 static int link_handle_bound_by_list(Link *link) {
1500 Iterator i;
1501 Link *l;
1502 int r;
1503
1504 assert(link);
1505
1506 if (hashmap_isempty(link->bound_by_links))
1507 return 0;
1508
1509 HASHMAP_FOREACH (l, link->bound_by_links, i) {
1510 r = link_handle_bound_to_list(l);
1511 if (r < 0)
1512 return r;
1513 }
1514
1515 return 0;
1516 }
1517
1518 static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) {
1519 int r;
1520
1521 assert(link);
1522 assert(carrier);
1523
1524 if (link == carrier)
1525 return 0;
1526
1527 if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex)))
1528 return 0;
1529
1530 r = hashmap_ensure_allocated(h, NULL);
1531 if (r < 0)
1532 return r;
1533
1534 r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier);
1535 if (r < 0)
1536 return r;
1537
1538 return 0;
1539 }
1540
1541 static int link_new_bound_by_list(Link *link) {
1542 Manager *m;
1543 Link *carrier;
1544 Iterator i;
1545 int r;
1546 bool list_updated = false;
1547
1548 assert(link);
1549 assert(link->manager);
1550
1551 m = link->manager;
1552
1553 HASHMAP_FOREACH (carrier, m->links, i) {
1554 if (!carrier->network)
1555 continue;
1556
1557 if (strv_isempty(carrier->network->bind_carrier))
1558 continue;
1559
1560 if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) {
1561 r = link_put_carrier(link, carrier, &link->bound_by_links);
1562 if (r < 0)
1563 return r;
1564
1565 list_updated = true;
1566 }
1567 }
1568
1569 if (list_updated)
1570 link_dirty(link);
1571
1572 HASHMAP_FOREACH (carrier, link->bound_by_links, i) {
1573 r = link_put_carrier(carrier, link, &carrier->bound_to_links);
1574 if (r < 0)
1575 return r;
1576
1577 link_dirty(carrier);
1578 }
1579
1580 return 0;
1581 }
1582
1583 static int link_new_bound_to_list(Link *link) {
1584 Manager *m;
1585 Link *carrier;
1586 Iterator i;
1587 int r;
1588 bool list_updated = false;
1589
1590 assert(link);
1591 assert(link->manager);
1592
1593 if (!link->network)
1594 return 0;
1595
1596 if (strv_isempty(link->network->bind_carrier))
1597 return 0;
1598
1599 m = link->manager;
1600
1601 HASHMAP_FOREACH (carrier, m->links, i) {
1602 if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) {
1603 r = link_put_carrier(link, carrier, &link->bound_to_links);
1604 if (r < 0)
1605 return r;
1606
1607 list_updated = true;
1608 }
1609 }
1610
1611 if (list_updated)
1612 link_dirty(link);
1613
1614 HASHMAP_FOREACH (carrier, link->bound_to_links, i) {
1615 r = link_put_carrier(carrier, link, &carrier->bound_by_links);
1616 if (r < 0)
1617 return r;
1618
1619 link_dirty(carrier);
1620 }
1621
1622 return 0;
1623 }
1624
1625 static int link_new_carrier_maps(Link *link) {
1626 int r;
1627
1628 r = link_new_bound_by_list(link);
1629 if (r < 0)
1630 return r;
1631
1632 r = link_handle_bound_by_list(link);
1633 if (r < 0)
1634 return r;
1635
1636 r = link_new_bound_to_list(link);
1637 if (r < 0)
1638 return r;
1639
1640 r = link_handle_bound_to_list(link);
1641 if (r < 0)
1642 return r;
1643
1644 return 0;
1645 }
1646
1647 static void link_free_bound_to_list(Link *link) {
1648 Link *bound_to;
1649 Iterator i;
1650
1651 HASHMAP_FOREACH (bound_to, link->bound_to_links, i) {
1652 hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex));
1653
1654 if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex)))
1655 link_dirty(bound_to);
1656 }
1657
1658 return;
1659 }
1660
1661 static void link_free_bound_by_list(Link *link) {
1662 Link *bound_by;
1663 Iterator i;
1664
1665 HASHMAP_FOREACH (bound_by, link->bound_by_links, i) {
1666 hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex));
1667
1668 if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) {
1669 link_dirty(bound_by);
1670 link_handle_bound_to_list(bound_by);
1671 }
1672 }
1673
1674 return;
1675 }
1676
1677 static void link_free_carrier_maps(Link *link) {
1678 bool list_updated = false;
1679
1680 assert(link);
1681
1682 if (!hashmap_isempty(link->bound_to_links)) {
1683 link_free_bound_to_list(link);
1684 list_updated = true;
1685 }
1686
1687 if (!hashmap_isempty(link->bound_by_links)) {
1688 link_free_bound_by_list(link);
1689 list_updated = true;
1690 }
1691
1692 if (list_updated)
1693 link_dirty(link);
1694
1695 return;
1696 }
1697
1698 void link_drop(Link *link) {
1699 if (!link || link->state == LINK_STATE_LINGER)
1700 return;
1701
1702 link_set_state(link, LINK_STATE_LINGER);
1703
1704 link_free_carrier_maps(link);
1705
1706 log_link_debug(link, "Link removed");
1707
1708 (void)unlink(link->state_file);
1709 link_unref(link);
1710
1711 return;
1712 }
1713
1714 static int link_joined(Link *link) {
1715 int r;
1716
1717 assert(link);
1718 assert(link->network);
1719
1720 if (!hashmap_isempty(link->bound_to_links)) {
1721 r = link_handle_bound_to_list(link);
1722 if (r < 0)
1723 return r;
1724 } else if (!(link->flags & IFF_UP)) {
1725 r = link_up(link);
1726 if (r < 0) {
1727 link_enter_failed(link);
1728 return r;
1729 }
1730 }
1731
1732 if(link->network->bridge) {
1733 r = link_set_bridge(link);
1734 if (r < 0)
1735 log_link_error_errno(link, r, "Could not set bridge message: %m");
1736 }
1737
1738 return link_enter_set_addresses(link);
1739 }
1740
1741 static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
1742 _cleanup_link_unref_ Link *link = userdata;
1743 int r;
1744
1745 assert(link);
1746 assert(link->network);
1747
1748 link->enslaving --;
1749
1750 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1751 return 1;
1752
1753 r = sd_netlink_message_get_errno(m);
1754 if (r < 0 && r != -EEXIST) {
1755 log_link_error_errno(link, r, "Could not join netdev: %m");
1756 link_enter_failed(link);
1757 return 1;
1758 } else
1759 log_link_debug(link, "Joined netdev");
1760
1761 if (link->enslaving <= 0)
1762 link_joined(link);
1763
1764 return 1;
1765 }
1766
1767 static int link_enter_join_netdev(Link *link) {
1768 NetDev *netdev;
1769 Iterator i;
1770 int r;
1771
1772 assert(link);
1773 assert(link->network);
1774 assert(link->state == LINK_STATE_PENDING);
1775
1776 link_set_state(link, LINK_STATE_ENSLAVING);
1777
1778 link_dirty(link);
1779
1780 if (!link->network->bridge &&
1781 !link->network->bond &&
1782 hashmap_isempty(link->network->stacked_netdevs))
1783 return link_joined(link);
1784
1785 if (link->network->bond) {
1786 log_struct(LOG_DEBUG,
1787 LOG_LINK_INTERFACE(link),
1788 LOG_NETDEV_INTERFACE(link->network->bond),
1789 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname),
1790 NULL);
1791
1792 r = netdev_join(link->network->bond, link, netdev_join_handler);
1793 if (r < 0) {
1794 log_struct_errno(LOG_WARNING, r,
1795 LOG_LINK_INTERFACE(link),
1796 LOG_NETDEV_INTERFACE(link->network->bond),
1797 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname),
1798 NULL);
1799
1800 link_enter_failed(link);
1801 return r;
1802 }
1803
1804 link->enslaving ++;
1805 }
1806
1807 if (link->network->bridge) {
1808 log_struct(LOG_DEBUG,
1809 LOG_LINK_INTERFACE(link),
1810 LOG_NETDEV_INTERFACE(link->network->bridge),
1811 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname),
1812 NULL);
1813
1814 r = netdev_join(link->network->bridge, link, netdev_join_handler);
1815 if (r < 0) {
1816 log_struct_errno(LOG_WARNING, r,
1817 LOG_LINK_INTERFACE(link),
1818 LOG_NETDEV_INTERFACE(link->network->bridge),
1819 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname),
1820 NULL),
1821 link_enter_failed(link);
1822 return r;
1823 }
1824
1825 link->enslaving ++;
1826 }
1827
1828 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
1829
1830 log_struct(LOG_DEBUG,
1831 LOG_LINK_INTERFACE(link),
1832 LOG_NETDEV_INTERFACE(netdev),
1833 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname),
1834 NULL);
1835
1836 r = netdev_join(netdev, link, netdev_join_handler);
1837 if (r < 0) {
1838 log_struct_errno(LOG_WARNING, r,
1839 LOG_LINK_INTERFACE(link),
1840 LOG_NETDEV_INTERFACE(netdev),
1841 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname),
1842 NULL);
1843 link_enter_failed(link);
1844 return r;
1845 }
1846
1847 link->enslaving ++;
1848 }
1849
1850 return 0;
1851 }
1852
1853 static int link_set_ipv4_forward(Link *link) {
1854 const char *p = NULL, *v;
1855 int r;
1856
1857 if (link->flags & IFF_LOOPBACK)
1858 return 0;
1859
1860 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1861 return 0;
1862
1863 p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
1864 v = one_zero(link_ipv4_forward_enabled(link));
1865
1866 r = write_string_file(p, v, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1867 if (r < 0)
1868 log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
1869
1870 return 0;
1871 }
1872
1873 static int link_set_ipv6_forward(Link *link) {
1874 const char *p = NULL, *v = NULL;
1875 int r;
1876
1877 /* Make this a NOP if IPv6 is not available */
1878 if (!socket_ipv6_is_supported())
1879 return 0;
1880
1881 if (link->flags & IFF_LOOPBACK)
1882 return 0;
1883
1884 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1885 return 0;
1886
1887 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
1888 v = one_zero(link_ipv6_forward_enabled(link));
1889
1890 r = write_string_file(p, v, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1891 if (r < 0)
1892 log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
1893
1894 return 0;
1895 }
1896
1897 static int link_set_ipv6_privacy_extensions(Link *link) {
1898 char buf[DECIMAL_STR_MAX(unsigned) + 1];
1899 IPv6PrivacyExtensions s;
1900 const char *p = NULL;
1901 int r;
1902
1903 s = link_ipv6_privacy_extensions(link);
1904 if (s < 0)
1905 return 0;
1906
1907 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
1908 xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions);
1909
1910 r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1911 if (r < 0)
1912 log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
1913
1914 return 0;
1915 }
1916
1917 static int link_set_ipv6_accept_ra(Link *link) {
1918 const char *p = NULL;
1919 int r;
1920
1921 /* Make this a NOP if IPv6 is not available */
1922 if (!socket_ipv6_is_supported())
1923 return 0;
1924
1925 if (link->flags & IFF_LOOPBACK)
1926 return 0;
1927
1928 if (!link->network)
1929 return 0;
1930
1931 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
1932
1933 /* We handle router advertisments ourselves, tell the kernel to GTFO */
1934 r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1935 if (r < 0)
1936 log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
1937
1938 return 0;
1939 }
1940
1941 static int link_set_ipv6_dad_transmits(Link *link) {
1942 char buf[DECIMAL_STR_MAX(int) + 1];
1943 const char *p = NULL;
1944 int r;
1945
1946 /* Make this a NOP if IPv6 is not available */
1947 if (!socket_ipv6_is_supported())
1948 return 0;
1949
1950 if (link->flags & IFF_LOOPBACK)
1951 return 0;
1952
1953 if (!link->network)
1954 return 0;
1955
1956 if (link->network->ipv6_dad_transmits < 0)
1957 return 0;
1958
1959 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits");
1960 xsprintf(buf, "%i", link->network->ipv6_dad_transmits);
1961
1962 r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1963 if (r < 0)
1964 log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m");
1965
1966 return 0;
1967 }
1968
1969 static int link_set_ipv6_hop_limit(Link *link) {
1970 char buf[DECIMAL_STR_MAX(int) + 1];
1971 const char *p = NULL;
1972 int r;
1973
1974 /* Make this a NOP if IPv6 is not available */
1975 if (!socket_ipv6_is_supported())
1976 return 0;
1977
1978 if (link->flags & IFF_LOOPBACK)
1979 return 0;
1980
1981 if (!link->network)
1982 return 0;
1983
1984 if (link->network->ipv6_hop_limit < 0)
1985 return 0;
1986
1987 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit");
1988 xsprintf(buf, "%i", link->network->ipv6_hop_limit);
1989
1990 r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1991 if (r < 0)
1992 log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m");
1993
1994 return 0;
1995 }
1996
1997 static int link_drop_foreign_config(Link *link) {
1998 Address *address;
1999 Route *route;
2000 Iterator i;
2001 int r;
2002
2003 SET_FOREACH(address, link->addresses_foreign, i) {
2004 /* we consider IPv6LL addresses to be managed by the kernel */
2005 if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1)
2006 continue;
2007
2008 r = address_remove(address, link, link_address_remove_handler);
2009 if (r < 0)
2010 return r;
2011 }
2012
2013 SET_FOREACH(route, link->routes_foreign, i) {
2014 /* do not touch routes managed by the kernel */
2015 if (route->protocol == RTPROT_KERNEL)
2016 continue;
2017
2018 r = route_remove(route, link, link_address_remove_handler);
2019 if (r < 0)
2020 return r;
2021 }
2022
2023 return 0;
2024 }
2025
2026 static int link_configure(Link *link) {
2027 int r;
2028
2029 assert(link);
2030 assert(link->network);
2031 assert(link->state == LINK_STATE_PENDING);
2032
2033 r = link_drop_foreign_config(link);
2034 if (r < 0)
2035 return r;
2036
2037 r = link_set_bridge_fdb(link);
2038 if (r < 0)
2039 return r;
2040
2041 r = link_set_ipv4_forward(link);
2042 if (r < 0)
2043 return r;
2044
2045 r = link_set_ipv6_forward(link);
2046 if (r < 0)
2047 return r;
2048
2049 r = link_set_ipv6_privacy_extensions(link);
2050 if (r < 0)
2051 return r;
2052
2053 r = link_set_ipv6_accept_ra(link);
2054 if (r < 0)
2055 return r;
2056
2057 r = link_set_ipv6_dad_transmits(link);
2058 if (r < 0)
2059 return r;
2060
2061 r = link_set_ipv6_hop_limit(link);
2062 if (r < 0)
2063 return r;
2064
2065 if (link_ipv4ll_enabled(link)) {
2066 r = ipv4ll_configure(link);
2067 if (r < 0)
2068 return r;
2069 }
2070
2071 if (link_dhcp4_enabled(link)) {
2072 r = dhcp4_configure(link);
2073 if (r < 0)
2074 return r;
2075 }
2076
2077 if (link_dhcp4_server_enabled(link)) {
2078 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
2079 if (r < 0)
2080 return r;
2081
2082 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
2083 if (r < 0)
2084 return r;
2085 }
2086
2087 if (link_dhcp6_enabled(link)) {
2088 r = dhcp6_configure(link);
2089 if (r < 0)
2090 return r;
2091 }
2092
2093 if (link_ipv6_accept_ra_enabled(link)) {
2094 r = ndisc_configure(link);
2095 if (r < 0)
2096 return r;
2097 }
2098
2099 if (link_lldp_enabled(link)) {
2100 r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
2101 if (r < 0)
2102 return r;
2103
2104 r = sd_lldp_attach_event(link->lldp, NULL, 0);
2105 if (r < 0)
2106 return r;
2107
2108 r = sd_lldp_set_callback(link->lldp,
2109 lldp_handler, link);
2110 if (r < 0)
2111 return r;
2112 }
2113
2114 if (link_has_carrier(link)) {
2115 r = link_acquire_conf(link);
2116 if (r < 0)
2117 return r;
2118
2119 if (link->ipv6ll_address) {
2120 r = link_acquire_ipv6_conf(link);
2121 if (r < 0)
2122 return r;
2123 }
2124 }
2125
2126 return link_enter_join_netdev(link);
2127 }
2128
2129 static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
2130 void *userdata) {
2131 _cleanup_link_unref_ Link *link = userdata;
2132 Network *network;
2133 int r;
2134
2135 assert(link);
2136 assert(link->ifname);
2137 assert(link->manager);
2138
2139 if (link->state != LINK_STATE_PENDING)
2140 return 1;
2141
2142 log_link_debug(link, "Link state is up-to-date");
2143
2144 r = link_new_bound_by_list(link);
2145 if (r < 0)
2146 return r;
2147
2148 r = link_handle_bound_by_list(link);
2149 if (r < 0)
2150 return r;
2151
2152 if (!link->network) {
2153 r = network_get(link->manager, link->udev_device, link->ifname,
2154 &link->mac, &network);
2155 if (r == -ENOENT) {
2156 link_enter_unmanaged(link);
2157 return 1;
2158 } else if (r < 0)
2159 return r;
2160
2161 if (link->flags & IFF_LOOPBACK) {
2162 if (network->link_local != ADDRESS_FAMILY_NO)
2163 log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
2164
2165 if (network->dhcp != ADDRESS_FAMILY_NO)
2166 log_link_debug(link, "Ignoring DHCP clients for loopback link");
2167
2168 if (network->dhcp_server)
2169 log_link_debug(link, "Ignoring DHCP server for loopback link");
2170 }
2171
2172 r = network_apply(link->manager, network, link);
2173 if (r < 0)
2174 return r;
2175 }
2176
2177 r = link_new_bound_to_list(link);
2178 if (r < 0)
2179 return r;
2180
2181 r = link_configure(link);
2182 if (r < 0)
2183 return r;
2184
2185 return 1;
2186 }
2187
2188 int link_initialized(Link *link, struct udev_device *device) {
2189 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
2190 int r;
2191
2192 assert(link);
2193 assert(link->manager);
2194 assert(link->manager->rtnl);
2195 assert(device);
2196
2197 if (link->state != LINK_STATE_PENDING)
2198 return 0;
2199
2200 if (link->udev_device)
2201 return 0;
2202
2203 log_link_debug(link, "udev initialized link");
2204
2205 link->udev_device = udev_device_ref(device);
2206
2207 /* udev has initialized the link, but we don't know if we have yet
2208 * processed the NEWLINK messages with the latest state. Do a GETLINK,
2209 * when it returns we know that the pending NEWLINKs have already been
2210 * processed and that we are up-to-date */
2211
2212 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
2213 link->ifindex);
2214 if (r < 0)
2215 return r;
2216
2217 r = sd_netlink_call_async(link->manager->rtnl, req,
2218 link_initialized_and_synced, link, 0, NULL);
2219 if (r < 0)
2220 return r;
2221
2222 link_ref(link);
2223
2224 return 0;
2225 }
2226
2227 static int link_load(Link *link) {
2228 _cleanup_free_ char *network_file = NULL,
2229 *addresses = NULL,
2230 *routes = NULL,
2231 *dhcp4_address = NULL,
2232 *ipv4ll_address = NULL;
2233 union in_addr_union address;
2234 union in_addr_union route_dst;
2235 const char *p;
2236 int r;
2237
2238 assert(link);
2239
2240 r = parse_env_file(link->state_file, NEWLINE,
2241 "NETWORK_FILE", &network_file,
2242 "ADDRESSES", &addresses,
2243 "ROUTES", &routes,
2244 "DHCP4_ADDRESS", &dhcp4_address,
2245 "IPV4LL_ADDRESS", &ipv4ll_address,
2246 NULL);
2247 if (r < 0 && r != -ENOENT)
2248 return log_link_error_errno(link, r, "Failed to read %s: %m", link->state_file);
2249
2250 if (network_file) {
2251 Network *network;
2252 char *suffix;
2253
2254 /* drop suffix */
2255 suffix = strrchr(network_file, '.');
2256 if (!suffix) {
2257 log_link_debug(link, "Failed to get network name from %s", network_file);
2258 goto network_file_fail;
2259 }
2260 *suffix = '\0';
2261
2262 r = network_get_by_name(link->manager, basename(network_file), &network);
2263 if (r < 0) {
2264 log_link_debug_errno(link, r, "Failed to get network %s: %m", basename(network_file));
2265 goto network_file_fail;
2266 }
2267
2268 r = network_apply(link->manager, network, link);
2269 if (r < 0)
2270 return log_link_error_errno(link, r, "Failed to apply network %s: %m", basename(network_file));
2271 }
2272
2273 network_file_fail:
2274
2275 if (addresses) {
2276 p = addresses;
2277
2278 for (;;) {
2279 _cleanup_free_ char *address_str = NULL;
2280 char *prefixlen_str;
2281 int family;
2282 unsigned char prefixlen;
2283
2284 r = extract_first_word(&p, &address_str, NULL, 0);
2285 if (r < 0) {
2286 log_link_debug_errno(link, r, "Failed to extract next address string: %m");
2287 continue;
2288 } if (r == 0)
2289 break;
2290
2291 prefixlen_str = strchr(address_str, '/');
2292 if (!prefixlen_str) {
2293 log_link_debug(link, "Failed to parse address and prefix length %s", address_str);
2294 continue;
2295 }
2296
2297 *prefixlen_str ++ = '\0';
2298
2299 r = sscanf(prefixlen_str, "%hhu", &prefixlen);
2300 if (r != 1) {
2301 log_link_error(link, "Failed to parse prefixlen %s", prefixlen_str);
2302 continue;
2303 }
2304
2305 r = in_addr_from_string_auto(address_str, &family, &address);
2306 if (r < 0) {
2307 log_link_debug_errno(link, r, "Failed to parse address %s: %m", address_str);
2308 continue;
2309 }
2310
2311 r = address_add(link, family, &address, prefixlen, NULL);
2312 if (r < 0)
2313 return log_link_error_errno(link, r, "Failed to add address: %m");
2314 }
2315 }
2316
2317 if (routes) {
2318 for (;;) {
2319 Route *route;
2320 _cleanup_free_ char *route_str = NULL;
2321 _cleanup_event_source_unref_ sd_event_source *expire = NULL;
2322 usec_t lifetime;
2323 char *prefixlen_str;
2324 int family;
2325 unsigned char prefixlen, tos, table;
2326 uint32_t priority;
2327
2328 r = extract_first_word(&p, &route_str, NULL, 0);
2329 if (r < 0) {
2330 log_link_debug_errno(link, r, "Failed to extract next route string: %m");
2331 continue;
2332 } if (r == 0)
2333 break;
2334
2335 prefixlen_str = strchr(route_str, '/');
2336 if (!prefixlen_str) {
2337 log_link_debug(link, "Failed to parse route %s", route_str);
2338 continue;
2339 }
2340
2341 *prefixlen_str ++ = '\0';
2342
2343 r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu/"USEC_FMT, &prefixlen, &tos, &priority, &table, &lifetime);
2344 if (r != 5) {
2345 log_link_debug(link,
2346 "Failed to parse destination prefix length, tos, priority, table or expiration %s",
2347 prefixlen_str);
2348 continue;
2349 }
2350
2351 r = in_addr_from_string_auto(route_str, &family, &route_dst);
2352 if (r < 0) {
2353 log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str);
2354 continue;
2355 }
2356
2357 r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, &route);
2358 if (r < 0)
2359 return log_link_error_errno(link, r, "Failed to add route: %m");
2360
2361 if (lifetime != USEC_INFINITY) {
2362 r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), lifetime,
2363 0, route_expire_handler, route);
2364 if (r < 0)
2365 log_link_warning_errno(link, r, "Could not arm route expiration handler: %m");
2366 }
2367
2368 route->lifetime = lifetime;
2369 sd_event_source_unref(route->expire);
2370 route->expire = expire;
2371 expire = NULL;
2372 }
2373 }
2374
2375 if (dhcp4_address) {
2376 r = in_addr_from_string(AF_INET, dhcp4_address, &address);
2377 if (r < 0) {
2378 log_link_debug_errno(link, r, "Falied to parse DHCPv4 address %s: %m", dhcp4_address);
2379 goto dhcp4_address_fail;
2380 }
2381
2382 r = sd_dhcp_client_new(&link->dhcp_client);
2383 if (r < 0)
2384 return log_link_error_errno(link, r, "Falied to create DHCPv4 client: %m");
2385
2386 r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in);
2387 if (r < 0)
2388 return log_link_error_errno(link, r, "Falied to set inital DHCPv4 address %s: %m", dhcp4_address);
2389 }
2390
2391 dhcp4_address_fail:
2392
2393 if (ipv4ll_address) {
2394 r = in_addr_from_string(AF_INET, ipv4ll_address, &address);
2395 if (r < 0) {
2396 log_link_debug_errno(link, r, "Falied to parse IPv4LL address %s: %m", ipv4ll_address);
2397 goto ipv4ll_address_fail;
2398 }
2399
2400 r = sd_ipv4ll_new(&link->ipv4ll);
2401 if (r < 0)
2402 return log_link_error_errno(link, r, "Falied to create IPv4LL client: %m");
2403
2404 r = sd_ipv4ll_set_address(link->ipv4ll, &address.in);
2405 if (r < 0)
2406 return log_link_error_errno(link, r, "Falied to set inital IPv4LL address %s: %m", ipv4ll_address);
2407 }
2408
2409 ipv4ll_address_fail:
2410
2411 return 0;
2412 }
2413
2414 int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
2415 Link *link;
2416 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
2417 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
2418 int r;
2419
2420 assert(m);
2421 assert(m->rtnl);
2422 assert(message);
2423 assert(ret);
2424
2425 r = link_new(m, message, ret);
2426 if (r < 0)
2427 return r;
2428
2429 link = *ret;
2430
2431 log_link_debug(link, "Link %d added", link->ifindex);
2432
2433 r = link_load(link);
2434 if (r < 0)
2435 return r;
2436
2437 if (detect_container() <= 0) {
2438 /* not in a container, udev will be around */
2439 sprintf(ifindex_str, "n%d", link->ifindex);
2440 device = udev_device_new_from_device_id(m->udev, ifindex_str);
2441 if (!device) {
2442 r = log_link_warning_errno(link, errno, "Could not find udev device: %m");
2443 goto failed;
2444 }
2445
2446 if (udev_device_get_is_initialized(device) <= 0) {
2447 /* not yet ready */
2448 log_link_debug(link, "link pending udev initialization...");
2449 return 0;
2450 }
2451
2452 r = link_initialized(link, device);
2453 if (r < 0)
2454 goto failed;
2455 } else {
2456 /* we are calling a callback directly, so must take a ref */
2457 link_ref(link);
2458
2459 r = link_initialized_and_synced(m->rtnl, NULL, link);
2460 if (r < 0)
2461 goto failed;
2462 }
2463
2464 return 0;
2465 failed:
2466 link_enter_failed(link);
2467 return r;
2468 }
2469
2470 int link_ipv6ll_gained(Link *link) {
2471 int r;
2472
2473 assert(link);
2474
2475 log_link_info(link, "Gained IPv6LL");
2476
2477 link->ipv6ll_address = true;
2478 link_check_ready(link);
2479
2480 if (link->network) {
2481 r = link_acquire_ipv6_conf(link);
2482 if (r < 0) {
2483 link_enter_failed(link);
2484 return r;
2485 }
2486 }
2487
2488 return 0;
2489 }
2490
2491 static int link_carrier_gained(Link *link) {
2492 int r;
2493
2494 assert(link);
2495
2496 if (link->network) {
2497 r = link_acquire_conf(link);
2498 if (r < 0) {
2499 link_enter_failed(link);
2500 return r;
2501 }
2502 }
2503
2504 r = link_handle_bound_by_list(link);
2505 if (r < 0)
2506 return r;
2507
2508 return 0;
2509 }
2510
2511 static int link_carrier_lost(Link *link) {
2512 int r;
2513
2514 assert(link);
2515
2516 r = link_stop_clients(link);
2517 if (r < 0) {
2518 link_enter_failed(link);
2519 return r;
2520 }
2521
2522 r = link_handle_bound_by_list(link);
2523 if (r < 0)
2524 return r;
2525
2526 return 0;
2527 }
2528
2529 int link_carrier_reset(Link *link) {
2530 int r;
2531
2532 assert(link);
2533
2534 if (link_has_carrier(link)) {
2535 r = link_carrier_lost(link);
2536 if (r < 0)
2537 return r;
2538
2539 r = link_carrier_gained(link);
2540 if (r < 0)
2541 return r;
2542
2543 log_link_info(link, "Reset carrier");
2544 }
2545
2546 return 0;
2547 }
2548
2549
2550 int link_update(Link *link, sd_netlink_message *m) {
2551 struct ether_addr mac;
2552 const char *ifname;
2553 uint32_t mtu;
2554 bool had_carrier, carrier_gained, carrier_lost;
2555 int r;
2556
2557 assert(link);
2558 assert(link->ifname);
2559 assert(m);
2560
2561 if (link->state == LINK_STATE_LINGER) {
2562 link_ref(link);
2563 log_link_info(link, "Link readded");
2564 link_set_state(link, LINK_STATE_ENSLAVING);
2565
2566 r = link_new_carrier_maps(link);
2567 if (r < 0)
2568 return r;
2569 }
2570
2571 r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
2572 if (r >= 0 && !streq(ifname, link->ifname)) {
2573 log_link_info(link, "Renamed to %s", ifname);
2574
2575 link_free_carrier_maps(link);
2576
2577 r = free_and_strdup(&link->ifname, ifname);
2578 if (r < 0)
2579 return r;
2580
2581 r = link_new_carrier_maps(link);
2582 if (r < 0)
2583 return r;
2584 }
2585
2586 r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
2587 if (r >= 0 && mtu > 0) {
2588 link->mtu = mtu;
2589 if (!link->original_mtu) {
2590 link->original_mtu = mtu;
2591 log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
2592 }
2593
2594 if (link->dhcp_client) {
2595 r = sd_dhcp_client_set_mtu(link->dhcp_client,
2596 link->mtu);
2597 if (r < 0) {
2598 log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m");
2599 return r;
2600 }
2601 }
2602 }
2603
2604 /* The kernel may broadcast NEWLINK messages without the MAC address
2605 set, simply ignore them. */
2606 r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
2607 if (r >= 0) {
2608 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
2609 ETH_ALEN)) {
2610
2611 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
2612 ETH_ALEN);
2613
2614 log_link_debug(link, "MAC address: "
2615 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2616 mac.ether_addr_octet[0],
2617 mac.ether_addr_octet[1],
2618 mac.ether_addr_octet[2],
2619 mac.ether_addr_octet[3],
2620 mac.ether_addr_octet[4],
2621 mac.ether_addr_octet[5]);
2622
2623 if (link->ipv4ll) {
2624 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
2625 if (r < 0)
2626 return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m");
2627 }
2628
2629 if (link->dhcp_client) {
2630 r = sd_dhcp_client_set_mac(link->dhcp_client,
2631 (const uint8_t *) &link->mac,
2632 sizeof (link->mac),
2633 ARPHRD_ETHER);
2634 if (r < 0)
2635 return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
2636 }
2637
2638 if (link->dhcp6_client) {
2639 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
2640 (const uint8_t *) &link->mac,
2641 sizeof (link->mac),
2642 ARPHRD_ETHER);
2643 if (r < 0)
2644 return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
2645 }
2646 }
2647 }
2648
2649 had_carrier = link_has_carrier(link);
2650
2651 r = link_update_flags(link, m);
2652 if (r < 0)
2653 return r;
2654
2655 carrier_gained = !had_carrier && link_has_carrier(link);
2656 carrier_lost = had_carrier && !link_has_carrier(link);
2657
2658 if (carrier_gained) {
2659 log_link_info(link, "Gained carrier");
2660
2661 r = link_carrier_gained(link);
2662 if (r < 0)
2663 return r;
2664 } else if (carrier_lost) {
2665 log_link_info(link, "Lost carrier");
2666
2667 r = link_carrier_lost(link);
2668 if (r < 0)
2669 return r;
2670
2671 }
2672
2673 return 0;
2674 }
2675
2676 int link_save(Link *link) {
2677 _cleanup_free_ char *temp_path = NULL;
2678 _cleanup_fclose_ FILE *f = NULL;
2679 const char *admin_state, *oper_state;
2680 Address *a;
2681 Route *route;
2682 Iterator i;
2683 int r;
2684
2685 assert(link);
2686 assert(link->state_file);
2687 assert(link->lease_file);
2688 assert(link->manager);
2689
2690 if (link->state == LINK_STATE_LINGER) {
2691 unlink(link->state_file);
2692 return 0;
2693 }
2694
2695 admin_state = link_state_to_string(link->state);
2696 assert(admin_state);
2697
2698 oper_state = link_operstate_to_string(link->operstate);
2699 assert(oper_state);
2700
2701 r = fopen_temporary(link->state_file, &f, &temp_path);
2702 if (r < 0)
2703 goto fail;
2704
2705 fchmod(fileno(f), 0644);
2706
2707 fprintf(f,
2708 "# This is private data. Do not parse.\n"
2709 "ADMIN_STATE=%s\n"
2710 "OPER_STATE=%s\n",
2711 admin_state, oper_state);
2712
2713 if (link->network) {
2714 char **address, **domain;
2715 bool space;
2716 sd_dhcp6_lease *dhcp6_lease = NULL;
2717
2718 if (link->dhcp6_client) {
2719 r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
2720 if (r < 0 && r != -ENOMSG)
2721 log_link_debug(link, "No DHCPv6 lease");
2722 }
2723
2724 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
2725
2726 fputs("DNS=", f);
2727 space = false;
2728 STRV_FOREACH(address, link->network->dns) {
2729 if (space)
2730 fputc(' ', f);
2731 fputs(*address, f);
2732 space = true;
2733 }
2734
2735 if (link->network->dhcp_dns &&
2736 link->dhcp_lease) {
2737 const struct in_addr *addresses;
2738
2739 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
2740 if (r > 0) {
2741 if (space)
2742 fputc(' ', f);
2743 serialize_in_addrs(f, addresses, r);
2744 space = true;
2745 }
2746 }
2747
2748 if (link->network->dhcp_dns && dhcp6_lease) {
2749 struct in6_addr *in6_addrs;
2750
2751 r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
2752 if (r > 0) {
2753 if (space)
2754 fputc(' ', f);
2755 serialize_in6_addrs(f, in6_addrs, r);
2756 }
2757 }
2758
2759 fputc('\n', f);
2760
2761 fputs("NTP=", f);
2762 space = false;
2763 STRV_FOREACH(address, link->network->ntp) {
2764 if (space)
2765 fputc(' ', f);
2766 fputs(*address, f);
2767 space = true;
2768 }
2769
2770 if (link->network->dhcp_ntp &&
2771 link->dhcp_lease) {
2772 const struct in_addr *addresses;
2773
2774 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
2775 if (r > 0) {
2776 if (space)
2777 fputc(' ', f);
2778 serialize_in_addrs(f, addresses, r);
2779 space = true;
2780 }
2781 }
2782
2783 if (link->network->dhcp_ntp && dhcp6_lease) {
2784 struct in6_addr *in6_addrs;
2785 char **hosts;
2786 char **hostname;
2787
2788 r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
2789 &in6_addrs);
2790 if (r > 0) {
2791 if (space)
2792 fputc(' ', f);
2793 serialize_in6_addrs(f, in6_addrs, r);
2794 space = true;
2795 }
2796
2797 r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
2798 if (r > 0) {
2799 STRV_FOREACH(hostname, hosts) {
2800 if (space)
2801 fputc(' ', f);
2802 fputs(*hostname, f);
2803 space = true;
2804 }
2805 }
2806 }
2807
2808 fputc('\n', f);
2809
2810 fputs("DOMAINS=", f);
2811 space = false;
2812 STRV_FOREACH(domain, link->network->domains) {
2813 if (space)
2814 fputc(' ', f);
2815 fputs(*domain, f);
2816 space = true;
2817 }
2818
2819 if (link->network->dhcp_domains &&
2820 link->dhcp_lease) {
2821 const char *domainname;
2822
2823 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
2824 if (r >= 0) {
2825 if (space)
2826 fputc(' ', f);
2827 fputs(domainname, f);
2828 space = true;
2829 }
2830 }
2831
2832 if (link->network->dhcp_domains && dhcp6_lease) {
2833 char **domains;
2834
2835 r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
2836 if (r >= 0) {
2837 STRV_FOREACH(domain, domains) {
2838 if (space)
2839 fputc(' ', f);
2840 fputs(*domain, f);
2841 space = true;
2842 }
2843 }
2844 }
2845
2846 fputc('\n', f);
2847
2848 fprintf(f, "WILDCARD_DOMAIN=%s\n",
2849 yes_no(link->network->wildcard_domain));
2850
2851 fprintf(f, "LLMNR=%s\n",
2852 resolve_support_to_string(link->network->llmnr));
2853
2854 fputs("ADDRESSES=", f);
2855 space = false;
2856 SET_FOREACH(a, link->addresses, i) {
2857 _cleanup_free_ char *address_str = NULL;
2858
2859 r = in_addr_to_string(a->family, &a->in_addr, &address_str);
2860 if (r < 0)
2861 goto fail;
2862
2863 fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen);
2864 space = true;
2865 }
2866
2867 fputc('\n', f);
2868
2869 fputs("ROUTES=", f);
2870 space = false;
2871 SET_FOREACH(route, link->routes, i) {
2872 _cleanup_free_ char *route_str = NULL;
2873
2874 r = in_addr_to_string(route->family, &route->dst, &route_str);
2875 if (r < 0)
2876 goto fail;
2877
2878 fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu/"USEC_FMT, space ? " " : "", route_str,
2879 route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime);
2880 space = true;
2881 }
2882
2883 fputc('\n', f);
2884 }
2885
2886 if (!hashmap_isempty(link->bound_to_links)) {
2887 Link *carrier;
2888 bool space = false;
2889
2890 fputs("CARRIER_BOUND_TO=", f);
2891 HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
2892 if (space)
2893 fputc(' ', f);
2894 fputs(carrier->ifname, f);
2895 space = true;
2896 }
2897
2898 fputc('\n', f);
2899 }
2900
2901 if (!hashmap_isempty(link->bound_by_links)) {
2902 Link *carrier;
2903 bool space = false;
2904
2905 fputs("CARRIER_BOUND_BY=", f);
2906 HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
2907 if (space)
2908 fputc(' ', f);
2909 fputs(carrier->ifname, f);
2910 space = true;
2911 }
2912
2913 fputc('\n', f);
2914 }
2915
2916 if (link->dhcp_lease) {
2917 struct in_addr address;
2918 const char *tz = NULL;
2919
2920 assert(link->network);
2921
2922 r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
2923 if (r >= 0)
2924 fprintf(f, "TIMEZONE=%s\n", tz);
2925
2926 r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
2927 if (r >= 0) {
2928 fputs("DHCP4_ADDRESS=", f);
2929 serialize_in_addrs(f, &address, 1);
2930 fputc('\n', f);
2931 }
2932
2933 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
2934 if (r < 0)
2935 goto fail;
2936
2937 fprintf(f,
2938 "DHCP_LEASE=%s\n",
2939 link->lease_file);
2940 } else
2941 unlink(link->lease_file);
2942
2943 if (link->ipv4ll) {
2944 struct in_addr address;
2945
2946 r = sd_ipv4ll_get_address(link->ipv4ll, &address);
2947 if (r >= 0) {
2948 fputs("IPV4LL_ADDRESS=", f);
2949 serialize_in_addrs(f, &address, 1);
2950 fputc('\n', f);
2951 }
2952 }
2953
2954 if (link->lldp) {
2955 assert(link->network);
2956
2957 r = sd_lldp_save(link->lldp, link->lldp_file);
2958 if (r < 0)
2959 goto fail;
2960
2961 fprintf(f,
2962 "LLDP_FILE=%s\n",
2963 link->lldp_file);
2964 } else
2965 unlink(link->lldp_file);
2966
2967 r = fflush_and_check(f);
2968 if (r < 0)
2969 goto fail;
2970
2971 if (rename(temp_path, link->state_file) < 0) {
2972 r = -errno;
2973 goto fail;
2974 }
2975
2976 return 0;
2977
2978 fail:
2979 (void) unlink(link->state_file);
2980 if (temp_path)
2981 (void) unlink(temp_path);
2982
2983 return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
2984 }
2985
2986 /* The serialized state in /run is no longer up-to-date. */
2987 void link_dirty(Link *link) {
2988 int r;
2989
2990 assert(link);
2991
2992 r = set_ensure_allocated(&link->manager->dirty_links, NULL);
2993 if (r < 0)
2994 /* allocation errors are ignored */
2995 return;
2996
2997 r = set_put(link->manager->dirty_links, link);
2998 if (r < 0)
2999 /* allocation errors are ignored */
3000 return;
3001
3002 link_ref(link);
3003 }
3004
3005 /* The serialized state in /run is up-to-date */
3006 void link_clean(Link *link) {
3007 assert(link);
3008 assert(link->manager);
3009
3010 set_remove(link->manager->dirty_links, link);
3011 link_unref(link);
3012 }
3013
3014 static const char* const link_state_table[_LINK_STATE_MAX] = {
3015 [LINK_STATE_PENDING] = "pending",
3016 [LINK_STATE_ENSLAVING] = "configuring",
3017 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
3018 [LINK_STATE_SETTING_ROUTES] = "configuring",
3019 [LINK_STATE_CONFIGURED] = "configured",
3020 [LINK_STATE_UNMANAGED] = "unmanaged",
3021 [LINK_STATE_FAILED] = "failed",
3022 [LINK_STATE_LINGER] = "linger",
3023 };
3024
3025 DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
3026
3027 static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
3028 [LINK_OPERSTATE_OFF] = "off",
3029 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
3030 [LINK_OPERSTATE_DORMANT] = "dormant",
3031 [LINK_OPERSTATE_CARRIER] = "carrier",
3032 [LINK_OPERSTATE_DEGRADED] = "degraded",
3033 [LINK_OPERSTATE_ROUTABLE] = "routable",
3034 };
3035
3036 DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);