1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <netinet/in.h>
8 #include "sd-dhcp6-lease.h"
10 #include "alloc-util.h"
11 #include "dns-domain.h"
12 #include "dns-resolver-internal.h"
13 #include "errno-util.h"
18 #include "network-internal.h"
19 #include "networkd-dhcp-common.h"
20 #include "networkd-link.h"
21 #include "networkd-manager.h"
22 #include "networkd-manager-bus.h"
23 #include "networkd-network.h"
24 #include "networkd-ntp.h"
25 #include "networkd-state-file.h"
26 #include "ordered-set.h"
28 #include "string-util.h"
30 #include "tmpfile-util.h"
32 static int ordered_set_put_dns_servers(OrderedSet
**s
, int ifindex
, struct in_addr_full
**dns
, unsigned n
) {
36 assert(dns
|| n
== 0);
38 FOREACH_ARRAY(a
, dns
, n
) {
41 if ((*a
)->ifindex
!= 0 && (*a
)->ifindex
!= ifindex
)
44 p
= in_addr_full_to_string(*a
);
48 r
= ordered_set_put_strdup(s
, p
);
56 static int ordered_set_put_in4_addrv(
58 const struct in_addr
*addresses
,
60 bool (*predicate
)(const struct in_addr
*addr
)) {
65 assert(n
== 0 || addresses
);
67 FOREACH_ARRAY(a
, addresses
, n
) {
68 if (predicate
&& !predicate(a
))
71 r
= ordered_set_put_strdup(s
, IN4_ADDR_TO_STRING(a
));
79 static int ordered_set_put_in6_addrv(
81 const struct in6_addr
*addresses
,
87 assert(n
== 0 || addresses
);
89 FOREACH_ARRAY(a
, addresses
, n
) {
90 r
= ordered_set_put_strdup(s
, IN6_ADDR_TO_STRING(a
));
98 static int link_put_dns(Link
*link
, OrderedSet
**s
) {
102 assert(link
->network
);
105 if (link
->n_dns
!= UINT_MAX
)
106 return ordered_set_put_dns_servers(s
, link
->ifindex
, link
->dns
, link
->n_dns
);
108 r
= ordered_set_put_dns_servers(s
, link
->ifindex
, link
->network
->dns
, link
->network
->n_dns
);
112 if (link
->dhcp_lease
&& link_get_use_dns(link
, NETWORK_CONFIG_SOURCE_DHCP4
)) {
113 const struct in_addr
*addresses
;
115 r
= sd_dhcp_lease_get_dns(link
->dhcp_lease
, &addresses
);
117 r
= ordered_set_put_in4_addrv(s
, addresses
, r
, in4_addr_is_non_local
);
123 if (link
->dhcp_lease
&& link_get_use_dnr(link
, NETWORK_CONFIG_SOURCE_DHCP4
)) {
124 sd_dns_resolver
*resolvers
;
126 r
= sd_dhcp_lease_get_dnr(link
->dhcp_lease
, &resolvers
);
128 struct in_addr_full
**dot_servers
;
130 CLEANUP_ARRAY(dot_servers
, n
, in_addr_full_array_free
);
132 r
= dns_resolvers_to_dot_addrs(resolvers
, r
, &dot_servers
, &n
);
135 r
= ordered_set_put_dns_servers(s
, link
->ifindex
, dot_servers
, n
);
141 if (link
->dhcp6_lease
&& link_get_use_dns(link
, NETWORK_CONFIG_SOURCE_DHCP6
)) {
142 const struct in6_addr
*addresses
;
144 r
= sd_dhcp6_lease_get_dns(link
->dhcp6_lease
, &addresses
);
146 r
= ordered_set_put_in6_addrv(s
, addresses
, r
);
152 if (link
->dhcp6_lease
&& link_get_use_dnr(link
, NETWORK_CONFIG_SOURCE_DHCP6
)) {
153 sd_dns_resolver
*resolvers
;
155 r
= sd_dhcp6_lease_get_dnr(link
->dhcp6_lease
, &resolvers
);
157 struct in_addr_full
**dot_servers
;
159 CLEANUP_ARRAY(dot_servers
, n
, in_addr_full_array_free
);
161 r
= dns_resolvers_to_dot_addrs(resolvers
, r
, &dot_servers
, &n
);
165 r
= ordered_set_put_dns_servers(s
, link
->ifindex
, dot_servers
, n
);
171 if (link_get_use_dns(link
, NETWORK_CONFIG_SOURCE_NDISC
)) {
174 SET_FOREACH(a
, link
->ndisc_rdnss
) {
175 r
= ordered_set_put_in6_addrv(s
, &a
->address
, 1);
181 if (link_get_use_dnr(link
, NETWORK_CONFIG_SOURCE_NDISC
)) {
184 SET_FOREACH(a
, link
->ndisc_dnr
) {
185 struct in_addr_full
**dot_servers
= NULL
;
187 CLEANUP_ARRAY(dot_servers
, n
, in_addr_full_array_free
);
189 r
= dns_resolvers_to_dot_addrs(&a
->resolver
, 1, &dot_servers
, &n
);
193 r
= ordered_set_put_dns_servers(s
, link
->ifindex
, dot_servers
, n
);
202 static int link_put_ntp(Link
*link
, OrderedSet
**s
) {
206 assert(link
->network
);
210 return ordered_set_put_strdupv(s
, link
->ntp
);
212 r
= ordered_set_put_strdupv(s
, link
->network
->ntp
);
216 if (link
->dhcp_lease
&& link_get_use_ntp(link
, NETWORK_CONFIG_SOURCE_DHCP4
)) {
217 const struct in_addr
*addresses
;
219 r
= sd_dhcp_lease_get_ntp(link
->dhcp_lease
, &addresses
);
221 r
= ordered_set_put_in4_addrv(s
, addresses
, r
, in4_addr_is_non_local
);
227 if (link
->dhcp6_lease
&& link_get_use_ntp(link
, NETWORK_CONFIG_SOURCE_DHCP6
)) {
228 const struct in6_addr
*addresses
;
231 r
= sd_dhcp6_lease_get_ntp_addrs(link
->dhcp6_lease
, &addresses
);
233 r
= ordered_set_put_in6_addrv(s
, addresses
, r
);
238 r
= sd_dhcp6_lease_get_ntp_fqdn(link
->dhcp6_lease
, &fqdn
);
240 r
= ordered_set_put_strdupv(s
, fqdn
);
249 static int link_put_sip(Link
*link
, OrderedSet
**s
) {
253 assert(link
->network
);
256 if (link
->dhcp_lease
&& link
->network
->dhcp_use_sip
) {
257 const struct in_addr
*addresses
;
259 r
= sd_dhcp_lease_get_sip(link
->dhcp_lease
, &addresses
);
261 r
= ordered_set_put_in4_addrv(s
, addresses
, r
, in4_addr_is_non_local
);
270 static int link_put_domains(Link
*link
, bool is_route
, OrderedSet
**s
) {
271 OrderedSet
*link_domains
, *network_domains
;
272 UseDomains use_domains
;
276 assert(link
->network
);
279 link_domains
= is_route
? link
->route_domains
: link
->search_domains
;
280 network_domains
= is_route
? link
->network
->route_domains
: link
->network
->search_domains
;
281 use_domains
= is_route
? USE_DOMAINS_ROUTE
: USE_DOMAINS_YES
;
284 return ordered_set_put_string_set_full(s
, &dns_name_hash_ops_free
, link_domains
);
286 r
= ordered_set_put_string_set_full(s
, &dns_name_hash_ops_free
, network_domains
);
290 if (link
->dhcp_lease
&& link_get_use_domains(link
, NETWORK_CONFIG_SOURCE_DHCP4
) == use_domains
) {
291 const char *domainname
;
294 r
= sd_dhcp_lease_get_domainname(link
->dhcp_lease
, &domainname
);
296 r
= ordered_set_put_strdup_full(s
, &dns_name_hash_ops_free
, domainname
);
301 r
= sd_dhcp_lease_get_search_domains(link
->dhcp_lease
, &domains
);
303 r
= ordered_set_put_strdupv_full(s
, &dns_name_hash_ops_free
, domains
);
309 if (link
->dhcp6_lease
&& link_get_use_domains(link
, NETWORK_CONFIG_SOURCE_DHCP6
) == use_domains
) {
312 r
= sd_dhcp6_lease_get_domains(link
->dhcp6_lease
, &domains
);
314 r
= ordered_set_put_strdupv_full(s
, &dns_name_hash_ops_free
, domains
);
320 if (link_get_use_domains(link
, NETWORK_CONFIG_SOURCE_NDISC
) == use_domains
) {
323 SET_FOREACH(a
, link
->ndisc_dnssl
) {
324 r
= ordered_set_put_strdup_full(s
, &dns_name_hash_ops_free
, ndisc_dnssl_domain(a
));
333 int manager_save(Manager
*m
) {
334 _cleanup_ordered_set_free_ OrderedSet
*dns
= NULL
, *ntp
= NULL
, *sip
= NULL
, *search_domains
= NULL
, *route_domains
= NULL
;
335 const char *operstate_str
, *carrier_state_str
, *address_state_str
, *ipv4_address_state_str
, *ipv6_address_state_str
, *online_state_str
;
336 LinkOperationalState operstate
= LINK_OPERSTATE_OFF
;
337 LinkCarrierState carrier_state
= LINK_CARRIER_STATE_OFF
;
338 LinkAddressState ipv4_address_state
= LINK_ADDRESS_STATE_OFF
, ipv6_address_state
= LINK_ADDRESS_STATE_OFF
,
339 address_state
= LINK_ADDRESS_STATE_OFF
;
340 LinkOnlineState online_state
;
341 size_t links_offline
= 0, links_online
= 0;
346 if (isempty(m
->state_file
))
347 return 0; /* Do not update state file when running in test mode. */
350 HASHMAP_FOREACH(link
, m
->links_by_index
) {
351 if (link
->flags
& IFF_LOOPBACK
)
354 operstate
= MAX(operstate
, link
->operstate
);
355 carrier_state
= MAX(carrier_state
, link
->carrier_state
);
356 address_state
= MAX(address_state
, link
->address_state
);
357 ipv4_address_state
= MAX(ipv4_address_state
, link
->ipv4_address_state
);
358 ipv6_address_state
= MAX(ipv6_address_state
, link
->ipv6_address_state
);
363 if (link
->network
->required_for_online
) {
364 if (link
->online_state
== LINK_ONLINE_STATE_OFFLINE
)
366 else if (link
->online_state
== LINK_ONLINE_STATE_ONLINE
)
370 r
= link_put_dns(link
, &dns
);
374 r
= link_put_ntp(link
, &ntp
);
378 r
= link_put_sip(link
, &sip
);
382 r
= link_put_domains(link
, /* is_route = */ false, &search_domains
);
386 r
= link_put_domains(link
, /* is_route = */ true, &route_domains
);
391 if (carrier_state
>= LINK_CARRIER_STATE_ENSLAVED
)
392 carrier_state
= LINK_CARRIER_STATE_CARRIER
;
394 online_state
= links_online
> 0 ?
395 (links_offline
> 0 ? LINK_ONLINE_STATE_PARTIAL
: LINK_ONLINE_STATE_ONLINE
) :
396 (links_offline
> 0 ? LINK_ONLINE_STATE_OFFLINE
: _LINK_ONLINE_STATE_INVALID
);
398 operstate_str
= ASSERT_PTR(link_operstate_to_string(operstate
));
399 carrier_state_str
= ASSERT_PTR(link_carrier_state_to_string(carrier_state
));
400 address_state_str
= ASSERT_PTR(link_address_state_to_string(address_state
));
401 ipv4_address_state_str
= ASSERT_PTR(link_address_state_to_string(ipv4_address_state
));
402 ipv6_address_state_str
= ASSERT_PTR(link_address_state_to_string(ipv6_address_state
));
404 _cleanup_(unlink_and_freep
) char *temp_path
= NULL
;
405 _cleanup_fclose_
FILE *f
= NULL
;
407 r
= fopen_temporary(m
->state_file
, &f
, &temp_path
);
411 (void) fchmod(fileno(f
), 0644);
414 "# This is private data. Do not parse.\n"
418 "IPV4_ADDRESS_STATE=%s\n"
419 "IPV6_ADDRESS_STATE=%s\n",
420 operstate_str
, carrier_state_str
, address_state_str
, ipv4_address_state_str
, ipv6_address_state_str
);
422 online_state_str
= link_online_state_to_string(online_state
);
423 if (online_state_str
)
424 fprintf(f
, "ONLINE_STATE=%s\n", online_state_str
);
426 ordered_set_print(f
, "DNS=", dns
);
427 ordered_set_print(f
, "NTP=", ntp
);
428 ordered_set_print(f
, "SIP=", sip
);
429 ordered_set_print(f
, "DOMAINS=", search_domains
);
430 ordered_set_print(f
, "ROUTE_DOMAINS=", route_domains
);
432 r
= fflush_and_check(f
);
436 r
= conservative_rename(temp_path
, m
->state_file
);
440 temp_path
= mfree(temp_path
);
442 _cleanup_strv_free_
char **p
= NULL
;
444 if (m
->operational_state
!= operstate
) {
445 m
->operational_state
= operstate
;
446 if (strv_extend(&p
, "OperationalState") < 0)
450 if (m
->carrier_state
!= carrier_state
) {
451 m
->carrier_state
= carrier_state
;
452 if (strv_extend(&p
, "CarrierState") < 0)
456 if (m
->address_state
!= address_state
) {
457 m
->address_state
= address_state
;
458 if (strv_extend(&p
, "AddressState") < 0)
462 if (m
->ipv4_address_state
!= ipv4_address_state
) {
463 m
->ipv4_address_state
= ipv4_address_state
;
464 if (strv_extend(&p
, "IPv4AddressState") < 0)
468 if (m
->ipv6_address_state
!= ipv6_address_state
) {
469 m
->ipv6_address_state
= ipv6_address_state
;
470 if (strv_extend(&p
, "IPv6AddressState") < 0)
474 if (m
->online_state
!= online_state
) {
475 m
->online_state
= online_state
;
476 if (strv_extend(&p
, "OnlineState") < 0)
481 r
= manager_send_changed_strv(m
, p
);
483 log_warning_errno(r
, "Could not emit changed properties, ignoring: %m");
491 static void print_link_hashmap(FILE *f
, const char *prefix
, Hashmap
* h
) {
498 if (hashmap_isempty(h
))
502 HASHMAP_FOREACH(link
, h
) {
506 fprintf(f
, "%i", link
->ifindex
);
513 static void link_save_dns(Link
*link
, FILE *f
, struct in_addr_full
**dns
, unsigned n_dns
, bool *space
) {
519 for (unsigned j
= 0; j
< n_dns
; j
++) {
522 if (dns
[j
]->ifindex
!= 0 && dns
[j
]->ifindex
!= link
->ifindex
)
525 str
= in_addr_full_to_string(dns
[j
]);
536 static void serialize_addresses(
541 sd_dhcp_lease
*lease
,
543 sd_dhcp_lease_server_type_t what
,
544 sd_dhcp6_lease
*lease6
,
546 int (*lease6_get_addr
)(sd_dhcp6_lease
*, const struct in6_addr
**),
547 int (*lease6_get_fqdn
)(sd_dhcp6_lease
*, char ***)) {
556 fprintf(f
, "%s=", lvalue
);
557 fputstrv(f
, addresses
, NULL
, space
);
559 if (lease
&& conditional
) {
560 const struct in_addr
*lease_addresses
;
562 r
= sd_dhcp_lease_get_servers(lease
, what
, &lease_addresses
);
564 serialize_in_addrs(f
, lease_addresses
, r
, space
, in4_addr_is_non_local
);
567 if (lease6
&& conditional6
&& lease6_get_addr
) {
568 const struct in6_addr
*in6_addrs
;
570 r
= lease6_get_addr(lease6
, &in6_addrs
);
572 serialize_in6_addrs(f
, in6_addrs
, r
, space
);
575 if (lease6
&& conditional6
&& lease6_get_fqdn
) {
578 r
= lease6_get_fqdn(lease6
, &in6_hosts
);
580 fputstrv(f
, in6_hosts
, NULL
, space
);
587 static void serialize_resolvers(
591 sd_dhcp_lease
*lease
,
593 sd_dhcp6_lease
*lease6
,
601 fprintf(f
, "%s=", lvalue
);
603 if (lease
&& conditional
) {
604 sd_dns_resolver
*resolvers
;
605 _cleanup_strv_free_
char **names
= NULL
;
608 r
= sd_dhcp_lease_get_dnr(lease
, &resolvers
);
609 if (r
< 0 && r
!= -ENODATA
)
610 log_warning_errno(r
, "Failed to get DNR from DHCP lease, ignoring: %m");
613 r
= dns_resolvers_to_dot_strv(resolvers
, r
, &names
);
615 return (void) log_warning_errno(r
, "Failed to get DoT servers from DHCP DNR, ignoring: %m");
617 fputstrv(f
, names
, NULL
, space
);
621 if (lease6
&& conditional6
) {
622 sd_dns_resolver
*resolvers
;
623 _cleanup_strv_free_
char **names
= NULL
;
626 r
= sd_dhcp6_lease_get_dnr(lease6
, &resolvers
);
627 if (r
< 0 && r
!= -ENODATA
)
628 log_warning_errno(r
, "Failed to get DNR from DHCPv6 lease, ignoring: %m");
631 r
= dns_resolvers_to_dot_strv(resolvers
, r
, &names
);
633 return (void) log_warning_errno(r
, "Failed to get DoT servers from DHCPv6 DNR, ignoring: %m");
635 fputstrv(f
, names
, NULL
, space
);
645 static void link_save_domains(Link
*link
, FILE *f
, OrderedSet
*static_domains
, UseDomains use_domains
) {
650 assert(link
->network
);
653 ORDERED_SET_FOREACH(p
, static_domains
)
654 fputs_with_separator(f
, p
, NULL
, &space
);
656 if (use_domains
== USE_DOMAINS_NO
)
659 if (link
->dhcp_lease
&& link_get_use_domains(link
, NETWORK_CONFIG_SOURCE_DHCP4
) == use_domains
) {
660 const char *domainname
;
663 if (sd_dhcp_lease_get_domainname(link
->dhcp_lease
, &domainname
) >= 0)
664 fputs_with_separator(f
, domainname
, NULL
, &space
);
665 if (sd_dhcp_lease_get_search_domains(link
->dhcp_lease
, &domains
) >= 0)
666 fputstrv(f
, domains
, NULL
, &space
);
669 if (link
->dhcp6_lease
&& link_get_use_domains(link
, NETWORK_CONFIG_SOURCE_DHCP6
) == use_domains
) {
672 if (sd_dhcp6_lease_get_domains(link
->dhcp6_lease
, &domains
) >= 0)
673 fputstrv(f
, domains
, NULL
, &space
);
676 if (link_get_use_domains(link
, NETWORK_CONFIG_SOURCE_NDISC
) == use_domains
) {
679 SET_FOREACH(dd
, link
->ndisc_dnssl
)
680 fputs_with_separator(f
, ndisc_dnssl_domain(dd
), NULL
, &space
);
684 static int serialize_config_files(FILE *f
, const char *prefix
, const char *main_config
, char * const *dropins
) {
689 fprintf(f
, "%s_FILE=%s\n", prefix
, main_config
);
693 fprintf(f
, "%s_FILE_DROPINS=\"", prefix
);
694 STRV_FOREACH(d
, dropins
) {
695 _cleanup_free_
char *escaped
= NULL
;
697 escaped
= xescape(*d
, ":");
701 fputs_with_separator(f
, escaped
, ":", &space
);
708 static int link_save(Link
*link
) {
709 const char *admin_state
, *oper_state
, *carrier_state
, *address_state
, *ipv4_address_state
, *ipv6_address_state
;
710 _cleanup_(unlink_and_freep
) char *temp_path
= NULL
;
711 _cleanup_fclose_
FILE *f
= NULL
;
715 assert(link
->manager
);
717 if (isempty(link
->state_file
))
718 return 0; /* Do not update state files when running in test mode. */
720 if (link
->state
== LINK_STATE_LINGER
)
723 admin_state
= ASSERT_PTR(link_state_to_string(link
->state
));
724 oper_state
= ASSERT_PTR(link_operstate_to_string(link
->operstate
));
725 carrier_state
= ASSERT_PTR(link_carrier_state_to_string(link
->carrier_state
));
726 address_state
= ASSERT_PTR(link_address_state_to_string(link
->address_state
));
727 ipv4_address_state
= ASSERT_PTR(link_address_state_to_string(link
->ipv4_address_state
));
728 ipv6_address_state
= ASSERT_PTR(link_address_state_to_string(link
->ipv6_address_state
));
730 r
= fopen_temporary(link
->state_file
, &f
, &temp_path
);
734 (void) fchmod(fileno(f
), 0644);
737 "# This is private data. Do not parse.\n"
742 "IPV4_ADDRESS_STATE=%s\n"
743 "IPV6_ADDRESS_STATE=%s\n",
744 admin_state
, oper_state
, carrier_state
, address_state
, ipv4_address_state
, ipv6_address_state
);
747 r
= serialize_config_files(f
, "NETDEV", link
->netdev
->filename
, link
->netdev
->dropins
);
753 const char *online_state
, *captive_portal
;
756 online_state
= link_online_state_to_string(link
->online_state
);
758 fprintf(f
, "ONLINE_STATE=%s\n", online_state
);
760 fprintf(f
, "REQUIRED_FOR_ONLINE=%s\n",
761 yes_no(link
->network
->required_for_online
));
763 LinkOperationalStateRange st
;
764 link_required_operstate_for_online(link
, &st
);
766 fprintf(f
, "REQUIRED_OPER_STATE_FOR_ONLINE=%s:%s\n",
767 link_operstate_to_string(st
.min
), link_operstate_to_string(st
.max
));
769 fprintf(f
, "REQUIRED_FAMILY_FOR_ONLINE=%s\n",
770 link_required_address_family_to_string(link_required_family_for_online(link
)));
772 fprintf(f
, "ACTIVATION_POLICY=%s\n",
773 activation_policy_to_string(link
->network
->activation_policy
));
775 r
= serialize_config_files(f
, "NETWORK", link
->network
->filename
, link
->network
->dropins
);
779 /************************************************************/
782 if (link
->n_dns
!= UINT_MAX
)
783 link_save_dns(link
, f
, link
->dns
, link
->n_dns
, NULL
);
786 link_save_dns(link
, f
, link
->network
->dns
, link
->network
->n_dns
, &space
);
788 /* DNR resolvers are not required to provide Do53 service, however resolved doesn't
789 * know how to handle such a server so for now Do53 service is required, and
791 serialize_resolvers(f
, NULL
, &space
,
793 link_get_use_dnr(link
, NETWORK_CONFIG_SOURCE_DHCP4
),
795 link_get_use_dnr(link
, NETWORK_CONFIG_SOURCE_DHCP6
));
797 if (link_get_use_dnr(link
, NETWORK_CONFIG_SOURCE_NDISC
)) {
799 SET_FOREACH(dnr
, link
->ndisc_dnr
)
800 serialize_dnr(f
, &dnr
->resolver
, 1, &space
);
803 serialize_addresses(f
, NULL
, &space
,
806 link_get_use_dns(link
, NETWORK_CONFIG_SOURCE_DHCP4
),
809 link_get_use_dns(link
, NETWORK_CONFIG_SOURCE_DHCP6
),
810 sd_dhcp6_lease_get_dns
,
813 if (link_get_use_dns(link
, NETWORK_CONFIG_SOURCE_NDISC
)) {
816 SET_FOREACH(dd
, link
->ndisc_rdnss
)
817 serialize_in6_addrs(f
, &dd
->address
, 1, &space
);
823 /************************************************************/
827 fputstrv(f
, link
->ntp
, NULL
, NULL
);
830 serialize_addresses(f
, "NTP", NULL
,
833 link_get_use_ntp(link
, NETWORK_CONFIG_SOURCE_DHCP4
),
836 link_get_use_ntp(link
, NETWORK_CONFIG_SOURCE_DHCP6
),
837 sd_dhcp6_lease_get_ntp_addrs
,
838 sd_dhcp6_lease_get_ntp_fqdn
);
840 serialize_addresses(f
, "SIP", NULL
,
843 link
->network
->dhcp_use_sip
,
845 NULL
, false, NULL
, NULL
);
847 /************************************************************/
849 r
= link_get_captive_portal(link
, &captive_portal
);
854 fprintf(f
, "CAPTIVE_PORTAL=%s\n", captive_portal
);
856 /************************************************************/
858 fputs("DOMAINS=", f
);
859 if (link
->search_domains
)
860 link_save_domains(link
, f
, link
->search_domains
, USE_DOMAINS_NO
);
862 link_save_domains(link
, f
, link
->network
->search_domains
, USE_DOMAINS_YES
);
865 /************************************************************/
867 fputs("ROUTE_DOMAINS=", f
);
868 if (link
->route_domains
)
869 link_save_domains(link
, f
, link
->route_domains
, USE_DOMAINS_NO
);
871 link_save_domains(link
, f
, link
->network
->route_domains
, USE_DOMAINS_ROUTE
);
874 /************************************************************/
876 fprintf(f
, "LLMNR=%s\n",
877 resolve_support_to_string(link
->llmnr
>= 0 ? link
->llmnr
: link
->network
->llmnr
));
879 /************************************************************/
881 fprintf(f
, "MDNS=%s\n",
882 resolve_support_to_string(link
->mdns
>= 0 ? link
->mdns
: link
->network
->mdns
));
884 /************************************************************/
886 int dns_default_route
=
887 link
->dns_default_route
>= 0 ? link
->dns_default_route
:
888 link
->network
->dns_default_route
;
889 if (dns_default_route
>= 0)
890 fprintf(f
, "DNS_DEFAULT_ROUTE=%s\n", yes_no(dns_default_route
));
892 /************************************************************/
894 DnsOverTlsMode dns_over_tls_mode
=
895 link
->dns_over_tls_mode
!= _DNS_OVER_TLS_MODE_INVALID
? link
->dns_over_tls_mode
:
896 link
->network
->dns_over_tls_mode
;
897 if (dns_over_tls_mode
!= _DNS_OVER_TLS_MODE_INVALID
)
898 fprintf(f
, "DNS_OVER_TLS=%s\n", dns_over_tls_mode_to_string(dns_over_tls_mode
));
900 /************************************************************/
902 DnssecMode dnssec_mode
=
903 link
->dnssec_mode
!= _DNSSEC_MODE_INVALID
? link
->dnssec_mode
:
904 link
->network
->dnssec_mode
;
905 if (dnssec_mode
!= _DNSSEC_MODE_INVALID
)
906 fprintf(f
, "DNSSEC=%s\n", dnssec_mode_to_string(dnssec_mode
));
908 /************************************************************/
910 Set
*nta_anchors
= link
->dnssec_negative_trust_anchors
;
911 if (set_isempty(nta_anchors
))
912 nta_anchors
= link
->network
->dnssec_negative_trust_anchors
;
914 if (!set_isempty(nta_anchors
)) {
919 fputs("DNSSEC_NTA=", f
);
920 SET_FOREACH(n
, nta_anchors
)
921 fputs_with_separator(f
, n
, NULL
, &space
);
926 print_link_hashmap(f
, "CARRIER_BOUND_TO=", link
->bound_to_links
);
927 print_link_hashmap(f
, "CARRIER_BOUND_BY=", link
->bound_by_links
);
929 if (link
->dhcp_lease
) {
930 r
= dhcp_lease_save(link
->dhcp_lease
, link
->lease_file
);
934 fprintf(f
, "DHCP_LEASE=%s\n", link
->lease_file
);
936 (void) unlink(link
->lease_file
);
938 r
= link_serialize_dhcp6_client(link
, f
);
942 r
= fflush_and_check(f
);
946 r
= conservative_rename(temp_path
, link
->state_file
);
950 temp_path
= mfree(temp_path
);
955 void link_dirty(Link
*link
) {
957 assert(link
->manager
);
959 /* When the manager is in MANAGER_STOPPED, it is not necessary to update state files anymore, as they
960 * will be removed soon anyway. Moreover, we cannot call link_ref() in that case. */
961 if (link
->manager
->state
== MANAGER_STOPPED
)
964 /* The serialized state in /run is no longer up-to-date. */
966 /* Also mark manager dirty as link is dirty */
967 link
->manager
->dirty
= true;
969 if (set_ensure_put(&link
->manager
->dirty_links
, &link_hash_ops
, link
) <= 0)
970 return; /* Ignore allocation errors and don't take another ref if the link was already dirty */
975 void link_clean(Link
*link
) {
977 assert(link
->manager
);
979 /* The serialized state in /run is up-to-date */
981 link_unref(set_remove(link
->manager
->dirty_links
, link
));
984 int link_save_and_clean_full(Link
*link
, bool also_save_manager
) {
988 assert(link
->manager
);
990 if (also_save_manager
)
991 k
= manager_save(link
->manager
);
1001 int manager_clean_all(Manager
*manager
) {
1006 if (manager
->dirty
) {
1007 r
= manager_save(manager
);
1009 log_warning_errno(r
, "Failed to update state file %s, ignoring: %m", manager
->state_file
);
1014 SET_FOREACH(link
, manager
->dirty_links
) {
1015 r
= link_save_and_clean(link
);
1017 log_link_warning_errno(link
, r
, "Failed to update link state file %s, ignoring: %m", link
->state_file
);