diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9c14d9960e..08a189ddc3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -88,7 +88,7 @@ stages:
- test -w "${CCACHE_DIR}" && export PATH="/usr/lib/ccache:${PATH}"
- ./autogen.sh
script:
- - ./configure --enable-developer --with-libtool --disable-static --with-atf=/usr/local
+ - ./configure --enable-developer --with-libtool --disable-static --with-atf=/usr/local --with-libidn2
- make -j${PARALLEL_JOBS_BUILD:-1} -k all V=1
artifacts:
expire_in: '1 hour'
diff --git a/CHANGES b/CHANGES
index 2c2e503716..bcdf8f3849 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+4915. [func] Implement IDNA2008 support in dig by adding support
+ for libidn2. New dig option +idnin has been added,
+ which allows to process invalid domain names much
+ like dig without IDN support. libidn2 version 2.0
+ or higher is needed for +idnout enabled by default.
+
4914. [bug] A bug in zone database reference counting could lead to
a crash when multiple versions of a slave zone were
transferred from a master in close succession.
diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in
index 46a4cf60f7..ceb272d0a2 100644
--- a/bin/dig/Makefile.in
+++ b/bin/dig/Makefile.in
@@ -19,7 +19,7 @@ READLINE_LIB = @READLINE_LIB@
CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} \
${BIND9_INCLUDES} ${ISC_INCLUDES} \
- ${IRS_INCLUDES} ${ISCCFG_INCLUDES} @DST_OPENSSL_INC@
+ ${IRS_INCLUDES} ${ISCCFG_INCLUDES} @LIBIDN2_CFLAGS@ @DST_OPENSSL_INC@
CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@
CWARNINGS =
@@ -41,10 +41,10 @@ DEPLIBS = ${DNSDEPLIBS} ${IRSDEPLIBS} ${BIND9DEPLIBS} \
${ISCDEPLIBS} ${ISCCFGDEPLIBS}
LIBS = ${DNSLIBS} ${IRSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
- ${ISCLIBS} @IDNLIBS@ @LIBS@
+ ${ISCLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@
NOSYMLIBS = ${DNSLIBS} ${IRSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
- ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@
+ ${ISCNOSYMLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@
SUBDIRS =
diff --git a/bin/dig/dig.c b/bin/dig/dig.c
index cfe05cd7b4..482809ccf0 100644
--- a/bin/dig/dig.c
+++ b/bin/dig/dig.c
@@ -190,7 +190,8 @@ help(void) {
" +[no]fail (Don't try next server on SERVFAIL)\n"
" +[no]header-only (Send query without a question section)\n"
" +[no]identify (ID responders in short answers)\n"
-" +[no]idnout (convert IDN response)\n"
+" +[no]idnin (Parse IDN names)\n"
+" +[no]idnout (Convert IDN response)\n"
" +[no]ignore (Don't revert to TCP for TC responses.)\n"
" +[no]keepalive (Request EDNS TCP keepalive)\n"
" +[no]keepopen (Keep the TCP socket open between queries)\n"
@@ -1045,13 +1046,29 @@ plus_option(const char *option, isc_boolean_t is_batchfile,
lookup->identify = state;
break;
case 'n':
- FULLCHECK("idnout");
-#ifndef WITH_IDN
- fprintf(stderr, ";; IDN support not enabled\n");
+ switch (cmd[3]) {
+ case 'i':
+ FULLCHECK("idnin");
+#ifndef WITH_IDN_SUPPORT
+ fprintf(stderr, ";; IDN input support"
+ " not enabled\n");
#else
- lookup->idnout = state;
+ lookup->idnin = state;
#endif
break;
+ case 'o':
+ FULLCHECK("idnout");
+#ifndef WITH_IDN_OUT_SUPPORT
+ fprintf(stderr, ";; IDN output support"
+ " not enabled\n");
+#else
+ lookup->idnout = state;
+#endif
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
default:
goto invalid_option;
}
diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook
index 219cfd5dee..80318bb32f 100644
--- a/bin/dig/dig.docbook
+++ b/bin/dig/dig.docbook
@@ -776,6 +776,17 @@
+
+
+
+
+ Process [do not process] IDN domain names on input.
+ This requires IDN SUPPORT to have been enabled at
+ compile time. The default is to process IDN input.
+
+
+
+
@@ -1288,10 +1299,9 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr
dig appropriately converts character encoding of
domain name before sending a request to DNS server or displaying a
reply from the server.
- If you'd like to turn off the IDN support for some reason, defines
- the IDN_DISABLE environment variable.
- The IDN support is disabled if the variable is set when
- dig runs.
+ If you'd like to turn off the IDN support for some reason, use
+ parameters +noidnin and
+ +noidnout.
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index 508c620e67..c5d027bd4f 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -24,18 +24,25 @@
#include
#include
#include
+#include
#ifdef HAVE_LOCALE_H
#include
#endif
-#ifdef WITH_IDN
+#ifdef WITH_IDN_SUPPORT
+#ifdef WITH_IDNKIT
#include
#include
#include
#include
#endif
+#ifdef WITH_LIBIDN2
+#include
+#endif
+#endif /* WITH_IDN_SUPPORT */
+
#include
#include
#include
@@ -134,18 +141,26 @@ int lookup_counter = 0;
static char servercookie[256];
-#ifdef WITH_IDN
-static void initialize_idn(void);
-static isc_result_t output_filter(isc_buffer_t *buffer,
- unsigned int used_org,
- isc_boolean_t absolute);
-static idn_result_t append_textname(char *name, const char *origin,
- size_t namesize);
-static void idn_check_result(idn_result_t r, const char *msg);
+#ifdef WITH_IDN_SUPPORT
+static void idn_initialize(void);
+static isc_result_t idn_locale_to_ace(const char *from,
+ char *to,
+ size_t tolen);
+#endif /* WITH_IDN_SUPPORT */
-#define MAXDLEN 256
-int idnoptions = 0;
+#ifdef WITH_IDN_OUT_SUPPORT
+static isc_result_t idn_ace_to_locale(const char *from,
+ char *to,
+ size_t tolen);
+static isc_result_t output_filter(isc_buffer_t *buffer,
+ unsigned int used_org,
+ isc_boolean_t absolute);
+#define MAXDLEN 256
+
+#ifdef WITH_IDNKIT
+int idnoptions = 0;
#endif
+#endif /* WITH_IDN_OUT_SUPPORT */
isc_socket_t *keep = NULL;
isc_sockaddr_t keepaddr;
@@ -646,7 +661,12 @@ make_empty_lookup(void) {
looknew->ttlunits = ISC_FALSE;
looknew->ttlunits = ISC_FALSE;
looknew->qr = ISC_FALSE;
-#ifdef WITH_IDN
+#ifdef WITH_IDN_SUPPORT
+ looknew->idnin = ISC_TRUE;
+#else
+ looknew->idnin = ISC_FALSE;
+#endif
+#ifdef WITH_IDN_OUT_SUPPORT
looknew->idnout = ISC_TRUE;
#else
looknew->idnout = ISC_FALSE;
@@ -791,6 +811,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
looknew->nocrypto = lookold->nocrypto;
looknew->ttlunits = lookold->ttlunits;
looknew->qr = lookold->qr;
+ looknew->idnin = lookold->idnin;
looknew->idnout = lookold->idnout;
looknew->udpsize = lookold->udpsize;
looknew->edns = lookold->edns;
@@ -1294,8 +1315,19 @@ setup_system(isc_boolean_t ipv4only, isc_boolean_t ipv6only) {
irs_resconf_destroy(&resconf);
-#ifdef WITH_IDN
- initialize_idn();
+#ifdef HAVE_SETLOCALE
+ /* Set locale */
+ (void)setlocale(LC_ALL, "");
+#endif
+
+#ifdef WITH_IDN_SUPPORT
+ idn_initialize();
+#endif
+
+#ifdef WITH_IDN_OUT_SUPPORT
+ /* Set domain name -> text post-conversion filter. */
+ result = dns_name_settotextfilter(output_filter);
+ check_result(result, "dns_name_settotextfilter");
#endif
if (keyfile[0] != 0)
@@ -2026,12 +2058,13 @@ setup_lookup(dig_lookup_t *lookup) {
char store[MXNAME];
char ecsbuf[20];
char cookiebuf[256];
-#ifdef WITH_IDN
- idn_result_t mr;
- char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
+ char *origin = NULL;
+ char *textname = NULL;
+#ifdef WITH_IDN_SUPPORT
+ char idn_origin[MXNAME], idn_textname[MXNAME];
#endif
-#ifdef WITH_IDN
+#ifdef WITH_IDN_OUT_SUPPORT
result = dns_name_settotextfilter(lookup->idnout ?
output_filter : NULL);
check_result(result, "dns_name_settotextfilter");
@@ -2064,15 +2097,20 @@ setup_lookup(dig_lookup_t *lookup) {
isc_buffer_init(&lookup->onamebuf, lookup->oname_space,
sizeof(lookup->oname_space));
-#ifdef WITH_IDN
/*
* We cannot convert `textname' and `origin' separately.
* `textname' doesn't contain TLD, but local mapping needs
* TLD.
*/
- mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
- utf8_textname, sizeof(utf8_textname));
- idn_check_result(mr, "convert textname to UTF-8");
+ textname = lookup->textname;
+#ifdef WITH_IDN_SUPPORT
+ if (lookup->idnin) {
+ result = idn_locale_to_ace(lookup->textname, idn_textname,
+ sizeof(idn_textname));
+ check_result(result, "convert textname to IDN encoding");
+ debug("idn_textname: %s", idn_textname);
+ textname = idn_textname;
+ }
#endif
/*
@@ -2083,8 +2121,8 @@ setup_lookup(dig_lookup_t *lookup) {
* is TRUE or we got a domain line in the resolv.conf file.
*/
if (lookup->new_search) {
-#ifdef WITH_IDN
- if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
+ if ((count_dots(textname) >= ndots) || !usesearch)
+ {
lookup->origin = NULL; /* Force abs lookup */
lookup->done_as_is = ISC_TRUE;
lookup->need_search = usesearch;
@@ -2092,33 +2130,8 @@ setup_lookup(dig_lookup_t *lookup) {
lookup->origin = ISC_LIST_HEAD(search_list);
lookup->need_search = ISC_FALSE;
}
-#else
- if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
- lookup->origin = NULL; /* Force abs lookup */
- lookup->done_as_is = ISC_TRUE;
- lookup->need_search = usesearch;
- } else if (lookup->origin == NULL && usesearch) {
- lookup->origin = ISC_LIST_HEAD(search_list);
- lookup->need_search = ISC_FALSE;
- }
-#endif
}
-#ifdef WITH_IDN
- if (lookup->origin != NULL) {
- mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
- lookup->origin->origin, utf8_origin,
- sizeof(utf8_origin));
- idn_check_result(mr, "convert origin to UTF-8");
- mr = append_textname(utf8_textname, utf8_origin,
- sizeof(utf8_textname));
- idn_check_result(mr, "append origin to textname");
- }
- mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
- IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
- idn_textname, sizeof(idn_textname));
- idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
-#else
if (lookup->origin != NULL) {
debug("trying origin %s", lookup->origin->origin);
result = dns_message_gettempname(lookup->sendmsg,
@@ -2126,8 +2139,18 @@ setup_lookup(dig_lookup_t *lookup) {
check_result(result, "dns_message_gettempname");
dns_name_init(lookup->oname, NULL);
/* XXX Helper funct to conv char* to name? */
- len = (unsigned int) strlen(lookup->origin->origin);
- isc_buffer_init(&b, lookup->origin->origin, len);
+ origin = lookup->origin->origin;
+#ifdef WITH_IDN_SUPPORT
+ if (lookup->idnin) {
+ result = idn_locale_to_ace(lookup->origin->origin,
+ idn_origin, sizeof(idn_origin));
+ check_result(result, "convert origin to IDN encoding");
+ debug("trying idn origin %s", idn_origin);
+ origin = idn_origin;
+ }
+#endif
+ len = (unsigned int) strlen(origin);
+ isc_buffer_init(&b, origin, len);
isc_buffer_add(&b, len);
result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
0, &lookup->onamebuf);
@@ -2137,7 +2160,7 @@ setup_lookup(dig_lookup_t *lookup) {
dns_message_puttempname(lookup->sendmsg,
&lookup->oname);
fatal("'%s' is not in legal name syntax (%s)",
- lookup->origin->origin,
+ origin,
isc_result_totext(result));
}
if (lookup->trace && lookup->trace_root) {
@@ -2148,8 +2171,8 @@ setup_lookup(dig_lookup_t *lookup) {
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
- len = (unsigned int) strlen(lookup->textname);
- isc_buffer_init(&b, lookup->textname, len);
+ len = (unsigned int) strlen(textname);
+ isc_buffer_init(&b, textname, len);
isc_buffer_add(&b, len);
result = dns_name_fromtext(name, &b, NULL, 0, NULL);
if (result == ISC_R_SUCCESS &&
@@ -2174,28 +2197,17 @@ setup_lookup(dig_lookup_t *lookup) {
}
}
dns_message_puttempname(lookup->sendmsg, &lookup->oname);
- } else
-#endif
- {
+ } else {
debug("using root origin");
if (lookup->trace && lookup->trace_root)
dns_name_clone(dns_rootname, lookup->name);
else {
-#ifdef WITH_IDN
- len = (unsigned int) strlen(idn_textname);
- isc_buffer_init(&b, idn_textname, len);
+ len = (unsigned int) strlen(textname);
+ isc_buffer_init(&b, textname, len);
isc_buffer_add(&b, len);
result = dns_name_fromtext(lookup->name, &b,
dns_rootname, 0,
&lookup->namebuf);
-#else
- len = (unsigned int) strlen(lookup->textname);
- isc_buffer_init(&b, lookup->textname, len);
- isc_buffer_add(&b, len);
- result = dns_name_fromtext(lookup->name, &b,
- dns_rootname, 0,
- &lookup->namebuf);
-#endif
}
if (result != ISC_R_SUCCESS) {
dns_message_puttempname(lookup->sendmsg,
@@ -4153,7 +4165,7 @@ cancel_all(void) {
*/
void
destroy_libs(void) {
-#ifdef WITH_IDN
+#ifdef WITH_IDN_SUPPORT
isc_result_t result;
#endif
@@ -4187,7 +4199,7 @@ destroy_libs(void) {
clear_searchlist();
-#ifdef WITH_IDN
+#ifdef WITH_IDN_SUPPORT
result = dns_name_settotextfilter(NULL);
check_result(result, "dns_name_settotextfilter");
#endif
@@ -4234,27 +4246,7 @@ destroy_libs(void) {
isc_mem_destroy(&mctx);
}
-#ifdef WITH_IDN
-static void
-initialize_idn(void) {
- idn_result_t r;
- isc_result_t result;
-
-#ifdef HAVE_SETLOCALE
- /* Set locale */
- (void)setlocale(LC_ALL, "");
-#endif
- /* Create configuration context. */
- r = idn_nameinit(1);
- if (r != idn_success)
- fatal("idn api initialization failed: %s",
- idn_result_tostring(r));
-
- /* Set domain name -> text post-conversion filter. */
- result = dns_name_settotextfilter(output_filter);
- check_result(result, "dns_name_settotextfilter");
-}
-
+#ifdef WITH_IDN_OUT_SUPPORT
static isc_result_t
output_filter(isc_buffer_t *buffer, unsigned int used_org,
isc_boolean_t absolute)
@@ -4262,6 +4254,7 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org,
char tmp1[MAXDLEN], tmp2[MAXDLEN];
size_t fromlen, tolen;
isc_boolean_t end_with_dot;
+ isc_result_t result;
/*
* Copy contents of 'buffer' to 'tmp1', supply trailing dot
@@ -4270,6 +4263,7 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org,
fromlen = isc_buffer_usedlength(buffer) - used_org;
if (fromlen >= MAXDLEN)
return (ISC_R_SUCCESS);
+
memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
if (absolute && !end_with_dot) {
@@ -4278,13 +4272,16 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org,
return (ISC_R_SUCCESS);
tmp1[fromlen - 1] = '.';
}
+
tmp1[fromlen] = '\0';
/*
* Convert contents of 'tmp1' to local encoding.
*/
- if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
+ result = idn_ace_to_locale(tmp1, tmp2, sizeof(tmp2));
+ if (result != ISC_R_SUCCESS) {
return (ISC_R_SUCCESS);
+ }
strlcpy(tmp1, tmp2, MAXDLEN);
/*
@@ -4304,32 +4301,115 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org,
return (ISC_R_SUCCESS);
}
+#endif
-static idn_result_t
-append_textname(char *name, const char *origin, size_t namesize) {
- size_t namelen = strlen(name);
- size_t originlen = strlen(origin);
-
- /* Already absolute? */
- if (namelen > 0 && name[namelen - 1] == '.')
- return (idn_success);
-
- /* Append dot and origin */
-
- if (namelen + 1 + originlen >= namesize)
- return (idn_buffer_overflow);
-
- if (*origin != '.')
- name[namelen++] = '.';
- (void)strlcpy(name + namelen, origin, namesize - namelen);
- return (idn_success);
+#ifdef WITH_IDN_SUPPORT
+#ifdef WITH_IDNKIT
+static void
+idnkit_check_result(idn_result_t result, const char *msg) {
+ if (result != idn_success) {
+ fatal("%s: %s", msg, idn_result_tostring(result));
+ }
}
static void
-idn_check_result(idn_result_t r, const char *msg) {
- if (r != idn_success) {
- exitcode = 1;
- fatal("%s: %s", msg, idn_result_tostring(r));
- }
+idn_initialize(void) {
+ idn_result_t result;
+
+ /* Create configuration context. */
+ result = idn_nameinit(1);
+ idnkit_check_result(result, "idnkit api initialization failed");
+ return (ISC_R_SUCCESS);
}
-#endif /* WITH_IDN */
+
+static isc_result_t
+idn_locale_to_ace(const char *from, char *to, size_t tolen) {
+ char utf8_textname[MXNAME];
+ idn_result_t result;
+
+ result = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, from,
+ utf8_textname, sizeof(utf8_textname));
+ idnkit_check_result(result, "idnkit idn_encodename to utf8 failed");
+
+ result = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
+ IDN_IDNCONV | IDN_LENCHECK,
+ utf8_textname, to, tolen);
+ idnkit_check_result(result, "idnkit idn_encodename to idn failed");
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+idn_ace_to_locale(const char *from, char *to, size_t tolen) {
+ idn_result_t result;
+
+ result = idn_decodename(IDN_DECODE_APP, from, to, tolen);
+ if (result != idn_success) {
+ debug("idnkit idn_decodename failed: %s",
+ idn_result_tostring(result));
+ return (ISC_R_FAILURE);
+ }
+ return (ISC_R_SUCCESS);
+}
+#endif /* WITH_IDNKIT */
+
+#ifdef WITH_LIBIDN2
+static void
+idn_initialize(void) {
+}
+
+static isc_result_t
+idn_locale_to_ace(const char *from, char *to, size_t tolen) {
+ int res;
+ char *tmp_str = NULL;
+
+ res = idn2_lookup_ul(from, &tmp_str, IDN2_NONTRANSITIONAL);
+ if (res == IDN2_DISALLOWED)
+ res = idn2_lookup_ul(from, &tmp_str, IDN2_TRANSITIONAL);
+
+ if (res == IDN2_OK) {
+ /* check the length */
+ if (strlen(tmp_str) >= tolen) {
+ debug("ACE string is too long");
+ idn2_free(tmp_str);
+ return ISC_R_NOSPACE;
+ }
+
+ (void) strlcpy(to, tmp_str, tolen);
+ idn2_free(tmp_str);
+ return ISC_R_SUCCESS;
+ }
+
+ fatal("idn2_lookup_ul failed: %s", idn2_strerror(res));
+ return ISC_R_FAILURE;
+}
+
+#ifdef WITH_IDN_OUT_SUPPORT
+static isc_result_t
+idn_ace_to_locale(const char *from, char *to, size_t tolen) {
+ int res;
+ char *tmp_str = NULL;
+
+ res = idn2_to_unicode_8zlz(from, &tmp_str,
+ IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT);
+
+ if (res == IDN2_OK) {
+ /* check the length */
+ if (strlen(tmp_str) >= tolen) {
+ debug("encoded ASC string is too long");
+ idn2_free(tmp_str);
+ return ISC_R_FAILURE;
+ }
+
+ (void) strncpy(to, tmp_str, tolen);
+ free(tmp_str);
+ return ISC_R_SUCCESS;
+ } else {
+ debug("idn2_to_unicode_8zlz failed: %s",
+ idn2_strerror(res));
+ }
+
+ return ISC_R_FAILURE;
+}
+#endif /* WITH_IDN_OUT_SUPPORT */
+#endif /* WITH_LIBIDN2 */
+#endif /* WITH_IDN_SUPPORT */
diff --git a/bin/dig/host.c b/bin/dig/host.c
index f27b839c7b..cbb548d2fc 100644
--- a/bin/dig/host.c
+++ b/bin/dig/host.c
@@ -19,7 +19,7 @@
#include
#endif
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
#include
#include
#include
@@ -721,7 +721,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
lookup->rdtype != dns_rdatatype_axfr)
lookup->rdtype = rdtype;
lookup->rdtypeset = ISC_TRUE;
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
idnoptions = 0;
#endif
if (rdtype == dns_rdatatype_axfr) {
@@ -736,7 +736,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
} else if (rdtype == dns_rdatatype_any) {
if (!lookup->tcp_mode_set)
lookup->tcp_mode = ISC_TRUE;
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
} else if (rdtype == dns_rdatatype_a ||
rdtype == dns_rdatatype_aaaa ||
rdtype == dns_rdatatype_mx) {
@@ -771,7 +771,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
if (!lookup->rdtypeset ||
lookup->rdtype != dns_rdatatype_axfr)
lookup->rdtype = dns_rdatatype_any;
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
idnoptions = 0;
#endif
list_type = dns_rdatatype_any;
@@ -885,7 +885,7 @@ main(int argc, char **argv) {
ISC_LIST_INIT(search_list);
fatalexit = 1;
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
idnoptions = IDN_ASCCHECK;
#endif
diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h
index 48fc8f14b5..b08e99f94b 100644
--- a/bin/dig/include/dig/dig.h
+++ b/bin/dig/include/dig/dig.h
@@ -129,6 +129,7 @@ struct dig_lookup {
use_usec,
nocrypto,
ttlunits,
+ idnin,
idnout,
qr;
char textname[MXNAME]; /*% Name we're going to be looking up */
@@ -268,7 +269,7 @@ extern char *progname;
extern int tries;
extern int fatalexit;
extern isc_boolean_t verbose;
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
extern int idnoptions;
#endif
diff --git a/config.h.in b/config.h.in
index 79eba6384e..52277996f9 100644
--- a/config.h.in
+++ b/config.h.in
@@ -597,7 +597,16 @@ int sigwait(const unsigned int *set, int *sig);
#undef WANT_QUERYTRACE
/* define if idnkit support is to be included. */
-#undef WITH_IDN
+#undef WITH_IDNKIT
+
+/* define if IDN output support is to be included. */
+#undef WITH_IDN_OUT_SUPPORT
+
+/* define if IDN input support is to be included. */
+#undef WITH_IDN_SUPPORT
+
+/* define if libidn2 support is to be included. */
+#undef WITH_LIBIDN2
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
diff --git a/configure b/configure
index 4073acba3b..5a64ba72bf 100755
--- a/configure
+++ b/configure
@@ -681,7 +681,9 @@ UNITTESTS
ATFLIBS
ATFBIN
ATFBUILD
-IDNLIBS
+LIBIDN2_LIBS
+LIBIDN2_CFLAGS
+IDNKIT_LIBS
XSLT_DBLATEX_FASTBOOK
XSLT_DBLATEX_STYLE
XSLT_DOCBOOK_MAKETOC_XHTML
@@ -942,7 +944,6 @@ infodir
docdir
oldincludedir
includedir
-runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -1041,10 +1042,11 @@ enable_dnstap
with_protobuf_c
with_libfstrm
with_docbook_xsl
-with_idn
+with_idnkit
with_libiconv
with_iconv
with_idnlib
+with_libidn2
with_atf
with_tuning
enable_querytrace
@@ -1107,7 +1109,6 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
-runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1360,15 +1361,6 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
- -runstatedir | --runstatedir | --runstatedi | --runstated \
- | --runstate | --runstat | --runsta | --runst | --runs \
- | --run | --ru | --r)
- ac_prev=runstatedir ;;
- -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
- | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
- | --run=* | --ru=* | --r=*)
- runstatedir=$ac_optarg ;;
-
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1506,7 +1498,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir runstatedir
+ libdir localedir mandir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -1659,7 +1651,6 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -1786,10 +1777,11 @@ Optional Packages:
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
--with-libfstrm=path Path where libfstrm is installed, for dnstap
--with-docbook-xsl=PATH specify path for Docbook-XSL stylesheets
- --with-idn=MPREFIX enable IDN support using idnkit [default PREFIX]
+ --with-idnkit=PATH enable IDN support using idnkit [yes|no|path]
--with-libiconv=IPREFIX GNU libiconv are in IPREFIX [default PREFIX]
--with-iconv=LIBSPEC specify iconv library [default -liconv]
--with-idnlib=ARG specify libidnkit
+ --with-libidn2=PATH enable IDN support using GNU libidn2 [yes|no|path]
--with-atf support Automated Test Framework
--with-tuning=ARG Specify server tuning (large or default)
--with-dlopen=ARG support dynamically loadable DLZ drivers
@@ -22552,28 +22544,28 @@ fi
#
-# IDN support
+# IDN support using idnkit
#
-# Check whether --with-idn was given.
-if test "${with_idn+set}" = set; then :
- withval=$with_idn; use_idn="$withval"
+# Check whether --with-idnkit was given.
+if test "${with_idnkit+set}" = set; then :
+ withval=$with_idnkit; use_idnkit="$withval"
else
- use_idn="no"
+ use_idnkit="no"
fi
-case "$use_idn" in
+case "$use_idnkit" in
yes)
if test X$prefix = XNONE ; then
- idn_path=/usr/local
+ idnkit_path=/usr/local
else
- idn_path=$prefix
+ idnkit_path=$prefix
fi
;;
no)
;;
*)
- idn_path="$use_idn"
+ idnkit_path="$use_idnkit"
;;
esac
@@ -22630,20 +22622,161 @@ if test "yes" = "$idnlib"; then
as_fn_error $? "You must specify ARG for --with-idnlib." "$LINENO" 5
fi
-IDNLIBS=
-if test "no" != "$use_idn"; then
+IDNKIT_LIBS=
+if test "no" != "$use_idnkit"; then
-$as_echo "#define WITH_IDN 1" >>confdefs.h
+$as_echo "#define WITH_IDNKIT 1" >>confdefs.h
- STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include"
+ STD_CINCLUDES="$STD_CINCLUDES -I$idnkit_path/include"
if test "no" != "$idnlib"; then
- IDNLIBS="$idnlib $iconvlib"
+ IDNKIT_LIBS="$idnlib $iconvlib"
else
- IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib"
+ IDNKIT_LIBS="-L$idnkit_path/lib -lidnkit $iconvlib"
fi
fi
+#
+# IDN support using libidn2
+#
+
+LIBIDN2_CFLAGS=
+LIBIDN2_LIBS=
+
+# Check whether --with-libidn2 was given.
+if test "${with_libidn2+set}" = set; then :
+ withval=$with_libidn2; use_libidn2="$withval"
+else
+ use_libidn2="no"
+fi
+
+case $use_libidn2 in #(
+ no) :
+ : ;; #(
+ yes) :
+
+ LIBIDN2_LIBS="-lidn2"
+ ;; #(
+ *) :
+
+ LIBIDN2_CFLAGS="-I$use_libidn2/include"
+ LIBIDN2_LIBS="-L$use_libidn2/lib -lidn2"
+ ;; #(
+ *) :
+ ;;
+esac
+
+if test "$use_libidn2" != "no"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing idn2_to_ascii_8z" >&5
+$as_echo_n "checking for library containing idn2_to_ascii_8z... " >&6; }
+if ${ac_cv_search_idn2_to_ascii_8z+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char idn2_to_ascii_8z ();
+int
+main ()
+{
+return idn2_to_ascii_8z ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' idn2; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_idn2_to_ascii_8z=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_idn2_to_ascii_8z+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_idn2_to_ascii_8z+:} false; then :
+
+else
+ ac_cv_search_idn2_to_ascii_8z=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_idn2_to_ascii_8z" >&5
+$as_echo "$ac_cv_search_idn2_to_ascii_8z" >&6; }
+ac_res=$ac_cv_search_idn2_to_ascii_8z
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define WITH_LIBIDN2 1" >>confdefs.h
+
+else
+ as_fn_error $? "libidn2 requested, but not found" "$LINENO" 5
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libidn2 supports idn2_to_unicode_8zlz" >&5
+$as_echo_n "checking whether libidn2 supports idn2_to_unicode_8zlz... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+int
+main ()
+{
+idn2_to_unicode_8zlz(".", NULL, IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define WITH_IDN_OUT_SUPPORT 1" >>confdefs.h
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+
+#
+# IDN support in general
+#
+
+# check if idnkit and libidn2 are not used at the same time
+if test "$use_idnkit" != no && test "$use_libidn2" != no; then
+ as_fn_error $? "idnkit and libidn2 cannot be used at the same time." "$LINENO" 5
+fi
+# the IDN support is on
+if test "$use_idnkit" != no || test "$use_libidn2" != no; then
+
+$as_echo "#define WITH_IDN_SUPPORT 1" >>confdefs.h
+
+ if test "$use_libidn2" = no || test "$use_libidn2_out" != no; then
+
+$as_echo "#define WITH_IDN_OUT_SUPPORT 1" >>confdefs.h
+
+ fi
+fi
+
#
# Check whether to build Automated Test Framework unit tests
#
diff --git a/configure.in b/configure.in
index f2acb659fb..a4fa556243 100644
--- a/configure.in
+++ b/configure.in
@@ -4698,24 +4698,24 @@ NOM_PATH_FILE(XSLT_DBLATEX_STYLE, xsl/docbook.xsl, $dblatex_xsl_trees)
NOM_PATH_FILE(XSLT_DBLATEX_FASTBOOK, xsl/latex_book_fast.xsl, $dblatex_xsl_trees)
#
-# IDN support
+# IDN support using idnkit
#
-AC_ARG_WITH(idn,
- AS_HELP_STRING([--with-idn[=MPREFIX]],
- [enable IDN support using idnkit [default PREFIX]]),
- use_idn="$withval", use_idn="no")
-case "$use_idn" in
+AC_ARG_WITH(idnkit,
+ AS_HELP_STRING([--with-idnkit[=PATH]],
+ [enable IDN support using idnkit [yes|no|path]]),
+ use_idnkit="$withval", use_idnkit="no")
+case "$use_idnkit" in
yes)
if test X$prefix = XNONE ; then
- idn_path=/usr/local
+ idnkit_path=/usr/local
else
- idn_path=$prefix
+ idnkit_path=$prefix
fi
;;
no)
;;
*)
- idn_path="$use_idn"
+ idnkit_path="$use_idnkit"
;;
esac
@@ -4761,17 +4761,66 @@ if test "yes" = "$idnlib"; then
AC_MSG_ERROR([You must specify ARG for --with-idnlib.])
fi
-IDNLIBS=
-if test "no" != "$use_idn"; then
- AC_DEFINE(WITH_IDN, 1, [define if idnkit support is to be included.])
- STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include"
+IDNKIT_LIBS=
+if test "no" != "$use_idnkit"; then
+ AC_DEFINE(WITH_IDNKIT, 1, [define if idnkit support is to be included.])
+ STD_CINCLUDES="$STD_CINCLUDES -I$idnkit_path/include"
if test "no" != "$idnlib"; then
- IDNLIBS="$idnlib $iconvlib"
+ IDNKIT_LIBS="$idnlib $iconvlib"
else
- IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib"
+ IDNKIT_LIBS="-L$idnkit_path/lib -lidnkit $iconvlib"
+ fi
+fi
+AC_SUBST(IDNKIT_LIBS)
+
+#
+# IDN support using libidn2
+#
+
+LIBIDN2_CFLAGS=
+LIBIDN2_LIBS=
+AC_ARG_WITH(libidn2,
+ AS_HELP_STRING([--with-libidn2[=PATH]], [enable IDN support using GNU libidn2 [yes|no|path]]),
+ use_libidn2="$withval", use_libidn2="no")
+AS_CASE([$use_libidn2],
+ [no],[:],
+ [yes],[
+ LIBIDN2_LIBS="-lidn2"
+ ],
+ [*],[
+ LIBIDN2_CFLAGS="-I$use_libidn2/include"
+ LIBIDN2_LIBS="-L$use_libidn2/lib -lidn2"
+ ])
+
+AS_IF([test "$use_libidn2" != "no"],
+ [AC_SEARCH_LIBS([idn2_to_ascii_8z], [idn2],
+ [AC_DEFINE(WITH_LIBIDN2, 1, [define if libidn2 support is to be included.])],
+ [AC_MSG_ERROR([libidn2 requested, but not found])])
+ AC_MSG_CHECKING(whether libidn2 supports idn2_to_unicode_8zlz)
+ AC_TRY_LINK([#include ],
+ [idn2_to_unicode_8zlz(".", NULL, IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT);],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE(WITH_IDN_OUT_SUPPORT, 1, [define if IDN output support is to be included.])],
+ [AC_MSG_RESULT([no])])
+ ])
+AC_SUBST([LIBIDN2_CFLAGS])
+AC_SUBST([LIBIDN2_LIBS])
+
+#
+# IDN support in general
+#
+
+# check if idnkit and libidn2 are not used at the same time
+if test "$use_idnkit" != no && test "$use_libidn2" != no; then
+ AC_MSG_ERROR([idnkit and libidn2 cannot be used at the same time.])
+fi
+# the IDN support is on
+if test "$use_idnkit" != no || test "$use_libidn2" != no; then
+ AC_DEFINE(WITH_IDN_SUPPORT, 1, [define if IDN input support is to be included.])
+ if test "$use_libidn2" = no || test "$use_libidn2_out" != no; then
+ AC_DEFINE(WITH_IDN_OUT_SUPPORT, 1, [define if IDN output support is to be included.])
fi
fi
-AC_SUBST(IDNLIBS)
#
# Check whether to build Automated Test Framework unit tests
diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml
index 599a29148b..453fa814fa 100644
--- a/doc/arm/notes.xml
+++ b/doc/arm/notes.xml
@@ -66,7 +66,9 @@
- None.
+ BIND now can be compiled against libidn2 library to add
+ IDNA2008 support. Previously BIND only supported IDNA2003
+ using (now obsolete) idnkit-1 library.
@@ -120,6 +122,13 @@
that have timed out, in addition to those that respond. [GL #64]
+
+
+ dig +noidnin can be used to disable IDN
+ processing on the input domain name, when BIND is compiled
+ with IDN support.
+
+