0N/AIDN patch for bind-9.2.2
0N/AThis is a patch file for ISC BIND 9.2.2 to make it work with
0N/Ainternationalized domain names. With this patch you'll get IDN-aware
0N/ATo apply this patch, you should go to the top directory of the BIND
0N/Adistribution (where you see `README' file), then invoke `patch'
0N/A % patch -p0 < this-file
0N/A+ Japan Network Information Center (JPNIC)
0N/A+ * What is this patch for?
0N/A+ This patch adds internationalized domain name (IDN) support to BIND-9.
0N/A+ codeset (such as Shift JIS, Big5 or ISO8859-1) determined by
0N/A+ the locale information. The domain names are normalized and
0N/A+ converted to the encoding on the DNS protocol, and sent to DNS
0N/A+ servers. The replies are converted back to the local codeset
0N/A+ * Compilation & installation
0N/A+ You have to build and install idnkit before building this patched version
0N/A+ 1. Running configure script
0N/A+ Run `configure' in the top directory. See `README' for the
0N/A+ configuration options.
0N/A+ This patch adds the following 4 options to `configure'. You should
0N/A+ at least specify `--with-idn' option to enable IDN support.
0N/A+ --with-idn[=IDN_PREFIX]
0N/A+ To enable IDN support, you have to specify `--with-idn' option.
0N/A+ The argument IDN_PREFIX is the install prefix of idnkit. If
0N/A+ IDN_PREFIX is omitted, PREFIX (derived from `--prefix=PREFIX')
0N/A+ --with-libiconv[=LIBICONV_PREFIX]
0N/A+ Specify this option if idnkit you have installed links GNU
0N/A+ libiconv. The argument LIBICONV_PREFIX is install prefix of
0N/A+ GNU libiconv. If the argument is omitted, PREFIX (derived
0N/A+ from `--prefix=PREFIX') is assumed.
0N/A+ `--with-libiconv' is shorthand option for GNU libiconv.
0N/A+ This is equivalent to:
0N/A+ `--with-libiconv' assumes that your C compiler has `-R'
0N/A+ option, and that the option adds the specified run-time path
0N/A+ to an exacutable binary. If `-R' option of your compiler has
0N/A+ different meaning, or your compiler lacks the option, you
0N/A+ should use `--with-iconv' option instead. Binary command
0N/A+ without run-time path information might be unexecutable.
0N/A+ In that case, you would see an error message like:
0N/A+ open shared object file
0N/A+ If both `--with-libiconv' and `--with-iconv' options are
0N/A+ specified, `--with-iconv' is prior to `--with-libiconv'.
0N/A+ --with-iconv=ICONV_LIBSPEC
0N/A+ If your libc doens't provide iconv(), you need to specify the
0N/A+ library containing iconv() with this option. `ICONV_LIBSPEC'
0N/A+ is the argument(s) to `cc' or `ld' to link the library, for
0N/A+ You don't need to specify the header file directory for "
iconv.h"
0N/A+ to the compiler, as it isn't included directly by bind-9 with
0N/A+ --with-idnlib=IDN_LIBSPEC
0N/A+ With this option, you can explicitly specify the argument(s)
+ to `cc' or `ld' to link the idnkit's library, `libidnkit'. If
+ this option is not specified, `-L${PREFIX}/lib -lidnkit' is
+ assumed, where ${PREFIX} is the installation prefix specified
+ with `--with-idn' option above. You may need to use this
+ option to specify extra argments, for example,
+ Please consult `README' for other configuration options.
+ Note that if you want to specify some extra header file directories,
+ you should use the environment variable STD_CINCLUDES instead of
+ CFLAGS, as described in README.
+ 2. Compilation and installation
+ After running "configure", just do
+ for compiling and installing.
+ about idnkit and this patch.
+ Bug reports and comments on this kit should be sent to
+ mdnkit-bugs@nic.ad.jp and idn-cmt@nic.ad.jp, respectively.
+ ; $Id: bind-9.2.2-patch,v 1.1 2003/06/04 00:27:32 marka Exp $
/* define if you have strerror in the C library. */
+ /* Define if you have the setlocale function. */
/* Define if you have the <
dlfcn.h> header file. */
#undef HAVE_LINUX_CAPABILITY_H
+ /* Define if you have the <
locale.h> header file. */
/* Define if you have the <
sys/prctl.h> header file. */
/* Define if you have the socket library (-lsocket). */
+ /* define if idnkit support is to be included. */
*** configure Wed Mar 5 17:14:55 2003
--- configure Thu Mar 6 20:10:05 2003
--with-gnu-ld assume the C compiler uses GNU ld default=no
--with-pic try to use only
PIC/non-PIC objects default=use both
+ --with-idn=MPREFIX enable IDN support using idnkit default PREFIX
+ --with-libiconv=IPREFIX GNU libiconv are in IPREFIX default PREFIX
+ --with-iconv=LIBSPEC specify iconv library default -liconv
+ --with-idnlib=ARG specify libidnkit
Some influential environment variables:
# Find out which ABI we are using.
! echo '#line 7374 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
# Find out which ABI we are using.
! echo '#line 7378 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
cat > conftest.$ac_ext <<EOF
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
cat > conftest.$ac_ext <<EOF
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
cat > conftest.$ac_ext <<EOF
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
cat > conftest.$ac_ext <<EOF
+ # Check whether --with-idn or --without-idn was given.
+ if test "${with_idn+set}" = set; then
+ if test X$prefix = XNONE ; then
+ # Check whether --with-libiconv or --without-libiconv was given.
+ if test "${with_libiconv+set}" = set; then
+ withval="$with_libiconv"
+ use_libiconv="$withval"
+ case "$use_libiconv" in
+ if test X$prefix = XNONE ; then
+ # Check whether --with-iconv or --without-iconv was given.
+ if test "${with_iconv+set}" = set; then
+ # Check whether --with-idnlib or --without-idnlib was given.
+ if test "${with_idnlib+set}" = set; then
+ if test "$idnlib" = yes; then
+ { { echo "$as_me:$LINENO: error: You must specify ARG for --with-idnlib." >&5
+ echo "$as_me: error: You must specify ARG for --with-idnlib." >&2;}
+ { (exit 1); exit 1; }; }
+ if test "$use_idn" != no; then
+ if test "$idnlib" != no; then
+ IDNLIBS="$idnlib $iconvlib"
+ as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+ echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+ if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+ echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+ # Is the header compilable?
+ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+ echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -f conftest.$ac_objext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+ echo "${ECHO_T}$ac_header_compiler" >&6
+ # Is the header present?
+ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+ echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ if test -z "$ac_cpp_err"; then
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+ echo "${ECHO_T}$ac_header_preproc" >&6
+ # So? What about this header?
+ case $ac_header_compiler:$ac_header_preproc in
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+ echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+ echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+ echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+ echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+ if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ eval "$as_ac_Header=$ac_header_preproc"
+ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+ echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+ if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+ for ac_func in setlocale
+ as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ echo "$as_me:$LINENO: checking for $ac_func" >&5
+ echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+ if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ /* From autoconf 2.57 */
+ /* Define $ac_func to an innocuous variant, in case <
limits.h> declares $ac_func.
+ For example, HP-UX 11i <
limits.h> declares gettimeofday. */
+ #define $ac_func innocuous_$ac_func
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ <
limits.h> exists even on freestanding compilers. */
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+ /* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+ #if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+ char (*f) () = $ac_func;
+ int F77_DUMMY_MAIN() { return 1; }
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+ echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+ if test `eval echo '${'$as_ac_var'}'` = yes; then
+ #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
s,@PRINTSTYLE@,$PRINTSTYLE,;t t
s,@DOCBOOK2MANSPEC@,$DOCBOOK2MANSPEC,;t t
+ s,@IDNLIBS@,$IDNLIBS,;t t
s,@BIND9_TOP_BUILDDIR@,$BIND9_TOP_BUILDDIR,;t t
s,@BIND9_ISC_BUILDINCLUDE@,$BIND9_ISC_BUILDINCLUDE,;t t
s,@BIND9_ISCCC_BUILDINCLUDE@,$BIND9_ISCCC_BUILDINCLUDE,;t t
+ [ --with-idn[=MPREFIX] enable IDN support using idnkit [default PREFIX]],
+ use_idn="$withval", use_idn="no")
+ if test X$prefix = XNONE ; then
+ [ --with-libiconv[=IPREFIX] GNU libiconv are in IPREFIX [default PREFIX]],
+ use_libiconv="$withval", use_libiconv="no")
+ case "$use_libiconv" in
+ if test X$prefix = XNONE ; then
+ [ --with-iconv[=LIBSPEC] specify iconv library [default -liconv]],
+ [ --with-idnlib=ARG specify libidnkit],
+ idnlib="$withval", idnlib="no")
+ if test "$idnlib" = yes; then
+ AC_MSG_ERROR([You must specify ARG for --with-idnlib.])
+ if test "$use_idn" != no; then
+ AC_DEFINE(WITH_IDN, 1, [define if idnkit support is to be included.])
+ if test "$idnlib" != no; then
+ IDNLIBS="$idnlib $iconvlib"
+ AC_CHECK_FUNCS(setlocale)
AC_SUBST(BIND9_TOP_BUILDDIR)
DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
! LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
! LIBS = ${DNSLIBS} ${ISCLIBS} @IDNLIBS@ @LIBS@
\fI+noqr\fR which means that \fBdig\fR
will not print the initial query when it looks up the NS records for
+ If \fBdig\fR has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ \fBdig\fR appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ If you'd like to turn off the IDN support for some reason, defines
+ the \fBIDN_DISABLE\fR environment variable.
+ The IDN support is disabled if the the variable is set when
+ <title>IDN SUPPORT</title>
+ If <command>dig</command> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <command>dig</command> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ If you'd like to turn off the IDN support for some reason, defines
+ the <envar>IDN_DISABLE</envar> environment variable.
+ The IDN support is disabled if the the variable is set when
+ <command>dig</command> runs.
dig_lookup_t *current_lookup = NULL;
+ static void initialize_idn(void);
+ static isc_result_t output_filter(isc_buffer_t *buffer,
+ isc_boolean_t absolute);
+ static idn_result_t append_textname(char *name, const char *origin,
+ static void idn_check_result(idn_result_t r, const char *msg);
* Apply and clear locks at the event level in global task.
* Can I get rid of these using shutdown events? XXX
ISC_LIST_APPEND(server_list, srv, link);
else if (keysecret[0] != 0)
+ char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
+ dns_name_settotextfilter(output_filter);
isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
sizeof(lookup->onamespace));
+ * We cannot convert `textname' and `origin' separately.
+ * `textname' doesn't contain TLD, but local mapping needs
+ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
+ utf8_textname, sizeof(utf8_textname));
+ idn_check_result(mr, "convert textname to UTF-8");
* If the name has too many dots, force the origin to be NULL
* (which produces an absolute lookup). Otherwise, take the origin
* is TRUE or we got a domain line in the
resolv.conf file.
/* XXX New search here? */
+ if ((count_dots(utf8_textname) >= ndots) || !usesearch)
+ lookup->origin = NULL; /* Force abs lookup */
+ else if (lookup->origin == NULL && lookup->new_search && usesearch) {
+ lookup->origin = ISC_LIST_HEAD(search_list);
if ((count_dots(lookup->textname) >= ndots) || !usesearch)
lookup->origin = NULL; /* Force abs lookup */
else if (lookup->origin == NULL && lookup->new_search && usesearch) {
lookup->origin = ISC_LIST_HEAD(search_list);
if (lookup->origin != NULL) {
+ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
+ lookup->origin->origin, 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(IDN_LOCALMAP | IDN_NAMEPREP | IDN_ASCCHECK |
+ IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
+ idn_textname, sizeof(idn_textname));
+ idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
+ if (lookup->origin != NULL) {
debug("trying origin %s", lookup->origin->origin);
result = dns_message_gettempname(lookup->sendmsg,
if (lookup->trace && lookup->trace_root)
dns_name_clone(dns_rootname, lookup->name);
+ len = strlen(idn_textname);
+ isc_buffer_init(&b, idn_textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->name, &b,
len = strlen(lookup->textname);
isc_buffer_init(&b, lookup->textname, len);
if (result != ISC_R_SUCCESS) {
dns_message_puttempname(lookup->sendmsg,
+ (void)setlocale(LC_ALL, "");
+ /* Create configuration context. */
+ fatal("idn api initialization failed: %s",
+ idn_result_tostring(r));
+ /* Set domain name -> text post-conversion filter. */
+ dns_name_settotextfilter(output_filter);
+ output_filter(isc_buffer_t *buffer, unsigned int used_org,
+ isc_boolean_t absolute)
+ char tmp1[MAXDLEN], tmp2[MAXDLEN];
+ isc_boolean_t end_with_dot;
+ * Copy contents of 'buffer' to 'tmp1', supply trailing dot
+ * if 'absolute' is true, and terminate with NUL.
+ fromlen = isc_buffer_usedlength(buffer) - used_org;
+ if (fromlen >= MAXDLEN)
+ return (ISC_R_SUCCESS);
+ memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
+ end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
+ if (absolute && !end_with_dot) {
+ if (fromlen >= MAXDLEN)
+ return (ISC_R_SUCCESS);
+ tmp1[fromlen - 1] = '.';
+ * Convert contents of 'tmp1' to local encoding.
+ if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
+ return (ISC_R_SUCCESS);
+ * Copy the converted contents in 'tmp1' back to 'buffer'.
+ * If we have appended trailing dot, remove it.
+ if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
+ if (isc_buffer_length(buffer) < used_org + tolen)
+ return (ISC_R_NOSPACE);
+ isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
+ memcpy(isc_buffer_used(buffer), tmp1, tolen);
+ isc_buffer_add(buffer, tolen);
+ return (ISC_R_SUCCESS);
+ 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] == '.')
+ /* Append dot and origin */
+ if (namelen + 1 + originlen >= namesize)
+ return idn_buffer_overflow;
+ (void)strcpy(name + namelen, origin);
+ idn_check_result(idn_result_t r, const char *msg) {
+ if (r != idn_success) {
+ fatal("%s: %s", msg, idn_result_tostring(r));
effectively wait forever for a reply. The time to wait for a response
will be set to the number of seconds given by the hardware's maximum
value for an integer quantity.
+ If \fBhost\fR has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ \fBhost\fR appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ If you'd like to turn off the IDN support for some reason, defines
+ the \fBIDN_DISABLE\fR environment variable.
+ The IDN support is disabled if the the variable is set when
+ <title>IDN SUPPORT</title>
+ If <command>host</command> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <command>host</command> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ If you'd like to turn off the IDN support for some reason, defines
+ the <envar>IDN_DISABLE</envar> environment variable.
+ The IDN support is disabled if the the variable is set when
+ <command>host</command> runs.
dns_name_t *dns_wildcardname = &wild;
+ * dns_name_t to text post-conversion procedure.
+ static dns_name_totextfilter_t totext_filter_proc = NULL;
set_offsets(const dns_name_t *name, unsigned char *offsets,
isc_boolean_t saw_root = ISC_FALSE;
+ unsigned int oused = target->used;
* This function assumes the name is in proper uncompressed
isc_buffer_add(target, tlen - trem);
+ if (totext_filter_proc != NULL)
+ return ((*totext_filter_proc)(target, oused, saw_root));
+ dns_name_settotextfilter(dns_name_totextfilter_t proc) {
+ totext_filter_proc = proc;
#define DNS_NAME_MAXWIRE 255
+ * Text output filter procedure.
+ * 'target' is the buffer to be converted. The region to be converted
+ * is from 'buffer'->base + 'used_org' to the end of the used region.
+ typedef isc_result_t (*dns_name_totextfilter_t)(isc_buffer_t *target,
+ isc_boolean_t absolute);
+ dns_name_settotextfilter(dns_name_totextfilter_t proc);
+ * Call 'proc' at the end of dns_name_totext.
#define DNS_NAME_FORMATSIZE (DNS_NAME_MAXTEXT + 1)