release v0.1.8

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJVNB2sAAoJEOX4+CEvd6SYQVkP/1AgRoUw+5BM6gm+z5J4heXg
 W9EpICfKn2BTC8JVwVOzA3LHJZ95tosNv+fy0faK0n7jByvT4ySl4V/k2W9JSd/S
 bhDR5A1zyfYJdLTDONdkwXki9H90MW69lRGfh+zb0VHzFwi/10xQqYlUatF0IxY3
 Vg4L0PBaUC4UsQevjJNxDJQkr4Q5hJph9jLyij7Zfty/rqjDIZoQpZgMeoZIr9xI
 v51lnlG0ss6lnSRUkM1Nta3mFsXhTDNAhe8/pPUP+lWXceXqCWK63vJGf6Lp3LN4
 gw/COsGnQdiUIbfRGWWGXuqG4c52SAK+ZE9D01bOeLJHw2S8IuA8oFvXdwfGcvYQ
 /gax26lguWk4IrgWIHTRalZJbn+mTNG/DXqrpOuw+BWp3prdoJmyvtOc0rLX1OB2
 ueDDphPg/kSiSknnMmrUgHC2elWewsZCFhx5Umy149ONQK85AQ08DAtJP5dHsXzi
 Om/wuvbuzhoHtPV9YZZYcTa6uSVWaMLHLVJ5K9ifTJEvIKk4pVwbsFS5XIZAVEig
 yGmSsngTQP4w3LdFZSCk3FRu0D+y60sG++Gs1X2X+TsLP/6ZoOL0lYEkPwGfHsvL
 dhgG+iNUgSKmLwrpyI7c1DD1ZlpZluomjQQ5evfogHOmZC22AJvuNQI6hJY1pvXQ
 AU+pzxUfo8947+nEJxMR
 =qFXQ
 -----END PGP SIGNATURE-----

Merge tag 'v0.1.8'

release v0.1.8
This commit is contained in:
Willem Toorop 2015-04-19 23:28:49 +02:00
commit 29b378ab16
16 changed files with 691 additions and 112 deletions

View File

@ -1,3 +1,8 @@
* 2015-04-19: Version 0.1.8
* The GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN and
GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN
DNS over TLS transport options.
* 2015-04-08: Version 0.1.7 * 2015-04-08: Version 0.1.7
* Individual getter functions for context settings * Individual getter functions for context settings
* Fix: --with-current-date function to make build deterministically * Fix: --with-current-date function to make build deterministically

