mirror of
https://github.com/systemd/systemd.git
synced 2025-02-15 09:57:39 +03:00
Merge pull request #28265 from yuwata/network-captive-portal-follow-ups
network: several follow-ups for captive portal support
This commit is contained in:
commit
9103278ff7
@ -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;
|
||||
|
@ -259,6 +259,74 @@ 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) {
|
||||
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))
|
||||
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,
|
||||
|
@ -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_;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
@ -770,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;
|
||||
@ -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;
|
||||
|
||||
@ -845,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:
|
||||
@ -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;
|
||||
|
||||
@ -1040,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;
|
||||
@ -1062,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) {
|
||||
@ -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] = {
|
||||
|
@ -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,11 +26,19 @@ 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;
|
||||
|
||||
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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
/************************************************************/
|
||||
|
||||
|
@ -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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user