1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <netinet/in.h>
6 #include "alloc-util.h"
7 #include "dns-domain.h"
12 #include "network-internal.h"
13 #include "networkd-dhcp-common.h"
14 #include "networkd-link.h"
15 #include "networkd-manager-bus.h"
16 #include "networkd-manager.h"
17 #include "networkd-network.h"
18 #include "networkd-state-file.h"
19 #include "ordered-set.h"
22 #include "tmpfile-util.h"
24 static int ordered_set_put_dns_servers(OrderedSet
**s
, int ifindex
, struct in_addr_full
**dns
, unsigned n
) {
28 assert(dns
|| n
== 0);
30 FOREACH_ARRAY(a
, dns
, n
) {
33 if ((*a
)->ifindex
!= 0 && (*a
)->ifindex
!= ifindex
)
36 p
= in_addr_full_to_string(*a
);
40 r
= ordered_set_put_strdup(s
, p
);
48 static int ordered_set_put_in4_addrv(
50 const struct in_addr
*addresses
,
52 bool (*predicate
)(const struct in_addr
*addr
)) {
57 assert(n
== 0 || addresses
);
59 FOREACH_ARRAY(a
, addresses
, n
) {
60 if (predicate
&& !predicate(a
))
63 r
= ordered_set_put_strdup(s
, IN4_ADDR_TO_STRING(a
));
71 static int ordered_set_put_in6_addrv(
73 const struct in6_addr
*addresses
,
79 assert(n
== 0 || addresses
);
81 FOREACH_ARRAY(a
, addresses
, n
) {
82 r
= ordered_set_put_strdup(s
, IN6_ADDR_TO_STRING(a
));
90 static int link_put_dns(Link
*link
, OrderedSet
**s
) {
94 assert(link
->network
);
97 if (link
->n_dns
!= UINT_MAX
)
98 return ordered_set_put_dns_servers(s
, link
->ifindex
, link
->dns
, link
->n_dns
);
100 r
= ordered_set_put_dns_servers(s
, link
->ifindex
, link
->network
->dns
, link
->network
->n_dns
);
104 if (link
->dhcp_lease
&& link
->network
->dhcp_use_dns
) {
105 const struct in_addr
*addresses
;
107 r
= sd_dhcp_lease_get_dns(link
->dhcp_lease
, &addresses
);
109 r
= ordered_set_put_in4_addrv(s
, addresses
, r
, in4_addr_is_non_local
);
115 if (link
->dhcp6_lease
&& link
->network
->dhcp6_use_dns
) {
116 const struct in6_addr
*addresses
;
118 r
= sd_dhcp6_lease_get_dns(link
->dhcp6_lease
, &addresses
);
120 r
= ordered_set_put_in6_addrv(s
, addresses
, r
);
126 if (link
->network
->ipv6_accept_ra_use_dns
) {
129 SET_FOREACH(a
, link
->ndisc_rdnss
) {
130 r
= ordered_set_put_in6_addrv(s
, &a
->router
, 1);
139 static int link_put_ntp(Link
*link
, OrderedSet
**s
) {
143 assert(link
->network
);
147 return ordered_set_put_strdupv(s
, link
->ntp
);
149 r
= ordered_set_put_strdupv(s
, link
->network
->ntp
);
153 if (link
->dhcp_lease
&& link
->network
->dhcp_use_ntp
) {
154 const struct in_addr
*addresses
;
156 r
= sd_dhcp_lease_get_ntp(link
->dhcp_lease
, &addresses
);
158 r
= ordered_set_put_in4_addrv(s
, addresses
, r
, in4_addr_is_non_local
);
164 if (link
->dhcp6_lease
&& link
->network
->dhcp6_use_ntp
) {
165 const struct in6_addr
*addresses
;
168 r
= sd_dhcp6_lease_get_ntp_addrs(link
->dhcp6_lease
, &addresses
);
170 r
= ordered_set_put_in6_addrv(s
, addresses
, r
);
175 r
= sd_dhcp6_lease_get_ntp_fqdn(link
->dhcp6_lease
, &fqdn
);
177 r
= ordered_set_put_strdupv(s
, fqdn
);
186 static int link_put_sip(Link
*link
, OrderedSet
**s
) {
190 assert(link
->network
);
193 if (link
->dhcp_lease
&& link
->network
->dhcp_use_ntp
) {
194 const struct in_addr
*addresses
;
196 r
= sd_dhcp_lease_get_sip(link
->dhcp_lease
, &addresses
);
198 r
= ordered_set_put_in4_addrv(s
, addresses
, r
, in4_addr_is_non_local
);
207 static int link_put_domains(Link
*link
, bool is_route
, OrderedSet
**s
) {
208 OrderedSet
*link_domains
, *network_domains
;
209 DHCPUseDomains use_domains
;
213 assert(link
->network
);
216 link_domains
= is_route
? link
->route_domains
: link
->search_domains
;
217 network_domains
= is_route
? link
->network
->route_domains
: link
->network
->search_domains
;
218 use_domains
= is_route
? DHCP_USE_DOMAINS_ROUTE
: DHCP_USE_DOMAINS_YES
;
221 return ordered_set_put_string_set(s
, link_domains
);
223 r
= ordered_set_put_string_set(s
, network_domains
);
227 if (link
->dhcp_lease
&& link
->network
->dhcp_use_domains
== use_domains
) {
228 const char *domainname
;
231 r
= sd_dhcp_lease_get_domainname(link
->dhcp_lease
, &domainname
);
233 r
= ordered_set_put_strdup(s
, domainname
);
238 r
= sd_dhcp_lease_get_search_domains(link
->dhcp_lease
, &domains
);
240 r
= ordered_set_put_strdupv(s
, domains
);
246 if (link
->dhcp6_lease
&& link
->network
->dhcp6_use_domains
== use_domains
) {
249 r
= sd_dhcp6_lease_get_domains(link
->dhcp6_lease
, &domains
);
251 r
= ordered_set_put_strdupv(s
, domains
);
257 if (link
->network
->ipv6_accept_ra_use_domains
== use_domains
) {
260 SET_FOREACH(a
, link
->ndisc_dnssl
) {
261 r
= ordered_set_put_strdup(s
, NDISC_DNSSL_DOMAIN(a
));
270 int manager_save(Manager
*m
) {
271 _cleanup_ordered_set_free_ OrderedSet
*dns
= NULL
, *ntp
= NULL
, *sip
= NULL
, *search_domains
= NULL
, *route_domains
= NULL
;
272 const char *operstate_str
, *carrier_state_str
, *address_state_str
, *ipv4_address_state_str
, *ipv6_address_state_str
, *online_state_str
;
273 LinkOperationalState operstate
= LINK_OPERSTATE_OFF
;
274 LinkCarrierState carrier_state
= LINK_CARRIER_STATE_OFF
;
275 LinkAddressState ipv4_address_state
= LINK_ADDRESS_STATE_OFF
, ipv6_address_state
= LINK_ADDRESS_STATE_OFF
,
276 address_state
= LINK_ADDRESS_STATE_OFF
;
277 LinkOnlineState online_state
;
278 size_t links_offline
= 0, links_online
= 0;
279 _cleanup_(unlink_and_freep
) char *temp_path
= NULL
;
280 _cleanup_strv_free_
char **p
= NULL
;
281 _cleanup_fclose_
FILE *f
= NULL
;
287 if (isempty(m
->state_file
))
288 return 0; /* Do not update state file when running in test mode. */
290 HASHMAP_FOREACH(link
, m
->links_by_index
) {
291 if (link
->flags
& IFF_LOOPBACK
)
294 operstate
= MAX(operstate
, link
->operstate
);
295 carrier_state
= MAX(carrier_state
, link
->carrier_state
);
296 address_state
= MAX(address_state
, link
->address_state
);
297 ipv4_address_state
= MAX(ipv4_address_state
, link
->ipv4_address_state
);
298 ipv6_address_state
= MAX(ipv6_address_state
, link
->ipv6_address_state
);
303 if (link
->network
->required_for_online
) {
304 if (link
->online_state
== LINK_ONLINE_STATE_OFFLINE
)
306 else if (link
->online_state
== LINK_ONLINE_STATE_ONLINE
)
310 r
= link_put_dns(link
, &dns
);
314 r
= link_put_ntp(link
, &ntp
);
318 r
= link_put_sip(link
, &sip
);
322 r
= link_put_domains(link
, /* is_route = */ false, &search_domains
);
326 r
= link_put_domains(link
, /* is_route = */ true, &route_domains
);
331 if (carrier_state
>= LINK_CARRIER_STATE_ENSLAVED
)
332 carrier_state
= LINK_CARRIER_STATE_CARRIER
;
334 online_state
= links_online
> 0 ?
335 (links_offline
> 0 ? LINK_ONLINE_STATE_PARTIAL
: LINK_ONLINE_STATE_ONLINE
) :
336 (links_offline
> 0 ? LINK_ONLINE_STATE_OFFLINE
: _LINK_ONLINE_STATE_INVALID
);
338 operstate_str
= link_operstate_to_string(operstate
);
339 assert(operstate_str
);
341 carrier_state_str
= link_carrier_state_to_string(carrier_state
);
342 assert(carrier_state_str
);
344 address_state_str
= link_address_state_to_string(address_state
);
345 assert(address_state_str
);
347 ipv4_address_state_str
= link_address_state_to_string(ipv4_address_state
);
348 assert(ipv4_address_state_str
);
350 ipv6_address_state_str
= link_address_state_to_string(ipv6_address_state
);
351 assert(ipv6_address_state_str
);
353 r
= fopen_temporary(m
->state_file
, &f
, &temp_path
);
357 (void) fchmod(fileno(f
), 0644);
360 "# This is private data. Do not parse.\n"
364 "IPV4_ADDRESS_STATE=%s\n"
365 "IPV6_ADDRESS_STATE=%s\n",
366 operstate_str
, carrier_state_str
, address_state_str
, ipv4_address_state_str
, ipv6_address_state_str
);
368 online_state_str
= link_online_state_to_string(online_state
);
369 if (online_state_str
)
370 fprintf(f
, "ONLINE_STATE=%s\n", online_state_str
);
372 ordered_set_print(f
, "DNS=", dns
);
373 ordered_set_print(f
, "NTP=", ntp
);
374 ordered_set_print(f
, "SIP=", sip
);
375 ordered_set_print(f
, "DOMAINS=", search_domains
);
376 ordered_set_print(f
, "ROUTE_DOMAINS=", route_domains
);
378 r
= fflush_and_check(f
);
382 r
= conservative_rename(temp_path
, m
->state_file
);
386 temp_path
= mfree(temp_path
);
388 if (m
->operational_state
!= operstate
) {
389 m
->operational_state
= operstate
;
390 if (strv_extend(&p
, "OperationalState") < 0)
394 if (m
->carrier_state
!= carrier_state
) {
395 m
->carrier_state
= carrier_state
;
396 if (strv_extend(&p
, "CarrierState") < 0)
400 if (m
->address_state
!= address_state
) {
401 m
->address_state
= address_state
;
402 if (strv_extend(&p
, "AddressState") < 0)
406 if (m
->ipv4_address_state
!= ipv4_address_state
) {
407 m
->ipv4_address_state
= ipv4_address_state
;
408 if (strv_extend(&p
, "IPv4AddressState") < 0)
412 if (m
->ipv6_address_state
!= ipv6_address_state
) {
413 m
->ipv6_address_state
= ipv6_address_state
;
414 if (strv_extend(&p
, "IPv6AddressState") < 0)
418 if (m
->online_state
!= online_state
) {
419 m
->online_state
= online_state
;
420 if (strv_extend(&p
, "OnlineState") < 0)
425 r
= manager_send_changed_strv(m
, p
);
427 log_warning_errno(r
, "Could not emit changed properties, ignoring: %m");
435 static void print_link_hashmap(FILE *f
, const char *prefix
, Hashmap
* h
) {
442 if (hashmap_isempty(h
))
446 HASHMAP_FOREACH(link
, h
) {
450 fprintf(f
, "%i", link
->ifindex
);
457 static void link_save_dns(Link
*link
, FILE *f
, struct in_addr_full
**dns
, unsigned n_dns
, bool *space
) {
463 for (unsigned j
= 0; j
< n_dns
; j
++) {
466 if (dns
[j
]->ifindex
!= 0 && dns
[j
]->ifindex
!= link
->ifindex
)
469 str
= in_addr_full_to_string(dns
[j
]);
480 static void serialize_addresses(
485 sd_dhcp_lease
*lease
,
487 sd_dhcp_lease_server_type_t what
,
488 sd_dhcp6_lease
*lease6
,
490 int (*lease6_get_addr
)(sd_dhcp6_lease
*, const struct in6_addr
**),
491 int (*lease6_get_fqdn
)(sd_dhcp6_lease
*, char ***)) {
500 fprintf(f
, "%s=", lvalue
);
501 fputstrv(f
, addresses
, NULL
, space
);
503 if (lease
&& conditional
) {
504 const struct in_addr
*lease_addresses
;
506 r
= sd_dhcp_lease_get_servers(lease
, what
, &lease_addresses
);
508 serialize_in_addrs(f
, lease_addresses
, r
, space
, in4_addr_is_non_local
);
511 if (lease6
&& conditional6
&& lease6_get_addr
) {
512 const struct in6_addr
*in6_addrs
;
514 r
= lease6_get_addr(lease6
, &in6_addrs
);
516 serialize_in6_addrs(f
, in6_addrs
, r
, space
);
519 if (lease6
&& conditional6
&& lease6_get_fqdn
) {
522 r
= lease6_get_fqdn(lease6
, &in6_hosts
);
524 fputstrv(f
, in6_hosts
, NULL
, space
);
531 static void link_save_domains(Link
*link
, FILE *f
, OrderedSet
*static_domains
, DHCPUseDomains use_domains
) {
536 assert(link
->network
);
539 ORDERED_SET_FOREACH(p
, static_domains
)
540 fputs_with_space(f
, p
, NULL
, &space
);
542 if (use_domains
== DHCP_USE_DOMAINS_NO
)
545 if (link
->dhcp_lease
&& link
->network
->dhcp_use_domains
== use_domains
) {
546 const char *domainname
;
549 if (sd_dhcp_lease_get_domainname(link
->dhcp_lease
, &domainname
) >= 0)
550 fputs_with_space(f
, domainname
, NULL
, &space
);
551 if (sd_dhcp_lease_get_search_domains(link
->dhcp_lease
, &domains
) >= 0)
552 fputstrv(f
, domains
, NULL
, &space
);
555 if (link
->dhcp6_lease
&& link
->network
->dhcp6_use_domains
== use_domains
) {
558 if (sd_dhcp6_lease_get_domains(link
->dhcp6_lease
, &domains
) >= 0)
559 fputstrv(f
, domains
, NULL
, &space
);
562 if (link
->network
->ipv6_accept_ra_use_domains
== use_domains
) {
565 SET_FOREACH(dd
, link
->ndisc_dnssl
)
566 fputs_with_space(f
, NDISC_DNSSL_DOMAIN(dd
), NULL
, &space
);
570 int link_save(Link
*link
) {
571 const char *admin_state
, *oper_state
, *carrier_state
, *address_state
, *ipv4_address_state
, *ipv6_address_state
,
573 _cleanup_(unlink_and_freep
) char *temp_path
= NULL
;
574 _cleanup_fclose_
FILE *f
= NULL
;
578 assert(link
->manager
);
580 if (isempty(link
->state_file
))
581 return 0; /* Do not update state files when running in test mode. */
583 if (link
->state
== LINK_STATE_LINGER
)
586 link_lldp_save(link
);
588 admin_state
= link_state_to_string(link
->state
);
591 oper_state
= link_operstate_to_string(link
->operstate
);
594 carrier_state
= link_carrier_state_to_string(link
->carrier_state
);
595 assert(carrier_state
);
597 address_state
= link_address_state_to_string(link
->address_state
);
598 assert(address_state
);
600 ipv4_address_state
= link_address_state_to_string(link
->ipv4_address_state
);
601 assert(ipv4_address_state
);
603 ipv6_address_state
= link_address_state_to_string(link
->ipv6_address_state
);
604 assert(ipv6_address_state
);
606 r
= fopen_temporary(link
->state_file
, &f
, &temp_path
);
610 (void) fchmod(fileno(f
), 0644);
613 "# This is private data. Do not parse.\n"
618 "IPV4_ADDRESS_STATE=%s\n"
619 "IPV6_ADDRESS_STATE=%s\n",
620 admin_state
, oper_state
, carrier_state
, address_state
, ipv4_address_state
, ipv6_address_state
);
623 const char *online_state
;
626 online_state
= link_online_state_to_string(link
->online_state
);
628 fprintf(f
, "ONLINE_STATE=%s\n", online_state
);
630 fprintf(f
, "REQUIRED_FOR_ONLINE=%s\n",
631 yes_no(link
->network
->required_for_online
));
633 LinkOperationalStateRange st
= link
->network
->required_operstate_for_online
;
634 fprintf(f
, "REQUIRED_OPER_STATE_FOR_ONLINE=%s%s%s\n",
635 strempty(link_operstate_to_string(st
.min
)),
636 st
.max
!= LINK_OPERSTATE_RANGE_DEFAULT
.max
? ":" : "",
637 st
.max
!= LINK_OPERSTATE_RANGE_DEFAULT
.max
? strempty(link_operstate_to_string(st
.max
)) : "");
639 fprintf(f
, "REQUIRED_FAMILY_FOR_ONLINE=%s\n",
640 link_required_address_family_to_string(link
->network
->required_family_for_online
));
642 fprintf(f
, "ACTIVATION_POLICY=%s\n",
643 activation_policy_to_string(link
->network
->activation_policy
));
645 fprintf(f
, "NETWORK_FILE=%s\n", link
->network
->filename
);
647 fputs("NETWORK_FILE_DROPINS=\"", f
);
648 STRV_FOREACH(d
, link
->network
->dropins
) {
649 _cleanup_free_
char *escaped
= NULL
;
651 escaped
= xescape(*d
, ":");
655 fputs_with_space(f
, escaped
, ":", &space
);
659 /************************************************************/
662 if (link
->n_dns
!= UINT_MAX
)
663 link_save_dns(link
, f
, link
->dns
, link
->n_dns
, NULL
);
666 link_save_dns(link
, f
, link
->network
->dns
, link
->network
->n_dns
, &space
);
668 serialize_addresses(f
, NULL
, &space
,
671 link
->network
->dhcp_use_dns
,
674 link
->network
->dhcp6_use_dns
,
675 sd_dhcp6_lease_get_dns
,
678 if (link
->network
->ipv6_accept_ra_use_dns
) {
681 SET_FOREACH(dd
, link
->ndisc_rdnss
)
682 serialize_in6_addrs(f
, &dd
->address
, 1, &space
);
688 /************************************************************/
692 fputstrv(f
, link
->ntp
, NULL
, NULL
);
695 serialize_addresses(f
, "NTP", NULL
,
698 link
->network
->dhcp_use_ntp
,
701 link
->network
->dhcp6_use_ntp
,
702 sd_dhcp6_lease_get_ntp_addrs
,
703 sd_dhcp6_lease_get_ntp_fqdn
);
705 serialize_addresses(f
, "SIP", NULL
,
708 link
->network
->dhcp_use_sip
,
710 NULL
, false, NULL
, NULL
);
712 /************************************************************/
714 r
= link_get_captive_portal(link
, &captive_portal
);
719 fprintf(f
, "CAPTIVE_PORTAL=%s\n", captive_portal
);
721 /************************************************************/
723 fputs("DOMAINS=", f
);
724 if (link
->search_domains
)
725 link_save_domains(link
, f
, link
->search_domains
, DHCP_USE_DOMAINS_NO
);
727 link_save_domains(link
, f
, link
->network
->search_domains
, DHCP_USE_DOMAINS_YES
);
730 /************************************************************/
732 fputs("ROUTE_DOMAINS=", f
);
733 if (link
->route_domains
)
734 link_save_domains(link
, f
, link
->route_domains
, DHCP_USE_DOMAINS_NO
);
736 link_save_domains(link
, f
, link
->network
->route_domains
, DHCP_USE_DOMAINS_ROUTE
);
739 /************************************************************/
741 fprintf(f
, "LLMNR=%s\n",
742 resolve_support_to_string(link
->llmnr
>= 0 ? link
->llmnr
: link
->network
->llmnr
));
744 /************************************************************/
746 fprintf(f
, "MDNS=%s\n",
747 resolve_support_to_string(link
->mdns
>= 0 ? link
->mdns
: link
->network
->mdns
));
749 /************************************************************/
751 int dns_default_route
=
752 link
->dns_default_route
>= 0 ? link
->dns_default_route
:
753 link
->network
->dns_default_route
;
754 if (dns_default_route
>= 0)
755 fprintf(f
, "DNS_DEFAULT_ROUTE=%s\n", yes_no(dns_default_route
));
757 /************************************************************/
759 DnsOverTlsMode dns_over_tls_mode
=
760 link
->dns_over_tls_mode
!= _DNS_OVER_TLS_MODE_INVALID
? link
->dns_over_tls_mode
:
761 link
->network
->dns_over_tls_mode
;
762 if (dns_over_tls_mode
!= _DNS_OVER_TLS_MODE_INVALID
)
763 fprintf(f
, "DNS_OVER_TLS=%s\n", dns_over_tls_mode_to_string(dns_over_tls_mode
));
765 /************************************************************/
767 DnssecMode dnssec_mode
=
768 link
->dnssec_mode
!= _DNSSEC_MODE_INVALID
? link
->dnssec_mode
:
769 link
->network
->dnssec_mode
;
770 if (dnssec_mode
!= _DNSSEC_MODE_INVALID
)
771 fprintf(f
, "DNSSEC=%s\n", dnssec_mode_to_string(dnssec_mode
));
773 /************************************************************/
775 Set
*nta_anchors
= link
->dnssec_negative_trust_anchors
;
776 if (set_isempty(nta_anchors
))
777 nta_anchors
= link
->network
->dnssec_negative_trust_anchors
;
779 if (!set_isempty(nta_anchors
)) {
782 fputs("DNSSEC_NTA=", f
);
784 SET_FOREACH(n
, nta_anchors
)
785 fputs_with_space(f
, n
, NULL
, &space
);
790 print_link_hashmap(f
, "CARRIER_BOUND_TO=", link
->bound_to_links
);
791 print_link_hashmap(f
, "CARRIER_BOUND_BY=", link
->bound_by_links
);
793 if (link
->dhcp_lease
) {
794 r
= dhcp_lease_save(link
->dhcp_lease
, link
->lease_file
);
802 (void) unlink(link
->lease_file
);
804 r
= link_serialize_dhcp6_client(link
, f
);
808 r
= fflush_and_check(f
);
812 r
= conservative_rename(temp_path
, link
->state_file
);
816 temp_path
= mfree(temp_path
);
821 void link_dirty(Link
*link
) {
825 assert(link
->manager
);
827 /* The serialized state in /run is no longer up-to-date. */
829 /* Also mark manager dirty as link is dirty */
830 link
->manager
->dirty
= true;
832 r
= set_ensure_put(&link
->manager
->dirty_links
, NULL
, link
);
834 /* Ignore allocation errors and don't take another ref if the link was already dirty */
839 void link_clean(Link
*link
) {
841 assert(link
->manager
);
843 /* The serialized state in /run is up-to-date */
845 link_unref(set_remove(link
->manager
->dirty_links
, link
));
848 int link_save_and_clean(Link
*link
) {