74
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for getdns 0.1.7. # Generated by GNU Autoconf 2.69 for getdns 0.1.8.
# #
# Report bugs to <stub-resolver@verisignlabs.com>. # Report bugs to <stub-resolver@verisignlabs.com>.
# #
@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='getdns' PACKAGE_NAME='getdns'
PACKAGE_TARNAME='getdns' PACKAGE_TARNAME='getdns'
PACKAGE_VERSION='0.1.7' PACKAGE_VERSION='0.1.8'
PACKAGE_STRING='getdns 0.1.7' PACKAGE_STRING='getdns 0.1.8'
PACKAGE_BUGREPORT='stub-resolver@verisignlabs.com' PACKAGE_BUGREPORT='stub-resolver@verisignlabs.com'
PACKAGE_URL='http://getdnsapi.net' PACKAGE_URL='http://getdnsapi.net'
@ -1323,7 +1323,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures getdns 0.1.7 to adapt to many kinds of systems. \`configure' configures getdns 0.1.8 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1388,7 +1388,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of getdns 0.1.7:";; short | recursive ) echo "Configuration of getdns 0.1.8:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1519,7 +1519,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
getdns configure 0.1.7 getdns configure 0.1.8
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@ -2008,7 +2008,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by getdns $as_me 0.1.7, which was It was created by getdns $as_me 0.1.8, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -2367,7 +2367,7 @@ else
CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`" CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"
fi fi
GETDNS_COMPILATION_COMMENT="getdns 0.1.7 configured on $CURRENT_DATE for the January 2015 version of the API" GETDNS_COMPILATION_COMMENT="getdns 0.1.8 configured on $CURRENT_DATE for the January 2015 version of the API"
# Library version # Library version
# --------------- # ---------------
@ -2387,9 +2387,10 @@ GETDNS_COMPILATION_COMMENT="getdns 0.1.7 configured on $CURRENT_DATE for the Jan
# getdns-0.1.4 had libversion 0:0:0 # getdns-0.1.4 had libversion 0:0:0
# getdns-0.1.5 had libversion 1:0:0 # getdns-0.1.5 had libversion 1:0:0
# getdns-0.1.6 had libversion 1:1:0 # getdns-0.1.6 had libversion 1:1:0
# getdns-0.1.7 will have libversion 1:2:1 # getdns-0.1.7 had libversion 1:2:1
# getdns-0.1.8 will have libversion 1:3:0
# #
GETDNS_LIBVERSION=1:2:1 GETDNS_LIBVERSION=1:3:0
@ -11333,8 +11334,8 @@ $as_echo "found in $ssldir" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_CTX_init in -lcrypto" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_CTX_init in -lcrypto" >&5
$as_echo_n "checking for HMAC_CTX_init in -lcrypto... " >&6; } $as_echo_n "checking for HMAC_CTX_init in -lcrypto... " >&6; }
LIBS="$LIBS -lcrypto" LIBS="$LIBS -lcrypto -lssl"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto -lssl"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
@ -11543,6 +11544,51 @@ fi
done done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLSv1_2_client_method in -lssl" >&5
$as_echo_n "checking for TLSv1_2_client_method in -lssl... " >&6; }
if ${ac_cv_lib_ssl_TLSv1_2_client_method+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lssl $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 TLSv1_2_client_method ();
int
main ()
{
return TLSv1_2_client_method ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_ssl_TLSv1_2_client_method=yes
else
ac_cv_lib_ssl_TLSv1_2_client_method=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_TLSv1_2_client_method" >&5
$as_echo "$ac_cv_lib_ssl_TLSv1_2_client_method" >&6; }
if test "x$ac_cv_lib_ssl_TLSv1_2_client_method" = xyes; then :
$as_echo "#define HAVE_LIBTLS1_2 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find TLSv1_2_client_method in libssl library. TLS will not be available." >&5
$as_echo "$as_me: WARNING: Cannot find TLSv1_2_client_method in libssl library. TLS will not be available." >&2;}
fi
@ -14277,7 +14323,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by getdns $as_me 0.1.7, which was This file was extended by getdns $as_me 0.1.8, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -14344,7 +14390,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
getdns config.status 0.1.7 getdns config.status 0.1.8
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@ -31,7 +31,7 @@
AC_PREREQ([2.56]) AC_PREREQ([2.56])
AC_INIT([getdns], [0.1.7], [stub-resolver@verisignlabs.com], [], [http://getdnsapi.net]) AC_INIT([getdns], [0.1.8], [stub-resolver@verisignlabs.com], [], [http://getdnsapi.net])
AC_SUBST(RELEASE_CANDIDATE, []) AC_SUBST(RELEASE_CANDIDATE, [])
# Set current date from system if not set # Set current date from system if not set
@ -60,9 +60,10 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_STRING configured on $CURRENT_DATE for th
# getdns-0.1.4 had libversion 0:0:0 # getdns-0.1.4 had libversion 0:0:0
# getdns-0.1.5 had libversion 1:0:0 # getdns-0.1.5 had libversion 1:0:0
# getdns-0.1.6 had libversion 1:1:0 # getdns-0.1.6 had libversion 1:1:0
# getdns-0.1.7 will have libversion 1:2:1 # getdns-0.1.7 had libversion 1:2:1
# getdns-0.1.8 will have libversion 1:3:0
# #
GETDNS_LIBVERSION=1:2:1 GETDNS_LIBVERSION=1:3:0
AC_SUBST(GETDNS_COMPILATION_COMMENT) AC_SUBST(GETDNS_COMPILATION_COMMENT)
AC_SUBST(GETDNS_LIBVERSION) AC_SUBST(GETDNS_LIBVERSION)
@ -741,6 +742,10 @@ unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest);
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#endif
#ifdef HAVE_ATTR_FORMAT #ifdef HAVE_ATTR_FORMAT
# define ATTR_FORMAT(archetype, string_index, first_to_check) \ # define ATTR_FORMAT(archetype, string_index, first_to_check) \
__attribute__ ((format (archetype, string_index, first_to_check))) __attribute__ ((format (archetype, string_index, first_to_check)))

View File

@ -48,8 +48,8 @@ AC_DEFUN([ACX_SSL_CHECKS], [
fi fi
AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto]) AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
LIBS="$LIBS -lcrypto" LIBS="$LIBS -lcrypto -lssl"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto -lssl"
AC_TRY_LINK(, [ AC_TRY_LINK(, [
int HMAC_CTX_init(void); int HMAC_CTX_init(void);
(void)HMAC_CTX_init(); (void)HMAC_CTX_init();
@ -105,6 +105,8 @@ AC_DEFUN([ACX_SSL_CHECKS], [
AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_LIB(ssl, TLSv1_2_client_method,AC_DEFINE([HAVE_LIBTLS1_2], [1],
[Define if you have libssl with tls 1.2]),[AC_MSG_WARN([Cannot find TLSv1_2_client_method in libssl library. TLS will not be available.])])
])dnl End of ACX_SSL_CHECKS ])dnl End of ACX_SSL_CHECKS
dnl Check for SSL, where SSL is mandatory dnl Check for SSL, where SSL is mandatory

6
spec/index.html Normal file → Executable file
View File

@ -2193,8 +2193,10 @@ getdns_context_set_dns_transport(
The value is <span class=default> The value is <span class=default>
<code>GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP</code></span>, <code>GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP</code></span>,
<code>GETDNS_TRANSPORT_UDP_ONLY</code>, <code>GETDNS_TRANSPORT_UDP_ONLY</code>,
<code>GETDNS_TRANSPORT_TCP_ONLY</code>, or <code>GETDNS_TRANSPORT_TCP_ONLY</code>,
<code>GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN</code>.</p> <code>GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN></code>,
<code>GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN></code>, or
<code>GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN></code>
<div class=forh> <div class=forh>
getdns_return_t getdns_return_t

View File

@ -84,6 +84,9 @@
/* Define to 1 if you have the `ldns' library (-lldns). */ /* Define to 1 if you have the `ldns' library (-lldns). */
#undef HAVE_LIBLDNS #undef HAVE_LIBLDNS
/* Define if you have libssl with tls 1.2 */
#undef HAVE_LIBTLS1_2
/* Define to 1 if you have the `unbound' library (-lunbound). */ /* Define to 1 if you have the `unbound' library (-lunbound). */
#undef HAVE_LIBUNBOUND #undef HAVE_LIBUNBOUND
@ -320,6 +323,10 @@ unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest);
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#endif
#ifdef HAVE_ATTR_FORMAT #ifdef HAVE_ATTR_FORMAT
# define ATTR_FORMAT(archetype, string_index, first_to_check) \ # define ATTR_FORMAT(archetype, string_index, first_to_check) \
__attribute__ ((format (archetype, string_index, first_to_check))) __attribute__ ((format (archetype, string_index, first_to_check)))

2
src/const-info.c Normal file → Executable file
View File

@ -39,6 +39,8 @@ static struct const_info consts_info[] = {
{ 541, "GETDNS_TRANSPORT_UDP_ONLY", GETDNS_TRANSPORT_UDP_ONLY_TEXT }, { 541, "GETDNS_TRANSPORT_UDP_ONLY", GETDNS_TRANSPORT_UDP_ONLY_TEXT },
{ 542, "GETDNS_TRANSPORT_TCP_ONLY", GETDNS_TRANSPORT_TCP_ONLY_TEXT }, { 542, "GETDNS_TRANSPORT_TCP_ONLY", GETDNS_TRANSPORT_TCP_ONLY_TEXT },
{ 543, "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN_TEXT }, { 543, "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN_TEXT },
{ 544, "GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN_TEXT },
{ 545, "GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT },
{ 550, "GETDNS_APPEND_NAME_ALWAYS", GETDNS_APPEND_NAME_ALWAYS_TEXT }, { 550, "GETDNS_APPEND_NAME_ALWAYS", GETDNS_APPEND_NAME_ALWAYS_TEXT },
{ 551, "GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE_TEXT }, { 551, "GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE_TEXT },
{ 552, "GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE_TEXT }, { 552, "GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE_TEXT },

View File

@ -470,11 +470,22 @@ upstreams_resize(getdns_upstreams *upstreams, size_t size)
return r; return r;
} }
static void void
upstreams_dereference(getdns_upstreams *upstreams) priv_getdns_upstreams_dereference(getdns_upstreams *upstreams)
{ {
if (upstreams && --upstreams->referenced == 0) size_t i;
if (upstreams && --upstreams->referenced == 0) {
for (i = 0; i < upstreams->count; i++) {
if (upstreams->upstreams[i].tls_obj != NULL) {
SSL_shutdown(upstreams->upstreams[i].tls_obj);
SSL_free(upstreams->upstreams[i].tls_obj);
}
if (upstreams->upstreams[i].fd != -1)
close(upstreams->upstreams[i].fd);
}
GETDNS_FREE(upstreams->mf, upstreams); GETDNS_FREE(upstreams->mf, upstreams);
}
} }
static uint8_t* static uint8_t*
@ -503,7 +514,8 @@ upstream_scope_id(getdns_upstream *upstream)
} }
static void static void
upstream_ntop_buf(getdns_upstream *upstream, char *buf, size_t len) upstream_ntop_buf(getdns_upstream *upstream, getdns_transport_t transport,
char *buf, size_t len)
{ {
/* Also possible but prints scope_id by name (nor parsed by unbound) /* Also possible but prints scope_id by name (nor parsed by unbound)
* *
@ -515,7 +527,10 @@ upstream_ntop_buf(getdns_upstream *upstream, char *buf, size_t len)
if (upstream_scope_id(upstream)) if (upstream_scope_id(upstream))
(void) snprintf(buf + strlen(buf), len - strlen(buf), (void) snprintf(buf + strlen(buf), len - strlen(buf),
"%%%d", (int)*upstream_scope_id(upstream)); "%%%d", (int)*upstream_scope_id(upstream));
if (upstream_port(upstream) != 53 && upstream_port(upstream) != 0) if (transport == GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN)
(void) snprintf(buf + strlen(buf), len - strlen(buf),
"@%d", GETDNS_TLS_PORT);
else if (upstream_port(upstream) != 53 && upstream_port(upstream) != 0)
(void) snprintf(buf + strlen(buf), len - strlen(buf), (void) snprintf(buf + strlen(buf), len - strlen(buf),
"@%d", (int)upstream_port(upstream)); "@%d", (int)upstream_port(upstream));
} }
@ -541,6 +556,7 @@ upstream_init(getdns_upstream *upstream,
/* For sharing a socket to this upstream with TCP */ /* For sharing a socket to this upstream with TCP */
upstream->fd = -1; upstream->fd = -1;
upstream->tls_obj = NULL;
upstream->loop = NULL; upstream->loop = NULL;
(void) getdns_eventloop_event_init( (void) getdns_eventloop_event_init(
&upstream->event, upstream, NULL, NULL, NULL); &upstream->event, upstream, NULL, NULL, NULL);
@ -770,6 +786,7 @@ getdns_context_create_with_extended_memory_functions(
result->edns_extended_rcode = 0; result->edns_extended_rcode = 0;
result->edns_version = 0; result->edns_version = 0;
result->edns_do_bit = 0; result->edns_do_bit = 0;
result-> tls_ctx = NULL;
result->extension = &result->mini_event.loop; result->extension = &result->mini_event.loop;
if ((r = getdns_mini_event_init(result, &result->mini_event))) if ((r = getdns_mini_event_init(result, &result->mini_event)))
@ -789,6 +806,9 @@ getdns_context_create_with_extended_memory_functions(
result->return_dnssec_status = GETDNS_EXTENSION_FALSE; result->return_dnssec_status = GETDNS_EXTENSION_FALSE;
/* unbound context is initialized here */ /* unbound context is initialized here */
/* Unbound needs SSL to be init'ed this early when TLS is used. However we
* don't know that till later so we will have to do this every time. */
SSL_library_init();
result->unbound_ctx = NULL; result->unbound_ctx = NULL;
if ((r = rebuild_ub_ctx(result))) if ((r = rebuild_ub_ctx(result)))
goto error; goto error;
@ -876,6 +896,9 @@ getdns_context_destroy(struct getdns_context *context)
GETDNS_FREE(context->my_mf, context->fchg_hosts->prevstat); GETDNS_FREE(context->my_mf, context->fchg_hosts->prevstat);
GETDNS_FREE(context->my_mf, context->fchg_hosts); GETDNS_FREE(context->my_mf, context->fchg_hosts);
} }
if (context->tls_ctx) {
SSL_CTX_free(context->tls_ctx);
}
getdns_list_destroy(context->dns_root_servers); getdns_list_destroy(context->dns_root_servers);
getdns_list_destroy(context->suffix); getdns_list_destroy(context->suffix);
@ -887,7 +910,7 @@ getdns_context_destroy(struct getdns_context *context)
getdns_traverse_postorder(&context->local_hosts, getdns_traverse_postorder(&context->local_hosts,
destroy_local_host, context); destroy_local_host, context);
upstreams_dereference(context->upstreams); priv_getdns_upstreams_dereference(context->upstreams);
GETDNS_FREE(context->my_mf, context); GETDNS_FREE(context->my_mf, context);
} /* getdns_context_destroy */ } /* getdns_context_destroy */
@ -1101,6 +1124,33 @@ getdns_context_set_namespaces(struct getdns_context *context,
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_namespaces */ } /* getdns_context_set_namespaces */
getdns_base_transport_t
priv_get_base_transport(getdns_transport_t transport, int level) {
if (!(level == 0 || level == 1)) return GETDNS_TRANSPORT_NONE;
switch (transport) {
case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP:
if (level == 0) return GETDNS_TRANSPORT_UDP;
if (level == 1) return GETDNS_TRANSPORT_TCP;
case GETDNS_TRANSPORT_UDP_ONLY:
if (level == 0) return GETDNS_TRANSPORT_UDP;
if (level == 1) return GETDNS_TRANSPORT_NONE;
case GETDNS_TRANSPORT_TCP_ONLY:
if (level == 0) return GETDNS_TRANSPORT_TCP_SINGLE;
if (level == 1) return GETDNS_TRANSPORT_NONE;
case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN:
if (level == 0) return GETDNS_TRANSPORT_TCP;
if (level == 1) return GETDNS_TRANSPORT_NONE;
case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN:
if (level == 0) return GETDNS_TRANSPORT_TLS;
if (level == 1) return GETDNS_TRANSPORT_NONE;
case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
if (level == 0) return GETDNS_TRANSPORT_TLS;
if (level == 1) return GETDNS_TRANSPORT_TCP;
default:
return GETDNS_TRANSPORT_NONE;
}
}
static getdns_return_t static getdns_return_t
set_ub_dns_transport(struct getdns_context* context, set_ub_dns_transport(struct getdns_context* context,
getdns_transport_t value) { getdns_transport_t value) {
@ -1114,13 +1164,25 @@ set_ub_dns_transport(struct getdns_context* context,
set_ub_string_opt(context, "do-tcp:", "no"); set_ub_string_opt(context, "do-tcp:", "no");
break; break;
case GETDNS_TRANSPORT_TCP_ONLY: case GETDNS_TRANSPORT_TCP_ONLY:
case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN: /* Note: no pipelining available directly in unbound.*/
case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN:
set_ub_string_opt(context, "do-udp:", "no"); set_ub_string_opt(context, "do-udp:", "no");
set_ub_string_opt(context, "do-tcp:", "yes"); set_ub_string_opt(context, "do-tcp:", "yes");
break; break;
default: case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN:
/* TODO GETDNS_CONTEXT_TCP_ONLY_KEEP_CONNECTIONS_OPEN */ /* Hum. If used in recursive mode this will try TLS on port 53...
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; * So we need to fix or document that or delay setting it until
* resolution.*/
set_ub_string_opt(context, "ssl-upstream:", "yes");
/* Fall through*/
case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
/* Note: no fallback to TCP available directly in unbound, so we just
* use TCP for now to make sure the messages are sent. */
set_ub_string_opt(context, "do-udp:", "no");
set_ub_string_opt(context, "do-tcp:", "yes");
break;
default:
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
} }
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
@ -1134,6 +1196,11 @@ getdns_context_set_dns_transport(struct getdns_context *context,
getdns_transport_t value) getdns_transport_t value)
{ {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* Note that the call below does not have any effect in unbound after the
* ctx is finalised. So will not apply for recursive mode or stub + dnssec.
* However the method returns success as otherwise the transport could not
* be reset for stub mode.....
* Also, not all transport options supported in libunbound yet */
if (set_ub_dns_transport(context, value) != GETDNS_RETURN_GOOD) { if (set_ub_dns_transport(context, value) != GETDNS_RETURN_GOOD) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
} }
@ -1447,7 +1514,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
upstreams->count++; upstreams->count++;
freeaddrinfo(ai); freeaddrinfo(ai);
} }
upstreams_dereference(context->upstreams); priv_getdns_upstreams_dereference(context->upstreams);
context->upstreams = upstreams; context->upstreams = upstreams;
dispatch_updated(context, dispatch_updated(context,
GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS); GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS);
@ -1457,7 +1524,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
invalid_parameter: invalid_parameter:
r = GETDNS_RETURN_INVALID_PARAMETER; r = GETDNS_RETURN_INVALID_PARAMETER;
error: error:
upstreams_dereference(upstreams); priv_getdns_upstreams_dereference(upstreams);
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
} /* getdns_context_set_upstream_recursive_servers */ } /* getdns_context_set_upstream_recursive_servers */
@ -1653,17 +1720,18 @@ getdns_cancel_callback(getdns_context *context,
} /* getdns_cancel_callback */ } /* getdns_cancel_callback */
static getdns_return_t static getdns_return_t
ub_setup_stub(struct ub_ctx *ctx, getdns_upstreams *upstreams) ub_setup_stub(struct ub_ctx *ctx, getdns_context *context)
{ {
getdns_return_t r = GETDNS_RETURN_GOOD; getdns_return_t r = GETDNS_RETURN_GOOD;
size_t i; size_t i;
getdns_upstream *upstream; getdns_upstream *upstream;
char addr[1024]; char addr[1024];
getdns_upstreams *upstreams = context->upstreams;
(void) ub_ctx_set_fwd(ctx, NULL); (void) ub_ctx_set_fwd(ctx, NULL);
for (i = 0; i < upstreams->count; i++) { for (i = 0; i < upstreams->count; i++) {
upstream = &upstreams->upstreams[i]; upstream = &upstreams->upstreams[i];
upstream_ntop_buf(upstream, addr, 1024); upstream_ntop_buf(upstream, context->dns_transport, addr, 1024);
ub_ctx_set_fwd(ctx, addr); ub_ctx_set_fwd(ctx, addr);
} }
@ -1735,7 +1803,7 @@ priv_getdns_ns_dns_setup(struct getdns_context *context)
case GETDNS_RESOLUTION_STUB: case GETDNS_RESOLUTION_STUB:
if (!context->upstreams || !context->upstreams->count) if (!context->upstreams || !context->upstreams->count)
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
return ub_setup_stub(context->unbound_ctx, context->upstreams); return ub_setup_stub(context->unbound_ctx, context);
case GETDNS_RESOLUTION_RECURSING: case GETDNS_RESOLUTION_RECURSING:
/* TODO: use the root servers via root hints file */ /* TODO: use the root servers via root hints file */
@ -1756,6 +1824,33 @@ getdns_context_prepare_for_resolution(struct getdns_context *context,
if (context->destroying) { if (context->destroying) {
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
} }
/* Transport can in theory be set per query in stub mode */
/* TODO: move this transport logic to a separate functions*/
if (context->resolution_type == GETDNS_RESOLUTION_STUB) {
switch (context->dns_transport) {
case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN:
case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
if (context->tls_ctx == NULL) {
#ifdef HAVE_LIBTLS1_2
/* Create client context, use TLS v1.2 only for now */
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
#endif
if(!context->tls_ctx && context->dns_transport ==
GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN) {
return GETDNS_RETURN_BAD_CONTEXT;
}
}
break;
default:
break;
}
}
/* Block use of TLS ONLY in recursive mode as it won't work */
if (context->resolution_type == GETDNS_RESOLUTION_RECURSING
&& context->dns_transport == GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN)
return GETDNS_RETURN_BAD_CONTEXT;
if (context->resolution_type_set == context->resolution_type) if (context->resolution_type_set == context->resolution_type)
/* already set and no config changes /* already set and no config changes
* have caused this to be bad. * have caused this to be bad.

View File

@ -49,6 +49,7 @@ struct ub_ctx;
#define GETDNS_FN_RESOLVCONF "/etc/resolv.conf" #define GETDNS_FN_RESOLVCONF "/etc/resolv.conf"
#define GETDNS_FN_HOSTS "/etc/hosts" #define GETDNS_FN_HOSTS "/etc/hosts"
#define GETDNS_TLS_PORT 1021
enum filechgs { GETDNS_FCHG_ERRORS = -1 enum filechgs { GETDNS_FCHG_ERRORS = -1
, GETDNS_FCHG_NOERROR = 0 , GETDNS_FCHG_NOERROR = 0
@ -71,6 +72,14 @@ struct filechg {
struct stat *prevstat; struct stat *prevstat;
}; };
typedef enum getdns_base_transport {
GETDNS_TRANSPORT_NONE,
GETDNS_TRANSPORT_UDP,
GETDNS_TRANSPORT_TCP_SINGLE,
GETDNS_TRANSPORT_TCP,
GETDNS_TRANSPORT_TLS
} getdns_base_transport_t;
typedef struct getdns_upstream { typedef struct getdns_upstream {
struct getdns_upstreams *upstreams; struct getdns_upstreams *upstreams;
@ -83,6 +92,7 @@ typedef struct getdns_upstream {
/* For sharing a TCP socket to this upstream */ /* For sharing a TCP socket to this upstream */
int fd; int fd;
SSL* tls_obj;
getdns_eventloop_event event; getdns_eventloop_event event;
getdns_eventloop *loop; getdns_eventloop *loop;
getdns_tcp_state tcp; getdns_tcp_state tcp;
@ -133,6 +143,7 @@ struct getdns_context {
uint8_t edns_version; uint8_t edns_version;
uint8_t edns_do_bit; uint8_t edns_do_bit;
int edns_maximum_udp_payload_size; /* -1 is unset */ int edns_maximum_udp_payload_size; /* -1 is unset */
SSL_CTX* tls_ctx;
getdns_update_callback update_callback; getdns_update_callback update_callback;
getdns_update_callback2 update_callback2; getdns_update_callback2 update_callback2;
@ -220,4 +231,8 @@ int filechg_check(struct getdns_context *context, struct filechg *fchg);
void priv_getdns_context_ub_read_cb(void *userarg); void priv_getdns_context_ub_read_cb(void *userarg);
getdns_base_transport_t priv_get_base_transport(getdns_transport_t transport, int level);
void priv_getdns_upstreams_dereference(getdns_upstreams *upstreams);
#endif /* _GETDNS_CONTEXT_H_ */ #endif /* _GETDNS_CONTEXT_H_ */

6
src/getdns/getdns.h.in Normal file → Executable file
View File

@ -163,7 +163,9 @@ typedef enum getdns_transport_t {
GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP = 540, GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP = 540,
GETDNS_TRANSPORT_UDP_ONLY = 541, GETDNS_TRANSPORT_UDP_ONLY = 541,
GETDNS_TRANSPORT_TCP_ONLY = 542, GETDNS_TRANSPORT_TCP_ONLY = 542,
GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN = 543 GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN = 543,
GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN = 544,
GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN = 545
} getdns_transport_t; } getdns_transport_t;
/** /**
@ -174,6 +176,8 @@ typedef enum getdns_transport_t {
#define GETDNS_TRANSPORT_UDP_ONLY_TEXT "See getdns_context_set_dns_transport()" #define GETDNS_TRANSPORT_UDP_ONLY_TEXT "See getdns_context_set_dns_transport()"
#define GETDNS_TRANSPORT_TCP_ONLY_TEXT "See getdns_context_set_dns_transport()" #define GETDNS_TRANSPORT_TCP_ONLY_TEXT "See getdns_context_set_dns_transport()"
#define GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()" #define GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()"
#define GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()"
#define GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()"
/** @} /** @}
*/ */

View File

@ -177,8 +177,7 @@ dns_req_free(getdns_dns_req * req)
return; return;
} }
if (req->upstreams && --req->upstreams->referenced == 0) priv_getdns_upstreams_dereference(req->upstreams);
GETDNS_FREE(req->upstreams->mf, req->upstreams);
/* cleanup network requests */ /* cleanup network requests */
for (net_req = req->netreqs; *net_req; net_req++) for (net_req = req->netreqs; *net_req; net_req++)

392
src/stub.c Normal file → Executable file
View File

@ -318,6 +318,13 @@ upstream_erred(getdns_upstream *upstream)
netreq->state = NET_REQ_FINISHED; netreq->state = NET_REQ_FINISHED;
priv_getdns_check_dns_req_complete(netreq->owner); priv_getdns_check_dns_req_complete(netreq->owner);
} }
/* TODO[TLS]: When we get an error (which is probably a timeout) and are
* using to keep connections open should we leave the connection up here? */
if (upstream->tls_obj) {
SSL_shutdown(upstream->tls_obj);
SSL_free(upstream->tls_obj);
upstream->tls_obj = NULL;
}
close(upstream->fd); close(upstream->fd);
upstream->fd = -1; upstream->fd = -1;
} }
@ -521,7 +528,7 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
tcp->to_read -= read; tcp->to_read -= read;
tcp->read_pos += read; tcp->read_pos += read;
if (tcp->to_read > 0) if ((int)tcp->to_read > 0)
return STUB_TCP_AGAIN; return STUB_TCP_AGAIN;
read = tcp->read_pos - tcp->read_buf; read = tcp->read_pos - tcp->read_buf;
@ -595,6 +602,187 @@ stub_tcp_read_cb(void *userarg)
} }
} }
/** wait for a socket to become ready */
static int
sock_wait(int sockfd)
{
int ret;
fd_set fds;
FD_ZERO(&fds);
FD_SET(FD_SET_T sockfd, &fds);
/*TODO[TLS]: Pick up this timeout from the context*/
struct timeval timeout = {5, 0 };
ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
if(ret == 0)
/* timeout expired */
return 0;
else if(ret == -1)
/* error */
return 0;
return 1;
}
static int
sock_connected(int sockfd)
{
/* wait(write) until connected or error */
while(1) {
int error = 0;
socklen_t len = (socklen_t)sizeof(error);
if(!sock_wait(sockfd)) {
close(sockfd);
return -1;
}
/* check if there is a pending error for nonblocking connect */
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error, &len) < 0) {
error = errno; /* on solaris errno is error */
}
if (error == EINPROGRESS || error == EWOULDBLOCK)
continue; /* try again */
else if (error != 0) {
close(sockfd);
return -1;
}
/* connected */
break;
}
return sockfd;
}
/* The connection testing and handshake should be handled by integrating this
* with the event loop framework, but for now just implement a standalone
* handshake method.*/
static SSL*
do_tls_handshake(getdns_dns_req *dnsreq, getdns_upstream *upstream)
{
/*Lets make sure the connection is up before we try a handshake*/
if (errno == EINPROGRESS && sock_connected(upstream->fd) == -1) {
return NULL;
}
/* Create SSL instance */
if (dnsreq->context->tls_ctx == NULL)
return NULL;
SSL* ssl = SSL_new(dnsreq->context->tls_ctx);
if(!ssl) {
return NULL;
}
/* Connect the SSL object with a file descriptor */
if(!SSL_set_fd(ssl, upstream->fd)) {
SSL_free(ssl);
return NULL;
}
SSL_set_connect_state(ssl);
(void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
int r;
int want;
fd_set fds;
FD_ZERO(&fds);
FD_SET(upstream->fd, &fds);
struct timeval timeout = {dnsreq->context->timeout/1000, 0 };
while ((r = SSL_do_handshake(ssl)) != 1)
{
want = SSL_get_error(ssl, r);
switch (want) {
case SSL_ERROR_WANT_READ:
if (select(upstream->fd + 1, &fds, NULL, NULL, &timeout) == 0) {
SSL_free(ssl);
return NULL;
}
break;
case SSL_ERROR_WANT_WRITE:
if (select(upstream->fd + 1, NULL, &fds, NULL, &timeout) == 0) {
SSL_free(ssl);
return NULL;
}
break;
default:
SSL_free(ssl);
return NULL;
}
}
return ssl;
}
static int
stub_tls_read(SSL* tls_obj, getdns_tcp_state *tcp, struct mem_funcs *mf)
{
ssize_t read;
uint8_t *buf;
size_t buf_size;
if (!tcp->read_buf) {
/* First time tls read, create a buffer for reading */
if (!(tcp->read_buf = GETDNS_XMALLOC(*mf, uint8_t, 4096)))
return STUB_TCP_ERROR;
tcp->read_buf_len = 4096;
tcp->read_pos = tcp->read_buf;
tcp->to_read = 2; /* Packet size */
}
ERR_clear_error();
read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read);
if (read <= 0) {
/* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake
renegotiation. Need to keep handshake state to do that.*/
int want = SSL_get_error(tls_obj, read);
if (want == SSL_ERROR_WANT_READ) {
return STUB_TCP_AGAIN; /* read more later */
} else
return STUB_TCP_ERROR;
}
tcp->to_read -= read;
tcp->read_pos += read;
if ((int)tcp->to_read > 0)
return STUB_TCP_AGAIN;
read = tcp->read_pos - tcp->read_buf;
if (read == 2) {
/* Read the packet size short */
tcp->to_read = gldns_read_uint16(tcp->read_buf);
if (tcp->to_read < GLDNS_HEADER_SIZE)
return STUB_TCP_ERROR;
/* Resize our buffer if needed */
if (tcp->to_read > tcp->read_buf_len) {
buf_size = tcp->read_buf_len;
while (tcp->to_read > buf_size)
buf_size *= 2;
if (!(buf = GETDNS_XREALLOC(*mf,
tcp->read_buf, uint8_t, buf_size)))
return STUB_TCP_ERROR;
tcp->read_buf = buf;
tcp->read_buf_len = buf_size;
}
/* Ready to start reading the packet */
tcp->read_pos = tcp->read_buf;
read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read);
if (read <= 0) {
/* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake
renegotiation. Need to keep handshake state to do that.*/
int want = SSL_get_error(tls_obj, read);
if (want == SSL_ERROR_WANT_READ) {
return STUB_TCP_AGAIN; /* read more later */
} else
return STUB_TCP_ERROR;
}
tcp->to_read -= read;
tcp->read_pos += read;
if ((int)tcp->to_read > 0)
return STUB_TCP_AGAIN;
}
return GLDNS_ID_WIRE(tcp->read_buf);
}
static void netreq_upstream_read_cb(void *userarg); static void netreq_upstream_read_cb(void *userarg);
static void netreq_upstream_write_cb(void *userarg); static void netreq_upstream_write_cb(void *userarg);
static void static void
@ -607,8 +795,14 @@ upstream_read_cb(void *userarg)
uint16_t query_id; uint16_t query_id;
intptr_t query_id_intptr; intptr_t query_id_intptr;
switch ((q = stub_tcp_read(upstream->fd, &upstream->tcp, if (upstream->tls_obj)
&upstream->upstreams->mf))) { q = stub_tls_read(upstream->tls_obj, &upstream->tcp,
&upstream->upstreams->mf);
else
q = stub_tcp_read(upstream->fd, &upstream->tcp,
&upstream->upstreams->mf);
switch (q) {
case STUB_TCP_AGAIN: case STUB_TCP_AGAIN:
return; return;
@ -617,6 +811,7 @@ upstream_read_cb(void *userarg)
return; return;
default: default:
/* Lookup netreq */ /* Lookup netreq */
query_id = (uint16_t) q; query_id = (uint16_t) q;
query_id_intptr = (intptr_t) query_id; query_id_intptr = (intptr_t) query_id;
@ -705,9 +900,9 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
* the write_queue) for that upstream. Register this netreq * the write_queue) for that upstream. Register this netreq
* by query_id in the process. * by query_id in the process.
*/ */
if (dnsreq->context->dns_transport != if ((dnsreq->context->dns_transport == GETDNS_TRANSPORT_TCP_ONLY) ||
GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN) (dnsreq->context->dns_transport == GETDNS_TRANSPORT_UDP_ONLY) ||
(dnsreq->context->dns_transport == GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP))
query_id = arc4random(); query_id = arc4random();
else do { else do {
query_id = arc4random(); query_id = arc4random();
@ -822,6 +1017,54 @@ stub_tcp_write_cb(void *userarg)
} }
} }
static int
stub_tls_write(SSL* tls_obj, getdns_tcp_state *tcp, getdns_network_req *netreq)
{
size_t pkt_len = netreq->response - netreq->query;
ssize_t written;
uint16_t query_id;
intptr_t query_id_intptr;
/* Do we have remaining data that we could not write before? */
if (! tcp->write_buf) {
/* No, this is an initial write. Try to send
*/
/* Find a unique query_id not already written (or in
* the write_queue) for that upstream. Register this netreq
* by query_id in the process.
*/
do {
query_id = ldns_get_random();
query_id_intptr = (intptr_t)query_id;
netreq->node.key = (void *)query_id_intptr;
} while (!getdns_rbtree_insert(
&netreq->upstream->netreq_by_query_id, &netreq->node));
GLDNS_ID_SET(netreq->query, query_id);
if (netreq->opt)
/* no limits on the max udp payload size with tcp */
gldns_write_uint16(netreq->opt + 3, 65535);
/* We have an initialized packet buffer.
* Lets see how much of it we can write */
// TODO[TLS]: Handle error cases, partial writes, renegotiation etc.
ERR_clear_error();
written = SSL_write(tls_obj, netreq->query - 2, pkt_len + 2);
if (written <= 0)
return STUB_TCP_ERROR;
/* We were able to write everything! Start reading. */
return (int) query_id;
}
return STUB_TCP_ERROR;
}
static void static void
upstream_write_cb(void *userarg) upstream_write_cb(void *userarg)
{ {
@ -830,7 +1073,12 @@ upstream_write_cb(void *userarg)
getdns_dns_req *dnsreq = netreq->owner; getdns_dns_req *dnsreq = netreq->owner;
int q; int q;
switch ((q = stub_tcp_write(upstream->fd, &upstream->tcp, netreq))) { if (upstream->tls_obj)
q = stub_tls_write(upstream->tls_obj, &upstream->tcp, netreq);
else
q = stub_tcp_write(upstream->fd, &upstream->tcp, netreq);
switch (q) {
case STUB_TCP_AGAIN: case STUB_TCP_AGAIN:
return; return;
@ -902,6 +1150,58 @@ upstream_schedule_netreq(getdns_upstream *upstream, getdns_network_req *netreq)
} }
} }
static in_port_t
get_port(struct sockaddr_storage* addr)
{
return ntohs(addr->ss_family == AF_INET
? ((struct sockaddr_in *)addr)->sin_port
: ((struct sockaddr_in6*)addr)->sin6_port);
}
static void
set_port(struct sockaddr_storage* addr, in_port_t port)
{
addr->ss_family == AF_INET
? (((struct sockaddr_in *)addr)->sin_port = htons(port))
: (((struct sockaddr_in6*)addr)->sin6_port = htons(port));
}
static int
tcp_connect (getdns_upstream *upstream, getdns_base_transport_t transport) {
int fd =-1;
struct sockaddr_storage connect_addr;
struct sockaddr_storage* addr = &upstream->addr;
socklen_t addr_len = upstream->addr_len;
/* TODO[TLS]: For now, override the port to a hardcoded value*/
if (transport == GETDNS_TRANSPORT_TLS &&
(int)get_port(addr) != GETDNS_TLS_PORT) {
connect_addr = upstream->addr;
addr = &connect_addr;
set_port(addr, GETDNS_TLS_PORT);
}
if ((fd = socket(addr->ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
return -1;
getdns_sock_nonblock(fd);
#ifdef USE_TCP_FASTOPEN
/* Leave the connect to the later call to sendto() if using TCP*/
if (transport == GETDNS_TRANSPORT_TCP ||
transport == GETDNS_TRANSPORT_TCP_SINGLE)
return fd;
#endif
if (connect(fd, (struct sockaddr *)addr,
addr_len) == -1) {
if (errno != EINPROGRESS) {
close(fd);
return -1;
}
}
return fd;
}
getdns_return_t getdns_return_t
priv_getdns_submit_stub_request(getdns_network_req *netreq) priv_getdns_submit_stub_request(getdns_network_req *netreq)
{ {
@ -911,9 +1211,13 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq)
if (!upstream) if (!upstream)
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
switch(dnsreq->context->dns_transport) { // Work out the primary and fallback transport options
case GETDNS_TRANSPORT_UDP_ONLY: getdns_base_transport_t transport = priv_get_base_transport(
case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP: dnsreq->context->dns_transport,0);
getdns_base_transport_t fb_transport = priv_get_base_transport(
dnsreq->context->dns_transport,1);
switch(transport) {
case GETDNS_TRANSPORT_UDP:
if ((netreq->fd = socket( if ((netreq->fd = socket(
upstream->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) upstream->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1)
@ -929,23 +1233,10 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
case GETDNS_TRANSPORT_TCP_ONLY: case GETDNS_TRANSPORT_TCP_SINGLE:
if ((netreq->fd = socket( if ((netreq->fd = tcp_connect(upstream, transport)) == -1)
upstream->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
getdns_sock_nonblock(netreq->fd);
#ifdef USE_TCP_FASTOPEN
/* Leave the connect to the later call to sendto() */
#else
if (connect(netreq->fd, (struct sockaddr *)&upstream->addr,
upstream->addr_len) == -1 && errno != EINPROGRESS) {
close(netreq->fd);
return GETDNS_RETURN_GENERIC_ERROR;
}
#endif
netreq->upstream = upstream; netreq->upstream = upstream;
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(
@ -955,34 +1246,51 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN: case GETDNS_TRANSPORT_TCP:
case GETDNS_TRANSPORT_TLS:
/* In coming comments, "global" means "context wide" */ /* In coming comments, "global" means "context wide" */
/* Are we the first? (Is global socket initialized?) */ /* Are we the first? (Is global socket initialized?) */
if (upstream->fd == -1) { if (upstream->fd == -1) {
/* We are the first. Make global socket and connect. */ /* TODO[TLS]: We should remember on the context if we had to fallback
if ((upstream->fd = socket(upstream->addr.ss_family, * for this upstream so when re-connecting from a dropped TCP
SOCK_STREAM, IPPROTO_TCP)) == -1) * connection we don't retry TLS. */
return GETDNS_RETURN_GENERIC_ERROR; int fallback = 0;
getdns_sock_nonblock(upstream->fd);
#ifdef USE_TCP_FASTOPEN
/* Leave the connect to the later call to sendto() */
#else
if (connect(upstream->fd,
(struct sockaddr *)&upstream->addr,
upstream->addr_len) == -1 && errno != EINPROGRESS){
close(upstream->fd); /* We are the first. Make global socket and connect. */
upstream->fd = -1; if ((upstream->fd = tcp_connect(upstream, transport)) == -1) {
return GETDNS_RETURN_GENERIC_ERROR; if (fb_transport == GETDNS_TRANSPORT_NONE)
return GETDNS_RETURN_GENERIC_ERROR;
if ((upstream->fd = tcp_connect(upstream, fb_transport)) == -1)
return GETDNS_RETURN_GENERIC_ERROR;
fallback = 1;
}
/* Now do a handshake for TLS. Note waiting for this to succeed or
* timeout blocks the scheduling of any messages for this upstream*/
if (transport == GETDNS_TRANSPORT_TLS && (fallback == 0)) {
upstream->tls_obj = do_tls_handshake(dnsreq, upstream);
if (!upstream->tls_obj) {
if (fb_transport == GETDNS_TRANSPORT_NONE)
return GETDNS_RETURN_GENERIC_ERROR;
close(upstream->fd);
if ((upstream->fd = tcp_connect(upstream, fb_transport)) == -1)
return GETDNS_RETURN_GENERIC_ERROR;
}
} }
#endif
/* Attach to the global event loop /* Attach to the global event loop
* so it can do it's own scheduling * so it can do it's own scheduling
*/ */
upstream->loop = dnsreq->context->extension; upstream->loop = dnsreq->context->extension;
} else {
/* Cater for the case of the user downgrading and existing TLS
connection to TCP for some reason...*/
if (transport == GETDNS_TRANSPORT_TCP && upstream->tls_obj) {
SSL_shutdown(upstream->tls_obj);
SSL_free(upstream->tls_obj);
upstream->tls_obj = NULL;
}
} }
netreq->upstream = upstream; netreq->upstream = upstream;

View File

@ -29,9 +29,23 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <dirent.h>
#include <getdns/getdns.h> #include <getdns/getdns.h>
#include <getdns/getdns_extra.h> #include <getdns/getdns_extra.h>
static int quiet = 0;
static int batch_mode = 0;
static char *query_file = NULL;
static int json = 0;
static char *the_root = ".";
static char *name;
static getdns_context *context;
static getdns_dict *extensions;
static uint16_t request_type = GETDNS_RRTYPE_NS;
static int timeout, edns0_size;
static int async = 0, interactive = 0;
static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL;
int get_rrtype(const char *t); int get_rrtype(const char *t);
getdns_dict * getdns_dict *
@ -90,6 +104,7 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-b <bufsize>\tSet edns0 max_udp_payload size\n"); fprintf(out, "\t-b <bufsize>\tSet edns0 max_udp_payload size\n");
fprintf(out, "\t-D\tSet edns0 do bit\n"); fprintf(out, "\t-D\tSet edns0 do bit\n");
fprintf(out, "\t-d\tclear edns0 do bit\n"); fprintf(out, "\t-d\tclear edns0 do bit\n");
fprintf(out, "\t-F <filename>\tread the queries from the specified file\n");
fprintf(out, "\t-G\tgeneral lookup\n"); fprintf(out, "\t-G\tgeneral lookup\n");
fprintf(out, "\t-H\thostname lookup. (<name> must be an IP address; <type> is ignored)\n"); fprintf(out, "\t-H\thostname lookup. (<name> must be an IP address; <type> is ignored)\n");
fprintf(out, "\t-h\tPrint this help\n"); fprintf(out, "\t-h\tPrint this help\n");
@ -104,29 +119,45 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-t <timeout>\tSet timeout in miliseconds\n"); fprintf(out, "\t-t <timeout>\tSet timeout in miliseconds\n");
fprintf(out, "\t-T\tSet transport to TCP only\n"); fprintf(out, "\t-T\tSet transport to TCP only\n");
fprintf(out, "\t-O\tSet transport to TCP only keep connections open\n"); fprintf(out, "\t-O\tSet transport to TCP only keep connections open\n");
fprintf(out, "\t-L\tSet transport to TLS only keep connections open\n");
fprintf(out, "\t-E\tSet transport to TLS with TCP fallback only keep connections open\n");
fprintf(out, "\t-u\tSet transport to UDP with TCP fallback\n"); fprintf(out, "\t-u\tSet transport to UDP with TCP fallback\n");
fprintf(out, "\t-U\tSet transport to UDP only\n"); fprintf(out, "\t-U\tSet transport to UDP only\n");
fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n");
fprintf(out, "\t-q\tQuiet mode - don't print response\n");
} }
void callback(getdns_context *context, getdns_callback_type_t callback_type, void callback(getdns_context *context, getdns_callback_type_t callback_type,
getdns_dict *response, void *userarg, getdns_transaction_t trans_id) getdns_dict *response, void *userarg, getdns_transaction_t trans_id)
{ {
getdns_dict **response_ptr = (getdns_dict **)userarg; char *response_str;
if (response) if (callback_type == GETDNS_CALLBACK_COMPLETE) {
*response_ptr = response; /* This is a callback with data */;
if (!quiet && (response_str = json ?
getdns_print_json_dict(response, json == 1)
: getdns_pretty_print_dict(response))) {
fprintf(stdout, "ASYNC response:\n%s\n", response_str);
free(response_str);
}
fprintf(stderr,
"The callback with ID %llu was successfull.\n",
(unsigned long long)trans_id);
} else if (callback_type == GETDNS_CALLBACK_CANCEL)
fprintf(stderr,
"The callback with ID %llu was cancelled. Exiting.\n",
(unsigned long long)trans_id);
else
fprintf(stderr,
"The callback got a callback_type of %d. Exiting.\n",
callback_type);
getdns_dict_destroy(response);
response = NULL;
} }
static char *the_root = ".";
static char *name;
static getdns_context *context;
static getdns_dict *extensions;
static uint16_t request_type = GETDNS_RRTYPE_NS;
static int timeout, edns0_size;
static int async = 0, interactive = 0;
static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL;
static int json = 0;
#define CONTINUE ((getdns_return_t)-2) #define CONTINUE ((getdns_return_t)-2)
static getdns_return_t set_cookie(getdns_dict *exts, char *cookie) static getdns_return_t set_cookie(getdns_dict *exts, char *cookie)
@ -259,6 +290,15 @@ getdns_return_t parse_args(int argc, char **argv)
case 'd': case 'd':
(void) getdns_context_set_edns_do_bit(context, 0); (void) getdns_context_set_edns_do_bit(context, 0);
break; break;
case 'F':
if (c[1] != 0 || ++i >= argc || !*argv[i]) {
fprintf(stderr, "file name expected "
"after -F\n");
return GETDNS_RETURN_GENERIC_ERROR;
}
query_file = argv[i];
interactive = 1;
break;
case 'G': case 'G':
calltype = GENERAL; calltype = GENERAL;
break; break;
@ -282,6 +322,8 @@ getdns_return_t parse_args(int argc, char **argv)
break; break;
case 'p': case 'p':
json = 0; json = 0;
case 'q':
quiet = 1;
break; break;
case 'r': case 'r':
getdns_context_set_resolution_type( getdns_context_set_resolution_type(
@ -319,6 +361,14 @@ getdns_return_t parse_args(int argc, char **argv)
getdns_context_set_dns_transport(context, getdns_context_set_dns_transport(context,
GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN); GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN);
break; break;
case 'L':
getdns_context_set_dns_transport(context,
GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN);
break;
case 'E':
getdns_context_set_dns_transport(context,
GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN);
break;
case 'u': case 'u':
getdns_context_set_dns_transport(context, getdns_context_set_dns_transport(context,
GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP); GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP);
@ -327,6 +377,9 @@ getdns_return_t parse_args(int argc, char **argv)
getdns_context_set_dns_transport(context, getdns_context_set_dns_transport(context,
GETDNS_TRANSPORT_UDP_ONLY); GETDNS_TRANSPORT_UDP_ONLY);
break; break;
case 'B':
batch_mode = 1;
break;
default: default:
@ -361,6 +414,7 @@ main(int argc, char **argv)
char *response_str; char *response_str;
getdns_return_t r; getdns_return_t r;
getdns_dict *address = NULL; getdns_dict *address = NULL;
FILE *fp = NULL;
name = the_root; name = the_root;
if ((r = getdns_context_create(&context, 1))) { if ((r = getdns_context_create(&context, 1))) {
@ -376,14 +430,28 @@ main(int argc, char **argv)
if ((r = parse_args(argc, argv))) if ((r = parse_args(argc, argv)))
goto done_destroy_context; goto done_destroy_context;
if (query_file) {
fp = fopen(query_file, "rt");
if (fp == NULL) {
fprintf(stderr, "Could not open query file: %s\n", query_file);
goto done_destroy_context;
}
}
/* Make the call */ /* Make the call */
do { do {
char line[1024], *token, *linev[256]; char line[1024], *token, *linev[256];
int linec; int linec;
if (interactive) { if (interactive) {
fprintf(stdout, "> "); if (!query_file) {
if (!fgets(line, 1024, stdin) || !*line) fprintf(stdout, "> ");
break; if (!fgets(line, 1024, stdin) || !*line)
break;
} else {
if (!fgets(line, 1024, fp) || !*line)
break;
fprintf(stdout,"Found query: %s", line);
}
linev[0] = argv[0]; linev[0] = argv[0];
linec = 1; linec = 1;
@ -430,8 +498,8 @@ main(int argc, char **argv)
} }
if (r) if (r)
goto done_destroy_extensions; goto done_destroy_extensions;
if (!batch_mode)
getdns_context_run(context); getdns_context_run(context);
} else { } else {
switch (calltype) { switch (calltype) {
case GENERAL: case GENERAL:
@ -456,22 +524,29 @@ main(int argc, char **argv)
} }
if (r) if (r)
goto done_destroy_extensions; goto done_destroy_extensions;
} if (!quiet) {
if (json) if ((response_str = json ?
response_str = getdns_print_json_dict( getdns_print_json_dict(response, json == 1)
response, json == 1); : getdns_pretty_print_dict(response))) {
else
response_str = getdns_pretty_print_dict(response);
if (response_str) { fprintf( stdout, "SYNC response:\n%s\n"
fprintf(stdout, "%s\n", response_str); , response_str);
free(response_str); free(response_str);
} else { } else {
r = GETDNS_RETURN_MEMORY_ERROR; r = GETDNS_RETURN_MEMORY_ERROR;
fprintf(stderr, "Could not print response\n"); fprintf( stderr
, "Could not print response\n");
}
} else if (r == GETDNS_RETURN_GOOD)
fprintf(stdout, "Response code was: GOOD\n");
else if (interactive)
fprintf(stderr, "An error occurred: %d\n", r);
} }
} while (interactive); } while (interactive);
if (batch_mode)
getdns_context_run(context);
/* Clean up */ /* Clean up */
done_destroy_extensions: done_destroy_extensions:
getdns_dict_destroy(extensions); getdns_dict_destroy(extensions);
@ -479,6 +554,9 @@ done_destroy_context:
if (response) getdns_dict_destroy(response); if (response) getdns_dict_destroy(response);
getdns_context_destroy(context); getdns_context_destroy(context);
if (fp)
fclose(fp);
if (r == CONTINUE) if (r == CONTINUE)
return 0; return 0;
if (r) if (r)

View File

@ -44,6 +44,8 @@
#define TRANSPORT_UDP "udp" #define TRANSPORT_UDP "udp"
#define TRANSPORT_TCP "tcp" #define TRANSPORT_TCP "tcp"
#define TRANSPORT_PIPELINE "pipeline" #define TRANSPORT_PIPELINE "pipeline"
#define TRANSPORT_TLS_KEEPOPEN "tls"
#define TRANSPORT_TLS_TCP_KEEPOPEN "dns-over-tls"
#define RESOLUTION_STUB "stub" #define RESOLUTION_STUB "stub"
#define RESOLUTION_REC "rec" #define RESOLUTION_REC "rec"
@ -98,6 +100,10 @@ main(int argc, char** argv)
getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY); getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY);
else if (strncmp(transport, TRANSPORT_PIPELINE, 8) == 0) else if (strncmp(transport, TRANSPORT_PIPELINE, 8) == 0)
getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN); getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN);
else if (strncmp(transport, TRANSPORT_TLS_KEEPOPEN, 3) == 0)
getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN);
else if (strncmp(transport, TRANSPORT_TLS_TCP_KEEPOPEN, 12) == 0)
getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN);
else if (strncmp(transport, TRANSPORT_UDP, 3) != 0) { else if (strncmp(transport, TRANSPORT_UDP, 3) != 0) {
fprintf(stderr, "Invalid transport %s, must be one of udp, tcp or pipeline\n", transport); fprintf(stderr, "Invalid transport %s, must be one of udp, tcp or pipeline\n", transport);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

@ -41,6 +41,8 @@
#define TRANSPORT_UDP "udp" #define TRANSPORT_UDP "udp"
#define TRANSPORT_TCP "tcp" #define TRANSPORT_TCP "tcp"
#define TRANSPORT_PIPELINE "pipeline" #define TRANSPORT_PIPELINE "pipeline"
#define TRANSPORT_TLS_KEEPOPEN "tls"
#define TRANSPORT_TLS_TCP_KEEPOPEN "dns-over-tls"
#define RESOLUTION_STUB "stub" #define RESOLUTION_STUB "stub"
#define RESOLUTION_REC "rec" #define RESOLUTION_REC "rec"
@ -82,6 +84,10 @@ main(int argc, char** argv)
getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY); getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY);
else if (strncmp(transport, TRANSPORT_PIPELINE, 8) == 0) else if (strncmp(transport, TRANSPORT_PIPELINE, 8) == 0)
getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN); getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN);
else if (strncmp(transport, TRANSPORT_TLS_KEEPOPEN, 3) == 0)
getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN);
else if (strncmp(transport, TRANSPORT_TLS_TCP_KEEPOPEN, 12) == 0)
getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN);
else if (strncmp(transport, TRANSPORT_UDP, 3) != 0) { else if (strncmp(transport, TRANSPORT_UDP, 3) != 0) {
fprintf(stderr, "Invalid transport %s, must be one of udp, tcp or pipeline\n", transport); fprintf(stderr, "Invalid transport %s, must be one of udp, tcp or pipeline\n", transport);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

@ -36,7 +36,6 @@
#ifndef TYPES_INTERNAL_H_ #ifndef TYPES_INTERNAL_H_
#define TYPES_INTERNAL_H_ #define TYPES_INTERNAL_H_
#include <netinet/in.h>
#include "getdns/getdns.h" #include "getdns/getdns.h"
#include "getdns/getdns_extra.h" #include "getdns/getdns_extra.h"
#include "util/rbtree.h" #include "util/rbtree.h"