mirror of https://github.com/getdnsapi/getdns.git
Merge branch 'features/windows-support' into develop
This commit is contained in:
commit
a2bdfb2f22
|
@ -193,6 +193,7 @@ $(distdir):
|
||||||
cp $(srcdir)/install-sh $(distdir)
|
cp $(srcdir)/install-sh $(distdir)
|
||||||
cp $(srcdir)/config.sub $(distdir)
|
cp $(srcdir)/config.sub $(distdir)
|
||||||
cp $(srcdir)/config.guess $(distdir)
|
cp $(srcdir)/config.guess $(distdir)
|
||||||
|
cp $(srcdir)/getdns.pc.in $(distdir)
|
||||||
cp libtool $(distdir)
|
cp libtool $(distdir)
|
||||||
cp $(srcdir)/ltmain.sh $(distdir)
|
cp $(srcdir)/ltmain.sh $(distdir)
|
||||||
cp $(srcdir)/m4/*.m4 $(distdir)/m4
|
cp $(srcdir)/m4/*.m4 $(distdir)/m4
|
||||||
|
|
37
README.md
37
README.md
|
@ -35,6 +35,7 @@ The goals of this implementation of the getdns API are:
|
||||||
|
|
||||||
* Provide an open source implementation, in C, of the formally described getdns API by getdns API team at <https://getdnsapi.net/spec.html>
|
* Provide an open source implementation, in C, of the formally described getdns API by getdns API team at <https://getdnsapi.net/spec.html>
|
||||||
* Initial support for FreeBSD, OSX, Linux (CentOS/RHEL, Ubuntu) via functional "configure" script
|
* Initial support for FreeBSD, OSX, Linux (CentOS/RHEL, Ubuntu) via functional "configure" script
|
||||||
|
* Initial support for Windows 8.1
|
||||||
* Initial support to include the Android platform
|
* Initial support to include the Android platform
|
||||||
* Include examples and tests as part of the build
|
* Include examples and tests as part of the build
|
||||||
* Document code using doxygen
|
* Document code using doxygen
|
||||||
|
@ -84,6 +85,7 @@ Building/External Dependencies
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
External dependencies are linked outside the getdns API build tree (we rely on configure to find them). We would like to keep the dependency tree short.
|
External dependencies are linked outside the getdns API build tree (we rely on configure to find them). We would like to keep the dependency tree short.
|
||||||
|
Please refer to section for building on Windows for separate dependency and build instructions.
|
||||||
|
|
||||||
* [libunbound from NLnet Labs](https://unbound.net/) version 1.4.16 or later.
|
* [libunbound from NLnet Labs](https://unbound.net/) version 1.4.16 or later.
|
||||||
* [libidn from the FSF](https://www.gnu.org/software/libidn/) version 1.
|
* [libidn from the FSF](https://www.gnu.org/software/libidn/) version 1.
|
||||||
|
@ -112,6 +114,8 @@ The implementation works with a variety of event loops, each built as a separate
|
||||||
* [libuv](https://github.com/joyent/libuv)
|
* [libuv](https://github.com/joyent/libuv)
|
||||||
* [libev](http://software.schmorp.de/pkg/libev.html)
|
* [libev](http://software.schmorp.de/pkg/libev.html)
|
||||||
|
|
||||||
|
NOTE: The current Windows implementation does not support the above.
|
||||||
|
|
||||||
## Regression Tests
|
## Regression Tests
|
||||||
|
|
||||||
A suite of regression tests are included with the library, if you make changes or just
|
A suite of regression tests are included with the library, if you make changes or just
|
||||||
|
@ -119,6 +123,8 @@ want to sanity check things on your system take a look at src/test. You will ne
|
||||||
to install [libcheck](http://check.sourceforge.net/) and [libldns from NLnet Labs](https://nlnetlabs.nl/projects/ldns/) version 1.6.17 or later. Both libraries are also available from
|
to install [libcheck](http://check.sourceforge.net/) and [libldns from NLnet Labs](https://nlnetlabs.nl/projects/ldns/) version 1.6.17 or later. Both libraries are also available from
|
||||||
many of the package repositories for the more popular operating systems.
|
many of the package repositories for the more popular operating systems.
|
||||||
|
|
||||||
|
NOTE: The current Windows implementation does not support the above.
|
||||||
|
|
||||||
## DNSSEC
|
## DNSSEC
|
||||||
|
|
||||||
For the library to be DNSSEC capable, it needs to know the root trust anchor.
|
For the library to be DNSSEC capable, it needs to know the root trust anchor.
|
||||||
|
@ -167,8 +173,9 @@ The primary platforms targeted are Linux and FreeBSD, other platform are support
|
||||||
* RHEL/CentOS 6.4
|
* RHEL/CentOS 6.4
|
||||||
* OSX 10.8
|
* OSX 10.8
|
||||||
* Ubuntu 14.04
|
* Ubuntu 14.04
|
||||||
|
* Microsoft Windows 8.1 (initial support for DNSSEC but no TLS provided for version 0.5.1)
|
||||||
|
|
||||||
We intend to add MS-Windows, Android and other platforms to the releases as we have time to port it.
|
We intend to add Android and other platforms to the releases as we have time to port it.
|
||||||
|
|
||||||
|
|
||||||
##Platform Specific Build Reports
|
##Platform Specific Build Reports
|
||||||
|
@ -233,6 +240,34 @@ Note that in order to compile the examples, the `--with-libevent` switch is requ
|
||||||
|
|
||||||
As of the 0.2.0 release, when installing via Homebrew, the trust anchor is expected to be located at `$(brew --prefix)/etc/getdns-root.key`. Additionally, the OpenSSL library installed by Homebrew is linked against. Note that the Homebrew OpenSSL installation clones the Keychain certificates to the default OpenSSL location so TLS certificate authentication should work out of the box.
|
As of the 0.2.0 release, when installing via Homebrew, the trust anchor is expected to be located at `$(brew --prefix)/etc/getdns-root.key`. Additionally, the OpenSSL library installed by Homebrew is linked against. Note that the Homebrew OpenSSL installation clones the Keychain certificates to the default OpenSSL location so TLS certificate authentication should work out of the box.
|
||||||
|
|
||||||
|
|
||||||
|
### Microsoft Windows 8.1
|
||||||
|
|
||||||
|
This section has some Windows specific build instructions.
|
||||||
|
|
||||||
|
Build tested using Mingw(3.21.0) and Msys 1.0 (http://www.mingw.org/) on Windows 8.1
|
||||||
|
|
||||||
|
Dependencies:
|
||||||
|
The following dependencies are built from source on Mingw
|
||||||
|
openssl1.0.2a
|
||||||
|
libidn
|
||||||
|
|
||||||
|
The windows version of getdns currently only is supported in the stub only mode.
|
||||||
|
|
||||||
|
To configure:
|
||||||
|
./configure --enable-stub-only --with-trust-anchor="c:\\\MinGW\\\msys\\\1.0\\\etc\\\unbound\\\getdns-root.key" --with-ssl=/c/OpenSSL --with-getdns_query
|
||||||
|
|
||||||
|
The trust anchor is also installed by unbound on c:\program Files (X86)\unbound\root.key and can be referenced from there
|
||||||
|
or anywhere else that the user chooses to configure it.
|
||||||
|
|
||||||
|
After configuring, do a 'make' and 'make install' to build getdns for Windows.
|
||||||
|
|
||||||
|
Example test queries:
|
||||||
|
./getdns_query.exe -s gmadkat.com A @64.6.64.6 +return_call_reporting (UDP)
|
||||||
|
./getdns_query.exe -s gmadkat.com A @64.6.64.6 -T +return_call_reporting (TCP)
|
||||||
|
./getdns_query.exe -s gmadkat.com A -l L @185.49.141.37 +return_call_reporting (TLS without authentication)
|
||||||
|
./getdns_query.exe -s www.huque.com A +dnssec_return_status +return_call_reporting (DNSSEC)
|
||||||
|
|
||||||
Contributors
|
Contributors
|
||||||
============
|
============
|
||||||
* Theogene Bucuti
|
* Theogene Bucuti
|
||||||
|
|
121
configure.ac
121
configure.ac
|
@ -32,6 +32,7 @@
|
||||||
AC_PREREQ([2.56])
|
AC_PREREQ([2.56])
|
||||||
AC_CONFIG_MACRO_DIRS([m4])
|
AC_CONFIG_MACRO_DIRS([m4])
|
||||||
sinclude(./m4/acx_openssl.m4)
|
sinclude(./m4/acx_openssl.m4)
|
||||||
|
sinclude(./m4/acx_getaddrinfo.m4)
|
||||||
sinclude(./m4/ax_check_compile_flag.m4)
|
sinclude(./m4/ax_check_compile_flag.m4)
|
||||||
sinclude(./m4/pkg.m4)
|
sinclude(./m4/pkg.m4)
|
||||||
|
|
||||||
|
@ -444,37 +445,53 @@ case "$enable_stub_only" in
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# search to set include and library paths right
|
# search to set include and library paths right
|
||||||
# find libidn
|
# find libidn (no libidn on windows though)
|
||||||
my_with_libidn=1
|
AC_CHECK_HEADERS([windows.h winsock.h stdio.h winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT])
|
||||||
AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
|
ACX_CHECK_GETADDRINFO_WITH_INCLUDES
|
||||||
[path to libidn (default: search /usr/local ..)]),
|
if test "$USE_WINSOCK" = 1; then
|
||||||
[], [withval="yes"])
|
AC_MSG_NOTICE([ Building on Windows ... YES! ])
|
||||||
if test x_$withval = x_yes; then
|
AC_DEFINE_UNQUOTED([GETDNS_ON_WINDOWS], [1], [Define this to enable Windows build.])
|
||||||
for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
|
AC_DEFINE_UNQUOTED([STUB_NATIVE_DNSSEC], [1])
|
||||||
if test -f "$dir/include/idna.h"; then
|
LIBS="$LIBS -lgdi32 -liphlpapi"
|
||||||
CFLAGS="$CFLAGS -I$dir/include"
|
my_with_libunbound=0
|
||||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
my_with_libidn=0
|
||||||
AC_MSG_NOTICE([Found libidn in $dir])
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
if test -f "$dir/include/idn/idna.h"; then
|
|
||||||
CFLAGS="$CFLAGS -I$dir/include/idn"
|
|
||||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
|
||||||
AC_MSG_NOTICE([Found libidn in $dir])
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if test -f "/usr/include/idn/idna.h"; then
|
|
||||||
CFLAGS="$CFLAGS -I/usr/include/idn"
|
|
||||||
#LDFLAGS="$LDFLAGS -L/usr/lib"
|
|
||||||
AC_MSG_NOTICE([Found libidn in /usr])
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
if test x_$withval != x_no; then
|
my_with_libidn=1
|
||||||
CFLAGS="$CFLAGS -I$withval/include"
|
fi
|
||||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
|
||||||
|
|
||||||
|
if test $my_with_libidn = 1
|
||||||
|
then
|
||||||
|
AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
|
||||||
|
[path to libidn (default: search /usr/local ..)]),
|
||||||
|
[], [withval="yes"])
|
||||||
|
if test x_$withval = x_yes; then
|
||||||
|
for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
|
||||||
|
if test -f "$dir/include/idna.h"; then
|
||||||
|
CFLAGS="$CFLAGS -I$dir/include"
|
||||||
|
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||||
|
AC_MSG_NOTICE([Found libidn in $dir])
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if test -f "$dir/include/idn/idna.h"; then
|
||||||
|
CFLAGS="$CFLAGS -I$dir/include/idn"
|
||||||
|
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||||
|
AC_MSG_NOTICE([Found libidn in $dir])
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -f "/usr/include/idn/idna.h"; then
|
||||||
|
CFLAGS="$CFLAGS -I/usr/include/idn"
|
||||||
|
#LDFLAGS="$LDFLAGS -L/usr/lib"
|
||||||
|
AC_MSG_NOTICE([Found libidn in /usr])
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
my_with_libidn=0
|
if test x_$withval != x_no; then
|
||||||
|
CFLAGS="$CFLAGS -I$withval/include"
|
||||||
|
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||||
|
else
|
||||||
|
my_with_libidn=0
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -942,6 +959,8 @@ if test $ac_cv_c_unused_attribute = yes; then
|
||||||
AC_DEFINE(HAVE_ATTR_UNUSED, 1, [Whether the C compiler accepts the "unused" attribute])
|
AC_DEFINE(HAVE_ATTR_UNUSED, 1, [Whether the C compiler accepts the "unused" attribute])
|
||||||
fi
|
fi
|
||||||
AC_CHECK_DECLS([strlcpy,arc4random,arc4random_uniform])
|
AC_CHECK_DECLS([strlcpy,arc4random,arc4random_uniform])
|
||||||
|
AC_REPLACE_FUNCS(inet_pton)
|
||||||
|
AC_REPLACE_FUNCS(inet_ntop)
|
||||||
AC_REPLACE_FUNCS(strlcpy)
|
AC_REPLACE_FUNCS(strlcpy)
|
||||||
AC_REPLACE_FUNCS(arc4random)
|
AC_REPLACE_FUNCS(arc4random)
|
||||||
AC_REPLACE_FUNCS(arc4random_uniform)
|
AC_REPLACE_FUNCS(arc4random_uniform)
|
||||||
|
@ -999,6 +1018,35 @@ esac
|
||||||
AC_SUBST(C99COMPATFLAGS)
|
AC_SUBST(C99COMPATFLAGS)
|
||||||
|
|
||||||
AH_BOTTOM([
|
AH_BOTTOM([
|
||||||
|
|
||||||
|
/* the version of the windows API enabled */
|
||||||
|
#undef WINVER
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define WINVER 0x0600 // 0x0502
|
||||||
|
#define _WIN32_WINNT 0x0600 // 0x0502
|
||||||
|
#ifdef HAVE_WINSOCK2_H
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include<BaseTsd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_WS2TCPIP_H
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
|
#define ARG_LL "%ll"
|
||||||
|
#else
|
||||||
|
#define ARG_LL "%I64"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
|
||||||
|
#ifdef HAVE_WINSOCK2_H
|
||||||
|
#define FD_SET_T (u_int)
|
||||||
|
#else
|
||||||
|
#define FD_SET_T
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -1055,6 +1103,14 @@ void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
|
||||||
unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest);
|
unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest);
|
||||||
#endif /* COMPAT_SHA512 */
|
#endif /* COMPAT_SHA512 */
|
||||||
|
|
||||||
|
#ifndef HAVE_INET_PTON
|
||||||
|
int inet_pton(int af, const char* src, void* dst);
|
||||||
|
#endif /* HAVE_INET_PTON */
|
||||||
|
|
||||||
|
#ifndef HAVE_INET_NTOP
|
||||||
|
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1108,13 +1164,6 @@ unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest);
|
||||||
# define ATTR_UNUSED(x) x
|
# define ATTR_UNUSED(x) x
|
||||||
#endif /* !HAVE_ATTR_UNUSED */
|
#endif /* !HAVE_ATTR_UNUSED */
|
||||||
|
|
||||||
/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
|
|
||||||
#ifdef HAVE_WINSOCK2_H
|
|
||||||
#define FD_SET_T (u_int)
|
|
||||||
#else
|
|
||||||
#define FD_SET_T
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TIME_WITH_SYS_TIME
|
#ifdef TIME_WITH_SYS_TIME
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
# Taken from acx_nlnetlabs.m4 - common macros for configure checks
|
||||||
|
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||||
|
# BSD licensed.
|
||||||
|
#
|
||||||
|
|
||||||
|
dnl Check getaddrinfo.
|
||||||
|
dnl Works on linux, solaris, bsd and windows(links winsock).
|
||||||
|
dnl defines HAVE_GETADDRINFO, USE_WINSOCK.
|
||||||
|
AC_DEFUN([ACX_CHECK_GETADDRINFO_WITH_INCLUDES],
|
||||||
|
[AC_REQUIRE([AC_PROG_CC])
|
||||||
|
AC_MSG_CHECKING(for getaddrinfo)
|
||||||
|
ac_cv_func_getaddrinfo=no
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
[AC_LANG_SOURCE([[
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
char* getaddrinfo();
|
||||||
|
char* (*f) () = getaddrinfo;
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
int main() {
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
]])],
|
||||||
|
dnl this case on linux, solaris, bsd
|
||||||
|
[ac_cv_func_getaddrinfo="yes"
|
||||||
|
dnl see if on windows
|
||||||
|
if test "$ac_cv_header_windows_h" = "yes"; then
|
||||||
|
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||||
|
USE_WINSOCK="1"
|
||||||
|
LIBS="$LIBS -lws2_32"
|
||||||
|
fi
|
||||||
|
],
|
||||||
|
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
|
||||||
|
ORIGLIBS="$LIBS"
|
||||||
|
LIBS="$LIBS -lws2_32"
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM(
|
||||||
|
[
|
||||||
|
#define _WIN32_WINNT 0x0501
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WINSOCK_H
|
||||||
|
#include <winsock.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WINSOCK2_H
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_WS2TCPIP_H
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#endif
|
||||||
|
],
|
||||||
|
[
|
||||||
|
(void)getaddrinfo(NULL, NULL, NULL, NULL);
|
||||||
|
]
|
||||||
|
)],
|
||||||
|
[
|
||||||
|
ac_cv_func_getaddrinfo="yes"
|
||||||
|
dnl already: LIBS="$LIBS -lws2_32"
|
||||||
|
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||||
|
USE_WINSOCK="1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
ac_cv_func_getaddrinfo="no"
|
||||||
|
LIBS="$ORIGLIBS"
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_MSG_RESULT($ac_cv_func_getaddrinfo)
|
||||||
|
if test $ac_cv_func_getaddrinfo = yes; then
|
||||||
|
AC_DEFINE(HAVE_GETADDRINFO, 1, [Whether getaddrinfo is available])
|
||||||
|
fi
|
||||||
|
])dnl Endof AC_CHECK_GETADDRINFO_WITH_INCLUDES
|
||||||
|
|
||||||
|
dnl End of file
|
|
@ -74,7 +74,7 @@ LIBOBJDIR=
|
||||||
LIBOBJS=@LIBOBJS@
|
LIBOBJS=@LIBOBJS@
|
||||||
COMPAT_OBJ=$(LIBOBJS:.o=.lo)
|
COMPAT_OBJ=$(LIBOBJS:.o=.lo)
|
||||||
|
|
||||||
UTIL_OBJ=mini_event.lo rbtree.lo val_secalgo.lo
|
UTIL_OBJ=mini_event.lo winsock_event.lo rbtree.lo val_secalgo.lo
|
||||||
|
|
||||||
EXTENSION_OBJ=libmini_event.lo libevent.lo libev.lo
|
EXTENSION_OBJ=libmini_event.lo libevent.lo libev.lo
|
||||||
|
|
||||||
|
@ -238,11 +238,11 @@ convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns
|
||||||
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
||||||
$(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
$(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
||||||
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/convert.h
|
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/convert.h
|
||||||
dict.lo dict.o: $(srcdir)/dict.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
|
dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
|
||||||
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
|
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \
|
||||||
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
$(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h \
|
||||||
$(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
$(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||||
$(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
|
$(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
|
||||||
dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \
|
dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \
|
||||||
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
|
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
|
||||||
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
||||||
|
@ -309,6 +309,8 @@ getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c conf
|
||||||
getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h
|
getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h
|
||||||
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h
|
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h
|
||||||
getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
|
getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
|
||||||
|
inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h
|
||||||
|
inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h
|
||||||
sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h
|
sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h
|
||||||
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
|
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
|
||||||
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
||||||
|
@ -317,6 +319,7 @@ rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcd
|
||||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h
|
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h
|
||||||
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \
|
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \
|
||||||
$(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h
|
$(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h
|
||||||
|
winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.h
|
||||||
libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
|
libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
|
||||||
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
|
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
|
||||||
$(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h
|
$(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h
|
||||||
|
|
|
@ -33,8 +33,42 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#ifndef UB_ON_WINDOWS
|
#ifndef GETDNS_ON_WINDOWS
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#else
|
||||||
|
#include <wincrypt.h>
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
int getentropy(void *buf, size_t len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On Windows, CryptGenRandom is supposed to be a well-seeded
|
||||||
|
* cryptographically strong random number generator.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getentropy(void *buf, size_t len)
|
||||||
|
{
|
||||||
|
HCRYPTPROV provider;
|
||||||
|
|
||||||
|
if (len > 256) {
|
||||||
|
errno = EIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
|
||||||
|
CRYPT_VERIFYCONTEXT) == 0)
|
||||||
|
goto fail;
|
||||||
|
if (CryptGenRandom(provider, len, buf) == 0) {
|
||||||
|
CryptReleaseContext(provider, 0);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
CryptReleaseContext(provider, 0);
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
errno = EIO;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define KEYSTREAM_ONLY
|
#define KEYSTREAM_ONLY
|
||||||
|
@ -73,7 +107,7 @@ _rs_init(u_char *buf, size_t n)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (rs == NULL) {
|
if (rs == NULL) {
|
||||||
#ifndef UB_ON_WINDOWS
|
#ifndef GETDNS_ON_WINDOWS
|
||||||
if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE,
|
if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE,
|
||||||
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
|
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
|
||||||
abort();
|
abort();
|
||||||
|
@ -88,7 +122,7 @@ _rs_init(u_char *buf, size_t n)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (rsx == NULL) {
|
if (rsx == NULL) {
|
||||||
#ifndef UB_ON_WINDOWS
|
#ifndef GETDNS_ON_WINDOWS
|
||||||
if ((rsx = mmap(NULL, sizeof(*rsx), PROT_READ|PROT_WRITE,
|
if ((rsx = mmap(NULL, sizeof(*rsx), PROT_READ|PROT_WRITE,
|
||||||
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
|
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
|
||||||
abort();
|
abort();
|
||||||
|
|
|
@ -16,7 +16,10 @@
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#ifndef GETDNS_ON_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#define _POSIX_C_SOURCE 199309L
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
@ -538,3 +541,4 @@ getentropy_fallback(void *buf, size_t len)
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,218 @@
|
||||||
|
/* From openssh 4.3p2 compat/inet_ntop.c */
|
||||||
|
/* Copyright (c) 1996 by Internet Software Consortium.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||||
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||||
|
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* OPENBSD ORIGINAL: lib/libc/net/inet_ntop.c */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifndef HAVE_INET_NTOP
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef IN6ADDRSZ
|
||||||
|
#define IN6ADDRSZ 16 /* IPv6 T_AAAA */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INT16SZ
|
||||||
|
#define INT16SZ 2 /* for systems without 16-bit ints */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WARNING: Don't even consider trying to compile this on a system where
|
||||||
|
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
|
||||||
|
static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
|
||||||
|
|
||||||
|
/* char *
|
||||||
|
* inet_ntop(af, src, dst, size)
|
||||||
|
* convert a network format address to presentation format.
|
||||||
|
* return:
|
||||||
|
* pointer to presentation format address (`dst'), or NULL (see errno).
|
||||||
|
* author:
|
||||||
|
* Paul Vixie, 1996.
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
inet_ntop(int af, const void *src, char *dst, size_t size)
|
||||||
|
{
|
||||||
|
switch (af) {
|
||||||
|
case AF_INET:
|
||||||
|
return (inet_ntop4(src, dst, size));
|
||||||
|
case AF_INET6:
|
||||||
|
return (inet_ntop6(src, dst, size));
|
||||||
|
default:
|
||||||
|
#ifdef EAFNOSUPPORT
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
#endif
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* const char *
|
||||||
|
* inet_ntop4(src, dst, size)
|
||||||
|
* format an IPv4 address, more or less like inet_ntoa()
|
||||||
|
* return:
|
||||||
|
* `dst' (as a const)
|
||||||
|
* notes:
|
||||||
|
* (1) uses no statics
|
||||||
|
* (2) takes a u_char* not an in_addr as input
|
||||||
|
* author:
|
||||||
|
* Paul Vixie, 1996.
|
||||||
|
*/
|
||||||
|
static const char *
|
||||||
|
inet_ntop4(const u_char *src, char *dst, size_t size)
|
||||||
|
{
|
||||||
|
static const char fmt[] = "%u.%u.%u.%u";
|
||||||
|
char tmp[sizeof "255.255.255.255"];
|
||||||
|
int l;
|
||||||
|
|
||||||
|
l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
|
||||||
|
if (l <= 0 || l >= (int)size) {
|
||||||
|
errno = ENOSPC;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
strlcpy(dst, tmp, size);
|
||||||
|
return (dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* const char *
|
||||||
|
* inet_ntop6(src, dst, size)
|
||||||
|
* convert IPv6 binary address into presentation (printable) format
|
||||||
|
* author:
|
||||||
|
* Paul Vixie, 1996.
|
||||||
|
*/
|
||||||
|
static const char *
|
||||||
|
inet_ntop6(const u_char *src, char *dst, size_t size)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Note that int32_t and int16_t need only be "at least" large enough
|
||||||
|
* to contain a value of the specified size. On some systems, like
|
||||||
|
* Crays, there is no such thing as an integer variable with 16 bits.
|
||||||
|
* Keep this in mind if you think this function should have been coded
|
||||||
|
* to use pointer overlays. All the world's not a VAX.
|
||||||
|
*/
|
||||||
|
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
|
||||||
|
char *tp, *ep;
|
||||||
|
struct { int base, len; } best, cur;
|
||||||
|
u_int words[IN6ADDRSZ / INT16SZ];
|
||||||
|
int i;
|
||||||
|
int advance;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Preprocess:
|
||||||
|
* Copy the input (bytewise) array into a wordwise array.
|
||||||
|
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
||||||
|
*/
|
||||||
|
memset(words, '\0', sizeof words);
|
||||||
|
for (i = 0; i < IN6ADDRSZ; i++)
|
||||||
|
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||||
|
best.base = -1;
|
||||||
|
best.len = 0;
|
||||||
|
cur.base = -1;
|
||||||
|
cur.len = 0;
|
||||||
|
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
|
||||||
|
if (words[i] == 0) {
|
||||||
|
if (cur.base == -1)
|
||||||
|
cur.base = i, cur.len = 1;
|
||||||
|
else
|
||||||
|
cur.len++;
|
||||||
|
} else {
|
||||||
|
if (cur.base != -1) {
|
||||||
|
if (best.base == -1 || cur.len > best.len)
|
||||||
|
best = cur;
|
||||||
|
cur.base = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cur.base != -1) {
|
||||||
|
if (best.base == -1 || cur.len > best.len)
|
||||||
|
best = cur;
|
||||||
|
}
|
||||||
|
if (best.base != -1 && best.len < 2)
|
||||||
|
best.base = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format the result.
|
||||||
|
*/
|
||||||
|
tp = tmp;
|
||||||
|
ep = tmp + sizeof(tmp);
|
||||||
|
for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
|
||||||
|
/* Are we inside the best run of 0x00's? */
|
||||||
|
if (best.base != -1 && i >= best.base &&
|
||||||
|
i < (best.base + best.len)) {
|
||||||
|
if (i == best.base) {
|
||||||
|
if (tp + 1 >= ep)
|
||||||
|
return (NULL);
|
||||||
|
*tp++ = ':';
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Are we following an initial run of 0x00s or any real hex? */
|
||||||
|
if (i != 0) {
|
||||||
|
if (tp + 1 >= ep)
|
||||||
|
return (NULL);
|
||||||
|
*tp++ = ':';
|
||||||
|
}
|
||||||
|
/* Is this address an encapsulated IPv4? */
|
||||||
|
if (i == 6 && best.base == 0 &&
|
||||||
|
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
|
||||||
|
if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
|
||||||
|
return (NULL);
|
||||||
|
tp += strlen(tp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
advance = snprintf(tp, ep - tp, "%x", words[i]);
|
||||||
|
if (advance <= 0 || advance >= ep - tp)
|
||||||
|
return (NULL);
|
||||||
|
tp += advance;
|
||||||
|
}
|
||||||
|
/* Was it a trailing run of 0x00's? */
|
||||||
|
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
|
||||||
|
if (tp + 1 >= ep)
|
||||||
|
return (NULL);
|
||||||
|
*tp++ = ':';
|
||||||
|
}
|
||||||
|
if (tp + 1 >= ep)
|
||||||
|
return (NULL);
|
||||||
|
*tp++ = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for overflow, copy, and we're done.
|
||||||
|
*/
|
||||||
|
if ((size_t)(tp - tmp) > size) {
|
||||||
|
errno = ENOSPC;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
strlcpy(dst, tmp, size);
|
||||||
|
return (dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !HAVE_INET_NTOP */
|
|
@ -0,0 +1,230 @@
|
||||||
|
/* $KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */
|
||||||
|
|
||||||
|
/* Copyright (c) 1996 by Internet Software Consortium.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||||
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||||
|
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WARNING: Don't even consider trying to compile this on a system where
|
||||||
|
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int inet_pton4 (const char *src, uint8_t *dst);
|
||||||
|
static int inet_pton6 (const char *src, uint8_t *dst);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* The definitions we might miss.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef NS_INT16SZ
|
||||||
|
#define NS_INT16SZ 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NS_IN6ADDRSZ
|
||||||
|
#define NS_IN6ADDRSZ 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NS_INADDRSZ
|
||||||
|
#define NS_INADDRSZ 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* int
|
||||||
|
* inet_pton(af, src, dst)
|
||||||
|
* convert from presentation format (which usually means ASCII printable)
|
||||||
|
* to network format (which is usually some kind of binary format).
|
||||||
|
* return:
|
||||||
|
* 1 if the address was valid for the specified address family
|
||||||
|
* 0 if the address wasn't valid (`dst' is untouched in this case)
|
||||||
|
* -1 if some other error occurred (`dst' is untouched in this case, too)
|
||||||
|
* author:
|
||||||
|
* Paul Vixie, 1996.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
inet_pton(af, src, dst)
|
||||||
|
int af;
|
||||||
|
const char *src;
|
||||||
|
void *dst;
|
||||||
|
{
|
||||||
|
switch (af) {
|
||||||
|
case AF_INET:
|
||||||
|
return (inet_pton4(src, dst));
|
||||||
|
case AF_INET6:
|
||||||
|
return (inet_pton6(src, dst));
|
||||||
|
default:
|
||||||
|
#ifdef EAFNOSUPPORT
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
#endif
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* int
|
||||||
|
* inet_pton4(src, dst)
|
||||||
|
* like inet_aton() but without all the hexadecimal and shorthand.
|
||||||
|
* return:
|
||||||
|
* 1 if `src' is a valid dotted quad, else 0.
|
||||||
|
* notice:
|
||||||
|
* does not touch `dst' unless it's returning 1.
|
||||||
|
* author:
|
||||||
|
* Paul Vixie, 1996.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
inet_pton4(src, dst)
|
||||||
|
const char *src;
|
||||||
|
uint8_t *dst;
|
||||||
|
{
|
||||||
|
static const char digits[] = "0123456789";
|
||||||
|
int saw_digit, octets, ch;
|
||||||
|
uint8_t tmp[NS_INADDRSZ], *tp;
|
||||||
|
|
||||||
|
saw_digit = 0;
|
||||||
|
octets = 0;
|
||||||
|
*(tp = tmp) = 0;
|
||||||
|
while ((ch = *src++) != '\0') {
|
||||||
|
const char *pch;
|
||||||
|
|
||||||
|
if ((pch = strchr(digits, ch)) != NULL) {
|
||||||
|
uint32_t new = *tp * 10 + (pch - digits);
|
||||||
|
|
||||||
|
if (new > 255)
|
||||||
|
return (0);
|
||||||
|
*tp = new;
|
||||||
|
if (! saw_digit) {
|
||||||
|
if (++octets > 4)
|
||||||
|
return (0);
|
||||||
|
saw_digit = 1;
|
||||||
|
}
|
||||||
|
} else if (ch == '.' && saw_digit) {
|
||||||
|
if (octets == 4)
|
||||||
|
return (0);
|
||||||
|
*++tp = 0;
|
||||||
|
saw_digit = 0;
|
||||||
|
} else
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (octets < 4)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
memcpy(dst, tmp, NS_INADDRSZ);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* int
|
||||||
|
* inet_pton6(src, dst)
|
||||||
|
* convert presentation level address to network order binary form.
|
||||||
|
* return:
|
||||||
|
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
|
||||||
|
* notice:
|
||||||
|
* (1) does not touch `dst' unless it's returning 1.
|
||||||
|
* (2) :: in a full address is silently ignored.
|
||||||
|
* credit:
|
||||||
|
* inspired by Mark Andrews.
|
||||||
|
* author:
|
||||||
|
* Paul Vixie, 1996.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
inet_pton6(src, dst)
|
||||||
|
const char *src;
|
||||||
|
uint8_t *dst;
|
||||||
|
{
|
||||||
|
static const char xdigits_l[] = "0123456789abcdef",
|
||||||
|
xdigits_u[] = "0123456789ABCDEF";
|
||||||
|
uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
|
||||||
|
const char *xdigits, *curtok;
|
||||||
|
int ch, saw_xdigit;
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
|
||||||
|
endp = tp + NS_IN6ADDRSZ;
|
||||||
|
colonp = NULL;
|
||||||
|
/* Leading :: requires some special handling. */
|
||||||
|
if (*src == ':')
|
||||||
|
if (*++src != ':')
|
||||||
|
return (0);
|
||||||
|
curtok = src;
|
||||||
|
saw_xdigit = 0;
|
||||||
|
val = 0;
|
||||||
|
while ((ch = *src++) != '\0') {
|
||||||
|
const char *pch;
|
||||||
|
|
||||||
|
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
|
||||||
|
pch = strchr((xdigits = xdigits_u), ch);
|
||||||
|
if (pch != NULL) {
|
||||||
|
val <<= 4;
|
||||||
|
val |= (pch - xdigits);
|
||||||
|
if (val > 0xffff)
|
||||||
|
return (0);
|
||||||
|
saw_xdigit = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ch == ':') {
|
||||||
|
curtok = src;
|
||||||
|
if (!saw_xdigit) {
|
||||||
|
if (colonp)
|
||||||
|
return (0);
|
||||||
|
colonp = tp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tp + NS_INT16SZ > endp)
|
||||||
|
return (0);
|
||||||
|
*tp++ = (uint8_t) (val >> 8) & 0xff;
|
||||||
|
*tp++ = (uint8_t) val & 0xff;
|
||||||
|
saw_xdigit = 0;
|
||||||
|
val = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
|
||||||
|
inet_pton4(curtok, tp) > 0) {
|
||||||
|
tp += NS_INADDRSZ;
|
||||||
|
saw_xdigit = 0;
|
||||||
|
break; /* '\0' was seen by inet_pton4(). */
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (saw_xdigit) {
|
||||||
|
if (tp + NS_INT16SZ > endp)
|
||||||
|
return (0);
|
||||||
|
*tp++ = (uint8_t) (val >> 8) & 0xff;
|
||||||
|
*tp++ = (uint8_t) val & 0xff;
|
||||||
|
}
|
||||||
|
if (colonp != NULL) {
|
||||||
|
/*
|
||||||
|
* Since some memmove()'s erroneously fail to handle
|
||||||
|
* overlapping regions, we'll do the shift by hand.
|
||||||
|
*/
|
||||||
|
const int n = tp - colonp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i <= n; i++) {
|
||||||
|
endp[- i] = colonp[n - i];
|
||||||
|
colonp[n - i] = 0;
|
||||||
|
}
|
||||||
|
tp = endp;
|
||||||
|
}
|
||||||
|
if (tp != endp)
|
||||||
|
return (0);
|
||||||
|
memcpy(dst, tmp, NS_IN6ADDRSZ);
|
||||||
|
return (1);
|
||||||
|
}
|
115
src/context.c
115
src/context.c
|
@ -34,14 +34,24 @@
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#else
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
typedef unsigned short in_port_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <netdb.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -97,7 +107,6 @@ getdns_port_str_array[] = {
|
||||||
/* Private functions */
|
/* Private functions */
|
||||||
static getdns_return_t create_default_namespaces(struct getdns_context *context);
|
static getdns_return_t create_default_namespaces(struct getdns_context *context);
|
||||||
static getdns_return_t create_default_dns_transports(struct getdns_context *context);
|
static getdns_return_t create_default_dns_transports(struct getdns_context *context);
|
||||||
static getdns_return_t set_os_defaults(struct getdns_context *);
|
|
||||||
static int transaction_id_cmp(const void *, const void *);
|
static int transaction_id_cmp(const void *, const void *);
|
||||||
static void dispatch_updated(struct getdns_context *, uint16_t);
|
static void dispatch_updated(struct getdns_context *, uint16_t);
|
||||||
static void cancel_dns_req(getdns_dns_req *);
|
static void cancel_dns_req(getdns_dns_req *);
|
||||||
|
@ -358,7 +367,11 @@ create_local_hosts(getdns_context *context)
|
||||||
int start_of_line = 1;
|
int start_of_line = 1;
|
||||||
getdns_dict *address = NULL;
|
getdns_dict *address = NULL;
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
in = fopen("c:\\WINDOWS\\system32\\drivers\\etc\\hosts", "r");
|
||||||
|
#else
|
||||||
in = fopen("/etc/hosts", "r");
|
in = fopen("/etc/hosts", "r");
|
||||||
|
#endif
|
||||||
while (fgets(pos, (int)(sizeof(buf) - (pos - buf)), in)) {
|
while (fgets(pos, (int)(sizeof(buf) - (pos - buf)), in)) {
|
||||||
pos = buf;
|
pos = buf;
|
||||||
/* Break out of for to read more */
|
/* Break out of for to read more */
|
||||||
|
@ -700,6 +713,89 @@ upstream_init(getdns_upstream *upstream,
|
||||||
net_req_query_id_cmp);
|
net_req_query_id_cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
static getdns_return_t
|
||||||
|
set_os_defaults_windows(struct getdns_context *context)
|
||||||
|
{
|
||||||
|
char domain[1024];
|
||||||
|
size_t upstreams_limit = 10, length;
|
||||||
|
struct getdns_bindata bindata;
|
||||||
|
struct addrinfo hints;
|
||||||
|
struct addrinfo *result;
|
||||||
|
getdns_upstream *upstream;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
if (context->fchg_resolvconf == NULL) {
|
||||||
|
context->fchg_resolvconf =
|
||||||
|
GETDNS_MALLOC(context->my_mf, struct filechg);
|
||||||
|
if (context->fchg_resolvconf == NULL)
|
||||||
|
return GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
context->fchg_resolvconf->fn = "InvalidOnWindows";
|
||||||
|
context->fchg_resolvconf->prevstat = NULL;
|
||||||
|
context->fchg_resolvconf->changes = GETDNS_FCHG_NOCHANGES;
|
||||||
|
context->fchg_resolvconf->errors = GETDNS_FCHG_NOERROR;
|
||||||
|
}
|
||||||
|
_getdns_filechg_check(context, context->fchg_resolvconf);
|
||||||
|
|
||||||
|
context->suffix = getdns_list_create_with_context(context);
|
||||||
|
context->upstreams = upstreams_create(context, upstreams_limit);
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
|
||||||
|
hints.ai_socktype = 0; /* Datagram socket */
|
||||||
|
hints.ai_flags = AI_NUMERICHOST; /* No reverse name lookups */
|
||||||
|
hints.ai_protocol = 0; /* Any protocol */
|
||||||
|
hints.ai_canonname = NULL;
|
||||||
|
hints.ai_addr = NULL;
|
||||||
|
hints.ai_next = NULL;
|
||||||
|
|
||||||
|
FIXED_INFO *info;
|
||||||
|
ULONG buflen = sizeof(*info);
|
||||||
|
IP_ADDR_STRING *ptr = 0;
|
||||||
|
|
||||||
|
info = (FIXED_INFO *)malloc(sizeof(FIXED_INFO));
|
||||||
|
if (info == NULL)
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
|
if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) {
|
||||||
|
free(info);
|
||||||
|
info = (FIXED_INFO *)malloc(buflen);
|
||||||
|
if (info == NULL)
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetNetworkParams(info, &buflen) == NO_ERROR) {
|
||||||
|
ptr = info->DnsServerList.Next;
|
||||||
|
*domain = 0;
|
||||||
|
while (ptr) {
|
||||||
|
for (size_t i = 0; i < GETDNS_UPSTREAM_TRANSPORTS; i++) {
|
||||||
|
char *port_str = getdns_port_str_array[i];
|
||||||
|
if ((s = getaddrinfo(ptr->IpAddress.String, port_str, &hints, &result)))
|
||||||
|
continue;
|
||||||
|
if (!result)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
upstream = &context->upstreams->
|
||||||
|
upstreams[context->upstreams->count++];
|
||||||
|
upstream_init(upstream, context->upstreams, result);
|
||||||
|
upstream->transport = getdns_upstream_transports[i];
|
||||||
|
freeaddrinfo(result);
|
||||||
|
}
|
||||||
|
ptr = ptr->Next;
|
||||||
|
|
||||||
|
}
|
||||||
|
free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)getdns_list_get_length(context->suffix, &length);
|
||||||
|
if (length == 0 && *domain != 0) {
|
||||||
|
bindata.data = (uint8_t *)domain;
|
||||||
|
bindata.size = strlen(domain) + 1;
|
||||||
|
(void)getdns_list_set_bindata(context->suffix, 0, &bindata);
|
||||||
|
}
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
} /* set_os_defaults_windows */
|
||||||
|
#else
|
||||||
static getdns_return_t
|
static getdns_return_t
|
||||||
set_os_defaults(struct getdns_context *context)
|
set_os_defaults(struct getdns_context *context)
|
||||||
{
|
{
|
||||||
|
@ -811,6 +907,7 @@ set_os_defaults(struct getdns_context *context)
|
||||||
_getdns_list_append_string(context->suffix, domain);
|
_getdns_list_append_string(context->suffix, domain);
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
} /* set_os_defaults */
|
} /* set_os_defaults */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* compare of transaction ids in DESCENDING order
|
/* compare of transaction ids in DESCENDING order
|
||||||
so that 0 comes last
|
so that 0 comes last
|
||||||
|
@ -953,8 +1050,14 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
result->fchg_resolvconf = NULL;
|
result->fchg_resolvconf = NULL;
|
||||||
result->fchg_hosts = NULL;
|
result->fchg_hosts = NULL;
|
||||||
|
|
||||||
|
// resolv.conf does not exist on Windows, handle differently
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
if (set_from_os && (r = set_os_defaults(result)))
|
if (set_from_os && (r = set_os_defaults(result)))
|
||||||
goto error;
|
goto error;
|
||||||
|
#else
|
||||||
|
if (set_from_os && (r = set_os_defaults_windows(result)))
|
||||||
|
goto error;
|
||||||
|
#endif
|
||||||
|
|
||||||
result->dnssec_allowed_skew = 0;
|
result->dnssec_allowed_skew = 0;
|
||||||
result->edns_maximum_udp_payload_size = -1;
|
result->edns_maximum_udp_payload_size = -1;
|
||||||
|
@ -2443,7 +2546,11 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context,
|
||||||
/* Create client context, use TLS v1.2 only for now */
|
/* Create client context, use TLS v1.2 only for now */
|
||||||
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
|
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
|
||||||
if(context->tls_ctx == NULL)
|
if(context->tls_ctx == NULL)
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
return GETDNS_RETURN_BAD_CONTEXT;
|
return GETDNS_RETURN_BAD_CONTEXT;
|
||||||
|
#else
|
||||||
|
printf("Warning! Bad TLS context, check openssl version on Windows!\n");;
|
||||||
|
#endif
|
||||||
/* Be strict and only use the cipher suites recommended in RFC7525
|
/* Be strict and only use the cipher suites recommended in RFC7525
|
||||||
Unless we later fallback to opportunistic. */
|
Unless we later fallback to opportunistic. */
|
||||||
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM";
|
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM";
|
||||||
|
|
|
@ -34,9 +34,11 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_LIBIDN
|
#ifdef HAVE_LIBIDN
|
||||||
#include <stringprep.h>
|
#include <stringprep.h>
|
||||||
#include <idna.h>
|
#include <idna.h>
|
||||||
|
|
|
@ -35,10 +35,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include "config.h"
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "types-internal.h"
|
#include "types-internal.h"
|
||||||
#include "util-internal.h"
|
#include "util-internal.h"
|
||||||
|
|
|
@ -206,6 +206,17 @@ _getdns_mini_event_init(getdns_context *context, _getdns_mini_event *ext)
|
||||||
if (!ext)
|
if (!ext)
|
||||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
int r;
|
||||||
|
WSADATA wsa_data;
|
||||||
|
|
||||||
|
if ((r = WSAStartup(MAKEWORD(2, 2), &wsa_data)) != 0) {
|
||||||
|
printf("could not init winsock. WSAStartup: %s",
|
||||||
|
wsa_strerror(r));
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ext->n_events = 0;
|
ext->n_events = 0;
|
||||||
ext->loop.vmt = &_getdns_mini_event_vmt;
|
ext->loop.vmt = &_getdns_mini_event_vmt;
|
||||||
ext->base = _getdns_event_init(&ext->time_secs, &ext->time_tv);
|
ext->base = _getdns_event_init(&ext->time_secs, &ext->time_tv);
|
||||||
|
|
|
@ -35,7 +35,11 @@
|
||||||
#define _GETDNS_LIBMINI_EVENT_H_
|
#define _GETDNS_LIBMINI_EVENT_H_
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
#include "util/mini_event.h"
|
#include "util/mini_event.h"
|
||||||
|
#else
|
||||||
|
#include "util/winsock_event.h"
|
||||||
|
#endif
|
||||||
#include "types-internal.h"
|
#include "types-internal.h"
|
||||||
|
|
||||||
typedef struct _getdns_mini_event {
|
typedef struct _getdns_mini_event {
|
||||||
|
|
|
@ -346,50 +346,50 @@ _getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
|
||||||
switch (address_data->size) {
|
switch (address_data->size) {
|
||||||
case 4:
|
case 4:
|
||||||
(void)snprintf(name, sizeof(name),
|
(void)snprintf(name, sizeof(name),
|
||||||
"%hhu.%hhu.%hhu.%hhu.in-addr.arpa.",
|
"%d.%d.%d.%d.in-addr.arpa.",
|
||||||
((uint8_t *)address_data->data)[3],
|
(int)((uint8_t *)address_data->data)[3],
|
||||||
((uint8_t *)address_data->data)[2],
|
(int)((uint8_t *)address_data->data)[2],
|
||||||
((uint8_t *)address_data->data)[1],
|
(int)((uint8_t *)address_data->data)[1],
|
||||||
((uint8_t *)address_data->data)[0]);
|
(int)((uint8_t *)address_data->data)[0]);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
(void)snprintf(name, sizeof(name),
|
(void)snprintf(name, sizeof(name),
|
||||||
"%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx."
|
"%x.%x.%x.%x.%x.%x.%x.%x."
|
||||||
"%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx."
|
"%x.%x.%x.%x.%x.%x.%x.%x."
|
||||||
"%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx."
|
"%x.%x.%x.%x.%x.%x.%x.%x."
|
||||||
"%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.ip6.arpa.",
|
"%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[15] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[15] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[15] >> 4),
|
(int)(((uint8_t *)address_data->data)[15] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[14] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[14] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[14] >> 4),
|
(int)(((uint8_t *)address_data->data)[14] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[13] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[13] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[13] >> 4),
|
(int)(((uint8_t *)address_data->data)[13] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[12] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[12] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[12] >> 4),
|
(int)(((uint8_t *)address_data->data)[12] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[11] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[11] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[11] >> 4),
|
(int)(((uint8_t *)address_data->data)[11] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[10] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[10] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[10] >> 4),
|
(int)(((uint8_t *)address_data->data)[10] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[9] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[9] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[9] >> 4),
|
(int)(((uint8_t *)address_data->data)[9] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[8] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[8] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[8] >> 4),
|
(int)(((uint8_t *)address_data->data)[8] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[7] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[7] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[7] >> 4),
|
(int)(((uint8_t *)address_data->data)[7] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[6] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[6] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[6] >> 4),
|
(int)(((uint8_t *)address_data->data)[6] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[5] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[5] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[5] >> 4),
|
(int)(((uint8_t *)address_data->data)[5] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[4] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[4] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[4] >> 4),
|
(int)(((uint8_t *)address_data->data)[4] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[3] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[3] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[3] >> 4),
|
(int)(((uint8_t *)address_data->data)[3] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[2] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[2] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[2] >> 4),
|
(int)(((uint8_t *)address_data->data)[2] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[1] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[1] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[1] >> 4),
|
(int)(((uint8_t *)address_data->data)[1] >> 4),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[0] & 0x0F),
|
(int)(((uint8_t *)address_data->data)[0] & 0x0F),
|
||||||
(uint8_t)(((uint8_t *)address_data->data)[0] >> 4));
|
(int)(((uint8_t *)address_data->data)[0] >> 4));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
|
41
src/stub.c
41
src/stub.c
|
@ -49,6 +49,13 @@
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
#include "pubkey-pinning.h"
|
#include "pubkey-pinning.h"
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
#define EINPROGRESS 112
|
||||||
|
#define EWOULDBLOCK 140
|
||||||
|
typedef u_short sa_family_t;
|
||||||
|
#include "util/winsock_event.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
|
#define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
|
||||||
#define STUB_TLS_SETUP_ERROR -4
|
#define STUB_TLS_SETUP_ERROR -4
|
||||||
#define STUB_TCP_AGAIN -3
|
#define STUB_TCP_AGAIN -3
|
||||||
|
@ -618,7 +625,7 @@ stub_tls_timeout_cb(void *userarg)
|
||||||
/****************************/
|
/****************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
|
stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf, getdns_eventloop_event* event)
|
||||||
{
|
{
|
||||||
ssize_t read;
|
ssize_t read;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
|
@ -633,12 +640,26 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
|
||||||
tcp->read_pos = tcp->read_buf;
|
tcp->read_pos = tcp->read_buf;
|
||||||
tcp->to_read = 2; /* Packet size */
|
tcp->to_read = 2; /* Packet size */
|
||||||
}
|
}
|
||||||
read = recv(fd, tcp->read_pos, tcp->to_read, 0);
|
read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0);
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
printf("read (in tcp ) %s\n",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
if (WSAGetLastError() == WSAECONNRESET)
|
||||||
|
return STUB_TCP_AGAIN;
|
||||||
|
if (WSAGetLastError() == WSAEINPROGRESS)
|
||||||
|
return STUB_TCP_AGAIN;
|
||||||
|
if (WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||||
|
winsock_tcp_wouldblock(event->ev, EV_READ);
|
||||||
|
return STUB_TCP_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
return STUB_TCP_AGAIN;
|
return STUB_TCP_AGAIN;
|
||||||
else
|
else
|
||||||
return STUB_TCP_ERROR;
|
return STUB_TCP_ERROR;
|
||||||
|
#endif
|
||||||
} else if (read == 0) {
|
} else if (read == 0) {
|
||||||
/* Remote end closed the socket */
|
/* Remote end closed the socket */
|
||||||
/* TODO: Try to reconnect */
|
/* TODO: Try to reconnect */
|
||||||
|
@ -750,8 +771,17 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
upstream). We must let the handshake complete since non-blocking. */
|
upstream). We must let the handshake complete since non-blocking. */
|
||||||
errno == EINPROGRESS)) ||
|
errno == EINPROGRESS)) ||
|
||||||
written < pkt_len + 2) {
|
written < pkt_len + 2) {
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
written = sendto(fd, (const char *)(netreq->query - 2),
|
||||||
|
pkt_len + 2, 0,
|
||||||
|
(struct sockaddr *)&(netreq->upstream->addr),
|
||||||
|
netreq->upstream->addr_len);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
written = write(fd, netreq->query - 2, pkt_len + 2);
|
written = write(fd, netreq->query - 2, pkt_len + 2);
|
||||||
|
#endif
|
||||||
if ((written == -1 && (errno == EAGAIN ||
|
if ((written == -1 && (errno == EAGAIN ||
|
||||||
errno == EWOULDBLOCK)) ||
|
errno == EWOULDBLOCK)) ||
|
||||||
written < pkt_len + 2) {
|
written < pkt_len + 2) {
|
||||||
|
@ -1264,7 +1294,7 @@ stub_udp_read_cb(void *userarg)
|
||||||
|
|
||||||
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||||
|
|
||||||
read = recvfrom(netreq->fd, netreq->response,
|
read = recvfrom(netreq->fd, (void *)netreq->response,
|
||||||
netreq->max_udp_payload_size + 1, /* If read == max_udp_payload_size
|
netreq->max_udp_payload_size + 1, /* If read == max_udp_payload_size
|
||||||
* then all is good. If read ==
|
* then all is good. If read ==
|
||||||
* max_udp_payload_size + 1, then
|
* max_udp_payload_size + 1, then
|
||||||
|
@ -1344,7 +1374,8 @@ stub_udp_write_cb(void *userarg)
|
||||||
return; /* too many upstream options */
|
return; /* too many upstream options */
|
||||||
}
|
}
|
||||||
pkt_len = _getdns_network_req_add_tsig(netreq);
|
pkt_len = _getdns_network_req_add_tsig(netreq);
|
||||||
if ((ssize_t)pkt_len != sendto(netreq->fd, netreq->query, pkt_len, 0,
|
if ((ssize_t)pkt_len != sendto(
|
||||||
|
netreq->fd, (const void *)netreq->query, pkt_len, 0,
|
||||||
(struct sockaddr *)&netreq->upstream->addr,
|
(struct sockaddr *)&netreq->upstream->addr,
|
||||||
netreq->upstream->addr_len)) {
|
netreq->upstream->addr_len)) {
|
||||||
close(netreq->fd);
|
close(netreq->fd);
|
||||||
|
@ -1375,7 +1406,7 @@ upstream_read_cb(void *userarg)
|
||||||
&upstream->upstreams->mf);
|
&upstream->upstreams->mf);
|
||||||
else
|
else
|
||||||
q = stub_tcp_read(upstream->fd, &upstream->tcp,
|
q = stub_tcp_read(upstream->fd, &upstream->tcp,
|
||||||
&upstream->upstreams->mf);
|
&upstream->upstreams->mf, &upstream->event);
|
||||||
|
|
||||||
switch (q) {
|
switch (q) {
|
||||||
case STUB_TCP_AGAIN:
|
case STUB_TCP_AGAIN:
|
||||||
|
|
|
@ -555,8 +555,7 @@ static getdns_return_t validate_chain(getdns_dict *response)
|
||||||
if ((r = getdns_list_set_dict(to_validate, 0, reply)))
|
if ((r = getdns_list_set_dict(to_validate, 0, reply)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
fprintf( stdout
|
printf("reply %u, dnssec_status: ", (unsigned)i);
|
||||||
, "reply %zu, dnssec_status: ", i);
|
|
||||||
switch ((s = getdns_validate_dnssec(
|
switch ((s = getdns_validate_dnssec(
|
||||||
to_validate, validation_chain, trust_anchor))) {
|
to_validate, validation_chain, trust_anchor))) {
|
||||||
|
|
||||||
|
@ -604,14 +603,13 @@ void callback(getdns_context *context, getdns_callback_type_t callback_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback_type == GETDNS_CALLBACK_COMPLETE) {
|
if (callback_type == GETDNS_CALLBACK_COMPLETE) {
|
||||||
fprintf(stdout,
|
printf("Response code was: GOOD. Status was: Callback with ID %"PRIu64" was successfull.\n",
|
||||||
"Response code was: GOOD. Status was: Callback with ID %llu was successfull.\n",
|
trans_id);
|
||||||
(unsigned long long)trans_id);
|
|
||||||
|
|
||||||
} else if (callback_type == GETDNS_CALLBACK_CANCEL)
|
} else if (callback_type == GETDNS_CALLBACK_CANCEL)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"An error occurred: The callback with ID %llu was cancelled. Exiting.\n",
|
"An error occurred: The callback with ID %"PRIu64" was cancelled. Exiting.\n",
|
||||||
(unsigned long long)trans_id);
|
trans_id);
|
||||||
else {
|
else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"An error occurred: The callback got a callback_type of %d. Exiting.\n",
|
"An error occurred: The callback got a callback_type of %d. Exiting.\n",
|
||||||
|
|
|
@ -0,0 +1,844 @@
|
||||||
|
/*
|
||||||
|
* util/winsock_event.c - implementation of the getdns winsock event handler.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015, Verisign/NLnet Labs. All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is open source.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the NLNET LABS/Verisign nor the names of its contributors may
|
||||||
|
* be used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Implementation of the getdns WinSock2 API event notification handler
|
||||||
|
* for the getdns Windows port.
|
||||||
|
* Code is originally from the Unbound source for Windows.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#ifdef USE_WINSOCK // only included for Windows builds
|
||||||
|
#include <signal.h>
|
||||||
|
#ifdef HAVE_TIME_H
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "util/winsock_event.h"
|
||||||
|
#include "util/fptr_wlist.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* implementation of log_err
|
||||||
|
* @param format: format string printf-style.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
log_err(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
fprintf(stderr, "error ");
|
||||||
|
fprintf(stderr, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* wsa_strerror(DWORD err)
|
||||||
|
{
|
||||||
|
static char unknown[32];
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case WSA_INVALID_HANDLE: return "Specified event object handle is invalid.";
|
||||||
|
case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available.";
|
||||||
|
case WSA_INVALID_PARAMETER: return "One or more parameters are invalid.";
|
||||||
|
case WSA_OPERATION_ABORTED: return "Overlapped operation aborted.";
|
||||||
|
case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state.";
|
||||||
|
case WSA_IO_PENDING: return "Overlapped operations will complete later.";
|
||||||
|
case WSAEINTR: return "Interrupted function call.";
|
||||||
|
case WSAEBADF: return "File handle is not valid.";
|
||||||
|
case WSAEACCES: return "Permission denied.";
|
||||||
|
case WSAEFAULT: return "Bad address.";
|
||||||
|
case WSAEINVAL: return "Invalid argument.";
|
||||||
|
case WSAEMFILE: return "Too many open files.";
|
||||||
|
case WSAEWOULDBLOCK: return "Resource temporarily unavailable.";
|
||||||
|
case WSAEINPROGRESS: return "Operation now in progress.";
|
||||||
|
case WSAEALREADY: return "Operation already in progress.";
|
||||||
|
case WSAENOTSOCK: return "Socket operation on nonsocket.";
|
||||||
|
case WSAEDESTADDRREQ: return "Destination address required.";
|
||||||
|
case WSAEMSGSIZE: return "Message too long.";
|
||||||
|
case WSAEPROTOTYPE: return "Protocol wrong type for socket.";
|
||||||
|
case WSAENOPROTOOPT: return "Bad protocol option.";
|
||||||
|
case WSAEPROTONOSUPPORT: return "Protocol not supported.";
|
||||||
|
case WSAESOCKTNOSUPPORT: return "Socket type not supported.";
|
||||||
|
case WSAEOPNOTSUPP: return "Operation not supported.";
|
||||||
|
case WSAEPFNOSUPPORT: return "Protocol family not supported.";
|
||||||
|
case WSAEAFNOSUPPORT: return "Address family not supported by protocol family.";
|
||||||
|
case WSAEADDRINUSE: return "Address already in use.";
|
||||||
|
case WSAEADDRNOTAVAIL: return "Cannot assign requested address.";
|
||||||
|
case WSAENETDOWN: return "Network is down.";
|
||||||
|
case WSAENETUNREACH: return "Network is unreachable.";
|
||||||
|
case WSAENETRESET: return "Network dropped connection on reset.";
|
||||||
|
case WSAECONNABORTED: return "Software caused connection abort.";
|
||||||
|
case WSAECONNRESET: return "Connection reset by peer.";
|
||||||
|
case WSAENOBUFS: return "No buffer space available.";
|
||||||
|
case WSAEISCONN: return "Socket is already connected.";
|
||||||
|
case WSAENOTCONN: return "Socket is not connected.";
|
||||||
|
case WSAESHUTDOWN: return "Cannot send after socket shutdown.";
|
||||||
|
case WSAETOOMANYREFS: return "Too many references.";
|
||||||
|
case WSAETIMEDOUT: return "Connection timed out.";
|
||||||
|
case WSAECONNREFUSED: return "Connection refused.";
|
||||||
|
case WSAELOOP: return "Cannot translate name.";
|
||||||
|
case WSAENAMETOOLONG: return "Name too long.";
|
||||||
|
case WSAEHOSTDOWN: return "Host is down.";
|
||||||
|
case WSAEHOSTUNREACH: return "No route to host.";
|
||||||
|
case WSAENOTEMPTY: return "Directory not empty.";
|
||||||
|
case WSAEPROCLIM: return "Too many processes.";
|
||||||
|
case WSAEUSERS: return "User quota exceeded.";
|
||||||
|
case WSAEDQUOT: return "Disk quota exceeded.";
|
||||||
|
case WSAESTALE: return "Stale file handle reference.";
|
||||||
|
case WSAEREMOTE: return "Item is remote.";
|
||||||
|
case WSASYSNOTREADY: return "Network subsystem is unavailable.";
|
||||||
|
case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range.";
|
||||||
|
case WSANOTINITIALISED: return "Successful WSAStartup not yet performed.";
|
||||||
|
case WSAEDISCON: return "Graceful shutdown in progress.";
|
||||||
|
case WSAENOMORE: return "No more results.";
|
||||||
|
case WSAECANCELLED: return "Call has been canceled.";
|
||||||
|
case WSAEINVALIDPROCTABLE: return "Procedure call table is invalid.";
|
||||||
|
case WSAEINVALIDPROVIDER: return "Service provider is invalid.";
|
||||||
|
case WSAEPROVIDERFAILEDINIT: return "Service provider failed to initialize.";
|
||||||
|
case WSASYSCALLFAILURE: return "System call failure.";
|
||||||
|
case WSASERVICE_NOT_FOUND: return "Service not found.";
|
||||||
|
case WSATYPE_NOT_FOUND: return "Class type not found.";
|
||||||
|
case WSA_E_NO_MORE: return "No more results.";
|
||||||
|
case WSA_E_CANCELLED: return "Call was canceled.";
|
||||||
|
case WSAEREFUSED: return "Database query was refused.";
|
||||||
|
case WSAHOST_NOT_FOUND: return "Host not found.";
|
||||||
|
case WSATRY_AGAIN: return "Nonauthoritative host not found.";
|
||||||
|
case WSANO_RECOVERY: return "This is a nonrecoverable error.";
|
||||||
|
case WSANO_DATA: return "Valid name, no data record of requested type.";
|
||||||
|
case WSA_QOS_RECEIVERS: return "QOS receivers.";
|
||||||
|
case WSA_QOS_SENDERS: return "QOS senders.";
|
||||||
|
case WSA_QOS_NO_SENDERS: return "No QOS senders.";
|
||||||
|
case WSA_QOS_NO_RECEIVERS: return "QOS no receivers.";
|
||||||
|
case WSA_QOS_REQUEST_CONFIRMED: return "QOS request confirmed.";
|
||||||
|
case WSA_QOS_ADMISSION_FAILURE: return "QOS admission error.";
|
||||||
|
case WSA_QOS_POLICY_FAILURE: return "QOS policy failure.";
|
||||||
|
case WSA_QOS_BAD_STYLE: return "QOS bad style.";
|
||||||
|
case WSA_QOS_BAD_OBJECT: return "QOS bad object.";
|
||||||
|
case WSA_QOS_TRAFFIC_CTRL_ERROR: return "QOS traffic control error.";
|
||||||
|
case WSA_QOS_GENERIC_ERROR: return "QOS generic error.";
|
||||||
|
case WSA_QOS_ESERVICETYPE: return "QOS service type error.";
|
||||||
|
case WSA_QOS_EFLOWSPEC: return "QOS flowspec error.";
|
||||||
|
case WSA_QOS_EPROVSPECBUF: return "Invalid QOS provider buffer.";
|
||||||
|
case WSA_QOS_EFILTERSTYLE: return "Invalid QOS filter style.";
|
||||||
|
case WSA_QOS_EFILTERTYPE: return "Invalid QOS filter type.";
|
||||||
|
case WSA_QOS_EFILTERCOUNT: return "Incorrect QOS filter count.";
|
||||||
|
case WSA_QOS_EOBJLENGTH: return "Invalid QOS object length.";
|
||||||
|
case WSA_QOS_EFLOWCOUNT: return "Incorrect QOS flow count.";
|
||||||
|
/*case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QOS object.";*/
|
||||||
|
case WSA_QOS_EPOLICYOBJ: return "Invalid QOS policy object.";
|
||||||
|
case WSA_QOS_EFLOWDESC: return "Invalid QOS flow descriptor.";
|
||||||
|
case WSA_QOS_EPSFLOWSPEC: return "Invalid QOS provider-specific flowspec.";
|
||||||
|
case WSA_QOS_EPSFILTERSPEC: return "Invalid QOS provider-specific filterspec.";
|
||||||
|
case WSA_QOS_ESDMODEOBJ: return "Invalid QOS shape discard mode object.";
|
||||||
|
case WSA_QOS_ESHAPERATEOBJ: return "Invalid QOS shaping rate object.";
|
||||||
|
case WSA_QOS_RESERVED_PETYPE: return "Reserved policy QOS element type.";
|
||||||
|
default:
|
||||||
|
snprintf(unknown, sizeof(unknown),
|
||||||
|
"unknown WSA error code %d", (int)err);
|
||||||
|
return unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getdns_mini_ev_cmp(const void* a, const void* b)
|
||||||
|
{
|
||||||
|
const struct _getdns_event *e = (const struct _getdns_event*)a;
|
||||||
|
const struct _getdns_event *f = (const struct _getdns_event*)b;
|
||||||
|
if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec)
|
||||||
|
return -1;
|
||||||
|
if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec)
|
||||||
|
return 1;
|
||||||
|
if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec)
|
||||||
|
return -1;
|
||||||
|
if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec)
|
||||||
|
return 1;
|
||||||
|
if(e < f)
|
||||||
|
return -1;
|
||||||
|
if(e > f)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set time */
|
||||||
|
static int
|
||||||
|
settime(struct _getdns_event_base* base)
|
||||||
|
{
|
||||||
|
if(gettimeofday(base->time_tv, NULL) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifndef S_SPLINT_S
|
||||||
|
*base->time_secs = (time_t)base->time_tv->tv_sec;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WINSOCK_DEBUG
|
||||||
|
/**
|
||||||
|
* Find a fd in the list of items.
|
||||||
|
* Note that not all items have a fd associated (those are -1).
|
||||||
|
* Signals are stored separately, and not searched.
|
||||||
|
* @param base: event base to look in.
|
||||||
|
* @param fd: what socket to look for.
|
||||||
|
* @return the index in the array, or -1 on failure.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
find_fd(struct _getdns_event_base* base, int fd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i=0; i<base->max; i++) {
|
||||||
|
if(base->items[i]->ev_fd == fd)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Find ptr in base array */
|
||||||
|
static void
|
||||||
|
zero_waitfor(WSAEVENT waitfor[], WSAEVENT x)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i=0; i<WSK_MAX_ITEMS; i++) {
|
||||||
|
if(waitfor[i] == x)
|
||||||
|
waitfor[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv)
|
||||||
|
{
|
||||||
|
struct _getdns_event_base* base = (struct _getdns_event_base*)malloc(
|
||||||
|
sizeof(struct _getdns_event_base));
|
||||||
|
if(!base)
|
||||||
|
return NULL;
|
||||||
|
memset(base, 0, sizeof(*base));
|
||||||
|
base->time_secs = time_secs;
|
||||||
|
base->time_tv = time_tv;
|
||||||
|
if(settime(base) < 0) {
|
||||||
|
_getdns_event_base_free(base);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
base->items = (struct _getdns_event**)calloc(WSK_MAX_ITEMS,
|
||||||
|
sizeof(struct _getdns_event*));
|
||||||
|
if(!base->items) {
|
||||||
|
_getdns_event_base_free(base);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
base->cap = WSK_MAX_ITEMS;
|
||||||
|
base->max = 0;
|
||||||
|
base->times = _getdns_rbtree_create(_getdns_mini_ev_cmp);
|
||||||
|
if(!base->times) {
|
||||||
|
_getdns_event_base_free(base);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
base->signals = (struct _getdns_event**)calloc(MAX_SIG,
|
||||||
|
sizeof(struct _getdns_event*));
|
||||||
|
if(!base->signals) {
|
||||||
|
_getdns_event_base_free(base);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
base->tcp_stickies = 0;
|
||||||
|
base->tcp_reinvigorated = 0;
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *_getdns_event_get_version(void)
|
||||||
|
{
|
||||||
|
return "winsock-event-"PACKAGE_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *_getdns_event_get_method(void)
|
||||||
|
{
|
||||||
|
return "WSAWaitForMultipleEvents";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** call timeouts handlers, and return how long to wait for next one or -1 */
|
||||||
|
void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now,
|
||||||
|
struct timeval* wait)
|
||||||
|
{
|
||||||
|
struct _getdns_event* p;
|
||||||
|
#ifndef S_SPLINT_S
|
||||||
|
wait->tv_sec = (time_t)-1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while((_getdns_rbnode_t*)(p = (struct _getdns_event*)_getdns_rbtree_first(base->times))
|
||||||
|
!=RBTREE_NULL) {
|
||||||
|
#ifndef S_SPLINT_S
|
||||||
|
if(p->ev_timeout.tv_sec > now->tv_sec ||
|
||||||
|
(p->ev_timeout.tv_sec==now->tv_sec &&
|
||||||
|
p->ev_timeout.tv_usec > now->tv_usec)) {
|
||||||
|
/* there is a next larger timeout. wait for it */
|
||||||
|
wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec;
|
||||||
|
if(now->tv_usec > p->ev_timeout.tv_usec) {
|
||||||
|
wait->tv_sec--;
|
||||||
|
wait->tv_usec = 1000000 - (now->tv_usec -
|
||||||
|
p->ev_timeout.tv_usec);
|
||||||
|
} else {
|
||||||
|
wait->tv_usec = p->ev_timeout.tv_usec
|
||||||
|
- now->tv_usec;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* event times out, remove it */
|
||||||
|
(void)_getdns_rbtree_delete(base->times, p);
|
||||||
|
p->ev_events &= ~EV_TIMEOUT;
|
||||||
|
fptr_ok(fptr_whitelist_event(p->ev_callback));
|
||||||
|
(*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** handle is_signal events and see if signalled */
|
||||||
|
static void _getdns_handle_signal(struct _getdns_event* ev)
|
||||||
|
{
|
||||||
|
printf("In _getdns_handle_signal\n");
|
||||||
|
DWORD ret;
|
||||||
|
//log_assert(ev->is_signal && ev->hEvent);
|
||||||
|
/* see if the event is signalled */
|
||||||
|
ret = WSAWaitForMultipleEvents(1, &ev->hEvent, 0 /* any object */,
|
||||||
|
0 /* return immediately */, 0 /* not alertable for IOcomple*/);
|
||||||
|
if(ret == WSA_WAIT_IO_COMPLETION || ret == WSA_WAIT_FAILED) {
|
||||||
|
log_err("getdns: WSAWaitForMultipleEvents(signal) failed: %s",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(ret == WSA_WAIT_TIMEOUT) {
|
||||||
|
/* not signalled */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset the signal */
|
||||||
|
if(!WSAResetEvent(ev->hEvent))
|
||||||
|
log_err("getdns: WSAResetEvent failed: %s",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
/* do the callback (which may set the signal again) */
|
||||||
|
fptr_ok(fptr_whitelist_event(ev->ev_callback));
|
||||||
|
(*ev->ev_callback)(ev->ev_fd, ev->ev_events, ev->ev_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** call select and callbacks for that */
|
||||||
|
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
|
||||||
|
{
|
||||||
|
DWORD timeout = 0; /* in milliseconds */
|
||||||
|
DWORD ret;
|
||||||
|
WSANETWORKEVENTS netev;
|
||||||
|
struct _getdns_event* eventlist[WSK_MAX_ITEMS];
|
||||||
|
int i, numwait = 0, startidx = 0;
|
||||||
|
int newstickies = 0;
|
||||||
|
struct timeval nultm;
|
||||||
|
|
||||||
|
#ifndef S_SPLINT_S
|
||||||
|
if(wait->tv_sec==(time_t)-1)
|
||||||
|
wait = NULL;
|
||||||
|
if (wait)
|
||||||
|
// timeout = 10 + wait->tv_usec / 1000;
|
||||||
|
timeout = wait->tv_sec * 1000 + wait->tv_usec / 1000;
|
||||||
|
if(base->tcp_stickies) {
|
||||||
|
wait = &nultm;
|
||||||
|
nultm.tv_sec = 0;
|
||||||
|
nultm.tv_usec = 0;
|
||||||
|
timeout = 0; /* no waiting, we have sticky events */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* prepare event array */
|
||||||
|
for(i=0; i<base->max; i++) {
|
||||||
|
if(base->items[i]->ev_fd == -1 && !base->items[i]->is_signal)
|
||||||
|
continue; /* skip timer only events */
|
||||||
|
eventlist[numwait] = base->items[i];
|
||||||
|
base->waitfor[numwait++] = base->items[i]->hEvent;
|
||||||
|
printf("winsock_event bmax=%d numwait=%d wait=%x "
|
||||||
|
"timeout=%d hEvent %d\n", base->max, numwait, (int)wait,
|
||||||
|
(int)timeout, (int)base->items[i]->hEvent);
|
||||||
|
if (numwait == WSK_MAX_ITEMS)
|
||||||
|
break; /* sanity check */
|
||||||
|
}
|
||||||
|
//log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);
|
||||||
|
|
||||||
|
/* do the wait */
|
||||||
|
if(numwait == 0) {
|
||||||
|
/* WSAWaitFor.. doesn't like 0 event objects */
|
||||||
|
if(wait) {
|
||||||
|
Sleep(timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//gv: do not schedule udp write
|
||||||
|
for (i = 0; i<base->max; i++) {
|
||||||
|
if (!base->items[i]->is_tcp && base->items[i]->ev_events&EV_WRITE) {
|
||||||
|
printf("skip UDP sched\n");
|
||||||
|
(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
|
||||||
|
EV_WRITE & eventlist[i]->ev_events,
|
||||||
|
eventlist[i]->ev_arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("before wait %d\n", base->items[0]->ev_events);
|
||||||
|
ret = WSAWaitForMultipleEvents(numwait, base->waitfor,
|
||||||
|
0 /* do not wait for all, just one will do */,
|
||||||
|
wait?timeout:WSA_INFINITE,
|
||||||
|
0); /* we are not alertable (IO completion events) */
|
||||||
|
printf("after wait %d %d\n", (int)ret, numwait);
|
||||||
|
if(ret == WSA_WAIT_IO_COMPLETION) {
|
||||||
|
//printf("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION");
|
||||||
|
return -1;
|
||||||
|
} else if(ret == WSA_WAIT_FAILED) {
|
||||||
|
//printf("getdns: WSAWaitForMultipleEvents failed: %s",
|
||||||
|
// wsa_strerror(WSAGetLastError()));
|
||||||
|
return -1;
|
||||||
|
} else if(ret == WSA_WAIT_TIMEOUT) {
|
||||||
|
printf("timeout\n");
|
||||||
|
} else
|
||||||
|
startidx = ret - WSA_WAIT_EVENT_0;
|
||||||
|
}
|
||||||
|
////verbose(VERB_CLIENT, "winsock_event wake was_timeout=%d startidx=%d",
|
||||||
|
// was_timeout, startidx);
|
||||||
|
|
||||||
|
/* get new time after wait */
|
||||||
|
if(settime(base) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* callbacks */
|
||||||
|
if(base->tcp_stickies)
|
||||||
|
startidx = 0; /* process all events, some are sticky */
|
||||||
|
for(i=startidx; i<numwait; i++)
|
||||||
|
eventlist[i]->just_checked = 1;
|
||||||
|
|
||||||
|
//verbose(VERB_CLIENT, "winsock_event signals");
|
||||||
|
for(i=startidx; i<numwait; i++) {
|
||||||
|
if(!base->waitfor[i])
|
||||||
|
continue; /* was deleted */
|
||||||
|
if(eventlist[i]->is_signal) {
|
||||||
|
eventlist[i]->just_checked = 0;
|
||||||
|
_getdns_handle_signal(eventlist[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* early exit - do not process network, exit quickly */
|
||||||
|
if(base->need_to_exit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
//verbose(VERB_CLIENT, "winsock_event net");
|
||||||
|
for(i=startidx; i<numwait; i++) {
|
||||||
|
short bits = 0;
|
||||||
|
/* eventlist[i] fired */
|
||||||
|
/* see if eventlist[i] is still valid and just checked from
|
||||||
|
* WSAWaitForEvents */
|
||||||
|
if(!base->waitfor[i])
|
||||||
|
continue; /* was deleted */
|
||||||
|
if(!eventlist[i]->just_checked)
|
||||||
|
continue; /* added by other callback */
|
||||||
|
if(eventlist[i]->is_signal)
|
||||||
|
continue; /* not a network event at all */
|
||||||
|
eventlist[i]->just_checked = 0;
|
||||||
|
|
||||||
|
if(WSAEnumNetworkEvents(eventlist[i]->ev_fd,
|
||||||
|
base->waitfor[i], /* reset the event handle */
|
||||||
|
/*NULL,*/ /* do not reset the event handle */
|
||||||
|
&netev) != 0) {
|
||||||
|
log_err("getdns: WSAEnumNetworkEvents failed: %s",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if((netev.lNetworkEvents & FD_READ)) {
|
||||||
|
if(netev.iErrorCode[FD_READ_BIT] != 0)
|
||||||
|
printf("FD_READ_BIT error: %s\n",
|
||||||
|
wsa_strerror(netev.iErrorCode[FD_READ_BIT]));
|
||||||
|
bits |= EV_READ;
|
||||||
|
printf("FD_READ_BIT\n");
|
||||||
|
}
|
||||||
|
if((netev.lNetworkEvents & FD_WRITE)) {
|
||||||
|
if(netev.iErrorCode[FD_WRITE_BIT] != 0)
|
||||||
|
printf("FD_WRITE_BIT error: %s\n",
|
||||||
|
wsa_strerror(netev.iErrorCode[FD_WRITE_BIT]));
|
||||||
|
bits |= EV_WRITE;
|
||||||
|
printf("FD_WRITE_BIT\n");
|
||||||
|
}
|
||||||
|
if((netev.lNetworkEvents & FD_CONNECT)) {
|
||||||
|
if(netev.iErrorCode[FD_CONNECT_BIT] != 0)
|
||||||
|
printf("FD_CONNECT_BIT error: %s\n",
|
||||||
|
wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT]));
|
||||||
|
bits |= EV_READ;
|
||||||
|
bits |= EV_WRITE;
|
||||||
|
printf("FD_CONNECT_BIT\n");
|
||||||
|
}
|
||||||
|
if((netev.lNetworkEvents & FD_ACCEPT)) {
|
||||||
|
if(netev.iErrorCode[FD_ACCEPT_BIT] != 0)
|
||||||
|
printf("FD_ACCEPT_BIT error: %s\n",
|
||||||
|
wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT]));
|
||||||
|
bits |= EV_READ;
|
||||||
|
printf("FD_ACCEPT_BIT\n");
|
||||||
|
}
|
||||||
|
if((netev.lNetworkEvents & FD_CLOSE)) {
|
||||||
|
if(netev.iErrorCode[FD_CLOSE_BIT] != 0)
|
||||||
|
printf("FD_CLOSE_BIT error: %s\n",
|
||||||
|
wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT]));
|
||||||
|
//g bits |= EV_READ;
|
||||||
|
//g bits |= EV_WRITE;
|
||||||
|
printf("FD_CLOSE_BIT\n");
|
||||||
|
}
|
||||||
|
if(eventlist[i]->is_tcp && eventlist[i]->stick_events) {
|
||||||
|
|
||||||
|
printf("winsock %d pass sticky %s%s\n",
|
||||||
|
eventlist[i]->ev_fd,
|
||||||
|
(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
|
||||||
|
(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
|
||||||
|
|
||||||
|
bits |= eventlist[i]->old_events;
|
||||||
|
}
|
||||||
|
if(eventlist[i]->is_tcp && bits) {
|
||||||
|
eventlist[i]->old_events = bits;
|
||||||
|
eventlist[i]->stick_events = 1;
|
||||||
|
if((eventlist[i]->ev_events & bits)) {
|
||||||
|
newstickies = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("winsock %d store sticky %s%s",
|
||||||
|
eventlist[i]->ev_fd,
|
||||||
|
(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
|
||||||
|
(eventlist[i]->old_events&EV_WRITE) ? "EV_WRITE" : "");
|
||||||
|
|
||||||
|
}
|
||||||
|
if((bits & eventlist[i]->ev_events)) {
|
||||||
|
printf( "winsock event callback %p fd=%d "
|
||||||
|
"%s%s%s%s%s ; %s%s%s\n",
|
||||||
|
eventlist[i], eventlist[i]->ev_fd,
|
||||||
|
(netev.lNetworkEvents&FD_READ)?" FD_READ":"",
|
||||||
|
(netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"",
|
||||||
|
(netev.lNetworkEvents&FD_CONNECT)?
|
||||||
|
" FD_CONNECT":"",
|
||||||
|
(netev.lNetworkEvents&FD_ACCEPT)?
|
||||||
|
" FD_ACCEPT":"",
|
||||||
|
(netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"",
|
||||||
|
(bits&EV_READ)?" EV_READ":"",
|
||||||
|
(bits&EV_WRITE)?" EV_WRITE":"",
|
||||||
|
(bits&EV_TIMEOUT)?" EV_TIMEOUT":"");
|
||||||
|
|
||||||
|
fptr_ok(fptr_whitelist_event(
|
||||||
|
eventlist[i]->ev_callback));
|
||||||
|
(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
|
||||||
|
bits & eventlist[i]->ev_events,
|
||||||
|
eventlist[i]->ev_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(eventlist[i]->is_tcp && bits)
|
||||||
|
printf( "winsock %d got sticky %s%s\n",
|
||||||
|
eventlist[i]->ev_fd,
|
||||||
|
(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
|
||||||
|
(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
|
||||||
|
|
||||||
|
}
|
||||||
|
//verbose(VERB_CLIENT, "winsock_event net");
|
||||||
|
if(base->tcp_reinvigorated) {
|
||||||
|
printf("winsock_event reinvigorated\n");
|
||||||
|
base->tcp_reinvigorated = 0;
|
||||||
|
newstickies = 1;
|
||||||
|
}
|
||||||
|
base->tcp_stickies = newstickies;
|
||||||
|
//gprintf("winsock_event handle_select end\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getdns_event_base_dispatch(struct _getdns_event_base *base)
|
||||||
|
{
|
||||||
|
struct timeval wait;
|
||||||
|
if(settime(base) < 0)
|
||||||
|
return -1;
|
||||||
|
while(!base->need_to_exit)
|
||||||
|
{
|
||||||
|
/* see if timeouts need handling */
|
||||||
|
_getdns_handle_timeouts(base, base->time_tv, &wait);
|
||||||
|
if(base->need_to_exit)
|
||||||
|
return 0;
|
||||||
|
/* do select */
|
||||||
|
if(_getdns_handle_select(base, &wait) < 0) {
|
||||||
|
if(base->need_to_exit)
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getdns_event_base_loopexit(struct _getdns_event_base *base,
|
||||||
|
struct timeval * ATTR_UNUSED(tv))
|
||||||
|
{
|
||||||
|
base->need_to_exit = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _getdns_event_base_free(struct _getdns_event_base *base)
|
||||||
|
{
|
||||||
|
if(!base)
|
||||||
|
return;
|
||||||
|
if(base->items)
|
||||||
|
free(base->items);
|
||||||
|
if(base->times)
|
||||||
|
free(base->times);
|
||||||
|
if(base->signals)
|
||||||
|
free(base->signals);
|
||||||
|
free(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _getdns_event_set(struct _getdns_event *ev, int fd, short bits,
|
||||||
|
void (*cb)(int, short, void *), void *arg)
|
||||||
|
{
|
||||||
|
ev->node.key = ev;
|
||||||
|
ev->ev_fd = fd;
|
||||||
|
ev->ev_events = bits;
|
||||||
|
ev->ev_callback = cb;
|
||||||
|
fptr_ok(fptr_whitelist_event(ev->ev_callback));
|
||||||
|
ev->ev_arg = arg;
|
||||||
|
ev->just_checked = 0;
|
||||||
|
ev->added = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getdns_event_base_set(struct _getdns_event_base *base, struct _getdns_event *ev)
|
||||||
|
{
|
||||||
|
ev->ev_base = base;
|
||||||
|
ev->old_events = 0;
|
||||||
|
ev->stick_events = 0;
|
||||||
|
ev->added = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getdns_event_add(struct _getdns_event *ev, struct timeval *tv)
|
||||||
|
{
|
||||||
|
printf( "event_add %p added=%d fd=%d tv=" ARG_LL "d %s%s%s\n",
|
||||||
|
ev, ev->added, ev->ev_fd,
|
||||||
|
(tv?(long long)tv->tv_sec*1000+(long long)tv->tv_usec/1000:-1),
|
||||||
|
(ev->ev_events&EV_READ)?" EV_READ":"",
|
||||||
|
(ev->ev_events&EV_WRITE)?" EV_WRITE":"",
|
||||||
|
(ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":"");
|
||||||
|
|
||||||
|
if(ev->added)
|
||||||
|
_getdns_event_del(ev);
|
||||||
|
|
||||||
|
ev->is_tcp = 0;
|
||||||
|
ev->is_signal = 0;
|
||||||
|
ev->just_checked = 0;
|
||||||
|
|
||||||
|
if ((ev->ev_events&(EV_READ | EV_WRITE)) && ev->ev_fd != -1) {
|
||||||
|
BOOL b = 0;
|
||||||
|
int t, l;
|
||||||
|
long events = 0;
|
||||||
|
//gprintf("\getdns_event_add %d %d\n", ev->ev_fd, events);
|
||||||
|
|
||||||
|
if (ev->ev_base->max == ev->ev_base->cap)
|
||||||
|
return -1;
|
||||||
|
ev->idx = ev->ev_base->max++;
|
||||||
|
ev->ev_base->items[ev->idx] = ev;
|
||||||
|
|
||||||
|
if ((ev->ev_events&EV_READ))
|
||||||
|
events |= FD_READ;
|
||||||
|
if ((ev->ev_events&EV_WRITE))
|
||||||
|
{
|
||||||
|
events |= FD_CONNECT;
|
||||||
|
events |= FD_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("\getdns_event_add %d read = %d write = %d %d\n", ev->ev_fd, ev->ev_events&EV_READ, ev->ev_events&EV_WRITE, events);
|
||||||
|
|
||||||
|
l = sizeof(t);
|
||||||
|
if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_TYPE,
|
||||||
|
(void*)&t, &l) != 0)
|
||||||
|
log_err("getdns: getsockopt(SO_TYPE) failed: %s",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
if(t == SOCK_STREAM) {
|
||||||
|
/* TCP socket */
|
||||||
|
ev->is_tcp = 1;
|
||||||
|
events |= FD_CLOSE;
|
||||||
|
if( (ev->ev_events&EV_WRITE) )
|
||||||
|
events |= FD_CONNECT;
|
||||||
|
l = sizeof(b);
|
||||||
|
if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_ACCEPTCONN,
|
||||||
|
(void*)&b, &l) != 0)
|
||||||
|
log_err("getdns: getsockopt(SO_ACCEPTCONN) failed: %s",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
if(b) /* TCP accept socket */
|
||||||
|
events |= FD_ACCEPT;
|
||||||
|
}
|
||||||
|
ev->hEvent = WSACreateEvent();
|
||||||
|
if(ev->hEvent == WSA_INVALID_EVENT)
|
||||||
|
log_err("getdns: WSACreateEvent failed: %s",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
/* automatically sets fd to nonblocking mode.
|
||||||
|
* nonblocking cannot be disabled, until wsaES(fd, NULL, 0) */
|
||||||
|
printf("\nWSAEventSelect %d events %d hEvent %d\n", ev->ev_fd, (int)events, (int)ev->hEvent);
|
||||||
|
if (WSAEventSelect(ev->ev_fd, ev->hEvent, events) != 0) {
|
||||||
|
log_err("getdns: WSAEventSelect in getdns failed: %s",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
}
|
||||||
|
if(ev->is_tcp && ev->stick_events &&
|
||||||
|
(ev->ev_events & ev->old_events)) {
|
||||||
|
/* go to processing the sticky event right away */
|
||||||
|
printf("\nWSAEventSelect sticky %d events %d hEvent %d\n", ev->ev_fd, (int)events, (int)ev->hEvent);
|
||||||
|
ev->ev_base->tcp_reinvigorated = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tv && (ev->ev_events&EV_TIMEOUT)) {
|
||||||
|
printf("\nWSAEventSelect timeout %d hEvent %d\n", ev->ev_fd, (int)ev->hEvent);
|
||||||
|
|
||||||
|
#ifndef S_SPLINT_S
|
||||||
|
struct timeval *now = ev->ev_base->time_tv;
|
||||||
|
ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec;
|
||||||
|
ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec;
|
||||||
|
while(ev->ev_timeout.tv_usec > 1000000) {
|
||||||
|
ev->ev_timeout.tv_usec -= 1000000;
|
||||||
|
ev->ev_timeout.tv_sec++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
(void)_getdns_rbtree_insert(ev->ev_base->times, &ev->node);
|
||||||
|
}
|
||||||
|
ev->added = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getdns_event_del(struct _getdns_event *ev)
|
||||||
|
{
|
||||||
|
//verbose(VERB_ALGO, "event_del %p added=%d fd=%d tv=" ARG_LL "d %s%s%s",
|
||||||
|
// ev, ev->added, ev->ev_fd,
|
||||||
|
// (ev->ev_events&EV_TIMEOUT)?(long long)ev->ev_timeout.tv_sec*1000+
|
||||||
|
// (long long)ev->ev_timeout.tv_usec/1000:-1,
|
||||||
|
// (ev->ev_events&EV_READ)?" EV_READ":"",
|
||||||
|
// (ev->ev_events&EV_WRITE)?" EV_WRITE":"",
|
||||||
|
// (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":"");
|
||||||
|
if(!ev->added)
|
||||||
|
return 0;
|
||||||
|
//log_assert(ev->added);
|
||||||
|
if((ev->ev_events&EV_TIMEOUT))
|
||||||
|
(void)_getdns_rbtree_delete(ev->ev_base->times, &ev->node);
|
||||||
|
if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) {
|
||||||
|
//log_assert(ev->ev_base->max > 0);
|
||||||
|
/* remove item and compact the list */
|
||||||
|
ev->ev_base->items[ev->idx] =
|
||||||
|
ev->ev_base->items[ev->ev_base->max-1];
|
||||||
|
ev->ev_base->items[ev->ev_base->max-1] = NULL;
|
||||||
|
ev->ev_base->max--;
|
||||||
|
if(ev->idx < ev->ev_base->max)
|
||||||
|
ev->ev_base->items[ev->idx]->idx = ev->idx;
|
||||||
|
zero_waitfor(ev->ev_base->waitfor, ev->hEvent);
|
||||||
|
|
||||||
|
if(WSAEventSelect(ev->ev_fd, ev->hEvent, 0) != 0)
|
||||||
|
log_err("getdns: WSAEventSelect(disable) failed: %s",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
if(!WSACloseEvent(ev->hEvent))
|
||||||
|
log_err("getdns: WSACloseEvent failed: %s",
|
||||||
|
wsa_strerror(WSAGetLastError()));
|
||||||
|
}
|
||||||
|
ev->just_checked = 0;
|
||||||
|
ev->added = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** which base gets to handle signals */
|
||||||
|
static struct _getdns_event_base* signal_base = NULL;
|
||||||
|
/** signal handler */
|
||||||
|
static RETSIGTYPE sigh(int sig)
|
||||||
|
{
|
||||||
|
if(!signal_base || sig < 0 || sig >= MAX_SIG)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getdns_signal_add(struct _getdns_event *ev, struct timeval * ATTR_UNUSED(tv))
|
||||||
|
{
|
||||||
|
if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG)
|
||||||
|
return -1;
|
||||||
|
signal_base = ev->ev_base;
|
||||||
|
ev->ev_base->signals[ev->ev_fd] = ev;
|
||||||
|
ev->added = 1;
|
||||||
|
if(signal(ev->ev_fd, sigh) == SIG_ERR) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getdns_signal_del(struct _getdns_event *ev)
|
||||||
|
{
|
||||||
|
if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG)
|
||||||
|
return -1;
|
||||||
|
ev->ev_base->signals[ev->ev_fd] = NULL;
|
||||||
|
ev->added = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbits)
|
||||||
|
{
|
||||||
|
printf("winsock: tcp wouldblock %s\n",
|
||||||
|
eventbits==EV_READ?"EV_READ":"EV_WRITE");
|
||||||
|
ev->old_events &= (~eventbits);
|
||||||
|
if(ev->old_events == 0)
|
||||||
|
ev->stick_events = 0;
|
||||||
|
/* in case this is the last sticky event, we could
|
||||||
|
* possibly run an empty handler loop to reset the base
|
||||||
|
* tcp_stickies variable
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev,
|
||||||
|
WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg)
|
||||||
|
{
|
||||||
|
if(base->max == base->cap)
|
||||||
|
return 0;
|
||||||
|
memset(ev, 0, sizeof(*ev));
|
||||||
|
ev->ev_fd = -1;
|
||||||
|
ev->ev_events = EV_READ;
|
||||||
|
ev->ev_callback = cb;
|
||||||
|
ev->ev_arg = arg;
|
||||||
|
ev->is_signal = 1;
|
||||||
|
ev->hEvent = wsaevent;
|
||||||
|
ev->added = 1;
|
||||||
|
ev->ev_base = base;
|
||||||
|
ev->idx = ev->ev_base->max++;
|
||||||
|
ev->ev_base->items[ev->idx] = ev;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void winsock_unregister_wsaevent(struct _getdns_event* ev)
|
||||||
|
{
|
||||||
|
if(!ev || !ev->added) return;
|
||||||
|
//log_assert(ev->added && ev->ev_base->max > 0)
|
||||||
|
/* remove item and compact the list */
|
||||||
|
ev->ev_base->items[ev->idx] = ev->ev_base->items[ev->ev_base->max-1];
|
||||||
|
ev->ev_base->items[ev->ev_base->max-1] = NULL;
|
||||||
|
ev->ev_base->max--;
|
||||||
|
if(ev->idx < ev->ev_base->max)
|
||||||
|
ev->ev_base->items[ev->idx]->idx = ev->idx;
|
||||||
|
ev->added = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* USE_WINSOCK */
|
||||||
|
/** symbol so this codefile defines symbols. pleasing ranlib on OSX 10.5 */
|
||||||
|
int winsock_unused_symbol = 1;
|
||||||
|
#endif /* USE_WINSOCK */
|
|
@ -0,0 +1,295 @@
|
||||||
|
/*
|
||||||
|
* util/winsock_event.h - getdns event handling for winsock on windows
|
||||||
|
* extracted from Unbound source code and modified for getdns
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015, NLnet Labs/Verisign. All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is open source.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the NLNET LABS or Verisign nor the names of its contributors may
|
||||||
|
* be used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
*
|
||||||
|
* This file contains interface functions with the WinSock2 API on Windows.
|
||||||
|
* It uses the winsock WSAWaitForMultipleEvents interface on a number of
|
||||||
|
* sockets.
|
||||||
|
* Code is originally from the Unbound source for Windows.
|
||||||
|
*
|
||||||
|
* Note that windows can only wait for max 64 events at one time.
|
||||||
|
*
|
||||||
|
* Also, file descriptors cannot be waited for.
|
||||||
|
*
|
||||||
|
* Named pipes are not easily available (and are not usable in select() ).
|
||||||
|
* For interprocess communication, it is possible to wait for a hEvent to
|
||||||
|
* be signaled by another thread.
|
||||||
|
*
|
||||||
|
* When a socket becomes readable, then it will not be flagged as
|
||||||
|
* readable again until you have gotten WOULDBLOCK from a recv routine.
|
||||||
|
* That means the event handler must store the readability (edge notify)
|
||||||
|
* and process the incoming data until it blocks.
|
||||||
|
* The function performing recv then has to inform the event handler that
|
||||||
|
* the socket has blocked, and the event handler can mark it as such.
|
||||||
|
* Thus, this file transforms the edge notify from windows to a level notify
|
||||||
|
* that is compatible with UNIX.
|
||||||
|
* The WSAEventSelect page says that it does do level notify, as long
|
||||||
|
* as you call a recv/write/accept at least once when it is signalled.
|
||||||
|
* This last bit is not true, even though documented in server2008 api docs
|
||||||
|
* from microsoft, it does not happen at all. Instead you have to test for
|
||||||
|
* WSAEWOULDBLOCK on a tcp stream, and only then retest the socket.
|
||||||
|
* And before that remember the previous result as still valid.
|
||||||
|
*
|
||||||
|
* To stay 'fair', instead of emptying a socket completely, the event handler
|
||||||
|
* can test the other (marked as blocking) sockets for new events.
|
||||||
|
*
|
||||||
|
* Additionally, TCP accept sockets get special event support.
|
||||||
|
*
|
||||||
|
* Socket numbers are not starting small, they can be any number (say 33060).
|
||||||
|
* Therefore, bitmaps are not used, but arrays.
|
||||||
|
*
|
||||||
|
* on winsock, you must use recv() and send() for TCP reads and writes,
|
||||||
|
* not read() and write(), those work only on files.
|
||||||
|
*
|
||||||
|
* Also fseek and fseeko do not work if a FILE is not fopen-ed in binary mode.
|
||||||
|
*
|
||||||
|
* When under a high load windows gives out lots of errors, from recvfrom
|
||||||
|
* on udp sockets for example (WSAECONNRESET). Even though the udp socket
|
||||||
|
* has no connection per se.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UTIL_WINSOCK_EVENT_H
|
||||||
|
#define UTIL_WINSOCK_EVENT_H
|
||||||
|
|
||||||
|
// Only enabled for Windows
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
|
||||||
|
#ifndef HAVE_EVENT_BASE_FREE
|
||||||
|
#define HAVE_EVENT_BASE_FREE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* redefine the calls to different names so that there is no name
|
||||||
|
* collision with other code that uses libevent names. (that uses libunbound)*/
|
||||||
|
#define _getdns_event_init winsockevent_init
|
||||||
|
#define event_get_version winsockevent_get_version
|
||||||
|
#define event_get_method winsockevent_get_method
|
||||||
|
#define _getdns_event_base_dispatch winsockevent_base_dispatch
|
||||||
|
#define event_base_loopexit winsockevent_base_loopexit
|
||||||
|
#define _getdns_event_base_free winsockevent_base_free
|
||||||
|
#define _getdns_event_set winsockevent_set
|
||||||
|
#define _getdns_event_base_set winsockevent_base_set
|
||||||
|
#define _getdns_event_add winsockevent_add
|
||||||
|
#define _getdns_event_del winsockevent_del
|
||||||
|
#define signal_add winsocksignal_add
|
||||||
|
#define signal_del winsocksignal_del
|
||||||
|
|
||||||
|
/** event timeout */
|
||||||
|
#define EV_TIMEOUT 0x01
|
||||||
|
/** event fd readable */
|
||||||
|
#define EV_READ 0x02
|
||||||
|
/** event fd writable */
|
||||||
|
#define EV_WRITE 0x04
|
||||||
|
/** event signal */
|
||||||
|
#define EV_SIGNAL 0x08
|
||||||
|
/** event must persist */
|
||||||
|
#define EV_PERSIST 0x10
|
||||||
|
|
||||||
|
/* needs our redblack tree */
|
||||||
|
#include "util/rbtree.h"
|
||||||
|
|
||||||
|
/** max number of signals to support */
|
||||||
|
#define MAX_SIG 32
|
||||||
|
|
||||||
|
/** The number of items that the winsock event handler can service.
|
||||||
|
* Windows cannot handle more anyway */
|
||||||
|
#define WSK_MAX_ITEMS 64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event base for winsock event handler
|
||||||
|
*/
|
||||||
|
struct _getdns_event_base
|
||||||
|
{
|
||||||
|
/** sorted by timeout (absolute), ptr */
|
||||||
|
_getdns_rbtree_t* times;
|
||||||
|
/** array (first part in use) of handles to work on */
|
||||||
|
struct _getdns_event** items;
|
||||||
|
/** number of items in use in array */
|
||||||
|
int max;
|
||||||
|
/** capacity of array, size of array in items */
|
||||||
|
int cap;
|
||||||
|
/** array of 0 - maxsig of ptr to event for it */
|
||||||
|
struct _getdns_event** signals;
|
||||||
|
/** if we need to exit */
|
||||||
|
int need_to_exit;
|
||||||
|
/** where to store time in seconds */
|
||||||
|
time_t* time_secs;
|
||||||
|
/** where to store time in microseconds */
|
||||||
|
struct timeval* time_tv;
|
||||||
|
/**
|
||||||
|
* TCP streams have sticky events to them, these are not
|
||||||
|
* reported by the windows event system anymore, we have to
|
||||||
|
* keep reporting those events as present until wouldblock() is
|
||||||
|
* signalled by the handler back to use.
|
||||||
|
*/
|
||||||
|
int tcp_stickies;
|
||||||
|
/**
|
||||||
|
* should next cycle process reinvigorated stickies,
|
||||||
|
* these are stickies that have been stored, but due to a new
|
||||||
|
* event_add a sudden interest in the event has incepted.
|
||||||
|
*/
|
||||||
|
int tcp_reinvigorated;
|
||||||
|
/** The list of events that is currently being processed. */
|
||||||
|
WSAEVENT waitfor[WSK_MAX_ITEMS];
|
||||||
|
|
||||||
|
/* fdset for read write, for fds ready, and added */
|
||||||
|
fd_set
|
||||||
|
/** fds for reading */
|
||||||
|
reads,
|
||||||
|
/** fds for writing */
|
||||||
|
writes,
|
||||||
|
/** fds determined ready for use */
|
||||||
|
ready,
|
||||||
|
/** ready plus newly added events. */
|
||||||
|
content;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event structure. Has some of the event elements.
|
||||||
|
*/
|
||||||
|
struct _getdns_event {
|
||||||
|
/** node in timeout rbtree */
|
||||||
|
_getdns_rbnode_t node;
|
||||||
|
/** is event already added */
|
||||||
|
int added;
|
||||||
|
|
||||||
|
/** event base it belongs to */
|
||||||
|
struct _getdns_event_base *ev_base;
|
||||||
|
/** fd to poll or -1 for timeouts. signal number for sigs. */
|
||||||
|
int ev_fd;
|
||||||
|
/** what events this event is interested in, see EV_.. above. */
|
||||||
|
short ev_events;
|
||||||
|
/** timeout value */
|
||||||
|
struct timeval ev_timeout;
|
||||||
|
|
||||||
|
/** callback to call: fd, eventbits, userarg */
|
||||||
|
void (*ev_callback)(int, short, void *);
|
||||||
|
/** callback user arg */
|
||||||
|
void *ev_arg;
|
||||||
|
|
||||||
|
/* ----- nonpublic part, for winsock_event only ----- */
|
||||||
|
/** index of this event in the items array (if added) */
|
||||||
|
int idx;
|
||||||
|
/** the event handle to wait for new events to become ready */
|
||||||
|
WSAEVENT hEvent;
|
||||||
|
/** true if this filedes is a TCP socket and needs special attention */
|
||||||
|
int is_tcp;
|
||||||
|
/** remembered EV_ values */
|
||||||
|
short old_events;
|
||||||
|
/** should remembered EV_ values be used for TCP streams.
|
||||||
|
* Reset after WOULDBLOCK is signaled using the function. */
|
||||||
|
int stick_events;
|
||||||
|
|
||||||
|
/** true if this event is a signaling WSAEvent by the user.
|
||||||
|
* User created and user closed WSAEvent. Only signaled/unsigneled,
|
||||||
|
* no read/write/distinctions needed. */
|
||||||
|
int is_signal;
|
||||||
|
/** used during callbacks to see which events were just checked */
|
||||||
|
int just_checked;
|
||||||
|
};
|
||||||
|
|
||||||
|
char* wsa_strerror(DWORD err);
|
||||||
|
void log_err(const char *format, ...);
|
||||||
|
/** create event base */
|
||||||
|
void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv);
|
||||||
|
/** get version */
|
||||||
|
const char *event_get_version(void);
|
||||||
|
/** get polling method (select,epoll) */
|
||||||
|
const char *event_get_method(void);
|
||||||
|
/** run select in a loop */
|
||||||
|
int _getdns_event_base_dispatch(struct _getdns_event_base *);
|
||||||
|
/** exit that loop */
|
||||||
|
int event_base_loopexit(struct _getdns_event_base *, struct timeval *);
|
||||||
|
/** free event base. Free events yourself */
|
||||||
|
void _getdns_event_base_free(struct _getdns_event_base *);
|
||||||
|
/** set content of event */
|
||||||
|
void _getdns_event_set(struct _getdns_event *, int, short, void (*)(int, short, void *), void *);
|
||||||
|
|
||||||
|
/** add event to a base. You *must* call this for every event. */
|
||||||
|
int _getdns_event_base_set(struct _getdns_event_base *, struct _getdns_event *);
|
||||||
|
/** add event to make it active. You may not change it with event_set anymore */
|
||||||
|
int _getdns_event_add(struct _getdns_event *, struct timeval *);
|
||||||
|
/** remove event. You may change it again */
|
||||||
|
int _getdns_event_del(struct _getdns_event *);
|
||||||
|
|
||||||
|
#define evtimer_add(ev, tv) event_add(ev, tv)
|
||||||
|
#define evtimer_del(ev) event_del(ev)
|
||||||
|
|
||||||
|
/* uses different implementation. Cannot mix fd/timeouts and signals inside
|
||||||
|
* the same struct event. create several event structs for that. */
|
||||||
|
/** install signal handler */
|
||||||
|
int signal_add(struct _getdns_event *, struct timeval *);
|
||||||
|
/** set signal event contents */
|
||||||
|
#define signal_set(ev, x, cb, arg) \
|
||||||
|
event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
|
||||||
|
/** remove signal handler */
|
||||||
|
int signal_del(struct _getdns_event *);
|
||||||
|
|
||||||
|
/** compare events in tree, based on timevalue, ptr for uniqueness */
|
||||||
|
int getdns_mini_ev_cmp(const void* a, const void* b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Routine for windows only, where the handling layer can signal that
|
||||||
|
* a TCP stream encountered WSAEWOULDBLOCK for a stream and thus needs
|
||||||
|
* retesting the event.
|
||||||
|
* Pass if EV_READ or EV_WRITE gave wouldblock.
|
||||||
|
*/
|
||||||
|
void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Routine for windows only. where you pass a signal WSAEvent that
|
||||||
|
* you wait for. When the event is signaled, the callback gets called.
|
||||||
|
* The callback has to WSAResetEvent to disable the signal.
|
||||||
|
* @param base: the event base.
|
||||||
|
* @param ev: the event structure for data storage
|
||||||
|
* can be passed uninitialised.
|
||||||
|
* @param wsaevent: the WSAEvent that gets signaled.
|
||||||
|
* @param cb: callback routine.
|
||||||
|
* @param arg: user argument to callback routine.
|
||||||
|
* @return false on error.
|
||||||
|
*/
|
||||||
|
int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev,
|
||||||
|
WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a wsaevent. User has to close the WSAEVENT itself.
|
||||||
|
* @param ev: event data storage.
|
||||||
|
*/
|
||||||
|
void winsock_unregister_wsaevent(struct _getdns_event* ev);
|
||||||
|
|
||||||
|
#endif /* USE_WINSOCK */
|
||||||
|
#endif /* UTIL_WINSOCK_EVENT_H */
|
Loading…
Reference in New Issue