summaryrefslogtreecommitdiff
path: root/src/clients
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2014-12-10 03:05:47 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2014-12-10 03:05:47 +0000
commit416ef5e2bf59bb2e45066a1d5d91ac677c0f48e5 (patch)
tree1c746d673dcec7a8488c6ac51db8245411034376 /src/clients
downloads6-dns-416ef5e2bf59bb2e45066a1d5d91ac677c0f48e5.tar.xz
Initial commit
Diffstat (limited to 'src/clients')
-rw-r--r--src/clients/deps-exe/s6-dnsip44
-rw-r--r--src/clients/deps-exe/s6-dnsip4-filter6
-rw-r--r--src/clients/deps-exe/s6-dnsip64
-rw-r--r--src/clients/deps-exe/s6-dnsip6-filter6
-rw-r--r--src/clients/deps-exe/s6-dnsmx4
-rw-r--r--src/clients/deps-exe/s6-dnsname4
-rw-r--r--src/clients/deps-exe/s6-dnsname-filter6
-rw-r--r--src/clients/deps-exe/s6-dnsns4
-rw-r--r--src/clients/deps-exe/s6-dnsq4
-rw-r--r--src/clients/deps-exe/s6-dnsqr4
-rw-r--r--src/clients/deps-exe/s6-dnsqualify2
-rw-r--r--src/clients/deps-exe/s6-dnssoa4
-rw-r--r--src/clients/deps-exe/s6-dnssrv4
-rw-r--r--src/clients/deps-exe/s6-dnstxt4
-rw-r--r--src/clients/deps-exe/s6-randomip3
-rw-r--r--src/clients/deps-lib/s6dnsgenericfilter2
-rw-r--r--src/clients/s6-dnsip4-filter.c52
-rw-r--r--src/clients/s6-dnsip4.c62
-rw-r--r--src/clients/s6-dnsip6-filter.c52
-rw-r--r--src/clients/s6-dnsip6.c62
-rw-r--r--src/clients/s6-dnsmx.c64
-rw-r--r--src/clients/s6-dnsname-filter.c83
-rw-r--r--src/clients/s6-dnsname.c75
-rw-r--r--src/clients/s6-dnsns.c61
-rw-r--r--src/clients/s6-dnsq.c99
-rw-r--r--src/clients/s6-dnsqr.c74
-rw-r--r--src/clients/s6-dnsqualify.c34
-rw-r--r--src/clients/s6-dnssoa.c63
-rw-r--r--src/clients/s6-dnssrv.c75
-rw-r--r--src/clients/s6-dnstxt.c78
-rw-r--r--src/clients/s6-randomip.c62
-rw-r--r--src/clients/s6dns-generic-filter.h22
-rw-r--r--src/clients/s6dns_generic_filter_main.c230
-rw-r--r--src/clients/s6dns_namescanner.c12
34 files changed, 1325 insertions, 0 deletions
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 <skalibs/bytestr.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <s6-dns/s6dns-constants.h>
+#include <s6-dns/s6dns-message.h>
+#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 <errno.h>
+#include <skalibs/uint.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <skalibs/tai.h>
+#include <skalibs/random.h>
+#include <s6-dns/s6dns.h>
+
+#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 <skalibs/bytestr.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <s6-dns/s6dns-constants.h>
+#include <s6-dns/s6dns-message.h>
+#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 <errno.h>
+#include <skalibs/uint.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <skalibs/tai.h>
+#include <skalibs/random.h>
+#include <s6-dns/s6dns.h>
+
+#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 <errno.h>
+#include <skalibs/uint16.h>
+#include <skalibs/uint.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <skalibs/tai.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/random.h>
+#include <s6-dns/s6dns.h>
+
+#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 <errno.h>
+#include <skalibs/error.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/stralloc.h>
+#include <s6-dns/s6dns-constants.h>
+#include <s6-dns/s6dns-domain.h>
+#include <s6-dns/s6dns-message.h>
+#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 <errno.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/tai.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/ip46.h>
+#include <skalibs/random.h>
+#include <skalibs/s6dns.h>
+
+#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 <errno.h>
+#include <skalibs/uint.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <skalibs/tai.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/random.h>
+#include <s6-dns/s6dns.h>
+
+#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 <errno.h>
+#include <skalibs/uint16.h>
+#include <skalibs/uint32.h>
+#include <skalibs/uint.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/bitarray.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/buffer.h>
+#include <skalibs/genwrite.h>
+#include <skalibs/tai.h>
+#include <skalibs/ip46.h>
+#include <s6-dns/s6dns.h>
+#include <s6-dns/s6dns-analyze.h>
+#include <s6-dns/s6dns-debug.h>
+
+#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 <errno.h>
+#include <skalibs/uint16.h>
+#include <skalibs/uint.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/buffer.h>
+#include <skalibs/genwrite.h>
+#include <skalibs/tai.h>
+#include <s6-dns/s6dns.h>
+#include <s6-dns/s6dns-analyze.h>
+#include <s6-dns/s6dns-debug.h>
+
+#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 <skalibs/bytestr.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <s6-dns/s6dns.h>
+
+#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 <errno.h>
+#include <skalibs/uint.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <skalibs/tai.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/random.h>
+#include <s6-dns/s6dns.h>
+
+#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 <errno.h>
+#include <skalibs/uint.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <skalibs/tai.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/random.h>
+#include <s6-dns/s6dns.h>
+
+#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 <errno.h>
+#include <skalibs/uint.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <skalibs/tai.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/skamisc.h>
+#include <skalibs/random.h>
+#include <s6-dns/s6dns.h>
+
+#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(&quoted, sa.s + beg, end - beg) || !stralloc_0(&quoted))
+ 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(&quoted) ;
+ 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 <errno.h>
+#include <skalibs/uint.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/buffer.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/random.h>
+
+#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 <skalibs/uint16.h>
+#include <skalibs/stralloc.h>
+#include <s6-dns/s6dns-domain.h>
+
+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 <errno.h>
+#include <skalibs/error.h>
+#include <skalibs/uint16.h>
+#include <skalibs/uint.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/env.h>
+#include <skalibs/tai.h>
+#include <skalibs/iopause.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/buffer.h>
+#include <skalibs/bufalloc.h>
+#include <skalibs/skamisc.h>
+#include <s6-dns/s6dns-constants.h>
+#include <s6-dns/s6dns-domain.h>
+#include <s6-dns/skadns.h>
+#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 <s6-dns/s6dns-domain.h>
+#include <s6-dns/s6dns-generic-filter.h>
+
+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 ;
+}