From 416ef5e2bf59bb2e45066a1d5d91ac677c0f48e5 Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Wed, 10 Dec 2014 03:05:47 +0000
Subject: Initial commit
---
.gitignore | 5 +
AUTHORS | 6 +
COPYING | 13 +
INSTALL | 132 +++++++
Makefile | 121 +++++++
README | 23 ++
README.macosx | 4 +
README.solaris | 12 +
configure | 378 ++++++++++++++++++++
doc/getaddrinfo.html | 94 +++++
doc/index.html | 175 ++++++++++
doc/libresolv.html | 140 ++++++++
doc/libs6dns/index.html | 104 ++++++
doc/libs6dns/s6dns-domain.html | 137 ++++++++
doc/libs6dns/s6dns-engine.html | 255 ++++++++++++++
doc/libs6dns/s6dns-fmt.html | 92 +++++
doc/libs6dns/s6dns-ip46.html | 69 ++++
doc/libs6dns/s6dns-message.html | 261 ++++++++++++++
doc/libs6dns/s6dns-rci.html | 109 ++++++
doc/libs6dns/s6dns-resolve.html | 387 +++++++++++++++++++++
doc/s6-dnsip4-filter.html | 111 ++++++
doc/s6-dnsip4.html | 63 ++++
doc/s6-dnsip6-filter.html | 99 ++++++
doc/s6-dnsip6.html | 73 ++++
doc/s6-dnsmx.html | 64 ++++
doc/s6-dnsname-filter.html | 103 ++++++
doc/s6-dnsname.html | 72 ++++
doc/s6-dnsns.html | 63 ++++
doc/s6-dnsq.html | 82 +++++
doc/s6-dnsqr.html | 80 +++++
doc/s6-dnsqualify.html | 41 +++
doc/s6-dnssoa.html | 65 ++++
doc/s6-dnssrv.html | 65 ++++
doc/s6-dnstxt.html | 77 ++++
doc/s6-randomip.html | 57 +++
doc/skadns/index.html | 262 ++++++++++++++
doc/skadns/skadnsd.html | 120 +++++++
doc/upgrade.html | 32 ++
package/deps-build | 1 +
package/deps.mak | 150 ++++++++
package/info | 4 +
package/modes | 16 +
package/targets.mak | 27 ++
patch-for-solaris | 17 +
src/clients/deps-exe/s6-dnsip4 | 4 +
src/clients/deps-exe/s6-dnsip4-filter | 6 +
src/clients/deps-exe/s6-dnsip6 | 4 +
src/clients/deps-exe/s6-dnsip6-filter | 6 +
src/clients/deps-exe/s6-dnsmx | 4 +
src/clients/deps-exe/s6-dnsname | 4 +
src/clients/deps-exe/s6-dnsname-filter | 6 +
src/clients/deps-exe/s6-dnsns | 4 +
src/clients/deps-exe/s6-dnsq | 4 +
src/clients/deps-exe/s6-dnsqr | 4 +
src/clients/deps-exe/s6-dnsqualify | 2 +
src/clients/deps-exe/s6-dnssoa | 4 +
src/clients/deps-exe/s6-dnssrv | 4 +
src/clients/deps-exe/s6-dnstxt | 4 +
src/clients/deps-exe/s6-randomip | 3 +
src/clients/deps-lib/s6dnsgenericfilter | 2 +
src/clients/s6-dnsip4-filter.c | 52 +++
src/clients/s6-dnsip4.c | 62 ++++
src/clients/s6-dnsip6-filter.c | 52 +++
src/clients/s6-dnsip6.c | 62 ++++
src/clients/s6-dnsmx.c | 64 ++++
src/clients/s6-dnsname-filter.c | 83 +++++
src/clients/s6-dnsname.c | 75 ++++
src/clients/s6-dnsns.c | 61 ++++
src/clients/s6-dnsq.c | 99 ++++++
src/clients/s6-dnsqr.c | 74 ++++
src/clients/s6-dnsqualify.c | 34 ++
src/clients/s6-dnssoa.c | 63 ++++
src/clients/s6-dnssrv.c | 75 ++++
src/clients/s6-dnstxt.c | 78 +++++
src/clients/s6-randomip.c | 62 ++++
src/clients/s6dns-generic-filter.h | 22 ++
src/clients/s6dns_generic_filter_main.c | 230 ++++++++++++
src/clients/s6dns_namescanner.c | 12 +
src/include/s6-dns/s6dns-analyze.h | 39 +++
src/include/s6-dns/s6dns-constants.h | 52 +++
src/include/s6-dns/s6dns-debug.h | 16 +
src/include/s6-dns/s6dns-domain.h | 47 +++
src/include/s6-dns/s6dns-engine.h | 108 ++++++
src/include/s6-dns/s6dns-fmt.h | 29 ++
src/include/s6-dns/s6dns-ip46.h | 29 ++
src/include/s6-dns/s6dns-message.h | 175 ++++++++++
src/include/s6-dns/s6dns-rci.h | 29 ++
src/include/s6-dns/s6dns-resolve.h | 242 +++++++++++++
src/include/s6-dns/s6dns.h | 18 +
src/include/s6-dns/skadns.h | 73 ++++
src/libs6dns/deps-lib/s6dns | 88 +++++
src/libs6dns/s6dns-message-internal.h | 12 +
src/libs6dns/s6dns_analyze_packet.c | 127 +++++++
src/libs6dns/s6dns_analyze_qtype_parse.c | 46 +++
src/libs6dns/s6dns_analyze_record.c | 37 ++
src/libs6dns/s6dns_analyze_record_a.c | 17 +
src/libs6dns/s6dns_analyze_record_aaaa.c | 17 +
src/libs6dns/s6dns_analyze_record_domain.c | 23 ++
src/libs6dns/s6dns_analyze_record_hinfo.c | 22 ++
src/libs6dns/s6dns_analyze_record_mx.c | 22 ++
src/libs6dns/s6dns_analyze_record_soa.c | 22 ++
src/libs6dns/s6dns_analyze_record_srv.c | 22 ++
src/libs6dns/s6dns_analyze_record_strings.c | 23 ++
src/libs6dns/s6dns_analyze_record_unknown.c | 25 ++
src/libs6dns/s6dns_analyze_rtypetable.c | 20 ++
src/libs6dns/s6dns_constants_error.c | 23 ++
src/libs6dns/s6dns_constants_error_str.c | 11 +
src/libs6dns/s6dns_debug_dumpdt_post_recv.c | 14 +
src/libs6dns/s6dns_debug_dumpdt_post_send.c | 30 ++
src/libs6dns/s6dns_debug_dumpdt_pre_send.c | 59 ++++
src/libs6dns/s6dns_debug_dumpdt_stderr.c | 7 +
src/libs6dns/s6dns_debug_dumpdt_stdout.c | 7 +
src/libs6dns/s6dns_debughook_zero.c | 5 +
src/libs6dns/s6dns_domain_arpafromip4.c | 19 +
src/libs6dns/s6dns_domain_arpafromip6.c | 21 ++
src/libs6dns/s6dns_domain_decode.c | 30 ++
src/libs6dns/s6dns_domain_encode.c | 21 ++
src/libs6dns/s6dns_domain_encodelist.c | 11 +
src/libs6dns/s6dns_domain_fromstring.c | 30 ++
.../s6dns_domain_fromstring_noqualify_encode.c | 10 +
.../s6dns_domain_fromstring_qualify_encode.c | 10 +
src/libs6dns/s6dns_domain_noqualify.c | 14 +
src/libs6dns/s6dns_domain_qualify.c | 30 ++
src/libs6dns/s6dns_domain_tostring.c | 21 ++
src/libs6dns/s6dns_engine.c | 372 ++++++++++++++++++++
src/libs6dns/s6dns_engine_free.c | 11 +
src/libs6dns/s6dns_engine_freen.c | 8 +
src/libs6dns/s6dns_engine_here.c | 7 +
src/libs6dns/s6dns_engine_nextdeadline.c | 10 +
src/libs6dns/s6dns_engine_zero.c | 5 +
src/libs6dns/s6dns_fmt_domainlist.c | 25 ++
src/libs6dns/s6dns_fmt_hinfo.c | 15 +
src/libs6dns/s6dns_fmt_mx.c | 19 +
src/libs6dns/s6dns_fmt_soa.c | 44 +++
src/libs6dns/s6dns_fmt_srv.c | 29 ++
src/libs6dns/s6dns_message_counts_next.c | 12 +
src/libs6dns/s6dns_message_counts_pack.c | 12 +
src/libs6dns/s6dns_message_counts_unpack.c | 12 +
src/libs6dns/s6dns_message_counts_zero.c | 5 +
src/libs6dns/s6dns_message_get_domain.c | 11 +
src/libs6dns/s6dns_message_get_domain_internal.c | 47 +++
src/libs6dns/s6dns_message_get_hinfo.c | 9 +
src/libs6dns/s6dns_message_get_mx.c | 14 +
src/libs6dns/s6dns_message_get_soa.c | 19 +
src/libs6dns/s6dns_message_get_srv.c | 15 +
src/libs6dns/s6dns_message_get_string.c | 13 +
src/libs6dns/s6dns_message_get_string_internal.c | 16 +
src/libs6dns/s6dns_message_get_strings.c | 17 +
src/libs6dns/s6dns_message_header_pack.c | 12 +
src/libs6dns/s6dns_message_header_unpack.c | 18 +
src/libs6dns/s6dns_message_header_zero.c | 5 +
src/libs6dns/s6dns_message_parse.c | 37 ++
src/libs6dns/s6dns_message_parse_answer_a.c | 16 +
src/libs6dns/s6dns_message_parse_answer_aaaa.c | 16 +
src/libs6dns/s6dns_message_parse_answer_domain.c | 21 ++
src/libs6dns/s6dns_message_parse_answer_hinfo.c | 21 ++
src/libs6dns/s6dns_message_parse_answer_mx.c | 21 ++
src/libs6dns/s6dns_message_parse_answer_soa.c | 21 ++
src/libs6dns/s6dns_message_parse_answer_srv.c | 21 ++
src/libs6dns/s6dns_message_parse_answer_strings.c | 36 ++
src/libs6dns/s6dns_message_parse_getrr.c | 19 +
src/libs6dns/s6dns_message_parse_init.c | 13 +
src/libs6dns/s6dns_message_parse_next.c | 11 +
src/libs6dns/s6dns_message_parse_skipqd.c | 15 +
src/libs6dns/s6dns_rci_free.c | 10 +
src/libs6dns/s6dns_rci_here.c | 7 +
src/libs6dns/s6dns_rci_init.c | 173 +++++++++
src/libs6dns/s6dns_rci_zero.c | 7 +
src/libs6dns/s6dns_resolve_core.c | 16 +
src/libs6dns/s6dns_resolve_dpag.c | 20 ++
src/libs6dns/s6dns_resolve_mpag.c | 23 ++
src/libs6dns/s6dns_resolve_name4.c | 23 ++
src/libs6dns/s6dns_resolve_name6.c | 24 ++
src/libs6dns/s6dns_resolve_parse.c | 21 ++
src/libs6dns/s6dns_resolven_loop.c | 54 +++
src/libs6dns/s6dns_resolven_parse.c | 47 +++
src/libs6dns/s6dns_resolvenoq.c | 16 +
src/libs6dns/s6dns_resolvenoq_aaaaa.c | 50 +++
src/libs6dns/s6dns_resolveq.c | 89 +++++
src/libs6dns/s6dns_resolveq_aaaaa.c | 96 +++++
src/skadns/deps-exe/skadnsd | 4 +
src/skadns/deps-lib/skadns | 10 +
src/skadns/skadns_cancel.c | 23 ++
src/skadns/skadns_end.c | 24 ++
src/skadns/skadns_packet.c | 16 +
src/skadns/skadns_packetlen.c | 16 +
src/skadns/skadns_release.c | 26 ++
src/skadns/skadns_send.c | 41 +++
src/skadns/skadns_start.c | 10 +
src/skadns/skadns_startf.c | 12 +
src/skadns/skadns_update.c | 45 +++
src/skadns/skadns_zero.c | 5 +
src/skadns/skadnsd.c | 199 +++++++++++
tools/gen-deps.sh | 79 +++++
tools/install.sh | 64 ++++
195 files changed, 9639 insertions(+)
create mode 100644 .gitignore
create mode 100644 AUTHORS
create mode 100644 COPYING
create mode 100644 INSTALL
create mode 100644 Makefile
create mode 100644 README
create mode 100644 README.macosx
create mode 100644 README.solaris
create mode 100755 configure
create mode 100644 doc/getaddrinfo.html
create mode 100644 doc/index.html
create mode 100644 doc/libresolv.html
create mode 100644 doc/libs6dns/index.html
create mode 100644 doc/libs6dns/s6dns-domain.html
create mode 100644 doc/libs6dns/s6dns-engine.html
create mode 100644 doc/libs6dns/s6dns-fmt.html
create mode 100644 doc/libs6dns/s6dns-ip46.html
create mode 100644 doc/libs6dns/s6dns-message.html
create mode 100644 doc/libs6dns/s6dns-rci.html
create mode 100644 doc/libs6dns/s6dns-resolve.html
create mode 100644 doc/s6-dnsip4-filter.html
create mode 100644 doc/s6-dnsip4.html
create mode 100644 doc/s6-dnsip6-filter.html
create mode 100644 doc/s6-dnsip6.html
create mode 100644 doc/s6-dnsmx.html
create mode 100644 doc/s6-dnsname-filter.html
create mode 100644 doc/s6-dnsname.html
create mode 100644 doc/s6-dnsns.html
create mode 100644 doc/s6-dnsq.html
create mode 100644 doc/s6-dnsqr.html
create mode 100644 doc/s6-dnsqualify.html
create mode 100644 doc/s6-dnssoa.html
create mode 100644 doc/s6-dnssrv.html
create mode 100644 doc/s6-dnstxt.html
create mode 100644 doc/s6-randomip.html
create mode 100644 doc/skadns/index.html
create mode 100644 doc/skadns/skadnsd.html
create mode 100644 doc/upgrade.html
create mode 100644 package/deps-build
create mode 100644 package/deps.mak
create mode 100644 package/info
create mode 100644 package/modes
create mode 100644 package/targets.mak
create mode 100755 patch-for-solaris
create mode 100644 src/clients/deps-exe/s6-dnsip4
create mode 100644 src/clients/deps-exe/s6-dnsip4-filter
create mode 100644 src/clients/deps-exe/s6-dnsip6
create mode 100644 src/clients/deps-exe/s6-dnsip6-filter
create mode 100644 src/clients/deps-exe/s6-dnsmx
create mode 100644 src/clients/deps-exe/s6-dnsname
create mode 100644 src/clients/deps-exe/s6-dnsname-filter
create mode 100644 src/clients/deps-exe/s6-dnsns
create mode 100644 src/clients/deps-exe/s6-dnsq
create mode 100644 src/clients/deps-exe/s6-dnsqr
create mode 100644 src/clients/deps-exe/s6-dnsqualify
create mode 100644 src/clients/deps-exe/s6-dnssoa
create mode 100644 src/clients/deps-exe/s6-dnssrv
create mode 100644 src/clients/deps-exe/s6-dnstxt
create mode 100644 src/clients/deps-exe/s6-randomip
create mode 100644 src/clients/deps-lib/s6dnsgenericfilter
create mode 100644 src/clients/s6-dnsip4-filter.c
create mode 100644 src/clients/s6-dnsip4.c
create mode 100644 src/clients/s6-dnsip6-filter.c
create mode 100644 src/clients/s6-dnsip6.c
create mode 100644 src/clients/s6-dnsmx.c
create mode 100644 src/clients/s6-dnsname-filter.c
create mode 100644 src/clients/s6-dnsname.c
create mode 100644 src/clients/s6-dnsns.c
create mode 100644 src/clients/s6-dnsq.c
create mode 100644 src/clients/s6-dnsqr.c
create mode 100644 src/clients/s6-dnsqualify.c
create mode 100644 src/clients/s6-dnssoa.c
create mode 100644 src/clients/s6-dnssrv.c
create mode 100644 src/clients/s6-dnstxt.c
create mode 100644 src/clients/s6-randomip.c
create mode 100644 src/clients/s6dns-generic-filter.h
create mode 100644 src/clients/s6dns_generic_filter_main.c
create mode 100644 src/clients/s6dns_namescanner.c
create mode 100644 src/include/s6-dns/s6dns-analyze.h
create mode 100644 src/include/s6-dns/s6dns-constants.h
create mode 100644 src/include/s6-dns/s6dns-debug.h
create mode 100644 src/include/s6-dns/s6dns-domain.h
create mode 100644 src/include/s6-dns/s6dns-engine.h
create mode 100644 src/include/s6-dns/s6dns-fmt.h
create mode 100644 src/include/s6-dns/s6dns-ip46.h
create mode 100644 src/include/s6-dns/s6dns-message.h
create mode 100644 src/include/s6-dns/s6dns-rci.h
create mode 100644 src/include/s6-dns/s6dns-resolve.h
create mode 100644 src/include/s6-dns/s6dns.h
create mode 100644 src/include/s6-dns/skadns.h
create mode 100755 src/libs6dns/deps-lib/s6dns
create mode 100644 src/libs6dns/s6dns-message-internal.h
create mode 100644 src/libs6dns/s6dns_analyze_packet.c
create mode 100644 src/libs6dns/s6dns_analyze_qtype_parse.c
create mode 100644 src/libs6dns/s6dns_analyze_record.c
create mode 100644 src/libs6dns/s6dns_analyze_record_a.c
create mode 100644 src/libs6dns/s6dns_analyze_record_aaaa.c
create mode 100644 src/libs6dns/s6dns_analyze_record_domain.c
create mode 100644 src/libs6dns/s6dns_analyze_record_hinfo.c
create mode 100644 src/libs6dns/s6dns_analyze_record_mx.c
create mode 100644 src/libs6dns/s6dns_analyze_record_soa.c
create mode 100644 src/libs6dns/s6dns_analyze_record_srv.c
create mode 100644 src/libs6dns/s6dns_analyze_record_strings.c
create mode 100644 src/libs6dns/s6dns_analyze_record_unknown.c
create mode 100644 src/libs6dns/s6dns_analyze_rtypetable.c
create mode 100644 src/libs6dns/s6dns_constants_error.c
create mode 100644 src/libs6dns/s6dns_constants_error_str.c
create mode 100644 src/libs6dns/s6dns_debug_dumpdt_post_recv.c
create mode 100644 src/libs6dns/s6dns_debug_dumpdt_post_send.c
create mode 100644 src/libs6dns/s6dns_debug_dumpdt_pre_send.c
create mode 100644 src/libs6dns/s6dns_debug_dumpdt_stderr.c
create mode 100644 src/libs6dns/s6dns_debug_dumpdt_stdout.c
create mode 100644 src/libs6dns/s6dns_debughook_zero.c
create mode 100644 src/libs6dns/s6dns_domain_arpafromip4.c
create mode 100644 src/libs6dns/s6dns_domain_arpafromip6.c
create mode 100644 src/libs6dns/s6dns_domain_decode.c
create mode 100644 src/libs6dns/s6dns_domain_encode.c
create mode 100644 src/libs6dns/s6dns_domain_encodelist.c
create mode 100644 src/libs6dns/s6dns_domain_fromstring.c
create mode 100644 src/libs6dns/s6dns_domain_fromstring_noqualify_encode.c
create mode 100644 src/libs6dns/s6dns_domain_fromstring_qualify_encode.c
create mode 100644 src/libs6dns/s6dns_domain_noqualify.c
create mode 100644 src/libs6dns/s6dns_domain_qualify.c
create mode 100644 src/libs6dns/s6dns_domain_tostring.c
create mode 100644 src/libs6dns/s6dns_engine.c
create mode 100644 src/libs6dns/s6dns_engine_free.c
create mode 100644 src/libs6dns/s6dns_engine_freen.c
create mode 100644 src/libs6dns/s6dns_engine_here.c
create mode 100644 src/libs6dns/s6dns_engine_nextdeadline.c
create mode 100644 src/libs6dns/s6dns_engine_zero.c
create mode 100644 src/libs6dns/s6dns_fmt_domainlist.c
create mode 100644 src/libs6dns/s6dns_fmt_hinfo.c
create mode 100644 src/libs6dns/s6dns_fmt_mx.c
create mode 100644 src/libs6dns/s6dns_fmt_soa.c
create mode 100644 src/libs6dns/s6dns_fmt_srv.c
create mode 100644 src/libs6dns/s6dns_message_counts_next.c
create mode 100644 src/libs6dns/s6dns_message_counts_pack.c
create mode 100644 src/libs6dns/s6dns_message_counts_unpack.c
create mode 100644 src/libs6dns/s6dns_message_counts_zero.c
create mode 100644 src/libs6dns/s6dns_message_get_domain.c
create mode 100644 src/libs6dns/s6dns_message_get_domain_internal.c
create mode 100644 src/libs6dns/s6dns_message_get_hinfo.c
create mode 100644 src/libs6dns/s6dns_message_get_mx.c
create mode 100644 src/libs6dns/s6dns_message_get_soa.c
create mode 100644 src/libs6dns/s6dns_message_get_srv.c
create mode 100644 src/libs6dns/s6dns_message_get_string.c
create mode 100644 src/libs6dns/s6dns_message_get_string_internal.c
create mode 100644 src/libs6dns/s6dns_message_get_strings.c
create mode 100644 src/libs6dns/s6dns_message_header_pack.c
create mode 100644 src/libs6dns/s6dns_message_header_unpack.c
create mode 100644 src/libs6dns/s6dns_message_header_zero.c
create mode 100644 src/libs6dns/s6dns_message_parse.c
create mode 100644 src/libs6dns/s6dns_message_parse_answer_a.c
create mode 100644 src/libs6dns/s6dns_message_parse_answer_aaaa.c
create mode 100644 src/libs6dns/s6dns_message_parse_answer_domain.c
create mode 100644 src/libs6dns/s6dns_message_parse_answer_hinfo.c
create mode 100644 src/libs6dns/s6dns_message_parse_answer_mx.c
create mode 100644 src/libs6dns/s6dns_message_parse_answer_soa.c
create mode 100644 src/libs6dns/s6dns_message_parse_answer_srv.c
create mode 100644 src/libs6dns/s6dns_message_parse_answer_strings.c
create mode 100644 src/libs6dns/s6dns_message_parse_getrr.c
create mode 100644 src/libs6dns/s6dns_message_parse_init.c
create mode 100644 src/libs6dns/s6dns_message_parse_next.c
create mode 100644 src/libs6dns/s6dns_message_parse_skipqd.c
create mode 100644 src/libs6dns/s6dns_rci_free.c
create mode 100644 src/libs6dns/s6dns_rci_here.c
create mode 100644 src/libs6dns/s6dns_rci_init.c
create mode 100644 src/libs6dns/s6dns_rci_zero.c
create mode 100644 src/libs6dns/s6dns_resolve_core.c
create mode 100644 src/libs6dns/s6dns_resolve_dpag.c
create mode 100644 src/libs6dns/s6dns_resolve_mpag.c
create mode 100644 src/libs6dns/s6dns_resolve_name4.c
create mode 100644 src/libs6dns/s6dns_resolve_name6.c
create mode 100644 src/libs6dns/s6dns_resolve_parse.c
create mode 100644 src/libs6dns/s6dns_resolven_loop.c
create mode 100644 src/libs6dns/s6dns_resolven_parse.c
create mode 100644 src/libs6dns/s6dns_resolvenoq.c
create mode 100644 src/libs6dns/s6dns_resolvenoq_aaaaa.c
create mode 100644 src/libs6dns/s6dns_resolveq.c
create mode 100644 src/libs6dns/s6dns_resolveq_aaaaa.c
create mode 100755 src/skadns/deps-exe/skadnsd
create mode 100644 src/skadns/deps-lib/skadns
create mode 100644 src/skadns/skadns_cancel.c
create mode 100644 src/skadns/skadns_end.c
create mode 100644 src/skadns/skadns_packet.c
create mode 100644 src/skadns/skadns_packetlen.c
create mode 100644 src/skadns/skadns_release.c
create mode 100644 src/skadns/skadns_send.c
create mode 100644 src/skadns/skadns_start.c
create mode 100644 src/skadns/skadns_startf.c
create mode 100644 src/skadns/skadns_update.c
create mode 100644 src/skadns/skadns_zero.c
create mode 100644 src/skadns/skadnsd.c
create mode 100755 tools/gen-deps.sh
create mode 100755 tools/install.sh
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5c6415e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.o
+*.a
+*.lo
+*.so
+*.so.*
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..b3b2e27
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,6 @@
+Main author:
+ Laurent Bercot
+
+Thanks to:
+ Dan J. Bernstein
+ Vallo Kallaste
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..63309ba
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,13 @@
+Copyright (c) 2011-2014 Laurent Bercot
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..1978a5a
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,132 @@
+Build Instructions
+------------------
+
+* Requirements
+ ------------
+
+ - A POSIX-compliant C development environment
+ - GNU make version 3.81 or later
+ - skalibs version 2.0.0.0 or later: http://skarnet.org/software/skalibs/
+
+ This software will run on any operating system that implements
+POSIX.1-2008, available at:
+ http://pubs.opengroup.org/onlinepubs/9699919799/
+
+
+* Standard usage
+ --------------
+
+ ./configure && make && sudo make install
+
+ will work for most users.
+ It will install the binaries in /bin and the static libraries in
+/usr/lib/s6-dns.
+
+ You can strip the binaries and libraries of their extra symbols via
+"make strip" before the "make install" phase. It will shave a few bytes
+off them.
+
+
+* Customization
+ -------------
+
+ You can customize paths via flags given to configure.
+ See ./configure --help for a list of all available configure options.
+
+
+* Environment variables
+ ---------------------
+
+ Controlling a build process via environment variables is a big and
+dangerous hammer. You should try and pass flags to configure instead;
+nevertheless, the standard environment variables are recognized.
+
+ The value of the CROSS_COMPILE environment variable will prefix the
+building tools' names. The --enable-cross option is preferred, see
+"Cross-compilation" below.
+
+ If the CC environment variable is set, its value will override compiler
+detection by configure.
+
+ The values of CFLAGS, CPPFLAGS and LDFLAGS will be appended to flags
+auto-detected by configure. To entirely override the flags set by
+configure, use make -e.
+
+ The value of LDLIBS will be appended by make to command lines that link
+an executable, even without the -e option.
+
+ The Makefile supports the DESTDIR convention for staging.
+
+
+* Shared libraries
+ ----------------
+
+ Software from skarnet.org is small enough that shared libraries are
+generally not worth using. Static linking is simpler and incurs less
+runtime overhead and less points of failure: so by default, shared
+libraries are not built and binaries are linked against the static
+versions of the skarnet.org libraries. Nevertheless, you can:
+ * build shared libraries: --enable-shared
+ * link binaries against shared libraries: --disable-allstatic
+
+
+* Static binaries
+ ---------------
+
+ By default, binaries are linked against static versions of all the
+libraries they depend on, except for the libc. You can enforce
+linking against the static libc with --enable-static-libc.
+
+ (If you are using a GNU/Linux system, be aware that the GNU libc
+behaves badly with static linking and produces huge executables,
+which is why it is not the default. Other libcs are better suited
+to static linking, for instance musl: http://musl-libc.org/)
+
+
+* Cross-compilation
+ -----------------
+
+ skarnet.org packages centralize all the difficulty of
+cross-compilation in one place: skalibs. Once you have
+cross-compiled skalibs, the rest is easy.
+
+ Use the --enable-cross=PREFIX option to configure, or simply
+--enable-cross if your default toolchain is a cross-compiling
+toolchain. And make sure to use the correct version of skalibs
+for your target, and the correct sysdeps directory, making use
+of the --with-include, --with-lib, --with-dynlib and --with-sysdeps
+options as necessary.
+
+
+* The slashpackage convention
+ ---------------------------
+
+ The slashpackage convention (http://cr.yp.to/slashpackage.html)
+is a package installation scheme that provides a few guarantees
+over other conventions such as the FHS, for instance fixed
+absolute pathnames. skarnet.org packages support it: use the
+--enable-slashpackage option to configure, or
+--enable-slashpackage=DIR for a prefixed DIR/package tree.
+This option will activate slashpackage support during the build
+and set slashpackage-compatible installation directories.
+Other options setting individual installation directories will be
+ignored.
+
+ When using slashpackage, two additional Makefile targets are
+available after "make install":
+ - "make update" changes the default version of the software to the
+freshly installed one. (This is useful when you have several installed
+versions of the same software, which slashpackage supports.)
+ - "make -L global-links" adds links from /command and /library.so to the
+default version of the binaries and shared libraries. The "-L" option to
+make is necessary because targets are symbolic links, and the default make
+behaviour is to check the pointed file's timestamp and not the symlink's
+timestamp.
+
+
+* Out-of-tree builds
+ ------------------
+
+ skarnet.org packages do not support out-of-tree builds. They
+are small, so it does not cost much to duplicate the entire
+source tree if parallel builds are needed.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7d8901c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,121 @@
+#
+# This Makefile requires GNU make.
+#
+# Do not make changes here.
+# Use the included .mak files.
+#
+
+it: all
+
+CC = $(error Please use ./configure first)
+
+include package/targets.mak
+include package/deps.mak
+-include config.mak
+
+version_m := $(basename $(version))
+version_M := $(basename $(version_m))
+version_l := $(basename $(version_M))
+CPPFLAGS_ALL := -iquote src/include-local -Isrc/include $(CPPFLAGS)
+CFLAGS_ALL := $(CFLAGS) -pipe -Wall
+CFLAGS_SHARED := -fPIC
+LDFLAGS_ALL := $(LDFLAGS)
+LDFLAGS_SHARED := -shared
+LDLIBS_ALL := $(LDLIBS)
+REALCC = $(CROSS_COMPILE)$(CC)
+AR := $(CROSS_COMPILE)ar
+RANLIB := $(CROSS_COMPILE)ranlib
+STRIP := $(CROSS_COMPILE)strip
+INSTALL := ./tools/install.sh
+
+ALL_BINS := $(LIBEXEC_TARGETS) $(BIN_TARGETS) $(SBIN_TARGETS)
+ALL_LIBS := $(SHARED_LIBS) $(STATIC_LIBS)
+ALL_INCLUDES := $(wildcard src/include/$(package)/*.h)
+
+all: $(ALL_LIBS) $(ALL_BINS) $(ALL_INCLUDES)
+
+clean:
+ @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(wildcard src/*/*.o src/*/*.lo)
+
+distclean: clean
+ @exec rm -f config.mak src/include/${package}/config.h
+
+tgz: distclean
+ @. package/info && \
+ rm -rf /tmp/$$package-$$version && \
+ cp -a . /tmp/$$package-$$version && \
+ cd /tmp && \
+ tar -zpcv --owner=0 --group=0 --numeric-owner --exclude=.git* -f /tmp/$$package-$$version.tar.gz $$package-$$version && \
+ exec rm -rf /tmp/$$package-$$version
+
+strip: $(ALL_LIBS) $(ALL_BINS)
+ifneq ($(strip $(ALL_LIBS)),)
+ exec ${STRIP} -x -R .note -R .comment -R .note.GNU-stack $(ALL_LIBS)
+endif
+ifneq ($(strip $(ALL_BINS)),)
+ exec ${STRIP} -R .note -R .comment -R .note.GNU-stack $(ALL_BINS)
+endif
+
+install: install-dynlib install-libexec install-bin install-sbin install-lib install-include
+install-dynlib: $(SHARED_LIBS:lib%.so=$(DESTDIR)$(dynlibdir)/lib%.so)
+install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%)
+install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%)
+install-sbin: $(SBIN_TARGETS:%=$(DESTDIR)$(sbindir)/%)
+install-lib: $(STATIC_LIBS:lib%.a=$(DESTDIR)$(libdir)/lib%.a)
+install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h)
+
+ifneq ($(exthome),)
+
+update:
+ exec $(INSTALL) -l $(notdir $(home)) $(DESTDIR)$(exthome)
+
+global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so=$(DESTDIR)$(sproot)/library.so/lib%.so) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(SBIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%)
+
+$(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/%
+ exec $(INSTALL) -D -l ..$(exthome)/command/$(
+
+ Please use the mailing-list for
+questions about s6-dns.
diff --git a/README.macosx b/README.macosx
new file mode 100644
index 0000000..d71a096
--- /dev/null
+++ b/README.macosx
@@ -0,0 +1,4 @@
+
+ This package will compile and run on Darwin (MacOS X), but the building of
+shared libraries is not supported.
+ Make sure you use the --disable-shared option to configure.
diff --git a/README.solaris b/README.solaris
new file mode 100644
index 0000000..91a5b26
--- /dev/null
+++ b/README.solaris
@@ -0,0 +1,12 @@
+
+ This package assumes the existence of a POSIX shell in /bin/sh.
+ On Solaris, /bin/sh is not POSIX. Most versions of Solaris provide
+a POSIX shell in /usr/xpg4/bin/sh.
+
+ To compile this package on Solaris, you will need to run
+
+ ./patch-for-solaris
+
+ before you run ./configure. This script will change the #! invocation
+of the configure script and various tools so that a POSIX shell is used
+for the compilation process.
diff --git a/configure b/configure
new file mode 100755
index 0000000..5ca8165
--- /dev/null
+++ b/configure
@@ -0,0 +1,378 @@
+#!/bin/sh
+
+usage () {
+cat </dev/null 2>&1 && { echo "$1" ; return 0 ; }
+$1
+EOF
+ echo "$1" | sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/" -e "s#^'\([-[:alnum:]_,./:]*\)=\(.*\)\$#\1='\2#" -e "s|\*/|* /|g"
+}
+
+fail () {
+ echo "$*"
+ exit 1
+}
+
+fnmatch () {
+ eval "case \"\$2\" in $1) return 0 ;; *) return 1 ;; esac"
+}
+
+cmdexists () {
+ type "$1" >/dev/null 2>&1
+}
+
+trycc () {
+ test -z "$CC_AUTO" && cmdexists "$1" && CC_AUTO=$1
+}
+
+stripdir () {
+ while eval "fnmatch '*/' \"\${$1}\"" ; do
+ eval "$1=\${$1%/}"
+ done
+}
+
+tryflag () {
+ echo "checking whether compiler accepts $2 ..."
+ echo "typedef int x;" > "$tmpc"
+ if $CC_AUTO $CPPFLAGS_AUTO $CFLAGS_AUTO "$2" -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
+ echo " ... yes"
+ eval "$1=\"\${$1} \$2\""
+ eval "$1=\${$1# }"
+ return 0
+ else
+ echo " ... no"
+ return 1
+ fi
+}
+
+tryldflag () {
+ echo "checking whether linker accepts $2 ..."
+ echo "typedef int x;" > "$tmpc"
+ if $CC_AUTO $CFLAGS_AUTO $LDFLAGS_AUTO -nostdlib "$2" -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
+ echo " ... yes"
+ eval "$1=\"\${$1} \$2\""
+ eval "$1=\${$1# }"
+ return 0
+ else
+ echo " ... no"
+ return 1
+ fi
+}
+
+
+# Actual script
+
+. package/info
+
+CC_AUTO="$CC"
+CFLAGS_AUTO="$CFLAGS"
+CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=600 $CPPFLAGS"
+LDFLAGS_AUTO="$LDFLAGS"
+LDFLAGS_NOSHARED=
+prefix=
+exec_prefix='$prefix'
+dynlibdir='$prefix/lib'
+libexecdir='$exec_prefix/libexec'
+bindir='$exec_prefix/bin'
+sbindir='$exec_prefix/sbin'
+libdir='$prefix/usr/lib/'$package
+includedir='$prefix/usr/include'
+sysdeps='$prefix/usr/lib/skalibs/sysdeps'
+manualsysdeps=false
+shared=false
+static=true
+slashpackage=false
+sproot=
+home=
+exthome=
+allstatic=true
+evenmorestatic=false
+addincpath=''
+addlibspath=''
+addlibdpath=''
+vpaths=''
+vpathd=''
+cross="$CROSS_COMPILE"
+
+for arg ; do
+ case "$arg" in
+ --help) usage ;;
+ --prefix=*) prefix=${arg#*=} ;;
+ --exec-prefix=*) exec_prefix=${arg#*=} ;;
+ --dynlibdir=*) dynlibdir=${arg#*=} ;;
+ --libexecdir=*) libexecdir=${arg#*=} ;;
+ --bindir=*) bindir=${arg#*=} ;;
+ --sbindir=*) sbindir=${arg#*=} ;;
+ --libdir=*) libdir=${arg#*=} ;;
+ --includedir=*) includedir=${arg#*=} ;;
+ --with-sysdeps=*) sysdeps=${arg#*=} manualsysdeps=true ;;
+ --with-include=*) var=${arg#*=} ; stripdir var ; addincpath="$addincpath -I$var" ;;
+ --with-lib=*) var=${arg#*=} ; stripdir var ; addlibspath="$addlibspath -L$var" ; vpaths="$vpaths $var" ;;
+ --with-dynlib=*) var=${arg#*=} ; stripdir var ; addlibdpath="$addlibdpath -L$var" ; vpathd="$vpathd $var" ;;
+ --enable-shared|--enable-shared=yes) shared=true ;;
+ --disable-shared|--enable-shared=no) shared=false ;;
+ --enable-static|--enable-static=yes) static=true ;;
+ --disable-static|--enable-static=no) static=false ;;
+ --enable-allstatic|--enable-allstatic=yes) allstatic=true ;;
+ --disable-allstatic|--enable-allstatic=no) allstatic=false ;;
+ --enable-static-libc|--enable-static-libc=yes) evenmorestatic=true ;;
+ --disable-static-libc|--enable-static-libc=no) evenmorestatic=false ;;
+ --enable-slashpackage=*) sproot=${arg#*=} ; slashpackage=true ; ;;
+ --enable-slashpackage) sproot= ; slashpackage=true ;;
+ --disable-slashpackage) sproot= ; slashpackage=false ;;
+ --enable-cross=*) cross=${arg#*=} ;;
+ --enable-cross) cross= ;;
+ --disable-cross) cross= ;;
+ --enable-*|--disable-*|--with-*|--without-*|--*dir=*|--build=*) ;;
+ --host=*|--target=*) target=${arg#*=} ;;
+ -* ) echo "$0: unknown option $arg" ;;
+ *=*) ;;
+ *) target=$arg ;;
+ esac
+done
+
+for i in prefix exec_prefix dynlibdir libexecdir bindir sbindir libdir includedir linkdynlibdir linkbindir linksbindir sysdeps sproot skalibs ; do
+ eval tmp=\${$i}
+ eval $i=$tmp
+ stripdir $i
+done
+
+# Get usable temp filenames
+i=0
+set -C
+while : ; do
+ i=$(($i+1))
+ tmpc="./tmp-configure-$$-$PPID-$i.c"
+ tmpe="./tmp-configure-$$-$PPID-$i.tmp"
+ 2>|/dev/null > "$tmpc" && break
+ 2>|/dev/null > "$tmpe" && break
+ test "$i" -gt 50 && fail "$0: cannot create temporary files"
+done
+set +C
+trap 'rm -f "$tmpc" "$tmpe"' EXIT ABRT INT QUIT TERM HUP
+
+# Set slashpackage values
+if $slashpackage ; then
+ home=${sproot}/package/${category}/${package}-${version}
+ exthome=${sproot}/package/${category}/${package}
+ if $manualsysdeps ; then
+ :
+ else
+ sysdeps=${sproot}/package/prog/skalibs/sysdeps
+ fi
+ binprefix=${home}/command
+ extbinprefix=${exthome}/command
+ dynlibdir=${home}/library.so
+ libexecdir=$binprefix
+ bindir=$binprefix
+ sbindir=$binprefix
+ libdir=${home}/library
+ includedir=${home}/include
+ while read dep ; do
+ addincpath="$addincpath -I${sproot}${dep}/include"
+ vpaths="$vpaths ${sproot}${dep}/library"
+ addlibspath="$addlibspath -L${sproot}${dep}/library"
+ if $allstatic ; then : ; else
+ vpathd="$vpathd ${sproot}${dep}/library.so"
+ addlibdpath="$addlibdpath -L${sproot}${dep}/library.so"
+ fi
+ done < package/deps-build
+fi
+
+# Find a C compiler to use
+echo "checking for C compiler..."
+trycc ${cross}gcc
+trycc ${cross}c99
+trycc ${cross}cc
+test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; }
+echo " ... $CC_AUTO"
+echo "checking whether C compiler works... "
+echo "typedef int x;" > "$tmpc"
+if $CC_AUTO $CPPFLAGS_AUTO $CFLAGS_AUTO -c -o /dev/null "$tmpc" 2>"$tmpe" ; then
+ echo " ... yes"
+else
+ echo " ... no. Compiler output follows:"
+ cat < "$tmpe"
+ exit 1
+fi
+
+echo "checking target system type..."
+test -n "$target" || target=$($CC_AUTO -dumpmachine 2>/dev/null) || target=unknown
+echo " ... $target"
+if test ! -d $sysdeps || test ! -f $sysdeps/target ; then
+ echo "$0: error: $sysdeps is not a valid sysdeps directory"
+ exit 1
+fi
+if [ "x$target" != "x$(cat $sysdeps/target)" ] ; then
+ echo "$0: error: target $target does not match the contents of $sysdeps/target"
+ exit 1
+fi
+
+rt_lib=$(cat $sysdeps/rt.lib)
+socket_lib=$(cat $sysdeps/socket.lib)
+sysclock_lib=$(cat $sysdeps/sysclock.lib)
+tainnow_lib=$(cat $sysdeps/tainnow.lib)
+util_lib=$(cat $sysdeps/util.lib)
+
+tryflag CFLAGS_AUTO -std=c99
+tryflag CFLAGS_AUTO -fomit-frame-pointer
+tryflag CFLAGS_AUTO -fno-exceptions
+tryflag CFLAGS_AUTO -fno-unwind-tables
+tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables
+tryflag CFLAGS_AUTO -Wa,--noexecstack
+tryflag CFLAGS_AUTO -fno-stack-protector
+tryflag CPPFLAGS_AUTO -Werror=implicit-function-declaration
+tryflag CPPFLAGS_AUTO -Werror=implicit-int
+tryflag CPPFLAGS_AUTO -Werror=pointer-sign
+tryflag CPPFLAGS_AUTO -Werror=pointer-arith
+
+if $evenmorestatic ; then
+ LDFLAGS_NOSHARED=-static
+fi
+
+if $shared ; then
+ tryldflag LDFLAGS_AUTO -Wl,--hash-style=both
+fi
+
+if test -z "$vpaths" ; then
+ while read dep ; do
+ base=$(basename $dep) ;
+ vpaths="$vpaths /usr/lib/$base"
+ addlibspath="$addlibspath -L/usr/lib/$base"
+ done < package/deps-build
+fi
+
+CPPFLAGS_AUTO="$CPPFLAGS_AUTO $addincpath"
+LDFLAGS_AUTO="$LDFLAGS_AUTO $addlibspath"
+$allstatic || LDFLAGS_AUTO="$LDFLAGS_AUTO $addlibdpath"
+
+echo "creating config.mak..."
+cmdline=$(quote "$0")
+for i ; do cmdline="$cmdline $(quote "$i")" ; done
+exec 3>&1 1>config.mak
+cat << EOF
+# This file was generated by:
+# $cmdline
+# Any changes made here will be lost if configure is re-run.
+
+target := $target
+package := $package
+prefix := $prefix
+exec_prefix := $exec_prefix
+dynlibdir := $dynlibdir
+libexecdir := $libexecdir
+bindir := $bindir
+sbindir := $sbindir
+libdir := $libdir
+includedir := $includedir
+sysdeps := $sysdeps
+slashpackage := $slashpackage
+sproot := $sproot
+version := $version
+home := $home
+exthome := $exthome
+RT_LIB := ${rt_lib}
+SOCKET_LIB := ${socket_lib}
+SYSCLOCK_LIB := ${sysclock_lib}
+TAINNOW_LIB := ${tainnow_lib}
+UTIL_LIB := ${util_lib}
+
+CC := $CC_AUTO
+CFLAGS := $CFLAGS_AUTO
+CPPFLAGS := $CPPFLAGS_AUTO
+LDFLAGS := $LDFLAGS_AUTO
+LDFLAGS_NOSHARED := $LDFLAGS_NOSHARED
+CROSS_COMPILE := $cross
+
+vpath lib%a$vpaths
+EOF
+if $allstatic ; then
+ echo ".LIBPATTERNS := lib%.a"
+ vpathd=
+fi
+ echo "vpath lib%.so$vpathd"
+echo
+$static || echo "STATIC_LIBS :="
+$shared || echo "SHARED_LIBS :="
+exec 1>&3 3>&-
+echo " ... done."
+
+echo "creating src/include/${package}/config.h..."
+mkdir -p -m 0755 src/include/${package}
+exec 3>&1 1> src/include/${package}/config.h
+cat <&3 3>&-
+echo " ... done."
diff --git a/doc/getaddrinfo.html b/doc/getaddrinfo.html
new file mode 100644
index 0000000..da0469c
--- /dev/null
+++ b/doc/getaddrinfo.html
@@ -0,0 +1,94 @@
+
+
+
+
+ s6-dns: the problem with getaddrinfo()
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The problem with getaddrinfo()
+
+
+ The standard C library provides an API to perform name
+resolution:
+getaddrinfo(),
+formerly gethostbyname(). However, for DNS resolution as well as
+implementation in the libc, this interface is very impractical, to the point of
+being unusable. Here are a few reasons why.
+
+
+ getaddrinfo() performs NSS resolution, not DNS resolution.
+
+
+ I explained this point in a message to the
+Busybox mailing-list. You can
+read
+the post here.
+(There is a mistake in that post about /etc/nsswitch.conf and
+/etc/host.conf syntax; the following two messages in the thread
+correct that mistake.)
+
+
+
+ TLDR: depending on the machine configuration, it is possible that
+getaddrinfo() will not use DNS at all.
+
+
+ It is unboundedly synchronous.
+
+
+ DNS resolution performs network I/O, which can take a non-negligible
+amount of time. getaddrinfo() is a blocking call and there is
+no way to specify a timeout to make it return early, so it may block
+indefinitely. This is bad design.
+
+
+
+ Also, network operations being asynchronous by nature, even a
+synchronous API should provide a way to perform several queries at
+once and return when one of them, or all of them, get an answer.
+getaddrinfo() does not even offer that.
+
+
+ It focuses on the wrong details.
+
+
+ Because it's generic, getaddrinfo() is cumbersome to use.
+ The data structures are impractical, requiring the user to fill in
+information that is irrelevant to DNS resolution. The details of the
+network transport protocols are of no interest to the user who just
+wants answers to his DNS queries!
+
+
+
+ But at the same time, getaddrinfo() does not allow the
+user to provide the details he wants or refine his search. It's a very
+basic and monolithic entry point, with no DNS-specific knobs. For
+instance, only A and AAAA queries are supported, which is clearly
+insufficient.
+
+
+ Conclusion
+
+
+getaddrinfo() is a toy interface. For any half-serious DNS work,
+another API must be used.
+
+
+
+ Most people who need a real DNS client library use BIND's libresolv.
+This page explains what is wrong with it,
+and what s6-dns tries to do better.
+
+
+
+
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 0000000..5263664
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,175 @@
+
+
+
+
+ s6-dns - a complete DNS client suite
+
+
+
+
+
+
+
+Software
+skarnet.org
+
+
+ s6-dns
+
+ What is it ?
+
+
+ s6-dns is a suite of DNS client programs and libraries for Unix
+systems, as an alternative to the BIND, djbdns or other DNS clients.
+
+
+
+ s6-dns may include its own series of DNS caches and servers at some
+point in the future.
+
+
+
+
+
+
+
+
+ Installation
+
+ Requirements
+
+
+ - A POSIX-compliant system with a standard C development environment
+ - GNU make, version 3.81 or later
+ - skalibs version
+2.0.0.0 or later
+
+
+ Licensing
+
+
+ s6-dns is free software. It is available under the
+ISC license.
+
+
+ Download
+
+
+
+ Compilation
+
+
+ - See the enclosed INSTALL file for installation details.
+
+
+ Upgrade notes
+
+
+ - This page lists the differences to be aware of between
+the previous versions of s6-dns and the current one.
+
+
+ Reference
+
+ Commands
+
+
+ All these commands exit 111 if they encounter a temporary error or
+hardware error, and
+100 if they encounter a permanent error - such as a misuse. Short-lived
+commands exit 0 on success. Other exit codes are documented in the
+relevant page.
+
+
+ Command-line DNS clients programs
+
+
+
+ Filtering tools
+
+
+
+ Command-line qualification
+
+
+
+ DNS analysis and debug tools
+
+
+
+ Miscellaneous utilities
+
+
+
+
+ Libraries
+
+ Protocol implementation and synchronous resolution
+
+
+
+ Asynchronous resolution
+
+
+
+
+
+
+ Related resources
+
+
+ s6-dns discussion
+
+
+
+ Similar work
+
+
+ - BIND is the most widely
+used DNS software suite on the Internet. It's also arguably the most
+buggy,
+convoluted and impossible to understand.
+ - djbdns is DJB's DNS suite.
+It works very well, but is unfortunately unmaintained by the author. s6-dns
+follows the
+same design principles.
+
+
+
+
diff --git a/doc/libresolv.html b/doc/libresolv.html
new file mode 100644
index 0000000..7a9fd31
--- /dev/null
+++ b/doc/libresolv.html
@@ -0,0 +1,140 @@
+
+
+
+
+ s6-dns: the problem with libresolv
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The problem with libresolv
+
+
+ The BIND name server software comes with its own client library,
+named libresolv.
+
+
+
+ As can be expected from an ISC product, libresolv is not good software.
+Here are a few reasons why.
+
+
+ libresolv's security model is flawed.
+
+
+ The same people who wrote BIND wrote libresolv. That is the amount of
+trust you can place in libresolv. Ten years ago, the security status
+of libresolv looked like
+this. I am not
+confident that is has improved: bugs in the software may have been
+fixed, but new ones will appear, and most importantly, the security
+management policy at ISC is still the same: security holes will be
+denied instead of acknowledged and worked upon.
+
+
+
+ If you find a bug, and a fortiori a security hole, in
+s6-dns, you can be sure it will be fixed promptly with apologies
+from the author. skarnet.org doesn't do obfuscation, and never lets
+politics get in the way of technical quality.
+
+
+ libresolv is unboundedly synchronous.
+
+
+ You'd expect a real DNS client library to do better in this aspect
+than getaddrinfo(), but no: libresolv's
+function calls are still purely synchronous and may uncontrollably
+block if the network is unresponsive.
+
+
+
+ Additionally, libresolv only provides a synchronous
+interface to clients. Despite the fundamentally asynchronous nature
+of DNS, and the need to implement asynchronous primitives
+internally, only blocking calls are made available in the API.
+This forces users to stack yet another piece of software on top
+of their dependencies if they need asynchronous DNS resolution.
+
+
+
+ libs6dns provides several layers of asynchronous interfaces.
+The user has access to
+low-level packet sending
+and receiving, to
+synchronous
+resolution of several queries at once, and to a
+real high-level asynchronous DNS library.
+
+
+ It is too big for what it does.
+
+
+ The libresolv-2.13.so binary file compiled for an i386
+Debian Linux system is roughly 71k bytes. The libs6dns.so.2.0
+file, for the same system, is roughly 41k bytes, while offering
+more functionality. libresolv does not do any high-level answer
+parsing, so the user still has to do some work after the libresolv
+calls. s6-dns tries to be small and still provide the user comfortable
+interfaces.
+
+
+ The API is cumbersome to use.
+
+
+ Some examples of less-than-ideal interfaces for the users:
+
+
+
+ - There is a flag in libresolv's global state structure that
+determines if queries are to be sent recursive or iterative. Which
+means that a program that needs to make both recursive and iterative
+queries must duplicate this state structure and use one for recursive
+queries, one for iterative queries. Why this complexity ? The
+recursive flag should be given for every query, not be a part
+of the resolver state.
+ - When a libresolv answer arrives but doesn't fit into the
+user-supplied buffer, the query is discarded and has to be retried.
+Does "network efficiency" ring a bell ? Also, the length of
+the original answer is returned by the first call, which is a good
+thing: the user can now provide a large enough buffer so the call
+succeeds the next time, right ? Wrong. The next answer can
+be different from the first, and in particular, longer, which
+means that the next query can still fail.
+
+
+
+ There is a reason why system calls and local functions take
+user-supplied buffers as arguments. They are relatively fast, it is
+not too costly to call them again if the buffer is too small the
+first time, and the result is consistent, i.e. after the first call,
+the right buffer length is known. But functions making
+network exchanges with variable-length results from one call to
+another ? Those need heap-allocated storage. It is
+good design to avoid using the heap whenever possible, but it is
+not good design to waste network round-trips to save a malloc().
+
+
+ Conclusion
+
+
+ Like many other "standards", and C library interfaces in particular,
+libresolv is at best a mediocre one, that people use because
+there has been nothing better so far.
+
+
+
+ s6-dns tries to be an alternative solution - not as ambitious,
+but based on solid design principles and a reliable code base.
+
+
+
+
diff --git a/doc/libs6dns/index.html b/doc/libs6dns/index.html
new file mode 100644
index 0000000..db7ee35
--- /dev/null
+++ b/doc/libs6dns/index.html
@@ -0,0 +1,104 @@
+
+
+
+
+ s6-dns: the s6dns library interface
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6dns library interface
+
+ General information
+
+
+ libs6dns is a DNS client library, designed for clarity
+and simplicity - which translates into smallness of the code.
+
+
+
+ A major focus of libs6dns is to avoid unnecessary use
+of heap memory. Memory is only allocated in the heap to store
+queries and response packets during a DNS resolution process, and
+to store the final answers into a user-provided
+
+stralloc; all the other operations use stack memory, and perform
+as few copies as possible.
+
+
+ Compiling
+
+
+ - Make sure the s6-dns headers, as well as the skalibs headers,
+are visible in your header search path.
+ - Use #include <s6-dns/s6dns.h>
+
+
+ Linking
+
+
+ - Make sure the s6-dns libraries, as well as the skalibs libraries,
+are visible in your library search path.
+ - Link against -ls6dns, -lskarnet,
+`cat $SYSDEPS/socket.lib` and
+`cat $SYSDEPS/tainnow.lib`, $SYSDEPS being your skalibs
+sysdeps directory.
+
+
+ Programming
+
+
+ The s6dns.h header is actually a concatenation of other headers:
+the libs6dns is separated into several modules, each of them with its
+own header.
+
+
+
+ - The s6dns-constants.h header provides constants used in
+other parts of the library.
+ - The s6dns-ip46.h header provides an
+abstraction for IPv4 and IPv6 transports.
+ - The s6dns-domain.h header provides
+basic string manipulation primitives for domain names.
+ - The s6dns-message.h header provides
+function to parse a message following the DNS protocol.
+ - The s6dns-engine.h header provides
+the low-level asynchronous networking functions.
+ - The s6dns-rci.h header provides an
+interface to resolv.conf reading.
+ - The s6dns-resolve.h header provides
+the user-level synchronous resolution functions.
+ - The s6dns-fmt.h header provides
+formatting primitives to display RR contents.
+
+
+
+ (User-level asynchronous resolution functions are provided in the
+skadns library.)
+
+
+
+ Two functional macros are actually directly declared in the s6dns.h
+header:
+
+
+
+ - Call s6dns_init() before all your s6dns operations.
+s6dns_init() calls s6dns_rci_init(),
+extracting resolv.conf information to an internal global
+variable. The function returns 1 on success, and 0 (and sets errno)
+on failure.
+ - Call s6dns_finish() when you're done with the libs6dns.
+It frees the resources used.
+
+
+
+
diff --git a/doc/libs6dns/s6dns-domain.html b/doc/libs6dns/s6dns-domain.html
new file mode 100644
index 0000000..b1492c3
--- /dev/null
+++ b/doc/libs6dns/s6dns-domain.html
@@ -0,0 +1,137 @@
+
+
+
+
+ s6-dns: the s6dns_domain library interface
+
+
+
+
+
+
+
+libs6dns
+s6-dns
+Software
+skarnet.org
+
+
+ The s6dns_domain library interface
+
+
+ The following functions and structures are declared in the s6-dns/s6dns-domain.h header,
+and implemented in the libs6dns.a or libs6dns.so library.
+
+
+ General information
+
+
+ s6dns_domain provides primitives to perform basic operations
+on domain names.
+
+
+ Data structures
+
+
+ A s6dns_domain_t is a structure that s6dns uses internally to
+represent a domain name. It can be in string form (or
+decoded form), which is close to the printable form seen
+by users, or in packet form (or encoded form), which
+is the format used in the DNS protocol.
+
+
+
+ A s6dns_domain_t is a flat structure and can be declared
+on the stack.
+
+
+ Functions
+
+
+ int s6dns_domain_fromstring (s6dns_domain_t *d, char const *s, unsigned int len)
+Makes a (string form) domain from string s of length len,
+and stores it into *d. Returns 1 if it succeeds, otherwise it
+returns 0 and sets errno appropriately - most likely ENAMETOOLONG, i.e.
+the name in s is not a well-formed domain name.
+
+
+
+ unsigned int s6dns_domain_tostring (char *s, unsigned int max, s6dns_domain_t const *d)
+Writes into string s the domain contained in *d (in string
+form). Returns the number of bytes written, or 0 in case of failure. If
+the output would be more than max bytes, 0 ENAMETOOLONG is returned.
+
+
+
+ int s6dns_domain_noqualify (s6dns_domain_t *d)
+Makes sure that *d is fully qualified. This is done without using
+qualification: a trailing dot is simply appended if the domain
+doesn't already have one. Returns 1 if it succeeds, or 0 if it fails.
+
+
+
+ unsigned int s6dns_domain_qualify (s6dns_domain_t *list, s6dns_domain_t const *d, char const *rules, unsigned int rulesnum)
+Performs qualification on domain *d according to the first
+rulesnum rules stored in string rules. Stores the output
+(at most rulesnum domains) into the array pointed to by list.
+Returns 0 on failure, or the number of written domains if it succeeds. This
+number can be lesser than rulesnum, for instance if *d is
+already fully qualified.
+Valid rules and rulesnum can be obtained via functions
+declared in s6dns-rci.h.
+
+
+
+ int s6dns_domain_encode (s6dns_domain_t *d)
+Encodes domain *d from string form to packet form. Returns 1
+if it succeeds or 0 if it fails - for instance, *d is not a
+valid string form (EINVAL).
+
+
+
+ unsigned int s6dns_domain_encodelist (s6dns_domain_t *list, unsigned int n)
+Encodes n domains pointed to by list from string form to packet form,
+stopping at the first failure.
+Returns the number of successfully encoded domains, normally n.
+
+
+
+ int s6dns_domain_decode (s6dns_domain_t *d)
+Decodes domain *d from packet form to string form. Returns 1
+if it succeeds or 0 if it fails - for instance, *d is not a
+valid packet form (EPROTO).
+
+
+
+ int s6dns_domain_fromstring_noqualify_encode (s6dns_domain_t *d, char const *s, unsigned int len)
+Higher-level function wrapping some of the above. Makes an encoded, fully qualified
+(without resorting to qualification) domain from string s of
+length len. Returns 1 if it succeeds and 0 if it fails.
+
+
+
+ unsigned int s6dns_domain_fromstring_qualify_encode (s6dns_domain_t *list, char const *s, unsigned int len, char const *rules, unsigned int rulesnum)
+Another wrapping function. It makes a list of encoded, fully qualified domains,
+from string s of length len using rulesnum qualification
+rules in rules. It writes at most rulesnum domains into the array
+pointed to by list and returns the number of written domains, or 0 on an
+error.
+
+
+
+ void s6dns_domain_arpafromip4 (s6dns_domain_t *d, char const *ip)
+Writes into d the in-addr.arpa. domain corresponding to IPv4 address
+ip (4 bytes, in network byte order), in string form.
+
+
+
+ void s6dns_domain_arpafromip6 (s6dns_domain_t *d, char const *ip, unsigned int mask)
+Writes into d the ip6.arpa. domain corresponding to the first
+mask bits of IPv6 address ip (16 bytes, in network byte order),
+in string form.
+Only multiples of 4 count for mask, i.e. the output will be the same
+if mask is (for instance) 125, 126, 127 or 128.
+
+
+
+
diff --git a/doc/libs6dns/s6dns-engine.html b/doc/libs6dns/s6dns-engine.html
new file mode 100644
index 0000000..f0f9573
--- /dev/null
+++ b/doc/libs6dns/s6dns-engine.html
@@ -0,0 +1,255 @@
+
+
+
+
+ s6-dns: the s6dns_engine library interface
+
+
+
+
+
+
+
+libs6dns
+s6-dns
+Software
+skarnet.org
+
+
+ The s6dns_engine library interface
+
+
+ The following functions are declared in the s6-dns/s6dns-engine.h header,
+and implemented in the libs6dns.a or libs6dns.so library.
+
+
+ General information
+
+
+ s6dns_engine is the nitty-gritty of DNS query management. These
+are the low-level asynchronous primitives sending DNS queries over the
+network, and getting answers.
+
+
+
+ s6dns_engine has been inspired by Dan J. Bernstein's
+dns_transmit
+library, but does not borrow any code from it. Unlike
+dns_transmit, s6dns_engine does not assume that
+network send operations are instant successes; s6dns_engine
+descriptors can be selected for writing as well as for reading.
+Also, if the underlying
+skalibs has been compiled with IPv6 support, s6dns_engine
+supports native IPv6 transport.
+
+
+
+ The s6dns_engine functions are used in the implementation of the
+s6dns_resolven_loop function - which is nothing more than a
+simple event loop around the s6dns_engine primitives - and the
+skadnsd daemon. Both pieces of code are
+good examples of how to use s6dns_engine.
+
+
+
+ However, unless you're implementing a DNS cache, you probably should
+not call the
+s6dns_engine functions directly: they are very low-level. If you
+need synchronous resolution, use the
+s6dns_resolve functions. If you need
+asynchronous DNS operations, use the
+skadns functions, which are
+designed to provide a higher level interface to multiple asynchronous
+DNS queries.
+
+
+ Data structures
+
+
+ A s6dns_engine_t structure holds all the data necessary to
+manage a DNS query (and response). It must be initialized to S6DNS_ENGINE_ZERO
+when first declared, and recycled with s6dns_engine_recycle()
+after each use. It contains a stralloc, so it must be freed with
+s6dns_engine_free() before being discarded, to avoid memory leaks.
+
+
+ Functions
+
+ s6dns_engine_t life cycle
+
+
+ int s6dns_engine_init (s6dns_engine_t *dt, s6dns_ip46list_t const *servers, uint32 options, char const *q, unsigned int qlen, uint16 qtype, struct taia const *deadline, struct taia const *stamp)
+
+
+
+Initializes dt with query q of length qlen
+and type qtype. If d is an
+encoded s6dns_domain_t, then d.s and d.len
+are appropriate candidates for arguments q and qlen
+respectively.
+
+
+
+options can be 0 or an OR'ed
+combination of the following, defined in s6-dns/s6dns-constants.h:
+
+
+
+ - S6DNS_O_RECURSIVE: the query will be recursive and assuming it is
+sent to a DNS cache, instead of iterative and assuming it is sent to a
+DNS server.
+ - S6DNS_O_STRICT: the library will only accept authoritative answers
+to iterative queries. This is normally the sane behaviour, but badly
+configured DNS software around the world - notably,
+BIND when it's configured to be both a cache and a server - often
+serve non-authoritative data even when they could, so it
+breaks things, hence why the option isn't set by default.
+
+
+
+servers must point to a list of IP addresses as defined in
+s6-dns/s6dns-ip46.h. Such a list can be
+obtained from the /etc/resolv.conf file via the
+s6dns_rci_fill() call when performing a
+recursive query, or it must be constructed from a list of relevant
+NS addresses when performing an iterative query.
+
+
+
+stamp must be an accurate enough timestamp. deadline
+sets up a deadline for the query: if the query hasn't been
+satisfactorily answered by deadline - no matter how many
+round-trips to network servers the library performs internally - then
+it will be considered failed, and a timeout will be reported.
+
+
+
+The function returns 1 if all went well, and 0 if an error occurred.
+It returns instantly; it does not perform any network operation,
+it just prepares dt to send a query. The actual data sending
+will take place on the next s6dns_engine_event() call.
+
+
+
+ void s6dns_engine_recycle (s6dns_engine_t *dt)
+
+
+
+Recycles dt, making it ready for another use. This function
+does not deallocate the heap memory used by dt, so it's faster than
+s6dns_engine_free() and does not cause heap fragmentation.
+
+
+
+ void s6dns_engine_free (s6dns_engine_t *dt)
+
+
+
+Frees the heap memory used by dt. Also makes dt
+ready for another use. It's advised to only use this function when
+certain that dt will not be reused.
+
+
+ Before the iopause()
+
+
+ The descriptor to select on is available as the fd field in
+the s6dns_engine_t structure.
+dt→fd should be read every iteration, because it can
+change between iterations even if no event or timeout is reported
+for dt.
+
+
+
+ void s6dns_engine_nextdeadline (s6dns_engine_t const *dt, struct taia *a)
+
+
+
+If dt needs handling before the absolute date *a,
+then *a is updated
+so it contains the earlier date. This is useful to compute the next
+deadline in an iopause() loop.
+
+
+
+ int s6dns_engine_isreadable (s6dns_engine_t const *dt)
+
+
+
+Returns nonzero iff dt→fd is to be selected for reading.
+Should be called in every iteration.
+
+
+
+ int s6dns_engine_iswritable (s6dns_engine_t const *dt)
+
+
+
+Returns nonzero iff dt→fd is to be selected for writing.
+Should be called in every iteration.
+
+
+ After the iopause()
+
+
+ int s6dns_engine_timeout (s6dns_engine_t *dt, struct taia const *stamp)
+
+
+
+This function should be called if your selecting function returned 0, which
+means that an event timed out.
+stamp should contain the current time. The function returns -1 if
+an error occurred, 1 if dt actually timed out, and 0 if nothing
+special happened to dt (and your iopause timeout was caused by
+something else). If the return value is not 0, dt is automatically
+recycled.
+
+
+
+ int s6dns_engine_event (s6dns_engine_t *dt, struct taia const *stamp)
+
+
+
+This function should be called if your selecting function returned a positive
+number, which means that some event got triggered.
+stamp should contain the current time. The function returns
+-1 if an error occurred (and dt is automatically recycled). It
+returns 0 if no answer has arrived yet, and 1 if an answer is available.
+
+
+
+The s6dns_engine_timeout() and s6dns_engine_event() functions,
+when returning -1, make use of the following error codes:
+
+
+ - EINVAL: Invalid dt.
+
- ENETUNREACH: All the servers in the servers list have been
+unsuccessfully tried.
+ - EPROTO: An answer arrived, but it didn't follow the DNS protocol.
+ - Other error codes reporting socket or system failures.
+
+
+
+ char *s6dns_engine_packet (s6dns_engine_t const *dt)
+
+
+
+Points to the response packet received from the network,
+if s6dns_engine_event() returned 1.
+
+
+
+ unsigned int s6dns_engine_packetlen (s6dns_engine_t const *dt)
+
+
+
+Gives the length of the response packet,
+if s6dns_engine_event() returned 1.
+
+
+
+ You should recycle or free dt after reading the response packet.
+
+
+
+
diff --git a/doc/libs6dns/s6dns-fmt.html b/doc/libs6dns/s6dns-fmt.html
new file mode 100644
index 0000000..a586846
--- /dev/null
+++ b/doc/libs6dns/s6dns-fmt.html
@@ -0,0 +1,92 @@
+
+
+
+
+ s6-dns: the s6dns_fmt library interface
+
+
+
+
+
+
+
+libs6dns
+s6-dns
+Software
+skarnet.org
+
+
+ The s6dns_fmt library interface
+
+
+ The following functions and structures are declared in the s6-dns/s6dns-fmt.h header,
+and implemented in the libs6dns.a or libs6dns.so library.
+
+
+ General information
+
+
+ s6dns_fmt provides primitives to format RR contents into
+printable strings.
+
+
+ Functions
+
+
+ unsigned int s6dns_fmt_domain (char *s, unsigned int max, s6dns_domain_t const *d)
+Writes into string s the domain contained in *d (in string
+form). Returns the number of bytes written, or 0 in case of failure. If
+the output would be more than max bytes, 0 ENAMETOOLONG is returned.
+To avoid that, S6DNS_FMT_DOMAIN is a suitable number of bytes to preallocate s.
+This function is actually an alias to s6dns_domain_tostring.
+
+
+
+ unsigned int s6dns_fmt_domainlist (char *s, unsigned int max, s6dns_domain_t const *list, unsigned int n, char const *delin, unsigned int delimlen)
+Writes into string s the list of n domains (in string form)
+pointed to by list. Between each domain (and not after the last one),
+string delim of length delimlen is appended.
+The function returns the number of bytes written, or 0 in case of failure. If
+the output would be more than max bytes, 0 ENAMETOOLONG is returned.
+To avoid that, S6DNS_FMT_DOMAINLIST(n) is a suitable number of bytes to preallocate s.
+
+
+
+ unsigned int s6dns_fmt_hinfo (char *s, unsigned int max, s6dns_message_rr_hinfo_t const *p)
+Writes into string s the HINFO contained in *p: cpu, then os,
+separated by a space.
+Returns the number of bytes written, or 0 in case of failure. If
+the output would be more than max bytes, 0 ENAMETOOLONG is returned.
+To avoid that, S6DNS_FMT_HINFO is a suitable number of bytes to preallocate s.
+
+
+
+ unsigned int s6dns_fmt_mx (char *s, unsigned int max, s6dns_message_rr_mx_t const *p)
+Writes into string s the MX contained in *p: preference, then
+exchanger name, separated by a space.
+Returns the number of bytes written, or 0 in case of failure. If
+the output would be more than max bytes, 0 ENAMETOOLONG is returned.
+To avoid that, S6DNS_FMT_MX is a suitable number of bytes to preallocate s.
+
+
+
+ unsigned int s6dns_fmt_soa (char *s, unsigned int max, s6dns_message_rr_soa_t const *p)
+Writes into string s the SOA contained in *p:
+mname, then rname, then serial number, refresh time, retry time, expiration time
+and minimum time, separated by spaces.
+Returns the number of bytes written, or 0 in case of failure. If
+the output would be more than max bytes, 0 ENAMETOOLONG is returned.
+To avoid that, S6DNS_FMT_SOA is a suitable number of bytes to preallocate s.
+
+
+
+ unsigned int s6dns_fmt_srv (char *s, unsigned int max, s6dns_message_rr_srv_t const *p)
+Writes into string s the SRV contained in *p: priority,
+then weight, then port, then target, separated by spaces.
+Returns the number of bytes written, or 0 in case of failure. If
+the output would be more than max bytes, 0 ENAMETOOLONG is returned.
+To avoid that, S6DNS_FMT_SRV is a suitable number of bytes to preallocate s.
+
+
+
+
diff --git a/doc/libs6dns/s6dns-ip46.html b/doc/libs6dns/s6dns-ip46.html
new file mode 100644
index 0000000..27cbe2c
--- /dev/null
+++ b/doc/libs6dns/s6dns-ip46.html
@@ -0,0 +1,69 @@
+
+
+
+
+ s6-dns: the s6dns_ip46 library interface
+
+
+
+
+
+
+
+libs6dns
+s6-dns
+Software
+skarnet.org
+
+
+ The s6dns_ip46 library interface
+
+
+ The following functions are declared in the s6-dns/s6dns-ip46.h header,
+and implemented as macros.
+
+
+ General information
+
+
+ s6dns_ip46 is the transport abstraction layer. It allows
+the functions declared in s6-dns/s6dns-engine.h
+and s6-dns/s6dns-rci.h to be transport-agnostic,
+i.e. to be able to work with both IPv4 and IPv6.
+
+
+
+ If the underlying skalibs
+has been compiled with
+ flag-noipv6,
+or if it has detected at build time that the target host does not support
+IPv6, then the s6dns-ip46 abstraction will be totally transparent and use
+no resources at all.
+
+
+ Data structures
+
+
+ A s6dns_ip46list_t structure holds a list of S6DNS_MAX_SERVERS (16)
+IPv4 or IPv6 addresses. Such a mixed list can be constructed, for
+instance, if the /etc/resolv.conf file contains both v4 and v6
+nameserver lines.
+
+
+ Functions
+
+
+ If list is a s6dns_ip46list_t and i an integer
+between 0 and DNS_MAX_SERVERS-1, then
+
+
+
+ -
s6dns_ip46list_is6(&list, i) is 1 if the ith
+address in list is IPv6 and 0 if it is IPv4.
+ -
s6dns_ip46list_ip(&list, i) is a char * pointer to
+16 (if IPv6) or 4 (IPv4) bytes representing the ith address in
+list, in network byte order.
+
+
+
+
diff --git a/doc/libs6dns/s6dns-message.html b/doc/libs6dns/s6dns-message.html
new file mode 100644
index 0000000..e06aa91
--- /dev/null
+++ b/doc/libs6dns/s6dns-message.html
@@ -0,0 +1,261 @@
+
+
+
+
+ s6-dns: the s6dns_message library interface
+
+
+
+
+
+
+
+libs6dns
+s6-dns
+Software
+skarnet.org
+
+
+ The s6dns_message library interface
+
+
+ The following functions are declared in the s6-dns/s6dns-message.h header,
+and implemented in the libs6dns.a or libs6dns.so library.
+
+
+ General information
+
+
+ s6dns_message provides functions to read and parse DNS messages
+sent by servers and caches and containing answers to queries.
+
+
+ Data structures
+
+
+ A s6dns_message_header_t is a structure containing the header
+of a received DNS packet, broken down for easy access to the bits.
+
+
+
+ A s6dns_message_rr_t is a structure containing the information
+about a resource record given by an answer packet - all of it, except the
+value of the answer itself, which is rtype-specific and has to be decoded
+by rtype-specific functions.
+
+
+
+ A s6dns_message_rr_func_t is the type of such a function. The
+prototype is
+ int f (s6dns_message_rr_t const *rr, char const *packet, unsigned int packetlen, unsigned int pos, unsigned int section, void *data)
+
+
+
+ - *rr contains the header information of the resource record,
+including the domain to which it applies, the rtype, and the ttl.
+ - packet points to the whole DNS packet the RR
+is a part of.
+ - packetlen is the total length of said packet.
+ - pos is the offset of the RR in the DNS packet, i.e. f
+should start parsing at packet + pos.
+ - section is the section the RR belongs to: 2 for answer, 3 for
+authority, 4 for additional.
+ - data is a user-specified pointer; it is typically used to
+write the decoded output, in a rtype-specific way.
+ - f must return 1 or more if it succeeds in decoding the packet.
+Else it must set errno appropriately, and return -1 if the error is local,
+unrelated to the packet - for instance, it has run out of memory - or 0 if it
+cannot decode the RR because of the packet contents.
+
+
+
+ Various structures designed to store specific resource record types are
+also provided. The list includes:
+
+
+
+ - s6dns_message_rr_hinfo for HINFO RRs
+ - s6dns_message_rr_mx for MX RRs
+ - s6dns_message_rr_soa for SOA RRs
+ - s6dns_message_rr_srv for SRV RRs
+
+
+ Functions
+
+ Header management
+
+
+ void s6dns_message_header_pack (char *s, s6dns_message_header_t const *h)
+Packs the header *h into the 12 bytes pointed to by s.
+
+
+
+ void s6dns_message_header_unpack (char const *s, s6dns_message_header_t *h)
+Unpacks the 12 bytes pointed to by s into the structure *h.
+
+
+ Low-level RR decoding
+
+
+ The following primitives are used in the implementation of
+s6dns_message_rr_func_t-typed functions, to read and decode information
+stored in a DNS packet. Their arguments are:
+
+
+
+ - A pointer to the structure where the information is going to be stored
+ - A read-only pointer to the beginning of the DNS packet
+ - The length of the DNS packet
+ - A pointer to an integer containing the current position in the
+DNS packet, i.e. where the information is going to be read. If the functions
+succeed, they automatically update the position so information can be read
+sequentially.
+
+
+
+ int s6dns_message_get_string (s6dns_domain_t *d, char const *packet, unsigned int packetlen, unsigned int *pos)
+Reads a character-string and stores it into *d. Returns 1 on success
+and 0 on failure. Note that *d does not contain a domain, but the
+s6dns_domain_t structure is adapted to store strings that do not
+exceed 255 characters. d→s can be used to access the string,
+and d→len its length.
+
+
+
+ int s6dns_message_get_strings (char *s, unsigned int rdlength, char const *packet, unsigned int packetlen, unsigned int *pos
+This function takes an additional parameter rdlength. It reads a series of
+character-strings and stores their concatenation into the string s, which
+must be preallocated; it can never store more than rdlength bytes. It returns
+-1 if it fails; on success, it returns the number of bytes written. The
+rdlength parameter must be the length of the resource record containing
+the series of character-strings.
+
+
+
+ unsigned int s6dns_message_get_domain (s6dns_domain_t *d, char const *packet, unsigned int packetlen, unsigned int *pos)
+Reads a domain and stores it, in string form, into *d.
+Returns 1 on success and 0 on failure, and sets errno:
+
+
+
+ - EPROTO: there is no proper domain to be read in position *pos of
+packet. Either the packet is malformed or the function is being
+misused.
+ - EPROTONOSUPPORT: the domain encoding uses an extension that the function
+does not recognize.
+
+
+
+ int s6dns_message_get_hinfo (s6dns_message_rr_hinfo_t *p, char const *packet, unsigned int packetlen, unsigned int *pos)
+Reads a HINFO RR and stores it into *p. Returns 1 on success or 0
+on failure.
+
+
+
+ int s6dns_message_get_mx (s6dns_message_rr_mx_t *p, char const *packet, unsigned int packetlen, unsigned int *pos)
+Reads a MX RR and stores it into *p. Returns 1 on success or 0 on failure.
+
+
+
+ int s6dns_message_get_soa (s6dns_message_rr_soa_t *p, char const *packet, unsigned int packetlen, unsigned int *pos)
+Reads a SOA RR and stores it into *p. Returns 1 on success or 0 on failure.
+
+
+
+ int s6dns_message_get_srv (s6dns_message_rr_srv_t *p, char const *packet, unsigned int packetlen, unsigned int *pos)
+Reads a SRV RR and stores it into *p. Returns 1 on success or 0 on failure.
+
+
+ High-level RR-specific parsing functions
+
+
+ s6dns_message_func_t s6dns_message_parse_answer_strings
+Parses character-strings located in the answer section of the packet. The
+data argument is interpreted as a pointer to a s6dns_mpag_t,
+which is a structure defined in the s6-dns/s6dns-message.h header
+and used to store multiple character-strings.
+
+
+
+ s6dns_message_func_t s6dns_message_parse_answer_domain
+Parses domains located in the answer section of the packet. The
+data argument is interpreted as a pointer to a s6dns_dpag_t,
+which is a structure defined in the s6-dns/s6dns-message.h header
+and used to store multiple domains.
+
+
+
+ s6dns_message_func_t s6dns_message_parse_answer_a
+Parses A RRs located in the answer section of the packet. The
+data argument is interpreted as a pointer to a
+stralloc,
+and 4 bytes are appended to this stralloc for every IPv4 address found.
+
+
+
+ s6dns_message_func_t s6dns_message_parse_answer_aaaa
+Parses AAAA RRs located in the answer section of the packet. The
+data argument is interpreted as a pointer to a
+stralloc,
+and 16 bytes are appended to this stralloc for every IPv6 address found.
+
+
+
+ s6dns_message_func_t s6dns_message_parse_answer_hinfo
+Parses HINFO RRs located in the answer section of the packet. The
+data argument is interpreted as a pointer to a
+genalloc
+containing s6dns_message_rr_hinfo_t structures.
+
+
+
+ s6dns_message_func_t s6dns_message_parse_answer_mx
+Parses MX RRs located in the answer section of the packet. The
+data argument is interpreted as a pointer to a
+genalloc
+containing s6dns_message_rr_mx_t structures.
+
+
+
+ s6dns_message_func_t s6dns_message_parse_answer_soa
+Parses SOA RRs located in the answer section of the packet. The
+data argument is interpreted as a pointer to a
+genalloc
+containing s6dns_message_rr_soa_t structures.
+
+
+
+ s6dns_message_func_t s6dns_message_parse_answer_srv
+Parses SRV RRs located in the answer section of the packet. The
+data argument is interpreted as a pointer to a
+genalloc
+containing s6dns_message_rr_srv_t structures.
+
+
+ High-level packet parsing
+
+
+ int s6dns_message_parse (s6dns_message_header_t *h, char const *packet, unsigned int packetlen, s6dns_message_rr_func_t *f, void *data)
+ This function parses the DNS packet packet of length packetlen.
+It stores the packet header into *h. Then, for every RR in the answer,
+authority or additional section of the packet, it calls f with the
+relevant parameters. data is the extra pointer given to f to
+store information. The function returns 1 if the parsing succeeds. Otherwise it
+returns -1 if there is a local error unrelated to the packet, or 0 if no
+appropriate answer can be decoded from the packet. errno then contains one
+of the following values:
+
+
+
+ - EPROTO: the packet is malformed, syntax error
+ - EBADMSG: rcode 1, query format error
+ - EBUSY: rcode 2, server failure
+ - ENOENT: rcode 3, nxdomain
+ - ENOTSUP: rcode 4, query type not implemented
+ - ECONNREFUSED: rcode 5, operation refused by server
+ - EIO: unknown rcode
+ - any other value being set by f if it returns a failure code.
+
+
+
+
diff --git a/doc/libs6dns/s6dns-rci.html b/doc/libs6dns/s6dns-rci.html
new file mode 100644
index 0000000..1cf8a0e
--- /dev/null
+++ b/doc/libs6dns/s6dns-rci.html
@@ -0,0 +1,109 @@
+
+
+
+
+ s6-dns: the s6dns_rci library interface
+
+
+
+
+
+
+
+libs6dns
+s6-dns
+Software
+skarnet.org
+
+
+ The s6dns_rci library interface
+
+
+ The following functions and structures are declared in the s6-dns/s6dns-rci.h header,
+and implemented in the libs6dns.a or libs6dns.so library.
+
+
+ General information
+
+
+ s6dns_rci provides functions to get information from
+the /etc/resolv.conf file.
+
+
+ Data structures
+
+
+ A s6dns_rci_t is a structure storing information
+provided by the /etc/resolv.conf file, i.e.
+
+
+
+ - The list of "nameserver" addresses, i.e. IP addresses of DNS caches
+contacted by clients for recursive queries
+ - The list of qualification rules provided by "domain" or "search"
+lines
+
+
+
+ Nameserver addresses are stored in a
+s6dns_ip46list_t. Qualification rules are
+stored in a stralloc
+with an additional integer storing the number of rules.
+
+
+
+ Most programs won't need more than one s6dns_rci_t, so
+the library provides the global variable s6dns_rci_here, used
+by default in simple resolution macros.
+
+
+ Functions
+
+
+ int s6dns_rci_init (s6dns_rci_t *rci, char const *file)
+Extracts information from file, which must be in /etc/resolv.conf
+format, and stores it into *rci. rci must be previously
+initialized to the S6DNS_RCI_ZERO constant. The function returns 1 if
+it succeeds, or 0 (and sets errno) if it fails.
+
+
+
+ If the DNSCACHEIP environment variable is set, and contains a list of
+IP addresses separated by commas, semicolons, spaces, tabs, newlines or
+carriage returns, then this list overrides any nameserver information
+from file. If the variable is empty, file will be used
+as the source of the information.
+
+
+
+ If the DNSQUALIFY environment variable is set, a list of domain suffixes,
+separated by spaces, tabs, newlines or carriage returns, is read from it,
+and overrides any qualification information from file. If the
+variable is empty, it amounts to one rule saying "no qualification".
+
+
+
+ s6dns_init() is an alias to
+s6dns_rci_init(&s6dns_rci_here, "/etc/resolv.conf").
+
+
+
+ void s6dns_rci_free (s6dns_rci_t *rci)
+Frees the memory used by *rci. rci is then suitable to
+be reused in a s6dns_rci_init call.
+
+
+
+ s6dns_finish() calls s6dns_rci_free(&s6dns_rci_here).
+
+
+
+ unsigned int s6dns_qualify (s6dns_domain_t *list, s6dns_domain_t const *d)
+Qualifies domain *d into the list of domains pointed to by list
+according to the rules stored in s6dns_rci_here. Returns the number of
+written domains (0 if it fails); this number cannot exceed
+s6dns_rci_here.rulesnum.
+
+
+
+
diff --git a/doc/libs6dns/s6dns-resolve.html b/doc/libs6dns/s6dns-resolve.html
new file mode 100644
index 0000000..bbb3f57
--- /dev/null
+++ b/doc/libs6dns/s6dns-resolve.html
@@ -0,0 +1,387 @@
+
+
+
+
+ s6-dns: the s6dns_resolve library interface
+
+
+
+
+
+
+
+libs6dns
+s6-dns
+Software
+skarnet.org
+
+
+ The s6dns_resolve library interface
+
+
+ The following functions are declared in the s6-dns/s6dns-resolve.h header,
+and implemented in the libs6dns.a or libs6dns.so library.
+
+
+ General information
+
+
+ s6dns_resolve provides functions and macros - mostly macros -
+to perform high level synchronous DNS resolution.
+
+
+
+ All the functions declared here make synchronous calls to the network, so
+they can block for a non-negligible amount of time. To avoid unbounded
+waiting times, they always take 2 arguments at the end, deadline
+and stamp. deadline is the read-only address of a
+struct taia
+containing an absolute time which is the deadline for the function, and
+stamp is the read-write address of a struct taia being
+an accurate enough representation of the current absolute time. If
+the function has not returned by *deadline, then it immediately
+returns with a failure code and errno set to ETIMEDOUT. In every case,
+*stamp is automatically updated so it always represents the
+absolute time accurately enough.
+
+
+
+ In a single-threaded program, the STAMP global variable can be used to
+store the current time. Macros ending with _g use this variable
+automatically so you don't have to provide the stamp argument
+everytime. Additionally, several resolution functions make implicit use
+of global variables such as:
+
+
+
+ - s6dns_engine_here: a global
+s6dns_engine_t storing the current
+query, for sequential queries.
+ - s6dns_debughook_zero: a global s6dns_debughook_t
+meaning no debugging is needed.
+ - s6dns_rci_here: a global
+s6dns_rci_t containing the current
+resolv.conf information.
+
+
+
+ Reentrant, non-global-using functions are also provided, with the _r
+suffix. In other words, if foobarfunc is a resolution function,
+the following prototypes are generally provided, from the simplest to the
+most complex:
+
+
+
+ - foobarfunc_g: only the relevant parameters and a deadline
+must be given, the function uses the STAMP global and maybe DNS-specific
+globals
+ - foobarfunc: a deadline and stamp must be given, the function
+uses all the DNS-specific globals
+ - foobarfunc_r_g: No DNS-specific globals are used, the
+information must be given via parameters, but the STAMP global is used
+ - foobarfunc_r: fully reentrant function using no globals
+at all
+
+
+
+ For each set of four functions, only one is documented here.
+The other prototypes can be found in the s6-dns/s6dns-resolve.h file.
+
+
+
+ Some errno codes reported by these functions do not have
+exactly the system meaning given by
+strerror().
+To get a user-friendly error message, use
+s6dns_constants_error_str(errno) instead. The s6dns_constants_error_str
+function is declared in the s6dns-constants.h header.
+
+
+ Functions
+
+ Single query resolution
+
+
+ These functions are ordered from the lowest level to the highest level.
+
+
+ Basic wrapper around s6dns_engine
+
+
+ int s6dns_resolve_loop_r_g (s6dns_engine_t *dt, struct taia const *deadline)
+Resolves the query stored in dt.
+Returns 1 on success or 0 on failure.
+
+
+ Generic resolution functions
+
+
+ int s6dns_resolve_core_g (s6dns_domain_t const *d, uint16 qtype, struct taia const *deadline)
+Resolves the query on domain *d (in packet form), of type qtype.
+Returns 0 on failure, or 1 on success, in which case
+s6dns_engine_here contains the answer.
+
+
+
+ int s6dns_resolve_parse_g (s6dns_domain_t const *d, uint16 qtype, s6dns_message_rr_func_t *f, void *data, struct taia const *deadline)
+Resolves the query on domain *d (in packet form), of type qtype,
+then parses the answer with function f and stores the result into data.
+Returns 1 if it succeeds, 0 if no data can be extracted from the answer, or -1 if an
+error occurs. Sets errno in the last two cases.
+
+
+
+ Note that the function can return 1 without appending anything to data.
+This means that the servers confirmed that the domain exists, but f
+has not been able to find any data relevant to the query in the answer.
+This is very different from NXDOMAIN, which means that
+the servers deny the actual existence of the domain, and which is reported
+here as a return code of 0 with errno set to ENOENT.
+
+
+
+ int s6dns_resolvenoq_g (char const *name, unsigned int len, uint16 qtype, s6dns_message_rr_func_t *f, void *data, struct taia const *deadline)
+Performs a query of type qtype on name name of length len,
+without qualifying it. Parses the answer with function f and stores the
+result into data. Returns 1 if it succeeds, 0 if no data can be extracted,
+or -1 if an error occurs. Sets errno in the last two cases.
+
+
+
+ int s6dns_resolveq_g (char const *name, unsigned int len, uint16 qtype, s6dns_message_rr_func_t *f, void *data, struct taia const *deadline)
+Performs a query of type qtype on name name of length len,
+qualifying it first. Parses the answer with function f and stores the
+result into data. Returns 1 if it succeeds, 0 if none of the FQDNs can
+get a positive answer, or -1 if an error occurs. Sets errno in the last two cases.
+
+
+
+ int s6dns_resolve_g (char const *name, unsigned int len, uint16 qtype, s6dns_message_rr_func_t *f, void *data, int qualif, struct taia const *deadline)
+Performs a query of type qtype on name name of length len.
+Qualifies name first if qualif is nonzero; else, does not
+qualify it. Parses the answer with function f and stores the
+result into data. Returns 1 if it succeeds, 0 if none of the FQDNs can
+get a positive answer, or -1 if an error occurs. Sets errno in the last two cases.
+
+
+ High-level type-specific functions
+
+
+ int s6dns_resolve_a_g (stralloc *ips, char const *name, unsigned int len, int qualif, struct taia const *deadline)
+Performs an A query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the IPs are
+appended to the stralloc *ips, using 4 bytes per answer.
+
+
+
+ int s6dns_resolve_aaaa_g (stralloc *ips, char const *name, unsigned int len, int qualif, struct taia const *deadline)
+Performs an AAAA query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the IPs are
+appended to the stralloc *ips, using 16 bytes per answer.
+
+
+
+ int s6dns_resolve_aaaaa_g (genalloc *ips, char const *name, unsigned int len, int qualif, struct taia const *deadline)
+Performs an AAAA query and an A query at the same time on name name
+of length len, qualifying it first iff qualif is nonzero.
+Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or a positive number if it succeeds: 1 if IPv4 addresses
+were found, 2 if IPv6 addresses were found, and 3 if both were found.
+The IPs are appended to the genalloc *ips, which contains an array of
+ip46_t, the skalibs structure used to store IPv4 and IPv6 addresses
+indiscriminately.
+
+
+
+ int s6dns_resolve_ptr_g (genalloc *ds, char const *name, unsigned int len, int qualif, struct taia const *deadline)
+Performs a PTR query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the domains are
+appended to the genalloc *ds, which contains an array of s6dns_domain_t.
+
+
+
+ int s6dns_resolve_name4_g (genalloc *ds, char const *ip, struct taia const *deadline)
+Performs a PTR query on the in-addr.arpa. name representing the IPv4
+address ip (4 network-order bytes).
+Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the domains are
+appended to the genalloc *ds, which contains an array of s6dns_domain_t.
+
+
+
+ int s6dns_resolve_name6_g (genalloc *ds, char const *ip, struct taia const *deadline)
+Performs a PTR query on the ip6.arpa. name representing the IPv6
+address ip (16 network-order bytes).
+Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the domains are
+appended to the genalloc *ds, which contains an array of s6dns_domain_t.
+
+
+
+ int s6dns_resolve_name46_g (genalloc *ds, ip46_t const *ip, struct taia const *deadline)
+Calls s6dns_resolve_name6_g() or s6dns_resolve_name4_g()
+depending on which ip is an IPv6 or IPv4 address.
+
+
+
+ int s6dns_resolve_ns_g (genalloc *ds, char const *name, unsigned int len, int qualif, struct taia const *deadline)
+Performs a NS query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the domains are
+appended to the genalloc *ds, which contains an array of s6dns_domain_t.
+
+
+
+ int s6dns_resolve_cname_g (genalloc *ds, char const *name, unsigned int len, int qualif, struct taia const *deadline)
+Performs a CNAME query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the domains are
+appended to the genalloc *ds, which contains an array of s6dns_domain_t.
+
+
+
+ int s6dns_resolve_hinfo_g (genalloc *hinfos, char const *name,
+unsigned int len, int qualif, struct taia const *deadline)
+ Performs an HINFO query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the domains are
+appended to the genalloc *hinfos, which contains an array of
+s6dns_message_rr_hinfo_t.
+
+
+
+ int s6dns_resolve_mx_g (genalloc *mxs, char const *name,
+unsigned int len, int qualif, struct taia const *deadline)
+ Performs an MX query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the domains are
+appended to the genalloc *mxs, which contains an array of
+s6dns_message_rr_mx_t.
+
+
+
+ int s6dns_resolve_soa_g (genalloc *soas, char const *name,
+unsigned int len, int qualif, struct taia const *deadline)
+ Performs an SOA query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the domains are
+appended to the genalloc *soas, which contains an array of
+s6dns_message_rr_soa_t.
+
+
+
+ int s6dns_resolve_srv_g (genalloc *srvs, char const *name,
+unsigned int len, int qualif, struct taia const *deadline)
+ Performs an SRV query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case the domains are
+appended to the genalloc *srvs, which contains an array of
+s6dns_message_rr_srv_t.
+
+
+
+ int s6dns_resolve_txt_g (stralloc *sa, genalloc *offsets, char const *name,
+unsigned int len, int qualif, struct taia const *deadline)
+ Performs an TXT query on name name of length len, qualifying it
+iff qualif is nonzero. Returns -1 if an error occurs, or 0 if no answer
+can be obtained from servers, or 1 if it succeeds, in which case:
+
+
+
+ - The resulting strings are all stored into stralloc *sa.
+Every string is terminated by a null character.
+ - A series of unsigned ints is appended to genalloc *offsets.
+Every integer represents the offset in *sa at which a string is stored.
+The number of appended integers is the total number of answers.
+
+
+ Parallel resolution
+
+
+ int s6dns_resolven_loop_g (s6dns_engine_t *dtl, unsigned int n,
+unsigned int or, struct taia const *deadline)
+ Resolves the n queries stored in the array pointed to by dtl,
+in parallel. If or is zero, it does not return before all answers
+have arrived. If or is 1, it returns when an answer arrives, but does
+not return if a query generates an error (unless all queries do so). If
+or is 2, it returns when an answer arrives or an error occurs.
+Other values of or are unspecified yet.
+
+
+ The return code is as follows:
+
+
+
+ - If or is 0: -1 on a global error (i.e. not specific to
+a query), or a non-negative number which is the total of successful
+queries.
+ - If or is 1 or 2: -1 on a global error, or a non-negative
+number which is the index of the query that triggered the event.
+
+
+
+ If or is 1, a return code of -1 with errno set to ENOENT
+means that all the queries failed.
+
+
+
+ After the function returns, the status field of each
+s6dns_engine_t contains the error code relative to the query.
+A status of 0 means that an answer has properly arrived; EAGAIN means
+that the query is still pending (and the s6dns_engine_t has not been
+recycled); ECONNABORTED means that the query has not been properly
+initialized. Other codes report various network problems.
+
+
+
+ int s6dns_resolven_parse_g (s6dns_resolve_t const *list, unsigned int n,
+struct taia const *deadline)
+Performs n complete resolutions in parallel, parsing the results.
+Returns 1 in case of success or 0 if a global error occurred.
+
+
+
+list is a pointer to an array of n s6dns_resolve_t,
+which is a structure containing at least the following fields:
+
+
+
+ - q : a s6dns_domain_t containing the query.
+It must be in encoded form.
+ - qtype : a uint16 containing the query type.
+A list of valid query types can be found in the s6dns-constants.h
+header.
+ - options : a uint32 containing options passed
+to s6dns_engine_init().
+ - deadline : a struct taia containing the
+deadline for this query, i.e. the query will fail with an ETIMEDOUT code
+if no answer has arrived by then. Note that the deadline
+argument given to s6dns_resolven_parse() is a global deadline that
+can make the function return with 0 ETIMEDOUT, but is independent from
+this field, which is local to every query.
+ - parsefunc : a s6dns_message_rr_func_t
+function that will be used to parse the answer.
+ - data : a void * that will be passed as an
+additional pointer to the parsefunc function; it is generally
+used to store the parsing result.
+ - status : an int. It does not need to be
+initialized. It will contain the error code for the query after the
+function returns. ECONNABORTED means that the query could not be
+started at all; EAGAIN means that the query was still pending when
+an error happened; other codes report various network problems.
+
+
+
+ The s6dns_resolven_parse() function is a simple, convenient way to
+perform several resolutions in parallel to avoid the waiting time
+incurred by serial resolutions. However, it is still a synchronous
+function, and cannot replace a real asynchronous DNS library: for
+more complex parallel resolution needs, use the
+skadns library.
+
+
+
+
diff --git a/doc/s6-dnsip4-filter.html b/doc/s6-dnsip4-filter.html
new file mode 100644
index 0000000..5433438
--- /dev/null
+++ b/doc/s6-dnsip4-filter.html
@@ -0,0 +1,111 @@
+
+
+
+
+ s6-dns: the s6-dnsip4-filter program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsip4-filter program
+
+
+ s6-dnsip4-filter reads domain names on its standard input and
+prints the corresponding IPv4 addresses on its standard output.
+
+
+ Interface
+
+
+ s6-dnsip4-filter [ -l maxlines ] [ -c maxconn ] [ -t timeout ] [ -f normalfmt ] [ -e errorfmt ]
+
+
+
+ - s6-dnsip4-filter reads lines from its stdin, processes them, and prints
+the processed lines to its stdout, in the same order. It exits 0 when it
+reads EOF on stdin.
+ - Every line starting with a domain name is processed. Lines not
+starting with a domain name are not, and the formatting rules treat them
+as a pure "remainder".
+ - For every processed line, an A query is made, and the result is
+printed according to the formatting rules. The domain is not qualified
+before being resolved.
+ - By default, s6-dnsip4-filter looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -l maxlines : maximum lines. s6-dnsip4-filter
+will keep at most maxlines lines in memory at the same time. If line
+n is still waiting for resolution and cannot be printed, then
+s6-dnsip4-filter will stop reading from stdin before line n+maxlines,
+until the result arrives for line n. By default, maxlines
+is 256.
+ - -c maxconn : maximum concurrent resolutions.
+s6-dnsip4-filter will perform at most maxconn resolutions in
+parallel at the same time. maxlines cannot be lesser than maxconn.
+By default, maxconn is 128.
+ - -t timeout : if any resolution takes more
+than timeout milliseconds, then it is aborted and printed as a
+timeout error. By default, timeout is 0, which means no timeout.
+ - -f normalfmt : print the positive results according to
+the normalfmt format string. By default, normalfmt is
+%s=%d%w%r, which means: print the original domain name, then an equal
+sign, then the corresponding IPv4 address, then the remainder of the line.
+ - -e errorfmt : print the negative results according to
+the errorfmt format string. By default, errorfmt is
+%s=<%e%>%w%r, which means: print the original domain name, then an equal
+sign, then the error message between angle brackets, then the remainder of the line.
+
+
+ Formatting rules
+
+
+ normalfmt and errorfmt are format strings, i.e. they tell the
+program how a line must be printed. The following sequences are recognized:
+
+
+
+ - %% prints a single % character
+ - %s prints the original domain name
+ - %d prints the IP address, if any
+ - %e prints the error message, if any
+ - %w%r prints the remainder of the input line
+
+
+ Example
+
+
+ s6-dnsns google.com | s6-dnsip4-filter -f "%d"
+
+
+
+ prints all the nameserver addresses for the google.com
+domain. This is useful, for instance, to give the result as an
+argument to s6-dnsq.
+
+
+ Notes
+
+
+ s6-dnsip4-filter does not perform DNS resolutions itself. Instead, if forks
+a skadnsd child and sends it queries, getting
+the results asynchronously. The s6-dns filter programs have actually been
+written as example uses of the skadns library.
+
+
+
+
diff --git a/doc/s6-dnsip4.html b/doc/s6-dnsip4.html
new file mode 100644
index 0000000..72f585b
--- /dev/null
+++ b/doc/s6-dnsip4.html
@@ -0,0 +1,63 @@
+
+
+
+
+ s6-dns: the s6-dnsip4 program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsip4 program
+
+
+ s6-dnsip4 finds the IPv4 addresses associated to a domain name.
+
+
+ Interface
+
+
+ s6-dnsip4 [ -q ] [ -r ] [ -t timeout ] domain
+
+
+
+ - s6-dnsip4 makes an A query for the name domain. It
+waits for the result and prints the obtained IPv4 addresses, one per line,
+then exits 0.
+ - If the domain exists but no relevant field has been found, it exits 1.
+ - If the DNS answered but no answer is available, it prints a relevant
+error message and exits 2.
+ - By default, s6-dnsip4 looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -q : qualify. Qualifies domain before resolution,
+according to suffixes found in /etc/resolv.conf. If the DNSQUALIFY
+environment variable is set and contains a list of suffixes separated by spaces,
+tabs, newlines or carriage returns, then this list is used instead. By
+default, no qualification is used: if domain is not a FQDN, a dot
+is just appended to it.
+ - -r : random. By default, the program does not sort the
+result, but prints them in the order received from the DNS. With this
+option, it performs a random permutation on the results before printing
+them.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+
+
+
+
diff --git a/doc/s6-dnsip6-filter.html b/doc/s6-dnsip6-filter.html
new file mode 100644
index 0000000..7cbad6b
--- /dev/null
+++ b/doc/s6-dnsip6-filter.html
@@ -0,0 +1,99 @@
+
+
+
+
+ s6-dns: the s6-dnsip6-filter program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsip6-filter program
+
+
+ s6-dnsip6-filter reads domain names on its standard input and
+prints the corresponding IPv6 addresses on its standard output.
+
+
+ Interface
+
+
+ s6-dnsip6-filter [ -l maxlines ] [ -c maxconn ] [ -t timeout ] [ -f normalfmt ] [ -e errorfmt ]
+
+
+
+ - s6-dnsip6-filter reads lines from its stdin, processes them, and prints
+the processed lines to its stdout, in the same order. It exits 0 when it
+reads EOF on stdin.
+ - Every line starting with a domain name is processed. Lines not
+starting with a domain name are not, and the formatting rules treat them
+as a pure "remainder".
+ - For every processed line, an AAAA query is made, and the result is
+printed according to the formatting rules. The domain is not qualified before
+being resolved.
+ - By default, s6-dnsip6-filter looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -l maxlines : maximum lines. s6-dnsip6-filter
+will keep at most maxlines lines in memory at the same time. If line
+n is still waiting for resolution and cannot be printed, then
+s6-dnsip6-filter will stop reading from stdin before line n+maxlines,
+until the result arrives for line n. By default, maxlines
+is 256.
+ - -c maxconn : maximum concurrent resolutions.
+s6-dnsip6-filter will perform at most maxconn resolutions in
+parallel at the same time. maxlines cannot be lesser than maxconn.
+By default, maxconn is 128.
+ - -t timeout : if any resolution takes more
+than timeout milliseconds, then it is aborted and printed as a
+timeout error. By default, timeout is 0, which means no timeout.
+ - -f normalfmt : print the positive results according to
+the normalfmt format string. By default, normalfmt is
+%s=%d%w%r, which means: print the original domain name, then an equal
+sign, then the corresponding IPv6 address, then the remainder of the line.
+ - -e errorfmt : print the negative results according to
+the errorfmt format string. By default, errorfmt is
+%s=<%e%>%w%r, which means: print the original domain name, then an equal
+sign, then the error message between angle brackets, then the remainder of the line.
+
+
+ Formatting rules
+
+
+ normalfmt and errorfmt are format strings, i.e. they tell the
+program how a line must be printed. The following sequences are recognized:
+
+
+
+ - %% prints a single % character
+ - %s prints the original domain name
+ - %d prints the IP address, if any
+ - %e prints the error message, if any
+ - %w%r prints the remainder of the input line
+
+
+ Notes
+
+
+ s6-dnsip6-filter does not perform DNS resolutions itself. Instead, if forks
+a skadnsd child and sends it queries, getting
+the results asynchronously. The s6-dns filter programs have actually been
+written as example uses of the skadns library.
+
+
+
+
diff --git a/doc/s6-dnsip6.html b/doc/s6-dnsip6.html
new file mode 100644
index 0000000..d417011
--- /dev/null
+++ b/doc/s6-dnsip6.html
@@ -0,0 +1,73 @@
+
+
+
+
+ s6-dns: the s6-dnsip6 program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsip6 program
+
+
+ s6-dnsip6 finds the IPv6 addresses associated to a domain name.
+
+
+ Interface
+
+
+ s6-dnsip6 [ -q ] [ -r ] [ -t timeout ] domain
+
+
+
+ - s6-dnsip6 makes an AAAA query for the name domain. It
+waits for the result and prints the obtained IPv6 addresses, one per line,
+then exits 0.
+ - If the domain exists but no relevant field has been found, it exits 1.
+ - If the DNS answered but no answer is available, it prints a relevant
+error message and exits 2.
+ - By default, s6-dnsip6 looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -q : qualify. Qualifies domain before resolution,
+according to suffixes found in /etc/resolv.conf. If the DNSQUALIFY
+environment variable is set and contains a list of suffixes separated by spaces,
+tabs, newlines or carriage returns, then this list is used instead. By
+default, no qualification is used: if domain is not a FQDN, a dot
+is just appended to it.
+ - -r : random. By default, the program does not sort the
+result, but prints them in the order received from the DNS. With this
+option, it performs a random permutation on the results before printing
+them.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+
+
+ Notes
+
+
+ Bear in mind that making AAAA queries is very different, and
+totally independent, from using IPv6 transport for the DNS queries.
+Even if the underlying skalibs has been compiled without IPv6 support,
+or IPv6 DNS transport is unavailable for any reason, you can still perform
+AAAA queries and s6-dnsip6 will answer correctly.
+
+
+
+
diff --git a/doc/s6-dnsmx.html b/doc/s6-dnsmx.html
new file mode 100644
index 0000000..1396aed
--- /dev/null
+++ b/doc/s6-dnsmx.html
@@ -0,0 +1,64 @@
+
+
+
+
+ s6-dns: the s6-dnsmx program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsmx program
+
+
+ s6-dnsmx finds the MX information associated to a domain name.
+
+
+ Interface
+
+
+ s6-dnsmx [ -q ] [ -r ] [ -t timeout ] domain
+
+
+
+ - s6-dnsmx makes an MX query for the name domain. It
+waits for the result and prints the obtained information, one exchanger
+per line, then exits 0. It prints the preference, then a space, then
+the exchanger name.
+ - If the domain exists but no relevant field has been found, it exits 1.
+ - If the DNS answered but no answer is available, it prints a relevant
+error message and exits 2.
+ - By default, s6-dnsmx looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -q : qualify. Qualifies domain before resolution,
+according to suffixes found in /etc/resolv.conf. If the DNSQUALIFY
+environment variable is set and contains a list of suffixes separated by spaces,
+tabs, newlines or carriage returns, then this list is used instead. By
+default, no qualification is used: if domain is not a FQDN, a dot
+is just appended to it.
+ - -r : random. By default, the program does not sort the
+result, but prints them in the order received from the DNS. With this
+option, it performs a random permutation on the results before printing
+them.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+
+
+
+
diff --git a/doc/s6-dnsname-filter.html b/doc/s6-dnsname-filter.html
new file mode 100644
index 0000000..1554270
--- /dev/null
+++ b/doc/s6-dnsname-filter.html
@@ -0,0 +1,103 @@
+
+
+
+
+ s6-dns: the s6-dnsname-filter program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsname-filter program
+
+
+ s6-dnsname-filter reads IP addresses on its standard input and
+prints the corresponding domain names on its standard output.
+
+
+ Interface
+
+
+ s6-dnsname-filter [ -4 ] [ -6 ] [ -l maxlines ] [ -c maxconn ] [ -t timeout ] [ -f normalfmt ] [ -e errorfmt ]
+
+
+
+ - s6-dnsname-filter reads lines from its stdin, processes them, and prints
+the processed lines to its stdout, in the same order. It exits 0 when it
+reads EOF on stdin.
+ - Every line starting with an IP address is processed. Lines not
+starting with an IP address are not, and the formatting rules treat them
+as a pure "remainder".
+ - For every processed line, the read IP address is converted to an
+in-addr.arpa. or ip6.arpa. domain on which a PTR query is made,
+and the result is printed according to the formatting rules.
+ - By default, s6-dnsname-filter looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -4 : scan for IPv4 addresses.
+ - -6 : scan for IPv6 addresses. Both the -4 and
+-6 options may be given. If none is given, by default
+s6-dnsname-filter will only scan for IPv4 addresses.
+ - -l maxlines : maximum lines. s6-dnsname-filter
+will keep at most maxlines lines in memory at the same time. If line
+n is still waiting for resolution and cannot be printed, then
+s6-dnsname-filter will stop reading from stdin before line n+maxlines,
+until the result arrives for line n. By default, maxlines
+is 256.
+ - -c maxconn : maximum concurrent resolutions.
+s6-dnsname-filter will perform at most maxconn resolutions in
+parallel at the same time. maxlines cannot be lesser than maxconn.
+By default, maxconn is 128.
+ - -t timeout : if any resolution takes more
+than timeout milliseconds, then it is aborted and printed as a
+timeout error. By default, timeout is 0, which means no timeout.
+ - -f normalfmt : print the positive results according to
+the normalfmt format string. By default, normalfmt is
+%s=%d%w%r, which means: print the original IP address, then an equal
+sign, then the corresponding domain name, then the remainder of the line.
+ - -e errorfmt : print the negative results according to
+the errorfmt format string. By default, errorfmt is
+%s=<%e%>%w%r, which means: print the original IP address, then an equal
+sign, then the error message between angle brackets, then the remainder of the line.
+
+
+ Formatting rules
+
+
+ normalfmt and errorfmt are format strings, i.e. they tell the
+program how a line must be printed. The following sequences are recognized:
+
+
+
+ - %% prints a single % character
+ - %s prints the original IP address
+ - %d prints the domain name, if any
+ - %e prints the error message, if any
+ - %w%r prints the remainder of the input line
+
+
+ Notes
+
+
+ s6-dnsname-filter does not perform DNS resolutions itself. Instead, if forks
+a skadnsd child and sends it queries, getting
+the results asynchronously. The s6-dns filter programs have actually been
+written as example uses of the skadns library.
+
+
+
+
diff --git a/doc/s6-dnsname.html b/doc/s6-dnsname.html
new file mode 100644
index 0000000..0c0c5b0
--- /dev/null
+++ b/doc/s6-dnsname.html
@@ -0,0 +1,72 @@
+
+
+
+
+ s6-dns: the s6-dnsname program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsname program
+
+
+ s6-dnsname finds the name associated to an IPv4 or IPv6 address.
+
+
+ Interface
+
+
+ s6-dnsname [ -4 | -6 ] [ -r ] [ -t timeout ] ip
+
+
+
+ - s6-dnsname converts the IP address ip to a name
+ending in in-addr.arpa. or ip6.arpa. then makes a
+PTR query for this name.
+It waits for the result and prints the obtained names, one per line,
+then exits 0.
+ - If the domain exists but no relevant field has been found, it exits 1.
+ - If the DNS answered but no answer is available, it prints a relevant
+error message and exits 2.
+ - By default, s6-dnsname looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -4 : interpret ip as an IPv4 address.
+ - -6 : interpret ip as an IPv6 address.
+If neither of the -4 and -6 is given, or if both are
+given, then ip will be interpreted as v4 or v6 depending on
+its syntax.
+ - -r : random. By default, the program does not sort the
+result, but prints them in the order received from the DNS. With this
+option, it performs a random permutation on the results before printing
+them.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+
+
+ Notes
+
+
+ - If the underlying skalibs has been compiled with IPv6 support disabled,
+s6-dnsname will not be able to use IPv6 transport for its resolution, but it
+will still accept and resolve IPv6 addresses.
+
+
+
+
diff --git a/doc/s6-dnsns.html b/doc/s6-dnsns.html
new file mode 100644
index 0000000..c15a7df
--- /dev/null
+++ b/doc/s6-dnsns.html
@@ -0,0 +1,63 @@
+
+
+
+
+ s6-dns: the s6-dnsns program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsns program
+
+
+ s6-dnsns finds the relevant nameservers providing data for a domain.
+
+
+ Interface
+
+
+ s6-dnsns [ -q ] [ -r ] [ -t timeout ] domain
+
+
+
+ - s6-dnsns makes an NS query for the name domain. It
+waits for the result and prints the obtained information, one name
+per line, then exits 0.
+ - If the domain exists but no relevant field has been found, it exits 1.
+ - If the DNS answered but no answer is available, it prints a relevant
+error message and exits 2.
+ - By default, s6-dnsns looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -q : qualify. Qualifies domain before resolution,
+according to suffixes found in /etc/resolv.conf. If the DNSQUALIFY
+environment variable is set and contains a list of suffixes separated by spaces,
+tabs, newlines or carriage returns, then this list is used instead. By
+default, no qualification is used: if domain is not a FQDN, a dot
+is just appended to it.
+ - -r : random. By default, the program does not sort the
+result, but prints them in the order received from the DNS. With this
+option, it performs a random permutation on the results before printing
+them.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+
+
+
+
diff --git a/doc/s6-dnsq.html b/doc/s6-dnsq.html
new file mode 100644
index 0000000..9a22602
--- /dev/null
+++ b/doc/s6-dnsq.html
@@ -0,0 +1,82 @@
+
+
+
+
+ s6-dns: the s6-dnsq program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsq program
+
+
+ s6-dnsq is an analysis and debug tool. It performs a non-recursive DNS query
+to a given list of servers,
+then prints the contents of the answer packet, and optionally debug
+information during the resolution.
+
+
+ Interface
+
+
+ s6-dnsq [ -1 | -2 ] [ -t timeout ] [ -D level ] qtype domain serverlist
+
+
+
+ - s6-dnsq makes an iterative DNS query of type qtype for the name domain
+to serverlist.
+It prints the answer packet, in human-readable form, to its standard output,
+then exits 0.
+ - It does not qualify domain.
+ - If the resolution fails for some reason, s6-dnsq exits 2.
+ - serverlist is a list of IP addresses (v4 or v6), one or more addresses
+per argument on the command line (so you can use, for instance,
+`s6-dnsip4 ns.example.com` as argument, and get all the addresses for
+ns.example.com in your server list).
+Servers are tried in the order given, until a definitive
+answer is obtained or s6-dnsq runs out of server addresses.
+
+
+ Options
+
+
+ - -1 : send debug information to stdout.
+ - -2 : send debug information to stderr. This is the default. Note that
+those options only apply to debug output, not to the regular packet dump, which
+is always printed to stdout.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+ - -D level : produce debug output during
+resolution. If level is:
+
+ - 0: no debug output is produced
+ - 1: information is printed when s6-dnsq receives a DNS packet from a server
+ - 2: information is printed before and after s6-dnsq sends a DNS packet to a server
+ - 3: both 1. and 2. apply
+
+
+
+ Notes
+
+
+ - TXT records are printed in a quoted form similar to
+s6-quote's
+output.
+ - If s6-dnsq finds a record it cannot print, such as an unknown RR type,
+it dumps its contents in the same quoted form.
+ - The normal output format should be stable, so you can write programs that
+automatically parse it. However, the debug output format is undocumented and subject
+to change.
+
+
+
+
diff --git a/doc/s6-dnsqr.html b/doc/s6-dnsqr.html
new file mode 100644
index 0000000..ce308bd
--- /dev/null
+++ b/doc/s6-dnsqr.html
@@ -0,0 +1,80 @@
+
+
+
+
+ s6-dns: the s6-dnsqr program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsqr program
+
+
+ s6-dnsqr is an analysis and debug tool. It performs a DNS resolution,
+then prints the contents of the answer packet, and optionally debug
+information during the resolution.
+
+
+ Interface
+
+
+ s6-dnsqr [ -1 | -2 ] [ -t timeout ] [ -D level ] qtype domain
+
+
+
+ - s6-dnsqr makes a recursive DNS query of type qtype for the name domain.
+It prints the answer packet, in human-readable form, to its standard output,
+then exits 0.
+ - It does not qualify domain.
+ - If the resolution fails for some reason, s6-dnsqr exits 2.
+ - By default, s6-dnsqr looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -1 : send debug information to stdout.
+ - -2 : send debug information to stderr. This is the default. Not that
+those options only apply to debug output, not to the regular packet dump, which
+is always printed to stdout.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+ - -D level : produce debug output during
+resolution. If level is:
+
+ - 0: no debug output is produced
+ - 1: information is printed when s6-dnsqr receives a DNS packet from a cache
+ - 2: information is printed before and after s6-dnsqr sends a DNS packet to a cache
+ - 3: both 1. and 2. apply
+
+
+
+
+ Notes
+
+
+ - TXT records are printed in a quoted form similar to
+s6-quote's
+output.
+ - If s6-dnsqr finds a record it cannot print, such as an unknown RR type,
+it dumps its content in the same quoted form.
+ - The normal output format should be stable, so you can write programs that
+automatically parse it. However, the debug output format is undocumented and subject
+to change.
+
+
+
+
diff --git a/doc/s6-dnsqualify.html b/doc/s6-dnsqualify.html
new file mode 100644
index 0000000..f515be7
--- /dev/null
+++ b/doc/s6-dnsqualify.html
@@ -0,0 +1,41 @@
+
+
+
+
+ s6-dns: the s6-dnsqualify program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnsqualify program
+
+
+ s6-dnsqualify qualifies a domain name.
+
+
+ Interface
+
+
+ s6-dnsqualify domain
+
+
+
+ - s6-dnsqualify qualifies domain according to the "domain" and
+"search" rules in /etc/resolv.conf. It prints the result on
+stdout, one FQDN per line.
+ - If the DNSQUALIFY
+environment variable is set and contains a list of suffixes separated by spaces,
+tabs, newlines or carriage returns, then this list is used instead of the
+/etc/resolv.conf rules.
+
+
+
+
diff --git a/doc/s6-dnssoa.html b/doc/s6-dnssoa.html
new file mode 100644
index 0000000..6f4a8f2
--- /dev/null
+++ b/doc/s6-dnssoa.html
@@ -0,0 +1,65 @@
+
+
+
+
+ s6-dns: the s6-dnssoa program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnssoa program
+
+
+ s6-dnssoa finds the SOA information associated to a domain.
+
+
+ Interface
+
+
+ s6-dnssoa [ -q ] [ -r ] [ -t timeout ] domain
+
+
+
+ - s6-dnsmx makes an SOA query for the name domain. It
+waits for the result and prints the obtained information line by line,
+then exits 0. It prints the mname, the rname, the serial number, and
+the refresh, retry, expiration and minimum times, in that order,
+separated by spaces.
+ - If the domain exists but no relevant field has been found, it exits 1.
+ - If the DNS answered but no answer is available, it prints a relevant
+error message and exits 2.
+ - By default, s6-dnssoa looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -q : qualify. Qualifies domain before resolution,
+according to suffixes found in /etc/resolv.conf. If the DNSQUALIFY
+environment variable is set and contains a list of suffixes separated by spaces,
+tabs, newlines or carriage returns, then this list is used instead. By
+default, no qualification is used: if domain is not a FQDN, a dot
+is just appended to it.
+ - -r : random. By default, the program does not sort the
+result, but prints them in the order received from the DNS. With this
+option, it performs a random permutation on the results before printing
+them.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+
+
+
+
diff --git a/doc/s6-dnssrv.html b/doc/s6-dnssrv.html
new file mode 100644
index 0000000..2a88408
--- /dev/null
+++ b/doc/s6-dnssrv.html
@@ -0,0 +1,65 @@
+
+
+
+
+ s6-dns: the s6-dnssrv program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnssrv program
+
+
+ s6-dnssrv finds the SRV information associated to a
+service name, protocol name and domain name.
+
+
+ Interface
+
+
+ s6-dnssrv [ -q ] [ -r ] [ -t timeout ] service proto domain
+
+
+
+ - s6-dnssrv makes an SRV query for _service._proto.domain.
+It waits for the result and prints the obtained information line by line,
+then exits 0. It prints the priority, the weight, the port number and the
+target, in that order, separated by spaces.
+ - If the domain exists but no relevant field has been found, it exits 1.
+ - If the DNS answered but no answer is available, it prints a relevant
+error message and exits 2.
+ - By default, s6-dnssrv looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -q : qualify. Qualifies domain before resolution,
+according to suffixes found in /etc/resolv.conf. If the DNSQUALIFY
+environment variable is set and contains a list of suffixes separated by spaces,
+tabs, newlines or carriage returns, then this list is used instead. By
+default, no qualification is used: if domain is not a FQDN, a dot
+is just appended to it.
+ - -r : random. By default, the program does not sort the
+result, but prints them in the order received from the DNS. With this
+option, it performs a random permutation on the results before printing
+them.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+
+
+
+
diff --git a/doc/s6-dnstxt.html b/doc/s6-dnstxt.html
new file mode 100644
index 0000000..fa84174
--- /dev/null
+++ b/doc/s6-dnstxt.html
@@ -0,0 +1,77 @@
+
+
+
+
+ s6-dns: the s6-dnstxt program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-dnstxt program
+
+
+ s6-dnstxt finds the TXT information associated to a domain name.
+
+
+ Interface
+
+
+ s6-dnstxt [ -q ] [ -r ] [ -t timeout ] domain
+
+
+
+ - s6-dnstxt makes a TXT query for the name domain. It
+waits for the result and prints the obtained strings, one by line,
+in a quoted form similar to
+s6-quote's
+output. You can pipe s6-dnstxt's output through
+s6-unquote-filter
+to get unquoted TXT fields.
+ - If the domain exists but no relevant field has been found, it exits 1.
+ - If the DNS answered but no answer is available, it prints a relevant
+error message and exits 2.
+ - By default, s6-dnstxt looks for DNS cache addresses in the
+/etc/resolv.conf file. If the DNSCACHEIP environment variable is set
+and contains a list of IP (v4 or v6) addresses, separated by commas,
+semicolons, spaces, tabs, newlines or carriage returns, then this list
+is used instead.
+
+
+ Options
+
+
+ - -q : qualify. Qualifies domain before resolution,
+according to suffixes found in /etc/resolv.conf. If the DNSQUALIFY
+environment variable is set and contains a list of suffixes separated by spaces,
+tabs, newlines or carriage returns, then this list is used instead. By
+default, no qualification is used: if domain is not a FQDN, a dot
+is just appended to it.
+ - -r : random. By default, the program does not sort the
+result, but prints them in the order received from the DNS. With this
+option, it performs a random permutation on the results before printing
+them.
+ - -t timeout : if the resolution takes more
+than timeout milliseconds, then it exits 99 right away with an error
+message. By default, timeout is 0, which means no timeout.
+
+
+ Notes
+
+
+ There can be more than one character-string in a TXT RR, and there can be
+more than one TXT RR per domain. DNS clients usually concatenate all this
+and only give one string. s6-dnstxt concatenates all the character-strings
+in one TXT record, but separates different TXT records, printing each one
+on a separate line.
+
+
+
+
diff --git a/doc/s6-randomip.html b/doc/s6-randomip.html
new file mode 100644
index 0000000..0ad3b46
--- /dev/null
+++ b/doc/s6-randomip.html
@@ -0,0 +1,57 @@
+
+
+
+
+ s6-dns: the s6-randomip program
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The s6-randomip program
+
+
+ s6-randomip generates random IP addresses and prints them to
+its standard output, one per line.
+
+
+ Interface
+
+
+ s6-randomip [ -4 ] [ -6 ] [ -n max ]
+
+
+
+ - s6-randomip makes up IP addresses and prints
+them to its stdout. It keeps running until it receives a signal.
+ - IP addresses are not guaranteed to represent anything. They are totally random.
+
+
+ Options
+
+
+ - -4 : generate IPv4 addresses.
+ - -6 : generate IPv6 addresses. Both the -4 and
+-6 options may be given. If none is given, by default
+s6-randomip will only generate IPv4 addresses.
+ - -n max : s6-randomip will only generate
+max addresses, then exit 0, instead of running forever.
+
+
+ Notes
+
+
+ s6-randomip can be used in conjunction with
+s6-dnsname-filter to stress-test your
+DNS architecture. Please use this responsibly and ethically.
+
+
+
+
diff --git a/doc/skadns/index.html b/doc/skadns/index.html
new file mode 100644
index 0000000..f02f2dd
--- /dev/null
+++ b/doc/skadns/index.html
@@ -0,0 +1,262 @@
+
+
+
+
+ s6-dns: the skadns library interface
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ The skadns library interface
+
+
+ The skadns library provides an API for asynchronous DNS
+resolution.
+
+
+ Compiling
+
+
+
+ - Make sure the s6-dns headers, as well as the skalibs headers,
+are visible in your header search path.
+ - Use #include <s6-dns/skadns.h>
+ - You might also want to include the s6-dns/s6dns.h header for
+the definition of the s6dns_domain_t type and the various
+qtype constants
+
+
+ Linking
+
+
+ - Make sure the s6 libraries, as well as the skalibs libraries,
+are visible in your library search path.
+ - Link against -lskadns and -lskarnet.
+ - If you're using a skadnsd service, also add `cat $SYSDEPS/socket.lib`
+to the end of your linking command line, $SYSDEPS standing for your
+skalibs sysdeps directory.
+
+
+
+ Programming
+
+
+ Check the s6-dns/skadns.h header for the
+exact function prototypes.
+
+
+
+ Make sure your application is not disturbed by children it doesn't
+know it has. This means paying some attention to the SIGCHLD handler,
+if any, and to the way you perform waitpid()s. The best
+practice is to use a
+self-pipe
+to handle SIGCHLD (as well as other signals the application needs to trap),
+and to always use wait_nohang() to reap children,
+simply ignoring pids you don't know.
+
+
+
+ If your (badly programmed) application has trouble handling unknown
+children, consider using a skadnsd service.
+
+
+ A programming example
+
+
+ The src/clients/s6dns_generic_filter_main.c file in the s6-dns
+package, used in the s6-dns*-filter programs, illustrates how to
+use the skadns library.
+
+
+ Starting and ending a session
+
+
+skadns_t a = SKADNS_ZERO ;
+tain_t deadline, stamp ;
+
+tain_now(&stamp) ;
+tain_addsec(&deadline, &stamp, 2)
+
+// char const *path = SKADNS_IPCPATH ;
+// skadns_start(&a, path, &deadline, &stamp) ;
+skadns_startf(&a, &deadline, &stamp) ;
+
+
+
+skadns_start starts a session with a skadnsd service, listening
+on path.
+skadns_startf starts a session with a skadnsd process as a child
+(which is the simplest usage).
+a is a skadns_t structure that must be declared and
+initialized to SKADNS_ZERO.
+stamp must be an accurate enough timestamp.
+If the session initialization fails, the function returns 0 and errno is set;
+else the function returns 1.
+
+
+If the absolute time deadline is reached and the function
+has not returned yet, it immediately returns 0 with errno set to ETIMEDOUT.
+
+Only local interprocess communications are involved; unless your system is
+heavily overloaded, the function should return near-instantly. One or two
+seconds of delay between stamp and deadline should be
+enough: if the function takes more than that to return, then there is a
+problem with the underlying processes.
+
+
+
+ You can have more than one session open in parallel, by declaring
+several distinct skadns_t structures and calling
+skadns_startf (or skadns_start) more than once.
+However, this is only useful if you need to perform more than
+SKADNS_MAXCONCURRENCY, i.e. a thousand, concurrent requests. In
+most situations, a single skadns session will be enough.
+
+
+
+skadns_end(&a) ;
+
+
+
+skadns_end frees all the resources used by the session. The
+a structure is then reusable for another session.
+
+
+ Sending a DNS query
+
+
+s6dns_domain_t d ;
+uint16 qtype ;
+uint16 id ;
+tain_t limit, deadline, stamp ;
+
+skadns_send(&a, &id, &d, qtype, &limit, &deadline, &stamp) ;
+
+
+
+skadns_send starts the asynchronous resolution of domain d
+with query type qtype. d must be encoded in packet form.
+stamp must be an accurate enough timetamp.
+If the resolution hasn't completed by deadline limit, it will
+automatically fail with a status set to ETIMEDOUT.
+
+
+
+ Like skadns_startf(), the skadns_send() call
+is synchronous but should not be blocking; however, if it hasn't returned by
+deadline deadline, it then returns 0 with errno set to ETIMEDOUT.
+On failure, the call returns 0 and sets errno. On success, it returns 1 and
+id is set to a 16-bit number identifying the query.
+
+
+ Cancelling a query
+
+
+skadns_cancel(&a, id, &deadline, &stamp) ;
+
+
+
+ skadns_cancel cancels the resolution identified by id.
+stamp must be an accurate enough timestamp.
+The call returns 1 on success, or 0 (and sets errno) on failure. It is
+synchronous but should return almost-instantly; if it hasn't returned
+by deadline, it then returns 0 ETIMEDOUT.
+
+
+
+ After a query has been successfully canceled, its id can be discarded.
+
+
+ Asynchronously waiting for answers
+
+
+ (from now on, the functions are listed with their prototypes instead
+of usage examples.)
+
+
+
+int skadns_fd (skadns_t const *a)
+
+
+
+ Returns a file descriptor to select on for reading. Do not
+read() it though.
+
+
+
+int skadns_update (skadns_t *a)
+
+
+
+ Call this function whenever the fd checks readability: it will
+update a's internal structures with information from the
+skadnsd daemon. It returns -1 if an error
+occurs; in case of success, it returns the number of identifiers for
+which something happened.
+
+
+
+ When skadns_update returns,
+genalloc_s(uint16, &a->list) points to an array of
+genalloc_len(uint16, &a->list) 16-bit unsigned
+integers. Those integers are valid ids that can be used with the
+following functions.
+
+
+
+char const *skadns_packet (skadns_t *a, uint16 id)
+int skadns_packetlen (skadns_t *a, uint16 id)
+
+
+
+ skadns_packet() returns a pointer to the DNS packet
+containing the answer to the query identified by id,
+and skadns_packetlen() returns its length. If an
+error has occurred, skadns_packet() returns NULL and
+skadns_packetlen() returns -1; either call sets errno
+to a value identifying the error. Some errno values have a
+special meaning:
+
+
+
+ - EAGAIN: the result has not arrived yet.
+ - ECANCELED: the query has been canceled.
+ - EINVAL: id does not identify a valid query. Note
+that if you get EINVAL, then
+id is invalid, but the reverse is not true:
+using invalid ids is a programming error and may result in a crash.
+
+
+
+int skadns_release (skadns_t *a, uint16 id)
+
+
+
+ skadns_release() frees the cell holding the result of
+query id. It returns 1 on success, then id can
+be discarded - further calls to skadns_send() may reuse
+the same number.
+
+
+
+ skadns_release() may fail, and return 0. This signals a
+programming error and shouldn't be relied on - however, if it happens,
+errno can help you identify the problem:
+
+
+
+ - EBUSY: the query is still pending, cancelled or not.
+ - EINVAL: id is invalid.
+
+
+
+
diff --git a/doc/skadns/skadnsd.html b/doc/skadns/skadnsd.html
new file mode 100644
index 0000000..e8316b8
--- /dev/null
+++ b/doc/skadns/skadnsd.html
@@ -0,0 +1,120 @@
+
+
+
+
+ s6-dns: the skadnsd internal program
+
+
+
+
+
+
+libskadns
+s6-dns
+Software
+skarnet.org
+
+ The skadnsd program
+
+
+skadnsd is the skadns daemon. It reads a series of
+queries from the client on stdin, resolves them asynchronously,
+and writes
+the answers to the client as soon as it gets them. It exits 0
+when its stdin closes. It exits 111 on any serious error,
+writing the error message to stderr.
+
+
+
+skadnsd is a stub resolver. It reads /etc/resolv.conf
+at start looking for a "nameserver" line containing
+the address of a DNS cache (aka full resolver). It will exit 111 if it cannot
+find any valid cache address in /etc/resolv.conf. If the
+DNSCACHEIP environment variable is set, its value overrides
+what /etc/resolv.conf says.
+
+
+ Interface
+
+
+skadnsd does not fork, does not background itself automatically,
+and does not use syslog. It is not meant to be run directly by the
+user: it will be invoked and spawned by the skadns library calls.
+
+
+
+ There are 2 ways to use skadnsd:
+
+
+- (preferred) Use the skadns_startf() library call.
+A skadnsd child will then be spawned from your
+calling process, and automatically reaped when you call
+skadns_end(). It requires care with applications that
+trap SIGCHLD.
+- Use the skadns_start() library call, together with
+a skadnsd service.
+
+
+ Running skadnsd as a child process
+
+
+ This is the simplest and safest way of using skadns. Forget
+about skadnsd: just start your library calls with
+skadns_startf() and end them with skadns_end().
+Be careful though: if you're using SIGCHLD handlers, make sure they do
+not interfere with the child processes your application has without
+knowing. This is a general Unix programming rule.
+
+
+ Running a skadnsd as a daemon: the skadnsd service
+
+
+ In this mode, you set up a daemon listening on a Unix domain socket,
+and clients connect to this socket to access the service. The
+advantage of this setup is that it works even with badly written
+clients that have trouble handling a child process; the drawback is
+that it requires support from the system administrator.
+
+
+
+skadnsd has no "standalone" mode: it is designed to work with a Unix
+domain superserver, like
+s6-ipcserver.
+skadnsd follows the UCSPI"
+interface, it can be directly executed from the superserver.
+
+
+
+You should run skadnsd (and its Unix superserver) under a specific user
+and group, for elementary security reasons; and you should run its
+dedicated logger as another specific user. Do NOT run skadnsd as root;
+check your super-server documentation to find how
+to run it under a specific account.
+
+
+ Notes
+
+
+ - Users should never invoke skadnsd directly. It's an
+internal program designed to be spawned by the skadns library.
+ - If a poorly designed client sends a lot of queries and never reads the
+answers, those will indefinitely queue up in the daemon, eating up
+memory. You should run your process (or your Unix superserver, if you're
+using a skadnsd service) under a program like
+s6-softlimit to
+set a memory limit to every skadnsd instance. If skadnsd runs out of
+allowed memory, it will simply die.
+ - If you're using a skadnsd service: you should configure your
+Unix superserver to set a maximum
+number of concurrent skadnsd instances; most
+Unix superserver implementations provide the
+-c option for this. The s6-ipcserver program also
+allows you to specify a maximum number of concurrent daemon
+instances per client.
+- The only way to ensure absolute reliability of the skadnsd process is
+to run it as a child, not as a daemon: use skadnsd_startf() when
+possible.
+
+
+
+
diff --git a/doc/upgrade.html b/doc/upgrade.html
new file mode 100644
index 0000000..c75d08e
--- /dev/null
+++ b/doc/upgrade.html
@@ -0,0 +1,32 @@
+
+
+
+
+ s6-dns: how to upgrade
+
+
+
+
+
+
+
+s6-dns
+Software
+skarnet.org
+
+
+ What has changed in s6-dns
+
+ in 2.0.0.0
+
+
+ - The build system has completely changed. It is now a standard
+./configure && make && sudo make install
+build system. See the enclosed INSTALL file for details.
+ - slashpackage is not activated by default.
+ - shared libraries are not used by default.
+ - skalibs dependency bumped to 2.0.0.0.
+
+
+
+
diff --git a/package/deps-build b/package/deps-build
new file mode 100644
index 0000000..05d5af4
--- /dev/null
+++ b/package/deps-build
@@ -0,0 +1 @@
+/package/prog/skalibs
diff --git a/package/deps.mak b/package/deps.mak
new file mode 100644
index 0000000..e298f1b
--- /dev/null
+++ b/package/deps.mak
@@ -0,0 +1,150 @@
+#
+# This file has been generated by tools/gen-deps.sh
+#
+
+src/include/s6-dns/s6dns-analyze.h: src/include/s6-dns/s6dns-message.h
+src/include/s6-dns/s6dns-debug.h: src/include/s6-dns/s6dns-engine.h
+src/include/s6-dns/s6dns-engine.h: src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-ip46.h
+src/include/s6-dns/s6dns-fmt.h: src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-message.h
+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.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/clients/s6dns-generic-filter.h: src/include/s6-dns/s6dns-domain.h
+src/clients/s6-dnsip4-filter.o src/clients/s6-dnsip4-filter.lo: src/clients/s6-dnsip4-filter.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-message.h src/clients/s6dns-generic-filter.h
+src/clients/s6-dnsip4.o src/clients/s6-dnsip4.lo: src/clients/s6-dnsip4.c src/include/s6-dns/s6dns.h
+src/clients/s6-dnsip6-filter.o src/clients/s6-dnsip6-filter.lo: src/clients/s6-dnsip6-filter.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-message.h src/clients/s6dns-generic-filter.h
+src/clients/s6-dnsip6.o src/clients/s6-dnsip6.lo: src/clients/s6-dnsip6.c src/include/s6-dns/s6dns.h
+src/clients/s6-dnsmx.o src/clients/s6-dnsmx.lo: src/clients/s6-dnsmx.c src/include/s6-dns/s6dns.h
+src/clients/s6-dnsname-filter.o src/clients/s6-dnsname-filter.lo: src/clients/s6-dnsname-filter.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-message.h src/clients/s6dns-generic-filter.h
+src/clients/s6-dnsname.o src/clients/s6-dnsname.lo: src/clients/s6-dnsname.c
+src/clients/s6-dnsns.o src/clients/s6-dnsns.lo: src/clients/s6-dnsns.c src/include/s6-dns/s6dns.h
+src/clients/s6-dnsq.o src/clients/s6-dnsq.lo: src/clients/s6-dnsq.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-debug.h src/include/s6-dns/s6dns.h
+src/clients/s6-dnsqr.o src/clients/s6-dnsqr.lo: src/clients/s6-dnsqr.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-debug.h src/include/s6-dns/s6dns.h
+src/clients/s6-dnsqualify.o src/clients/s6-dnsqualify.lo: src/clients/s6-dnsqualify.c src/include/s6-dns/s6dns.h
+src/clients/s6-dnssoa.o src/clients/s6-dnssoa.lo: src/clients/s6-dnssoa.c src/include/s6-dns/s6dns.h
+src/clients/s6-dnssrv.o src/clients/s6-dnssrv.lo: src/clients/s6-dnssrv.c src/include/s6-dns/s6dns.h
+src/clients/s6-dnstxt.o src/clients/s6-dnstxt.lo: src/clients/s6-dnstxt.c src/include/s6-dns/s6dns.h
+src/clients/s6-randomip.o src/clients/s6-randomip.lo: src/clients/s6-randomip.c
+src/clients/s6dns_generic_filter_main.o src/clients/s6dns_generic_filter_main.lo: src/clients/s6dns_generic_filter_main.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-domain.h src/include/s6-dns/skadns.h src/clients/s6dns-generic-filter.h
+src/clients/s6dns_namescanner.o src/clients/s6dns_namescanner.lo: src/clients/s6dns_namescanner.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-generic-filter.h
+src/libs6dns/s6dns_analyze_packet.o src/libs6dns/s6dns_analyze_packet.lo: src/libs6dns/s6dns_analyze_packet.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_qtype_parse.o src/libs6dns/s6dns_analyze_qtype_parse.lo: src/libs6dns/s6dns_analyze_qtype_parse.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-constants.h
+src/libs6dns/s6dns_analyze_record.o src/libs6dns/s6dns_analyze_record.lo: src/libs6dns/s6dns_analyze_record.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_record_a.o src/libs6dns/s6dns_analyze_record_a.lo: src/libs6dns/s6dns_analyze_record_a.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_record_aaaa.o src/libs6dns/s6dns_analyze_record_aaaa.lo: src/libs6dns/s6dns_analyze_record_aaaa.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_record_domain.o src/libs6dns/s6dns_analyze_record_domain.lo: src/libs6dns/s6dns_analyze_record_domain.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_record_hinfo.o src/libs6dns/s6dns_analyze_record_hinfo.lo: src/libs6dns/s6dns_analyze_record_hinfo.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_record_mx.o src/libs6dns/s6dns_analyze_record_mx.lo: src/libs6dns/s6dns_analyze_record_mx.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_record_soa.o src/libs6dns/s6dns_analyze_record_soa.lo: src/libs6dns/s6dns_analyze_record_soa.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_record_srv.o src/libs6dns/s6dns_analyze_record_srv.lo: src/libs6dns/s6dns_analyze_record_srv.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_record_strings.o src/libs6dns/s6dns_analyze_record_strings.lo: src/libs6dns/s6dns_analyze_record_strings.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_record_unknown.o src/libs6dns/s6dns_analyze_record_unknown.lo: src/libs6dns/s6dns_analyze_record_unknown.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_analyze_rtypetable.o src/libs6dns/s6dns_analyze_rtypetable.lo: src/libs6dns/s6dns_analyze_rtypetable.c src/include/s6-dns/s6dns-analyze.h
+src/libs6dns/s6dns_constants_error.o src/libs6dns/s6dns_constants_error.lo: src/libs6dns/s6dns_constants_error.c src/include/s6-dns/s6dns-constants.h
+src/libs6dns/s6dns_constants_error_str.o src/libs6dns/s6dns_constants_error_str.lo: src/libs6dns/s6dns_constants_error_str.c src/include/s6-dns/s6dns-constants.h
+src/libs6dns/s6dns_debug_dumpdt_post_recv.o src/libs6dns/s6dns_debug_dumpdt_post_recv.lo: src/libs6dns/s6dns_debug_dumpdt_post_recv.c src/include/s6-dns/s6dns-debug.h src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_debug_dumpdt_post_send.o src/libs6dns/s6dns_debug_dumpdt_post_send.lo: src/libs6dns/s6dns_debug_dumpdt_post_send.c src/include/s6-dns/s6dns-debug.h src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_debug_dumpdt_pre_send.o src/libs6dns/s6dns_debug_dumpdt_pre_send.lo: src/libs6dns/s6dns_debug_dumpdt_pre_send.c src/include/s6-dns/s6dns-analyze.h src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-debug.h src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-ip46.h
+src/libs6dns/s6dns_debug_dumpdt_stderr.o src/libs6dns/s6dns_debug_dumpdt_stderr.lo: src/libs6dns/s6dns_debug_dumpdt_stderr.c src/include/s6-dns/s6dns-debug.h src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_debug_dumpdt_stdout.o src/libs6dns/s6dns_debug_dumpdt_stdout.lo: src/libs6dns/s6dns_debug_dumpdt_stdout.c src/include/s6-dns/s6dns-debug.h src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_debughook_zero.o src/libs6dns/s6dns_debughook_zero.lo: src/libs6dns/s6dns_debughook_zero.c src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_domain_arpafromip4.o src/libs6dns/s6dns_domain_arpafromip4.lo: src/libs6dns/s6dns_domain_arpafromip4.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_arpafromip6.o src/libs6dns/s6dns_domain_arpafromip6.lo: src/libs6dns/s6dns_domain_arpafromip6.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_decode.o src/libs6dns/s6dns_domain_decode.lo: src/libs6dns/s6dns_domain_decode.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_encode.o src/libs6dns/s6dns_domain_encode.lo: src/libs6dns/s6dns_domain_encode.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_encodelist.o src/libs6dns/s6dns_domain_encodelist.lo: src/libs6dns/s6dns_domain_encodelist.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_fromstring.o src/libs6dns/s6dns_domain_fromstring.lo: src/libs6dns/s6dns_domain_fromstring.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_fromstring_noqualify_encode.o src/libs6dns/s6dns_domain_fromstring_noqualify_encode.lo: src/libs6dns/s6dns_domain_fromstring_noqualify_encode.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_fromstring_qualify_encode.o src/libs6dns/s6dns_domain_fromstring_qualify_encode.lo: src/libs6dns/s6dns_domain_fromstring_qualify_encode.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_noqualify.o src/libs6dns/s6dns_domain_noqualify.lo: src/libs6dns/s6dns_domain_noqualify.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_qualify.o src/libs6dns/s6dns_domain_qualify.lo: src/libs6dns/s6dns_domain_qualify.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_domain_tostring.o src/libs6dns/s6dns_domain_tostring.lo: src/libs6dns/s6dns_domain_tostring.c src/include/s6-dns/s6dns-domain.h
+src/libs6dns/s6dns_engine.o src/libs6dns/s6dns_engine.lo: src/libs6dns/s6dns_engine.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-message-internal.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_engine_free.o src/libs6dns/s6dns_engine_free.lo: src/libs6dns/s6dns_engine_free.c src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_engine_freen.o src/libs6dns/s6dns_engine_freen.lo: src/libs6dns/s6dns_engine_freen.c src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_engine_here.o src/libs6dns/s6dns_engine_here.lo: src/libs6dns/s6dns_engine_here.c src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_engine_nextdeadline.o src/libs6dns/s6dns_engine_nextdeadline.lo: src/libs6dns/s6dns_engine_nextdeadline.c src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_engine_zero.o src/libs6dns/s6dns_engine_zero.lo: src/libs6dns/s6dns_engine_zero.c src/include/s6-dns/s6dns-engine.h
+src/libs6dns/s6dns_fmt_domainlist.o src/libs6dns/s6dns_fmt_domainlist.lo: src/libs6dns/s6dns_fmt_domainlist.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-fmt.h
+src/libs6dns/s6dns_fmt_hinfo.o src/libs6dns/s6dns_fmt_hinfo.lo: src/libs6dns/s6dns_fmt_hinfo.c src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_fmt_mx.o src/libs6dns/s6dns_fmt_mx.lo: src/libs6dns/s6dns_fmt_mx.c src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_fmt_soa.o src/libs6dns/s6dns_fmt_soa.lo: src/libs6dns/s6dns_fmt_soa.c src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_fmt_srv.o src/libs6dns/s6dns_fmt_srv.lo: src/libs6dns/s6dns_fmt_srv.c src/include/s6-dns/s6dns-fmt.h src/include/s6-dns/s6dns-message.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
+src/libs6dns/s6dns_message_counts_unpack.o src/libs6dns/s6dns_message_counts_unpack.lo: src/libs6dns/s6dns_message_counts_unpack.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_counts_zero.o src/libs6dns/s6dns_message_counts_zero.lo: src/libs6dns/s6dns_message_counts_zero.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_get_domain.o src/libs6dns/s6dns_message_get_domain.lo: src/libs6dns/s6dns_message_get_domain.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-message-internal.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_get_domain_internal.o src/libs6dns/s6dns_message_get_domain_internal.lo: src/libs6dns/s6dns_message_get_domain_internal.c src/libs6dns/s6dns-message-internal.h
+src/libs6dns/s6dns_message_get_hinfo.o src/libs6dns/s6dns_message_get_hinfo.lo: src/libs6dns/s6dns_message_get_hinfo.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_get_mx.o src/libs6dns/s6dns_message_get_mx.lo: src/libs6dns/s6dns_message_get_mx.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_get_soa.o src/libs6dns/s6dns_message_get_soa.lo: src/libs6dns/s6dns_message_get_soa.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_get_srv.o src/libs6dns/s6dns_message_get_srv.lo: src/libs6dns/s6dns_message_get_srv.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_get_string.o src/libs6dns/s6dns_message_get_string.lo: src/libs6dns/s6dns_message_get_string.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-message.h src/libs6dns/s6dns-message-internal.h
+src/libs6dns/s6dns_message_get_string_internal.o src/libs6dns/s6dns_message_get_string_internal.lo: src/libs6dns/s6dns_message_get_string_internal.c src/libs6dns/s6dns-message-internal.h
+src/libs6dns/s6dns_message_get_strings.o src/libs6dns/s6dns_message_get_strings.lo: src/libs6dns/s6dns_message_get_strings.c src/include/s6-dns/s6dns-message.h src/libs6dns/s6dns-message-internal.h
+src/libs6dns/s6dns_message_header_pack.o src/libs6dns/s6dns_message_header_pack.lo: src/libs6dns/s6dns_message_header_pack.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_header_unpack.o src/libs6dns/s6dns_message_header_unpack.lo: src/libs6dns/s6dns_message_header_unpack.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_header_zero.o src/libs6dns/s6dns_message_header_zero.lo: src/libs6dns/s6dns_message_header_zero.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse.o src/libs6dns/s6dns_message_parse.lo: src/libs6dns/s6dns_message_parse.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_answer_a.o src/libs6dns/s6dns_message_parse_answer_a.lo: src/libs6dns/s6dns_message_parse_answer_a.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_answer_aaaa.o src/libs6dns/s6dns_message_parse_answer_aaaa.lo: src/libs6dns/s6dns_message_parse_answer_aaaa.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_answer_domain.o src/libs6dns/s6dns_message_parse_answer_domain.lo: src/libs6dns/s6dns_message_parse_answer_domain.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_answer_hinfo.o src/libs6dns/s6dns_message_parse_answer_hinfo.lo: src/libs6dns/s6dns_message_parse_answer_hinfo.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_answer_mx.o src/libs6dns/s6dns_message_parse_answer_mx.lo: src/libs6dns/s6dns_message_parse_answer_mx.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_answer_soa.o src/libs6dns/s6dns_message_parse_answer_soa.lo: src/libs6dns/s6dns_message_parse_answer_soa.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_answer_srv.o src/libs6dns/s6dns_message_parse_answer_srv.lo: src/libs6dns/s6dns_message_parse_answer_srv.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_answer_strings.o src/libs6dns/s6dns_message_parse_answer_strings.lo: src/libs6dns/s6dns_message_parse_answer_strings.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_getrr.o src/libs6dns/s6dns_message_parse_getrr.lo: src/libs6dns/s6dns_message_parse_getrr.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_init.o src/libs6dns/s6dns_message_parse_init.lo: src/libs6dns/s6dns_message_parse_init.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_next.o src/libs6dns/s6dns_message_parse_next.lo: src/libs6dns/s6dns_message_parse_next.c src/include/s6-dns/s6dns-message.h
+src/libs6dns/s6dns_message_parse_skipqd.o src/libs6dns/s6dns_message_parse_skipqd.lo: src/libs6dns/s6dns_message_parse_skipqd.c src/include/s6-dns/s6dns-message.h src/libs6dns/s6dns-message-internal.h
+src/libs6dns/s6dns_rci_free.o src/libs6dns/s6dns_rci_free.lo: src/libs6dns/s6dns_rci_free.c src/include/s6-dns/s6dns-rci.h
+src/libs6dns/s6dns_rci_here.o src/libs6dns/s6dns_rci_here.lo: src/libs6dns/s6dns_rci_here.c src/include/s6-dns/s6dns-rci.h
+src/libs6dns/s6dns_rci_init.o src/libs6dns/s6dns_rci_init.lo: src/libs6dns/s6dns_rci_init.c src/include/s6-dns/s6dns-constants.h src/include/s6-dns/s6dns-rci.h
+src/libs6dns/s6dns_rci_zero.o src/libs6dns/s6dns_rci_zero.lo: src/libs6dns/s6dns_rci_zero.c src/include/s6-dns/s6dns-rci.h
+src/libs6dns/s6dns_resolve_core.o src/libs6dns/s6dns_resolve_core.lo: src/libs6dns/s6dns_resolve_core.c 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-resolve.h
+src/libs6dns/s6dns_resolve_dpag.o src/libs6dns/s6dns_resolve_dpag.lo: src/libs6dns/s6dns_resolve_dpag.c src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-message.h src/include/s6-dns/s6dns-rci.h src/include/s6-dns/s6dns-resolve.h
+src/libs6dns/s6dns_resolve_mpag.o src/libs6dns/s6dns_resolve_mpag.lo: src/libs6dns/s6dns_resolve_mpag.c src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-message.h src/include/s6-dns/s6dns-rci.h src/include/s6-dns/s6dns-resolve.h
+src/libs6dns/s6dns_resolve_name4.o src/libs6dns/s6dns_resolve_name4.lo: src/libs6dns/s6dns_resolve_name4.c src/include/s6-dns/s6dns-constants.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-resolve.h
+src/libs6dns/s6dns_resolve_name6.o src/libs6dns/s6dns_resolve_name6.lo: src/libs6dns/s6dns_resolve_name6.c 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-resolve.h
+src/libs6dns/s6dns_resolve_parse.o src/libs6dns/s6dns_resolve_parse.lo: src/libs6dns/s6dns_resolve_parse.c 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-resolve.h
+src/libs6dns/s6dns_resolven_loop.o src/libs6dns/s6dns_resolven_loop.lo: src/libs6dns/s6dns_resolven_loop.c src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-resolve.h
+src/libs6dns/s6dns_resolven_parse.o src/libs6dns/s6dns_resolven_parse.lo: src/libs6dns/s6dns_resolven_parse.c 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-resolve.h
+src/libs6dns/s6dns_resolvenoq.o src/libs6dns/s6dns_resolvenoq.lo: src/libs6dns/s6dns_resolvenoq.c 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-resolve.h
+src/libs6dns/s6dns_resolvenoq_aaaaa.o src/libs6dns/s6dns_resolvenoq_aaaaa.lo: src/libs6dns/s6dns_resolvenoq_aaaaa.c 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-message.h src/include/s6-dns/s6dns-resolve.h
+src/libs6dns/s6dns_resolveq.o src/libs6dns/s6dns_resolveq.lo: src/libs6dns/s6dns_resolveq.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-message.h src/include/s6-dns/s6dns-rci.h src/include/s6-dns/s6dns-resolve.h
+src/libs6dns/s6dns_resolveq_aaaaa.o src/libs6dns/s6dns_resolveq_aaaaa.lo: src/libs6dns/s6dns_resolveq_aaaaa.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/s6dns-engine.h src/include/s6-dns/s6dns-message.h src/include/s6-dns/s6dns-rci.h src/include/s6-dns/s6dns-resolve.h
+src/skadns/skadns_cancel.o src/skadns/skadns_cancel.lo: src/skadns/skadns_cancel.c src/include/s6-dns/skadns.h
+src/skadns/skadns_end.o src/skadns/skadns_end.lo: src/skadns/skadns_end.c src/include/s6-dns/skadns.h
+src/skadns/skadns_packet.o src/skadns/skadns_packet.lo: src/skadns/skadns_packet.c src/include/s6-dns/skadns.h
+src/skadns/skadns_packetlen.o src/skadns/skadns_packetlen.lo: src/skadns/skadns_packetlen.c src/include/s6-dns/skadns.h
+src/skadns/skadns_release.o src/skadns/skadns_release.lo: src/skadns/skadns_release.c src/include/s6-dns/skadns.h
+src/skadns/skadns_send.o src/skadns/skadns_send.lo: src/skadns/skadns_send.c src/include/s6-dns/s6dns-domain.h src/include/s6-dns/skadns.h
+src/skadns/skadns_start.o src/skadns/skadns_start.lo: src/skadns/skadns_start.c src/include/s6-dns/skadns.h
+src/skadns/skadns_startf.o src/skadns/skadns_startf.lo: src/skadns/skadns_startf.c src/include/s6-dns/skadns.h
+src/skadns/skadns_update.o src/skadns/skadns_update.lo: src/skadns/skadns_update.c
+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
+
+libs6dnsgenericfilter.a: src/clients/s6dns_generic_filter_main.o src/clients/s6dns_namescanner.o
+s6-dnsip4: src/clients/s6-dnsip4.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsip4-filter: src/clients/s6-dnsip4-filter.o libs6dnsgenericfilter.a -lskadns -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsip6: src/clients/s6-dnsip6.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsip6-filter: src/clients/s6-dnsip6-filter.o libs6dnsgenericfilter.a -lskadns -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsmx: src/clients/s6-dnsmx.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsname: src/clients/s6-dnsname.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsname-filter: src/clients/s6-dnsname-filter.o libs6dnsgenericfilter.a -lskadns -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsns: src/clients/s6-dnsns.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsq: src/clients/s6-dnsq.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsqr: src/clients/s6-dnsqr.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnsqualify: src/clients/s6-dnsqualify.o -ls6dns -lskarnet
+s6-dnssoa: src/clients/s6-dnssoa.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnssrv: src/clients/s6-dnssrv.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-dnstxt: src/clients/s6-dnstxt.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+s6-randomip: src/clients/s6-randomip.o -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
+libs6dns.a: 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_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_internal.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_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_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_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_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
+libs6dns.so: 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_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_internal.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_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_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_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_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
+libskadns.a: 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
+skadnsd: src/skadns/skadnsd.o -ls6dns -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB}
diff --git a/package/info b/package/info
new file mode 100644
index 0000000..c5b7191
--- /dev/null
+++ b/package/info
@@ -0,0 +1,4 @@
+package=s6-dns
+version=2.0.0.0
+category=web
+package_macro_name=S6_DNS
diff --git a/package/modes b/package/modes
new file mode 100644
index 0000000..c9e951a
--- /dev/null
+++ b/package/modes
@@ -0,0 +1,16 @@
+skadnsd 0755
+s6-randomip 0755
+s6-dnsqualify 0755
+s6-dnsip4 0755
+s6-dnsip6 0755
+s6-dnsmx 0755
+s6-dnsname 0755
+s6-dnsns 0755
+s6-dnssoa 0755
+s6-dnssrv 0755
+s6-dnstxt 0755
+s6-dnsip4-filter 0755
+s6-dnsip6-filter 0755
+s6-dnsname-filter 0755
+s6-dnsq 0755
+s6-dnsqr 0755
diff --git a/package/targets.mak b/package/targets.mak
new file mode 100644
index 0000000..dbc4608
--- /dev/null
+++ b/package/targets.mak
@@ -0,0 +1,27 @@
+BIN_TARGETS = \
+skadnsd \
+s6-randomip \
+s6-dnsqualify \
+s6-dnsip4 \
+s6-dnsip6 \
+s6-dnsmx \
+s6-dnsname \
+s6-dnsns \
+s6-dnssoa \
+s6-dnssrv \
+s6-dnstxt \
+s6-dnsip4-filter \
+s6-dnsip6-filter \
+s6-dnsname-filter \
+s6-dnsq \
+s6-dnsqr
+
+LIBEXEC_TARGETS =
+
+SHARED_LIBS = \
+libs6dns.so \
+libskadns.so
+
+STATIC_LIBS = \
+libs6dns.a \
+libskadns.a
diff --git a/patch-for-solaris b/patch-for-solaris
new file mode 100755
index 0000000..02f2e3c
--- /dev/null
+++ b/patch-for-solaris
@@ -0,0 +1,17 @@
+#!/usr/xpg4/bin/sh
+
+patchit () {
+ echo '#!/usr/xpg4/bin/sh' > $1.tmp
+ tail -n +2 $1 >> $1.tmp
+ mv -f $1.tmp $1
+ chmod 755 $1
+}
+
+patchit ./configure
+patchit ./tools/install.sh
+patchit ./tools/gen-deps.sh
+
+echo 'SHELL := /usr/xpg4/bin/sh' > Makefile.tmp
+echo >> Makefile.tmp
+cat Makefile >> Makefile.tmp
+mv -f Makefile.tmp Makefile
diff --git a/src/clients/deps-exe/s6-dnsip4 b/src/clients/deps-exe/s6-dnsip4
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsip4
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsip4-filter b/src/clients/deps-exe/s6-dnsip4-filter
new file mode 100644
index 0000000..2c61392
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsip4-filter
@@ -0,0 +1,6 @@
+libs6dnsgenericfilter.a
+-lskadns
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsip6 b/src/clients/deps-exe/s6-dnsip6
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsip6
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsip6-filter b/src/clients/deps-exe/s6-dnsip6-filter
new file mode 100644
index 0000000..2c61392
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsip6-filter
@@ -0,0 +1,6 @@
+libs6dnsgenericfilter.a
+-lskadns
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsmx b/src/clients/deps-exe/s6-dnsmx
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsmx
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsname b/src/clients/deps-exe/s6-dnsname
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsname
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsname-filter b/src/clients/deps-exe/s6-dnsname-filter
new file mode 100644
index 0000000..2c61392
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsname-filter
@@ -0,0 +1,6 @@
+libs6dnsgenericfilter.a
+-lskadns
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsns b/src/clients/deps-exe/s6-dnsns
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsns
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsq b/src/clients/deps-exe/s6-dnsq
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsq
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsqr b/src/clients/deps-exe/s6-dnsqr
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsqr
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnsqualify b/src/clients/deps-exe/s6-dnsqualify
new file mode 100644
index 0000000..295d71e
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnsqualify
@@ -0,0 +1,2 @@
+-ls6dns
+-lskarnet
diff --git a/src/clients/deps-exe/s6-dnssoa b/src/clients/deps-exe/s6-dnssoa
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnssoa
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnssrv b/src/clients/deps-exe/s6-dnssrv
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnssrv
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-dnstxt b/src/clients/deps-exe/s6-dnstxt
new file mode 100644
index 0000000..4181fd6
--- /dev/null
+++ b/src/clients/deps-exe/s6-dnstxt
@@ -0,0 +1,4 @@
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-exe/s6-randomip b/src/clients/deps-exe/s6-randomip
new file mode 100644
index 0000000..e027835
--- /dev/null
+++ b/src/clients/deps-exe/s6-randomip
@@ -0,0 +1,3 @@
+-lskarnet
+${SOCKET_LIB}
+${TAINNOW_LIB}
diff --git a/src/clients/deps-lib/s6dnsgenericfilter b/src/clients/deps-lib/s6dnsgenericfilter
new file mode 100644
index 0000000..2d5eee8
--- /dev/null
+++ b/src/clients/deps-lib/s6dnsgenericfilter
@@ -0,0 +1,2 @@
+s6dns_generic_filter_main.o
+s6dns_namescanner.o
diff --git a/src/clients/s6-dnsip4-filter.c b/src/clients/s6-dnsip4-filter.c
new file mode 100644
index 0000000..6d6862e
--- /dev/null
+++ b/src/clients/s6-dnsip4-filter.c
@@ -0,0 +1,52 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "s6dns-generic-filter.h"
+
+#define USAGE "s6-dnsip4-filter [ -l lines ] [ -c concurrency ] [ -t timeout ] [ -f format ] [ -e errorformat ]"
+
+typedef struct s6dns_a1_s s6dns_a1_t, *s6dns_a1_t_ref ;
+struct s6dns_a1_s
+{
+ char ip[4] ;
+ unsigned int got : 1 ;
+} ;
+
+static int s6dns_message_parse_answer_a1 (s6dns_message_rr_t const *rr, char const *packet, unsigned int packetlen, unsigned int pos, unsigned int section, void *stuff)
+{
+ if ((section == 2) && (rr->rtype == S6DNS_T_A) && (rr->rdlength == 4))
+ {
+ s6dns_a1_t *data = stuff ;
+ if (data->got) return 1 ;
+ byte_copy(data->ip, 4, packet+pos) ;
+ data->got = 1 ;
+ }
+ (void)packetlen ;
+ return 1 ;
+}
+
+static int ipformatter (stralloc *sa, char const *packet, unsigned int packetlen)
+{
+ s6dns_a1_t data ;
+ s6dns_message_header_t h ;
+ register int r ;
+ data.got = 0 ;
+ r = s6dns_message_parse(&h, packet, packetlen, &s6dns_message_parse_answer_a1, &data) ;
+ if (r <= 0) return r ;
+ if (!data.got) return 1 ;
+ if (!stralloc_readyplus(sa, IP4_FMT)) return -1 ;
+ sa->len += ip4_fmt(sa->s + sa->len, data.ip) ;
+ stralloc_0(sa) ;
+ return 1 ;
+}
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ PROG = "s6-dnsip4-filter" ;
+ return s6dns_generic_filter_main(argc, argv, envp, S6DNS_T_A, &s6dns_namescanner, &ipformatter, USAGE) ;
+}
diff --git a/src/clients/s6-dnsip4.c b/src/clients/s6-dnsip4.c
new file mode 100644
index 0000000..03c52dd
--- /dev/null
+++ b/src/clients/s6-dnsip4.c
@@ -0,0 +1,62 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnsip4 [ -q ] [ -r ] [ -t timeout ] domain"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ stralloc ips = STRALLOC_ZERO ;
+ tain_t deadline ;
+ unsigned int i = 0 ;
+ int flagqualify = 0 ;
+ int flagunsort = 0 ;
+ PROG = "s6-dnsip4" ;
+
+ for (;;)
+ {
+ register int opt = subgetopt(argc, argv, "qrt:") ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'q' : flagqualify = 1 ; break ;
+ case 'r' : flagunsort = 1 ; break ;
+ case 't' : if (!uint0_scan(subgetopt_here.arg, &i)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
+ if (argc < 1) dieusage() ;
+
+ tain_now_g() ;
+ if (i) tain_from_millisecs(&deadline, i) ; else deadline = tain_infinite_relative ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ {
+ register int r = s6dns_resolve_a_g(&ips, argv[0], str_len(argv[0]), flagqualify, &deadline) ;
+ if (r < 0) strerr_diefu2sys((errno == ETIMEDOUT) ? 99 : 111, "resolve ", argv[0]) ;
+ if (!r) strerr_diefu4x(2, "resolve ", argv[0], ": ", s6dns_constants_error_str(errno)) ;
+ }
+ if (!ips.len) return 1 ;
+ if (flagunsort) random_unsort(ips.s, ips.len / 4, 4) ;
+ for (i = 0 ; i < ips.len / 4 ; i++)
+ {
+ char fmt[IP4_FMT] ;
+ register unsigned int n = ip4_fmt(fmt, ips.s + 4 * i) ;
+ fmt[n++] = '\n' ;
+ if (buffer_put(buffer_1small, fmt, n) < (int)n)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ if (!buffer_flush(buffer_1small))
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/clients/s6-dnsip6-filter.c b/src/clients/s6-dnsip6-filter.c
new file mode 100644
index 0000000..a5c7418
--- /dev/null
+++ b/src/clients/s6-dnsip6-filter.c
@@ -0,0 +1,52 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "s6dns-generic-filter.h"
+
+#define USAGE "s6-dnsip6-filter [ -l lines ] [ -c concurrency ] [ -t timeout ] [ -f format ] [ -e errorformat ]"
+
+typedef struct s6dns_aaaa1_s s6dns_aaaa1_t, *s6dns_aaaa1_t_ref ;
+struct s6dns_aaaa1_s
+{
+ char ip[16] ;
+ unsigned int got : 1 ;
+} ;
+
+static int s6dns_message_parse_answer_aaaa1 (s6dns_message_rr_t const *rr, char const *packet, unsigned int packetlen, unsigned int pos, unsigned int section, void *stuff)
+{
+ if ((section == 2) && (rr->rtype == S6DNS_T_AAAA) && (rr->rdlength == 16))
+ {
+ s6dns_aaaa1_t *data = stuff ;
+ if (data->got) return 1 ;
+ byte_copy(data->ip, 16, packet+pos) ;
+ data->got = 1 ;
+ }
+ (void)packetlen ;
+ return 1 ;
+}
+
+static int ipformatter (stralloc *sa, char const *packet, unsigned int packetlen)
+{
+ s6dns_aaaa1_t data ;
+ s6dns_message_header_t h ;
+ register int r ;
+ data.got = 0 ;
+ r = s6dns_message_parse(&h, packet, packetlen, &s6dns_message_parse_answer_aaaa1, &data) ;
+ if (r <= 0) return r ;
+ if (!data.got) return 1 ;
+ if (!stralloc_readyplus(sa, IP6_FMT)) return -1 ;
+ sa->len += ip6_fmt(sa->s + sa->len, data.ip) ;
+ stralloc_0(sa) ;
+ return 1 ;
+}
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ PROG = "s6-dnsip6-filter" ;
+ return s6dns_generic_filter_main(argc, argv, envp, S6DNS_T_AAAA, &s6dns_namescanner, &ipformatter, USAGE) ;
+}
diff --git a/src/clients/s6-dnsip6.c b/src/clients/s6-dnsip6.c
new file mode 100644
index 0000000..e07ba53
--- /dev/null
+++ b/src/clients/s6-dnsip6.c
@@ -0,0 +1,62 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnsip6 [ -q ] [ -r ] [ -t timeout ] domain"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ stralloc ips = STRALLOC_ZERO ;
+ tain_t deadline ;
+ unsigned int i = 0 ;
+ int flagqualify = 0 ;
+ int flagunsort = 0 ;
+ PROG = "s6-dnsip6" ;
+
+ for (;;)
+ {
+ register int opt = subgetopt(argc, argv, "qrt:") ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'q' : flagqualify = 1 ; break ;
+ case 'r' : flagunsort = 1 ; break ;
+ case 't' : if (!uint0_scan(subgetopt_here.arg, &i)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
+ if (argc < 1) dieusage() ;
+
+ tain_now_g() ;
+ if (i) tain_from_millisecs(&deadline, i) ; else deadline = tain_infinite_relative ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ {
+ register int r = s6dns_resolve_aaaa_g(&ips, argv[0], str_len(argv[0]), flagqualify, &deadline) ;
+ if (r < 0) strerr_diefu2sys((errno == ETIMEDOUT) ? 99 : 111, "resolve ", argv[0]) ;
+ if (!r) strerr_diefu4x(2, "resolve ", argv[0], ": ", s6dns_constants_error_str(errno)) ;
+ }
+ if (!ips.len) return 1 ;
+ if (flagunsort) random_unsort(ips.s, ips.len / 16, 16) ;
+ for (i = 0 ; i < ips.len / 16 ; i++)
+ {
+ char fmt[IP6_FMT] ;
+ register unsigned int n = ip6_fmt(fmt, ips.s + 16 * i) ;
+ fmt[n++] = '\n' ;
+ if (buffer_put(buffer_1small, fmt, n) < (int)n)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ if (!buffer_flush(buffer_1small))
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/clients/s6-dnsmx.c b/src/clients/s6-dnsmx.c
new file mode 100644
index 0000000..a495cb2
--- /dev/null
+++ b/src/clients/s6-dnsmx.c
@@ -0,0 +1,64 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnsmx [ -q ] [ -r ] [ -t timeout ] name"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ genalloc mxs = GENALLOC_ZERO ; /* array of s6dns_message_rr_mx_t */
+ tain_t deadline ;
+ unsigned int i = 0 ;
+ int flagqualify = 0 ;
+ int flagunsort = 0 ;
+ PROG = "s6-dnsmx" ;
+ for (;;)
+ {
+ register int opt = subgetopt(argc, argv, "qrt:") ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'q' : flagqualify = 1 ; break ;
+ case 'r' : flagunsort = 1 ; break ;
+ case 't' : if (!uint0_scan(subgetopt_here.arg, &i)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
+ if (argc < 1) dieusage() ;
+
+ tain_now_g() ;
+ if (i) tain_from_millisecs(&deadline, i) ; else deadline = tain_infinite_relative ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ {
+ register int r = s6dns_resolve_mx_g(&mxs, argv[0], str_len(argv[0]), flagqualify, &deadline) ;
+ if (r < 0) strerr_diefu2sys((errno == ETIMEDOUT) ? 99 : 111, "resolve ", argv[0]) ;
+ if (!r) strerr_diefu4x(2, "resolve ", argv[0], ": ", s6dns_constants_error_str(errno)) ;
+ }
+ if (!genalloc_len(s6dns_message_rr_mx_t, &mxs)) return 1 ;
+ if (flagunsort) random_unsort(mxs.s, genalloc_len(s6dns_message_rr_mx_t, &mxs), sizeof(s6dns_message_rr_mx_t)) ;
+ for (i = 0 ; i < genalloc_len(s6dns_message_rr_mx_t, &mxs) ; i++)
+ {
+ char buf[S6DNS_FMT_MX] ;
+ register unsigned int len = s6dns_fmt_mx(buf, S6DNS_FMT_MX, genalloc_s(s6dns_message_rr_mx_t, &mxs) + i) ;
+ if (!len) strerr_diefu1sys(111, "format result") ;
+ if (buffer_put(buffer_1, buf, len) < 0) goto err ;
+ if (buffer_put(buffer_1, "\n", 1) < 0) goto err ;
+ }
+ if (!buffer_flush(buffer_1)) goto err ;
+ return 0 ;
+ err:
+ strerr_diefu1sys(111, "write to stdout") ;
+}
diff --git a/src/clients/s6-dnsname-filter.c b/src/clients/s6-dnsname-filter.c
new file mode 100644
index 0000000..6522003
--- /dev/null
+++ b/src/clients/s6-dnsname-filter.c
@@ -0,0 +1,83 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "s6dns-generic-filter.h"
+
+#define USAGE "s6-dnsname-filter [ -4 ] [ -6 ] [ -l lines ] [ -c concurrency ] [ -t timeout ] [ -f format ] [ -e errorformat ]"
+
+static unsigned int ipscanner (s6dns_domain_t_ref d, char const *s)
+{
+ char ip[16] ;
+ register unsigned int pos ;
+ if (flag6)
+ {
+ pos = ip6_scan(s, ip) ;
+ if (pos)
+ {
+ s6dns_domain_arpafromip6(d, ip, 128) ;
+ goto yes ;
+ }
+ }
+ if (flag4)
+ {
+ pos = ip4_scan(s, ip) ;
+ if (pos)
+ {
+ s6dns_domain_arpafromip4(d, ip) ;
+ goto yes ;
+ }
+ }
+ return 0 ;
+ yes:
+ if (!s6dns_domain_encode(d)) return 0 ;
+ return pos ;
+}
+
+typedef struct s6dns_domain1_s s6dns_domain1_t, *s6dns_domain1_t_ref ;
+struct s6dns_domain1_s
+{
+ s6dns_domain_t d ;
+ unsigned int got : 1 ;
+} ;
+
+static int s6dns_message_parse_answer_domain1 (s6dns_message_rr_t const *rr, char const *packet, unsigned int packetlen, unsigned int pos, unsigned int section, void *stuff)
+{
+ if ((section == 2) && (rr->rtype == S6DNS_T_PTR))
+ {
+ s6dns_domain1_t *data = stuff ;
+ register unsigned int start = pos ;
+ if (data->got) return 1 ;
+ if (!s6dns_message_get_domain(&data->d, packet, packetlen, &pos)) return 0 ;
+ if (rr->rdlength != pos - start) return (errno = EPROTO, 0) ;
+ data->got = 1 ;
+ }
+ return 1 ;
+}
+
+static int domainformatter (stralloc *sa, char const *packet, unsigned int packetlen)
+{
+ s6dns_domain1_t data ;
+ s6dns_message_header_t h ;
+ register int r ;
+ data.got = 0 ;
+ r = s6dns_message_parse(&h, packet, packetlen, &s6dns_message_parse_answer_domain1, &data) ;
+ if (r <= 0) return r ;
+ if (!data.got) return 1 ;
+ if (!stralloc_readyplus(sa, data.d.len + 1)) return -1 ;
+ sa->len += s6dns_domain_tostring(sa->s + sa->len, data.d.len + 1, &data.d) ;
+ stralloc_0(sa) ;
+ return 1 ;
+}
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ PROG = "s6-dnsname-filter" ;
+ return s6dns_generic_filter_main(argc, argv, envp, S6DNS_T_PTR, &ipscanner, &domainformatter, USAGE) ;
+}
diff --git a/src/clients/s6-dnsname.c b/src/clients/s6-dnsname.c
new file mode 100644
index 0000000..d65da3a
--- /dev/null
+++ b/src/clients/s6-dnsname.c
@@ -0,0 +1,75 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnsname [ -4 | -6 ] [ -r ] [ -t timeout ] ip"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ genalloc ds = GENALLOC_ZERO ; /* array of s6dns_domain_t */
+ tain_t deadline ;
+ ip46full_t ip = IP46FULL_ZERO ;
+ unsigned int i = 0 ;
+ int flagunsort = 0 ;
+ int do4 = 0 ;
+ int do6 = 0 ;
+ PROG = "s6-dnsname" ;
+ for (;;)
+ {
+ register int opt = subgetopt(argc, argv, "46rt:") ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case '4' : do4 = 1 ; break ;
+ case '6' : do6 = 1 ; break ;
+ case 'r' : flagunsort = 1 ; break ;
+ case 't' : if (!uint0_scan(subgetopt_here.arg, &i)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
+ if (argc < 1) dieusage() ;
+ if (!do4 && !do6) do4 = do6 = 1 ;
+ if (do4 && do6)
+ {
+ if (!ip46full_scan(argv[0], &ip)) dieusage() ;
+ }
+ else if (do6)
+ {
+ if (!ip6_scan(argv[0], ip.ip)) dieusage() ;
+ ip.is6 = 1 ;
+ }
+ else if (!ip4_scan(argv[0], ip.ip)) dieusage() ;
+
+ tain_now_g() ;
+ if (i) tain_from_millisecs(&deadline, i) ; else deadline = tain_infinite_relative ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ {
+ register int r = ip.is6 ? s6dns_resolve_name6_g(&ds, ip.ip, &deadline) : s6dns_resolve_name4_g(&ds, ip.ip, &deadline) ;
+ if (r < 0) strerr_diefu2sys((errno == ETIMEDOUT) ? 99 : 111, "resolve ", argv[0]) ;
+ if (!r) strerr_diefu4x(2, "resolve ", argv[0], ": ", s6dns_constants_error_str(errno)) ;
+ }
+ if (!genalloc_len(s6dns_domain_t, &ds)) return 1 ;
+ if (flagunsort) random_unsort(ds.s, genalloc_len(s6dns_domain_t, &ds), sizeof(s6dns_domain_t)) ;
+ {
+ char buf[S6DNS_FMT_DOMAINLIST(genalloc_len(s6dns_domain_t, &ds))] ;
+ unsigned int len = s6dns_fmt_domainlist(buf, S6DNS_FMT_DOMAINLIST(genalloc_len(s6dns_domain_t, &ds)), genalloc_s(s6dns_domain_t, &ds), genalloc_len(s6dns_domain_t, &ds), "\n", 1) ;
+ if (!len) strerr_diefu1sys(111, "format result") ;
+ if (buffer_putalign(buffer_1, buf, len) < 0) goto err ;
+ }
+ if (buffer_putflush(buffer_1, "\n", 1) < 0) goto err ;
+ return 0 ;
+ err:
+ strerr_diefu1sys(111, "write to stdout") ;
+}
diff --git a/src/clients/s6-dnsns.c b/src/clients/s6-dnsns.c
new file mode 100644
index 0000000..d1caba5
--- /dev/null
+++ b/src/clients/s6-dnsns.c
@@ -0,0 +1,61 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnsns [ -q ] [ -r ] [ -t timeout ] name"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ genalloc ds = GENALLOC_ZERO ; /* array of s6dns_domain_t */
+ tain_t deadline ;
+ unsigned int i = 0 ;
+ int flagqualify = 0 ;
+ int flagunsort = 0 ;
+ PROG = "s6-dnsns" ;
+ for (;;)
+ {
+ register int opt = subgetopt(argc, argv, "qrt:") ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'q' : flagqualify = 1 ; break ;
+ case 'r' : flagunsort = 1 ; break ;
+ case 't' : if (!uint0_scan(subgetopt_here.arg, &i)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
+ if (argc < 1) dieusage() ;
+
+ tain_now_g() ;
+ if (i) tain_from_millisecs(&deadline, i) ; else deadline = tain_infinite_relative ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ {
+ register int r = s6dns_resolve_ns_g(&ds, argv[0], str_len(argv[0]), flagqualify, &deadline) ;
+ if (r < 0) strerr_diefu2sys((errno == ETIMEDOUT) ? 99 : 111, "resolve ", argv[0]) ;
+ if (!r) strerr_diefu4x(2, "resolve ", argv[0], ": ", s6dns_constants_error_str(errno)) ;
+ }
+ if (!genalloc_len(s6dns_domain_t, &ds)) return 1 ;
+ if (flagunsort) random_unsort(ds.s, genalloc_len(s6dns_domain_t, &ds), sizeof(s6dns_domain_t)) ;
+ {
+ char buf[S6DNS_FMT_DOMAINLIST(genalloc_len(s6dns_domain_t, &ds))] ;
+ unsigned int len = s6dns_fmt_domainlist(buf, S6DNS_FMT_DOMAINLIST(genalloc_len(s6dns_domain_t, &ds)), genalloc_s(s6dns_domain_t, &ds), genalloc_len(s6dns_domain_t, &ds), "\n", 1) ;
+ if (!len) strerr_diefu1sys(111, "format result") ;
+ if (buffer_put(buffer_1, buf, len) < 0) goto err ;
+ }
+ if (buffer_putflush(buffer_1, "\n", 1) < 0) goto err ;
+ return 0 ;
+ err:
+ strerr_diefu1sys(111, "write to stdout") ;
+}
diff --git a/src/clients/s6-dnsq.c b/src/clients/s6-dnsq.c
new file mode 100644
index 0000000..76ca4ea
--- /dev/null
+++ b/src/clients/s6-dnsq.c
@@ -0,0 +1,99 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnsq [ -1 | -2 ] [ -t timeout ] [ -D debuglevel ] qtype query serverip..."
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ tain_t deadline ;
+ unsigned int debuglevel = 0 ;
+ uint16 qtype ;
+ genwrite_t *where = &genwrite_stderr ;
+ PROG = "s6-dnsq" ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ unsigned int t = 0 ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, "12t:D:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case '1' : where = &genwrite_stdout ; break ;
+ case '2' : where = &genwrite_stderr ; break ;
+ case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
+ case 'D' : if (!uint0_scan(l.arg, &debuglevel)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ if (t) tain_from_millisecs(&deadline, t) ; else deadline = tain_infinite_relative ;
+ }
+ if (argc < 3) dieusage() ;
+ {
+ s6dns_debughook_t dbh = { .post_recv = 0, .pre_send = 0, .post_send = 0 } ;
+ s6dns_ip46list_t servers ;
+ s6dns_domain_t d ;
+ unsigned int i = 0, j = 0 ;
+ qtype = s6dns_analyze_qtype_parse(argv[0]) ;
+ if (!qtype) dieusage() ;
+ if (!s6dns_domain_fromstring_noqualify_encode(&d, argv[1], str_len(argv[1])))
+ strerr_diefu2sys(100, "encode ", argv[1]) ;
+ dbh.external = where ;
+ byte_zero(&servers, sizeof(s6dns_ip46list_t)) ;
+ for (; (i < (unsigned int)(argc - 2)) && (j < S6DNS_MAX_SERVERS) ; i++)
+ {
+ ip46_t z[S6DNS_MAX_SERVERS] ;
+ unsigned int n ;
+ register unsigned int k = 0 ;
+ if (!*argv[2+i]) continue ;
+ if (!ip46_scanlist(z, S6DNS_MAX_SERVERS - j, argv[2 + i], &n))
+ strerr_diefu2sys(100, "make an IP address list out of ", argv[2+i]) ;
+ for (; k < n ; k++)
+ {
+ byte_copy(s6dns_ip46list_ip(&servers, j + k), SKALIBS_IP_SIZE, z[k].ip) ;
+#ifdef SKALIBS_IPV6_ENABLED
+ if (ip46_is6(z + k)) bitarray_set(servers.is6, j + k) ;
+#endif
+ }
+ j += n ;
+ }
+ if (debuglevel & 1) dbh.post_recv = &s6dns_debug_dumpdt_post_recv ;
+ if (debuglevel & 2) { dbh.pre_send = &s6dns_debug_dumpdt_pre_send ; dbh.post_send = &s6dns_debug_dumpdt_post_send ; }
+ tain_now_g() ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!s6dns_engine_init_r_g(&s6dns_engine_here, &servers, 0, d.s, d.len, qtype, &dbh, &deadline))
+ strerr_diefu1sys(111, "initialize query") ;
+ }
+ if (!s6dns_resolve_loop_g(&deadline))
+ {
+ char fmt[UINT16_FMT] ;
+ fmt[uint16_fmt(fmt, qtype)] = 0 ;
+ strerr_diefu6x((errno == ETIMEDOUT) ? 99 : 2, "resolve query ", argv[0], " of qtype ", fmt, ": ", s6dns_constants_error_str(errno)) ;
+ }
+ if (!s6dns_analyze_packet(&genwrite_stdout, s6dns_engine_packet(&s6dns_engine_here), s6dns_engine_packetlen(&s6dns_engine_here), 0))
+ {
+ int e = errno ;
+ buffer_flush(buffer_1) ;
+ errno = e ;
+ strerr_diefu1sys(111, "analyze response") ;
+ }
+ if (!buffer_flush(buffer_1)) strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/clients/s6-dnsqr.c b/src/clients/s6-dnsqr.c
new file mode 100644
index 0000000..1effe68
--- /dev/null
+++ b/src/clients/s6-dnsqr.c
@@ -0,0 +1,74 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnsqr [ -1 | -2 ] [ -t timeout ] [ -D debuglevel ] qtype query"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ tain_t deadline ;
+ unsigned int debuglevel = 0 ;
+ genwrite_t *where = &genwrite_stderr ;
+ PROG = "s6-dnsqr" ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ unsigned int t = 0 ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, "12t:D:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case '1' : where = &genwrite_stdout ; break ;
+ case '2' : where = &genwrite_stderr ; break ;
+ case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
+ case 'D' : if (!uint0_scan(l.arg, &debuglevel)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ if (t) tain_from_millisecs(&deadline, t) ; else deadline = tain_infinite_relative ;
+ }
+ if (argc < 2) dieusage() ;
+ {
+ s6dns_debughook_t dbh = { .post_recv = 0, .pre_send = 0, .post_send = 0 } ;
+ s6dns_domain_t d ;
+ uint16 qtype = s6dns_analyze_qtype_parse(argv[0]) ;
+ if (!qtype) dieusage() ;
+ if (!s6dns_domain_fromstring_noqualify_encode(&d, argv[1], str_len(argv[1])))
+ strerr_diefu2sys(100, "encode ", argv[1]) ;
+ dbh.external = where ;
+ if (debuglevel & 1) dbh.post_recv = &s6dns_debug_dumpdt_post_recv ;
+ if (debuglevel & 2) { dbh.pre_send = &s6dns_debug_dumpdt_pre_send ; dbh.post_send = &s6dns_debug_dumpdt_post_send ; }
+ tain_now_g() ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ if (!s6dns_resolve_core_r_g(&d, qtype, &s6dns_engine_here, &s6dns_rci_here.servers, &dbh, &deadline))
+ {
+ char fmt[UINT16_FMT] ;
+ fmt[uint16_fmt(fmt, qtype)] = 0 ;
+ strerr_diefu6x((errno == ETIMEDOUT) ? 99 : 2, "resolve query ", argv[1], " of qtype ", fmt, ": ", s6dns_constants_error_str(errno)) ;
+ }
+ }
+ if (!s6dns_analyze_packet(&genwrite_stdout, s6dns_engine_packet(&s6dns_engine_here), s6dns_engine_packetlen(&s6dns_engine_here), 1))
+ {
+ int e = errno ;
+ buffer_flush(buffer_1) ;
+ errno = e ;
+ strerr_diefu1sys(111, "analyze response") ;
+ }
+ if (!buffer_flush(buffer_1)) strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/clients/s6-dnsqualify.c b/src/clients/s6-dnsqualify.c
new file mode 100644
index 0000000..64767ae
--- /dev/null
+++ b/src/clients/s6-dnsqualify.c
@@ -0,0 +1,34 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnsqualify name"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ s6dns_domain_t d ;
+ PROG = "s6-dnsqualify" ;
+ if (argc < 2) dieusage() ;
+ if (!s6dns_domain_fromstring(&d, argv[1], str_len(argv[1])))
+ strerr_diefu2sys(100, "make a domain name from ", argv[1]) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ {
+ s6dns_domain_t list[s6dns_rci_here.rulesnum] ;
+ unsigned int n = s6dns_qualify(list, &d) ;
+ if (!n) strerr_diefu2sys(111, "qualify ", argv[1]) ;
+ {
+ char buf[S6DNS_FMT_DOMAINLIST(n)] ;
+ unsigned int len = s6dns_fmt_domainlist(buf, S6DNS_FMT_DOMAINLIST(n), list, n, "\n", 1) ;
+ if (!len) strerr_diefu1sys(111, "format result") ;
+ if (buffer_put(buffer_1, buf, len) < 0) goto err ;
+ }
+ }
+ if (buffer_putflush(buffer_1, "\n", 1) < 0) goto err ;
+ return 0 ;
+ err:
+ strerr_diefu1sys(111, "write to stdout") ;
+}
diff --git a/src/clients/s6-dnssoa.c b/src/clients/s6-dnssoa.c
new file mode 100644
index 0000000..1b02ff6
--- /dev/null
+++ b/src/clients/s6-dnssoa.c
@@ -0,0 +1,63 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnssoa [ -q ] [ -r ] [ -t timeout ] name"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ genalloc soas = GENALLOC_ZERO ; /* array of s6dns_message_rr_soa_t */
+ tain_t deadline ;
+ unsigned int i = 0 ;
+ int flagqualify = 0 ;
+ int flagunsort = 0 ;
+ PROG = "s6-dnssoa" ;
+ for (;;)
+ {
+ register int opt = subgetopt(argc, argv, "qrt:") ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'q' : flagqualify = 1 ; break ;
+ case 'r' : flagunsort = 1 ; break ;
+ case 't' : if (!uint0_scan(subgetopt_here.arg, &i)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
+ if (argc < 1) dieusage() ;
+
+ tain_now_g() ;
+ if (i) tain_from_millisecs(&deadline, i) ; else deadline = tain_infinite_relative ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ {
+ register int r = s6dns_resolve_soa_g(&soas, argv[0], str_len(argv[0]), flagqualify, &deadline) ;
+ if (r < 0) strerr_diefu2sys((errno == ETIMEDOUT) ? 99 : 111, "resolve ", argv[0]) ;
+ if (!r) strerr_diefu4x(2, "resolve ", argv[0], ": ", s6dns_constants_error_str(errno)) ;
+ }
+ if (!genalloc_len(s6dns_message_rr_soa_t, &soas)) return 1 ;
+ if (flagunsort) random_unsort(soas.s, genalloc_len(s6dns_message_rr_soa_t, &soas), sizeof(s6dns_message_rr_soa_t)) ;
+ for (i = 0 ; i < genalloc_len(s6dns_message_rr_soa_t, &soas) ; i++)
+ {
+ char buf[S6DNS_FMT_SOA] ;
+ register unsigned int len = s6dns_fmt_soa(buf, S6DNS_FMT_SOA, genalloc_s(s6dns_message_rr_soa_t, &soas) + i) ;
+ if (!len) strerr_diefu1sys(111, "format result") ;
+ if (buffer_put(buffer_1, buf, len) < 0) goto err ;
+ if (buffer_put(buffer_1, "\n", 1) < 0) goto err ;
+ }
+ if (!buffer_flush(buffer_1)) goto err ;
+ return 0 ;
+ err:
+ strerr_diefu1sys(111, "write to stdout") ;
+}
diff --git a/src/clients/s6-dnssrv.c b/src/clients/s6-dnssrv.c
new file mode 100644
index 0000000..283f1cd
--- /dev/null
+++ b/src/clients/s6-dnssrv.c
@@ -0,0 +1,75 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnssrv [ -q ] [ -r ] [ -t timeout ] service protocol name"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ genalloc srvs = GENALLOC_ZERO ; /* array of s6dns_message_rr_srv_t */
+ tain_t deadline ;
+ unsigned int i = 0 ;
+ int flagqualify = 0 ;
+ int flagunsort = 0 ;
+ PROG = "s6-dnssrv" ;
+ for (;;)
+ {
+ register int opt = subgetopt(argc, argv, "qt:") ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'q' : flagqualify = 1 ; break ;
+ case 'r' : flagunsort = 1 ; break ;
+ case 't' : if (!uint0_scan(subgetopt_here.arg, &i)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
+ if (argc < 3) dieusage() ;
+
+ tain_now_g() ;
+ if (i) tain_from_millisecs(&deadline, i) ; else deadline = tain_infinite_relative ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ {
+ unsigned int n0 = str_len(argv[0]) ;
+ unsigned int n1 = str_len(argv[1]) ;
+ unsigned int n2 = str_len(argv[2]) ;
+ char name[n0 + n1 + n2 + 5] ;
+ name[0] = '_' ;
+ byte_copy(name + 1, n0, argv[0]) ;
+ name[n0 + 1] = '.' ;
+ name[n0 + 2] = '_' ;
+ byte_copy(name + n0 + 3, n1, argv[1]) ;
+ name[n0 + n1 + 3] = '.' ;
+ byte_copy(name + n0 + n1 + 4, n2, argv[2]) ;
+ name[n0 + n1 + n2 + 4] = 0 ;
+ register int r = s6dns_resolve_srv_g(&srvs, name, n0 + n1 + n2 + 4, flagqualify, &deadline) ;
+ if (r < 0) strerr_diefu2sys((errno == ETIMEDOUT) ? 99 : 111, "resolve ", argv[0]) ;
+ if (!r) strerr_diefu4x(2, "resolve ", name, ": ", s6dns_constants_error_str(errno)) ;
+ }
+ if (!genalloc_len(s6dns_message_rr_srv_t, &srvs)) return 1 ;
+ if (flagunsort) random_unsort(srvs.s, genalloc_len(s6dns_message_rr_srv_t, &srvs), sizeof(s6dns_message_rr_srv_t)) ;
+ for (i = 0 ; i < genalloc_len(s6dns_message_rr_srv_t, &srvs) ; i++)
+ {
+ char buf[S6DNS_FMT_SRV] ;
+ register unsigned int len = s6dns_fmt_srv(buf, S6DNS_FMT_SRV, genalloc_s(s6dns_message_rr_srv_t, &srvs) + i) ;
+ if (!len) strerr_diefu1sys(111, "format result") ;
+ if (buffer_put(buffer_1, buf, len) < 0) goto err ;
+ if (buffer_put(buffer_1, "\n", 1) < 0) goto err ;
+ }
+ if (!buffer_flush(buffer_1)) goto err ;
+ return 0 ;
+ err:
+ strerr_diefu1sys(111, "write to stdout") ;
+}
diff --git a/src/clients/s6-dnstxt.c b/src/clients/s6-dnstxt.c
new file mode 100644
index 0000000..fde69d2
--- /dev/null
+++ b/src/clients/s6-dnstxt.c
@@ -0,0 +1,78 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dnstxt [ -q ] [ -r ] [ -t timeout ] name"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ stralloc quoted = STRALLOC_ZERO ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc offsets = GENALLOC_ZERO ; /* array of unsigned int */
+ tain_t deadline, stamp ;
+ unsigned int n ;
+ unsigned int i = 0 ;
+ int flagqualify = 0 ;
+ int flagunsort = 0 ;
+ PROG = "s6-dnstxt" ;
+ for (;;)
+ {
+ register int opt = subgetopt(argc, argv, "qrt:") ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'q' : flagqualify = 1 ; break ;
+ case 'r' : flagunsort = 1 ; break ;
+ case 't' : if (!uint0_scan(subgetopt_here.arg, &i)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
+ if (argc < 1) dieusage() ;
+
+ tain_now(&stamp) ;
+ if (i) tain_from_millisecs(&deadline, i) ; else deadline = tain_infinite_relative ;
+ tain_add(&deadline, &deadline, &stamp) ;
+ if (!s6dns_init()) strerr_diefu1sys(111, "s6dns_init") ;
+ {
+ register int r = s6dns_resolve_txt(&sa, &offsets, argv[0], str_len(argv[0]), flagqualify, &deadline, &stamp) ;
+ if (r < 0) strerr_diefu2sys((errno == ETIMEDOUT) ? 99 : 111, "resolve ", argv[0]) ;
+ if (!r) strerr_diefu4x(2, "resolve ", argv[0], ": ", s6dns_constants_error_str(errno)) ;
+ }
+ n = genalloc_len(unsigned int, &offsets) ;
+ if (!n) return 1 ;
+ {
+ unsigned int printable_offsets[n] ;
+ for (i = 0 ; i < n ; i++)
+ {
+ unsigned int beg = genalloc_s(unsigned int, &offsets)[i] ;
+ unsigned int end = (i < n-1 ? genalloc_s(unsigned int, &offsets)[i+1] : sa.len) - 1 ;
+ printable_offsets[i] = quoted.len ;
+ if (!string_quote("ed, sa.s + beg, end - beg) || !stralloc_0("ed))
+ strerr_diefu2sys(111, "quote ", sa.s + beg) ;
+ }
+ genalloc_free(unsigned int, &offsets) ;
+ stralloc_free(&sa) ;
+ if (flagunsort) random_unsort((char *)printable_offsets, n, sizeof(unsigned int)) ;
+ for (i = 0 ; i < n ; i++)
+ if ((buffer_puts(buffer_1small, quoted.s + printable_offsets[i]) < 0)
+ || (buffer_put(buffer_1small, "\n", 1) < 1))
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ stralloc_free("ed) ;
+ if (!buffer_flush(buffer_1small))
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/clients/s6-randomip.c b/src/clients/s6-randomip.c
new file mode 100644
index 0000000..b220374
--- /dev/null
+++ b/src/clients/s6-randomip.c
@@ -0,0 +1,62 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-randomip [ -4 ] [ -6 ] [ -n number ]"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ char fmt[IP6_FMT] ;
+ char ip[16] ;
+ unsigned int n ;
+ unsigned int i = 0 ;
+ unsigned int what = 0 ;
+ int finite = 0 ;
+ PROG = "s6-randomip" ;
+ for (;;)
+ {
+ register int opt = subgetopt(argc, argv, "46n:") ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case '4' : what |= 1 ; break ;
+ case '6' : what |= 2 ; break ;
+ case 'n' :
+ if (!uint0_scan(subgetopt_here.arg, &n)) dieusage() ;
+ finite = 1 ;
+ break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
+ if (!what) what = 1 ;
+ what = 1 << (1 << what) ;
+ if (!badrandom_init()) strerr_diefu1sys(111, "init RNG") ;
+ for (i = 0 ; !finite || (i < n) ; i++)
+ {
+ unsigned int len = what ;
+ if (len > 16)
+ {
+ char c ;
+ if (badrandom_string(&c, 1) < 1)
+ strerr_diefu1sys(111, "badrandom_string") ;
+ len = (c & 1) ? 16 : 4 ;
+ }
+ if (badrandom_string(ip, len) < 4)
+ strerr_diefu1sys(111, "badrandom_string") ;
+ len = (len == 16) ? ip6_fmt(fmt, ip) : ip4_fmt(fmt, ip) ;
+ fmt[len++] = '\n' ;
+ if (buffer_put(buffer_1, fmt, len) < (int)len)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ if (!buffer_flush(buffer_1))
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/clients/s6dns-generic-filter.h b/src/clients/s6dns-generic-filter.h
new file mode 100644
index 0000000..53fa560
--- /dev/null
+++ b/src/clients/s6dns-generic-filter.h
@@ -0,0 +1,22 @@
+/* ISC license. */
+
+#ifndef SKADNS_GENERIC_FILTER_H
+#define SKADNS_GENERIC_FILTER_H
+
+#include
+#include
+#include
+
+typedef unsigned int scan_func_t (s6dns_domain_t *, char const *) ;
+typedef scan_func_t *scan_func_t_ref ;
+typedef int fmt_func_t (stralloc *, char const *, unsigned int) ;
+typedef fmt_func_t *fmt_func_t_ref ;
+
+extern unsigned int s6dns_namescanner (s6dns_domain_t *, char const *) ;
+extern int s6dns_domainformatter (stralloc *, char const *, unsigned int) ;
+extern int s6dns_generic_filter_main (int, char const *const *, char const *const *, uint16, scan_func_t_ref, fmt_func_t_ref, char const *) ;
+
+extern int flag4 ;
+extern int flag6 ;
+
+#endif
diff --git a/src/clients/s6dns_generic_filter_main.c b/src/clients/s6dns_generic_filter_main.c
new file mode 100644
index 0000000..430b0c3
--- /dev/null
+++ b/src/clients/s6dns_generic_filter_main.c
@@ -0,0 +1,230 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "s6dns-generic-filter.h"
+
+#define dieusage() strerr_dief1x(100, USAGE) ;
+
+typedef struct line_s line_t, *line_t_ref ;
+struct line_s
+{
+ stralloc swrd ;
+ unsigned int wpos ;
+ int dpos ;
+ char w[2] ;
+ unsigned int pending : 1 ;
+} ;
+
+#define LINE_ZERO { STRALLOC_ZERO, 0, 0, "\0", 0 }
+
+static void line_recycle (line_t_ref l)
+{
+ l->swrd.len = 0 ;
+ l->pending = 0 ;
+}
+
+int flag4 = 0 ;
+int flag6 = 0 ;
+
+int s6dns_generic_filter_main (int argc, char const *const *argv, char const *const *envp, uint16 qtype, scan_func_t_ref scanner, fmt_func_t_ref formatter, char const *USAGE)
+{
+ skadns_t a = SKADNS_ZERO ;
+ tain_t deadline, tto ;
+ char const *normalformat = "%s=%d%w%r" ;
+ char const *errorformat = "%s=<%e>%w%r" ;
+ uint16 maxlines = 256 ;
+ uint16 maxconn = 128 ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ unsigned int t = 0 ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, (qtype == S6DNS_T_PTR) ? "46l:c:t:f:e:" : "l:c:t:f:e:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case '4' : flag4 = 1 ; break ;
+ case '6' : flag6 = 1 ; break ;
+ case 'l' : if (!uint160_scan(l.arg, &maxlines)) dieusage() ; break ;
+ case 'c' : if (!uint160_scan(l.arg, &maxconn)) dieusage() ; break ;
+ case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
+ case 'f' : normalformat = l.arg ; break ;
+ case 'e' : errorformat = l.arg ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ if (t) tain_from_millisecs(&tto, t) ; else tto = tain_infinite_relative ;
+ }
+ if (!flag4 && !flag6) flag4 = 1 ;
+ if (maxconn < 1) maxconn = 1 ;
+ if (maxconn > SKADNS_MAXCONCURRENCY) maxconn = SKADNS_MAXCONCURRENCY ;
+ if (maxlines < maxconn) maxlines = maxconn ;
+
+ tain_now_g() ;
+ tain_addsec_g(&deadline, 2) ;
+ if (!skadns_startf_g(&a, &deadline))
+ strerr_diefu1sys(111, "establish skadns connection") ;
+ if ((ndelay_on(0) < 0) || (ndelay_on(1) < 0))
+ strerr_diefu1sys(111, "ndelay_on") ;
+
+ {
+ iopause_fd x[3] = { { 0, 0, 0 }, { 1, 0, 0 }, { -1, 0, 0 } } ;
+ uint16 lhead = 0, ltail = 0, numlines = 0, pending = 0 ;
+ line_t storage[maxlines+1] ;
+ uint16 lineindex[maxconn] ;
+ x[2].fd = skadns_fd(&a) ;
+ {
+ line_t line_zero = LINE_ZERO ;
+ char const *args[4] = { "", "", "", "" } ;
+ uint16 i = 0 ;
+ for (; i <= maxlines ; i++) storage[i] = line_zero ;
+ if (!string_format(&storage[0].swrd, "sdwr", normalformat, args)
+ || !string_format(&storage[0].swrd, "sewr", errorformat, args))
+ strerr_diefu1sys(111, "format a string") ;
+ storage[0].swrd.len = 0 ;
+ }
+
+ for (;;)
+ {
+ x[0].events = !x[0].fd && (numlines < maxlines) && (pending < maxconn) ? IOPAUSE_READ : 0 ;
+ x[1].events = bufalloc_len(bufalloc_1) ? IOPAUSE_WRITE : 0 ;
+ x[2].events = pending ? IOPAUSE_READ : 0 ;
+ if (!x[0].events && !x[1].events && !x[2].events) break ;
+ tain_add_g(&deadline, &tain_infinite_relative) ;
+
+ if (iopause_g(x + !(x[0].events & IOPAUSE_READ), 3 - !(x[0].events & IOPAUSE_READ), &deadline) < 0)
+ strerr_diefu1sys(111, "iopause") ;
+
+
+ /* Flush stdout */
+
+ if (x[1].revents)
+ {
+ if (!bufalloc_flush(bufalloc_1) && !error_isagain(errno))
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+
+
+ /* Get and format results from skadnsd */
+
+ if (x[2].revents)
+ {
+ register int j = 0 ;
+ register uint16 const *list ;
+ int n = skadns_update(&a) ;
+ if (n < 0) strerr_diefu1sys(111, "skadns_update") ;
+ list = skadns_list(&a) ;
+ for (; j < n ; j++)
+ {
+ register uint16 i = lineindex[list[j]] ;
+ register char const *packet = skadns_packet(&a, list[j]) ;
+ if (packet)
+ {
+ register int r ;
+ r = (*formatter)(&storage[i].swrd, packet, skadns_packetlen(&a, list[j])) ;
+ if (r < 0) strerr_diefu1sys(111, "format skadns answer") ;
+ if (!r) storage[i].dpos = -errno ;
+ }
+ else storage[i].dpos = -errno ;
+ storage[i].pending = 0 ;
+ skadns_release(&a, list[j]) ;
+ pending-- ;
+ }
+ skadns_clearlist(&a) ;
+ }
+
+
+ /* Scan stdin and send queries to skadnsd */
+
+ if (buffer_len(buffer_0) || (!x[0].fd && x[0].revents))
+ {
+ for (; (numlines < maxlines) && (pending < maxconn) ; lhead = (lhead+1) % (maxlines+1), numlines++)
+ {
+ s6dns_domain_t d ;
+ register line_t_ref line = storage + lhead ;
+ register int r = skagetln(buffer_0, &line->swrd, '\n') ;
+ if (r < 0)
+ {
+ if (error_isagain(errno)) break ;
+ if (errno != EPIPE) strerr_diefu1sys(111, "read from stdin") ;
+ if (!stralloc_catb(&line->swrd, "\n", 1)) strerr_diefu1sys(111, "stralloc_catb") ;
+ x[0].fd = -1 ;
+ break ;
+ }
+ else if (!r)
+ {
+ x[0].fd = -1 ;
+ break ;
+ }
+ line->swrd.s[line->swrd.len-1] = 0 ;
+ line->wpos = (*scanner)(&d, line->swrd.s) ;
+ if (!line->wpos)
+ {
+ line->wpos = line->swrd.len - 1 ;
+ line->w[0] = 0 ;
+ line->dpos = -errno ;
+ }
+ else
+ {
+ tain_t sendlimit ;
+ uint16 id ;
+ line->w[0] = line->swrd.s[line->wpos] ;
+ line->swrd.s[line->wpos] = 0 ;
+ tain_addsec_g(&sendlimit, 2) ;
+ tain_add_g(&deadline, &tto) ;
+ if (!skadns_send_g(&a, &id, &d, qtype, &deadline, &sendlimit))
+ line->dpos = -errno ;
+ else
+ {
+ line->dpos = line->swrd.len ;
+ lineindex[id] = lhead ;
+ line->pending = 1 ;
+ pending++ ;
+ }
+ }
+ }
+ }
+
+ if (x[0].revents & IOPAUSE_EXCEPT) x[0].fd = -1 ;
+
+
+ /* Send processed lines to stdout */
+
+ for (; ltail != lhead ; ltail = (ltail+1) % (maxlines+1), numlines--)
+ {
+ char *args[4] ;
+ register line_t_ref line = storage + ltail ;
+ if (line->pending) break ;
+ args[0] = line->swrd.s ;
+ args[1] = line->dpos < 0 ? (char *)s6dns_constants_error_str(-line->dpos) : line->swrd.s + line->dpos ;
+ args[2] = line->w ;
+ args[3] = line->swrd.s + line->wpos + !!line->w[0] ;
+ if (!string_format(&bufalloc_1->x, line->dpos < 0 ? "sewr" : "sdwr", line->dpos < 0 ? errorformat : normalformat, (char const **)args))
+ strerr_diefu1sys(111, "format output line") ;
+ line_recycle(line) ;
+ if (!bufalloc_put(bufalloc_1, "\n", 1))
+ strerr_diefu1sys(111, "bufalloc_put") ;
+ }
+ }
+ }
+
+ (void)envp ;
+ return 0 ;
+}
diff --git a/src/clients/s6dns_namescanner.c b/src/clients/s6dns_namescanner.c
new file mode 100644
index 0000000..b23fb3d
--- /dev/null
+++ b/src/clients/s6dns_namescanner.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include
+#include
+
+unsigned int s6dns_namescanner (s6dns_domain_t *d, char const *s)
+{
+ register unsigned int pos = 0 ;
+ while (s[pos] && (s[pos] != ' ') && (s[pos] != '\t') && (s[pos] != '\r') && (s[pos] != '\n')) pos++ ;
+ if (!s6dns_domain_fromstring_noqualify_encode(d, s, pos)) return 0 ;
+ return pos ;
+}
diff --git a/src/include/s6-dns/s6dns-analyze.h b/src/include/s6-dns/s6dns-analyze.h
new file mode 100644
index 0000000..2908763
--- /dev/null
+++ b/src/include/s6-dns/s6dns-analyze.h
@@ -0,0 +1,39 @@
+/* ISC license. */
+
+#ifndef S6DNS_ANALYZE_H
+#define S6DNS_ANALYZE_H
+
+#include
+#include
+#include
+
+typedef int s6dns_analyze_record_func_t (genwrite_t *, s6dns_message_rr_t const *, char const *, unsigned int, unsigned int) ;
+typedef s6dns_analyze_record_func_t *s6dns_analyze_record_func_t_ref ;
+
+typedef struct s6dns_analyze_rtypetable_s s6dns_analyze_rtypetable_t, *s6dns_analyze_rtypetable_t_ref ;
+struct s6dns_analyze_rtypetable_s
+{
+ uint16 rtype ;
+ char const *string ;
+ s6dns_analyze_record_func_t_ref f ;
+} ;
+
+extern uint16 s6dns_analyze_qtype_parse (char const *) ;
+
+extern s6dns_analyze_rtypetable_t const *s6dns_analyze_rtypetable ;
+
+extern s6dns_analyze_record_func_t s6dns_analyze_record_a ;
+extern s6dns_analyze_record_func_t s6dns_analyze_record_aaaa ;
+extern s6dns_analyze_record_func_t s6dns_analyze_record_hinfo ;
+extern s6dns_analyze_record_func_t s6dns_analyze_record_soa ;
+extern s6dns_analyze_record_func_t s6dns_analyze_record_mx ;
+extern s6dns_analyze_record_func_t s6dns_analyze_record_srv ;
+extern s6dns_analyze_record_func_t s6dns_analyze_record_domain ;
+extern s6dns_analyze_record_func_t s6dns_analyze_record_strings ;
+extern s6dns_analyze_record_func_t s6dns_analyze_record_unknown ;
+
+extern s6dns_analyze_record_func_t s6dns_analyze_record ;
+
+extern int s6dns_analyze_packet (genwrite_t *, char const *, unsigned int, int) ;
+
+#endif
diff --git a/src/include/s6-dns/s6dns-constants.h b/src/include/s6-dns/s6dns-constants.h
new file mode 100644
index 0000000..ad47dc1
--- /dev/null
+++ b/src/include/s6-dns/s6dns-constants.h
@@ -0,0 +1,52 @@
+/* ISC license. */
+
+#ifndef S6DNS_CONSTANTS_H
+#define S6DNS_CONSTANTS_H
+
+#include
+
+#define S6DNS_MAX_SERVERS 16U
+
+#define S6DNS_C_IN 0x0001U
+#define S6DNS_C_ANY 0x00ffU
+
+#define S6DNS_T_A 1U
+#define S6DNS_T_NS 2U
+#define S6DNS_T_CNAME 5U
+#define S6DNS_T_SOA 6U
+#define S6DNS_T_PTR 12U
+#define S6DNS_T_HINFO 13U
+#define S6DNS_T_MX 15U
+#define S6DNS_T_TXT 16U
+#define S6DNS_T_RP 17U
+#define S6DNS_T_SIG 24U
+#define S6DNS_T_KEY 25U
+#define S6DNS_T_AAAA 28U
+#define S6DNS_T_SRV 33U
+#define S6DNS_T_AXFR 252U
+#define S6DNS_T_ANY 255U
+
+#define S6DNS_O_RECURSIVE 0x0001U
+#define S6DNS_O_STRICT 0x0002U
+
+#define S6DNS_W_AND 0
+#define S6DNS_W_OR 1
+#define S6DNS_W_BEST 2
+
+typedef struct s6dns_constants_error_message_s s6dns_constants_error_message_t, *s6dns_constants_error_message_t_ref ;
+struct s6dns_constants_error_message_s
+{
+ int num ;
+ char const *string ;
+} ;
+
+extern s6dns_constants_error_message_t const *const s6dns_constants_error ;
+extern char const *s6dns_constants_error_str (int) ;
+
+#ifdef SKALIBS_IPV6_ENABLED
+# define S6DNS_LOCALHOST_IP IP6_LOCAL
+#else
+# define S6DNS_LOCALHOST_IP "\177\0\0\1"
+#endif
+
+#endif
diff --git a/src/include/s6-dns/s6dns-debug.h b/src/include/s6-dns/s6dns-debug.h
new file mode 100644
index 0000000..acc5818
--- /dev/null
+++ b/src/include/s6-dns/s6dns-debug.h
@@ -0,0 +1,16 @@
+/* ISC license. */
+
+#ifndef S6DNS_DEBUG_H
+#define S6DNS_DEBUG_H
+
+#include
+
+extern s6dns_debughook_func_t s6dns_debug_dumpdt_post_recv ;
+extern s6dns_debughook_func_t s6dns_debug_dumpdt_pre_send ;
+extern s6dns_debughook_func_t s6dns_debug_dumpdt_post_send ;
+
+#define S6DNS_DEBUG_DUMPDT_INIT(gp) { &s6dns_debug_dumpdt_post_recv, &s6dns_debug_dumpdt_pre_send, &s6dns_debug_dumpdt_post_send, (gp) }
+extern s6dns_debughook_t const s6dns_debug_dumpdt_stdout ;
+extern s6dns_debughook_t const s6dns_debug_dumpdt_stderr ;
+
+#endif
diff --git a/src/include/s6-dns/s6dns-domain.h b/src/include/s6-dns/s6dns-domain.h
new file mode 100644
index 0000000..3faae07
--- /dev/null
+++ b/src/include/s6-dns/s6dns-domain.h
@@ -0,0 +1,47 @@
+/* ISC license. */
+
+#ifndef S6DNS_DOMAIN_H
+#define S6DNS_DOMAIN_H
+
+#include
+
+typedef struct s6dns_domain_s s6dns_domain_t, *s6dns_domain_t_ref ;
+struct s6dns_domain_s
+{
+ unsigned char len ;
+ char s[255] ;
+} ;
+
+
+ /* Conversions from/to user strings */
+
+extern int s6dns_domain_fromstring (s6dns_domain_t_ref, char const *, unsigned int) ;
+extern unsigned int s6dns_domain_tostring (char *, unsigned int, s6dns_domain_t const *) ;
+
+
+ /* Qualification */
+
+extern int s6dns_domain_noqualify (s6dns_domain_t_ref) ;
+extern unsigned int s6dns_domain_qualify (s6dns_domain_t *, s6dns_domain_t const *, char const *, unsigned int) ;
+
+
+ /* Internal coding/encoding to/from protocol form */
+
+extern int s6dns_domain_encode (s6dns_domain_t_ref) ;
+extern unsigned int s6dns_domain_encodelist (s6dns_domain_t_ref, unsigned int) ;
+extern int s6dns_domain_decode (s6dns_domain_t_ref) ;
+
+
+ /* Useful shortcuts */
+
+extern int s6dns_domain_fromstring_noqualify_encode (s6dns_domain_t_ref, char const *, unsigned int) ;
+extern unsigned int s6dns_domain_fromstring_qualify_encode (s6dns_domain_t *, char const *, unsigned int, char const *, unsigned int) ;
+
+
+ /* Helpers for PTR */
+
+extern void s6dns_domain_arpafromip4 (s6dns_domain_t_ref, char const *) ;
+extern void s6dns_domain_arpafromip6 (s6dns_domain_t_ref, char const *, unsigned int) ;
+#define s6dns_domain_arpafromip46(d, i) (ip46_is6(i) ? s6dns_domain_arpafromip6(d, (i)->ip, 128) : s6dns_domain_arpafromip4(d, (i)->ip))
+
+#endif
diff --git a/src/include/s6-dns/s6dns-engine.h b/src/include/s6-dns/s6dns-engine.h
new file mode 100644
index 0000000..d6b0503
--- /dev/null
+++ b/src/include/s6-dns/s6dns-engine.h
@@ -0,0 +1,108 @@
+/* ISC license. */
+
+#ifndef S6DNS_ENGINE_H
+#define S6DNS_ENGINE_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+ /* The dt structure: all the DNS q/r state information, transport-agnostic */
+
+typedef struct s6dns_engine_s s6dns_engine_t, *s6dns_engine_t_ref ;
+
+
+ /* Debug function hooks */
+
+typedef int s6dns_debughook_func_t (s6dns_engine_t const *, void *) ;
+typedef s6dns_debughook_func_t *s6dns_debughook_func_t_ref ;
+
+typedef struct s6dns_debughook_s s6dns_debughook_t, *s6dns_debughook_t_ref ;
+struct s6dns_debughook_s
+{
+ s6dns_debughook_func_t_ref post_recv ;
+ s6dns_debughook_func_t_ref pre_send ;
+ s6dns_debughook_func_t_ref post_send ;
+ void *external ;
+} ;
+#define S6DNS_DEBUGHOOK_ZERO { 0, 0, 0, 0 }
+extern s6dns_debughook_t const s6dns_debughook_zero ;
+
+
+ /*
+ s6dns-engine: the asynchronous DNS resolution primitives.
+ */
+
+struct s6dns_engine_s
+{
+ stralloc sa ; /* 2 bytes (qlen) + qlen bytes (query) + answers */
+ tain_t deadline ;
+ tain_t localdeadline ;
+ unsigned int querylen ;
+ int fd ;
+ uint32 protostate ;
+ s6dns_ip46list_t servers ;
+ s6dns_debughook_t const *debughook ;
+ unsigned int curserver ;
+ int status ;
+ unsigned int flagstrict : 1 ;
+ unsigned int flagtcp : 1 ;
+ unsigned int flagconnecting : 1 ;
+ unsigned int flagreading : 1 ;
+ unsigned int flagwriting : 1 ;
+} ;
+
+#define S6DNS_ENGINE_ZERO { \
+ .sa = STRALLOC_ZERO, \
+ .deadline = TAIN_ZERO, \
+ .localdeadline = TAIN_ZERO, \
+ .querylen = 0, \
+ .fd = -1, \
+ .protostate = 0, \
+ .servers = S6DNS_IP46LIST_ZERO, \
+ .debughook = 0, \
+ .curserver = 0, \
+ .status = ECONNABORTED, \
+ .flagstrict = 0, \
+ .flagtcp = 0, \
+ .flagconnecting = 0, \
+ .flagreading = 0, \
+ .flagwriting = 0 \
+}
+
+extern s6dns_engine_t const s6dns_engine_zero ;
+extern s6dns_engine_t s6dns_engine_here ;
+
+extern void s6dns_engine_recycle (s6dns_engine_t *) ;
+extern void s6dns_engine_free (s6dns_engine_t *) ;
+extern void s6dns_engine_freen (s6dns_engine_t *, unsigned int) ;
+
+#define s6dns_engine_init(dt, servers, options, q, qlen, qtype, deadline, stamp) s6dns_engine_init_r(dt, servers, options, q, qlen, qtype, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_engine_init_g(dt, servers, options, q, qlen, qtype, deadline) s6dns_engine_init(dt, servers, options, q, qlen, qtype, (deadline), &STAMP)
+extern int s6dns_engine_init_r (s6dns_engine_t *, s6dns_ip46list_t const *, uint32, char const *, unsigned int, uint16, s6dns_debughook_t const *, tain_t const *, tain_t const *) ;
+#define s6dns_engine_init_r_g(dt, servers, options, q, qlen, qtype, dbh, deadline) s6dns_engine_init_r(dt, servers, options, q, qlen, qtype, dbh, (deadline), &STAMP)
+
+
+ /* Call before iopause() */
+
+extern void s6dns_engine_nextdeadline (s6dns_engine_t const *, tain_t *) ;
+#define s6dns_engine_isreadable(dt) ((dt)->flagreading)
+#define s6dns_engine_iswritable(dt) ((dt)->flagwriting)
+
+
+ /* Call after iopause(): _timeout if iopause returns 0, _event otherwise */
+
+extern int s6dns_engine_timeout (s6dns_engine_t *, tain_t const *) ;
+#define s6dns_engine_timeout_g(dt) s6dns_engine_timeout((dt), &STAMP)
+extern int s6dns_engine_event (s6dns_engine_t *, tain_t const *) ;
+#define s6dns_engine_event_g(dt) s6dns_engine_event((dt), &STAMP)
+
+#define s6dns_engine_packet(dt) ((dt)->sa.s + (dt)->querylen)
+#define s6dns_engine_packetlen(dt) ((dt)->sa.len - (dt)->querylen)
+
+#endif
diff --git a/src/include/s6-dns/s6dns-fmt.h b/src/include/s6-dns/s6dns-fmt.h
new file mode 100644
index 0000000..fd4dfc5
--- /dev/null
+++ b/src/include/s6-dns/s6dns-fmt.h
@@ -0,0 +1,29 @@
+/* ISC license. */
+
+#ifndef S6DNS_FMT_H
+#define S6DNS_FMT_H
+
+#include
+#include
+#include
+#include
+
+#define S6DNS_FMT_DOMAIN 256
+#define s6dns_fmt_domain(s, max, d) s6dns_domain_tostring(s, max, d)
+
+#define S6DNS_FMT_DOMAINLIST(n) ((n) * S6DNS_FMT_DOMAIN)
+extern unsigned int s6dns_fmt_domainlist (char *, unsigned int, s6dns_domain_t const *, unsigned int, char const *, unsigned int) ;
+
+#define S6DNS_FMT_HINFO 512
+extern unsigned int s6dns_fmt_hinfo (char *, unsigned int, s6dns_message_rr_hinfo_t const *) ;
+
+#define S6DNS_FMT_MX (S6DNS_FMT_DOMAIN + UINT16_FMT)
+extern unsigned int s6dns_fmt_mx (char *, unsigned int, s6dns_message_rr_mx_t const *) ;
+
+#define S6DNS_FMT_SOA (S6DNS_FMT_DOMAIN * 2 + 5 * UINT32_FMT)
+extern unsigned int s6dns_fmt_soa (char *, unsigned int, s6dns_message_rr_soa_t const *) ;
+
+#define S6DNS_FMT_SRV (S6DNS_FMT_DOMAIN + 3 * UINT16_FMT)
+extern unsigned int s6dns_fmt_srv (char *, unsigned int, s6dns_message_rr_srv_t const *) ;
+
+#endif
diff --git a/src/include/s6-dns/s6dns-ip46.h b/src/include/s6-dns/s6dns-ip46.h
new file mode 100644
index 0000000..d09aa7f
--- /dev/null
+++ b/src/include/s6-dns/s6dns-ip46.h
@@ -0,0 +1,29 @@
+/* ISC license. */
+
+#ifndef S6DNS_IP46_H
+#define S6DNS_IP46_H
+
+#include
+#include
+#include
+
+typedef struct s6dns_ip46list_s s6dns_ip46list_t, *s6dns_ip46list_t_ref ;
+struct s6dns_ip46list_s
+{
+ char ip[S6DNS_MAX_SERVERS * SKALIBS_IP_SIZE] ;
+#ifdef SKALIBS_IPV6_ENABLED
+ unsigned char is6[bitarray_div8(S6DNS_MAX_SERVERS)] ;
+#endif
+} ;
+
+#define s6dns_ip46list_ip(list, i) ((list)->ip + SKALIBS_IP_SIZE * (i))
+
+#ifdef SKALIBS_IPV6_ENABLED
+# define S6DNS_IP46LIST_ZERO { .ip = S6DNS_LOCALHOST_IP, .is6 = "\0" }
+# define s6dns_ip46list_is6(list, i) bitarray_peek((list)->is6, i)
+#else
+# define S6DNS_IP46LIST_ZERO { .ip = S6DNS_LOCALHOST_IP }
+# define s6dns_ip46list_is6(list, i) 0
+#endif
+
+#endif
diff --git a/src/include/s6-dns/s6dns-message.h b/src/include/s6-dns/s6dns-message.h
new file mode 100644
index 0000000..d26106b
--- /dev/null
+++ b/src/include/s6-dns/s6dns-message.h
@@ -0,0 +1,175 @@
+/* ISC license. */
+
+#ifndef S6DNS_MESSAGE_H
+#define S6DNS_MESSAGE_H
+
+#include
+#include
+#include
+#include
+#include
+
+
+ /* Header */
+
+typedef struct s6dns_message_counts_s s6dns_message_counts_t, *s6dns_message_counts_t_ref ;
+struct s6dns_message_counts_s
+{
+ uint16 qd ;
+ uint16 an ;
+ uint16 ns ;
+ uint16 nr ;
+} ;
+
+#define S6DNS_MESSAGE_COUNTS_ZERO { .qd = 0, .an = 0, .ns = 0, .nr = 0 }
+extern s6dns_message_counts_t const s6dns_message_counts_zero ;
+
+extern void s6dns_message_counts_pack (char *, s6dns_message_counts_t const *) ;
+extern void s6dns_message_counts_unpack (char const *, s6dns_message_counts_t *) ;
+extern unsigned int s6dns_message_counts_next (s6dns_message_counts_t *) ;
+
+typedef struct s6dns_message_header_s s6dns_message_header_t, *s6dns_message_header_t_ref ;
+struct s6dns_message_header_s
+{
+ uint16 id ;
+ unsigned int qr : 1 ;
+ unsigned int opcode : 4 ;
+ unsigned int aa : 1 ;
+ unsigned int tc : 1 ;
+ unsigned int rd : 1 ;
+ unsigned int ra : 1 ;
+ unsigned int z : 3 ;
+ unsigned int rcode : 4 ;
+ s6dns_message_counts_t counts ;
+} ;
+
+#define S6DNS_MESSAGE_HEADER_ZERO { \
+ .id = 0, \
+ .qr = 0, \
+ .opcode = 0, \
+ .aa = 0, \
+ .tc = 0, \
+ .rd = 0, \
+ .ra = 0, \
+ .z = 0, \
+ .rcode = 0, \
+ .counts = S6DNS_MESSAGE_COUNTS_ZERO \
+}
+extern s6dns_message_header_t const s6dns_message_header_zero ;
+
+extern void s6dns_message_header_pack (char *, s6dns_message_header_t const *) ;
+extern void s6dns_message_header_unpack (char const *, s6dns_message_header_t *) ;
+
+
+ /* Specific RR helpers */
+
+extern int s6dns_message_get_string (s6dns_domain_t *, char const *, unsigned int, unsigned int *) ;
+extern int s6dns_message_get_strings (char *, unsigned int, char const *, unsigned int, unsigned int *) ;
+extern int s6dns_message_get_domain (s6dns_domain_t *, char const *, unsigned int, unsigned int *) ;
+
+typedef struct s6dns_message_rr_hinfo_s s6dns_message_rr_hinfo_t, *s6dns_message_rr_hinfo_t_ref ;
+struct s6dns_message_rr_hinfo_s
+{
+ s6dns_domain_t cpu ;
+ s6dns_domain_t os ;
+} ;
+
+extern int s6dns_message_get_hinfo (s6dns_message_rr_hinfo_t *, char const *, unsigned int, unsigned int *) ;
+
+typedef struct s6dns_message_rr_mx_s s6dns_message_rr_mx_t, *s6dns_message_rr_mx_t_ref ;
+struct s6dns_message_rr_mx_s
+{
+ uint16 preference ;
+ s6dns_domain_t exchange ;
+} ;
+
+extern int s6dns_message_get_mx (s6dns_message_rr_mx_t *, char const *, unsigned int, unsigned int *) ;
+
+typedef struct s6dns_message_rr_soa_s s6dns_message_rr_soa_t, *s6dns_message_rr_soa_t_ref ;
+struct s6dns_message_rr_soa_s
+{
+ s6dns_domain_t mname ;
+ s6dns_domain_t rname ;
+ uint32 serial ;
+ uint32 refresh ;
+ uint32 retry ;
+ uint32 expire ;
+ uint32 minimum ;
+} ;
+
+extern int s6dns_message_get_soa (s6dns_message_rr_soa_t *, char const *, unsigned int, unsigned int *) ;
+
+typedef struct s6dns_message_rr_srv_s s6dns_message_rr_srv_t, *s6dns_message_rr_srv_t_ref ;
+struct s6dns_message_rr_srv_s
+{
+ uint16 priority ;
+ uint16 weight ;
+ uint16 port ;
+ s6dns_domain_t target ;
+} ;
+
+extern int s6dns_message_get_srv (s6dns_message_rr_srv_t *, char const *, unsigned int, unsigned int *) ;
+
+
+ /* The callback function type: how to parse RRs */
+
+typedef struct s6dns_message_rr_s s6dns_message_rr_t, *s6dns_message_rr_t_ref ;
+struct s6dns_message_rr_s
+{
+ s6dns_domain_t name ;
+ uint16 rtype ;
+ uint16 rclass ;
+ uint32 ttl ;
+ uint16 rdlength ;
+} ;
+
+typedef int s6dns_message_rr_func_t (s6dns_message_rr_t const *, char const *, unsigned int, unsigned int, unsigned int, void *) ;
+typedef s6dns_message_rr_func_t *s6dns_message_rr_func_t_ref ;
+
+
+ /* mpag: structure to encode several variable-length results */
+
+typedef struct s6dns_mpag_s s6dns_mpag_t, *s6dns_mpag_t_ref ;
+struct s6dns_mpag_s
+{
+ stralloc sa ;
+ genalloc offsets ; /* array of unsigned int */
+ uint16 rtype ;
+} ;
+#define S6DNS_MPAG_ZERO { .sa = STRALLOC_ZERO, .offsets = GENALLOC_ZERO, .rtype = 0 }
+
+
+ /* dpag: structure for domain lists */
+
+typedef struct s6dns_dpag_s s6dns_dpag_t, *s6dns_dpag_t_ref ;
+struct s6dns_dpag_s
+{
+ genalloc ds ; /* array of s6dns_domain_t */
+ uint16 rtype ;
+} ;
+#define S6DNS_DPAG_ZERO { .ds = GENALLOC_ZERO, .rtype = 0 }
+
+
+extern s6dns_message_rr_func_t s6dns_message_parse_answer_strings ;
+extern s6dns_message_rr_func_t s6dns_message_parse_answer_domain ;
+extern s6dns_message_rr_func_t s6dns_message_parse_answer_a ;
+extern s6dns_message_rr_func_t s6dns_message_parse_answer_aaaa ;
+extern s6dns_message_rr_func_t s6dns_message_parse_answer_mx ;
+extern s6dns_message_rr_func_t s6dns_message_parse_answer_hinfo ;
+extern s6dns_message_rr_func_t s6dns_message_parse_answer_soa ;
+extern s6dns_message_rr_func_t s6dns_message_parse_answer_srv ;
+
+
+ /* The actual parsing function */
+
+extern int s6dns_message_parse (s6dns_message_header_t_ref, char const *, unsigned int, s6dns_message_rr_func_t_ref, void *) ;
+
+
+ /* Internals of this function, for lower level access */
+
+extern int s6dns_message_parse_init (s6dns_message_header_t *, s6dns_message_counts_t_ref, char const *, unsigned int, unsigned int *) ;
+extern unsigned int s6dns_message_parse_skipqd (s6dns_message_counts_t *, char const *, unsigned int, unsigned int *) ;
+extern int s6dns_message_parse_getrr (s6dns_message_rr_t_ref, char const *, unsigned int, unsigned int *) ;
+extern unsigned int s6dns_message_parse_next (s6dns_message_counts_t *, s6dns_message_rr_t const *, char const *, unsigned int, unsigned int *) ;
+
+#endif
diff --git a/src/include/s6-dns/s6dns-rci.h b/src/include/s6-dns/s6dns-rci.h
new file mode 100644
index 0000000..5822a71
--- /dev/null
+++ b/src/include/s6-dns/s6dns-rci.h
@@ -0,0 +1,29 @@
+/* ISC license. */
+
+#ifndef S6DNS_RCI_H
+#define S6DNS_RCI_H
+
+#include
+#include
+#include
+#include
+
+ /* rci: resolv.conf information */
+
+typedef struct s6dns_rci_s s6dns_rci_t, *s6dns_rci_t_ref ;
+struct s6dns_rci_s
+{
+ s6dns_ip46list_t servers ;
+ stralloc rules ;
+ unsigned int rulesnum ;
+} ;
+#define S6DNS_RCI_ZERO { .servers = S6DNS_IP46LIST_ZERO, .rules = STRALLOC_ZERO, .rulesnum = 0 }
+
+extern s6dns_rci_t const s6dns_rci_zero ;
+extern s6dns_rci_t s6dns_rci_here ;
+extern int s6dns_rci_init (s6dns_rci_t_ref, char const *) ;
+extern void s6dns_rci_free (s6dns_rci_t_ref) ;
+
+#define s6dns_qualify(list, d) s6dns_domain_qualify(list, (d), s6dns_rci_here.rules.s, s6dns_rci_here.rulesnum)
+
+#endif
diff --git a/src/include/s6-dns/s6dns-resolve.h b/src/include/s6-dns/s6dns-resolve.h
new file mode 100644
index 0000000..d188a67
--- /dev/null
+++ b/src/include/s6-dns/s6dns-resolve.h
@@ -0,0 +1,242 @@
+ /* ISC license. */
+
+#ifndef S6DNS_RESOLVE_H
+#define S6DNS_RESOLVE_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+ /*
+ Synchronous DNS resolution primitives.
+ The non-reentrant functions are just wrappers around the reentrant ones,
+ using globals for the parameters the user doesn't care about:
+ s6dns_engine_here for the query storage (dt),
+ s6dns_debughook_zero meaning no debugging needed,
+ s6dns_rci_here for the resolv.conf information (qualification rules and
+ initial cache IPs)
+ */
+
+ /*
+ The basic s6dns_engine wrapper loop: takes an initted dt and resolves it.
+ */
+
+#define s6dns_resolve_loop(deadline, stamp) s6dns_resolve_loop_r(&s6dns_engine_here, (deadline), stamp)
+#define s6dns_resolve_loop_g(deadline) s6dns_resolve_loop((deadline), &STAMP)
+#define s6dns_resolve_loop_r(dt, deadline, stamp) (s6dns_resolven_loop(dt, 1, 2, deadline, stamp) < 0 ? 0 : (dt)->status ? (errno = (dt)->status, 0) : 1)
+#define s6dns_resolve_loop_r_g(dt, deadline) s6dns_resolve_loop(dt, (deadline), &STAMP)
+
+
+ /* QoL functions for single-domain synchronous resolution. */
+
+ /*
+ The innermost one:
+ Initializes the dt with the given data (d, qtype), then calls the loop.
+ */
+
+#define s6dns_resolve_core(d, qtype, deadline, stamp) s6dns_resolve_core_r(d, qtype, &s6dns_engine_here, &s6dns_rci_here.servers, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_core_g(d, qtype, deadline) s6dns_resolve_core(d, qtype, (deadline), &STAMP)
+extern int s6dns_resolve_core_r (s6dns_domain_t const *, uint16, s6dns_engine_t_ref, s6dns_ip46list_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolve_core_r_g(d, qtype, dt, servers, dbh, deadline) s6dns_resolve_core_r(d, qtype, dt, servers, dbh, (deadline), &STAMP)
+
+
+ /*
+ Just above. Calls s6dns_resolve_core() then feeds the result to s6dns_message_parse().
+ Returns -1 if a resolving or parsing error occurs.
+ Returns 0 if everything works but the result is empty for some reason (i.e. nxdomain).
+ Returns 1 if everything works and there's an actual answer.
+ */
+
+#define s6dns_resolve_parse(d, qtype, parsefunc, parsedata, deadline, stamp) s6dns_resolve_parse_r(d, qtype, parsefunc, parsedata, &s6dns_engine_here, &s6dns_rci_here.servers, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_parse_g(d, qtype, parsefunc, parsedata, deadline) s6dns_resolve_parse(d, qtype, parsefunc, parsedata, (deadline), &STAMP)
+extern int s6dns_resolve_parse_r (s6dns_domain_t const *, uint16, s6dns_message_rr_func_t_ref, void *, s6dns_engine_t_ref, s6dns_ip46list_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolve_parse_r_g(d, qtype, parsefunc, parsedata, dt, servers, dbh, deadline) s6dns_resolve_parse_r(d, qtype, parsefunc, parsedata, dt, servers, dbh, (deadline), &STAMP)
+
+
+ /*
+ Resolution without qualification. Encoding/decoding included.
+ */
+
+#define s6dns_resolvenoq(name, len, qtype, parsefunc, parsedata, deadline, stamp) s6dns_resolvenoq_r(name, len, qtype, parsefunc, parsedata, &s6dns_engine_here, &s6dns_rci_here.servers, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolvenoq_g(name, len, qtype, parsefunc, parsedata, deadline) s6dns_resolvenoq(name, len, qtype, parsefunc, parsedata, (deadline), &STAMP)
+extern int s6dns_resolvenoq_r (char const *, unsigned int, uint16, s6dns_message_rr_func_t_ref, void *, s6dns_engine_t_ref, s6dns_ip46list_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolvenoq_r_g(name, len, qtype, parsefunc, parsedata, dt, servers, dbh, deadline) s6dns_resolvenoq_r(name, len, qtype, parsefunc, parsedata, dt, servers, dbh, (deadline), &STAMP)
+
+
+ /*
+ Resolution with qualification:
+ Get a qualification list from a name, then resolve the list in parallel.
+ */
+
+#define s6dns_resolveq(name, len, qtype, parsefunc, parsedata, deadline, stamp) s6dns_resolveq_r(name, len, qtype, parsefunc, parsedata, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolveq_g(name, len, qtype, parsefunc, parsedata, deadline) s6dns_resolveq(name, len, qtype, parsefunc, parsedata, (deadline), &STAMP)
+extern int s6dns_resolveq_r (char const *, unsigned int, uint16, s6dns_message_rr_func_t_ref, void *, s6dns_rci_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolveq_r_g(name, len, qtype, parsefunc, parsedata, rci, dbh, deadline) s6dns_resolveq_r(name, len, qtype, parsefunc, parsedata, rci, dbh, (deadline), &STAMP)
+
+
+ /*
+ The resolution primitive that calls s6dns_resolvenoq() if the
+ qualif flag is cleared and s6dns_resolveq() if it is set.
+ */
+
+#define s6dns_resolve(name, len, qtype, parsefunc, parsedata, qualif, deadline, stamp) s6dns_resolve_r(name, len, qtype, parsefunc, parsedata, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_t const *, deadline, stamp)
+#define s6dns_resolve_g(name, len, qtype, parsefunc, parsedata, qualif, deadline) s6dns_resolve(name, len, qtype, parsefunc, parsedata, qualif, (deadline), &STAMP)
+#define s6dns_resolve_r(name, len, qtype, parsefunc, parsedata, qualif, dt, rci, dbh, deadline, stamp) ((qualif) ? s6dns_resolveq_r(name, len, qtype, parsefunc, parsedata, rci, dbh, deadline, stamp) : s6dns_resolvenoq_r(name, len, qtype, parsefunc, parsedata, dt, &(rci)->servers, dbh, deadline, stamp))
+#define s6dns_resolve_r_g(name, len, qtype, parsefunc, parsedata, qualif, dt, rci, dbh, deadline) s6dns_resolve_r(name, len, qtype, parsefunc, parsedata, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+
+ /* How to perform both AAAA and A queries at the same time */
+
+#define s6dns_resolvenoq_aaaaa(ips, name, len, deadline, stamp) s6dns_resolvenoq_aaaaa_r(ips, name, len, &s6dns_rci_here.servers, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolvenoq_aaaaa_g(ips, name, len, deadline) s6dns_resolvenoq_aaaaa(ips, name, len, (deadline), &STAMP)
+extern int s6dns_resolvenoq_aaaaa_r(genalloc *, char const *, unsigned int, s6dns_ip46list_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolvenoq_aaaaa_r_g(ips, name, len, servers, dbh, deadline) s6dns_resolvenoq_aaaaa_r(ips, name, len, servers, dbh, (deadline), &STAMP)
+
+#define s6dns_resolveq_aaaaa(ips, name, len, deadline, stamp) s6dns_resolveq_aaaaa_r(ips, name, len, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolveq_aaaaa_g(ips, name, len, deadline) s6dns_resolveq_aaaaa(ips, name, len, (deadline), &STAMP)
+extern int s6dns_resolveq_aaaaa_r(genalloc *, char const *, unsigned int, s6dns_rci_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolveq_aaaaa_r_g(ips, name, len, rci, dbh, deadline) s6dns_resolvenoq_aaaaa_r(ips, name, len, rci, dbh, (deadline), &STAMP)
+
+
+ /*
+ Some high-level functions.
+ Queries are automatically translated to domain form and encoded.
+ Domains returned in a stralloc are automatically decoded.
+ Warning: decoded domains all start with '.'
+ The int flag decides if qualification is needed or not.
+ */
+
+ /*
+ For A fields: the stralloc answer has 4 chars per IP4.
+ For AAAA fields: the stralloc answer has 16 chars per IP6.
+ For TXT fields (and other mpag stuff): the stralloc contains the strings
+ and the genalloc contains a list of offsets into that stralloc.
+ For other fields: the result is stored in a genalloc of the appropriate type.
+ */
+
+#define s6dns_resolve_a(ips, name, len, qualif, deadline, stamp) s6dns_resolve_a_r(ips, name, len, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_a_g(ips, name, len, qualif, deadline) s6dns_resolve_a(ips, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_a_r(ips, name, len, qualif, dt, rci, dbh, deadline, stamp) s6dns_resolve_r(name, len, S6DNS_T_A, &s6dns_message_parse_answer_a, (ips), qualif, dt, rci, dbh, deadline, stamp)
+#define s6dns_resolve_a_r_g(ips, name, len, qualif, dt, rci, dbh, deadline) s6dns_resolve_a_r(ips, name, len, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_aaaa(ip6s, name, len, qualif, deadline, stamp) s6dns_resolve_aaaa_r(ip6s, name, len, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_aaaa_g(ip6s, name, len, qualif, deadline) s6dns_resolve_aaaa(ip6s, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_aaaa_r(ip6s, name, len, qualif, dt, rci, dbh, deadline, stamp) s6dns_resolve_r(name, len, S6DNS_T_AAAA, &s6dns_message_parse_answer_aaaa, (ip6s), qualif, dt, rci, dbh, deadline, stamp)
+#define s6dns_resolve_aaaa_r_g(ip6s, name, len, qualif, dt, rci, dbh, deadline) s6dns_resolve_aaaa_r(ip6s, name, len, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_aaaaa(ips, name, len, qualif, deadline, stamp) s6dns_resolve_aaaaa_r(ips, name, len, qualif, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_aaaaa_g(ips, name, len, qualif, deadline) s6dns_resolve_aaaaa(ips, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_aaaaa_r(ips, name, len, qualif, rci, dbh, deadline, stamp) ((qualif) ? s6dns_resolveq_aaaaa_r(ips, name, len, rci, dbh, deadline, stamp) : s6dns_resolvenoq_aaaaa_r(ips, name, len, &(rci)->servers, dbh, deadline, stamp))
+#define s6dns_resolve_aaaaa_r_g(ips, name, len, qualif, rci, dbh, deadline) s6dns_resolve_aaaaa_r(ips, name, len, qualif, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_ptr(ds, name, len, deadline, stamp) s6dns_resolve_ptr_r(ds, name, len, &s6dns_engine_here, &s6dns_rci_here.servers, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_ptr_g(ds, name, len, deadline) s6dns_resolve_ptr(ds, name, len, (deadline), &STAMP)
+#define s6dns_resolve_ptr_r(ds, name, len, dt, servers, dbh, deadline, stamp) s6dns_resolvenoq_r(name, len, S6DNS_T_PTR, &s6dns_message_parse_answer_domain, (ds), dt, servers, dbh, deadline, stamp)
+#define s6dns_resolve_ptr_r_g(ds, name, len, dt, servers, dbh, deadline) s6dns_resolve_ptr_r(ds, name, len, dt, servers, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_name4(ds, ip, deadline, stamp) s6dns_resolve_name4_r(ds, ip, &s6dns_engine_here, &s6dns_rci_here.servers, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_name4_g(ds, ip, deadline) s6dns_resolve_name4(ds, ip, (deadline), &STAMP)
+extern int s6dns_resolve_name4_r (genalloc *, char const *, s6dns_engine_t_ref, s6dns_ip46list_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolve_name4_r_g(ds, ip, dt, servers, dbh, deadline) s6dns_resolve_name4_r(ds, ip, dt, servers, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_name6(ds, ip6, deadline, stamp) s6dns_resolve_name6_r(ds, ip6, &s6dns_engine_here, &s6dns_rci_here.servers, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_name6_g(ds, ip6, deadline) s6dns_resolve_name6(ds, ip6, (deadline), &STAMP)
+extern int s6dns_resolve_name6_r (genalloc *, char const *, s6dns_engine_t_ref, s6dns_ip46list_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolve_name6_r_g(ds, ip6, dt, servers, dbh, deadline) s6dns_resolve_name6_r(ds, ip6, dt, servers, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_name46(ds, i, deadline, stamp) s6dns_resolve_name46_r(ds, i, &s6dns_engine_here, &s6dns_rci_here.servers, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_name46_g(ds, i, deadline) s6dns_resolve_name46(ds, i, (deadline), &STAMP)
+#define s6dns_resolve_name46_r(ds, i, dt, servers, dbh, deadline, stamp) (ip46_is6(i) ? s6dns_resolve_name6_r(ds, (i)->ip, dt, servers, dbh, deadline, stamp) : s6dns_resolve_name4_r(ds, (i)->ip, dt, servers, dbh, deadline, stamp))
+#define s6dns_resolve_name46_r_g(ds, i, dt, servers, dbh, deadline) s6dns_resolve_name46_r(ds, i, dt, servers, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_txt(sa, offsets, name, len, qualif, deadline, stamp) s6dns_resolve_txt_r(sa, offsets, name, len, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_txt_g(sa, offsets, name, len, qualif, deadline) s6dns_resolve_txt(sa, offsets, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_txt_r(sa, offsets, name, len, qualif, dt, rci, dbh, deadline, stamp) s6dns_resolve_mpag_r(sa, offsets, name, len, S6DNS_T_TXT, &s6dns_message_parse_answer_strings, qualif, dt, rci, dbh, deadline, stamp)
+#define s6dns_resolve_txt_r_g(sa, offsets, name, len, qualif, dt, rci, dbh, deadline) s6dns_resolve_txt_r(sa, offsets, name, len, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_mx(mxs, name, len, qualif, deadline, stamp) s6dns_resolve_mx_r(mxs, name, len, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_mx_g(mxs, name, len, qualif, deadline) s6dns_resolve_mx(mxs, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_mx_r(mxs, name, len, qualif, dt, rci, dbh, deadline, stamp) s6dns_resolve_r(name, len, S6DNS_T_MX, &s6dns_message_parse_answer_mx, (mxs), qualif, dt, rci, dbh, deadline, stamp)
+#define s6dns_resolve_mx_r_g(mxs, name, len, qualif, dt, rci, dbh, deadline) s6dns_resolve_mx_r(mxs, name, len, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_ns(ds, name, len, qualif, deadline, stamp) s6dns_resolve_ns_r(ds, name, len, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_ns_g(ds, name, len, qualif, deadline) s6dns_resolve_ns(ds, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_ns_r(ds, name, len, qualif, dt, rci, dbh, deadline, stamp) s6dns_resolve_dpag_r(ds, name, len, S6DNS_T_NS, qualif, dt, rci, dbh, deadline, stamp)
+#define s6dns_resolve_ns_r_g(ds, name, len, qualif, dt, rci, dbh, deadline) s6dns_resolve_ns_r(ds, name, len, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_cname(ds, name, len, qualif, deadline, stamp) s6dns_resolve_cname_r(ds, name, len, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_cname_g(ds, name, len, qualif, deadline) s6dns_resolve_cname(ds, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_cname_r(ds, name, len, qualif, dt, rci, dbh, deadline, stamp) s6dns_resolve_dpag_r(ds, name, len, S6DNS_T_CNAME, qualif, dt, rci, dbh, deadline, stamp)
+#define s6dns_resolve_cname_r_g(ds, name, len, qualif, dt, rci, dbh, deadline) s6dns_resolve_cname_r(ds, name, len, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_hinfo(hinfos, name, len, qualif, deadline, stamp) s6dns_resolve_hinfo_r(hinfos, name, len, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_hinfo_g(hinfos, name, len, qualif, deadline) s6dns_resolve_hinfo(hinfos, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_hinfo_r(hinfos, name, len, qualif, dt, rci, dbh, deadline, stamp) s6dns_resolve_r(name, len, S6DNS_T_HINFO, &s6dns_message_parse_answer_hinfo, (hinfos), qualif, dt, rci, dbh, deadline, stamp)
+#define s6dns_resolve_hinfo_r_g(hinfos, name, len, qualif, dt, rci, dbh, deadline) s6dns_resolve_hinfo_r(hinfos, name, len, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_srv(srvs, name, len, qualif, deadline, stamp) s6dns_resolve_srv_r(srvs, name, len, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_srv_g(srvs, name, len, qualif, deadline) s6dns_resolve_srv(srvs, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_srv_r(srvs, name, len, qualif, dt, rci, dbh, deadline, stamp) s6dns_resolve_r(name, len, S6DNS_T_SRV, &s6dns_message_parse_answer_srv, (srvs), qualif, dt, rci, dbh, deadline, stamp)
+#define s6dns_resolve_srv_r_g(srvs, name, len, qualif, dt, rci, dbh, deadline) s6dns_resolve_srv_r(srvs, name, len, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_soa(soas, name, len, qualif, deadline, stamp) s6dns_resolve_soa_r(soas, name, len, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_soa_g(soas, name, len, qualif, deadline) s6dns_resolve_soa(soas, name, len, qualif, (deadline), &STAMP)
+#define s6dns_resolve_soa_r(soas, name, len, qualif, dt, rci, dbh, deadline, stamp) s6dns_resolve_r(name, len, S6DNS_T_SOA, &s6dns_message_parse_answer_soa, (soas), qualif, dt, rci, dbh, deadline, stamp)
+#define s6dns_resolve_soa_r_g(soas, name, len, qualif, dt, rci, dbh, deadline) s6dns_resolve_soa_r(soas, name, len, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+
+ /* Internals for the high-level functions. */
+
+ /* dpag: structure for generic domain lists + rtype */
+ /* mpag: encoding variable-length information into storage+offsets */
+
+#define s6dns_resolve_dpag(ds, name, len, qtype, qualif, deadline, stamp) s6dns_resolve_dpag_r(ds, name, len, qtype, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_dpag_g(ds, name, len, qtype, qualif, deadline) s6dns_resolve_dpag(ds, name, len, qtype, qualif, (deadline), &STAMP)
+extern int s6dns_resolve_dpag_r (genalloc *, char const *, unsigned int, uint16, int, s6dns_engine_t_ref, s6dns_rci_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolve_dpag_r_g(ds, name, len, qtype, qualif, dt, rci, dbh, deadline) s6dns_resolve_dpag_r(ds, name, len, qtype, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+#define s6dns_resolve_mpag(sa, offsets, name, len, qtype, parsefunc, qualif, deadline, stamp) s6dns_resolve_mpag_r(sa, offsets, name, len, qtype, parsefunc, qualif, &s6dns_engine_here, &s6dns_rci_here, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolve_mpag_g(sa, offsets, name, len, qtype, parsefunc, qualif, deadline) s6dns_resolve_mpag(sa, offsets, name, len, qtype, parsefunc, qualif, (deadline), &STAMP)
+extern int s6dns_resolve_mpag_r (stralloc *, genalloc *, char const *, unsigned int, uint16, s6dns_message_rr_func_t_ref, int, s6dns_engine_t_ref, s6dns_rci_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolve_mpag_r_g(sa, offsets, name, len, qtype, parsefunc, qualif, dt, rci, dbh, deadline) s6dns_resolve_mpag_r(sa, offsets, name, len, qtype, parsefunc, qualif, dt, rci, dbh, (deadline), &STAMP)
+
+
+ /*
+ Functions for n-domain parallel resolution.
+ s6dns_resolven_loop() is the core primitive.
+ s6dns_resolven_parse() is built upon it.
+ This API is still very limited in what it can do; for full
+ asynchronous resolution, use the skadns library.
+ */
+
+extern int s6dns_resolven_loop (s6dns_engine_t_ref, unsigned int, unsigned int, tain_t const *, tain_t *) ;
+#define s6dns_resolven_loop_g(list, n, or, deadline) s6dns_resolven(list, n, or, (deadline), &STAMP)
+
+typedef struct s6dns_resolve_s s6dns_resolve_t, *s6dns_resolve_t_ref ;
+struct s6dns_resolve_s
+{
+ s6dns_domain_t q ;
+ tain_t deadline ;
+ s6dns_message_rr_func_t_ref parsefunc ;
+ void *data ;
+ uint32 options ;
+ int status ;
+ uint16 qtype ;
+} ;
+
+#define s6dns_resolven_parse(list, n, deadline, stamp) s6dns_resolven_parse_r(list, n, &s6dns_rci_here.servers, &s6dns_debughook_zero, deadline, stamp)
+#define s6dns_resolven_parse_g(list, n, deadline) s6dns_resolven_parse(list, n, (deadline), &STAMP)
+extern int s6dns_resolven_parse_r (s6dns_resolve_t_ref, unsigned int, s6dns_ip46list_t const *, s6dns_debughook_t const *, tain_t const *, tain_t *) ;
+#define s6dns_resolven_parse_r_g(list, n, servers, dbh, deadline) s6dns_resolven_parse_r(list, n, servers, dbh, (deadline), &STAMP)
+
+#endif
diff --git a/src/include/s6-dns/s6dns.h b/src/include/s6-dns/s6dns.h
new file mode 100644
index 0000000..dbc1138
--- /dev/null
+++ b/src/include/s6-dns/s6dns.h
@@ -0,0 +1,18 @@
+/* ISC license. */
+
+#ifndef S6DNS_H
+#define S6DNS_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define s6dns_init() s6dns_rci_init(&s6dns_rci_here, "/etc/resolv.conf")
+#define s6dns_finish() (s6dns_engine_free(&s6dns_engine_here), s6dns_rci_free(&s6dns_rci_here))
+
+#endif
diff --git a/src/include/s6-dns/skadns.h b/src/include/s6-dns/skadns.h
new file mode 100644
index 0000000..d5ed82f
--- /dev/null
+++ b/src/include/s6-dns/skadns.h
@@ -0,0 +1,73 @@
+/* ISC license. */
+
+#ifndef SKADNS_H
+#define SKADNS_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define SKADNSD_PROG S6_DNS_BINPREFIX "skadnsd"
+#define SKADNS_BANNER1 "skadns v1.0 (b)\n"
+#define SKADNS_BANNER1_LEN (sizeof SKADNS_BANNER1 - 1)
+#define SKADNS_BANNER2 "skadns v1.0 (a)\n"
+#define SKADNS_BANNER2_LEN (sizeof SKADNS_BANNER2 - 1)
+#define SKADNS_MAXCONCURRENCY 1000
+
+typedef struct skadnsanswer_s skadnsanswer_t, *skadnsanswer_t_ref ;
+struct skadnsanswer_s
+{
+ int status ;
+ char *data ;
+ unsigned int len ;
+} ;
+#define SKADNSANSWER_ZERO { .status = EINVAL, .data = 0, .len = 0 }
+
+typedef struct skadns_s skadns_t, *skadns_t_ref ;
+struct skadns_s
+{
+ skaclient_t connection ;
+ genalloc list ; /* array of uint16 */
+ gensetdyn q ; /* set of skadnsanswer_t */
+ skaclient_buffer_t buffers ;
+} ;
+#define SKADNS_ZERO { .connection = SKACLIENT_ZERO, .list = GENALLOC_ZERO, .q = GENSETDYN_INIT(skadnsanswer_t, 3, 3, 8) }
+extern skadns_t const skadns_zero ;
+
+
+ /* Starting and ending a session */
+
+extern int skadns_start (skadns_t *, char const *, tain_t const *, tain_t *) ;
+#define skadns_start_g(a, path, deadline) skadns_start(a, path, (deadline), &STAMP)
+extern int skadns_startf (skadns_t *, tain_t const *, tain_t *) ;
+#define skadns_startf_g(a, deadline) skadns_startf(a, (deadline), &STAMP)
+extern void skadns_end (skadns_t *) ;
+
+
+ /* Synchronous functions */
+
+extern int skadns_send (skadns_t *, uint16 *, s6dns_domain_t const *, uint16, tain_t const *, tain_t const *, tain_t *) ;
+#define skadns_send_g(a, id, d, qtype, limit, deadline) skadns_send(a, id, d, qtype, limit, (deadline), &STAMP)
+extern int skadns_cancel (skadns_t *, uint16, tain_t const *, tain_t *) ;
+#define skadns_cancel_g(a, id, deadline) skadns_cancel(a, id, (deadline), &STAMP)
+
+
+ /* Asynchronous functions */
+
+#define skadns_fd(a) skaclient_fd(&(a)->connection)
+extern int skadns_update (skadns_t *) ;
+#define skadns_list(a) genalloc_s(uint16 const, &(a)->list)
+#define skadns_clearlist(a) ((a)->list.len = 0)
+extern int skadns_packetlen (skadns_t const *, uint16) ;
+extern char const *skadns_packet (skadns_t const *, uint16) ;
+extern int skadns_release (skadns_t *, uint16) ;
+
+#endif
diff --git a/src/libs6dns/deps-lib/s6dns b/src/libs6dns/deps-lib/s6dns
new file mode 100755
index 0000000..b218652
--- /dev/null
+++ b/src/libs6dns/deps-lib/s6dns
@@ -0,0 +1,88 @@
+s6dns_constants_error.o
+s6dns_constants_error_str.o
+s6dns_debughook_zero.o
+s6dns_domain_arpafromip4.o
+s6dns_domain_arpafromip6.o
+s6dns_domain_decode.o
+s6dns_domain_encode.o
+s6dns_domain_encodelist.o
+s6dns_domain_fromstring.o
+s6dns_domain_fromstring_noqualify_encode.o
+s6dns_domain_fromstring_qualify_encode.o
+s6dns_domain_noqualify.o
+s6dns_domain_qualify.o
+s6dns_domain_tostring.o
+s6dns_engine.o
+s6dns_engine_free.o
+s6dns_engine_freen.o
+s6dns_engine_here.o
+s6dns_engine_nextdeadline.o
+s6dns_engine_zero.o
+s6dns_fmt_domainlist.o
+s6dns_fmt_hinfo.o
+s6dns_fmt_mx.o
+s6dns_fmt_soa.o
+s6dns_fmt_srv.o
+s6dns_message_counts_next.o
+s6dns_message_counts_pack.o
+s6dns_message_counts_unpack.o
+s6dns_message_counts_zero.o
+s6dns_message_get_domain.o
+s6dns_message_get_domain_internal.o
+s6dns_message_get_hinfo.o
+s6dns_message_get_string.o
+s6dns_message_get_string_internal.o
+s6dns_message_get_strings.o
+s6dns_message_get_mx.o
+s6dns_message_get_soa.o
+s6dns_message_get_srv.o
+s6dns_message_header_pack.o
+s6dns_message_header_unpack.o
+s6dns_message_header_zero.o
+s6dns_message_parse_answer_aaaa.o
+s6dns_message_parse_answer_a.o
+s6dns_message_parse_answer_domain.o
+s6dns_message_parse_answer_hinfo.o
+s6dns_message_parse_answer_mx.o
+s6dns_message_parse_answer_soa.o
+s6dns_message_parse_answer_srv.o
+s6dns_message_parse_answer_strings.o
+s6dns_message_parse.o
+s6dns_message_parse_getrr.o
+s6dns_message_parse_init.o
+s6dns_message_parse_next.o
+s6dns_message_parse_skipqd.o
+s6dns_rci_free.o
+s6dns_rci_here.o
+s6dns_rci_init.o
+s6dns_rci_zero.o
+s6dns_resolve_core.o
+s6dns_resolve_parse.o
+s6dns_resolven_loop.o
+s6dns_resolven_parse.o
+s6dns_resolve_dpag.o
+s6dns_resolve_mpag.o
+s6dns_resolve_name4.o
+s6dns_resolve_name6.o
+s6dns_resolvenoq.o
+s6dns_resolveq.o
+s6dns_resolvenoq_aaaaa.o
+s6dns_resolveq_aaaaa.o
+s6dns_analyze_packet.o
+s6dns_analyze_qtype_parse.o
+s6dns_analyze_record.o
+s6dns_analyze_record_a.o
+s6dns_analyze_record_aaaa.o
+s6dns_analyze_record_hinfo.o
+s6dns_analyze_record_mx.o
+s6dns_analyze_record_soa.o
+s6dns_analyze_record_srv.o
+s6dns_analyze_record_domain.o
+s6dns_analyze_record_strings.o
+s6dns_analyze_record_unknown.o
+s6dns_analyze_rtypetable.o
+s6dns_debug_dumpdt_stdout.o
+s6dns_debug_dumpdt_stderr.o
+s6dns_debug_dumpdt_post_recv.o
+s6dns_debug_dumpdt_pre_send.o
+s6dns_debug_dumpdt_post_send.o
diff --git a/src/libs6dns/s6dns-message-internal.h b/src/libs6dns/s6dns-message-internal.h
new file mode 100644
index 0000000..e0d10d6
--- /dev/null
+++ b/src/libs6dns/s6dns-message-internal.h
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#ifndef S6DNS_MESSAGE_INTERNAL_H
+#define S6DNS_MESSAGE_INTERNAL_H
+
+
+ /* Low-level packet parsing */
+
+extern int s6dns_message_get_string_internal (char *, unsigned int, char const *, unsigned int, unsigned int *) ;
+extern unsigned int s6dns_message_get_domain_internal (char *, unsigned int, char const *, unsigned int, unsigned int *) ;
+
+#endif
diff --git a/src/libs6dns/s6dns_analyze_packet.c b/src/libs6dns/s6dns_analyze_packet.c
new file mode 100644
index 0000000..57a5ce5
--- /dev/null
+++ b/src/libs6dns/s6dns_analyze_packet.c
@@ -0,0 +1,127 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define add(s) if ((*gp->put)(gp->target, (s), str_len(s)) < 0) return 0
+#define addfmt(n) if ((*gp->put)(gp->target, fmt, uint_fmt(fmt, (n))) < 0) return 0
+#define addfmt16(n) if ((*gp->put)(gp->target, fmt, uint16_fmt(fmt, (n))) < 0) return 0
+
+int s6dns_analyze_packet (genwrite_t *gp, char const *packet, unsigned int packetlen, int rec)
+{
+ s6dns_message_header_t h ;
+ s6dns_message_counts_t counts ;
+ unsigned int pos ;
+ unsigned int section ;
+ char fmt[UINT_FMT] ;
+ if (!s6dns_message_parse_init(&h, &counts, packet, packetlen, &pos))
+ return 0 ;
+
+ addfmt(packetlen) ;
+ add(" bytes, ") ;
+ addfmt16(counts.qd) ;
+ add("+") ;
+ addfmt16(counts.an) ;
+ add("+") ;
+ addfmt16(counts.ns) ;
+ add("+") ;
+ addfmt16(counts.nr) ;
+ add(" records") ;
+ if (h.qr) add(", response") ;
+ if (h.opcode)
+ {
+ add(", weird op (") ;
+ addfmt(h.opcode) ;
+ add(")") ;
+ }
+ if (h.aa) add(", authoritative") ;
+ if (h.tc) add(", truncated") ;
+ if (h.rd)
+ {
+ add(", ") ;
+ if (!rec) add("weird ") ;
+ add("rd") ;
+ }
+ if (h.ra)
+ {
+ add(", ") ;
+ if (!rec) add("weird ") ;
+ add("ra") ;
+ }
+ switch (h.rcode)
+ {
+ case 0 : add(", noerror") ; break ;
+ case 1 : add(", fmterror") ; break ;
+ case 2 : add(", servfail") ; break ;
+ case 3 : add(", nxdomain") ; break ;
+ case 4 : add(", notimpl") ; break ;
+ case 5 : add(", refused") ; break ;
+ default:
+ {
+ add(", weird rcode (") ;
+ addfmt(h.rcode) ;
+ add(")") ;
+ }
+ }
+ if (h.z)
+ {
+ add(", weird z (") ;
+ addfmt(h.z) ;
+ add(")") ;
+ }
+ add("\n") ;
+
+ for (;;)
+ {
+ s6dns_domain_t d ;
+ char buf[257] ;
+ unsigned int len ;
+ uint16 qtype ;
+ uint16 qclass ;
+ section = s6dns_message_counts_next(&counts) ;
+ if (section != 1) break ;
+ add("query: ") ;
+ if (!s6dns_message_get_domain(&d, packet, packetlen, &pos)) return 0 ;
+ len = s6dns_domain_tostring(buf, 255, &d) ;
+ if (!len) return 0 ;
+ buf[len++] = '\n' ; buf[len++] = 0 ;
+ if (pos + 4 > packetlen) return (errno = EPROTO, 0) ;
+ uint16_unpack_big(packet + pos, &qtype) ; pos += 2 ;
+ uint16_unpack_big(packet + pos, &qclass) ; pos += 2 ;
+ if (qclass != S6DNS_C_IN)
+ {
+ add("weird class (") ;
+ addfmt16(qclass) ;
+ add(") - ") ;
+ }
+ addfmt16(qtype) ;
+ add(" ") ;
+ add(buf) ;
+ }
+
+ while (section)
+ {
+ static char const *intro[3] = { "answer: ", "authority: ", "additional: " } ;
+ s6dns_message_rr_t rr ;
+ if (!s6dns_message_parse_getrr(&rr, packet, packetlen, &pos)) return 0 ;
+ add(intro[section-2]) ;
+ if (rr.rclass != S6DNS_C_IN)
+ {
+ add("weird class (") ;
+ addfmt16(rr.rclass) ;
+ add("), not attempting to analyze record\n") ;
+ }
+ else if (!s6dns_analyze_record(gp, &rr, packet, packetlen, pos)) return 0 ;
+ section = s6dns_message_parse_next(&counts, &rr, packet, packetlen, &pos) ;
+ }
+
+ return 1 ;
+}
diff --git a/src/libs6dns/s6dns_analyze_qtype_parse.c b/src/libs6dns/s6dns_analyze_qtype_parse.c
new file mode 100644
index 0000000..8c04137
--- /dev/null
+++ b/src/libs6dns/s6dns_analyze_qtype_parse.c
@@ -0,0 +1,46 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+
+typedef struct lookuptable_s lookuptable_t, *lookuptable_t_ref ;
+struct lookuptable_s
+{
+ char const *text ;
+ uint16 qtype ;
+} ;
+
+static lookuptable_t const table[] =
+{
+ { "ANY", S6DNS_T_ANY },
+ { "A", S6DNS_T_A },
+ { "NS", S6DNS_T_NS },
+ { "CNAME", S6DNS_T_CNAME },
+ { "SOA", S6DNS_T_SOA },
+ { "PTR", S6DNS_T_PTR },
+ { "HINFO", S6DNS_T_HINFO },
+ { "MX", S6DNS_T_MX },
+ { "TXT", S6DNS_T_TXT },
+ { "AAAA", S6DNS_T_AAAA },
+ { "SRV", S6DNS_T_SRV },
+ { "RP", S6DNS_T_RP },
+ { "SIG", S6DNS_T_SIG },
+ { "KEY", S6DNS_T_KEY },
+ { "AXFR", S6DNS_T_AXFR },
+ { 0, 0 }
+} ;
+
+uint16 s6dns_analyze_qtype_parse (char const *s)
+{
+ {
+ uint16 u ;
+ if (uint160_scan(s, &u)) return u ;
+ }
+ {
+ register lookuptable_t const *p = table ;
+ for (; p->text ; p++) if (case_equals(s, p->text)) return p->qtype ;
+ }
+ return 0 ;
+}
diff --git a/src/libs6dns/s6dns_analyze_record.c b/src/libs6dns/s6dns_analyze_record.c
new file mode 100644
index 0000000..dd2e7d2
--- /dev/null
+++ b/src/libs6dns/s6dns_analyze_record.c
@@ -0,0 +1,37 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static s6dns_analyze_rtypetable_t const *rtypelookup (uint16 rtype)
+{
+ register s6dns_analyze_rtypetable_t const *wut = s6dns_analyze_rtypetable ;
+ while (wut->rtype && wut->rtype != rtype) wut++ ;
+ return wut ;
+}
+
+int s6dns_analyze_record (genwrite_t *gp, s6dns_message_rr_t const *rr, char const *packet, unsigned int packetlen, unsigned int pos)
+{
+ s6dns_analyze_rtypetable_t const *wut = rtypelookup(rr->rtype) ;
+ {
+ char buf[256] ;
+ register unsigned int n = s6dns_domain_tostring(buf, 256, &rr->name) ;
+ if (!n) return 0 ;
+ if ((*gp->put)(gp->target, buf, n) < 0) return 0 ;
+ }
+ {
+ char fmt[UINT32_FMT+1] = " " ;
+ if ((*gp->put)(gp->target, fmt, 1 + uint32_fmt(fmt+1, rr->ttl)) < 0) return 0 ;
+ }
+ if ((*gp->put)(gp->target, " ", 1) < 0) return 0 ;
+ if ((*gp->put)(gp->target, wut->string, str_len(wut->string)) < 0) return 0 ;
+ if ((*gp->put)(gp->target, " ", 1) < 0) return 0 ;
+ if (!(*wut->f)(gp, rr, packet, packetlen, pos)) return 0 ;
+ if ((*gp->put)(gp->target, "\n", 1) < 0) return 0 ;
+ return 1 ;
+}
diff --git a/src/libs6dns/s6dns_analyze_record_a.c b/src/libs6dns/s6dns_analyze_record_a.c
new file mode 100644
index 0000000..5e374cb
--- /dev/null
+++ b/src/libs6dns/s6dns_analyze_record_a.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+int s6dns_analyze_record_a (genwrite_t *gp, s6dns_message_rr_t const *rr, char const *packet, unsigned int packetlen, unsigned int pos)
+{
+ char fmt[IP4_FMT] ;
+ if (rr->rdlength != 4) return (errno = EPROTO, 0) ;
+ if (pos + 4 > packetlen) return (errno = EPROTO, 0) ;
+ if ((*gp->put)(gp->target, fmt, ip4_fmt(fmt, packet + pos)) < 0) return 0 ;
+ return 1 ;
+}
diff --git a/src/libs6dns/s6dns_analyze_record_aaaa.c b/src/libs6dns/s6dns_analyze_record_aaaa.c
new file mode 100644
index 0000000..495ba24
--- /dev/null
+++ b/src/libs6dns/s6dns_analyze_record_aaaa.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include