diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index 1f32a1eb46d..e1e9a399c16 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -37,27 +37,27 @@ static int network_get_string(const char *field, char **ret) { return 0; } -_public_ int sd_network_get_operational_state(char **state) { +int sd_network_get_operational_state(char **state) { return network_get_string("OPER_STATE", state); } -_public_ int sd_network_get_carrier_state(char **state) { +int sd_network_get_carrier_state(char **state) { return network_get_string("CARRIER_STATE", state); } -_public_ int sd_network_get_address_state(char **state) { +int sd_network_get_address_state(char **state) { return network_get_string("ADDRESS_STATE", state); } -_public_ int sd_network_get_ipv4_address_state(char **state) { +int sd_network_get_ipv4_address_state(char **state) { return network_get_string("IPV4_ADDRESS_STATE", state); } -_public_ int sd_network_get_ipv6_address_state(char **state) { +int sd_network_get_ipv6_address_state(char **state) { return network_get_string("IPV6_ADDRESS_STATE", state); } -_public_ int sd_network_get_online_state(char **state) { +int sd_network_get_online_state(char **state) { return network_get_string("ONLINE_STATE", state); } @@ -90,24 +90,24 @@ static int network_get_strv(const char *key, char ***ret) { return r; } -_public_ int sd_network_get_dns(char ***ret) { +int sd_network_get_dns(char ***ret) { return network_get_strv("DNS", ret); } -_public_ int sd_network_get_ntp(char ***ret) { +int sd_network_get_ntp(char ***ret) { return network_get_strv("NTP", ret); } -_public_ int sd_network_get_search_domains(char ***ret) { +int sd_network_get_search_domains(char ***ret) { return network_get_strv("DOMAINS", ret); } -_public_ int sd_network_get_route_domains(char ***ret) { +int sd_network_get_route_domains(char ***ret) { return network_get_strv("ROUTE_DOMAINS", ret); } static int network_link_get_string(int ifindex, const char *field, char **ret) { - char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; + char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex)]; _cleanup_free_ char *s = NULL; int r; @@ -130,7 +130,7 @@ static int network_link_get_string(int ifindex, const char *field, char **ret) { } static int network_link_get_strv(int ifindex, const char *key, char ***ret) { - char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; + char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex)]; _cleanup_strv_free_ char **a = NULL; _cleanup_free_ char *s = NULL; int r; @@ -161,19 +161,19 @@ static int network_link_get_strv(int ifindex, const char *key, char ***ret) { return r; } -_public_ int sd_network_link_get_setup_state(int ifindex, char **state) { +int sd_network_link_get_setup_state(int ifindex, char **state) { return network_link_get_string(ifindex, "ADMIN_STATE", state); } -_public_ int sd_network_link_get_network_file(int ifindex, char **filename) { +int sd_network_link_get_network_file(int ifindex, char **filename) { return network_link_get_string(ifindex, "NETWORK_FILE", filename); } -_public_ int sd_network_link_get_operational_state(int ifindex, char **state) { +int sd_network_link_get_operational_state(int ifindex, char **state) { return network_link_get_string(ifindex, "OPER_STATE", state); } -_public_ int sd_network_link_get_required_family_for_online(int ifindex, char **state) { +int sd_network_link_get_required_family_for_online(int ifindex, char **state) { _cleanup_free_ char *s = NULL; int r; @@ -193,35 +193,35 @@ _public_ int sd_network_link_get_required_family_for_online(int ifindex, char ** return 0; } -_public_ int sd_network_link_get_carrier_state(int ifindex, char **state) { +int sd_network_link_get_carrier_state(int ifindex, char **state) { return network_link_get_string(ifindex, "CARRIER_STATE", state); } -_public_ int sd_network_link_get_address_state(int ifindex, char **state) { +int sd_network_link_get_address_state(int ifindex, char **state) { return network_link_get_string(ifindex, "ADDRESS_STATE", state); } -_public_ int sd_network_link_get_ipv4_address_state(int ifindex, char **state) { +int sd_network_link_get_ipv4_address_state(int ifindex, char **state) { return network_link_get_string(ifindex, "IPV4_ADDRESS_STATE", state); } -_public_ int sd_network_link_get_ipv6_address_state(int ifindex, char **state) { +int sd_network_link_get_ipv6_address_state(int ifindex, char **state) { return network_link_get_string(ifindex, "IPV6_ADDRESS_STATE", state); } -_public_ int sd_network_link_get_online_state(int ifindex, char **state) { +int sd_network_link_get_online_state(int ifindex, char **state) { return network_link_get_string(ifindex, "ONLINE_STATE", state); } -_public_ int sd_network_link_get_dhcp6_client_iaid_string(int ifindex, char **iaid) { +int sd_network_link_get_dhcp6_client_iaid_string(int ifindex, char **iaid) { return network_link_get_string(ifindex, "DHCP6_CLIENT_IAID", iaid); } -_public_ int sd_network_link_get_dhcp6_client_duid_string(int ifindex, char **duid) { +int sd_network_link_get_dhcp6_client_duid_string(int ifindex, char **duid) { return network_link_get_string(ifindex, "DHCP6_CLIENT_DUID", duid); } -_public_ int sd_network_link_get_required_for_online(int ifindex) { +int sd_network_link_get_required_for_online(int ifindex) { _cleanup_free_ char *s = NULL; int r; @@ -236,7 +236,7 @@ _public_ int sd_network_link_get_required_for_online(int ifindex) { return parse_boolean(s); } -_public_ int sd_network_link_get_required_operstate_for_online(int ifindex, char **state) { +int sd_network_link_get_required_operstate_for_online(int ifindex, char **state) { _cleanup_free_ char *s = NULL; int r; @@ -257,7 +257,7 @@ _public_ int sd_network_link_get_required_operstate_for_online(int ifindex, char return 0; } -_public_ int sd_network_link_get_activation_policy(int ifindex, char **policy) { +int sd_network_link_get_activation_policy(int ifindex, char **policy) { _cleanup_free_ char *s = NULL; int r; @@ -278,48 +278,48 @@ _public_ int sd_network_link_get_activation_policy(int ifindex, char **policy) { return 0; } -_public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) { +int sd_network_link_get_llmnr(int ifindex, char **llmnr) { return network_link_get_string(ifindex, "LLMNR", llmnr); } -_public_ int sd_network_link_get_mdns(int ifindex, char **mdns) { +int sd_network_link_get_mdns(int ifindex, char **mdns) { return network_link_get_string(ifindex, "MDNS", mdns); } -_public_ int sd_network_link_get_dns_over_tls(int ifindex, char **dns_over_tls) { +int sd_network_link_get_dns_over_tls(int ifindex, char **dns_over_tls) { return network_link_get_string(ifindex, "DNS_OVER_TLS", dns_over_tls); } -_public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) { +int sd_network_link_get_dnssec(int ifindex, char **dnssec) { return network_link_get_string(ifindex, "DNSSEC", dnssec); } -_public_ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta) { +int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta) { return network_link_get_strv(ifindex, "DNSSEC_NTA", nta); } -_public_ int sd_network_link_get_dns(int ifindex, char ***ret) { +int sd_network_link_get_dns(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "DNS", ret); } -_public_ int sd_network_link_get_ntp(int ifindex, char ***ret) { +int sd_network_link_get_ntp(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "NTP", ret); } -_public_ int sd_network_link_get_sip(int ifindex, char ***ret) { +int sd_network_link_get_sip(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "SIP", ret); } -_public_ int sd_network_link_get_search_domains(int ifindex, char ***ret) { +int sd_network_link_get_search_domains(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "DOMAINS", ret); } -_public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) { +int sd_network_link_get_route_domains(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret); } -_public_ int sd_network_link_get_dns_default_route(int ifindex) { - char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; +int sd_network_link_get_dns_default_route(int ifindex) { + char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex)]; _cleanup_free_ char *s = NULL; int r; @@ -338,7 +338,7 @@ _public_ int sd_network_link_get_dns_default_route(int ifindex) { } static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) { - char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; + char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex)]; _cleanup_free_ int *ifis = NULL; _cleanup_free_ char *s = NULL; size_t c = 0; @@ -379,14 +379,31 @@ static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) { return c; } -_public_ int sd_network_link_get_carrier_bound_to(int ifindex, int **ret) { +int sd_network_link_get_carrier_bound_to(int ifindex, int **ret) { return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_TO", ret); } -_public_ int sd_network_link_get_carrier_bound_by(int ifindex, int **ret) { +int sd_network_link_get_carrier_bound_by(int ifindex, int **ret) { return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_BY", ret); } +int sd_network_link_get_stat(int ifindex, struct stat *ret) { + char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex)]; + struct stat st; + + assert_return(ifindex > 0, -EINVAL); + + xsprintf(path, "/run/systemd/netif/links/%i", ifindex); + + if (stat(path, &st) < 0) + return -errno; + + if (ret) + *ret = st; + + return 0; +} + static int MONITOR_TO_FD(sd_network_monitor *m) { return (int) (unsigned long) m - 1; } @@ -417,7 +434,7 @@ static int monitor_add_inotify_watch(int fd) { return 0; } -_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) { +int sd_network_monitor_new(sd_network_monitor **m, const char *category) { _cleanup_close_ int fd = -1; int k; bool good = false; @@ -443,14 +460,14 @@ _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category return 0; } -_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) { +sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) { if (m) (void) close_nointr(MONITOR_TO_FD(m)); return NULL; } -_public_ int sd_network_monitor_flush(sd_network_monitor *m) { +int sd_network_monitor_flush(sd_network_monitor *m) { union inotify_event_buffer buffer; struct inotify_event *e; ssize_t l; @@ -483,14 +500,14 @@ _public_ int sd_network_monitor_flush(sd_network_monitor *m) { return 0; } -_public_ int sd_network_monitor_get_fd(sd_network_monitor *m) { +int sd_network_monitor_get_fd(sd_network_monitor *m) { assert_return(m, -EINVAL); return MONITOR_TO_FD(m); } -_public_ int sd_network_monitor_get_events(sd_network_monitor *m) { +int sd_network_monitor_get_events(sd_network_monitor *m) { assert_return(m, -EINVAL); @@ -501,7 +518,7 @@ _public_ int sd_network_monitor_get_events(sd_network_monitor *m) { return POLLIN; } -_public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) { +int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) { assert_return(m, -EINVAL); assert_return(timeout_usec, -EINVAL); diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 0013cd0b7fb..6c910498a25 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -16,6 +16,7 @@ #include "resolved-llmnr.h" #include "resolved-mdns.h" #include "socket-netlink.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "tmpfile-util.h" @@ -568,27 +569,42 @@ static int link_is_managed(Link *l) { return !STR_IN_SET(state, "pending", "initialized", "unmanaged"); } +static void link_enter_unmanaged(Link *l) { + assert(l); + + /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */ + if (l->is_managed) + link_flush_settings(l); + + l->is_managed = false; +} + static void link_read_settings(Link *l) { + struct stat st; int r; assert(l); /* Read settings from networkd, except when networkd is not managing this interface. */ + r = sd_network_link_get_stat(l->ifindex, &st); + if (r == -ENOENT) + return link_enter_unmanaged(l); + if (r < 0) + return (void) log_link_warning_errno(l, r, "Failed to stat() networkd's link state file, ignoring: %m"); + + if (stat_inode_unmodified(&l->networkd_state_file_stat, &st)) + /* The state file is unmodified. Not necessary to re-read settings. */ + return; + + /* Save the new stat for the next event. */ + l->networkd_state_file_stat = st; + r = link_is_managed(l); - if (r < 0) { - log_link_warning_errno(l, r, "Failed to determine whether the interface is managed: %m"); - return; - } - if (r == 0) { - - /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */ - if (l->is_managed) - link_flush_settings(l); - - l->is_managed = false; - return; - } + if (r < 0) + return (void) log_link_warning_errno(l, r, "Failed to determine whether the interface is managed, ignoring: %m"); + if (r == 0) + return link_enter_unmanaged(l); l->is_managed = true; diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index 3c364866f6d..f65718ce310 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include + #include "sd-netlink.h" #include "in-addr-util.h" @@ -65,6 +67,7 @@ struct Link { DnsScope *mdns_ipv4_scope; DnsScope *mdns_ipv6_scope; + struct stat networkd_state_file_stat; bool is_managed; char *ifname; diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index 776f6b5243e..a74a4964b77 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -18,6 +18,7 @@ ***/ #include +#include #include #include "_sd-common.h" @@ -187,6 +188,8 @@ int sd_network_link_get_dhcp6_client_iaid_string(int ifindex, char **iaid); /* Get DHCPv6 client DUID for a given link. */ int sd_network_link_get_dhcp6_client_duid_string(int ifindex, char **duid); +int sd_network_link_get_stat(int ifindex, struct stat *ret); + /* Monitor object */ typedef struct sd_network_monitor sd_network_monitor;