From: Yu Watanabe Date: Mon, 10 Jul 2023 04:28:59 +0000 (+0900) Subject: network/ndisc: do not store too many captive portals provided through RA X-Git-Tag: v255-rc1~627^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bf943a9d49941801b45e4631f010359619173d12;p=thirdparty%2Fsystemd.git network/ndisc: do not store too many captive portals provided through RA Prompted by https://github.com/systemd/systemd/pull/28285#issuecomment-1627585140. --- diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index c6ca7f95e2d..de03abad224 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -27,6 +27,9 @@ #define NDISC_DNSSL_MAX 64U #define NDISC_RDNSS_MAX 64U +/* Not defined RFC, but let's set an upper limit to make not consume much memory. + * This should be safe as typically there should be at most 1 portal per network. */ +#define NDISC_CAPTIVE_PORTAL_MAX 64U bool link_ipv6_accept_ra_enabled(Link *link) { assert(link); @@ -914,6 +917,19 @@ static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt) return 0; } + if (set_size(link->ndisc_captive_portals) >= NDISC_CAPTIVE_PORTAL_MAX) { + NDiscCaptivePortal *c, *target = NULL; + + /* Find the portal who has the minimal lifetime and drop it to store new one. */ + SET_FOREACH(c, link->ndisc_captive_portals) + if (!target || c->lifetime_usec < target->lifetime_usec) + target = c; + + assert(target); + assert(set_remove(link->ndisc_captive_portals, target) == target); + ndisc_captive_portal_free(target); + } + new_entry = new(NDiscCaptivePortal, 1); if (!new_entry) return log_oom();