From 6341ea54675a1aadbc0a61c27bb74f1df17c979e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 6 Jul 2023 10:31:01 +0900 Subject: [PATCH 1/6] network: introduce link_get_captive_portal() Then, downgrade log level of the message about mis-match of captive portals in different protocols. --- src/network/networkd-dhcp-common.c | 52 ++++++++++++++++++++++++++++++ src/network/networkd-dhcp-common.h | 2 ++ src/network/networkd-json.c | 25 +++----------- src/network/networkd-state-file.c | 38 ++++------------------ 4 files changed, 66 insertions(+), 51 deletions(-) diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index ca9a825e7b..c3a2b92f3c 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -259,6 +259,58 @@ bool address_is_filtered(int family, const union in_addr_union *address, uint8_t return false; } +int link_get_captive_portal(Link *link, const char **ret) { + const char *dhcp4_cp = NULL, *dhcp6_cp = NULL, *ndisc_cp = NULL; + int r; + + assert(link); + + if (!link->network) { + *ret = NULL; + return 0; + } + + if (link->network->dhcp_use_captive_portal && link->dhcp_lease) { + r = sd_dhcp_lease_get_captive_portal(link->dhcp_lease, &dhcp4_cp); + if (r < 0 && r != -ENODATA) + return r; + } + + if (link->network->dhcp6_use_captive_portal && link->dhcp6_lease) { + r = sd_dhcp6_lease_get_captive_portal(link->dhcp6_lease, &dhcp6_cp); + if (r < 0 && r != -ENODATA) + return r; + } + + if (link->network->ipv6_accept_ra_use_captive_portal && link->ndisc_captive_portal) + ndisc_cp = link->ndisc_captive_portal; + + if (dhcp4_cp) { + if (dhcp6_cp && !streq(dhcp4_cp, dhcp6_cp)) + log_link_debug(link, "DHCPv6 captive portal (%s) does not match DHCPv4 (%s), ignoring DHCPv6 captive portal.", + dhcp6_cp, dhcp4_cp); + + if (ndisc_cp && !streq(dhcp4_cp, ndisc_cp)) + log_link_debug(link, "IPv6RA captive portal (%s) does not match DHCPv4 (%s), ignoring IPv6RA captive portal.", + ndisc_cp, dhcp4_cp); + + *ret = dhcp4_cp; + return 1; + } + + if (dhcp6_cp) { + if (ndisc_cp && !streq(dhcp6_cp, ndisc_cp)) + log_link_debug(link, "IPv6RA captive portal (%s) does not match DHCPv6 (%s), ignoring IPv6RA captive portal.", + ndisc_cp, dhcp6_cp); + + *ret = dhcp6_cp; + return 1; + } + + *ret = ndisc_cp; + return !!ndisc_cp; +} + int config_parse_dhcp( const char* unit, const char *filename, diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h index 6f57b78a7f..07367d4d24 100644 --- a/src/network/networkd-dhcp-common.h +++ b/src/network/networkd-dhcp-common.h @@ -85,6 +85,8 @@ static inline bool in6_prefix_is_filtered(const struct in6_addr *prefix, uint8_t return address_is_filtered(AF_INET6, &(union in_addr_union) { .in6 = *prefix }, prefixlen, allow_list, deny_list); } +int link_get_captive_portal(Link *link, const char **ret); + const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; diff --git a/src/network/networkd-json.c b/src/network/networkd-json.c index 31ccb9679a..da26f797fe 100644 --- a/src/network/networkd-json.c +++ b/src/network/networkd-json.c @@ -7,6 +7,7 @@ #include "ip-protocol-list.h" #include "netif-util.h" #include "networkd-address.h" +#include "networkd-dhcp-common.h" #include "networkd-json.h" #include "networkd-link.h" #include "networkd-manager.h" @@ -874,31 +875,15 @@ finalize: } static int captive_portal_build_json(Link *link, JsonVariant **ret) { + const char *captive_portal; int r; - const char *captive_portal = NULL; assert(link); assert(ret); - if (!link->network) { - *ret = NULL; - return 0; - } - - if (link->network->dhcp_use_captive_portal && link->dhcp_lease) { - r = sd_dhcp_lease_get_captive_portal(link->dhcp_lease, &captive_portal); - if (r < 0 && r != -ENODATA) - return r; - } - - if (link->network->dhcp6_use_captive_portal && link->dhcp6_lease && !captive_portal) { - r = sd_dhcp6_lease_get_captive_portal(link->dhcp6_lease, &captive_portal); - if (r < 0 && r != -ENODATA) - return r; - } - - if (link->network->ipv6_accept_ra_use_captive_portal && !captive_portal) - captive_portal = link->ndisc_captive_portal; + r = link_get_captive_portal(link, &captive_portal); + if (r < 0) + return r; if (!captive_portal) { *ret = NULL; diff --git a/src/network/networkd-state-file.c b/src/network/networkd-state-file.c index c9366e97d8..85c9d21082 100644 --- a/src/network/networkd-state-file.c +++ b/src/network/networkd-state-file.c @@ -10,6 +10,7 @@ #include "fileio.h" #include "fs-util.h" #include "network-internal.h" +#include "networkd-dhcp-common.h" #include "networkd-link.h" #include "networkd-manager-bus.h" #include "networkd-manager.h" @@ -465,7 +466,7 @@ static void link_save_domains(Link *link, FILE *f, OrderedSet *static_domains, D int link_save(Link *link) { const char *admin_state, *oper_state, *carrier_state, *address_state, *ipv4_address_state, *ipv6_address_state, - *dhcp_captive_portal = NULL, *dhcp6_captive_portal = NULL; + *captive_portal; _cleanup_(unlink_and_freep) char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; @@ -607,37 +608,12 @@ int link_save(Link *link) { /************************************************************/ - if (link->dhcp_lease && link->network->dhcp_use_captive_portal) { - r = sd_dhcp_lease_get_captive_portal(link->dhcp_lease, &dhcp_captive_portal); - if (r < 0 && r != -ENODATA) - return r; - } + r = link_get_captive_portal(link, &captive_portal); + if (r < 0) + return r; - if (link->dhcp6_lease && link->network->dhcp6_use_captive_portal) { - r = sd_dhcp6_lease_get_captive_portal(link->dhcp6_lease, &dhcp6_captive_portal); - if (r < 0 && r != -ENODATA) - return r; - } - - if (dhcp6_captive_portal && dhcp_captive_portal && !streq(dhcp_captive_portal, dhcp6_captive_portal)) - log_link_warning(link, "DHCPv6 Captive Portal (%s) does not match DHCPv4 (%s). Ignoring DHCPv6 portal.", - dhcp6_captive_portal, dhcp_captive_portal); - - if (link->network->ipv6_accept_ra_use_captive_portal && link->ndisc_captive_portal) { - if (dhcp_captive_portal && !streq(dhcp_captive_portal, link->ndisc_captive_portal)) - log_link_warning(link, "IPv6RA captive portal (%s) does not match DHCPv4 (%s). Ignorning IPv6RA portal.", - link->ndisc_captive_portal, dhcp_captive_portal); - if (dhcp6_captive_portal && !streq(dhcp6_captive_portal, link->ndisc_captive_portal)) - log_link_warning(link, "IPv6RA captive portal (%s) does not match DHCPv6 (%s). Ignorning IPv6RA portal.", - link->ndisc_captive_portal, dhcp6_captive_portal); - } - - if (dhcp_captive_portal) - fprintf(f, "CAPTIVE_PORTAL=%s\n", dhcp_captive_portal); - else if (dhcp6_captive_portal) - fprintf(f, "CAPTIVE_PORTAL=%s\n", dhcp6_captive_portal); - else if (link->ndisc_captive_portal) - fprintf(f, "CAPTIVE_PORTAL=%s\n", link->ndisc_captive_portal); + if (captive_portal) + fprintf(f, "CAPTIVE_PORTAL=%s\n", captive_portal); /************************************************************/ From 04eaf63c6665422eab47ece211cbe7ecc3695e7b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 6 Jul 2023 10:34:24 +0900 Subject: [PATCH 2/6] network: update comment --- src/network/networkd-ndisc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 6ccc1295d0..7affa8217e 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -18,7 +18,7 @@ typedef enum IPv6AcceptRAStartDHCP6Client { typedef struct NDiscRDNSS { struct in6_addr router; /* This is an absolute point in time, and NOT a timespan/duration. - * Must be specified with clock_boottime_or_monotonic(). */ + * Must be specified with CLOCK_BOOTTIME. */ usec_t lifetime_usec; struct in6_addr address; } NDiscRDNSS; @@ -26,7 +26,7 @@ typedef struct NDiscRDNSS { typedef struct NDiscDNSSL { struct in6_addr router; /* This is an absolute point in time, and NOT a timespan/duration. - * Must be specified with clock_boottime_or_monotonic(). */ + * Must be specified with CLOCK_BOOTTIME. */ usec_t lifetime_usec; /* The domain name follows immediately. */ } NDiscDNSSL; From 64de00c49fde341d09b817164fe8cc8f7da46268 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 6 Jul 2023 11:12:19 +0900 Subject: [PATCH 3/6] network: handle captive portal with multiple routers Before this patch, if a network has multiple routers and one of them provides a captive portal, then the portal was overwritten or cleared when another RA from another router is received. This makes captive portals managed in the similar way as DNS servers or DNS domains. So now captive portal can safely handled even if a network has multiple routers. --- src/network/networkd-dhcp-common.c | 20 +++- src/network/networkd-link.c | 1 - src/network/networkd-link.h | 2 +- src/network/networkd-ndisc.c | 155 ++++++++++++++++++++++------- src/network/networkd-ndisc.h | 8 ++ 5 files changed, 144 insertions(+), 42 deletions(-) diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index c3a2b92f3c..5f9ef80e3e 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -282,8 +282,24 @@ int link_get_captive_portal(Link *link, const char **ret) { return r; } - if (link->network->ipv6_accept_ra_use_captive_portal && link->ndisc_captive_portal) - ndisc_cp = link->ndisc_captive_portal; + if (link->network->ipv6_accept_ra_use_captive_portal) { + NDiscCaptivePortal *cp; + usec_t usec = 0; + + /* Use the captive portal with the longest lifetime. */ + + SET_FOREACH(cp, link->ndisc_captive_portals) { + if (cp->lifetime_usec < usec) + continue; + + ndisc_cp = cp->captive_portal; + usec = cp->lifetime_usec; + } + + if (set_size(link->ndisc_captive_portals) > 1) + log_link_debug(link, "Multiple captive portals obtained by IPv6RA, using \"%s\" and ignoring others.", + ndisc_cp); + } if (dhcp4_cp) { if (dhcp6_cp && !streq(dhcp4_cp, dhcp6_cp)) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 7d9ea6f8e7..62dd892afa 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -196,7 +196,6 @@ static Link *link_free(Link *link) { free(link->ssid); free(link->previous_ssid); free(link->driver); - free(link->ndisc_captive_portal); unlink_and_free(link->lease_file); unlink_and_free(link->lldp_file); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index bc8fe08374..b91259c487 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -154,7 +154,7 @@ typedef struct Link { sd_event_source *ndisc_expire; Set *ndisc_rdnss; Set *ndisc_dnssl; - char *ndisc_captive_portal; + Set *ndisc_captive_portals; unsigned ndisc_messages; bool ndisc_configured:1; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 8115595dc5..66d8d27870 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -716,43 +716,6 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( ndisc_dnssl_compare_func, free); -static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt) { - const char *uri; - _cleanup_free_ char *captive_portal = NULL; - size_t len; - int r; - - assert(link); - assert(link->network); - assert(rt); - - if (!link->network->ipv6_accept_ra_use_captive_portal) - return 0; - - r = sd_ndisc_router_captive_portal_get_uri(rt, &uri, &len); - if (r < 0) - return r; - - if (len == 0) { - link->ndisc_captive_portal = mfree(link->ndisc_captive_portal); - return 0; - } - - r = make_cstring(uri, len, MAKE_CSTRING_REFUSE_TRAILING_NUL, &captive_portal); - if (r < 0) - return r; - - if (!in_charset(captive_portal, URI_VALID)) - return -EBADMSG; - - if (!streq_ptr(link->ndisc_captive_portal, captive_portal)) { - free_and_replace(link->ndisc_captive_portal, captive_portal); - link_dirty(link); - } - - return 0; -} - static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { _cleanup_strv_free_ char **l = NULL; usec_t lifetime_usec, timestamp_usec; @@ -834,6 +797,108 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { return 0; } +static NDiscCaptivePortal* ndisc_captive_portal_free(NDiscCaptivePortal *x) { + if (!x) + return NULL; + + free(x->captive_portal); + return mfree(x); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(NDiscCaptivePortal*, ndisc_captive_portal_free); + +static void ndisc_captive_portal_hash_func(const NDiscCaptivePortal *x, struct siphash *state) { + assert(x); + siphash24_compress_string(x->captive_portal, state); +} + +static int ndisc_captive_portal_compare_func(const NDiscCaptivePortal *a, const NDiscCaptivePortal *b) { + assert(a); + assert(b); + return strcmp_ptr(a->captive_portal, b->captive_portal); +} + +DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( + ndisc_captive_portal_hash_ops, + NDiscCaptivePortal, + ndisc_captive_portal_hash_func, + ndisc_captive_portal_compare_func, + free); + +static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt) { + _cleanup_(ndisc_captive_portal_freep) NDiscCaptivePortal *new_entry = NULL; + _cleanup_free_ char *captive_portal = NULL; + usec_t lifetime_usec, timestamp_usec; + NDiscCaptivePortal *exist; + struct in6_addr router; + uint16_t lifetime_sec; + const char *uri; + size_t len; + int r; + + assert(link); + assert(link->network); + assert(rt); + + if (!link->network->ipv6_accept_ra_use_captive_portal) + return 0; + + r = sd_ndisc_router_get_address(rt, &router); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get router address from RA: %m"); + + r = sd_ndisc_router_get_lifetime(rt, &lifetime_sec); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get lifetime of RA message: %m"); + + r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); + + lifetime_usec = sec16_to_usec(lifetime_sec, timestamp_usec); + + r = sd_ndisc_router_captive_portal_get_uri(rt, &uri, &len); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get captive portal from RA: %m"); + + if (len == 0) + return 0; + + r = make_cstring(uri, len, MAKE_CSTRING_REFUSE_TRAILING_NUL, &captive_portal); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to convert captive portal URI: %m"); + + if (!in_charset(captive_portal, URI_VALID)) + return log_link_debug_errno(link, SYNTHETIC_ERRNO(EBADMSG), "Received invalid captive portal, ignoring."); + + exist = set_get(link->ndisc_captive_portals, &(NDiscCaptivePortal) { .captive_portal = captive_portal }); + if (exist) { + /* update existing entry */ + exist->router = router; + exist->lifetime_usec = lifetime_usec; + return 0; + } + + new_entry = new(NDiscCaptivePortal, 1); + if (!new_entry) + return log_oom(); + + *new_entry = (NDiscCaptivePortal) { + .router = router, + .lifetime_usec = lifetime_usec, + .captive_portal = TAKE_PTR(captive_portal), + }; + + r = set_ensure_put(&link->ndisc_captive_portals, &ndisc_captive_portal_hash_ops, new_entry); + if (r < 0) + return log_oom(); + assert(r > 0); + TAKE_PTR(new_entry); + + link_dirty(link); + return 0; +} + static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { int r; @@ -882,6 +947,7 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { bool updated = false; NDiscDNSSL *dnssl; NDiscRDNSS *rdnss; + NDiscCaptivePortal *cp; Address *address; Route *route; int r = 0, k; @@ -934,6 +1000,14 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { updated = true; } + SET_FOREACH(cp, link->ndisc_captive_portals) { + if (cp->lifetime_usec >= timestamp_usec) + continue; /* the captive portal is still valid */ + + free(set_remove(link->ndisc_captive_portals, cp)); + updated = true; + } + if (updated) link_dirty(link); @@ -957,6 +1031,7 @@ static int ndisc_expire_handler(sd_event_source *s, uint64_t usec, void *userdat static int ndisc_setup_expire(Link *link) { usec_t lifetime_usec = USEC_INFINITY; + NDiscCaptivePortal *cp; NDiscDNSSL *dnssl; NDiscRDNSS *rdnss; Address *address; @@ -992,6 +1067,9 @@ static int ndisc_setup_expire(Link *link) { SET_FOREACH(dnssl, link->ndisc_dnssl) lifetime_usec = MIN(lifetime_usec, dnssl->lifetime_usec); + SET_FOREACH(cp, link->ndisc_captive_portals) + lifetime_usec = MIN(lifetime_usec, cp->lifetime_usec); + if (lifetime_usec == USEC_INFINITY) return 0; @@ -1254,10 +1332,11 @@ int ndisc_stop(Link *link) { void ndisc_flush(Link *link) { assert(link); - /* Removes all RDNSS and DNSSL entries, without exception */ + /* Remove all RDNSS, DNSSL, and Captive Portal entries, without exception. */ link->ndisc_rdnss = set_free(link->ndisc_rdnss); link->ndisc_dnssl = set_free(link->ndisc_dnssl); + link->ndisc_captive_portals = set_free(link->ndisc_captive_portals); } static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = { diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 7affa8217e..267f7d4a02 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -31,6 +31,14 @@ typedef struct NDiscDNSSL { /* The domain name follows immediately. */ } NDiscDNSSL; +typedef struct NDiscCaptivePortal { + struct in6_addr router; + /* This is an absolute point in time, and NOT a timespan/duration. + * Must be specified with CLOCK_BOOTTIME. */ + usec_t lifetime_usec; + char *captive_portal; +} NDiscCaptivePortal; + static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) { return ((char*) n) + ALIGN(sizeof(NDiscDNSSL)); } From 2c5bca17346f07e93a687205a70ab70c44a10e2e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 6 Jul 2023 11:22:21 +0900 Subject: [PATCH 4/6] network/ndisc: downgrade log level The failures may be critical for per-link operation, but not critical for the service. --- src/network/networkd-ndisc.c | 82 ++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 66d8d27870..64c192a539 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -269,17 +269,17 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_get_lifetime(rt, &lifetime_sec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get gateway lifetime from RA: %m"); r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); lifetime_usec = sec16_to_usec(lifetime_sec, timestamp_usec); r = sd_ndisc_router_get_address(rt, &gateway); if (r < 0) - return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) { if (DEBUG_LOGGING) @@ -290,12 +290,12 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_get_preference(rt, &preference); if (r < 0) - return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m"); if (link->network->ipv6_accept_ra_use_mtu) { r = sd_ndisc_router_get_mtu(rt, &mtu); if (r < 0 && r != -ENODATA) - return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get default router MTU from RA: %m"); } if (link->network->ipv6_accept_ra_use_gateway) { @@ -314,7 +314,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { r = ndisc_request_route(TAKE_PTR(route), link, rt); if (r < 0) - return log_link_error_errno(link, r, "Could not request default route: %m"); + return log_link_warning_errno(link, r, "Could not request default route: %m"); } Route *route_gw; @@ -340,7 +340,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { r = ndisc_request_route(TAKE_PTR(route), link, rt); if (r < 0) - return log_link_error_errno(link, r, "Could not request gateway: %m"); + return log_link_warning_errno(link, r, "Could not request gateway: %m"); } return 0; @@ -363,15 +363,15 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); r = sd_ndisc_router_prefix_get_address(rt, &prefix); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix address: %m"); + return log_link_warning_errno(link, r, "Failed to get prefix address: %m"); r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix length: %m"); + return log_link_warning_errno(link, r, "Failed to get prefix length: %m"); /* ndisc_generate_addresses() below requires the prefix length <= 64. */ if (prefixlen > 64) { @@ -382,11 +382,11 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid_sec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m"); + return log_link_warning_errno(link, r, "Failed to get prefix valid lifetime: %m"); r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred_sec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m"); + return log_link_warning_errno(link, r, "Failed to get prefix preferred lifetime: %m"); /* The preferred lifetime is never greater than the valid lifetime */ if (lifetime_preferred_sec > lifetime_valid_sec) @@ -397,7 +397,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses); if (r < 0) - return log_link_error_errno(link, r, "Failed to generate SLAAC addresses: %m"); + return log_link_warning_errno(link, r, "Failed to generate SLAAC addresses: %m"); SET_FOREACH(a, addresses) { _cleanup_(address_freep) Address *address = NULL; @@ -415,7 +415,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r r = ndisc_request_address(TAKE_PTR(address), link, rt); if (r < 0) - return log_link_error_errno(link, r, "Could not request SLAAC address: %m"); + return log_link_warning_errno(link, r, "Could not request SLAAC address: %m"); } return 0; @@ -438,19 +438,19 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_sec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m"); + return log_link_warning_errno(link, r, "Failed to get prefix lifetime: %m"); r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); r = sd_ndisc_router_prefix_get_address(rt, &prefix); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix address: %m"); + return log_link_warning_errno(link, r, "Failed to get prefix address: %m"); r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix length: %m"); + return log_link_warning_errno(link, r, "Failed to get prefix length: %m"); r = route_new(&route); if (r < 0) @@ -463,7 +463,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { r = ndisc_request_route(TAKE_PTR(route), link, rt); if (r < 0) - return log_link_error_errno(link, r, "Could not request prefix route: %m"); + return log_link_warning_errno(link, r, "Could not request prefix route: %m"); return 0; } @@ -480,7 +480,7 @@ static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_prefix_get_address(rt, &a); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix address: %m"); + return log_link_warning_errno(link, r, "Failed to get prefix address: %m"); /* RFC 4861 Section 4.6.2: * A router SHOULD NOT send a prefix option for the link-local prefix and a host SHOULD ignore such @@ -492,7 +492,7 @@ static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix length: %m"); + return log_link_warning_errno(link, r, "Failed to get prefix length: %m"); if (in6_prefix_is_filtered(&a, prefixlen, link->network->ndisc_allow_listed_prefix, link->network->ndisc_deny_listed_prefix)) { if (DEBUG_LOGGING) @@ -505,7 +505,7 @@ static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_prefix_get_flags(rt, &flags); if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA prefix flags: %m"); + return log_link_warning_errno(link, r, "Failed to get RA prefix flags: %m"); if (FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) { r = ndisc_router_process_onlink_prefix(link, rt); @@ -537,15 +537,15 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_route_get_lifetime(rt, &lifetime_sec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get route lifetime from RA: %m"); r = sd_ndisc_router_route_get_address(rt, &dst); if (r < 0) - return log_link_error_errno(link, r, "Failed to get route destination address: %m"); + return log_link_warning_errno(link, r, "Failed to get route destination address: %m"); r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen); if (r < 0) - return log_link_error_errno(link, r, "Failed to get route prefix length: %m"); + return log_link_warning_errno(link, r, "Failed to get route prefix length: %m"); if (in6_addr_is_null(&dst) && prefixlen == 0) { log_link_debug(link, "Route prefix is ::/0, ignoring"); @@ -566,7 +566,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_get_address(rt, &gateway); if (r < 0) - return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) { if (DEBUG_LOGGING) @@ -577,11 +577,11 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_route_get_preference(rt, &preference); if (r < 0) - return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m"); r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); r = route_new(&route); if (r < 0) @@ -597,7 +597,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { r = ndisc_request_route(TAKE_PTR(route), link, rt); if (r < 0) - return log_link_error_errno(link, r, "Could not request additional route: %m"); + return log_link_warning_errno(link, r, "Could not request additional route: %m"); return 0; } @@ -634,21 +634,21 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_get_address(rt, &router); if (r < 0) - return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get router address from RA: %m"); r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime_sec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m"); + return log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m"); lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec); n = sd_ndisc_router_rdnss_get_addresses(rt, &a); if (n < 0) - return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m"); + return log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m"); for (int j = 0; j < n; j++) { _cleanup_free_ NDiscRDNSS *x = NULL; @@ -733,21 +733,21 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { r = sd_ndisc_router_get_address(rt, &router); if (r < 0) - return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get router address from RA: %m"); r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime_sec); if (r < 0) - return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m"); + return log_link_warning_errno(link, r, "Failed to get DNSSL lifetime: %m"); lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec); r = sd_ndisc_router_dnssl_get_domains(rt, &l); if (r < 0) - return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m"); + return log_link_warning_errno(link, r, "Failed to get DNSSL addresses: %m"); STRV_FOREACH(j, l) { _cleanup_free_ NDiscDNSSL *s = NULL; @@ -910,13 +910,13 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { uint8_t type; if (r < 0) - return log_link_error_errno(link, r, "Failed to iterate through options: %m"); + return log_link_warning_errno(link, r, "Failed to iterate through options: %m"); if (r == 0) /* EOF */ return 0; r = sd_ndisc_router_option_get_type(rt, &type); if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA option type: %m"); + return log_link_warning_errno(link, r, "Failed to get RA option type: %m"); switch (type) { case SD_NDISC_OPTION_PREFIX_INFORMATION: @@ -1118,7 +1118,7 @@ static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) { } if (r < 0) - return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m"); + return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m"); log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request"); return 0; @@ -1140,7 +1140,7 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { return 0; } if (r < 0) - return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); + return log_link_warning_errno(link, r, "Failed to get router address from RA: %m"); if (in6_prefix_is_filtered(&router, 128, link->network->ndisc_allow_listed_router, link->network->ndisc_deny_listed_router)) { if (DEBUG_LOGGING) { From 62eaf8d039a14e7bc4e682fa3ad4b3bfe366c29a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 6 Jul 2023 11:33:44 +0900 Subject: [PATCH 5/6] test-network: drop ExecReload= in networkd.service and udevd.service Follow-up for 0e07cdb0e77d0322bc866b5e13abbe38e988059d and f84331539deae28fbeb42d45ad0c8d583b3372a3. --- test/test-network/systemd-networkd-tests.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index be3ac67216..3138a102b7 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -357,17 +357,12 @@ def create_unit_dropin(unit, contents): with open(f'/run/systemd/system/{unit}.d/00-override.conf', mode='w', encoding='utf-8') as f: f.write('\n'.join(contents)) -def create_service_dropin(service, command, reload_command=None, additional_settings=None): +def create_service_dropin(service, command, additional_settings=None): drop_in = [ '[Service]', 'ExecStart=', f'ExecStart=!!{valgrind_cmd}{command}', ] - if reload_command: - drop_in += [ - 'ExecReload=', - f'ExecReload={valgrind_cmd}{reload_command}', - ] if enable_debug: drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug'] if asan_options: @@ -688,7 +683,6 @@ def setUpModule(): save_timezone() create_service_dropin('systemd-networkd', networkd_bin, - f'{networkctl_bin} reload', ['[Service]', 'Restart=no', '[Unit]', 'StartLimitIntervalSec=0']) create_service_dropin('systemd-resolved', resolved_bin) create_service_dropin('systemd-timesyncd', timesyncd_bin) @@ -702,8 +696,6 @@ def setUpModule(): '[Service]', 'ExecStart=', f'ExecStart=!!{udevd_bin}', - 'ExecReload=', - f'ExecReload={udevadm_bin} control --reload --timeout 0', ] ) create_unit_dropin( From 52ee8ecf07e956402ce782e563155fee52f5e8c4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 6 Jul 2023 11:48:43 +0900 Subject: [PATCH 6/6] networkctl: urlify captive portal entry --- src/network/networkctl.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index ec60c5e6b8..ffbda5dc0e 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -2359,8 +2359,15 @@ static int link_status_one( return table_log_add_error(r); } - if (captive_portal) - table_add_string_line(table, "Captive Portal:", captive_portal); + if (captive_portal) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Captive Portal:", + TABLE_STRING, captive_portal, + TABLE_SET_URL, captive_portal); + if (r < 0) + return table_log_add_error(r); + } if (lease) { const void *client_id;