<div dir="auto">"<span style="font-size:inherit;word-spacing:1px;background-color:rgba(0,0,0,0);border-color:rgb(0,0,0);color:rgb(0,0,0)">No pre-processing nor sorting is needed"</span></div><div dir="auto"><span style="font-size:inherit;word-spacing:1px;background-color:rgba(0,0,0,0);border-color:rgb(0,0,0);color:rgb(0,0,0)"><br></span></div><div dir="auto"><span style="font-size:inherit;word-spacing:1px;background-color:rgba(0,0,0,0);border-color:rgb(0,0,0);color:rgb(0,0,0)">Correction: (post-)sorting at program start (qsort) does happen. I just wanted to express that no pre-sorting before loading the input file was needed (manually or automated outside dnsmasq).</span></div><div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Sat, 10 Oct 2026 at 21:39, Roman Valls Guimera <<a href="mailto:brainstorm@nopcode.org">brainstorm@nopcode.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello Simon,<br>
<br>
First submission ever on dnsmasq, here goes nothing :)<br>
<br>
These three patches add --blocklist, which blocks the domains listed in a<br>
file such as the published ad- and malware-filtering domain lists<br>
(i.e HaGeZi Ultimate). No pre-processing nor sorting is needed and takes<br>
around 0,4 seconds to load (for >180.000 entries) because it doesn't <br>
just mmap() the domain names themselves. Instead, it keeps eight bytes <br>
per domain name and uses hashing and a bloom filter.<br>
<br>
Patch 1 keeps only a sorted array of 64-bit keyed hashes of the names.<br>
<br>
Patch 2 (optionally) puts a small Bloom filter in front of it, behind<br>
HAVE_BLOCKLIST_BLOOM... I previously wrote software using Bloom filters<br>
to de-contaminate DNA sequences, hence my bias towards this beautiful<br>
probabilistic data structure over, say, Cuckoo filters, MPH or others.<br>
<br>
I tested/benchmarked those other hashes too previously before <br>
submitting this, I reckon this is the simplest solution I could attain.<br>
<br>
Patch 3 also blocks answers which reach a listed name through a CNAME.<br>
Without it, such an answer is cached and a query for the listed name <br>
is then answered from the cache. AFAIK, --address has the same <br>
gap today if I'm not mistaken?:<br>
<br>
<a href="https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2025q3/018320.html" rel="noreferrer" target="_blank">https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2025q3/018320.html</a><br>
<br>
Other relevant threads I went through and relatively on topic:<br>
<br>
<a href="https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2024q3/017627.html" rel="noreferrer" target="_blank">https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2024q3/017627.html</a><br>
<a href="https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2026q2/018480.html" rel="noreferrer" target="_blank">https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2026q2/018480.html</a><br>
<a href="https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2021q2/014994.html" rel="noreferrer" target="_blank">https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2021q2/014994.html</a><br>
<br>
Here's some informal benchmarks I've run on my OpenWrt BananaPi BPI-R3<br>
router (apologies for the slightly different list name counts between<br>
tests, I fell into benchmarking fatigue after so many tests):<br>
<br>
  memory for a 189,000 name list (x86_64):<br>
    address=/name/ lines                    13.9 MB<br>
    --blocklist                              1.5 MB<br>
    --blocklist with the Bloom filter        2.0 MB<br>
<br>
  CPU per query, same list, against address= lines (x86_64):<br>
    name not listed                         10.6 us vs 30.2 us<br>
    name listed                              4.5 us vs  5.3 us<br>
<br>
  lookup on my router (Cortex-A53, 231,175 names):<br>
                                   name not listed    name listed<br>
    --blocklist                         1198 ns          1108 ns<br>
    --blocklist with the Bloom filter    460 ns          1227 ns<br>
<br>
CPU per query is dnsmasq's own, against a stub upstream with the cache<br>
disabled. I can share the benchmarking code too if there's interest.<br>
<br>
Future improvements if I see this catching steam: multi-platform SIMD<br>
speedups with <a href="https://github.com/simd-everywhere/simde" rel="noreferrer" target="_blank">https://github.com/simd-everywhere/simde</a> ?<br>
<br>
Thanks to Manel for code review pre-submission and Lars for the <br>
Bloom filter lessons!<br>
<br>
Roman Valls Guimera (3):<br>
  Add --blocklist to block the names listed in a file.<br>
  Add an optional Bloom filter in front of the --blocklist search.<br>
  Block answers which go through a CNAME to a --blocklist name.<br>
<br>
 Makefile           |   2 +-<br>
 man/dnsmasq.8      |  25 +++-<br>
 src/blocklist.c    | 329 +++++++++++++++++++++++++++++++++++++++++++++<br>
 src/config.h       |  18 ++-<br>
 src/dnsmasq.c      |  16 +++<br>
 src/dnsmasq.h      |  15 ++-<br>
 src/domain-match.c |   7 +-<br>
 src/forward.c      |  60 ++++++++-<br>
 src/option.c       |  11 ++<br>
 9 files changed, 475 insertions(+), 8 deletions(-)<br>
 create mode 100644 src/blocklist.c<br>
<br>
<br>
base-commit: 03fd0c19efbc68710bf96784adcbb402deef9726<br>
-- <br>
2.53.0<br>
<br>
</blockquote></div></div>