From: Andre Brait <[email protected]> pat_parse_ip() calls str2net() with DNS resolution enabled before trying str62net(), so every IPv6 entry of a pattern file pays a blocking DNS resolution attempt (which necessarily fails) before being parsed as an IPv6 literal. On a configuration loading a 20k-entry IPv6 acl file on a host with a resolv.conf search domain, this added two DNS round trips per entry and made "haproxy -c" take 14 seconds instead of about 1.
Try both literal parsers first, then fall back to the resolving call of str2net(). An IPv6 literal can never be a valid host name (colons are not permitted in DNS labels) and host names keep resolving exactly as before, so no working configuration changes behaviour. Diagnosed on pfSense, where large pfBlockerNG IP block lists are loaded through "acl ... -f" files: https://github.com/pfsense/FreeBSD-ports/pull/1450 Co-authored-by: Claude Fable 5 <[email protected]> --- src/pattern.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/pattern.c b/src/pattern.c index 17322e3..d627182 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -408,8 +408,14 @@ int pat_parse_dotted_ver(const char *text, struct pattern *pattern, int mflags, */ int pat_parse_ip(const char *text, struct pattern *pattern, int mflags, char **err) { - if (str2net(text, !(mflags & PAT_MF_NO_DNS) && (global.mode & MODE_STARTING), - &pattern->val.ipv4.addr, &pattern->val.ipv4.mask)) { + /* Try literal parsing of both address families first, and only then + * fall back to a DNS resolution attempt for the IPv4 case. Resolving + * before trying the IPv6 literal parsing would cost a useless blocking + * DNS round trip for every IPv6 entry of a pattern file, since an IPv6 + * literal can never be a valid host name (colons are not permitted in + * DNS labels). + */ + if (str2net(text, 0, &pattern->val.ipv4.addr, &pattern->val.ipv4.mask)) { pattern->type = SMP_T_IPV4; return 1; } @@ -417,6 +423,11 @@ int pat_parse_ip(const char *text, struct pattern *pattern, int mflags, char **e pattern->type = SMP_T_IPV6; return 1; } + else if (!(mflags & PAT_MF_NO_DNS) && (global.mode & MODE_STARTING) && + str2net(text, 1, &pattern->val.ipv4.addr, &pattern->val.ipv4.mask)) { + pattern->type = SMP_T_IPV4; + return 1; + } else { memprintf(err, "'%s' is not a valid IPv4 or IPv6 address", text); return 0; -- 2.54.0

