diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | doc/dnsfunneld.html | 9 | ||||
-rw-r--r-- | doc/index.html | 2 | ||||
-rw-r--r-- | doc/upgrade.html | 3 | ||||
-rw-r--r-- | package/info | 2 | ||||
-rw-r--r-- | src/dnsfunnel/dnsfunneld.c | 42 | ||||
-rw-r--r-- | src/dnsfunnel/dnsfunneld.h | 10 | ||||
-rw-r--r-- | src/dnsfunnel/dnsfunneld_answer.c | 14 | ||||
-rw-r--r-- | src/dnsfunnel/dnsfunneld_process.c | 2 |
9 files changed, 44 insertions, 44 deletions
diff --git a/NEWS b/NEWS index 63c84ce..0aad5c7 100644 --- a/NEWS +++ b/NEWS @@ -1,9 +1,9 @@ Changelog for dnsfunnel. -In 0.0.1.7 +In 0.0.2.0 ---------- - - Align on rest of skaware. + - dnsfunneld can now listen on IPv6 addresses. In 0.0.1.6 diff --git a/doc/dnsfunneld.html b/doc/dnsfunneld.html index ae03cf1..48ea870 100644 --- a/doc/dnsfunneld.html +++ b/doc/dnsfunneld.html @@ -34,8 +34,8 @@ queries, the responses, or both. <ul> <li> dnsfunneld creates a UDP inet domain socket and binds it -to IPv4 address <em>ip</em> (normally 127.0.0.1) and port <em>port</em> -(normally 53). </li> +to IP (v4 or v6) address <em>ip</em> (by default 127.0.0.1) and +port <em>port</em> (normally 53). </li> <li> Depending on the options it has been given, it may chroot and lose privileges on its gid and uid. </li> <li> It reads the <tt>caches</tt> file (relative to its current @@ -86,7 +86,7 @@ in the GID environment variable, and drop privileges to that uid/gid. </li> <li> <tt>-g <em>gid</em></tt> : drop privileges to numerical gid <em>gid</em>. </li> <li> <tt>-i <em>ip</em></tt> : bind the socket to -IPv4 <em>ip</em>. Default is <tt>127.0.0.1</tt>. </li> +IP address <em>ip</em>. Default is <tt>127.0.0.1</tt>. </li> <li> <tt>-p <em>port</em></tt> : bind the socket to port <em>port</em>. Default is <tt>53</tt>. </li> <li> <tt>-R <em>root</em></tt> : chroot to <em>root</em>. Default @@ -201,6 +201,9 @@ changes on the <tt>/etc/resolv.conf</tt> file (via inotify or kqueue, depending on your system) and immediately calling <a href="dnsfunnel-translate.html">dnsfunnel-translate</a>, sending a SIGHUP to dnsfunneld, and forcefully overwriting <tt>/etc/resolv.conf</tt>. </li> + <li> dnsfunneld can also be used as a simple forwarder, for instance to +transmit DNS queries arriving on an IPv6 address to a DNS cache that only +listens to IPv4 addresses. </li> <li> It is easy to send a SIGHUP to dnsfunneld even without knowing its pid, if it is run under a process supervision system such as <a href="//skarnet.org/software/s6/">s6</a>. </li> diff --git a/doc/index.html b/doc/index.html index a1648c5..ba3dadd 100644 --- a/doc/index.html +++ b/doc/index.html @@ -65,7 +65,7 @@ library. </li> <ul> <li> The current released version of dnsfunnel is -<a href="dnsfunnel-0.0.1.7.tar.gz">0.0.1.7</a>. +<a href="dnsfunnel-0.0.2.0.tar.gz">0.0.2.0</a>. (dnsfunnel is in beta development at the moment. Use at your own risk.) </li> <li> Alternatively, you can checkout a copy of the diff --git a/doc/upgrade.html b/doc/upgrade.html index f478bdc..8f83451 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -18,7 +18,7 @@ <h1> What has changed in dnsfunnel </h1> -<h2> in 0.0.1.7 </h2> +<h2> in 0.0.2.0 </h2> <ul> <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> dependency bumped to @@ -27,6 +27,7 @@ 2.3.8.0. </li> <li> Static libraries (if any, which isn't the case for now) are installed in <tt>/usr/lib</tt> by default. </li> + <li> <a href="dnsfunneld.html">dnsfunneld</a> can now listen on IPv6 addresses. </a> </ul> <h2> in 0.0.1.6 </h2> diff --git a/package/info b/package/info index 44f9e4b..d1e9959 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=dnsfunnel -version=0.0.1.7 +version=0.0.2.0 category=web package_macro_name=DNSFUNNEL diff --git a/src/dnsfunnel/dnsfunneld.c b/src/dnsfunnel/dnsfunneld.c index 61e2cc1..f57b265 100644 --- a/src/dnsfunnel/dnsfunneld.c +++ b/src/dnsfunnel/dnsfunneld.c @@ -31,6 +31,7 @@ #include <skalibs/iopause.h> #include <skalibs/selfpipe.h> #include <skalibs/gensetdyn.h> +#include <skalibs/ip46.h> #include <s6-dns/s6dns.h> @@ -42,6 +43,8 @@ #define DNSFUNNELD_INPUT_MAX 64 unsigned int verbosity = 1 ; +unsigned int ipsz = 4 ; + static tain globaltto ; static int cont = 1 ; static s6dns_ip46list_t cachelist ; @@ -110,14 +113,13 @@ static uint32_t sentinel ; #define inflight (gensetdyn_n(&queries) - 1) #define QUERY(i) GENSETDYN_P(dfquery_t, &queries, i) -void query_new (s6dns_domain_t const *d, uint16_t qtype, uint16_t id, uint32_t ip, uint16_t port, uint32_t procid) +void query_new (s6dns_domain_t const *d, uint16_t qtype, uint16_t id, char const *ip, uint16_t port, uint32_t procid) { dfquery_t q = { .next = QUERY(sentinel)->next, .xindex = 0, .procid = procid, - .ip = ip, .port = port, .id = id, .dt = S6DNS_ENGINE_ZERO @@ -125,6 +127,7 @@ void query_new (s6dns_domain_t const *d, uint16_t qtype, uint16_t id, uint32_t i s6dns_domain_t dd = *d ; tain deadline ; uint32_t i ; + memcpy(q.ip, ip, ipsz) ; if (!gensetdyn_new(&queries, &i)) strerr_diefu1sys(111, "create new query") ; s6dns_domain_encode(&dd) ; @@ -135,10 +138,9 @@ void query_new (s6dns_domain_t const *d, uint16_t qtype, uint16_t id, uint32_t i QUERY(sentinel)->next = i ; } -static inline void sanitize_and_new (char const *buf, unsigned int len, char const *ippack, uint16_t port) +static inline void sanitize_and_new (char const *buf, unsigned int len, char const *ip, uint16_t port) { s6dns_domain_t d ; - uint32_t ip ; unsigned int pos ; s6dns_message_header_t hdr ; s6dns_message_counts_t counts ; @@ -150,20 +152,10 @@ static inline void sanitize_and_new (char const *buf, unsigned int len, char con || hdr.counts.qd != 1 || hdr.counts.an || hdr.counts.ns || hdr.counts.nr || !s6dns_message_parse_question(&counts, &d, &qtype, buf, len, &pos)) return ; - uint32_unpack_big(ippack, &ip) ; if (ops) query_process_question(ops, &d, qtype, hdr.id, ip, port) ; else query_new(&d, qtype, hdr.id, ip, port, 0) ; } -static inline size_t ip40_scan (char const *s, char *ip) -{ - char t[4] ; - size_t l = ip4_scan(s, t) ; - if (!l || s[l]) return 0 ; - memcpy(ip, t, 4) ; - return l ; -} - int main (int argc, char const *const *argv) { int spfd = -1 ; @@ -178,9 +170,10 @@ int main (int argc, char const *const *argv) int notif = 0 ; int fd ; unsigned int t = 0 ; - char ip[4] = { 127, 0, 0, 1 } ; - uint16_t port = 53 ; subgetopt l = SUBGETOPT_ZERO ; + uint16_t port = 53 ; + ip46 ip ; + (void)ip46_from_ip4(&ip, IP4_LOCAL) ; for (;;) { @@ -193,7 +186,7 @@ int main (int argc, char const *const *argv) case 'U' : flagU = 1 ; break ; case 'u' : if (!uid0_scan(l.arg, &uid)) dieusage() ; break ; case 'g' : if (!gid0_scan(l.arg, &gid)) dieusage() ; break ; - case 'i' : if (!ip40_scan(l.arg, ip)) dieusage() ; break ; + case 'i' : if (!ip46_scan(l.arg, &ip)) dieusage() ; break ; case 'p' : if (!uint160_scan(l.arg, &port)) dieusage() ; break ; case 'R' : root = l.arg ; break ; case 'b' : if (!uint0_scan(l.arg, &bufsize)) dieusage() ; break ; @@ -214,13 +207,14 @@ int main (int argc, char const *const *argv) if (notif) strerr_dief1sys(100, "option -1 given but stdout unavailable") ; } else if (!notif) close(1) ; - fd = socket_udp4() ; + ipsz = ip46_is6(&ip) ? 16 : 4 ; + fd = socket_udp46(ip46_is6(&ip)) ; if (fd < 0) strerr_diefu1sys(111, "create UDP socket") ; - if (socket_bind4_reuse(fd, ip, port) < 0) + if (socket_bind46_reuse(fd, &ip, port) < 0) { - char fmti[IP4_FMT] ; + char fmti[IP46_FMT] ; char fmtp[UINT16_FMT] ; - fmti[ip4_fmt(fmti, ip)] = 0 ; + fmti[ip46_fmt(fmti, &ip)] = 0 ; fmtp[uint16_fmt(fmtp, port)] = 0 ; strerr_diefu4sys(111, "bind on ip ", fmti, " port ", fmtp) ; } @@ -383,10 +377,10 @@ int main (int argc, char const *const *argv) uint32_t n = DNSFUNNELD_INPUT_MAX ; while (n--) { - char ip[4] ; - uint16_t port ; char buf[512] ; - ssize_t r = socket_recv4(0, buf, 512, ip, &port) ; + char ip[16] ; + uint16_t port ; + ssize_t r = ipsz == 16 ? socket_recv6(0, buf, 512, ip, &port) : socket_recv4(0, buf, 512, ip, &port) ; if (r < 0) if (error_isagain(errno)) break ; else strerr_diefu1sys(111, "socket_recv") ; diff --git a/src/dnsfunnel/dnsfunneld.h b/src/dnsfunnel/dnsfunneld.h index 4b9acd3..e4d5d64 100644 --- a/src/dnsfunnel/dnsfunneld.h +++ b/src/dnsfunnel/dnsfunneld.h @@ -7,6 +7,7 @@ #include <stdint.h> #include <skalibs/gensetdyn.h> +#include <skalibs/ip46.h> #include <s6-dns/s6dns-domain.h> #include <s6-dns/s6dns-engine.h> @@ -17,14 +18,15 @@ struct dfquery_s uint32_t next ; uint32_t xindex ; uint32_t procid ; - uint32_t ip ; + char ip[SKALIBS_IP_SIZE] ; uint16_t port ; uint16_t id ; s6dns_engine_t dt ; } ; -#define DFQUERY_ZERO { .next = 0, .xindex = 0, .procid = 0, .ip = 0, .port = 0, .id = 0, .dt = S6DNS_ENGINE_ZERO } +#define DFQUERY_ZERO { .next = 0, .xindex = 0, .procid = 0, .ip = { 0 }, .port = 0, .id = 0, .dt = S6DNS_ENGINE_ZERO } extern unsigned int verbosity ; +extern unsigned int ipsz ; extern size_t dfanswer_pending (void) ; extern int dfanswer_flush (void) ; extern void dfanswer_fail (dfquery_t const *, int) ; @@ -33,11 +35,11 @@ extern void dfanswer_nodata (dfquery_t const *, int) ; extern void dfanswer_pass (dfquery_t const *, char *, unsigned int) ; -extern void query_new (s6dns_domain_t const *, uint16_t, uint16_t, uint32_t, uint16_t, uint32_t) ; +extern void query_new (s6dns_domain_t const *, uint16_t, uint16_t, char const *, uint16_t, uint32_t) ; extern int query_process_init (void) ; extern void query_process_reload (void) ; -extern void query_process_question (uint32_t, s6dns_domain_t const *, uint16_t, uint16_t, uint32_t, uint16_t) ; +extern void query_process_question (uint32_t, s6dns_domain_t const *, uint16_t, uint16_t, char const *, uint16_t) ; extern void query_process_response_failure (uint32_t, dfquery_t const *) ; extern void query_process_response_success (uint32_t, dfquery_t const *) ; diff --git a/src/dnsfunnel/dnsfunneld_answer.c b/src/dnsfunnel/dnsfunneld_answer.c index 4266089..c16c280 100644 --- a/src/dnsfunnel/dnsfunneld_answer.c +++ b/src/dnsfunnel/dnsfunneld_answer.c @@ -24,7 +24,7 @@ size_t dfanswer_pending () return q.len - head ; } -static void dfanswer_push (char const *s, size_t len, uint32_t ip, uint16_t port) +static void dfanswer_push (char const *s, size_t len, char const *ip, uint16_t port) { if (len > 512) { @@ -33,10 +33,10 @@ static void dfanswer_push (char const *s, size_t len, uint32_t ip, uint16_t port } else { - if (!stralloc_readyplus(&q, len + 8)) strerr_diefu1sys(111, "queue answer to client") ; - uint32_pack_big(q.s + q.len, ip) ; q.len += 4 ; + if (!stralloc_readyplus(&q, len + 4 + ipsz)) strerr_diefu1sys(111, "queue answer to client") ; uint16_pack_big(q.s + q.len, port) ; q.len += 2 ; uint16_pack_big(q.s + q.len, len) ; q.len += 2 ; + memcpy(q.s + q.len, ip, ipsz) ; q.len += ipsz ; memcpy(q.s + q.len, s, len) ; q.len += len ; } } @@ -46,11 +46,11 @@ int dfanswer_flush () while (dfanswer_pending()) { uint16_t port, len ; - uint16_unpack_big(q.s + head + 4, &port) ; - uint16_unpack_big(q.s + head + 6, &len) ; - if (socket_send4(0, q.s + head + 8, len, q.s + head, port) < 0) + uint16_unpack_big(q.s + head, &port) ; + uint16_unpack_big(q.s + head + 2, &len) ; + if ((ipsz == 16 ? socket_send6(0, q.s + head + 20, len, q.s + head + 4, port) : socket_send4(0, q.s + head + 8, len, q.s + head + 4, port)) < 0) return error_isagain(errno) ? (errno = 0, 0) : -1 ; - head += len + 8 ; + head += 4 + ipsz + len ; if ((q.len - head) >> 2 <= q.len) { memmove(q.s, q.s + head, q.len - head) ; diff --git a/src/dnsfunnel/dnsfunneld_process.c b/src/dnsfunnel/dnsfunneld_process.c index 5f28a37..9ccdf2e 100644 --- a/src/dnsfunnel/dnsfunneld_process.c +++ b/src/dnsfunnel/dnsfunneld_process.c @@ -25,7 +25,7 @@ void query_process_reload () { } -void query_process_question (uint32_t ops, s6dns_domain_t const *d, uint16_t qtype, uint16_t id, uint32_t ip, uint16_t port) +void query_process_question (uint32_t ops, s6dns_domain_t const *d, uint16_t qtype, uint16_t id, char const *ip, uint16_t port) { if (ops & 2 && (qtype == S6DNS_T_A || qtype == S6DNS_T_AAAA)) { |