1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <netinet/in.h>
6 #include "alloc-util.h"
7 #include "dns-domain.h"
11 #include "network-internal.h"
12 #include "networkd-link.h"
13 #include "networkd-manager-bus.h"
14 #include "networkd-manager.h"
15 #include "networkd-network.h"
16 #include "networkd-state-file.h"
17 #include "ordered-set.h"
20 #include "tmpfile-util.h"
22 static int ordered_set_put_dns_server(OrderedSet
*s
, int ifindex
, struct in_addr_full
*dns
) {
29 if (dns
->ifindex
!= 0 && dns
->ifindex
!= ifindex
)
32 p
= in_addr_full_to_string(dns
);
36 r
= ordered_set_put_strdup(s
, p
);
43 static int ordered_set_put_dns_servers(OrderedSet
*s
, int ifindex
, struct in_addr_full
**dns
, unsigned n
) {
47 assert(dns
|| n
== 0);
49 for (unsigned i
= 0; i
< n
; i
++) {
50 r
= ordered_set_put_dns_server(s
, ifindex
, dns
[i
]);
60 static int ordered_set_put_in4_addr(OrderedSet
*s
, const struct in_addr
*address
) {
67 r
= in_addr_to_string(AF_INET
, (const union in_addr_union
*) address
, &p
);
71 r
= ordered_set_consume(s
, p
);
78 static int ordered_set_put_in4_addrv(
80 const struct in_addr
*addresses
,
82 bool (*predicate
)(const struct in_addr
*addr
)) {
87 assert(n
== 0 || addresses
);
89 for (size_t i
= 0; i
< n
; i
++) {
90 if (predicate
&& !predicate(&addresses
[i
]))
92 r
= ordered_set_put_in4_addr(s
, addresses
+i
);
102 int manager_save(Manager
*m
) {
103 _cleanup_ordered_set_free_free_ OrderedSet
*dns
= NULL
, *ntp
= NULL
, *sip
= NULL
, *search_domains
= NULL
, *route_domains
= NULL
;
104 const char *operstate_str
, *carrier_state_str
, *address_state_str
;
105 LinkOperationalState operstate
= LINK_OPERSTATE_OFF
;
106 LinkCarrierState carrier_state
= LINK_CARRIER_STATE_OFF
;
107 LinkAddressState address_state
= LINK_ADDRESS_STATE_OFF
;
108 _cleanup_(unlink_and_freep
) char *temp_path
= NULL
;
109 _cleanup_strv_free_
char **p
= NULL
;
110 _cleanup_fclose_
FILE *f
= NULL
;
115 assert(m
->state_file
);
117 /* We add all NTP and DNS server to a set, to filter out duplicates */
118 dns
= ordered_set_new(&string_hash_ops
);
122 ntp
= ordered_set_new(&string_hash_ops
);
126 sip
= ordered_set_new(&string_hash_ops
);
130 search_domains
= ordered_set_new(&dns_name_hash_ops
);
134 route_domains
= ordered_set_new(&dns_name_hash_ops
);
138 HASHMAP_FOREACH(link
, m
->links
) {
139 const struct in_addr
*addresses
;
141 if (link
->flags
& IFF_LOOPBACK
)
144 if (link
->operstate
> operstate
)
145 operstate
= link
->operstate
;
147 if (link
->carrier_state
> carrier_state
)
148 carrier_state
= link
->carrier_state
;
150 if (link
->address_state
> address_state
)
151 address_state
= link
->address_state
;
156 /* First add the static configured entries */
157 if (link
->n_dns
!= UINT_MAX
)
158 r
= ordered_set_put_dns_servers(dns
, link
->ifindex
, link
->dns
, link
->n_dns
);
160 r
= ordered_set_put_dns_servers(dns
, link
->ifindex
, link
->network
->dns
, link
->network
->n_dns
);
164 r
= ordered_set_put_strdupv(ntp
, link
->ntp
?: link
->network
->ntp
);
168 r
= ordered_set_put_string_set(search_domains
, link
->search_domains
?: link
->network
->search_domains
);
172 r
= ordered_set_put_string_set(route_domains
, link
->route_domains
?: link
->network
->route_domains
);
176 if (!link
->dhcp_lease
)
179 /* Secondly, add the entries acquired via DHCP */
180 if (link
->network
->dhcp_use_dns
) {
181 r
= sd_dhcp_lease_get_dns(link
->dhcp_lease
, &addresses
);
183 r
= ordered_set_put_in4_addrv(dns
, addresses
, r
, in4_addr_is_non_local
);
186 } else if (r
< 0 && r
!= -ENODATA
)
190 if (link
->network
->dhcp_use_ntp
) {
191 r
= sd_dhcp_lease_get_ntp(link
->dhcp_lease
, &addresses
);
193 r
= ordered_set_put_in4_addrv(ntp
, addresses
, r
, in4_addr_is_non_local
);
196 } else if (r
< 0 && r
!= -ENODATA
)
200 if (link
->network
->dhcp_use_sip
) {
201 r
= sd_dhcp_lease_get_sip(link
->dhcp_lease
, &addresses
);
203 r
= ordered_set_put_in4_addrv(sip
, addresses
, r
, in4_addr_is_non_local
);
206 } else if (r
< 0 && r
!= -ENODATA
)
210 if (link
->network
->dhcp_use_domains
!= DHCP_USE_DOMAINS_NO
) {
211 const char *domainname
;
212 char **domains
= NULL
;
214 OrderedSet
*target_domains
= (link
->network
->dhcp_use_domains
== DHCP_USE_DOMAINS_YES
) ? search_domains
: route_domains
;
215 r
= sd_dhcp_lease_get_domainname(link
->dhcp_lease
, &domainname
);
217 r
= ordered_set_put_strdup(target_domains
, domainname
);
220 } else if (r
!= -ENODATA
)
223 r
= sd_dhcp_lease_get_search_domains(link
->dhcp_lease
, &domains
);
225 r
= ordered_set_put_strdupv(target_domains
, domains
);
228 } else if (r
!= -ENODATA
)
233 if (carrier_state
>= LINK_CARRIER_STATE_ENSLAVED
)
234 carrier_state
= LINK_CARRIER_STATE_CARRIER
;
236 operstate_str
= link_operstate_to_string(operstate
);
237 assert(operstate_str
);
239 carrier_state_str
= link_carrier_state_to_string(carrier_state
);
240 assert(carrier_state_str
);
242 address_state_str
= link_address_state_to_string(address_state
);
243 assert(address_state_str
);
245 r
= fopen_temporary(m
->state_file
, &f
, &temp_path
);
249 (void) fchmod(fileno(f
), 0644);
252 "# This is private data. Do not parse.\n"
255 "ADDRESS_STATE=%s\n",
256 operstate_str
, carrier_state_str
, address_state_str
);
258 ordered_set_print(f
, "DNS=", dns
);
259 ordered_set_print(f
, "NTP=", ntp
);
260 ordered_set_print(f
, "SIP=", sip
);
261 ordered_set_print(f
, "DOMAINS=", search_domains
);
262 ordered_set_print(f
, "ROUTE_DOMAINS=", route_domains
);
264 r
= fflush_and_check(f
);
268 r
= conservative_rename(temp_path
, m
->state_file
);
272 temp_path
= mfree(temp_path
);
274 if (m
->operational_state
!= operstate
) {
275 m
->operational_state
= operstate
;
276 if (strv_extend(&p
, "OperationalState") < 0)
280 if (m
->carrier_state
!= carrier_state
) {
281 m
->carrier_state
= carrier_state
;
282 if (strv_extend(&p
, "CarrierState") < 0)
286 if (m
->address_state
!= address_state
) {
287 m
->address_state
= address_state
;
288 if (strv_extend(&p
, "AddressState") < 0)
293 r
= manager_send_changed_strv(m
, p
);
295 log_warning_errno(r
, "Could not emit changed properties, ignoring: %m");
303 static void print_link_hashmap(FILE *f
, const char *prefix
, Hashmap
* h
) {
310 if (hashmap_isempty(h
))
314 HASHMAP_FOREACH(link
, h
) {
318 fprintf(f
, "%i", link
->ifindex
);
325 static void link_save_dns(Link
*link
, FILE *f
, struct in_addr_full
**dns
, unsigned n_dns
, bool *space
) {
326 for (unsigned j
= 0; j
< n_dns
; j
++) {
329 if (dns
[j
]->ifindex
!= 0 && dns
[j
]->ifindex
!= link
->ifindex
)
332 str
= in_addr_full_to_string(dns
[j
]);
343 static void serialize_addresses(
348 sd_dhcp_lease
*lease
,
350 sd_dhcp_lease_server_type_t what
,
351 sd_dhcp6_lease
*lease6
,
353 int (*lease6_get_addr
)(sd_dhcp6_lease
*, const struct in6_addr
**),
354 int (*lease6_get_fqdn
)(sd_dhcp6_lease
*, char ***)) {
363 fprintf(f
, "%s=", lvalue
);
364 fputstrv(f
, addresses
, NULL
, space
);
366 if (lease
&& conditional
) {
367 const struct in_addr
*lease_addresses
;
369 r
= sd_dhcp_lease_get_servers(lease
, what
, &lease_addresses
);
371 serialize_in_addrs(f
, lease_addresses
, r
, space
, in4_addr_is_non_local
);
374 if (lease6
&& conditional6
&& lease6_get_addr
) {
375 const struct in6_addr
*in6_addrs
;
377 r
= lease6_get_addr(lease6
, &in6_addrs
);
379 serialize_in6_addrs(f
, in6_addrs
, r
, space
);
382 if (lease6
&& conditional6
&& lease6_get_fqdn
) {
385 r
= lease6_get_fqdn(lease6
, &in6_hosts
);
387 fputstrv(f
, in6_hosts
, NULL
, space
);
394 int link_save(Link
*link
) {
395 const char *admin_state
, *oper_state
, *carrier_state
, *address_state
;
396 _cleanup_(unlink_and_freep
) char *temp_path
= NULL
;
397 _cleanup_fclose_
FILE *f
= NULL
;
401 assert(link
->state_file
);
402 assert(link
->lease_file
);
403 assert(link
->manager
);
405 if (link
->state
== LINK_STATE_LINGER
)
408 link_lldp_save(link
);
410 admin_state
= link_state_to_string(link
->state
);
413 oper_state
= link_operstate_to_string(link
->operstate
);
416 carrier_state
= link_carrier_state_to_string(link
->carrier_state
);
417 assert(carrier_state
);
419 address_state
= link_address_state_to_string(link
->address_state
);
420 assert(address_state
);
422 r
= fopen_temporary(link
->state_file
, &f
, &temp_path
);
426 (void) fchmod(fileno(f
), 0644);
429 "# This is private data. Do not parse.\n"
433 "ADDRESS_STATE=%s\n",
434 admin_state
, oper_state
, carrier_state
, address_state
);
437 char **dhcp6_domains
= NULL
, **dhcp_domains
= NULL
;
438 const char *dhcp_domainname
= NULL
, *p
;
441 fprintf(f
, "REQUIRED_FOR_ONLINE=%s\n",
442 yes_no(link
->network
->required_for_online
));
444 LinkOperationalStateRange st
= link
->network
->required_operstate_for_online
;
445 fprintf(f
, "REQUIRED_OPER_STATE_FOR_ONLINE=%s%s%s\n",
446 strempty(link_operstate_to_string(st
.min
)),
447 st
.max
!= LINK_OPERSTATE_RANGE_DEFAULT
.max
? ":" : "",
448 st
.max
!= LINK_OPERSTATE_RANGE_DEFAULT
.max
? strempty(link_operstate_to_string(st
.max
)) : "");
450 fprintf(f
, "ACTIVATION_POLICY=%s\n",
451 activation_policy_to_string(link
->network
->activation_policy
));
453 fprintf(f
, "NETWORK_FILE=%s\n", link
->network
->filename
);
455 /************************************************************/
459 if (link
->n_dns
!= UINT_MAX
)
460 link_save_dns(link
, f
, link
->dns
, link
->n_dns
, &space
);
462 link_save_dns(link
, f
, link
->network
->dns
, link
->network
->n_dns
, &space
);
464 serialize_addresses(f
, NULL
, &space
,
467 link
->network
->dhcp_use_dns
,
470 link
->network
->dhcp6_use_dns
,
471 sd_dhcp6_lease_get_dns
,
474 /* Make sure to flush out old entries before we use the NDisc data */
477 if (link
->network
->ipv6_accept_ra_use_dns
&& link
->ndisc_rdnss
) {
480 SET_FOREACH(dd
, link
->ndisc_rdnss
)
481 serialize_in6_addrs(f
, &dd
->address
, 1, &space
);
486 /************************************************************/
488 serialize_addresses(f
, "NTP", NULL
,
489 link
->ntp
?: link
->network
->ntp
,
491 link
->network
->dhcp_use_ntp
,
494 link
->network
->dhcp6_use_ntp
,
495 sd_dhcp6_lease_get_ntp_addrs
,
496 sd_dhcp6_lease_get_ntp_fqdn
);
498 serialize_addresses(f
, "SIP", NULL
,
501 link
->network
->dhcp_use_sip
,
503 NULL
, false, NULL
, NULL
);
505 /************************************************************/
507 if (link
->network
->dhcp_use_domains
!= DHCP_USE_DOMAINS_NO
&& link
->dhcp_lease
) {
508 (void) sd_dhcp_lease_get_domainname(link
->dhcp_lease
, &dhcp_domainname
);
509 (void) sd_dhcp_lease_get_search_domains(link
->dhcp_lease
, &dhcp_domains
);
511 if (link
->network
->dhcp6_use_domains
!= DHCP_USE_DOMAINS_NO
&& link
->dhcp6_lease
)
512 (void) sd_dhcp6_lease_get_domains(link
->dhcp6_lease
, &dhcp6_domains
);
514 fputs("DOMAINS=", f
);
516 ORDERED_SET_FOREACH(p
, link
->search_domains
?: link
->network
->search_domains
)
517 fputs_with_space(f
, p
, NULL
, &space
);
519 if (link
->network
->dhcp_use_domains
== DHCP_USE_DOMAINS_YES
) {
521 fputs_with_space(f
, dhcp_domainname
, NULL
, &space
);
523 fputstrv(f
, dhcp_domains
, NULL
, &space
);
525 fputstrv(f
, dhcp6_domains
, NULL
, &space
);
528 if (link
->network
->ipv6_accept_ra_use_domains
== DHCP_USE_DOMAINS_YES
) {
531 SET_FOREACH(dd
, link
->ndisc_dnssl
)
532 fputs_with_space(f
, NDISC_DNSSL_DOMAIN(dd
), NULL
, &space
);
537 /************************************************************/
539 fputs("ROUTE_DOMAINS=", f
);
541 ORDERED_SET_FOREACH(p
, link
->route_domains
?: link
->network
->route_domains
)
542 fputs_with_space(f
, p
, NULL
, &space
);
544 if (link
->network
->dhcp_use_domains
== DHCP_USE_DOMAINS_ROUTE
) {
546 fputs_with_space(f
, dhcp_domainname
, NULL
, &space
);
548 fputstrv(f
, dhcp_domains
, NULL
, &space
);
550 fputstrv(f
, dhcp6_domains
, NULL
, &space
);
553 if (link
->network
->ipv6_accept_ra_use_domains
== DHCP_USE_DOMAINS_ROUTE
) {
556 SET_FOREACH(dd
, link
->ndisc_dnssl
)
557 fputs_with_space(f
, NDISC_DNSSL_DOMAIN(dd
), NULL
, &space
);
562 /************************************************************/
564 fprintf(f
, "LLMNR=%s\n",
565 resolve_support_to_string(link
->llmnr
>= 0 ? link
->llmnr
: link
->network
->llmnr
));
567 /************************************************************/
569 fprintf(f
, "MDNS=%s\n",
570 resolve_support_to_string(link
->mdns
>= 0 ? link
->mdns
: link
->network
->mdns
));
572 /************************************************************/
574 int dns_default_route
=
575 link
->dns_default_route
>= 0 ? link
->dns_default_route
:
576 link
->network
->dns_default_route
;
577 if (dns_default_route
>= 0)
578 fprintf(f
, "DNS_DEFAULT_ROUTE=%s\n", yes_no(dns_default_route
));
580 /************************************************************/
582 DnsOverTlsMode dns_over_tls_mode
=
583 link
->dns_over_tls_mode
!= _DNS_OVER_TLS_MODE_INVALID
? link
->dns_over_tls_mode
:
584 link
->network
->dns_over_tls_mode
;
585 if (dns_over_tls_mode
!= _DNS_OVER_TLS_MODE_INVALID
)
586 fprintf(f
, "DNS_OVER_TLS=%s\n", dns_over_tls_mode_to_string(dns_over_tls_mode
));
588 /************************************************************/
590 DnssecMode dnssec_mode
=
591 link
->dnssec_mode
!= _DNSSEC_MODE_INVALID
? link
->dnssec_mode
:
592 link
->network
->dnssec_mode
;
593 if (dnssec_mode
!= _DNSSEC_MODE_INVALID
)
594 fprintf(f
, "DNSSEC=%s\n", dnssec_mode_to_string(dnssec_mode
));
596 /************************************************************/
598 Set
*nta_anchors
= link
->dnssec_negative_trust_anchors
;
599 if (set_isempty(nta_anchors
))
600 nta_anchors
= link
->network
->dnssec_negative_trust_anchors
;
602 if (!set_isempty(nta_anchors
)) {
605 fputs("DNSSEC_NTA=", f
);
607 SET_FOREACH(n
, nta_anchors
)
608 fputs_with_space(f
, n
, NULL
, &space
);
613 print_link_hashmap(f
, "CARRIER_BOUND_TO=", link
->bound_to_links
);
614 print_link_hashmap(f
, "CARRIER_BOUND_BY=", link
->bound_by_links
);
616 if (link
->dhcp_lease
) {
617 r
= dhcp_lease_save(link
->dhcp_lease
, link
->lease_file
);
625 (void) unlink(link
->lease_file
);
627 r
= link_serialize_dhcp6_client(link
, f
);
631 r
= fflush_and_check(f
);
635 r
= conservative_rename(temp_path
, link
->state_file
);
639 temp_path
= mfree(temp_path
);
644 void link_dirty(Link
*link
) {
648 assert(link
->manager
);
650 /* The serialized state in /run is no longer up-to-date. */
652 /* Also mark manager dirty as link is dirty */
653 link
->manager
->dirty
= true;
655 r
= set_ensure_put(&link
->manager
->dirty_links
, NULL
, link
);
657 /* Ignore allocation errors and don't take another ref if the link was already dirty */
662 void link_clean(Link
*link
) {
664 assert(link
->manager
);
666 /* The serialized state in /run is up-to-date */
668 link_unref(set_remove(link
->manager
->dirty_links
, link
));
671 int link_save_and_clean(Link
*link
) {