summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-07-03 18:57:42 +0000
committerLaurent Bercot <ska@appnovation.com>2023-07-03 18:57:42 +0000
commit5dc54a39e47148803d950d2facb42500e08f4769 (patch)
tree7875d1088c002ae64b7fc962ba013e948515f1c1
parenta02a1c5608a47211b3e672c8834a8e8a2f917ce6 (diff)
downloads6-dns-5dc54a39e47148803d950d2facb42500e08f4769.tar.xz
Add s6-dns-hosts-compile, prepare for 2.3.6.0
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--.gitignore1
-rw-r--r--NEWS4
-rw-r--r--doc/index.html5
-rw-r--r--doc/s6-dns-hosts-compile.html75
-rw-r--r--doc/upgrade.html2
-rw-r--r--package/deps.mak14
-rw-r--r--package/info2
-rw-r--r--package/modes1
-rw-r--r--package/targets.mak3
-rw-r--r--src/include/s6-dns/hosts.h16
-rw-r--r--src/include/s6-dns/s6dns.h1
-rw-r--r--src/libs6dns/deps-lib/s6dns1
-rw-r--r--src/libs6dns/s6dns_hosts_compile.c357
-rw-r--r--src/libs6dns/s6dns_hosts_compile.txt31
-rw-r--r--src/libs6dns/s6dns_hosts_here.c7
-rw-r--r--src/libs6dns/s6dns_hosts_init.c62
-rw-r--r--src/utilities/deps-exe/s6-dns-hosts-compile2
-rw-r--r--src/utilities/s6-dns-hosts-compile.c54
18 files changed, 628 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore
index d30de7c..7273fb1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,5 +23,6 @@
/s6-dnssoa
/s6-dnssrv
/s6-dnstxt
+/s6-dns-hosts-compile
/s6-randomip
/skadnsd
diff --git a/NEWS b/NEWS
index 8cc8eb2..9f7679e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,11 @@
Changelog for s6-dns.
-In 2.3.5.6
+In 2.3.6.0
----------
- Bugfixes.
+ - New s6dns_hosts functions.
+ - New command: s6-dns-hosts-compile
In 2.3.5.5
diff --git a/doc/index.html b/doc/index.html
index 49bb4c7..5d27705 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -72,7 +72,7 @@ requirement if you link against the shared version of the skalibs library. </li>
<h3> Download </h3>
<ul>
- <li> The current released version of s6-dns is <a href="s6-dns-2.3.5.6.tar.gz">2.3.5.6</a>. </li>
+ <li> The current released version of s6-dns is <a href="s6-dns-2.3.6.0.tar.gz">2.3.6.0</a>. </li>
<li> Alternatively, you can checkout a copy of the
<a href="//git.skarnet.org/cgi-bin/cgit.cgi/s6-dns/">s6-dns
git repository</a>:
@@ -147,7 +147,8 @@ relevant page.
<h4> Miscellaneous utilities </h4>
<ul>
-<li><a href="s6-randomip.html">The <tt>s6-randomip</tt> program</a></li>
+<li> <a href="s6-randomip.html">The <tt>s6-randomip</tt> program</a> </li>
+<li> <a href="s6-dns-hosts-compile.html">The <tt>s6-dns-hosts-compile</tt> program</a> </li>
</ul>
diff --git a/doc/s6-dns-hosts-compile.html b/doc/s6-dns-hosts-compile.html
new file mode 100644
index 0000000..c499ded
--- /dev/null
+++ b/doc/s6-dns-hosts-compile.html
@@ -0,0 +1,75 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>s6-dns: the s6-dns-hosts-compile program</title>
+ <meta name="Description" content="s6-dns: the s6-dns-hosts-compile program" />
+ <meta name="Keywords" content="s6-dns s6-dns-hosts-compile /etc/hosts /etc/hosts.cdb hosts file cdb" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-dns</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The s6-dns-hosts-compile program </h1>
+
+<p>
+ s6-dns-hosts-compile compiles the system's <tt>/etc/hosts</tt> file into a
+CDB file for more efficient later use by s6-dns programs that may use the
+data contained in the hosts file.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-dns-hosts-compile [ -i <em>ifile</em> ] [ -o <em>ofile</em> ]
+</pre>
+
+<ul>
+ <li> s6-randomip reads the <tt>/etc/hosts</tt> file, which must follow the
+<a href="https://man7.org/linux/man-pages/man5/hosts.5.html">traditional hosts format</a>. </li>
+ <li> It outputs a CDB database in the <tt>/etc/hosts.cdb</tt> file. </li>
+ <li> It exits 0. </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-i</tt>&nbsp;<em>ifile</em>&nbsp;: read from <em>ifile</em> instead of <tt>/etc/hosts</tt>. </li>
+ <li> <tt>-o</tt>&nbsp;<em>ofile</em>&nbsp;: write to <em>ofile</em> instead of <tt>/etc/hosts.cdb</tt>. </li>
+</ul>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> The <tt>/etc/hosts</tt> file is an old way of specifying IP from/to domain
+name correspondences. It's convenient in a pinch when a user needs to locally
+override DNS data - for instance, to redirect common advertising sites to 127.0.0.1 -
+but it does not map exactly to the DNS view of domain names. </li>
+ <li> Due to this, and to its line-by-line text syntax, lookups using this file
+are terribly inefficient and rely on approximate qualification heuristics. </li>
+ <li> To avoid that, s6-dns tools prefer having the <tt>/etc/hosts</tt> data in
+a format that's both more DNS-like and more efficient; the file output by
+s6-dns-hosts-compile is the result. </li>
+ <li> When asked to take <tt>/etc/hosts</tt> data into account, s6-dns tools will
+first look for a <tt>/etc/hosts.cdb</tt> file and use the data from it. If
+absent, they will read the <tt>/etc/hosts</tt> file and compile its contents
+into a temporary cdb file under <tt>/tmp</tt> (which they immediately unlink),
+and use that cdb to query hosts data. </li>
+ <li> As a consequence, lookups are always efficient, but there's an initial
+compilation step. Using s6-dns-hosts-compile to produce a <tt>/etc/hosts.cdb</tt>
+file in advance saves the cost of that compilation step in subsequent
+invocations of s6-dns tools. </li>
+ <li> If s6-dns tools detect that <tt>/etc/hosts</tt> has been modified more recently
+than <tt>/etc/hosts.cdb</tt>, they will not use <tt>/etc/hosts.cdb</tt> and will
+perform the compilation step into a temporary file. So, remember to run
+s6-dns-hosts-compile after modifying your <tt>/etc/hosts</tt>. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index 29db742..1fe84e6 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -18,7 +18,7 @@
<h1> What has changed in s6-dns </h1>
-<h2> in 2.3.5.6 </h2>
+<h2> in 2.3.6.0 </h2>
<ul>
<li> <a href="//skarnet.org/software/skalibs/">skalibs</a>
diff --git a/package/deps.mak b/package/deps.mak
index 3cb587d..982a2e1 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -10,7 +10,7 @@ src/include/s6-dns/s6dns-ip46.h: src/include/s6-dns/s6dns-constants.h
src/include/s6-dns/s6dns-message.h: src/include/s6-dns/s6dns-domain.h
src/include/s6-dns/s6dns-rci.h: src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-ip46.h
src/include/s6-dns/s6dns-resolve.h: src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-ip46.h src/include/s6-dns/s6dns-message.h src/include/s6-dns/s6dns-rci.h
-src/include/s6-dns/s6dns.h: src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-ip46.h src/include/s6-dns/s6dns-message.h src/include/s6-dns/s6dns-rci.h src/include/s6-dns/s6dns-resolve.h
+src/include/s6-dns/s6dns.h: src/include/s6-dns/hosts.h src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-ip46.h src/include/s6-dns/s6dns-message.h src/include/s6-dns/s6dns-rci.h src/include/s6-dns/s6dns-resolve.h
src/include/s6-dns/skadns.h: src/include/s6-dns/config.h src/include/s6-dns/s6dns-domain.h
src/caches/dcache-internal.h: src/include/s6-dns/dcache.h
src/clients/s6dns-generic-filter.h: src/include/s6-dns/s6dns-domain.h
@@ -91,6 +91,9 @@ src/libs6dns/s6dns_fmt_hinfo.o src/libs6dns/s6dns_fmt_hinfo.lo: src/libs6dns/s6d
src/libs6dns/s6dns_fmt_mx.o src/libs6dns/s6dns_fmt_mx.lo: src/libs6dns/s6dns_fmt_mx.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-fmt.h
src/libs6dns/s6dns_fmt_soa.o src/libs6dns/s6dns_fmt_soa.lo: src/libs6dns/s6dns_fmt_soa.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-fmt.h
src/libs6dns/s6dns_fmt_srv.o src/libs6dns/s6dns_fmt_srv.lo: src/libs6dns/s6dns_fmt_srv.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-fmt.h
+src/libs6dns/s6dns_hosts_compile.o src/libs6dns/s6dns_hosts_compile.lo: src/libs6dns/s6dns_hosts_compile.c src/include/s6-dns/hosts.h
+src/libs6dns/s6dns_hosts_here.o src/libs6dns/s6dns_hosts_here.lo: src/libs6dns/s6dns_hosts_here.c src/include/s6-dns/hosts.h
+src/libs6dns/s6dns_hosts_init.o src/libs6dns/s6dns_hosts_init.lo: src/libs6dns/s6dns_hosts_init.c src/include/s6-dns/hosts.h
src/libs6dns/s6dns_init.o src/libs6dns/s6dns_init.lo: src/libs6dns/s6dns_init.c src/include/s6-dns/s6dns-rci.h src/include/s6-dns/s6dns.h
src/libs6dns/s6dns_message_counts_next.o src/libs6dns/s6dns_message_counts_next.lo: src/libs6dns/s6dns_message_counts_next.c src/include/s6-dns/s6dns-message.h
src/libs6dns/s6dns_message_counts_pack.o src/libs6dns/s6dns_message_counts_pack.lo: src/libs6dns/s6dns_message_counts_pack.c src/include/s6-dns/s6dns-message.h
@@ -151,6 +154,7 @@ src/skadns/skadns_startf.o src/skadns/skadns_startf.lo: src/skadns/skadns_startf
src/skadns/skadns_update.o src/skadns/skadns_update.lo: src/skadns/skadns_update.c src/include/s6-dns/skadns.h
src/skadns/skadns_zero.o src/skadns/skadns_zero.lo: src/skadns/skadns_zero.c src/include/s6-dns/skadns.h
src/skadns/skadnsd.o src/skadns/skadnsd.lo: src/skadns/skadnsd.c src/include/s6-dns/s6dns.h src/include/s6-dns/skadns.h
+src/utilities/s6-dns-hosts-compile.o src/utilities/s6-dns-hosts-compile.lo: src/utilities/s6-dns-hosts-compile.c src/include/s6-dns/hosts.h
ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
libdcache.a.xyzzy: src/caches/dcache_add.o src/caches/dcache_clean_expired.o src/caches/dcache_delete.o src/caches/dcache_free.o src/caches/dcache_init.o src/caches/dcache_load.o src/caches/dcache_save.o src/caches/dcache_search.o
@@ -201,12 +205,12 @@ s6-dnstxt: src/clients/s6-dnstxt.o ${LIBS6DNS}
s6-randomip: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
s6-randomip: src/clients/s6-randomip.o
ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
-libs6dns.a.xyzzy: src/libs6dns/s6dns_constants_error.o src/libs6dns/s6dns_constants_error_str.o src/libs6dns/s6dns_debughook_zero.o src/libs6dns/s6dns_domain_arpafromip4.o src/libs6dns/s6dns_domain_arpafromip6.o src/libs6dns/s6dns_domain_decode.o src/libs6dns/s6dns_domain_encode.o src/libs6dns/s6dns_domain_encodelist.o src/libs6dns/s6dns_domain_fromstring.o src/libs6dns/s6dns_domain_fromstring_noqualify_encode.o src/libs6dns/s6dns_domain_fromstring_qualify_encode.o src/libs6dns/s6dns_domain_noqualify.o src/libs6dns/s6dns_domain_qualify.o src/libs6dns/s6dns_domain_tostring.o src/libs6dns/s6dns_engine.o src/libs6dns/s6dns_engine_free.o src/libs6dns/s6dns_engine_freen.o src/libs6dns/s6dns_engine_here.o src/libs6dns/s6dns_engine_nextdeadline.o src/libs6dns/s6dns_engine_zero.o src/libs6dns/s6dns_fmt_domainlist.o src/libs6dns/s6dns_fmt_hinfo.o src/libs6dns/s6dns_fmt_mx.o src/libs6dns/s6dns_fmt_soa.o src/libs6dns/s6dns_fmt_srv.o src/libs6dns/s6dns_fmt_caa.o src/libs6dns/s6dns_message_counts_next.o src/libs6dns/s6dns_message_counts_pack.o src/libs6dns/s6dns_message_counts_unpack.o src/libs6dns/s6dns_message_counts_zero.o src/libs6dns/s6dns_message_get_domain.o src/libs6dns/s6dns_message_get_domain_nodecode.o src/libs6dns/s6dns_message_get_hinfo.o src/libs6dns/s6dns_message_get_string.o src/libs6dns/s6dns_message_get_string_internal.o src/libs6dns/s6dns_message_get_strings.o src/libs6dns/s6dns_message_get_mx.o src/libs6dns/s6dns_message_get_soa.o src/libs6dns/s6dns_message_get_srv.o src/libs6dns/s6dns_message_get_caa.o src/libs6dns/s6dns_message_header_pack.o src/libs6dns/s6dns_message_header_unpack.o src/libs6dns/s6dns_message_header_zero.o src/libs6dns/s6dns_message_parse_answer_aaaa.o src/libs6dns/s6dns_message_parse_answer_a.o src/libs6dns/s6dns_message_parse_answer_domain.o src/libs6dns/s6dns_message_parse_answer_hinfo.o src/libs6dns/s6dns_message_parse_answer_mx.o src/libs6dns/s6dns_message_parse_answer_soa.o src/libs6dns/s6dns_message_parse_answer_srv.o src/libs6dns/s6dns_message_parse_answer_caa.o src/libs6dns/s6dns_message_parse_answer_strings.o src/libs6dns/s6dns_message_parse.o src/libs6dns/s6dns_message_parse_getrr.o src/libs6dns/s6dns_message_parse_init.o src/libs6dns/s6dns_message_parse_next.o src/libs6dns/s6dns_message_parse_question.o src/libs6dns/s6dns_message_parse_skipqd.o src/libs6dns/s6dns_rci_free.o src/libs6dns/s6dns_rci_here.o src/libs6dns/s6dns_rci_init.o src/libs6dns/s6dns_rci_zero.o src/libs6dns/s6dns_resolve_core.o src/libs6dns/s6dns_resolve_parse.o src/libs6dns/s6dns_resolven_loop.o src/libs6dns/s6dns_resolven_parse.o src/libs6dns/s6dns_resolve_dpag.o src/libs6dns/s6dns_resolve_mpag.o src/libs6dns/s6dns_resolve_name4.o src/libs6dns/s6dns_resolve_name6.o src/libs6dns/s6dns_resolvenoq.o src/libs6dns/s6dns_resolveq.o src/libs6dns/s6dns_resolvenoq_aaaaa.o src/libs6dns/s6dns_resolveq_aaaaa.o src/libs6dns/s6dns_analyze_packet.o src/libs6dns/s6dns_analyze_qtype_parse.o src/libs6dns/s6dns_analyze_record.o src/libs6dns/s6dns_analyze_record_a.o src/libs6dns/s6dns_analyze_record_aaaa.o src/libs6dns/s6dns_analyze_record_hinfo.o src/libs6dns/s6dns_analyze_record_mx.o src/libs6dns/s6dns_analyze_record_soa.o src/libs6dns/s6dns_analyze_record_srv.o src/libs6dns/s6dns_analyze_record_caa.o src/libs6dns/s6dns_analyze_record_domain.o src/libs6dns/s6dns_analyze_record_strings.o src/libs6dns/s6dns_analyze_record_unknown.o src/libs6dns/s6dns_analyze_rtypetable.o src/libs6dns/s6dns_debug_dumpdt_stdout.o src/libs6dns/s6dns_debug_dumpdt_stderr.o src/libs6dns/s6dns_debug_dumpdt_post_recv.o src/libs6dns/s6dns_debug_dumpdt_pre_send.o src/libs6dns/s6dns_debug_dumpdt_post_send.o src/libs6dns/s6dns_init.o src/libs6dns/s6dns_finish.o
+libs6dns.a.xyzzy: src/libs6dns/s6dns_constants_error.o src/libs6dns/s6dns_constants_error_str.o src/libs6dns/s6dns_debughook_zero.o src/libs6dns/s6dns_domain_arpafromip4.o src/libs6dns/s6dns_domain_arpafromip6.o src/libs6dns/s6dns_domain_decode.o src/libs6dns/s6dns_domain_encode.o src/libs6dns/s6dns_domain_encodelist.o src/libs6dns/s6dns_domain_fromstring.o src/libs6dns/s6dns_domain_fromstring_noqualify_encode.o src/libs6dns/s6dns_domain_fromstring_qualify_encode.o src/libs6dns/s6dns_domain_noqualify.o src/libs6dns/s6dns_domain_qualify.o src/libs6dns/s6dns_domain_tostring.o src/libs6dns/s6dns_engine.o src/libs6dns/s6dns_engine_free.o src/libs6dns/s6dns_engine_freen.o src/libs6dns/s6dns_engine_here.o src/libs6dns/s6dns_engine_nextdeadline.o src/libs6dns/s6dns_engine_zero.o src/libs6dns/s6dns_fmt_domainlist.o src/libs6dns/s6dns_fmt_hinfo.o src/libs6dns/s6dns_fmt_mx.o src/libs6dns/s6dns_fmt_soa.o src/libs6dns/s6dns_fmt_srv.o src/libs6dns/s6dns_fmt_caa.o src/libs6dns/s6dns_hosts_compile.o src/libs6dns/s6dns_message_counts_next.o src/libs6dns/s6dns_message_counts_pack.o src/libs6dns/s6dns_message_counts_unpack.o src/libs6dns/s6dns_message_counts_zero.o src/libs6dns/s6dns_message_get_domain.o src/libs6dns/s6dns_message_get_domain_nodecode.o src/libs6dns/s6dns_message_get_hinfo.o src/libs6dns/s6dns_message_get_string.o src/libs6dns/s6dns_message_get_string_internal.o src/libs6dns/s6dns_message_get_strings.o src/libs6dns/s6dns_message_get_mx.o src/libs6dns/s6dns_message_get_soa.o src/libs6dns/s6dns_message_get_srv.o src/libs6dns/s6dns_message_get_caa.o src/libs6dns/s6dns_message_header_pack.o src/libs6dns/s6dns_message_header_unpack.o src/libs6dns/s6dns_message_header_zero.o src/libs6dns/s6dns_message_parse_answer_aaaa.o src/libs6dns/s6dns_message_parse_answer_a.o src/libs6dns/s6dns_message_parse_answer_domain.o src/libs6dns/s6dns_message_parse_answer_hinfo.o src/libs6dns/s6dns_message_parse_answer_mx.o src/libs6dns/s6dns_message_parse_answer_soa.o src/libs6dns/s6dns_message_parse_answer_srv.o src/libs6dns/s6dns_message_parse_answer_caa.o src/libs6dns/s6dns_message_parse_answer_strings.o src/libs6dns/s6dns_message_parse.o src/libs6dns/s6dns_message_parse_getrr.o src/libs6dns/s6dns_message_parse_init.o src/libs6dns/s6dns_message_parse_next.o src/libs6dns/s6dns_message_parse_question.o src/libs6dns/s6dns_message_parse_skipqd.o src/libs6dns/s6dns_rci_free.o src/libs6dns/s6dns_rci_here.o src/libs6dns/s6dns_rci_init.o src/libs6dns/s6dns_rci_zero.o src/libs6dns/s6dns_resolve_core.o src/libs6dns/s6dns_resolve_parse.o src/libs6dns/s6dns_resolven_loop.o src/libs6dns/s6dns_resolven_parse.o src/libs6dns/s6dns_resolve_dpag.o src/libs6dns/s6dns_resolve_mpag.o src/libs6dns/s6dns_resolve_name4.o src/libs6dns/s6dns_resolve_name6.o src/libs6dns/s6dns_resolvenoq.o src/libs6dns/s6dns_resolveq.o src/libs6dns/s6dns_resolvenoq_aaaaa.o src/libs6dns/s6dns_resolveq_aaaaa.o src/libs6dns/s6dns_analyze_packet.o src/libs6dns/s6dns_analyze_qtype_parse.o src/libs6dns/s6dns_analyze_record.o src/libs6dns/s6dns_analyze_record_a.o src/libs6dns/s6dns_analyze_record_aaaa.o src/libs6dns/s6dns_analyze_record_hinfo.o src/libs6dns/s6dns_analyze_record_mx.o src/libs6dns/s6dns_analyze_record_soa.o src/libs6dns/s6dns_analyze_record_srv.o src/libs6dns/s6dns_analyze_record_caa.o src/libs6dns/s6dns_analyze_record_domain.o src/libs6dns/s6dns_analyze_record_strings.o src/libs6dns/s6dns_analyze_record_unknown.o src/libs6dns/s6dns_analyze_rtypetable.o src/libs6dns/s6dns_debug_dumpdt_stdout.o src/libs6dns/s6dns_debug_dumpdt_stderr.o src/libs6dns/s6dns_debug_dumpdt_post_recv.o src/libs6dns/s6dns_debug_dumpdt_pre_send.o src/libs6dns/s6dns_debug_dumpdt_post_send.o src/libs6dns/s6dns_init.o src/libs6dns/s6dns_finish.o
else
-libs6dns.a.xyzzy: src/libs6dns/s6dns_constants_error.lo src/libs6dns/s6dns_constants_error_str.lo src/libs6dns/s6dns_debughook_zero.lo src/libs6dns/s6dns_domain_arpafromip4.lo src/libs6dns/s6dns_domain_arpafromip6.lo src/libs6dns/s6dns_domain_decode.lo src/libs6dns/s6dns_domain_encode.lo src/libs6dns/s6dns_domain_encodelist.lo src/libs6dns/s6dns_domain_fromstring.lo src/libs6dns/s6dns_domain_fromstring_noqualify_encode.lo src/libs6dns/s6dns_domain_fromstring_qualify_encode.lo src/libs6dns/s6dns_domain_noqualify.lo src/libs6dns/s6dns_domain_qualify.lo src/libs6dns/s6dns_domain_tostring.lo src/libs6dns/s6dns_engine.lo src/libs6dns/s6dns_engine_free.lo src/libs6dns/s6dns_engine_freen.lo src/libs6dns/s6dns_engine_here.lo src/libs6dns/s6dns_engine_nextdeadline.lo src/libs6dns/s6dns_engine_zero.lo src/libs6dns/s6dns_fmt_domainlist.lo src/libs6dns/s6dns_fmt_hinfo.lo src/libs6dns/s6dns_fmt_mx.lo src/libs6dns/s6dns_fmt_soa.lo src/libs6dns/s6dns_fmt_srv.lo src/libs6dns/s6dns_fmt_caa.lo src/libs6dns/s6dns_message_counts_next.lo src/libs6dns/s6dns_message_counts_pack.lo src/libs6dns/s6dns_message_counts_unpack.lo src/libs6dns/s6dns_message_counts_zero.lo src/libs6dns/s6dns_message_get_domain.lo src/libs6dns/s6dns_message_get_domain_nodecode.lo src/libs6dns/s6dns_message_get_hinfo.lo src/libs6dns/s6dns_message_get_string.lo src/libs6dns/s6dns_message_get_string_internal.lo src/libs6dns/s6dns_message_get_strings.lo src/libs6dns/s6dns_message_get_mx.lo src/libs6dns/s6dns_message_get_soa.lo src/libs6dns/s6dns_message_get_srv.lo src/libs6dns/s6dns_message_get_caa.lo src/libs6dns/s6dns_message_header_pack.lo src/libs6dns/s6dns_message_header_unpack.lo src/libs6dns/s6dns_message_header_zero.lo src/libs6dns/s6dns_message_parse_answer_aaaa.lo src/libs6dns/s6dns_message_parse_answer_a.lo src/libs6dns/s6dns_message_parse_answer_domain.lo src/libs6dns/s6dns_message_parse_answer_hinfo.lo src/libs6dns/s6dns_message_parse_answer_mx.lo src/libs6dns/s6dns_message_parse_answer_soa.lo src/libs6dns/s6dns_message_parse_answer_srv.lo src/libs6dns/s6dns_message_parse_answer_caa.lo src/libs6dns/s6dns_message_parse_answer_strings.lo src/libs6dns/s6dns_message_parse.lo src/libs6dns/s6dns_message_parse_getrr.lo src/libs6dns/s6dns_message_parse_init.lo src/libs6dns/s6dns_message_parse_next.lo src/libs6dns/s6dns_message_parse_question.lo src/libs6dns/s6dns_message_parse_skipqd.lo src/libs6dns/s6dns_rci_free.lo src/libs6dns/s6dns_rci_here.lo src/libs6dns/s6dns_rci_init.lo src/libs6dns/s6dns_rci_zero.lo src/libs6dns/s6dns_resolve_core.lo src/libs6dns/s6dns_resolve_parse.lo src/libs6dns/s6dns_resolven_loop.lo src/libs6dns/s6dns_resolven_parse.lo src/libs6dns/s6dns_resolve_dpag.lo src/libs6dns/s6dns_resolve_mpag.lo src/libs6dns/s6dns_resolve_name4.lo src/libs6dns/s6dns_resolve_name6.lo src/libs6dns/s6dns_resolvenoq.lo src/libs6dns/s6dns_resolveq.lo src/libs6dns/s6dns_resolvenoq_aaaaa.lo src/libs6dns/s6dns_resolveq_aaaaa.lo src/libs6dns/s6dns_analyze_packet.lo src/libs6dns/s6dns_analyze_qtype_parse.lo src/libs6dns/s6dns_analyze_record.lo src/libs6dns/s6dns_analyze_record_a.lo src/libs6dns/s6dns_analyze_record_aaaa.lo src/libs6dns/s6dns_analyze_record_hinfo.lo src/libs6dns/s6dns_analyze_record_mx.lo src/libs6dns/s6dns_analyze_record_soa.lo src/libs6dns/s6dns_analyze_record_srv.lo src/libs6dns/s6dns_analyze_record_caa.lo src/libs6dns/s6dns_analyze_record_domain.lo src/libs6dns/s6dns_analyze_record_strings.lo src/libs6dns/s6dns_analyze_record_unknown.lo src/libs6dns/s6dns_analyze_rtypetable.lo src/libs6dns/s6dns_debug_dumpdt_stdout.lo src/libs6dns/s6dns_debug_dumpdt_stderr.lo src/libs6dns/s6dns_debug_dumpdt_post_recv.lo src/libs6dns/s6dns_debug_dumpdt_pre_send.lo src/libs6dns/s6dns_debug_dumpdt_post_send.lo src/libs6dns/s6dns_init.lo src/libs6dns/s6dns_finish.lo
+libs6dns.a.xyzzy: src/libs6dns/s6dns_constants_error.lo src/libs6dns/s6dns_constants_error_str.lo src/libs6dns/s6dns_debughook_zero.lo src/libs6dns/s6dns_domain_arpafromip4.lo src/libs6dns/s6dns_domain_arpafromip6.lo src/libs6dns/s6dns_domain_decode.lo src/libs6dns/s6dns_domain_encode.lo src/libs6dns/s6dns_domain_encodelist.lo src/libs6dns/s6dns_domain_fromstring.lo src/libs6dns/s6dns_domain_fromstring_noqualify_encode.lo src/libs6dns/s6dns_domain_fromstring_qualify_encode.lo src/libs6dns/s6dns_domain_noqualify.lo src/libs6dns/s6dns_domain_qualify.lo src/libs6dns/s6dns_domain_tostring.lo src/libs6dns/s6dns_engine.lo src/libs6dns/s6dns_engine_free.lo src/libs6dns/s6dns_engine_freen.lo src/libs6dns/s6dns_engine_here.lo src/libs6dns/s6dns_engine_nextdeadline.lo src/libs6dns/s6dns_engine_zero.lo src/libs6dns/s6dns_fmt_domainlist.lo src/libs6dns/s6dns_fmt_hinfo.lo src/libs6dns/s6dns_fmt_mx.lo src/libs6dns/s6dns_fmt_soa.lo src/libs6dns/s6dns_fmt_srv.lo src/libs6dns/s6dns_fmt_caa.lo src/libs6dns/s6dns_hosts_compile.lo src/libs6dns/s6dns_message_counts_next.lo src/libs6dns/s6dns_message_counts_pack.lo src/libs6dns/s6dns_message_counts_unpack.lo src/libs6dns/s6dns_message_counts_zero.lo src/libs6dns/s6dns_message_get_domain.lo src/libs6dns/s6dns_message_get_domain_nodecode.lo src/libs6dns/s6dns_message_get_hinfo.lo src/libs6dns/s6dns_message_get_string.lo src/libs6dns/s6dns_message_get_string_internal.lo src/libs6dns/s6dns_message_get_strings.lo src/libs6dns/s6dns_message_get_mx.lo src/libs6dns/s6dns_message_get_soa.lo src/libs6dns/s6dns_message_get_srv.lo src/libs6dns/s6dns_message_get_caa.lo src/libs6dns/s6dns_message_header_pack.lo src/libs6dns/s6dns_message_header_unpack.lo src/libs6dns/s6dns_message_header_zero.lo src/libs6dns/s6dns_message_parse_answer_aaaa.lo src/libs6dns/s6dns_message_parse_answer_a.lo src/libs6dns/s6dns_message_parse_answer_domain.lo src/libs6dns/s6dns_message_parse_answer_hinfo.lo src/libs6dns/s6dns_message_parse_answer_mx.lo src/libs6dns/s6dns_message_parse_answer_soa.lo src/libs6dns/s6dns_message_parse_answer_srv.lo src/libs6dns/s6dns_message_parse_answer_caa.lo src/libs6dns/s6dns_message_parse_answer_strings.lo src/libs6dns/s6dns_message_parse.lo src/libs6dns/s6dns_message_parse_getrr.lo src/libs6dns/s6dns_message_parse_init.lo src/libs6dns/s6dns_message_parse_next.lo src/libs6dns/s6dns_message_parse_question.lo src/libs6dns/s6dns_message_parse_skipqd.lo src/libs6dns/s6dns_rci_free.lo src/libs6dns/s6dns_rci_here.lo src/libs6dns/s6dns_rci_init.lo src/libs6dns/s6dns_rci_zero.lo src/libs6dns/s6dns_resolve_core.lo src/libs6dns/s6dns_resolve_parse.lo src/libs6dns/s6dns_resolven_loop.lo src/libs6dns/s6dns_resolven_parse.lo src/libs6dns/s6dns_resolve_dpag.lo src/libs6dns/s6dns_resolve_mpag.lo src/libs6dns/s6dns_resolve_name4.lo src/libs6dns/s6dns_resolve_name6.lo src/libs6dns/s6dns_resolvenoq.lo src/libs6dns/s6dns_resolveq.lo src/libs6dns/s6dns_resolvenoq_aaaaa.lo src/libs6dns/s6dns_resolveq_aaaaa.lo src/libs6dns/s6dns_analyze_packet.lo src/libs6dns/s6dns_analyze_qtype_parse.lo src/libs6dns/s6dns_analyze_record.lo src/libs6dns/s6dns_analyze_record_a.lo src/libs6dns/s6dns_analyze_record_aaaa.lo src/libs6dns/s6dns_analyze_record_hinfo.lo src/libs6dns/s6dns_analyze_record_mx.lo src/libs6dns/s6dns_analyze_record_soa.lo src/libs6dns/s6dns_analyze_record_srv.lo src/libs6dns/s6dns_analyze_record_caa.lo src/libs6dns/s6dns_analyze_record_domain.lo src/libs6dns/s6dns_analyze_record_strings.lo src/libs6dns/s6dns_analyze_record_unknown.lo src/libs6dns/s6dns_analyze_rtypetable.lo src/libs6dns/s6dns_debug_dumpdt_stdout.lo src/libs6dns/s6dns_debug_dumpdt_stderr.lo src/libs6dns/s6dns_debug_dumpdt_post_recv.lo src/libs6dns/s6dns_debug_dumpdt_pre_send.lo src/libs6dns/s6dns_debug_dumpdt_post_send.lo src/libs6dns/s6dns_init.lo src/libs6dns/s6dns_finish.lo
endif
libs6dns.so.xyzzy: EXTRA_LIBS := -lskarnet
-libs6dns.so.xyzzy: src/libs6dns/s6dns_constants_error.lo src/libs6dns/s6dns_constants_error_str.lo src/libs6dns/s6dns_debughook_zero.lo src/libs6dns/s6dns_domain_arpafromip4.lo src/libs6dns/s6dns_domain_arpafromip6.lo src/libs6dns/s6dns_domain_decode.lo src/libs6dns/s6dns_domain_encode.lo src/libs6dns/s6dns_domain_encodelist.lo src/libs6dns/s6dns_domain_fromstring.lo src/libs6dns/s6dns_domain_fromstring_noqualify_encode.lo src/libs6dns/s6dns_domain_fromstring_qualify_encode.lo src/libs6dns/s6dns_domain_noqualify.lo src/libs6dns/s6dns_domain_qualify.lo src/libs6dns/s6dns_domain_tostring.lo src/libs6dns/s6dns_engine.lo src/libs6dns/s6dns_engine_free.lo src/libs6dns/s6dns_engine_freen.lo src/libs6dns/s6dns_engine_here.lo src/libs6dns/s6dns_engine_nextdeadline.lo src/libs6dns/s6dns_engine_zero.lo src/libs6dns/s6dns_fmt_domainlist.lo src/libs6dns/s6dns_fmt_hinfo.lo src/libs6dns/s6dns_fmt_mx.lo src/libs6dns/s6dns_fmt_soa.lo src/libs6dns/s6dns_fmt_srv.lo src/libs6dns/s6dns_fmt_caa.lo src/libs6dns/s6dns_message_counts_next.lo src/libs6dns/s6dns_message_counts_pack.lo src/libs6dns/s6dns_message_counts_unpack.lo src/libs6dns/s6dns_message_counts_zero.lo src/libs6dns/s6dns_message_get_domain.lo src/libs6dns/s6dns_message_get_domain_nodecode.lo src/libs6dns/s6dns_message_get_hinfo.lo src/libs6dns/s6dns_message_get_string.lo src/libs6dns/s6dns_message_get_string_internal.lo src/libs6dns/s6dns_message_get_strings.lo src/libs6dns/s6dns_message_get_mx.lo src/libs6dns/s6dns_message_get_soa.lo src/libs6dns/s6dns_message_get_srv.lo src/libs6dns/s6dns_message_get_caa.lo src/libs6dns/s6dns_message_header_pack.lo src/libs6dns/s6dns_message_header_unpack.lo src/libs6dns/s6dns_message_header_zero.lo src/libs6dns/s6dns_message_parse_answer_aaaa.lo src/libs6dns/s6dns_message_parse_answer_a.lo src/libs6dns/s6dns_message_parse_answer_domain.lo src/libs6dns/s6dns_message_parse_answer_hinfo.lo src/libs6dns/s6dns_message_parse_answer_mx.lo src/libs6dns/s6dns_message_parse_answer_soa.lo src/libs6dns/s6dns_message_parse_answer_srv.lo src/libs6dns/s6dns_message_parse_answer_caa.lo src/libs6dns/s6dns_message_parse_answer_strings.lo src/libs6dns/s6dns_message_parse.lo src/libs6dns/s6dns_message_parse_getrr.lo src/libs6dns/s6dns_message_parse_init.lo src/libs6dns/s6dns_message_parse_next.lo src/libs6dns/s6dns_message_parse_question.lo src/libs6dns/s6dns_message_parse_skipqd.lo src/libs6dns/s6dns_rci_free.lo src/libs6dns/s6dns_rci_here.lo src/libs6dns/s6dns_rci_init.lo src/libs6dns/s6dns_rci_zero.lo src/libs6dns/s6dns_resolve_core.lo src/libs6dns/s6dns_resolve_parse.lo src/libs6dns/s6dns_resolven_loop.lo src/libs6dns/s6dns_resolven_parse.lo src/libs6dns/s6dns_resolve_dpag.lo src/libs6dns/s6dns_resolve_mpag.lo src/libs6dns/s6dns_resolve_name4.lo src/libs6dns/s6dns_resolve_name6.lo src/libs6dns/s6dns_resolvenoq.lo src/libs6dns/s6dns_resolveq.lo src/libs6dns/s6dns_resolvenoq_aaaaa.lo src/libs6dns/s6dns_resolveq_aaaaa.lo src/libs6dns/s6dns_analyze_packet.lo src/libs6dns/s6dns_analyze_qtype_parse.lo src/libs6dns/s6dns_analyze_record.lo src/libs6dns/s6dns_analyze_record_a.lo src/libs6dns/s6dns_analyze_record_aaaa.lo src/libs6dns/s6dns_analyze_record_hinfo.lo src/libs6dns/s6dns_analyze_record_mx.lo src/libs6dns/s6dns_analyze_record_soa.lo src/libs6dns/s6dns_analyze_record_srv.lo src/libs6dns/s6dns_analyze_record_caa.lo src/libs6dns/s6dns_analyze_record_domain.lo src/libs6dns/s6dns_analyze_record_strings.lo src/libs6dns/s6dns_analyze_record_unknown.lo src/libs6dns/s6dns_analyze_rtypetable.lo src/libs6dns/s6dns_debug_dumpdt_stdout.lo src/libs6dns/s6dns_debug_dumpdt_stderr.lo src/libs6dns/s6dns_debug_dumpdt_post_recv.lo src/libs6dns/s6dns_debug_dumpdt_pre_send.lo src/libs6dns/s6dns_debug_dumpdt_post_send.lo src/libs6dns/s6dns_init.lo src/libs6dns/s6dns_finish.lo
+libs6dns.so.xyzzy: src/libs6dns/s6dns_constants_error.lo src/libs6dns/s6dns_constants_error_str.lo src/libs6dns/s6dns_debughook_zero.lo src/libs6dns/s6dns_domain_arpafromip4.lo src/libs6dns/s6dns_domain_arpafromip6.lo src/libs6dns/s6dns_domain_decode.lo src/libs6dns/s6dns_domain_encode.lo src/libs6dns/s6dns_domain_encodelist.lo src/libs6dns/s6dns_domain_fromstring.lo src/libs6dns/s6dns_domain_fromstring_noqualify_encode.lo src/libs6dns/s6dns_domain_fromstring_qualify_encode.lo src/libs6dns/s6dns_domain_noqualify.lo src/libs6dns/s6dns_domain_qualify.lo src/libs6dns/s6dns_domain_tostring.lo src/libs6dns/s6dns_engine.lo src/libs6dns/s6dns_engine_free.lo src/libs6dns/s6dns_engine_freen.lo src/libs6dns/s6dns_engine_here.lo src/libs6dns/s6dns_engine_nextdeadline.lo src/libs6dns/s6dns_engine_zero.lo src/libs6dns/s6dns_fmt_domainlist.lo src/libs6dns/s6dns_fmt_hinfo.lo src/libs6dns/s6dns_fmt_mx.lo src/libs6dns/s6dns_fmt_soa.lo src/libs6dns/s6dns_fmt_srv.lo src/libs6dns/s6dns_fmt_caa.lo src/libs6dns/s6dns_hosts_compile.lo src/libs6dns/s6dns_message_counts_next.lo src/libs6dns/s6dns_message_counts_pack.lo src/libs6dns/s6dns_message_counts_unpack.lo src/libs6dns/s6dns_message_counts_zero.lo src/libs6dns/s6dns_message_get_domain.lo src/libs6dns/s6dns_message_get_domain_nodecode.lo src/libs6dns/s6dns_message_get_hinfo.lo src/libs6dns/s6dns_message_get_string.lo src/libs6dns/s6dns_message_get_string_internal.lo src/libs6dns/s6dns_message_get_strings.lo src/libs6dns/s6dns_message_get_mx.lo src/libs6dns/s6dns_message_get_soa.lo src/libs6dns/s6dns_message_get_srv.lo src/libs6dns/s6dns_message_get_caa.lo src/libs6dns/s6dns_message_header_pack.lo src/libs6dns/s6dns_message_header_unpack.lo src/libs6dns/s6dns_message_header_zero.lo src/libs6dns/s6dns_message_parse_answer_aaaa.lo src/libs6dns/s6dns_message_parse_answer_a.lo src/libs6dns/s6dns_message_parse_answer_domain.lo src/libs6dns/s6dns_message_parse_answer_hinfo.lo src/libs6dns/s6dns_message_parse_answer_mx.lo src/libs6dns/s6dns_message_parse_answer_soa.lo src/libs6dns/s6dns_message_parse_answer_srv.lo src/libs6dns/s6dns_message_parse_answer_caa.lo src/libs6dns/s6dns_message_parse_answer_strings.lo src/libs6dns/s6dns_message_parse.lo src/libs6dns/s6dns_message_parse_getrr.lo src/libs6dns/s6dns_message_parse_init.lo src/libs6dns/s6dns_message_parse_next.lo src/libs6dns/s6dns_message_parse_question.lo src/libs6dns/s6dns_message_parse_skipqd.lo src/libs6dns/s6dns_rci_free.lo src/libs6dns/s6dns_rci_here.lo src/libs6dns/s6dns_rci_init.lo src/libs6dns/s6dns_rci_zero.lo src/libs6dns/s6dns_resolve_core.lo src/libs6dns/s6dns_resolve_parse.lo src/libs6dns/s6dns_resolven_loop.lo src/libs6dns/s6dns_resolven_parse.lo src/libs6dns/s6dns_resolve_dpag.lo src/libs6dns/s6dns_resolve_mpag.lo src/libs6dns/s6dns_resolve_name4.lo src/libs6dns/s6dns_resolve_name6.lo src/libs6dns/s6dns_resolvenoq.lo src/libs6dns/s6dns_resolveq.lo src/libs6dns/s6dns_resolvenoq_aaaaa.lo src/libs6dns/s6dns_resolveq_aaaaa.lo src/libs6dns/s6dns_analyze_packet.lo src/libs6dns/s6dns_analyze_qtype_parse.lo src/libs6dns/s6dns_analyze_record.lo src/libs6dns/s6dns_analyze_record_a.lo src/libs6dns/s6dns_analyze_record_aaaa.lo src/libs6dns/s6dns_analyze_record_hinfo.lo src/libs6dns/s6dns_analyze_record_mx.lo src/libs6dns/s6dns_analyze_record_soa.lo src/libs6dns/s6dns_analyze_record_srv.lo src/libs6dns/s6dns_analyze_record_caa.lo src/libs6dns/s6dns_analyze_record_domain.lo src/libs6dns/s6dns_analyze_record_strings.lo src/libs6dns/s6dns_analyze_record_unknown.lo src/libs6dns/s6dns_analyze_rtypetable.lo src/libs6dns/s6dns_debug_dumpdt_stdout.lo src/libs6dns/s6dns_debug_dumpdt_stderr.lo src/libs6dns/s6dns_debug_dumpdt_post_recv.lo src/libs6dns/s6dns_debug_dumpdt_pre_send.lo src/libs6dns/s6dns_debug_dumpdt_post_send.lo src/libs6dns/s6dns_init.lo src/libs6dns/s6dns_finish.lo
ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
libskadns.a.xyzzy: src/skadns/skadns_cancel.o src/skadns/skadns_end.o src/skadns/skadns_packet.o src/skadns/skadns_packetlen.o src/skadns/skadns_release.o src/skadns/skadns_send.o src/skadns/skadns_start.o src/skadns/skadns_startf.o src/skadns/skadns_update.o src/skadns/skadns_zero.o
else
@@ -216,3 +220,5 @@ libskadns.so.xyzzy: EXTRA_LIBS := -lskarnet
libskadns.so.xyzzy: src/skadns/skadns_cancel.lo src/skadns/skadns_end.lo src/skadns/skadns_packet.lo src/skadns/skadns_packetlen.lo src/skadns/skadns_release.lo src/skadns/skadns_send.lo src/skadns/skadns_start.lo src/skadns/skadns_startf.lo src/skadns/skadns_update.lo src/skadns/skadns_zero.lo
skadnsd: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
skadnsd: src/skadns/skadnsd.o ${LIBS6DNS}
+s6-dns-hosts-compile: EXTRA_LIBS := -lskarnet
+s6-dns-hosts-compile: src/utilities/s6-dns-hosts-compile.o ${LIBS6DNS}
diff --git a/package/info b/package/info
index 6880434..f17f611 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
package=s6-dns
-version=2.3.5.6
+version=2.3.6.0
category=web
package_macro_name=S6_DNS
diff --git a/package/modes b/package/modes
index c9e951a..f2bb442 100644
--- a/package/modes
+++ b/package/modes
@@ -14,3 +14,4 @@ s6-dnsip6-filter 0755
s6-dnsname-filter 0755
s6-dnsq 0755
s6-dnsqr 0755
+s6-dns-hosts-compile 0755
diff --git a/package/targets.mak b/package/targets.mak
index ffab27d..f4300e9 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -15,7 +15,8 @@ s6-dnsip4-filter \
s6-dnsip6-filter \
s6-dnsname-filter \
s6-dnsq \
-s6-dnsqr
+s6-dnsqr \
+s6-dns-hosts-compile
LIBEXEC_TARGETS :=
diff --git a/src/include/s6-dns/hosts.h b/src/include/s6-dns/hosts.h
new file mode 100644
index 0000000..9c2baaf
--- /dev/null
+++ b/src/include/s6-dns/hosts.h
@@ -0,0 +1,16 @@
+/* ISC license. */
+
+#ifndef S6DNS_HOSTS_H
+#define S6DNS_HOSTS_H
+
+#include <skalibs/cdb.h>
+#include <skalibs/genalloc.h>
+
+extern cdb s6dns_hosts_here ;
+
+extern int s6dns_hosts_init (cdb *) ;
+#define s6dns_hosts_free(c) cdb_free(c)
+
+extern int s6dns_hosts_compile (int, int) ;
+
+#endif
diff --git a/src/include/s6-dns/s6dns.h b/src/include/s6-dns/s6dns.h
index 448f14d..de8c085 100644
--- a/src/include/s6-dns/s6dns.h
+++ b/src/include/s6-dns/s6dns.h
@@ -11,6 +11,7 @@
#include <s6-dns/s6dns-rci.h>
#include <s6-dns/s6dns-resolve.h>
#include <s6-dns/s6dns-fmt.h>
+#include <s6-dns/hosts.h>
extern int s6dns_init (void) ;
extern void s6dns_finish (void) ;
diff --git a/src/libs6dns/deps-lib/s6dns b/src/libs6dns/deps-lib/s6dns
index fd74385..7ade4f4 100644
--- a/src/libs6dns/deps-lib/s6dns
+++ b/src/libs6dns/deps-lib/s6dns
@@ -24,6 +24,7 @@ s6dns_fmt_mx.o
s6dns_fmt_soa.o
s6dns_fmt_srv.o
s6dns_fmt_caa.o
+s6dns_hosts_compile.o
s6dns_message_counts_next.o
s6dns_message_counts_pack.o
s6dns_message_counts_unpack.o
diff --git a/src/libs6dns/s6dns_hosts_compile.c b/src/libs6dns/s6dns_hosts_compile.c
new file mode 100644
index 0000000..20da86f
--- /dev/null
+++ b/src/libs6dns/s6dns_hosts_compile.c
@@ -0,0 +1,357 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/uio.h>
+
+#include <skalibs/buffer.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/cdbmake.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/gensetdyn.h>
+#include <skalibs/avltree.h>
+
+#include <s6-dns/hosts.h>
+
+
+ /* Definitions */
+
+typedef struct node_name_s node_name, *node_name_ref ;
+struct node_name_s
+{
+ size_t pos ;
+ stralloc ipv4 ;
+ stralloc ipv6 ;
+} ;
+
+typedef struct node_ip_s node_ip, *node_ip_ref ;
+struct node_ip_s
+{
+ char addr[16] ;
+ genalloc names ; /* size_t */
+} ;
+
+typedef struct hostdata_s hostdata, *hostdata_ref ;
+struct hostdata_s
+{
+ stralloc storage ;
+ gensetdyn alias ;
+ gensetdyn fqdn ;
+ gensetdyn ipv4 ;
+ gensetdyn ipv6 ;
+ avltree byalias ;
+ avltree byfqdn ;
+ avltree byipv4 ;
+ avltree byipv6 ;
+} ;
+#define HOSTDATA_ZERO \
+{ \
+ .storage = STRALLOC_ZERO, \
+ .alias = GENSETDYN_INIT(node_name, 3, 3, 8), \
+ .fqdn = GENSETDYN_INIT(node_name, 3, 3, 8), \
+ .ipv4 = GENSETDYN_INIT(node_ip, 3, 3, 8), \
+ .ipv6 = GENSETDYN_INIT(node_ip, 3, 3, 8), \
+ .byalias = AVLTREE_ZERO, \
+ .byfqdn = AVLTREE_ZERO, \
+ .byipv4 = AVLTREE_ZERO, \
+ .byipv6 = AVLTREE_ZERO \
+}
+
+typedef struct hdcm_s hdcm, *hdcm_ref ;
+struct hdcm_s
+{
+ hostdata *hd ;
+ cdbmaker *cm ;
+ char key[2] ;
+} ;
+
+
+ /* Utility */
+
+static void node_name_free (void *data)
+{
+ node_name *node = data ;
+ stralloc_free(&node->ipv4) ;
+ stralloc_free(&node->ipv6) ;
+}
+
+static void node_ip_free (void *data)
+{
+ node_ip *node = data ;
+ genalloc_free(size_t, &node->names) ;
+}
+
+static void hostdata_free (hostdata *hd)
+{
+ gensetdyn_deepfree(&hd->alias, &node_name_free) ;
+ gensetdyn_deepfree(&hd->fqdn, &node_name_free) ;
+ gensetdyn_deepfree(&hd->ipv4, &node_ip_free) ;
+ gensetdyn_deepfree(&hd->ipv6, &node_ip_free) ;
+ avltree_free(&hd->byalias) ;
+ avltree_free(&hd->byfqdn) ;
+ avltree_free(&hd->byipv4) ;
+ avltree_free(&hd->byipv6) ;
+ stralloc_free(&hd->storage) ;
+}
+
+static int name_cmp (void const *a, void const *b, void *aux)
+{
+ (void)aux ;
+ return strcmp((char const *)a, (char const *)b) ;
+}
+
+static void *byalias_dtok (uint32_t d, void *aux)
+{
+ hostdata *hd = aux ;
+ return hd->storage.s + GENSETDYN_P(node_name, &hd->alias, d)->pos ;
+}
+
+static void *byfqdn_dtok (uint32_t d, void *aux)
+{
+ hostdata *hd = aux ;
+ return hd->storage.s + GENSETDYN_P(node_name, &hd->fqdn, d)->pos ;
+}
+
+static int ipv4_cmp (void const *a, void const *b, void *aux)
+{
+ (void)aux ;
+ return memcmp((char const *)a, (char const *)b, 4) ;
+}
+
+static void *byipv4_dtok (uint32_t d, void *aux)
+{
+ hostdata *hd = aux ;
+ return GENSETDYN_P(node_ip, &hd->ipv4, d)->addr ;
+}
+
+static int ipv6_cmp (void const *a, void const *b, void *aux)
+{
+ (void)aux ;
+ return memcmp((char const *)a, (char const *)b, 16) ;
+}
+
+static void *byipv6_dtok (uint32_t d, void *aux)
+{
+ hostdata *hd = aux ;
+ return GENSETDYN_P(node_ip, &hd->ipv6, d)->addr ;
+}
+
+
+ /* Reading */
+
+static inline uint8_t cclass (char c)
+{
+ static uint8_t const ctable[128] = "09999999913111999999999999999999199999999999945977777777776999999888888888888888888888888889999898888888888888888888888888899999" ;
+ return c < 0 ? 9 : ctable[(uint8_t)c] - '0' ;
+}
+
+static inline char next (buffer *b)
+{
+ char c ;
+ return buffer_get(b, &c, 1) <= 0 ? 0 : c ;
+}
+
+static int s6dns_hosts_parse (buffer *b, hostdata *hd)
+{
+ static uint8_t const table[6][10] =
+ {
+ { 0x06, 0x00, 0x01, 0x00, 0x07, 0x07, 0x0a, 0x0a, 0x0a, 0x07 },
+ { 0x06, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0x16, 0x13, 0x07, 0x10, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x07 },
+ { 0x06, 0x03, 0x01, 0x00, 0x07, 0x07, 0x07, 0x07, 0x0c, 0x07 },
+ { 0x26, 0x64, 0x07, 0x20, 0x0c, 0x0c, 0x07, 0x0c, 0x0c, 0x07 },
+ { 0x06, 0x05, 0x01, 0x00, 0x07, 0x07, 0x07, 0x07, 0x0c, 0x07 }
+ } ;
+ node_ip *node = 0 ;
+ size_t mark = hd->storage.len ;
+ uint8_t flags = 0 ;
+ uint8_t state = 0 ;
+ while (state < 0x06)
+ {
+ uint8_t c ;
+ char cur ;
+ ssize_t r = buffer_get(b, &cur, 1) ;
+ if (r == -1) goto err ;
+ if (!r) cur = 0 ;
+ c = table[state][cclass(cur)] ;
+ state = c & 0x07 ;
+ if (c & 0x08) if (!stralloc_catb(&hd->storage, &cur, 1)) goto err ;
+ if (c & 0x10)
+ {
+ char ip[16] ;
+ if (!stralloc_0(&hd->storage)) goto err ;
+ if (ip6_scan(hd->storage.s + mark, ip))
+ {
+ uint32_t d ;
+ if (!avltree_search(&hd->byipv6, ip, &d))
+ {
+ if (!gensetdyn_new(&hd->ipv6, &d)) goto err ;
+ memcpy(GENSETDYN_P(node_ip, &hd->ipv6, d)->addr, ip, 16) ;
+ GENSETDYN_P(node_ip, &hd->ipv6, d)->names = genalloc_zero ;
+ if (!avltree_insert(&hd->byipv6, d)) goto err ;
+ }
+ flags |= 1 ;
+ node = GENSETDYN_P(node_ip, &hd->ipv6, d) ;
+ }
+ else if (ip4_scan(hd->storage.s + mark, ip))
+ {
+ uint32_t d ;
+ if (!avltree_search(&hd->byipv4, ip, &d))
+ {
+ if (!gensetdyn_new(&hd->ipv4, &d)) goto err ;
+ memcpy(GENSETDYN_P(node_ip, &hd->ipv4, d)->addr, ip, 4) ;
+ GENSETDYN_P(node_ip, &hd->ipv4, d)->names = genalloc_zero ;
+ if (!avltree_insert(&hd->byipv4, d)) goto err ;
+ }
+ flags &= ~1 ;
+ node = GENSETDYN_P(node_ip, &hd->ipv4, d) ;
+ }
+ else goto err ;
+ hd->storage.len = mark ;
+ flags &= ~2 ;
+ }
+ if (c & 0x20)
+ {
+ node_name *noden ;
+ size_t i = 0 ;
+ if (flags & 2)
+ {
+ uint32_t d ;
+ if (!stralloc_0(&hd->storage)) goto err ;
+ if (!avltree_search(&hd->byalias, hd->storage.s + mark, &d))
+ {
+ if (!gensetdyn_new(&hd->alias, &d)) goto err ;
+ GENSETDYN_P(node_name, &hd->alias, d)->pos = mark ;
+ GENSETDYN_P(node_name, &hd->alias, d)->ipv4 = stralloc_zero ;
+ GENSETDYN_P(node_name, &hd->alias, d)->ipv6 = stralloc_zero ;
+ if (!avltree_insert(&hd->byalias, d)) goto err ;
+ }
+ else hd->storage.len = mark ;
+ noden = GENSETDYN_P(node_name, &hd->alias, d) ;
+ }
+ else
+ {
+ uint32_t d ;
+ if (!stralloc_catb(&hd->storage, ".", 2)) goto err ;
+ if (!avltree_search(&hd->byfqdn, hd->storage.s + mark, &d))
+ {
+ if (!gensetdyn_new(&hd->fqdn, &d)) goto err ;
+ GENSETDYN_P(node_name, &hd->fqdn, d)->pos = mark ;
+ GENSETDYN_P(node_name, &hd->fqdn, d)->ipv4 = stralloc_zero ;
+ GENSETDYN_P(node_name, &hd->fqdn, d)->ipv6 = stralloc_zero ;
+ if (!avltree_insert(&hd->byfqdn, d)) goto err ;
+ }
+ else hd->storage.len = mark ;
+ noden = GENSETDYN_P(node_name, &hd->fqdn, d) ;
+ }
+ for (; i < genalloc_len(size_t, &node->names) ; i++)
+ if (!strcmp(hd->storage.s + mark, hd->storage.s + genalloc_s(size_t, &node->names)[i])) break ;
+ if (i >= genalloc_len(size_t, &node->names))
+ if (!genalloc_catb(size_t, &node->names, &mark, 1)) goto err ;
+ if (flags & 1)
+ {
+ for (i = 0 ; i < noden->ipv6.len ; i += 16)
+ if (!memcmp(node->addr, noden->ipv6.s + i, 16)) break ;
+ if (i >= noden->ipv6.len)
+ if (!stralloc_catb(&noden->ipv6, node->addr, 16)) goto err ;
+ }
+ else
+ {
+ for (i = 0 ; i < noden->ipv4.len ; i += 4)
+ if (!memcmp(node->addr, noden->ipv4.s + i, 4)) break ;
+ if (i >= noden->ipv4.len)
+ if (!stralloc_catb(&noden->ipv4, node->addr, 4)) goto err ;
+ }
+ mark = hd->storage.len ;
+ }
+ if (c & 0x40) flags |= 2 ;
+ }
+ if (state > 0x06) return (errno = EILSEQ, 0) ;
+ return 1 ;
+
+ err:
+ hostdata_free(hd) ;
+ return 0 ;
+}
+
+ /* Writing */
+
+static int name_write_iter (void *data, void *aux)
+{
+ node_name *node = data ;
+ hdcm *blah = aux ;
+ struct iovec kv[2] = { { .iov_base = "q4:", .iov_len = 3 }, { .iov_base = blah->hd->storage.s + node->pos, .iov_len = strlen(blah->hd->storage.s + node->pos) + 1 } } ;
+ struct iovec dv = { .iov_base = node->ipv4.s, .iov_len = node->ipv4.len } ;
+ if (node->ipv4.len && !cdbmake_addv(blah->cm, kv, 2, &dv, 1)) return 0 ;
+ if (node->ipv6.len)
+ {
+ ((char *)kv[0].iov_base)[1] = '6' ;
+ dv.iov_base = node->ipv6.s ; dv.iov_len = node->ipv6.len ;
+ if (!cdbmake_addv(blah->cm, kv, 2, &dv, 1)) return 0 ;
+ }
+ return 1 ;
+}
+
+static int ip_write_iter (void *data, void *aux)
+{
+ node_ip *node = data ;
+ size_t n = genalloc_len(size_t, &node->names) ;
+ if (n)
+ {
+ hdcm *blah = aux ;
+ size_t const *p = genalloc_s(size_t, &node->names) ;
+ struct iovec kv[3] = { { .iov_base = blah->key, .iov_len = 2 }, { .iov_base = ":", .iov_len = 1 }, { .iov_base = node->addr, .iov_len = blah->key[1] == '6' ? 16 : 4 } } ;
+ struct iovec dv[n] ;
+ for (size_t i = 0 ; i < n ; i++)
+ {
+ dv[i].iov_base = blah->hd->storage.s + p[i] ;
+ dv[i].iov_len = strlen(blah->hd->storage.s + p[i]) + 1 ;
+ }
+ if (!cdbmake_addv(blah->cm, kv, 3, dv, n)) return 0 ;
+ }
+ return 1 ;
+}
+
+static int s6dns_hosts_write (hostdata *hd, cdbmaker *cm)
+{
+ hdcm blah = { .hd = hd, .cm = cm, .key = { 'q', '4' } } ;
+ if (gensetdyn_iter(&hd->alias, &name_write_iter, &blah) < gensetdyn_n(&hd->alias)) return 0 ;
+ blah.key[0] = 'a' ;
+ if (gensetdyn_iter(&hd->fqdn, &name_write_iter, &blah) < gensetdyn_n(&hd->fqdn)) return 0 ;
+ blah.key[0] = 'p' ;
+ if (gensetdyn_iter(&hd->ipv4, &ip_write_iter, &blah) < gensetdyn_n(&hd->ipv4)) return 0 ;
+ blah.key[1] = '6' ;
+ if (gensetdyn_iter(&hd->ipv6, &ip_write_iter, &blah) < gensetdyn_n(&hd->ipv6)) return 0 ;
+ return 1 ;
+}
+
+
+ /* Capstone */
+
+int s6dns_hosts_compile (int fdr, int fdw)
+{
+ hostdata hd = HOSTDATA_ZERO ;
+ {
+ char buf[BUFFER_INSIZE] ;
+ buffer b = BUFFER_INIT(&buffer_read, fdr, buf, BUFFER_INSIZE) ;
+ avltree_init(&hd.byalias, 3, 3, 8, &byalias_dtok, &name_cmp, &hd) ;
+ avltree_init(&hd.byfqdn, 3, 3, 8, &byfqdn_dtok, &name_cmp, &hd) ;
+ avltree_init(&hd.byipv4, 3, 3, 8, &byipv4_dtok, &ipv4_cmp, &hd) ;
+ avltree_init(&hd.byipv6, 3, 3, 8, &byipv6_dtok, &ipv6_cmp, &hd) ;
+ if (!s6dns_hosts_parse(&b, &hd)) return 0 ;
+ }
+ {
+ cdbmaker cm = CDBMAKER_ZERO ;
+ if (!cdbmake_start(&cm, fdw)) goto err ;
+ if (!s6dns_hosts_write(&hd, &cm)) goto err ;
+ if (!cdbmake_finish(&cm)) goto err ;
+ }
+ hostdata_free(&hd) ;
+ return 1 ;
+
+ err:
+ hostdata_free(&hd) ;
+ return 0 ;
+}
diff --git a/src/libs6dns/s6dns_hosts_compile.txt b/src/libs6dns/s6dns_hosts_compile.txt
new file mode 100644
index 0000000..97c5bac
--- /dev/null
+++ b/src/libs6dns/s6dns_hosts_compile.txt
@@ -0,0 +1,31 @@
+class | 0 1 2 3 4 5 6 7 8 9
+st\ev | \0 space # \n - . : 0-9 alpha other
+
+START | p p p
+00 | END START COMMENT START X X IP IP IP X
+
+COMMENT |
+01 | END COMMENT COMMENT START COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT
+
+IP | s s sa p p p p
+02 | END IPDONE X START X IP IP IP IP X
+
+IPDONE | p
+03 | END IPDONE COMMENT START X X X X NAME X
+
+NAME | f fn f p p p p
+04 | END NAMES X START NAME NAME X NAME NAME X
+
+NAMES | p
+05 | END NAMES COMMENT START X X X X NAME X
+
+END = 06
+X = 07
+
+state: 3 bits
+actions: 4 bits
+
+0x08 p store cur
+0x10 s scan IP, reset fqdn
+0x20 f scan name
+0x40 n fqdn done, now aliases
diff --git a/src/libs6dns/s6dns_hosts_here.c b/src/libs6dns/s6dns_hosts_here.c
new file mode 100644
index 0000000..4be4969
--- /dev/null
+++ b/src/libs6dns/s6dns_hosts_here.c
@@ -0,0 +1,7 @@
+/* ISC license. */
+
+#include <skalibs/cdb.h>
+
+#include <s6-dns/hosts.h>
+
+cdb s6dns_hosts_here = CDB_ZERO ;
diff --git a/src/libs6dns/s6dns_hosts_init.c b/src/libs6dns/s6dns_hosts_init.c
new file mode 100644
index 0000000..d3cd863
--- /dev/null
+++ b/src/libs6dns/s6dns_hosts_init.c
@@ -0,0 +1,62 @@
+/* ISC license. */
+
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include <skalibs/posixplz.h>
+#include <skalibs/cdb.h>
+#include <skalibs/djbunix.h>
+
+#include <s6-dns/hosts.h>
+
+int s6dns_hosts_init (void)
+{
+ int fdr, fdw ;
+ char tmp[24] = "/tmp/hosts.cdb:XXXXXX" ;
+ int fdc = openc_read("/etc/hosts.cdb") ;
+ if (fdc >= 0)
+ {
+ struct stat stc, str ;
+ if (fstat(fdc, &stc) == -1) goto errc ;
+ if (stat("/etc/hosts", &str) == -1)
+ {
+ if (errno == ENOENT) goto useit ;
+ else goto errc ;
+ }
+ if (stc.st_mtim > str.st_mtim) goto useit ;
+ fd_close(fdc) ;
+ }
+ fdr = openc_read("/etc/hosts") ;
+ if (fdr == -1) return errno == ENOENT ? (errno = 0, 0) : -1 ;
+ fdw = mkstemp(tmp) ;
+ if (fdw == -1) goto errr ;
+ if (!s6dns_hosts_compile(fdr, fdw)) goto errw ;
+ if (lseek(fdw, 0, SEEK_SET) == -1) goto errw ;
+ if (!cdb_init_fromfd(&s6dns_hosts_here, fdw)) goto errw ;
+ fd_close(fdw) ;
+ unlink_void(tmp) ;
+ fd_close(fdr) ;
+ return 1 ;
+
+ errw:
+ fd_close(fdw) ;
+ unlink_void(tmp) ;
+ errr:
+ fd_close(fdr) ;
+ return -1 ;
+
+ errc:
+ fd_close(fdc) ;
+ return -1 ;
+
+ useit:
+ if (!cdb_init_fromfd(&s6dns_hosts_here, fdc))
+ {
+ fd_close(fdc) ;
+ return 0 ;
+ }
+ fd_close(fdc) ;
+ return 1 ;
+}
diff --git a/src/utilities/deps-exe/s6-dns-hosts-compile b/src/utilities/deps-exe/s6-dns-hosts-compile
new file mode 100644
index 0000000..833e88d
--- /dev/null
+++ b/src/utilities/deps-exe/s6-dns-hosts-compile
@@ -0,0 +1,2 @@
+${LIBS6DNS}
+-lskarnet
diff --git a/src/utilities/s6-dns-hosts-compile.c b/src/utilities/s6-dns-hosts-compile.c
new file mode 100644
index 0000000..4a38955
--- /dev/null
+++ b/src/utilities/s6-dns-hosts-compile.c
@@ -0,0 +1,54 @@
+/* ISC license. */
+
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr.h>
+#include <skalibs/djbunix.h>
+
+#include <s6-dns/hosts.h>
+
+#define USAGE "s6-dns-hosts-compile [ -i ifile ] [ -o ofile ]"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ char const *ifile = "/etc/hosts" ;
+ char const *ofile = "/etc/hosts.cdb" ;
+ PROG = "s6-dns-hosts-compile" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "i:o:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'i' : ifile = l.arg ; break ;
+ case 'o' : ofile = l.arg ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ {
+ int fdr, fdw ;
+ size_t len = strlen(ofile) ;
+ char tmp[len + 29] ;
+ memcpy(tmp, ofile, len) ;
+ memcpy(tmp + len, ":s6-dns-hosts-compile:XXXXXX", 29) ;
+ fdr = openc_read(ifile) ;
+ if (fdr == -1) strerr_diefu2sys(111, "open ", ifile) ;
+ fdw = mkstemp(tmp) ;
+ if (fdw == -1) strerr_diefu2sys(111, "create ", tmp) ;
+ if (!s6dns_hosts_compile(fdr, fdw))
+ strerr_diefu4sys(111, "compile ", ifile, " to ", tmp) ;
+ if (fsync(fdw) == -1) strerr_diefu2sys(111, "fsync ", tmp) ;
+ if (rename(tmp, ofile) == -1) strerr_diefu4sys(111, "rename ", tmp, " to ", ofile) ;
+ }
+ return 0 ;
+}