1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
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.
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.
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/>.
22 #include <netinet/ether.h>
26 #include "alloc-util.h"
28 #include "dhcp-lease-internal.h"
29 #include "event-util.h"
32 #include "netlink-util.h"
33 #include "network-internal.h"
34 #include "networkd-link.h"
35 #include "networkd-netdev.h"
37 #include "socket-util.h"
38 #include "stdio-util.h"
39 #include "string-table.h"
40 #include "udev-util.h"
44 bool link_dhcp6_enabled(Link
*link
) {
45 if (link
->flags
& IFF_LOOPBACK
)
51 return link
->network
->dhcp
& ADDRESS_FAMILY_IPV6
;
54 bool link_dhcp4_enabled(Link
*link
) {
55 if (link
->flags
& IFF_LOOPBACK
)
61 return link
->network
->dhcp
& ADDRESS_FAMILY_IPV4
;
64 bool link_dhcp4_server_enabled(Link
*link
) {
65 if (link
->flags
& IFF_LOOPBACK
)
71 return link
->network
->dhcp_server
;
74 bool link_ipv4ll_enabled(Link
*link
) {
75 if (link
->flags
& IFF_LOOPBACK
)
81 return link
->network
->link_local
& ADDRESS_FAMILY_IPV4
;
84 bool link_ipv6ll_enabled(Link
*link
) {
85 if (link
->flags
& IFF_LOOPBACK
)
91 return link
->network
->link_local
& ADDRESS_FAMILY_IPV6
;
94 bool link_lldp_enabled(Link
*link
) {
95 if (link
->flags
& IFF_LOOPBACK
)
101 if (link
->network
->bridge
)
104 return link
->network
->lldp
;
107 static bool link_ipv4_forward_enabled(Link
*link
) {
108 if (link
->flags
& IFF_LOOPBACK
)
114 return link
->network
->ip_forward
& ADDRESS_FAMILY_IPV4
;
117 static bool link_ipv6_forward_enabled(Link
*link
) {
118 if (link
->flags
& IFF_LOOPBACK
)
124 return link
->network
->ip_forward
& ADDRESS_FAMILY_IPV6
;
127 static IPv6PrivacyExtensions
link_ipv6_privacy_extensions(Link
*link
) {
128 if (link
->flags
& IFF_LOOPBACK
)
129 return _IPV6_PRIVACY_EXTENSIONS_INVALID
;
132 return _IPV6_PRIVACY_EXTENSIONS_INVALID
;
134 return link
->network
->ipv6_privacy_extensions
;
137 void link_update_operstate(Link
*link
) {
138 LinkOperationalState operstate
;
141 if (link
->kernel_operstate
== IF_OPER_DORMANT
)
142 operstate
= LINK_OPERSTATE_DORMANT
;
143 else if (link_has_carrier(link
)) {
145 uint8_t scope
= RT_SCOPE_NOWHERE
;
148 /* if we have carrier, check what addresses we have */
149 SET_FOREACH(address
, link
->addresses
, i
) {
150 if (!address_is_ready(address
))
153 if (address
->scope
< scope
)
154 scope
= address
->scope
;
157 /* for operstate we also take foreign addresses into account */
158 SET_FOREACH(address
, link
->addresses_foreign
, i
) {
159 if (!address_is_ready(address
))
162 if (address
->scope
< scope
)
163 scope
= address
->scope
;
166 if (scope
< RT_SCOPE_SITE
)
167 /* universally accessible addresses found */
168 operstate
= LINK_OPERSTATE_ROUTABLE
;
169 else if (scope
< RT_SCOPE_HOST
)
170 /* only link or site local addresses found */
171 operstate
= LINK_OPERSTATE_DEGRADED
;
173 /* no useful addresses found */
174 operstate
= LINK_OPERSTATE_CARRIER
;
175 } else if (link
->flags
& IFF_UP
)
176 operstate
= LINK_OPERSTATE_NO_CARRIER
;
178 operstate
= LINK_OPERSTATE_OFF
;
180 if (link
->operstate
!= operstate
) {
181 link
->operstate
= operstate
;
182 link_send_changed(link
, "OperationalState", NULL
);
184 manager_dirty(link
->manager
);
188 #define FLAG_STRING(string, flag, old, new) \
189 (((old ^ new) & flag) \
190 ? ((old & flag) ? (" -" string) : (" +" string)) \
193 static int link_update_flags(Link
*link
, sd_netlink_message
*m
) {
194 unsigned flags
, unknown_flags_added
, unknown_flags_removed
, unknown_flags
;
200 r
= sd_rtnl_message_link_get_flags(m
, &flags
);
202 return log_link_warning_errno(link
, r
, "Could not get link flags: %m");
204 r
= sd_netlink_message_read_u8(m
, IFLA_OPERSTATE
, &operstate
);
206 /* if we got a message without operstate, take it to mean
207 the state was unchanged */
208 operstate
= link
->kernel_operstate
;
210 if ((link
->flags
== flags
) && (link
->kernel_operstate
== operstate
))
213 if (link
->flags
!= flags
) {
214 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",
215 FLAG_STRING("LOOPBACK", IFF_LOOPBACK
, link
->flags
, flags
),
216 FLAG_STRING("MASTER", IFF_MASTER
, link
->flags
, flags
),
217 FLAG_STRING("SLAVE", IFF_SLAVE
, link
->flags
, flags
),
218 FLAG_STRING("UP", IFF_UP
, link
->flags
, flags
),
219 FLAG_STRING("DORMANT", IFF_DORMANT
, link
->flags
, flags
),
220 FLAG_STRING("LOWER_UP", IFF_LOWER_UP
, link
->flags
, flags
),
221 FLAG_STRING("RUNNING", IFF_RUNNING
, link
->flags
, flags
),
222 FLAG_STRING("MULTICAST", IFF_MULTICAST
, link
->flags
, flags
),
223 FLAG_STRING("BROADCAST", IFF_BROADCAST
, link
->flags
, flags
),
224 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT
, link
->flags
, flags
),
225 FLAG_STRING("PROMISC", IFF_PROMISC
, link
->flags
, flags
),
226 FLAG_STRING("ALLMULTI", IFF_ALLMULTI
, link
->flags
, flags
),
227 FLAG_STRING("PORTSEL", IFF_PORTSEL
, link
->flags
, flags
),
228 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA
, link
->flags
, flags
),
229 FLAG_STRING("DYNAMIC", IFF_DYNAMIC
, link
->flags
, flags
),
230 FLAG_STRING("NOARP", IFF_NOARP
, link
->flags
, flags
),
231 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS
, link
->flags
, flags
),
232 FLAG_STRING("DEBUG", IFF_DEBUG
, link
->flags
, flags
),
233 FLAG_STRING("ECHO", IFF_ECHO
, link
->flags
, flags
));
235 unknown_flags
= ~(IFF_LOOPBACK
| IFF_MASTER
| IFF_SLAVE
| IFF_UP
|
236 IFF_DORMANT
| IFF_LOWER_UP
| IFF_RUNNING
|
237 IFF_MULTICAST
| IFF_BROADCAST
| IFF_POINTOPOINT
|
238 IFF_PROMISC
| IFF_ALLMULTI
| IFF_PORTSEL
|
239 IFF_AUTOMEDIA
| IFF_DYNAMIC
| IFF_NOARP
|
240 IFF_NOTRAILERS
| IFF_DEBUG
| IFF_ECHO
);
241 unknown_flags_added
= ((link
->flags
^ flags
) & flags
& unknown_flags
);
242 unknown_flags_removed
= ((link
->flags
^ flags
) & link
->flags
& unknown_flags
);
244 /* link flags are currently at most 18 bits, let's align to
246 if (unknown_flags_added
)
248 "Unknown link flags gained: %#.5x (ignoring)",
249 unknown_flags_added
);
251 if (unknown_flags_removed
)
253 "Unknown link flags lost: %#.5x (ignoring)",
254 unknown_flags_removed
);
258 link
->kernel_operstate
= operstate
;
260 link_update_operstate(link
);
265 static int link_new(Manager
*manager
, sd_netlink_message
*message
, Link
**ret
) {
266 _cleanup_link_unref_ Link
*link
= NULL
;
275 r
= sd_netlink_message_get_type(message
, &type
);
278 else if (type
!= RTM_NEWLINK
)
281 r
= sd_rtnl_message_link_get_ifindex(message
, &ifindex
);
284 else if (ifindex
<= 0)
287 r
= sd_netlink_message_read_string(message
, IFLA_IFNAME
, &ifname
);
291 link
= new0(Link
, 1);
296 link
->manager
= manager
;
297 link
->state
= LINK_STATE_PENDING
;
298 link
->rtnl_extended_attrs
= true;
299 link
->ifindex
= ifindex
;
300 link
->ifname
= strdup(ifname
);
304 r
= sd_netlink_message_read_ether_addr(message
, IFLA_ADDRESS
, &link
->mac
);
306 log_link_debug(link
, "MAC address not found for new device, continuing without");
308 r
= asprintf(&link
->state_file
, "/run/systemd/netif/links/%d",
313 r
= asprintf(&link
->lease_file
, "/run/systemd/netif/leases/%d",
318 r
= asprintf(&link
->lldp_file
, "/run/systemd/netif/lldp/%d",
324 r
= hashmap_ensure_allocated(&manager
->links
, NULL
);
328 r
= hashmap_put(manager
->links
, INT_TO_PTR(link
->ifindex
), link
);
332 r
= link_update_flags(link
, message
);
342 static void link_free(Link
*link
) {
350 while (!set_isempty(link
->addresses
))
351 address_free(set_first(link
->addresses
));
353 while (!set_isempty(link
->addresses_foreign
))
354 address_free(set_first(link
->addresses_foreign
));
356 link
->addresses
= set_free(link
->addresses
);
358 link
->addresses_foreign
= set_free(link
->addresses_foreign
);
360 while ((address
= link
->pool_addresses
)) {
361 LIST_REMOVE(addresses
, link
->pool_addresses
, address
);
362 address_free(address
);
365 sd_dhcp_server_unref(link
->dhcp_server
);
366 sd_dhcp_client_unref(link
->dhcp_client
);
367 sd_dhcp_lease_unref(link
->dhcp_lease
);
369 free(link
->lease_file
);
371 sd_lldp_free(link
->lldp
);
373 free(link
->lldp_file
);
375 sd_ipv4ll_unref(link
->ipv4ll
);
376 sd_dhcp6_client_unref(link
->dhcp6_client
);
377 sd_ndisc_unref(link
->ndisc_router_discovery
);
380 hashmap_remove(link
->manager
->links
, INT_TO_PTR(link
->ifindex
));
384 (void)unlink(link
->state_file
);
385 free(link
->state_file
);
387 udev_device_unref(link
->udev_device
);
389 HASHMAP_FOREACH (carrier
, link
->bound_to_links
, i
)
390 hashmap_remove(link
->bound_to_links
, INT_TO_PTR(carrier
->ifindex
));
391 hashmap_free(link
->bound_to_links
);
393 HASHMAP_FOREACH (carrier
, link
->bound_by_links
, i
)
394 hashmap_remove(link
->bound_by_links
, INT_TO_PTR(carrier
->ifindex
));
395 hashmap_free(link
->bound_by_links
);
400 Link
*link_unref(Link
*link
) {
404 assert(link
->n_ref
> 0);
416 Link
*link_ref(Link
*link
) {
420 assert(link
->n_ref
> 0);
427 int link_get(Manager
*m
, int ifindex
, Link
**ret
) {
434 link
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
443 static void link_set_state(Link
*link
, LinkState state
) {
446 if (link
->state
== state
)
451 link_send_changed(link
, "AdministrativeState", NULL
);
456 static void link_enter_unmanaged(Link
*link
) {
459 log_link_debug(link
, "Unmanaged");
461 link_set_state(link
, LINK_STATE_UNMANAGED
);
466 static int link_stop_clients(Link
*link
) {
470 assert(link
->manager
);
471 assert(link
->manager
->event
);
476 if (link
->dhcp_client
) {
477 k
= sd_dhcp_client_stop(link
->dhcp_client
);
479 r
= log_link_warning_errno(link
, r
, "Could not stop DHCPv4 client: %m");
483 k
= sd_ipv4ll_stop(link
->ipv4ll
);
485 r
= log_link_warning_errno(link
, r
, "Could not stop IPv4 link-local: %m");
488 if(link
->ndisc_router_discovery
) {
489 if (link
->dhcp6_client
) {
490 k
= sd_dhcp6_client_stop(link
->dhcp6_client
);
492 r
= log_link_warning_errno(link
, r
, "Could not stop DHCPv6 client: %m");
495 k
= sd_ndisc_stop(link
->ndisc_router_discovery
);
497 r
= log_link_warning_errno(link
, r
, "Could not stop IPv6 Router Discovery: %m");
501 k
= sd_lldp_stop(link
->lldp
);
503 r
= log_link_warning_errno(link
, r
, "Could not stop LLDP: %m");
509 void link_enter_failed(Link
*link
) {
512 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
515 log_link_warning(link
, "Failed");
517 link_set_state(link
, LINK_STATE_FAILED
);
519 link_stop_clients(link
);
524 static Address
* link_find_dhcp_server_address(Link
*link
) {
528 assert(link
->network
);
530 /* The first statically configured address if there is any */
531 LIST_FOREACH(addresses
, address
, link
->network
->static_addresses
) {
533 if (address
->family
!= AF_INET
)
536 if (in_addr_is_null(address
->family
, &address
->in_addr
))
542 /* If that didn't work, find a suitable address we got from the pool */
543 LIST_FOREACH(addresses
, address
, link
->pool_addresses
) {
544 if (address
->family
!= AF_INET
)
553 static int link_enter_configured(Link
*link
) {
555 assert(link
->network
);
556 assert(link
->state
== LINK_STATE_SETTING_ROUTES
);
558 log_link_info(link
, "Configured");
560 link_set_state(link
, LINK_STATE_CONFIGURED
);
567 void link_check_ready(Link
*link
) {
576 if (!link
->static_configured
)
579 if (link_ipv4ll_enabled(link
))
580 if (!link
->ipv4ll_address
||
584 if ((link_dhcp4_enabled(link
) && !link_dhcp6_enabled(link
) &&
585 !link
->dhcp4_configured
) ||
586 (link_dhcp6_enabled(link
) && !link_dhcp4_enabled(link
) &&
587 !link
->dhcp6_configured
) ||
588 (link_dhcp4_enabled(link
) && link_dhcp6_enabled(link
) &&
589 !link
->dhcp4_configured
&& !link
->dhcp6_configured
))
592 SET_FOREACH(a
, link
->addresses
, i
)
593 if (!address_is_ready(a
))
596 if (link
->state
!= LINK_STATE_CONFIGURED
)
597 link_enter_configured(link
);
602 static int route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
603 _cleanup_link_unref_ Link
*link
= userdata
;
606 assert(link
->link_messages
> 0);
607 assert(IN_SET(link
->state
, LINK_STATE_SETTING_ADDRESSES
,
608 LINK_STATE_SETTING_ROUTES
, LINK_STATE_FAILED
,
611 link
->link_messages
--;
613 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
616 r
= sd_netlink_message_get_errno(m
);
617 if (r
< 0 && r
!= -EEXIST
)
618 log_link_warning_errno(link
, r
, "Could not set route: %m");
620 if (link
->link_messages
== 0) {
621 log_link_debug(link
, "Routes set");
622 link
->static_configured
= true;
623 link_check_ready(link
);
629 static int link_enter_set_routes(Link
*link
) {
634 assert(link
->network
);
635 assert(link
->state
== LINK_STATE_SETTING_ADDRESSES
);
637 link_set_state(link
, LINK_STATE_SETTING_ROUTES
);
639 LIST_FOREACH(routes
, rt
, link
->network
->static_routes
) {
640 r
= route_configure(rt
, link
, &route_handler
);
642 log_link_warning_errno(link
, r
, "Could not set routes: %m");
643 link_enter_failed(link
);
647 link
->link_messages
++;
650 if (link
->link_messages
== 0) {
651 link
->static_configured
= true;
652 link_check_ready(link
);
654 log_link_debug(link
, "Setting routes");
659 int link_route_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
660 _cleanup_link_unref_ Link
*link
= userdata
;
665 assert(link
->ifname
);
667 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
670 r
= sd_netlink_message_get_errno(m
);
671 if (r
< 0 && r
!= -ESRCH
)
672 log_link_warning_errno(link
, r
, "Could not drop route: %m");
677 static int address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
678 _cleanup_link_unref_ Link
*link
= userdata
;
684 assert(link
->ifname
);
685 assert(link
->link_messages
> 0);
686 assert(IN_SET(link
->state
, LINK_STATE_SETTING_ADDRESSES
,
687 LINK_STATE_FAILED
, LINK_STATE_LINGER
));
689 link
->link_messages
--;
691 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
694 r
= sd_netlink_message_get_errno(m
);
695 if (r
< 0 && r
!= -EEXIST
)
696 log_link_warning_errno(link
, r
, "could not set address: %m");
698 manager_rtnl_process_address(rtnl
, m
, link
->manager
);
700 if (link
->link_messages
== 0) {
701 log_link_debug(link
, "Addresses set");
702 link_enter_set_routes(link
);
708 static int link_push_dns_to_dhcp_server(Link
*link
, sd_dhcp_server
*s
) {
709 _cleanup_free_
struct in_addr
*addresses
= NULL
;
710 size_t n_addresses
= 0, n_allocated
= 0;
713 log_debug("Copying DNS server information from %s", link
->ifname
);
718 STRV_FOREACH(a
, link
->network
->dns
) {
721 /* Only look for IPv4 addresses */
722 if (inet_pton(AF_INET
, *a
, &ia
) <= 0)
725 if (!GREEDY_REALLOC(addresses
, n_allocated
, n_addresses
+ 1))
728 addresses
[n_addresses
++] = ia
;
731 if (link
->network
->dhcp_dns
&&
733 const struct in_addr
*da
= NULL
;
736 n
= sd_dhcp_lease_get_dns(link
->dhcp_lease
, &da
);
739 if (!GREEDY_REALLOC(addresses
, n_allocated
, n_addresses
+ n
))
742 memcpy(addresses
+ n_addresses
, da
, n
* sizeof(struct in_addr
));
747 if (n_addresses
<= 0)
750 return sd_dhcp_server_set_dns(s
, addresses
, n_addresses
);
753 static int link_push_ntp_to_dhcp_server(Link
*link
, sd_dhcp_server
*s
) {
754 _cleanup_free_
struct in_addr
*addresses
= NULL
;
755 size_t n_addresses
= 0, n_allocated
= 0;
761 log_debug("Copying NTP server information from %s", link
->ifname
);
763 STRV_FOREACH(a
, link
->network
->ntp
) {
766 /* Only look for IPv4 addresses */
767 if (inet_pton(AF_INET
, *a
, &ia
) <= 0)
770 if (!GREEDY_REALLOC(addresses
, n_allocated
, n_addresses
+ 1))
773 addresses
[n_addresses
++] = ia
;
776 if (link
->network
->dhcp_ntp
&&
778 const struct in_addr
*da
= NULL
;
781 n
= sd_dhcp_lease_get_ntp(link
->dhcp_lease
, &da
);
784 if (!GREEDY_REALLOC(addresses
, n_allocated
, n_addresses
+ n
))
787 memcpy(addresses
+ n_addresses
, da
, n
* sizeof(struct in_addr
));
792 if (n_addresses
<= 0)
795 return sd_dhcp_server_set_ntp(s
, addresses
, n_addresses
);
798 static int link_enter_set_addresses(Link
*link
) {
803 assert(link
->network
);
804 assert(link
->state
!= _LINK_STATE_INVALID
);
806 link_set_state(link
, LINK_STATE_SETTING_ADDRESSES
);
808 LIST_FOREACH(addresses
, ad
, link
->network
->static_addresses
) {
809 r
= address_configure(ad
, link
, &address_handler
, false);
811 log_link_warning_errno(link
, r
, "Could not set addresses: %m");
812 link_enter_failed(link
);
816 link
->link_messages
++;
819 /* now that we can figure out a default address for the dhcp server,
821 if (link_dhcp4_server_enabled(link
)) {
824 bool acquired_uplink
= false;
826 address
= link_find_dhcp_server_address(link
);
828 log_link_warning(link
, "Failed to find suitable address for DHCPv4 server instance.");
829 link_enter_failed(link
);
833 /* use the server address' subnet as the pool */
834 r
= sd_dhcp_server_configure_pool(link
->dhcp_server
, &address
->in_addr
.in
, address
->prefixlen
,
835 link
->network
->dhcp_server_pool_offset
, link
->network
->dhcp_server_pool_size
);
840 r = sd_dhcp_server_set_router(link->dhcp_server,
841 &main_address->in_addr.in);
846 if (link
->network
->dhcp_server_max_lease_time_usec
> 0) {
847 r
= sd_dhcp_server_set_max_lease_time(
849 DIV_ROUND_UP(link
->network
->dhcp_server_max_lease_time_usec
, USEC_PER_SEC
));
854 if (link
->network
->dhcp_server_default_lease_time_usec
> 0) {
855 r
= sd_dhcp_server_set_default_lease_time(
857 DIV_ROUND_UP(link
->network
->dhcp_server_default_lease_time_usec
, USEC_PER_SEC
));
862 if (link
->network
->dhcp_server_emit_dns
) {
864 if (link
->network
->n_dhcp_server_dns
> 0)
865 r
= sd_dhcp_server_set_dns(link
->dhcp_server
, link
->network
->dhcp_server_dns
, link
->network
->n_dhcp_server_dns
);
867 uplink
= manager_find_uplink(link
->manager
, link
);
868 acquired_uplink
= true;
871 log_link_debug(link
, "Not emitting DNS server information on link, couldn't find suitable uplink.");
874 r
= link_push_dns_to_dhcp_server(uplink
, link
->dhcp_server
);
877 log_link_warning_errno(link
, r
, "Failed to set DNS server for DHCP server, ignoring: %m");
881 if (link
->network
->dhcp_server_emit_ntp
) {
883 if (link
->network
->n_dhcp_server_ntp
> 0)
884 r
= sd_dhcp_server_set_ntp(link
->dhcp_server
, link
->network
->dhcp_server_ntp
, link
->network
->n_dhcp_server_ntp
);
886 if (!acquired_uplink
)
887 uplink
= manager_find_uplink(link
->manager
, link
);
890 log_link_debug(link
, "Not emitting NTP server information on link, couldn't find suitable uplink.");
893 r
= link_push_ntp_to_dhcp_server(uplink
, link
->dhcp_server
);
897 log_link_warning_errno(link
, r
, "Failed to set NTP server for DHCP server, ignoring: %m");
900 if (link
->network
->dhcp_server_emit_timezone
) {
901 _cleanup_free_
char *buffer
= NULL
;
902 const char *tz
= NULL
;
904 if (link
->network
->dhcp_server_timezone
)
905 tz
= link
->network
->dhcp_server_timezone
;
907 r
= get_timezone(&buffer
);
909 log_warning_errno(r
, "Failed to determine timezone: %m");
915 r
= sd_dhcp_server_set_timezone(link
->dhcp_server
, tz
);
921 r
= sd_dhcp_server_start(link
->dhcp_server
);
923 log_link_warning_errno(link
, r
, "Could not start DHCPv4 server instance: %m");
925 link_enter_failed(link
);
930 log_link_debug(link
, "Offering DHCPv4 leases");
933 if (link
->link_messages
== 0)
934 link_enter_set_routes(link
);
936 log_link_debug(link
, "Setting addresses");
941 int link_address_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
942 _cleanup_link_unref_ Link
*link
= userdata
;
947 assert(link
->ifname
);
949 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
952 r
= sd_netlink_message_get_errno(m
);
953 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
954 log_link_warning_errno(link
, r
, "Could not drop address: %m");
959 static int link_set_bridge_fdb(Link
*const link
) {
963 LIST_FOREACH(static_fdb_entries
, fdb_entry
, link
->network
->static_fdb_entries
) {
964 r
= fdb_entry_configure(link
, fdb_entry
);
966 log_link_error_errno(link
, r
, "Failed to add MAC entry to static MAC table: %m");
974 static int link_set_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
975 _cleanup_link_unref_ Link
*link
= userdata
;
978 log_link_debug(link
, "Set link");
980 r
= sd_netlink_message_get_errno(m
);
981 if (r
< 0 && r
!= -EEXIST
) {
982 log_link_error_errno(link
, r
, "Could not join netdev: %m");
983 link_enter_failed(link
);
990 static int set_hostname_handler(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
991 _cleanup_link_unref_ Link
*link
= userdata
;
992 const sd_bus_error
*e
;
997 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1000 e
= sd_bus_message_get_error(m
);
1002 log_link_warning_errno(link
, sd_bus_error_get_errno(e
), "Could not set hostname: %s", e
->message
);
1007 int link_set_hostname(Link
*link
, const char *hostname
) {
1011 assert(link
->manager
);
1013 log_link_debug(link
, "Setting transient hostname: '%s'", strna(hostname
));
1015 if (!link
->manager
->bus
) {
1016 /* TODO: replace by assert when we can rely on kdbus */
1017 log_link_info(link
, "Not connected to system bus, ignoring transient hostname.");
1021 r
= sd_bus_call_method_async(
1024 "org.freedesktop.hostname1",
1025 "/org/freedesktop/hostname1",
1026 "org.freedesktop.hostname1",
1028 set_hostname_handler
,
1035 return log_link_error_errno(link
, r
, "Could not set transient hostname: %m");
1042 static int set_timezone_handler(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
1043 _cleanup_link_unref_ Link
*link
= userdata
;
1044 const sd_bus_error
*e
;
1049 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1052 e
= sd_bus_message_get_error(m
);
1054 log_link_warning_errno(link
, sd_bus_error_get_errno(e
), "Could not set timezone: %s", e
->message
);
1059 int link_set_timezone(Link
*link
, const char *tz
) {
1063 assert(link
->manager
);
1066 log_link_debug(link
, "Setting system timezone: '%s'", tz
);
1068 if (!link
->manager
->bus
) {
1069 log_link_info(link
, "Not connected to system bus, ignoring timezone.");
1073 r
= sd_bus_call_method_async(
1076 "org.freedesktop.timedate1",
1077 "/org/freedesktop/timedate1",
1078 "org.freedesktop.timedate1",
1080 set_timezone_handler
,
1086 return log_link_error_errno(link
, r
, "Could not set timezone: %m");
1093 static int set_mtu_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
1094 _cleanup_link_unref_ Link
*link
= userdata
;
1099 assert(link
->ifname
);
1101 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1104 r
= sd_netlink_message_get_errno(m
);
1106 log_link_warning_errno(link
, r
, "Could not set MTU: %m");
1111 int link_set_mtu(Link
*link
, uint32_t mtu
) {
1112 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
1116 assert(link
->manager
);
1117 assert(link
->manager
->rtnl
);
1119 log_link_debug(link
, "Setting MTU: %" PRIu32
, mtu
);
1121 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
1123 return log_link_error_errno(link
, r
, "Could not allocate RTM_SETLINK message: %m");
1125 r
= sd_netlink_message_append_u32(req
, IFLA_MTU
, mtu
);
1127 return log_link_error_errno(link
, r
, "Could not append MTU: %m");
1129 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, set_mtu_handler
, link
, 0, NULL
);
1131 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
1138 static int link_set_bridge(Link
*link
) {
1139 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
1143 assert(link
->network
);
1145 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
1147 return log_link_error_errno(link
, r
, "Could not allocate RTM_SETLINK message: %m");
1149 r
= sd_rtnl_message_link_set_family(req
, PF_BRIDGE
);
1151 return log_link_error_errno(link
, r
, "Could not set message family: %m");
1153 r
= sd_netlink_message_open_container(req
, IFLA_PROTINFO
);
1155 return log_link_error_errno(link
, r
, "Could not append IFLA_PROTINFO attribute: %m");
1157 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_GUARD
, !link
->network
->use_bpdu
);
1159 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_GUARD attribute: %m");
1161 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_MODE
, link
->network
->hairpin
);
1163 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_MODE attribute: %m");
1165 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_FAST_LEAVE
, link
->network
->fast_leave
);
1167 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
1169 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_PROTECT
, !link
->network
->allow_port_to_be_root
);
1171 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
1173 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_UNICAST_FLOOD
, link
->network
->unicast_flood
);
1175 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
1177 if(link
->network
->cost
!= 0) {
1178 r
= sd_netlink_message_append_u32(req
, IFLA_BRPORT_COST
, link
->network
->cost
);
1180 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_COST attribute: %m");
1183 r
= sd_netlink_message_close_container(req
);
1185 return log_link_error_errno(link
, r
, "Could not append IFLA_LINKINFO attribute: %m");
1187 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, link_set_handler
, link
, 0, NULL
);
1189 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
1196 static void lldp_handler(sd_lldp
*lldp
, int event
, void *userdata
) {
1197 Link
*link
= userdata
;
1201 assert(link
->network
);
1202 assert(link
->manager
);
1205 case SD_LLDP_EVENT_UPDATE_INFO
:
1206 r
= sd_lldp_save(link
->lldp
, link
->lldp_file
);
1208 log_link_warning_errno(link
, r
, "Could not save LLDP: %m");
1216 static int link_acquire_conf(Link
*link
) {
1220 assert(link
->network
);
1221 assert(link
->manager
);
1222 assert(link
->manager
->event
);
1224 if (link_ipv4ll_enabled(link
)) {
1225 assert(link
->ipv4ll
);
1227 log_link_debug(link
, "Acquiring IPv4 link-local address");
1229 r
= sd_ipv4ll_start(link
->ipv4ll
);
1231 return log_link_warning_errno(link
, r
, "Could not acquire IPv4 link-local address: %m");
1234 if (link_dhcp4_enabled(link
)) {
1235 assert(link
->dhcp_client
);
1237 log_link_debug(link
, "Acquiring DHCPv4 lease");
1239 r
= sd_dhcp_client_start(link
->dhcp_client
);
1241 return log_link_warning_errno(link
, r
, "Could not acquire DHCPv4 lease: %m");
1244 if (link_dhcp6_enabled(link
)) {
1245 assert(link
->ndisc_router_discovery
);
1247 log_link_debug(link
, "Discovering IPv6 routers");
1249 r
= sd_ndisc_router_discovery_start(link
->ndisc_router_discovery
);
1251 return log_link_warning_errno(link
, r
, "Could not start IPv6 Router Discovery: %m");
1254 if (link_lldp_enabled(link
)) {
1257 log_link_debug(link
, "Starting LLDP");
1259 r
= sd_lldp_start(link
->lldp
);
1261 return log_link_warning_errno(link
, r
, "Could not start LLDP: %m");
1267 bool link_has_carrier(Link
*link
) {
1268 /* see Documentation/networking/operstates.txt in the kernel sources */
1270 if (link
->kernel_operstate
== IF_OPER_UP
)
1273 if (link
->kernel_operstate
== IF_OPER_UNKNOWN
)
1274 /* operstate may not be implemented, so fall back to flags */
1275 if ((link
->flags
& IFF_LOWER_UP
) && !(link
->flags
& IFF_DORMANT
))
1281 static int link_up_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
1282 _cleanup_link_unref_ Link
*link
= userdata
;
1287 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1290 r
= sd_netlink_message_get_errno(m
);
1292 /* we warn but don't fail the link, as it may be
1294 log_link_warning_errno(link
, r
, "Could not bring up interface: %m");
1299 static int link_up(Link
*link
) {
1300 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
1301 uint8_t ipv6ll_mode
;
1305 assert(link
->network
);
1306 assert(link
->manager
);
1307 assert(link
->manager
->rtnl
);
1309 log_link_debug(link
, "Bringing link up");
1311 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
1313 return log_link_error_errno(link
, r
, "Could not allocate RTM_SETLINK message: %m");
1315 r
= sd_rtnl_message_link_set_flags(req
, IFF_UP
, IFF_UP
);
1317 return log_link_error_errno(link
, r
, "Could not set link flags: %m");
1319 if (link
->network
->mac
) {
1320 r
= sd_netlink_message_append_ether_addr(req
, IFLA_ADDRESS
, link
->network
->mac
);
1322 return log_link_error_errno(link
, r
, "Could not set MAC address: %m");
1325 if (link
->network
->mtu
) {
1326 r
= sd_netlink_message_append_u32(req
, IFLA_MTU
, link
->network
->mtu
);
1328 return log_link_error_errno(link
, r
, "Could not set MTU: %m");
1331 r
= sd_netlink_message_open_container(req
, IFLA_AF_SPEC
);
1333 return log_link_error_errno(link
, r
, "Could not open IFLA_AF_SPEC container: %m");
1335 if (socket_ipv6_is_supported()) {
1336 /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
1337 r
= sd_netlink_message_open_container(req
, AF_INET6
);
1339 return log_link_error_errno(link
, r
, "Could not open AF_INET6 container: %m");
1341 ipv6ll_mode
= link_ipv6ll_enabled(link
) ? IN6_ADDR_GEN_MODE_EUI64
: IN6_ADDR_GEN_MODE_NONE
;
1342 r
= sd_netlink_message_append_u8(req
, IFLA_INET6_ADDR_GEN_MODE
, ipv6ll_mode
);
1344 return log_link_error_errno(link
, r
, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
1346 if (!in_addr_is_null(AF_INET6
, &link
->network
->ipv6_token
)) {
1347 r
= sd_netlink_message_append_in6_addr(req
, IFLA_INET6_TOKEN
, &link
->network
->ipv6_token
.in6
);
1349 return log_link_error_errno(link
, r
, "Could not append IFLA_INET6_TOKEN: %m");
1352 r
= sd_netlink_message_close_container(req
);
1354 return log_link_error_errno(link
, r
, "Could not close AF_INET6 container: %m");
1357 r
= sd_netlink_message_close_container(req
);
1359 return log_link_error_errno(link
, r
, "Could not close IFLA_AF_SPEC container: %m");
1361 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, link_up_handler
, link
, 0, NULL
);
1363 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
1370 static int link_down_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
1371 _cleanup_link_unref_ Link
*link
= userdata
;
1376 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1379 r
= sd_netlink_message_get_errno(m
);
1381 log_link_warning_errno(link
, r
, "Could not bring down interface: %m");
1386 static int link_down(Link
*link
) {
1387 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
1391 assert(link
->manager
);
1392 assert(link
->manager
->rtnl
);
1394 log_link_debug(link
, "Bringing link down");
1396 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &req
,
1397 RTM_SETLINK
, link
->ifindex
);
1399 return log_link_error_errno(link
, r
, "Could not allocate RTM_SETLINK message: %m");
1401 r
= sd_rtnl_message_link_set_flags(req
, 0, IFF_UP
);
1403 return log_link_error_errno(link
, r
, "Could not set link flags: %m");
1405 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, link_down_handler
, link
, 0, NULL
);
1407 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
1414 static int link_handle_bound_to_list(Link
*link
) {
1418 bool required_up
= false;
1419 bool link_is_up
= false;
1423 if (hashmap_isempty(link
->bound_to_links
))
1426 if (link
->flags
& IFF_UP
)
1429 HASHMAP_FOREACH (l
, link
->bound_to_links
, i
)
1430 if (link_has_carrier(l
)) {
1435 if (!required_up
&& link_is_up
) {
1436 r
= link_down(link
);
1439 } else if (required_up
&& !link_is_up
) {
1448 static int link_handle_bound_by_list(Link
*link
) {
1455 if (hashmap_isempty(link
->bound_by_links
))
1458 HASHMAP_FOREACH (l
, link
->bound_by_links
, i
) {
1459 r
= link_handle_bound_to_list(l
);
1467 static int link_put_carrier(Link
*link
, Link
*carrier
, Hashmap
**h
) {
1473 if (link
== carrier
)
1476 if (hashmap_get(*h
, INT_TO_PTR(carrier
->ifindex
)))
1479 r
= hashmap_ensure_allocated(h
, NULL
);
1483 r
= hashmap_put(*h
, INT_TO_PTR(carrier
->ifindex
), carrier
);
1490 static int link_new_bound_by_list(Link
*link
) {
1495 bool list_updated
= false;
1498 assert(link
->manager
);
1502 HASHMAP_FOREACH (carrier
, m
->links
, i
) {
1503 if (!carrier
->network
)
1506 if (strv_isempty(carrier
->network
->bind_carrier
))
1509 if (strv_fnmatch(carrier
->network
->bind_carrier
, link
->ifname
, 0)) {
1510 r
= link_put_carrier(link
, carrier
, &link
->bound_by_links
);
1514 list_updated
= true;
1521 HASHMAP_FOREACH (carrier
, link
->bound_by_links
, i
) {
1522 r
= link_put_carrier(carrier
, link
, &carrier
->bound_to_links
);
1526 link_dirty(carrier
);
1532 static int link_new_bound_to_list(Link
*link
) {
1537 bool list_updated
= false;
1540 assert(link
->manager
);
1545 if (strv_isempty(link
->network
->bind_carrier
))
1550 HASHMAP_FOREACH (carrier
, m
->links
, i
) {
1551 if (strv_fnmatch(link
->network
->bind_carrier
, carrier
->ifname
, 0)) {
1552 r
= link_put_carrier(link
, carrier
, &link
->bound_to_links
);
1556 list_updated
= true;
1563 HASHMAP_FOREACH (carrier
, link
->bound_to_links
, i
) {
1564 r
= link_put_carrier(carrier
, link
, &carrier
->bound_by_links
);
1568 link_dirty(carrier
);
1574 static int link_new_carrier_maps(Link
*link
) {
1577 r
= link_new_bound_by_list(link
);
1581 r
= link_handle_bound_by_list(link
);
1585 r
= link_new_bound_to_list(link
);
1589 r
= link_handle_bound_to_list(link
);
1596 static void link_free_bound_to_list(Link
*link
) {
1600 HASHMAP_FOREACH (bound_to
, link
->bound_to_links
, i
) {
1601 hashmap_remove(link
->bound_to_links
, INT_TO_PTR(bound_to
->ifindex
));
1603 if (hashmap_remove(bound_to
->bound_by_links
, INT_TO_PTR(link
->ifindex
)))
1604 link_dirty(bound_to
);
1610 static void link_free_bound_by_list(Link
*link
) {
1614 HASHMAP_FOREACH (bound_by
, link
->bound_by_links
, i
) {
1615 hashmap_remove(link
->bound_by_links
, INT_TO_PTR(bound_by
->ifindex
));
1617 if (hashmap_remove(bound_by
->bound_to_links
, INT_TO_PTR(link
->ifindex
))) {
1618 link_dirty(bound_by
);
1619 link_handle_bound_to_list(bound_by
);
1626 static void link_free_carrier_maps(Link
*link
) {
1627 bool list_updated
= false;
1631 if (!hashmap_isempty(link
->bound_to_links
)) {
1632 link_free_bound_to_list(link
);
1633 list_updated
= true;
1636 if (!hashmap_isempty(link
->bound_by_links
)) {
1637 link_free_bound_by_list(link
);
1638 list_updated
= true;
1647 void link_drop(Link
*link
) {
1648 if (!link
|| link
->state
== LINK_STATE_LINGER
)
1651 link_set_state(link
, LINK_STATE_LINGER
);
1653 link_free_carrier_maps(link
);
1655 log_link_debug(link
, "Link removed");
1657 (void)unlink(link
->state_file
);
1663 static int link_joined(Link
*link
) {
1667 assert(link
->network
);
1669 if (!hashmap_isempty(link
->bound_to_links
)) {
1670 r
= link_handle_bound_to_list(link
);
1673 } else if (!(link
->flags
& IFF_UP
)) {
1676 link_enter_failed(link
);
1681 if(link
->network
->bridge
) {
1682 r
= link_set_bridge(link
);
1684 log_link_error_errno(link
, r
, "Could not set bridge message: %m");
1687 return link_enter_set_addresses(link
);
1690 static int netdev_join_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
1691 _cleanup_link_unref_ Link
*link
= userdata
;
1695 assert(link
->network
);
1699 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1702 r
= sd_netlink_message_get_errno(m
);
1703 if (r
< 0 && r
!= -EEXIST
) {
1704 log_link_error_errno(link
, r
, "Could not join netdev: %m");
1705 link_enter_failed(link
);
1708 log_link_debug(link
, "Joined netdev");
1710 if (link
->enslaving
<= 0)
1716 static int link_enter_join_netdev(Link
*link
) {
1722 assert(link
->network
);
1723 assert(link
->state
== LINK_STATE_PENDING
);
1725 link_set_state(link
, LINK_STATE_ENSLAVING
);
1729 if (!link
->network
->bridge
&&
1730 !link
->network
->bond
&&
1731 hashmap_isempty(link
->network
->stacked_netdevs
))
1732 return link_joined(link
);
1734 if (link
->network
->bond
) {
1735 log_struct(LOG_DEBUG
,
1736 LOG_LINK_INTERFACE(link
),
1737 LOG_NETDEV_INTERFACE(link
->network
->bond
),
1738 LOG_LINK_MESSAGE(link
, "Enslaving by '%s'", link
->network
->bond
->ifname
),
1741 r
= netdev_join(link
->network
->bond
, link
, netdev_join_handler
);
1743 log_struct_errno(LOG_WARNING
, r
,
1744 LOG_LINK_INTERFACE(link
),
1745 LOG_NETDEV_INTERFACE(link
->network
->bond
),
1746 LOG_LINK_MESSAGE(link
, "Could not join netdev '%s': %m", link
->network
->bond
->ifname
),
1749 link_enter_failed(link
);
1756 if (link
->network
->bridge
) {
1757 log_struct(LOG_DEBUG
,
1758 LOG_LINK_INTERFACE(link
),
1759 LOG_NETDEV_INTERFACE(link
->network
->bridge
),
1760 LOG_LINK_MESSAGE(link
, "Enslaving by '%s'", link
->network
->bridge
->ifname
),
1763 r
= netdev_join(link
->network
->bridge
, link
, netdev_join_handler
);
1765 log_struct_errno(LOG_WARNING
, r
,
1766 LOG_LINK_INTERFACE(link
),
1767 LOG_NETDEV_INTERFACE(link
->network
->bridge
),
1768 LOG_LINK_MESSAGE(link
, "Could not join netdev '%s': %m", link
->network
->bridge
->ifname
),
1770 link_enter_failed(link
);
1777 HASHMAP_FOREACH(netdev
, link
->network
->stacked_netdevs
, i
) {
1779 log_struct(LOG_DEBUG
,
1780 LOG_LINK_INTERFACE(link
),
1781 LOG_NETDEV_INTERFACE(netdev
),
1782 LOG_LINK_MESSAGE(link
, "Enslaving by '%s'", netdev
->ifname
),
1785 r
= netdev_join(netdev
, link
, netdev_join_handler
);
1787 log_struct_errno(LOG_WARNING
, r
,
1788 LOG_LINK_INTERFACE(link
),
1789 LOG_NETDEV_INTERFACE(netdev
),
1790 LOG_LINK_MESSAGE(link
, "Could not join netdev '%s': %m", netdev
->ifname
),
1792 link_enter_failed(link
);
1802 static int link_set_ipv4_forward(Link
*link
) {
1803 const char *p
= NULL
, *v
;
1806 if (link
->flags
& IFF_LOOPBACK
)
1809 if (link
->network
->ip_forward
== _ADDRESS_FAMILY_BOOLEAN_INVALID
)
1812 p
= strjoina("/proc/sys/net/ipv4/conf/", link
->ifname
, "/forwarding");
1813 v
= one_zero(link_ipv4_forward_enabled(link
));
1815 r
= write_string_file(p
, v
, 0);
1817 /* If the right value is set anyway, don't complain */
1818 if (verify_one_line_file(p
, v
) > 0)
1821 log_link_warning_errno(link
, r
, "Cannot configure IPv4 forwarding for interface %s: %m", link
->ifname
);
1827 static int link_set_ipv6_forward(Link
*link
) {
1828 const char *p
= NULL
, *v
= NULL
;
1831 /* Make this a NOP if IPv6 is not available */
1832 if (!socket_ipv6_is_supported())
1835 if (link
->flags
& IFF_LOOPBACK
)
1838 if (link
->network
->ip_forward
== _ADDRESS_FAMILY_BOOLEAN_INVALID
)
1841 p
= strjoina("/proc/sys/net/ipv6/conf/", link
->ifname
, "/forwarding");
1842 v
= one_zero(link_ipv6_forward_enabled(link
));
1844 r
= write_string_file(p
, v
, 0);
1846 /* If the right value is set anyway, don't complain */
1847 if (verify_one_line_file(p
, v
) > 0)
1850 log_link_warning_errno(link
, r
, "Cannot configure IPv6 forwarding for interface: %m");
1856 static int link_set_ipv6_privacy_extensions(Link
*link
) {
1857 char buf
[DECIMAL_STR_MAX(unsigned) + 1];
1858 IPv6PrivacyExtensions s
;
1859 const char *p
= NULL
;
1862 /* Make this a NOP if IPv6 is not available */
1863 if (!socket_ipv6_is_supported())
1866 s
= link_ipv6_privacy_extensions(link
);
1867 if (s
== _IPV6_PRIVACY_EXTENSIONS_INVALID
)
1870 p
= strjoina("/proc/sys/net/ipv6/conf/", link
->ifname
, "/use_tempaddr");
1871 xsprintf(buf
, "%u", link
->network
->ipv6_privacy_extensions
);
1873 r
= write_string_file(p
, buf
, 0);
1875 /* If the right value is set anyway, don't complain */
1876 if (verify_one_line_file(p
, buf
) > 0)
1879 log_link_warning_errno(link
, r
, "Cannot configure IPv6 privacy extension for interface: %m");
1885 static int link_set_ipv6_accept_ra(Link
*link
) {
1886 const char *p
= NULL
, *v
= NULL
;
1889 /* Make this a NOP if IPv6 is not available */
1890 if (!socket_ipv6_is_supported())
1893 if (link
->flags
& IFF_LOOPBACK
)
1896 /* If unset use system default (enabled if local forwarding is disabled.
1897 * disabled if local forwarding is enabled).
1898 * If set, ignore or enforce RA independent of local forwarding state.
1900 if (link
->network
->ipv6_accept_ra
< 0)
1901 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
1903 else if (link
->network
->ipv6_accept_ra
> 0)
1904 /* "2" means accept RA even if ip_forward is enabled */
1907 /* "0" means ignore RA */
1910 p
= strjoina("/proc/sys/net/ipv6/conf/", link
->ifname
, "/accept_ra");
1912 r
= write_string_file(p
, v
, 0);
1914 /* If the right value is set anyway, don't complain */
1915 if (verify_one_line_file(p
, v
) > 0)
1918 log_link_warning_errno(link
, r
, "Cannot configure IPv6 accept_ra for interface: %m");
1924 static int link_set_ipv6_dad_transmits(Link
*link
) {
1925 char buf
[DECIMAL_STR_MAX(unsigned) + 1];
1926 const char *p
= NULL
;
1929 /* Make this a NOP if IPv6 is not available */
1930 if (!socket_ipv6_is_supported())
1933 if (link
->flags
& IFF_LOOPBACK
)
1936 if (link
->network
->ipv6_dad_transmits
< 0)
1939 p
= strjoina("/proc/sys/net/ipv6/conf/", link
->ifname
, "/dad_transmits");
1941 xsprintf(buf
, "%u", link
->network
->ipv6_dad_transmits
);
1943 r
= write_string_file(p
, buf
, 0);
1945 /* If the right value is set anyway, don't complain */
1946 if (verify_one_line_file(p
, buf
) > 0)
1949 log_link_warning_errno(link
, r
, "Cannot set IPv6 dad transmits for interface: %m");
1955 static int link_configure(Link
*link
) {
1959 assert(link
->network
);
1960 assert(link
->state
== LINK_STATE_PENDING
);
1962 r
= link_set_bridge_fdb(link
);
1966 r
= link_set_ipv4_forward(link
);
1970 r
= link_set_ipv6_forward(link
);
1974 r
= link_set_ipv6_privacy_extensions(link
);
1978 r
= link_set_ipv6_accept_ra(link
);
1982 r
= link_set_ipv6_dad_transmits(link
);
1986 if (link_ipv4ll_enabled(link
)) {
1987 r
= ipv4ll_configure(link
);
1992 if (link_dhcp4_enabled(link
)) {
1993 r
= dhcp4_configure(link
);
1998 if (link_dhcp4_server_enabled(link
)) {
1999 r
= sd_dhcp_server_new(&link
->dhcp_server
, link
->ifindex
);
2003 r
= sd_dhcp_server_attach_event(link
->dhcp_server
, NULL
, 0);
2008 if (link_dhcp6_enabled(link
)) {
2009 r
= ndisc_configure(link
);
2014 if (link_lldp_enabled(link
)) {
2015 r
= sd_lldp_new(link
->ifindex
, link
->ifname
, &link
->mac
, &link
->lldp
);
2019 r
= sd_lldp_attach_event(link
->lldp
, NULL
, 0);
2023 r
= sd_lldp_set_callback(link
->lldp
,
2024 lldp_handler
, link
);
2029 if (link_has_carrier(link
)) {
2030 r
= link_acquire_conf(link
);
2035 return link_enter_join_netdev(link
);
2038 static int link_initialized_and_synced(sd_netlink
*rtnl
, sd_netlink_message
*m
,
2040 _cleanup_link_unref_ Link
*link
= userdata
;
2045 assert(link
->ifname
);
2046 assert(link
->manager
);
2048 if (link
->state
!= LINK_STATE_PENDING
)
2051 log_link_debug(link
, "Link state is up-to-date");
2053 r
= link_new_bound_by_list(link
);
2057 r
= link_handle_bound_by_list(link
);
2061 if (!link
->network
) {
2062 r
= network_get(link
->manager
, link
->udev_device
, link
->ifname
,
2063 &link
->mac
, &network
);
2065 link_enter_unmanaged(link
);
2070 if (link
->flags
& IFF_LOOPBACK
) {
2071 if (network
->link_local
!= ADDRESS_FAMILY_NO
)
2072 log_link_debug(link
, "Ignoring link-local autoconfiguration for loopback link");
2074 if (network
->dhcp
!= ADDRESS_FAMILY_NO
)
2075 log_link_debug(link
, "Ignoring DHCP clients for loopback link");
2077 if (network
->dhcp_server
)
2078 log_link_debug(link
, "Ignoring DHCP server for loopback link");
2081 r
= network_apply(link
->manager
, network
, link
);
2086 r
= link_new_bound_to_list(link
);
2090 r
= link_configure(link
);
2097 int link_initialized(Link
*link
, struct udev_device
*device
) {
2098 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
;
2102 assert(link
->manager
);
2103 assert(link
->manager
->rtnl
);
2106 if (link
->state
!= LINK_STATE_PENDING
)
2109 if (link
->udev_device
)
2112 log_link_debug(link
, "udev initialized link");
2114 link
->udev_device
= udev_device_ref(device
);
2116 /* udev has initialized the link, but we don't know if we have yet
2117 * processed the NEWLINK messages with the latest state. Do a GETLINK,
2118 * when it returns we know that the pending NEWLINKs have already been
2119 * processed and that we are up-to-date */
2121 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &req
, RTM_GETLINK
,
2126 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
,
2127 link_initialized_and_synced
, link
, 0, NULL
);
2136 static int link_load(Link
*link
) {
2137 _cleanup_free_
char *network_file
= NULL
,
2140 *dhcp4_address
= NULL
,
2141 *ipv4ll_address
= NULL
;
2142 union in_addr_union address
;
2143 union in_addr_union route_dst
;
2149 r
= parse_env_file(link
->state_file
, NEWLINE
,
2150 "NETWORK_FILE", &network_file
,
2151 "ADDRESSES", &addresses
,
2153 "DHCP4_ADDRESS", &dhcp4_address
,
2154 "IPV4LL_ADDRESS", &ipv4ll_address
,
2156 if (r
< 0 && r
!= -ENOENT
)
2157 return log_link_error_errno(link
, r
, "Failed to read %s: %m", link
->state_file
);
2164 suffix
= strrchr(network_file
, '.');
2166 log_link_debug(link
, "Failed to get network name from %s", network_file
);
2167 goto network_file_fail
;
2171 r
= network_get_by_name(link
->manager
, basename(network_file
), &network
);
2173 log_link_debug_errno(link
, r
, "Failed to get network %s: %m", basename(network_file
));
2174 goto network_file_fail
;
2177 r
= network_apply(link
->manager
, network
, link
);
2179 return log_link_error_errno(link
, r
, "Failed to apply network %s: %m", basename(network_file
));
2188 _cleanup_free_
char *address_str
= NULL
;
2189 char *prefixlen_str
;
2191 unsigned char prefixlen
;
2193 r
= extract_first_word(&p
, &address_str
, NULL
, 0);
2195 log_link_debug_errno(link
, r
, "Failed to extract next address string: %m");
2200 prefixlen_str
= strchr(address_str
, '/');
2201 if (!prefixlen_str
) {
2202 log_link_debug(link
, "Failed to parse address and prefix length %s", address_str
);
2206 *prefixlen_str
++ = '\0';
2208 r
= sscanf(prefixlen_str
, "%hhu", &prefixlen
);
2210 log_link_error(link
, "Failed to parse prefixlen %s", prefixlen_str
);
2214 r
= in_addr_from_string_auto(address_str
, &family
, &address
);
2216 log_link_debug_errno(link
, r
, "Failed to parse address %s: %m", address_str
);
2220 r
= address_add(link
, family
, &address
, prefixlen
, NULL
);
2222 return log_link_error_errno(link
, r
, "Failed to add address: %m");
2229 _cleanup_free_
char *route_str
= NULL
;
2230 _cleanup_event_source_unref_ sd_event_source
*expire
= NULL
;
2232 char *prefixlen_str
;
2234 unsigned char prefixlen
, tos
, table
;
2237 r
= extract_first_word(&p
, &route_str
, NULL
, 0);
2239 log_link_debug_errno(link
, r
, "Failed to extract next route string: %m");
2244 prefixlen_str
= strchr(route_str
, '/');
2245 if (!prefixlen_str
) {
2246 log_link_debug(link
, "Failed to parse route %s", route_str
);
2250 *prefixlen_str
++ = '\0';
2252 r
= sscanf(prefixlen_str
, "%hhu/%hhu/%"SCNu32
"/%hhu/"USEC_FMT
, &prefixlen
, &tos
, &priority
, &table
, &lifetime
);
2254 log_link_debug(link
,
2255 "Failed to parse destination prefix length, tos, priority, table or expiration %s",
2260 r
= in_addr_from_string_auto(route_str
, &family
, &route_dst
);
2262 log_link_debug_errno(link
, r
, "Failed to parse route destination %s: %m", route_str
);
2266 r
= route_add(link
, family
, &route_dst
, prefixlen
, tos
, priority
, table
, &route
);
2268 return log_link_error_errno(link
, r
, "Failed to add route: %m");
2270 if (lifetime
!= USEC_INFINITY
) {
2271 r
= sd_event_add_time(link
->manager
->event
, &expire
, clock_boottime_or_monotonic(), lifetime
,
2272 0, route_expire_handler
, route
);
2274 log_link_warning_errno(link
, r
, "Could not arm route expiration handler: %m");
2277 route
->lifetime
= lifetime
;
2278 sd_event_source_unref(route
->expire
);
2279 route
->expire
= expire
;
2284 if (dhcp4_address
) {
2285 r
= in_addr_from_string(AF_INET
, dhcp4_address
, &address
);
2287 log_link_debug_errno(link
, r
, "Falied to parse DHCPv4 address %s: %m", dhcp4_address
);
2288 goto dhcp4_address_fail
;
2291 r
= sd_dhcp_client_new(&link
->dhcp_client
);
2293 return log_link_error_errno(link
, r
, "Falied to create DHCPv4 client: %m");
2295 r
= sd_dhcp_client_set_request_address(link
->dhcp_client
, &address
.in
);
2297 return log_link_error_errno(link
, r
, "Falied to set inital DHCPv4 address %s: %m", dhcp4_address
);
2302 if (ipv4ll_address
) {
2303 r
= in_addr_from_string(AF_INET
, ipv4ll_address
, &address
);
2305 log_link_debug_errno(link
, r
, "Falied to parse IPv4LL address %s: %m", ipv4ll_address
);
2306 goto ipv4ll_address_fail
;
2309 r
= sd_ipv4ll_new(&link
->ipv4ll
);
2311 return log_link_error_errno(link
, r
, "Falied to create IPv4LL client: %m");
2313 r
= sd_ipv4ll_set_address(link
->ipv4ll
, &address
.in
);
2315 return log_link_error_errno(link
, r
, "Falied to set inital IPv4LL address %s: %m", ipv4ll_address
);
2318 ipv4ll_address_fail
:
2323 int link_add(Manager
*m
, sd_netlink_message
*message
, Link
**ret
) {
2325 _cleanup_udev_device_unref_
struct udev_device
*device
= NULL
;
2326 char ifindex_str
[2 + DECIMAL_STR_MAX(int)];
2334 r
= link_new(m
, message
, ret
);
2340 log_link_debug(link
, "Link %d added", link
->ifindex
);
2342 r
= link_load(link
);
2346 if (detect_container() <= 0) {
2347 /* not in a container, udev will be around */
2348 sprintf(ifindex_str
, "n%d", link
->ifindex
);
2349 device
= udev_device_new_from_device_id(m
->udev
, ifindex_str
);
2351 r
= log_link_warning_errno(link
, errno
, "Could not find udev device: %m");
2355 if (udev_device_get_is_initialized(device
) <= 0) {
2357 log_link_debug(link
, "link pending udev initialization...");
2361 r
= link_initialized(link
, device
);
2365 /* we are calling a callback directly, so must take a ref */
2368 r
= link_initialized_and_synced(m
->rtnl
, NULL
, link
);
2375 link_enter_failed(link
);
2379 static int link_carrier_gained(Link
*link
) {
2384 if (link
->network
) {
2385 r
= link_acquire_conf(link
);
2387 link_enter_failed(link
);
2392 r
= link_handle_bound_by_list(link
);
2399 static int link_carrier_lost(Link
*link
) {
2404 r
= link_stop_clients(link
);
2406 link_enter_failed(link
);
2410 r
= link_handle_bound_by_list(link
);
2417 int link_carrier_reset(Link
*link
) {
2422 if (link_has_carrier(link
)) {
2423 r
= link_carrier_lost(link
);
2427 r
= link_carrier_gained(link
);
2431 log_link_info(link
, "Reset carrier");
2438 int link_update(Link
*link
, sd_netlink_message
*m
) {
2439 struct ether_addr mac
;
2442 bool had_carrier
, carrier_gained
, carrier_lost
;
2446 assert(link
->ifname
);
2449 if (link
->state
== LINK_STATE_LINGER
) {
2451 log_link_info(link
, "Link readded");
2452 link_set_state(link
, LINK_STATE_ENSLAVING
);
2454 r
= link_new_carrier_maps(link
);
2459 r
= sd_netlink_message_read_string(m
, IFLA_IFNAME
, &ifname
);
2460 if (r
>= 0 && !streq(ifname
, link
->ifname
)) {
2461 log_link_info(link
, "Renamed to %s", ifname
);
2463 link_free_carrier_maps(link
);
2465 r
= free_and_strdup(&link
->ifname
, ifname
);
2469 r
= link_new_carrier_maps(link
);
2474 r
= sd_netlink_message_read_u32(m
, IFLA_MTU
, &mtu
);
2475 if (r
>= 0 && mtu
> 0) {
2477 if (!link
->original_mtu
) {
2478 link
->original_mtu
= mtu
;
2479 log_link_debug(link
, "Saved original MTU: %" PRIu32
, link
->original_mtu
);
2482 if (link
->dhcp_client
) {
2483 r
= sd_dhcp_client_set_mtu(link
->dhcp_client
,
2486 log_link_warning_errno(link
, r
, "Could not update MTU in DHCP client: %m");
2492 /* The kernel may broadcast NEWLINK messages without the MAC address
2493 set, simply ignore them. */
2494 r
= sd_netlink_message_read_ether_addr(m
, IFLA_ADDRESS
, &mac
);
2496 if (memcmp(link
->mac
.ether_addr_octet
, mac
.ether_addr_octet
,
2499 memcpy(link
->mac
.ether_addr_octet
, mac
.ether_addr_octet
,
2502 log_link_debug(link
, "MAC address: "
2503 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2504 mac
.ether_addr_octet
[0],
2505 mac
.ether_addr_octet
[1],
2506 mac
.ether_addr_octet
[2],
2507 mac
.ether_addr_octet
[3],
2508 mac
.ether_addr_octet
[4],
2509 mac
.ether_addr_octet
[5]);
2512 r
= sd_ipv4ll_set_mac(link
->ipv4ll
, &link
->mac
);
2514 return log_link_warning_errno(link
, r
, "Could not update MAC address in IPv4LL client: %m");
2517 if (link
->dhcp_client
) {
2518 r
= sd_dhcp_client_set_mac(link
->dhcp_client
,
2519 (const uint8_t *) &link
->mac
,
2523 return log_link_warning_errno(link
, r
, "Could not update MAC address in DHCP client: %m");
2526 if (link
->dhcp6_client
) {
2527 r
= sd_dhcp6_client_set_mac(link
->dhcp6_client
,
2528 (const uint8_t *) &link
->mac
,
2532 return log_link_warning_errno(link
, r
, "Could not update MAC address in DHCPv6 client: %m");
2537 had_carrier
= link_has_carrier(link
);
2539 r
= link_update_flags(link
, m
);
2543 carrier_gained
= !had_carrier
&& link_has_carrier(link
);
2544 carrier_lost
= had_carrier
&& !link_has_carrier(link
);
2546 if (carrier_gained
) {
2547 log_link_info(link
, "Gained carrier");
2549 r
= link_carrier_gained(link
);
2552 } else if (carrier_lost
) {
2553 log_link_info(link
, "Lost carrier");
2555 r
= link_carrier_lost(link
);
2564 int link_save(Link
*link
) {
2565 _cleanup_free_
char *temp_path
= NULL
;
2566 _cleanup_fclose_
FILE *f
= NULL
;
2567 const char *admin_state
, *oper_state
;
2574 assert(link
->state_file
);
2575 assert(link
->lease_file
);
2576 assert(link
->manager
);
2578 if (link
->state
== LINK_STATE_LINGER
) {
2579 unlink(link
->state_file
);
2583 admin_state
= link_state_to_string(link
->state
);
2584 assert(admin_state
);
2586 oper_state
= link_operstate_to_string(link
->operstate
);
2589 r
= fopen_temporary(link
->state_file
, &f
, &temp_path
);
2593 fchmod(fileno(f
), 0644);
2596 "# This is private data. Do not parse.\n"
2599 admin_state
, oper_state
);
2601 if (link
->network
) {
2602 char **address
, **domain
;
2604 sd_dhcp6_lease
*dhcp6_lease
= NULL
;
2606 if (link
->dhcp6_client
) {
2607 r
= sd_dhcp6_client_get_lease(link
->dhcp6_client
,
2610 log_link_debug(link
, "No DHCPv6 lease");
2613 fprintf(f
, "NETWORK_FILE=%s\n", link
->network
->filename
);
2617 STRV_FOREACH(address
, link
->network
->dns
) {
2624 if (link
->network
->dhcp_dns
&&
2626 const struct in_addr
*addresses
;
2628 r
= sd_dhcp_lease_get_dns(link
->dhcp_lease
, &addresses
);
2632 serialize_in_addrs(f
, addresses
, r
);
2637 if (link
->network
->dhcp_dns
&& dhcp6_lease
) {
2638 struct in6_addr
*in6_addrs
;
2640 r
= sd_dhcp6_lease_get_dns(dhcp6_lease
, &in6_addrs
);
2644 serialize_in6_addrs(f
, in6_addrs
, r
);
2652 STRV_FOREACH(address
, link
->network
->ntp
) {
2659 if (link
->network
->dhcp_ntp
&&
2661 const struct in_addr
*addresses
;
2663 r
= sd_dhcp_lease_get_ntp(link
->dhcp_lease
, &addresses
);
2667 serialize_in_addrs(f
, addresses
, r
);
2672 if (link
->network
->dhcp_ntp
&& dhcp6_lease
) {
2673 struct in6_addr
*in6_addrs
;
2677 r
= sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease
,
2682 serialize_in6_addrs(f
, in6_addrs
, r
);
2686 r
= sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease
, &hosts
);
2688 STRV_FOREACH(hostname
, hosts
) {
2691 fputs(*hostname
, f
);
2699 fputs("DOMAINS=", f
);
2701 STRV_FOREACH(domain
, link
->network
->domains
) {
2708 if (link
->network
->dhcp_domains
&&
2710 const char *domainname
;
2712 r
= sd_dhcp_lease_get_domainname(link
->dhcp_lease
, &domainname
);
2716 fputs(domainname
, f
);
2721 if (link
->network
->dhcp_domains
&& dhcp6_lease
) {
2724 r
= sd_dhcp6_lease_get_domains(dhcp6_lease
, &domains
);
2726 STRV_FOREACH(domain
, domains
) {
2737 fprintf(f
, "WILDCARD_DOMAIN=%s\n",
2738 yes_no(link
->network
->wildcard_domain
));
2740 fprintf(f
, "LLMNR=%s\n",
2741 resolve_support_to_string(link
->network
->llmnr
));
2743 fputs("ADDRESSES=", f
);
2745 SET_FOREACH(a
, link
->addresses
, i
) {
2746 _cleanup_free_
char *address_str
= NULL
;
2748 r
= in_addr_to_string(a
->family
, &a
->in_addr
, &address_str
);
2752 fprintf(f
, "%s%s/%u", space
? " " : "", address_str
, a
->prefixlen
);
2758 fputs("ROUTES=", f
);
2760 SET_FOREACH(route
, link
->routes
, i
) {
2761 _cleanup_free_
char *route_str
= NULL
;
2763 r
= in_addr_to_string(route
->family
, &route
->dst
, &route_str
);
2767 fprintf(f
, "%s%s/%hhu/%hhu/%"PRIu32
"/%hhu/"USEC_FMT
, space
? " " : "", route_str
,
2768 route
->dst_prefixlen
, route
->tos
, route
->priority
, route
->table
, route
->lifetime
);
2775 if (!hashmap_isempty(link
->bound_to_links
)) {
2779 fputs("CARRIER_BOUND_TO=", f
);
2780 HASHMAP_FOREACH(carrier
, link
->bound_to_links
, i
) {
2783 fputs(carrier
->ifname
, f
);
2790 if (!hashmap_isempty(link
->bound_by_links
)) {
2794 fputs("CARRIER_BOUND_BY=", f
);
2795 HASHMAP_FOREACH(carrier
, link
->bound_by_links
, i
) {
2798 fputs(carrier
->ifname
, f
);
2805 if (link
->dhcp_lease
) {
2806 struct in_addr address
;
2807 const char *tz
= NULL
;
2809 assert(link
->network
);
2811 r
= sd_dhcp_lease_get_timezone(link
->dhcp_lease
, &tz
);
2813 fprintf(f
, "TIMEZONE=%s\n", tz
);
2815 r
= sd_dhcp_lease_get_address(link
->dhcp_lease
, &address
);
2817 fputs("DHCP4_ADDRESS=", f
);
2818 serialize_in_addrs(f
, &address
, 1);
2822 r
= dhcp_lease_save(link
->dhcp_lease
, link
->lease_file
);
2830 unlink(link
->lease_file
);
2833 struct in_addr address
;
2835 r
= sd_ipv4ll_get_address(link
->ipv4ll
, &address
);
2837 fputs("IPV4LL_ADDRESS=", f
);
2838 serialize_in_addrs(f
, &address
, 1);
2844 assert(link
->network
);
2846 r
= sd_lldp_save(link
->lldp
, link
->lldp_file
);
2854 unlink(link
->lldp_file
);
2856 r
= fflush_and_check(f
);
2860 if (rename(temp_path
, link
->state_file
) < 0) {
2868 (void) unlink(link
->state_file
);
2870 (void) unlink(temp_path
);
2872 return log_link_error_errno(link
, r
, "Failed to save link data to %s: %m", link
->state_file
);
2875 /* The serialized state in /run is no longer up-to-date. */
2876 void link_dirty(Link
*link
) {
2881 r
= set_ensure_allocated(&link
->manager
->dirty_links
, NULL
);
2883 /* allocation errors are ignored */
2886 r
= set_put(link
->manager
->dirty_links
, link
);
2888 /* allocation errors are ignored */
2894 /* The serialized state in /run is up-to-date */
2895 void link_clean(Link
*link
) {
2897 assert(link
->manager
);
2899 set_remove(link
->manager
->dirty_links
, link
);
2903 static const char* const link_state_table
[_LINK_STATE_MAX
] = {
2904 [LINK_STATE_PENDING
] = "pending",
2905 [LINK_STATE_ENSLAVING
] = "configuring",
2906 [LINK_STATE_SETTING_ADDRESSES
] = "configuring",
2907 [LINK_STATE_SETTING_ROUTES
] = "configuring",
2908 [LINK_STATE_CONFIGURED
] = "configured",
2909 [LINK_STATE_UNMANAGED
] = "unmanaged",
2910 [LINK_STATE_FAILED
] = "failed",
2911 [LINK_STATE_LINGER
] = "linger",
2914 DEFINE_STRING_TABLE_LOOKUP(link_state
, LinkState
);
2916 static const char* const link_operstate_table
[_LINK_OPERSTATE_MAX
] = {
2917 [LINK_OPERSTATE_OFF
] = "off",
2918 [LINK_OPERSTATE_NO_CARRIER
] = "no-carrier",
2919 [LINK_OPERSTATE_DORMANT
] = "dormant",
2920 [LINK_OPERSTATE_CARRIER
] = "carrier",
2921 [LINK_OPERSTATE_DEGRADED
] = "degraded",
2922 [LINK_OPERSTATE_ROUTABLE
] = "routable",
2925 DEFINE_STRING_TABLE_LOOKUP(link_operstate
, LinkOperationalState
);