Codebase list getdns / upstream/0.9.0
Imported Upstream version 0.9.0 Ondřej Surý 8 years ago
66 changed file(s) with 7218 addition(s) and 1726 deletion(s). Raw diff Collapse all Expand all
0 * 2015-12-31: Version 0.9.0
1 * Update of unofficial extension to the API that supports stub mode
2 TLS verification. GETDNS_AUTHENTICATION_HOSTNAME is replaced by
3 GETDNS_AUTHENTICATION_REQUIRED (but remains available as an alias).
4 Upstreams can now be configured with either a hostname or a SPKI pinset
5 for TLS authentication (or both). If the GETDNS_AUTHENTICATION_REQUIRED
6 option is used at least one piece of authentication information must be
7 configured for each upstream, and all the configured authentication
8 information for an upstream must validate.
9 * Remove STARTTLS implementation (no change to SPEC)
10 * Enable TCP Fast Open when possible. Add OSX support for TFO.
11 * Rename return_call_debugging to return_call_reporting
12 * Bugfix: configure problem with getdns-0.5.1 on OpenBSD
13 Thanks Claus Assmann.
14 * pkg-config support. Thanks Neil Cook.
15 * Functions to convert from RR dicts to wireformat and text format
16 and vice versa. Including a function that builds a getdns_list
17 of RR dicts from a zonefile.
18 * Use the with the getdns_context_set_dns_root_servers() function
19 provided root servers in recursing resolution modus.
20 * getdns_query option (-f) to read a DNSSEC trust anchor from file.
21 * getdns_query option (-R) to read a "root hints" file.
22 * Bugfix: Detect and prevent duplicate NSEC(3)s to be returned with
23 dnssec_return_validation_chain.
24 * Bugfix: Remove duplicate RRs from RRsets when DNSSEC verifying
25 * Client side edns-tcp-keepalive support
26 * TSIG support + getdns_query syntax to specify TSIG parameters
27 per upstream: @<ip>[^[<algorithm>:]<name>:<secret in Base64>]
28 * Bugfix: Allow truncated answers to be returned in case of missing
29 fallback transport.
30 * Verify upstream TLS pubkeys with pinsets; A getdns_query option
31 (-K) to attach pinsets to getdns_contexts.
32 Thanks Daniel Kahn Gillmor
33 * Initial support for Windows. Thanks Gowri Visweswaran
34 * add_warning_for_bad_dns extension
35 * Try and retry with suffixes giving with getdns_context_set_suffix()
36 following directions given by getdns_context_set_append_name()
37 getdns_query options to set suffixes and append_name directions:
38 '-W' to append suffix always (default)
39 '-1' to append suffix only to single label after failure
40 '-M' to append suffix only to multi label name after failure
41 '-N' to never append a suffix
42 '-Z <suffixes>' to set suffixes with the given comma separed list
43 * Better help text for getdns_query (printed with the '-h' option)
44 * Setting the +specify_class extension with getdns_query
45 * Return NOT_IMPLEMENTED for not implemented namespaces, and the
46 not implemented getdns_context_set_follow_redirects() function.
47
048 * 2015-11-18: Version 0.5.1
149 * Bugfix: growing upstreams arrow.
250 * Bugfix: Segfault on timeout in specific conditions
3838 exec_prefix = @exec_prefix@
3939 bindir = @bindir@
4040 docdir = @docdir@
41 libdir = @libdir@
4142
4243 srcdir = @srcdir@
4344 INSTALL = @INSTALL@
4445
45 all : default @GETDNS_QUERY@
46 all : default @GETDNS_QUERY@
4647
4748 default:
4849 cd src && $(MAKE) $@
4950
50 install: all @INSTALL_GETDNS_QUERY@
51 install: all getdns.pc @INSTALL_GETDNS_QUERY@
5152 $(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
5253 $(INSTALL) -m 644 $(srcdir)/AUTHORS $(DESTDIR)$(docdir)
5354 $(INSTALL) -m 644 $(srcdir)/ChangeLog $(DESTDIR)$(docdir)
5657 $(INSTALL) -m 644 $(srcdir)/LICENSE $(DESTDIR)$(docdir)
5758 $(INSTALL) -m 644 $(srcdir)/NEWS $(DESTDIR)$(docdir)
5859 $(INSTALL) -m 644 $(srcdir)/README.md $(DESTDIR)$(docdir)
60 $(INSTALL) -m 755 -d $(DESTDIR)$(libdir)/pkgconfig
61 $(INSTALL) -m 644 getdns.pc $(DESTDIR)$(libdir)/pkgconfig
5962 $(INSTALL) -m 755 -d $(DESTDIR)$(docdir)/spec
6063 $(INSTALL) -m 644 $(srcdir)/spec/index.html $(DESTDIR)$(docdir)/spec
6164 $(INSTALL) -m 644 $(srcdir)/spec/getdns*tgz $(DESTDIR)$(docdir)/spec || true
112115 cd src && $(MAKE) $@
113116 cd doc && $(MAKE) $@
114117 cd spec/example && $(MAKE) $@
115 rm -f *.o
118 rm -f *.o *.pc
116119
117120 depend:
118121 cd src && $(MAKE) $@
122 cd spec/example && $(MAKE) $@
119123
120124 distclean:
121125 cd src && $(MAKE) $@
125129 cd spec/example && $(MAKE) $@
126130 rmdir spec/example 2>/dev/null || true
127131 rmdir spec 2>/dev/null || true
128 rm -f config.log config.status Makefile libtool
132 rm -f config.log config.status Makefile libtool getdns.pc
129133 rm -fR autom4te.cache
130134 rm -f m4/libtool.m4
131135 rm -f m4/lt~obsolete.m4
189193 cp $(srcdir)/install-sh $(distdir)
190194 cp $(srcdir)/config.sub $(distdir)
191195 cp $(srcdir)/config.guess $(distdir)
196 cp $(srcdir)/getdns.pc.in $(distdir)
192197 cp libtool $(distdir)
193198 cp $(srcdir)/ltmain.sh $(distdir)
194199 cp $(srcdir)/m4/*.m4 $(distdir)/m4
231236 rm -rf $(distdir)
232237 @echo "*** Package $(distdir).tar.gz is ready for distribution"
233238
239 getdns.pc: $(srcdir)/getdns.pc.in
240 ./config.status $@
241
234242 Makefile: $(srcdir)/Makefile.in config.status
235243 ./config.status $@
236244
00 getdns API
11 ==========
22
3 * Date: 2015-10-22
3 * Date: 2015-12-30
44 * GitHub: <https://github.com/getdnsapi/getdns>
55
66 getdns is an implementation of a modern asynchronous DNS API specification
1414 Download the sources from our [github repo](https://github.com/getdnsapi/getdns)
1515 or from [getdnsapi.net](https://getdnsapi.net) and verify the download using
1616 the checksums (SHA1 or MD5) or using gpg to verify the signature. Our keys are
17 available from the [pgp keyservers](http://keyserver.pgp.com)
17 available from the [pgp keyservers](https://keyserver.pgp.com)
1818
1919 * willem@nlnetlabs.nl, key id E5F8F8212F77A498
2020 * gwiley@verisign.com, key id 9DC3D572A6B73532
2121
22 The [getdns-api mailing list](http://www.vpnc.org/mailman/listinfo/getdns-api)
22 We have a [users list](https://getdnsapi.net/mailman/listinfo/spec) for this implementation.
23
24 The [getdns-api mailing list](https://getdnsapi.net/mailman/listinfo/spec)
2325 is a good place to engage in discussions regarding the design of the API.
2426
2527 If you are just getting started with the library take a look at the section
3436
3537 * Provide an open source implementation, in C, of the formally described getdns API by getdns API team at <https://getdnsapi.net/spec.html>
3638 * Initial support for FreeBSD, OSX, Linux (CentOS/RHEL, Ubuntu) via functional "configure" script
39 * Initial support for Windows 8.1
3740 * Initial support to include the Android platform
3841 * Include examples and tests as part of the build
3942 * Document code using doxygen
8386 ==============================
8487
8588 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.
89 Please refer to section for building on Windows for separate dependency and build instructions.
8690
8791 * [libunbound from NLnet Labs](https://unbound.net/) version 1.4.16 or later.
8892 * [libidn from the FSF](https://www.gnu.org/software/libidn/) version 1.
111115 * [libuv](https://github.com/joyent/libuv)
112116 * [libev](http://software.schmorp.de/pkg/libev.html)
113117
118 NOTE: The current Windows implementation does not support the above.
119
114120 ## Regression Tests
115121
116122 A suite of regression tests are included with the library, if you make changes or just
117123 want to sanity check things on your system take a look at src/test. You will need
118 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
124 to install [libcheck](https://libcheck.github.io/check/) and [libldns from NLnet Labs](https://nlnetlabs.nl/projects/ldns/) version 1.6.17 or later. Both libraries are also available from
119125 many of the package repositories for the more popular operating systems.
126
127 NOTE: The current Windows implementation does not support the above.
120128
121129 ## DNSSEC
122130
127135 format. Note that this is different than the format of BIND.keys.
128136
129137 The best way to setup or update the root trust anchor is by using
130 [`unbound-anchor`](http://www.unbound.net/documentation/unbound-anchor.html).
138 [`unbound-anchor`](https://www.unbound.net/documentation/unbound-anchor.html).
131139 To setup the library with the root trust anchor at the default location,
132140 execute the following steps as root:
133141
138146
139147 The following API calls are documented in getDNS but *not supported* by the implementation at this time:
140148
141 * DNS Search suffixes
142 * `getdns_context_set_append_name`
143 * `getdns_context_set_suffix`
144 * Setting root servers via `getdns_context_set_dns_root_servers`
149 * Disabling following of `CNAME`s with `getdns_context_set_follow_redirects()`
145150 * Detecting changes to resolv.conf and hosts
146 * MDNS and NetBIOS namespaces (only DNS and LOCALFILES are supported)
147
148 Some platform specific features are not implemented in the first public release of getdns, however they are on the radar. These include:
149
150 * Respecting settings in /etc/nsswitch.conf (linux and some other OSes), for the first release we simply check local files (/etc/hosts) before checking the DNS.
151 * Search suffixes specified in /etc/resolv.conf
151 * MDNS, NIS and NetBIOS namespaces (only DNS and LOCALFILES are supported)
152152
153153 #Known Issues
154154
166166 * RHEL/CentOS 6.4
167167 * OSX 10.8
168168 * Ubuntu 14.04
169
170 We intend to add MS-Windows, Android and other platforms to the releases as we have time to port it.
169 * Microsoft Windows 8.1 (initial support for DNSSEC but no TLS provided for version 0.5.1)
170
171 We intend to add Android and other platforms to the releases as we have time to port it.
171172
172173
173174 ##Platform Specific Build Reports
176177
177178 ###FreeBSD
178179
179 If you're using [FreeBSD](http://www.freebsd.org/), you may install getdns via the [ports tree](http://www.freshports.org/dns/getdns/) by running: `cd /usr/ports/dns/getdns && make install clean`
180 If you're using [FreeBSD](https://www.freebsd.org/), you may install getdns via the [ports tree](https://www.freshports.org/dns/getdns/) by running: `cd /usr/ports/dns/getdns && make install clean`
180181
181182 If you are using FreeBSD 10 getdns can be intalled via 'pkg install getdns'.
182183
232233
233234 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.
234235
236
237 ### Microsoft Windows 8.1
238
239 This section has some Windows specific build instructions.
240
241 Build tested using [Mingw(3.21.0) and Msys 1.0](http://www.mingw.org/) on Windows 8.1
242
243 Dependencies:
244 The following dependencies are built from source on Mingw
245 openssl1.0.2a
246 libidn
247
248 The windows version of getdns currently only is supported in the stub only mode.
249
250 To configure:
251
252 ./configure --enable-stub-only --with-trust-anchor="c:\\\MinGW\\\msys\\\1.0\\\etc\\\unbound\\\getdns-root.key" --with-ssl=/c/OpenSSL --with-getdns_query
253
254 The trust anchor is also installed by unbound on c:\program Files (X86)\unbound\root.key and can be referenced from there
255 or anywhere else that the user chooses to configure it.
256
257 After configuring, do a `make` and `make install` to build getdns for Windows.
258
259 Example test queries:
260
261 ./getdns_query.exe -s gmadkat.com A @64.6.64.6 +return_call_reporting (UDP)
262 ./getdns_query.exe -s gmadkat.com A @64.6.64.6 -T +return_call_reporting (TCP)
263 ./getdns_query.exe -s gmadkat.com A -l L @185.49.141.37 +return_call_reporting (TLS without authentication)
264 ./getdns_query.exe -s www.huque.com A +dnssec_return_status +return_call_reporting (DNSSEC)
265
266
235267 Contributors
236268 ============
237269 * Theogene Bucuti
238270 * Andrew Cathrow, Verisign Labs
271 * Neil Cook
239272 * Saúl Ibarra Corretgé
240273 * Craig Despeaux, Verisign, Inc.
241274 * John Dickinson, Sinodun
268301
269302 Acknowledgements
270303 ================
271 The development team explicitly acknowledges Paul Hoffman for his initiative and efforts to develop a consensus based DNS API. We would like to thank the participants of the [mailing list](http://www.vpnc.org/mailman/listinfo/getdns-api) for their contributions.
304 The development team explicitly acknowledges Paul Hoffman for his initiative and efforts to develop a consensus based DNS API. We would like to thank the participants of the [mailing list](https://getdnsapi.net/mailman/listinfo/spec) for their contributions.
00 #! /bin/sh
11 # Guess values for system-dependent variables and create Makefiles.
2 # Generated by GNU Autoconf 2.69 for getdns 0.5.1.
2 # Generated by GNU Autoconf 2.69 for getdns 0.9.0.
33 #
44 # Report bugs to <stub-resolver@verisignlabs.com>.
55 #
589589 # Identity of this package.
590590 PACKAGE_NAME='getdns'
591591 PACKAGE_TARNAME='getdns'
592 PACKAGE_VERSION='0.5.1'
593 PACKAGE_STRING='getdns 0.5.1'
592 PACKAGE_VERSION='0.9.0'
593 PACKAGE_STRING='getdns 0.9.0'
594594 PACKAGE_BUGREPORT='stub-resolver@verisignlabs.com'
595595 PACKAGE_URL='https://getdnsapi.net'
596596
770770 enable_debug_sched
771771 enable_debug_stub
772772 enable_debug_sec
773 enable_all_debugging
773774 enable_tcp_fastopen
774775 enable_native_stub_dnssec
775776 with_ssl
778779 enable_ecdsa
779780 enable_draft_dnssec_roadblock_avoidance
780781 enable_draft_edns_cookies
782 enable_all_drafts
781783 enable_stub_only
782784 with_libidn
783785 with_libunbound
13421344 # Omit some internal or obsolete options to make the list less imposing.
13431345 # This message is too long to be a string in the A/UX 3.1 sh.
13441346 cat <<_ACEOF
1345 \`configure' configures getdns 0.5.1 to adapt to many kinds of systems.
1347 \`configure' configures getdns 0.9.0 to adapt to many kinds of systems.
13461348
13471349 Usage: $0 [OPTION]... [VAR=VALUE]...
13481350
14071409
14081410 if test -n "$ac_init_help"; then
14091411 case $ac_init_help in
1410 short | recursive ) echo "Configuration of getdns 0.5.1:";;
1412 short | recursive ) echo "Configuration of getdns 0.9.0:";;
14111413 esac
14121414 cat <<\_ACEOF
14131415
14241426 --enable-debug-sched Enable scheduling debugging messages
14251427 --enable-debug-stub Enable stub debugging messages
14261428 --enable-debug-sec Enable dnssec debugging messages
1427 --enable-tcp-fastopen Enable TCP Fast Open
1429 --enable-all-debugging Enable scheduling, stub and dnssec debugging
1430 --disable-tcp-fastopen Disable TCP Fast Open (default=enabled if available)
14281431 --disable-native-stub-dnssec
14291432 Disable native stub DNSSEC support
14301433 --disable-sha2 Disable SHA256 and SHA512 RRSIG support
14341437 Enable experimental dnssec roadblock avoidance
14351438 --enable-draft-edns-cookies
14361439 Enable experimental edns cookies
1440 --enable-all-drafts Enable cookies and roadblock avoidance
14371441 --enable-stub-only Restricts resolution modes to STUB (which will be
14381442 the default mode). Removes the libunbound
14391443 dependency.
15491553 test -n "$ac_init_help" && exit $ac_status
15501554 if $ac_init_version; then
15511555 cat <<\_ACEOF
1552 getdns configure 0.5.1
1556 getdns configure 0.9.0
15531557 generated by GNU Autoconf 2.69
15541558
15551559 Copyright (C) 2012 Free Software Foundation, Inc.
19811985 This file contains any messages produced by compilers while
19821986 running configure, to aid debugging if configure makes a mistake.
19831987
1984 It was created by getdns $as_me 0.5.1, which was
1988 It was created by getdns $as_me 0.9.0, which was
19851989 generated by GNU Autoconf 2.69. Invocation command line was
19861990
19871991 $ $0 $@
23412345 fi
23422346
23432347
2344 GETDNS_VERSION="0.5.1$RELEASE_CANDIDATE"
2345
2346 GETDNS_NUMERIC_VERSION=0x00050100
2347
2348 API_VERSION="October 2015"
2349
2350 API_NUMERIC_VERSION=0x07df0a00
2348 GETDNS_VERSION="0.9.0$RELEASE_CANDIDATE"
2349
2350 GETDNS_NUMERIC_VERSION=0x00090000
2351
2352 API_VERSION="December 2015"
2353
2354 API_NUMERIC_VERSION=0x07df0c00
23512355
23522356 GETDNS_COMPILATION_COMMENT="getdns $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"
23532357
23742378 # getdns-0.3.2 had libversion 3:5:2
23752379 # getdns-0.3.3 had libversion 3:6:2
23762380 # getdns-0.5.0 had libversion 4:0:3
2377 # getdns-0.5.1 has libversion 4:1:3
2381 # getdns-0.5.1 had libversion 4:1:3 (but should have been getdns-0.6.0)
2382 # getdns-0.9.0 will have libversion 5:0:4
23782383 #
2379 GETDNS_LIBVERSION=4:1:3
2384 GETDNS_LIBVERSION=5:0:4
23802385
23812386
23822387
36653670
36663671
36673672 case "$host_os" in
3668 linux* ) CFLAGS="$CFLAGS -D_BSD_SOURCE"
3673 linux* ) CFLAGS="$CFLAGS -D_BSD_SOURCE -D_DEFAULT_SOURCE"
36693674 ;;
36703675 solaris* ) CFLAGS="$CFLAGS -D__EXTENSIONS__" # for strdup() from <string.h>
36713676 ;;
1122111226 fi
1122211227
1122311228
11229
1122411230 # Check whether --enable-debug-sched was given.
1122511231 if test "${enable_debug_sched+set}" = set; then :
1122611232 enableval=$enable_debug_sched;
1122711233 fi
1122811234
11229 case "$enable_debug_sched" in
11235 # Check whether --enable-debug-stub was given.
11236 if test "${enable_debug_stub+set}" = set; then :
11237 enableval=$enable_debug_stub;
11238 fi
11239
11240 # Check whether --enable-debug-sec was given.
11241 if test "${enable_debug_sec+set}" = set; then :
11242 enableval=$enable_debug_sec;
11243 fi
11244
11245 # Check whether --enable-all-debugging was given.
11246 if test "${enable_all_debugging+set}" = set; then :
11247 enableval=$enable_all_debugging;
11248 fi
11249
11250 case "$enable_all_debugging" in
1123011251 yes)
11231
11232 cat >>confdefs.h <<_ACEOF
11233 #define SCHED_DEBUG 1
11234 _ACEOF
11235
11252 enable_debug_sched=yes
11253 enable_debug_stub=yes
11254 enable_debug_sec=yes
1123611255 ;;
1123711256 no|*)
1123811257 ;;
1123911258 esac
11240 # Check whether --enable-debug-stub was given.
11241 if test "${enable_debug_stub+set}" = set; then :
11242 enableval=$enable_debug_stub;
11243 fi
11244
11245 case "$enable_debug_stub" in
11259 case "$enable_debug_sched" in
1124611260 yes)
1124711261
1124811262 cat >>confdefs.h <<_ACEOF
11249 #define STUB_DEBUG 1
11263 #define SCHED_DEBUG 1
1125011264 _ACEOF
1125111265
1125211266 ;;
1125311267 no|*)
1125411268 ;;
1125511269 esac
11256 # Check whether --enable-debug-sec was given.
11257 if test "${enable_debug_sec+set}" = set; then :
11258 enableval=$enable_debug_sec;
11259 fi
11260
11261 case "$enable_debug_sec" in
11270 case "$enable_debug_stub" in
1126211271 yes)
1126311272
1126411273 cat >>confdefs.h <<_ACEOF
11265 #define SEC_DEBUG 1
11274 #define STUB_DEBUG 1
1126611275 _ACEOF
1126711276
1126811277 ;;
1126911278 no|*)
1127011279 ;;
1127111280 esac
11272
11273 # Check whether --enable-tcp-fastopen was given.
11274 if test "${enable_tcp_fastopen+set}" = set; then :
11275 enableval=$enable_tcp_fastopen;
11276 fi
11277
11278 case "$enable_tcp_fastopen" in
11281 case "$enable_debug_sec" in
1127911282 yes)
11280 ac_fn_c_check_decl "$LINENO" "MSG_FASTOPEN" "ac_cv_have_decl_MSG_FASTOPEN" "$ac_includes_default
11281 #include <sys/socket.h>
11282
11283 "
11284 if test "x$ac_cv_have_decl_MSG_FASTOPEN" = xyes; then :
11285
11286 else
11287 as_fn_error $? "TCP Fast Open is not available: please rerun without --enable-tcp-fastopen" "$LINENO" 5
11288 fi
11289
1129011283
1129111284 cat >>confdefs.h <<_ACEOF
11292 #define USE_TCP_FASTOPEN 1
11285 #define SEC_DEBUG 1
1129311286 _ACEOF
1129411287
1129511288 ;;
1129711290 ;;
1129811291 esac
1129911292
11300 # Not yet enabled by default as crash found when TCP fails.
11301 # AC_ARG_ENABLE(tcp-fastopen, AC_HELP_STRING([--disable-tcp-fastopen], Disable TCP Fast Open (default=enabled if available)),
11302 # enable_tcp_fastopen="$enableval", enable_tcp_fastopen=yes)
11303 # if test "x$enable_tcp_fastopen" = xno; then
11304 # AC_MSG_WARN([TCP Fast Open is disabled])
11305 # else
11306 # AC_CHECK_DECL([MSG_FASTOPEN], [AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])],
11307 # [AC_MSG_WARN([TCP Fast Open is not available.])], [AC_INCLUDES_DEFAULT
11308 # #include <sys/socket.h>
11309 # ])
11310 # fi
11293 # Check whether --enable-tcp-fastopen was given.
11294 if test "${enable_tcp_fastopen+set}" = set; then :
11295 enableval=$enable_tcp_fastopen; enable_tcp_fastopen="$enableval"
11296 else
11297 enable_tcp_fastopen=yes
11298 fi
11299
11300 if test "x$enable_tcp_fastopen" = xno; then
11301 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: TCP Fast Open is disabled" >&5
11302 $as_echo "$as_me: WARNING: TCP Fast Open is disabled" >&2;}
11303 else
11304 case `uname` in
11305 Linux) ac_fn_c_check_decl "$LINENO" "MSG_FASTOPEN" "ac_cv_have_decl_MSG_FASTOPEN" "#include <sys/socket.h>
11306 "
11307 if test "x$ac_cv_have_decl_MSG_FASTOPEN" = xyes; then :
11308
11309 cat >>confdefs.h <<_ACEOF
11310 #define USE_TCP_FASTOPEN 1
11311 _ACEOF
11312
11313 else
11314 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: TCP Fast Open is not available, continuing without" >&5
11315 $as_echo "$as_me: WARNING: TCP Fast Open is not available, continuing without" >&2;}
11316 fi
11317
11318 ;;
11319 Darwin) ac_fn_c_check_decl "$LINENO" "CONNECT_RESUME_ON_READ_WRITE" "ac_cv_have_decl_CONNECT_RESUME_ON_READ_WRITE" "#include <sys/socket.h>
11320 "
11321 if test "x$ac_cv_have_decl_CONNECT_RESUME_ON_READ_WRITE" = xyes; then :
11322
11323 cat >>confdefs.h <<_ACEOF
11324 #define USE_OSX_TCP_FASTOPEN 1
11325 _ACEOF
11326
11327 else
11328 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: TCP Fast Open is not available, continuing without" >&5
11329 $as_echo "$as_me: WARNING: TCP Fast Open is not available, continuing without" >&2;}
11330 fi
11331
11332 ;;
11333 *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: TCP Fast Open is not available, continuing without" >&5
11334 $as_echo "$as_me: WARNING: TCP Fast Open is not available, continuing without" >&2;}
11335 ;;
11336 esac
11337 fi
1131111338
1131211339 # Check whether --enable-native-stub-dnssec was given.
1131311340 if test "${enable_native_stub_dnssec+set}" = set; then :
1138511412
1138611413 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_CTX_init in -lcrypto" >&5
1138711414 $as_echo_n "checking for HMAC_CTX_init in -lcrypto... " >&6; }
11388 LIBS="$LIBS -lcrypto -lssl"
11389 LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto -lssl"
11415 LIBS="$LIBS -lssl -lcrypto"
11416 LIBSSL_LIBS="$LIBSSL_LIBS -lssl -lcrypto"
1139011417 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
1139111418 /* end confdefs.h. */
1139211419
1181411841
1181511842 done
1181611843
11817 for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode
11844 for ac_func in OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode
1181811845 do :
1181911846 as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
1182011847 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
1218012207 ;;
1218112208 esac
1218212209
12210
1218312211 # Check whether --enable-draft-dnssec-roadblock-avoidance was given.
1218412212 if test "${enable_draft_dnssec_roadblock_avoidance+set}" = set; then :
1218512213 enableval=$enable_draft_dnssec_roadblock_avoidance;
1218612214 fi
1218712215
12188 case "$enable_draft_dnssec_roadblock_avoidance" in
12216 # Check whether --enable-draft-edns-cookies was given.
12217 if test "${enable_draft_edns_cookies+set}" = set; then :
12218 enableval=$enable_draft_edns_cookies;
12219 fi
12220
12221 # Check whether --enable-all-drafts was given.
12222 if test "${enable_all_drafts+set}" = set; then :
12223 enableval=$enable_all_drafts;
12224 fi
12225
12226 case "$enable_all_drafts" in
1218912227 yes)
12190
12191 cat >>confdefs.h <<_ACEOF
12192 #define DNSSEC_ROADBLOCK_AVOIDANCE 1
12193 _ACEOF
12194
12228 enable_draft_dnssec_roadblock_avoidance=yes
12229 enable_draft_edns_cookies=yes
1219512230 ;;
1219612231 no|*)
1219712232 ;;
1219812233 esac
12199
12200 # Check whether --enable-draft-edns-cookies was given.
12201 if test "${enable_draft_edns_cookies+set}" = set; then :
12202 enableval=$enable_draft_edns_cookies;
12203 fi
12204
12234 case "$enable_draft_dnssec_roadblock_avoidance" in
12235 yes)
12236
12237 cat >>confdefs.h <<_ACEOF
12238 #define DNSSEC_ROADBLOCK_AVOIDANCE 1
12239 _ACEOF
12240
12241 ;;
12242 no|*)
12243 ;;
12244 esac
1220512245 case "$enable_draft_edns_cookies" in
1220612246 yes)
1220712247 if test "x_$HAVE_SSL" != "x_yes"; then
1225312293 esac
1225412294
1225512295 # search to set include and library paths right
12256 # find libidn
12257 my_with_libidn=1
12296 # find libidn (no libidn on windows though)
12297 for ac_header in windows.h winsock.h stdio.h winsock2.h ws2tcpip.h
12298 do :
12299 as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
12300 ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
12301 "
12302 if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
12303 cat >>confdefs.h <<_ACEOF
12304 #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
12305 _ACEOF
12306
12307 fi
12308
12309 done
12310
12311
12312 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5
12313 $as_echo_n "checking for getaddrinfo... " >&6; }
12314 ac_cv_func_getaddrinfo=no
12315 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
12316 /* end confdefs.h. */
12317
12318 #ifdef __cplusplus
12319 extern "C"
12320 {
12321 #endif
12322 char* getaddrinfo();
12323 char* (*f) () = getaddrinfo;
12324 #ifdef __cplusplus
12325 }
12326 #endif
12327 int main() {
12328 ;
12329 return 0;
12330 }
12331
12332 _ACEOF
12333 if ac_fn_c_try_link "$LINENO"; then :
12334 ac_cv_func_getaddrinfo="yes"
12335 if test "$ac_cv_header_windows_h" = "yes"; then
12336
12337 $as_echo "#define USE_WINSOCK 1" >>confdefs.h
12338
12339 USE_WINSOCK="1"
12340 LIBS="$LIBS -lws2_32"
12341 fi
12342
12343 else
12344 ORIGLIBS="$LIBS"
12345 LIBS="$LIBS -lws2_32"
12346 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
12347 /* end confdefs.h. */
12348
12349 #define _WIN32_WINNT 0x0501
12350 #ifdef HAVE_WINDOWS_H
12351 #include <windows.h>
12352 #endif
12353 #ifdef HAVE_WINSOCK_H
12354 #include <winsock.h>
12355 #endif
12356 #ifdef HAVE_WINSOCK2_H
12357 #include <winsock2.h>
12358 #endif
12359 #include <stdio.h>
12360 #ifdef HAVE_WS2TCPIP_H
12361 #include <ws2tcpip.h>
12362 #endif
12363
12364 int
12365 main ()
12366 {
12367
12368 (void)getaddrinfo(NULL, NULL, NULL, NULL);
12369
12370
12371 ;
12372 return 0;
12373 }
12374 _ACEOF
12375 if ac_fn_c_try_link "$LINENO"; then :
12376
12377 ac_cv_func_getaddrinfo="yes"
12378
12379 $as_echo "#define USE_WINSOCK 1" >>confdefs.h
12380
12381 USE_WINSOCK="1"
12382
12383 else
12384
12385 ac_cv_func_getaddrinfo="no"
12386 LIBS="$ORIGLIBS"
12387
12388 fi
12389 rm -f core conftest.err conftest.$ac_objext \
12390 conftest$ac_exeext conftest.$ac_ext
12391
12392 fi
12393 rm -f core conftest.err conftest.$ac_objext \
12394 conftest$ac_exeext conftest.$ac_ext
12395
12396 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getaddrinfo" >&5
12397 $as_echo "$ac_cv_func_getaddrinfo" >&6; }
12398 if test $ac_cv_func_getaddrinfo = yes; then
12399
12400 $as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h
12401
12402 fi
12403
12404 if test "$USE_WINSOCK" = 1; then
12405 { $as_echo "$as_me:${as_lineno-$LINENO}: Building on Windows ... YES! " >&5
12406 $as_echo "$as_me: Building on Windows ... YES! " >&6;}
12407
12408 cat >>confdefs.h <<_ACEOF
12409 #define GETDNS_ON_WINDOWS 1
12410 _ACEOF
12411
12412 cat >>confdefs.h <<_ACEOF
12413 #define STUB_NATIVE_DNSSEC 1
12414 _ACEOF
12415
12416 LIBS="$LIBS -lgdi32 -liphlpapi"
12417 my_with_libunbound=0
12418 my_with_libidn=0
12419 else
12420 my_with_libidn=1
12421 fi
12422
12423
12424 if test $my_with_libidn = 1
12425 then
1225812426
1225912427 # Check whether --with-libidn was given.
1226012428 if test "${with_libidn+set}" = set; then :
1226312431 withval="yes"
1226412432 fi
1226512433
12266 if test x_$withval = x_yes; then
12267 for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
12268 if test -f "$dir/include/idna.h"; then
12269 CFLAGS="$CFLAGS -I$dir/include"
12270 LDFLAGS="$LDFLAGS -L$dir/lib"
12271 { $as_echo "$as_me:${as_lineno-$LINENO}: Found libidn in $dir" >&5
12434 if test x_$withval = x_yes; then
12435 for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
12436 if test -f "$dir/include/idna.h"; then
12437 CFLAGS="$CFLAGS -I$dir/include"
12438 LDFLAGS="$LDFLAGS -L$dir/lib"
12439 { $as_echo "$as_me:${as_lineno-$LINENO}: Found libidn in $dir" >&5
1227212440 $as_echo "$as_me: Found libidn in $dir" >&6;}
12273 break
12441 break
12442 fi
12443 if test -f "$dir/include/idn/idna.h"; then
12444 CFLAGS="$CFLAGS -I$dir/include/idn"
12445 LDFLAGS="$LDFLAGS -L$dir/lib"
12446 { $as_echo "$as_me:${as_lineno-$LINENO}: Found libidn in $dir" >&5
12447 $as_echo "$as_me: Found libidn in $dir" >&6;}
12448 break
12449 fi
12450 done
12451 if test -f "/usr/include/idn/idna.h"; then
12452 CFLAGS="$CFLAGS -I/usr/include/idn"
12453 #LDFLAGS="$LDFLAGS -L/usr/lib"
12454 { $as_echo "$as_me:${as_lineno-$LINENO}: Found libidn in /usr" >&5
12455 $as_echo "$as_me: Found libidn in /usr" >&6;}
1227412456 fi
12275 if test -f "$dir/include/idn/idna.h"; then
12276 CFLAGS="$CFLAGS -I$dir/include/idn"
12277 LDFLAGS="$LDFLAGS -L$dir/lib"
12278 { $as_echo "$as_me:${as_lineno-$LINENO}: Found libidn in $dir" >&5
12279 $as_echo "$as_me: Found libidn in $dir" >&6;}
12280 break
12457 else
12458 if test x_$withval != x_no; then
12459 CFLAGS="$CFLAGS -I$withval/include"
12460 LDFLAGS="$LDFLAGS -L$withval/lib"
12461 else
12462 my_with_libidn=0
1228112463 fi
12282 done
12283 if test -f "/usr/include/idn/idna.h"; then
12284 CFLAGS="$CFLAGS -I/usr/include/idn"
12285 #LDFLAGS="$LDFLAGS -L/usr/lib"
12286 { $as_echo "$as_me:${as_lineno-$LINENO}: Found libidn in /usr" >&5
12287 $as_echo "$as_me: Found libidn in /usr" >&6;}
12288 fi
12289 else
12290 if test x_$withval != x_no; then
12291 CFLAGS="$CFLAGS -I$withval/include"
12292 LDFLAGS="$LDFLAGS -L$withval/lib"
12293 else
12294 my_with_libidn=0
1229512464 fi
1229612465 fi
1229712466
1403414203
1403514204
1403614205
14037 ac_config_files="$ac_config_files Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile doc/Makefile"
14206 ac_config_files="$ac_config_files Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile doc/Makefile getdns.pc"
1403814207
1403914208 if test -n "$DOXYGEN"
1404014209 then ac_config_files="$ac_config_files src/Doxyfile"
1416414333 cat >>confdefs.h <<_ACEOF
1416514334 #define HAVE_DECL_ARC4RANDOM_UNIFORM $ac_have_decl
1416614335 _ACEOF
14336
14337 ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton"
14338 if test "x$ac_cv_func_inet_pton" = xyes; then :
14339 $as_echo "#define HAVE_INET_PTON 1" >>confdefs.h
14340
14341 else
14342 case " $LIBOBJS " in
14343 *" inet_pton.$ac_objext "* ) ;;
14344 *) LIBOBJS="$LIBOBJS inet_pton.$ac_objext"
14345 ;;
14346 esac
14347
14348 fi
14349
14350
14351 ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop"
14352 if test "x$ac_cv_func_inet_ntop" = xyes; then :
14353 $as_echo "#define HAVE_INET_NTOP 1" >>confdefs.h
14354
14355 else
14356 case " $LIBOBJS " in
14357 *" inet_ntop.$ac_objext "* ) ;;
14358 *) LIBOBJS="$LIBOBJS inet_ntop.$ac_objext"
14359 ;;
14360 esac
14361
14362 fi
14363
1416714364
1416814365 ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy"
1416914366 if test "x$ac_cv_func_strlcpy" = xyes; then :
1500715204 # report actual input values of CONFIG_FILES etc. instead of their
1500815205 # values after options handling.
1500915206 ac_log="
15010 This file was extended by getdns $as_me 0.5.1, which was
15207 This file was extended by getdns $as_me 0.9.0, which was
1501115208 generated by GNU Autoconf 2.69. Invocation command line was
1501215209
1501315210 CONFIG_FILES = $CONFIG_FILES
1507415271 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
1507515272 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
1507615273 ac_cs_version="\\
15077 getdns config.status 0.5.1
15274 getdns config.status 0.9.0
1507815275 configured by $0, generated by GNU Autoconf 2.69,
1507915276 with options \\"\$ac_cs_config\\"
1508015277
1548815685 "spec/example/Makefile") CONFIG_FILES="$CONFIG_FILES spec/example/Makefile" ;;
1548915686 "src/test/Makefile") CONFIG_FILES="$CONFIG_FILES src/test/Makefile" ;;
1549015687 "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
15688 "getdns.pc") CONFIG_FILES="$CONFIG_FILES getdns.pc" ;;
1549115689 "src/Doxyfile") CONFIG_FILES="$CONFIG_FILES src/Doxyfile" ;;
1549215690 "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;;
1549315691
3131 AC_PREREQ([2.56])
3232 AC_CONFIG_MACRO_DIRS([m4])
3333 sinclude(./m4/acx_openssl.m4)
34 sinclude(./m4/acx_getaddrinfo.m4)
3435 sinclude(./m4/ax_check_compile_flag.m4)
3536 sinclude(./m4/pkg.m4)
3637
37 AC_INIT([getdns], [0.5.1], [stub-resolver@verisignlabs.com], [], [https://getdnsapi.net])
38 AC_INIT([getdns], [0.9.0], [stub-resolver@verisignlabs.com], [], [https://getdnsapi.net])
3839 AC_SUBST(RELEASE_CANDIDATE, [])
3940
4041 # Set current date from system if not set
4546 [CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])
4647
4748 AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"])
48 AC_SUBST(GETDNS_NUMERIC_VERSION, [0x00050100])
49 AC_SUBST(API_VERSION, ["October 2015"])
50 AC_SUBST(API_NUMERIC_VERSION, [0x07df0a00])
49 AC_SUBST(GETDNS_NUMERIC_VERSION, [0x00090000])
50 AC_SUBST(API_VERSION, ["December 2015"])
51 AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00])
5152 GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"
5253
5354
7374 # getdns-0.3.2 had libversion 3:5:2
7475 # getdns-0.3.3 had libversion 3:6:2
7576 # getdns-0.5.0 had libversion 4:0:3
76 # getdns-0.5.1 has libversion 4:1:3
77 # getdns-0.5.1 had libversion 4:1:3 (but should have been getdns-0.6.0)
78 # getdns-0.9.0 will have libversion 5:0:4
7779 #
78 GETDNS_LIBVERSION=4:1:3
80 GETDNS_LIBVERSION=5:0:4
7981
8082 AC_SUBST(GETDNS_COMPILATION_COMMENT)
8183 AC_SUBST(GETDNS_LIBVERSION)
9698 AX_CHECK_COMPILE_FLAG([-Wall],[CFLAGS="$CFLAGS -Wall"],[],[])
9799
98100 case "$host_os" in
99 linux* ) CFLAGS="$CFLAGS -D_BSD_SOURCE"
101 linux* ) CFLAGS="$CFLAGS -D_BSD_SOURCE -D_DEFAULT_SOURCE"
100102 ;;
101103 solaris* ) CFLAGS="$CFLAGS -D__EXTENSIONS__" # for strdup() from <string.h>
102104 ;;
136138 ])
137139 ACX_ARG_RPATH
138140
141
139142 AC_ARG_ENABLE(debug-sched, AC_HELP_STRING([--enable-debug-sched], [Enable scheduling debugging messages]))
143 AC_ARG_ENABLE(debug-stub, AC_HELP_STRING([--enable-debug-stub], [Enable stub debugging messages]))
144 AC_ARG_ENABLE(debug-sec, AC_HELP_STRING([--enable-debug-sec], [Enable dnssec debugging messages]))
145 AC_ARG_ENABLE(all-debugging, AC_HELP_STRING([--enable-all-debugging], [Enable scheduling, stub and dnssec debugging]))
146 case "$enable_all_debugging" in
147 yes)
148 enable_debug_sched=yes
149 enable_debug_stub=yes
150 enable_debug_sec=yes
151 ;;
152 no|*)
153 ;;
154 esac
140155 case "$enable_debug_sched" in
141156 yes)
142157 AC_DEFINE_UNQUOTED([SCHED_DEBUG], [1], [Define this to enable printing of scheduling debugging messages.])
144159 no|*)
145160 ;;
146161 esac
147 AC_ARG_ENABLE(debug-stub, AC_HELP_STRING([--enable-debug-stub], [Enable stub debugging messages]))
148162 case "$enable_debug_stub" in
149163 yes)
150164 AC_DEFINE_UNQUOTED([STUB_DEBUG], [1], [Define this to enable printing of stub debugging messages.])
152166 no|*)
153167 ;;
154168 esac
155 AC_ARG_ENABLE(debug-sec, AC_HELP_STRING([--enable-debug-sec], [Enable dnssec debugging messages]))
156169 case "$enable_debug_sec" in
157170 yes)
158171 AC_DEFINE_UNQUOTED([SEC_DEBUG], [1], [Define this to enable printing of dnssec debugging messages.])
161174 ;;
162175 esac
163176
164 AC_ARG_ENABLE(tcp-fastopen, AC_HELP_STRING([--enable-tcp-fastopen], [Enable TCP Fast Open]))
165 case "$enable_tcp_fastopen" in
166 yes)
167 AC_CHECK_DECL([MSG_FASTOPEN], [], [AC_MSG_ERROR([TCP Fast Open is not available: please rerun without --enable-tcp-fastopen])], [AC_INCLUDES_DEFAULT
168 #include <sys/socket.h>
169 ])
170 AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])
171 ;;
172 no|*)
173 ;;
174 esac
175
176 # Not yet enabled by default as crash found when TCP fails.
177 # AC_ARG_ENABLE(tcp-fastopen, AC_HELP_STRING([--disable-tcp-fastopen], Disable TCP Fast Open (default=enabled if available)),
178 # enable_tcp_fastopen="$enableval", enable_tcp_fastopen=yes)
179 # if test "x$enable_tcp_fastopen" = xno; then
180 # AC_MSG_WARN([TCP Fast Open is disabled])
181 # else
182 # AC_CHECK_DECL([MSG_FASTOPEN], [AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])],
183 # [AC_MSG_WARN([TCP Fast Open is not available.])], [AC_INCLUDES_DEFAULT
184 # #include <sys/socket.h>
185 # ])
186 # fi
177 AC_ARG_ENABLE(tcp-fastopen, AC_HELP_STRING([--disable-tcp-fastopen], Disable TCP Fast Open (default=enabled if available)),
178 enable_tcp_fastopen="$enableval", enable_tcp_fastopen=yes)
179 if test "x$enable_tcp_fastopen" = xno; then
180 AC_MSG_WARN([TCP Fast Open is disabled])
181 else
182 case `uname` in
183 Linux) AC_CHECK_DECL([MSG_FASTOPEN], [AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])],
184 [AC_MSG_WARN([TCP Fast Open is not available, continuing without])], [#include <sys/socket.h>])
185 ;;
186 Darwin) AC_CHECK_DECL([CONNECT_RESUME_ON_READ_WRITE], [AC_DEFINE_UNQUOTED([USE_OSX_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])],
187 [AC_MSG_WARN([TCP Fast Open is not available, continuing without])], [#include <sys/socket.h>])
188 ;;
189 *) AC_MSG_WARN([TCP Fast Open is not available, continuing without])
190 ;;
191 esac
192 fi
187193
188194 AC_ARG_ENABLE(native-stub-dnssec, AC_HELP_STRING([--disable-native-stub-dnssec], [Disable native stub DNSSEC support]))
189195 case "$enable_native_stub_dnssec" in
211217 fi
212218 AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
213219 AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
214 AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode])
220 AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode])
215221 AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
216222 AC_INCLUDES_DEFAULT
217223 #ifdef HAVE_OPENSSL_ERR_H
392398 ;;
393399 esac
394400
401
395402 AC_ARG_ENABLE(draft-dnssec-roadblock-avoidance, AC_HELP_STRING([--enable-draft-dnssec-roadblock-avoidance], [Enable experimental dnssec roadblock avoidance]))
403 AC_ARG_ENABLE(draft-edns-cookies, AC_HELP_STRING([--enable-draft-edns-cookies], [Enable experimental edns cookies]))
404 AC_ARG_ENABLE(all-drafts, AC_HELP_STRING([--enable-all-drafts], [Enable cookies and roadblock avoidance]))
405 case "$enable_all_drafts" in
406 yes)
407 enable_draft_dnssec_roadblock_avoidance=yes
408 enable_draft_edns_cookies=yes
409 ;;
410 no|*)
411 ;;
412 esac
396413 case "$enable_draft_dnssec_roadblock_avoidance" in
397414 yes)
398415 AC_DEFINE_UNQUOTED([DNSSEC_ROADBLOCK_AVOIDANCE], [1], [Define this to enable the experimental draft dnssec roadblock avoidance.])
400417 no|*)
401418 ;;
402419 esac
403
404 AC_ARG_ENABLE(draft-edns-cookies, AC_HELP_STRING([--enable-draft-edns-cookies], [Enable experimental edns cookies]))
405420 case "$enable_draft_edns_cookies" in
406421 yes)
407422 if test "x_$HAVE_SSL" != "x_yes"; then
429444 esac
430445
431446 # search to set include and library paths right
432 # find libidn
433 my_with_libidn=1
434 AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
435 [path to libidn (default: search /usr/local ..)]),
436 [], [withval="yes"])
437 if test x_$withval = x_yes; then
438 for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
439 if test -f "$dir/include/idna.h"; then
440 CFLAGS="$CFLAGS -I$dir/include"
441 LDFLAGS="$LDFLAGS -L$dir/lib"
442 AC_MSG_NOTICE([Found libidn in $dir])
443 break
447 # find libidn (no libidn on windows though)
448 AC_CHECK_HEADERS([windows.h winsock.h stdio.h winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT])
449 ACX_CHECK_GETADDRINFO_WITH_INCLUDES
450 if test "$USE_WINSOCK" = 1; then
451 AC_MSG_NOTICE([ Building on Windows ... YES! ])
452 AC_DEFINE_UNQUOTED([GETDNS_ON_WINDOWS], [1], [Define this to enable Windows build.])
453 AC_DEFINE_UNQUOTED([STUB_NATIVE_DNSSEC], [1])
454 LIBS="$LIBS -lgdi32 -liphlpapi"
455 my_with_libunbound=0
456 my_with_libidn=0
457 else
458 my_with_libidn=1
459 fi
460
461
462 if test $my_with_libidn = 1
463 then
464 AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
465 [path to libidn (default: search /usr/local ..)]),
466 [], [withval="yes"])
467 if test x_$withval = x_yes; then
468 for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
469 if test -f "$dir/include/idna.h"; then
470 CFLAGS="$CFLAGS -I$dir/include"
471 LDFLAGS="$LDFLAGS -L$dir/lib"
472 AC_MSG_NOTICE([Found libidn in $dir])
473 break
474 fi
475 if test -f "$dir/include/idn/idna.h"; then
476 CFLAGS="$CFLAGS -I$dir/include/idn"
477 LDFLAGS="$LDFLAGS -L$dir/lib"
478 AC_MSG_NOTICE([Found libidn in $dir])
479 break
480 fi
481 done
482 if test -f "/usr/include/idn/idna.h"; then
483 CFLAGS="$CFLAGS -I/usr/include/idn"
484 #LDFLAGS="$LDFLAGS -L/usr/lib"
485 AC_MSG_NOTICE([Found libidn in /usr])
444486 fi
445 if test -f "$dir/include/idn/idna.h"; then
446 CFLAGS="$CFLAGS -I$dir/include/idn"
447 LDFLAGS="$LDFLAGS -L$dir/lib"
448 AC_MSG_NOTICE([Found libidn in $dir])
449 break
487 else
488 if test x_$withval != x_no; then
489 CFLAGS="$CFLAGS -I$withval/include"
490 LDFLAGS="$LDFLAGS -L$withval/lib"
491 else
492 my_with_libidn=0
450493 fi
451 done
452 if test -f "/usr/include/idn/idna.h"; then
453 CFLAGS="$CFLAGS -I/usr/include/idn"
454 #LDFLAGS="$LDFLAGS -L/usr/lib"
455 AC_MSG_NOTICE([Found libidn in /usr])
456 fi
457 else
458 if test x_$withval != x_no; then
459 CFLAGS="$CFLAGS -I$withval/include"
460 LDFLAGS="$LDFLAGS -L$withval/lib"
461 else
462 my_with_libidn=0
463494 fi
464495 fi
465496
876907 AC_SUBST(INSTALL_GETDNS_QUERY)
877908 AC_SUBST(UNINSTALL_GETDNS_QUERY)
878909
879 AC_CONFIG_FILES([Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile doc/Makefile])
910 AC_CONFIG_FILES([Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile doc/Makefile getdns.pc])
880911 if [ test -n "$DOXYGEN" ]
881912 then AC_CONFIG_FILES([src/Doxyfile])
882913 fi
927958 AC_DEFINE(HAVE_ATTR_UNUSED, 1, [Whether the C compiler accepts the "unused" attribute])
928959 fi
929960 AC_CHECK_DECLS([strlcpy,arc4random,arc4random_uniform])
961 AC_REPLACE_FUNCS(inet_pton)
962 AC_REPLACE_FUNCS(inet_ntop)
930963 AC_REPLACE_FUNCS(strlcpy)
931964 AC_REPLACE_FUNCS(arc4random)
932965 AC_REPLACE_FUNCS(arc4random_uniform)
9841017 AC_SUBST(C99COMPATFLAGS)
9851018
9861019 AH_BOTTOM([
1020
1021 /* the version of the windows API enabled */
1022 #undef WINVER
1023 #undef _WIN32_WINNT
1024 #define WINVER 0x0600 // 0x0502
1025 #define _WIN32_WINNT 0x0600 // 0x0502
1026 #ifdef HAVE_WINSOCK2_H
1027 #include <winsock2.h>
1028 #include<BaseTsd.h>
1029 #endif
1030
1031 #ifdef HAVE_WS2TCPIP_H
1032 #include <ws2tcpip.h>
1033 #endif
1034
1035 #ifndef USE_WINSOCK
1036 #define ARG_LL "%ll"
1037 #else
1038 #define ARG_LL "%I64"
1039 #endif
1040
1041 /* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
1042 #ifdef HAVE_WINSOCK2_H
1043 #define FD_SET_T (u_int)
1044 #else
1045 #define FD_SET_T
1046 #endif
1047
1048
9871049 #include <stdint.h>
9881050 #include <stdio.h>
9891051 #include <unistd.h>
10401102 unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest);
10411103 #endif /* COMPAT_SHA512 */
10421104
1105 #ifndef HAVE_INET_PTON
1106 int inet_pton(int af, const char* src, void* dst);
1107 #endif /* HAVE_INET_PTON */
1108
1109 #ifndef HAVE_INET_NTOP
1110 const char *inet_ntop(int af, const void *src, char *dst, size_t size);
1111 #endif
1112
10431113 #ifdef __cplusplus
10441114 }
10451115 #endif
10931163 # define ATTR_UNUSED(x) x
10941164 #endif /* !HAVE_ATTR_UNUSED */
10951165
1096 /* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
1097 #ifdef HAVE_WINSOCK2_H
1098 #define FD_SET_T (u_int)
1099 #else
1100 #define FD_SET_T
1101 #endif
1102
11031166 #ifdef TIME_WITH_SYS_TIME
11041167 # include <sys/time.h>
11051168 # include <time.h>
274274 Set to the DNS class number (other than Internet (IN) class desired in query.
275275
276276 .HP 3
277 "return_call_debugging" (int)
277 "return_call_reporting" (int)
278278
279279 Set to GETDNS_EXTENSION_TRUE to add the name
280 .I call_debugging
280 .I call_reporting
281281 (list) to the top level of the response object that includes a dict for each call made to the API. TBD: more detail
282282
283283 .LP
0 prefix=@prefix@
1 exec_prefix=${prefix}
2 libdir=${exec_prefix}/lib
3 includedir=${prefix}/include
4
5 Name: getdns
6 Version: @GETDNS_VERSION@
7 Description: A modern asynchronous DNS library
8
9 Libs: -L${libdir} -lgetdns
10 Cflags: -I${includedir}
163163 LTCC="gcc"
164164
165165 # LTCC compiler flags.
166 LTCFLAGS="-g -O2 -Wall -D_BSD_SOURCE -I/usr/local/include"
166 LTCFLAGS="-g -O2 -Wall -D_BSD_SOURCE -D_DEFAULT_SOURCE -I/usr/local/include"
167167
168168 # Take the output of nm and produce a listing of raw symbols and C names.
169169 global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ ][ ]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p' | sed '/ __gnu_lto/d'"
0 # Taken from acx_nlnetlabs.m4 - common macros for configure checks
1 # Copyright 2009, Wouter Wijngaards, NLnet Labs.
2 # BSD licensed.
3 #
4
5 dnl Check getaddrinfo.
6 dnl Works on linux, solaris, bsd and windows(links winsock).
7 dnl defines HAVE_GETADDRINFO, USE_WINSOCK.
8 AC_DEFUN([ACX_CHECK_GETADDRINFO_WITH_INCLUDES],
9 [AC_REQUIRE([AC_PROG_CC])
10 AC_MSG_CHECKING(for getaddrinfo)
11 ac_cv_func_getaddrinfo=no
12 AC_LINK_IFELSE(
13 [AC_LANG_SOURCE([[
14 #ifdef __cplusplus
15 extern "C"
16 {
17 #endif
18 char* getaddrinfo();
19 char* (*f) () = getaddrinfo;
20 #ifdef __cplusplus
21 }
22 #endif
23 int main() {
24 ;
25 return 0;
26 }
27 ]])],
28 dnl this case on linux, solaris, bsd
29 [ac_cv_func_getaddrinfo="yes"
30 dnl see if on windows
31 if test "$ac_cv_header_windows_h" = "yes"; then
32 AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
33 USE_WINSOCK="1"
34 LIBS="$LIBS -lws2_32"
35 fi
36 ],
37 dnl no quick getaddrinfo, try mingw32 and winsock2 library.
38 ORIGLIBS="$LIBS"
39 LIBS="$LIBS -lws2_32"
40 AC_LINK_IFELSE(
41 [AC_LANG_PROGRAM(
42 [
43 #define _WIN32_WINNT 0x0501
44 #ifdef HAVE_WINDOWS_H
45 #include <windows.h>
46 #endif
47 #ifdef HAVE_WINSOCK_H
48 #include <winsock.h>
49 #endif
50 #ifdef HAVE_WINSOCK2_H
51 #include <winsock2.h>
52 #endif
53 #include <stdio.h>
54 #ifdef HAVE_WS2TCPIP_H
55 #include <ws2tcpip.h>
56 #endif
57 ],
58 [
59 (void)getaddrinfo(NULL, NULL, NULL, NULL);
60 ]
61 )],
62 [
63 ac_cv_func_getaddrinfo="yes"
64 dnl already: LIBS="$LIBS -lws2_32"
65 AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
66 USE_WINSOCK="1"
67 ],
68 [
69 ac_cv_func_getaddrinfo="no"
70 LIBS="$ORIGLIBS"
71 ])
72 )
73
74 AC_MSG_RESULT($ac_cv_func_getaddrinfo)
75 if test $ac_cv_func_getaddrinfo = yes; then
76 AC_DEFINE(HAVE_GETADDRINFO, 1, [Whether getaddrinfo is available])
77 fi
78 ])dnl Endof AC_CHECK_GETADDRINFO_WITH_INCLUDES
79
80 dnl End of file
4747 fi
4848
4949 AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
50 LIBS="$LIBS -lcrypto -lssl"
51 LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto -lssl"
50 LIBS="$LIBS -lssl -lcrypto"
51 LIBSSL_LIBS="$LIBSSL_LIBS -lssl -lcrypto"
5252 AC_TRY_LINK(, [
5353 int HMAC_CTX_init(void);
5454 (void)HMAC_CTX_init();
132132
133133 depend:
134134 (cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
135 (cd $(srcdir) ; gcc -MM -I. -I../../src *.c | \
136 sed -e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
137 -e 's? \$$(srcdir)/config\.h? ../../src/config.h?g' \
138 -e 's? \.\./\.\./src/getdns/getdns_extra\.h? $$(srcdir)/../../src/getdns/getdns_extra.h?g' \
135 (blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I../../src -I"$$blddir"/../../src *.c | \
136 sed -e "s? $$blddir/? ?g" \
137 -e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
138 -e 's? \$$(srcdir)/\.\./\.\./src/config\.h? ../../src/config.h?g' \
139 -e 's? $$(srcdir)/\.\./\.\./src/getdns/getdns_extra\.h? ../../src/getdns/getdns_extra.h?g' \
139140 -e 's? \.\./\.\./src/getdns/getdns_ext_libevent\.h? $$(srcdir)/../../src/getdns/getdns_ext_libevent.h?g' \
140141 -e 's? \.\./\.\./src/getdns/getdns_ext_libev\.h? $$(srcdir)/../../src/getdns/getdns_ext_libev.h?g' \
141142 -e 's? \.\./\.\./src/getdns/getdns_ext_libuv\.h? $$(srcdir)/../../src/getdns/getdns_ext_libuv.h?g' \
143 -e 's? \.\./\.\./src/debug\.h? $$(srcdir)/../../src/debug.h?g' \
142144 -e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' >> Makefile.in.new )
143145 (cd $(srcdir) ; diff Makefile.in.new Makefile.in && rm Makefile.in.new \
144 || mv Makefile.in.new Makefile.in )
146 || mv Makefile.in.new Makefile.in )
145147
146148
147149 # Dependencies for the examples
148150 example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \
149151 ../../src/config.h ../../src/getdns/getdns.h \
150 $(srcdir)/../../src/getdns/getdns_ext_libevent.h $(srcdir)/../../src/getdns/getdns_extra.h
152 $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h
151153 example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h ../../src/config.h \
152154 ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \
153 $(srcdir)/../../src/getdns/getdns_extra.h
155 ../../src/getdns/getdns_extra.h
154156 example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \
155157 ../../src/config.h ../../src/getdns/getdns.h \
156 $(srcdir)/../../src/getdns/getdns_ext_libevent.h $(srcdir)/../../src/getdns/getdns_extra.h
158 $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h
157159 example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \
158160 ../../src/getdns/getdns.h
159161 example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h ../../src/config.h \
160162 ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \
161 $(srcdir)/../../src/getdns/getdns_extra.h
163 ../../src/getdns/getdns_extra.h
9393 <p class=title2>Originally edited by Paul Hoffman</p>
9494 <p class=title2>Currently maintained by the <a
9595 href="mailto:team@getdnsapi.net">getdns team</a></p>
96 <p class=title2>Document version: "getdns October 2015"</p>
96 <p class=title2>Document version: "getdns December 2015"</p>
9797
9898 <p>This document describes a modern asynchronous DNS API. This new API is intended to be useful to
9999 application developers and operating system distributors as a way of making
667667
668668 <li><code>specify_class</code></li>
669669
670 <li><code>return_call_debugging</code></li>
670 <li><code>return_call_reporting</code></li>
671671
672672 </ul>
673673
864864 <h2>3.6 Extensions Relating to the API</h2>
865865
866866 <p>An application might want to see debugging information for queries such as the length of time it
867 takes for each query to return to the API. Use the <code>return_call_debugging</code> extension. The
867 takes for each query to return to the API. Use the <code>return_call_reporting</code> extension. The
868868 extension's value (an int) is set to <code>GETDNS_EXTENSION_TRUE</code> to add the name
869 <code>call_debugging</code> (a list) to the top level of the response object. Each member of the
869 <code>call_reporting</code> (a list) to the top level of the response object. Each member of the
870870 list is a dict that represents one call made for the call to the API. Each member has the following
871871 names:</p>
872872
874874 <li><code>query_name</code> (a bindata) is the name that was sent</li>
875875 <li><code>query_type</code> (an int) is the type that was queried for</li>
876876 <li><code>query_to</code> (a bindata) is the address to which the query was sent</li>
877 <li><code>start_time</code> (a bindata) is the time the query started in milliseconds since the epoch,
878 represented as a uint64_t</li>
879 <li><code>end_time</code> (a bindata) is the time the query was received in milliseconds since the epoch,
880 represented as a uint64_t</li>
877 <li><code>run_time</code> (a bindata) is the difference between the time the successful
878 query started and ended in milliseconds, represented
879 as a uint32_t (this does not include time taken for connection set up
880 or transport fallback)</li>
881881 <li><code>entire_reply</code> (a bindata) is the entire response received</li>
882882 <li><code>dnssec_result</code> (an int) is the DNSSEC status, or <code>GETDNS_DNSSEC_NOT_PERFORMED</code>
883883 if DNSSEC validation was not performed</li>
21462146 Fallback transport options are specified by including multiple values in the list.
21472147 The values are <span class=default>
21482148 <code>GETDNS_TRANSPORT_UDP</code></span>,
2149 <code>GETDNS_TRANSPORT_TCP</code>,
2150 <code>GETDNS_TRANSPORT_TLS</code>, or
2151 <code>GETDNS_TRANSPORT_STARTTLS</code>.
2149 <code>GETDNS_TRANSPORT_TCP</code>, or
2150 <code>GETDNS_TRANSPORT_TLS</code>.
21522151 The default is <span class=default> a list containing <code>GETDNS_TRANSPORT_UDP</code> then <code>GETDNS_TRANSPORT_TCP</code></span>.</p>
21532152
21542153 <div class=forh>
21572156 getdns_context *context,
21582157 uint64_t timeout
21592158 );</div>
2160 <p class=cont>Specifies number of milliseconds the API will leave an idle TCP, TLS or STARTTLS connection open for (idle means no outstanding responses and no pending queries).
2159 <p class=cont>Specifies number of milliseconds the API will leave an idle TCP or TLS connection open for (idle means no outstanding responses and no pending queries).
21612160 The default is <span class=default>0</span>.</p>
21622161
21632162 <div class=forh>
22832282 <code>port</code> to specify which port to use to contact these DNS servers; the default is 53. If
22842283 the stub and a recursive resolver both support TSIG (RFC 2845), the <code>upstream_list</code> entry
22852284 can also contain <code>tsig_algorithm</code> (a bindata) that is the name of the TSIG hash
2286 algorithm, and <code>tsig_secret</code> (a bindata) that is the TSIG key.</p>
2285 algorithm, <code>tsig_name</code> (a bindata) that is the name of the TSIG key, and <code>tsig_secret</code> (a bindata) that is the TSIG key.</p>
22872286
22882287 <h2>8.8 Context for EDNS</h2>
22892288
24252424
24262425 <h1>9. The Generated Files</h1>
24272426
2428 <p>There is <a href="getdns-0.701.tgz">a tarball</a> that includes the .h files,
2427 <p>There is <a href="getdns-0.901.tgz">a tarball</a> that includes the .h files,
24292428 the examples, and so on. The examples all make, even though there is no API implementation, based
24302429 on a pseudo-implementation in the tarball; see make-examples-PLATFORM.sh. Note that this currently builds fine
24312430 on the Macintosh and Ubuntu; help is definitely appreciated on making the build process
6363 C99COMPATFLAGS=@C99COMPATFLAGS@
6464
6565 GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
66 list.lo request-internal.lo rr-dict.lo rr-iter.lo stub.lo sync.lo \
67 util-internal.lo
66 list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \
67 rr-iter.lo stub.lo sync.lo util-internal.lo
6868
6969 GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \
7070 str2wire.lo
7373 LIBOBJS=@LIBOBJS@
7474 COMPAT_OBJ=$(LIBOBJS:.o=.lo)
7575
76 UTIL_OBJ=mini_event.lo rbtree.lo val_secalgo.lo
76 UTIL_OBJ=mini_event.lo winsock_event.lo rbtree.lo val_secalgo.lo
7777
7878 EXTENSION_OBJ=libmini_event.lo libevent.lo libev.lo
7979
166166 distclean : clean
167167 cd test && $(MAKE) $@
168168 rmdir test 2>/dev/null || true
169 rm -f Makefile config.status config.log Doxyfile config.h getdns/Makefile getdns/getdns.h
169 rm -f Makefile config.status config.log Doxyfile config.h version.c getdns/Makefile getdns/getdns.h getdns/getdns_extra.h
170170 rmdir getdns 2>/dev/null || true
171171 rmdir extension 2>/dev/null || true
172172 rm -Rf autom4te.cache
202202
203203 depend:
204204 (cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
205 (cd $(srcdir) ; gcc -MM -I. *.c gldns/*.c compat/*.c util/*.c extension/*.c| \
206 sed -e 's?gldns/?$$(srcdir)/gldns/?g' \
205 (blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" *.c gldns/*.c compat/*.c util/*.c extension/*.c| \
206 sed -e "s? $$blddir/? ?g" \
207 -e 's?gldns/?$$(srcdir)/gldns/?g' \
207208 -e 's?compat/?$$(srcdir)/compat/?g' \
208209 -e 's?util/?$$(srcdir)/util/?g' \
209210 -e 's?extension/?$$(srcdir)/extension/?g' \
225226 # Dependencies for gldns, utils, the extensions and compat functions
226227 const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h getdns/getdns_extra.h \
227228 getdns/getdns.h $(srcdir)/const-info.h
228 context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
229 context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
229230 $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \
230231 getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h \
231232 config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h \
232233 $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
233 $(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/list.h
234 $(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
234235 convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \
235236 getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
236237 $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
237238 $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
238 $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h
239 dict.lo dict.o: $(srcdir)/dict.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
240 getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
241 $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
242 $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
243 $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
244 dnssec.lo dnssec.o: $(srcdir)/dnssec.c getdns/getdns.h config.h $(srcdir)/context.h \
239 $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/convert.h
240 dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
241 getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \
242 $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h \
243 $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
244 $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
245 dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \
245246 getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
246247 $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
247248 $(srcdir)/types-internal.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
252253 getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
253254 $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
254255 $(srcdir)/types-internal.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
255 $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/stub.h
256 $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/general.h
256257 list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
257258 getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
258259 $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
259260 $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
260261 $(srcdir)/list.h $(srcdir)/dict.h
262 pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \
263 $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
264 $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h \
265 $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h
261266 request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \
262267 getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
263268 $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h \
264269 $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
265270 $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \
266 $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h
271 $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/debug.h
267272 rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \
268273 $(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \
269274 $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h config.h \
271276 $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h
272277 rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h getdns/getdns.h $(srcdir)/rr-dict.h config.h \
273278 $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h
274 stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \
279 stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \
275280 getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \
276 $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/rr-iter.h \
277 $(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h \
278 $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/util-internal.h $(srcdir)/general.h
281 $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
282 $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h \
283 config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h \
284 $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
279285 sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \
280286 getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h \
281287 config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/general.h \
282288 $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
283289 $(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
284 util-internal.lo util-internal.o: $(srcdir)/util-internal.c getdns/getdns.h $(srcdir)/dict.h $(srcdir)/util/rbtree.h \
285 $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/list.h \
286 $(srcdir)/util-internal.h config.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h \
290 util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \
291 $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \
292 $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h \
287293 $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
288294 $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h
289295 version.lo version.o: version.c
306312 getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h
307313 getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h
308314 getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
315 inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h
316 inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h
309317 sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h
310318 strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
311319 mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
312320 $(srcdir)/util/fptr_wlist.h
313 rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/util-internal.h config.h \
314 $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h \
315 $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h \
316 $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
317 $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util/fptr_wlist.h
321 rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/debug.h config.h \
322 $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h
318323 val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \
319 $(srcdir)/util-internal.h config.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \
320 getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h \
321 $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
322 $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h \
323 $(srcdir)/gldns/gbuffer.h
324 libev.lo libev.o: $(srcdir)/extension/libev.c $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns.h \
325 getdns/getdns_extra.h $(srcdir)/types-internal.h getdns/getdns.h \
326 getdns/getdns_extra.h $(srcdir)/util/rbtree.h config.h
327 libevent.lo libevent.o: $(srcdir)/extension/libevent.c $(srcdir)/getdns/getdns_ext_libevent.h \
328 getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h getdns/getdns.h \
329 getdns/getdns_extra.h $(srcdir)/util/rbtree.h config.h
330 libmini_event.lo libmini_event.o: $(srcdir)/extension/libmini_event.c $(srcdir)/extension/libmini_event.h \
331 config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h \
324 $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h
325 winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.h
326 libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
327 getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
328 $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h
329 libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types-internal.h \
332330 getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
333 $(srcdir)/context.h config.h $(srcdir)/types-internal.h $(srcdir)/extension/libmini_event.h \
334 $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
335 $(srcdir)/gldns/pkthdr.h
336 libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/getdns/getdns_ext_libuv.h \
337 getdns/getdns.h getdns/getdns_extra.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
338 getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
339 $(srcdir)/extension/libmini_event.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
340 $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h
331 $(srcdir)/getdns/getdns_ext_libevent.h getdns/getdns_extra.h
332 libmini_event.lo libmini_event.o: $(srcdir)/extension/libmini_event.c config.h $(srcdir)/debug.h config.h \
333 $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h \
334 $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
335 libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \
336 getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
337 $(srcdir)/getdns/getdns_ext_libuv.h getdns/getdns_extra.h
3232 #include <sys/types.h>
3333 #include <sys/param.h>
3434 #include <sys/time.h>
35 #ifndef UB_ON_WINDOWS
35 #ifndef GETDNS_ON_WINDOWS
3636 #include <sys/mman.h>
37 #else
38 #include <wincrypt.h>
39 #include <process.h>
40
41 int getentropy(void *buf, size_t len);
42
43 /*
44 * On Windows, CryptGenRandom is supposed to be a well-seeded
45 * cryptographically strong random number generator.
46 */
47 int
48 getentropy(void *buf, size_t len)
49 {
50 HCRYPTPROV provider;
51
52 if (len > 256) {
53 errno = EIO;
54 return -1;
55 }
56
57 if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
58 CRYPT_VERIFYCONTEXT) == 0)
59 goto fail;
60 if (CryptGenRandom(provider, len, buf) == 0) {
61 CryptReleaseContext(provider, 0);
62 goto fail;
63 }
64 CryptReleaseContext(provider, 0);
65 return (0);
66
67 fail:
68 errno = EIO;
69 return (-1);
70 }
3771 #endif
3872
3973 #define KEYSTREAM_ONLY
72106 return;
73107
74108 if (rs == NULL) {
75 #ifndef UB_ON_WINDOWS
109 #ifndef GETDNS_ON_WINDOWS
76110 if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE,
77111 MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
78112 abort();
87121 #endif
88122 }
89123 if (rsx == NULL) {
90 #ifndef UB_ON_WINDOWS
124 #ifndef GETDNS_ON_WINDOWS
91125 if ((rsx = mmap(NULL, sizeof(*rsx), PROT_READ|PROT_WRITE,
92126 MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
93127 abort();
1515 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1616 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1717 */
18
1819 #include "config.h"
20 #ifndef GETDNS_ON_WINDOWS
21
1922
2023 /*
2124 #define _POSIX_C_SOURCE 199309L
537540 errno = EIO;
538541 return -1;
539542 }
543 #endif
0 /* From openssh 4.3p2 compat/inet_ntop.c */
1 /* Copyright (c) 1996 by Internet Software Consortium.
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
8 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
9 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
10 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
11 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
12 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
13 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
14 * SOFTWARE.
15 */
16
17 /* OPENBSD ORIGINAL: lib/libc/net/inet_ntop.c */
18
19 #include <config.h>
20
21 #ifndef HAVE_INET_NTOP
22
23 #include <sys/param.h>
24 #include <sys/types.h>
25 #ifdef HAVE_SYS_SOCKET_H
26 #include <sys/socket.h>
27 #endif
28 #ifdef HAVE_NETINET_IN_H
29 #include <netinet/in.h>
30 #endif
31 #include <string.h>
32 #include <errno.h>
33 #include <stdio.h>
34
35 #ifndef IN6ADDRSZ
36 #define IN6ADDRSZ 16 /* IPv6 T_AAAA */
37 #endif
38
39 #ifndef INT16SZ
40 #define INT16SZ 2 /* for systems without 16-bit ints */
41 #endif
42
43 /*
44 * WARNING: Don't even consider trying to compile this on a system where
45 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
46 */
47
48 static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
49 static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
50
51 /* char *
52 * inet_ntop(af, src, dst, size)
53 * convert a network format address to presentation format.
54 * return:
55 * pointer to presentation format address (`dst'), or NULL (see errno).
56 * author:
57 * Paul Vixie, 1996.
58 */
59 const char *
60 inet_ntop(int af, const void *src, char *dst, size_t size)
61 {
62 switch (af) {
63 case AF_INET:
64 return (inet_ntop4(src, dst, size));
65 case AF_INET6:
66 return (inet_ntop6(src, dst, size));
67 default:
68 #ifdef EAFNOSUPPORT
69 errno = EAFNOSUPPORT;
70 #else
71 errno = ENOSYS;
72 #endif
73 return (NULL);
74 }
75 /* NOTREACHED */
76 }
77
78 /* const char *
79 * inet_ntop4(src, dst, size)
80 * format an IPv4 address, more or less like inet_ntoa()
81 * return:
82 * `dst' (as a const)
83 * notes:
84 * (1) uses no statics
85 * (2) takes a u_char* not an in_addr as input
86 * author:
87 * Paul Vixie, 1996.
88 */
89 static const char *
90 inet_ntop4(const u_char *src, char *dst, size_t size)
91 {
92 static const char fmt[] = "%u.%u.%u.%u";
93 char tmp[sizeof "255.255.255.255"];
94 int l;
95
96 l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
97 if (l <= 0 || l >= (int)size) {
98 errno = ENOSPC;
99 return (NULL);
100 }
101 strlcpy(dst, tmp, size);
102 return (dst);
103 }
104
105 /* const char *
106 * inet_ntop6(src, dst, size)
107 * convert IPv6 binary address into presentation (printable) format
108 * author:
109 * Paul Vixie, 1996.
110 */
111 static const char *
112 inet_ntop6(const u_char *src, char *dst, size_t size)
113 {
114 /*
115 * Note that int32_t and int16_t need only be "at least" large enough
116 * to contain a value of the specified size. On some systems, like
117 * Crays, there is no such thing as an integer variable with 16 bits.
118 * Keep this in mind if you think this function should have been coded
119 * to use pointer overlays. All the world's not a VAX.
120 */
121 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
122 char *tp, *ep;
123 struct { int base, len; } best, cur;
124 u_int words[IN6ADDRSZ / INT16SZ];
125 int i;
126 int advance;
127
128 /*
129 * Preprocess:
130 * Copy the input (bytewise) array into a wordwise array.
131 * Find the longest run of 0x00's in src[] for :: shorthanding.
132 */
133 memset(words, '\0', sizeof words);
134 for (i = 0; i < IN6ADDRSZ; i++)
135 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
136 best.base = -1;
137 best.len = 0;
138 cur.base = -1;
139 cur.len = 0;
140 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
141 if (words[i] == 0) {
142 if (cur.base == -1)
143 cur.base = i, cur.len = 1;
144 else
145 cur.len++;
146 } else {
147 if (cur.base != -1) {
148 if (best.base == -1 || cur.len > best.len)
149 best = cur;
150 cur.base = -1;
151 }
152 }
153 }
154 if (cur.base != -1) {
155 if (best.base == -1 || cur.len > best.len)
156 best = cur;
157 }
158 if (best.base != -1 && best.len < 2)
159 best.base = -1;
160
161 /*
162 * Format the result.
163 */
164 tp = tmp;
165 ep = tmp + sizeof(tmp);
166 for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
167 /* Are we inside the best run of 0x00's? */
168 if (best.base != -1 && i >= best.base &&
169 i < (best.base + best.len)) {
170 if (i == best.base) {
171 if (tp + 1 >= ep)
172 return (NULL);
173 *tp++ = ':';
174 }
175 continue;
176 }
177 /* Are we following an initial run of 0x00s or any real hex? */
178 if (i != 0) {
179 if (tp + 1 >= ep)
180 return (NULL);
181 *tp++ = ':';
182 }
183 /* Is this address an encapsulated IPv4? */
184 if (i == 6 && best.base == 0 &&
185 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
186 if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
187 return (NULL);
188 tp += strlen(tp);
189 break;
190 }
191 advance = snprintf(tp, ep - tp, "%x", words[i]);
192 if (advance <= 0 || advance >= ep - tp)
193 return (NULL);
194 tp += advance;
195 }
196 /* Was it a trailing run of 0x00's? */
197 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
198 if (tp + 1 >= ep)
199 return (NULL);
200 *tp++ = ':';
201 }
202 if (tp + 1 >= ep)
203 return (NULL);
204 *tp++ = '\0';
205
206 /*
207 * Check for overflow, copy, and we're done.
208 */
209 if ((size_t)(tp - tmp) > size) {
210 errno = ENOSPC;
211 return (NULL);
212 }
213 strlcpy(dst, tmp, size);
214 return (dst);
215 }
216
217 #endif /* !HAVE_INET_NTOP */
0 /* $KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */
1
2 /* Copyright (c) 1996 by Internet Software Consortium.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15 * SOFTWARE.
16 */
17
18 #include <config.h>
19
20 #include <string.h>
21 #include <stdio.h>
22 #include <errno.h>
23
24 /*
25 * WARNING: Don't even consider trying to compile this on a system where
26 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
27 */
28
29 static int inet_pton4 (const char *src, uint8_t *dst);
30 static int inet_pton6 (const char *src, uint8_t *dst);
31
32 /*
33 *
34 * The definitions we might miss.
35 *
36 */
37 #ifndef NS_INT16SZ
38 #define NS_INT16SZ 2
39 #endif
40
41 #ifndef NS_IN6ADDRSZ
42 #define NS_IN6ADDRSZ 16
43 #endif
44
45 #ifndef NS_INADDRSZ
46 #define NS_INADDRSZ 4
47 #endif
48
49 /* int
50 * inet_pton(af, src, dst)
51 * convert from presentation format (which usually means ASCII printable)
52 * to network format (which is usually some kind of binary format).
53 * return:
54 * 1 if the address was valid for the specified address family
55 * 0 if the address wasn't valid (`dst' is untouched in this case)
56 * -1 if some other error occurred (`dst' is untouched in this case, too)
57 * author:
58 * Paul Vixie, 1996.
59 */
60 int
61 inet_pton(af, src, dst)
62 int af;
63 const char *src;
64 void *dst;
65 {
66 switch (af) {
67 case AF_INET:
68 return (inet_pton4(src, dst));
69 case AF_INET6:
70 return (inet_pton6(src, dst));
71 default:
72 #ifdef EAFNOSUPPORT
73 errno = EAFNOSUPPORT;
74 #else
75 errno = ENOSYS;
76 #endif
77 return (-1);
78 }
79 /* NOTREACHED */
80 }
81
82 /* int
83 * inet_pton4(src, dst)
84 * like inet_aton() but without all the hexadecimal and shorthand.
85 * return:
86 * 1 if `src' is a valid dotted quad, else 0.
87 * notice:
88 * does not touch `dst' unless it's returning 1.
89 * author:
90 * Paul Vixie, 1996.
91 */
92 static int
93 inet_pton4(src, dst)
94 const char *src;
95 uint8_t *dst;
96 {
97 static const char digits[] = "0123456789";
98 int saw_digit, octets, ch;
99 uint8_t tmp[NS_INADDRSZ], *tp;
100
101 saw_digit = 0;
102 octets = 0;
103 *(tp = tmp) = 0;
104 while ((ch = *src++) != '\0') {
105 const char *pch;
106
107 if ((pch = strchr(digits, ch)) != NULL) {
108 uint32_t new = *tp * 10 + (pch - digits);
109
110 if (new > 255)
111 return (0);
112 *tp = new;
113 if (! saw_digit) {
114 if (++octets > 4)
115 return (0);
116 saw_digit = 1;
117 }
118 } else if (ch == '.' && saw_digit) {
119 if (octets == 4)
120 return (0);
121 *++tp = 0;
122 saw_digit = 0;
123 } else
124 return (0);
125 }
126 if (octets < 4)
127 return (0);
128
129 memcpy(dst, tmp, NS_INADDRSZ);
130 return (1);
131 }
132
133 /* int
134 * inet_pton6(src, dst)
135 * convert presentation level address to network order binary form.
136 * return:
137 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
138 * notice:
139 * (1) does not touch `dst' unless it's returning 1.
140 * (2) :: in a full address is silently ignored.
141 * credit:
142 * inspired by Mark Andrews.
143 * author:
144 * Paul Vixie, 1996.
145 */
146 static int
147 inet_pton6(src, dst)
148 const char *src;
149 uint8_t *dst;
150 {
151 static const char xdigits_l[] = "0123456789abcdef",
152 xdigits_u[] = "0123456789ABCDEF";
153 uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
154 const char *xdigits, *curtok;
155 int ch, saw_xdigit;
156 uint32_t val;
157
158 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
159 endp = tp + NS_IN6ADDRSZ;
160 colonp = NULL;
161 /* Leading :: requires some special handling. */
162 if (*src == ':')
163 if (*++src != ':')
164 return (0);
165 curtok = src;
166 saw_xdigit = 0;
167 val = 0;
168 while ((ch = *src++) != '\0') {
169 const char *pch;
170
171 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
172 pch = strchr((xdigits = xdigits_u), ch);
173 if (pch != NULL) {
174 val <<= 4;
175 val |= (pch - xdigits);
176 if (val > 0xffff)
177 return (0);
178 saw_xdigit = 1;
179 continue;
180 }
181 if (ch == ':') {
182 curtok = src;
183 if (!saw_xdigit) {
184 if (colonp)
185 return (0);
186 colonp = tp;
187 continue;
188 }
189 if (tp + NS_INT16SZ > endp)
190 return (0);
191 *tp++ = (uint8_t) (val >> 8) & 0xff;
192 *tp++ = (uint8_t) val & 0xff;
193 saw_xdigit = 0;
194 val = 0;
195 continue;
196 }
197 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
198 inet_pton4(curtok, tp) > 0) {
199 tp += NS_INADDRSZ;
200 saw_xdigit = 0;
201 break; /* '\0' was seen by inet_pton4(). */
202 }
203 return (0);
204 }
205 if (saw_xdigit) {
206 if (tp + NS_INT16SZ > endp)
207 return (0);
208 *tp++ = (uint8_t) (val >> 8) & 0xff;
209 *tp++ = (uint8_t) val & 0xff;
210 }
211 if (colonp != NULL) {
212 /*
213 * Since some memmove()'s erroneously fail to handle
214 * overlapping regions, we'll do the shift by hand.
215 */
216 const int n = tp - colonp;
217 int i;
218
219 for (i = 1; i <= n; i++) {
220 endp[- i] = colonp[n - i];
221 colonp[n - i] = 0;
222 }
223 tp = endp;
224 }
225 if (tp != endp)
226 return (0);
227 memcpy(dst, tmp, NS_IN6ADDRSZ);
228 return (1);
229 }
1616
1717 /* The edns padding option code. */
1818 #undef EDNS_PADDING_OPCODE
19
20 /* Define this to enable Windows build. */
21 #undef GETDNS_ON_WINDOWS
1922
2023 /* Define to 1 if you have the `arc4random' function. */
2124 #undef HAVE_ARC4RANDOM
9093 /* Define to 1 if you have the <event.h> header file. */
9194 #undef HAVE_EVENT_H
9295
96 /* Define to 1 if you have the `EVP_md5' function. */
97 #undef HAVE_EVP_MD5
98
9399 /* Define to 1 if you have the `EVP_sha1' function. */
94100 #undef HAVE_EVP_SHA1
95101
102 /* Define to 1 if you have the `EVP_sha224' function. */
103 #undef HAVE_EVP_SHA224
104
96105 /* Define to 1 if you have the `EVP_sha256' function. */
97106 #undef HAVE_EVP_SHA256
98107
108 /* Define to 1 if you have the `EVP_sha384' function. */
109 #undef HAVE_EVP_SHA384
110
99111 /* Define to 1 if you have the `EVP_sha512' function. */
100112 #undef HAVE_EVP_SHA512
101113
108120 /* Define to 1 if you have the `FIPS_mode' function. */
109121 #undef HAVE_FIPS_MODE
110122
123 /* Whether getaddrinfo is available */
124 #undef HAVE_GETADDRINFO
125
111126 /* Define to 1 if you have the `getauxval' function. */
112127 #undef HAVE_GETAUXVAL
113128
117132 /* If you have HMAC_CTX_init */
118133 #undef HAVE_HMAC_CTX_INIT
119134
135 /* Define to 1 if you have the `inet_ntop' function. */
136 #undef HAVE_INET_NTOP
137
138 /* Define to 1 if you have the `inet_pton' function. */
139 #undef HAVE_INET_PTON
140
120141 /* Define to 1 if you have the <inttypes.h> header file. */
121142 #undef HAVE_INTTYPES_H
122143
183204 /* Define to 1 if you have the <stdint.h> header file. */
184205 #undef HAVE_STDINT_H
185206
207 /* Define to 1 if you have the <stdio.h> header file. */
208 #undef HAVE_STDIO_H
209
186210 /* Define to 1 if you have the <stdlib.h> header file. */
187211 #undef HAVE_STDLIB_H
188212
227251
228252 /* Define to 1 if you have the <uv.h> header file. */
229253 #undef HAVE_UV_H
254
255 /* Define to 1 if you have the <windows.h> header file. */
256 #undef HAVE_WINDOWS_H
257
258 /* Define to 1 if you have the <winsock2.h> header file. */
259 #undef HAVE_WINSOCK2_H
260
261 /* Define to 1 if you have the <winsock.h> header file. */
262 #undef HAVE_WINSOCK_H
263
264 /* Define to 1 if you have the <ws2tcpip.h> header file. */
265 #undef HAVE_WS2TCPIP_H
230266
231267 /* Define to the sub-directory in which libtool stores uninstalled libraries.
232268 */
289325 /* Needed for sync stub resolver functions */
290326 #undef USE_MINI_EVENT
291327
328 /* Define this to enable TCP fast open. */
329 #undef USE_OSX_TCP_FASTOPEN
330
292331 /* Define this to enable SHA256 and SHA512 support. */
293332 #undef USE_SHA2
294333
295334 /* Define this to enable TCP fast open. */
296335 #undef USE_TCP_FASTOPEN
336
337 /* Whether the windows socket API is used */
338 #undef USE_WINSOCK
297339
298340 /* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
299341 <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
328370 /* Define to the type of an unsigned integer type of width exactly 8 bits if
329371 such a type exists and the standard includes do not define it. */
330372 #undef uint8_t
373
374
375
376 /* the version of the windows API enabled */
377 #undef WINVER
378 #undef _WIN32_WINNT
379 #define WINVER 0x0600 // 0x0502
380 #define _WIN32_WINNT 0x0600 // 0x0502
381 #ifdef HAVE_WINSOCK2_H
382 #include <winsock2.h>
383 #include<BaseTsd.h>
384 #endif
385
386 #ifdef HAVE_WS2TCPIP_H
387 #include <ws2tcpip.h>
388 #endif
389
390 #ifndef USE_WINSOCK
391 #define ARG_LL "%ll"
392 #else
393 #define ARG_LL "%I64"
394 #endif
395
396 /* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
397 #ifdef HAVE_WINSOCK2_H
398 #define FD_SET_T (u_int)
399 #else
400 #define FD_SET_T
401 #endif
331402
332403
333404 #include <stdint.h>
386457 unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest);
387458 #endif /* COMPAT_SHA512 */
388459
460 #ifndef HAVE_INET_PTON
461 int inet_pton(int af, const char* src, void* dst);
462 #endif /* HAVE_INET_PTON */
463
464 #ifndef HAVE_INET_NTOP
465 const char *inet_ntop(int af, const void *src, char *dst, size_t size);
466 #endif
467
389468 #ifdef __cplusplus
390469 }
391470 #endif
439518 # define ATTR_UNUSED(x) x
440519 #endif /* !HAVE_ATTR_UNUSED */
441520
442 /* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
443 #ifdef HAVE_WINSOCK2_H
444 #define FD_SET_T (u_int)
445 #else
446 #define FD_SET_T
447 #endif
448
449521 #ifdef TIME_WITH_SYS_TIME
450522 # include <sys/time.h>
451523 # include <time.h>
66 #include "const-info.h"
77
88 static struct const_info consts_info[] = {
9 { -1, NULL, "/* <unknown getdns value> */" },
10 { 0, "GETDNS_RETURN_GOOD", GETDNS_RETURN_GOOD_TEXT },
11 { 1, "GETDNS_RETURN_GENERIC_ERROR", GETDNS_RETURN_GENERIC_ERROR_TEXT },
12 { 300, "GETDNS_RETURN_BAD_DOMAIN_NAME", GETDNS_RETURN_BAD_DOMAIN_NAME_TEXT },
13 { 301, "GETDNS_RETURN_BAD_CONTEXT", GETDNS_RETURN_BAD_CONTEXT_TEXT },
14 { 302, "GETDNS_RETURN_CONTEXT_UPDATE_FAIL", GETDNS_RETURN_CONTEXT_UPDATE_FAIL_TEXT },
15 { 303, "GETDNS_RETURN_UNKNOWN_TRANSACTION", GETDNS_RETURN_UNKNOWN_TRANSACTION_TEXT },
16 { 304, "GETDNS_RETURN_NO_SUCH_LIST_ITEM", GETDNS_RETURN_NO_SUCH_LIST_ITEM_TEXT },
17 { 305, "GETDNS_RETURN_NO_SUCH_DICT_NAME", GETDNS_RETURN_NO_SUCH_DICT_NAME_TEXT },
18 { 306, "GETDNS_RETURN_WRONG_TYPE_REQUESTED", GETDNS_RETURN_WRONG_TYPE_REQUESTED_TEXT },
19 { 307, "GETDNS_RETURN_NO_SUCH_EXTENSION", GETDNS_RETURN_NO_SUCH_EXTENSION_TEXT },
20 { 308, "GETDNS_RETURN_EXTENSION_MISFORMAT", GETDNS_RETURN_EXTENSION_MISFORMAT_TEXT },
21 { 309, "GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED", GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED_TEXT },
22 { 310, "GETDNS_RETURN_MEMORY_ERROR", GETDNS_RETURN_MEMORY_ERROR_TEXT },
23 { 311, "GETDNS_RETURN_INVALID_PARAMETER", GETDNS_RETURN_INVALID_PARAMETER_TEXT },
24 { 400, "GETDNS_DNSSEC_SECURE", GETDNS_DNSSEC_SECURE_TEXT },
25 { 401, "GETDNS_DNSSEC_BOGUS", GETDNS_DNSSEC_BOGUS_TEXT },
26 { 402, "GETDNS_DNSSEC_INDETERMINATE", GETDNS_DNSSEC_INDETERMINATE_TEXT },
27 { 403, "GETDNS_DNSSEC_INSECURE", GETDNS_DNSSEC_INSECURE_TEXT },
28 { 404, "GETDNS_DNSSEC_NOT_PERFORMED", GETDNS_DNSSEC_NOT_PERFORMED_TEXT },
29 { 500, "GETDNS_NAMESPACE_DNS", GETDNS_NAMESPACE_DNS_TEXT },
30 { 501, "GETDNS_NAMESPACE_LOCALNAMES", GETDNS_NAMESPACE_LOCALNAMES_TEXT },
31 { 502, "GETDNS_NAMESPACE_NETBIOS", GETDNS_NAMESPACE_NETBIOS_TEXT },
32 { 503, "GETDNS_NAMESPACE_MDNS", GETDNS_NAMESPACE_MDNS_TEXT },
33 { 504, "GETDNS_NAMESPACE_NIS", GETDNS_NAMESPACE_NIS_TEXT },
34 { 520, "GETDNS_RESOLUTION_STUB", GETDNS_RESOLUTION_STUB_TEXT },
35 { 521, "GETDNS_RESOLUTION_RECURSING", GETDNS_RESOLUTION_RECURSING_TEXT },
36 { 530, "GETDNS_REDIRECTS_FOLLOW", GETDNS_REDIRECTS_FOLLOW_TEXT },
37 { 531, "GETDNS_REDIRECTS_DO_NOT_FOLLOW", GETDNS_REDIRECTS_DO_NOT_FOLLOW_TEXT },
38 { 540, "GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP", GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP_TEXT },
39 { 541, "GETDNS_TRANSPORT_UDP_ONLY", GETDNS_TRANSPORT_UDP_ONLY_TEXT },
40 { 542, "GETDNS_TRANSPORT_TCP_ONLY", GETDNS_TRANSPORT_TCP_ONLY_TEXT },
41 { 543, "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN_TEXT },
42 { 544, "GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN_TEXT },
43 { 545, "GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT },
44 { 546, "GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT },
45 { 550, "GETDNS_APPEND_NAME_ALWAYS", GETDNS_APPEND_NAME_ALWAYS_TEXT },
46 { 551, "GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE_TEXT },
47 { 552, "GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE_TEXT },
48 { 553, "GETDNS_APPEND_NAME_NEVER", GETDNS_APPEND_NAME_NEVER_TEXT },
49 { 600, "GETDNS_CONTEXT_CODE_NAMESPACES", GETDNS_CONTEXT_CODE_NAMESPACES_TEXT },
50 { 601, "GETDNS_CONTEXT_CODE_RESOLUTION_TYPE", GETDNS_CONTEXT_CODE_RESOLUTION_TYPE_TEXT },
51 { 602, "GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS", GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS_TEXT },
52 { 603, "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS_TEXT },
53 { 604, "GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS", GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS_TEXT },
54 { 605, "GETDNS_CONTEXT_CODE_DNS_TRANSPORT", GETDNS_CONTEXT_CODE_DNS_TRANSPORT_TEXT },
55 { 606, "GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES", GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES_TEXT },
56 { 607, "GETDNS_CONTEXT_CODE_APPEND_NAME", GETDNS_CONTEXT_CODE_APPEND_NAME_TEXT },
57 { 608, "GETDNS_CONTEXT_CODE_SUFFIX", GETDNS_CONTEXT_CODE_SUFFIX_TEXT },
58 { 609, "GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS", GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS_TEXT },
59 { 610, "GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE", GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE_TEXT },
60 { 611, "GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE", GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE_TEXT },
61 { 612, "GETDNS_CONTEXT_CODE_EDNS_VERSION", GETDNS_CONTEXT_CODE_EDNS_VERSION_TEXT },
62 { 613, "GETDNS_CONTEXT_CODE_EDNS_DO_BIT", GETDNS_CONTEXT_CODE_EDNS_DO_BIT_TEXT },
63 { 614, "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW_TEXT },
64 { 615, "GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS", GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS_TEXT },
65 { 616, "GETDNS_CONTEXT_CODE_TIMEOUT", GETDNS_CONTEXT_CODE_TIMEOUT_TEXT },
66 { 617, "GETDNS_CONTEXT_CODE_IDLE_TIMEOUT", GETDNS_CONTEXT_CODE_IDLE_TIMEOUT_TEXT },
67 { 618, "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION_TEXT },
68 { 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
69 { 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
70 { 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },
71 { 703, "GETDNS_CALLBACK_ERROR", GETDNS_CALLBACK_ERROR_TEXT },
72 { 800, "GETDNS_NAMETYPE_DNS", GETDNS_NAMETYPE_DNS_TEXT },
73 { 801, "GETDNS_NAMETYPE_WINS", GETDNS_NAMETYPE_WINS_TEXT },
74 { 900, "GETDNS_RESPSTATUS_GOOD", GETDNS_RESPSTATUS_GOOD_TEXT },
75 { 901, "GETDNS_RESPSTATUS_NO_NAME", GETDNS_RESPSTATUS_NO_NAME_TEXT },
76 { 902, "GETDNS_RESPSTATUS_ALL_TIMEOUT", GETDNS_RESPSTATUS_ALL_TIMEOUT_TEXT },
77 { 903, "GETDNS_RESPSTATUS_NO_SECURE_ANSWERS", GETDNS_RESPSTATUS_NO_SECURE_ANSWERS_TEXT },
78 { 904, "GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS", GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS_TEXT },
9 { -1, NULL, "/* <unknown getdns value> */" },
10 { 0, "GETDNS_RETURN_GOOD", GETDNS_RETURN_GOOD_TEXT },
11 { 1, "GETDNS_RETURN_GENERIC_ERROR", GETDNS_RETURN_GENERIC_ERROR_TEXT },
12 { 300, "GETDNS_RETURN_BAD_DOMAIN_NAME", GETDNS_RETURN_BAD_DOMAIN_NAME_TEXT },
13 { 301, "GETDNS_RETURN_BAD_CONTEXT", GETDNS_RETURN_BAD_CONTEXT_TEXT },
14 { 302, "GETDNS_RETURN_CONTEXT_UPDATE_FAIL", GETDNS_RETURN_CONTEXT_UPDATE_FAIL_TEXT },
15 { 303, "GETDNS_RETURN_UNKNOWN_TRANSACTION", GETDNS_RETURN_UNKNOWN_TRANSACTION_TEXT },
16 { 304, "GETDNS_RETURN_NO_SUCH_LIST_ITEM", GETDNS_RETURN_NO_SUCH_LIST_ITEM_TEXT },
17 { 305, "GETDNS_RETURN_NO_SUCH_DICT_NAME", GETDNS_RETURN_NO_SUCH_DICT_NAME_TEXT },
18 { 306, "GETDNS_RETURN_WRONG_TYPE_REQUESTED", GETDNS_RETURN_WRONG_TYPE_REQUESTED_TEXT },
19 { 307, "GETDNS_RETURN_NO_SUCH_EXTENSION", GETDNS_RETURN_NO_SUCH_EXTENSION_TEXT },
20 { 308, "GETDNS_RETURN_EXTENSION_MISFORMAT", GETDNS_RETURN_EXTENSION_MISFORMAT_TEXT },
21 { 309, "GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED", GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED_TEXT },
22 { 310, "GETDNS_RETURN_MEMORY_ERROR", GETDNS_RETURN_MEMORY_ERROR_TEXT },
23 { 311, "GETDNS_RETURN_INVALID_PARAMETER", GETDNS_RETURN_INVALID_PARAMETER_TEXT },
24 { 312, "GETDNS_RETURN_NOT_IMPLEMENTED", GETDNS_RETURN_NOT_IMPLEMENTED_TEXT },
25 { 399, "GETDNS_RETURN_NEED_MORE_SPACE", GETDNS_RETURN_NEED_MORE_SPACE_TEXT },
26 { 400, "GETDNS_DNSSEC_SECURE", GETDNS_DNSSEC_SECURE_TEXT },
27 { 401, "GETDNS_DNSSEC_BOGUS", GETDNS_DNSSEC_BOGUS_TEXT },
28 { 402, "GETDNS_DNSSEC_INDETERMINATE", GETDNS_DNSSEC_INDETERMINATE_TEXT },
29 { 403, "GETDNS_DNSSEC_INSECURE", GETDNS_DNSSEC_INSECURE_TEXT },
30 { 404, "GETDNS_DNSSEC_NOT_PERFORMED", GETDNS_DNSSEC_NOT_PERFORMED_TEXT },
31 { 500, "GETDNS_NAMESPACE_DNS", GETDNS_NAMESPACE_DNS_TEXT },
32 { 501, "GETDNS_NAMESPACE_LOCALNAMES", GETDNS_NAMESPACE_LOCALNAMES_TEXT },
33 { 502, "GETDNS_NAMESPACE_NETBIOS", GETDNS_NAMESPACE_NETBIOS_TEXT },
34 { 503, "GETDNS_NAMESPACE_MDNS", GETDNS_NAMESPACE_MDNS_TEXT },
35 { 504, "GETDNS_NAMESPACE_NIS", GETDNS_NAMESPACE_NIS_TEXT },
36 { 520, "GETDNS_RESOLUTION_STUB", GETDNS_RESOLUTION_STUB_TEXT },
37 { 521, "GETDNS_RESOLUTION_RECURSING", GETDNS_RESOLUTION_RECURSING_TEXT },
38 { 530, "GETDNS_REDIRECTS_FOLLOW", GETDNS_REDIRECTS_FOLLOW_TEXT },
39 { 531, "GETDNS_REDIRECTS_DO_NOT_FOLLOW", GETDNS_REDIRECTS_DO_NOT_FOLLOW_TEXT },
40 { 540, "GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP", GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP_TEXT },
41 { 541, "GETDNS_TRANSPORT_UDP_ONLY", GETDNS_TRANSPORT_UDP_ONLY_TEXT },
42 { 542, "GETDNS_TRANSPORT_TCP_ONLY", GETDNS_TRANSPORT_TCP_ONLY_TEXT },
43 { 543, "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN_TEXT },
44 { 544, "GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN_TEXT },
45 { 545, "GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT },
46 { 550, "GETDNS_APPEND_NAME_ALWAYS", GETDNS_APPEND_NAME_ALWAYS_TEXT },
47 { 551, "GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE_TEXT },
48 { 552, "GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE_TEXT },
49 { 553, "GETDNS_APPEND_NAME_NEVER", GETDNS_APPEND_NAME_NEVER_TEXT },
50 { 600, "GETDNS_CONTEXT_CODE_NAMESPACES", GETDNS_CONTEXT_CODE_NAMESPACES_TEXT },
51 { 601, "GETDNS_CONTEXT_CODE_RESOLUTION_TYPE", GETDNS_CONTEXT_CODE_RESOLUTION_TYPE_TEXT },
52 { 602, "GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS", GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS_TEXT },
53 { 603, "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS_TEXT },
54 { 604, "GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS", GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS_TEXT },
55 { 605, "GETDNS_CONTEXT_CODE_DNS_TRANSPORT", GETDNS_CONTEXT_CODE_DNS_TRANSPORT_TEXT },
56 { 606, "GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES", GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES_TEXT },
57 { 607, "GETDNS_CONTEXT_CODE_APPEND_NAME", GETDNS_CONTEXT_CODE_APPEND_NAME_TEXT },
58 { 608, "GETDNS_CONTEXT_CODE_SUFFIX", GETDNS_CONTEXT_CODE_SUFFIX_TEXT },
59 { 609, "GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS", GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS_TEXT },
60 { 610, "GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE", GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE_TEXT },
61 { 611, "GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE", GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE_TEXT },
62 { 612, "GETDNS_CONTEXT_CODE_EDNS_VERSION", GETDNS_CONTEXT_CODE_EDNS_VERSION_TEXT },
63 { 613, "GETDNS_CONTEXT_CODE_EDNS_DO_BIT", GETDNS_CONTEXT_CODE_EDNS_DO_BIT_TEXT },
64 { 614, "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW_TEXT },
65 { 615, "GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS", GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS_TEXT },
66 { 616, "GETDNS_CONTEXT_CODE_TIMEOUT", GETDNS_CONTEXT_CODE_TIMEOUT_TEXT },
67 { 617, "GETDNS_CONTEXT_CODE_IDLE_TIMEOUT", GETDNS_CONTEXT_CODE_IDLE_TIMEOUT_TEXT },
68 { 618, "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION_TEXT },
69 { 619, "GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE", GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE_TEXT },
70 { 620, "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT },
71 { 621, "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT },
72 { 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
73 { 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
74 { 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },
75 { 703, "GETDNS_CALLBACK_ERROR", GETDNS_CALLBACK_ERROR_TEXT },
76 { 800, "GETDNS_NAMETYPE_DNS", GETDNS_NAMETYPE_DNS_TEXT },
77 { 801, "GETDNS_NAMETYPE_WINS", GETDNS_NAMETYPE_WINS_TEXT },
78 { 900, "GETDNS_RESPSTATUS_GOOD", GETDNS_RESPSTATUS_GOOD_TEXT },
79 { 901, "GETDNS_RESPSTATUS_NO_NAME", GETDNS_RESPSTATUS_NO_NAME_TEXT },
80 { 902, "GETDNS_RESPSTATUS_ALL_TIMEOUT", GETDNS_RESPSTATUS_ALL_TIMEOUT_TEXT },
81 { 903, "GETDNS_RESPSTATUS_NO_SECURE_ANSWERS", GETDNS_RESPSTATUS_NO_SECURE_ANSWERS_TEXT },
82 { 904, "GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS", GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS_TEXT },
7983 { 1000, "GETDNS_EXTENSION_TRUE", GETDNS_EXTENSION_TRUE_TEXT },
8084 { 1001, "GETDNS_EXTENSION_FALSE", GETDNS_EXTENSION_FALSE_TEXT },
8185 { 1100, "GETDNS_BAD_DNS_CNAME_IN_TARGET", GETDNS_BAD_DNS_CNAME_IN_TARGET_TEXT },
8488 { 1200, "GETDNS_TRANSPORT_UDP", GETDNS_TRANSPORT_UDP_TEXT },
8589 { 1201, "GETDNS_TRANSPORT_TCP", GETDNS_TRANSPORT_TCP_TEXT },
8690 { 1202, "GETDNS_TRANSPORT_TLS", GETDNS_TRANSPORT_TLS_TEXT },
87 { 1203, "GETDNS_TRANSPORT_STARTTLS", GETDNS_TRANSPORT_STARTTLS_TEXT },
8891 { 1300, "GETDNS_AUTHENTICATION_NONE", GETDNS_AUTHENTICATION_NONE_TEXT },
89 { 1301, "GETDNS_AUTHENTICATION_HOSTNAME", GETDNS_AUTHENTICATION_HOSTNAME_TEXT },
92 { 1301, "GETDNS_AUTHENTICATION_REQUIRED", GETDNS_AUTHENTICATION_REQUIRED_TEXT },
9093 };
9194
9295 static int const_info_cmp(const void *a, const void *b)
3333 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3434 */
3535
36 #include "config.h"
37
38 #ifndef USE_WINSOCK
3639 #include <arpa/inet.h>
40 #include <sys/time.h>
41 #include <netdb.h>
42 #else
43 #include <winsock2.h>
44 #include <iphlpapi.h>
45 typedef unsigned short in_port_t;
46 #endif
47
48 #include <sys/stat.h>
3749 #include <string.h>
3850 #include <stdio.h>
3951 #include <stdlib.h>
40 #include <sys/stat.h>
41 #include <sys/time.h>
52
4253 #include <assert.h>
43 #include <netdb.h>
4454 #include <ctype.h>
4555
4656 #include "config.h"
57 #include "debug.h"
4758 #include "gldns/str2wire.h"
4859 #include "gldns/wire2str.h"
4960 #include "context.h"
5263 #include "dnssec.h"
5364 #include "stub.h"
5465 #include "list.h"
66 #include "dict.h"
67 #include "pubkey-pinning.h"
5568
5669 #define GETDNS_PORT_ZERO 0
5770 #define GETDNS_PORT_DNS 53
6982 uint8_t host_name[];
7083 } host_name_addrs;
7184
85
86 /* If changing these lists also remember to
87 change the value of GETDNS_UPSTREAM_TRANSPORTS */
7288 static getdns_transport_list_t
7389 getdns_upstream_transports[GETDNS_UPSTREAM_TRANSPORTS] = {
74 GETDNS_TRANSPORT_STARTTLS, // Define before TCP to ease fallback
7590 GETDNS_TRANSPORT_TCP,
7691 GETDNS_TRANSPORT_TLS,
7792 };
7994 static in_port_t
8095 getdns_port_array[GETDNS_UPSTREAM_TRANSPORTS] = {
8196 GETDNS_PORT_DNS,
82 GETDNS_PORT_DNS,
8397 GETDNS_PORT_DNS_OVER_TLS
8498 };
8599
86 char*
100 static char*
87101 getdns_port_str_array[] = {
88 GETDNS_STR_PORT_DNS,
89102 GETDNS_STR_PORT_DNS,
90103 GETDNS_STR_PORT_DNS_OVER_TLS
91104 };
92105
106 static const uint8_t no_suffixes[] = { 1, 0 };
107
93108 /* Private functions */
94109 static getdns_return_t create_default_namespaces(struct getdns_context *context);
95110 static getdns_return_t create_default_dns_transports(struct getdns_context *context);
96 static struct getdns_list *create_default_root_servers(void);
97 static getdns_return_t set_os_defaults(struct getdns_context *);
98111 static int transaction_id_cmp(const void *, const void *);
99112 static void dispatch_updated(struct getdns_context *, uint16_t);
100113 static void cancel_dns_req(getdns_dns_req *);
165178 {
166179 uint8_t *next_label;
167180
168 while (*dname) {
181 while (*dname && !(*dname & 0xC0)) {
169182 next_label = dname + *dname + 1;
170183 dname += 1;
171184 while (dname < next_label) {
355368 int start_of_line = 1;
356369 getdns_dict *address = NULL;
357370
371 #ifdef USE_WINSOCK
372 in = fopen("c:\\WINDOWS\\system32\\drivers\\etc\\hosts", "r");
373 #else
358374 in = fopen("/etc/hosts", "r");
375 #endif
359376 while (fgets(pos, (int)(sizeof(buf) - (pos - buf)), in)) {
360377 pos = buf;
361378 /* Break out of for to read more */
437454 }
438455
439456 /**
440 * Helper to get the default root servers.
441 * TODO: Implement
442 */
443 static struct getdns_list *
444 create_default_root_servers()
445 {
446 return NULL;
447 }
448
449 /**
450457 * check a file for changes since the last check
451458 * and refresh the current data if changes are detected
452459 * @param context pointer to a previously created context to be used for this call
523530 ; upstreams->count
524531 ; upstreams->count--, upstream++ ) {
525532
533 sha256_pin_t *pin = upstream->tls_pubkey_pinset;
526534 if (upstream->loop && ( upstream->event.read_cb
527535 || upstream->event.write_cb
528536 || upstream->event.timeout_cb) ) {
538546 }
539547 if (upstream->fd != -1)
540548 close(upstream->fd);
549 while (pin) {
550 sha256_pin_t *nextpin = pin->next;
551 GETDNS_FREE(upstreams->mf, pin);
552 pin = nextpin;
553 }
554 upstream->tls_pubkey_pinset = NULL;
541555 }
542556 GETDNS_FREE(upstreams->mf, upstreams);
543557 }
556570 upstream->tcp.write_error = 0;
557571 upstream->writes_done = 0;
558572 upstream->responses_received = 0;
573 upstream->keepalive_timeout = 0;
559574 if (upstream->tls_hs_state != GETDNS_HS_FAILED) {
560575 upstream->tls_hs_state = GETDNS_HS_NONE;
561576 upstream->tls_auth_failed = 0;
573588 static int
574589 tls_is_in_transports_list(getdns_context *context) {
575590 for (int i=0; i< context->dns_transport_count;i++) {
576 if (context->dns_transports[i] == GETDNS_TRANSPORT_TLS ||
577 context->dns_transports[i] == GETDNS_TRANSPORT_STARTTLS)
591 if (context->dns_transports[i] == GETDNS_TRANSPORT_TLS)
578592 return 1;
579593 }
580594 return 0;
584598 tls_only_is_in_transports_list(getdns_context *context) {
585599 if (context->dns_transport_count != 1)
586600 return 0;
587 if (context->dns_transports[0] == GETDNS_TRANSPORT_TLS ||
588 context->dns_transports[0] == GETDNS_TRANSPORT_STARTTLS)
601 if (context->dns_transports[0] == GETDNS_TRANSPORT_TLS)
589602 return 1;
590603 return 0;
591604 }
595608 net_req_query_id_cmp(const void *id1, const void *id2)
596609 {
597610 return (intptr_t)id1 - (intptr_t)id2;
611 }
612
613 static getdns_tsig_info const tsig_info[] = {
614 { GETDNS_NO_TSIG, NULL, 0, NULL, 0, 0, 0 }
615 , { GETDNS_HMAC_MD5 , "hmac-md5.sig-alg.reg.int", 24
616 , (uint8_t *)"\x08hmac-md5\x07sig-alg\x03reg\x03int", 26, 10, 16 }
617 , { GETDNS_NO_TSIG, NULL, 0, NULL, 0, 0, 0 }
618 , { GETDNS_HMAC_SHA1 , "hmac-sha1" , 9
619 , (uint8_t *)"\x09hmac-sha1" , 11, 10, 20 }
620 , { GETDNS_HMAC_SHA224, "hmac-sha224", 11
621 , (uint8_t *)"\x0bhmac-sha224", 13, 14, 28 }
622 , { GETDNS_HMAC_SHA256, "hmac-sha256", 11
623 , (uint8_t *)"\x0bhmac-sha256", 13, 16, 32 }
624 , { GETDNS_HMAC_SHA384, "hmac-sha384", 11
625 , (uint8_t *)"\x0bhmac-sha384", 13, 24, 48 }
626 , { GETDNS_HMAC_SHA512, "hmac-sha512", 11
627 , (uint8_t *)"\x0bhmac-sha512", 13, 32, 64 }
628 , { GETDNS_HMAC_MD5 , "hmac-md5" , 8
629 , (uint8_t *)"\x08hmac-md5" , 10, 10, 16 }
630 };
631 static size_t const n_tsig_infos =
632 sizeof(tsig_info) / sizeof(getdns_tsig_info);
633
634 static getdns_tsig_info const * const last_tsig_info =
635 tsig_info + (sizeof(tsig_info) / sizeof(getdns_tsig_info));
636
637 const getdns_tsig_info *_getdns_get_tsig_info(getdns_tsig_algo tsig_alg)
638 {
639 return tsig_alg > n_tsig_infos - 1
640 || tsig_info[tsig_alg].alg == GETDNS_NO_TSIG ? NULL
641 : &tsig_info[tsig_alg];
642 }
643
644 static getdns_tsig_algo _getdns_get_tsig_algo(getdns_bindata *algo)
645 {
646 const getdns_tsig_info *i;
647
648 if (!algo || algo->size == 0)
649 return GETDNS_NO_TSIG;
650
651 if (algo->data[algo->size-1] != 0) {
652 /* Unterminated string */
653 for (i = tsig_info; i < last_tsig_info; i++)
654 if ((algo->size == i->strlen_name ||
655 (algo->size - 1 == i->strlen_name &&
656 algo->data[algo->size - 1] == '.'
657 )
658 )&&
659 strncasecmp((const char *)algo->data, i->name,
660 i->strlen_name) == 0)
661 return i->alg;
662
663 } else if (!_getdns_bindata_is_dname(algo)) {
664 /* Terminated string */
665 for (i = tsig_info; i < last_tsig_info; i++)
666 if (algo->size - 1 == i->strlen_name &&
667 strncasecmp((const char *)algo->data, i->name,
668 i->strlen_name) == 0)
669 return i->alg;
670
671 } else {
672 /* fqdn, canonical_dname_compare is now safe to use! */
673 for (i = tsig_info; i < last_tsig_info; i++)
674 if (canonical_dname_compare(algo->data, i->dname) == 0)
675 return i->alg;
676 }
677 return GETDNS_NO_TSIG;
598678 }
599679
600680 static void
609689 /* How is this upstream doing? */
610690 upstream->writes_done = 0;
611691 upstream->responses_received = 0;
692 upstream->keepalive_timeout = 0;
612693 upstream->to_retry = 2;
613694 upstream->back_off = 1;
614695
615696 /* For sharing a socket to this upstream with TCP */
616697 upstream->fd = -1;
617698 upstream->tls_obj = NULL;
618 upstream->starttls_req = NULL;
619699 upstream->transport = GETDNS_TRANSPORT_TCP;
620700 upstream->tls_hs_state = GETDNS_HS_NONE;
621701 upstream->tls_auth_failed = 0;
622702 upstream->tls_auth_name[0] = '\0';
703 upstream->tls_pubkey_pinset = NULL;
623704 upstream->tcp.write_error = 0;
624705 upstream->loop = NULL;
625706 (void) getdns_eventloop_event_init(
633714 upstream->has_prev_client_cookie = 0;
634715 upstream->has_server_cookie = 0;
635716
717 upstream->tsig_alg = GETDNS_NO_TSIG;
718 upstream->tsig_dname_len = 0;
719 upstream->tsig_size = 0;
720
636721 /* Tracking of network requests on this socket */
637722 _getdns_rbtree_init(&upstream->netreq_by_query_id,
638723 net_req_query_id_cmp);
639724 }
640725
726 #ifdef USE_WINSOCK
727 static getdns_return_t
728 set_os_defaults_windows(struct getdns_context *context)
729 {
730 char domain[1024] = "";
731 size_t upstreams_limit = 10;
732 struct addrinfo hints;
733 struct addrinfo *result;
734 getdns_upstream *upstream;
735 int s;
736
737 if (context->fchg_resolvconf == NULL) {
738 context->fchg_resolvconf =
739 GETDNS_MALLOC(context->my_mf, struct filechg);
740 if (context->fchg_resolvconf == NULL)
741 return GETDNS_RETURN_MEMORY_ERROR;
742 context->fchg_resolvconf->fn = "InvalidOnWindows";
743 context->fchg_resolvconf->prevstat = NULL;
744 context->fchg_resolvconf->changes = GETDNS_FCHG_NOCHANGES;
745 context->fchg_resolvconf->errors = GETDNS_FCHG_NOERROR;
746 }
747 _getdns_filechg_check(context, context->fchg_resolvconf);
748
749 context->upstreams = upstreams_create(context, upstreams_limit);
750
751 memset(&hints, 0, sizeof(struct addrinfo));
752 hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
753 hints.ai_socktype = 0; /* Datagram socket */
754 hints.ai_flags = AI_NUMERICHOST; /* No reverse name lookups */
755 hints.ai_protocol = 0; /* Any protocol */
756 hints.ai_canonname = NULL;
757 hints.ai_addr = NULL;
758 hints.ai_next = NULL;
759
760 FIXED_INFO *info;
761 ULONG buflen = sizeof(*info);
762 IP_ADDR_STRING *ptr = 0;
763
764 info = (FIXED_INFO *)malloc(sizeof(FIXED_INFO));
765 if (info == NULL)
766 return GETDNS_RETURN_GENERIC_ERROR;
767
768 if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) {
769 free(info);
770 info = (FIXED_INFO *)malloc(buflen);
771 if (info == NULL)
772 return GETDNS_RETURN_GENERIC_ERROR;
773 }
774
775 if (GetNetworkParams(info, &buflen) == NO_ERROR) {
776 ptr = info->DnsServerList.Next;
777 *domain = 0;
778 while (ptr) {
779 for (size_t i = 0; i < GETDNS_UPSTREAM_TRANSPORTS; i++) {
780 char *port_str = getdns_port_str_array[i];
781 if ((s = getaddrinfo(ptr->IpAddress.String, port_str, &hints, &result)))
782 continue;
783 if (!result)
784 continue;
785
786 upstream = &context->upstreams->
787 upstreams[context->upstreams->count++];
788 upstream_init(upstream, context->upstreams, result);
789 upstream->transport = getdns_upstream_transports[i];
790 freeaddrinfo(result);
791 }
792 ptr = ptr->Next;
793
794 }
795 free(info);
796 }
797 return GETDNS_RETURN_GOOD;
798 } /* set_os_defaults_windows */
799 #else
641800 static getdns_return_t
642801 set_os_defaults(struct getdns_context *context)
643802 {
648807 struct addrinfo hints;
649808 struct addrinfo *result;
650809 getdns_upstream *upstream;
810 getdns_list *suffix;
651811 int s;
652812
653813 if(context->fchg_resolvconf == NULL) {
672832 upstream_count++;
673833 fclose(in);
674834
675 context->suffix = getdns_list_create_with_context(context);
835 suffix = getdns_list_create_with_context(context);
676836 context->upstreams = upstreams_create(
677837 context, upstream_count * GETDNS_UPSTREAM_TRANSPORTS);
678838
713873 prev_ch = *token;
714874 *token = 0;
715875
716 _getdns_list_append_string(context->suffix, parse);
876 _getdns_list_append_string(suffix, parse);
717877
718878 *token = prev_ch;
719879 parse = token;
744904 }
745905 fclose(in);
746906
747 (void) getdns_list_get_length(context->suffix, &length);
907 (void) getdns_list_get_length(suffix, &length);
748908 if (length == 0 && *domain != 0)
749 _getdns_list_append_string(context->suffix, domain);
909 _getdns_list_append_string(suffix, domain);
910 (void )getdns_context_set_suffix(context, suffix);
911 getdns_list_destroy(suffix);
912
750913 return GETDNS_RETURN_GOOD;
751914 } /* set_os_defaults */
915 #endif
752916
753917 /* compare of transaction ids in DESCENDING order
754918 so that 0 comes last
8461010 result->timeout = 5000;
8471011 result->idle_timeout = 0;
8481012 result->follow_redirects = GETDNS_REDIRECTS_FOLLOW;
849 result->dns_root_servers = create_default_root_servers();
1013 result->dns_root_servers = NULL;
1014 result->root_servers_fn[0] = 0;
8501015 result->append_name = GETDNS_APPEND_NAME_ALWAYS;
851 result->suffix = NULL;
1016 result->suffixes = no_suffixes;
1017 result->suffixes_len = sizeof(no_suffixes);
8521018
8531019 gldns_buffer_init_frm_data(&gbuf, result->trust_anchors_spc
8541020 , sizeof(result->trust_anchors_spc));
8901056 result->fchg_resolvconf = NULL;
8911057 result->fchg_hosts = NULL;
8921058
1059 // resolv.conf does not exist on Windows, handle differently
1060 #ifndef USE_WINSOCK
8931061 if (set_from_os && (r = set_os_defaults(result)))
8941062 goto error;
1063 #else
1064 if (set_from_os && (r = set_os_defaults_windows(result)))
1065 goto error;
1066 #endif
8951067
8961068 result->dnssec_allowed_skew = 0;
8971069 result->edns_maximum_udp_payload_size = -1;
10101182 if (context->tls_ctx)
10111183 SSL_CTX_free(context->tls_ctx);
10121184
1013 getdns_list_destroy(context->dns_root_servers);
1014 getdns_list_destroy(context->suffix);
1185 if (context->dns_root_servers)
1186 getdns_list_destroy(context->dns_root_servers);
1187 if (context->root_servers_fn[0])
1188 unlink(context->root_servers_fn);
1189
1190 if (context->suffixes && context->suffixes != no_suffixes)
1191 GETDNS_FREE(context->mf, (void *)context->suffixes);
10151192
10161193 if (context->trust_anchors &&
10171194 context->trust_anchors != context->trust_anchors_spc)
12041381 *
12051382 */
12061383 getdns_return_t
1207 getdns_context_set_namespaces(struct getdns_context *context,
1384 getdns_context_set_namespaces(getdns_context *context,
12081385 size_t namespace_count, getdns_namespace_t *namespaces)
12091386 {
12101387 size_t i;
1211
1212 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
1213 if (namespace_count == 0 || namespaces == NULL) {
1214 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1215 }
1216
1217 for(i=0; i<namespace_count; i++)
1218 {
1219 if( namespaces[i] != GETDNS_NAMESPACE_DNS
1220 && namespaces[i] != GETDNS_NAMESPACE_LOCALNAMES
1221 && namespaces[i] != GETDNS_NAMESPACE_NETBIOS
1222 && namespaces[i] != GETDNS_NAMESPACE_MDNS
1223 && namespaces[i] != GETDNS_NAMESPACE_NIS)
1388 getdns_return_t r = GETDNS_RETURN_GOOD;
1389
1390 if (!context)
1391 return GETDNS_RETURN_INVALID_PARAMETER;
1392
1393 if (namespace_count == 0 || namespaces == NULL)
1394 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1395
1396 for (i = 0; i < namespace_count; i++) {
1397 if (namespaces[i] == GETDNS_NAMESPACE_NETBIOS ||
1398 namespaces[i] == GETDNS_NAMESPACE_MDNS ||
1399 namespaces[i] == GETDNS_NAMESPACE_NIS)
1400 r = GETDNS_RETURN_NOT_IMPLEMENTED;
1401
1402 else if (namespaces[i] != GETDNS_NAMESPACE_DNS &&
1403 namespaces[i] != GETDNS_NAMESPACE_LOCALNAMES)
12241404 return GETDNS_RETURN_INVALID_PARAMETER;
12251405 }
1226
1227 GETDNS_FREE(context->my_mf, context->namespaces);
1228
1229 /** duplicate **/
1230 context->namespaces = GETDNS_XMALLOC(context->my_mf, getdns_namespace_t,
1231 namespace_count);
1232 memcpy(context->namespaces, namespaces,
1233 namespace_count * sizeof(getdns_namespace_t));
1406 GETDNS_FREE(context->my_mf, context->namespaces);
1407
1408 /** duplicate **/
1409 context->namespaces = GETDNS_XMALLOC(
1410 context->my_mf, getdns_namespace_t, namespace_count);
1411 (void) memcpy(context->namespaces, namespaces,
1412 namespace_count * sizeof(getdns_namespace_t));
12341413 context->namespace_count = namespace_count;
1235 dispatch_updated(context, GETDNS_CONTEXT_CODE_NAMESPACES);
1236
1237 return GETDNS_RETURN_GOOD;
1414
1415 dispatch_updated(context, GETDNS_CONTEXT_CODE_NAMESPACES);
1416
1417 return r;
12381418 } /* getdns_context_set_namespaces */
12391419
12401420 static getdns_return_t
12481428 return GETDNS_RETURN_INVALID_PARAMETER;
12491429
12501430 /* Check for valid transports and that they are used only once*/
1251 int u=0,t=0,l=0,s=0;
1431 int u=0,t=0,l=0;
12521432 for(i=0; i<transport_count; i++)
12531433 {
12541434 switch (transports[i]) {
12551435 case GETDNS_TRANSPORT_UDP: u++; break;
12561436 case GETDNS_TRANSPORT_TCP: t++; break;
12571437 case GETDNS_TRANSPORT_TLS: l++; break;
1258 case GETDNS_TRANSPORT_STARTTLS: s++; break;
12591438 default: return GETDNS_RETURN_INVALID_PARAMETER;
12601439 }
12611440 }
1262 if ( u>1 || t>1 || l>1 || s>1)
1441 if ( u>1 || t>1 || l>1)
12631442 return GETDNS_RETURN_INVALID_PARAMETER;
12641443
12651444 if (!(new_transports = GETDNS_XMALLOC(context->my_mf,
12961475 set_ub_string_opt(context, "do-tcp:", "yes");
12971476 break;
12981477 case GETDNS_TRANSPORT_TLS:
1299 case GETDNS_TRANSPORT_STARTTLS:
13001478 set_ub_string_opt(context, "do-udp:", "no");
13011479 set_ub_string_opt(context, "do-tcp:", "yes");
13021480 /* Find out if there is a fallback available. */
13131491 break;
13141492 }
13151493 }
1316 if (context->dns_transports[0] == GETDNS_TRANSPORT_TLS) {
1317 if (fallback == 0)
1318 /* Use TLS if it is the only thing.*/
1319 set_ub_string_opt(context, "ssl-upstream:", "yes");
1320 break;
1321 } else if (fallback == 0)
1322 /* Can't support STARTTLS with no fallback. This leads to
1323 * timeouts with un stub validation.... */
1324 set_ub_string_opt(context, "do-tcp:", "no");
1494 if (fallback == 0)
1495 /* Use TLS if it is the only thing.*/
1496 set_ub_string_opt(context, "ssl-upstream:", "yes");
13251497 break;
13261498 default:
13271499 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
13781550 context->dns_transports[0] = GETDNS_TRANSPORT_TLS;
13791551 context->dns_transports[1] = GETDNS_TRANSPORT_TCP;
13801552 break;
1381 case GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
1382 context->dns_transports[0] = GETDNS_TRANSPORT_STARTTLS;
1383 context->dns_transports[1] = GETDNS_TRANSPORT_TCP;
1384 break;
13851553 default:
13861554 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
13871555 }
14321600 {
14331601 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
14341602 if (value != GETDNS_AUTHENTICATION_NONE &&
1435 value != GETDNS_AUTHENTICATION_HOSTNAME) {
1603 value != GETDNS_AUTHENTICATION_REQUIRED) {
14361604 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
14371605 }
14381606 context->tls_auth = value;
14951663 {
14961664 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
14971665
1498 if (timeout == 0) {
1499 return GETDNS_RETURN_INVALID_PARAMETER;
1500 }
1666 /* Shuold we enforce maximum based on edns-tcp-keepalive spec? */
1667 /* 0 should be allowed as that is the default.*/
15011668
15021669 context->idle_timeout = timeout;
15031670
15121679 *
15131680 */
15141681 getdns_return_t
1515 getdns_context_set_follow_redirects(struct getdns_context *context,
1516 getdns_redirects_t value)
1517 {
1518 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
1519 if (value != GETDNS_REDIRECTS_FOLLOW && value != GETDNS_REDIRECTS_DO_NOT_FOLLOW)
1520 return GETDNS_RETURN_INVALID_PARAMETER;
1521
1522 context->follow_redirects = value;
1523 if (context->resolution_type_set != 0) {
1524 /* already setup */
1525 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1526 }
1527
1528 dispatch_updated(context, GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS);
1529 return GETDNS_RETURN_GOOD;
1682 getdns_context_set_follow_redirects(
1683 getdns_context *context, getdns_redirects_t value)
1684 {
1685 if (!context)
1686 return GETDNS_RETURN_INVALID_PARAMETER;
1687
1688 if (value != GETDNS_REDIRECTS_FOLLOW &&
1689 value != GETDNS_REDIRECTS_DO_NOT_FOLLOW)
1690 return GETDNS_RETURN_INVALID_PARAMETER;
1691
1692 context->follow_redirects = value;
1693
1694 dispatch_updated(context, GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS);
1695
1696 return GETDNS_RETURN_NOT_IMPLEMENTED;
15301697 } /* getdns_context_set_follow_redirects */
15311698
15321699 /*
15341701 *
15351702 */
15361703 getdns_return_t
1537 getdns_context_set_dns_root_servers(struct getdns_context *context,
1538 struct getdns_list * addresses)
1539 {
1540 struct getdns_list *copy = NULL;
1541 size_t count = 0;
1542 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
1543 if (context->resolution_type_set != 0) {
1544 /* already setup */
1545 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1546 }
1547 if (addresses != NULL) {
1548 if (_getdns_list_copy(addresses, &copy) != GETDNS_RETURN_GOOD) {
1549 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1550 }
1551 addresses = copy;
1552 getdns_list_get_length(addresses, &count);
1553 if (count == 0) {
1554 getdns_list_destroy(addresses);
1555 addresses = NULL;
1556 } else {
1557 size_t i = 0;
1558 getdns_return_t r = GETDNS_RETURN_GOOD;
1559 /* validate and add ip str */
1560 for (i = 0; i < count; ++i) {
1561 struct getdns_dict *dict = NULL;
1562 getdns_list_get_dict(addresses, i, &dict);
1563 if (r != GETDNS_RETURN_GOOD) {
1564 break;
1565 }
1566 }
1567 if (r != GETDNS_RETURN_GOOD) {
1568 getdns_list_destroy(addresses);
1569 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1570 }
1571 }
1572 }
1573
1574 getdns_list_destroy(context->dns_root_servers);
1575 context->dns_root_servers = addresses;
1576
1577 dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS);
1578
1579 return GETDNS_RETURN_GOOD;
1704 getdns_context_set_dns_root_servers(
1705 getdns_context *context, getdns_list *addresses)
1706 {
1707 char tmpfn[FILENAME_MAX] = P_tmpdir "/getdns-root-dns-servers-XXXXXX";
1708 FILE *fh;
1709 int fd;
1710 size_t i;
1711 getdns_dict *rr_dict;
1712 getdns_return_t r;
1713 getdns_bindata *addr_bd;
1714 char dst[2048];
1715 size_t dst_len;
1716 getdns_list *newlist;
1717
1718 if (!context)
1719 return GETDNS_RETURN_INVALID_PARAMETER;
1720
1721 if (!addresses) {
1722 #ifdef HAVE_LIBUNBOUND
1723 if (ub_ctx_set_option(
1724 context->unbound_ctx, "root-hints:", ""))
1725 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1726 #endif
1727 if (context->dns_root_servers)
1728 getdns_list_destroy(context->dns_root_servers);
1729 context->dns_root_servers = NULL;
1730
1731 if (context->root_servers_fn[0])
1732 unlink(context->root_servers_fn);
1733 context->root_servers_fn[0] = 0;
1734
1735 dispatch_updated(
1736 context, GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS);
1737 return GETDNS_RETURN_GOOD;
1738 }
1739 if ((fd = mkstemp(tmpfn)) < 0)
1740 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1741
1742 if (!(fh = fdopen(fd, "w")))
1743 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1744
1745 for (i=0; (!(r = getdns_list_get_dict(addresses, i, &rr_dict))); i++) {
1746 dst_len = sizeof(dst);
1747 if (!getdns_rr_dict2str_buf(rr_dict, dst, &dst_len))
1748
1749 fprintf(fh, "%s", dst);
1750
1751 else if (getdns_dict_get_bindata(
1752 rr_dict, "address_data", &addr_bd) &&
1753 getdns_dict_get_bindata(
1754 rr_dict, "/rdata/ipv4_address", &addr_bd) &&
1755 getdns_dict_get_bindata(
1756 rr_dict, "/rdata/ipv6_address", &addr_bd))
1757
1758 ; /* pass */
1759
1760 else if (addr_bd->size == 16 &&
1761 inet_ntop(AF_INET6, addr_bd->data, dst, sizeof(dst)))
1762
1763 fprintf(fh, ". NS %zu.root-servers.getdnsapi.net.\n"
1764 "%zu.root-servers.getdnsapi.net. AAAA %s\n",
1765 i, i, dst);
1766
1767 else if (addr_bd->size == 4 &&
1768 inet_ntop(AF_INET, addr_bd->data, dst, sizeof(dst)))
1769
1770 fprintf(fh, ". NS %zu.root-servers.getdnsapi.net.\n"
1771 "%zu.root-servers.getdnsapi.net. A %s\n",
1772 i, i, dst);
1773 }
1774 fclose(fh);
1775 #ifdef HAVE_LIBUNBOUND
1776 if (ub_ctx_set_option(
1777 context->unbound_ctx, "root-hints:", tmpfn)) {
1778 unlink(tmpfn);
1779 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1780 }
1781 #endif
1782 if (_getdns_list_copy(addresses, &newlist)) {
1783 unlink(tmpfn);
1784 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1785 }
1786 if (context->dns_root_servers)
1787 getdns_list_destroy(context->dns_root_servers);
1788 context->dns_root_servers = newlist;
1789
1790 if (context->root_servers_fn[0])
1791 unlink(context->root_servers_fn);
1792 (void) memcpy(context->root_servers_fn, tmpfn, strlen(tmpfn));
1793
1794 dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS);
1795 return GETDNS_RETURN_GOOD;
15801796 } /* getdns_context_set_dns_root_servers */
15811797
15821798 /*
16071823 *
16081824 */
16091825 getdns_return_t
1610 getdns_context_set_suffix(struct getdns_context *context, struct getdns_list * value)
1611 {
1612 struct getdns_list *copy = NULL;
1613 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
1614 if (context->resolution_type_set != 0) {
1615 /* already setup */
1616 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1617 }
1618 if (value != NULL) {
1619 if (_getdns_list_copy(value, &copy) != GETDNS_RETURN_GOOD) {
1620 return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
1621 }
1622 value = copy;
1623 }
1624 getdns_list_destroy(context->suffix);
1625 context->suffix = value;
1626
1627 dispatch_updated(context, GETDNS_CONTEXT_CODE_SUFFIX);
1628
1629 return GETDNS_RETURN_GOOD;
1826 getdns_context_set_suffix(getdns_context *context, getdns_list *value)
1827 {
1828 getdns_return_t r;
1829 size_t i;
1830 gldns_buffer gbuf;
1831 uint8_t buf_spc[1024], *suffixes = NULL;
1832 size_t suffixes_len = 0;
1833 uint8_t dname[256];
1834 size_t dname_len;
1835 char name_spc[1025], *name;
1836 getdns_bindata *bindata;
1837
1838 if (!context)
1839 return GETDNS_RETURN_INVALID_PARAMETER;
1840
1841 if (value == NULL) {
1842 if (context->suffixes && context->suffixes != no_suffixes)
1843 GETDNS_FREE(context->mf, (void *)context->suffixes);
1844
1845 context->suffixes = no_suffixes;
1846 context->suffixes_len = sizeof(no_suffixes);
1847 return GETDNS_RETURN_GOOD;
1848 }
1849 gldns_buffer_init_frm_data(&gbuf, buf_spc, sizeof(buf_spc));
1850 for (;;) {
1851 for ( i = 0
1852 ; !(r = getdns_list_get_bindata(value, i, &bindata))
1853 ; i++) {
1854
1855 if (bindata->size == 0 || bindata->size >= sizeof(name_spc))
1856 continue;
1857
1858 if (bindata->data[bindata->size-1] != 0) {
1859 /* Unterminated string */
1860 (void) memcpy(name_spc, bindata->data, bindata->size);
1861 name_spc[bindata->size] = 0;
1862 name = name_spc;
1863 } else
1864 /* Terminated string */
1865 name = (char *)bindata->data;
1866
1867 dname_len = sizeof(dname);
1868 if (gldns_str2wire_dname_buf(name, dname, &dname_len))
1869 return GETDNS_RETURN_GENERIC_ERROR;
1870
1871 gldns_buffer_write_u8(&gbuf, dname_len);
1872 gldns_buffer_write(&gbuf, dname, dname_len);
1873 }
1874 if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
1875 r = GETDNS_RETURN_GOOD;
1876 else
1877 break;
1878
1879 gldns_buffer_write_u8(&gbuf, 1);
1880 gldns_buffer_write_u8(&gbuf, 0);
1881
1882 if (gldns_buffer_begin(&gbuf) != buf_spc)
1883 break;
1884
1885 suffixes_len = gldns_buffer_position(&gbuf);
1886 if (!(suffixes = GETDNS_XMALLOC(
1887 context->mf, uint8_t, suffixes_len))) {
1888 r = GETDNS_RETURN_MEMORY_ERROR;
1889 break;
1890 }
1891 if (suffixes_len <= gldns_buffer_limit(&gbuf)) {
1892 (void) memcpy (suffixes, buf_spc, suffixes_len);
1893 break;
1894 }
1895 gldns_buffer_init_frm_data(&gbuf, suffixes, suffixes_len);
1896 }
1897 if (r) {
1898 if (gldns_buffer_begin(&gbuf) != buf_spc)
1899 GETDNS_FREE(context->mf, suffixes);
1900 return r;
1901 }
1902 if (context->suffixes && context->suffixes != no_suffixes)
1903 GETDNS_FREE(context->mf, (void *)context->suffixes);
1904
1905 context->suffixes = suffixes;
1906 context->suffixes_len = suffixes_len;
1907
1908 dispatch_updated(context, GETDNS_CONTEXT_CODE_SUFFIX);
1909 return GETDNS_RETURN_GOOD;
16301910 } /* getdns_context_set_suffix */
16311911
16321912 /*
17131993 upstreams = upstreams_create(
17141994 context, count * GETDNS_UPSTREAM_TRANSPORTS);
17151995 for (i = 0; i < count; i++) {
1716 getdns_dict *dict;
1996 getdns_dict *dict;
17171997 getdns_bindata *address_type;
17181998 getdns_bindata *address_data;
17191999 getdns_bindata *tls_auth_name;
17202000 struct sockaddr_storage addr;
17212001
1722 getdns_bindata *scope_id;
2002 getdns_bindata *scope_id;
17232003 getdns_upstream *upstream;
2004
2005 getdns_bindata *tsig_alg_name, *tsig_name, *tsig_key;
2006 getdns_tsig_algo tsig_alg;
2007 char tsig_name_str[1024];
2008 uint8_t tsig_dname_spc[256], *tsig_dname;
2009 size_t tsig_dname_len;
17242010
17252011 if ((r = getdns_list_get_dict(upstream_list, i, &dict)))
17262012 goto error;
17582044 eos[scope_id->size] = 0;
17592045 }
17602046
2047 tsig_alg_name = tsig_name = tsig_key = NULL;
2048 tsig_dname = NULL;
2049 tsig_dname_len = 0;
2050
2051 if (getdns_dict_get_bindata(dict,
2052 "tsig_algorithm", &tsig_alg_name) == GETDNS_RETURN_GOOD)
2053 tsig_alg = _getdns_get_tsig_algo(tsig_alg_name);
2054 else
2055 tsig_alg = GETDNS_HMAC_MD5;
2056
2057 if (getdns_dict_get_bindata(dict, "tsig_name", &tsig_name))
2058 tsig_alg = GETDNS_NO_TSIG; /* No name, no TSIG */
2059
2060 else if (tsig_name->size == 0)
2061 tsig_alg = GETDNS_NO_TSIG;
2062
2063 else if (tsig_name->data[tsig_name->size - 1] != 0) {
2064 /* Unterminated string */
2065 if (tsig_name->size >= sizeof(tsig_name_str) - 1)
2066 tsig_alg = GETDNS_NO_TSIG;
2067 else {
2068 (void) memcpy(tsig_name_str, tsig_name->data
2069 , tsig_name->size);
2070 tsig_name_str[tsig_name->size] = 0;
2071
2072 tsig_dname_len = sizeof(tsig_dname_spc);
2073 if (gldns_str2wire_dname_buf(tsig_name_str,
2074 tsig_dname_spc, &tsig_dname_len))
2075 tsig_alg = GETDNS_NO_TSIG;
2076 else
2077 tsig_dname = tsig_dname_spc;
2078 }
2079 } else if (!_getdns_bindata_is_dname(tsig_name)) {
2080 /* Terminated string */
2081 tsig_dname_len = sizeof(tsig_dname_spc);
2082 if (gldns_str2wire_dname_buf(tsig_name_str,
2083 tsig_dname_spc, &tsig_dname_len))
2084 tsig_alg = GETDNS_NO_TSIG;
2085 else
2086 tsig_dname = tsig_dname_spc;
2087
2088 } else if (tsig_name->size > sizeof(tsig_dname_spc))
2089 tsig_alg = GETDNS_NO_TSIG;
2090
2091 else {
2092 /* fqdn */
2093 tsig_dname = memcpy(tsig_dname_spc, tsig_name->data
2094 , tsig_name->size);
2095 tsig_dname_len = tsig_name->size;
2096 }
2097 if (getdns_dict_get_bindata(dict, "tsig_secret", &tsig_key))
2098 tsig_alg = GETDNS_NO_TSIG; /* No key, no TSIG */
2099
2100 /* Don't check TSIG length contraints here.
2101 * Let the upstream decide what is secure enough.
2102 */
2103
17612104 /* Loop to create upstreams as needed*/
17622105 for (size_t j = 0; j < GETDNS_UPSTREAM_TRANSPORTS; j++) {
17632106 uint32_t port;
17852128 upstream->addr.ss_family = addr.ss_family;
17862129 upstream_init(upstream, upstreams, ai);
17872130 upstream->transport = getdns_upstream_transports[j];
1788 if (getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS ||
1789 getdns_upstream_transports[j] == GETDNS_TRANSPORT_STARTTLS) {
2131 if (getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS) {
2132 getdns_list *pubkey_pinset = NULL;
17902133 if ((r = getdns_dict_get_bindata(
17912134 dict, "tls_auth_name", &tls_auth_name)) == GETDNS_RETURN_GOOD) {
17922135 /*TODO: VALIDATE THIS STRING!*/
17952138 tls_auth_name->size);
17962139 upstream->tls_auth_name[tls_auth_name->size] = '\0';
17972140 }
2141 if ((r = getdns_dict_get_list(dict, "tls_pubkey_pinset",
2142 &pubkey_pinset)) == GETDNS_RETURN_GOOD) {
2143 /* TODO: what if the user supplies tls_pubkey_pinset with
2144 * something other than a list? */
2145 r = _getdns_get_pubkey_pinset_from_list(pubkey_pinset,
2146 &(upstreams->mf),
2147 &(upstream->tls_pubkey_pinset));
2148 if (r != GETDNS_RETURN_GOOD)
2149 goto invalid_parameter;
2150 }
2151 }
2152 if ((upstream->tsig_alg = tsig_alg)) {
2153 if (tsig_name) {
2154 (void) memcpy(upstream->tsig_dname,
2155 tsig_dname, tsig_dname_len);
2156 upstream->tsig_dname_len =
2157 tsig_dname_len;
2158 } else
2159 upstream->tsig_dname_len = 0;
2160
2161 if (tsig_key) {
2162 (void) memcpy(upstream->tsig_key,
2163 tsig_key->data, tsig_key->size);
2164 upstream->tsig_size = tsig_key->size;
2165 } else
2166 upstream->tsig_size = 0;
2167 } else {
2168 upstream->tsig_dname_len = 0;
2169 upstream->tsig_size = 0;
17982170 }
17992171 upstreams->count++;
18002172 freeaddrinfo(ai);
21822554 _getdns_rr_iter rr_spc, *rr;
21832555 char ta_str[8192];
21842556
2185 /* TODO: use the root servers via root hints file */
21862557 (void) ub_ctx_set_fwd(ctx, NULL);
21872558 if (!context->unbound_ta_set && context->trust_anchors) {
21882559 for ( rr = _getdns_rr_iter_init( &rr_spc
21902561 , context->trust_anchors_len)
21912562 ; rr ; rr = _getdns_rr_iter_next(rr) ) {
21922563
2193 (void) gldns_wire2str_rr_buf(rr->pos,
2564 (void) gldns_wire2str_rr_buf((UNCONST_UINT8_p)rr->pos,
21942565 rr->nxt - rr->pos, ta_str, sizeof(ta_str));
21952566 (void) ub_ctx_add_ta(ctx, ta_str);
21962567 }
22492620 /* Create client context, use TLS v1.2 only for now */
22502621 context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
22512622 if(context->tls_ctx == NULL)
2623 #ifndef USE_WINSOCK
22522624 return GETDNS_RETURN_BAD_CONTEXT;
2625 #else
2626 printf("Warning! Bad TLS context, check openssl version on Windows!\n");;
2627 #endif
22532628 /* Be strict and only use the cipher suites recommended in RFC7525
22542629 Unless we later fallback to opportunistic. */
22552630 const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM";
22652640 #endif
22662641 }
22672642 if (tls_only_is_in_transports_list(context) == 1 &&
2268 context->tls_auth == GETDNS_AUTHENTICATION_HOSTNAME) {
2269 context->tls_auth_min = GETDNS_AUTHENTICATION_HOSTNAME;
2643 context->tls_auth == GETDNS_AUTHENTICATION_REQUIRED) {
2644 context->tls_auth_min = GETDNS_AUTHENTICATION_REQUIRED;
22702645 /* TODO: If no auth data provided for any upstream, fail here */
22712646 }
22722647 else {
22742649 }
22752650 }
22762651
2277 /* Block use of STARTTLS/TLS ONLY in recursive mode as it won't work */
2652 /* Block use of TLS ONLY in recursive mode as it won't work */
22782653 /* Note: If TLS is used in recursive mode this will try TLS on port
2279 * 53 so it is blocked here. So is 'STARTTLS only' at the moment. */
2654 * 53 so it is blocked here. */
22802655 if (context->resolution_type == GETDNS_RESOLUTION_RECURSING &&
22812656 tls_only_is_in_transports_list(context) == 1)
22822657 return GETDNS_RETURN_BAD_CONTEXT;
23782753 }
23792754
23802755 struct getdns_bindata *
2381 _getdns_bindata_copy(struct mem_funcs *mfs,
2382 const struct getdns_bindata *src)
2756 _getdns_bindata_copy(struct mem_funcs *mfs, size_t size, const uint8_t *data)
23832757 {
23842758 /* Don't know why, but nodata allows
23852759 * empty bindatas with the python bindings
23872761 static uint8_t nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
23882762 struct getdns_bindata *dst;
23892763
2390 if (!src)
2391 return NULL;
2392
23932764 if (!(dst = GETDNS_MALLOC(*mfs, struct getdns_bindata)))
23942765 return NULL;
23952766
2396 dst->size = src->size;
2397 if ((dst->size = src->size)) {
2398 dst->data = GETDNS_XMALLOC(*mfs, uint8_t, src->size);
2767 if ((dst->size = size)) {
2768 dst->data = GETDNS_XMALLOC(*mfs, uint8_t, size);
23992769 if (!dst->data) {
24002770 GETDNS_FREE(*mfs, dst);
24012771 return NULL;
24022772 }
2403 (void) memcpy(dst->data, src->data, src->size);
2773 (void) memcpy(dst->data, data, size);
24042774 } else {
24052775 dst->data = nodata;
24062776 }
25402910 }
25412911
25422912 static getdns_dict*
2543 _get_context_settings(getdns_context* context) {
2913 _get_context_settings(getdns_context* context)
2914 {
25442915 getdns_return_t r = GETDNS_RETURN_GOOD;
25452916 getdns_dict* result = getdns_dict_create_with_context(context);
2917 getdns_list *list;
2918
25462919 if (!result) {
25472920 return NULL;
25482921 }
25592932 r |= getdns_dict_set_int(result, "edns_do_bit", context->edns_do_bit);
25602933 r |= getdns_dict_set_int(result, "append_name", context->append_name);
25612934 /* list fields */
2562 if (context->suffix) r |= getdns_dict_set_list(result, "suffix", context->suffix);
2563 if (context->upstreams && context->upstreams->count > 0) {
2564 size_t i;
2565 getdns_upstream *upstream;
2566 getdns_list *upstreams =
2567 getdns_list_create_with_context(context);
2568
2569 for (i = 0; i < context->upstreams->count;) {
2570 size_t j;
2571 getdns_dict *d;
2572 upstream = &context->upstreams->upstreams[i];
2573 d = sockaddr_dict(context,
2574 (struct sockaddr *)&upstream->addr);
2575 for ( j = 1, i++
2576 ; j < GETDNS_UPSTREAM_TRANSPORTS &&
2577 i < context->upstreams->count
2578 ; j++, i++) {
2579
2580 upstream = &context->upstreams->upstreams[i];
2581 if (upstream->transport != GETDNS_TRANSPORT_TLS)
2582 continue;
2583 if (upstream_port(upstream) != getdns_port_array[j])
2584 continue;
2585 (void) getdns_dict_set_int(d, "tls_port",
2586 (uint32_t) upstream_port(upstream));
2587 }
2588 r |= _getdns_list_append_dict(upstreams, d);
2589 getdns_dict_destroy(d);
2590 }
2935 if (!getdns_context_get_suffix(context, &list)) {
2936 r |= getdns_dict_set_list(result, "suffix", list);
2937 getdns_list_destroy(list);
2938 }
2939 if (!getdns_context_get_upstream_recursive_servers(context, &list)) {
25912940 r |= getdns_dict_set_list(result, "upstream_recursive_servers",
2592 upstreams);
2593 getdns_list_destroy(upstreams);
2941 list);
2942 getdns_list_destroy(list);
25942943 }
25952944 if (context->dns_transport_count > 0) {
25962945 /* create a namespace list */
28213170 else
28223171 return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
28233172 }
2824 if (transports[0] == GETDNS_TRANSPORT_STARTTLS) {
2825 if (count == 2 && transports[1] == GETDNS_TRANSPORT_TCP)
2826 *value = GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN;
2827 else
2828 return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
2829 }
28303173 return GETDNS_RETURN_GOOD;
28313174 }
28323175
28833226 }
28843227
28853228 getdns_return_t
2886 getdns_context_get_follow_redirects(getdns_context *context,
2887 getdns_redirects_t* value) {
2888 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
2889 RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
2890 *value = context->follow_redirects;
2891 return GETDNS_RETURN_GOOD;
3229 getdns_context_get_follow_redirects(
3230 getdns_context *context, getdns_redirects_t* value)
3231 {
3232 if (!context || !value)
3233 return GETDNS_RETURN_INVALID_PARAMETER;
3234 *value = context->follow_redirects;
3235 return GETDNS_RETURN_NOT_IMPLEMENTED;
28923236 }
28933237
28943238 getdns_return_t
28973241 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
28983242 RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
28993243 *value = NULL;
2900 if (context->dns_root_servers) {
3244 if (context->dns_root_servers)
29013245 return _getdns_list_copy(context->dns_root_servers, value);
2902 }
29033246 return GETDNS_RETURN_GOOD;
29043247 }
29053248
29133256 }
29143257
29153258 getdns_return_t
2916 getdns_context_get_suffix(getdns_context *context, getdns_list **value) {
2917 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
2918 RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
2919 *value = NULL;
2920 if (context->suffix) {
2921 return _getdns_list_copy(context->suffix, value);
2922 }
2923 return GETDNS_RETURN_GOOD;
3259 getdns_context_get_suffix(getdns_context *context, getdns_list **value)
3260 {
3261 size_t dname_len;
3262 const uint8_t *dname;
3263 char name[1024];
3264 getdns_return_t r = GETDNS_RETURN_GOOD;
3265 getdns_list *list;
3266
3267 if (!context || !value)
3268 return GETDNS_RETURN_INVALID_PARAMETER;
3269
3270 if (!(list = getdns_list_create_with_context(context)))
3271 return GETDNS_RETURN_MEMORY_ERROR;
3272
3273 assert(context->suffixes);
3274 dname_len = context->suffixes[0];
3275 dname = context->suffixes + 1;
3276 while (dname_len && *dname) {
3277 if (! gldns_wire2str_dname_buf((UNCONST_UINT8_p)
3278 dname, dname_len, name, sizeof(name))) {
3279 r = GETDNS_RETURN_GENERIC_ERROR;
3280 break;
3281 }
3282 if ((r = _getdns_list_append_const_bindata(
3283 list, strlen(name) + 1, name)))
3284 break;
3285 dname += dname_len;
3286 dname_len = *dname++;
3287 }
3288 if (r)
3289 getdns_list_destroy(list);
3290 else
3291 *value = list;
3292
3293 return GETDNS_RETURN_GOOD;
29243294 }
29253295
29263296 getdns_return_t
29543324
29553325 getdns_return_t
29563326 getdns_context_get_upstream_recursive_servers(getdns_context *context,
2957 getdns_list **upstream_list) {
2958 RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
2959 RETURN_IF_NULL(upstream_list, GETDNS_RETURN_INVALID_PARAMETER);
2960 *upstream_list = NULL;
2961 if (context->upstreams && context->upstreams->count > 0) {
2962 getdns_return_t r = GETDNS_RETURN_GOOD;
2963 size_t i;
2964 getdns_upstream *upstream;
2965 getdns_list *upstreams = getdns_list_create();
2966 for (i = 0; i < context->upstreams->count;) {
3327 getdns_list **upstreams_r)
3328 {
3329 size_t i;
3330 getdns_list *upstreams;
3331 getdns_return_t r;
3332
3333 if (!context || !upstreams_r)
3334 return GETDNS_RETURN_INVALID_PARAMETER;
3335
3336 if (!(upstreams = getdns_list_create_with_context(context)))
3337 return GETDNS_RETURN_MEMORY_ERROR;
3338
3339 if (!context->upstreams || context->upstreams->count == 0) {
3340 *upstreams_r = upstreams;
3341 return GETDNS_RETURN_GOOD;
3342 }
3343 r = GETDNS_RETURN_GOOD;
3344 i = 0;
3345 while (!r && i < context->upstreams->count) {
29673346 size_t j;
29683347 getdns_dict *d;
2969 upstream = &context->upstreams->upstreams[i];
2970 d = sockaddr_dict(context, (struct sockaddr *)&upstream->addr);
3348 getdns_upstream *upstream = &context->upstreams->upstreams[i];
3349 getdns_bindata bindata;
3350 const getdns_tsig_info *tsig_info;
3351
3352 if (!(d =
3353 sockaddr_dict(context, (struct sockaddr*)&upstream->addr))) {
3354 r = GETDNS_RETURN_MEMORY_ERROR;
3355 break;
3356 }
3357 if (upstream->tsig_alg) {
3358 tsig_info = _getdns_get_tsig_info(upstream->tsig_alg);
3359
3360 if ((r = _getdns_dict_set_const_bindata(
3361 d, "tsig_algorithm",
3362 tsig_info->dname_len, tsig_info->dname)))
3363 break;
3364
3365 if (upstream->tsig_dname_len) {
3366 bindata.data = upstream->tsig_dname;
3367 bindata.size = upstream->tsig_dname_len;
3368 if ((r = getdns_dict_set_bindata(
3369 d, "tsig_name", &bindata)))
3370 break;
3371 }
3372 if (upstream->tsig_size) {
3373 bindata.data = upstream->tsig_key;
3374 bindata.size = upstream->tsig_size;
3375 if ((r = getdns_dict_set_bindata(
3376 d, "tsig_secret", &bindata)))
3377 break;
3378 }
3379 }
29713380 for ( j = 1, i++
29723381 ; j < GETDNS_UPSTREAM_TRANSPORTS &&
29733382 i < context->upstreams->count
29743383 ; j++, i++) {
29753384
29763385 upstream = &context->upstreams->upstreams[i];
2977 if (upstream->transport != GETDNS_TRANSPORT_TLS)
2978 continue;
2979 if (upstream_port(upstream) != getdns_port_array[j])
2980 continue;
2981 (void) getdns_dict_set_int(d, "tls_port",
2982 (uint32_t) upstream_port(upstream));
3386
3387 if (upstream->transport == GETDNS_TRANSPORT_UDP &&
3388 upstream_port(upstream) != getdns_port_array[j] &&
3389 (r = getdns_dict_set_int(d, "port",
3390 (uint32_t)upstream_port(upstream))))
3391 break;
3392
3393 if (upstream->transport == GETDNS_TRANSPORT_TLS) {
3394 if (upstream_port(upstream) == getdns_port_array[j])
3395 (void) getdns_dict_set_int(d, "tls_port",
3396 (uint32_t) upstream_port(upstream));
3397 if (upstream->tls_pubkey_pinset) {
3398 getdns_list *pins = NULL;
3399 if (_getdns_get_pubkey_pinset_list(context,
3400 upstream->tls_pubkey_pinset,
3401 &pins) == GETDNS_RETURN_GOOD)
3402 (void) getdns_dict_set_list(d, "tls_pubkey_pinset", pins);
3403 getdns_list_destroy(pins);
3404 }
3405 }
29833406 }
2984 r |= _getdns_list_append_dict(upstreams, d);
3407 if (!r)
3408 r = _getdns_list_append_dict(upstreams, d);
29853409 getdns_dict_destroy(d);
29863410 }
2987 if (r != GETDNS_RETURN_GOOD) {
2988 getdns_list_destroy(upstreams);
2989 return GETDNS_RETURN_MEMORY_ERROR;
2990 }
2991 *upstream_list = upstreams;
2992 }
2993 return GETDNS_RETURN_GOOD;
3411 if (r)
3412 getdns_list_destroy(upstreams);
3413 else
3414 *upstreams_r = upstreams;
3415 return r;
29943416 }
29953417
29963418 getdns_return_t
7878 GETDNS_HS_FAILED
7979 } getdns_tls_hs_state_t;
8080
81 typedef enum getdns_tsig_algo {
82 GETDNS_NO_TSIG = 0, /* Do not use tsig */
83 GETDNS_HMAC_MD5 = 1, /* 128 bits */
84 GETDNS_GSS_TSIG = 2, /* Not supported */
85 GETDNS_HMAC_SHA1 = 3, /* 160 bits */
86 GETDNS_HMAC_SHA224 = 4,
87 GETDNS_HMAC_SHA256 = 5,
88 GETDNS_HMAC_SHA384 = 6,
89 GETDNS_HMAC_SHA512 = 7
90 } getdns_tsig_algo;
91
92 typedef struct getdns_tsig_info {
93 getdns_tsig_algo alg;
94 const char *name;
95 size_t strlen_name;
96 const uint8_t *dname;
97 size_t dname_len;
98 size_t min_size; /* in # octets */
99 size_t max_size; /* Actual size in # octets */
100 } getdns_tsig_info;
101
102 const getdns_tsig_info *_getdns_get_tsig_info(getdns_tsig_algo tsig_alg);
103
104 /* for doing public key pinning of TLS-capable upstreams: */
105 typedef struct sha256_pin {
106 char pin[SHA256_DIGEST_LENGTH];
107 struct sha256_pin *next;
108 } sha256_pin_t;
109
81110 typedef struct getdns_upstream {
82111 /* backpointer to containing upstreams structure */
83112 struct getdns_upstreams *upstreams;
88117 /* How is this upstream doing? */
89118 size_t writes_done;
90119 size_t responses_received;
120 uint64_t keepalive_timeout;
91121 int to_retry;
92122 int back_off;
93123
96126 getdns_transport_list_t transport;
97127 SSL* tls_obj;
98128 getdns_tls_hs_state_t tls_hs_state;
99 getdns_dns_req * starttls_req;
100129 getdns_eventloop_event event;
101130 getdns_eventloop *loop;
102131 getdns_tcp_state tcp;
103132 char tls_auth_name[256];
104133 size_t tls_auth_failed;
134 sha256_pin_t *tls_pubkey_pinset;
105135
106136 /* Pipelining of TCP network requests */
107137 getdns_network_req *write_queue;
118148 unsigned has_prev_client_cookie : 1;
119149 unsigned has_server_cookie : 1;
120150 unsigned server_cookie_len : 5;
151 unsigned tls_fallback_ok : 1;
152
153 /* TSIG */
154 uint8_t tsig_dname[256];
155 size_t tsig_dname_len;
156 size_t tsig_size;
157 uint8_t tsig_key[256];
158 getdns_tsig_algo tsig_alg;
121159
122160 } getdns_upstream;
123161
137175 uint64_t timeout;
138176 uint64_t idle_timeout;
139177 getdns_redirects_t follow_redirects;
140 struct getdns_list *dns_root_servers;
178 getdns_list *dns_root_servers;
179 char root_servers_fn[FILENAME_MAX];
141180 getdns_append_name_t append_name;
142 struct getdns_list *suffix;
181 /* Suffix buffer containing a list of (length byte | dname) where
182 * length bytes contains the length of the following dname.
183 * The last dname should be the zero byte.
184 */
185 const uint8_t *suffixes;
186 /* Length of all suffixes in the suffix buffer */
187 size_t suffixes_len;
143188 uint8_t *trust_anchors;
144189 size_t trust_anchors_len;
145190 getdns_upstreams *upstreams;
239284 char *_getdns_strdup(const struct mem_funcs *mfs, const char *str);
240285
241286 struct getdns_bindata *_getdns_bindata_copy(
242 struct mem_funcs *mfs,
243 const struct getdns_bindata *src);
287 struct mem_funcs *mfs, size_t size, const uint8_t *data);
244288
245289 void _getdns_bindata_destroy(
246290 struct mem_funcs *mfs,
3333
3434 #include <stdio.h>
3535 #include <string.h>
36 #include <arpa/inet.h>
3736 #include <locale.h>
3837 #include "config.h"
38 #ifndef USE_WINSOCK
39 #include <arpa/inet.h>
40 #endif
3941 #ifdef HAVE_LIBIDN
4042 #include <stringprep.h>
4143 #include <idna.h>
4547 #include "util-internal.h"
4648 #include "gldns/wire2str.h"
4749 #include "gldns/str2wire.h"
50 #include "dict.h"
51 #include "list.h"
52 #include "convert.h"
4853
4954 /* stuff to make it compile pedantically */
5055 #define UNUSED_PARAM(x) ((void)(x))
218223 return GETDNS_RETURN_GOOD;
219224 } /* getdns_strerror */
220225
226
227 /* --------------------- rr_dict, wire, str conversions --------------------- */
228
229
230 getdns_return_t
231 getdns_rr_dict2wire(
232 const getdns_dict *rr_dict, uint8_t **wire, size_t *wire_sz)
233 {
234 uint8_t buf_spc[4096], *buf;
235 size_t buf_len = sizeof(buf_spc);
236 getdns_return_t r = getdns_rr_dict2wire_buf(
237 rr_dict, buf_spc, &buf_len);
238
239 if (r != GETDNS_RETURN_GOOD && r != GETDNS_RETURN_NEED_MORE_SPACE)
240 return r;
241
242 if (!(buf = malloc(buf_len)))
243 return GETDNS_RETURN_MEMORY_ERROR;
244
245 if (!r)
246 memcpy(buf, buf_spc, buf_len);
247
248 else if ((r = getdns_rr_dict2wire_buf(rr_dict, buf, &buf_len))) {
249 free(buf);
250 return r;
251 }
252 *wire = buf;
253 *wire_sz = buf_len;
254 return GETDNS_RETURN_GOOD;
255 }
256
257 getdns_return_t
258 getdns_rr_dict2wire_buf(
259 const getdns_dict *rr_dict, uint8_t *wire, size_t *wire_sz)
260 {
261 int my_wire_sz;
262 getdns_return_t r;
263
264 if (!wire_sz)
265 return GETDNS_RETURN_INVALID_PARAMETER;
266 else
267 my_wire_sz = *wire_sz;
268
269 r = getdns_rr_dict2wire_scan(rr_dict, &wire, &my_wire_sz);
270 if (r == GETDNS_RETURN_GOOD || r == GETDNS_RETURN_NEED_MORE_SPACE)
271 *wire_sz -= my_wire_sz;
272 return r;
273 }
274
275 getdns_return_t
276 getdns_rr_dict2wire_scan(
277 const getdns_dict *rr_dict, uint8_t **wire, int *wire_sz)
278 {
279 getdns_return_t r;
280 gldns_buffer gbuf;
281
282 if (!rr_dict || !wire || !*wire || !wire_sz)
283 return GETDNS_RETURN_INVALID_PARAMETER;
284
285
286 gldns_buffer_init_frm_data(&gbuf, *wire, *wire_sz);
287 if ((r = _getdns_rr_dict2wire(rr_dict, &gbuf)))
288 return r;
289
290 if (gldns_buffer_position(&gbuf) == 0)
291 return GETDNS_RETURN_GENERIC_ERROR;
292
293 *wire += gldns_buffer_position(&gbuf);
294 *wire_sz -= gldns_buffer_position(&gbuf);
295 if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
296 return GETDNS_RETURN_NEED_MORE_SPACE;
297 else
298 return GETDNS_RETURN_GOOD;
299 }
300
301 static struct mem_funcs _getdns_plain_mem_funcs = {
302 MF_PLAIN, .mf.pln = { malloc, realloc, free }
303 };
304
305 getdns_return_t
306 _getdns_wire2rr_dict(struct mem_funcs *mf,
307 const uint8_t *wire, size_t wire_len, getdns_dict **rr_dict)
308 {
309 return _getdns_wire2rr_dict_scan(mf, &wire, &wire_len, rr_dict);
310 }
311 getdns_return_t
312 getdns_wire2rr_dict(
313 const uint8_t *wire, size_t wire_len, getdns_dict **rr_dict)
314 {
315 return _getdns_wire2rr_dict(
316 &_getdns_plain_mem_funcs, wire, wire_len, rr_dict);
317 }
318
319 getdns_return_t
320 _getdns_wire2rr_dict_buf(struct mem_funcs *mf,
321 const uint8_t *wire, size_t *wire_len, getdns_dict **rr_dict)
322 {
323 size_t my_wire_len;
324 getdns_return_t r;
325
326 if (!wire_len)
327 return GETDNS_RETURN_INVALID_PARAMETER;
328 else
329 my_wire_len = *wire_len;
330
331 if ((r = _getdns_wire2rr_dict_scan(mf, &wire, &my_wire_len, rr_dict)))
332 return r;
333
334 *wire_len -= my_wire_len;
335 return GETDNS_RETURN_GOOD;
336 }
337 getdns_return_t
338 getdns_wire2rr_dict_buf(
339 const uint8_t *wire, size_t *wire_len, getdns_dict **rr_dict)
340 {
341 return _getdns_wire2rr_dict_buf(
342 &_getdns_plain_mem_funcs, wire, wire_len, rr_dict);
343 }
344
345 getdns_return_t
346 _getdns_wire2rr_dict_scan(struct mem_funcs *mf,
347 const uint8_t **wire, size_t *wire_len, getdns_dict **rr_dict)
348 {
349 _getdns_rr_iter rr_iter_spc, *rr_iter;
350
351 if (!wire || !*wire || !wire_len || !rr_dict)
352 return GETDNS_RETURN_INVALID_PARAMETER;
353
354 if (!(rr_iter = _getdns_single_rr_iter_init(
355 &rr_iter_spc, *wire, *wire_len)))
356 return GETDNS_RETURN_GENERIC_ERROR;
357
358 if (!(*rr_dict = _getdns_rr_iter2rr_dict(mf, rr_iter)))
359 return GETDNS_RETURN_MEMORY_ERROR;
360
361 *wire_len -= (rr_iter->nxt - rr_iter->pos);
362 *wire = rr_iter->nxt;
363
364 return GETDNS_RETURN_GOOD;
365 }
366 getdns_return_t
367 getdns_wire2rr_dict_scan(
368 const uint8_t **wire, size_t *wire_len, getdns_dict **rr_dict)
369 {
370 return _getdns_wire2rr_dict_scan(
371 &_getdns_plain_mem_funcs, wire, wire_len, rr_dict);
372 }
373
374
375 getdns_return_t
376 getdns_rr_dict2str(
377 const getdns_dict *rr_dict, char **str)
378 {
379 char buf_spc[4096], *buf;
380 size_t buf_len = sizeof(buf_spc) - 1;
381 getdns_return_t r = getdns_rr_dict2str_buf(
382 rr_dict, buf_spc, &buf_len);
383
384 if (r != GETDNS_RETURN_GOOD && r != GETDNS_RETURN_NEED_MORE_SPACE)
385 return r;
386
387 buf_len += 1;
388 if (!(buf = malloc(buf_len)))
389 return GETDNS_RETURN_MEMORY_ERROR;
390
391 if (!r)
392 memcpy(buf, buf_spc, buf_len);
393
394 else if ((r = getdns_rr_dict2str_buf(rr_dict, buf, &buf_len))) {
395 free(buf);
396 return r;
397 }
398 *str = buf;
399 return GETDNS_RETURN_GOOD;
400 }
401
402 getdns_return_t
403 getdns_rr_dict2str_buf(
404 const getdns_dict *rr_dict, char *str, size_t *str_len)
405 {
406 int my_str_len;
407 getdns_return_t r;
408
409 if (!str_len)
410 return GETDNS_RETURN_INVALID_PARAMETER;
411 else
412 my_str_len = *str_len;
413
414 r = getdns_rr_dict2str_scan(rr_dict, &str, &my_str_len);
415 if (r == GETDNS_RETURN_GOOD || r == GETDNS_RETURN_NEED_MORE_SPACE)
416 *str_len -= my_str_len;
417 return r;
418
419 }
420
421 getdns_return_t
422 getdns_rr_dict2str_scan(
423 const getdns_dict *rr_dict, char **str, int *str_len)
424 {
425 getdns_return_t r;
426 gldns_buffer gbuf;
427 uint8_t buf_spc[4096], *buf = buf_spc, *scan_buf;
428 size_t sz, scan_sz;
429 int prev_str_len;
430 char *prev_str;
431 int sz_needed;
432
433 if (!rr_dict || !str || !*str || !str_len)
434 return GETDNS_RETURN_INVALID_PARAMETER;
435
436 gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc));
437 r = _getdns_rr_dict2wire(rr_dict, &gbuf);
438 if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) {
439 if (!(buf = GETDNS_XMALLOC(
440 rr_dict->mf, uint8_t, (sz = gldns_buffer_position(&gbuf))))) {
441 return GETDNS_RETURN_MEMORY_ERROR;
442 }
443 gldns_buffer_init_frm_data(&gbuf, buf, sz);
444 r = _getdns_rr_dict2wire(rr_dict, &gbuf);
445 }
446 if (r) {
447 if (buf != buf_spc)
448 GETDNS_FREE(rr_dict->mf, buf);
449 return r;
450 }
451 scan_buf = gldns_buffer_begin(&gbuf);
452 scan_sz = gldns_buffer_position(&gbuf);
453 prev_str = *str;
454 prev_str_len = *str_len;
455 sz = (size_t)*str_len;
456 sz_needed = gldns_wire2str_rr_scan(
457 &scan_buf, &scan_sz, str, &sz, NULL, 0);
458
459 if (sz_needed > prev_str_len) {
460 *str = prev_str + sz_needed;
461 *str_len = prev_str_len - sz_needed;
462 r = GETDNS_RETURN_NEED_MORE_SPACE;
463 } else {
464 *str_len = sz;
465 **str = 0;
466 }
467 if (buf != buf_spc)
468 GETDNS_FREE(rr_dict->mf, buf);
469 return r;
470 }
471
472
473 getdns_return_t
474 _getdns_str2rr_dict(struct mem_funcs *mf,
475 const char *str, getdns_dict **rr_dict, const char *origin, uint32_t default_ttl)
476 {
477 uint8_t wire_spc[4096], *wire = wire_spc;
478 uint8_t origin_spc[256], *origin_wf;
479 size_t origin_len = sizeof(origin_spc), wire_len = sizeof(wire_spc);
480 int e;
481 getdns_return_t r;
482
483 if (!str || !rr_dict)
484 return GETDNS_RETURN_INVALID_PARAMETER;
485
486 if (!origin)
487 origin_wf = NULL;
488
489 else if (gldns_str2wire_dname_buf(origin, origin_spc, &origin_len))
490 return GETDNS_RETURN_GENERIC_ERROR;
491 else
492 origin_wf = origin_spc;
493
494 e = gldns_str2wire_rr_buf(str, wire, &wire_len,
495 NULL, default_ttl, origin_wf, origin_len, NULL, 0);
496 if (GLDNS_WIREPARSE_ERROR(e) == GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL) {
497
498 if (!(wire = GETDNS_XMALLOC(
499 *mf, uint8_t, (wire_len = GLDNS_RR_BUF_SIZE))))
500 return GETDNS_RETURN_MEMORY_ERROR;
501 e = gldns_str2wire_rr_buf(str, wire, &wire_len,
502 NULL, default_ttl, origin_wf, origin_len, NULL, 0);
503 }
504 if (e) {
505 if (wire != wire_spc)
506 GETDNS_FREE(*mf, wire);
507 return GETDNS_RETURN_GENERIC_ERROR;
508 }
509 r = _getdns_wire2rr_dict(mf, wire, wire_len, rr_dict);
510 if (wire != wire_spc)
511 GETDNS_FREE(*mf, wire);
512 return r;
513 }
514 getdns_return_t
515 getdns_str2rr_dict(
516 const char *str, getdns_dict **rr_dict, const char *origin, uint32_t default_ttl)
517 {
518 return _getdns_str2rr_dict(
519 &_getdns_plain_mem_funcs, str, rr_dict, origin, default_ttl);
520 }
521
522
523 getdns_return_t
524 _getdns_fp2rr_list(struct mem_funcs *mf,
525 FILE *in, getdns_list **rr_list, const char *origin, uint32_t default_ttl)
526 {
527 struct gldns_file_parse_state pst;
528 getdns_list *rrs;
529 getdns_return_t r = GETDNS_RETURN_GOOD;
530 uint8_t *rr;
531 size_t len, dname_len;
532 getdns_dict *rr_dict;
533
534 if (!in || !rr_list)
535 return GETDNS_RETURN_INVALID_PARAMETER;
536
537 if (!origin) {
538 *pst.origin = 0;
539 pst.origin_len = 1;
540
541 } else if (gldns_str2wire_dname_buf(origin,pst.origin,&pst.origin_len))
542 return GETDNS_RETURN_GENERIC_ERROR;
543
544 *pst.prev_rr = 0;
545 pst.prev_rr_len = 1;
546 pst.default_ttl = default_ttl;
547 pst.lineno = 1;
548
549 if (!(rrs = _getdns_list_create_with_mf(mf)))
550 return GETDNS_RETURN_MEMORY_ERROR;
551
552
553 if (!(rr = GETDNS_XMALLOC(*mf, uint8_t, GLDNS_RR_BUF_SIZE)))
554 r = GETDNS_RETURN_MEMORY_ERROR;
555
556 else while (r == GETDNS_RETURN_GOOD && !feof(in)) {
557 len = GLDNS_RR_BUF_SIZE;
558 dname_len = 0;
559 if (gldns_fp2wire_rr_buf(in, rr, &len, &dname_len, &pst))
560 break;
561 if (dname_len && dname_len < sizeof(pst.prev_rr)) {
562 memcpy(pst.prev_rr, rr, dname_len);
563 pst.prev_rr_len = dname_len;
564 }
565 if (len == 0)
566 continue;
567 if ((r = _getdns_wire2rr_dict(mf, rr, len, &rr_dict)))
568 break;
569 r = _getdns_list_append_dict(rrs, rr_dict);
570 getdns_dict_destroy(rr_dict);
571 }
572 if (rr)
573 GETDNS_FREE(*mf, rr);
574 if (r)
575 getdns_list_destroy(rrs);
576 else
577 *rr_list = rrs;
578 return r;
579 }
580
581 getdns_return_t
582 getdns_fp2rr_list(
583 FILE *in, getdns_list **rr_list, const char *origin, uint32_t default_ttl)
584 {
585 return _getdns_fp2rr_list(
586 &_getdns_plain_mem_funcs, in, rr_list, origin, default_ttl);
587 }
588
221589 /* convert.c */
0 /**
1 *
2 * \file convert.h
3 * @brief getdns label conversion functions
4 *
5 */
6
7 /*
8 * Copyright (c) 2013, NLnet Labs, Verisign, Inc.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * * Neither the names of the copyright holders nor the
19 * names of its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #ifndef _GETDNS_CONVERT_H_
35 #define _GETDNS_CONVERT_H_
36
37 #include "types-internal.h"
38 #include <stdio.h>
39
40 getdns_return_t _getdns_wire2rr_dict(struct mem_funcs *mf,
41 const uint8_t *wire, size_t wire_len, getdns_dict **rr_dict);
42
43 getdns_return_t _getdns_wire2rr_dict_buf(struct mem_funcs *mf,
44 const uint8_t *wire, size_t *wire_len, getdns_dict **rr_dict);
45
46 getdns_return_t _getdns_wire2rr_dict_scan(struct mem_funcs *mf,
47 const uint8_t **wire, size_t *wire_len, getdns_dict **rr_dict);
48
49 getdns_return_t _getdns_str2rr_dict(struct mem_funcs *mf, const char *str,
50 getdns_dict **rr_dict, const char *origin, uint32_t default_ttl);
51
52 getdns_return_t _getdns_fp2rr_list(struct mem_funcs *mf, FILE *in,
53 getdns_list **rr_list, const char *origin, uint32_t default_ttl);
54
55 #endif
56 /* convert.h */
0 /**
1 *
2 * \file debug.h
3 * /brief Macro's for debugging
4 *
5 */
6
7 /*
8 * Copyright (c) 2015, NLnet Labs, Verisign, Inc.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * * Neither the names of the copyright holders nor the
19 * names of its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #ifndef DEBUG_H
35 #define DEBUG_H
36
37 #include "config.h"
38
39 #define DEBUG_ON(...) do { \
40 struct timeval tv; \
41 struct tm tm; \
42 char buf[10]; \
43 \
44 gettimeofday(&tv, NULL); \
45 gmtime_r(&tv.tv_sec, &tm); \
46 strftime(buf, 10, "%T", &tm); \
47 fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
48 fprintf(stderr, __VA_ARGS__); \
49 } while (0)
50
51 #define DEBUG_NL(...) do { \
52 struct timeval tv; \
53 struct tm tm; \
54 char buf[10]; \
55 \
56 gettimeofday(&tv, NULL); \
57 gmtime_r(&tv.tv_sec, &tm); \
58 strftime(buf, 10, "%T", &tm); \
59 fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
60 fprintf(stderr, __VA_ARGS__); \
61 fprintf(stderr, "\n"); \
62 } while (0)
63
64
65 #define DEBUG_OFF(...) do {} while (0)
66
67 #if defined(SCHED_DEBUG) && SCHED_DEBUG
68 #include <time.h>
69 #define DEBUG_SCHED(...) DEBUG_ON(__VA_ARGS__)
70 #else
71 #define DEBUG_SCHED(...) DEBUG_OFF(__VA_ARGS__)
72 #endif
73
74 #if defined(STUB_DEBUG) && STUB_DEBUG
75 #include <time.h>
76 #define DEBUG_STUB(...) DEBUG_ON(__VA_ARGS__)
77 #else
78 #define DEBUG_STUB(...) DEBUG_OFF(__VA_ARGS__)
79 #endif
80
81 #if defined(SEC_DEBUG) && SEC_DEBUG
82 #include <time.h>
83 #define DEBUG_SEC(...) DEBUG_ON(__VA_ARGS__)
84 #else
85 #define DEBUG_SEC(...) DEBUG_OFF(__VA_ARGS__)
86 #endif
87
88 #endif
89 /* debug.h */
3434 */
3535
3636 #include <ctype.h>
37 #include "config.h"
38 #ifndef USE_WINSOCK
3739 #include <sys/types.h>
3840 #include <sys/socket.h>
3941 #include <netinet/in.h>
4042 #include <arpa/inet.h>
43 #endif
4144
4245 #include "types-internal.h"
4346 #include "util-internal.h"
276279
277280 RBTREE_FOR(item, struct getdns_dict_item *,
278281 (_getdns_rbtree_t *)&(dict->root)) {
279 _getdns_list_append_string(*answer, item->node.key);
282 _getdns_list_append_const_bindata(*answer,
283 strlen(item->node.key) + 1, item->node.key);
280284 }
281285 return GETDNS_RETURN_GOOD;
282286 } /* getdns_dict_get_names */
573577
574578 /*---------------------------------------- getdns_dict_set_bindata */
575579 getdns_return_t
576 getdns_dict_set_bindata(
577 getdns_dict *dict, const char *name, const getdns_bindata *child_bindata)
580 _getdns_dict_set_const_bindata(
581 getdns_dict *dict, const char *name, size_t size, const void *data)
578582 {
579583 getdns_item *item;
580584 getdns_bindata *newbindata;
581585 getdns_return_t r;
582586
583 if (!dict || !name || !child_bindata)
587 if (!dict || !name)
584588 return GETDNS_RETURN_INVALID_PARAMETER;
585589
586 if (!(newbindata = _getdns_bindata_copy(&dict->mf, child_bindata)))
590 if (!(newbindata = _getdns_bindata_copy(&dict->mf, size, data)))
587591 return GETDNS_RETURN_MEMORY_ERROR;
588592
589593 if ((r = _getdns_dict_find_and_add(dict, name, &item))) {
595599 return GETDNS_RETURN_GOOD;
596600 } /* getdns_dict_set_bindata */
597601
602 getdns_return_t
603 getdns_dict_set_bindata(
604 getdns_dict *dict, const char *name, const getdns_bindata *child_bindata)
605 {
606 return !child_bindata ? GETDNS_RETURN_INVALID_PARAMETER
607 : _getdns_dict_set_const_bindata(
608 dict, name, child_bindata->size, child_bindata->data);
609 }
610
598611 /*---------------------------------------- getdns_dict_set_bindata */
599612 getdns_return_t
600613 getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value)
601614 {
602 getdns_item *item;
603 getdns_bindata *newbindata;
604 getdns_return_t r;
605
606 if (!dict || !name || !value)
607 return GETDNS_RETURN_INVALID_PARAMETER;
608
609 if (!(newbindata = GETDNS_MALLOC(dict->mf, getdns_bindata)))
610 return GETDNS_RETURN_MEMORY_ERROR;
611
612 newbindata->size = strlen(value);
613 if (!(newbindata->data = (void *)_getdns_strdup(&dict->mf, value))) {
614 GETDNS_FREE(dict->mf, newbindata);
615 return GETDNS_RETURN_MEMORY_ERROR;
616 }
617 if ((r = _getdns_dict_find_and_add(dict, name, &item))) {
618 _getdns_bindata_destroy(&dict->mf, newbindata);
619 return r;
620 }
621 item->dtype = t_bindata;
622 item->data.bindata = newbindata;
623 return GETDNS_RETURN_GOOD;
615 return value
616 ? _getdns_dict_set_const_bindata(dict, name, strlen(value), value)
617 : GETDNS_RETURN_INVALID_PARAMETER;
624618 } /* getdns_dict_util_set_dict */
625619
626620 /*---------------------------------------- getdns_dict_set_int */
655649 return spaces + 80 - (indent < 80 ? indent : 0);
656650 } /* getdns_indent */
657651
658 static int
652 int
659653 _getdns_bindata_is_dname(getdns_bindata *bindata)
660654 {
661655 size_t i = 0, n_labels = 0;
662656
663657 while (i < bindata->size && bindata->data[i]) {
658 if (bindata->data[i] & 0xC0) /* Compression pointer! */
659 return 0;
660
664661 i += ((size_t)bindata->data[i]) + 1;
665662 n_labels++;
666663 }
991988 if (!json &&
992989 (strcmp(item->node.key, "answer_type") == 0 ||
993990 strcmp(item->node.key, "dnssec_status") == 0 ||
991 strcmp(item->node.key, "tsig_status") == 0 ||
994992 strcmp(item->node.key, "status") == 0 ||
995993 strcmp(item->node.key, "append_name") == 0 ||
996994 strcmp(item->node.key, "follow_redirects") == 0 ||
10591057 return -1;
10601058 if (getdns_pp_list(buf, indent, item->i.data.list,
10611059 (strcmp(item->node.key, "namespaces") == 0 ||
1062 strcmp(item->node.key, "dns_transport_list") == 0),
1060 strcmp(item->node.key, "dns_transport_list") == 0
1061 || strcmp(item->node.key, "bad_dns") == 0),
10631062 json) < 0)
10641063 return -1;
10651064 break;
7070 getdns_return_t _getdns_dict_find_and_add(
7171 getdns_dict *dict, const char *key, getdns_item **item);
7272
73 /* Return 1 (true) if bindata can be interpreted as an
74 * uncompressed dname.
75 */
76 int _getdns_bindata_is_dname(getdns_bindata *bindata);
77
7378 #endif
7479
7580 /* dict.h */
187187 * "dnssec_return_validation_chain Extension".
188188 */
189189
190 #include "config.h"
191 #include "debug.h"
190192 #include <sys/types.h>
191193 #include <sys/stat.h>
192194 #include <unistd.h>
193195 #include <ctype.h>
194196 #include <openssl/sha.h>
195197 #include "getdns/getdns.h"
196 #include "config.h"
197198 #include "context.h"
198199 #include "util-internal.h"
199200 #include "types-internal.h"
218219 /******************* Frequently Used Utility Functions *********************
219220 *****************************************************************************/
220221
221 inline static size_t _dname_len(uint8_t *name)
222 {
223 uint8_t *p;
222 inline static size_t _dname_len(const uint8_t *name)
223 {
224 const uint8_t *p;
224225 for (p = name; *p; p += *p + 1)
225226 /* pass */
226227 ;
227228 return p - name + 1;
228229 }
229230
230 inline static size_t _dname_label_count(uint8_t *name)
231 inline static size_t _dname_label_count(const uint8_t *name)
231232 {
232233 size_t c;
233234 for (c = 0; *name; name += *name + 1, c++)
266267 return r;
267268 }
268269
269 inline static void _dname_canonicalize(uint8_t *dname)
270 {
271 uint8_t *next_label;
272
273 while (*dname) {
274 next_label = dname + *dname + 1;
275 dname += 1;
276 while (dname < next_label) {
277 *dname = (uint8_t)tolower((unsigned char)*dname);
278 dname++;
279 }
280 }
281 }
270 inline static void _dname_canonicalize(const uint8_t *src, uint8_t *dst)
271 {
272 const uint8_t *next_label;
273
274 while (*src) {
275 next_label = src + *src + 1;
276 *dst++ = *src++;
277 while (src < next_label)
278 *dst++ = (uint8_t)tolower((unsigned char)*src++);
279 }
280 }
281
282 inline static void _dname_canonicalize2(uint8_t *dname)
283 {
284 _dname_canonicalize(dname, dname);
285 }
286
282287
283288 /* Fills the array pointed to by labels (of at least 128 uint8_t * pointers)
284289 * with pointers to labels in given dname in reversed order. So that
293298 * labels[3] will be "www.getdnsapi.net."
294299 * The returned value will be &labels[4]
295300 */
296 static uint8_t **reverse_labels(uint8_t *dname, uint8_t **labels)
301 static const uint8_t **reverse_labels(
302 const uint8_t *dname, const uint8_t **labels)
297303 {
298304 if (*dname)
299305 labels = reverse_labels(dname + *dname + 1, labels);
301307 return labels + 1;
302308 }
303309
304 static uint8_t *dname_shared_parent(uint8_t *left, uint8_t *right)
305 {
306 uint8_t *llabels[128], *rlabels[128], **last_llabel, **last_rlabel,
307 **llabel, **rlabel, *l, *r, sz;
310 static const uint8_t *dname_shared_parent(
311 const uint8_t *left, const uint8_t *right)
312 {
313 const uint8_t *llabels[128], *rlabels[128], **last_llabel, **last_rlabel,
314 **llabel, **rlabel, *l, *r;
315 uint8_t sz;
308316
309317 last_llabel = reverse_labels(left, llabels);
310318 last_rlabel = reverse_labels(right, rlabels);
332340 return llabel[-1];
333341 }
334342
335 static int dname_compare(uint8_t *left, uint8_t *right)
336 {
337 uint8_t *llabels[128], *rlabels[128], **last_llabel, **last_rlabel,
338 **llabel, **rlabel, *l, *r, lsz, rsz;
343 static int dname_compare(const uint8_t *left, const uint8_t *right)
344 {
345 const uint8_t *llabels[128], *rlabels[128], **last_llabel, **last_rlabel,
346 **llabel, **rlabel, *l, *r;
347 uint8_t lsz, rsz;
339348
340349 last_llabel = reverse_labels(left, llabels);
341350 last_rlabel = reverse_labels(right, rlabels);
372381
373382 static int bitmap_has_type(_getdns_rdf_iter *bitmap, uint16_t rr_type)
374383 {
375 uint8_t *dptr, *dend;
384 const uint8_t *dptr, *dend;
376385 uint8_t window = rr_type >> 8;
377386 uint8_t subtype = rr_type & 0xFF;
378387
396405 {
397406 char str_spc[8192], *str = str_spc;
398407 size_t str_len = sizeof(str_spc);
399 uint8_t *data = rr->pos;
408 const uint8_t *data = rr->pos;
400409 size_t data_len = rr->nxt - rr->pos;
401410
402411 if (!rr || !rr->pos) {
404413 return;
405414 }
406415 (void) gldns_wire2str_rr_scan(
407 &data, &data_len, &str, &str_len, rr->pkt, rr->pkt_end - rr->pkt);
416 (UNCONST_UINT8_p *) &data, &data_len, &str, &str_len,
417 (UNCONST_UINT8_p) rr->pkt, rr->pkt_end - rr->pkt);
408418 DEBUG_SEC("%s%s", msg, str_spc);
409419 }
410 inline static void debug_sec_print_dname(const char *msg, uint8_t *label)
420 inline static void debug_sec_print_dname(const char *msg, const uint8_t *label)
411421 {
412422 char str[1024];
413423
414 if (label && gldns_wire2str_dname_buf(label, 256, str, sizeof(str)))
424 if (label && gldns_wire2str_dname_buf(
425 (UNCONST_UINT8_p)label, 256, str, sizeof(str)))
415426 DEBUG_SEC("%s%s\n", msg, str);
416427 else
417428 DEBUG_SEC("%s<nil>\n", msg);
418 }
419 inline static void debug_sec_print_pkt(
420 const char *msg, uint8_t *pkt, size_t pkt_len)
421 {
422 char *str;
423 DEBUG_SEC("%s%s\n", msg, (str = gldns_wire2str_pkt(pkt, pkt_len)));
424 if (str) free(str);
425429 }
426430 #else
427431 #define debug_sec_print_rr(...) DEBUG_OFF(__VA_ARGS__)
441445 { return rr->rr_type + 4 <= rr->nxt ? gldns_read_uint16(rr->rr_type + 2) : 0; }
442446
443447 /* Utility function to compare owner name of rr with name */
444 static int rr_owner_equal(_getdns_rr_iter *rr, uint8_t *name)
445 {
446 uint8_t owner_spc[256], *owner;
448 static int rr_owner_equal(_getdns_rr_iter *rr, const uint8_t *name)
449 {
450 uint8_t owner_spc[256];
451 const uint8_t *owner;
447452 size_t owner_len = sizeof(owner_spc);
448453
449454 return (owner = _getdns_owner_if_or_as_decompressed(rr, owner_spc
469474
470475 /* Filter that only iterates over RRs with a certain name/class/type */
471476 static _getdns_rr_iter *rr_iter_name_class_type(_getdns_rr_iter *rr,
472 uint8_t *name, uint16_t rr_class, uint16_t rr_type)
477 const uint8_t *name, uint16_t rr_class, uint16_t rr_type)
473478 {
474479 while (rr_iter_ansauth(rr) && !(
475480 rr_iter_type(rr) == rr_type &&
483488
484489 /* Filter that only iterates over RRs that do not have a name/class/type */
485490 static _getdns_rr_iter *rr_iter_not_name_class_type(_getdns_rr_iter *rr,
486 uint8_t *name, uint16_t rr_class, uint16_t rr_type)
491 const uint8_t *name, uint16_t rr_class, uint16_t rr_type)
487492 {
488493 while (rr_iter_ansauth(rr) && (
489494 rr_iter_type(rr) == GETDNS_RRTYPE_RRSIG || (
500505 * a RRset with a certain name/class/type
501506 */
502507 static _getdns_rr_iter *rr_iter_rrsig_covering(_getdns_rr_iter *rr,
503 uint8_t *name, uint16_t rr_class, uint16_t rr_type)
508 const uint8_t *name, uint16_t rr_class, uint16_t rr_type)
504509 {
505510 while (rr_iter_ansauth(rr) && !(
506511 rr_iter_type(rr) == GETDNS_RRTYPE_RRSIG &&
515520 }
516521
517522 typedef struct getdns_rrset {
518 uint8_t *name;
519 uint16_t rr_class;
520 uint16_t rr_type;
521 uint8_t *pkt;
522 size_t pkt_len;
523 const uint8_t *name;
524 uint16_t rr_class;
525 uint16_t rr_type;
526 uint8_t *pkt;
527 size_t pkt_len;
523528 } getdns_rrset;
524529
525530 typedef struct rrtype_iter {
589594 return;
590595 }
591596 gldns_buffer_init_frm_data(&buf, buf_space, sizeof(buf_space));
592 if (gldns_wire2str_dname_buf(rrset->name, 256, owner, sizeof(owner)))
597 if (gldns_wire2str_dname_buf(
598 (UNCONST_UINT8_p)rrset->name, 256, owner, sizeof(owner)))
593599 gldns_buffer_printf(&buf, "%s ", owner);
594600 else gldns_buffer_printf(&buf, "<nil> ");
595601
763769 * to equip the chain nodes with their RR sets are done alongside construction.
764770 * Hence they need to be enumerated before the construction functions.
765771 */
766 static void val_chain_sched(chain_head *head, uint8_t *dname);
767 static void val_chain_sched_ds(chain_head *head, uint8_t *dname);
772 static void val_chain_sched(chain_head *head, const uint8_t *dname);
773 static void val_chain_sched_ds(chain_head *head, const uint8_t *dname);
768774 static void val_chain_sched_signer(chain_head *head, rrsig_iter *rrsig);
769 static void val_chain_sched_soa(chain_head *head, uint8_t *dname);
775 static void val_chain_sched_soa(chain_head *head, const uint8_t *dname);
770776
771777 static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
772778 chain_head **chain_p, getdns_rrset *rrset, getdns_network_req *netreq)
773779 {
774780 chain_head *head;
775 uint8_t *labels[128], **last_label, **label;
781 const uint8_t *labels[128], **last_label, **label;
776782
777783 size_t max_labels; /* max labels in common */
778784 chain_head *max_head;
779785 chain_node *max_node;
780786
781787 size_t dname_len, head_sz, node_count, n;
782 uint8_t *dname, *region;
788 const uint8_t *dname;
789 uint8_t *region;
783790 chain_node *node;
784791
785792 last_label = reverse_labels(rrset->name, labels);
905912 _getdns_rdf_iter rdf_spc, *rdf;
906913 rrtype_iter drr_spc, *drr;
907914 _getdns_rdf_iter drdf_spc, *drdf;
908 uint8_t cname_rdata_spc[256], *cname_rdata,
909 dname_rdata_spc[256], *dname_rdata,
915 uint8_t cname_rdata_spc[256],
916 dname_rdata_spc[256],
910917 synth_name[256],
911 *synth_name_end = synth_name + sizeof(synth_name) - 1, *s, *c;
918 *synth_name_end = synth_name + sizeof(synth_name) - 1, *s;
919 const uint8_t *cname_rdata, *dname_rdata, *c;
912920 size_t cname_rdata_len = sizeof(cname_rdata_spc),
913921 dname_rdata_len = sizeof(dname_rdata_len),
914922 cname_labels, dname_labels;
10481056 */
10491057 static void add_question2val_chain(struct mem_funcs *mf,
10501058 chain_head **chain_p, uint8_t *pkt, size_t pkt_len,
1051 uint8_t *qname, uint16_t qtype, uint16_t qclass,
1059 const uint8_t *qname, uint16_t qtype, uint16_t qclass,
10521060 getdns_network_req *netreq)
10531061 {
10541062 getdns_rrset q_rrset;
11321140 context = node->chains->netreq->owner->context;
11331141 loop = node->chains->netreq->owner->loop;
11341142
1135 if (!gldns_wire2str_dname_buf(node->ds.name, 256, name, sizeof(name)))
1143 if (!gldns_wire2str_dname_buf(
1144 (UNCONST_UINT8_p)node->ds.name, 256, name, sizeof(name)))
11361145 return;
11371146
11381147 DEBUG_SEC("schedule SOA lookup for %s\n", name);
11501159 * answer, then a DS/DNSKEY lookup will follow the acquire the link of the
11511160 * authentication chain.
11521161 */
1153 static void val_chain_sched_soa(chain_head *head, uint8_t *dname)
1162 static void val_chain_sched_soa(chain_head *head, const uint8_t *dname)
11541163 {
11551164 chain_node *node;
11561165
11791188 context = node->chains->netreq->owner->context;
11801189 loop = node->chains->netreq->owner->loop;
11811190
1182 if (!gldns_wire2str_dname_buf(node->ds.name, 256, name, sizeof(name)))
1191 if (!gldns_wire2str_dname_buf(
1192 (UNCONST_UINT8_p)node->ds.name, 256, name, sizeof(name)))
11831193 return;
11841194
11851195 DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name);
11991209 node->ds_req = dnsreq->netreqs[0];
12001210 }
12011211
1202 static void val_chain_sched(chain_head *head, uint8_t *dname)
1212 static void val_chain_sched(chain_head *head, const uint8_t *dname)
12031213 {
12041214 chain_node *node;
12051215
12231233 context = node->chains->netreq->owner->context;
12241234 loop = node->chains->netreq->owner->loop;
12251235
1226 if (!gldns_wire2str_dname_buf(node->ds.name, 256, name, sizeof(name)))
1236 if (!gldns_wire2str_dname_buf(
1237 (UNCONST_UINT8_p)node->ds.name, 256, name, sizeof(name)))
1238
12271239 return;
12281240
12291241 DEBUG_SEC("schedule DS lookup for %s\n", name);
12361248 node->ds_req = ds_req->netreqs[0];
12371249 }
12381250
1239 static void val_chain_sched_ds(chain_head *head, uint8_t *dname)
1251 static void val_chain_sched_ds(chain_head *head, const uint8_t *dname)
12401252 {
12411253 chain_node *node;
12421254
12531265 static void val_chain_sched_signer_node(chain_node *node, rrsig_iter *rrsig)
12541266 {
12551267 _getdns_rdf_iter rdf_spc, *rdf;
1256 uint8_t signer_spc[256], *signer;
1257 size_t signer_len;
1268 uint8_t signer_spc[256];
1269 const uint8_t *signer;
1270 size_t signer_len;
12581271
12591272 if (!(rdf = _getdns_rdf_iter_init_at(&rdf_spc, &rrsig->rr_i, 7)))
12601273 return;
13681381 rrsig_iter rrsig_spc, *rrsig;
13691382 uint16_t keytag;
13701383 _getdns_rdf_iter rdf_spc, *rdf;
1371 uint8_t signer_spc[256], *signer;
1384 uint8_t signer_spc[256];
1385 const uint8_t *signer;
13721386 size_t signer_len = sizeof(signer_spc);
13731387
13741388 assert(dnskey->rr_type == GETDNS_RRTYPE_DNSKEY);
13831397 continue;
13841398
13851399 /* Then we have at least 4 bytes to calculate keytag */
1386 keytag = gldns_calc_keytag_raw(rr->rr_i.rr_type + 10,
1387 rr->rr_i.nxt - rr->rr_i.rr_type - 10);
1400 keytag = gldns_calc_keytag_raw(
1401 (UNCONST_UINT8_p)rr->rr_i.rr_type + 10,
1402 rr->rr_i.nxt - rr->rr_i.rr_type - 10);
13881403
13891404 for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset)
13901405 ; rrsig ; rrsig = rrsig_iter_next(rrsig) ) {
14561471 _getdns_rdf_iter rdf_spc;
14571472 _getdns_rdf_iter *rdf;
14581473 uint8_t cdname[256]; /* Canonical dname */
1459 uint8_t *pos;
1474 const uint8_t *pos;
14601475 size_t len;
14611476 } canon_rdata_iter;
14621477
14661481 if ((i->rdf->rdd_pos->type & GETDNS_RDF_N) == GETDNS_RDF_N) {
14671482 i->len = sizeof(i->cdname);
14681483 if ((i->pos = _getdns_rdf_if_or_as_decompressed(
1469 i->rdf, i->cdname, &i->len)))
1470 _dname_canonicalize(i->pos);
1484 i->rdf, i->cdname, &i->len))) {
1485 _dname_canonicalize(i->pos, i->cdname);
1486 i->pos = i->cdname;
1487 }
14711488 } else {
14721489 i->pos = i->rdf->pos;
14731490 i->len = i->rdf->nxt - i->rdf->pos;
15571574 */
15581575 #define VAL_RRSET_SPC_SZ 1024
15591576 static int _getdns_verify_rrsig(struct mem_funcs *mf,
1560 getdns_rrset *rrset, rrsig_iter *rrsig, rrtype_iter *key, uint8_t **nc_name)
1577 getdns_rrset *rrset, rrsig_iter *rrsig, rrtype_iter *key, const uint8_t **nc_name)
15611578 {
15621579 int r;
15631580 int to_skip;
15671584 size_t n_rrs, i, valbuf_sz, owner_len;
15681585 _getdns_rdf_iter *signer, signer_spc, *rdf, rdf_spc;
15691586 uint8_t valbuf_spc[4096], *valbuf_buf = valbuf_spc;
1570 uint8_t cdname_spc[256], *cdname, owner[256];
1587 uint8_t cdname_spc[256], owner[256];
1588 const uint8_t *cdname;
15711589 size_t cdname_len, pos;
15721590 uint32_t orig_ttl;
15731591 gldns_buffer valbuf;
16191637 gldns_buffer_init_frm_data(&valbuf, valbuf_buf, valbuf_sz);
16201638 gldns_buffer_write(&valbuf,
16211639 rrsig->rr_i.rr_type + 10, signer->nxt - rrsig->rr_i.rr_type - 10);
1622 _dname_canonicalize(gldns_buffer_at(&valbuf, 18));
1640 _dname_canonicalize2(gldns_buffer_at(&valbuf, 18));
16231641
16241642 orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14);
16251643
16261644 (void) memcpy(owner, rrset->name, owner_len);
1627 _dname_canonicalize(owner);
1645 _dname_canonicalize2(owner);
16281646
16291647 if (!_dnssec_rdata_to_canonicalize(rrset->rr_type))
16301648 for (i = 0; i < n_rrs; i++) {
1649 if (i && !_rr_iter_rdata_cmp(
1650 &val_rrset[i], &val_rrset[i-1]))
1651 continue;
1652
16311653 gldns_buffer_write(&valbuf, owner, owner_len);
16321654 gldns_buffer_write_u16(&valbuf, rrset->rr_type);
16331655 gldns_buffer_write_u16(&valbuf, rrset->rr_class);
16361658 val_rrset[i].nxt - val_rrset[i].rr_type - 8);
16371659 }
16381660 else for (i = 0; i < n_rrs; i++) {
1661 if (i && !_rr_iter_rdata_cmp(&val_rrset[i], &val_rrset[i-1]))
1662 continue;
16391663 gldns_buffer_write(&valbuf, owner, owner_len);
16401664 gldns_buffer_write_u16(&valbuf, rrset->rr_type);
16411665 gldns_buffer_write_u16(&valbuf, rrset->rr_class);
16551679 rdf, cdname_spc, &cdname_len)))
16561680 continue;
16571681 gldns_buffer_write(&valbuf, cdname, cdname_len);
1658 _dname_canonicalize(
1682 _dname_canonicalize2(
16591683 gldns_buffer_current(&valbuf) - cdname_len);
16601684 }
16611685 gldns_buffer_write_u16_at(&valbuf, pos,
16631687 }
16641688 DEBUG_SEC( "written to valbuf: %zu bytes\n"
16651689 , gldns_buffer_position(&valbuf));
1666 assert(gldns_buffer_position(&valbuf) == valbuf_sz);
1667
1690 assert(gldns_buffer_position(&valbuf) <= valbuf_sz);
1691
1692 gldns_buffer_flip(&valbuf);
16681693 r = _getdns_verify_canonrrset(&valbuf, key->rr_i.rr_type[13],
1669 signer->nxt, rrsig->rr_i.nxt - signer->nxt,
1670 key->rr_i.rr_type+14, key->rr_i.nxt - key->rr_i.rr_type-14,
1694 (UNCONST_UINT8_p)signer->nxt, rrsig->rr_i.nxt - signer->nxt,
1695 (UNCONST_UINT8_p)key->rr_i.rr_type+14,
1696 key->rr_i.nxt - key->rr_i.rr_type-14,
16711697 &reason);
16721698
16731699 #if defined(SEC_DEBUG) && SEC_DEBUG
1674 if (r == 0)
1700 if (r == 0) {
16751701 DEBUG_SEC("verification failed: %s\n", reason);
1702 debug_sec_print_rrset("verification failed: ", rrset);
1703 debug_sec_print_rr("verification failed: ", &rrsig->rr_i);
1704 debug_sec_print_rr("verification failed: ", &key->rr_i);
1705 }
16761706 #endif
16771707 if (val_rrset != val_rrset_spc)
16781708 GETDNS_FREE(*mf, val_rrset);
17091739
17101740 /* Calculates NSEC3 hash for name, and stores that into label */
17111741 static uint8_t *_getdns_nsec3_hash_label(uint8_t *label, size_t label_len,
1712 uint8_t *name, uint8_t algorithm, uint16_t iterations, uint8_t *salt)
1742 const uint8_t *name, uint8_t algorithm,
1743 uint16_t iterations, const uint8_t *salt)
17131744 {
17141745 uint8_t buf[512], *dst, *eob;
17151746 const uint8_t *src;
17461777 }
17471778
17481779 static uint8_t *name2nsec3_label(
1749 getdns_rrset *nsec3, uint8_t *name, uint8_t *label, size_t label_len)
1780 getdns_rrset *nsec3, const uint8_t *name, uint8_t *label, size_t label_len)
17501781 {
17511782 rrsig_iter rrsig_spc, *rrsig;
17521783 _getdns_rdf_iter rdf_spc, *rdf;
1753 uint8_t signer_spc[256], *signer;
1784 uint8_t signer_spc[256];
1785 const uint8_t *signer;
17541786 size_t signer_len = sizeof(signer_spc);
17551787 rrtype_iter rr_spc, *rr;
17561788
18311863 * expansion, nc_name will point to the next closer part of the name in rrset.
18321864 */
18331865 static int dnskey_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
1834 rrtype_iter *dnskey, getdns_rrset *rrset, uint8_t **nc_name)
1866 rrtype_iter *dnskey, getdns_rrset *rrset, const uint8_t **nc_name)
18351867 {
18361868 rrsig_iter rrsig_spc, *rrsig;
18371869 _getdns_rdf_iter rdf_spc, *rdf;
1838 uint8_t signer_spc[256], *signer;
1870 uint8_t signer_spc[256];
1871 const uint8_t *signer;
18391872 size_t signer_len = sizeof(signer_spc);
18401873 uint16_t keytag;
18411874
18491882 return 0;
18501883
18511884 /* Then we have at least 4 bytes to calculate keytag */
1852 keytag = gldns_calc_keytag_raw(dnskey->rr_i.rr_type + 10,
1885 keytag = gldns_calc_keytag_raw((UNCONST_UINT8_p)dnskey->rr_i.rr_type + 10,
18531886 dnskey->rr_i.nxt - dnskey->rr_i.rr_type - 10);
18541887
18551888 for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset)
18981931 }
18991932
19001933 static int find_nsec_covering_name(
1901 struct mem_funcs *mf, time_t now, uint32_t skew,
1902 getdns_rrset *dnskey, getdns_rrset *rrset, uint8_t *name, int *opt_out);
1934 struct mem_funcs *mf, time_t now, uint32_t skew, getdns_rrset *dnskey,
1935 getdns_rrset *rrset, const uint8_t *name, int *opt_out);
19031936
19041937 /* Returns whether a dnskey for keyset signed rrset. */
19051938 static int a_key_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew,
19061939 getdns_rrset *keyset, getdns_rrset *rrset)
19071940 {
19081941 rrtype_iter dnskey_spc, *dnskey;
1909 uint8_t *nc_name;
1942 const uint8_t *nc_name;
19101943 int keytag;
19111944
19121945 assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
19481981 rrtype_iter dnskey_spc, *dnskey;
19491982 rrtype_iter ds_spc, *ds;
19501983 uint16_t keytag;
1951 uint8_t *nc_name;
1984 const uint8_t *nc_name;
19521985 size_t valid_dsses = 0, supported_dsses = 0;
19531986 uint8_t max_supported_digest = 0;
19541987 int max_supported_result = 0;
19712004 return 0;
19722005
19732006 (void) memcpy(digest_buf_spc, dnskey_set->name, dnskey_owner_len);
1974 _dname_canonicalize(digest_buf_spc);
2007 _dname_canonicalize2(digest_buf_spc);
19752008
19762009 for ( dnskey = rrtype_iter_init(&dnskey_spc, dnskey_set)
19772010 ; dnskey ; dnskey = rrtype_iter_next(dnskey)) {
19802013 if (dnskey->rr_i.nxt < dnskey->rr_i.rr_type + 14)
19812014 continue;
19822015
1983 keytag = gldns_calc_keytag_raw(dnskey->rr_i.rr_type + 10,
1984 dnskey->rr_i.nxt - dnskey->rr_i.rr_type - 10);
2016 keytag = gldns_calc_keytag_raw(
2017 (UNCONST_UINT8_p) dnskey->rr_i.rr_type + 10,
2018 dnskey->rr_i.nxt - dnskey->rr_i.rr_type - 10);
19852019
19862020 for ( ds = rrtype_iter_init(&ds_spc, ds_set)
19872021 ; ds ; ds = rrtype_iter_next(ds)) {
21042138 }
21052139
21062140 static int nsec_covers_name(
2107 getdns_rrset *nsec, uint8_t *name, uint8_t **ce_name)
2108 {
2109 uint8_t owner_spc[256], *owner;
2110 size_t owner_len = sizeof(owner_spc);
2111 uint8_t next_spc[256], *next;
2112 size_t next_len = sizeof(next_spc);
2141 getdns_rrset *nsec, const uint8_t *name, const uint8_t **ce_name)
2142 {
2143 uint8_t owner_spc[256], next_spc[256];
2144 const uint8_t *owner, *next;
2145 size_t owner_len = sizeof(owner_spc), next_len = sizeof(next_spc);
2146
21132147 rrtype_iter rr_spc, *rr;
21142148 _getdns_rdf_iter rdf_spc, *rdf;
21152149 int nsec_cmp;
2116 uint8_t *common1, *common2;
2150 const uint8_t *common1, *common2;
21172151
21182152 if (/* Get owner and next, nicely decompressed */
21192153 !(rr = rrtype_iter_init(&rr_spc, nsec))
21622196 }
21632197 }
21642198
2165 static int nsec3_matches_name(getdns_rrset *nsec3, uint8_t *name)
2199 static int nsec3_matches_name(getdns_rrset *nsec3, const uint8_t *name)
21662200 {
21672201 uint8_t label[64], owner[64];
21682202
21752209 return 0;
21762210 }
21772211
2178 static int nsec3_covers_name(getdns_rrset *nsec3, uint8_t *name, int *opt_out)
2212 static int nsec3_covers_name(
2213 getdns_rrset *nsec3, const uint8_t *name, int *opt_out)
21792214 {
21802215 uint8_t label[65], next[65], owner[65];
21812216 rrtype_iter rr_spc, *rr;
22262261 }
22272262
22282263 static int find_nsec_covering_name(
2229 struct mem_funcs *mf, time_t now, uint32_t skew,
2230 getdns_rrset *dnskey, getdns_rrset *rrset, uint8_t *name, int *opt_out)
2264 struct mem_funcs *mf, time_t now, uint32_t skew, getdns_rrset *dnskey,
2265 getdns_rrset *rrset, const uint8_t *name, int *opt_out)
22312266 {
22322267 rrset_iter i_spc, *i;
22332268 getdns_rrset *n;
23242359
23252360 static int nsec3_find_next_closer(
23262361 struct mem_funcs *mf, time_t now, uint32_t skew,
2327 getdns_rrset *dnskey, getdns_rrset *rrset, uint8_t *nc_name, int *opt_out)
2362 getdns_rrset *dnskey, getdns_rrset *rrset,
2363 const uint8_t *nc_name, int *opt_out)
23282364 {
23292365 uint8_t wc_name[256] = { 1, (uint8_t)'*' };
23302366 int my_opt_out, keytag;
23812417 rrtype_iter nsec_spc, *nsec_rr;
23822418 _getdns_rdf_iter bitmap_spc, *bitmap;
23832419 rrset_iter i_spc, *i;
2384 uint8_t *ce_name, *nc_name;
2420 const uint8_t *ce_name, *nc_name;
23852421 uint8_t wc_name[256] = { 1, (uint8_t)'*' };
23862422 int keytag;
23872423
27652801
27662802 if ((s = chain_node_get_trusted_keys(
27672803 mf, now, skew, head->parent, ta, &keys)) != GETDNS_DNSSEC_SECURE)
2768 return s;
2804 return s;
27692805
27702806 if (rrset_has_rrs(&head->rrset)) {
27712807 if ((keytag = a_key_signed_rrset(
29793015 return count + count_outstanding_requests(head->next);
29803016 }
29813017
3018 static int rrset_in_list(getdns_rrset *rrset, getdns_list *list)
3019 {
3020 size_t i;
3021 getdns_dict *rr_dict;
3022 uint32_t rr_type;
3023 uint32_t rr_class;
3024 getdns_bindata *name;
3025
3026 for (i = 0; !getdns_list_get_dict(list, i, &rr_dict); i++) {
3027 if (!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
3028 rrset->rr_type == rr_type &&
3029 !getdns_dict_get_int(rr_dict, "class", &rr_class) &&
3030 rrset->rr_class == rr_class &&
3031 !getdns_dict_get_bindata(rr_dict, "name", &name) &&
3032 dname_compare(rrset->name, name->data) == 0)
3033 return 1;
3034 }
3035 return 0;
3036 }
3037
29823038 static void append_rrs2val_chain_list(getdns_context *ctxt,
29833039 getdns_list *val_chain_list, getdns_network_req *netreq, int signer)
29843040 {
29943050
29953051 rrset = rrset_iter_value(i);
29963052
2997 if (rrset->rr_type != GETDNS_RRTYPE_DNSKEY &&
2998 rrset->rr_type != GETDNS_RRTYPE_DS &&
2999 rrset->rr_type != GETDNS_RRTYPE_NSEC &&
3000 rrset->rr_type != GETDNS_RRTYPE_NSEC3)
3053 if (rrset->rr_type == GETDNS_RRTYPE_NSEC ||
3054 rrset->rr_type == GETDNS_RRTYPE_NSEC3) {
3055
3056 if (rrset_in_list(rrset, val_chain_list))
3057 continue;
3058
3059 } else if (rrset->rr_type != GETDNS_RRTYPE_DNSKEY &&
3060 rrset->rr_type != GETDNS_RRTYPE_DS)
30013061 continue;
30023062
30033063 for ( rr = rrtype_iter_init(&rr_spc, rrset)
30433103 return;
30443104
30453105 bindata.size = _dname_len(ds->name);
3046 bindata.data = ds->name;
3106 bindata.data = (UNCONST_UINT8_p)ds->name;
30473107 (void) getdns_dict_set_bindata(rr_dict, "name", &bindata);
30483108 (void) getdns_dict_set_int(rr_dict, "class", ds->rr_class);
30493109 (void) getdns_dict_set_int(rr_dict, "type", ds->rr_type);
32013261 , netreq->response, netreq->response_len
32023262 , netreq->owner->name
32033263 , netreq->request_type
3204 , netreq->request_class
3264 , netreq->owner->request_class
32053265 , netreq
32063266 );
32073267 }
32243284 chain_head *chain, *head, *next_head;
32253285 chain_node *node;
32263286
3227 uint8_t qname_spc[256], *qname = NULL;
3287 uint8_t qname_spc[256];
3288 const uint8_t *qname = NULL;
32283289 size_t qname_len = sizeof(qname_spc);
32293290 uint16_t qtype = 0, qclass = GETDNS_RRCLASS_IN;
32303291
3030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131 */
3232
33 #include "config.h"
34 #include "types-internal.h"
3335 #include "getdns/getdns_ext_libev.h"
34 #include "types-internal.h"
35 #include "config.h"
3636
3737 #ifdef HAVE_LIBEV_EV_H
3838 #include <libev/ev.h>
3030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131 */
3232
33 #include "config.h"
34 #include "types-internal.h"
3335 #include <sys/time.h>
3436 #include "getdns/getdns_ext_libevent.h"
35 #include "types-internal.h"
36 #include "config.h"
3737
3838 #ifdef HAVE_EVENT2_EVENT_H
3939 # include <event2/event.h>
3131 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3232 */
3333
34 #include "config.h"
35 #include "debug.h"
36 #include "types-internal.h"
3437 #include "extension/libmini_event.h"
35 #include "context.h"
36 #include "util-internal.h"
3738 #if defined(SCHED_DEBUG) && SCHED_DEBUG
3839 #include <inttypes.h>
3940 #endif
204205 if (!ext)
205206 return GETDNS_RETURN_INVALID_PARAMETER;
206207
208 #ifdef USE_WINSOCK
209 int r;
210 WSADATA wsa_data;
211
212 if ((r = WSAStartup(MAKEWORD(2, 2), &wsa_data)) != 0) {
213 printf("could not init winsock. WSAStartup: %s",
214 wsa_strerror(r));
215 return GETDNS_RETURN_GENERIC_ERROR;
216 }
217 #endif
218
207219 ext->n_events = 0;
208220 ext->loop.vmt = &_getdns_mini_event_vmt;
209221 ext->base = _getdns_event_init(&ext->time_secs, &ext->time_tv);
210222 if (!ext->base)
211223 return GETDNS_RETURN_MEMORY_ERROR;
212224
213 ext->mf = context->mf;
225 ext->mf = *priv_getdns_context_mf(context);
214226 return GETDNS_RETURN_GOOD;
215227 }
216228
220232 if (!context) return GETDNS_RETURN_BAD_CONTEXT;
221233 if (!ext) return GETDNS_RETURN_INVALID_PARAMETER;
222234
223 *ext = GETDNS_MALLOC(context->mf, _getdns_mini_event);
235 *ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), _getdns_mini_event);
224236 return _getdns_mini_event_init(context, *ext);
225237 }
3434 #define _GETDNS_LIBMINI_EVENT_H_
3535
3636 #include "config.h"
37 #ifndef USE_WINSOCK
3738 #include "util/mini_event.h"
39 #else
40 #include "util/winsock_event.h"
41 #endif
3842 #include "types-internal.h"
3943
4044 typedef struct _getdns_mini_event {
3131 */
3232
3333 #include "config.h"
34 #include "debug.h"
35 #include "types-internal.h"
3436 #include <uv.h>
3537 #include "getdns/getdns_ext_libuv.h"
36 #include "util-internal.h"
3738
3839 #define UV_DEBUG 0
3940
4343 #include "util-internal.h"
4444 #include "dnssec.h"
4545 #include "stub.h"
46 #include "general.h"
4647
4748 /* cancel, cleanup and send timeout to callback */
4849 static void
6970 (response ? GETDNS_CALLBACK_COMPLETE : GETDNS_CALLBACK_ERROR),
7071 response, user_arg, trans_id);
7172 context->processing = 0;
73 }
74
75 static int
76 no_answer(getdns_dns_req *dns_req)
77 {
78 getdns_network_req **netreq_p, *netreq;
79 int new_canonical = 0;
80 uint8_t canon_spc[256];
81 const uint8_t *canon;
82 size_t canon_len;
83 uint8_t owner_spc[256];
84 const uint8_t *owner;
85 size_t owner_len;
86
87 _getdns_rr_iter rr_spc, *rr;
88 _getdns_rdf_iter rdf_spc, *rdf;
89
90 for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++) {
91 if (netreq->response_len == 0 ||
92 GLDNS_ANCOUNT(netreq->response) == 0)
93 continue;
94 canon = netreq->owner->name;
95 canon_len = netreq->owner->name_len;
96 if (netreq->request_type != GETDNS_RRTYPE_CNAME
97 && GLDNS_ANCOUNT(netreq->response) > 1) do {
98 new_canonical = 0;
99 for ( rr = _getdns_rr_iter_init(&rr_spc
100 , netreq->response
101 , netreq->response_len)
102 ; rr && _getdns_rr_iter_section(rr)
103 <= GLDNS_SECTION_ANSWER
104 ; rr = _getdns_rr_iter_next(rr)) {
105
106 if (_getdns_rr_iter_section(rr) !=
107 GLDNS_SECTION_ANSWER)
108 continue;
109
110 if (gldns_read_uint16(rr->rr_type) !=
111 GETDNS_RRTYPE_CNAME)
112 continue;
113
114 owner = _getdns_owner_if_or_as_decompressed(
115 rr, owner_spc, &owner_len);
116 if (!_getdns_dname_equal(canon, owner))
117 continue;
118
119 if (!(rdf = _getdns_rdf_iter_init(
120 &rdf_spc, rr)))
121 continue;
122
123 canon = _getdns_rdf_if_or_as_decompressed(
124 rdf, canon_spc, &canon_len);
125 new_canonical = 1;
126 }
127 } while (new_canonical);
128 for ( rr = _getdns_rr_iter_init(&rr_spc
129 , netreq->response
130 , netreq->response_len)
131 ; rr && _getdns_rr_iter_section(rr)
132 <= GLDNS_SECTION_ANSWER
133 ; rr = _getdns_rr_iter_next(rr)) {
134
135 if (_getdns_rr_iter_section(rr) !=
136 GLDNS_SECTION_ANSWER)
137 continue;
138
139 if (gldns_read_uint16(rr->rr_type) !=
140 netreq->request_type)
141 continue;
142
143 owner = _getdns_owner_if_or_as_decompressed(
144 rr, owner_spc, &owner_len);
145 if (_getdns_dname_equal(canon, owner))
146 return 0;
147 }
148 }
149 return 1;
72150 }
73151
74152 void
84162 else if (netreq->response_len > 0)
85163 results_found = 1;
86164
165 /* Do we have to check more suffixes on nxdomain/nodata?
166 */
167 if (dns_req->suffix_appended && /* Something was appended */
168 dns_req->suffix_len > 1 && /* Next suffix available */
169 no_answer(dns_req)) {
170 /* Remove suffix from name */
171 dns_req->name_len -= dns_req->suffix_len - 1;
172 dns_req->name[dns_req->name_len - 1] = 0;
173 do {
174 dns_req->suffix += dns_req->suffix_len;
175 dns_req->suffix_len = *dns_req->suffix++;
176 if (dns_req->suffix_len + dns_req->name_len - 1 <
177 sizeof(dns_req->name)) {
178 memcpy(dns_req->name + dns_req->name_len - 1,
179 dns_req->suffix, dns_req->suffix_len);
180 dns_req->name_len += dns_req->suffix_len - 1;
181 dns_req->suffix_appended = 1;
182 break;
183 }
184 } while (dns_req->suffix_len > 1 && *dns_req->suffix);
185 if (dns_req->append_name == GETDNS_APPEND_NAME_ALWAYS ||
186 (dns_req->suffix_len > 1 && *dns_req->suffix)) {
187 for ( netreq_p = dns_req->netreqs
188 ; (netreq = *netreq_p)
189 ; netreq_p++ ) {
190 _getdns_netreq_reinit(netreq);
191 if (_getdns_submit_netreq(netreq))
192 netreq->state = NET_REQ_FINISHED;
193 }
194 _getdns_check_dns_req_complete(dns_req);
195 return;
196 }
197 } else if (
198 ( dns_req->append_name ==
199 GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE ||
200 dns_req->append_name ==
201 GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE
202 ) &&
203 !dns_req->suffix_appended &&
204 dns_req->suffix_len > 1 &&
205 no_answer(dns_req)) {
206 /* Initial suffix append */
207 for (
208 ; dns_req->suffix_len > 1 && *dns_req->suffix
209 ; dns_req->suffix += dns_req->suffix_len
210 , dns_req->suffix_len = *dns_req->suffix++) {
211
212 if (dns_req->suffix_len + dns_req->name_len - 1 <
213 sizeof(dns_req->name)) {
214 memcpy(dns_req->name + dns_req->name_len - 1,
215 dns_req->suffix, dns_req->suffix_len);
216 dns_req->name_len += dns_req->suffix_len - 1;
217 dns_req->suffix_appended = 1;
218 break;
219 }
220 }
221 if (dns_req->suffix_appended) {
222 for ( netreq_p = dns_req->netreqs
223 ; (netreq = *netreq_p)
224 ; netreq_p++ ) {
225 _getdns_netreq_reinit(netreq);
226 if (_getdns_submit_netreq(netreq))
227 netreq->state = NET_REQ_FINISHED;
228 }
229 _getdns_check_dns_req_complete(dns_req);
230 return;
231 }
232 }
87233 if (dns_req->internal_cb)
88234 dns_req->internal_cb(dns_req);
89235 else if (! results_found)
172318
173319 #ifdef HAVE_LIBUNBOUND
174320 return ub_resolve_async(dns_req->context->unbound_ctx,
175 name, netreq->request_type, netreq->request_class,
321 name, netreq->request_type, netreq->owner->request_class,
176322 netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
177323 GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
178324 #else
345491 switch (address_data->size) {
346492 case 4:
347493 (void)snprintf(name, sizeof(name),
348 "%hhu.%hhu.%hhu.%hhu.in-addr.arpa.",
349 ((uint8_t *)address_data->data)[3],
350 ((uint8_t *)address_data->data)[2],
351 ((uint8_t *)address_data->data)[1],
352 ((uint8_t *)address_data->data)[0]);
494 "%d.%d.%d.%d.in-addr.arpa.",
495 (int)((uint8_t *)address_data->data)[3],
496 (int)((uint8_t *)address_data->data)[2],
497 (int)((uint8_t *)address_data->data)[1],
498 (int)((uint8_t *)address_data->data)[0]);
353499 break;
354500 case 16:
355501 (void)snprintf(name, sizeof(name),
356 "%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx."
357 "%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx."
358 "%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx."
359 "%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.ip6.arpa.",
360 (uint8_t)(((uint8_t *)address_data->data)[15] & 0x0F),
361 (uint8_t)(((uint8_t *)address_data->data)[15] >> 4),
362 (uint8_t)(((uint8_t *)address_data->data)[14] & 0x0F),
363 (uint8_t)(((uint8_t *)address_data->data)[14] >> 4),
364 (uint8_t)(((uint8_t *)address_data->data)[13] & 0x0F),
365 (uint8_t)(((uint8_t *)address_data->data)[13] >> 4),
366 (uint8_t)(((uint8_t *)address_data->data)[12] & 0x0F),
367 (uint8_t)(((uint8_t *)address_data->data)[12] >> 4),
368 (uint8_t)(((uint8_t *)address_data->data)[11] & 0x0F),
369 (uint8_t)(((uint8_t *)address_data->data)[11] >> 4),
370 (uint8_t)(((uint8_t *)address_data->data)[10] & 0x0F),
371 (uint8_t)(((uint8_t *)address_data->data)[10] >> 4),
372 (uint8_t)(((uint8_t *)address_data->data)[9] & 0x0F),
373 (uint8_t)(((uint8_t *)address_data->data)[9] >> 4),
374 (uint8_t)(((uint8_t *)address_data->data)[8] & 0x0F),
375 (uint8_t)(((uint8_t *)address_data->data)[8] >> 4),
376 (uint8_t)(((uint8_t *)address_data->data)[7] & 0x0F),
377 (uint8_t)(((uint8_t *)address_data->data)[7] >> 4),
378 (uint8_t)(((uint8_t *)address_data->data)[6] & 0x0F),
379 (uint8_t)(((uint8_t *)address_data->data)[6] >> 4),
380 (uint8_t)(((uint8_t *)address_data->data)[5] & 0x0F),
381 (uint8_t)(((uint8_t *)address_data->data)[5] >> 4),
382 (uint8_t)(((uint8_t *)address_data->data)[4] & 0x0F),
383 (uint8_t)(((uint8_t *)address_data->data)[4] >> 4),
384 (uint8_t)(((uint8_t *)address_data->data)[3] & 0x0F),
385 (uint8_t)(((uint8_t *)address_data->data)[3] >> 4),
386 (uint8_t)(((uint8_t *)address_data->data)[2] & 0x0F),
387 (uint8_t)(((uint8_t *)address_data->data)[2] >> 4),
388 (uint8_t)(((uint8_t *)address_data->data)[1] & 0x0F),
389 (uint8_t)(((uint8_t *)address_data->data)[1] >> 4),
390 (uint8_t)(((uint8_t *)address_data->data)[0] & 0x0F),
391 (uint8_t)(((uint8_t *)address_data->data)[0] >> 4));
502 "%x.%x.%x.%x.%x.%x.%x.%x."
503 "%x.%x.%x.%x.%x.%x.%x.%x."
504 "%x.%x.%x.%x.%x.%x.%x.%x."
505 "%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
506 (int)(((uint8_t *)address_data->data)[15] & 0x0F),
507 (int)(((uint8_t *)address_data->data)[15] >> 4),
508 (int)(((uint8_t *)address_data->data)[14] & 0x0F),
509 (int)(((uint8_t *)address_data->data)[14] >> 4),
510 (int)(((uint8_t *)address_data->data)[13] & 0x0F),
511 (int)(((uint8_t *)address_data->data)[13] >> 4),
512 (int)(((uint8_t *)address_data->data)[12] & 0x0F),
513 (int)(((uint8_t *)address_data->data)[12] >> 4),
514 (int)(((uint8_t *)address_data->data)[11] & 0x0F),
515 (int)(((uint8_t *)address_data->data)[11] >> 4),
516 (int)(((uint8_t *)address_data->data)[10] & 0x0F),
517 (int)(((uint8_t *)address_data->data)[10] >> 4),
518 (int)(((uint8_t *)address_data->data)[9] & 0x0F),
519 (int)(((uint8_t *)address_data->data)[9] >> 4),
520 (int)(((uint8_t *)address_data->data)[8] & 0x0F),
521 (int)(((uint8_t *)address_data->data)[8] >> 4),
522 (int)(((uint8_t *)address_data->data)[7] & 0x0F),
523 (int)(((uint8_t *)address_data->data)[7] >> 4),
524 (int)(((uint8_t *)address_data->data)[6] & 0x0F),
525 (int)(((uint8_t *)address_data->data)[6] >> 4),
526 (int)(((uint8_t *)address_data->data)[5] & 0x0F),
527 (int)(((uint8_t *)address_data->data)[5] >> 4),
528 (int)(((uint8_t *)address_data->data)[4] & 0x0F),
529 (int)(((uint8_t *)address_data->data)[4] >> 4),
530 (int)(((uint8_t *)address_data->data)[3] & 0x0F),
531 (int)(((uint8_t *)address_data->data)[3] >> 4),
532 (int)(((uint8_t *)address_data->data)[2] & 0x0F),
533 (int)(((uint8_t *)address_data->data)[2] >> 4),
534 (int)(((uint8_t *)address_data->data)[1] & 0x0F),
535 (int)(((uint8_t *)address_data->data)[1] >> 4),
536 (int)(((uint8_t *)address_data->data)[0] & 0x0F),
537 (int)(((uint8_t *)address_data->data)[0] >> 4));
392538 break;
393539 default:
394540 return GETDNS_RETURN_INVALID_PARAMETER;
184184 GETDNS_TRANSPORT_UDP = 1200,
185185 GETDNS_TRANSPORT_TCP = 1201,
186186 GETDNS_TRANSPORT_TLS = 1202,
187 GETDNS_TRANSPORT_STARTTLS = 1203
188187 } getdns_transport_list_t;
189188
190189 /**
194193 #define GETDNS_TRANSPORT_UDP_TEXT "See getdns_context_set_dns_transport_list()"
195194 #define GETDNS_TRANSPORT_TCP_TEXT "See getdns_context_set_dns_transport_list()"
196195 #define GETDNS_TRANSPORT_TLS_TEXT "See getdns_context_set_dns_transport_list()"
197 #define GETDNS_TRANSPORT_STARTTLS_TEXT "See getdns_context_set_dns_transport_list()"
198196 /** @}
199197 */
200198
2929
3030 #include <getdns/getdns.h>
3131 #include <sys/time.h>
32 #include <stdio.h>
3233
3334 #ifdef __cplusplus
3435 extern "C" {
340341 */
341342 const char *getdns_get_errorstr_by_id(uint16_t err);
342343
343
344
345
346 /**
347 * Public Key Pinning functionality:
348 *
349 * a public key pinset is a list of dicts. each dict should have a
350 * "digest" and a "value".
351 *
352 * "digest": a string indicating the type of digest. at the moment, we
353 * only support a "digest" of "sha256".
354 *
355 * "value": a binary representation of the digest provided.
356 *
357 * given a such a pinset, we should be able to validate a chain
358 * properly according to section 2.6 of RFC 7469.
359 */
360
361 /**
362 * convert an HPKP-style pin description to an appropriate getdns data
363 * structure. An example string is: (with the quotes, without any
364 * leading or trailing whitespace):
365 *
366 * pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="
367 *
368 * It is the caller's responsibility to call getdns_dict_destroy() on
369 * the dict returned when it is no longer needed.
370 *
371 * @param context a context to use to create the dict, or NULL to create
372 * it generically
373 * @param str the pinning string to parse
374 * @return a dict created from ctx, or NULL if the string did not match.
375 */
376 getdns_dict* getdns_pubkey_pin_create_from_string(
377 getdns_context* context,
378 const char* str);
379
380
381 /**
382 * Test whether a given pinset is reasonable, including:
383 *
384 * is it well-formed?
385 * are there at least two pins?
386 * are the digests used sane?
387 *
388 * @param pinset the set of public key pins to check for sanity. This
389 * should be a list of dicts.
390 * @return errorlist if not NULL, a list of human-readable strings is
391 * appended to errorlist.
392 * @return GETDNS_RETURN_GOOD if the pinset passes the sanity check.
393 */
394 getdns_return_t getdns_pubkey_pinset_sanity_check(
395 const getdns_list* pinset,
396 getdns_list* errorlist);
397
398
399
344400 /* WARNING! Function getdns_strerror is not in the API specification and
345401 * is likely to be removed from future versions of our implementation, to be
346402 * replaced by getdns_get_errorstr_by_id or something similar.
348404 */
349405 getdns_return_t getdns_strerror(getdns_return_t err, char *buf, size_t buflen);
350406
351 #define GETDNS_VERSION "0.5.1"
352 #define GETDNS_NUMERIC_VERSION 0x00050100
353 #define GETDNS_API_VERSION "October 2015"
354 #define GETDNS_API_NUMERIC_VERSION 0x07df0a00
407 #define GETDNS_VERSION "0.9.0"
408 #define GETDNS_NUMERIC_VERSION 0x00090000
409 #define GETDNS_API_VERSION "December 2015"
410 #define GETDNS_API_NUMERIC_VERSION 0x07df0c00
355411
356412 const char *getdns_get_version(void);
357413 uint32_t getdns_get_version_number(void);
361417 /* Authentication options used when doing TLS */
362418 typedef enum getdns_tls_authentication_t {
363419 GETDNS_AUTHENTICATION_NONE = 1300,
364 GETDNS_AUTHENTICATION_HOSTNAME = 1301,
420 GETDNS_AUTHENTICATION_REQUIRED = 1301
365421 } getdns_tls_authentication_t;
422
423 /* an alias for REQUIRED */
424 #define GETDNS_AUTHENTICATION_HOSTNAME GETDNS_AUTHENTICATION_REQUIRED
366425
367426 /**
368427 * \defgroup Base authentication texts
369428 * @{
370429 */
371430 #define GETDNS_AUTHENTICATION_NONE_TEXT "See getdns_context_set_tls_authentication()"
372 #define GETDNS_AUTHENTICATION_HOSTNAME_TEXT "See getdns_context_set_tls_authentication()"
431 #define GETDNS_AUTHENTICATION_REQUIRED_TEXT "See getdns_context_set_tls_authentication()"
373432 /** @}
374433 */
375434
379438 #define GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE_TEXT "Change related to getdns_context_set_edns_client_subnet_private"
380439 #define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE 620
381440 #define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT "Change related to getdns_context_set_tls_query_padding_blocksize"
441 #define GETDNS_CONTEXT_CODE_PUBKEY_PINSET 621
442 #define GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT "Change related to getdns_context_set_pubkey_pinset"
382443
383444 getdns_return_t
384445 getdns_context_set_tls_authentication(
398459 #define GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()"
399460 #define GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN 545
400461 #define GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()"
401 #define GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN 546
402 #define GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()"
462
463 #define GETDNS_RETURN_NEED_MORE_SPACE ((getdns_return_t) 399 )
464 #define GETDNS_RETURN_NEED_MORE_SPACE_TEXT "The buffer was too small"
465
466 /**
467 * Convert rr_dict to wireformat representation of the resource record.
468 *
469 * @param rr_dict The getdns dict representation of the resource record
470 * @return wire A newly allocated buffer which will contain the wireformat.
471 * @return wire_sz The size of the allocated buffer and the wireformat.
472 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
473 */
474 getdns_return_t
475 getdns_rr_dict2wire(
476 const getdns_dict *rr_dict, uint8_t **wire, size_t *wire_sz);
477
478 /**
479 * Convert rr_dict to wireformat representation of the resource record.
480 *
481 * @param rr_dict The getdns dict representation of the resource record
482 * @param wire The buffer in which the wireformat will be written
483 * @param wire_sz On input the size of the wire buffer,
484 * On output the amount of wireformat needed for the
485 * wireformat representation of the resource record;
486 * even if it did not fit.
487 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
488 * GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
489 * small. wire_sz will be set to the needed buffer space then.
490 */
491 getdns_return_t
492 getdns_rr_dict2wire_buf(
493 const getdns_dict *rr_dict, uint8_t *wire, size_t *wire_sz);
494
495 /**
496 * Convert rr_dict to wireformat representation of the resource record.
497 *
498 * @param rr_dict The getdns dict representation of the resource record
499 * @param wire A pointer to the buffer pointer in which the wireformat
500 * will be written.
501 * On output the buffer pointer will have moved along
502 * the buffer and point right after the just written RR.
503 * @param wire_sz On input the size of the wire buffer,
504 * On output the amount of wireformat needed for the
505 * wireformat will have been substracted from wire_sz.
506 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
507 * GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
508 * small. The function will pretend that it had written beyond the end
509 * of the buffer, and wire will point past the buffer and wire_sz will
510 * contain a negative value.
511 */
512 getdns_return_t
513 getdns_rr_dict2wire_scan(
514 const getdns_dict *rr_dict, uint8_t **wire, int *wire_sz);
515
516
517 /**
518 * Convert wireformat resource record in a getdns rr_dict representation.
519 *
520 * @param wire Buffer containing the wireformat rr
521 * @param wire_sz Size of the wire buffer
522 * @return rr_dict The returned rr_dict
523 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
524 */
525 getdns_return_t
526 getdns_wire2rr_dict(
527 const uint8_t *wire, size_t wire_sz, getdns_dict **rr_dict);
528
529 /**
530 * Convert wireformat resource record in a getdns rr_dict representation.
531 *
532 * @param wire Buffer containing the wireformat rr
533 * @param wire_sz On input the size of the wire buffer
534 * On output the length of the wireformat rr.
535 * @return rr_dict The returned rr_dict
536 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
537 */
538 getdns_return_t
539 getdns_wire2rr_dict_buf(
540 const uint8_t *wire, size_t *wire_sz, getdns_dict **rr_dict);
541
542 /**
543 * Convert wireformat resource record in a getdns rr_dict representation.
544 *
545 * @param wire A pointer to the pointer of the wireformat buffer.
546 * On return this pointer is moved to after first read
547 * in resource record.
548 * @param wire_sz On input the size of the wire buffer
549 * On output the size is decreased with the length
550 * of the wireformat resource record.
551 * @return rr_dict The returned rr_dict
552 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
553 */
554 getdns_return_t
555 getdns_wire2rr_dict_scan(
556 const uint8_t **wire, size_t *wire_sz, getdns_dict **rr_dict);
557
558
559 /**
560 * Convert rr_dict to the string representation of the resource record.
561 *
562 * @param rr_dict The getdns dict representation of the resource record
563 * @return str A newly allocated string representation of the rr
564 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
565 */
566 getdns_return_t
567 getdns_rr_dict2str(
568 const getdns_dict *rr_dict, char **str);
569
570 /**
571 * Convert rr_dict to the string representation of the resource record.
572 *
573 * @param rr_dict The getdns dict representation of the resource record
574 * @param str The buffer in which the string will be written
575 * @param str_len On input the size of the text buffer,
576 * On output the amount of characters needed to write
577 * the string representation of the rr. Even if it does
578 * not fit.
579 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
580 * GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
581 * small. str_len will be set to the needed buffer space then.
582 */
583 getdns_return_t
584 getdns_rr_dict2str_buf(
585 const getdns_dict *rr_dict, char *str, size_t *str_len);
586
587 /**
588 * Convert rr_dict to the string representation of the resource record.
589 *
590 * @param rr_dict The getdns dict representation of the resource record
591 * @param str A pointer to the buffer pointer in which the string
592 * will be written.
593 * On output the buffer pointer will have moved along
594 * the buffer and point right after the just written RR.
595 * @param str_len On input the size of the str buffer,
596 * On output the number of characters needed for the
597 * string will have been substracted from strlen.
598 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
599 * GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
600 * small. The function will pretend that it had written beyond the end
601 * of the buffer, and str will point past the buffer and str_len will
602 * contain a negative value.
603 */
604 getdns_return_t
605 getdns_rr_dict2str_scan(
606 const getdns_dict *rr_dict, char **str, int *str_len);
607
608
609 /**
610 * Convert the string representation of the resource record to rr_dict format.
611 *
612 * @param str String representation of the resource record.
613 * @return rr_dict The result getdns dict representation of the resource record
614 * @param origin Default suffix for not fully qualified domain names
615 * @param default_ttl Default ttl
616 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
617 */
618 getdns_return_t
619 getdns_str2rr_dict(
620 const char *str, getdns_dict **rr_dict,
621 const char *origin, uint32_t default_ttl);
622
623 /**
624 * Read the zonefile and convert to a list of rr_dict's.
625 *
626 * @param fp String representation of the resource record.
627 * @return rr_list The result list of rr_dicts representing the zone file.
628 * @param origin Default suffix for not fully qualified domain names
629 * @param default_ttl Default ttl
630 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
631 */
632 getdns_return_t
633 getdns_fp2rr_list(
634 FILE *in, getdns_list **rr_list,
635 const char *origin, uint32_t default_ttl);
403636
404637 #ifdef __cplusplus
405638 }
2929
3030 #include <getdns/getdns.h>
3131 #include <sys/time.h>
32 #include <stdio.h>
3233
3334 #ifdef __cplusplus
3435 extern "C" {
340341 */
341342 const char *getdns_get_errorstr_by_id(uint16_t err);
342343
343
344
345
346 /**
347 * Public Key Pinning functionality:
348 *
349 * a public key pinset is a list of dicts. each dict should have a
350 * "digest" and a "value".
351 *
352 * "digest": a string indicating the type of digest. at the moment, we
353 * only support a "digest" of "sha256".
354 *
355 * "value": a binary representation of the digest provided.
356 *
357 * given a such a pinset, we should be able to validate a chain
358 * properly according to section 2.6 of RFC 7469.
359 */
360
361 /**
362 * convert an HPKP-style pin description to an appropriate getdns data
363 * structure. An example string is: (with the quotes, without any
364 * leading or trailing whitespace):
365 *
366 * pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="
367 *
368 * It is the caller's responsibility to call getdns_dict_destroy() on
369 * the dict returned when it is no longer needed.
370 *
371 * @param context a context to use to create the dict, or NULL to create
372 * it generically
373 * @param str the pinning string to parse
374 * @return a dict created from ctx, or NULL if the string did not match.
375 */
376 getdns_dict* getdns_pubkey_pin_create_from_string(
377 getdns_context* context,
378 const char* str);
379
380
381 /**
382 * Test whether a given pinset is reasonable, including:
383 *
384 * is it well-formed?
385 * are there at least two pins?
386 * are the digests used sane?
387 *
388 * @param pinset the set of public key pins to check for sanity. This
389 * should be a list of dicts.
390 * @return errorlist if not NULL, a list of human-readable strings is
391 * appended to errorlist.
392 * @return GETDNS_RETURN_GOOD if the pinset passes the sanity check.
393 */
394 getdns_return_t getdns_pubkey_pinset_sanity_check(
395 const getdns_list* pinset,
396 getdns_list* errorlist);
397
398
399
344400 /* WARNING! Function getdns_strerror is not in the API specification and
345401 * is likely to be removed from future versions of our implementation, to be
346402 * replaced by getdns_get_errorstr_by_id or something similar.
361417 /* Authentication options used when doing TLS */
362418 typedef enum getdns_tls_authentication_t {
363419 GETDNS_AUTHENTICATION_NONE = 1300,
364 GETDNS_AUTHENTICATION_HOSTNAME = 1301,
420 GETDNS_AUTHENTICATION_REQUIRED = 1301
365421 } getdns_tls_authentication_t;
422
423 /* an alias for REQUIRED */
424 #define GETDNS_AUTHENTICATION_HOSTNAME GETDNS_AUTHENTICATION_REQUIRED
366425
367426 /**
368427 * \defgroup Base authentication texts
369428 * @{
370429 */
371430 #define GETDNS_AUTHENTICATION_NONE_TEXT "See getdns_context_set_tls_authentication()"
372 #define GETDNS_AUTHENTICATION_HOSTNAME_TEXT "See getdns_context_set_tls_authentication()"
431 #define GETDNS_AUTHENTICATION_REQUIRED_TEXT "See getdns_context_set_tls_authentication()"
373432 /** @}
374433 */
375434
379438 #define GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE_TEXT "Change related to getdns_context_set_edns_client_subnet_private"
380439 #define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE 620
381440 #define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT "Change related to getdns_context_set_tls_query_padding_blocksize"
441 #define GETDNS_CONTEXT_CODE_PUBKEY_PINSET 621
442 #define GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT "Change related to getdns_context_set_pubkey_pinset"
382443
383444 getdns_return_t
384445 getdns_context_set_tls_authentication(
398459 #define GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()"
399460 #define GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN 545
400461 #define GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()"
401 #define GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN 546
402 #define GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()"
462
463 #define GETDNS_RETURN_NEED_MORE_SPACE ((getdns_return_t) 399 )
464 #define GETDNS_RETURN_NEED_MORE_SPACE_TEXT "The buffer was too small"
465
466 /**
467 * Convert rr_dict to wireformat representation of the resource record.
468 *
469 * @param rr_dict The getdns dict representation of the resource record
470 * @return wire A newly allocated buffer which will contain the wireformat.
471 * @return wire_sz The size of the allocated buffer and the wireformat.
472 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
473 */
474 getdns_return_t
475 getdns_rr_dict2wire(
476 const getdns_dict *rr_dict, uint8_t **wire, size_t *wire_sz);
477
478 /**
479 * Convert rr_dict to wireformat representation of the resource record.
480 *
481 * @param rr_dict The getdns dict representation of the resource record
482 * @param wire The buffer in which the wireformat will be written
483 * @param wire_sz On input the size of the wire buffer,
484 * On output the amount of wireformat needed for the
485 * wireformat representation of the resource record;
486 * even if it did not fit.
487 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
488 * GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
489 * small. wire_sz will be set to the needed buffer space then.
490 */
491 getdns_return_t
492 getdns_rr_dict2wire_buf(
493 const getdns_dict *rr_dict, uint8_t *wire, size_t *wire_sz);
494
495 /**
496 * Convert rr_dict to wireformat representation of the resource record.
497 *
498 * @param rr_dict The getdns dict representation of the resource record
499 * @param wire A pointer to the buffer pointer in which the wireformat
500 * will be written.
501 * On output the buffer pointer will have moved along
502 * the buffer and point right after the just written RR.
503 * @param wire_sz On input the size of the wire buffer,
504 * On output the amount of wireformat needed for the
505 * wireformat will have been substracted from wire_sz.
506 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
507 * GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
508 * small. The function will pretend that it had written beyond the end
509 * of the buffer, and wire will point past the buffer and wire_sz will
510 * contain a negative value.
511 */
512 getdns_return_t
513 getdns_rr_dict2wire_scan(
514 const getdns_dict *rr_dict, uint8_t **wire, int *wire_sz);
515
516
517 /**
518 * Convert wireformat resource record in a getdns rr_dict representation.
519 *
520 * @param wire Buffer containing the wireformat rr
521 * @param wire_sz Size of the wire buffer
522 * @return rr_dict The returned rr_dict
523 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
524 */
525 getdns_return_t
526 getdns_wire2rr_dict(
527 const uint8_t *wire, size_t wire_sz, getdns_dict **rr_dict);
528
529 /**
530 * Convert wireformat resource record in a getdns rr_dict representation.
531 *
532 * @param wire Buffer containing the wireformat rr
533 * @param wire_sz On input the size of the wire buffer
534 * On output the length of the wireformat rr.
535 * @return rr_dict The returned rr_dict
536 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
537 */
538 getdns_return_t
539 getdns_wire2rr_dict_buf(
540 const uint8_t *wire, size_t *wire_sz, getdns_dict **rr_dict);
541
542 /**
543 * Convert wireformat resource record in a getdns rr_dict representation.
544 *
545 * @param wire A pointer to the pointer of the wireformat buffer.
546 * On return this pointer is moved to after first read
547 * in resource record.
548 * @param wire_sz On input the size of the wire buffer
549 * On output the size is decreased with the length
550 * of the wireformat resource record.
551 * @return rr_dict The returned rr_dict
552 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
553 */
554 getdns_return_t
555 getdns_wire2rr_dict_scan(
556 const uint8_t **wire, size_t *wire_sz, getdns_dict **rr_dict);
557
558
559 /**
560 * Convert rr_dict to the string representation of the resource record.
561 *
562 * @param rr_dict The getdns dict representation of the resource record
563 * @return str A newly allocated string representation of the rr
564 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
565 */
566 getdns_return_t
567 getdns_rr_dict2str(
568 const getdns_dict *rr_dict, char **str);
569
570 /**
571 * Convert rr_dict to the string representation of the resource record.
572 *
573 * @param rr_dict The getdns dict representation of the resource record
574 * @param str The buffer in which the string will be written
575 * @param str_len On input the size of the text buffer,
576 * On output the amount of characters needed to write
577 * the string representation of the rr. Even if it does
578 * not fit.
579 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
580 * GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
581 * small. str_len will be set to the needed buffer space then.
582 */
583 getdns_return_t
584 getdns_rr_dict2str_buf(
585 const getdns_dict *rr_dict, char *str, size_t *str_len);
586
587 /**
588 * Convert rr_dict to the string representation of the resource record.
589 *
590 * @param rr_dict The getdns dict representation of the resource record
591 * @param str A pointer to the buffer pointer in which the string
592 * will be written.
593 * On output the buffer pointer will have moved along
594 * the buffer and point right after the just written RR.
595 * @param str_len On input the size of the str buffer,
596 * On output the number of characters needed for the
597 * string will have been substracted from strlen.
598 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
599 * GETDNS_RETURN_NEED_MORE_SPACE will be returned when the buffer was too
600 * small. The function will pretend that it had written beyond the end
601 * of the buffer, and str will point past the buffer and str_len will
602 * contain a negative value.
603 */
604 getdns_return_t
605 getdns_rr_dict2str_scan(
606 const getdns_dict *rr_dict, char **str, int *str_len);
607
608
609 /**
610 * Convert the string representation of the resource record to rr_dict format.
611 *
612 * @param str String representation of the resource record.
613 * @return rr_dict The result getdns dict representation of the resource record
614 * @param origin Default suffix for not fully qualified domain names
615 * @param default_ttl Default ttl
616 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
617 */
618 getdns_return_t
619 getdns_str2rr_dict(
620 const char *str, getdns_dict **rr_dict,
621 const char *origin, uint32_t default_ttl);
622
623 /**
624 * Read the zonefile and convert to a list of rr_dict's.
625 *
626 * @param fp String representation of the resource record.
627 * @return rr_list The result list of rr_dicts representing the zone file.
628 * @param origin Default suffix for not fully qualified domain names
629 * @param default_ttl Default ttl
630 * @return GETDNS_RETURN_GOOD on success or an error code on failure.
631 */
632 getdns_return_t
633 getdns_fp2rr_list(
634 FILE *in, getdns_list **rr_list,
635 const char *origin, uint32_t default_ttl);
403636
404637 #ifdef __cplusplus
405638 }
8383 p[2] = (uint8_t) ((data >> 8) & 0xff);
8484 p[3] = (uint8_t) (data & 0xff);
8585 #endif
86 }
87
88
89 INLINE void
90 gldns_write_uint48(void *dst, uint64_t data)
91 {
92 uint8_t *p = (uint8_t *) dst;
93 p[0] = (uint8_t) ((data >> 40) & 0xff);
94 p[1] = (uint8_t) ((data >> 32) & 0xff);
95 p[2] = (uint8_t) ((data >> 24) & 0xff);
96 p[3] = (uint8_t) ((data >> 16) & 0xff);
97 p[4] = (uint8_t) ((data >> 8) & 0xff);
98 p[5] = (uint8_t) (data & 0xff);
8699 }
87100
88101
534547 }
535548
536549 /**
550 * writes the given 6 byte integer at the given position in the buffer
551 * \param[in] buffer the buffer
552 * \param[in] at the position in the buffer
553 * \param[in] data the (lower) 48 bits to write
554 */
555 INLINE void
556 gldns_buffer_write_u48_at(gldns_buffer *buffer, size_t at, uint64_t data)
557 {
558 if (buffer->_fixed && at + 6 > buffer->_limit) return;
559 assert(gldns_buffer_available_at(buffer, at, 6));
560 gldns_write_uint48(buffer->_data + at, data);
561 }
562
563 /**
537564 * writes the given 4 byte integer at the current position in the buffer
538565 * \param[in] buffer the buffer
539566 * \param[in] data the 32 bits to write
543570 {
544571 gldns_buffer_write_u32_at(buffer, buffer->_position, data);
545572 buffer->_position += sizeof(data);
573 }
574
575 /**
576 * writes the given 6 byte integer at the current position in the buffer
577 * \param[in] buffer the buffer
578 * \param[in] data the 48 bits to write
579 */
580 INLINE void
581 gldns_buffer_write_u48(gldns_buffer *buffer, uint64_t data)
582 {
583 gldns_buffer_write_u48_at(buffer, buffer->_position, data);
584 buffer->_position += 6;
546585 }
547586
548587 /**
416416 GLDNS_EDNS_DAU = 5, /* RFC6975 */
417417 GLDNS_EDNS_DHU = 6, /* RFC6975 */
418418 GLDNS_EDNS_N3U = 7, /* RFC6975 */
419 GLDNS_EDNS_CLIENT_SUBNET = 8 /* draft-vandergaast-edns-client-subnet */
419 GLDNS_EDNS_CLIENT_SUBNET = 8, /* draft-vandergaast-edns-client-subnet */
420 GLDNS_EDNS_KEEPALIVE = 11 /* draft-ietf-dnsop-edns-tcp-keepalive*/
420421 };
421422 typedef enum gldns_enum_edns_option gldns_edns_option;
422423
866866 return s;
867867 } else if(strncmp(line, "$TTL", 4) == 0 && isspace(line[4])) {
868868 const char* end = NULL;
869 size_t off = 8;
869 size_t off = 5;
870870 *len = 0;
871871 *dname_len = 0;
872872 if(!parse_state) return GLDNS_WIREPARSE_ERR_OK;
164164 { 6, "DHU" },
165165 { 7, "N3U" },
166166 { 8, "edns-client-subnet" },
167 { 11, "edns-tcp-keepalive"},
167168 { 0, NULL}
168169 };
169170 gldns_lookup_table* gldns_edns_options = gldns_edns_options_data;
18321833 return w;
18331834 }
18341835
1836 int gldns_wire2str_edns_keepalive_print(char** s, size_t* sl, uint8_t* data,
1837 size_t len)
1838 {
1839 int w = 0;
1840 uint16_t timeout;
1841 if(!(len == 0 || len == 2)) {
1842 w += gldns_str_print(s, sl, "malformed keepalive ");
1843 w += print_hex_buf(s, sl, data, len);
1844 return w;
1845 }
1846 if(len == 0 ) {
1847 w += gldns_str_print(s, sl, "no timeout value (only valid for client option) ");
1848 } else {
1849 timeout = gldns_read_uint16(data);
1850 w += gldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout);
1851 }
1852 return w;
1853 }
1854
18351855 int gldns_wire2str_edns_option_print(char** s, size_t* sl,
18361856 uint16_t option_code, uint8_t* optdata, size_t optlen)
18371857 {
18601880 case GLDNS_EDNS_CLIENT_SUBNET:
18611881 w += gldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
18621882 break;
1883 case GLDNS_EDNS_KEEPALIVE:
1884 w += gldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen);
1885 break;
18631886 default:
18641887 /* unknown option code */
18651888 w += print_hex_buf(s, sl, optdata, optlen);
1212 getdns_context_get_dnssec_trust_anchors
1313 getdns_context_get_dns_transport
1414 getdns_context_get_dns_transport_list
15 getdns_context_get_tls_authentication
1615 getdns_context_get_edns_client_subnet_private
1716 getdns_context_get_edns_do_bit
1817 getdns_context_get_edns_extended_rcode
2625 getdns_context_get_resolution_type
2726 getdns_context_get_suffix
2827 getdns_context_get_timeout
28 getdns_context_get_tls_authentication
2929 getdns_context_get_tls_query_padding_blocksize
3030 getdns_context_get_update_callback
3131 getdns_context_get_upstream_recursive_servers
8282 getdns_dict_util_get_string
8383 getdns_dict_util_set_string
8484 getdns_display_ip_address
85 getdns_fp2rr_list
8586 getdns_general
8687 getdns_general_sync
8788 getdns_get_api_version
112113 getdns_pretty_snprint_list
113114 getdns_print_json_dict
114115 getdns_print_json_list
116 getdns_pubkey_pin_create_from_string
117 getdns_pubkey_pinset_sanity_check
115118 getdns_root_trust_anchor
119 getdns_rr_dict2str
120 getdns_rr_dict2str_buf
121 getdns_rr_dict2str_scan
122 getdns_rr_dict2wire
123 getdns_rr_dict2wire_buf
124 getdns_rr_dict2wire_scan
116125 getdns_service
117126 getdns_service_sync
118127 getdns_snprint_json_dict
119128 getdns_snprint_json_list
129 getdns_str2rr_dict
120130 getdns_strerror
121131 getdns_validate_dnssec
132 getdns_wire2rr_dict
133 getdns_wire2rr_dict_buf
134 getdns_wire2rr_dict_scan
122135 plain_mem_funcs_user_arg
123136 priv_getdns_context_mf
106106
107107 i = &list->items[index];
108108 if (!*next) {
109 switch (i->dtype) {
110 case t_dict : getdns_dict_destroy(i->data.dict); break;
111 case t_list : getdns_list_destroy(i->data.list); break;
112 case t_bindata: _getdns_bindata_destroy(
113 &list->mf, i->data.bindata);
114 default : break;
115 }
109116 if (index < list->numinuse - 1)
110117 (void) memmove( i, &i[1],
111118 (list->numinuse - index) * sizeof(getdns_item));
544551 } /* getdns_list_set_list */
545552
546553 /*---------------------------------------- getdns_list_set_bindata */
547 getdns_return_t
548 getdns_list_set_bindata(
549 getdns_list *list, size_t index, const getdns_bindata *child_bindata)
554 static getdns_return_t
555 _getdns_list_set_const_bindata(
556 getdns_list *list, size_t index, size_t size, const void *data)
550557 {
551558 getdns_bindata *newbindata;
552559 getdns_return_t r;
553560
554 if (!list || !child_bindata)
555 return GETDNS_RETURN_INVALID_PARAMETER;
556
557 if (!(newbindata = _getdns_bindata_copy(&list->mf, child_bindata)))
561 if (!list)
562 return GETDNS_RETURN_INVALID_PARAMETER;
563
564 if (!(newbindata = _getdns_bindata_copy(&list->mf, size, data)))
558565 return GETDNS_RETURN_MEMORY_ERROR;
559566
560567 if ((r = _getdns_list_request_index(list, index))) {
566573 return GETDNS_RETURN_GOOD;
567574 } /* getdns_list_set_bindata */
568575
576 getdns_return_t
577 getdns_list_set_bindata(
578 getdns_list *list, size_t index, const getdns_bindata *child_bindata)
579 {
580 return !child_bindata ? GETDNS_RETURN_INVALID_PARAMETER
581 : _getdns_list_set_const_bindata(
582 list, index, child_bindata->size, child_bindata->data);
583 }
584
569585 /*----------------------------------------- getdns_list_set_string */
570586 static getdns_return_t
571587 getdns_list_set_string(getdns_list *list, size_t index, const char *value)
572588 {
573 getdns_bindata *newbindata;
574 getdns_return_t r;
575
576 if (!list || !value)
577 return GETDNS_RETURN_INVALID_PARAMETER;
578
579 if (!(newbindata = GETDNS_MALLOC(list->mf, getdns_bindata)))
580 return GETDNS_RETURN_MEMORY_ERROR;
581
582 newbindata->size = strlen(value);
583 if (!(newbindata->data = (void *)_getdns_strdup(&list->mf, value))) {
584 GETDNS_FREE(list->mf, newbindata);
585 return GETDNS_RETURN_MEMORY_ERROR;
586 }
587 if ((r = _getdns_list_request_index(list, index))) {
588 GETDNS_FREE(list->mf, newbindata->data);
589 GETDNS_FREE(list->mf, newbindata);
590 return r;
591 }
592 list->items[index].dtype = t_bindata;
593 list->items[index].data.bindata = newbindata;
594 return GETDNS_RETURN_GOOD;
589 return value
590 ? _getdns_list_set_const_bindata(list, index, strlen(value), value)
591 : GETDNS_RETURN_INVALID_PARAMETER;
595592 } /* getdns_list_set_string */
596593
597594 /*---------------------------------------- getdns_list_set_int */
630627 return getdns_list_set_bindata(list, list->numinuse, child_bindata);
631628 }
632629 getdns_return_t
630 _getdns_list_append_const_bindata(
631 getdns_list *list, size_t size, const void *data)
632 {
633 if (!list) return GETDNS_RETURN_INVALID_PARAMETER;
634 return _getdns_list_set_const_bindata(list, list->numinuse, size, data);
635 }
636 getdns_return_t
633637 _getdns_list_append_string(getdns_list *list, const char *value)
634638 {
635639 if (!list) return GETDNS_RETURN_INVALID_PARAMETER;
0 /**
1 *
2 * /brief functions for Public Key Pinning
3 *
4 */
5
6 /*
7 * Copyright (c) 2015, Daniel Kahn Gillmor
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * * Neither the names of the copyright holders nor the
18 * names of its contributors may be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /**
34 * getdns Public Key Pinning
35 *
36 * a public key pinset is a list of dicts. each dict should have a
37 * "digest" and a "value".
38 *
39 * "digest": a string indicating the type of digest. at the moment, we
40 * only support a "digest" of "sha256".
41 *
42 * "value": a binary representation of the digest provided.
43 *
44 * given a such a pinset, we should be able to validate a chain
45 * properly according to section 2.6 of RFC 7469.
46 */
47 #include "config.h"
48 #include "debug.h"
49 #include <getdns/getdns.h>
50 #include <openssl/evp.h>
51 #include <openssl/bio.h>
52 #include <openssl/sha.h>
53 #include <openssl/x509.h>
54 #include <string.h>
55 #include "context.h"
56
57 /* we only support sha256 at the moment. adding support for another
58 digest is more complex than just adding another entry here. in
59 particular, you'll probably need a match for a particular cert
60 against all supported algorithms. better to wait on doing that
61 until it is a better-understood problem (i.e. wait until hpkp is
62 updated and follow the guidance in rfc7469bis)
63 */
64
65 static const getdns_bindata sha256 = {
66 .size = sizeof("sha256") - 1,
67 .data = (uint8_t*)"sha256"
68 };
69
70
71 #define PIN_PREFIX "pin-sha256=\""
72 #define PIN_PREFIX_LENGTH (sizeof(PIN_PREFIX) - 1)
73 /* b64 turns every 3 octets (or fraction thereof) into 4 octets */
74 #define B64_ENCODED_SHA256_LENGTH (((SHA256_DIGEST_LENGTH + 2)/3) * 4)
75
76 /* convert an HPKP-style pin description to an appropriate getdns data
77 structure. An example string is: (with the quotes, without any
78 leading or trailing whitespace):
79
80 pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="
81
82 getdns_build_pin_from_string returns a dict created from ctx, or
83 NULL if the string did not match. If ctx is NULL, the dict is
84 created via getdns_dict_create().
85
86 It is the caller's responsibility to call getdns_dict_destroy when
87 it is no longer needed.
88 */
89 getdns_dict* getdns_pubkey_pin_create_from_string(
90 getdns_context* context,
91 const char* str)
92 {
93 BIO *bio = NULL;
94 int i;
95 uint8_t buf[SHA256_DIGEST_LENGTH];
96 char inbuf[B64_ENCODED_SHA256_LENGTH + 1];
97 getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf };
98 getdns_dict* out = NULL;
99
100 /* we only do sha256 right now, make sure this is well-formed */
101 if (strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH))
102 return NULL;
103 for (i = PIN_PREFIX_LENGTH; i < PIN_PREFIX_LENGTH + B64_ENCODED_SHA256_LENGTH - 1; i++)
104 if (!((str[i] >= 'a' && str[i] <= 'z') ||
105 (str[i] >= 'A' && str[i] <= 'Z') ||
106 (str[i] >= '0' && str[i] <= '9') ||
107 (str[i] == '+') || (str[i] == '/')))
108 return NULL;
109 if (str[i++] != '=')
110 return NULL;
111 if (str[i++] != '"')
112 return NULL;
113 if (str[i++] != '\0')
114 return NULL;
115
116 /* openssl needs a trailing newline to base64 decode */
117 memcpy(inbuf, str + PIN_PREFIX_LENGTH, B64_ENCODED_SHA256_LENGTH);
118 inbuf[B64_ENCODED_SHA256_LENGTH] = '\n';
119
120 bio = BIO_push(BIO_new(BIO_f_base64()),
121 BIO_new_mem_buf(inbuf, sizeof(inbuf)));
122 if (BIO_read(bio, buf, sizeof(buf)) != sizeof(buf))
123 goto fail;
124
125 if (context)
126 out = getdns_dict_create_with_context(context);
127 else
128 out = getdns_dict_create();
129 if (out == NULL)
130 goto fail;
131 if (getdns_dict_set_bindata(out, "digest", &sha256))
132 goto fail;
133 if (getdns_dict_set_bindata(out, "value", &value))
134 goto fail;
135 return out;
136
137 fail:
138 BIO_free_all(bio);
139 getdns_dict_destroy(out);
140 return NULL;
141 }
142
143
144 /* Test whether a given pinset is reasonable, including:
145
146 * is it well-formed?
147 * are there at least two pins?
148 * are the digests used sane?
149
150 if errorlist is NULL, the sanity check just returns success or
151 failure.
152
153 if errorlist is not NULL, we append human-readable strings to
154 report the errors.
155 */
156
157 #define PKP_SC_ERR(e) { \
158 err.size = sizeof(e); \
159 err.data = (uint8_t*)e; \
160 if (errorlist) \
161 getdns_list_set_bindata(errorlist, \
162 preverrs + errorcount, &err); \
163 errorcount++; \
164 }
165 #define PKP_SC_HARDERR(e, val) { \
166 PKP_SC_ERR(e); return val; \
167 }
168 getdns_return_t getdns_pubkey_pinset_sanity_check(
169 const getdns_list* pinset,
170 getdns_list* errorlist)
171 {
172 size_t errorcount = 0, preverrs = 0, pins = 0, i;
173 getdns_bindata err;
174 getdns_dict * pin;
175 getdns_bindata * data;
176
177 if (errorlist)
178 if (getdns_list_get_length(errorlist, &preverrs))
179 return GETDNS_RETURN_INVALID_PARAMETER;
180
181 if (getdns_list_get_length(pinset, &pins))
182 PKP_SC_HARDERR("Can't get length of pinset",
183 GETDNS_RETURN_INVALID_PARAMETER);
184 if (pins < 2)
185 PKP_SC_ERR("This pinset has fewer than 2 pins");
186 for (i = 0; i < pins; i++)
187 {
188 /* is it a dict? */
189 if (getdns_list_get_dict(pinset, i, &pin)) {
190 PKP_SC_ERR("Could not retrieve a pin");
191 } else {
192 /* does the pin have the right digest type? */
193 if (getdns_dict_get_bindata(pin, "digest", &data)) {
194 PKP_SC_ERR("Pin has no 'digest' entry");
195 } else {
196 if (data->size != sha256.size ||
197 memcmp(data->data, sha256.data, sha256.size))
198 PKP_SC_ERR("Pin has 'digest' other than sha256");
199 }
200 /* if it does, is the value the right length? */
201 if (getdns_dict_get_bindata(pin, "value", &data)) {
202 PKP_SC_ERR("Pin has no 'value' entry");
203 } else {
204 if (data->size != SHA256_DIGEST_LENGTH)
205 PKP_SC_ERR("Pin has the wrong size 'value' (should be 32 octets for sha256)");
206 }
207
208 /* should we choke if it has some other key? for
209 * extensibility, we will not treat this as an
210 * error.*/
211 }
212 }
213
214 if (errorcount > 0)
215 return GETDNS_RETURN_GENERIC_ERROR;
216 return GETDNS_RETURN_GOOD;
217 }
218
219 getdns_return_t
220 _getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list,
221 struct mem_funcs *mf,
222 sha256_pin_t **pinset_out)
223 {
224 getdns_return_t r;
225 size_t pins, i;
226 sha256_pin_t *out = NULL, *onext = NULL;
227 getdns_dict * pin;
228 getdns_bindata * data = NULL;
229
230 if (r = getdns_list_get_length(pinset_list, &pins), r)
231 return r;
232 for (i = 0; i < pins; i++)
233 {
234 if (r = getdns_list_get_dict(pinset_list, i, &pin), r)
235 goto fail;
236 /* does the pin have the right digest type? */
237 if (r = getdns_dict_get_bindata(pin, "digest", &data), r)
238 goto fail;
239 if (data->size != sha256.size ||
240 memcmp(data->data, sha256.data, sha256.size)) {
241 r = GETDNS_RETURN_INVALID_PARAMETER;
242 goto fail;
243 }
244 /* if it does, is the value the right length? */
245 if (r = getdns_dict_get_bindata(pin, "value", &data), r)
246 goto fail;
247 if (data->size != SHA256_DIGEST_LENGTH) {
248 r = GETDNS_RETURN_INVALID_PARAMETER;
249 goto fail;
250 }
251 /* make a new pin */
252 onext = GETDNS_MALLOC(*mf, sha256_pin_t);
253 if (onext == NULL) {
254 r = GETDNS_RETURN_MEMORY_ERROR;
255 goto fail;
256 }
257 onext->next = out;
258 memcpy(onext->pin, data->data, SHA256_DIGEST_LENGTH);
259 out = onext;
260 }
261
262 *pinset_out = out;
263 return GETDNS_RETURN_GOOD;
264 fail:
265 while (out) {
266 onext = out->next;
267 GETDNS_FREE(*mf, out);
268 out = onext;
269 }
270 return r;
271 }
272
273 getdns_return_t
274 _getdns_get_pubkey_pinset_list(getdns_context *ctx,
275 const sha256_pin_t *pinset_in,
276 getdns_list **pinset_list)
277 {
278 getdns_list *out = getdns_list_create_with_context(ctx);
279 getdns_return_t r;
280 uint8_t buf[SHA256_DIGEST_LENGTH];
281 getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf };
282 getdns_dict *pin = NULL;
283 size_t idx = 0;
284
285 if (out == NULL)
286 return GETDNS_RETURN_MEMORY_ERROR;
287 while (pinset_in) {
288 pin = getdns_dict_create_with_context(ctx);
289 if (pin == NULL) {
290 r = GETDNS_RETURN_MEMORY_ERROR;
291 goto fail;
292 }
293 if (r = getdns_dict_set_bindata(pin, "digest", &sha256), r)
294 goto fail;
295 memcpy(buf, pinset_in->pin, sizeof(buf));
296 if (r = getdns_dict_set_bindata(pin, "value", &value), r)
297 goto fail;
298 if (r = getdns_list_set_dict(out, idx++, pin), r)
299 goto fail;
300 getdns_dict_destroy(pin);
301 pin = NULL;
302 pinset_in = pinset_in->next;
303 }
304
305 *pinset_list = out;
306 return GETDNS_RETURN_GOOD;
307 fail:
308 getdns_dict_destroy(pin);
309 getdns_list_destroy(out);
310 return r;
311 }
312
313 /* this should only happen once ever in the life of the library. it's
314 used to associate a getdns_context_t with an SSL_CTX, to be able to
315 do custom verification.
316
317 see doc/HOWTO/proxy_certificates.txt as an example
318 */
319 static int
320 _get_ssl_getdns_upstream_idx()
321 {
322 static volatile int idx = -1;
323 if (idx < 0) {
324 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
325 if (idx < 0)
326 idx = SSL_get_ex_new_index(0, "associated getdns upstream",
327 NULL,NULL,NULL);
328 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
329 }
330 return idx;
331 }
332
333 getdns_upstream*
334 _getdns_upstream_from_x509_store(X509_STORE_CTX *store)
335 {
336 int uidx = _get_ssl_getdns_upstream_idx();
337 int sslidx = SSL_get_ex_data_X509_STORE_CTX_idx();
338 const SSL *ssl;
339
340 /* all *_get_ex_data() should return NULL on failure anyway */
341 ssl = X509_STORE_CTX_get_ex_data(store, sslidx);
342 if (ssl)
343 return (getdns_upstream*) SSL_get_ex_data(ssl, uidx);
344 else
345 return NULL;
346 /* TODO: if we want more details about errors somehow, we
347 * might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
348 }
349
350 getdns_return_t
351 _getdns_associate_upstream_with_SSL(SSL *ssl,
352 getdns_upstream *upstream)
353 {
354 int uidx = _get_ssl_getdns_upstream_idx();
355 if (SSL_set_ex_data(ssl, uidx, upstream))
356 return GETDNS_RETURN_GOOD;
357 else
358 return GETDNS_RETURN_GENERIC_ERROR;
359 /* TODO: if we want more details about errors somehow, we
360 * might call ERR_get_error (see CRYPTO_set_ex_data(3ssl))*/
361 }
362
363 getdns_return_t
364 _getdns_verify_pinset_match(const sha256_pin_t *pinset,
365 X509_STORE_CTX *store)
366 {
367 getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR;
368 X509 *x;
369 int i, len;
370 unsigned char raw[4096];
371 unsigned char *next = raw;
372 unsigned char buf[sizeof(pinset->pin)];
373 const sha256_pin_t *p;
374
375 if (pinset == NULL || store == NULL)
376 return GETDNS_RETURN_GENERIC_ERROR;
377
378 /* start at the base of the chain (the end-entity cert) and
379 * make sure that some valid element of the chain does match
380 * the pinset. */
381
382 /* Testing with OpenSSL 1.0.1e-1 on debian indicates that
383 * store->untrusted holds the chain offered by the server in
384 * the order that the server offers it. If the server offers
385 * bogus certificates (that is, matching and valid certs that
386 * belong to private keys that the server does not control),
387 * the the verification will succeed (including this pinset
388 * check), but the handshake will fail outside of this
389 * verification. */
390
391 /* TODO: how do we handle raw public keys? */
392
393 for (i = 0; i < sk_X509_num(store->untrusted); i++) {
394 if (i > 0) {
395 /* TODO: how do we ensure that the certificates in
396 * each stage appropriately sign the previous one?
397 * for now, to be safe, we only examine the end-entity
398 * cert: */
399 return GETDNS_RETURN_GENERIC_ERROR;
400 }
401
402 x = sk_X509_value(store->untrusted, i);
403 if (x->cert_info == NULL)
404 continue;
405 #if defined(STUB_DEBUG) && STUB_DEBUG
406 DEBUG_STUB("--- %s: name of cert %d:\n", __FUNCTION__, i);
407 if (x->cert_info->subject != NULL)
408 X509_NAME_print_ex_fp(stderr, x->cert_info->subject, 4, XN_FLAG_ONELINE);
409 fprintf(stderr, "\n");
410 #endif
411 if (x->cert_info->key == NULL)
412 continue;
413
414 /* digest the cert with sha256 */
415 len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
416 if (len > sizeof(raw)) {
417 DEBUG_STUB("--- %s: pubkey %d is larger than %ld octets\n",
418 __FUNCTION__, i, sizeof(raw));
419 continue;
420 }
421 i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
422 if (next - raw != len) {
423 DEBUG_STUB("--- %s: pubkey %d claimed it needed %d octets, really needed %ld\n",
424 __FUNCTION__, i, len, next - raw);
425 continue;
426 }
427 SHA256(raw, len, buf);
428
429 /* compare it */
430 for (p = pinset; p; p = p->next)
431 if (0 == memcmp(buf, p->pin, sizeof(p->pin))) {
432 DEBUG_STUB("--- %s: pubkey %d matched pin %p (%ld)!\n",
433 __FUNCTION__, i, p, sizeof(p->pin));
434 return GETDNS_RETURN_GOOD;
435 } else
436 DEBUG_STUB("--- %s: pubkey %d did not match pin %p!\n",
437 __FUNCTION__, i, p);
438 }
439
440 return ret;
441 }
442
443 /* pubkey-pinning.c */
0 /**
1 *
2 * /brief internal functions for dealing with pubkey pinsets
3 *
4 */
5
6 /*
7 * Copyright (c) 2015 ACLU
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * * Neither the names of the copyright holders nor the
18 * names of its contributors may be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifndef PUBKEY_PINNING_H_
34 #define PUBKEY_PINNING_H_
35
36
37 /* create and populate a pinset linked list from a getdns_list pinset */
38 getdns_return_t
39 _getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list,
40 struct mem_funcs *mf,
41 sha256_pin_t **pinset_out);
42
43
44 /* create a getdns_list version of the pinset */
45 getdns_return_t
46 _getdns_get_pubkey_pinset_list(getdns_context *ctx,
47 const sha256_pin_t *pinset_in,
48 getdns_list **pinset_list);
49
50
51 /* internal functions for associating X.509 verification processes in
52 * OpenSSL with getdns_upstream objects. */
53
54 getdns_upstream*
55 _getdns_upstream_from_x509_store(X509_STORE_CTX *store);
56
57
58 getdns_return_t
59 _getdns_associate_upstream_with_SSL(SSL *ssl,
60 getdns_upstream *upstream);
61
62 getdns_return_t
63 _getdns_verify_pinset_match(const sha256_pin_t *pinset,
64 X509_STORE_CTX *store);
65
66 #endif
67 /* pubkey-pinning.h */
4040 #include "gldns/gbuffer.h"
4141 #include "gldns/pkthdr.h"
4242 #include "dict.h"
43 #include "debug.h"
44
45 /* MAXIMUM_TSIG_SPACE = TSIG name (dname) : 256
46 * TSIG type (uint16_t) : 2
47 * TSIG class (uint16_t) : 2
48 * TSIG TTL (uint32_t) : 4
49 * RdLen (uint16_t) : 2
50 * Algorithm name (dname) : 256
51 * Time Signed (uint48_t) : 6
52 * Fudge (uint16_t) : 2
53 * Mac Size (uint16_t) : 2
54 * Mac (variable) : EVP_MAX_MD_SIZE
55 * Original Id (uint16_t) : 2
56 * Error (uint16_t) : 2
57 * Other Len (uint16_t) : 2
58 * Other Data (nothing) : 0
59 * ---- +
60 * 538 + EVP_MAX_MD_SIZE
61 */
62 #define MAXIMUM_TSIG_SPACE (538 + EVP_MAX_MD_SIZE)
4363
4464 getdns_dict dnssec_ok_checking_disabled_spc = {
4565 { RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp },
89109 GETDNS_FREE(net_req->owner->my_mf, net_req->response);
90110 }
91111
112 static uint8_t *
113 netreq_reset(getdns_network_req *net_req)
114 {
115 uint8_t *buf;
116 /* variables that need to be reset on reinit
117 */
118 net_req->unbound_id = -1;
119 net_req->state = NET_REQ_NOT_SENT;
120 net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
121 net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
122 net_req->query_id = 0;
123 net_req->response_len = 0;
124 /* Some fields to record info for return_call_reporting */
125 net_req->debug_start_time = 0;
126 net_req->debug_end_time = 0;
127 if (!net_req->query)
128 return NULL;
129
130 buf = net_req->query + GLDNS_HEADER_SIZE;
131 (void) memcpy(buf, net_req->owner->name, net_req->owner->name_len);
132 buf += net_req->owner->name_len;
133
134 gldns_write_uint16(buf, net_req->request_type);
135 gldns_write_uint16(buf + 2, net_req->owner->request_class);
136 return buf + 4;
137 }
138
92139 static int
93140 network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
94 const char *name, uint16_t request_type, uint16_t request_class,
95 int dnssec_extension_set, int with_opt,
141 uint16_t request_type, int dnssec_extension_set, int with_opt,
96142 int edns_maximum_udp_payload_size,
97143 uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit,
98144 uint16_t opt_options_size, size_t noptions, getdns_list *options,
99145 size_t wire_data_sz, size_t max_query_sz)
100146 {
101147 uint8_t *buf;
102 size_t dname_len;
103148 getdns_dict *option;
104149 uint32_t option_code;
105150 getdns_bindata *option_data;
106151 size_t i;
107152 int r = 0;
108153
154 /* variables that stay the same on reinit, don't touch
155 */
109156 net_req->request_type = request_type;
110 net_req->request_class = request_class;
111 net_req->unbound_id = -1;
112 net_req->state = NET_REQ_NOT_SENT;
113157 net_req->owner = owner;
114
115 net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
116
117 net_req->upstream = NULL;
118 net_req->fd = -1;
119 net_req->transport_count = owner->context->dns_transport_count;
120 net_req->transport_current = 0;
121 memcpy(net_req->transports, owner->context->dns_transports,
122 net_req->transport_count * sizeof(getdns_transport_list_t));
123 net_req->tls_auth_min = owner->context->tls_auth_min;
124 memset(&net_req->event, 0, sizeof(net_req->event));
125 memset(&net_req->tcp, 0, sizeof(net_req->tcp));
126 net_req->query_id = 0;
127158 net_req->edns_maximum_udp_payload_size = edns_maximum_udp_payload_size;
128159 net_req->max_udp_payload_size = edns_maximum_udp_payload_size != -1
129160 ? edns_maximum_udp_payload_size : 1432;
161 net_req->base_query_option_sz = opt_options_size;
162 net_req->wire_data_sz = wire_data_sz;
163
164 net_req->transport_count = owner->context->dns_transport_count;
165 memcpy(net_req->transports, owner->context->dns_transports,
166 net_req->transport_count * sizeof(getdns_transport_list_t));
167 net_req->tls_auth_min = owner->context->tls_auth_min;
168
169 /* state variables from the resolver, don't touch
170 */
171 net_req->upstream = NULL;
172 net_req->fd = -1;
173 net_req->transport_current = 0;
174 memset(&net_req->event, 0, sizeof(net_req->event));
175 memset(&net_req->tcp, 0, sizeof(net_req->tcp));
176 net_req->keepalive_sent = 0;
130177 net_req->write_queue_tail = NULL;
131 net_req->response_len = 0;
132 net_req->base_query_option_sz = opt_options_size;
133
134 /* Some fields to record info for return_call_debugging */
135 net_req->debug_start_time = 0;
136 net_req->debug_end_time = 0;
178 /* Some fields to record info for return_call_reporting */
137179 net_req->debug_tls_auth_status = 0;
138180 net_req->debug_udp = 0;
139181
140 net_req->wire_data_sz = wire_data_sz;
141 if (max_query_sz) {
142 /* first two bytes will contain query length (for tcp) */
143 buf = net_req->query = net_req->wire_data + 2;
144
145 gldns_write_uint16(buf + 2, 0); /* reset all flags */
146 GLDNS_RD_SET(buf);
147 if (dnssec_extension_set) /* We will do validation ourselves */
148 GLDNS_CD_SET(buf);
149 GLDNS_OPCODE_SET(buf, GLDNS_PACKET_QUERY);
150 gldns_write_uint16(buf + GLDNS_QDCOUNT_OFF, 1); /* 1 query */
151 gldns_write_uint16(buf + GLDNS_ANCOUNT_OFF, 0); /* 0 answers */
152 gldns_write_uint16(buf + GLDNS_NSCOUNT_OFF, 0); /* 0 authorities */
153 gldns_write_uint16(buf + GLDNS_ARCOUNT_OFF, with_opt ? 1 : 0);
154
155 buf += GLDNS_HEADER_SIZE;
156 dname_len = max_query_sz - GLDNS_HEADER_SIZE;
157 if ((r = gldns_str2wire_dname_buf(name, buf, &dname_len))) {
158 net_req->opt = NULL;
159 return r;
160 }
161
162 buf += dname_len;
163
164 gldns_write_uint16(buf, request_type);
165 gldns_write_uint16(buf + 2, request_class);
166 buf += 4;
167
168 if (with_opt) {
169 net_req->opt = buf;
170 buf[0] = 0; /* dname for . */
171 gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
172 gldns_write_uint16(net_req->opt + 3,
173 net_req->max_udp_payload_size);
174 buf[5] = edns_extended_rcode;
175 buf[6] = edns_version;
176 buf[7] = edns_do_bit ? 0x80 : 0;
177 buf[8] = 0;
178 gldns_write_uint16(buf + 9, opt_options_size);
179 buf += 11;
180 for (i = 0; i < noptions; i++) {
181 if (getdns_list_get_dict(options, i, &option))
182 continue;
183 if (getdns_dict_get_int(
184 option, "option_code", &option_code))
185 continue;
186 if (getdns_dict_get_bindata(
187 option, "option_data", &option_data))
188 continue;
189
190 gldns_write_uint16(buf, (uint16_t) option_code);
191 gldns_write_uint16(buf + 2,
192 (uint16_t) option_data->size);
193 (void) memcpy(buf + 4, option_data->data,
194 option_data->size);
195
196 buf += option_data->size + 4;
197 }
198 } else
199 net_req->opt = NULL;
200 net_req->response = buf;
201 gldns_write_uint16(net_req->wire_data, net_req->response - net_req->query);
202 } else {
182 if (max_query_sz == 0) {
203183 net_req->query = NULL;
204184 net_req->opt = NULL;
205185 net_req->response = net_req->wire_data;
206 }
186 netreq_reset(net_req);
187 return r;
188 }
189 /* first two bytes will contain query length (for tcp) */
190 net_req->query = net_req->wire_data + 2;
191
192 buf = net_req->query;
193 gldns_write_uint16(buf + 2, 0); /* reset all flags */
194 GLDNS_RD_SET(buf);
195 if (dnssec_extension_set) /* We will do validation ourselves */
196 GLDNS_CD_SET(buf);
197 GLDNS_OPCODE_SET(buf, GLDNS_PACKET_QUERY);
198 gldns_write_uint16(buf + GLDNS_QDCOUNT_OFF, 1); /* 1 query */
199 gldns_write_uint16(buf + GLDNS_ANCOUNT_OFF, 0); /* 0 answers */
200 gldns_write_uint16(buf + GLDNS_NSCOUNT_OFF, 0); /* 0 authorities */
201 gldns_write_uint16(buf + GLDNS_ARCOUNT_OFF, with_opt ? 1 : 0);
202
203 buf = netreq_reset(net_req);
204 if (with_opt) {
205 net_req->opt = buf;
206 buf[0] = 0; /* dname for . */
207 gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
208 gldns_write_uint16(net_req->opt + 3,
209 net_req->max_udp_payload_size);
210 buf[5] = edns_extended_rcode;
211 buf[6] = edns_version;
212 buf[7] = edns_do_bit ? 0x80 : 0;
213 buf[8] = 0;
214 gldns_write_uint16(buf + 9, opt_options_size);
215 buf += 11;
216 for (i = 0; i < noptions; i++) {
217 if (getdns_list_get_dict(options, i, &option))
218 continue;
219 if (getdns_dict_get_int(
220 option, "option_code", &option_code))
221 continue;
222 if (getdns_dict_get_bindata(
223 option, "option_data", &option_data))
224 continue;
225
226 gldns_write_uint16(buf, (uint16_t) option_code);
227 gldns_write_uint16(buf + 2,
228 (uint16_t) option_data->size);
229 (void) memcpy(buf + 4, option_data->data,
230 option_data->size);
231
232 buf += option_data->size + 4;
233 }
234 } else
235 net_req->opt = NULL;
236
237 net_req->response = buf;
238 gldns_write_uint16(net_req->wire_data, net_req->response - net_req->query);
239
207240 return r;
208241 }
209242
224257 gldns_write_uint16(req->query - 2, pktlen);
225258 }
226259 }
260
261 void
262 _getdns_netreq_reinit(getdns_network_req *netreq)
263 {
264 uint8_t *base_opt_backup;
265 size_t base_opt_rr_sz;
266
267 if (!netreq->query) {
268 (void) netreq_reset(netreq);
269 return;
270
271 } else if (!netreq->opt) {
272 /* Remove TSIG (if any) */
273 gldns_write_uint16(netreq->query + GLDNS_ARCOUNT_OFF, 0);
274 netreq->response = netreq_reset(netreq);
275 gldns_write_uint16(netreq->wire_data,
276 netreq->response - netreq->query);
277 return;
278 }
279 _getdns_network_req_clear_upstream_options(netreq);
280 base_opt_rr_sz = netreq->base_query_option_sz + 11;
281 base_opt_backup = netreq->wire_data + netreq->wire_data_sz
282 - base_opt_rr_sz;
283 (void) memcpy(base_opt_backup, netreq->opt, base_opt_rr_sz);
284 netreq->opt = netreq_reset(netreq);
285 (void) memcpy(netreq->opt, base_opt_backup, base_opt_rr_sz);
286 netreq->response = netreq->opt + base_opt_rr_sz;
287 /* Remove TSIG (if any), but leave the opt RR */
288 gldns_write_uint16(netreq->query + GLDNS_ARCOUNT_OFF, 1);
289 gldns_write_uint16(netreq->wire_data,
290 netreq->response - netreq->query);
291 }
292
227293
228294 /* add_upstream_option appends an option that is derived at send time.
229295 (you can send data as NULL and it will fill with all zeros) */
248314
249315 /* no overflow allowed for OPT size either (maybe this is overkill
250316 given the above check?) */
251 oldlen = gldns_read_uint16(req->opt + 9);
317 oldlen = gldns_read_uint16(req->opt + 9);
252318 newlen = oldlen + 4 + sz;
253319 if (newlen > UINT16_MAX)
254320 return GETDNS_RETURN_GENERIC_ERROR;
276342 return GETDNS_RETURN_GOOD;
277343 }
278344
345 size_t
346 _getdns_network_req_add_tsig(getdns_network_req *req)
347 {
348 getdns_upstream *upstream = req->upstream;
349 gldns_buffer gbuf;
350 uint16_t arcount;
351 const getdns_tsig_info *tsig_info;
352 uint8_t md_buf[EVP_MAX_MD_SIZE];
353 unsigned int md_len = EVP_MAX_MD_SIZE;
354 const EVP_MD *digester;
355
356 /* Should only be called when in stub mode */
357 assert(req->query);
358
359 if (upstream->tsig_alg == GETDNS_NO_TSIG || !upstream->tsig_dname_len)
360 return req->response - req->query;
361
362 arcount = gldns_read_uint16(req->query + 10);
363
364 #if defined(STUB_DEBUG) && STUB_DEBUG
365 /* TSIG should not have been written yet. */
366 if (req->opt) {
367 assert(arcount == 1);
368 assert(req->opt + 11 + gldns_read_uint16(req->opt + 9)
369 == req->response);
370 } else
371 assert(arcount == 0);
372 #endif
373 tsig_info = _getdns_get_tsig_info(upstream->tsig_alg);
374
375 gldns_buffer_init_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE);
376 gldns_buffer_write(&gbuf,
377 upstream->tsig_dname, upstream->tsig_dname_len); /* Name */
378 gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */
379 gldns_buffer_write_u32(&gbuf, 0); /* TTL */
380 gldns_buffer_write(&gbuf,
381 tsig_info->dname, tsig_info->dname_len); /* Algorithm Name */
382 gldns_buffer_write_u48(&gbuf, time(NULL)); /* Time Signed */
383 gldns_buffer_write_u16(&gbuf, 300); /* Fudge */
384 gldns_buffer_write_u16(&gbuf, 0); /* Error */
385 gldns_buffer_write_u16(&gbuf, 0); /* Other len */
386
387 switch (upstream->tsig_alg) {
388 #ifdef HAVE_EVP_MD5
389 case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
390 #endif
391 #ifdef HAVE_EVP_SHA1
392 case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
393 #endif
394 #ifdef HAVE_EVP_SHA224
395 case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
396 #endif
397 #ifdef HAVE_EVP_SHA256
398 case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
399 #endif
400 #ifdef HAVE_EVP_SHA384
401 case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
402 #endif
403 #ifdef HAVE_EVP_SHA512
404 case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
405 #endif
406 default : return req->response - req->query;
407 }
408
409 (void) HMAC(digester, upstream->tsig_key, upstream->tsig_size,
410 (void *)req->query, gldns_buffer_current(&gbuf) - req->query,
411 md_buf, &md_len);
412
413 gldns_buffer_rewind(&gbuf);
414 gldns_buffer_write(&gbuf,
415 upstream->tsig_dname, upstream->tsig_dname_len); /* Name */
416 gldns_buffer_write_u16(&gbuf, GETDNS_RRTYPE_TSIG); /* Type*/
417 gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */
418 gldns_buffer_write_u32(&gbuf, 0); /* TTL */
419 gldns_buffer_write_u16(&gbuf,
420 tsig_info->dname_len + 10 + md_len + 6); /* RdLen */
421 gldns_buffer_write(&gbuf,
422 tsig_info->dname, tsig_info->dname_len); /* Algorithm Name */
423 gldns_buffer_write_u48(&gbuf, time(NULL)); /* Time Signed */
424 gldns_buffer_write_u16(&gbuf, 300); /* Fudge */
425 gldns_buffer_write_u16(&gbuf, md_len); /* MAC Size */
426 gldns_buffer_write(&gbuf, md_buf, md_len); /* MAC*/
427 gldns_buffer_write(&gbuf, req->query, 2); /* Original ID */
428 gldns_buffer_write_u16(&gbuf, 0); /* Error */
429 gldns_buffer_write_u16(&gbuf, 0); /* Other len */
430
431 if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
432 return req->response - req->query;
433
434 DEBUG_STUB("Sending with TSIG, mac length: %d\n", (int)md_len);
435 req->tsig_status = GETDNS_DNSSEC_INSECURE;
436 gldns_write_uint16(req->query + 10, arcount + 1);
437 req->response = gldns_buffer_current(&gbuf);
438 return req->response - req->query;
439 }
440
441
442
443 void
444 _getdns_network_validate_tsig(getdns_network_req *req)
445 {
446 _getdns_rr_iter rr_spc, *rr;
447 _getdns_rdf_iter rdf_spc, *rdf;
448 const uint8_t *request_mac;
449 uint16_t request_mac_len;
450 uint8_t tsig_vars[MAXIMUM_TSIG_SPACE];
451 gldns_buffer gbuf;
452 const uint8_t *dname;
453 size_t dname_len;
454 const uint8_t *response_mac;
455 uint16_t response_mac_len;
456 uint8_t other_len;
457 uint8_t result_mac[EVP_MAX_MD_SIZE];
458 unsigned int result_mac_len = EVP_MAX_MD_SIZE;
459 uint16_t original_id;
460 const EVP_MD *digester;
461 HMAC_CTX ctx;
462
463 DEBUG_STUB("Validate TSIG\n");
464 for ( rr = _getdns_rr_iter_init(&rr_spc, req->query,
465 (req->response - req->query))
466 ; rr
467 ; rr = _getdns_rr_iter_next(rr)) {
468
469 if (_getdns_rr_iter_section(rr) == GLDNS_SECTION_ADDITIONAL &&
470 gldns_read_uint16(rr->rr_type) == GETDNS_RRTYPE_TSIG)
471 break;
472 }
473 if (!rr || !(rdf = _getdns_rdf_iter_init_at(&rdf_spc, rr, 3)))
474 return; /* No good TSIG sent, so nothing expected on reply */
475
476 request_mac_len = gldns_read_uint16(rdf->pos);
477 if (request_mac_len != rdf->nxt - rdf->pos - 2)
478 return;
479 DEBUG_STUB("Request MAC found length: %d\n", (int)(request_mac_len));
480 request_mac = rdf->pos + 2;
481
482 /* Now we expect a TSIG on the response! */
483 req->tsig_status = GETDNS_DNSSEC_BOGUS;
484
485 for ( rr = _getdns_rr_iter_init(
486 &rr_spc, req->response, req->response_len)
487 ; rr
488 ; rr = _getdns_rr_iter_next(rr)) {
489
490 if (_getdns_rr_iter_section(rr) == GLDNS_SECTION_ADDITIONAL &&
491 gldns_read_uint16(rr->rr_type) == GETDNS_RRTYPE_TSIG)
492 break;
493 }
494 if (!rr || !(rdf = _getdns_rdf_iter_init(&rdf_spc, rr)))
495 return;
496 gldns_buffer_init_frm_data(&gbuf, tsig_vars, MAXIMUM_TSIG_SPACE);
497
498 dname_len = gldns_buffer_remaining(&gbuf);
499 if (!(dname = _getdns_owner_if_or_as_decompressed(
500 rr, gldns_buffer_current(&gbuf), &dname_len)))
501 return;
502 if (dname == gldns_buffer_current(&gbuf))
503 gldns_buffer_skip(&gbuf, dname_len);
504 else
505 gldns_buffer_write(&gbuf, dname, dname_len);
506
507 gldns_buffer_write(&gbuf, rr->rr_type + 2, 2); /* Class */
508 gldns_buffer_write(&gbuf, rr->rr_type + 4, 4); /* TTL */
509
510 dname_len = gldns_buffer_remaining(&gbuf);
511 if (!(dname = _getdns_rdf_if_or_as_decompressed(
512 rdf, gldns_buffer_current(&gbuf), &dname_len)))
513 return;
514 if (dname == gldns_buffer_current(&gbuf))
515 gldns_buffer_skip(&gbuf, dname_len);
516 else
517 gldns_buffer_write(&gbuf, dname, dname_len);
518
519 if (!(rdf = _getdns_rdf_iter_next(rdf)) ||
520 rdf->nxt - rdf->pos != 6)
521 return;
522 gldns_buffer_write(&gbuf, rdf->pos, 6); /* Time Signed */
523
524 if (!(rdf = _getdns_rdf_iter_next(rdf)) ||
525 rdf->nxt - rdf->pos != 2)
526 return;
527 gldns_buffer_write(&gbuf, rdf->pos, 2); /* Fudge */
528
529 if (!(rdf = _getdns_rdf_iter_next(rdf))) /* mac */
530 return;
531 response_mac_len = gldns_read_uint16(rdf->pos);
532 if (response_mac_len != rdf->nxt - rdf->pos - 2)
533 return;
534 DEBUG_STUB("Response MAC found length: %d\n", (int)(response_mac_len));
535 response_mac = rdf->pos + 2;
536
537 if (!(rdf = _getdns_rdf_iter_next(rdf)) ||
538 rdf->nxt -rdf->pos != 2) /* Original ID */
539 return;
540 original_id = gldns_read_uint16(rdf->pos);
541
542 if (!(rdf = _getdns_rdf_iter_next(rdf)) ||
543 rdf->nxt - rdf->pos != 2)
544 return;
545 gldns_buffer_write(&gbuf, rdf->pos, 2); /* Error */
546
547 if (!(rdf = _getdns_rdf_iter_next(rdf))) /* Other */
548 return;
549
550 gldns_buffer_write_u16(&gbuf, 0); /* Other len */
551 other_len = gldns_read_uint16(rdf->pos);
552 if (other_len != rdf->nxt - rdf->pos - 2)
553 return;
554 if (other_len)
555 gldns_buffer_write(&gbuf, rdf->pos, other_len);
556
557 /* TSIG found */
558 DEBUG_STUB("TSIG found, original ID: %d\n", (int)original_id);
559
560 gldns_write_uint16(req->response + 10,
561 gldns_read_uint16(req->response + 10) - 1);
562 gldns_write_uint16(req->response, original_id);
563
564 switch (req->upstream->tsig_alg) {
565 #ifdef HAVE_EVP_MD5
566 case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
567 #endif
568 #ifdef HAVE_EVP_SHA1
569 case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
570 #endif
571 #ifdef HAVE_EVP_SHA224
572 case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
573 #endif
574 #ifdef HAVE_EVP_SHA256
575 case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
576 #endif
577 #ifdef HAVE_EVP_SHA384
578 case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
579 #endif
580 #ifdef HAVE_EVP_SHA512
581 case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
582 #endif
583 default : return;
584 }
585
586 HMAC_CTX_init(&ctx);
587 (void) HMAC_Init_ex(&ctx, req->upstream->tsig_key,
588 req->upstream->tsig_size, digester, NULL);
589 (void) HMAC_Update(&ctx, request_mac - 2, request_mac_len + 2);
590 (void) HMAC_Update(&ctx, req->response, rr->pos - req->response);
591 (void) HMAC_Update(&ctx, tsig_vars, gldns_buffer_position(&gbuf));
592 HMAC_Final(&ctx, result_mac, &result_mac_len);
593
594 DEBUG_STUB("Result MAC length: %d\n", (int)(result_mac_len));
595 if (result_mac_len == response_mac_len &&
596 memcmp(result_mac, response_mac, result_mac_len) == 0)
597 req->tsig_status = GETDNS_DNSSEC_SECURE;
598
599 HMAC_CTX_cleanup(&ctx);
600
601 gldns_write_uint16(req->response, gldns_read_uint16(req->query));
602 gldns_write_uint16(req->response + 10,
603 gldns_read_uint16(req->response + 10) + 1);
604 }
605
279606 void
280607 _getdns_dns_req_free(getdns_dns_req * req)
281608 {
298625
299626 GETDNS_FREE(req->my_mf, req);
300627 }
628
629 static const uint8_t no_suffixes[] = { 1, 0 };
301630
302631 /* create a new dns req to be submitted */
303632 getdns_dns_req *
363692 * And align on the 8 byte boundry (hence the (x + 7) / 8 * 8)
364693 */
365694 size_t max_query_sz, max_response_sz, netreq_sz, dnsreq_base_sz;
366 uint8_t *region;
695 uint8_t *region, *suffixes;
367696
368697 if (extensions == dnssec_ok_checking_disabled ||
369698 extensions == dnssec_ok_checking_disabled_roadblock_avoidance ||
435764 ;
436765 }
437766 max_query_sz = ( GLDNS_HEADER_SIZE
438 + strlen(name) + 1 + 4 /* dname always smaller then strlen(name) + 1 */
767 + 256 + 4 /* dname maximum 255 bytes (256 with mdns)*/
439768 + 12 + opt_options_size /* space needed for OPT (if needed) */
440769 + MAXIMUM_UPSTREAM_OPTION_SPACE
441 /* TODO: TSIG */
770 + MAXIMUM_TSIG_SPACE
442771 + 7) / 8 * 8;
443772 }
444773 max_response_sz = (( edns_maximum_udp_payload_size != -1
450779 + max_query_sz + max_response_sz + 7 ) / 8 * 8;
451780 dnsreq_base_sz = (( sizeof(getdns_dns_req)
452781 + (a_aaaa_query ? 3 : 2) * sizeof(getdns_network_req*)
782 + context->suffixes_len
453783 ) + 7) / 8 * 8;
454784
455785 if (! (region = GETDNS_XMALLOC(context->mf, uint8_t,
466796 result->netreqs[1] = NULL;
467797
468798 result->my_mf = context->mf;
469
799
800 suffixes = region + dnsreq_base_sz - context->suffixes_len;
801 assert(context->suffixes);
802 assert(context->suffixes_len);
803 memcpy(suffixes, context->suffixes, context->suffixes_len);
804
805 result->append_name = context->append_name;
806 if (!strlen(name) || name[strlen(name)-1] == '.' ||
807 result->append_name == GETDNS_APPEND_NAME_NEVER) {
808 /* Absolute query string, no appending */
809 result->suffix_len = no_suffixes[0];
810 result->suffix = no_suffixes + 1;
811 result->suffix_appended = 1;
812 } else {
813 result->suffix_len = suffixes[0];
814 result->suffix = suffixes + 1;
815 result->suffix_appended = 0;
816 }
470817 result->name_len = sizeof(result->name);
471818 if (gldns_str2wire_dname_buf(name, result->name, &result->name_len)) {
472819 GETDNS_FREE(result->my_mf, result);
473820 return NULL;
821 }
822 if (result->append_name == GETDNS_APPEND_NAME_ALWAYS) {
823 for (
824 ; result->suffix_len > 1 && *result->suffix
825 ; result->suffix += result->suffix_len
826 , result->suffix_len = *result->suffix++) {
827
828 if (result->suffix_len + result->name_len - 1 <
829 sizeof(result->name)) {
830 memcpy(result->name + result->name_len - 1,
831 result->suffix, result->suffix_len);
832 result->name_len += result->suffix_len - 1;
833 result->suffix_appended = 1;
834 break;
835 }
836 }
837 } else if (result->append_name ==
838 GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE &&
839 result->name[result->name[0]+1] != 0) {
840 /* We have multiple labels, no appending */
841 result->suffix_len = no_suffixes[0];
842 result->suffix = no_suffixes + 1;
843 result->suffix_appended = 1;
474844 }
475845 result->context = context;
476846 result->loop = loop;
487857 #endif
488858 result->edns_client_subnet_private = context->edns_client_subnet_private;
489859 result->tls_query_padding_blocksize = context->tls_query_padding_blocksize;
490 result->return_call_debugging
491 = is_extension_set(extensions, "return_call_debugging");
860 result->return_call_reporting =
861 is_extension_set(extensions, "return_call_reporting");
862 result->add_warning_for_bad_dns =
863 is_extension_set(extensions, "add_warning_for_bad_dns");
492864
493865 /* will be set by caller */
494866 result->user_pointer = NULL;
497869
498870 /* check the specify_class extension */
499871 (void) getdns_dict_get_int(extensions, "specify_class", &klass);
872 result->request_class = klass;
500873
501874 result->upstreams = context->upstreams;
502875 if (result->upstreams)
503876 result->upstreams->referenced++;
504877
505878 network_req_init(result->netreqs[0], result,
506 name, request_type, klass,
507 dnssec_extension_set, with_opt,
879 request_type, dnssec_extension_set, with_opt,
508880 edns_maximum_udp_payload_size,
509881 edns_extended_rcode, edns_version, edns_do_bit,
510882 opt_options_size, noptions, options,
511883 netreq_sz - sizeof(getdns_network_req), max_query_sz);
512884
513885 if (a_aaaa_query)
514 network_req_init(result->netreqs[1], result, name,
886 network_req_init(result->netreqs[1], result,
515887 ( request_type == GETDNS_RRTYPE_A
516 ? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ), klass,
888 ? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ),
517889 dnssec_extension_set, with_opt,
518890 edns_maximum_udp_payload_size,
519891 edns_extended_rcode, edns_version, edns_do_bit,
4343 #define ALEN(a) (sizeof(a)/sizeof(a[0]))
4444 #define UNKNOWN_RDATA NULL
4545
46 static uint8_t *
47 apl_n_rdf_end(uint8_t *pkt, uint8_t *pkt_end, uint8_t *rdf)
46 static const uint8_t *
47 apl_n_rdf_end(const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
4848 {
4949 return rdf < pkt_end ? rdf + 1 : NULL;
5050 }
5151 static getdns_return_t
52 apl_n_dict_set_value(getdns_dict *dict, uint8_t *rdf)
52 apl_n_wire2dict(getdns_dict *dict, const uint8_t *rdf)
5353 {
5454 return getdns_dict_set_int(dict, "n", (*rdf >> 7));
5555 }
5656 static getdns_return_t
57 apl_n_list_append_value(getdns_list *list, uint8_t *rdf)
57 apl_n_wire2list(getdns_list *list, const uint8_t *rdf)
5858 {
5959 return _getdns_list_append_int(list, (*rdf >> 7));
6060 }
61 static getdns_return_t
62 apl_n_2wire(uint32_t value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
63 {
64 (void)rdata; /* unused parameter */
65
66 if (*rdf_len < 1) {
67 *rdf_len = 1;
68 return GETDNS_RETURN_NEED_MORE_SPACE;
69 }
70 *rdf_len = 1;
71 *rdf = value ? 0x80 : 0x00;
72 return GETDNS_RETURN_GOOD;
73 }
74 static getdns_return_t
75 apl_n_dict2wire(const getdns_dict *dict,
76 uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
77 {
78 getdns_return_t r;
79 uint32_t value;
80
81 if ((r = getdns_dict_get_int(dict, "n", &value)))
82 return r;
83 else
84 return apl_n_2wire(value, rdata, rdf, rdf_len);
85 }
86 static getdns_return_t
87 apl_n_list2wire(const getdns_list *list, size_t i,
88 uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
89 {
90 getdns_return_t r;
91 uint32_t value;
92
93 if ((r = getdns_list_get_int(list, i, &value)))
94 return r;
95 else
96 return apl_n_2wire(value, rdata, rdf, rdf_len);
97 }
6198 static _getdns_rdf_special apl_n = {
62 apl_n_rdf_end, apl_n_dict_set_value, apl_n_list_append_value
99 apl_n_rdf_end,
100 apl_n_wire2dict, apl_n_wire2list,
101 apl_n_dict2wire, apl_n_list2wire
63102 };
64103
65 static uint8_t *
66 apl_afdpart_rdf_end(uint8_t *pkt, uint8_t *pkt_end, uint8_t *rdf)
67 {
68 uint8_t *end = rdf + (rdf[-1] & 0x7F);
104 static const uint8_t *
105 apl_afdpart_rdf_end(
106 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
107 {
108 const uint8_t *end = rdf + (rdf[-1] & 0x7F);
69109 return end <= pkt_end ? end : NULL;
70110 }
71111 static getdns_return_t
72 apl_afdpart_dict_set_value(getdns_dict *dict, uint8_t *rdf)
73 {
74 getdns_bindata bindata = { (rdf[-1] & 0x7F), rdf };
75 return getdns_dict_set_bindata(dict, "afdpart", &bindata);
76 }
77 static getdns_return_t
78 apl_afdpart_list_append_value(getdns_list *list, uint8_t *rdf)
79 {
80 getdns_bindata bindata = { (rdf[-1] & 0x7F), rdf };
81 return _getdns_list_append_bindata(list, &bindata);
112 apl_afdpart_wire2dict(getdns_dict *dict, const uint8_t *rdf)
113 {
114 return _getdns_dict_set_const_bindata(
115 dict, "afdpart", (rdf[-1] & 0x7F), rdf);
116 }
117 static getdns_return_t
118 apl_afdpart_wire2list(getdns_list *list, const uint8_t *rdf)
119 {
120 return _getdns_list_append_const_bindata(list, (rdf[-1] & 0x7F), rdf);
121 }
122 static getdns_return_t
123 apl_afdpart_2wire(
124 const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
125 {
126 if (value->size > 0x7F)
127 return GETDNS_RETURN_INVALID_PARAMETER;
128
129 if (rdf - 1 < rdata)
130 return GETDNS_RETURN_GENERIC_ERROR;
131
132 if (*rdf_len < value->size) {
133 *rdf_len = value->size;
134 return GETDNS_RETURN_NEED_MORE_SPACE;
135 }
136 *rdf_len = value->size;
137
138 /* Keeping first bit is safe because value->size <= 0x7F */
139 rdf[-1] |= value->size;
140
141 (void) memcpy(rdf, value->data, value->size);
142 return GETDNS_RETURN_GOOD;
143 }
144 static getdns_return_t
145 apl_afdpart_dict2wire(
146 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
147 {
148 getdns_return_t r;
149 getdns_bindata *value;
150
151 if ((r = getdns_dict_get_bindata(dict, "afdpart", &value)))
152 return r;
153 else
154 return apl_afdpart_2wire(value, rdata, rdf, rdf_len);
155 }
156 static getdns_return_t
157 apl_afdpart_list2wire(const getdns_list *list,
158 size_t i, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
159 {
160 getdns_return_t r;
161 getdns_bindata *value;
162
163 if ((r = getdns_list_get_bindata(list, i, &value)))
164 return r;
165 else
166 return apl_afdpart_2wire(value, rdata, rdf, rdf_len);
82167 }
83168 static _getdns_rdf_special apl_afdpart = {
84169 apl_afdpart_rdf_end,
85 apl_afdpart_dict_set_value, apl_afdpart_list_append_value
170 apl_afdpart_wire2dict, apl_afdpart_wire2list,
171 apl_afdpart_dict2wire, apl_afdpart_list2wire
86172 };
87173
88 static uint8_t *
89 ipseckey_gateway_rdf_end(uint8_t *pkt, uint8_t *pkt_end, uint8_t *rdf)
90 {
91 uint8_t *end;
174 static const uint8_t *
175 ipseckey_gateway_rdf_end(
176 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
177 {
178 const uint8_t *end;
92179
93180 if (rdf - 5 < pkt)
94181 return NULL;
115202 return end <= pkt_end ? end : NULL;
116203 }
117204 static getdns_return_t
118 ipseckey_gateway_equip_bindata(uint8_t *rdf, getdns_bindata *bindata)
119 {
120 bindata->data = rdf;
205 ipseckey_gateway_equip_const_bindata(
206 const uint8_t *rdf, size_t *size, const uint8_t **data)
207 {
208 *data = rdf;
121209 switch (rdf[-2]) {
122 case 0: bindata->size = 0;
210 case 0: *size = 0;
123211 break;
124 case 1: bindata->size = 4;
212 case 1: *size = 4;
125213 break;
126 case 2: bindata->size = 16;
214 case 2: *size = 16;
127215 break;
128216 case 3: while (*rdf)
129217 if ((*rdf & 0xC0) == 0xC0)
132220 return GETDNS_RETURN_GENERIC_ERROR;
133221 else
134222 rdf += *rdf + 1;
135 bindata->size = rdf + 1 - bindata->data;
223 *size = rdf + 1 - *data;
136224 break;
137225 default:
138226 return GETDNS_RETURN_GENERIC_ERROR;
139227 }
140228 return GETDNS_RETURN_GOOD;
141
142 }
143 static getdns_return_t
144 ipseckey_gateway_dict_set_value(getdns_dict *dict, uint8_t *rdf)
145 {
146 getdns_bindata bindata;
147
148 if (ipseckey_gateway_equip_bindata(rdf, &bindata))
229 }
230
231 static getdns_return_t
232 ipseckey_gateway_wire2dict(getdns_dict *dict, const uint8_t *rdf)
233 {
234 size_t size;
235 const uint8_t *data;
236
237 if (ipseckey_gateway_equip_const_bindata(rdf, &size, &data))
149238 return GETDNS_RETURN_GENERIC_ERROR;
150239
151 else if (! bindata.size)
240 else if (! size)
152241 return GETDNS_RETURN_GOOD;
153242 else
154 return getdns_dict_set_bindata(dict, "gateway", &bindata);
155 }
156 static getdns_return_t
157 ipseckey_gateway_list_append_value(getdns_list *list, uint8_t *rdf)
158 {
159 getdns_bindata bindata;
160
161 if (ipseckey_gateway_equip_bindata(rdf, &bindata))
243 return _getdns_dict_set_const_bindata(dict, "gateway", size, data);
244 }
245 static getdns_return_t
246 ipseckey_gateway_wire2list(getdns_list *list, const uint8_t *rdf)
247 {
248 size_t size;
249 const uint8_t *data;
250
251 if (ipseckey_gateway_equip_const_bindata(rdf, &size, &data))
162252 return GETDNS_RETURN_GENERIC_ERROR;
163253
164 else if (! bindata.size)
254 else if (!size)
165255 return GETDNS_RETURN_GOOD;
166256 else
167 return _getdns_list_append_bindata(list, &bindata);
257 return _getdns_list_append_const_bindata(list, size, data);
258 }
259 static getdns_return_t
260 ipseckey_gateway_2wire(
261 const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
262 {
263 if (rdf - 2 < rdata)
264 return GETDNS_RETURN_GENERIC_ERROR;
265
266 switch (rdf[-2]) {
267 case 0: if (value && value->size > 0)
268 return GETDNS_RETURN_INVALID_PARAMETER;
269 break;
270 case 1: if (!value || value->size != 4)
271 return GETDNS_RETURN_INVALID_PARAMETER;
272 if (*rdf_len < 4) {
273 *rdf_len = 4;
274 return GETDNS_RETURN_NEED_MORE_SPACE;
275 }
276 *rdf_len = 4;
277 (void)memcpy(rdf, value->data, 4);
278 return GETDNS_RETURN_GOOD;
279 case 2: if (!value || value->size != 16)
280 return GETDNS_RETURN_INVALID_PARAMETER;
281 if (*rdf_len < 16) {
282 *rdf_len = 16;
283 return GETDNS_RETURN_NEED_MORE_SPACE;
284 }
285 *rdf_len = 16;
286 (void)memcpy(rdf, value->data, 16);
287 return GETDNS_RETURN_GOOD;
288 case 3: if (!value || value->size == 0)
289 return GETDNS_RETURN_INVALID_PARAMETER;
290 /* Assume bindata is a valid dname; garbage in, garbage out */
291 if (*rdf_len < value->size) {
292 *rdf_len = value->size;
293 return GETDNS_RETURN_NEED_MORE_SPACE;
294 }
295 *rdf_len = value->size;
296 (void)memcpy(rdf, value->data, value->size);
297 return GETDNS_RETURN_GOOD;
298 default:
299 return GETDNS_RETURN_GENERIC_ERROR;
300 }
301 return GETDNS_RETURN_GOOD;
302 }
303 static getdns_return_t
304 ipseckey_gateway_dict2wire(
305 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
306 {
307 getdns_return_t r;
308 getdns_bindata *value;
309
310 if ((r = getdns_dict_get_bindata(dict, "gateway", &value)))
311 return r;
312 else
313 return ipseckey_gateway_2wire(value, rdata, rdf, rdf_len);
314 }
315 static getdns_return_t
316 ipseckey_gateway_list2wire(const getdns_list *list,
317 size_t i, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
318 {
319 getdns_return_t r;
320 getdns_bindata *value;
321
322 if ((r = getdns_list_get_bindata(list, i, &value)))
323 return r;
324 else
325 return ipseckey_gateway_2wire(value, rdata, rdf, rdf_len);
168326 }
169327 static _getdns_rdf_special ipseckey_gateway = {
170328 ipseckey_gateway_rdf_end,
171 ipseckey_gateway_dict_set_value, ipseckey_gateway_list_append_value
329 ipseckey_gateway_wire2dict, ipseckey_gateway_wire2list,
330 ipseckey_gateway_dict2wire, ipseckey_gateway_list2wire
172331 };
173332
174 static uint8_t *
175 hip_pk_algorithm_rdf_end(uint8_t *pkt, uint8_t *pkt_end, uint8_t *rdf)
333 static const uint8_t *
334 hip_pk_algorithm_rdf_end(
335 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
176336 {
177337 return rdf + 4 > pkt_end ? NULL
178338 : rdf + 4 + *rdf + gldns_read_uint16(rdf + 2) > pkt_end ? NULL
179339 : rdf + 1;
180340 }
181341 static getdns_return_t
182 hip_pk_algorithm_dict_set_value(getdns_dict *dict, uint8_t *rdf)
342 hip_pk_algorithm_wire2dict(getdns_dict *dict, const uint8_t *rdf)
183343 {
184344 return getdns_dict_set_int(dict, "pk_algorithm", rdf[1]);
185345 }
186346 static getdns_return_t
187 hip_pk_algorithm_list_append_value(getdns_list *list, uint8_t *rdf)
347 hip_pk_algorithm_wire2list(getdns_list *list, const uint8_t *rdf)
188348 {
189349 return _getdns_list_append_int(list, rdf[1]);
350 }
351 static getdns_return_t
352 hip_pk_algorithm_2wire(uint32_t value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
353 {
354 if (rdata != rdf)
355 return GETDNS_RETURN_GENERIC_ERROR;
356 if (value > 0xFF)
357 return GETDNS_RETURN_INVALID_PARAMETER;
358 if (*rdf_len < 4) {
359 *rdf_len = 4;
360 return GETDNS_RETURN_NEED_MORE_SPACE;
361 }
362 *rdf_len = 4;
363 rdata[1] = value;
364 return GETDNS_RETURN_GOOD;
365 }
366 static getdns_return_t
367 hip_pk_algorithm_dict2wire(
368 const getdns_dict *dict,uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
369 {
370 getdns_return_t r;
371 uint32_t value;
372
373 if ((r = getdns_dict_get_int(dict, "pk_algorithm", &value)))
374 return r;
375 else
376 return hip_pk_algorithm_2wire(value, rdata, rdf, rdf_len);
377 }
378 static getdns_return_t
379 hip_pk_algorithm_list2wire(const getdns_list *list,
380 size_t i, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
381 {
382 getdns_return_t r;
383 uint32_t value;
384
385 if ((r = getdns_list_get_int(list, i, &value)))
386 return r;
387 else
388 return hip_pk_algorithm_2wire(value, rdata, rdf, rdf_len);
190389 }
191390 static _getdns_rdf_special hip_pk_algorithm = {
192391 hip_pk_algorithm_rdf_end,
193 hip_pk_algorithm_dict_set_value, hip_pk_algorithm_list_append_value
392 hip_pk_algorithm_wire2dict, hip_pk_algorithm_wire2list,
393 hip_pk_algorithm_dict2wire, hip_pk_algorithm_list2wire
194394 };
195395
196 static uint8_t *
197 hip_hit_rdf_end(uint8_t *pkt, uint8_t *pkt_end, uint8_t *rdf)
396 static const uint8_t *
397 hip_hit_rdf_end(const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
198398 {
199399 return rdf + 3 > pkt_end ? NULL
200400 : rdf + 3 + rdf[-1] + gldns_read_uint16(rdf + 1) > pkt_end ? NULL
201401 : rdf + 1;
202402 }
203403 static getdns_return_t
204 hip_hit_dict_set_value(getdns_dict *dict, uint8_t *rdf)
205 {
206 getdns_bindata bindata = { rdf[-1], rdf + 3 };
207 return getdns_dict_set_bindata(dict, "hit", &bindata);
208 }
209 static getdns_return_t
210 hip_hit_list_append_value(getdns_list *list, uint8_t *rdf)
211 {
212 getdns_bindata bindata = { rdf[-1], rdf + 3 };
213 return _getdns_list_append_bindata(list, &bindata);
404 hip_hit_wire2dict(getdns_dict *dict, const uint8_t *rdf)
405 {
406 return _getdns_dict_set_const_bindata(dict, "hit", rdf[-1], rdf + 3);
407 }
408 static getdns_return_t
409 hip_hit_wire2list(getdns_list *list, const uint8_t *rdf)
410 {
411 return _getdns_list_append_const_bindata(list, rdf[-1], rdf + 3);
412 }
413 static getdns_return_t
414 hip_hit_2wire(
415 const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
416 {
417 if (rdata != rdf - 4)
418 return GETDNS_RETURN_GENERIC_ERROR;
419 if (value && value->size > 0xFF)
420 return GETDNS_RETURN_INVALID_PARAMETER;
421 if (!value || value->size == 0) {
422 rdata[0] = 0;
423 *rdf_len = 0;
424 return GETDNS_RETURN_GOOD;
425 }
426 if (value->size > *rdf_len) {
427 *rdf_len = value->size;
428 return GETDNS_RETURN_NEED_MORE_SPACE;
429 }
430 *rdf_len = value->size;
431 rdata[0] = value->size;
432 (void)memcpy(rdf, value->data, value->size);
433 return GETDNS_RETURN_GOOD;
434 }
435 static getdns_return_t
436 hip_hit_dict2wire(
437 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
438 {
439 getdns_return_t r;
440 getdns_bindata *value;
441
442 if ((r = getdns_dict_get_bindata(dict, "hit", &value)))
443 return r;
444 else
445 return hip_hit_2wire(value, rdata, rdf, rdf_len);
446 }
447 static getdns_return_t
448 hip_hit_list2wire(const getdns_list *list,
449 size_t i, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
450 {
451 getdns_return_t r;
452 getdns_bindata *value;
453
454 if ((r = getdns_list_get_bindata(list, i, &value)))
455 return r;
456 else
457 return hip_hit_2wire(value, rdata, rdf, rdf_len);
214458 }
215459 static _getdns_rdf_special hip_hit = {
216 hip_hit_rdf_end, hip_hit_dict_set_value, hip_hit_list_append_value
460 hip_hit_rdf_end,
461 hip_hit_wire2dict, hip_hit_wire2list,
462 hip_hit_dict2wire, hip_hit_list2wire
217463 };
218464
219 static uint8_t *
220 hip_public_key_rdf_end(uint8_t *pkt, uint8_t *pkt_end, uint8_t *rdf)
465 static const uint8_t *
466 hip_public_key_rdf_end(
467 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
221468 {
222469 return rdf + 2 > pkt_end ? NULL
223470 : rdf + 2 + rdf[-2] + gldns_read_uint16(rdf) > pkt_end ? NULL
224471 : rdf + 2 + rdf[-2] + gldns_read_uint16(rdf);
225472 }
226473 static getdns_return_t
227 hip_public_key_dict_set_value(getdns_dict *dict, uint8_t *rdf)
228 {
229 getdns_bindata bindata = { gldns_read_uint16(rdf), rdf + 2 + rdf[-2] };
230 return getdns_dict_set_bindata(dict, "public_key", &bindata);
231 }
232 static getdns_return_t
233 hip_public_key_list_append_value(getdns_list *list, uint8_t *rdf)
234 {
235 getdns_bindata bindata = { gldns_read_uint16(rdf), rdf + 2 + rdf[-2] };
236 return _getdns_list_append_bindata(list, &bindata);
474 hip_public_key_wire2dict(getdns_dict *dict, const uint8_t *rdf)
475 {
476 return _getdns_dict_set_const_bindata(
477 dict, "public_key", gldns_read_uint16(rdf), rdf + 2 + rdf[-2]);
478 }
479 static getdns_return_t
480 hip_public_key_wire2list(getdns_list *list, const uint8_t *rdf)
481 {
482 return _getdns_list_append_const_bindata(
483 list, gldns_read_uint16(rdf), rdf + 2 + rdf[-2]);
484 }
485 static getdns_return_t
486 hip_public_key_2wire(
487 const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
488 {
489 if (rdata > rdf - 4 || rdata + 4 + rdata[0] != rdf)
490 return GETDNS_RETURN_GENERIC_ERROR;
491 if (value && value->size > 0xFFFF)
492 return GETDNS_RETURN_INVALID_PARAMETER;
493 if (!value || value->size == 0) {
494 rdata[2] = rdata[3] = 0;
495 *rdf_len = 0;
496 return GETDNS_RETURN_GOOD;
497 }
498 if (value->size > *rdf_len) {
499 *rdf_len = value->size;
500 return GETDNS_RETURN_NEED_MORE_SPACE;
501 }
502 *rdf_len = value->size;
503 gldns_write_uint16(rdata + 2, value->size);
504 (void)memcpy(rdf, value->data, value->size);
505 return GETDNS_RETURN_GOOD;
506 }
507 static getdns_return_t
508 hip_public_key_dict2wire(
509 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
510 {
511 getdns_return_t r;
512 getdns_bindata *value;
513
514 if ((r = getdns_dict_get_bindata(dict, "public_key", &value)))
515 return r;
516 else
517 return hip_public_key_2wire(value, rdata, rdf, rdf_len);
518 }
519 static getdns_return_t
520 hip_public_key_list2wire(
521 const getdns_list *list, size_t i, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
522 {
523 getdns_return_t r;
524 getdns_bindata *value;
525
526 if ((r = getdns_list_get_bindata(list, i, &value)))
527 return r;
528 else
529 return hip_public_key_2wire(value, rdata, rdf, rdf_len);
237530 }
238531 static _getdns_rdf_special hip_public_key = {
239532 hip_public_key_rdf_end,
240 hip_public_key_dict_set_value, hip_public_key_list_append_value
533 hip_public_key_wire2dict, hip_public_key_wire2list,
534 hip_public_key_dict2wire, hip_public_key_list2wire
241535 };
242536
243537
7401034 return _getdns_rr_def_lookup(rr_type)->name;
7411035 }
7421036
1037 static void
1038 write_int_rdata(gldns_buffer *buf, _getdns_rdf_type type, uint32_t value)
1039 {
1040 size_t j;
1041
1042 for (j = type & GETDNS_RDF_FIXEDSZ; j; j--)
1043 gldns_buffer_write_u8(buf,
1044 (uint8_t)(value >> (8 * (j - 1))) & 0xff);
1045 }
1046
1047 static void
1048 write_bindata_rdata(gldns_buffer *buf,
1049 _getdns_rdf_type type, getdns_bindata *bindata)
1050 {
1051 if (type & GETDNS_RDF_LEN_VAL)
1052 write_int_rdata(buf, type >> 8, bindata->size);
1053
1054 gldns_buffer_write(buf, bindata->data, bindata->size);
1055 }
1056
1057
1058 static getdns_return_t
1059 write_rdata_field(gldns_buffer *buf, uint8_t *rdata_start,
1060 const _getdns_rdata_def *rd_def, getdns_dict *rdata)
1061 {
1062 getdns_return_t r;
1063 getdns_list *list;
1064 uint32_t value;
1065 getdns_bindata *bindata;
1066 size_t i, rdf_len;
1067
1068 if (rd_def->type & GETDNS_RDF_INTEGER) {
1069 if (!(rd_def->type & GETDNS_RDF_REPEAT)) {
1070 if ((r = getdns_dict_get_int(
1071 rdata, rd_def->name, &value)))
1072 return r;
1073 else
1074 write_int_rdata(buf, rd_def->type, value);
1075
1076 } else if ((r = getdns_dict_get_list(
1077 rdata, rd_def->name, &list)))
1078
1079 return r == GETDNS_RETURN_NO_SUCH_DICT_NAME
1080 ? GETDNS_RETURN_GOOD : r;
1081
1082 else for ( i = 0
1083 ; GETDNS_RETURN_GOOD ==
1084 (r = getdns_list_get_int(list, i, &value))
1085 ; i++)
1086 write_int_rdata(buf, rd_def->type, value);
1087
1088
1089 } else if (rd_def->type & GETDNS_RDF_BINDATA) {
1090
1091
1092 if (!(rd_def->type & GETDNS_RDF_REPEAT)) {
1093 if ((r = getdns_dict_get_bindata(
1094 rdata, rd_def->name, &bindata)))
1095 return r;
1096 else
1097 write_bindata_rdata(buf, rd_def->type, bindata);
1098
1099 } else if ((r = getdns_dict_get_list(
1100 rdata, rd_def->name, &list)))
1101
1102 return r == GETDNS_RETURN_NO_SUCH_DICT_NAME
1103 ? GETDNS_RETURN_GOOD : r;
1104
1105 else for ( i = 0
1106 ; GETDNS_RETURN_GOOD ==
1107 (r = getdns_list_get_bindata(list, i, &bindata))
1108 ; i++)
1109 write_bindata_rdata(buf, rd_def->type, bindata);
1110
1111
1112 } else if (!(rd_def->type & GETDNS_RDF_SPECIAL)) {
1113 /* Unknown rdata type */
1114 return GETDNS_RETURN_GENERIC_ERROR;
1115
1116 } else if (!(rd_def->type & GETDNS_RDF_REPEAT)) {
1117
1118 rdf_len = gldns_buffer_remaining(buf);
1119 r = rd_def->special->dict2wire(rdata, rdata_start,
1120 gldns_buffer_current(buf), &rdf_len);
1121 if (r == GETDNS_RETURN_GOOD ||
1122 r == GETDNS_RETURN_NEED_MORE_SPACE)
1123 gldns_buffer_skip(buf, rdf_len);
1124 if (r)
1125 return r;
1126
1127 } else if ((r = getdns_dict_get_list(rdata, rd_def->name, &list))) {
1128
1129 return r == GETDNS_RETURN_NO_SUCH_DICT_NAME
1130 ? GETDNS_RETURN_GOOD : r;
1131
1132 } else for ( i = 0; r == GETDNS_RETURN_GOOD; i++ ) {
1133
1134 rdf_len = gldns_buffer_remaining(buf);
1135 r = rd_def->special->list2wire(list, i, rdata_start,
1136 gldns_buffer_current(buf), &rdf_len);
1137 if (r == GETDNS_RETURN_GOOD ||
1138 r == GETDNS_RETURN_NEED_MORE_SPACE)
1139 gldns_buffer_skip(buf, rdf_len);
1140 }
1141
1142 return r != GETDNS_RETURN_NO_SUCH_LIST_ITEM ? r : GETDNS_RETURN_GOOD;
1143 }
1144
7431145 getdns_return_t
744 _getdns_rr_dict2wire(getdns_dict *rr_dict, gldns_buffer *buf)
1146 _getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
7451147 {
7461148 getdns_return_t r = GETDNS_RETURN_GOOD;
747 struct getdns_bindata *name;
748 struct getdns_bindata *rdata_raw;
749 struct getdns_bindata *bindata;
750 struct getdns_dict *rdata;
1149 getdns_bindata *name;
1150 getdns_bindata *rdata_raw;
1151 getdns_dict *rdata;
7511152 uint32_t rr_type;
7521153 uint32_t rr_class = GETDNS_RRCLASS_IN;
7531154 uint32_t rr_ttl = 0;
754 uint32_t value;
7551155 const _getdns_rr_def *rr_def;
756 const _getdns_rdata_def *rd_def;
757 int n_rdata_fields;
758 size_t j, rdata_size_mark;
1156 const _getdns_rdata_def *rd_def, *rep_rd_def;
1157 int n_rdata_fields, rep_n_rdata_fields;
1158 size_t rdata_size_mark;
1159 uint8_t *rdata_start;
1160 getdns_list *list;
1161 size_t i;
7591162
7601163 assert(rr_dict);
7611164 assert(buf);
7621165
7631166 if ((r = getdns_dict_get_bindata(rr_dict, "name", &name)))
764 goto error;
1167 return r;
7651168 gldns_buffer_write(buf, name->data, name->size);
7661169
7671170 if ((r = getdns_dict_get_int(rr_dict, "type", &rr_type)))
768 goto error;
1171 return r;
7691172 gldns_buffer_write_u16(buf, (uint16_t)rr_type);
7701173
7711174 (void) getdns_dict_get_int(rr_dict, "class", &rr_class);
7861189 break;
7871190 }
7881191
789 if ((r = getdns_dict_get_dict(rr_dict, "rdata", &rdata)))
790 goto error;
791
792 if (n_rdata_fields == 0 && GETDNS_RETURN_GOOD ==
1192 if ((r = getdns_dict_get_dict(rr_dict, "rdata", &rdata))) {
1193 if (r == GETDNS_RETURN_NO_SUCH_DICT_NAME) {
1194 gldns_buffer_write_u16(buf, 0);
1195 r = GETDNS_RETURN_GOOD;
1196 }
1197
1198 } else if (n_rdata_fields == 0 && GETDNS_RETURN_GOOD ==
7931199 (r = getdns_dict_get_bindata(rdata, "rdata_raw", &rdata_raw))) {
7941200
7951201 gldns_buffer_write_u16(buf, (uint16_t)rdata_raw->size);
7971203
7981204 } else if (n_rdata_fields || r == GETDNS_RETURN_NO_SUCH_DICT_NAME) {
7991205
1206 r = GETDNS_RETURN_GOOD;
8001207 rdata_size_mark = gldns_buffer_position(buf);
8011208 gldns_buffer_skip(buf, 2);
1209 rdata_start = gldns_buffer_current(buf);
8021210
8031211 for ( rd_def = rr_def->rdata
8041212 , n_rdata_fields = rr_def->n_rdata_fields
8051213 ; n_rdata_fields ; n_rdata_fields-- , rd_def++ ) {
8061214
807 if (rd_def->type & GETDNS_RDF_BINDATA) {
808 if ((r = getdns_dict_get_bindata(rdata,
809 rd_def->name, &bindata)))
810 break;
811
812 gldns_buffer_write(buf, bindata->data
813 , bindata->size );
814 continue;
815 }
816 if (!(rd_def->type & GETDNS_RDF_INTEGER)) {
817 r = GETDNS_RETURN_GENERIC_ERROR;
1215 if (rd_def->type == GETDNS_RDF_REPEAT)
1216 break;
1217
1218 if ((r = write_rdata_field(buf,
1219 rdata_start, rd_def, rdata)))
1220 break;
1221 }
1222 if (n_rdata_fields == 0 || r) {
1223 /* pass */;
1224
1225 } else if ((r = getdns_dict_get_list(
1226 rdata, rd_def->name, &list))) {
1227 /* pass */;
1228
1229 } else for ( i = 0
1230 ; r == GETDNS_RETURN_GOOD
1231 ; i++) {
1232
1233 if ((r = getdns_list_get_dict(list, i, &rdata))) {
1234 if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
1235 r = GETDNS_RETURN_GOOD;
8181236 break;
8191237 }
820 if ((r = getdns_dict_get_int(
821 rdata, rd_def->name, &value)))
822 break;
823
824 for (j = rd_def->type & GETDNS_RDF_FIXEDSZ; j; j--)
825 gldns_buffer_write_u8(buf,
826 (uint8_t)(value >> (8 * (j - 1))) & 0xff);
1238 for ( rep_rd_def = rd_def + 1
1239 , rep_n_rdata_fields = n_rdata_fields - 1
1240 ; rep_n_rdata_fields
1241 ; rep_n_rdata_fields--, rep_rd_def++ ) {
1242
1243 if ((r = write_rdata_field(buf,
1244 rdata_start, rep_rd_def, rdata)))
1245 break;
1246 }
8271247 }
8281248 gldns_buffer_write_u16_at(buf, rdata_size_mark,
8291249 (uint16_t)(gldns_buffer_position(buf)-rdata_size_mark-2));
8301250 }
831 error:
8321251 return r;
8331252 }
8341253
3535 #include "getdns/getdns.h"
3636 #include "gldns/gbuffer.h"
3737
38 typedef uint8_t *(*_getdns_rdf_end_t)(
39 uint8_t *pkt, uint8_t *pkt_end, uint8_t *rdf);
38 /* rdf_end returns a pointer to the end of this rdf's data,
39 * i.e. where the next rdata field will start.
40 */
41 typedef const uint8_t *(*_getdns_rdf_end_t)(
42 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf);
4043 /* Limit checks are already done with _getdns_rdf_end_t */
41 typedef getdns_return_t (*_getdns_rdf_dict_set_value_t)(
42 getdns_dict *dict, uint8_t *rdf);
43 typedef getdns_return_t (*_getdns_rdf_list_append_value_t)(
44 getdns_list *list, uint8_t *rdf);
44 typedef getdns_return_t (*_getdns_rdf_wire2dict_t)(
45 getdns_dict *dict, const uint8_t *rdf);
46 typedef getdns_return_t (*_getdns_rdf_wire2list_t)(
47 getdns_list *list, const uint8_t *rdf);
48 typedef getdns_return_t (*_getdns_rdf_dict2wire_t)(
49 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len);
50 typedef getdns_return_t (*_getdns_rdf_list2wire_t)(
51 const getdns_list *list, size_t index,
52 uint8_t *rdata, uint8_t *rdf, size_t *rdf_len);
4553
4654 typedef struct _getdns_rdf_special {
47 _getdns_rdf_end_t rdf_end;
48 _getdns_rdf_dict_set_value_t dict_set_value;
49 _getdns_rdf_list_append_value_t list_append_value;
55 _getdns_rdf_end_t rdf_end;
56 _getdns_rdf_wire2dict_t wire2dict;
57 _getdns_rdf_wire2list_t wire2list;
58 _getdns_rdf_dict2wire_t dict2wire;
59 _getdns_rdf_list2wire_t list2wire;
5060 } _getdns_rdf_special;
5161
5262 /* draft-levine-dnsextlang'ish type rr and rdata definitions */
119129 } _getdns_rdf_type;
120130
121131 typedef struct _getdns_rdata_def {
122 const char *name;
132 const char *name;
123133 _getdns_rdf_type type;
124134 _getdns_rdf_special *special;
125135 } _getdns_rdata_def;
126136
127137 typedef struct _getdns_rr_def {
128 const char *name;
138 const char *name;
129139 const _getdns_rdata_def *rdata;
130 int n_rdata_fields;
140 int n_rdata_fields;
131141 } _getdns_rr_def;
132142
133143 const _getdns_rr_def *_getdns_rr_def_lookup(uint16_t rr_type);
134144
135145 getdns_return_t _getdns_rr_dict2wire(
136 getdns_dict *rr_dict, gldns_buffer *buf);
146 const getdns_dict *rr_dict, gldns_buffer *buf);
137147
138148 const char *_getdns_rr_type_name(int rr_type);
139149
3838 assert(i);
3939 assert(i->rr_type);
4040
41 i->nxt = i->n < GLDNS_QDCOUNT(i->pkt)
41 i->nxt = i->pkt && i->n < GLDNS_QDCOUNT(i->pkt)
4242 ? i->rr_type + 4
4343 : i->rr_type + 10 > i->pkt_end
4444 ? i->pkt_end
5050 static _getdns_rr_iter *
5151 find_rrtype(_getdns_rr_iter *i)
5252 {
53 uint8_t *pos;
53 const uint8_t *pos;
5454
5555 assert(i);
5656 assert(i->pos);
5757
5858 /* Past the last RR in the pkt */
59 if (GLDNS_QDCOUNT(i->pkt) + GLDNS_ANCOUNT(i->pkt) +
59 if (i->pkt &&
60 GLDNS_QDCOUNT(i->pkt) + GLDNS_ANCOUNT(i->pkt) +
6061 GLDNS_NSCOUNT(i->pkt) + GLDNS_ARCOUNT(i->pkt) <= i->n)
6162 goto done;
6263
8283 }
8384
8485 _getdns_rr_iter *
85 _getdns_rr_iter_init(_getdns_rr_iter *i, uint8_t *pkt, size_t pkt_len)
86 _getdns_rr_iter_init(_getdns_rr_iter *i, const uint8_t *pkt, size_t pkt_len)
8687 {
8788 assert(i);
8889
99100 }
100101
101102 _getdns_rr_iter *
103 _getdns_single_rr_iter_init(
104 _getdns_rr_iter *i, const uint8_t *wire, size_t wire_len)
105 {
106 assert(i);
107
108 if (!wire || wire_len < 5 /* name + type + class */) {
109 i->pos = NULL;
110 return NULL;
111 }
112 i->pkt = NULL;
113 i->pos = wire;
114 i->pkt_end = wire + wire_len;
115 i->n = 0;
116
117 return find_rrtype(i);
118 }
119
120
121 _getdns_rr_iter *
102122 _getdns_rr_iter_rewind(_getdns_rr_iter *i)
103123 {
104124 assert(i);
120140 return find_rrtype(i);
121141 }
122142
123 static uint8_t *
124 dname_if_or_as_decompressed(uint8_t *pkt, uint8_t *pkt_end, uint8_t *pos,
125 uint8_t *buf, size_t *len, size_t refs)
143 static const uint8_t *
144 dname_if_or_as_decompressed(const uint8_t *pkt, const uint8_t *pkt_end,
145 const uint8_t *pos, uint8_t *buf, size_t *len, size_t refs)
126146 {
127147 uint16_t offset;
128 uint8_t *start, *dst;
129
130 assert(pkt);
148 const uint8_t *start;
149 uint8_t *dst;
150
131151 assert(pkt_end);
132152 assert(pos);
133153 assert(buf);
137157 goto error;
138158
139159 if ((*pos & 0xC0) == 0xC0) {
140 if (pos + 1 >= pkt_end)
160 if (!pkt || pos + 1 >= pkt_end)
141161 goto error;
142162 offset = gldns_read_uint16(pos) & 0x3FFF;
143163 if (pkt + offset >= pkt_end)
174194 start = pos;
175195 }
176196 if ((*pos & 0xC0) == 0xC0) {
177 if (pos + 1 >= pkt_end)
197 if (!pkt || pos + 1 >= pkt_end)
178198 goto error;
179199 offset = gldns_read_uint16(pos) & 0x3FFF;
180200 if (pkt + offset >= pkt_end)
203223 return NULL;
204224 }
205225
206 uint8_t *
226 const uint8_t *
207227 _getdns_owner_if_or_as_decompressed(_getdns_rr_iter *i,
208228 uint8_t *ff_bytes, size_t *len)
209229 {
214234 static _getdns_rdf_iter *
215235 rdf_iter_find_nxt(_getdns_rdf_iter *i)
216236 {
217 uint8_t *pos;
237 const uint8_t *pos;
218238
219239 assert(i);
220240 assert(i->pos);
278298
279299 i->end = NULL;
280300 /* rr_iter already done or in question section */
281 if (!rr->pos || rr->n < GLDNS_QDCOUNT(rr->pkt))
301 if (!rr->pos || _getdns_rr_iter_section(rr) == GLDNS_SECTION_QUESTION)
282302 goto done;
283303
284304 i->pkt = rr->pkt;
333353 return i;
334354 }
335355
336 uint8_t *
356 const uint8_t *
337357 _getdns_rdf_if_or_as_decompressed(
338358 _getdns_rdf_iter *i, uint8_t *ff_bytes, size_t *len)
339359 {
3737 #include "gldns/gbuffer.h"
3838
3939 typedef struct _getdns_rr_iter {
40 uint8_t *pkt;
41 uint8_t *pkt_end;
40 const uint8_t *pkt;
41 const uint8_t *pkt_end;
4242
4343 /* Which RR are we currently at */
4444 size_t n;
4646 /* pos points to start of the owner name the RR.
4747 * Or is NULL when there are no RR's left.
4848 */
49 uint8_t *pos;
49 const uint8_t *pos;
5050
5151 /* rr_type will point to the rr_type right after the RR's owner name.
5252 * rr_type is guaranteed to have a value when pos has a value
5353 */
54 uint8_t *rr_type;
54 const uint8_t *rr_type;
5555
5656 /* nxt point to the owner name of the next RR or to pkt_end */
57 uint8_t *nxt;
57 const uint8_t *nxt;
5858
5959 } _getdns_rr_iter;
6060
6161 _getdns_rr_iter *_getdns_rr_iter_init(_getdns_rr_iter *i,
62 uint8_t *pkt, size_t pkt_len);
62 const uint8_t *pkt, const size_t pkt_len);
63
64 _getdns_rr_iter *_getdns_single_rr_iter_init(_getdns_rr_iter *i,
65 const uint8_t *wire, const size_t wire_len);
6366
6467 _getdns_rr_iter *_getdns_rr_iter_rewind(_getdns_rr_iter *i);
6568
6669 _getdns_rr_iter *_getdns_rr_iter_next(_getdns_rr_iter *i);
6770
68 uint8_t *_getdns_owner_if_or_as_decompressed(
71 const uint8_t *_getdns_owner_if_or_as_decompressed(
6972 _getdns_rr_iter *i, uint8_t *ff_bytes, size_t *len);
7073
7174 static inline gldns_pkt_section
7275 _getdns_rr_iter_section(_getdns_rr_iter *i)
7376 {
74 return i->n < GLDNS_QDCOUNT(i->pkt) ? GLDNS_SECTION_QUESTION
77 return !i->pkt ? (i->nxt - i->rr_type == 4 ? GLDNS_SECTION_QUESTION
78 : GLDNS_SECTION_ANSWER )
79 : i->n < GLDNS_QDCOUNT(i->pkt) ? GLDNS_SECTION_QUESTION
7580 : i->n < GLDNS_QDCOUNT(i->pkt)
7681 + GLDNS_ANCOUNT(i->pkt) ? GLDNS_SECTION_ANSWER
7782 : i->n < GLDNS_QDCOUNT(i->pkt)
8590 }
8691
8792 typedef struct piv_getdns_rdf_iter {
88 uint8_t *pkt;
89 uint8_t *pkt_end;
93 const uint8_t *pkt;
94 const uint8_t *pkt_end;
9095 const _getdns_rdata_def *rdd_pos;
9196 const _getdns_rdata_def *rdd_end;
9297 const _getdns_rdata_def *rdd_repeat;
93 uint8_t *pos;
94 uint8_t *end;
95 uint8_t *nxt;
98 const uint8_t *pos;
99 const uint8_t *end;
100 const uint8_t *nxt;
96101 } _getdns_rdf_iter;
97102
98103 _getdns_rdf_iter *_getdns_rdf_iter_init(_getdns_rdf_iter *i,
103108 _getdns_rdf_iter *_getdns_rdf_iter_init_at(_getdns_rdf_iter *i,
104109 _getdns_rr_iter *rr, size_t pos);
105110
106 uint8_t *_getdns_rdf_if_or_as_decompressed(
111 const uint8_t *_getdns_rdf_if_or_as_decompressed(
107112 _getdns_rdf_iter *i, uint8_t *ff_bytes, size_t *len);
108113
109114 #endif
3030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131 */
3232
33 #include "config.h"
34 #include "debug.h"
3335 #include <openssl/err.h>
3436 #include <openssl/conf.h>
3537 #include <openssl/x509v3.h>
36 #include "config.h"
3738 #include <fcntl.h>
3839 #include "stub.h"
3940 #include "gldns/gbuffer.h"
4041 #include "gldns/pkthdr.h"
4142 #include "gldns/rrdef.h"
4243 #include "gldns/str2wire.h"
44 #include "gldns/wire2str.h"
4345 #include "rr-iter.h"
4446 #include "context.h"
4547 #include "util-internal.h"
4648 #include "general.h"
49 #include "pubkey-pinning.h"
50
51 #ifdef USE_WINSOCK
52 #define EINPROGRESS 112
53 #define EWOULDBLOCK 140
54 typedef u_short sa_family_t;
55 #include "util/winsock_event.h"
56 #endif
4757
4858 #define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
4959 #define STUB_TLS_SETUP_ERROR -4
5262
5363 /* Don't currently have access to the context whilst doing handshake */
5464 #define TIMEOUT_TLS 2500
65 /* Arbritray number of message for EDNS keepalive resend*/
66 #define EDNS_KEEPALIVE_RESEND 5
5567
5668 static time_t secret_rollover_time = 0;
5769 static uint32_t secret = 0;
7385 static void netreq_upstream_write_cb(void *userarg);
7486 static int fallback_on_write(getdns_network_req *netreq);
7587
76 static void stub_tcp_write_cb(void *userarg);
7788 static void stub_timeout_cb(void *userarg);
7889 /*****************************/
7990 /* General utility functions */
144155 }
145156
146157 static getdns_return_t
158 attach_edns_keepalive(getdns_network_req *req)
159 {
160 /* Client always sends length 0, omits the timeout */
161 return _getdns_network_req_add_upstream_option(req,
162 GLDNS_EDNS_KEEPALIVE,
163 0, NULL);
164 }
165
166 static getdns_return_t
147167 attach_edns_cookie(getdns_network_req *req)
148168 {
149169 getdns_upstream *upstream = req->upstream;
181201
182202 }
183203
204 /* Will find a matching OPT RR, but leaves the caller to validate it*/
184205 static int
185 match_and_process_server_cookie(
186 getdns_upstream *upstream, uint8_t *response, size_t response_len)
206 match_edns_opt_rr(uint16_t code, uint8_t *response, size_t response_len,
207 const uint8_t **position, uint16_t *option_len)
187208 {
188209 _getdns_rr_iter rr_iter_storage, *rr_iter;
189 uint8_t *pos;
210 const uint8_t *pos;
190211 uint16_t rdata_len, opt_code = 0, opt_len = 0;
191212
192213 /* Search for the OPT RR (if any) */
209230
210231 pos = rr_iter->rr_type + 8;
211232
212 /* OPT found, now search for the cookie option */
233 #if defined(STUB_DEBUG) && STUB_DEBUG
234 char str_spc[8192], *str = str_spc;
235 size_t str_len = sizeof(str_spc);
236 uint8_t *data = (uint8_t *)rr_iter->pos;
237 size_t data_len = rr_iter->nxt - rr_iter->pos;
238 (void) gldns_wire2str_rr_scan(
239 &data, &data_len, &str, &str_len, (uint8_t *)rr_iter->pkt, rr_iter->pkt_end - rr_iter->pkt);
240 DEBUG_STUB("OPT RR: %s", str_spc);
241 #endif
242
243 /* OPT found, now search for the specified option */
213244 if (pos + 2 > rr_iter->nxt)
214245 return 1; /* FORMERR */
215246
222253 opt_len = gldns_read_uint16(pos); pos += 2;
223254 if (pos + opt_len > rr_iter->nxt)
224255 return 1; /* FORMERR */
225 if (opt_code == EDNS_COOKIE_OPCODE)
256 if (opt_code == code)
226257 break;
227258 pos += opt_len; /* Skip unknown options */
228259 }
229 if (pos >= rr_iter->nxt || opt_code != EDNS_COOKIE_OPCODE)
260 if (pos >= rr_iter->nxt || opt_code != code)
230261 return 0; /* Everything OK, just no cookie found. */
231
232 if (opt_len < 16 || opt_len > 40)
262 *position = pos;
263 *option_len = opt_len;
264 return 2;
265 }
266
267 /* TODO: Test combinations of EDNS0 options*/
268 static int
269 match_and_process_server_cookie(
270 getdns_upstream *upstream, uint8_t *response, size_t response_len)
271 {
272 const uint8_t *position = NULL;
273 uint16_t option_len = 0;
274 int found = match_edns_opt_rr(EDNS_COOKIE_OPCODE, response,
275 response_len, &position, &option_len);
276 if (found != 2)
277 return found;
278
279 if (option_len < 16 || option_len > 40)
233280 return 1; /* FORMERR */
234281
235282 if (!upstream->has_client_cookie)
236283 return 1; /* Cookie reply, but we didn't sent one */
237284
238 if (memcmp(upstream->client_cookie, pos, 8) != 0) {
285 if (memcmp(upstream->client_cookie, position, 8) != 0) {
239286 if (!upstream->has_prev_client_cookie)
240287 return 1; /* Cookie didn't match */
241 if (memcmp(upstream->prev_client_cookie, pos, 8) != 0)
288 if (memcmp(upstream->prev_client_cookie, position, 8) != 0)
242289 return 1; /* Previous cookie didn't match either */
243290
244291 upstream->has_server_cookie = 0;
246293 * is for our previous client cookie
247294 */
248295 }
249 pos += 8;
250 opt_len -= 8;
296 position += 8;
297 option_len -= 8;
251298 upstream->has_server_cookie = 1;
252 upstream->server_cookie_len = opt_len;
253 (void) memcpy(upstream->server_cookie, pos, opt_len);
299 upstream->server_cookie_len = option_len;
300 (void) memcpy(upstream->server_cookie, position, option_len);
254301 return 0;
255302 }
256303
257304 static int
258 create_starttls_request(getdns_dns_req *dnsreq, getdns_upstream *upstream,
259 getdns_eventloop *loop)
260 {
261 getdns_return_t r = GETDNS_RETURN_GOOD;
262 getdns_dict* extensions = getdns_dict_create_with_context(dnsreq->context);
263 if (!extensions) {
264 return 0;
265 }
266 r = getdns_dict_set_int(extensions, "specify_class", GLDNS_RR_CLASS_CH);
267 if (r != GETDNS_RETURN_GOOD) {
268 getdns_dict_destroy(extensions);
269 return 0;
270 }
271 upstream->starttls_req = _getdns_dns_req_new(dnsreq->context, loop,
272 "STARTTLS", GETDNS_RRTYPE_TXT, extensions);
273 /*TODO[TLS]: TO BIT*/
274 if (upstream->starttls_req == NULL)
275 return 0;
276 getdns_dict_destroy(extensions);
277
278 upstream->starttls_req->netreqs[0]->upstream = upstream;
279 return 1;
280 }
281
282 static int
283 is_starttls_response(getdns_network_req *netreq)
284 {
285 _getdns_rr_iter rr_iter_storage, *rr_iter;
286 _getdns_rdf_iter rdf_iter_storage, *rdf_iter;
287 uint16_t rr_type;
288 gldns_pkt_section section;
289 uint8_t starttls_name_space[256], *starttls_name;
290 uint8_t owner_name_space[256], *owner_name;
291 size_t starttls_name_len = sizeof(starttls_name_space);
292 size_t owner_name_len = sizeof(owner_name_space);;
293
294 /* Servers that are not STARTTLS aware will refuse the CH query*/
295 if (GLDNS_RCODE_NOERROR != GLDNS_RCODE_WIRE(netreq->response))
296 return 0;
297
298 if (GLDNS_ANCOUNT(netreq->response) != 1)
299 return 0;
300
301 for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage
302 , netreq->response
303 , netreq->response_len)
304 ; rr_iter
305 ; rr_iter = _getdns_rr_iter_next(rr_iter)) {
306
307 section = _getdns_rr_iter_section(rr_iter);
308 rr_type = gldns_read_uint16(rr_iter->rr_type);
309 if (section != GLDNS_SECTION_ANSWER
310 || rr_type != GETDNS_RRTYPE_TXT)
311 continue;
312
313 owner_name = _getdns_owner_if_or_as_decompressed(
314 rr_iter, owner_name_space, &owner_name_len);
315 if (!_getdns_dname_equal(netreq->owner->name, owner_name))
316 continue;
317
318 if (!(rdf_iter = _getdns_rdf_iter_init(
319 &rdf_iter_storage, rr_iter)))
320 continue;
321
322 if ((starttls_name = _getdns_rdf_if_or_as_decompressed(
323 rdf_iter, starttls_name_space, &starttls_name_len)) &&
324 _getdns_dname_equal(starttls_name, owner_name))
325 return 1;
326
327 return 0;
305 process_keepalive(
306 getdns_upstream *upstream, getdns_network_req *netreq,
307 uint8_t *response, size_t response_len)
308 {
309 const uint8_t *position = NULL;
310 uint16_t option_len = 0;
311 int found = match_edns_opt_rr(GLDNS_EDNS_KEEPALIVE, response,
312 response_len, &position, &option_len);
313 if (found != 2) {
314 if (netreq->keepalive_sent == 1)
315 /* If no keepalive sent back, then we must use 0 idle timeout
316 as server does not support it.*/
317 upstream->keepalive_timeout = 0;
318 return found;
319 }
320 if (option_len != 2)
321 return 1; /* FORMERR */
322 /* Use server sent value unless the client specified a shorter one.
323 Convert to ms first (wire value has units of 100ms) */
324 uint64_t server_keepalive = ((uint64_t)gldns_read_uint16(position))*100;
325 if (netreq->owner->context->idle_timeout < server_keepalive)
326 upstream->keepalive_timeout = netreq->owner->context->idle_timeout;
327 else {
328 upstream->keepalive_timeout = server_keepalive;
329 DEBUG_STUB("*** %s: SERVER KEEPALIVE USED : %d ms\n",
330 __FUNCTION__, (int)server_keepalive);
328331 }
329332 return 0;
330333 }
359362 getdns_sock_nonblock(fd);
360363 #ifdef USE_TCP_FASTOPEN
361364 /* Leave the connect to the later call to sendto() if using TCP*/
362 if (transport == GETDNS_TRANSPORT_TCP ||
363 transport == GETDNS_TRANSPORT_STARTTLS)
365 if (transport == GETDNS_TRANSPORT_TCP)
364366 return fd;
367 #elif USE_OSX_TCP_FASTOPEN
368 sa_endpoints_t endpoints;
369 endpoints.sae_srcif = 0;
370 endpoints.sae_srcaddr = NULL;
371 endpoints.sae_srcaddrlen = 0;
372 endpoints.sae_dstaddr = (struct sockaddr *)&upstream->addr;
373 endpoints.sae_dstaddrlen = upstream->addr_len;
374 if (connectx(fd, &endpoints, SAE_ASSOCID_ANY,
375 CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE,
376 NULL, 0, NULL, NULL) == -1) {
377 if (errno != EINPROGRESS) {
378 close(fd);
379 return -1;
380 }
381 }
382 return fd;
365383 #endif
366384 if (connect(fd, (struct sockaddr *)&upstream->addr,
367385 upstream->addr_len) == -1) {
448466 netreq->write_queue_tail = NULL;
449467 break;
450468 }
451 upstream_reschedule_events(upstream, netreq->owner->context->idle_timeout);
469 upstream_reschedule_events(upstream, upstream->keepalive_timeout);
452470 }
453471
454472 static int
504522 if (netreq->fd >= 0) close(netreq->fd);
505523 }
506524
507 static void
525 /* May be needed in future for better UDP error handling?*/
526 /*static void
508527 stub_erred(getdns_network_req *netreq)
509528 {
510529 DEBUG_STUB("*** %s\n", __FUNCTION__);
511530 stub_next_upstream(netreq);
512531 stub_cleanup(netreq);
513 /* TODO[TLS]: When we get an error (which is probably a timeout) and are
514 * using to keep connections open should we leave the connection up here? */
515532 if (netreq->fd >= 0) close(netreq->fd);
516533 netreq->state = NET_REQ_FINISHED;
517534 _getdns_check_dns_req_complete(netreq->owner);
518 }
535 }*/
519536
520537 static void
521538 stub_timeout_cb(void *userarg)
522539 {
523540 DEBUG_STUB("*** %s(%p)\n", __FUNCTION__, userarg);
524541 getdns_network_req *netreq = (getdns_network_req *)userarg;
525
526 /* For now, mark a STARTTLS timeout as a failured negotiation and allow
527 * fallback but don't close the connection. */
528 if (netreq->owner == netreq->upstream->starttls_req) {
529 netreq->upstream->tls_hs_state = GETDNS_HS_FAILED;
530 stub_next_upstream(netreq);
531 stub_cleanup(netreq);
532 return;
533 }
534542
535543 stub_next_upstream(netreq);
536544 stub_cleanup(netreq);
616624 /****************************/
617625
618626 static int
619 stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
627 stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf, getdns_eventloop_event* event)
620628 {
621629 ssize_t read;
622630 uint8_t *buf;
631639 tcp->read_pos = tcp->read_buf;
632640 tcp->to_read = 2; /* Packet size */
633641 }
634 read = recv(fd, tcp->read_pos, tcp->to_read, 0);
642 read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0);
635643 if (read == -1) {
644 #ifdef USE_WINSOCK
645 printf("read (in tcp ) %s\n",
646 wsa_strerror(WSAGetLastError()));
647 if (WSAGetLastError() == WSAECONNRESET)
648 return STUB_TCP_AGAIN;
649 if (WSAGetLastError() == WSAEINPROGRESS)
650 return STUB_TCP_AGAIN;
651 if (WSAGetLastError() == WSAEWOULDBLOCK) {
652 winsock_tcp_wouldblock(event->ev, EV_READ);
653 return STUB_TCP_AGAIN;
654 }
655
656 #else
636657 if (errno == EAGAIN || errno == EWOULDBLOCK)
637658 return STUB_TCP_AGAIN;
638659 else
639660 return STUB_TCP_ERROR;
661 #endif
640662 } else if (read == 0) {
641663 /* Remote end closed the socket */
642664 /* TODO: Try to reconnect */
718740 if (netreq->owner->edns_client_subnet_private)
719741 if (attach_edns_client_subnet_private(netreq))
720742 return STUB_OUT_OF_OPTIONS;
743 if (netreq->upstream->writes_done == 0 &&
744 netreq->owner->context->idle_timeout != 0) {
745 /* Add the keepalive option to the first query on this connection*/
746 DEBUG_STUB("# %s: Requesting keepalive\n", __FUNCTION__);
747 if (attach_edns_keepalive(netreq))
748 return STUB_OUT_OF_OPTIONS;
749 netreq->keepalive_sent = 1;
750 }
721751 }
722 pkt_len = netreq->response - netreq->query;
752 pkt_len = _getdns_network_req_add_tsig(netreq);
723753 /* We have an initialized packet buffer.
724754 * Lets see how much of it we can write
725755 */
741771 errno == EINPROGRESS)) ||
742772 written < pkt_len + 2) {
743773 #else
774
775 #ifdef USE_WINSOCK
776 written = sendto(fd, (const char *)(netreq->query - 2),
777 pkt_len + 2, 0,
778 (struct sockaddr *)&(netreq->upstream->addr),
779 netreq->upstream->addr_len);
780
781 #else
744782 written = write(fd, netreq->query - 2, pkt_len + 2);
783 #endif
745784 if ((written == -1 && (errno == EAGAIN ||
746785 errno == EWOULDBLOCK)) ||
747786 written < pkt_len + 2) {
795834 tls_requested(getdns_network_req *netreq)
796835 {
797836 return (netreq->transports[netreq->transport_current] ==
798 GETDNS_TRANSPORT_TLS ||
799 netreq->transports[netreq->transport_current] ==
800 GETDNS_TRANSPORT_STARTTLS) ?
837 GETDNS_TRANSPORT_TLS) ?
801838 1 : 0;
802839 }
803840
804841 static int
805842 tls_should_write(getdns_upstream *upstream)
806843 {
807 /* Should messages be written on TLS upstream. Remember that for STARTTLS
808 * the first message should got over TCP as the handshake isn't started yet.*/
809 return ((upstream->transport == GETDNS_TRANSPORT_TLS ||
810 upstream->transport == GETDNS_TRANSPORT_STARTTLS) &&
844 /* Should messages be written on TLS upstream. */
845 return ((upstream->transport == GETDNS_TRANSPORT_TLS) &&
811846 upstream->tls_hs_state != GETDNS_HS_NONE) ? 1 : 0;
812847 }
813848
814849 static int
815850 tls_should_read(getdns_upstream *upstream)
816851 {
817 return ((upstream->transport == GETDNS_TRANSPORT_TLS ||
818 upstream->transport == GETDNS_TRANSPORT_STARTTLS) &&
852 return ((upstream->transport == GETDNS_TRANSPORT_TLS) &&
819853 !(upstream->tls_hs_state == GETDNS_HS_FAILED ||
820854 upstream->tls_hs_state == GETDNS_HS_NONE)) ? 1 : 0;
821855 }
824858 tls_failed(getdns_upstream *upstream)
825859 {
826860 /* No messages should be scheduled onto an upstream in this state */
827 return ((upstream->transport == GETDNS_TRANSPORT_TLS ||
828 upstream->transport == GETDNS_TRANSPORT_STARTTLS) &&
861 return ((upstream->transport == GETDNS_TRANSPORT_TLS) &&
829862 upstream->tls_hs_state == GETDNS_HS_FAILED) ? 1 : 0;
830863 }
831864
832865 static int
833866 tls_auth_status_ok(getdns_upstream *upstream, getdns_network_req *netreq) {
834 return (netreq->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME &&
867 return (netreq->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED &&
835868 upstream->tls_auth_failed) ? 0 : 1;
836869 }
837870
838871 int
839872 tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
840873 {
841 #if defined(STUB_DEBUG) && STUB_DEBUG
842 int err;
843 const char * err_str;
844
845 err = X509_STORE_CTX_get_error(ctx);
846 err_str = X509_verify_cert_error_string(err);
847 DEBUG_STUB("--- %s, VERIFY RESULT: %s\n", __FUNCTION__, err_str);
874 getdns_upstream *upstream;
875 getdns_return_t pinset_ret = GETDNS_RETURN_GOOD;
876
877 #if defined(STUB_DEBUG) && STUB_DEBUG || defined(X509_V_ERR_HOSTNAME_MISMATCH)
878 int err = X509_STORE_CTX_get_error(ctx);
879
880 DEBUG_STUB("--- %s, VERIFY RESULT: (%d) \"%s\"\n", __FUNCTION__,
881 err, X509_verify_cert_error_string(err));
848882 #endif
849 /*Always proceed without changing result*/
850 return preverify_ok;
851 }
852
853 int
854 tls_verify_callback_with_fallback(int preverify_ok, X509_STORE_CTX *ctx)
855 {
883 upstream = _getdns_upstream_from_x509_store(ctx);
884
856885 #ifdef X509_V_ERR_HOSTNAME_MISMATCH
857 int err;
858 # if defined(STUB_DEBUG) && STUB_DEBUG
859 const char * err_str;
860 # endif
861
862 err = X509_STORE_CTX_get_error(ctx);
863 # if defined(STUB_DEBUG) && STUB_DEBUG
864 err_str = X509_verify_cert_error_string(err);
865 DEBUG_STUB("--- %s, VERIFY RESULT: (%d) \"%s\"\n", __FUNCTION__, err, err_str);
866 # endif
867 /*Proceed if error is hostname mismatch*/
868 if (err == X509_V_ERR_HOSTNAME_MISMATCH) {
869 DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__);
870 return 1;
871 }
872 else
886 /*Report if error is hostname mismatch*/
887 if (upstream && upstream->tls_fallback_ok && err == X509_V_ERR_HOSTNAME_MISMATCH)
888 DEBUG_STUB("--- %s, PROCEEDING EVEN THOUGH HOSTNAME VALIDATION FAILED!!\n", __FUNCTION__);
873889 #endif
874 return preverify_ok;
890 if (upstream && upstream->tls_pubkey_pinset)
891 pinset_ret = _getdns_verify_pinset_match(upstream->tls_pubkey_pinset, ctx);
892
893 if (pinset_ret != GETDNS_RETURN_GOOD) {
894 DEBUG_STUB("--- %s, PINSET VALIDATION FAILURE!!\n", __FUNCTION__);
895 preverify_ok = 0;
896 upstream->tls_auth_failed = 1;
897 if (upstream->tls_fallback_ok)
898 DEBUG_STUB("--- %s, PROCEEDING EVEN THOUGH PINSET VALIDATION FAILED!!\n", __FUNCTION__);
899 }
900 /* If fallback is allowed, proceed regardless of what the auth error is
901 (might not be hostname or pinset related) */
902 return (upstream && upstream->tls_fallback_ok) ? 1 : preverify_ok;
875903 }
876904
877905 static SSL*
889917 SSL_free(ssl);
890918 return NULL;
891919 }
920 /* make sure we'll be able to find the context again when we need it */
921 if (_getdns_associate_upstream_with_SSL(ssl, upstream) != GETDNS_RETURN_GOOD) {
922 SSL_free(ssl);
923 return NULL;
924 }
892925
893926 /* NOTE: this code will fallback on a given upstream, without trying
894927 authentication on other upstreams first. This is non-optimal and but avoids
895928 multiple TLS handshakes before getting a usable connection. */
896929
930 upstream->tls_fallback_ok = 0;
897931 /* If we have a hostname, always use it */
898932 if (upstream->tls_auth_name[0] != '\0') {
899933 /*Request certificate for the auth_name*/
906940 param = SSL_get0_param(ssl);
907941 X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
908942 X509_VERIFY_PARAM_set1_host(param, upstream->tls_auth_name, 0);
909 DEBUG_STUB("--- %s, HOSTNAME VERIFICATION REQUESTED \n", __FUNCTION__);
910943 #else
911 if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME) {
944 if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) {
912945 /* TODO: Trigger post-handshake custom validation*/
913 DEBUG_STUB("--- %s, ERROR: Authentication functionality not available\n", __FUNCTION__);
946 DEBUG_STUB("--- %s, ERROR: TLS Authentication functionality not available\n", __FUNCTION__);
914947 upstream->tls_hs_state = GETDNS_HS_FAILED;
915948 upstream->tls_auth_failed = 1;
916949 return NULL;
917950 }
918951 #endif
919952 /* Allow fallback to opportunistic if settings permit it*/
920 if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME)
921 SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
922 else {
923 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_callback_with_fallback);
924 SSL_set_cipher_list(ssl, "DEFAULT");
953 if (dnsreq->netreqs[0]->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
954 upstream->tls_fallback_ok = 1;
955 } else {
956 /* Lack of host name is OK unless only authenticated
957 * TLS is specified and we have no pubkey_pinset */
958 if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) {
959 if (upstream->tls_pubkey_pinset) {
960 DEBUG_STUB("--- %s, PROCEEDING WITH ONLY PUBKEY PINNING AUTHENTICATION\n", __FUNCTION__);
961 } else {
962 DEBUG_STUB("--- %s, ERROR: No host name or pubkey pinset provided for TLS authentication\n", __FUNCTION__);
963 upstream->tls_hs_state = GETDNS_HS_FAILED;
964 upstream->tls_auth_failed = 1;
965 return NULL;
966 }
967 } else {
968 /* no hostname verification, so we will make opportunistic connections */
969 DEBUG_STUB("--- %s, PROCEEDING EVEN THOUGH NO HOSTNAME PROVIDED!!\n", __FUNCTION__);
970 upstream->tls_auth_failed = 1;
971 upstream->tls_fallback_ok = 1;
925972 }
926 } else {
927 /* Lack of host name is OK unless only authenticated TLS is specified*/
928 if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME) {
929 DEBUG_STUB("--- %s, ERROR: No host name provided for authentication\n", __FUNCTION__);
930 upstream->tls_hs_state = GETDNS_HS_FAILED;
931 upstream->tls_auth_failed = 1;
932 return NULL;
933 } else {
934 /* no hostname verification, so we will make opportunistic connections */
935 DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__);
936 upstream->tls_auth_failed = 1;
937 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_callback_with_fallback);
938 SSL_set_cipher_list(ssl, "DEFAULT");
939 }
940 }
941
973 }
974 if (upstream->tls_fallback_ok) {
975 SSL_set_cipher_list(ssl, "DEFAULT");
976 DEBUG_STUB("--- %s, PROCEEDING WITH OPPOTUNISTIC TLS CONNECTION (FALLBACK ALLOWED)!!\n", __FUNCTION__);
977 } else
978 DEBUG_STUB("--- %s, PROCEEDING WITH STRICT TLS CONNECTION!!\n", __FUNCTION__);
979 SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
980
942981 SSL_set_connect_state(ssl);
943982 (void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
944983 return ssl;
9991038 }
10001039 upstream->tls_hs_state = GETDNS_HS_DONE;
10011040 r = SSL_get_verify_result(upstream->tls_obj);
1041 if (upstream->tls_auth_name[0])
10021042 #ifdef X509_V_ERR_HOSTNAME_MISMATCH
1003 if (r == X509_V_ERR_HOSTNAME_MISMATCH)
1043 if (r == X509_V_ERR_HOSTNAME_MISMATCH)
1044 #else
1045 /* if we weren't built against OpenSSL with hostname matching we
1046 * could not have matched the hostname, so this would be an automatic
1047 * tls_auth_fail. */
10041048 #endif
1005 upstream->tls_auth_failed = 1;
1049 upstream->tls_auth_failed = 1;
10061050 /* Reset timeout on success*/
10071051 GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
10081052 upstream->event.read_cb = NULL;
11711215 &netreq->upstream->netreq_by_query_id, &netreq->node));
11721216
11731217 GLDNS_ID_SET(netreq->query, query_id);
1218 /* TODO: Review if more EDNS0 handling can be centralised.*/
11741219 if (netreq->opt) {
11751220 _getdns_network_req_clear_upstream_options(netreq);
11761221 /* no limits on the max udp payload size with tcp */
11811226 if (netreq->owner->edns_client_subnet_private)
11821227 if (attach_edns_client_subnet_private(netreq))
11831228 return STUB_OUT_OF_OPTIONS;
1229 if (netreq->upstream->writes_done % EDNS_KEEPALIVE_RESEND == 0 &&
1230 netreq->owner->context->idle_timeout != 0) {
1231 /* Add the keepalive option to every nth query on this
1232 connection */
1233 DEBUG_STUB("# %s: Requesting keepalive\n", __FUNCTION__);
1234 if (attach_edns_keepalive(netreq))
1235 return STUB_OUT_OF_OPTIONS;
1236 netreq->keepalive_sent = 1;
1237 }
11841238 if (netreq->owner->tls_query_padding_blocksize > 1) {
11851239 pkt_len = netreq->response - netreq->query;
11861240 pkt_len += 4; /* this accounts for the OPTION-CODE and OPTION-LENGTH of the padding */
11941248 }
11951249 }
11961250
1197 pkt_len = netreq->response - netreq->query;
1251 pkt_len = _getdns_network_req_add_tsig(netreq);
11981252 /* We have an initialized packet buffer.
11991253 * Lets see how much of it we can write */
12001254
12411295
12421296 GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
12431297
1244 read = recvfrom(netreq->fd, netreq->response,
1298 read = recvfrom(netreq->fd, (void *)netreq->response,
12451299 netreq->max_udp_payload_size + 1, /* If read == max_udp_payload_size
12461300 * then all is good. If read ==
12471301 * max_udp_payload_size + 1, then
12631317 return; /* Client cookie didn't match? */
12641318
12651319 close(netreq->fd);
1266 if (GLDNS_TC_WIRE(netreq->response)) {
1320 while (GLDNS_TC_WIRE(netreq->response)) {
1321 DEBUG_STUB("TC bit set\n");
12671322 if (!(netreq->transport_current < netreq->transport_count))
1268 goto done;
1323 break;
12691324 getdns_transport_list_t next_transport =
12701325 netreq->transports[++netreq->transport_current];
1271 if (next_transport != GETDNS_TRANSPORT_TCP)
1272 goto done;
1326 if (next_transport != GETDNS_TRANSPORT_TCP &&
1327 next_transport != GETDNS_TRANSPORT_TLS)
1328 break;
12731329 /* For now, special case where fallback should be on the same upstream*/
12741330 if ((netreq->fd = upstream_connect(upstream, next_transport,
12751331 dnsreq)) == -1)
1276 goto done;
1332 break;
12771333 upstream_schedule_netreq(netreq->upstream, netreq);
12781334 GETDNS_SCHEDULE_EVENT(
12791335 dnsreq->loop, netreq->upstream->fd, dnsreq->context->timeout,
12851341 }
12861342 netreq->response_len = read;
12871343 dnsreq->upstreams->current = 0;
1288 done:
12891344 netreq->debug_end_time = _getdns_get_time_as_uintt64();
12901345 netreq->state = NET_REQ_FINISHED;
12911346 _getdns_check_dns_req_complete(dnsreq);
13191374 if (attach_edns_client_subnet_private(netreq))
13201375 return; /* too many upstream options */
13211376 }
1322 pkt_len = netreq->response - netreq->query;
1323 if ((ssize_t)pkt_len != sendto(netreq->fd, netreq->query, pkt_len, 0,
1377 pkt_len = _getdns_network_req_add_tsig(netreq);
1378 if ((ssize_t)pkt_len != sendto(
1379 netreq->fd, (const void *)netreq->query, pkt_len, 0,
13241380 (struct sockaddr *)&netreq->upstream->addr,
13251381 netreq->upstream->addr_len)) {
13261382 close(netreq->fd);
13331389 }
13341390
13351391 /**************************/
1336 /* TCP callback functions*/
1337 /**************************/
1338
1339 static void
1340 stub_tcp_read_cb(void *userarg)
1341 {
1342 getdns_network_req *netreq = (getdns_network_req *)userarg;
1343 getdns_dns_req *dnsreq = netreq->owner;
1344 int q;
1345
1346 switch ((q = stub_tcp_read(netreq->fd, &netreq->tcp,
1347 &dnsreq->context->mf))) {
1348
1349 case STUB_TCP_AGAIN:
1350 return;
1351
1352 case STUB_TCP_ERROR:
1353 stub_erred(netreq);
1354 return;
1355
1356 default:
1357 GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
1358 if (q != netreq->query_id)
1359 return;
1360 if (netreq->owner->edns_cookies &&
1361 match_and_process_server_cookie(
1362 netreq->upstream, netreq->tcp.read_buf,
1363 netreq->tcp.read_pos - netreq->tcp.read_buf))
1364 return; /* Client cookie didn't match? */
1365 netreq->state = NET_REQ_FINISHED;
1366 netreq->response = netreq->tcp.read_buf;
1367 netreq->response_len =
1368 netreq->tcp.read_pos - netreq->tcp.read_buf;
1369 netreq->tcp.read_buf = NULL;
1370 dnsreq->upstreams->current = 0;
1371 netreq->debug_end_time = _getdns_get_time_as_uintt64();
1372 stub_cleanup(netreq);
1373 close(netreq->fd);
1374 _getdns_check_dns_req_complete(dnsreq);
1375 }
1376 }
1377
1378 static void
1379 stub_tcp_write_cb(void *userarg)
1380 {
1381 getdns_network_req *netreq = (getdns_network_req *)userarg;
1382 getdns_dns_req *dnsreq = netreq->owner;
1383 int q;
1384 netreq->debug_start_time = _getdns_get_time_as_uintt64();
1385 switch ((q = stub_tcp_write(netreq->fd, &netreq->tcp, netreq))) {
1386 case STUB_TCP_AGAIN:
1387 return;
1388
1389 case STUB_TCP_ERROR:
1390 stub_erred(netreq);
1391 return;
1392
1393 default:
1394 netreq->debug_udp = 0;
1395 netreq->query_id = (uint16_t) q;
1396 GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
1397 GETDNS_SCHEDULE_EVENT(
1398 dnsreq->loop, netreq->fd, dnsreq->context->timeout,
1399 getdns_eventloop_event_init(&netreq->event, netreq,
1400 stub_tcp_read_cb, NULL, stub_timeout_cb));
1401 return;
1402 }
1403 }
1404
1405 /**************************/
14061392 /* Upstream callback functions*/
14071393 /**************************/
14081394
14121398 DEBUG_STUB("--- READ: %s\n", __FUNCTION__);
14131399 getdns_upstream *upstream = (getdns_upstream *)userarg;
14141400 getdns_network_req *netreq;
1415 getdns_dns_req *dnsreq;
14161401 int q;
14171402 uint16_t query_id;
14181403 intptr_t query_id_intptr;
14221407 &upstream->upstreams->mf);
14231408 else
14241409 q = stub_tcp_read(upstream->fd, &upstream->tcp,
1425 &upstream->upstreams->mf);
1410 &upstream->upstreams->mf, &upstream->event);
14261411
14271412 switch (q) {
14281413 case STUB_TCP_AGAIN:
14551440 /* TODO[TLS]: I don't think we should do this for TCP. We should stay
14561441 * on a working connection until we hit a problem.*/
14571442 upstream->upstreams->current = 0;
1458
1459 if (netreq->owner == upstream->starttls_req) {
1460 dnsreq = netreq->owner;
1461 if (is_starttls_response(netreq)) {
1462 upstream->tls_obj = tls_create_object(dnsreq,
1463 upstream->fd,
1464 upstream);
1465 if (upstream->tls_obj == NULL)
1466 upstream->tls_hs_state = GETDNS_HS_FAILED;
1467 upstream->tls_hs_state = GETDNS_HS_WRITE;
1468 } else
1469 upstream->tls_hs_state = GETDNS_HS_FAILED;
1470
1471 /* Now reschedule the writes on this connection */
1472 GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
1473 GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
1474 netreq->owner->context->timeout,
1475 getdns_eventloop_event_init(&upstream->event, upstream,
1476 NULL, upstream_write_cb, NULL));
1477 }
1443
1444 /* !THIS CODE NEEDS TESTING!*/
1445 if (netreq->owner->edns_cookies &&
1446 match_and_process_server_cookie(
1447 netreq->upstream, netreq->tcp.read_buf,
1448 netreq->tcp.read_pos - netreq->tcp.read_buf))
1449 return; /* Client cookie didn't match? */
1450
1451 if ((netreq->owner->context->idle_timeout != 0) &&
1452 process_keepalive(netreq->upstream, netreq, netreq->response,
1453 netreq->response_len))
1454 return;
1455
14781456 netreq->debug_end_time = _getdns_get_time_as_uintt64();
14791457 /* This also reschedules events for the upstream*/
14801458 stub_cleanup(netreq);
14831461 if (netreq->event.read_cb)
14841462 upstream_reschedule_netreq_events(upstream, netreq);
14851463
1486 if (netreq->owner != upstream->starttls_req)
1487 _getdns_check_dns_req_complete(netreq->owner);
1464 _getdns_check_dns_req_complete(netreq->owner);
14881465 }
14891466 }
14901467
15641541 GETDNS_SCHEDULE_EVENT(upstream->loop,
15651542 upstream->fd, TIMEOUT_FOREVER, &upstream->event);
15661543 }
1567 if (upstream->starttls_req && netreq->owner == upstream->starttls_req) {
1568 /* Now deschedule any further writes on this connection until we get
1569 * the STARTTLS answer*/
1570 GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
1571 upstream->event.write_cb = NULL;
1572 GETDNS_SCHEDULE_EVENT(upstream->loop,
1573 upstream->fd, TIMEOUT_FOREVER, &upstream->event);
1574 } else if (upstream->starttls_req) {
1575 /* Delay the cleanup of the STARTTLS req until the write of the next
1576 * req in the queue since for sync req, the event on a request is
1577 * used for the callback that writes the next req. */
1578 _getdns_dns_req_free(upstream->starttls_req);
1579 upstream->starttls_req = NULL;
1580 }
15811544 /* With synchonous lookups, schedule the read locally too */
15821545 if (netreq->event.write_cb) {
15831546 GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
15851548 dnsreq->loop, upstream->fd, dnsreq->context->timeout,
15861549 getdns_eventloop_event_init(&netreq->event, netreq,
15871550 netreq_upstream_read_cb,
1588 (upstream->write_queue && !upstream->starttls_req ?
1551 (upstream->write_queue ?
15891552 netreq_upstream_write_cb : NULL),
15901553 stub_timeout_cb));
15911554 }
16211584 upstream->tcp.write_error != 0) {
16221585 return 0;
16231586 }
1624 /* Allow TCP messages to be sent on a STARTTLS upstream that hasn't
1625 * upgraded to avoid opening a new connection if one is aleady open. */
1626 if (transport == GETDNS_TRANSPORT_TCP &&
1627 upstream->transport == GETDNS_TRANSPORT_STARTTLS &&
1628 upstream->tls_hs_state == GETDNS_HS_FAILED)
1629 return 1;
16301587 /* Otherwise, transport must match, and not have failed */
16311588 if (upstream->transport != transport)
16321589 return 0;
17221679 upstream->loop = dnsreq->context->extension;
17231680 upstream->fd = fd;
17241681 break;
1725 case GETDNS_TRANSPORT_STARTTLS:
1726 /* Use existing if available. Let the fallback code handle it if
1727 * STARTTLS isn't availble. */
1728 if (upstream->fd != -1)
1729 return upstream->fd;
1730 fd = tcp_connect(upstream, transport);
1731 if (fd == -1) return -1;
1732 if (!create_starttls_request(dnsreq, upstream, dnsreq->loop))
1733 return GETDNS_RETURN_GENERIC_ERROR;
1734 getdns_network_req *starttls_netreq = upstream->starttls_req->netreqs[0];
1735 upstream->loop = dnsreq->context->extension;
1736 upstream->fd = fd;
1737 upstream_schedule_netreq(upstream, starttls_netreq);
1738 /* Schedule at least the timeout locally, but use less than half the
1739 * context value so by default this timeouts before the TIMEOUT_TLS.
1740 * And also the write if we perform a synchronous lookup */
1741 GETDNS_SCHEDULE_EVENT(
1742 dnsreq->loop, upstream->fd, dnsreq->context->timeout / 3,
1743 getdns_eventloop_event_init(&starttls_netreq->event,
1744 starttls_netreq, NULL, (dnsreq->loop != upstream->loop
1745 ? netreq_upstream_write_cb : NULL), stub_timeout_cb));
1746 break;
17471682 default:
17481683 return -1;
17491684 /* Nothing to do*/
17801715 continue;
17811716 netreq->transport_current = i;
17821717 netreq->upstream = upstream;
1718 netreq->keepalive_sent = 0;
17831719 return fd;
17841720 }
17851721 return -1;
18911827 GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
18921828 upstream->event.timeout_cb = NULL;
18931829 upstream->event.write_cb = upstream_write_cb;
1894 if (upstream->tls_hs_state == GETDNS_HS_WRITE ||
1895 (upstream->starttls_req &&
1896 upstream->starttls_req->netreqs[0] == netreq)) {
1830 if (upstream->tls_hs_state == GETDNS_HS_WRITE) {
18971831 /* Set a timeout on the upstream so we can catch failed setup*/
18981832 /* TODO[TLS]: When generic fallback supported, we should decide how
18991833 * to split the timeout between transports. */
19331867 GETDNS_SCHEDULE_EVENT(
19341868 dnsreq->loop, netreq->fd, dnsreq->context->timeout,
19351869 getdns_eventloop_event_init(&netreq->event, netreq,
1936 NULL, (transport == GETDNS_TRANSPORT_UDP ?
1937 stub_udp_write_cb: stub_tcp_write_cb), stub_timeout_cb));
1870 NULL, stub_udp_write_cb, stub_timeout_cb));
19381871 return GETDNS_RETURN_GOOD;
1939
1940 case GETDNS_TRANSPORT_STARTTLS:
1872
19411873 case GETDNS_TRANSPORT_TLS:
19421874 case GETDNS_TRANSPORT_TCP:
19431875 upstream_schedule_netreq(netreq->upstream, netreq);
5757 CHECK_EV_PROG=@CHECK_EV_PROG@
5858
5959 CC=@CC@
60 CFLAGS=-I$(srcdir)/.. -I$(srcdir) -I.. $(cflags) @CFLAGS@
60 CFLAGS=-I$(srcdir)/.. -I$(srcdir) -I.. $(cflags) @CFLAGS@ @CPPFLAGS@
6161 LDFLAGS=-L.. @LDFLAGS@
6262 LDLIBS=../libgetdns.la @LIBS@
6363 CHECK_LIBS=@CHECK_LIBS@
7272 ALL_OBJS=$(CHECK_OBJS) check_getdns_libevent.lo check_getdns_libev.lo \
7373 check_getdns_selectloop.lo getdns_query.lo scratchpad.lo \
7474 testmessages.lo tests_dict.lo tests_list.lo tests_namespaces.lo \
75 tests_stub_async.lo tests_stub_sync.lo tests_json-pointers.lo
75 tests_stub_async.lo tests_stub_sync.lo
7676
7777 NON_C99_OBJS=check_getdns_libuv.lo
7878
79 PROGRAMS=tests_dict tests_list tests_namespaces tests_stub_async tests_stub_sync tests_json-pointers getdns_query $(CHECK_GETDNS) $(CHECK_EV_PROG) $(CHECK_EVENT_PROG) $(CHECK_UV_PROG)
79 PROGRAMS=tests_dict tests_list tests_namespaces tests_stub_async tests_stub_sync getdns_query $(CHECK_GETDNS) $(CHECK_EV_PROG) $(CHECK_EVENT_PROG) $(CHECK_UV_PROG)
8080
8181
8282 .SUFFIXES: .c .o .a .lo .h
111111
112112 tests_stub_sync: tests_stub_sync.lo
113113 $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ tests_stub_sync.lo
114
115 tests_json-pointers: tests_json-pointers.lo
116 $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ tests_json-pointers.lo
117114
118115 check_getdns_common: check_getdns_common.lo
119116 $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_common.lo
182179 distclean : clean
183180 rm -f scratchpad.c
184181 rm -f Makefile config.status config.log
182 rm -f check_getdns_uv.core check_getdns.core check_getdns_event.core
185183 rm -Rf autom4te.cache
186184
187185 $(distdir): FORCE
215213
216214 depend:
217215 (cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
218 (cd $(srcdir) ; gcc -MM -I. -I.. *.c | \
219 sed -e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
216 (blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I.. -I"$$blddir"/.. *.c | \
217 sed -e "s? $$blddir/? ?g" \
218 -e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
220219 -e 's? \$$(srcdir)/config\.h? ../config.h?g' \
221220 -e 's? $$(srcdir)/\.\./getdns/getdns_extra\.h? ../getdns/getdns_extra.h?g' \
222221 -e 's? \.\./getdns/getdns_ext_libevent\.h? $$(srcdir)/../getdns/getdns_ext_libevent.h?g' \
223222 -e 's? \.\./getdns/getdns_ext_libev\.h? $$(srcdir)/../getdns/getdns_ext_libev.h?g' \
224223 -e 's? \.\./getdns/getdns_ext_libuv\.h? $$(srcdir)/../getdns/getdns_ext_libuv.h?g' \
224 -e 's? \.\./debug\.h? $$(srcdir)/../debug.h?g' \
225225 -e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' >> Makefile.in.new )
226226 (cd $(srcdir) ; diff Makefile.in.new Makefile.in && rm Makefile.in.new \
227227 || mv Makefile.in.new Makefile.in )
274274 check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \
275275 $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \
276276 ../getdns/getdns_extra.h
277 getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h ../getdns/getdns.h \
278 ../getdns/getdns_extra.h
277 getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \
278 ../getdns/getdns.h ../getdns/getdns_extra.h
279279 scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \
280280 ../getdns/getdns_extra.h
281281 testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h
282282 tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h ../getdns/getdns.h
283 tests_json-pointers.lo tests_json-pointers.o: $(srcdir)/tests_json-pointers.c ../getdns/getdns.h \
284 ../getdns/getdns_extra.h
285283 tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h ../getdns/getdns.h
286284 tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h ../getdns/getdns.h
287285 tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c ../config.h $(srcdir)/testmessages.h \
213213
214214 expected_changed_item = GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS;
215215
216 ASSERT_RC(getdns_context_set_follow_redirects(context, GETDNS_REDIRECTS_DO_NOT_FOLLOW),
217 GETDNS_RETURN_GOOD, "Return code from getdns_context_set_follow_redirects()");
216 (void) getdns_context_set_follow_redirects(context, GETDNS_REDIRECTS_DO_NOT_FOLLOW);
218217
219218 CONTEXT_DESTROY;
220219
9595 {
9696 /*
9797 * timeout is 0
98 * expect: GETDNS_RETURN_INVALID_PARAMETER
98 * expect: GETDNS_RETURN_GOOD
9999 */
100100
101101 struct getdns_context *context = NULL;
102102 CONTEXT_CREATE(TRUE);
103103
104104 ASSERT_RC(getdns_context_set_idle_timeout(context, 0),
105 GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_context_set_timeout()");
105 GETDNS_RETURN_GOOD, "Return code from getdns_context_set_timeout()");
106106
107107 CONTEXT_DESTROY;
108108
330330 }
331331 END_TEST
332332
333 /* This test disabled because travis does not support IPv6 in their
334 * container based infrastructure!
335 */
336 #if 0
333337 START_TEST (getdns_context_set_upstream_recursive_servers_10)
334338 {
335339 /*
344348 struct getdns_dict *dict = NULL;
345349 struct getdns_dict *response = NULL;
346350 struct getdns_bindata address_type = { 5, (void *)"IPv6" };
347 struct getdns_bindata address_data = { 16, (void *)"\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00\x88\x44" };
351 struct getdns_bindata address_data = { 16, (void *)"\x26\x20\x00\x74\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01" };
348352 size_t index = 0;
349353
350354 CONTEXT_CREATE(TRUE);
378382 DICT_DESTROY(response);
379383 }
380384 END_TEST
381
385 #endif
382386 START_TEST (getdns_context_set_upstream_recursive_servers_11)
383387 {
384388 /*
459463 /* Positive test cases */
460464 TCase *tc_pos = tcase_create("Positive");
461465 tcase_add_test(tc_pos, getdns_context_set_upstream_recursive_servers_9);
462 tcase_add_test(tc_pos, getdns_context_set_upstream_recursive_servers_10);
466 /***** tcase_add_test(tc_pos, getdns_context_set_upstream_recursive_servers_10); *****/
463467 tcase_add_test(tc_pos, getdns_context_set_upstream_recursive_servers_11);
464468
465469 suite_add_tcase(s, tc_pos);
2525 */
2626
2727 #include "config.h"
28 #include "debug.h"
2829 #include <stdio.h>
2930 #include <stdlib.h>
3031 #include <string.h>
3132 #include <inttypes.h>
3233 #include <getdns/getdns.h>
3334 #include <getdns/getdns_extra.h>
34 #include "util-internal.h"
3535
3636 #define MAX_TIMEOUTS FD_SETSIZE
37
38 #define EXAMPLE_PIN "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""
3739
3840 /* Eventloop based on select */
3941 typedef struct my_eventloop {
259261 static char *name;
260262 static getdns_context *context;
261263 static getdns_dict *extensions;
264 static getdns_list *pubkey_pinset = NULL;
265 static size_t pincount = 0;
262266 static uint16_t request_type = GETDNS_RRTYPE_NS;
263267 static int timeout, edns0_size, padding_blocksize;
264268 static int async = 0, interactive = 0;
265269 static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL;
266270
267271 int get_rrtype(const char *t);
272
273 int gqldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
274 {
275 const uint8_t pad64 = 64; /* is 64th in the b64 array */
276 const char* s = src;
277 uint8_t in[4];
278 size_t o = 0, incount = 0;
279
280 while(*s) {
281 /* skip any character that is not base64 */
282 /* conceptually we do:
283 const char* b64 = pad'=' is appended to array
284 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
285 const char* d = strchr(b64, *s++);
286 and use d-b64;
287 */
288 char d = *s++;
289 if(d <= 'Z' && d >= 'A')
290 d -= 'A';
291 else if(d <= 'z' && d >= 'a')
292 d = d - 'a' + 26;
293 else if(d <= '9' && d >= '0')
294 d = d - '0' + 52;
295 else if(d == '+')
296 d = 62;
297 else if(d == '/')
298 d = 63;
299 else if(d == '=')
300 d = 64;
301 else continue;
302 in[incount++] = (uint8_t)d;
303 if(incount != 4)
304 continue;
305 /* process whole block of 4 characters into 3 output bytes */
306 if(in[3] == pad64 && in[2] == pad64) { /* A B = = */
307 if(o+1 > targsize)
308 return -1;
309 target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
310 o += 1;
311 break; /* we are done */
312 } else if(in[3] == pad64) { /* A B C = */
313 if(o+2 > targsize)
314 return -1;
315 target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
316 target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
317 o += 2;
318 break; /* we are done */
319 } else {
320 if(o+3 > targsize)
321 return -1;
322 /* write xxxxxxyy yyyyzzzz zzwwwwww */
323 target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
324 target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
325 target[o+2]= ((in[2]&0x03)<<6) | in[3];
326 o += 3;
327 }
328 incount = 0;
329 }
330 return (int)o;
331 }
268332
269333 getdns_dict *
270334 ipaddr_dict(getdns_context *context, char *ipstr)
274338 char *p = strchr(ipstr, '@'), *portstr = "";
275339 char *t = strchr(ipstr, '#'), *tls_portstr = "";
276340 char *n = strchr(ipstr, '~'), *tls_namestr = "";
341 /* ^[alg:]name:key */
342 char *T = strchr(ipstr, '^'), *tsig_name_str = ""
343 , *tsig_secret_str = ""
344 , *tsig_algorithm_str = "";
345 int tsig_secret_size;
346 uint8_t tsig_secret_buf[256]; /* 4 times SHA512 */
347 getdns_bindata tsig_secret;
277348 uint8_t buf[sizeof(struct in6_addr)];
278349 getdns_bindata addr;
279350
295366 if (n) {
296367 *n = 0;
297368 tls_namestr = n + 1;
369 }
370 if (T) {
371 *T = 0;
372 tsig_name_str = T + 1;
373 if ((T = strchr(tsig_name_str, ':'))) {
374 *T = 0;
375 tsig_secret_str = T + 1;
376 if ((T = strchr(tsig_secret_str, ':'))) {
377 *T = 0;
378 tsig_algorithm_str = tsig_name_str;
379 tsig_name_str = tsig_secret_str;
380 tsig_secret_str = T + 1;
381 }
382 } else {
383 tsig_name_str = "";
384 }
298385 }
299386 if (strchr(ipstr, ':')) {
300387 getdns_dict_util_set_string(r, "address_type", "IPv6");
321408 }
322409 if (*scope_id_str)
323410 getdns_dict_util_set_string(r, "scope_id", scope_id_str);
324
411 if (*tsig_name_str)
412 getdns_dict_util_set_string(r, "tsig_name", tsig_name_str);
413 if (*tsig_algorithm_str)
414 getdns_dict_util_set_string(r, "tsig_algorithm", tsig_algorithm_str);
415 if (*tsig_secret_str) {
416 tsig_secret_size = gqldns_b64_pton(
417 tsig_secret_str, tsig_secret_buf, sizeof(tsig_secret_buf));
418 if (tsig_secret_size > 0) {
419 tsig_secret.size = tsig_secret_size;
420 tsig_secret.data = tsig_secret_buf;
421 getdns_dict_set_bindata(r, "tsig_secret", &tsig_secret);
422 }
423 }
325424 return r;
326425 }
327426
344443 case 'L':
345444 transports[i] = GETDNS_TRANSPORT_TLS;
346445 break;
347 case 'S':
348 transports[i] = GETDNS_TRANSPORT_STARTTLS;
349 break;
350446 default:
351447 fprintf(stderr, "Unrecognised transport '%c' in string %s\n",
352448 *(transport_list_str + i), transport_list_str);
359455 void
360456 print_usage(FILE *out, const char *progname)
361457 {
362 fprintf(out, "usage: %s [@<server>] [+extension] [<name>] [<type>]\n",
363 progname);
364 fprintf(out, "options:\n");
458 fprintf(out, "usage: %s [<option> ...] \\\n"
459 "\t\t[@<upstream> ...] [+<extension> ...] [<name>] [<type>]\n", progname);
460 fprintf(out, "\nupstreams: @<ip>[%%<scope_id>][@<port>][#<tls port>][~<tls name>][^<tsig spec>]\n");
461 fprintf(out, "\ntsig spec: [<algorithm>:]<name>:<secret in Base64>\n");
462 fprintf(out, "\nextensions:\n");
463 fprintf(out, "\t+add_warning_for_bad_dns\n");
464 fprintf(out, "\t+dnssec_return_status\n");
465 fprintf(out, "\t+dnssec_return_only_secure\n");
466 fprintf(out, "\t+dnssec_return_validation_chain\n");
467 #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
468 fprintf(out, "\t+dnssec_roadblock_avoidance\n");
469 #endif
470 #ifdef EDNS_COOKIES
471 fprintf(out, "\t+edns_cookies\n");
472 #endif
473 fprintf(out, "\t+return_both_v4_and_v6\n");
474 fprintf(out, "\t+return_call_reporting\n");
475 fprintf(out, "\t+sit=<cookie>\t\tSend along cookie OPT with value <cookie>\n");
476 fprintf(out, "\t+specify_class=<class>\n");
477 fprintf(out, "\t+0\t\t\tClear all extensions\n");
478 fprintf(out, "\noptions:\n");
365479 fprintf(out, "\t-a\tPerform asynchronous resolution "
366480 "(default = synchronous)\n");
367481 fprintf(out, "\t-A\taddress lookup (<type> is ignored)\n");
372486 fprintf(out, "\t-d\tclear edns0 do bit\n");
373487 fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in miliseconds\n");
374488 fprintf(out, "\t-F <filename>\tread the queries from the specified file\n");
489 fprintf(out, "\t-f <filename>\tRead DNSSEC trust anchors from <filename>\n");
375490 fprintf(out, "\t-G\tgeneral lookup\n");
376491 fprintf(out, "\t-H\thostname lookup. (<name> must be an IP address; <type> is ignored)\n");
377492 fprintf(out, "\t-h\tPrint this help\n");
380495 fprintf(out, "\t-j\tOutput json response dict\n");
381496 fprintf(out, "\t-J\tPretty print json response dict\n");
382497 fprintf(out, "\t-k\tPrint root trust anchors\n");
498 fprintf(out, "\t-K <pin>\tPin a public key for TLS connections (can repeat)\n");
499 fprintf(out, "\t\t(should look like '" EXAMPLE_PIN "')\n");
383500 fprintf(out, "\t-n\tSet TLS authentication mode to NONE (default)\n");
384 fprintf(out, "\t-m\tSet TLS authentication mode to HOSTNAME\n");
501 fprintf(out, "\t-m\tSet TLS authentication mode to REQUIRED\n");
385502 fprintf(out, "\t-p\tPretty print response dict\n");
386503 fprintf(out, "\t-P <blocksize>\tPad TLS queries to a multiple of blocksize\n");
387504 fprintf(out, "\t-r\tSet recursing resolution type\n");
505 fprintf(out, "\t-R <filename>\tRead root hints from <filename>\n");
388506 fprintf(out, "\t-q\tQuiet mode - don't print response\n");
389507 fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n");
390508 fprintf(out, "\t-S\tservice lookup (<type> is ignored)\n");
391509 fprintf(out, "\t-t <timeout>\tSet timeout in miliseconds\n");
510
511 fprintf(out, "\t-W\tAppend suffix always (default)\n");
512 fprintf(out, "\t-1\tAppend suffix only to single label after failure\n");
513 fprintf(out, "\t-M\tAppend suffix only to multi label name after failure\n");
514 fprintf(out, "\t-N\tNever append a suffix\n");
515 fprintf(out, "\t-Z <suffixes>\tSet suffixes with the given comma separed list\n");
516
392517 fprintf(out, "\t-T\tSet transport to TCP only\n");
393518 fprintf(out, "\t-O\tSet transport to TCP only keep connections open\n");
394519 fprintf(out, "\t-L\tSet transport to TLS only keep connections open\n");
395520 fprintf(out, "\t-E\tSet transport to TLS with TCP fallback only keep connections open\n");
396 fprintf(out, "\t-R\tSet transport to STARTTLS with TCP fallback only keep connections open\n");
397521 fprintf(out, "\t-u\tSet transport to UDP with TCP fallback\n");
398522 fprintf(out, "\t-U\tSet transport to UDP only\n");
399523 fprintf(out, "\t-l <transports>\tSet transport list. List can contain 1 of each of the characters\n");
400 fprintf(out, "\t\t\t U T L S for UDP, TCP, TLS or STARTTLS e.g 'UT' or 'LST' \n");
524 fprintf(out, "\t\t\t U T L S for UDP, TCP or TLS e.g 'UT' or 'LTU' \n");
401525
402526 }
403527
415539 if (!(to_validate = getdns_list_create()))
416540 return GETDNS_RETURN_MEMORY_ERROR;
417541
418 trust_anchor = getdns_root_trust_anchor(NULL);
542 if (getdns_context_get_dnssec_trust_anchors(context, &trust_anchor))
543 trust_anchor = getdns_root_trust_anchor(NULL);
419544
420545 if ((r = getdns_dict_get_list(
421546 response, "validation_chain", &validation_chain)))
454579 if ((r = getdns_list_set_dict(to_validate, 0, reply)))
455580 goto error;
456581
457 fprintf( stdout
458 , "reply %zu, dnssec_status: ", i);
582 printf("reply %u, dnssec_status: ", (unsigned)i);
459583 switch ((s = getdns_validate_dnssec(
460584 to_validate, validation_chain, trust_anchor))) {
461585
503627 }
504628
505629 if (callback_type == GETDNS_CALLBACK_COMPLETE) {
506 fprintf(stdout,
507 "Response code was: GOOD. Status was: Callback with ID %llu was successfull.\n",
508 (unsigned long long)trans_id);
630 printf("Response code was: GOOD. Status was: Callback with ID %"PRIu64" was successfull.\n",
631 trans_id);
509632
510633 } else if (callback_type == GETDNS_CALLBACK_CANCEL)
511634 fprintf(stderr,
512 "An error occurred: The callback with ID %llu was cancelled. Exiting.\n",
513 (unsigned long long)trans_id);
635 "An error occurred: The callback with ID %"PRIu64" was cancelled. Exiting.\n",
636 trans_id);
514637 else {
515638 fprintf(stderr,
516639 "An error occurred: The callback got a callback_type of %d. Exiting.\n",
581704 getdns_return_t parse_args(int argc, char **argv)
582705 {
583706 getdns_return_t r = GETDNS_RETURN_GOOD;
584 size_t i;
707 size_t i, j;
585708 char *arg, *c, *endptr;
586709 int t, print_api_info = 0, print_trust_anchors = 0;
587710 getdns_list *upstream_list = NULL;
588 getdns_list *tas = NULL;
711 getdns_list *tas = NULL, *hints = NULL;
712 getdns_dict *pubkey_pin = NULL;
713 getdns_list *suffixes;
714 char *suffix;
715 getdns_bindata bindata;
589716 size_t upstream_count = 0;
717 FILE *fh;
718 uint32_t klass;
590719
591720 for (i = 1; i < argc; i++) {
592721 arg = argv[i];
602731 " %d", r);
603732 break;
604733 }
734 } else if (strncmp(arg+1, "specify_class=", 14) == 0) {
735 if (strncasecmp(arg+15, "IN", 3) == 0)
736 r = getdns_dict_set_int(extensions,
737 "specify_class", GETDNS_RRCLASS_IN);
738 else if (strncasecmp(arg+15, "CH", 3) == 0)
739 r = getdns_dict_set_int(extensions,
740 "specify_class", GETDNS_RRCLASS_CH);
741 else if (strncasecmp(arg+15, "HS", 3) == 0)
742 r = getdns_dict_set_int(extensions,
743 "specify_class", GETDNS_RRCLASS_HS);
744 else if (strncasecmp(arg+15, "NONE", 5) == 0)
745 r = getdns_dict_set_int(extensions,
746 "specify_class", GETDNS_RRCLASS_NONE);
747 else if (strncasecmp(arg+15, "ANY", 4) == 0)
748 r = getdns_dict_set_int(extensions,
749 "specify_class", GETDNS_RRCLASS_ANY);
750 else if (strncasecmp(arg+15, "CLASS", 5) == 0) {
751 klass = strtol(arg + 20, &endptr, 10);
752 if (*endptr || klass > 255)
753 fprintf(stderr,
754 "Unknown class: %s\n",
755 arg+15);
756 else
757 r = getdns_dict_set_int(extensions,
758 "specify_class", klass);
759
760 } else
761 fprintf(stderr,
762 "Unknown class: %s\n", arg+15);
605763 } else if (arg[1] == '0') {
606764 /* Unset all existing extensions*/
607765 getdns_dict_destroy(extensions);
666824 case 'd':
667825 (void) getdns_context_set_edns_do_bit(context, 0);
668826 break;
827 case 'f':
828 if (c[1] != 0 || ++i >= argc || !*argv[i]) {
829 fprintf(stderr, "file name expected "
830 "after -f\n");
831 return GETDNS_RETURN_GENERIC_ERROR;
832 }
833 if (!(fh = fopen(argv[i], "r"))) {
834 fprintf(stderr, "Could not open \"%s\""
835 ": %s\n",argv[i], strerror(errno));
836 return GETDNS_RETURN_GENERIC_ERROR;
837 }
838 if (getdns_fp2rr_list(fh, &tas, NULL, 3600)) {
839 fprintf(stderr,"Could not parse "
840 "\"%s\"\n", argv[i]);
841 return GETDNS_RETURN_GENERIC_ERROR;
842 }
843 fclose(fh);
844 if (getdns_context_set_dnssec_trust_anchors(
845 context, tas)) {
846 fprintf(stderr,"Could not set "
847 "trust anchors from \"%s\"\n",
848 argv[i]);
849 return GETDNS_RETURN_GENERIC_ERROR;
850 }
851 getdns_list_destroy(tas);
852 tas = NULL;
853 break;
669854 case 'F':
670855 if (c[1] != 0 || ++i >= argc || !*argv[i]) {
671856 fprintf(stderr, "file name expected "
696881 case 'J':
697882 json = 1;
698883 break;
884 case 'K':
885 if (c[1] != 0 || ++i >= argc || !*argv[i]) {
886 fprintf(stderr, "pin string of the form "
887 EXAMPLE_PIN
888 "expected after -K\n");
889 return GETDNS_RETURN_GENERIC_ERROR;
890 }
891 pubkey_pin = getdns_pubkey_pin_create_from_string(context,
892 argv[i]);
893 if (pubkey_pin == NULL) {
894 fprintf(stderr, "could not convert '%s' into a "
895 "public key pin.\n"
896 "Good pins look like: " EXAMPLE_PIN "\n"
897 "Please see RFC 7469 for details about "
898 "the format\n", argv[i]);
899 return GETDNS_RETURN_GENERIC_ERROR;
900 }
901 if (pubkey_pinset == NULL)
902 pubkey_pinset = getdns_list_create_with_context(context);
903 if (r = getdns_list_set_dict(pubkey_pinset, pincount++,
904 pubkey_pin), r) {
905 fprintf(stderr, "Failed to add pin to pinset (error %d: %s)\n",
906 r, getdns_get_errorstr_by_id(r));
907 getdns_dict_destroy(pubkey_pin);
908 pubkey_pin = NULL;
909 return GETDNS_RETURN_GENERIC_ERROR;
910 }
911 getdns_dict_destroy(pubkey_pin);
912 pubkey_pin = NULL;
913 break;
699914 case 'k':
700915 print_trust_anchors = 1;
701916 break;
705920 break;
706921 case 'm':
707922 getdns_context_set_tls_authentication(context,
708 GETDNS_AUTHENTICATION_HOSTNAME);
923 GETDNS_AUTHENTICATION_REQUIRED);
709924 break;
710925 case 'P':
711926 if (c[1] != 0 || ++i >= argc || !*argv[i]) {
733948 getdns_context_set_resolution_type(
734949 context,
735950 GETDNS_RESOLUTION_RECURSING);
951 break;
952 case 'R':
953 if (c[1] != 0 || ++i >= argc || !*argv[i]) {
954 fprintf(stderr, "file name expected "
955 "after -f\n");
956 return GETDNS_RETURN_GENERIC_ERROR;
957 }
958 if (!(fh = fopen(argv[i], "r"))) {
959 fprintf(stderr, "Could not open \"%s\""
960 ": %s\n",argv[i], strerror(errno));
961 return GETDNS_RETURN_GENERIC_ERROR;
962 }
963 if (getdns_fp2rr_list(fh, &hints, NULL, 3600)) {
964 fprintf(stderr,"Could not parse "
965 "\"%s\"\n", argv[i]);
966 return GETDNS_RETURN_GENERIC_ERROR;
967 }
968 fclose(fh);
969 if (getdns_context_set_dns_root_servers(
970 context, hints)) {
971 fprintf(stderr,"Could not set "
972 "root servers from \"%s\"\n",
973 argv[i]);
974 return GETDNS_RETURN_GENERIC_ERROR;
975 }
976 getdns_list_destroy(hints);
977 hints = NULL;
736978 break;
737979 case 's':
738980 getdns_context_set_resolution_type(
7731015 getdns_context_set_idle_timeout(
7741016 context, timeout);
7751017 goto next;
1018 case 'W':
1019 (void) getdns_context_set_append_name(context,
1020 GETDNS_APPEND_NAME_ALWAYS);
1021 break;
1022 case '1':
1023 (void) getdns_context_set_append_name(context,
1024 GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE);
1025 break;
1026 case 'M':
1027 (void) getdns_context_set_append_name(context,
1028 GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE);
1029 break;
1030 case 'N':
1031 (void) getdns_context_set_append_name(context,
1032 GETDNS_APPEND_NAME_NEVER);
1033 break;
1034 case 'Z':
1035 if (c[1] != 0 || ++i >= argc || !*argv[i]) {
1036 fprintf(stderr, "suffixes expected"
1037 "after -Z\n");
1038 return GETDNS_RETURN_GENERIC_ERROR;
1039 }
1040 if (!(suffixes = getdns_list_create()))
1041 return GETDNS_RETURN_MEMORY_ERROR;
1042 suffix = strtok(argv[i], ",");
1043 j = 0;
1044 while (suffix) {
1045 bindata.size = strlen(suffix);
1046 bindata.data = (void *)suffix;
1047 (void) getdns_list_set_bindata(
1048 suffixes, j++, &bindata);
1049 suffix = strtok(NULL, ",");
1050 }
1051 (void) getdns_context_set_suffix(context,
1052 suffixes);
1053 getdns_list_destroy(suffixes);
1054 goto next;
7761055 case 'T':
7771056 getdns_context_set_dns_transport(context,
7781057 GETDNS_TRANSPORT_TCP_ONLY);
7881067 case 'E':
7891068 getdns_context_set_dns_transport(context,
7901069 GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN);
791 break;
792 case 'R':
793 getdns_context_set_dns_transport(context,
794 GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN);
7951070 break;
7961071 case 'u':
7971072 getdns_context_set_dns_transport(context,
8181093 break;
8191094 case 'B':
8201095 batch_mode = 1;
821 break;
1096 break;
8221097
8231098
8241099 default:
8331108 }
8341109 if (r)
8351110 return r;
1111 if (pubkey_pinset && upstream_count) {
1112 getdns_dict *upstream;
1113 /* apply the accumulated pubkey pinset to all upstreams: */
1114 for (i = 0; i < upstream_count; i++) {
1115 if (r = getdns_list_get_dict(upstream_list, i, &upstream), r) {
1116 fprintf(stderr, "Failed to get upstream %lu when adding pinset\n", (long unsigned int)i);
1117 return r;
1118 }
1119 if (r = getdns_dict_set_list(upstream, "tls_pubkey_pinset", pubkey_pinset), r) {
1120 fprintf(stderr, "Failed to set pubkey pinset on upstream %lu\n", (long unsigned int)i);
1121 return r;
1122 }
1123 }
1124 }
8361125 if (upstream_count &&
8371126 (r = getdns_context_set_upstream_recursive_servers(
8381127 context, upstream_list))) {
8441133 return CONTINUE;
8451134 }
8461135 if (print_trust_anchors) {
847 if ((tas = getdns_root_trust_anchor(NULL))) {
1136 if (!getdns_context_get_dnssec_trust_anchors(context, &tas)) {
1137 /* if ((tas = getdns_root_trust_anchor(NULL))) { */
8481138 fprintf(stdout, "%s\n", getdns_pretty_print_list(tas));
8491139 return CONTINUE;
8501140 } else
+0
-47
src/test/tests_json-pointers.c less more
0 #include <stdio.h>
1 #include <getdns/getdns.h>
2 #include <getdns/getdns_extra.h>
3
4 int main()
5 {
6 getdns_return_t r = GETDNS_RETURN_MEMORY_ERROR;
7 getdns_dict *dict = NULL;
8 unsigned char bladiebla_str[] = "bla die bla";
9 getdns_bindata bladiebla = { sizeof(bladiebla_str), bladiebla_str };
10
11 if (!(dict = getdns_dict_create()))
12 fprintf(stderr, "Could not create dict");
13
14 else if ((r = getdns_dict_set_int(dict, "/bla/bloe/blie", 53280))
15 || (r = getdns_dict_set_int(dict, "/bla/hola", 53281))
16 || (r = getdns_dict_set_int(dict, "/bla/cola/-", 1))
17 || (r = getdns_dict_set_int(dict, "/bla/cola/-", 2))
18 || (r = getdns_dict_set_int(dict, "/bla/cola/-/drie", 3))
19 || (r = getdns_dict_set_int(dict, "/bla/cola/-", 4))
20 || (r = getdns_dict_set_int(dict, "/bla/cola/1", 5))
21 || (r = getdns_dict_set_int(dict, "/bla/cola/2/zes", 6))
22 || (r = getdns_dict_set_bindata(dict, "/die/bla", &bladiebla))
23 )
24 fprintf(stderr, "Error setting dict data");
25 else {
26 char *dict_str = getdns_pretty_print_dict(dict);
27
28 if (!dict_str) {
29 fprintf(stderr, "Could not convert dict to string");
30 r = GETDNS_RETURN_MEMORY_ERROR;
31 } else {
32 printf("%s\n", dict_str);
33 free(dict_str);
34 }
35 }
36 if (r)
37 fprintf(stderr, ": %s\n", getdns_get_errorstr_by_id(r));
38
39 if (dict)
40 getdns_dict_destroy(dict);
41
42 if (r)
43 exit(EXIT_FAILURE);
44
45 exit(EXIT_SUCCESS);
46 }
+0
-24
src/test/tests_json-pointers.good less more
0 {
1 "bla":
2 {
3 "bloe":
4 {
5 "blie": 53280
6 },
7 "cola":
8 [
9 1,
10 5,
11 {
12 "drie": 3,
13 "zes": 6
14 },
15 4
16 ],
17 "hola": 53281
18 },
19 "die":
20 {
21 "bla": <bindata of "bla die bla">
22 }
23 }
4646 #define TRANSPORT_PIPELINE "pipeline"
4747 #define TRANSPORT_TLS_KEEPOPEN "tls"
4848 #define TRANSPORT_TLS_TCP_KEEPOPEN "dns-over-tls"
49 #define TRANSPORT_STARTTLS_TCP_KEEPOPEN "starttls"
5049 #define RESOLUTION_STUB "stub"
5150 #define RESOLUTION_REC "rec"
5251
110109 getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN);
111110 else if (strncmp(transport, TRANSPORT_TLS_TCP_KEEPOPEN, 12) == 0)
112111 getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN);
113 else if (strncmp(transport, TRANSPORT_STARTTLS_TCP_KEEPOPEN, 8) == 0)
114 getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN);
115112 else if (strncmp(transport, TRANSPORT_UDP_TCP, 3) != 0) {
116113 fprintf(stderr, "Invalid transport %s, must be one of udp, udp_tcp, tcp or pipeline\n", transport);
117114 exit(EXIT_FAILURE);
22 DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
33 SERVER_IP="8.8.8.8"
44 TLS_SERVER_IP="185.49.141.38~getdnsapi.net"
5 TLS_SERVER_KEY="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9S="
6 TLS_SERVER_WRONG_KEY="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc1S="
57 GOOD_RESULT_SYNC="Status was: At least one response was returned"
68 GOOD_RESULT_ASYNC="successfull"
79 BAD_RESULT_SYNC="1 'Generic error'"
4850 echo "it can be used to check the basic functionality for now. It is recommended that"
4951 echo "local or known test servers are used, but it should work with the default servers:"
5052 echo " - Google Open DNS for TCP and UDP only "
51 echo "- the getdnsapi.net test server Open Resolver for TLS, STARTTLS, TCP and UDP"
53 echo "- the getdnsapi.net test server Open Resolver for TLS, TCP and UDP"
5254 echo "NOTE: By default this script assumes it is located in the same directory"
5355 echo "as the getdns_query binary. If it is not, then the location of the binary"
5456 echo "can be specified via the command line option."
5658 echo "usage: test_transport.sh"
5759 echo " -p path to getdns_query binary"
5860 echo " -s server configured for only TCP and UDP"
59 echo " -t server configured for TLS, STARTTLS, TCP and UDP"
61 echo " -t server configured for TLS, TCP and UDP"
6062 echo " (This must include the hostname e.g. 185.49.141.38~getdnsapi.net)"
63 echo " -k SPKI pin for server configured for TLS, TCP and UDP"
6164 }
6265
63 while getopts ":p:s:t:dh" opt; do
66 while getopts ":p:s:t:k:dh" opt; do
6467 case $opt in
6568 d ) set -x ;;
6669 p ) DIR=$OPTARG ;;
6770 s ) SERVER_IP=$OPTARG ; echo "Setting server to $OPTARG" ;;
6871 t ) TLS_SERVER_IP=$OPTARG ; echo "Setting TLS server to $OPTARG" ;;
72 k ) TLS_SERVER_KEY=$OPTARG ; echo "Setting TLS server key to $OPTARG" ;;
6973 h ) usage ; exit ;;
7074 esac
7175 done
7276
7377 TLS_SERVER_IP_NO_NAME=`echo ${TLS_SERVER_IP%~*}`
7478 echo $TLS_SERVER_IP_NO_NAME
79 TLS_SERVER_IP_WRONG_NAME=`echo ${TLS_SERVER_IP::${#TLS_SERVER_IP}-1}`
7580
7681 GOOD_QUERIES=(
7782 "-s -A -q getdnsapi.net -l U @${SERVER_IP} "
7883 "-s -A -q getdnsapi.net -l T @${SERVER_IP} "
7984 "-s -A -q getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}"
80 "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP}")
81 #"-s -A -q getdnsapi.net -l S @${TLS_SERVER_IP_NO_NAME}")
85 "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP}"
86 "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\""
87 "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_KEY}\""
88 "-s -G -q DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D")
8289
8390 GOOD_FALLBACK_QUERIES=(
8491 "-s -A -q getdnsapi.net -l LT @${SERVER_IP}"
8996 "-s -G -q DNSKEY getdnsapi.net -l UT @${SERVER_IP} -b 512 -D")
9097
9198 NOT_AVAILABLE_QUERIES=(
92 "-s -A -q getdnsapi.net -l L @${SERVER_IP} "
93 #"-s -A -q getdnsapi.net -l S @${SERVER_IP} "
94 "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} "
95 "-s -G -q DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D")
99 "-s -A -q getdnsapi.net -l L @${SERVER_IP}"
100 "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_WRONG_NAME}"
101 "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME}"
102 "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} ${TLS_SERVER_WRONG_KEY}")
103
96104
97105 echo "Starting transport test"
98106 echo
115115 #define TIMEOUT_FOREVER ((int64_t)-1)
116116 #define ASSERT_UNREACHABLE 0
117117
118 #define GETDNS_TRANSPORTS_MAX 4
119 #define GETDNS_UPSTREAM_TRANSPORTS 3
118 #define GETDNS_TRANSPORTS_MAX 3
119 #define GETDNS_UPSTREAM_TRANSPORTS 2
120120
121121 /** @}
122122 */
202202 /* request type */
203203 uint16_t request_type;
204204
205 /* request class */
206 uint16_t request_class;
207
208205 /* dnssec status */
209206 int dnssec_status;
207
208 /* tsig status:
209 * GETDNS_DNSSEC_INDETERMINATE means "No TSIG processing"
210 * GETDNS_DNSSEC_INSECURE means "TSIG sent, validate reply"
211 * GETDNS_DNSSEC_SECURE means "Validated"
212 * GETDNS_DNSSEC_BOGUS means "Validation failed"
213 */
214 int tsig_status;
210215
211216 /* For stub resolving */
212217 struct getdns_upstream *upstream;
222227 int edns_maximum_udp_payload_size;
223228 uint16_t max_udp_payload_size;
224229
230 size_t keepalive_sent;
231
225232 /* Network requests scheduled to write after me */
226233 struct getdns_network_req *write_queue_tail;
227234
228 /* Some fields to record info for return_call_debugging */
235 /* Some fields to record info for return_call_reporting */
229236 uint64_t debug_start_time;
230237 uint64_t debug_end_time;
231238 size_t debug_tls_auth_status;
270277 /* name */
271278 uint8_t name[256];
272279 size_t name_len;
280
281 getdns_append_name_t append_name;
282 const uint8_t *suffix;
283 size_t suffix_len;
284 int suffix_appended;
285
286 uint16_t request_class;
273287
274288 /* canceled flag */
275289 int canceled;
288302 int edns_cookies;
289303 int edns_client_subnet_private;
290304 uint16_t tls_query_padding_blocksize;
291 int return_call_debugging;
305 int return_call_reporting;
306 int add_warning_for_bad_dns;
292307
293308 /* Internally used by return_validation_chain */
294309 int dnssec_ok_checking_disabled;
378393 uint16_t code, uint16_t sz, const void* data);
379394 void _getdns_network_req_clear_upstream_options(getdns_network_req * req);
380395
396 /* Adds TSIG signature (if needed) and returns query length */
397 size_t _getdns_network_req_add_tsig(getdns_network_req *req);
398
399 void _getdns_network_validate_tsig(getdns_network_req *req);
400
401 void _getdns_netreq_reinit(getdns_network_req *netreq);
402
381403 #endif
382404 /* types-internal.h */
3434 #define UTIL_LOG_H
3535
3636 #include "config.h"
37 #include "util-internal.h"
37 #include "debug.h"
3838
3939 #if defined(SEC_DEBUG) && SEC_DEBUG
4040 #define verbose(x, ...) DEBUG_NL(__VA_ARGS__)
0 /*
1 * util/winsock_event.c - implementation of the getdns winsock event handler.
2 *
3 * Copyright (c) 2015, Verisign/NLnet Labs. All rights reserved.
4 *
5 * This software is open source.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 *
18 * Neither the name of the NLNET LABS/Verisign nor the names of its contributors may
19 * be used to endorse or promote products derived from this software without
20 * specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34 /**
35 * \file
36 * Implementation of the getdns WinSock2 API event notification handler
37 * for the getdns Windows port.
38 * Code is originally from the Unbound source for Windows.
39 */
40
41 #include "config.h"
42 #ifdef USE_WINSOCK // only included for Windows builds
43 #include <signal.h>
44 #ifdef HAVE_TIME_H
45 #include <time.h>
46 #endif
47 #include <sys/time.h>
48 #include "util/winsock_event.h"
49 #include "util/fptr_wlist.h"
50
51 /**
52 * implementation of log_err
53 * @param format: format string printf-style.
54 */
55 void
56 log_err(const char *format, ...)
57 {
58 va_list args;
59 va_start(args, format);
60 fprintf(stderr, "error ");
61 fprintf(stderr, format, args);
62 va_end(args);
63 }
64
65
66 char* wsa_strerror(DWORD err)
67 {
68 static char unknown[32];
69
70 switch (err) {
71 case WSA_INVALID_HANDLE: return "Specified event object handle is invalid.";
72 case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available.";
73 case WSA_INVALID_PARAMETER: return "One or more parameters are invalid.";
74 case WSA_OPERATION_ABORTED: return "Overlapped operation aborted.";
75 case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state.";
76 case WSA_IO_PENDING: return "Overlapped operations will complete later.";
77 case WSAEINTR: return "Interrupted function call.";
78 case WSAEBADF: return "File handle is not valid.";
79 case WSAEACCES: return "Permission denied.";
80 case WSAEFAULT: return "Bad address.";
81 case WSAEINVAL: return "Invalid argument.";
82 case WSAEMFILE: return "Too many open files.";
83 case WSAEWOULDBLOCK: return "Resource temporarily unavailable.";
84 case WSAEINPROGRESS: return "Operation now in progress.";
85 case WSAEALREADY: return "Operation already in progress.";
86 case WSAENOTSOCK: return "Socket operation on nonsocket.";
87 case WSAEDESTADDRREQ: return "Destination address required.";
88 case WSAEMSGSIZE: return "Message too long.";
89 case WSAEPROTOTYPE: return "Protocol wrong type for socket.";
90 case WSAENOPROTOOPT: return "Bad protocol option.";
91 case WSAEPROTONOSUPPORT: return "Protocol not supported.";
92 case WSAESOCKTNOSUPPORT: return "Socket type not supported.";
93 case WSAEOPNOTSUPP: return "Operation not supported.";
94 case WSAEPFNOSUPPORT: return "Protocol family not supported.";
95 case WSAEAFNOSUPPORT: return "Address family not supported by protocol family.";
96 case WSAEADDRINUSE: return "Address already in use.";
97 case WSAEADDRNOTAVAIL: return "Cannot assign requested address.";
98 case WSAENETDOWN: return "Network is down.";
99 case WSAENETUNREACH: return "Network is unreachable.";
100 case WSAENETRESET: return "Network dropped connection on reset.";
101 case WSAECONNABORTED: return "Software caused connection abort.";
102 case WSAECONNRESET: return "Connection reset by peer.";
103 case WSAENOBUFS: return "No buffer space available.";
104 case WSAEISCONN: return "Socket is already connected.";
105 case WSAENOTCONN: return "Socket is not connected.";
106 case WSAESHUTDOWN: return "Cannot send after socket shutdown.";
107 case WSAETOOMANYREFS: return "Too many references.";
108 case WSAETIMEDOUT: return "Connection timed out.";
109 case WSAECONNREFUSED: return "Connection refused.";
110 case WSAELOOP: return "Cannot translate name.";
111 case WSAENAMETOOLONG: return "Name too long.";
112 case WSAEHOSTDOWN: return "Host is down.";
113 case WSAEHOSTUNREACH: return "No route to host.";
114 case WSAENOTEMPTY: return "Directory not empty.";
115 case WSAEPROCLIM: return "Too many processes.";
116 case WSAEUSERS: return "User quota exceeded.";
117 case WSAEDQUOT: return "Disk quota exceeded.";
118 case WSAESTALE: return "Stale file handle reference.";
119 case WSAEREMOTE: return "Item is remote.";
120 case WSASYSNOTREADY: return "Network subsystem is unavailable.";
121 case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range.";
122 case WSANOTINITIALISED: return "Successful WSAStartup not yet performed.";
123 case WSAEDISCON: return "Graceful shutdown in progress.";
124 case WSAENOMORE: return "No more results.";
125 case WSAECANCELLED: return "Call has been canceled.";
126 case WSAEINVALIDPROCTABLE: return "Procedure call table is invalid.";
127 case WSAEINVALIDPROVIDER: return "Service provider is invalid.";
128 case WSAEPROVIDERFAILEDINIT: return "Service provider failed to initialize.";
129 case WSASYSCALLFAILURE: return "System call failure.";
130 case WSASERVICE_NOT_FOUND: return "Service not found.";
131 case WSATYPE_NOT_FOUND: return "Class type not found.";
132 case WSA_E_NO_MORE: return "No more results.";
133 case WSA_E_CANCELLED: return "Call was canceled.";
134 case WSAEREFUSED: return "Database query was refused.";
135 case WSAHOST_NOT_FOUND: return "Host not found.";
136 case WSATRY_AGAIN: return "Nonauthoritative host not found.";
137 case WSANO_RECOVERY: return "This is a nonrecoverable error.";
138 case WSANO_DATA: return "Valid name, no data record of requested type.";
139 case WSA_QOS_RECEIVERS: return "QOS receivers.";
140 case WSA_QOS_SENDERS: return "QOS senders.";
141 case WSA_QOS_NO_SENDERS: return "No QOS senders.";
142 case WSA_QOS_NO_RECEIVERS: return "QOS no receivers.";
143 case WSA_QOS_REQUEST_CONFIRMED: return "QOS request confirmed.";
144 case WSA_QOS_ADMISSION_FAILURE: return "QOS admission error.";
145 case WSA_QOS_POLICY_FAILURE: return "QOS policy failure.";
146 case WSA_QOS_BAD_STYLE: return "QOS bad style.";
147 case WSA_QOS_BAD_OBJECT: return "QOS bad object.";
148 case WSA_QOS_TRAFFIC_CTRL_ERROR: return "QOS traffic control error.";
149 case WSA_QOS_GENERIC_ERROR: return "QOS generic error.";
150 case WSA_QOS_ESERVICETYPE: return "QOS service type error.";
151 case WSA_QOS_EFLOWSPEC: return "QOS flowspec error.";
152 case WSA_QOS_EPROVSPECBUF: return "Invalid QOS provider buffer.";
153 case WSA_QOS_EFILTERSTYLE: return "Invalid QOS filter style.";
154 case WSA_QOS_EFILTERTYPE: return "Invalid QOS filter type.";
155 case WSA_QOS_EFILTERCOUNT: return "Incorrect QOS filter count.";
156 case WSA_QOS_EOBJLENGTH: return "Invalid QOS object length.";
157 case WSA_QOS_EFLOWCOUNT: return "Incorrect QOS flow count.";
158 /*case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QOS object.";*/
159 case WSA_QOS_EPOLICYOBJ: return "Invalid QOS policy object.";
160 case WSA_QOS_EFLOWDESC: return "Invalid QOS flow descriptor.";
161 case WSA_QOS_EPSFLOWSPEC: return "Invalid QOS provider-specific flowspec.";
162 case WSA_QOS_EPSFILTERSPEC: return "Invalid QOS provider-specific filterspec.";
163 case WSA_QOS_ESDMODEOBJ: return "Invalid QOS shape discard mode object.";
164 case WSA_QOS_ESHAPERATEOBJ: return "Invalid QOS shaping rate object.";
165 case WSA_QOS_RESERVED_PETYPE: return "Reserved policy QOS element type.";
166 default:
167 snprintf(unknown, sizeof(unknown),
168 "unknown WSA error code %d", (int)err);
169 return unknown;
170 }
171 }
172
173 int _getdns_mini_ev_cmp(const void* a, const void* b)
174 {
175 const struct _getdns_event *e = (const struct _getdns_event*)a;
176 const struct _getdns_event *f = (const struct _getdns_event*)b;
177 if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec)
178 return -1;
179 if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec)
180 return 1;
181 if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec)
182 return -1;
183 if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec)
184 return 1;
185 if(e < f)
186 return -1;
187 if(e > f)
188 return 1;
189 return 0;
190 }
191
192 /** set time */
193 static int
194 settime(struct _getdns_event_base* base)
195 {
196 if(gettimeofday(base->time_tv, NULL) < 0) {
197 return -1;
198 }
199 #ifndef S_SPLINT_S
200 *base->time_secs = (time_t)base->time_tv->tv_sec;
201 #endif
202 return 0;
203 }
204
205 #ifdef WINSOCK_DEBUG
206 /**
207 * Find a fd in the list of items.
208 * Note that not all items have a fd associated (those are -1).
209 * Signals are stored separately, and not searched.
210 * @param base: event base to look in.
211 * @param fd: what socket to look for.
212 * @return the index in the array, or -1 on failure.
213 */
214 static int
215 find_fd(struct _getdns_event_base* base, int fd)
216 {
217 int i;
218 for(i=0; i<base->max; i++) {
219 if(base->items[i]->ev_fd == fd)
220 return i;
221 }
222 return -1;
223 }
224 #endif
225
226 /** Find ptr in base array */
227 static void
228 zero_waitfor(WSAEVENT waitfor[], WSAEVENT x)
229 {
230 int i;
231 for(i=0; i<WSK_MAX_ITEMS; i++) {
232 if(waitfor[i] == x)
233 waitfor[i] = 0;
234 }
235 }
236
237 void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv)
238 {
239 struct _getdns_event_base* base = (struct _getdns_event_base*)malloc(
240 sizeof(struct _getdns_event_base));
241 if(!base)
242 return NULL;
243 memset(base, 0, sizeof(*base));
244 base->time_secs = time_secs;
245 base->time_tv = time_tv;
246 if(settime(base) < 0) {
247 _getdns_event_base_free(base);
248 return NULL;
249 }
250 base->items = (struct _getdns_event**)calloc(WSK_MAX_ITEMS,
251 sizeof(struct _getdns_event*));
252 if(!base->items) {
253 _getdns_event_base_free(base);
254 return NULL;
255 }
256 base->cap = WSK_MAX_ITEMS;
257 base->max = 0;
258 base->times = _getdns_rbtree_create(_getdns_mini_ev_cmp);
259 if(!base->times) {
260 _getdns_event_base_free(base);
261 return NULL;
262 }
263 base->signals = (struct _getdns_event**)calloc(MAX_SIG,
264 sizeof(struct _getdns_event*));
265 if(!base->signals) {
266 _getdns_event_base_free(base);
267 return NULL;
268 }
269 base->tcp_stickies = 0;
270 base->tcp_reinvigorated = 0;
271
272 return base;
273 }
274
275 const char *_getdns_event_get_version(void)
276 {
277 return "winsock-event-"PACKAGE_VERSION;
278 }
279
280 const char *_getdns_event_get_method(void)
281 {
282 return "WSAWaitForMultipleEvents";
283 }
284
285 /** call timeouts handlers, and return how long to wait for next one or -1 */
286 void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now,
287 struct timeval* wait)
288 {
289 struct _getdns_event* p;
290 #ifndef S_SPLINT_S
291 wait->tv_sec = (time_t)-1;
292 #endif
293
294 while((_getdns_rbnode_t*)(p = (struct _getdns_event*)_getdns_rbtree_first(base->times))
295 !=RBTREE_NULL) {
296 #ifndef S_SPLINT_S
297 if(p->ev_timeout.tv_sec > now->tv_sec ||
298 (p->ev_timeout.tv_sec==now->tv_sec &&
299 p->ev_timeout.tv_usec > now->tv_usec)) {
300 /* there is a next larger timeout. wait for it */
301 wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec;
302 if(now->tv_usec > p->ev_timeout.tv_usec) {
303 wait->tv_sec--;
304 wait->tv_usec = 1000000 - (now->tv_usec -
305 p->ev_timeout.tv_usec);
306 } else {
307 wait->tv_usec = p->ev_timeout.tv_usec
308 - now->tv_usec;
309 }
310 return;
311 }
312 #endif
313 /* event times out, remove it */
314 (void)_getdns_rbtree_delete(base->times, p);
315 p->ev_events &= ~EV_TIMEOUT;
316 fptr_ok(fptr_whitelist_event(p->ev_callback));
317 (*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg);
318 }
319 }
320
321 /** handle is_signal events and see if signalled */
322 static void _getdns_handle_signal(struct _getdns_event* ev)
323 {
324 printf("In _getdns_handle_signal\n");
325 DWORD ret;
326 //log_assert(ev->is_signal && ev->hEvent);
327 /* see if the event is signalled */
328 ret = WSAWaitForMultipleEvents(1, &ev->hEvent, 0 /* any object */,
329 0 /* return immediately */, 0 /* not alertable for IOcomple*/);
330 if(ret == WSA_WAIT_IO_COMPLETION || ret == WSA_WAIT_FAILED) {
331 log_err("getdns: WSAWaitForMultipleEvents(signal) failed: %s",
332 wsa_strerror(WSAGetLastError()));
333 return;
334 }
335 if(ret == WSA_WAIT_TIMEOUT) {
336 /* not signalled */
337 return;
338 }
339
340 /* reset the signal */
341 if(!WSAResetEvent(ev->hEvent))
342 log_err("getdns: WSAResetEvent failed: %s",
343 wsa_strerror(WSAGetLastError()));
344 /* do the callback (which may set the signal again) */
345 fptr_ok(fptr_whitelist_event(ev->ev_callback));
346 (*ev->ev_callback)(ev->ev_fd, ev->ev_events, ev->ev_arg);
347 }
348
349 /** call select and callbacks for that */
350 int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
351 {
352 DWORD timeout = 0; /* in milliseconds */
353 DWORD ret;
354 WSANETWORKEVENTS netev;
355 struct _getdns_event* eventlist[WSK_MAX_ITEMS];
356 int i, numwait = 0, startidx = 0;
357 int newstickies = 0;
358 struct timeval nultm;
359
360 #ifndef S_SPLINT_S
361 if(wait->tv_sec==(time_t)-1)
362 wait = NULL;
363 if (wait)
364 // timeout = 10 + wait->tv_usec / 1000;
365 timeout = wait->tv_sec * 1000 + wait->tv_usec / 1000;
366 if(base->tcp_stickies) {
367 wait = &nultm;
368 nultm.tv_sec = 0;
369 nultm.tv_usec = 0;
370 timeout = 0; /* no waiting, we have sticky events */
371 }
372 #endif
373
374 /* prepare event array */
375 for(i=0; i<base->max; i++) {
376 if(base->items[i]->ev_fd == -1 && !base->items[i]->is_signal)
377 continue; /* skip timer only events */
378 eventlist[numwait] = base->items[i];
379 base->waitfor[numwait++] = base->items[i]->hEvent;
380 printf("winsock_event bmax=%d numwait=%d wait=%x "
381 "timeout=%d hEvent %d\n", base->max, numwait, (int)wait,
382 (int)timeout, (int)base->items[i]->hEvent);
383 if (numwait == WSK_MAX_ITEMS)
384 break; /* sanity check */
385 }
386 //log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);
387
388 /* do the wait */
389 if(numwait == 0) {
390 /* WSAWaitFor.. doesn't like 0 event objects */
391 if(wait) {
392 Sleep(timeout);
393 }
394 }
395 else {
396 //gv: do not schedule udp write
397 for (i = 0; i<base->max; i++) {
398 if (!base->items[i]->is_tcp && base->items[i]->ev_events&EV_WRITE) {
399 printf("skip UDP sched\n");
400 (*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
401 EV_WRITE & eventlist[i]->ev_events,
402 eventlist[i]->ev_arg);
403 return 0;
404 }
405 }
406 printf("before wait %d\n", base->items[0]->ev_events);
407 ret = WSAWaitForMultipleEvents(numwait, base->waitfor,
408 0 /* do not wait for all, just one will do */,
409 wait?timeout:WSA_INFINITE,
410 0); /* we are not alertable (IO completion events) */
411 printf("after wait %d %d\n", (int)ret, numwait);
412 if(ret == WSA_WAIT_IO_COMPLETION) {
413 //printf("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION");
414 return -1;
415 } else if(ret == WSA_WAIT_FAILED) {
416 //printf("getdns: WSAWaitForMultipleEvents failed: %s",
417 // wsa_strerror(WSAGetLastError()));
418 return -1;
419 } else if(ret == WSA_WAIT_TIMEOUT) {
420 printf("timeout\n");
421 } else
422 startidx = ret - WSA_WAIT_EVENT_0;
423 }
424 ////verbose(VERB_CLIENT, "winsock_event wake was_timeout=%d startidx=%d",
425 // was_timeout, startidx);
426
427 /* get new time after wait */
428 if(settime(base) < 0)
429 return -1;
430
431 /* callbacks */
432 if(base->tcp_stickies)
433 startidx = 0; /* process all events, some are sticky */
434 for(i=startidx; i<numwait; i++)
435 eventlist[i]->just_checked = 1;
436
437 //verbose(VERB_CLIENT, "winsock_event signals");
438 for(i=startidx; i<numwait; i++) {
439 if(!base->waitfor[i])
440 continue; /* was deleted */
441 if(eventlist[i]->is_signal) {
442 eventlist[i]->just_checked = 0;
443 _getdns_handle_signal(eventlist[i]);
444 }
445 }
446 /* early exit - do not process network, exit quickly */
447 if(base->need_to_exit)
448 return 0;
449
450 //verbose(VERB_CLIENT, "winsock_event net");
451 for(i=startidx; i<numwait; i++) {
452 short bits = 0;
453 /* eventlist[i] fired */
454 /* see if eventlist[i] is still valid and just checked from
455 * WSAWaitForEvents */
456 if(!base->waitfor[i])
457 continue; /* was deleted */
458 if(!eventlist[i]->just_checked)
459 continue; /* added by other callback */
460 if(eventlist[i]->is_signal)
461 continue; /* not a network event at all */
462 eventlist[i]->just_checked = 0;
463
464 if(WSAEnumNetworkEvents(eventlist[i]->ev_fd,
465 base->waitfor[i], /* reset the event handle */
466 /*NULL,*/ /* do not reset the event handle */
467 &netev) != 0) {
468 log_err("getdns: WSAEnumNetworkEvents failed: %s",
469 wsa_strerror(WSAGetLastError()));
470 return -1;
471 }
472 if((netev.lNetworkEvents & FD_READ)) {
473 if(netev.iErrorCode[FD_READ_BIT] != 0)
474 printf("FD_READ_BIT error: %s\n",
475 wsa_strerror(netev.iErrorCode[FD_READ_BIT]));
476 bits |= EV_READ;
477 printf("FD_READ_BIT\n");
478 }
479 if((netev.lNetworkEvents & FD_WRITE)) {
480 if(netev.iErrorCode[FD_WRITE_BIT] != 0)
481 printf("FD_WRITE_BIT error: %s\n",
482 wsa_strerror(netev.iErrorCode[FD_WRITE_BIT]));
483 bits |= EV_WRITE;
484 printf("FD_WRITE_BIT\n");
485 }
486 if((netev.lNetworkEvents & FD_CONNECT)) {
487 if(netev.iErrorCode[FD_CONNECT_BIT] != 0)
488 printf("FD_CONNECT_BIT error: %s\n",
489 wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT]));
490 bits |= EV_READ;
491 bits |= EV_WRITE;
492 printf("FD_CONNECT_BIT\n");
493 }
494 if((netev.lNetworkEvents & FD_ACCEPT)) {
495 if(netev.iErrorCode[FD_ACCEPT_BIT] != 0)
496 printf("FD_ACCEPT_BIT error: %s\n",
497 wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT]));
498 bits |= EV_READ;
499 printf("FD_ACCEPT_BIT\n");
500 }
501 if((netev.lNetworkEvents & FD_CLOSE)) {
502 if(netev.iErrorCode[FD_CLOSE_BIT] != 0)
503 printf("FD_CLOSE_BIT error: %s\n",
504 wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT]));
505 //g bits |= EV_READ;
506 //g bits |= EV_WRITE;
507 printf("FD_CLOSE_BIT\n");
508 }
509 if(eventlist[i]->is_tcp && eventlist[i]->stick_events) {
510
511 printf("winsock %d pass sticky %s%s\n",
512 eventlist[i]->ev_fd,
513 (eventlist[i]->old_events&EV_READ)?"EV_READ":"",
514 (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
515
516 bits |= eventlist[i]->old_events;
517 }
518 if(eventlist[i]->is_tcp && bits) {
519 eventlist[i]->old_events = bits;
520 eventlist[i]->stick_events = 1;
521 if((eventlist[i]->ev_events & bits)) {
522 newstickies = 1;
523 }
524
525 printf("winsock %d store sticky %s%s",
526 eventlist[i]->ev_fd,
527 (eventlist[i]->old_events&EV_READ)?"EV_READ":"",
528 (eventlist[i]->old_events&EV_WRITE) ? "EV_WRITE" : "");
529
530 }
531 if((bits & eventlist[i]->ev_events)) {
532 printf( "winsock event callback %p fd=%d "
533 "%s%s%s%s%s ; %s%s%s\n",
534 eventlist[i], eventlist[i]->ev_fd,
535 (netev.lNetworkEvents&FD_READ)?" FD_READ":"",
536 (netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"",
537 (netev.lNetworkEvents&FD_CONNECT)?
538 " FD_CONNECT":"",
539 (netev.lNetworkEvents&FD_ACCEPT)?
540 " FD_ACCEPT":"",
541 (netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"",
542 (bits&EV_READ)?" EV_READ":"",
543 (bits&EV_WRITE)?" EV_WRITE":"",
544 (bits&EV_TIMEOUT)?" EV_TIMEOUT":"");
545
546 fptr_ok(fptr_whitelist_event(
547 eventlist[i]->ev_callback));
548 (*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
549 bits & eventlist[i]->ev_events,
550 eventlist[i]->ev_arg);
551 }
552
553 if(eventlist[i]->is_tcp && bits)
554 printf( "winsock %d got sticky %s%s\n",
555 eventlist[i]->ev_fd,
556 (eventlist[i]->old_events&EV_READ)?"EV_READ":"",
557 (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
558
559 }
560 //verbose(VERB_CLIENT, "winsock_event net");
561 if(base->tcp_reinvigorated) {
562 printf("winsock_event reinvigorated\n");
563 base->tcp_reinvigorated = 0;
564 newstickies = 1;
565 }
566 base->tcp_stickies = newstickies;
567 //gprintf("winsock_event handle_select end\n");
568 return 0;
569 }
570
571 int _getdns_event_base_dispatch(struct _getdns_event_base *base)
572 {
573 struct timeval wait;
574 if(settime(base) < 0)
575 return -1;
576 while(!base->need_to_exit)
577 {
578 /* see if timeouts need handling */
579 _getdns_handle_timeouts(base, base->time_tv, &wait);
580 if(base->need_to_exit)
581 return 0;
582 /* do select */
583 if(_getdns_handle_select(base, &wait) < 0) {
584 if(base->need_to_exit)
585 return 0;
586 return -1;
587 }
588 }
589 return 0;
590 }
591
592 int _getdns_event_base_loopexit(struct _getdns_event_base *base,
593 struct timeval * ATTR_UNUSED(tv))
594 {
595 base->need_to_exit = 1;
596 return 0;
597 }
598
599 void _getdns_event_base_free(struct _getdns_event_base *base)
600 {
601 if(!base)
602 return;
603 if(base->items)
604 free(base->items);
605 if(base->times)
606 free(base->times);
607 if(base->signals)
608 free(base->signals);
609 free(base);
610 }
611
612 void _getdns_event_set(struct _getdns_event *ev, int fd, short bits,
613 void (*cb)(int, short, void *), void *arg)
614 {
615 ev->node.key = ev;
616 ev->ev_fd = fd;
617 ev->ev_events = bits;
618 ev->ev_callback = cb;
619 fptr_ok(fptr_whitelist_event(ev->ev_callback));
620 ev->ev_arg = arg;
621 ev->just_checked = 0;
622 ev->added = 0;
623 }
624
625 int _getdns_event_base_set(struct _getdns_event_base *base, struct _getdns_event *ev)
626 {
627 ev->ev_base = base;
628 ev->old_events = 0;
629 ev->stick_events = 0;
630 ev->added = 0;
631 return 0;
632 }
633
634 int _getdns_event_add(struct _getdns_event *ev, struct timeval *tv)
635 {
636 printf( "event_add %p added=%d fd=%d tv=" ARG_LL "d %s%s%s\n",
637 ev, ev->added, ev->ev_fd,
638 (tv?(long long)tv->tv_sec*1000+(long long)tv->tv_usec/1000:-1),
639 (ev->ev_events&EV_READ)?" EV_READ":"",
640 (ev->ev_events&EV_WRITE)?" EV_WRITE":"",
641 (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":"");
642
643 if(ev->added)
644 _getdns_event_del(ev);
645
646 ev->is_tcp = 0;
647 ev->is_signal = 0;
648 ev->just_checked = 0;
649
650 if ((ev->ev_events&(EV_READ | EV_WRITE)) && ev->ev_fd != -1) {
651 BOOL b = 0;
652 int t, l;
653 long events = 0;
654 //gprintf("\getdns_event_add %d %d\n", ev->ev_fd, events);
655
656 if (ev->ev_base->max == ev->ev_base->cap)
657 return -1;
658 ev->idx = ev->ev_base->max++;
659 ev->ev_base->items[ev->idx] = ev;
660
661 if ((ev->ev_events&EV_READ))
662 events |= FD_READ;
663 if ((ev->ev_events&EV_WRITE))
664 {
665 events |= FD_CONNECT;
666 events |= FD_WRITE;
667 }
668
669 //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);
670
671 l = sizeof(t);
672 if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_TYPE,
673 (void*)&t, &l) != 0)
674 log_err("getdns: getsockopt(SO_TYPE) failed: %s",
675 wsa_strerror(WSAGetLastError()));
676 if(t == SOCK_STREAM) {
677 /* TCP socket */
678 ev->is_tcp = 1;
679 events |= FD_CLOSE;
680 if( (ev->ev_events&EV_WRITE) )
681 events |= FD_CONNECT;
682 l = sizeof(b);
683 if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_ACCEPTCONN,
684 (void*)&b, &l) != 0)
685 log_err("getdns: getsockopt(SO_ACCEPTCONN) failed: %s",
686 wsa_strerror(WSAGetLastError()));
687 if(b) /* TCP accept socket */
688 events |= FD_ACCEPT;
689 }
690 ev->hEvent = WSACreateEvent();
691 if(ev->hEvent == WSA_INVALID_EVENT)
692 log_err("getdns: WSACreateEvent failed: %s",
693 wsa_strerror(WSAGetLastError()));
694 /* automatically sets fd to nonblocking mode.
695 * nonblocking cannot be disabled, until wsaES(fd, NULL, 0) */
696 printf("\nWSAEventSelect %d events %d hEvent %d\n", ev->ev_fd, (int)events, (int)ev->hEvent);
697 if (WSAEventSelect(ev->ev_fd, ev->hEvent, events) != 0) {
698 log_err("getdns: WSAEventSelect in getdns failed: %s",
699 wsa_strerror(WSAGetLastError()));
700 }
701 if(ev->is_tcp && ev->stick_events &&
702 (ev->ev_events & ev->old_events)) {
703 /* go to processing the sticky event right away */
704 printf("\nWSAEventSelect sticky %d events %d hEvent %d\n", ev->ev_fd, (int)events, (int)ev->hEvent);
705 ev->ev_base->tcp_reinvigorated = 1;
706 }
707 }
708
709 if(tv && (ev->ev_events&EV_TIMEOUT)) {
710 printf("\nWSAEventSelect timeout %d hEvent %d\n", ev->ev_fd, (int)ev->hEvent);
711
712 #ifndef S_SPLINT_S
713 struct timeval *now = ev->ev_base->time_tv;
714 ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec;
715 ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec;
716 while(ev->ev_timeout.tv_usec > 1000000) {
717 ev->ev_timeout.tv_usec -= 1000000;
718 ev->ev_timeout.tv_sec++;
719 }
720 #endif
721 (void)_getdns_rbtree_insert(ev->ev_base->times, &ev->node);
722 }
723 ev->added = 1;
724 return 0;
725 }
726
727 int _getdns_event_del(struct _getdns_event *ev)
728 {
729 //verbose(VERB_ALGO, "event_del %p added=%d fd=%d tv=" ARG_LL "d %s%s%s",
730 // ev, ev->added, ev->ev_fd,
731 // (ev->ev_events&EV_TIMEOUT)?(long long)ev->ev_timeout.tv_sec*1000+
732 // (long long)ev->ev_timeout.tv_usec/1000:-1,
733 // (ev->ev_events&EV_READ)?" EV_READ":"",
734 // (ev->ev_events&EV_WRITE)?" EV_WRITE":"",
735 // (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":"");
736 if(!ev->added)
737 return 0;
738 //log_assert(ev->added);
739 if((ev->ev_events&EV_TIMEOUT))
740 (void)_getdns_rbtree_delete(ev->ev_base->times, &ev->node);
741 if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) {
742 //log_assert(ev->ev_base->max > 0);
743 /* remove item and compact the list */
744 ev->ev_base->items[ev->idx] =
745 ev->ev_base->items[ev->ev_base->max-1];
746 ev->ev_base->items[ev->ev_base->max-1] = NULL;
747 ev->ev_base->max--;
748 if(ev->idx < ev->ev_base->max)
749 ev->ev_base->items[ev->idx]->idx = ev->idx;
750 zero_waitfor(ev->ev_base->waitfor, ev->hEvent);
751
752 if(WSAEventSelect(ev->ev_fd, ev->hEvent, 0) != 0)
753 log_err("getdns: WSAEventSelect(disable) failed: %s",
754 wsa_strerror(WSAGetLastError()));
755 if(!WSACloseEvent(ev->hEvent))
756 log_err("getdns: WSACloseEvent failed: %s",
757 wsa_strerror(WSAGetLastError()));
758 }
759 ev->just_checked = 0;
760 ev->added = 0;
761 return 0;
762 }
763
764 /** which base gets to handle signals */
765 static struct _getdns_event_base* signal_base = NULL;
766 /** signal handler */
767 static RETSIGTYPE sigh(int sig)
768 {
769 if(!signal_base || sig < 0 || sig >= MAX_SIG)
770 return;
771 }
772
773 int _getdns_signal_add(struct _getdns_event *ev, struct timeval * ATTR_UNUSED(tv))
774 {
775 if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG)
776 return -1;
777 signal_base = ev->ev_base;
778 ev->ev_base->signals[ev->ev_fd] = ev;
779 ev->added = 1;
780 if(signal(ev->ev_fd, sigh) == SIG_ERR) {
781 return -1;
782 }
783 return 0;
784 }
785
786 int _getdns_signal_del(struct _getdns_event *ev)
787 {
788 if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG)
789 return -1;
790 ev->ev_base->signals[ev->ev_fd] = NULL;
791 ev->added = 0;
792 return 0;
793 }
794
795 void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbits)
796 {
797 printf("winsock: tcp wouldblock %s\n",
798 eventbits==EV_READ?"EV_READ":"EV_WRITE");
799 ev->old_events &= (~eventbits);
800 if(ev->old_events == 0)
801 ev->stick_events = 0;
802 /* in case this is the last sticky event, we could
803 * possibly run an empty handler loop to reset the base
804 * tcp_stickies variable
805 */
806 }
807
808 int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev,
809 WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg)
810 {
811 if(base->max == base->cap)
812 return 0;
813 memset(ev, 0, sizeof(*ev));
814 ev->ev_fd = -1;
815 ev->ev_events = EV_READ;
816 ev->ev_callback = cb;
817 ev->ev_arg = arg;
818 ev->is_signal = 1;
819 ev->hEvent = wsaevent;
820 ev->added = 1;
821 ev->ev_base = base;
822 ev->idx = ev->ev_base->max++;
823 ev->ev_base->items[ev->idx] = ev;
824 return 1;
825 }
826
827 void winsock_unregister_wsaevent(struct _getdns_event* ev)
828 {
829 if(!ev || !ev->added) return;
830 //log_assert(ev->added && ev->ev_base->max > 0)
831 /* remove item and compact the list */
832 ev->ev_base->items[ev->idx] = ev->ev_base->items[ev->ev_base->max-1];
833 ev->ev_base->items[ev->ev_base->max-1] = NULL;
834 ev->ev_base->max--;
835 if(ev->idx < ev->ev_base->max)
836 ev->ev_base->items[ev->idx]->idx = ev->idx;
837 ev->added = 0;
838 }
839
840 #else /* USE_WINSOCK */
841 /** symbol so this codefile defines symbols. pleasing ranlib on OSX 10.5 */
842 int winsock_unused_symbol = 1;
843 #endif /* USE_WINSOCK */
0 /*
1 * util/winsock_event.h - getdns event handling for winsock on windows
2 * extracted from Unbound source code and modified for getdns
3 *
4 * Copyright (c) 2015, NLnet Labs/Verisign. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * Neither the name of the NLNET LABS or Verisign nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 /**
37 * \file
38 *
39 * This file contains interface functions with the WinSock2 API on Windows.
40 * It uses the winsock WSAWaitForMultipleEvents interface on a number of
41 * sockets.
42 * Code is originally from the Unbound source for Windows.
43 *
44 * Note that windows can only wait for max 64 events at one time.
45 *
46 * Also, file descriptors cannot be waited for.
47 *
48 * Named pipes are not easily available (and are not usable in select() ).
49 * For interprocess communication, it is possible to wait for a hEvent to
50 * be signaled by another thread.
51 *
52 * When a socket becomes readable, then it will not be flagged as
53 * readable again until you have gotten WOULDBLOCK from a recv routine.
54 * That means the event handler must store the readability (edge notify)
55 * and process the incoming data until it blocks.
56 * The function performing recv then has to inform the event handler that
57 * the socket has blocked, and the event handler can mark it as such.
58 * Thus, this file transforms the edge notify from windows to a level notify
59 * that is compatible with UNIX.
60 * The WSAEventSelect page says that it does do level notify, as long
61 * as you call a recv/write/accept at least once when it is signalled.
62 * This last bit is not true, even though documented in server2008 api docs
63 * from microsoft, it does not happen at all. Instead you have to test for
64 * WSAEWOULDBLOCK on a tcp stream, and only then retest the socket.
65 * And before that remember the previous result as still valid.
66 *
67 * To stay 'fair', instead of emptying a socket completely, the event handler
68 * can test the other (marked as blocking) sockets for new events.
69 *
70 * Additionally, TCP accept sockets get special event support.
71 *
72 * Socket numbers are not starting small, they can be any number (say 33060).
73 * Therefore, bitmaps are not used, but arrays.
74 *
75 * on winsock, you must use recv() and send() for TCP reads and writes,
76 * not read() and write(), those work only on files.
77 *
78 * Also fseek and fseeko do not work if a FILE is not fopen-ed in binary mode.
79 *
80 * When under a high load windows gives out lots of errors, from recvfrom
81 * on udp sockets for example (WSAECONNRESET). Even though the udp socket
82 * has no connection per se.
83 */
84
85 #ifndef UTIL_WINSOCK_EVENT_H
86 #define UTIL_WINSOCK_EVENT_H
87
88 // Only enabled for Windows
89 #ifdef USE_WINSOCK
90
91 #ifndef HAVE_EVENT_BASE_FREE
92 #define HAVE_EVENT_BASE_FREE
93 #endif
94
95 /* redefine the calls to different names so that there is no name
96 * collision with other code that uses libevent names. (that uses libunbound)*/
97 #define _getdns_event_init winsockevent_init
98 #define event_get_version winsockevent_get_version
99 #define event_get_method winsockevent_get_method
100 #define _getdns_event_base_dispatch winsockevent_base_dispatch
101 #define event_base_loopexit winsockevent_base_loopexit
102 #define _getdns_event_base_free winsockevent_base_free
103 #define _getdns_event_set winsockevent_set
104 #define _getdns_event_base_set winsockevent_base_set
105 #define _getdns_event_add winsockevent_add
106 #define _getdns_event_del winsockevent_del
107 #define signal_add winsocksignal_add
108 #define signal_del winsocksignal_del
109
110 /** event timeout */
111 #define EV_TIMEOUT 0x01
112 /** event fd readable */
113 #define EV_READ 0x02
114 /** event fd writable */
115 #define EV_WRITE 0x04
116 /** event signal */
117 #define EV_SIGNAL 0x08
118 /** event must persist */
119 #define EV_PERSIST 0x10
120
121 /* needs our redblack tree */
122 #include "util/rbtree.h"
123
124 /** max number of signals to support */
125 #define MAX_SIG 32
126
127 /** The number of items that the winsock event handler can service.
128 * Windows cannot handle more anyway */
129 #define WSK_MAX_ITEMS 64
130
131 /**
132 * event base for winsock event handler
133 */
134 struct _getdns_event_base
135 {
136 /** sorted by timeout (absolute), ptr */
137 _getdns_rbtree_t* times;
138 /** array (first part in use) of handles to work on */
139 struct _getdns_event** items;
140 /** number of items in use in array */
141 int max;
142 /** capacity of array, size of array in items */
143 int cap;
144 /** array of 0 - maxsig of ptr to event for it */
145 struct _getdns_event** signals;
146 /** if we need to exit */
147 int need_to_exit;
148 /** where to store time in seconds */
149 time_t* time_secs;
150 /** where to store time in microseconds */
151 struct timeval* time_tv;
152 /**
153 * TCP streams have sticky events to them, these are not
154 * reported by the windows event system anymore, we have to
155 * keep reporting those events as present until wouldblock() is
156 * signalled by the handler back to use.
157 */
158 int tcp_stickies;
159 /**
160 * should next cycle process reinvigorated stickies,
161 * these are stickies that have been stored, but due to a new
162 * event_add a sudden interest in the event has incepted.
163 */
164 int tcp_reinvigorated;
165 /** The list of events that is currently being processed. */
166 WSAEVENT waitfor[WSK_MAX_ITEMS];
167
168 /* fdset for read write, for fds ready, and added */
169 fd_set
170 /** fds for reading */
171 reads,
172 /** fds for writing */
173 writes,
174 /** fds determined ready for use */
175 ready,
176 /** ready plus newly added events. */
177 content;
178 };
179
180 /**
181 * Event structure. Has some of the event elements.
182 */
183 struct _getdns_event {
184 /** node in timeout rbtree */
185 _getdns_rbnode_t node;
186 /** is event already added */
187 int added;
188
189 /** event base it belongs to */
190 struct _getdns_event_base *ev_base;
191 /** fd to poll or -1 for timeouts. signal number for sigs. */
192 int ev_fd;
193 /** what events this event is interested in, see EV_.. above. */
194 short ev_events;
195 /** timeout value */
196 struct timeval ev_timeout;
197
198 /** callback to call: fd, eventbits, userarg */
199 void (*ev_callback)(int, short, void *);
200 /** callback user arg */
201 void *ev_arg;
202
203 /* ----- nonpublic part, for winsock_event only ----- */
204 /** index of this event in the items array (if added) */
205 int idx;
206 /** the event handle to wait for new events to become ready */
207 WSAEVENT hEvent;
208 /** true if this filedes is a TCP socket and needs special attention */
209 int is_tcp;
210 /** remembered EV_ values */
211 short old_events;
212 /** should remembered EV_ values be used for TCP streams.
213 * Reset after WOULDBLOCK is signaled using the function. */
214 int stick_events;
215
216 /** true if this event is a signaling WSAEvent by the user.
217 * User created and user closed WSAEvent. Only signaled/unsigneled,
218 * no read/write/distinctions needed. */
219 int is_signal;
220 /** used during callbacks to see which events were just checked */
221 int just_checked;
222 };
223
224 char* wsa_strerror(DWORD err);
225 void log_err(const char *format, ...);
226 /** create event base */
227 void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv);
228 /** get version */
229 const char *event_get_version(void);
230 /** get polling method (select,epoll) */
231 const char *event_get_method(void);
232 /** run select in a loop */
233 int _getdns_event_base_dispatch(struct _getdns_event_base *);
234 /** exit that loop */
235 int event_base_loopexit(struct _getdns_event_base *, struct timeval *);
236 /** free event base. Free events yourself */
237 void _getdns_event_base_free(struct _getdns_event_base *);
238 /** set content of event */
239 void _getdns_event_set(struct _getdns_event *, int, short, void (*)(int, short, void *), void *);
240
241 /** add event to a base. You *must* call this for every event. */
242 int _getdns_event_base_set(struct _getdns_event_base *, struct _getdns_event *);
243 /** add event to make it active. You may not change it with event_set anymore */
244 int _getdns_event_add(struct _getdns_event *, struct timeval *);
245 /** remove event. You may change it again */
246 int _getdns_event_del(struct _getdns_event *);
247
248 #define evtimer_add(ev, tv) event_add(ev, tv)
249 #define evtimer_del(ev) event_del(ev)
250
251 /* uses different implementation. Cannot mix fd/timeouts and signals inside
252 * the same struct event. create several event structs for that. */
253 /** install signal handler */
254 int signal_add(struct _getdns_event *, struct timeval *);
255 /** set signal event contents */
256 #define signal_set(ev, x, cb, arg) \
257 event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
258 /** remove signal handler */
259 int signal_del(struct _getdns_event *);
260
261 /** compare events in tree, based on timevalue, ptr for uniqueness */
262 int getdns_mini_ev_cmp(const void* a, const void* b);
263
264 /**
265 * Routine for windows only, where the handling layer can signal that
266 * a TCP stream encountered WSAEWOULDBLOCK for a stream and thus needs
267 * retesting the event.
268 * Pass if EV_READ or EV_WRITE gave wouldblock.
269 */
270 void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbit);
271
272 /**
273 * Routine for windows only. where you pass a signal WSAEvent that
274 * you wait for. When the event is signaled, the callback gets called.
275 * The callback has to WSAResetEvent to disable the signal.
276 * @param base: the event base.
277 * @param ev: the event structure for data storage
278 * can be passed uninitialised.
279 * @param wsaevent: the WSAEvent that gets signaled.
280 * @param cb: callback routine.
281 * @param arg: user argument to callback routine.
282 * @return false on error.
283 */
284 int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev,
285 WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg);
286
287 /**
288 * Unregister a wsaevent. User has to close the WSAEVENT itself.
289 * @param ev: event data storage.
290 */
291 void winsock_unregister_wsaevent(struct _getdns_event* ev);
292
293 #endif /* USE_WINSOCK */
294 #endif /* UTIL_WINSOCK_EVENT_H */
7171 #endif
7272 {"return_api_information", t_int},
7373 {"return_both_v4_and_v6", t_int},
74 {"return_call_debugging", t_int},
74 {"return_call_reporting", t_int},
7575 {"specify_class", t_int},
7676 };
7777
171171 _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
172172 {
173173 getdns_dict *rr_dict, *rdata_dict;
174 getdns_bindata bindata;
174 const uint8_t *bin_data;
175 size_t bin_size;
175176 uint32_t int_val = 0;
176 getdns_data_type val_type;
177 enum wf_data_type { wf_int, wf_bindata, wf_special } val_type;
177178 _getdns_rdf_iter rdf_storage, *rdf;
178179 getdns_list *repeat_list = NULL;
179180 getdns_dict *repeat_dict = NULL;
184185 if (!(rr_dict = _getdns_dict_create_with_mf(mf)))
185186 return NULL;
186187
187 bindata.data = _getdns_owner_if_or_as_decompressed(
188 i, ff_bytes, &bindata.size);
188 bin_data = _getdns_owner_if_or_as_decompressed(
189 i, ff_bytes, &bin_size);
189190
190191 /* question */
191192 if (_getdns_rr_iter_section(i) == GLDNS_SECTION_QUESTION) {
196197 getdns_dict_set_int(rr_dict, "qclass",
197198 (uint32_t) gldns_read_uint16(i->rr_type + 2)) ||
198199
199 getdns_dict_set_bindata(rr_dict, "qname", &bindata)) {
200 _getdns_dict_set_const_bindata(
201 rr_dict, "qname", bin_size, bin_data)) {
200202
201203 goto error;
202204 }
233235 getdns_dict_set_int(rr_dict, "ttl",
234236 (uint32_t) gldns_read_uint32(i->rr_type + 4)) ||
235237
236 getdns_dict_set_bindata(rr_dict, "name", &bindata)) {
238 _getdns_dict_set_const_bindata(
239 rr_dict, "name", bin_size, bin_data)) {
237240
238241 goto error;
239242 }
241244 return NULL;
242245
243246 if (i->rr_type + 10 <= i->nxt) {
244 bindata.size = i->nxt - (i->rr_type + 10);
245 bindata.data = i->rr_type + 10;
246 if (getdns_dict_set_bindata(rdata_dict, "rdata_raw", &bindata))
247 bin_size = i->nxt - (i->rr_type + 10);
248 bin_data = i->rr_type + 10;
249 if (_getdns_dict_set_const_bindata(
250 rdata_dict, "rdata_raw", bin_size, bin_data))
247251 goto rdata_error;
248252 }
249253 for ( rdf = _getdns_rdf_iter_init(&rdf_storage, i)
250254 ; rdf; rdf = _getdns_rdf_iter_next(rdf)) {
251255 if (rdf->rdd_pos->type & GETDNS_RDF_INTEGER) {
252 val_type = t_int;
256 val_type = wf_int;
253257 switch (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) {
254258 case 1: int_val = *rdf->pos;
255259 break;
261265 goto rdata_error;
262266 }
263267 } else if (rdf->rdd_pos->type & GETDNS_RDF_DNAME) {
264 val_type = t_bindata;
265
266 bindata.data = _getdns_rdf_if_or_as_decompressed(
267 rdf, ff_bytes, &bindata.size);
268 val_type = wf_bindata;
269
270 bin_data = _getdns_rdf_if_or_as_decompressed(
271 rdf, ff_bytes, &bin_size);
268272
269273 } else if (rdf->rdd_pos->type & GETDNS_RDF_BINDATA) {
270 val_type = t_bindata;
274 val_type = wf_bindata;
271275 if (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) {
272 bindata.size = rdf->rdd_pos->type
273 & GETDNS_RDF_FIXEDSZ;
274 bindata.data = rdf->pos;
276 bin_size = rdf->rdd_pos->type
277 & GETDNS_RDF_FIXEDSZ;
278 bin_data = rdf->pos;
275279
276280 } else switch(rdf->rdd_pos->type & GETDNS_RDF_LEN_VAL){
277281 case 0x100:
278 bindata.size = *rdf->pos;
279 bindata.data = rdf->pos + 1;
282 bin_size = *rdf->pos;
283 bin_data = rdf->pos + 1;
280284 break;
281285 case 0x200:
282 bindata.size = gldns_read_uint16(rdf->pos);
283 bindata.data = rdf->pos + 2;
286 bin_size = gldns_read_uint16(rdf->pos);
287 bin_data = rdf->pos + 2;
284288 break;
285289 default:
286 bindata.size = rdf->nxt - rdf->pos;
287 bindata.data = rdf->pos;
290 bin_size = rdf->nxt - rdf->pos;
291 bin_data = rdf->pos;
288292 break;
289293 }
290294 } else if (rdf->rdd_pos->type == GETDNS_RDF_SPECIAL)
291 /* Abuse t_dict for special values */
292 val_type = t_dict;
295 val_type = wf_special;
293296 else
294297 assert(0);
295298
296299 if (! rdf->rdd_repeat) {
297300 switch (val_type) {
298 case t_int:
301 case wf_int:
299302 if (getdns_dict_set_int(rdata_dict,
300303 rdf->rdd_pos->name, int_val))
301304 goto rdata_error;
302305 break;
303 case t_bindata:
304 if (getdns_dict_set_bindata(rdata_dict,
305 rdf->rdd_pos->name, &bindata))
306 case wf_bindata:
307 if (_getdns_dict_set_const_bindata(rdata_dict,
308 rdf->rdd_pos->name, bin_size, bin_data))
306309 goto rdata_error;
307310 break;
308 case t_dict:
309 if (rdf->rdd_pos->special->dict_set_value(
311 case wf_special:
312 if (rdf->rdd_pos->special->wire2dict(
310313 rdata_dict, rdf->pos))
311314 goto rdata_error;
312315 default:
323326 goto rdata_error;
324327
325328 switch (val_type) {
326 case t_int:
329 case wf_int:
327330 if (_getdns_list_append_int(repeat_list,
328331 int_val))
329332 goto rdata_error;
330333 break;
331 case t_bindata:
332 if (_getdns_list_append_bindata(repeat_list,
333 &bindata))
334 case wf_bindata:
335 if (_getdns_list_append_const_bindata(
336 repeat_list, bin_size, bin_data))
334337 goto rdata_error;
335338 break;
336 case t_dict:
337 if (rdf->rdd_pos->special->list_append_value(
339 case wf_special:
340 if (rdf->rdd_pos->special->wire2list(
338341 repeat_list, rdf->pos))
339342 goto rdata_error;
340343 default:
362365 }
363366 assert(repeat_dict);
364367 switch (val_type) {
365 case t_int:
368 case wf_int:
366369 if (getdns_dict_set_int(repeat_dict,
367370 rdf->rdd_pos->name, int_val))
368371 goto rdata_error;
369372 break;
370 case t_bindata:
371 if (getdns_dict_set_bindata(repeat_dict,
372 rdf->rdd_pos->name, &bindata))
373 case wf_bindata:
374 if (_getdns_dict_set_const_bindata(repeat_dict,
375 rdf->rdd_pos->name, bin_size, bin_data))
373376 goto rdata_error;
374377 break;
375 case t_dict:
376 if (rdf->rdd_pos->special->dict_set_value(
378 case wf_special:
379 if (rdf->rdd_pos->special->wire2dict(
377380 repeat_dict, rdf->pos))
378381 goto rdata_error;
379382 default:
433436 if (*var)
434437 getdns_dict_destroy(*var);
435438 return *var = value;
439 }
440
441 inline static int has_all_numeric_label(const uint8_t *dname)
442 {
443 size_t i;
444
445 while (*dname && !(*dname & 0xc0)) {
446 for (i = 1; i <= *dname; i++) {
447 if (!isdigit(dname[i]))
448 break;
449 }
450 if (i > *dname)
451 return 1;
452 dname += *dname + 1;
453 }
454 return 0;
436455 }
437456
438457 #define SET_WIRE_INT(X,Y) if (getdns_dict_set_int(header, #X , (int) \
496515 getdns_dict *rr_dict = NULL;
497516 _getdns_rr_iter rr_iter_storage, *rr_iter;
498517 _getdns_rdf_iter rdf_iter_storage, *rdf_iter;
499 getdns_bindata bindata;
518 size_t bin_size;
519 const uint8_t *bin_data;
500520 gldns_pkt_section section;
501 uint8_t canonical_name_space[256],
502 *canonical_name = canonical_name_space;
503 uint8_t owner_name_space[256], *owner_name;
521 uint8_t canonical_name_space[256], owner_name_space[256];
522 const uint8_t *canonical_name = canonical_name_space, *owner_name;
504523 size_t canonical_name_len = sizeof(canonical_name_space),
505524 owner_name_len = sizeof(owner_name_space);
506 int new_canonical = 0;
525 int new_canonical = 0, cnames_followed,
526 request_answered, all_numeric_label;
507527 uint16_t rr_type;
508528 getdns_dict *header = NULL;
529 getdns_list *bad_dns = NULL;
509530
510531 if (!result)
511532 goto error;
591612 &rdf_iter_storage, rr_iter)))
592613 continue;
593614
594 bindata.size = rdf_iter->nxt - rdf_iter->pos;
595 bindata.data = rdf_iter->pos;
615 bin_size = rdf_iter->nxt - rdf_iter->pos;
616 bin_data = rdf_iter->pos;
596617 if (!set_dict(&rr_dict, getdns_dict_create_with_context(context)) ||
597618
598619 getdns_dict_util_set_string(rr_dict, "address_type",
599620 rr_type == GETDNS_RRTYPE_A ? "IPv4" : "IPv6" ) ||
600621
601 getdns_dict_set_bindata(rr_dict,"address_data",&bindata) ||
622 _getdns_dict_set_const_bindata(
623 rr_dict, "address_data", bin_size, bin_data) ||
602624
603625 (just_addrs && _getdns_list_append_dict(just_addrs, rr_dict))) {
604626
623645 if (getdns_dict_set_int(result, "answer_type", GETDNS_NAMETYPE_DNS))
624646 goto error;
625647
648 cnames_followed = new_canonical;
626649 while (new_canonical) {
627650 new_canonical = 0;
628651
629652 for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage
630 , req->response
631 , req->response_len)
653 , req->response
654 , req->response_len)
632655 ; rr_iter && _getdns_rr_iter_section(rr_iter)
633656 <= GLDNS_SECTION_ANSWER
634657 ; rr_iter = _getdns_rr_iter_next(rr_iter)) {
655678 new_canonical = 1;
656679 }
657680 }
658 bindata.data = canonical_name;
659 bindata.size = canonical_name_len;
660 if (getdns_dict_set_bindata(result, "canonical_name", &bindata))
681 if (_getdns_dict_set_const_bindata(
682 result, "canonical_name", canonical_name_len, canonical_name))
683 goto error;
684
685 if (!req->owner->add_warning_for_bad_dns)
686 goto success;
687
688 if (!(bad_dns = getdns_list_create_with_context(context)))
689 goto error;
690
691 if (cnames_followed && req->request_type != GETDNS_RRTYPE_CNAME) {
692 request_answered = 0;
693 for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage
694 , req->response
695 , req->response_len)
696 ; rr_iter && _getdns_rr_iter_section(rr_iter)
697 <= GLDNS_SECTION_ANSWER
698 ; rr_iter = _getdns_rr_iter_next(rr_iter)) {
699
700 if (_getdns_rr_iter_section(rr_iter) !=
701 GLDNS_SECTION_ANSWER)
702 continue;
703 if (gldns_read_uint16(rr_iter->rr_type) !=
704 req->request_type)
705 continue;
706
707 owner_name=_getdns_owner_if_or_as_decompressed(
708 rr_iter, owner_name_space,&owner_name_len);
709 if (_getdns_dname_equal(
710 canonical_name, owner_name)) {
711 request_answered = 1;
712 break;
713 }
714 }
715 if (!request_answered &&
716 _getdns_list_append_int(bad_dns,
717 GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE))
718 goto error;
719 }
720 all_numeric_label = 0;
721 for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage
722 , req->response
723 , req->response_len)
724 ; rr_iter && !all_numeric_label
725 ; rr_iter = _getdns_rr_iter_next(rr_iter)) {
726
727 owner_name = _getdns_owner_if_or_as_decompressed(
728 rr_iter, owner_name_space, &owner_name_len);
729
730 if (has_all_numeric_label(owner_name)) {
731 all_numeric_label = 1;
732 break;
733 }
734 if (_getdns_rr_iter_section(rr_iter) ==
735 GLDNS_SECTION_QUESTION)
736 continue;
737
738 for ( rdf_iter = _getdns_rdf_iter_init(&rdf_iter_storage, rr_iter)
739 ; rdf_iter; rdf_iter = _getdns_rdf_iter_next(rdf_iter)) {
740
741 if (!(rdf_iter->rdd_pos->type & GETDNS_RDF_DNAME))
742 continue;
743
744 owner_name = _getdns_rdf_if_or_as_decompressed(
745 rdf_iter, owner_name_space, &owner_name_len);
746
747 if (has_all_numeric_label(owner_name)) {
748 all_numeric_label = 1;
749 break;
750 }
751 }
752 }
753 if (all_numeric_label &&
754 _getdns_list_append_int(bad_dns, GETDNS_BAD_DNS_ALL_NUMERIC_LABEL))
755 goto error;
756
757 if (getdns_dict_set_list(result, "bad_dns", bad_dns))
661758 goto error;
662759
663760 goto success;
671768 getdns_list_destroy(sections[GLDNS_SECTION_AUTHORITY]);
672769 getdns_list_destroy(sections[GLDNS_SECTION_ANSWER]);
673770 getdns_dict_destroy(question);
771 getdns_list_destroy(bad_dns);
674772 return result;
675773 }
676774
677775 getdns_dict *
678 _getdns_create_call_debugging_dict(
776 _getdns_create_call_reporting_dict(
679777 getdns_context *context, getdns_network_req *netreq)
680778 {
681779 getdns_bindata qname;
728826 return NULL;
729827 }
730828 getdns_dict_destroy(address_debug);
829
830 if (transport != GETDNS_TRANSPORT_UDP) {
831 /* Report the idle timeout actually used on the connection. Must trim,
832 maximum used in practice is 6553500ms, but this is stored in a uint64_t.*/
833 if (netreq->upstream->keepalive_timeout > UINT32_MAX) {
834 if (getdns_dict_set_int( netreq_debug, "idle timeout in ms (overflow)", UINT32_MAX)) {
835 getdns_dict_destroy(netreq_debug);
836 return NULL;
837 }
838 } else{
839 uint32_t idle_timeout = netreq->upstream->keepalive_timeout;
840 if (getdns_dict_set_int( netreq_debug, "idle timeout in ms", idle_timeout)) {
841 getdns_dict_destroy(netreq_debug);
842 return NULL;
843 }
844 }
845 }
731846
732847 if (netreq->upstream->transport != GETDNS_TRANSPORT_TLS)
733848 return netreq_debug;
750865 getdns_list *just_addrs = NULL;
751866 getdns_list *replies_full;
752867 getdns_list *replies_tree;
753 getdns_list *call_debugging = NULL;
868 getdns_list *call_reporting = NULL;
754869 getdns_network_req *netreq, **netreq_p;
755870 int rrsigs_in_answer = 0;
756871 getdns_dict *reply;
791906 if (!(replies_tree = getdns_list_create_with_context(context)))
792907 goto error_free_replies_full;
793908
794 if (completed_request->return_call_debugging &&
795 !(call_debugging = getdns_list_create_with_context(context)))
909 if (completed_request->return_call_reporting &&
910 !(call_reporting = getdns_list_create_with_context(context)))
796911 goto error_free_replies_full;
797912
798913 for ( netreq_p = completed_request->netreqs
800915
801916 if (! netreq->response_len)
802917 continue;
918
919 if (netreq->tsig_status == GETDNS_DNSSEC_INSECURE)
920 _getdns_network_validate_tsig(netreq);
803921
804922 nreplies++;
805923 if (netreq->dnssec_status == GETDNS_DNSSEC_SECURE)
819937 else if (completed_request->dnssec_return_only_secure
820938 && netreq->dnssec_status != GETDNS_DNSSEC_SECURE)
821939 continue;
940 else if (netreq->tsig_status == GETDNS_DNSSEC_BOGUS)
941 continue;
822942 }
823943 if (!(reply = _getdns_create_reply_dict(context,
824944 netreq, just_addrs, &rrsigs_in_answer)))
846966 netreq->dnssec_status))
847967 goto error;
848968 }
849
969 if (netreq->tsig_status != GETDNS_DNSSEC_INDETERMINATE) {
970 if (getdns_dict_set_int(reply, "tsig_status",
971 netreq->tsig_status))
972 goto error;
973 }
850974 if (_getdns_list_append_dict(replies_tree, reply)) {
851975 getdns_dict_destroy(reply);
852976 goto error;
853977 }
854978
855 if (call_debugging) {
979 if (call_reporting) {
856980 if (!(netreq_debug =
857 _getdns_create_call_debugging_dict(context,netreq)))
981 _getdns_create_call_reporting_dict(context,netreq)))
858982 goto error;
859983
860984 if (_getdns_list_append_dict(
861 call_debugging, netreq_debug)) {
985 call_reporting, netreq_debug)) {
862986
863987 getdns_dict_destroy(netreq_debug);
864988 goto error;
8781002 goto error;
8791003 getdns_list_destroy(replies_tree);
8801004
881 if (call_debugging &&
882 getdns_dict_set_list(result, "call_debugging", call_debugging))
883 goto error_free_call_debugging;
1005 if (call_reporting &&
1006 getdns_dict_set_list(result, "call_reporting", call_reporting))
1007 goto error_free_call_reporting;
8841008
8851009 if (getdns_dict_set_list(result, "replies_full", replies_full))
8861010 goto error_free_replies_full;
9051029 error:
9061030 /* cleanup */
9071031 getdns_list_destroy(replies_tree);
908 error_free_call_debugging:
909 getdns_list_destroy(call_debugging);
1032 error_free_call_reporting:
1033 getdns_list_destroy(call_reporting);
9101034 error_free_replies_full:
9111035 getdns_list_destroy(replies_full);
9121036 error_free_result:
10051129 , netreq->request_type);
10061130 gldns_write_uint16( netreq->response + GLDNS_HEADER_SIZE
10071131 + netreq->owner->name_len + 2
1008 , netreq->request_class);
1132 , netreq->owner->request_class);
10091133
10101134 netreq->response_len = GLDNS_HEADER_SIZE + netreq->owner->name_len + 4;
10111135
4141 #include "context.h"
4242 #include "rr-iter.h"
4343
44 #define UNCONST_UINT8_p uint8_t *
4445
4546 #ifdef S_SPLINT_S
4647 # define INLINE
7980
8081 getdns_return_t _getdns_list_append_int(getdns_list *list,
8182 uint32_t child_uint32);
83
84 getdns_return_t _getdns_list_append_const_bindata(getdns_list *list,
85 size_t size, const void *data);
86
87 getdns_return_t _getdns_dict_set_const_bindata(getdns_dict *dict,
88 const char *name, size_t size, const void *data);
8289
8390 /**
8491 * private function (API users should not be calling this), this uses library
152159 */
153160 getdns_return_t _getdns_validate_extensions(struct getdns_dict * extensions);
154161
155 #define DEBUG_ON(...) do { \
156 struct timeval tv; \
157 struct tm tm; \
158 char buf[10]; \
159 \
160 gettimeofday(&tv, NULL); \
161 gmtime_r(&tv.tv_sec, &tm); \
162 strftime(buf, 10, "%T", &tm); \
163 fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
164 fprintf(stderr, __VA_ARGS__); \
165 } while (0)
166
167 #define DEBUG_NL(...) do { \
168 struct timeval tv; \
169 struct tm tm; \
170 char buf[10]; \
171 \
172 gettimeofday(&tv, NULL); \
173 gmtime_r(&tv.tv_sec, &tm); \
174 strftime(buf, 10, "%T", &tm); \
175 fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
176 fprintf(stderr, __VA_ARGS__); \
177 fprintf(stderr, "\n"); \
178 } while (0)
179
180
181 #define DEBUG_OFF(...) do {} while (0)
182
183 #if defined(SCHED_DEBUG) && SCHED_DEBUG
184 #include <time.h>
185 #define DEBUG_SCHED(...) DEBUG_ON(__VA_ARGS__)
186 #else
187 #define DEBUG_SCHED(...) DEBUG_OFF(__VA_ARGS__)
188 #endif
189
190 #if defined(STUB_DEBUG) && STUB_DEBUG
191 #include <time.h>
192 #define DEBUG_STUB(...) DEBUG_ON(__VA_ARGS__)
193 #else
194 #define DEBUG_STUB(...) DEBUG_OFF(__VA_ARGS__)
195 #endif
196
197 #if defined(SEC_DEBUG) && SEC_DEBUG
198 #include <time.h>
199 #define DEBUG_SEC(...) DEBUG_ON(__VA_ARGS__)
200 #else
201 #define DEBUG_SEC(...) DEBUG_OFF(__VA_ARGS__)
202 #endif
203
204162 INLINE getdns_eventloop_event *getdns_eventloop_event_init(
205163 getdns_eventloop_event *ev,void *userarg, getdns_eventloop_callback read_cb,
206164 getdns_eventloop_callback write_cb, getdns_eventloop_callback timeout_cb)
3434
3535 const char *getdns_get_version(void)
3636 {
37 return "0.5.1";
37 return "0.9.0";
3838 }
3939
4040 uint32_t getdns_get_version_number(void)
4141 {
42 return 0x00050100;
42 return 0x00090000;
4343 }
4444
4545 const char *getdns_get_api_version(void)
4646 {
47 return "October 2015";
47 return "December 2015";
4848 }
4949
5050 uint32_t getdns_get_api_version_number(void)
5151 {
52 return 0x07df0a00;
52 return 0x07df0c00;
5353 }
5454
5555 /* version.c */