aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile.in182
-rw-r--r--examples/README5
-rw-r--r--examples/config.h.in363
-rwxr-xr-xexamples/configure7158
-rw-r--r--examples/configure.ac421
-rw-r--r--examples/fake-rfc2553.h175
-rw-r--r--examples/ldns-chaos.126
-rw-r--r--examples/ldns-chaos.c125
-rw-r--r--examples/ldns-compare-zones.157
-rw-r--r--examples/ldns-compare-zones.c283
-rw-r--r--examples/ldns-dpa.1151
-rw-r--r--examples/ldns-dpa.c2838
-rw-r--r--examples/ldns-dpa.h92
-rw-r--r--examples/ldns-gen-zone.198
-rw-r--r--examples/ldns-gen-zone.c310
-rw-r--r--examples/ldns-key2ds.141
-rw-r--r--examples/ldns-key2ds.c199
-rw-r--r--examples/ldns-keyfetcher.164
-rw-r--r--examples/ldns-keyfetcher.c722
-rw-r--r--examples/ldns-keygen.153
-rw-r--r--examples/ldns-keygen.c307
-rw-r--r--examples/ldns-mx.123
-rw-r--r--examples/ldns-mx.c88
-rw-r--r--examples/ldns-notify.166
-rw-r--r--examples/ldns-notify.c334
-rw-r--r--examples/ldns-nsec3-hash.134
-rw-r--r--examples/ldns-nsec3-hash.c127
-rw-r--r--examples/ldns-read-zone.169
-rw-r--r--examples/ldns-read-zone.c212
-rw-r--r--examples/ldns-resolver.126
-rw-r--r--examples/ldns-resolver.c47
-rw-r--r--examples/ldns-revoke.127
-rw-r--r--examples/ldns-revoke.c104
-rw-r--r--examples/ldns-rrsig.130
-rw-r--r--examples/ldns-rrsig.c219
-rw-r--r--examples/ldns-signzone.1164
-rw-r--r--examples/ldns-signzone.c839
-rw-r--r--examples/ldns-test-edns.141
-rw-r--r--examples/ldns-test-edns.c248
-rw-r--r--examples/ldns-testns.1131
-rw-r--r--examples/ldns-testns.c577
-rw-r--r--examples/ldns-testpkts.c881
-rw-r--r--examples/ldns-testpkts.h255
-rw-r--r--examples/ldns-update.144
-rw-r--r--examples/ldns-update.c310
-rw-r--r--examples/ldns-verify-zone.189
-rw-r--r--examples/ldns-verify-zone.c946
-rw-r--r--examples/ldns-version.122
-rw-r--r--examples/ldns-version.c16
-rw-r--r--examples/ldns-walk.149
-rw-r--r--examples/ldns-walk.c671
-rw-r--r--examples/ldns-zcat.130
-rw-r--r--examples/ldns-zcat.c171
-rw-r--r--examples/ldns-zsplit.139
-rw-r--r--examples/ldns-zsplit.c272
-rw-r--r--examples/ldnsd.126
-rw-r--r--examples/ldnsd.c243
57 files changed, 21140 insertions, 0 deletions
diff --git a/examples/Makefile.in b/examples/Makefile.in
new file mode 100644
index 000000000000..5344ee6739c0
--- /dev/null
+++ b/examples/Makefile.in
@@ -0,0 +1,182 @@
+# Standard installation pathnames
+# See the file LICENSE for the license
+SHELL = @SHELL@
+VERSION = @PACKAGE_VERSION@
+basesrcdir = $(shell basename `pwd`)
+srcdir = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+mandir = @mandir@
+libtool = @libtool@
+
+CC = @CC@
+CFLAGS = -I. -I${srcdir} @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBNSL_LIBS = @LIBNSL_LIBS@
+LIBSSL_CPPFLAGS = @LIBSSL_CPPFLAGS@
+LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
+LIBSSL_LIBS = @LIBSSL_LIBS@
+LIBS = @LIBS@
+RUNTIME_PATH = @RUNTIME_PATH@
+LDNSDIR = @LDNSDIR@
+
+INSTALL = $(srcdir)/../install-sh
+
+COMPILE = $(CC) $(CPPFLAGS) $(LIBSSL_CPPFLAGS) $(CFLAGS)
+LINK = $(libtool) --tag=CC --quiet --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(RUNTIME_PATH)
+LINK_STATIC = $(libtool) --tag=CC --quiet --mode=link $(CC) $(CFLAGS) -static $(LDFLAGS) $(LIBS) $(RUNTIME_PATH)
+
+LINT = splint
+LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64 -D__gnuc_va_list=va_list
+#-Dglob64=glob -Dglobfree64=globfree
+# compat with openssl linux edition.
+LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray -D"ENGINE=unsigned" -D"RSA=unsigned" -D"DSA=unsigned" -D"EVP_PKEY=unsigned" -D"EVP_MD=unsigned" -D"SSL=unsigned" -D"SSL_CTX=unsigned" -D"X509=unsigned" -D"RC4_KEY=unsigned" -D"EVP_MD_CTX=unsigned"
+# compat with NetBSD
+ifeq "$(shell uname)" "NetBSD"
+LINTFLAGS+="-D__RENAME(x)=" -D_NETINET_IN_H_
+endif
+# compat with OpenBSD
+LINTFLAGS+="-Dsigset_t=long"
+# FreeBSD8
+LINTFLAGS+="-D__uint16_t=uint16_t"
+LINTFLAGS+=-D__signed__=signed "-D__packed=" "-D__aligned(x)="
+# Ubuntu 11.04
+LINTFLAGS+="-D__u16=struct __u16" "-D__u32=struct __u32" "-D__u64=struct __u64"
+
+HEADER = config.h
+MAIN_SOURCES = ldns-read-zone.c \
+ ldns-mx.c \
+ ldns-chaos.c \
+ ldns-update.c \
+ ldns-keygen.c \
+ ldns-key2ds.c \
+ ldns-version.c \
+ ldns-rrsig.c \
+ ldns-walk.c \
+ ldns-zsplit.c \
+ ldns-zcat.c \
+ ldns-dpa.c \
+ ldns-resolver.c \
+ ldns-test-edns.c \
+ ldns-keyfetcher.c \
+ ldns-notify.c \
+ ldns-testns.c \
+ ldns-compare-zones.c \
+ ldns-gen-zone.c \
+ ldnsd.c
+
+MAIN_SSL_SOURCES = ldns-signzone.c \
+ ldns-verify-zone.c \
+ ldns-revoke.c \
+ ldns-nsec3-hash.c
+
+OTHER_SOURCES = ldns-testpkts.c
+
+PROGRAMS=$(MAIN_SOURCES:.c=)
+SSL_PROGRAMS=$(MAIN_SSL_SOURCES:.c=)
+
+.PHONY: all clean realclean all-static
+.SECONDARY: $(MAIN_SOURCES:.c=.o) $(OTHER_SOURCES:.c=.o) $(MAIN_SSL_SOURCES:.c=.o)
+
+all: $(addsuffix .prg,$(PROGRAMS)) $(addsuffix .prg-ssl,$(SSL_PROGRAMS))
+
+all-static: $(addsuffix .stc,$(PROGRAMS)) $(addsuffix .stc-ssl,$(SSL_PROGRAMS))
+
+%.o: $(srcdir)/%.c
+ $(COMPILE) -o $@ -c $<
+
+# ldns-testns uses more sources.
+ldns-testns.o: $(srcdir)/ldns-testns.c $(srcdir)/ldns-testpkts.c $(srcdir)/ldns-testpkts.h
+ldns-testns.prg: ldns-testpkts.o
+ldns-testns.stc: ldns-testpkts.o
+
+ldnsd.prg: ldnsd.o
+ @if test ! -f $(@:.prg=) -o $< -nt $(@:.prg=); then \
+ echo $(LINK) $(LIBNSL_LIBS) -o $(@:.prg=) $^ ; \
+ $(LINK) $(LIBNSL_LIBS) -o $(@:.prg=) $^ ; \
+ fi
+
+ldnsd.stc: ldnsd.o
+ @if test ! -f $@ -o $< -nt $@; then \
+ echo $(LINK_STATIC) $(LIBNSL_LDFLAGS) -o $@ $^ ; \
+ $(LINK_STATIC) $(LIBNSL_LDFLAGS) -o $@ $^ ; \
+ fi
+
+%.prg-ssl: %.o
+ @if test ! -f $(@:.prg-ssl=) -o $< -nt $(@:.prg-ssl=); then \
+ echo $(LINK) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -o $(@:.prg-ssl=) $^ ; \
+ $(LINK) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -o $(@:.prg-ssl=) $^ ; \
+ fi
+
+%.stc-ssl: %.o
+ @if test ! -f $@ -o $< -nt $@; then \
+ echo $(LINK_STATIC) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -o $@ $^ ; \
+ $(LINK_STATIC) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -o $@ $^ ; \
+ fi
+
+%.prg: %.o
+ @if test ! -f $(@:.prg=) -o $< -nt $(@:.prg=); then \
+ echo $(LINK) -o $(@:.prg=) $^ ; \
+ $(LINK) -o $(@:.prg=) $^ ; \
+ fi
+
+%.stc: %.o
+ @if test ! -f $@ -o $< -nt $@; then \
+ echo $(LINK_STATIC) -o $@ $^ ; \
+ $(LINK_STATIC) -o $@ $^ ; \
+ fi
+
+lint:
+ for i in $(MAIN_SOURCES) $(OTHER_SOURCES); do \
+ $(LINT) $(LINTFLAGS) -I. -I$(srcdir) $(srcdir)/$$i $(CPPFLAGS); \
+ if [ $$? -ne 0 ] ; then exit 1 ; fi ; \
+ done
+
+clean:
+ rm -f *.o *.lo
+ rm -rf .libs
+ rm -f $(PROGRAMS) $(SSL_PROGRAMS)
+ rm -f $(addsuffix .stc,$(PROGRAMS)) $(addsuffix .stc-ssl,$(SSL_PROGRAMS))
+
+realclean: clean
+ rm -rf autom4te.cache/
+ rm -f config.log config.status aclocal.m4 config.h.in configure Makefile
+ rm -f config.h
+
+confclean: clean
+ rm -rf config.log config.status config.h Makefile
+
+install: $(PROGRAMS) $(SSL_PROGRAMS)
+ $(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
+ $(INSTALL) -d -m 755 $(DESTDIR)$(mandir)
+ $(INSTALL) -d -m 755 $(DESTDIR)$(mandir)/man1
+ for i in $(PROGRAMS) $(SSL_PROGRAMS); do \
+ $(libtool) --tag=CC --mode=install ${INSTALL} -c $$i $(DESTDIR)$(bindir) ; \
+ $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \
+ done
+ exit 0
+
+install-static: all-static
+ $(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
+ $(INSTALL) -d -m 755 $(DESTDIR)$(mandir)
+ $(INSTALL) -d -m 755 $(DESTDIR)$(mandir)/man1
+ for i in $(PROGRAMS); do \
+ $(libtool) --tag=CC --mode=install ${INSTALL} -c $$i.stc $(DESTDIR)$(bindir) ; \
+ $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \
+ done
+ for i in $(SSL_PROGRAMS); do \
+ $(libtool) --tag=CC --mode=install ${INSTALL} -c $$i.stc-ssl $(DESTDIR)$(bindir) ; \
+ $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \
+ done
+ exit 0
+
+uninstall:
+ for i in $(PROGRAMS) $(SSL_PROGRAMS); do \
+ rm -f $(DESTDIR)$(bindir)/$$i ; \
+ rm -f $(DESTDIR)$(mandir)/man1/$$i.1 ; \
+ done
+ exit 0
+ rmdir -p $(DESTDIR)$(bindir)
+ rmdir -p $(DESTDIR)$(mandir)
diff --git a/examples/README b/examples/README
new file mode 100644
index 000000000000..f84fe9d8cf73
--- /dev/null
+++ b/examples/README
@@ -0,0 +1,5 @@
+These tools are examples of ldns usage. They are not meant for production
+systems and will not be supported as such.
+
+Compilation:
+autoreconf && ./configure && make
diff --git a/examples/config.h.in b/examples/config.h.in
new file mode 100644
index 000000000000..dad78b17a225
--- /dev/null
+++ b/examples/config.h.in
@@ -0,0 +1,363 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the <assert.h> header file. */
+#undef HAVE_ASSERT_H
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define to 1 if you have the declaration of `in6addr_any', and to 0 if you
+ don't. */
+#undef HAVE_DECL_IN6ADDR_ANY
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Whether getaddrinfo is available */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* If you have HMAC_CTX_init */
+#undef HAVE_HMAC_CTX_INIT
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `isblank' function. */
+#undef HAVE_ISBLANK
+
+/* Define to 1 if you have the `ldns' library (-lldns). */
+#undef HAVE_LIBLDNS
+
+/* Define to 1 if you have the `pcap' library (-lpcap). */
+#undef HAVE_LIBPCAP
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/if_ether.h> header file. */
+#undef HAVE_NETINET_IF_ETHER_H
+
+/* Define to 1 if you have the <netinet/igmp.h> header file. */
+#undef HAVE_NETINET_IGMP_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+#undef HAVE_NETINET_IN_SYSTM_H
+
+/* Define to 1 if you have the <netinet/ip6.h> header file. */
+#undef HAVE_NETINET_IP6_H
+
+/* Define to 1 if you have the <netinet/ip.h> header file. */
+#undef HAVE_NETINET_IP_H
+
+/* Define to 1 if you have the <netinet/udp.h> header file. */
+#undef HAVE_NETINET_UDP_H
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+#undef HAVE_OPENSSL_ERR_H
+
+/* Define to 1 if you have the <openssl/rand.h> header file. */
+#undef HAVE_OPENSSL_RAND_H
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define to 1 if you have the <pcap.h> header file. */
+#undef HAVE_PCAP_H
+
+/* Define to 1 if you have the `random' function. */
+#undef HAVE_RANDOM
+
+/* Define to 1 if you have the `sleep' function. */
+#undef HAVE_SLEEP
+
+/* Define to 1 if you have the `srandom' function. */
+#undef HAVE_SRANDOM
+
+/* Define if you have the SSL libraries installed. */
+#undef HAVE_SSL
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#undef HAVE_SYS_MOUNT_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the <winsock2.h> header file. */
+#undef HAVE_WINSOCK2_H
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if you have the <ws2tcpip.h> header file. */
+#undef HAVE_WS2TCPIP_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define this to enable ECDSA support. */
+#undef USE_ECDSA
+
+/* Define this to enable GOST support. */
+#undef USE_GOST
+
+/* Define this to enable SHA256 and SHA512 support. */
+#undef USE_SHA2
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* the version of the windows API enabled */
+#undef WINVER
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* in_addr_t */
+#undef in_addr_t
+
+/* in_port_t */
+#undef in_port_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `short' if <sys/types.h> does not define. */
+#undef int16_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef int32_t
+
+/* Define to `long long' if <sys/types.h> does not define. */
+#undef int64_t
+
+/* Define to `char' if <sys/types.h> does not define. */
+#undef int8_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to 'int' if not defined */
+#undef socklen_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define to `unsigned short' if <sys/types.h> does not define. */
+#undef uint16_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef uint32_t
+
+/* Define to `unsigned long long' if <sys/types.h> does not define. */
+#undef uint64_t
+
+/* Define to `unsigned char' if <sys/types.h> does not define. */
+#undef uint8_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_PCAP_H
+#include <pcap.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_NETINET_IF_ETHER_H
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+#define USE_WINSOCK 1
+#include <winsock2.h>
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+#ifndef HAVE_GETADDRINFO
+#include <fake-rfc2553.h>
+#endif
+
+#ifndef HAVE_RANDOM
+/* random can be replaced by rand for ldnsexamples */
+#define random rand
+#endif
+
+#ifndef HAVE_SRANDOM
+/* srandom can be replaced by srand for ldnsexamples */
+#define srandom srand
+#endif
+
+extern char *optarg;
+extern int optind, opterr;
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+
+#ifdef S_SPLINT_S
+#define FD_ZERO(a) /* a */
+#define FD_SET(a,b) /* a, b */
+#endif
+
diff --git a/examples/configure b/examples/configure
new file mode 100755
index 000000000000..46dc9988c1fb
--- /dev/null
+++ b/examples/configure
@@ -0,0 +1,7158 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.68 for ldns 1.6.13.
+#
+# Report bugs to <libdns@nlnetlabs.nl>.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ # Preserve -v and -x to the replacement shell.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+ esac
+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: libdns@nlnetlabs.nl about your system, including any
+$0: error possibly output before this message. Then install
+$0: a modern shell, or manually run the script under such a
+$0: shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='ldns'
+PACKAGE_TARNAME='libdns'
+PACKAGE_VERSION='1.6.13'
+PACKAGE_STRING='ldns 1.6.13'
+PACKAGE_BUGREPORT='libdns@nlnetlabs.nl'
+PACKAGE_URL=''
+
+ac_unique_file="ldns-read-zone.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+LDNSDIR
+LIBSSL_LIBS
+LIBSSL_LDFLAGS
+LIBSSL_CPPFLAGS
+RUNTIME_PATH
+HAVE_SSL
+LIBNSL_LIBS
+libtool
+SET_MAKE
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_rpath
+with_ssl
+enable_sha2
+enable_gost
+enable_ecdsa
+with_ldns
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures ldns 1.6.13 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/libdns]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of ldns 1.6.13:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-rpath Disable hardcoded rpath (default=enabled)
+ --disable-sha2 Disable SHA256 and SHA512 RRSIG support
+ --disable-gost Disable GOST support
+ --enable-ecdsa Enable ECDSA support, experimental
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl
+ /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw
+ /usr)
+ --with-ldns=PATH specify prefix of path of ldns library to use
+
+
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <libdns@nlnetlabs.nl>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+ldns configure 1.6.13
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ---------------------------------- ##
+## Report this to libdns@nlnetlabs.nl ##
+## ---------------------------------- ##"
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by ldns $as_me 1.6.13, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# acx_nlnetlabs.m4 - common macros for configure checks
+# Copyright 2009, Wouter Wijngaards, NLnet Labs.
+# BSD licensed.
+#
+# Version 21
+# 2012-02-09 Fix AHX_MEMCMP_BROKEN with undef in compat/memcmp.h.
+# 2012-01-20 Fix COMPILER_FLAGS_UNBOUND for gcc 4.6.2 assigned-not-used-warns.
+# 2011-12-05 Fix getaddrinfowithincludes on windows with fedora16 mingw32-gcc.
+# Fix ACX_MALLOC for redefined malloc error.
+# Fix GETADDRINFO_WITH_INCLUDES to add -lws2_32
+# 2011-11-10 Fix FLTO test to not drop a.out in current directory.
+# 2011-11-01 Fix FLTO test for llvm on Lion.
+# 2011-08-01 Fix nonblock test (broken at v13).
+# 2011-08-01 Fix autoconf 2.68 warnings
+# 2011-06-23 Add ACX_CHECK_FLTO to check -flto.
+# 2010-08-16 Fix FLAG_OMITTED for AS_TR_CPP changes in autoconf-2.66.
+# 2010-07-02 Add check for ss_family (for minix).
+# 2010-04-26 Fix to use CPPFLAGS for CHECK_COMPILER_FLAGS.
+# 2010-03-01 Fix RPATH using CONFIG_COMMANDS to run at the very end.
+# 2010-02-18 WITH_SSL outputs the LIBSSL_LDFLAGS, LIBS, CPPFLAGS seperate, -ldl
+# 2010-02-01 added ACX_CHECK_MEMCMP_SIGNED, AHX_MEMCMP_BROKEN
+# 2010-01-20 added AHX_COONFIG_STRLCAT
+# 2009-07-14 U_CHAR detection improved for windows crosscompile.
+# added ACX_FUNC_MALLOC
+# fixup some #if to #ifdef
+# NONBLOCKING test for mingw crosscompile.
+# 2009-07-13 added ACX_WITH_SSL_OPTIONAL
+# 2009-07-03 fixup LDFLAGS for empty ssl dir.
+#
+# Automates some of the checking constructs. Aims at portability for POSIX.
+# Documentation for functions is below.
+#
+# the following macro's are provided in this file:
+# (see below for details on each macro).
+#
+# ACX_ESCAPE_BACKSLASH - escape backslashes in var for C-preproc.
+# ACX_RSRC_VERSION - create windows resource version number.
+# ACX_CHECK_COMPILER_FLAG - see if cc supports a flag.
+# ACX_CHECK_ERROR_FLAGS - see which flag is -werror (used below).
+# ACX_CHECK_COMPILER_FLAG_NEEDED - see if flags make the code compile cleanly.
+# ACX_DEPFLAG - find cc dependency flags.
+# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX.
+# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax.
+# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax.
+# ACX_CHECK_FLTO - see if cc supports -flto and use it if so.
+# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved.
+# ACX_TYPE_U_CHAR - u_char type.
+# ACX_TYPE_RLIM_T - rlim_t type.
+# ACX_TYPE_SOCKLEN_T - socklen_t type.
+# ACX_TYPE_IN_ADDR_T - in_addr_t type.
+# ACX_TYPE_IN_PORT_T - in_port_t type.
+# ACX_ARG_RPATH - add --disable-rpath option.
+# ACX_WITH_SSL - add --with-ssl option, link -lcrypto.
+# ACX_WITH_SSL_OPTIONAL - add --with-ssl option, link -lcrypto,
+# where --without-ssl is also accepted
+# ACX_LIB_SSL - setup to link -lssl.
+# ACX_SYS_LARGEFILE - improved sys_largefile, fseeko, >2G files.
+# ACX_CHECK_GETADDRINFO_WITH_INCLUDES - find getaddrinfo, portably.
+# ACX_FUNC_DEPRECATED - see if func is deprecated.
+# ACX_CHECK_NONBLOCKING_BROKEN - see if nonblocking sockets really work.
+# ACX_MKDIR_ONE_ARG - determine mkdir(2) number of arguments.
+# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably.
+# ACX_FUNC_MALLOC - check malloc, define replacement .
+# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format.
+# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused.
+# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback.
+# AHX_CONFIG_RAND_MAX - define RAND_MAX if needed.
+# AHX_CONFIG_MAXHOSTNAMELEN - define MAXHOSTNAMELEN if needed.
+# AHX_CONFIG_IPV6_MIN_MTU - define IPV6_MIN_MTU if needed.
+# AHX_CONFIG_SNPRINTF - snprintf compat prototype
+# AHX_CONFIG_INET_PTON - inet_pton compat prototype
+# AHX_CONFIG_INET_NTOP - inet_ntop compat prototype
+# AHX_CONFIG_INET_ATON - inet_aton compat prototype
+# AHX_CONFIG_MEMMOVE - memmove compat prototype
+# AHX_CONFIG_STRLCAT - strlcat compat prototype
+# AHX_CONFIG_STRLCPY - strlcpy compat prototype
+# AHX_CONFIG_GMTIME_R - gmtime_r compat prototype
+# AHX_CONFIG_W32_SLEEP - w32 compat for sleep
+# AHX_CONFIG_W32_USLEEP - w32 compat for usleep
+# AHX_CONFIG_W32_RANDOM - w32 compat for random
+# AHX_CONFIG_W32_SRANDOM - w32 compat for srandom
+# AHX_CONFIG_W32_FD_SET_T - w32 detection of FD_SET_T.
+# ACX_CFLAGS_STRIP - strip one flag from CFLAGS
+# ACX_STRIP_EXT_FLAGS - strip extension flags from CFLAGS
+# AHX_CONFIG_FLAG_OMITTED - define omitted flag
+# AHX_CONFIG_FLAG_EXT - define omitted extension flag
+# AHX_CONFIG_EXT_FLAGS - define the stripped extension flags
+# ACX_CHECK_MEMCMP_SIGNED - check if memcmp uses signed characters.
+# AHX_MEMCMP_BROKEN - replace memcmp func for CHECK_MEMCMP_SIGNED.
+# ACX_CHECK_SS_FAMILY - check for sockaddr_storage.ss_family
+#
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+OURCPPFLAGS=''
+CPPFLAGS=${CPPFLAGS:-${OURCPPFLAGS}}
+OURCFLAGS='-g'
+CFLAGS=${CFLAGS:-${OURCFLAGS}}
+
+$as_echo "#define WINVER 0x0502" >>confdefs.h
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = xyes; then :
+ MINIX=yes
+else
+ MINIX=
+fi
+
+
+ if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if ${ac_cv_safe_to_define___extensions__+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# define __EXTENSIONS__ 1
+ $ac_includes_default
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_safe_to_define___extensions__=yes
+else
+ ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+ test $ac_cv_safe_to_define___extensions__ = yes &&
+ $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+ $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+ $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+
+# Checks for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+for ac_prog in glibtool libtool15 libtool
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_libtool+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$libtool"; then
+ ac_cv_prog_libtool="$libtool" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_libtool="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+libtool=$ac_cv_prog_libtool
+if test -n "$libtool"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libtool" >&5
+$as_echo "$libtool" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$libtool" && break
+done
+test -n "$libtool" || libtool="../libtool"
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -std=c99" >&5
+$as_echo_n "checking whether $CC supports -std=c99... " >&6; }
+cache=`echo std=c99 | sed 'y%.=/+-%___p_%'`
+if eval \${cv_prog_cc_flag_$cache+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+echo 'void f(){}' >conftest.c
+if test -z "`$CC $CPPFLAGS $CFLAGS -std=c99 -c conftest.c 2>&1`"; then
+eval "cv_prog_cc_flag_$cache=yes"
+else
+eval "cv_prog_cc_flag_$cache=no"
+fi
+rm -f conftest conftest.o conftest.c
+
+fi
+
+if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+:
+C99FLAG="-std=c99"
+else
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+:
+
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -xc99" >&5
+$as_echo_n "checking whether $CC supports -xc99... " >&6; }
+cache=`echo xc99 | sed 'y%.=/+-%___p_%'`
+if eval \${cv_prog_cc_flag_$cache+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+echo 'void f(){}' >conftest.c
+if test -z "`$CC $CPPFLAGS $CFLAGS -xc99 -c conftest.c 2>&1`"; then
+eval "cv_prog_cc_flag_$cache=yes"
+else
+eval "cv_prog_cc_flag_$cache=no"
+fi
+rm -f conftest conftest.o conftest.c
+
+fi
+
+if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+:
+C99FLAG="-xc99"
+else
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+:
+
+fi
+
+
+# Check whether --enable-rpath was given.
+if test "${enable_rpath+set}" = set; then :
+ enableval=$enable_rpath; enable_rpath=$enableval
+else
+ enable_rpath=yes
+fi
+
+
+if test "x$enable_rpath" = xyes; then
+ RPATH_VAL="-Wl,-rpath=\${libdir}"
+fi
+
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -O2" >&5
+$as_echo_n "checking whether $CC supports -O2... " >&6; }
+cache=`echo O2 | sed 'y%.=/+-%___p_%'`
+if eval \${cv_prog_cc_flag_$cache+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+echo 'void f(){}' >conftest.c
+if test -z "`$CC $CPPFLAGS $CFLAGS -O2 -c conftest.c 2>&1`"; then
+eval "cv_prog_cc_flag_$cache=yes"
+else
+eval "cv_prog_cc_flag_$cache=no"
+fi
+rm -f conftest conftest.o conftest.c
+
+fi
+
+if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+:
+CFLAGS="$CFLAGS -O2"
+else
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+:
+
+fi
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Werror" >&5
+$as_echo_n "checking whether $CC supports -Werror... " >&6; }
+cache=`echo Werror | sed 'y%.=/+-%___p_%'`
+if eval \${cv_prog_cc_flag_$cache+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+echo 'void f(){}' >conftest.c
+if test -z "`$CC $CPPFLAGS $CFLAGS -Werror -c conftest.c 2>&1`"; then
+eval "cv_prog_cc_flag_$cache=yes"
+else
+eval "cv_prog_cc_flag_$cache=no"
+fi
+rm -f conftest conftest.o conftest.c
+
+fi
+
+if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+:
+ERRFLAG="-Werror"
+else
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+:
+ERRFLAG="-errwarn"
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5
+$as_echo_n "checking whether $CC supports -Wall... " >&6; }
+cache=`echo Wall | sed 'y%.=/+-%___p_%'`
+if eval \${cv_prog_cc_flag_$cache+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+echo 'void f(){}' >conftest.c
+if test -z "`$CC $CPPFLAGS $CFLAGS -Wall -c conftest.c 2>&1`"; then
+eval "cv_prog_cc_flag_$cache=yes"
+else
+eval "cv_prog_cc_flag_$cache=no"
+fi
+rm -f conftest conftest.o conftest.c
+
+fi
+
+if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+:
+ERRFLAG="$ERRFLAG -Wall"
+else
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+:
+ERRFLAG="$ERRFLAG -errfmt"
+fi
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 as a flag for $CC" >&5
+$as_echo_n "checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 as a flag for $CC... " >&6; }
+cache=`$as_echo "$C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600" | $as_tr_sh`
+if eval \${cv_prog_cc_flag_needed_$cache+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+echo '
+#include "confdefs.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/time.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#include <unistd.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+int test() {
+ int a;
+ char **opts = NULL;
+ struct timeval tv;
+ char *t;
+ time_t time = 0;
+ char *buf = NULL;
+ t = ctime_r(&time, buf);
+ tv.tv_usec = 10;
+ srandom(32);
+ a = getopt(2, opts, "a");
+ a = isascii(32);
+ return a;
+}
+' > conftest.c
+echo 'void f(){}' >>conftest.c
+if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then
+eval "cv_prog_cc_flag_needed_$cache=no"
+else
+
+if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1`"; then
+eval "cv_prog_cc_flag_needed_$cache=yes"
+else
+eval "cv_prog_cc_flag_needed_$cache=fail"
+#echo 'Test with flag fails too!'
+#cat conftest.c
+#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1"
+#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1`
+#exit 1
+fi
+
+fi
+rm -f conftest conftest.c conftest.o
+
+fi
+
+if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+:
+CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600"
+else
+if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+#echo 'Test with flag is no!'
+#cat conftest.c
+#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1"
+#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1`
+#exit 1
+:
+
+else
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+:
+
+fi
+fi
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG as a flag for $CC" >&5
+$as_echo_n "checking whether we need $C99FLAG as a flag for $CC... " >&6; }
+cache=`$as_echo "$C99FLAG" | $as_tr_sh`
+if eval \${cv_prog_cc_flag_needed_$cache+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+echo '#include <stdbool.h>' > conftest.c
+echo 'void f(){}' >>conftest.c
+if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then
+eval "cv_prog_cc_flag_needed_$cache=no"
+else
+
+if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1`"; then
+eval "cv_prog_cc_flag_needed_$cache=yes"
+else
+eval "cv_prog_cc_flag_needed_$cache=fail"
+#echo 'Test with flag fails too!'
+#cat conftest.c
+#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1"
+#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1`
+#exit 1
+fi
+
+fi
+rm -f conftest conftest.c conftest.o
+
+fi
+
+if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+:
+CFLAGS="$CFLAGS $C99FLAG"
+else
+if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+#echo 'Test with flag is no!'
+#cat conftest.c
+#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1"
+#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1`
+#exit 1
+:
+
+else
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+:
+
+fi
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default"
+if test "x$ac_cv_type_int8_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define int8_t char
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default"
+if test "x$ac_cv_type_int16_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define int16_t short
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default"
+if test "x$ac_cv_type_int32_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define int32_t int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default"
+if test "x$ac_cv_type_int64_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define int64_t long long
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default"
+if test "x$ac_cv_type_uint8_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define uint8_t unsigned char
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default"
+if test "x$ac_cv_type_uint16_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define uint16_t unsigned short
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default"
+if test "x$ac_cv_type_uint32_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define uint32_t unsigned int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default"
+if test "x$ac_cv_type_uint64_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define uint64_t unsigned long long
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default"
+if test "x$ac_cv_type_ssize_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+
+for ac_header in sys/types.h getopt.h stdlib.h stdio.h assert.h netinet/in.h ctype.h time.h pcap.h arpa/inet.h sys/time.h sys/socket.h sys/select.h netdb.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in winsock2.h ws2tcpip.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/in_systm.h net/if.h netinet/ip.h netinet/udp.h netinet/igmp.h netinet/if_ether.h netinet/ip6.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "
+$ac_includes_default
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "
+$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+#endif
+
+"
+if test "x$ac_cv_type_socklen_t" = xyes; then :
+
+else
+
+$as_echo "#define socklen_t int" >>confdefs.h
+
+fi
+
+for ac_header in sys/param.h sys/mount.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+
+
+ #if HAVE_SYS_PARAM_H
+ # include <sys/param.h>
+ #endif
+
+
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" "
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+"
+if test "x$ac_cv_type_in_addr_t" = xyes; then :
+
+else
+
+$as_echo "#define in_addr_t uint32_t" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" "
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+"
+if test "x$ac_cv_type_in_port_t" = xyes; then :
+
+else
+
+$as_echo "#define in_port_t uint16_t" >>confdefs.h
+
+fi
+
+
+# check to see if libraries are needed for these functions.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
+$as_echo_n "checking for library containing socket... " >&6; }
+if ${ac_cv_search_socket+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_socket=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_socket+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_socket+:} false; then :
+
+else
+ ac_cv_search_socket=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
+$as_echo "$ac_cv_search_socket" >&6; }
+ac_res=$ac_cv_search_socket
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+tmp_LIBS="$LIBS"
+LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_pton" >&5
+$as_echo_n "checking for library containing inet_pton... " >&6; }
+if ${ac_cv_search_inet_pton+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_pton ();
+int
+main ()
+{
+return inet_pton ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' nsl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_inet_pton=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_inet_pton+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_inet_pton+:} false; then :
+
+else
+ ac_cv_search_inet_pton=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_pton" >&5
+$as_echo "$ac_cv_search_inet_pton" >&6; }
+ac_res=$ac_cv_search_inet_pton
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+LIBNSL_LIBS=$LIBS
+
+LIBS="$tmp_LIBS"
+
+tmp_CPPFLAGS="$CPPFLAGS"
+tmp_LDFLAGS="$LDFLAGS"
+tmp_LIBS="$LIBS"
+
+
+
+# Check whether --with-ssl was given.
+if test "${with_ssl+set}" = set; then :
+ withval=$with_ssl;
+
+else
+
+ withval="yes"
+
+fi
+
+
+ withval=$withval
+ if test x_$withval != x_no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL" >&5
+$as_echo_n "checking for SSL... " >&6; }
+ if test x_$withval = x_ -o x_$withval = x_yes; then
+ withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr"
+ fi
+ for dir in $withval; do
+ ssldir="$dir"
+ if test -f "$dir/include/openssl/ssl.h"; then
+ found_ssl="yes"
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SSL /**/
+_ACEOF
+
+ if test "$ssldir" != "/usr"; then
+ CPPFLAGS="$CPPFLAGS -I$ssldir/include"
+ LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include"
+ fi
+ break;
+ fi
+ done
+ if test x_$found_ssl != x_yes; then
+ as_fn_error $? "Cannot find the SSL libraries in $withval" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $ssldir" >&5
+$as_echo "found in $ssldir" >&6; }
+ HAVE_SSL=yes
+ if test "$ssldir" != "/usr" -a "$ssldir" != ""; then
+ LDFLAGS="$LDFLAGS -L$ssldir/lib"
+ LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib"
+
+ if test "x$enable_rpath" = xyes; then
+ if echo "$ssldir/lib" | grep "^/" >/dev/null; then
+ RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib"
+ fi
+ fi
+
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_CTX_init in -lcrypto" >&5
+$as_echo_n "checking for HMAC_CTX_init in -lcrypto... " >&6; }
+ LIBS="$LIBS -lcrypto"
+ LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ int HMAC_CTX_init(void);
+ (void)HMAC_CTX_init();
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ # check if -lwsock32 or -lgdi32 are needed.
+ BAKLIBS="$LIBS"
+ BAKSSLLIBS="$LIBSSL_LIBS"
+ LIBS="$LIBS -lgdi32"
+ LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -lgdi32" >&5
+$as_echo_n "checking if -lcrypto needs -lgdi32... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ int HMAC_CTX_init(void);
+ (void)HMAC_CTX_init();
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+
+$as_echo "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ LIBS="$BAKLIBS"
+ LIBSSL_LIBS="$BAKSSLLIBS"
+ LIBS="$LIBS -ldl"
+ LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl" >&5
+$as_echo_n "checking if -lcrypto needs -ldl... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ int HMAC_CTX_init(void);
+ (void)HMAC_CTX_init();
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+
+$as_echo "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "OpenSSL found in $ssldir, but version 0.9.7 or higher is required" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ fi
+
+
+ # openssl engine functionality needs dlopen().
+ BAKLIBS="$LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_dlopen+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+ ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ if test "$LIBS" != "$BAKLIBS"; then
+ LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
+ fi
+ fi
+for ac_header in openssl/ssl.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_openssl_ssl_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_OPENSSL_SSL_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in openssl/err.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "openssl/err.h" "ac_cv_header_openssl_err_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_openssl_err_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_OPENSSL_ERR_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in openssl/rand.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "openssl/rand.h" "ac_cv_header_openssl_rand_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_openssl_rand_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_OPENSSL_RAND_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+CPPFLAGS="$tmp_CPPFLAGS"
+LDFLAGS="$tmp_LDFLAGS"
+LIBS="$tmp_LIBS"
+
+# use libcrypto to check the following:
+tmp_LDFLAGS="$LDFLAGS"
+tmp_LIBS="$LIBS"
+LDFLAGS="$LDFLAGS $LIBSSL_LDFLAGS"
+LIBS="$LIBS $LIBSSL_LIBS"
+# Check whether --enable-sha2 was given.
+if test "${enable_sha2+set}" = set; then :
+ enableval=$enable_sha2;
+fi
+
+case "$enable_sha2" in
+ no)
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SHA256 and SHA512" >&5
+$as_echo_n "checking for SHA256 and SHA512... " >&6; }
+ ac_fn_c_check_func "$LINENO" "SHA256_Init" "ac_cv_func_SHA256_Init"
+if test "x$ac_cv_func_SHA256_Init" = xyes; then :
+
+else
+
+ as_fn_error $? "SHA2 enabled, but no SHA2 functions found in OpenSSL" "$LINENO" 5
+
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_SHA2 1
+_ACEOF
+
+ ;;
+esac
+
+# Check whether --enable-gost was given.
+if test "${enable_gost+set}" = set; then :
+ enableval=$enable_gost;
+fi
+
+case "$enable_gost" in
+ no)
+ ;;
+ *)
+ if test "x$HAVE_SSL" != "xyes"; then
+ as_fn_error $? "GOST enabled, but no SSL support" "$LINENO" 5
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GOST" >&5
+$as_echo_n "checking for GOST... " >&6; }
+ ac_fn_c_check_func "$LINENO" "EVP_PKEY_set_type_str" "ac_cv_func_EVP_PKEY_set_type_str"
+if test "x$ac_cv_func_EVP_PKEY_set_type_str" = xyes; then :
+
+else
+ as_fn_error $? "OpenSSL >= 1.0.0 is needed for GOST support or rerun with --disable-gost" "$LINENO" 5
+fi
+
+ ac_fn_c_check_func "$LINENO" "EC_KEY_new" "ac_cv_func_EC_KEY_new"
+if test "x$ac_cv_func_EC_KEY_new" = xyes; then :
+
+else
+ as_fn_error $? "No ECC functions found in OpenSSL: please upgrade OpenSSL or rerun with --disable-gost" "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_GOST 1
+_ACEOF
+
+ ;;
+esac
+
+# Check whether --enable-ecdsa was given.
+if test "${enable_ecdsa+set}" = set; then :
+ enableval=$enable_ecdsa;
+fi
+
+case "$enable_ecdsa" in
+ yes)
+ ac_fn_c_check_func "$LINENO" "ECDSA_sign" "ac_cv_func_ECDSA_sign"
+if test "x$ac_cv_func_ECDSA_sign" = xyes; then :
+
+else
+ as_fn_error $? "OpenSSL does not support ECDSA" "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_ECDSA 1
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+ *****************************************************************
+ *** YOU HAVE ENABLED ECDSA WHICH IS EXPERIMENTAL AT THIS TIME ***
+ *** PLEASE DO NOT USE THIS ON THE PUBLIC INTERNET ***
+ *****************************************************************" >&5
+$as_echo "$as_me: WARNING:
+ *****************************************************************
+ *** YOU HAVE ENABLED ECDSA WHICH IS EXPERIMENTAL AT THIS TIME ***
+ *** PLEASE DO NOT USE THIS ON THE PUBLIC INTERNET ***
+ *****************************************************************" >&2;}
+ ;;
+ no|*)
+ ;;
+esac
+
+LDFLAGS="$tmp_LDFLAGS"
+LIBS="$tmp_LIBS"
+
+#AC_CHECK_HEADER(ldns/ldns.h,, [
+# AC_MSG_ERROR([Can't find ldns headers (make copy-headers in devel source.)])
+# ], [AC_INCLUDES_DEFAULT]
+#)
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_open_offline in -lpcap" >&5
+$as_echo_n "checking for pcap_open_offline in -lpcap... " >&6; }
+if ${ac_cv_lib_pcap_pcap_open_offline+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pcap_open_offline ();
+int
+main ()
+{
+return pcap_open_offline ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pcap_pcap_open_offline=yes
+else
+ ac_cv_lib_pcap_pcap_open_offline=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_open_offline" >&5
+$as_echo "$ac_cv_lib_pcap_pcap_open_offline" >&6; }
+if test "x$ac_cv_lib_pcap_pcap_open_offline" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPCAP 1
+_ACEOF
+
+ LIBS="-lpcap $LIBS"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find pcap library (needed for ldns-dpa, will not build dpa now.)" >&5
+$as_echo "$as_me: WARNING: Can't find pcap library (needed for ldns-dpa, will not build dpa now.)" >&2;}
+
+
+fi
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5
+$as_echo_n "checking for getaddrinfo... " >&6; }
+if ${ac_cv_func_getaddrinfo+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_func_getaddrinfo=no
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+char* getaddrinfo();
+char* (*f) () = getaddrinfo;
+#ifdef __cplusplus
+}
+#endif
+int main() {
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_func_getaddrinfo="yes"
+else
+ ORIGLIBS="$LIBS"
+LIBS="$LIBS -lws2_32"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+int
+main ()
+{
+
+ (void)getaddrinfo(NULL, NULL, NULL, NULL);
+
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_func_getaddrinfo="yes"
+LDFLAGS="$LDFLAGS -lws2_32"
+
+else
+ ac_cv_func_getaddrinfo="no"
+LIBS="$ORIGLIBS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getaddrinfo" >&5
+$as_echo "$ac_cv_func_getaddrinfo" >&6; }
+if test $ac_cv_func_getaddrinfo = yes; then
+
+$as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+for ac_header in vfork.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default"
+if test "x$ac_cv_header_vfork_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VFORK_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in fork vfork
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
+$as_echo_n "checking for working fork... " >&6; }
+if ${ac_cv_func_fork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_fork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* By Ruediger Kuhlmann. */
+ return fork () < 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_fork_works=yes
+else
+ ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5
+$as_echo "$ac_cv_func_fork_works" >&6; }
+
+else
+ ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+ case $host in
+ *-*-amigaos* | *-*-msdosdjgpp*)
+ # Override, as these systems have only a dummy fork() stub
+ ac_cv_func_fork_works=no
+ ;;
+ *)
+ ac_cv_func_fork_works=yes
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
+$as_echo_n "checking for working vfork... " >&6; }
+if ${ac_cv_func_vfork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_vfork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Thanks to Paul Eggert for this test. */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent. The compiler
+ is told about this with #include <vfork.h>, but some compilers
+ (e.g. gcc -O) don't grok <vfork.h>. Test for this by using a
+ static variable whose address is put into a register that is
+ clobbered by the vfork. */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+
+int
+main ()
+{
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test (0);
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems. This
+ test uses lots of local variables, at least as many local
+ variables as main has allocated so far including compiler
+ temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris
+ 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should
+ reuse the register of parent for one of the local variables,
+ since it will think that parent can't possibly be used any more
+ in this routine. Assigning to the local variable will thus
+ munge parent in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+ from child file descriptors. If the child closes a descriptor
+ before it execs or exits, this munges the parent's descriptor
+ as well. Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ return (
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_vfork_works=yes
+else
+ ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5
+$as_echo "$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+ ac_cv_func_vfork_works=$ac_cv_func_vfork
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h
+
+else
+
+$as_echo "#define vfork fork" >>confdefs.h
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
+
+fi
+
+for ac_func in isblank srandom random sleep
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ac_fn_c_check_decl "$LINENO" "in6addr_any" "ac_cv_have_decl_in6addr_any" "$ac_includes_default
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+#ifdef HAVE_NETINET_IGMP_H
+#include <netinet/igmp.h>
+#endif
+
+"
+if test "x$ac_cv_have_decl_in6addr_any" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_IN6ADDR_ANY $ac_have_decl
+_ACEOF
+
+
+# check for ldns
+
+# Check whether --with-ldns was given.
+if test "${with_ldns+set}" = set; then :
+ withval=$with_ldns;
+ specialldnsdir="$withval"
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="-L$withval -L$withval/lib $LDFLAGS"
+ LDNSDIR="$withval"
+
+
+fi
+
+
+# check for ldns development source tree
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldns devel source" >&5
+$as_echo_n "checking for ldns devel source... " >&6; }
+ldns_dev_dir=..
+if test -f $ldns_dev_dir/ldns/util.h && \
+ grep LDNS_VERSION $ldns_dev_dir/ldns/util.h >/dev/null; then
+ ldns_version=`grep LDNS_VERSION $ldns_dev_dir/ldns/util.h | sed -e 's/^.*"\(.*\)".*$/\1/'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using $ldns_dev_dir with $ldns_version" >&5
+$as_echo "using $ldns_dev_dir with $ldns_version" >&6; }
+ CPPFLAGS="$CPPFLAGS -I$ldns_dev_dir/include"
+ LDFLAGS="-L$ldns_dev_dir -L$ldns_dev_dir/lib $LDFLAGS"
+ LIBS="$LIBS -lldns"
+
+$as_echo "#define HAVE_LIBLDNS 1" >>confdefs.h
+
+ LDNSDIR="$ldns_dev_dir"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldns_rr_new in -lldns" >&5
+$as_echo_n "checking for ldns_rr_new in -lldns... " >&6; }
+if ${ac_cv_lib_ldns_ldns_rr_new+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lldns $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldns_rr_new ();
+int
+main ()
+{
+return ldns_rr_new ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ldns_ldns_rr_new=yes
+else
+ ac_cv_lib_ldns_ldns_rr_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldns_ldns_rr_new" >&5
+$as_echo "$ac_cv_lib_ldns_ldns_rr_new" >&6; }
+if test "x$ac_cv_lib_ldns_ldns_rr_new" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBLDNS 1
+_ACEOF
+
+ LIBS="-lldns $LIBS"
+
+else
+
+ as_fn_error $? "Can't find ldns library" "$LINENO" 5
+
+
+fi
+
+fi
+
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile"
+
+ac_config_headers="$ac_config_headers config.h"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by ldns $as_me 1.6.13, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <libdns@nlnetlabs.nl>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+ldns config.status 1.6.13
+configured by $0, generated by GNU Autoconf 2.68,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/examples/configure.ac b/examples/configure.ac
new file mode 100644
index 000000000000..67345dac7cd2
--- /dev/null
+++ b/examples/configure.ac
@@ -0,0 +1,421 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.56)
+AC_INIT(ldns, 1.6.13, libdns@nlnetlabs.nl,libdns)
+AC_CONFIG_SRCDIR([ldns-read-zone.c])
+sinclude(../acx_nlnetlabs.m4)
+
+OURCPPFLAGS=''
+CPPFLAGS=${CPPFLAGS:-${OURCPPFLAGS}}
+OURCFLAGS='-g'
+CFLAGS=${CFLAGS:-${OURCFLAGS}}
+AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled])
+
+AC_AIX
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_MAKE_SET
+AC_CHECK_PROGS(libtool, [glibtool libtool15 libtool], [../libtool])
+
+ACX_CHECK_COMPILER_FLAG(std=c99, [C99FLAG="-std=c99"])
+ACX_CHECK_COMPILER_FLAG(xc99, [C99FLAG="-xc99"])
+
+AC_ARG_ENABLE(rpath,
+ [AC_HELP_STRING([--disable-rpath], [Disable hardcoded rpath (default=enabled)])],
+ enable_rpath=$enableval, enable_rpath=yes)
+
+if test "x$enable_rpath" = xyes; then
+ RPATH_VAL="-Wl,-rpath=\${libdir}"
+fi
+
+
+AC_TYPE_SIZE_T
+ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
+
+ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600,
+[
+#include "confdefs.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/time.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#include <unistd.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+int test() {
+ int a;
+ char **opts = NULL;
+ struct timeval tv;
+ char *t;
+ time_t time = 0;
+ char *buf = NULL;
+ t = ctime_r(&time, buf);
+ tv.tv_usec = 10;
+ srandom(32);
+ a = getopt(2, opts, "a");
+ a = isascii(32);
+ return a;
+}
+], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600"])
+
+
+ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG, [#include <stdbool.h>], [CFLAGS="$CFLAGS $C99FLAG"])
+
+AC_C_INLINE
+AC_CHECK_TYPE(int8_t, char)
+AC_CHECK_TYPE(int16_t, short)
+AC_CHECK_TYPE(int32_t, int)
+AC_CHECK_TYPE(int64_t, long long)
+AC_CHECK_TYPE(uint8_t, unsigned char)
+AC_CHECK_TYPE(uint16_t, unsigned short)
+AC_CHECK_TYPE(uint32_t, unsigned int)
+AC_CHECK_TYPE(uint64_t, unsigned long long)
+AC_CHECK_TYPE(ssize_t, int)
+
+AC_CHECK_HEADERS([sys/types.h getopt.h stdlib.h stdio.h assert.h netinet/in.h ctype.h time.h pcap.h arpa/inet.h sys/time.h sys/socket.h sys/select.h netdb.h],,, [AC_INCLUDES_DEFAULT])
+AC_CHECK_HEADERS([winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT])
+AC_CHECK_HEADERS([netinet/in_systm.h net/if.h netinet/ip.h netinet/udp.h netinet/igmp.h netinet/if_ether.h netinet/ip6.h],,, [
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif])
+
+ACX_TYPE_SOCKLEN_T
+AC_CHECK_HEADERS([sys/param.h sys/mount.h],,,
+[AC_INCLUDES_DEFAULT]
+[
+ [
+ #if HAVE_SYS_PARAM_H
+ # include <sys/param.h>
+ #endif
+ ]
+])
+AC_CHECK_TYPE(in_addr_t, [], [AC_DEFINE([in_addr_t], [uint32_t], [in_addr_t])], [
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif])
+AC_CHECK_TYPE(in_port_t, [], [AC_DEFINE([in_port_t], [uint16_t], [in_port_t])], [
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif])
+
+# check to see if libraries are needed for these functions.
+AC_SEARCH_LIBS(socket, socket)
+tmp_LIBS="$LIBS"
+LIBS=
+AC_SEARCH_LIBS(inet_pton, nsl)
+AC_SUBST(LIBNSL_LIBS,$LIBS)
+LIBS="$tmp_LIBS"
+
+tmp_CPPFLAGS="$CPPFLAGS"
+tmp_LDFLAGS="$LDFLAGS"
+tmp_LIBS="$LIBS"
+
+ACX_WITH_SSL_OPTIONAL
+
+AC_SUBST(LIBSSL_CPPFLAGS)
+AC_SUBST(LIBSSL_LDFLAGS)
+AC_SUBST(LIBSSL_LIBS)
+
+CPPFLAGS="$tmp_CPPFLAGS"
+LDFLAGS="$tmp_LDFLAGS"
+LIBS="$tmp_LIBS"
+
+# use libcrypto to check the following:
+tmp_LDFLAGS="$LDFLAGS"
+tmp_LIBS="$LIBS"
+LDFLAGS="$LDFLAGS $LIBSSL_LDFLAGS"
+LIBS="$LIBS $LIBSSL_LIBS"
+AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
+case "$enable_sha2" in
+ no)
+ ;;
+ *)
+ AC_MSG_CHECKING(for SHA256 and SHA512)
+ AC_CHECK_FUNC(SHA256_Init,, [
+ AC_MSG_ERROR([SHA2 enabled, but no SHA2 functions found in OpenSSL])
+ ])
+ AC_DEFINE_UNQUOTED([USE_SHA2], [1], [Define this to enable SHA256 and SHA512 support.])
+ ;;
+esac
+
+AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support]))
+case "$enable_gost" in
+ no)
+ ;;
+ *)
+ if test "x$HAVE_SSL" != "xyes"; then
+ AC_MSG_ERROR([GOST enabled, but no SSL support])
+ fi
+ AC_MSG_CHECKING(for GOST)
+ AC_CHECK_FUNC(EVP_PKEY_set_type_str, [],[AC_MSG_ERROR([OpenSSL >= 1.0.0 is needed for GOST support or rerun with --disable-gost])])
+ AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([No ECC functions found in OpenSSL: please upgrade OpenSSL or rerun with --disable-gost])])
+ AC_DEFINE_UNQUOTED([USE_GOST], [1], [Define this to enable GOST support.])
+ ;;
+esac
+
+AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--enable-ecdsa], [Enable ECDSA support, experimental]))
+case "$enable_ecdsa" in
+ yes)
+ AC_CHECK_FUNC(ECDSA_sign,,[AC_MSG_ERROR([OpenSSL does not support ECDSA])])
+ AC_DEFINE_UNQUOTED([USE_ECDSA], [1], [Define this to enable ECDSA support.])
+ AC_WARN([
+ *****************************************************************
+ *** YOU HAVE ENABLED ECDSA WHICH IS EXPERIMENTAL AT THIS TIME ***
+ *** PLEASE DO NOT USE THIS ON THE PUBLIC INTERNET ***
+ *****************************************************************])
+ ;;
+ no|*)
+ ;;
+esac
+
+LDFLAGS="$tmp_LDFLAGS"
+LIBS="$tmp_LIBS"
+
+#AC_CHECK_HEADER(ldns/ldns.h,, [
+# AC_MSG_ERROR([Can't find ldns headers (make copy-headers in devel source.)])
+# ], [AC_INCLUDES_DEFAULT]
+#)
+
+AC_CHECK_LIB(pcap, pcap_open_offline,, [
+ AC_MSG_WARN([Can't find pcap library (needed for ldns-dpa, will not build dpa now.)])
+ ]
+)
+
+
+AC_DEFUN([AC_CHECK_GETADDRINFO_WITH_INCLUDES],
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING(for getaddrinfo)
+AC_CACHE_VAL(ac_cv_func_getaddrinfo,
+[ac_cv_func_getaddrinfo=no
+AC_LINK_IFELSE(
+[
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+char* getaddrinfo();
+char* (*f) () = getaddrinfo;
+#ifdef __cplusplus
+}
+#endif
+int main() {
+ ;
+ return 0;
+}
+],
+dnl this case on linux, solaris, bsd
+[ac_cv_func_getaddrinfo="yes"],
+dnl no quick getaddrinfo, try mingw32 and winsock2 library.
+ORIGLIBS="$LIBS"
+LIBS="$LIBS -lws2_32"
+AC_LINK_IFELSE(
+AC_LANG_PROGRAM(
+[
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+],
+[
+ (void)getaddrinfo(NULL, NULL, NULL, NULL);
+]
+),
+[ac_cv_func_getaddrinfo="yes"
+LDFLAGS="$LDFLAGS -lws2_32"
+],
+[ac_cv_func_getaddrinfo="no"
+LIBS="$ORIGLIBS"
+])
+)
+])
+
+AC_MSG_RESULT($ac_cv_func_getaddrinfo)
+if test $ac_cv_func_getaddrinfo = yes; then
+ AC_DEFINE(HAVE_GETADDRINFO, 1, [Whether getaddrinfo is available])
+fi
+])dnl
+
+AC_CHECK_GETADDRINFO_WITH_INCLUDES
+
+AC_FUNC_FORK
+AC_CHECK_FUNCS(isblank srandom random sleep)
+AC_CHECK_DECLS([in6addr_any],,,[AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+#ifdef HAVE_NETINET_IGMP_H
+#include <netinet/igmp.h>
+#endif
+])
+
+# check for ldns
+AC_ARG_WITH(ldns,
+ AC_HELP_STRING([--with-ldns=PATH specify prefix of path of ldns library to use])
+ ,
+ [
+ specialldnsdir="$withval"
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="-L$withval -L$withval/lib $LDFLAGS"
+ LDNSDIR="$withval"
+ ]
+)
+
+# check for ldns development source tree
+AC_MSG_CHECKING([for ldns devel source])
+ldns_dev_dir=..
+if test -f $ldns_dev_dir/ldns/util.h && \
+ grep LDNS_VERSION $ldns_dev_dir/ldns/util.h >/dev/null; then
+ ldns_version=`grep LDNS_VERSION $ldns_dev_dir/ldns/util.h | sed -e 's/^.*"\(.*\)".*$/\1/'`
+ AC_MSG_RESULT([using $ldns_dev_dir with $ldns_version])
+ CPPFLAGS="$CPPFLAGS -I$ldns_dev_dir/include"
+ LDFLAGS="-L$ldns_dev_dir -L$ldns_dev_dir/lib $LDFLAGS"
+ LIBS="$LIBS -lldns"
+ AC_DEFINE(HAVE_LIBLDNS, 1, [If the ldns library is available.])
+ LDNSDIR="$ldns_dev_dir"
+else
+ AC_MSG_RESULT([no])
+ AC_CHECK_LIB(ldns, ldns_rr_new,, [
+ AC_MSG_ERROR([Can't find ldns library])
+ ]
+ )
+fi
+
+AC_SUBST(LDNSDIR)
+
+
+AH_BOTTOM([
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_PCAP_H
+#include <pcap.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_NETINET_IF_ETHER_H
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+#define USE_WINSOCK 1
+#include <winsock2.h>
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+#ifndef HAVE_GETADDRINFO
+#include <fake-rfc2553.h>
+#endif
+
+#ifndef HAVE_RANDOM
+/* random can be replaced by rand for ldnsexamples */
+#define random rand
+#endif
+
+#ifndef HAVE_SRANDOM
+/* srandom can be replaced by srand for ldnsexamples */
+#define srandom srand
+#endif
+
+extern char *optarg;
+extern int optind, opterr;
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+
+#ifdef S_SPLINT_S
+#define FD_ZERO(a) /* a */
+#define FD_SET(a,b) /* a, b */
+#endif
+])
+
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_HEADER([config.h])
+AC_OUTPUT
diff --git a/examples/fake-rfc2553.h b/examples/fake-rfc2553.h
new file mode 100644
index 000000000000..1e9add1eb033
--- /dev/null
+++ b/examples/fake-rfc2553.h
@@ -0,0 +1,175 @@
+/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */
+/*
+ * Copyright (C) 2000-2003 Damien Miller. All rights reserved.
+ * Copyright (C) 1999 WIDE Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Pseudo-implementation of RFC2553 name / address resolution functions
+ *
+ * But these functions are not implemented correctly. The minimum subset
+ * is implemented for ssh use only. For example, this routine assumes
+ * that ai_family is AF_INET. Don't use it for another purpose.
+ */
+
+#ifndef _FAKE_RFC2553_H
+#define _FAKE_RFC2553_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <limits.h>
+
+/*
+ * First, socket and INET6 related definitions
+ */
+#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
+#ifndef _SS_MAXSIZE
+# define _SS_MAXSIZE 128 /* Implementation specific max size */
+# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr))
+struct sockaddr_storage {
+ struct sockaddr ss_sa;
+ char __ss_pad2[_SS_PADSIZE];
+};
+# define ss_family ss_sa.sa_family
+#endif /* _SS_MAXSIZE */
+#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
+
+#ifndef IN6_IS_ADDR_LOOPBACK
+# define IN6_IS_ADDR_LOOPBACK(a) \
+ (((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \
+ ((uint32_t *)(a))[2] == 0 && ((uint32_t *)(a))[3] == htonl(1))
+#endif /* !IN6_IS_ADDR_LOOPBACK */
+
+#ifndef HAVE_STRUCT_IN6_ADDR
+struct in6_addr {
+ uint8_t s6_addr[16];
+};
+#endif /* !HAVE_STRUCT_IN6_ADDR */
+
+#ifndef HAVE_STRUCT_SOCKADDR_IN6
+struct sockaddr_in6 {
+ unsigned short sin6_family;
+ uint16_t sin6_port;
+ uint32_t sin6_flowinfo;
+ struct in6_addr sin6_addr;
+};
+#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */
+
+#ifndef AF_INET6
+/* Define it to something that should never appear */
+#define AF_INET6 AF_MAX
+#endif
+
+/*
+ * Next, RFC2553 name / address resolution API
+ */
+
+#ifndef NI_NUMERICHOST
+# define NI_NUMERICHOST (1)
+#endif
+#ifndef NI_NAMEREQD
+# define NI_NAMEREQD (1<<1)
+#endif
+#ifndef NI_NUMERICSERV
+# define NI_NUMERICSERV (1<<2)
+#endif
+
+#ifndef AI_PASSIVE
+# define AI_PASSIVE (1)
+#endif
+#ifndef AI_CANONNAME
+# define AI_CANONNAME (1<<1)
+#endif
+#ifndef AI_NUMERICHOST
+# define AI_NUMERICHOST (1<<2)
+#endif
+
+#ifndef NI_MAXSERV
+# define NI_MAXSERV 32
+#endif /* !NI_MAXSERV */
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
+#endif /* !NI_MAXHOST */
+
+#ifndef INT_MAX
+#define INT_MAX 0xffffffff
+#endif
+
+#ifndef EAI_NODATA
+# define EAI_NODATA (INT_MAX - 1)
+#endif
+#ifndef EAI_MEMORY
+# define EAI_MEMORY (INT_MAX - 2)
+#endif
+#ifndef EAI_NONAME
+# define EAI_NONAME (INT_MAX - 3)
+#endif
+#ifndef EAI_SYSTEM
+# define EAI_SYSTEM (INT_MAX - 4)
+#endif
+
+#ifndef HAVE_STRUCT_ADDRINFO
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+#endif /* !HAVE_STRUCT_ADDRINFO */
+
+#ifndef HAVE_GETADDRINFO
+#ifdef getaddrinfo
+# undef getaddrinfo
+#endif
+#define getaddrinfo(a,b,c,d) (ssh_getaddrinfo(a,b,c,d))
+int getaddrinfo(const char *, const char *,
+ const struct addrinfo *, struct addrinfo **);
+#endif /* !HAVE_GETADDRINFO */
+
+#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO)
+#define gai_strerror(a) (ssh_gai_strerror(a))
+char *gai_strerror(int);
+#endif /* !HAVE_GAI_STRERROR */
+
+#ifndef HAVE_FREEADDRINFO
+#define freeaddrinfo(a) (ssh_freeaddrinfo(a))
+void freeaddrinfo(struct addrinfo *);
+#endif /* !HAVE_FREEADDRINFO */
+
+#ifndef HAVE_GETNAMEINFO
+#define getnameinfo(a,b,c,d,e,f,g) (ssh_getnameinfo(a,b,c,d,e,f,g))
+int getnameinfo(const struct sockaddr *, size_t, char *, size_t,
+ char *, size_t, int);
+#endif /* !HAVE_GETNAMEINFO */
+
+#endif /* !_FAKE_RFC2553_H */
+
diff --git a/examples/ldns-chaos.1 b/examples/ldns-chaos.1
new file mode 100644
index 000000000000..e9b7bf46dc95
--- /dev/null
+++ b/examples/ldns-chaos.1
@@ -0,0 +1,26 @@
+.TH ldns-chaos 1 "27 Apr 2005"
+.SH NAME
+ldns-chaos \- give some information about a nameserver
+.SH SYNOPSIS
+.B ldns-chaos
+.IR NAMESERVER
+
+.SH DESCRIPTION
+\fBldns-chaos\fR retrieves all the addresses of the nameserver and then queries
+each address for its \fIversion.bind\fR and \fIhostname.bind\fR.
+.PP
+\fBldns-chaos\fR is a bit more complex than \fBldns-mx\fR.
+
+.SH OPTIONS
+\fBldns-chaos\fR has no options.
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-chaos.c b/examples/ldns-chaos.c
new file mode 100644
index 000000000000..a1e1b796bfb0
--- /dev/null
+++ b/examples/ldns-chaos.c
@@ -0,0 +1,125 @@
+/*
+ * chaos is a small programs that prints some information
+ * about a nameserver
+ *
+ * (c) NLnet Labs, 2005 - 2008
+ *
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+
+#include <ldns/ldns.h>
+
+static int
+usage(FILE *fp, char *prog) {
+ fprintf(fp, "%s server\n", prog);
+ fprintf(fp, " print out some information about server\n");
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ ldns_resolver *res;
+ ldns_rdf *name;
+ ldns_rdf *version, *id;
+ ldns_pkt *p;
+ ldns_rr_list *addr;
+ ldns_rr_list *info;
+ ldns_status s;
+ ldns_rdf *pop;
+ size_t i;
+
+ if (argc != 2) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ } else {
+ /* create a rdf from the command line arg */
+ name = ldns_dname_new_frm_str(argv[1]);
+ if (!name) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* create rdf for what we are going to ask */
+ version = ldns_dname_new_frm_str("version.bind");
+ id = ldns_dname_new_frm_str("hostname.bind");
+
+ /* create a new resolver from /etc/resolv.conf */
+ s = ldns_resolver_new_frm_file(&res, NULL);
+ if (s != LDNS_STATUS_OK) {
+ ldns_rdf_deep_free(name);
+ exit(EXIT_FAILURE);
+ }
+ ldns_resolver_set_retry(res, 1); /* don't want to wait too long */
+
+ /* use the resolver to send it a query for the a/aaaa of name */
+ addr = ldns_get_rr_list_addr_by_name(res, name, LDNS_RR_CLASS_IN, LDNS_RD);
+ if (!addr) {
+ fprintf(stderr, " *** could not get an address for %s\n", argv[1]);
+ ldns_rdf_deep_free(name);
+ ldns_resolver_deep_free(res);
+ exit(EXIT_FAILURE);
+ }
+
+ /* remove current list of nameservers from resolver */
+ while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }
+
+
+ /* can be multihomed */
+ for(i = 0; i < ldns_rr_list_rr_count(addr); i++) {
+ if (i > 0) {
+ fprintf(stdout, "\n");
+ }
+
+ if (ldns_resolver_push_nameserver_rr(res,
+ ldns_rr_list_rr(addr, i)) != LDNS_STATUS_OK) {
+ printf("Error adding nameserver to resolver\n");
+ }
+
+ ldns_rr_print(stdout, ldns_rr_list_rr(addr, i));
+ fprintf(stdout, "\n");
+
+ p = ldns_resolver_query(res, version, LDNS_RR_TYPE_TXT,
+ LDNS_RR_CLASS_CH, LDNS_RD);
+ if (p) {
+ ldns_pkt_print(stdout, p);
+ info = ldns_pkt_rr_list_by_type(p,
+ LDNS_RR_TYPE_TXT, LDNS_SECTION_ANSWER);
+
+ if (info) {
+ ldns_rr_list_print(stdout, info);
+ ldns_rr_list_deep_free(info);
+ } else {
+ printf(" *** version retrieval failed\n");
+ }
+ ldns_pkt_free(p);
+ } else {
+ printf(" *** query failed\n");
+ }
+
+ p = ldns_resolver_query(res, id, LDNS_RR_TYPE_TXT,
+ LDNS_RR_CLASS_CH, LDNS_RD);
+ if (p) {
+ info = ldns_pkt_rr_list_by_type(p,
+ LDNS_RR_TYPE_TXT, LDNS_SECTION_ANSWER);
+ if (info) {
+ ldns_rr_list_print(stdout, info);
+ ldns_rr_list_deep_free(info);
+ } else {
+ printf(" *** id retrieval failed\n");
+ }
+ ldns_pkt_free(p);
+ } else {
+ printf(" *** query failed for\n");
+ }
+ ldns_rdf_deep_free(ldns_resolver_pop_nameserver(res));
+
+ }
+
+ ldns_rdf_deep_free(name);
+ ldns_resolver_deep_free(res);
+ exit(EXIT_SUCCESS);
+}
diff --git a/examples/ldns-compare-zones.1 b/examples/ldns-compare-zones.1
new file mode 100644
index 000000000000..facccd874562
--- /dev/null
+++ b/examples/ldns-compare-zones.1
@@ -0,0 +1,57 @@
+.TH ldns-compare-zones 1 "17 Oct 2007"
+.SH NAME
+ldns-compare-zones \- read and compare two zonefiles and print differences
+.SH SYNOPSIS
+.B ldns-compare-zones
+.IR [-c]
+.IR [-i]
+.IR [-d]
+.IR [-z]
+.IR [-s]
+.IR ZONEFILE1
+.IR ZONEFILE2
+.SH DESCRIPTION
+\fBldns-compare-zones\fR reads two DNS zone files and prints number of differences.
+.nf
+Output is formated to:
+ +NUM_INS -NUM_DEL ~NUM_CHG
+
+.fi
+The major comparison is based on the owner name. If an owner name is present in zonefile 1, but not in zonefile 2, the resource records with this owner name are considered deleted, and counted as NUM_DEL. If an owner name is present in zonefile 2, but not in zonefile 1, the resource records with this owner name are considered inserted, and counted as NUM_INS. If an owner name is present in both, but there is a difference in the amount or content of the records, these are considered changed, and counted as NUM_CHG.
+.SH OPTIONS
+.TP
+\fB-c\fR
+Print resource records whose owner names are in both zone files, but with different resource records. (a.k.a. changed)
+.TP
+\fB-i\fR
+Print resource records whose owner names are present only in ZONEFILE2 (a.k.a. inserted)
+.TP
+\fB-d\fR
+Print resource records whose owner names are present only in ZONEFILE1 (a.k.a. deleted)
+.TP
+\fB-a\fR
+Print all changes. Specifying this option is the same as specifying -c -i
+amd -d.
+.TP
+\fB-z\fR
+Suppress zone sorting; this option is not recommended; it can cause records
+to be incorrectly marked as changed, depending of the nature of the changes.
+.TP
+\fB-s\fR
+Do not exclude the SOA record from the comparison. The SOA record may
+then show up as changed due to a new serial number. Off by default since
+you may be interested to know if (other zone apex elements) have changed.
+.TP
+\fB-h\fR
+Show usage and exit
+.TP
+\fB-v\fR
+Show the version and exit
+.SH AUTHOR
+Written by Ondřej Surý <ondrej@sury.org> for CZ.NIC, z.s.p.o. (czech domain registry)
+.SH REPORTING BUGS
+Report bugs to <ondrej@sury.org>.
+.SH COPYRIGHT
+Copyright (C) 2005 CZ.NIC, z.s.p.o.. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-compare-zones.c b/examples/ldns-compare-zones.c
new file mode 100644
index 000000000000..663b744acc57
--- /dev/null
+++ b/examples/ldns-compare-zones.c
@@ -0,0 +1,283 @@
+/*
+ * ldns-compare-zones compares two zone files
+ *
+ * Written by Ondrej Sury in 2007
+ *
+ * Modified a bit by NLnet Labs.
+ *
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include <ldns/ldns.h>
+
+#include <errno.h>
+
+#define OP_INS '+'
+#define OP_DEL '-'
+#define OP_CHG '~'
+
+static void
+usage(char *prog)
+{
+ printf("Usage: %s [-v] [-i] [-d] [-c] [-s] <zonefile1> <zonefile2>\n",
+ prog);
+ printf(" -i - print inserted\n");
+ printf(" -d - print deleted\n");
+ printf(" -c - print changed\n");
+ printf(" -a - print all differences (-i -d -c)\n");
+ printf(" -s - do not exclude SOA record from comparison\n");
+ printf(" -z - do not sort zones\n");
+}
+
+int
+main(int argc, char **argv)
+{
+ char *fn1, *fn2;
+ FILE *fp1, *fp2;
+ ldns_zone *z1, *z2;
+ ldns_status s;
+ size_t i , j;
+ ldns_rr_list *rrl1, *rrl2;
+ int rr_cmp, rr_chg = 0;
+ ldns_rr *rr1 = NULL, *rr2 = NULL, *rrx = NULL;
+ int line_nr1 = 0, line_nr2 = 0;
+ size_t rrc1 , rrc2;
+ size_t num_ins = 0, num_del = 0, num_chg = 0;
+ int c;
+ bool opt_deleted = false, opt_inserted = false, opt_changed = false;
+ bool sort = true, inc_soa = false;
+ char op = 0;
+
+ while ((c = getopt(argc, argv, "ahvdicsz")) != -1) {
+ switch (c) {
+ case 'h':
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'v':
+ printf("%s version %s (ldns version %s)\n",
+ argv[0],
+ LDNS_VERSION,
+ ldns_version());
+ exit(EXIT_SUCCESS);
+ break;
+ case 's':
+ inc_soa = true;
+ break;
+ case 'z':
+ sort = false;
+ break;
+ case 'd':
+ opt_deleted = true;
+ break;
+ case 'i':
+ opt_inserted = true;
+ break;
+ case 'c':
+ opt_changed = true;
+ break;
+ case 'a':
+ opt_deleted = true;
+ opt_inserted = true;
+ opt_changed = true;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2) {
+ argc -= optind;
+ argv -= optind;
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ fn1 = argv[0];
+ fp1 = fopen(fn1, "r");
+ if (!fp1) {
+ fprintf(stderr, "Unable to open %s: %s\n", fn1, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ /* Read first zone */
+ s = ldns_zone_new_frm_fp_l(&z1, fp1, NULL, 0,
+ LDNS_RR_CLASS_IN, &line_nr1);
+ if (s != LDNS_STATUS_OK) {
+ fclose(fp1);
+ fprintf(stderr, "%s: %s at %d\n",
+ fn1,
+ ldns_get_errorstr_by_id(s),
+ line_nr1);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fp1);
+
+ fn2 = argv[1];
+ fp2 = fopen(fn2, "r");
+ if (!fp2) {
+ fprintf(stderr, "Unable to open %s: %s\n", fn2, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ /* Read second zone */
+ s = ldns_zone_new_frm_fp_l(&z2, fp2, NULL, 0,
+ LDNS_RR_CLASS_IN, &line_nr2);
+ if (s != LDNS_STATUS_OK) {
+ ldns_zone_deep_free(z1);
+ fclose(fp2);
+ fprintf(stderr, "%s: %s at %d\n",
+ fn2,
+ ldns_get_errorstr_by_id(s),
+ line_nr2);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fp2);
+
+ rrl1 = ldns_zone_rrs(z1);
+ rrc1 = ldns_rr_list_rr_count(rrl1);
+
+ rrl2 = ldns_zone_rrs(z2);
+ rrc2 = ldns_rr_list_rr_count(rrl2);
+
+ if (sort) {
+ /* canonicalize zone 1 */
+ ldns_rr2canonical(ldns_zone_soa(z1));
+ for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z1)); i++) {
+ ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z1), i));
+ }
+ /* sort zone 1 */
+ ldns_zone_sort(z1);
+ /* canonicalize zone 2 */
+ ldns_rr2canonical(ldns_zone_soa(z2));
+ for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z2)); i++) {
+ ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z2), i));
+ }
+ /* sort zone 2 */
+ ldns_zone_sort(z2);
+ }
+
+ if(inc_soa) {
+ ldns_rr_list* wsoa = ldns_rr_list_new();
+ ldns_rr_list_push_rr(wsoa, ldns_zone_soa(z1));
+ ldns_rr_list_cat(wsoa, rrl1);
+ rrl1 = wsoa;
+ rrc1 = ldns_rr_list_rr_count(rrl1);
+ wsoa = ldns_rr_list_new();
+ ldns_rr_list_push_rr(wsoa, ldns_zone_soa(z2));
+ ldns_rr_list_cat(wsoa, rrl2);
+ rrl2 = wsoa;
+ rrc2 = ldns_rr_list_rr_count(rrl2);
+ if(sort) {
+ ldns_rr_list_sort(rrl1);
+ ldns_rr_list_sort(rrl2);
+ }
+ }
+
+ /*
+ * Walk through both zones. The previously seen resource record is
+ * kept (in the variable rrx) so that we can recognize when we are
+ * handling a new owner name. If the owner name changes, we have to
+ * set the operator again.
+ */
+ for (i = 0, j = 0; i < rrc1 || j < rrc2;) {
+ rr_cmp = 0;
+ if (i < rrc1 && j < rrc2) {
+ rr1 = ldns_rr_list_rr(rrl1, i);
+ rr2 = ldns_rr_list_rr(rrl2, j);
+ rr_cmp = ldns_rr_compare(rr1, rr2);
+
+ /* Completely skip if the rrs are equal */
+ if (rr_cmp == 0) {
+ i++;
+ j++;
+ continue;
+ }
+ rr_chg = ldns_dname_compare(ldns_rr_owner(rr1),
+ ldns_rr_owner(rr2));
+ } else if (i >= rrc1) {
+ /* we have reached the end of zone 1, so the current record
+ * from zone 2 automatically sorts higher
+ */
+ rr1 = NULL;
+ rr2 = ldns_rr_list_rr(rrl2, j);
+ rr_chg = rr_cmp = 1;
+ } else if (j >= rrc2) {
+ /* we have reached the end of zone 2, so the current record
+ * from zone 1 automatically sorts lower
+ */
+ rr1 = ldns_rr_list_rr(rrl1, i);
+ rr2 = NULL;
+ rr_chg = rr_cmp = -1;
+ }
+ if (rr_cmp < 0) {
+ i++;
+ if ((rrx != NULL) && (ldns_dname_compare(ldns_rr_owner(rr1),
+ ldns_rr_owner(rrx)
+ ) != 0)) {
+ /* The owner name is different, forget previous rr */
+ rrx = NULL;
+ }
+ if (rrx == NULL) {
+ if (rr_chg == 0) {
+ num_chg++;
+ op = OP_CHG;
+ } else {
+ num_del++;
+ op = OP_DEL;
+ }
+ rrx = rr1;
+ }
+ if (((op == OP_DEL) && opt_deleted) ||
+ ((op == OP_CHG) && opt_changed)) {
+ printf("%c-", op);
+ ldns_rr_print(stdout, rr1);
+ }
+ } else if (rr_cmp > 0) {
+ j++;
+ if ((rrx != NULL) && (ldns_dname_compare(ldns_rr_owner(rr2),
+ ldns_rr_owner(rrx)
+ ) != 0)) {
+ rrx = NULL;
+ }
+ if (rrx == NULL) {
+ if (rr_chg == 0) {
+ num_chg++;
+ op = OP_CHG;
+ } else {
+ num_ins++;
+ op = OP_INS;
+ }
+ /* remember this rr for it's name in the next iteration */
+ rrx = rr2;
+ }
+ if (((op == OP_INS) && opt_inserted) ||
+ ((op == OP_CHG) && opt_changed)) {
+ printf("%c+", op);
+ ldns_rr_print(stdout, rr2);
+ }
+ }
+ }
+
+ printf("\t%c%u\t%c%u\t%c%u\n",
+ OP_INS,
+ (unsigned int) num_ins,
+ OP_DEL,
+ (unsigned int) num_del,
+ OP_CHG,
+ (unsigned int) num_chg);
+
+ /* Free resources */
+ if(inc_soa) {
+ ldns_rr_list_free(rrl1);
+ ldns_rr_list_free(rrl2);
+ }
+ ldns_zone_deep_free(z2);
+ ldns_zone_deep_free(z1);
+
+ return 0;
+}
diff --git a/examples/ldns-dpa.1 b/examples/ldns-dpa.1
new file mode 100644
index 000000000000..0b433df66179
--- /dev/null
+++ b/examples/ldns-dpa.1
@@ -0,0 +1,151 @@
+.TH dpa 1 "1 Nov 2005"
+.SH NAME
+dpa \- DNS Packet Analyzer. Analyze DNS packets in ip trace files
+.SH SYNOPSIS
+.B dpa
+[
+.IR OPTION
+]
+.IR TRACEFILE
+
+.SH DESCRIPTION
+\fBdpa\fR is used to analyze dns packets in trace files. It has 3 main options: count, filter, and count uniques (i.e. count all different occurences).
+
+.SH OPTIONS
+.TP
+\fB-c\fR \fIexpressionlist\fR
+Count occurrences of matching expressions
+
+.TP
+\fB-f\fR \fIexpression\fR
+Filter: only process packets that match the expression
+
+.TP
+\fB-h\fR
+Show usage
+
+.TP
+\fB-p\fR
+Show the total number of correct DNS packets, and percentage of -u and
+-c values (of the total of matching on the -f filter. if no filter is
+given, percentages are on all correct dns packets)
+
+.TP
+\fB-of\fR \fIfile\fR
+Write all packets that match the -f flag to file, as pcap data.
+
+.TP
+\fB-ofh\fR \fIfile\fR
+Write all packets that match the -f flag to file, in hexadecimal format,
+readable by drill.
+
+.TP
+\fB-s\fR
+Show possible match names
+
+.TP
+\fB-s\fR \fImatchname\fR
+show possible match operators and values for name
+
+.TP
+\fB-sf\fR
+Only evaluate packets (in representation format) that match the -f filter.
+If no -f was given, evaluate all correct dns packets.
+
+.TP
+\fB-u\fR \fImatchnamelist\fR
+Count every occurence of every value of the matchname (for instance, count all packetsizes, see EXAMPLES in ldns-dpa(1) ).
+
+.TP
+\fB-ua\fR
+For every matchname in -u, show the average value of all matches. Behaviour for match types that do not have an integer value is undefined.
+
+.TP
+\fB-uac\fR
+For every matchname in -u, show the average number of times this value was encountered.
+
+.TP
+\fB-um\fR \fInumber\fR
+Only show the results from -u for values that occurred more than <number> times.
+
+.TP
+\fB-v\fR \fIlevel\fR
+Set verbosity to level (1-5, 5 being the highest). Mostly used for debugging.
+
+.TP
+\fB-notip\fR \fIfile\fR
+Write packets that were not recognized as IP packets to file (as pcap data).
+
+.TP
+\fB-baddns\fR \fIfile\fR
+Write dns packets that were too mangled to parse to file (as pcap data).
+
+.TP
+\fB-version\fR
+Show version and exit
+
+.SH LIST AND MATCHES
+
+A <matchnamelist> is a comma separated list of match names (use -s to see possible match names).
+A <expressionlist> is a comma separated list of expressions.
+
+An expression has the following form:
+<expr>: (<expr>)
+ <expr> | <expr>
+ <expr> & <expr>
+ <match>
+
+<match>: <matchname> <operator> <value>
+
+<operator>:
+ = equal to <value>
+ != not equal to <value>
+ > greater than <value>
+ < lesser than <value>
+ >= greater than or equal to <value>
+ <= lesser than or equal to <value>
+ ~= contains <value>
+
+See the -s option for possible matchnames, operators and values.
+
+.SH EXAMPLES
+
+.TP
+ldns-dpa -u packetsize -p test.tr
+Count all different packetsizes in test.tr and show the precentages.
+
+.TP
+ldns-dpa -f "edns=1&qr=0" -of edns.tr test.tr
+Filter out all edns enable queries in test.tr and put them in edns.tr
+
+.TP
+ldns-dpa -f edns=1 -c tc=1 -u rcode test.tr
+For all edns packets, count the number of truncated packets and all their rcodes in test.tr.
+
+.TP
+ldns-dpa -c tc=1,qr=0,qr=1,opcode=QUERY test.tr
+For all packets, count the number of truncated packets, the number of packets with qr=0, the number of packets with qr=1 and the number of queries in test.tr.
+
+.TP
+ldns-dpa -u packetsize -ua test.tr
+Show all packet sizes and the average packet size per packet.
+
+.TP
+ldns-dpa -u srcaddress -uac test.tr
+Show all packet source addresses and the average number of packets sent from this address.
+
+.TP
+sudo tcpdump -i eth0 -s 0 -U -w - port 53 | ldns-dpa -f qr=0 -sf
+Print all query packets seen on the specified interface.
+
+
+.SH AUTHOR
+Written by Jelte Jansen for NLnetLabs.
+
+.SH REPORTING BUGS
+Report bugs to <jelte@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-dpa.c b/examples/ldns-dpa.c
new file mode 100644
index 000000000000..c5717b245e9e
--- /dev/null
+++ b/examples/ldns-dpa.c
@@ -0,0 +1,2838 @@
+/*
+ * ldns-dpa inspects the (udp) DNS packets found in a pcap file
+ * and provides statistics about them
+ *
+ * (C) NLnet Labs 2006 - 2008
+ *
+ * See the file LICENSE for the license
+ */
+#include "config.h"
+
+#include <ldns/ldns.h>
+
+#ifdef HAVE_PCAP_H
+#ifdef HAVE_LIBPCAP
+#include "ldns-dpa.h"
+
+#ifdef HAVE_NETINET_IP6_H
+#include <netinet/ip6.h>
+#endif
+#include <errno.h>
+
+#ifndef IP_OFFMASK
+#define IP_OFFMASK 0x1fff
+#endif
+
+int verbosity = 1;
+
+#define ETHER_HEADER_LENGTH 14
+#define UDP_HEADER_LENGTH 8
+#define IP6_HEADER_LENGTH 40
+
+/* some systems don't have this? */
+#ifndef ETHERTYPE_IPV6
+#define ETHERTYPE_IPV6 0x86dd
+#endif
+
+#define MAX_MATCHES 20
+#define MAX_OPERATORS 7
+
+
+/* global options */
+bool show_filter_matches = false;
+size_t total_nr_of_dns_packets = 0;
+size_t total_nr_of_filtered_packets = 0;
+size_t not_ip_packets = 0;
+size_t bad_dns_packets = 0;
+size_t arp_packets = 0;
+size_t udp_packets = 0;
+size_t tcp_packets = 0;
+size_t fragmented_packets = 0;
+size_t lost_packet_fragments = 0;
+FILE *hexdumpfile = NULL;
+pcap_dumper_t *dumper = NULL;
+pcap_dumper_t *not_ip_dump = NULL;
+pcap_dumper_t *bad_dns_dump = NULL;
+
+
+struct
+fragment_part {
+ uint16_t ip_id;
+ uint8_t data[65536];
+ size_t cur_len;
+};
+
+struct fragment_part *fragment_p;
+
+/* To add a match,
+ * - add it to the enum
+ * - add it to the table_matches const
+ * - add a handler to value_matches
+ * - tell in get_string_value() where in the packet the data lies
+ * - add to parser?
+ * - add to show_match_ function
+ */
+enum enum_match_ids {
+ MATCH_ID,
+ MATCH_OPCODE,
+ MATCH_RCODE,
+ MATCH_PACKETSIZE,
+ MATCH_QR,
+ MATCH_TC,
+ MATCH_AD,
+ MATCH_CD,
+ MATCH_RD,
+ MATCH_EDNS,
+ MATCH_EDNS_PACKETSIZE,
+ MATCH_DO,
+ MATCH_QUESTION_SIZE,
+ MATCH_ANSWER_SIZE,
+ MATCH_AUTHORITY_SIZE,
+ MATCH_ADDITIONAL_SIZE,
+ MATCH_SRC_ADDRESS,
+ MATCH_DST_ADDRESS,
+ MATCH_TIMESTAMP,
+ MATCH_QUERY,
+ MATCH_QTYPE,
+ MATCH_QNAME,
+ MATCH_ANSWER,
+ MATCH_AUTHORITY,
+ MATCH_ADDITIONAL,
+ MATCH_LAST
+};
+typedef enum enum_match_ids match_id;
+
+enum enum_counter_types {
+ TYPE_INT,
+ TYPE_BOOL,
+ TYPE_OPCODE,
+ TYPE_RCODE,
+ TYPE_STRING,
+ TYPE_TIMESTAMP,
+ TYPE_ADDRESS,
+ TYPE_RR,
+ TYPE_RR_TYPE,
+ TYPE_LAST
+};
+typedef enum enum_counter_types counter_type;
+
+const ldns_lookup_table lt_types[] = {
+ {TYPE_INT, "int" },
+ {TYPE_BOOL, "bool" },
+ {TYPE_OPCODE, "opcode" },
+ {TYPE_RCODE, "rcode" },
+ {TYPE_STRING, "string" },
+ {TYPE_TIMESTAMP, "timestamp" },
+ {TYPE_ADDRESS, "address" },
+ {TYPE_RR, "rr" },
+ { 0, NULL }
+};
+
+enum enum_type_operators {
+ OP_EQUAL,
+ OP_NOTEQUAL,
+ OP_GREATER,
+ OP_LESSER,
+ OP_GREATEREQUAL,
+ OP_LESSEREQUAL,
+ OP_CONTAINS,
+ OP_LAST
+};
+typedef enum enum_type_operators type_operator;
+
+const ldns_lookup_table lt_operators[] = {
+ { OP_EQUAL, "=" },
+ { OP_NOTEQUAL, "!=" },
+ { OP_GREATER, ">" },
+ { OP_LESSER, "<" },
+ { OP_GREATEREQUAL, ">=" },
+ { OP_LESSEREQUAL, "<=" },
+ { OP_CONTAINS, "~=" },
+ { 0, NULL }
+};
+
+static const char *get_op_str(type_operator op) {
+ const ldns_lookup_table *lt;
+ lt = ldns_lookup_by_id((ldns_lookup_table *) lt_operators, op);
+ if (lt) {
+ return lt->name;
+ } else {
+ fprintf(stderr, "Unknown operator id: %u\n", op);
+ exit(1);
+ }
+}
+
+static type_operator
+get_op_id(char *op_str)
+{
+ const ldns_lookup_table *lt;
+ lt = ldns_lookup_by_name((ldns_lookup_table *) lt_operators, op_str);
+ if (lt) {
+ return (type_operator) lt->id;
+ } else {
+ fprintf(stderr, "Unknown operator: %s\n", op_str);
+ exit(1);
+ }
+}
+
+struct struct_type_operators {
+ counter_type type;
+ size_t operator_count;
+ type_operator operators[10];
+};
+typedef struct struct_type_operators type_operators;
+
+const type_operators const_type_operators[] = {
+ { TYPE_INT, 6, { OP_EQUAL, OP_NOTEQUAL, OP_GREATER, OP_LESSER, OP_GREATEREQUAL, OP_LESSEREQUAL, 0, 0, 0, 0 } },
+ { TYPE_BOOL, 2, { OP_EQUAL, OP_NOTEQUAL, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { TYPE_OPCODE, 2, { OP_EQUAL, OP_NOTEQUAL, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { TYPE_RCODE, 2, { OP_EQUAL, OP_NOTEQUAL, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { TYPE_STRING, 3, { OP_EQUAL, OP_NOTEQUAL, OP_CONTAINS, 0, 0, 0, 0, 0, 0, 0} },
+ { TYPE_TIMESTAMP, 6, { OP_EQUAL, OP_NOTEQUAL, OP_GREATER, OP_LESSER, OP_GREATEREQUAL, OP_LESSEREQUAL, 0, 0, 0, 0 } },
+ { TYPE_ADDRESS, 3, { OP_EQUAL, OP_NOTEQUAL, OP_CONTAINS, 0, 0, 0, 0, 0, 0, 0} },
+ { TYPE_RR, 3, { OP_EQUAL, OP_NOTEQUAL, OP_CONTAINS, 0, 0, 0, 0, 0, 0, 0} },
+ { TYPE_RR_TYPE, 6, { OP_EQUAL, OP_NOTEQUAL, OP_GREATER, OP_LESSER, OP_GREATEREQUAL, OP_LESSEREQUAL, 0, 0, 0, 0 } },
+ { 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
+};
+
+const type_operators *
+get_type_operators(counter_type type) {
+ const type_operators *to = const_type_operators;
+ while (to) {
+ if (to->type == type) {
+ return to;
+ }
+ to++;
+ }
+ return NULL;
+}
+
+struct struct_match_table {
+ match_id id;
+ const char *name;
+ const char *description;
+ const counter_type type;
+};
+typedef struct struct_match_table match_table;
+
+/* order of entries has been changed after gprof analysis, and reasoning
+ * about the uses of -u arguments
+ */
+const match_table matches[] = {
+ { MATCH_QUERY, "query", "String representation of the query RR", TYPE_RR },
+ { MATCH_QTYPE, "qtype", "RR Type of the question RR, if present", TYPE_RR_TYPE },
+ { MATCH_QNAME, "qname", "Owner name of the question RR, if present", TYPE_STRING },
+ { MATCH_SRC_ADDRESS, "srcaddress", "address the packet was sent from", TYPE_ADDRESS },
+ { MATCH_TIMESTAMP, "timestamp", "time the packet was sent", TYPE_TIMESTAMP },
+ { MATCH_DST_ADDRESS, "dstaddress", "address the packet was sent to", TYPE_ADDRESS },
+ { MATCH_EDNS_PACKETSIZE, "edns-packetsize", "packets size specified in edns rr", TYPE_INT },
+ { MATCH_ID, "id", "id of the packet", TYPE_INT },
+ { MATCH_OPCODE, "opcode", "opcode of packet (rfc1035)", TYPE_OPCODE },
+ { MATCH_RCODE, "rcode", "response code of packet", TYPE_RCODE },
+ { MATCH_PACKETSIZE, "packetsize", "size of packet in bytes", TYPE_INT },
+ { MATCH_QR, "qr", "value of qr bit", TYPE_BOOL },
+ { MATCH_TC, "tc", "value of tc bit", TYPE_BOOL },
+ { MATCH_AD, "ad", "value of ad bit", TYPE_BOOL },
+ { MATCH_CD, "cd", "value of cd bit", TYPE_BOOL },
+ { MATCH_RD, "rd", "value of rd bit", TYPE_BOOL },
+ { MATCH_EDNS, "edns", "existence of edns rr", TYPE_BOOL },
+ { MATCH_DO, "do", "value of do bit", TYPE_BOOL },
+ { MATCH_QUESTION_SIZE, "questionsize", "number of rrs in the question section", TYPE_INT },
+ { MATCH_ANSWER_SIZE, "answersize", "number of rrs in the answer section", TYPE_INT },
+ { MATCH_AUTHORITY_SIZE, "authoritysize", "number of rrs in the authority section", TYPE_INT },
+ { MATCH_ADDITIONAL_SIZE, "additionalsize", "number of rrs in the additional section", TYPE_INT },
+ { MATCH_ANSWER, "answer", "String representation of the answer RRs", TYPE_RR },
+ { MATCH_AUTHORITY, "authority", "String representation of the authority RRs", TYPE_RR },
+ { MATCH_ADDITIONAL, "additional", "String representation of the additional RRs", TYPE_RR },
+ { 0, NULL , NULL, TYPE_INT}
+};
+
+enum enum_match_expression_operators {
+ MATCH_EXPR_OR,
+ MATCH_EXPR_AND,
+ MATCH_EXPR_LEAF
+};
+typedef enum enum_match_expression_operators match_expression_operator;
+
+struct struct_match_operation {
+ match_id id;
+ type_operator operator;
+ char *value;
+};
+typedef struct struct_match_operation match_operation;
+
+typedef struct struct_match_expression match_expression;
+struct struct_match_expression {
+ /* and or or, or leaf (in which case there are no subtrees, but only a match_table */
+ match_expression_operator op;
+ match_expression *left;
+ match_expression *right;
+ match_operation *match;
+ size_t count;
+};
+
+typedef struct struct_match_counters match_counters;
+struct struct_match_counters {
+/*
+ match_expression **counter;
+ size_t size;
+*/
+ match_expression *match;
+ match_counters *left;
+ match_counters *right;
+};
+
+match_table *
+get_match_by_name(char *name) {
+ match_table *mt = (match_table *) matches;
+ if (name) {
+ while (mt->name != NULL) {
+ if (strcasecmp(name, mt->name) == 0) {
+ return mt;
+ }
+ mt++;
+ }
+ }
+ return NULL;
+}
+
+static match_table *
+get_match_by_id(match_id id) {
+ match_table *mt = (match_table *) matches;
+
+ while (mt->name != NULL) {
+ if (mt->id == id) {
+ return mt;
+ }
+ mt++;
+ }
+ return NULL;
+}
+
+static const char *
+get_match_name_str(match_id id) {
+ match_table *mt = get_match_by_id(id);
+ if (mt) {
+ return mt->name;
+ } else {
+ fprintf(stderr, "Unknown match id: %u\n", id);
+ exit(1);
+ return "Unknown match id";
+ }
+}
+
+static void
+print_match_operation(FILE *output, match_operation *mc)
+{
+ match_table *mt = NULL;
+ ldns_lookup_table *lt;
+ struct timeval time;
+ time_t time_tt;
+ int value;
+ size_t pos;
+ char *tmp, *tmp2;
+
+ if (mc) {
+ mt = get_match_by_id(mc->id);
+
+ if (mt) {
+ fprintf(output, "%s %s ",mt->name, get_op_str(mc->operator));
+
+ switch (mt->type) {
+ case TYPE_INT:
+ case TYPE_STRING:
+ case TYPE_ADDRESS:
+ case TYPE_RR:
+ fprintf(output, "'%s'", mc->value);
+ break;
+ case TYPE_BOOL:
+ if (strncmp(mc->value, "1", 2) == 0) {
+ fprintf(output,"'true'");
+ } else {
+ fprintf(output,"'false'");
+ }
+ break;
+ case TYPE_OPCODE:
+ value = atoi(mc->value);
+ lt = ldns_lookup_by_id(ldns_opcodes, value);
+ if (lt) {
+ fprintf(output, "%s", lt->name);
+ } else {
+ fprintf(output, "%s", mc->value);
+ }
+ break;
+ case TYPE_RCODE:
+ value = atoi(mc->value);
+ lt = ldns_lookup_by_id(ldns_rcodes, value);
+ if (lt) {
+ fprintf(output, "%s", lt->name);
+ } else {
+ fprintf(output, "%s", mc->value);
+ }
+ break;
+ case TYPE_TIMESTAMP:
+#ifndef S_SPLINT_S
+ time.tv_sec = (long int) atol(mc->value);
+#endif
+ time_tt = (time_t)time.tv_sec;
+ tmp = ctime(&time_tt);
+ tmp2 = malloc(strlen(tmp) + 1);
+ for (pos = 0; pos < strlen(tmp); pos++) {
+ if (tmp[pos] == '\n') {
+ tmp2[pos] = '\0';
+ } else {
+ tmp2[pos] = tmp[pos];
+ }
+ }
+ tmp2[pos] = '\0';
+ fprintf(output, "%s", tmp2);
+ free(tmp2);
+ break;
+ default:
+ fprintf(output, "'%s'", mc->value);
+ }
+
+ } else {
+ fprintf(output, "%u %s '%s'", mc->id, get_op_str(mc->operator), mc->value);
+ }
+ } else {
+ fprintf(output, "(nil)");
+ }
+}
+
+static void
+print_match_expression(FILE *output, match_expression *expr)
+{
+ if (expr) {
+ switch (expr->op) {
+ case MATCH_EXPR_OR:
+ fprintf(output, "(");
+ print_match_expression(output, expr->left);
+ fprintf(output, " | ");
+ print_match_expression(output, expr->right);
+ fprintf(output, ")");
+ break;
+ case MATCH_EXPR_AND:
+ fprintf(output, "(");
+ print_match_expression(output, expr->left);
+ fprintf(output, " & ");
+ print_match_expression(output, expr->right);
+ fprintf(output, ")");
+ break;
+ case MATCH_EXPR_LEAF:
+ print_match_operation(output, expr->match);
+ break;
+ default:
+/*
+ fprintf(output, "ERROR PRINTING MATCH: unknown op: %u\n", expr->op);
+ exit(1);
+*/
+ fprintf(output, "(");
+if (expr->left) {
+ print_match_expression(output, expr->left);
+}
+ fprintf(output, " ? ");
+if (expr->right) {
+ print_match_expression(output, expr->right);
+}
+ fprintf(output, ") _");
+if (expr->match) {
+ print_match_operation(output, expr->match);
+}
+fprintf(output, "_");
+ }
+ } else {
+ printf("(nil)");
+ }
+}
+
+static void
+print_counters(FILE *output, match_counters *counters, bool show_percentages, size_t total, int count_minimum)
+{
+ double percentage;
+
+ if (!counters || !output) {
+ return;
+ }
+
+ if (counters->left) {
+ print_counters(output, counters->left, show_percentages, total, count_minimum);
+ }
+ if (counters->match) {
+ if (count_minimum < (int) counters->match->count) {
+ print_match_expression(output, counters->match);
+ printf(": %u", (unsigned int) counters->match->count);
+ if (show_percentages) {
+ percentage = (double) counters->match->count / (double) total * 100.0;
+ printf(" (%.2f%%)", percentage);
+ }
+ printf("\n");
+ }
+ }
+ if (counters->right) {
+ print_counters(output, counters->right, show_percentages, total, count_minimum);
+ }
+
+ return;
+}
+
+static void
+ldns_pkt2file_hex(FILE *fp, const ldns_pkt *pkt)
+{
+ uint8_t *wire;
+ size_t size, i;
+ ldns_status status;
+
+ status = ldns_pkt2wire(&wire, pkt, &size);
+
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Unable to convert packet: error code %u", status);
+ return;
+ }
+
+ fprintf(fp, "; 0");
+ for (i = 1; i < 20; i++) {
+ fprintf(fp, " %2u", (unsigned int) i);
+ }
+ fprintf(fp, "\n");
+ fprintf(fp, ";--");
+ for (i = 1; i < 20; i++) {
+ fprintf(fp, " --");
+ }
+ fprintf(fp, "\n");
+ for (i = 0; i < size; i++) {
+ if (i % 20 == 0 && i > 0) {
+ fprintf(fp, "\t; %4u-%4u\n", (unsigned int) i-19, (unsigned int) i);
+ }
+ fprintf(fp, " %02x", (unsigned int)wire[i]);
+ }
+ fprintf(fp, "\n\n");
+}
+
+/*
+ * Calculate the total for all match operations with the same id as this one
+ * (if they are 'under' this one in the tree, which should be the case in
+ * the unique counter tree
+ */
+static size_t
+calculate_total_value(match_counters *counters, match_operation *cur)
+{
+ size_t result = 0;
+
+ if (!counters) {
+ return 0;
+ }
+
+ if (counters->match->match->id == cur->id) {
+ result = (size_t) atol(counters->match->match->value) * counters->match->count;
+ }
+
+ if (counters->left) {
+ result += calculate_total_value(counters->left, cur);
+ }
+ if (counters->right) {
+ result += calculate_total_value(counters->right, cur);
+ }
+
+ return result;
+}
+
+static size_t
+calculate_total_count_matches(match_counters *counters, match_operation *cur)
+{
+ size_t result = 0;
+
+ if (!counters) {
+ return 0;
+ }
+
+ if (counters->match->match->id == cur->id) {
+ result = 1;
+ }
+
+ if (counters->left) {
+ /* In some cases, you don't want the number of actual
+ counted matches, for instance when calculating the
+ average number of queries per second. In this case
+ you want the number of seconds */
+ if (cur->id == MATCH_TIMESTAMP) {
+ result += (size_t) abs((int) (atol(counters->match->match->value) - atol(counters->left->match->match->value))) - 1;
+ }
+ result += calculate_total_count_matches(counters->left, cur);
+ }
+ if (counters->right) {
+ if (cur->id == MATCH_TIMESTAMP) {
+ result += (size_t) abs((int) (atol(counters->right->match->match->value) - atol(counters->match->match->value))) - 1;
+ }
+ result += calculate_total_count_matches(counters->right, cur);
+ }
+
+ return result;
+}
+
+/**
+ * Returns true if there is a previous match operation with the given type
+ * in the counters structure
+ */
+static bool
+has_previous_match(match_counters *counters, match_operation *cur)
+{
+ if (!counters) {
+ return false;
+ }
+
+ if (counters->left) {
+ if (counters->left->match->match->id == cur->id) {
+ return true;
+ } else if (has_previous_match(counters->left, cur)) {
+ return true;
+ } else if (counters->left->right) {
+ if (counters->left->right->match->match->id == cur->id) {
+ return true;
+ } else if (has_previous_match(counters->left->right, cur)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/**
+ * Returns true if there is a later match operation with the given type
+ * in the counters structure
+ */
+static bool
+has_next_match(match_counters *counters, match_operation *cur)
+{
+ if (!counters) {
+ return false;
+ }
+
+ if (counters->right) {
+ if (counters->right->match->match->id == cur->id) {
+ return true;
+ } else if (has_next_match(counters->right, cur)) {
+ return true;
+ } else if (counters->right->left) {
+ if (counters->right->left->match->match->id == cur->id) {
+ return true;
+ } else if (has_next_match(counters->right->left, cur)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/**
+ * Returns the first match with the same type at *cur in
+ * the counter list, or NULL if it is not found
+ */
+static match_expression *
+get_first_match_expression(match_counters *counters, match_operation *cur)
+{
+ if (!counters) {
+ return NULL;
+ }
+
+ if (has_previous_match(counters, cur)) {
+ return get_first_match_expression(counters->left, cur);
+ } else if (counters->match->match->id == cur->id) {
+ return counters->match;
+ } else if (counters->right) {
+ return get_first_match_expression(counters->right, cur);
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * Returns the second match expression with the same type at *cur in
+ * the counter list, or NULL if it is not found
+ */
+static match_expression *
+get_second_match_expression(match_counters *counters, match_operation *cur)
+{
+ if (!counters) {
+ return NULL;
+ }
+
+ if (has_previous_match(counters, cur)) {
+ if (has_previous_match(counters->left, cur)) {
+ return get_second_match_expression(counters->left, cur);
+ } else {
+ return counters->left->match;
+ }
+/*
+ } else if (counters->match->match->id == cur->id) {
+ return counters->match->match->value;
+*/ } else if (counters->right) {
+ return get_first_match_expression(counters->right, cur);
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * Returns the last match expression with the same type at *cur in
+ * the counter list, or NULL if it is not found
+ */
+static match_expression *
+get_last_match_expression(match_counters *counters, match_operation *cur)
+{
+ if (!counters) {
+ return NULL;
+ }
+
+ if (has_next_match(counters, cur)) {
+ return get_last_match_expression(counters->right, cur);
+ } else if (counters->match->match->id == cur->id) {
+ return counters->match;
+ } else if (counters->left) {
+ return get_last_match_expression(counters->left, cur);
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * Returns the last but one match expression with the same type at *cur in
+ * the counter list, or NULL if it is not found
+ */
+static match_expression *
+get_last_but_one_match_expression(match_counters *counters, match_operation *cur)
+{
+ if (!counters) {
+ return NULL;
+ }
+
+ if (has_next_match(counters, cur)) {
+ if (has_next_match(counters->right, cur)) {
+ return get_last_but_one_match_expression(counters->right, cur);
+ } else {
+ return counters->match;
+ }
+/*
+ } else if (counters->match->match->id == cur->id) {
+ return counters->match->match->value;
+*/ } else if (counters->left) {
+ return get_last_match_expression(counters->right, cur);
+ } else {
+ return NULL;
+ }
+}
+
+static size_t
+get_first_count(match_counters *counters, match_operation *cur)
+{
+ match_expression *o = get_first_match_expression(counters, cur);
+ if (o) {
+ return o->count;
+ } else {
+ return 0;
+ }
+}
+
+static size_t
+get_last_count(match_counters *counters, match_operation *cur)
+{
+ match_expression *o = get_last_match_expression(counters, cur);
+ if (o) {
+ return o->count;
+ } else {
+ return 0;
+ }
+}
+
+
+static size_t
+calculate_total_count(match_counters *counters, match_operation *cur)
+{
+ size_t result = 0;
+
+ if (!counters) {
+ return 0;
+ }
+
+ if (counters->match->match->id == cur->id) {
+ result = counters->match->count;
+ }
+
+ if (counters->left) {
+ result += calculate_total_count(counters->left, cur);
+ }
+ if (counters->right) {
+ result += calculate_total_count(counters->right, cur);
+ }
+
+ return result;
+}
+
+static void
+print_counter_averages(FILE *output, match_counters *counters, match_operation *cur)
+{
+ size_t total_value;
+ size_t total_count;
+ match_table *mt;
+
+ if (!counters || !output) {
+ return;
+ }
+
+ if (!cur) {
+ cur = counters->match->match;
+ mt = get_match_by_id(cur->id);
+ total_value = calculate_total_value(counters, cur);
+ total_count = calculate_total_count(counters, cur);
+ printf("Average for %s: (%u / %u) %.02f\n", mt->name, (unsigned int) total_value, (unsigned int) total_count, (float) total_value / (float) total_count);
+ if (counters->left) {
+ print_counter_averages(output, counters->left, cur);
+ }
+ if (counters->right) {
+ print_counter_averages(output, counters->right, cur);
+ }
+ } else {
+ if (counters->left) {
+ if (counters->left->match->match->id != cur->id) {
+ print_counter_averages(output, counters->left, NULL);
+ }
+ }
+ if (counters->right) {
+ if (counters->right->match->match->id != cur->id) {
+ print_counter_averages(output, counters->right, NULL);
+ }
+ }
+ }
+
+ return;
+}
+
+static void
+print_counter_average_count(FILE *output, match_counters *counters, match_operation *cur, bool remove_first_last)
+{
+ size_t total_matches;
+ size_t total_count;
+ match_table *mt;
+
+ if (!counters || !output) {
+ return;
+ }
+
+ if (!cur) {
+ cur = counters->match->match;
+ mt = get_match_by_id(cur->id);
+ total_matches = calculate_total_count_matches(counters, cur);
+ total_count = calculate_total_count(counters, cur);
+ /* Remove the first and last for instance for timestamp average counts (half seconds drag down the average) */
+ if (remove_first_last) {
+ total_count -= get_first_count(counters, cur);
+ total_count -= get_last_count(counters, cur);
+ printf("Removing first count from average: %u\n", (unsigned int) get_first_count(counters,cur));
+ printf("Removing last count from average: %u\n", (unsigned int) get_last_count(counters,cur));
+ /* in the case where we count the differences between match values too
+ * (like with timestamps) we need to subtract from the match count too
+ */
+ if (cur->id == MATCH_TIMESTAMP) {
+ if (get_first_match_expression(counters, cur) && get_second_match_expression(counters, cur)) {
+ total_matches -= atol(get_second_match_expression(counters, cur)->match->value) - atol(get_first_match_expression(counters, cur)->match->value);
+ }
+ if (get_last_match_expression(counters, cur) && get_last_but_one_match_expression(counters, cur)) {
+ total_matches -= atol(get_last_match_expression(counters, cur)->match->value) - atol(get_last_but_one_match_expression(counters, cur)->match->value);
+ }
+ } else {
+ total_matches -= 2;
+ }
+ }
+ printf("Average count for %s: (%u / %u) %.02f\n", mt->name, (unsigned int) total_count, (unsigned int) total_matches, (float) total_count / (float) total_matches);
+ if (counters->left) {
+ print_counter_averages(output, counters->left, cur);
+ }
+ if (counters->right) {
+ print_counter_averages(output, counters->right, cur);
+ }
+ } else {
+ if (counters->left) {
+ if (counters->left->match->match->id != cur->id) {
+ print_counter_averages(output, counters->left, NULL);
+ }
+ }
+ if (counters->right) {
+ if (counters->right->match->match->id != cur->id) {
+ print_counter_averages(output, counters->right, NULL);
+ }
+ }
+ }
+
+ return;
+}
+
+static bool
+match_int(type_operator operator,
+ char *value,
+ char *mvalue)
+{
+ int a, b;
+
+ if (!value || !mvalue) {
+ return false;
+ }
+
+ a = atoi(value);
+ b = atoi(mvalue);
+
+ switch (operator) {
+ case OP_EQUAL:
+ return a == b;
+ break;
+ case OP_NOTEQUAL:
+ return a != b;
+ break;
+ case OP_GREATER:
+ return a > b;
+ break;
+ case OP_LESSER:
+ return a < b;
+ break;
+ case OP_GREATEREQUAL:
+ return a >= b;
+ break;
+ case OP_LESSEREQUAL:
+ return a <= b;
+ break;
+ default:
+ fprintf(stderr, "Unknown operator: %u\n", operator);
+ exit(2);
+ }
+}
+
+static bool
+match_opcode(type_operator operator,
+ char *value,
+ char *mvalue)
+{
+ ldns_pkt_opcode a, b;
+ int i;
+ ldns_lookup_table *lt;
+
+ /* try parse name first, then parse as int */
+ lt = ldns_lookup_by_name(ldns_opcodes, value);
+ if (lt) {
+ a = lt->id;
+ } else {
+ i = atoi(value);
+ if (i >= 0 && !isdigit(value[0]) == 0) {
+ lt = ldns_lookup_by_id(ldns_opcodes, i);
+ if (lt) {
+ a = lt->id;
+ } else {
+ fprintf(stderr, "Unknown opcode: %s\n", value);
+ exit(1);
+ return false;
+ }
+ } else {
+ fprintf(stderr, "Unknown opcode: %s\n", value);
+ exit(1);
+ return false;
+ }
+ }
+
+ lt = ldns_lookup_by_name(ldns_opcodes, mvalue);
+ if (lt) {
+ b = lt->id;
+ } else {
+ i = atoi(mvalue);
+ if (i >= 0 && !isdigit(mvalue[0]) == 0) {
+ lt = ldns_lookup_by_id(ldns_opcodes, i);
+ if (lt) {
+ b = lt->id;
+ } else {
+ fprintf(stderr, "Unknown opcode: %s\n", mvalue);
+ exit(1);
+ return false;
+ }
+ } else {
+ fprintf(stderr, "Unknown opcode: %s\n", mvalue);
+ exit(1);
+ return false;
+ }
+ }
+
+ switch(operator) {
+ case OP_EQUAL:
+ return a == b;
+ break;
+ case OP_NOTEQUAL:
+ return a != b;
+ break;
+ default:
+ fprintf(stderr, "Error bad operator for opcode: %s\n", get_op_str(operator));
+ return false;
+ break;
+ }
+}
+
+static bool
+match_str(type_operator operator,
+ char *value,
+ char *mvalue)
+{
+ char *valuedup, *mvaluedup;
+ size_t i;
+ bool result;
+
+ if (operator == OP_CONTAINS) {
+ /* strcasestr is not C89
+ return strcasestr(value, mvalue) != 0;
+ */
+ valuedup = strdup(value);
+ mvaluedup = strdup(mvalue);
+ for (i = 0; i < strlen(valuedup); i++) {
+ valuedup[i] = tolower(valuedup[i]);
+ }
+ for (i = 0; i < strlen(mvaluedup); i++) {
+ mvaluedup[i] = tolower(mvaluedup[i]);
+ }
+ result = strstr(valuedup, mvaluedup) != 0;
+ free(valuedup);
+ free(mvaluedup);
+ return result;
+ } else if (operator == OP_EQUAL) {
+ return strcmp(value, mvalue) == 0;
+ } else {
+ return strcmp(value, mvalue) != 0;
+ }
+}
+
+static bool
+match_rr_type(type_operator operator,
+ char *value,
+ char *mvalue)
+{
+ ldns_rr_type a,b;
+
+ a = ldns_get_rr_type_by_name(value);
+ b = ldns_get_rr_type_by_name(mvalue);
+
+ switch (operator) {
+ case OP_EQUAL:
+ return a == b;
+ break;
+ case OP_NOTEQUAL:
+ return a != b;
+ break;
+ case OP_GREATER:
+ return a > b;
+ break;
+ case OP_LESSER:
+ return a < b;
+ break;
+ case OP_GREATEREQUAL:
+ return a >= b;
+ break;
+ case OP_LESSEREQUAL:
+ return a <= b;
+ break;
+ default:
+ fprintf(stderr, "Unknown operator: %u\n", operator);
+ exit(2);
+ }
+}
+
+static bool
+match_rcode(type_operator operator,
+ char *value,
+ char *mvalue)
+{
+ int a, b;
+ int i;
+ ldns_lookup_table *lt;
+
+ /* try parse name first, then parse as int */
+ lt = ldns_lookup_by_name(ldns_rcodes, value);
+ if (lt) {
+ a = lt->id;
+ } else {
+ i = atoi(value);
+ if (i >= 0 && !isdigit(value[0]) == 0) {
+ lt = ldns_lookup_by_id(ldns_rcodes, i);
+ if (lt) {
+ a = lt->id;
+ } else {
+ fprintf(stderr, "Unknown rcode: %s\n", value);
+ exit(1);
+ return false;
+ }
+ } else {
+ fprintf(stderr, "Unknown rcode: %s\n", value);
+ exit(1);
+ return false;
+ }
+ }
+
+ lt = ldns_lookup_by_name(ldns_rcodes, mvalue);
+ if (lt) {
+ b = lt->id;
+ } else {
+ i = atoi(mvalue);
+
+ if (i >= 0 && !isdigit(mvalue[0]) == 0) {
+ lt = ldns_lookup_by_id(ldns_rcodes, i);
+ if (lt) {
+ b = lt->id;
+ } else {
+ fprintf(stderr, "Unknown rcode: %s\n", mvalue);
+ exit(1);
+ return false;
+ }
+ } else {
+ fprintf(stderr, "Unknown rcode: %s\n", mvalue);
+ exit(1);
+ return false;
+ }
+ }
+
+ switch(operator) {
+ case OP_EQUAL:
+ return a == b;
+ break;
+ case OP_NOTEQUAL:
+ return a != b;
+ break;
+ default:
+ fprintf(stderr, "Error bad operator for rcode: %s\n", get_op_str(operator));
+ return false;
+ break;
+ }
+}
+
+static bool
+value_matches(match_id id,
+ type_operator operator,
+ char *value,
+ char *mvalue)
+{
+ int result;
+
+ if (verbosity >= 5) {
+ printf("Match %s: %s %s %s: ", get_match_name_str(id), value, get_op_str(operator), mvalue);
+ }
+ switch(id) {
+ case MATCH_OPCODE:
+ result = match_opcode(operator, value, mvalue);
+ break;
+ case MATCH_RCODE:
+ result = match_rcode(operator, value, mvalue);
+ break;
+ case MATCH_ID:
+ case MATCH_QR:
+ case MATCH_TC:
+ case MATCH_AD:
+ case MATCH_CD:
+ case MATCH_RD:
+ case MATCH_DO:
+ case MATCH_PACKETSIZE:
+ case MATCH_EDNS:
+ case MATCH_EDNS_PACKETSIZE:
+ case MATCH_QUESTION_SIZE:
+ case MATCH_ANSWER_SIZE:
+ case MATCH_AUTHORITY_SIZE:
+ case MATCH_ADDITIONAL_SIZE:
+ case MATCH_TIMESTAMP:
+ result = match_int(operator, value, mvalue);
+ break;
+ case MATCH_QUERY:
+ case MATCH_QNAME:
+ case MATCH_ANSWER:
+ case MATCH_AUTHORITY:
+ case MATCH_ADDITIONAL:
+ result = match_str(operator, value, mvalue);
+ break;
+ case MATCH_SRC_ADDRESS:
+ case MATCH_DST_ADDRESS:
+ result = match_str(operator, value, mvalue);
+ break;
+ case MATCH_QTYPE:
+ result = match_rr_type(operator, value, mvalue);
+ break;
+ default:
+ fprintf(stderr, "Error: value_matches() for operator %s not implemented yet.\n", get_op_str((type_operator) id));
+ exit(3);
+ }
+ if (verbosity >= 5) {
+ if (result) {
+ printf("true\n");
+ } else {
+ printf("false\n");
+ }
+ }
+ return result;
+}
+
+static char *
+get_string_value(match_id id, ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr)
+{
+ char *val;
+ match_table *mt;
+ size_t valsize = 100;
+
+ val = malloc(valsize);
+ memset(val, 0, valsize);
+
+ switch(id) {
+ case MATCH_QR:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_qr(pkt));
+ break;
+ case MATCH_ID:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_id(pkt));
+ break;
+ case MATCH_OPCODE:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_get_opcode(pkt));
+ break;
+ case MATCH_RCODE:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_get_rcode(pkt));
+ break;
+ case MATCH_PACKETSIZE:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_size(pkt));
+ break;
+ case MATCH_TC:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_tc(pkt));
+ break;
+ case MATCH_AD:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_ad(pkt));
+ break;
+ case MATCH_CD:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_cd(pkt));
+ break;
+ case MATCH_RD:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_rd(pkt));
+ break;
+ case MATCH_EDNS:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns(pkt));
+ break;
+ case MATCH_EDNS_PACKETSIZE:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns_udp_size(pkt));
+ break;
+ case MATCH_DO:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns_do(pkt));
+ break;
+ case MATCH_QUESTION_SIZE:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_qdcount(pkt));
+ break;
+ case MATCH_ANSWER_SIZE:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_ancount(pkt));
+ break;
+ case MATCH_AUTHORITY_SIZE:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_nscount(pkt));
+ break;
+ case MATCH_ADDITIONAL_SIZE:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_arcount(pkt));
+ break;
+ case MATCH_SRC_ADDRESS:
+ free(val);
+ val = ldns_rdf2str(src_addr);
+ break;
+ case MATCH_DST_ADDRESS:
+ free(val);
+ val = ldns_rdf2str(dst_addr);
+ break;
+ case MATCH_TIMESTAMP:
+ snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_timestamp(pkt).tv_sec);
+ break;
+ case MATCH_QUERY:
+ if (ldns_pkt_qdcount(pkt) > 0) {
+ free(val);
+ val = ldns_rr2str(ldns_rr_list_rr(ldns_pkt_question(pkt), 0));
+ /* replace \n for nicer printing later */
+ if (strchr(val, '\n')) {
+ *(strchr(val, '\n')) = '\0';
+ }
+ } else {
+ val[0] = '\0';
+ }
+ break;
+ case MATCH_QNAME:
+ if (ldns_pkt_qdcount(pkt) > 0) {
+ free(val);
+ val = ldns_rdf2str(ldns_rr_owner(ldns_rr_list_rr(ldns_pkt_question(pkt), 0)));
+ /* replace \n for nicer printing later */
+ if (strchr(val, '\n')) {
+ *(strchr(val, '\n')) = '\0';
+ }
+ } else {
+ val[0] = '\0';
+ }
+ break;
+ case MATCH_QTYPE:
+ if (ldns_pkt_qdcount(pkt) > 0) {
+ free(val);
+ val = ldns_rr_type2str(ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_question(pkt), 0)));
+ } else {
+ val[0] = '\0';
+ }
+ break;
+ case MATCH_ANSWER:
+ if (ldns_pkt_ancount(pkt) > 0) {
+ free(val);
+ val = ldns_rr_list2str(ldns_pkt_answer(pkt));
+ } else {
+ val[0] = '\0';
+ }
+ break;
+ case MATCH_AUTHORITY:
+ if (ldns_pkt_nscount(pkt) > 0) {
+ free(val);
+ val = ldns_rr_list2str(ldns_pkt_authority(pkt));
+ } else {
+ val[0] = '\0';
+ }
+ break;
+ case MATCH_ADDITIONAL:
+ if (ldns_pkt_arcount(pkt) > 0) {
+ free(val);
+ val = ldns_rr_list2str(ldns_pkt_additional(pkt));
+ } else {
+ val[0] = '\0';
+ }
+ break;
+ default:
+ mt = get_match_by_id(id);
+ if (!mt) {
+ printf("ERROR UNKNOWN MATCH_TABLE ID %u\n", id);
+ exit(1);
+ }
+ printf("Matcher for %s not implemented yet\n", mt->name);
+ exit(1);
+ return NULL;
+ }
+
+ return val;
+}
+
+static bool
+match_packet_to_operation(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_operation *operation)
+{
+ bool result;
+ char *val;
+
+ if (!pkt || !operation) {
+ return false;
+ } else {
+ val = get_string_value(operation->id, pkt, src_addr, dst_addr);
+ if (!val) {
+ return false;
+ }
+ result = value_matches(operation->id, operation->operator, val, operation->value);
+ free(val);
+ return result;
+ }
+}
+
+static int
+match_operation_compare(const void *a, const void *b)
+{
+ match_operation *moa, *mob;
+ match_table *mt;
+ long ia, ib;
+
+ if (!a) {
+ return 1;
+ } else if (!b) {
+ return -1;
+ } else {
+ moa = (match_operation *) a;
+ mob = (match_operation *) b;
+
+ if (moa->id < mob->id) {
+ return -1;
+ } else if (moa->id > mob->id) {
+ return 1;
+ } else {
+ if (moa->operator < mob->operator) {
+ return -1;
+ } else if (moa->operator > mob->operator) {
+ return 1;
+ } else {
+ mt = get_match_by_id(moa->id);
+ if (mt) {
+ switch (mt->type) {
+ case TYPE_INT:
+ case TYPE_TIMESTAMP:
+ case TYPE_BOOL:
+ case TYPE_OPCODE:
+ case TYPE_RCODE:
+ ia = atol(moa->value);
+ ib = atol(mob->value);
+ return ia - ib;
+ break;
+ case TYPE_STRING:
+ case TYPE_ADDRESS:
+ case TYPE_RR:
+ default:
+ return strcmp(moa->value, mob->value);
+ break;
+ }
+ } else {
+ return strcmp(moa->value, mob->value);
+ }
+ }
+ }
+ }
+}
+
+static int
+match_expression_compare(const void *a, const void *b)
+{
+ match_expression *mea, *meb;
+
+ if (!a) {
+ return 1;
+ } else if (!b) {
+ return -1;
+ } else {
+ mea = (match_expression *) a;
+ meb = (match_expression *) b;
+
+ if (mea->op < meb->op) {
+ return -1;
+ } else if (mea->op > meb->op) {
+ return 1;
+ } else {
+ switch(mea->op) {
+ case MATCH_EXPR_AND:
+ case MATCH_EXPR_OR:
+ if (match_expression_compare(mea->left, meb->left) < 0) {
+ return -1;
+ } else if (match_expression_compare(mea->left, meb->left) > 0) {
+ return 1;
+ } else {
+ return match_expression_compare(mea->right, meb->right);
+ }
+ break;
+ case MATCH_EXPR_LEAF:
+ return match_operation_compare(mea->match, meb->match);
+ break;
+ default:
+ fprintf(stderr, "Unknown Match Expression logic operator: %u\n", mea->op);
+ exit(1);
+ }
+ }
+ }
+}
+
+/**
+ * If count is true, and the counter is found, its count is increased by 1
+ */
+static int
+add_match_counter(match_counters *counters,
+ match_expression *expr,
+ bool count)
+{
+ int cmp;
+ match_counters *new;
+
+ if (!counters || !expr) {
+ return -1;
+ } else {
+ if (counters->match) {
+ cmp = match_expression_compare(counters->match,
+ expr);
+ if (cmp > 0) {
+ if (counters->left) {
+ return add_match_counter(counters->left,
+ expr,
+ count);
+ } else {
+ new = malloc(sizeof(match_counters));
+ new->left = NULL;
+ new->right = NULL;
+ new->match = expr;
+ counters->left = new;
+ return 0;
+ }
+ } else if (cmp < 0) {
+ if (counters->right) {
+ return add_match_counter(counters->right,
+ expr,
+ count);
+ } else {
+ new = malloc(sizeof(match_counters));
+ new->left = NULL;
+ new->right = NULL;
+ new->match = expr;
+ counters->right = new;
+ return 0;
+ }
+ } else {
+ /* already there? */
+ if (count) {
+ counters->match->count++;
+ }
+ return 1;
+ }
+ } else {
+ /* shouldn't happen but anyway */
+ counters->match = expr;
+ }
+ }
+ return 0;
+}
+
+static bool
+match_dns_packet_to_expr(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_expression *expr)
+{
+ bool result;
+
+ if (!pkt || !expr) {
+ return false;
+ }
+
+ switch(expr->op) {
+ case MATCH_EXPR_OR:
+ result = (match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->left) ||
+ match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->right));
+ break;
+ case MATCH_EXPR_AND:
+ result = (match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->left) &&
+ match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->right));
+ break;
+ case MATCH_EXPR_LEAF:
+ result = match_packet_to_operation(pkt, src_addr, dst_addr, expr->match);
+ break;
+ default:
+ fprintf(stderr, "Error, unknown expression operator %u\n", expr->op);
+ fprintf(stderr, "full expression:\n");
+ print_match_expression(stderr, expr);
+ fprintf(stderr, "\n");
+ exit(1);
+ }
+
+ if (result) {
+ if (verbosity >= 5) {
+ printf("Found Match:\n");
+ print_match_expression(stdout, expr);
+ printf("\nCount now %u\n", (unsigned int) expr->count);
+ }
+ expr->count++;
+ }
+
+ return result;
+}
+
+static void
+free_match_operation(match_operation *operation)
+{
+ if (operation) {
+ if (operation->value) {
+ free(operation->value);
+ }
+ free(operation);
+ }
+}
+
+static void
+free_match_expression(match_expression *expr)
+{
+ if (expr) {
+ switch(expr->op) {
+ case MATCH_EXPR_OR:
+ case MATCH_EXPR_AND:
+ free_match_expression(expr->left);
+ free_match_expression(expr->right);
+ break;
+ case MATCH_EXPR_LEAF:
+ free_match_operation(expr->match);
+ break;
+ }
+ free(expr);
+ }
+}
+
+static void
+free_counters(match_counters *counters)
+{
+ if (counters) {
+ if (counters->left) {
+ free_counters(counters->left);
+ }
+ if (counters->match) {
+ free_match_expression(counters->match);
+ }
+ if (counters->right) {
+ free_counters(counters->right);
+ }
+ free(counters);
+ }
+}
+
+static void
+match_pkt_counters(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_counters *counts)
+{
+ if (counts->left) {
+ match_pkt_counters(pkt, src_addr, dst_addr, counts->left);
+ }
+ if (counts->match) {
+ if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, counts->match)) {
+/*
+ counts->match->count++;
+*/
+ }
+ }
+ if (counts->right) {
+ match_pkt_counters(pkt, src_addr, dst_addr, counts->right);
+ }
+}
+
+static void
+match_pkt_uniques(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_counters *uniques, match_id unique_ids[], size_t unique_id_count)
+{
+ match_expression *me;
+ size_t i;
+ match_operation *mo;
+ int add_result;
+
+ for (i = 0; i < unique_id_count; i++) {
+ mo = malloc(sizeof(match_operation));
+ mo->id = unique_ids[i];
+ mo->operator = OP_EQUAL;
+ mo->value = get_string_value(mo->id, pkt, src_addr, dst_addr);
+
+ me = malloc(sizeof(match_expression));
+ me->op = MATCH_EXPR_LEAF;
+ me->left = NULL;
+ me->right = NULL;
+ me->match = mo;
+ me->count = 1;
+
+ add_result = add_match_counter(uniques, me, true);
+ /* if result=1 it was already found, so delete new one */
+ if (add_result == 1) {
+ free_match_expression(me);
+ }
+ }
+
+#if 0
+ size_t i, j;
+ bool found;
+ match_expression *me;
+ match_operation *mo;
+
+ /* get the value, match uniques for that, if not match, add new */
+ /* all unique values should be MATCH_EXPR_LEAF */
+ found = false;
+ for (j = 0; j < uniques->size; j++) {
+ if (uniques->counter[j]->match->id == unique_ids[i]) {
+ if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, uniques->counter[j])) {
+ found = true;
+ }
+ }
+ }
+ if (!found) {
+ mo = malloc(sizeof(match_operation));
+ mo->id = unique_ids[i];
+ mo->operator = OP_EQUAL;
+ mo->value = get_string_value(mo->id, pkt, src_addr, dst_addr);
+
+ me = malloc(sizeof(match_expression));
+ me->match = mo;
+ me->op = MATCH_EXPR_LEAF;
+ me->left = NULL;
+ me->right = NULL;
+ me->count = 1;
+
+ add_counter(uniques, me);
+ }
+ }
+#endif
+}
+
+static match_expression *
+parse_match_expression(char *string)
+{
+ match_expression *expr;
+ size_t i,j;
+ size_t leftstart, leftend = 0;
+ char *left_str, *op, *val;
+ match_table *mt;
+ match_operation *mo = NULL;
+ const type_operators *tos;
+ match_expression *result;
+ ldns_lookup_table *lt = NULL;
+
+ /* remove whitespace */
+ char *str = malloc(strlen(string) + 1);
+
+ j = 0;
+ for (i = 0; i < strlen(string); i++) {
+ if(!isspace(string[i])) {
+ str[j] = string[i];
+ j++;
+ }
+ }
+ str[j] = '\0';
+
+ expr = malloc(sizeof(match_expression));
+ expr->left = NULL;
+ expr->right = NULL;
+ expr->match = NULL;
+ expr->count = 0;
+ leftstart = 0;
+ for (i = 0; i < strlen(str); i++) {
+ if (str[i] == '&') {
+ expr->op = MATCH_EXPR_AND;
+ if (!expr->left) {
+ left_str = malloc(leftend - leftstart + 2);
+ strncpy(left_str, &str[leftstart], leftend-leftstart+1);
+ left_str[leftend - leftstart + 1] = '\0';
+ expr->left = parse_match_expression(left_str);
+ free(left_str);
+ }
+ expr->right = parse_match_expression(&str[i+1]);
+ if (expr->left && expr->right) {
+ result = expr;
+ goto done;
+ } else {
+ result = NULL;
+ goto done;
+ }
+ } else if (str[i] == '|') {
+ expr->op = MATCH_EXPR_OR;
+ if (!expr->left) {
+ left_str = malloc(leftend - leftstart + 2);
+ strncpy(left_str, &str[leftstart], leftend-leftstart+1);
+ left_str[leftend - leftstart + 1] = '\0';
+ expr->left = parse_match_expression(left_str);
+ free(left_str);
+ }
+ expr->right = parse_match_expression(&str[i+1]);
+ expr->count = 0;
+ if (expr->left && expr->right) {
+ result = expr;
+ goto done;
+ } else {
+ result = NULL;
+ goto done;
+ }
+ } else if (str[i] == '(') {
+ leftstart = i + 1;
+ j = 1;
+ while (j > 0) {
+ i++;
+ if (i > strlen(str)) {
+ printf("parse error: no closing bracket: %s\n", str);
+ printf(" ");
+ for (j = 0; j < leftstart - 1; j++) {
+ printf(" ");
+ }
+ printf("^\n");
+ result = NULL;
+ goto done;
+ }
+ if (str[i] == ')') {
+ j--;
+ } else if (str[i] == '(') {
+ j++;
+ } else {
+ }
+ }
+ leftend = i-1;
+ left_str = malloc(leftend - leftstart + 1);
+ strncpy(left_str, &str[leftstart], leftend - leftstart + 1);
+ expr->left = parse_match_expression(left_str);
+ free(left_str);
+ if (i >= strlen(str)-1) {
+ result = expr->left;
+ goto done;
+ }
+ } else if (str[i] == ')') {
+ printf("parse error: ) without (\n");
+ result = NULL;
+ goto done;
+ } else {
+ leftend = i;
+ }
+ }
+
+ /* no operators or hooks left, expr should be of the form
+ <name><operator><value> now */
+ for (i = 0; i < strlen(str); i++) {
+ if (str[i] == '=' ||
+ str[i] == '>' ||
+ str[i] == '<' ||
+ str[i] == '!' ||
+ str[i] == '~'
+ ) {
+ leftend = i-1;
+ op = malloc(3);
+ j = 0;
+ op[j] = str[i];
+ i++;
+ j++;
+
+ if (i > strlen(str)) {
+ printf("parse error no right hand side: %s\n", str);
+ result = NULL;
+ goto done;
+ }
+ if (str[i] == '=' ||
+ str[i] == '>' ||
+ str[i] == '<' ||
+ str[i] == '!' ||
+ str[i] == '~'
+ ) {
+ op[j] = str[i];
+ i++;
+ j++;
+ if (i > strlen(str)) {
+ printf("parse error no right hand side: %s\n", str);
+ result = NULL;
+ goto done;
+ }
+ }
+ op[j] = '\0';
+ left_str = malloc(leftend - leftstart + 2);
+ strncpy(left_str, &str[leftstart], leftend - leftstart + 1);
+ left_str[leftend - leftstart + 1] = '\0';
+ mt = get_match_by_name(left_str);
+ if (!mt) {
+ printf("parse error: unknown match name: %s\n", left_str);
+ result = NULL;
+ goto done;
+ } else {
+ /* check if operator is allowed */
+ tos = get_type_operators(mt->type);
+ for (j = 0; j < tos->operator_count; j++) {
+ if (get_op_id(op) == tos->operators[j]) {
+ mo = malloc(sizeof(match_operation));
+ mo->id = mt->id;
+ mo->operator = get_op_id(op);
+ switch (mt->type) {
+ case TYPE_BOOL:
+ val = malloc(2);
+ if (strncmp(&str[i], "true", 5) == 0 ||
+ strncmp(&str[i], "TRUE", 5) == 0 ||
+ strncmp(&str[i], "True", 5) == 0 ||
+ strncmp(&str[i], "1", 2) == 0
+ ) {
+ val[0] = '1';
+ val[1] = '\0';
+ } else if (strncmp(&str[i], "false", 5) == 0 ||
+ strncmp(&str[i], "FALSE", 5) == 0 ||
+ strncmp(&str[i], "False", 5) == 0 ||
+ strncmp(&str[i], "0", 2) == 0
+ ) {
+
+ val[0] = '0';
+ } else {
+ fprintf(stderr, "Bad value for bool: %s\n", &str[i]);
+ exit(EXIT_FAILURE);
+ }
+ val[1] = '\0';
+ break;
+ case TYPE_RR:
+ /* convert first so we have the same strings for the same rrs in match_ later */
+ /*
+ qrr = ldns_rr_new_frm_str(&str[i], LDNS_DEFAULT_TTL, NULL);
+ if (!qrr) {
+ fprintf(stderr, "Bad value for RR: %s\n", &str[i]);
+ exit(EXIT_FAILURE);
+ }
+ val = ldns_rr2str(qrr);
+ */
+ /* remove \n for readability */
+ /*
+ if (strchr(val, '\n')) {
+ *(strchr(val, '\n')) = '\0';
+ }
+ ldns_rr_free(qrr);
+ */
+ val = strdup(&str[i]);
+ break;
+ case TYPE_OPCODE:
+ lt = ldns_lookup_by_name(ldns_opcodes, &str[i]);
+ if (lt) {
+ val = malloc(4);
+ snprintf(val, 3, "%u", (unsigned int) lt->id);
+ } else {
+ val = strdup(&str[i]);
+ }
+ break;
+ case TYPE_RCODE:
+ lt = ldns_lookup_by_name(ldns_rcodes, &str[i]);
+ if (lt) {
+ val = malloc(4);
+ snprintf(val, 3, "%u", (unsigned int) lt->id);
+ } else {
+ val = strdup(&str[i]);
+ }
+ break;
+ default:
+ val = strdup(&str[i]);
+ break;
+ }
+ mo->value = val;
+ }
+ }
+ if (!mo) {
+ printf("parse error: operator %s not allowed for match %s\n", op, left_str);
+ result = NULL;
+ goto done;
+ }
+ }
+ free(left_str);
+ free(op);
+ expr->match = mo;
+ expr->op = MATCH_EXPR_LEAF;
+ result = expr;
+ goto done;
+ }
+ }
+
+ result = NULL;
+
+ done:
+ free(str);
+ if (!result) {
+ free_match_expression(expr);
+ }
+ return result;
+
+}
+/* end of matches and counts */
+void
+usage(FILE *output)
+{
+ fprintf(output, "Usage: ldns-dpa [OPTIONS] <pcap file>\n");
+ fprintf(output, "Options:\n");
+ fprintf(output, "\t-c <exprlist>:\tCount occurrences of matching expressions\n");
+ fprintf(output, "\t-f <expression>:\tFilter occurrences of matching expressions\n");
+ fprintf(output, "\t-h:\t\tshow this help\n");
+ fprintf(output, "\t-p:\t\tshow percentage of -u and -c values (of the total of\n\t\t\tmatching on the -f filter. if no filter is given,\n\t\t\tpercentages are on all correct dns packets)\n");
+ fprintf(output, "\t-of <file>:\tWrite pcap packets that match the -f flag to file\n");
+ fprintf(output, "\t-ofh <file>:\tWrite pcap packets that match the -f flag to file\n\t\tin a hexadecimal format readable by drill\n");
+ fprintf(output, "\t-s:\t\tshow possible match names\n");
+ fprintf(output, "\t-s <matchname>:\tshow possible match operators and values for <name>\n");
+ fprintf(output, "\t-sf:\t\tPrint packet that match -f. If no -f is given, print\n\t\t\tall dns packets\n");
+ fprintf(output, "\t-u <matchnamelist>:\tCount all occurrences of matchname\n");
+ fprintf(output, "\t-ua:\t\tShow average value of every -u matchname\n");
+ fprintf(output, "\t-uac:\t\tShow average count of every -u matchname\n");
+ fprintf(output, "\t-um <number>:\tOnly show -u results that occured more than number times\n");
+ fprintf(output, "\t-v <level>:\tbe more verbose\n");
+ fprintf(output, "\t-notip <file>:\tDump pcap packets that were not recognized as\n\t\t\tIP packets to file\n");
+ fprintf(output, "\t-baddns <file>:\tDump mangled dns packets to file\n");
+ fprintf(output, "\t-version:\tShow the version and exit\n");
+ fprintf(output, "\n");
+ fprintf(output, "The filename '-' stands for stdin or stdout, so you can use \"-of -\" if you want to pipe the output to another process\n");
+ fprintf(output, "\n");
+ fprintf(output, "A <list> is a comma separated list of items\n");
+ fprintf(output, "\n");
+ fprintf(output, "An expression has the following form:\n");
+ fprintf(output, "<expr>:\t(<expr>)\n");
+ fprintf(output, "\t<expr> | <expr>\n");
+ fprintf(output, "\t<expr> & <expr>\n");
+ fprintf(output, "\t<match>\n");
+ fprintf(output, "\n");
+ fprintf(output, "<match>:\t<matchname> <operator> <value>\n");
+ fprintf(output, "\n");
+ fprintf(output, "See the -s option for possible matchnames, operators and values.\n");
+}
+
+void
+show_match_names(char *name)
+{
+ size_t j;
+ match_table *mt;
+ ldns_lookup_table *lt;
+ const type_operators *tos;
+ char *str;
+ size_t i;
+
+ if (name) {
+ mt = get_match_by_name(name);
+ if (mt) {
+ printf("%s:\n", mt->name);
+ printf("\t%s.\n", mt->description);
+ printf("\toperators: ");
+ printf("\t");
+ tos = get_type_operators(mt->type);
+ if (tos) {
+ for (j = 0; j < tos->operator_count; j++) {
+ printf("%s ", get_op_str(tos->operators[j]));
+/*
+ lt = ldns_lookup_by_id((ldns_lookup_table *) lt_operators, tos->operators[j]);
+ if (lt) {
+ printf("%s ", lt->name);
+ } else {
+ printf("? ");
+ }
+*/
+ }
+ } else {
+ printf("unknown type");
+ }
+
+ printf("\n");
+ printf("\tValues:\n");
+ switch (mt->type) {
+ case TYPE_INT:
+ printf("\t\t<Integer>\n");
+ break;
+ case TYPE_BOOL:
+ printf("\t\t0\n");
+ printf("\t\t1\n");
+ printf("\t\ttrue\n");
+ printf("\t\tfalse\n");
+ break;
+ case TYPE_OPCODE:
+ printf("\t\t<Integer>\n");
+ lt = ldns_opcodes;
+ while (lt->name != NULL) {
+ printf("\t\t%s\n", lt->name);
+ lt++;
+ }
+ break;
+ case TYPE_RCODE:
+ printf("\t\t<Integer>\n");
+ lt = ldns_rcodes;
+ while (lt->name != NULL) {
+ printf("\t\t%s\n", lt->name);
+ lt++;
+ }
+ break;
+ case TYPE_STRING:
+ printf("\t\t<String>\n");
+ break;
+ case TYPE_TIMESTAMP:
+ printf("\t\t<Integer> (seconds since epoch)\n");
+ break;
+ case TYPE_ADDRESS:
+ printf("\t\t<IP address>\n");
+ break;
+ case TYPE_RR:
+ printf("\t\t<Resource Record>\n");
+ break;
+ default:
+ break;
+ }
+ } else {
+ printf("Unknown match name: %s\n", name);
+ }
+ } else {
+ mt = (match_table *) matches;
+ while (mt->name != NULL) {
+ str = (char *) mt->name;
+ printf("%s:", str);
+ i = strlen(str) + 1;
+ while (i < 24) {
+ printf(" ");
+ i++;
+ }
+ printf("%s\n", mt->description);
+ mt++;
+ }
+ }
+}
+
+int
+handle_ether_packet(const u_char *data, struct pcap_pkthdr cur_hdr, match_counters *count, match_expression *match_expr, match_counters *uniques, match_id unique_ids[], size_t unique_id_count)
+{
+ struct ether_header *eptr;
+ struct ip *iptr;
+ struct ip6_hdr *ip6_hdr;
+ int ip_hdr_size;
+ uint8_t protocol;
+ size_t data_offset = 0;
+ ldns_rdf *src_addr, *dst_addr;
+ uint8_t *ap;
+ char *astr;
+ bpf_u_int32 len = cur_hdr.caplen;
+ struct timeval timestamp;
+ uint16_t ip_flags;
+ uint16_t ip_len;
+ uint16_t ip_id;
+ uint16_t ip_f_offset;
+ const u_char *newdata = NULL;
+/*
+printf("timeval: %u ; %u\n", cur_hdr.ts.tv_sec, cur_hdr.ts.tv_usec);
+*/
+
+ uint8_t *dnspkt;
+
+ ldns_pkt *pkt;
+ ldns_status status;
+
+ /* lets start with the ether header... */
+ eptr = (struct ether_header *) data;
+ /* Do a couple of checks to see what packet type we have..*/
+ if (ntohs (eptr->ether_type) == ETHERTYPE_IP)
+ {
+ if (verbosity >= 5) {
+ printf("Ethernet type hex:%x dec:%u is an IP packet\n",
+ (unsigned int) ntohs(eptr->ether_type),
+ (unsigned int) ntohs(eptr->ether_type));
+ }
+
+ data_offset = ETHER_HEADER_LENGTH;
+ iptr = (struct ip *) (data + data_offset);
+ /*
+ printf("IP_OFF: %u (%04x) %04x %04x (%d) (%d)\n", iptr->ip_off, iptr->ip_off, IP_MF, IP_DF, iptr->ip_off & 0x4000, iptr->ip_off & 0x2000);
+ */
+ ip_flags = ldns_read_uint16(&(iptr->ip_off));
+ ip_id = ldns_read_uint16(&(iptr->ip_id));
+ ip_len = ldns_read_uint16(&(iptr->ip_len));
+ ip_f_offset = (ip_flags & IP_OFFMASK)*8;
+ if (ip_flags & IP_MF && ip_f_offset == 0) {
+ /*printf("First Frag id %u len\n", ip_id, ip_len);*/
+ fragment_p->ip_id = ip_id;
+ memset(fragment_p->data, 0, 65535);
+ memcpy(fragment_p->data, iptr, ip_len);
+ fragment_p->cur_len = ip_len + 20;
+/*
+ for (ip_len = 0; ip_len < fragment_p->cur_len; ip_len++) {
+ if (ip_len > 0 && ip_len % 20 == 0) {
+ printf("\t; %u - %u\n", ip_len - 19, ip_len);
+ }
+ printf("%02x ", fragment_p->data[ip_len]);
+ }
+ printf("\t; ??? - %u\n", ip_len);
+*/
+ return 0;
+ } else
+ if (ip_flags & IP_MF && ip_f_offset != 0) {
+ /*printf("Next frag\n");*/
+ if (ip_id == fragment_p->ip_id) {
+ /*printf("add fragment to current id %u len %u offset %u\n", ip_id, ip_len, ip_f_offset);*/
+ memcpy(fragment_p->data + (ip_f_offset) + 20, data+data_offset+20, ip_len - (iptr->ip_hl)*4);
+ /*printf("COPIED %u\n", ip_len);*/
+ fragment_p->cur_len = fragment_p->cur_len + ip_len - 20;
+ /*printf("cur len now %u\n", fragment_p->cur_len);*/
+/*
+ for (ip_len = 0; ip_len < fragment_p->cur_len; ip_len++) {
+ if (ip_len > 0 && ip_len % 20 == 0) {
+ printf("\t; %u - %u\n", ip_len - 19, ip_len);
+ }
+ printf("%02x ", fragment_p->data[ip_len]);
+ }
+ printf("\t; ??? - %u\n", ip_len);
+*/
+ return 0;
+ } else {
+ /*printf("Lost fragment %u\n", iptr->ip_id);*/
+ lost_packet_fragments++;
+ return 1;
+ }
+ } else
+ if (!(ip_flags & IP_MF) && ip_f_offset != 0) {
+ /*printf("Last frag\n");*/
+ if (ip_id == fragment_p->ip_id) {
+ /*printf("add fragment to current id %u len %u offset %u\n", ip_id, ip_len, ip_f_offset);*/
+ memcpy(fragment_p->data + ip_f_offset + 20, data+data_offset+20, ip_len - 20);
+ fragment_p->cur_len = fragment_p->cur_len + ip_len - 20;
+ iptr = (struct ip *) fragment_p->data;
+ newdata = malloc(fragment_p->cur_len + data_offset);
+ if (!newdata) {
+ printf("Malloc failed, out of mem?\n");
+ exit(4);
+ }
+ memcpy((char *) newdata, data, data_offset);
+ memcpy((char *) newdata+data_offset, fragment_p->data, fragment_p->cur_len);
+ iptr->ip_len = (u_short) ldns_read_uint16(&(fragment_p->cur_len));
+ iptr->ip_off = 0;
+ len = (bpf_u_int32) fragment_p->cur_len;
+ cur_hdr.caplen = len;
+ fragment_p->ip_id = 0;
+ fragmented_packets++;
+/*
+ for (ip_len = 0; ip_len < fragment_p->cur_len; ip_len++) {
+ if (ip_len > 0 && ip_len % 20 == 0) {
+ printf("\t; %u - %u\n", ip_len - 19, ip_len);
+ }
+ printf("%02x ", fragment_p->data[ip_len]);
+ }
+ printf("\t; ??? - %u\n", ip_len);
+*/
+ } else {
+ /*printf("Lost fragment %u\n", iptr->ip_id);*/
+ lost_packet_fragments++;
+ return 1;
+ }
+ } else {
+ newdata = data;
+ }
+/*
+ if (iptr->ip_off & 0x0040) {
+ printf("Don't fragment\n");
+ }
+*/
+
+ /* in_addr portability woes, going manual for now */
+ /* ipv4 */
+ ap = (uint8_t *) &(iptr->ip_src);
+ astr = malloc(INET_ADDRSTRLEN);
+ if (inet_ntop(AF_INET, ap, astr, INET_ADDRSTRLEN)) {
+ if (ldns_str2rdf_a(&src_addr, astr) == LDNS_STATUS_OK) {
+
+ }
+ free(astr);
+ }
+ ap = (uint8_t *) &(iptr->ip_dst);
+ astr = malloc(INET_ADDRSTRLEN);
+ if (inet_ntop(AF_INET, ap, astr, INET_ADDRSTRLEN)) {
+ if (ldns_str2rdf_a(&dst_addr, astr) == LDNS_STATUS_OK) {
+
+ }
+ free(astr);
+ }
+
+ ip_hdr_size = (int) iptr->ip_hl * 4;
+ protocol = (uint8_t) iptr->ip_p;
+
+ data_offset += ip_hdr_size;
+
+ if (protocol == IPPROTO_UDP) {
+ udp_packets++;
+ data_offset += UDP_HEADER_LENGTH;
+
+ dnspkt = (uint8_t *) (newdata + data_offset);
+
+ /*printf("packet starts at byte %u\n", data_offset);*/
+
+ /*printf("Len: %u\n", len);*/
+
+ status = ldns_wire2pkt(&pkt, dnspkt, len - data_offset);
+
+ if (status != LDNS_STATUS_OK) {
+ if (verbosity >= 3) {
+ printf("No dns packet: %s\n", ldns_get_errorstr_by_id(status));
+ }
+ if (verbosity >= 5) {
+ for (ip_len = 0; ip_len < len - data_offset; ip_len++) {
+ if (ip_len > 0 && ip_len % 20 == 0) {
+ printf("\t; %u - %u\n", (unsigned int) ip_len - 19, (unsigned int) ip_len);
+ }
+ printf("%02x ", (unsigned int) dnspkt[ip_len]);
+ }
+ printf("\t; ??? - %u\n", (unsigned int) ip_len);
+
+ }
+ bad_dns_packets++;
+ if (bad_dns_dump) {
+ pcap_dump((u_char *)bad_dns_dump, &cur_hdr, newdata);
+ }
+ } else {
+ timestamp.tv_sec = cur_hdr.ts.tv_sec;
+ timestamp.tv_usec = cur_hdr.ts.tv_usec;
+ ldns_pkt_set_timestamp(pkt, timestamp);
+
+ if (verbosity >= 4) {
+ printf("DNS packet\n");
+ ldns_pkt_print(stdout, pkt);
+ printf("\n\n");
+ }
+
+ total_nr_of_dns_packets++;
+
+ if (match_expr) {
+ if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, match_expr)) {
+ /* if outputfile write */
+ if (dumper) {
+ pcap_dump((u_char *)dumper, &cur_hdr, data);
+ }
+ if (hexdumpfile) {
+ fprintf(hexdumpfile, ";; %u\n", (unsigned int) total_nr_of_dns_packets);
+ ldns_pkt2file_hex(hexdumpfile, pkt);
+ }
+ if (show_filter_matches) {
+ printf(";; From: ");
+ ldns_rdf_print(stdout, src_addr);
+ printf("\n");
+ printf(";; To: ");
+ ldns_rdf_print(stdout, dst_addr);
+ printf("\n");
+ ldns_pkt_print(stdout, pkt);
+ printf("------------------------------------------------------------\n\n");
+ }
+ } else {
+ ldns_pkt_free(pkt);
+ ldns_rdf_deep_free(src_addr);
+ ldns_rdf_deep_free(dst_addr);
+ return 0;
+ }
+ } else {
+ if (dumper) {
+ pcap_dump((u_char *)dumper, &cur_hdr, data);
+ }
+ if (hexdumpfile) {
+ fprintf(hexdumpfile, ";; %u\n", (unsigned int) total_nr_of_dns_packets);
+ ldns_pkt2file_hex(hexdumpfile, pkt);
+ }
+ if (show_filter_matches) {
+ printf(";; From: ");
+ ldns_rdf_print(stdout, src_addr);
+ printf("\n");
+ printf(";; To: ");
+ ldns_rdf_print(stdout, dst_addr);
+ printf("\n");
+ ldns_pkt_print(stdout, pkt);
+ printf("------------------------------------------------------------\n\n");
+ }
+ }
+
+ /* General counters here */
+ total_nr_of_filtered_packets++;
+
+ match_pkt_counters(pkt, src_addr, dst_addr, count);
+ match_pkt_uniques(pkt, src_addr, dst_addr, uniques, unique_ids, unique_id_count);
+
+ ldns_pkt_free(pkt);
+ pkt = NULL;
+ }
+ ldns_rdf_deep_free(src_addr);
+ ldns_rdf_deep_free(dst_addr);
+
+ } else if (protocol == IPPROTO_TCP) {
+ /* tcp packets are skipped */
+ tcp_packets++;
+ }
+ /* don't have a define for ethertype ipv6 */
+ } else if (ntohs (eptr->ether_type) == ETHERTYPE_IPV6) {
+ /*printf("IPv6!\n");*/
+
+
+ /* copied from ipv4, move this to function? */
+
+ data_offset = ETHER_HEADER_LENGTH;
+ ip6_hdr = (struct ip6_hdr *) (data + data_offset);
+
+ newdata = data;
+
+ /* in_addr portability woes, going manual for now */
+ /* ipv6 */
+ ap = (uint8_t *) &(ip6_hdr->ip6_src);
+ astr = malloc(INET6_ADDRSTRLEN);
+ if (inet_ntop(AF_INET6, ap, astr, INET6_ADDRSTRLEN)) {
+ if (ldns_str2rdf_aaaa(&src_addr, astr) == LDNS_STATUS_OK) {
+
+ }
+ free(astr);
+ }
+ ap = (uint8_t *) &(ip6_hdr->ip6_dst);
+ astr = malloc(INET6_ADDRSTRLEN);
+ if (inet_ntop(AF_INET6, ap, astr, INET6_ADDRSTRLEN)) {
+ if (ldns_str2rdf_aaaa(&dst_addr, astr) == LDNS_STATUS_OK) {
+
+ }
+ free(astr);
+ }
+
+ ip_hdr_size = IP6_HEADER_LENGTH;
+ protocol = (uint8_t) ip6_hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt;
+
+ data_offset += ip_hdr_size;
+
+ if (protocol == IPPROTO_UDP) {
+ udp_packets++;
+ /*printf("V6 UDP!\n");*/
+ data_offset += UDP_HEADER_LENGTH;
+
+ dnspkt = (uint8_t *) (newdata + data_offset);
+
+ /*printf("Len: %u\n", len);*/
+
+ status = ldns_wire2pkt(&pkt, dnspkt, len - data_offset);
+
+ if (status != LDNS_STATUS_OK) {
+ if (verbosity >= 3) {
+ printf("No dns packet: %s\n", ldns_get_errorstr_by_id(status));
+ }
+ bad_dns_packets++;
+ if (bad_dns_dump) {
+ pcap_dump((u_char *)bad_dns_dump, &cur_hdr, newdata);
+ }
+ } else {
+ timestamp.tv_sec = cur_hdr.ts.tv_sec;
+ timestamp.tv_usec = cur_hdr.ts.tv_usec;
+ ldns_pkt_set_timestamp(pkt, timestamp);
+
+ if (verbosity >= 4) {
+ printf("DNS packet\n");
+ ldns_pkt_print(stdout, pkt);
+ printf("\n\n");
+ }
+
+ total_nr_of_dns_packets++;
+
+ if (match_expr) {
+ if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, match_expr)) {
+ /* if outputfile write */
+ if (dumper) {
+ pcap_dump((u_char *)dumper, &cur_hdr, data);
+ }
+ if (show_filter_matches) {
+ printf(";; From: ");
+ ldns_rdf_print(stdout, src_addr);
+ printf("\n");
+ printf(";; To: ");
+ ldns_rdf_print(stdout, dst_addr);
+ printf("\n");
+ ldns_pkt_print(stdout, pkt);
+ printf("------------------------------------------------------------\n\n");
+ }
+ } else {
+ ldns_pkt_free(pkt);
+ ldns_rdf_deep_free(src_addr);
+ ldns_rdf_deep_free(dst_addr);
+ return 0;
+ }
+ } else {
+ if (show_filter_matches) {
+ printf(";; From: ");
+ ldns_rdf_print(stdout, src_addr);
+ printf("\n");
+ printf(";; To: ");
+ ldns_rdf_print(stdout, dst_addr);
+ printf("\n");
+ ldns_pkt_print(stdout, pkt);
+ printf("------------------------------------------------------------\n\n");
+ }
+ }
+
+ /* General counters here */
+ total_nr_of_filtered_packets++;
+
+ match_pkt_counters(pkt, src_addr, dst_addr, count);
+ match_pkt_uniques(pkt, src_addr, dst_addr, uniques, unique_ids, unique_id_count);
+
+ ldns_pkt_free(pkt);
+ pkt = NULL;
+ }
+ ldns_rdf_deep_free(src_addr);
+ ldns_rdf_deep_free(dst_addr);
+
+ } else if (protocol == IPPROTO_TCP) {
+ /* tcp packets are skipped */
+ tcp_packets++;
+ } else {
+ printf("ipv6 unknown next header type: %u\n", (unsigned int) protocol);
+ }
+
+
+
+ } else if (ntohs (eptr->ether_type) == ETHERTYPE_ARP) {
+ if (verbosity >= 5) {
+ printf("Ethernet type hex:%x dec:%u is an ARP packet\n",
+ (unsigned int) ntohs(eptr->ether_type),
+ (unsigned int) ntohs(eptr->ether_type));
+ }
+ arp_packets++;
+ } else {
+ printf("Ethernet type %x not IP\n", (unsigned int) ntohs(eptr->ether_type));
+ if (verbosity >= 5) {
+ printf("Ethernet type %x not IP\n", (unsigned int) ntohs(eptr->ether_type));
+ }
+ not_ip_packets++;
+ if (not_ip_dump) {
+ pcap_dump((u_char *)not_ip_dump, &cur_hdr, data);
+ }
+ }
+
+ return 0;
+}
+
+bool
+parse_match_list(match_counters *counters, char *string)
+{
+ size_t i;
+ match_expression *expr;
+/* match_counter *mc;*/
+ size_t lastpos = 0;
+ char *substring;
+
+ /*printf("Parsing match list: '%s'\n", string);*/
+
+ for (i = 0; i < strlen(string); i++) {
+ if (string[i] == ',') {
+ if (i<2) {
+ fprintf(stderr, "Matchlist cannot start with ,\n");
+ return false;
+ } else {
+ substring = malloc(strlen(string)+1);
+ strncpy(substring, &string[lastpos], i - lastpos + 1);
+ substring[i - lastpos] = '\0';
+ expr = parse_match_expression(substring);
+ if (!expr) {
+ return false;
+ }
+ free(substring);
+ /*
+ if (expr->op != MATCH_EXPR_LEAF) {
+ fprintf(stderr, "Matchlist can only contain <match>, not a logic expression\n");
+ return false;
+ }
+ */
+ add_match_counter(counters, expr, false);
+ lastpos = i+1;
+ }
+ }
+ }
+ substring = malloc(strlen(string) + 1);
+ strncpy(substring, &string[lastpos], i - lastpos + 1);
+ substring[i - lastpos] = '\0';
+ expr = parse_match_expression(substring);
+
+ if (!expr) {
+ fprintf(stderr, "Bad match: %s\n", substring);
+ return false;
+ }
+ free(substring);
+ /*
+ if (expr->op != MATCH_EXPR_LEAF) {
+ fprintf(stderr, "Matchlist can only contain <match>, not a logic expression\n");
+ return false;
+ }
+ */
+ add_match_counter(counters, expr, false);
+ return true;
+}
+
+bool
+parse_uniques(match_id ids[], size_t *count, char *string)
+{
+ size_t i, j, lastpos;
+ char *str, *strpart;
+ match_table *mt;
+
+ /*printf("Parsing unique counts: '%s'\n", string);*/
+ str = malloc(strlen(string) + 1);
+ j = 0;
+ for (i = 0; i < strlen(string); i++) {
+ if (!isspace(string[i])) {
+ str[j] = string[i];
+ j++;
+ }
+ }
+ str[j] = '\0';
+
+ lastpos = 0;
+ for (i = 0; i <= strlen(str); i++) {
+ if (str[i] == ',' || i >= strlen(str)) {
+ strpart = malloc(i - lastpos + 1);
+ strncpy(strpart, &str[lastpos], i - lastpos);
+ strpart[i - lastpos] = '\0';
+ if ((mt = get_match_by_name(strpart))) {
+ ids[*count] = mt->id;
+ *count = *count + 1;
+ } else {
+ printf("Error parsing match list; unknown match name: %s\n", strpart);
+ return false;
+ }
+ free(strpart);
+ lastpos = i + 1;
+ }
+ }
+ if (i > lastpos) {
+ strpart = malloc(i - lastpos + 1);
+ strncpy(strpart, &str[lastpos], i - lastpos);
+ strpart[i - lastpos] = '\0';
+ if ((mt = get_match_by_name(strpart))) {
+ ids[*count] = mt->id;
+ *count = *count + 1;
+ } else {
+ printf("Error parsing match list; unknown match name: %s\n", strpart);
+ return false;
+ }
+ free(strpart);
+ lastpos = i + 1;
+ }
+ free(str);
+ return true;
+}
+
+int main(int argc, char *argv[]) {
+
+ int i;
+ int status = EXIT_SUCCESS;
+ match_counters *count = malloc(sizeof(match_counters));
+ const char *inputfile = NULL;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ pcap_t *pc = NULL;
+ const u_char *cur;
+ struct pcap_pkthdr cur_hdr;
+ match_expression *expr = NULL;
+ match_id unique_ids[MAX_MATCHES];
+ size_t unique_id_count = 0; /* number of unique counters */
+ match_counters *uniques = malloc(sizeof(match_counters));
+ char *dumpfile = NULL;
+ char *hexdumpfilename = NULL;
+ char *not_ip_dumpfile = NULL;
+ char *bad_dns_dumpfile = NULL;
+
+ bool show_percentages = false;
+ bool show_averages = false;
+ bool show_average_count = false;
+ int unique_minimum = 0;
+
+ count->left = NULL;
+ count->match = NULL;
+ count->right = NULL;
+ uniques->left = NULL;
+ uniques->match = NULL;
+ uniques->right = NULL;
+
+ fragment_p = malloc(sizeof(struct fragment_part));
+ fragment_p->ip_id = 0;
+ fragment_p->cur_len = 0;
+
+ for (i = 1; i < argc; i++) {
+
+ if (strncmp(argv[i], "-baddns", 8) == 0) {
+ if (i + 1 < argc) {
+ bad_dns_dumpfile = argv[i + 1];
+ i++;
+ } else {
+ usage(stderr);
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ } else if (strncmp(argv[i], "-notip", 7) == 0) {
+ if (i + 1 < argc) {
+ not_ip_dumpfile = argv[i + 1];
+ i++;
+ } else {
+ usage(stderr);
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ } else if (strncmp(argv[i], "-c", 3) == 0) {
+ if (i + 1 < argc) {
+ if (!parse_match_list(count, argv[i + 1])) {
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ i++;
+ } else {
+ usage(stderr);
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ } else if (strncmp(argv[i], "-f", 3) == 0) {
+ if (i + 1 < argc) {
+ if (expr || strchr(argv[i+1], ',')) {
+ fprintf(stderr, "You can only specify 1 filter expression.\n");
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ expr = parse_match_expression(argv[i + 1]);
+ i++;
+ } else {
+ usage(stderr);
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ } else if (strncmp(argv[i], "-h", 3) == 0) {
+ usage(stdout);
+ status = EXIT_SUCCESS;
+ goto exit;
+ } else if (strncmp(argv[i], "-p", 3) == 0) {
+ show_percentages = true;
+ } else if (strncmp(argv[i], "-of", 4) == 0) {
+ if (i + 1 < argc) {
+ dumpfile = argv[i + 1];
+ i++;
+ } else {
+ usage(stderr);
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ } else if (strncmp(argv[i], "-ofh", 5) == 0) {
+ if (i + 1 < argc) {
+ hexdumpfilename = argv[i + 1];
+ i++;
+ } else {
+ usage(stderr);
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ } else if (strncmp(argv[i], "-s", 3) == 0) {
+ if (i + 1 < argc) {
+ show_match_names(argv[i + 1]);
+ } else {
+ show_match_names(NULL);
+ }
+ status = EXIT_SUCCESS;
+ goto exit;
+ } else if (strncmp(argv[i], "-sf", 4) == 0) {
+ show_filter_matches = true;
+ } else if (strncmp(argv[i], "-u", 3) == 0) {
+ if (i + 1 < argc) {
+ if (!parse_uniques(unique_ids, &unique_id_count, argv[i + 1])) {
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ i++;
+ } else {
+ usage(stderr);
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ } else if (strcmp("-ua", argv[i]) == 0) {
+ show_averages = true;
+ } else if (strcmp("-uac", argv[i]) == 0) {
+ show_average_count = true;
+ } else if (strcmp("-um", argv[i]) == 0) {
+ if (i + 1 < argc) {
+ unique_minimum = atoi(argv[i+1]);
+ i++;
+ } else {
+ fprintf(stderr, "-um requires an argument");
+ usage(stderr);
+ status = EXIT_FAILURE;
+ goto exit;
+ }
+ } else if (strcmp("-v", argv[i]) == 0) {
+ i++;
+ if (i < argc) {
+ verbosity = atoi(argv[i]);
+ }
+ } else if (strcmp("-version", argv[i]) == 0) {
+ printf("dns packet analyzer, version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
+ goto exit;
+ } else {
+ if (inputfile) {
+ fprintf(stderr, "You can only specify 1 input file\n");
+ exit(1);
+ }
+ inputfile = argv[i];
+ }
+ }
+
+ if (!inputfile) {
+ inputfile = "-";
+ }
+
+ if (verbosity >= 5) {
+ printf("Filter:\n");
+ print_match_expression(stdout, expr);
+ printf("\n\n");
+ }
+
+ pc = pcap_open_offline(inputfile, errbuf);
+
+ if (!pc) {
+ if (errno != 0) {
+ printf("Error opening pcap file %s: %s\n", inputfile, errbuf);
+ exit(1);
+ } else {
+ goto showresult;
+ }
+ }
+
+ if (dumpfile) {
+ dumper = pcap_dump_open(pc, dumpfile);
+
+ if (!dumper) {
+ printf("Error opening pcap dump file %s: %s\n", dumpfile, errbuf);
+ exit(1);
+ }
+ }
+
+ if (hexdumpfilename) {
+ if (strncmp(hexdumpfilename, "-", 2) != 0) {
+ printf("hexdump is file\n");
+ hexdumpfile = fopen(hexdumpfilename, "w");
+ } else {
+ printf("hexdump is stdout\n");
+ hexdumpfile = stdout;
+ }
+
+ if (!hexdumpfile) {
+ printf("Error opening hex dump file %s: %s\n", hexdumpfilename, strerror(errno));
+ exit(1);
+ }
+ }
+
+ if (not_ip_dumpfile) {
+ not_ip_dump = pcap_dump_open(pc, not_ip_dumpfile);
+ if (!not_ip_dump) {
+ printf("Error opening pcap dump file NOT_IP: %s\n", errbuf);
+ }
+ }
+ if (bad_dns_dumpfile) {
+ bad_dns_dump = pcap_dump_open(pc, bad_dns_dumpfile);
+ if (!bad_dns_dump) {
+ printf("Error opening pcap dump file NOT_IP: %s\n", errbuf);
+ }
+ }
+
+ while ((cur = pcap_next(pc, &cur_hdr))) {
+ if (verbosity >= 5) {
+ printf("\n\n\n[PKT_HDR] caplen: %u \tlen: %u\n", (unsigned int)cur_hdr.caplen, (unsigned int)cur_hdr.len);
+ }
+ handle_ether_packet(cur, cur_hdr, count, expr, uniques, unique_ids, unique_id_count);
+ }
+
+ if (not_ip_dump) {
+ pcap_dump_close(not_ip_dump);
+ }
+
+ if (bad_dns_dump) {
+ pcap_dump_close(bad_dns_dump);
+ }
+
+ if (dumper) {
+ pcap_dump_close(dumper);
+ }
+
+ if (hexdumpfile && hexdumpfile != stdout) {
+ fclose(hexdumpfile);
+ }
+
+ pcap_close(pc);
+
+ showresult:
+ if (show_percentages) {
+ fprintf(stdout, "Packets that are not IP: %u\n", (unsigned int) not_ip_packets);
+ fprintf(stdout, "bad dns packets: %u\n", (unsigned int) bad_dns_packets);
+ fprintf(stdout, "arp packets: %u\n", (unsigned int) arp_packets);
+ fprintf(stdout, "udp packets: %u\n", (unsigned int) udp_packets);
+ fprintf(stdout, "tcp packets (skipped): %u\n", (unsigned int) tcp_packets);
+ fprintf(stdout, "reassembled fragmented packets: %u\n", (unsigned int) fragmented_packets);
+ fprintf(stdout, "packet fragments lost: %u\n", (unsigned int) lost_packet_fragments);
+ fprintf(stdout, "Total number of DNS packets: %u\n", (unsigned int) total_nr_of_dns_packets);
+ fprintf(stdout, "Total number of DNS packets after filter: %u\n", (unsigned int) total_nr_of_filtered_packets);
+ }
+ if (count->match) {
+ print_counters(stdout, count, show_percentages, total_nr_of_filtered_packets, 0);
+ }
+ if (uniques->match) {
+ print_counters(stdout, uniques, show_percentages, total_nr_of_filtered_packets, unique_minimum);
+ if (show_averages) {
+ print_counter_averages(stdout, uniques, NULL);
+ }
+ if (show_average_count) {
+ print_counter_average_count(stdout, uniques, NULL, true);
+ }
+ }
+
+ exit:
+
+ free_match_expression(expr);
+ free_counters(count);
+ free_counters(uniques);
+
+ return status;
+}
+
+#else
+int main() {
+ fprintf(stderr, "ldns-dpa was not built because there is no pcap library on this system, or there was no pcap header file at compilation time. Please install pcap and rebuild.\n");
+ return 1;
+}
+#endif
+#else
+int main() {
+ fprintf(stderr, "ldns-dpa was not built because there is no pcap library on this system, or there was no pcap header file at compilation time. Please install pcap and rebuild.\n");
+ return 1;
+}
+#endif
+
+
diff --git a/examples/ldns-dpa.h b/examples/ldns-dpa.h
new file mode 100644
index 000000000000..b56530d0ef0e
--- /dev/null
+++ b/examples/ldns-dpa.h
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_PCAP_H
+#include <pcap.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_NETINET_IF_ETHER_H
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+#define USE_WINSOCK 1
+#include <winsock2.h>
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+#ifndef HAVE_GETADDRINFO
+#include <fake-rfc2553.h>
+#endif
+
+#ifndef HAVE_RANDOM
+/* random can be replaced by rand for ldnsexamples */
+#define random rand
+#endif
+
+#ifndef HAVE_SRANDOM
+/* srandom can be replaced by srand for ldnsexamples */
+#define srandom srand
+#endif
+
+extern char *optarg;
+extern int optind, opterr;
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+
+#ifdef S_SPLINT_S
+#define FD_ZERO(a) /* a */
+#define FD_SET(a,b) /* a, b */
+#endif
+
diff --git a/examples/ldns-gen-zone.1 b/examples/ldns-gen-zone.1
new file mode 100644
index 000000000000..5e7129b88922
--- /dev/null
+++ b/examples/ldns-gen-zone.1
@@ -0,0 +1,98 @@
+.TH ldns-gen-zone 1 "10 June 2010"
+.SH NAME
+ldns-gen-zone \- read a zonefile and print it while adding DS records and extra RR's
+.SH SYNOPSIS
+.B ldns-gen-zone
+.IR ZONEFILE
+
+.SH DESCRIPTION
+
+\fBldns-gen-zone\fR reads a DNS zone file and prints it.
+
+It is build for speed, not for a nice formatting. The output
+has one resource record per line and no pretty-printing makeup.
+
+DNSSEC data (NSEC, NSEC3, RRSIG or DNSKEY) is not stripped. You may want to
+use \fBldns-read-zone\fR for that. Existing DS records are also not stripped.
+
+The idea is to use this tool for quickly generating a representative
+artificial zonefile from a real zonefile, to use it for testing purposes.
+
+.SH OPTIONS
+.TP
+\fB-a NUM\fR
+Adds NUM extra artificial NS RRSets to the output.
+The RRSets owner names start
+with 'xn--' in an attempt to ensure uniqueness (nl.-zone does not support
+IDN's - and this tool was written with that knowledge in mind).
+
+An artificial NS RRSet has two NS records; ns1.example.com and
+ns2.example.com.
+
+.TP
+\fB-p NUM\fR
+Add NUM% of DS RRSets to the NS RRSets (anywhere between
+1-4 DS records per RRSet).
+
+.TP
+\fB-o ORIGIN\fR
+Sets an $ORIGIN, which can be handy if the one in the zonefile
+is set to '@' for example. If there is an $ORIGIN in the zonefile,
+this option will silently be ignored.
+
+.TP
+\fB-s\fR
+This is the recommended way of processing large zones that
+are already sorted and canonicalized (ie lowercase). It skips the
+sorting and canonicalization step that is required for properly
+grouping RRSets together (before adding any DS records to them. Skipping
+this step will speed things up.
+
+It is not recommended to use this option if you want to add DS records
+to unsorted, non-canonicalized zones.
+
+.TP
+\fB-h\fR
+Show usage and exit.
+
+.TP
+\fB-v\fR
+Show version and exit.
+
+.SH EXAMPLES
+
+.TP
+\fBldns-gen-zone -a 100000 -p 10 -s ./zonefile.txt\fR
+Read a zonefile, add 100.000 artificial NS RRSets and 10% of DS records,
+print it to standard output. Don't sort (will only work well if the input
+zonefile is already sorted and canonicalized).
+
+.TP
+\fBldns-gen-zone -p 10 -s -o nl zonefile.txt | named-compilezone -s relative -i none -o zonefile_10.txt nl /dev/stdin\fR
+This creates a nicely formatted zone file with the help of \fBnamed-compilezone\fR.
+It adds 10% DS records to the .nl zone, reformats it and saves it as \fBzonefile_10.txt\fR.
+
+.SH AUTHOR
+Initially written by Marco Davids, several modifications added by Miek
+Gieben, both from SIDN.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH BUGS
+Only undiscovered ones.
+
+.SH CAVEATS
+May require a machine with a considerable amount of memory for large zone files.
+
+Fake DS records hashes are generated as digest type SHA-256 (RFC4509). Be aware not to change
+the DIGESTTYPE #define in the source code in anything else but 2 if you want
+to keep things realistic.
+
+Despite a number of efforts, this program is still not the fastest in the
+world.
+
+.SH COPYRIGHT
+Copyright (C) 2010 SIDN. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-gen-zone.c b/examples/ldns-gen-zone.c
new file mode 100644
index 000000000000..cf5e5fd8d7a5
--- /dev/null
+++ b/examples/ldns-gen-zone.c
@@ -0,0 +1,310 @@
+/*
+ * Reads a zone file from disk and prints it to stdout, one RR per line.
+ * Adds artificial DS records and RRs.
+ * For the purpose of generating a test zone file
+ *
+ * (c) SIDN 2010/2011 - Marco Davids/Miek Gieben
+ *
+ * See the LICENSE file for the license
+ */
+
+#include "config.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <ldns/ldns.h>
+#include <errno.h>
+
+#define NUM_DS 4 /* maximum of 4 DS records per delegation */
+#define ALGO 8 /* Algorithm to use for fake DS records - RSASHA256 - RFC5702 */
+#define DIGESTTYPE 2 /* Digest type to use for fake DS records - SHA-256 - RFC 4509 */
+
+
+/**
+ * Usage function.
+ *
+ */
+static void
+usage(FILE *fp, char *prog) {
+ fprintf(fp, "\n\nUsage: %s [-hsv] [-ap NUM] [-o ORIGIN] [<zonefile>]\n", prog);
+ fprintf(fp, "\tReads a zonefile and add some artificial NS RRsets and DS records.\n");
+ fprintf(fp, "\tIf no zonefile is given, the zone is read from stdin.\n");
+ fprintf(fp, "\t-a <NUM> add NUM artifical delegations (NS RRSets) to output.\n");
+ fprintf(fp, "\t-p <NUM> add NUM percent of DS RRset's to the NS RRsets (1-%d RR's per DS RRset).\n", NUM_DS);
+ fprintf(fp, "\t-o ORIGIN sets an $ORIGIN, which can be handy if the one in the zonefile is set to @.\n");
+ fprintf(fp, "\t-s if input zone file is already sorted and canonicalized (ie all lowercase),\n\t use this option to speed things up while inserting DS records.\n");
+ fprintf(fp, "\t-h show this text.\n");
+ fprintf(fp, "\t-v shows the version and exits.\n");
+ fprintf(fp, "\nif no file is given standard input is read.\n\n");
+}
+
+/**
+ * Insert the DS records, return the amount added.
+ *
+ */
+static int
+insert_ds(ldns_rdf *dsowner, uint32_t ttl)
+{
+ int d, dsrand;
+ int keytag = 0;
+ char *dsownerstr;
+ char digeststr[70];
+
+ /**
+ * Average the amount of DS records per delegation a little.
+ */
+ dsrand = 1+rand() % NUM_DS;
+ for(d = 0; d < dsrand; d++) {
+ keytag = 1+rand() % 65535;
+ /**
+ * Dynamic hashes method below is still too slow... 20% slower than a fixed string...
+ *
+ * We assume RAND_MAX is 32 bit, http://www.gnu.org/s/libc/manual/html_node/ISO-Random.html
+ * 2147483647 or 0x7FFFFFFF
+ */
+ snprintf(digeststr, 65,
+ "%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
+ (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX,
+ (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX,
+ (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX,
+ (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX,
+ (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX,
+ (unsigned) rand()%RAND_MAX);
+ dsownerstr = ldns_rdf2str(dsowner);
+ fprintf(stdout, "%s\t%u\tIN\tDS\t%d %d %d %s\n", dsownerstr, (unsigned) ttl, keytag, ALGO, DIGESTTYPE, digeststr);
+ }
+ return dsrand;
+}
+
+int
+main(int argc, char **argv) {
+ char *filename, *rrstr, *ownerstr;
+ const char *classtypestr1 = "IN NS ns1.example.com.";
+ const char *classtypestr2 = "IN NS ns2.example.com.";
+ const size_t classtypelen = strlen(classtypestr1);
+ /* Simply because this was developed by SIDN and we don't use xn-- for .nl :-) */
+ const char *punystr = "xn--fake-rr";
+ const size_t punylen = strlen(punystr);
+ size_t rrstrlen, ownerlen;
+ FILE *fp;
+ int c, nsrand;
+ uint32_t ttl;
+ int counta,countd,countr;
+ ldns_zone *z;
+ ldns_rdf *origin = NULL;
+ int line_nr = 0;
+ int addrrs = 0;
+ int dsperc = 0;
+ bool canonicalize = true;
+ bool sort = true;
+ bool do_ds = false;
+ ldns_status s;
+ size_t i;
+ ldns_rr_list *rrset_list;
+ ldns_rdf *owner;
+ ldns_rr_type cur_rr_type;
+ ldns_rr *cur_rr;
+ ldns_status status;
+
+ counta = countd = countr = 0;
+
+ /**
+ * Set some random seed.
+ */
+ srand((unsigned int)time(NULL));
+
+ /**
+ * Commandline options.
+ */
+ while ((c = getopt(argc, argv, "a:p:shvo:")) != -1) {
+ switch (c) {
+ case 'a':
+ addrrs = atoi(optarg);
+ if (addrrs <= 0) {
+ fprintf(stderr, "error\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'o':
+ origin = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, optarg);
+ if (!origin) {
+ fprintf(stderr, "error: creating origin from -o %s failed.\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'p':
+ dsperc = atoi(optarg);
+ if (dsperc <= 0 || dsperc > 100) {
+ fprintf(stderr, "error: percentage of signed delegations must be between [0-100].\n");
+ exit(EXIT_FAILURE);
+ }
+ do_ds = true;
+ break;
+ case 's':
+ sort = false;
+ canonicalize = false;
+ break;
+ case 'h':
+ usage(stdout, argv[0]);
+ exit(EXIT_SUCCESS);
+ case 'v':
+ fprintf(stdout, "ldns-gen-zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
+ exit(EXIT_SUCCESS);
+ default:
+ fprintf(stderr, "\nTry -h for more information.\n\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /**
+ * Read zone.
+ */
+ if (argc == 0) {
+ fp = stdin;
+ } else {
+ filename = argv[0];
+ fp = fopen(filename, "r");
+ if (!fp) {
+ fprintf(stderr, "Unable to open %s: %s\n", filename, strerror (errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+ s = ldns_zone_new_frm_fp_l(&z, fp, origin, 0, LDNS_RR_CLASS_IN, &line_nr);
+ if (s != LDNS_STATUS_OK) {
+ fprintf(stderr, "%s at %d\n", ldns_get_errorstr_by_id(s), line_nr);
+ exit(EXIT_FAILURE);
+ }
+ if (!ldns_zone_soa(z)) {
+ fprintf(stderr, "No zone data seen\n");
+ exit(EXIT_FAILURE);
+ }
+
+ ttl = ldns_rr_ttl(ldns_zone_soa(z));
+ if (!origin) {
+ origin = ldns_rr_owner(ldns_zone_soa(z));
+ // Check for root (.) origin here TODO(MG)
+ }
+ ownerstr = ldns_rdf2str(origin);
+ if (!ownerstr) {
+ fprintf(stderr, "ldns_rdf2str(origin) failed\n");
+ exit(EXIT_FAILURE);
+ }
+ ownerlen = strlen(ownerstr);
+
+ ldns_rr_print(stdout, ldns_zone_soa(z));
+
+ if (addrrs > 0) {
+ while (addrrs > counta) {
+ counta++;
+ rrstrlen = punylen + ownerlen + classtypelen + 4;
+ rrstrlen *= 2; /* estimate */
+ rrstr = (char*)malloc(rrstrlen);
+ if (!rrstr) {
+ fprintf(stderr, "malloc() failed: Out of memory\n");
+ exit(EXIT_FAILURE);
+ }
+ (void)snprintf(rrstr, rrstrlen, "%s%d.%s %u %s", punystr, counta,
+ ownerstr, (unsigned) ttl, classtypestr1);
+ status = ldns_rr_new_frm_str(&cur_rr, rrstr, 0, NULL, NULL);
+ if (status == LDNS_STATUS_OK) {
+ ldns_rr_print(stdout, cur_rr);
+ ldns_rr_free(cur_rr);
+ } else {
+ fprintf(stderr, "ldns_rr_new_frm_str() failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ (void)snprintf(rrstr, rrstrlen, "%s%d.%s %u %s", punystr, counta,
+ ownerstr, (unsigned) ttl, classtypestr2);
+ status = ldns_rr_new_frm_str(&cur_rr, rrstr, 0, NULL, NULL);
+ if (status == LDNS_STATUS_OK) {
+ ldns_rr_print(stdout, cur_rr);
+ } else {
+ fprintf(stderr, "ldns_rr_new_frm_str() failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ free(rrstr);
+
+ /* may we add a DS record as well? */
+ if (do_ds) {
+ /*
+ * Per definition this may not be the same as the origin, so no
+ * check required same for NS check - so the only thing left is some
+ * randomization.
+ */
+ nsrand = rand() % 100;
+ if (nsrand < dsperc) {
+ owner = ldns_rr_owner(cur_rr);
+ ttl = ldns_rr_ttl(cur_rr);
+ countd += insert_ds(owner, ttl);
+ }
+ }
+ ldns_rr_free(cur_rr);
+ }
+ }
+
+ if (!do_ds) {
+ ldns_rr_list_print(stdout, ldns_zone_rrs(z));
+ } else {
+ /*
+ * We use dns_rr_list_pop_rrset and that requires a sorted list weird things may happen
+ * if the -s option was used on unsorted, non-canonicalized input
+ */
+ if (canonicalize) {
+ ldns_rr2canonical(ldns_zone_soa(z));
+ for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) {
+ ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i));
+ }
+ }
+
+ if (sort) {
+ ldns_zone_sort(z);
+ }
+
+ /* Work on a per RRset basis for DS records - weird things will happen if the -s option
+ * was used in combination with an unsorted zone file
+ */
+ while((rrset_list = ldns_rr_list_pop_rrset(ldns_zone_rrs(z)))) {
+ owner = ldns_rr_list_owner(rrset_list);
+ cur_rr_type = ldns_rr_list_type(rrset_list);
+ /**
+ * Print them...
+ */
+ cur_rr = ldns_rr_list_pop_rr(rrset_list);
+ while (cur_rr) {
+ ttl = ldns_rr_ttl(cur_rr);
+ fprintf(stdout, "%s", ldns_rr2str(cur_rr));
+ cur_rr = ldns_rr_list_pop_rr(rrset_list);
+ }
+ /*
+ * And all the way at the end a DS record if
+ * we are dealing with an NS rrset
+ */
+ nsrand = rand() % 100;
+ if (nsrand == 0) {
+ nsrand = 100;
+ }
+
+ if ((cur_rr_type == LDNS_RR_TYPE_NS) &&
+ (ldns_rdf_compare(owner, origin) != 0) && (nsrand < dsperc)) {
+ /**
+ * No DS records for the $ORIGIN, only for delegations, obey dsperc.
+ */
+ countr++;
+ countd += insert_ds(owner, ttl);
+ }
+ ldns_rr_list_free(rrset_list);
+ ldns_rdf_free(owner);
+ }
+ }
+
+ /**
+ * And done...
+ */
+ fclose(fp);
+ fprintf(stdout, ";; Added %d DS records (percentage was %d) to %d NS RRset's (from input-zone: %d, from added: %d)\n;; lines in original input-zone: %d\n",
+ countd, dsperc, counta + countr, countr, counta, line_nr);
+ exit(EXIT_SUCCESS);
+}
diff --git a/examples/ldns-key2ds.1 b/examples/ldns-key2ds.1
new file mode 100644
index 000000000000..6fdbee5f1a3f
--- /dev/null
+++ b/examples/ldns-key2ds.1
@@ -0,0 +1,41 @@
+.TH ldns-key2ds 1 "30 May 2005"
+.SH NAME
+ldns-key2ds \- transform a DNSKEY RR to a DS RR
+.SH SYNOPSIS
+.B ldns-key2ds
+.IR file
+
+.SH DESCRIPTION
+\fBldns-key2ds\fR is used to transform a public DNSKEY RR to a DS RR.
+When run it will read \fIfile\fR with a DNSKEY RR in it and
+it will create a .ds file with the DS RR in it.
+
+It prints out the basename for this file (K<name>+<alg>+<id>).
+
+By default it takes a pick of algorithm similar to the key algorithm,
+SHA1 for RSASHA1, and so on.
+
+.SH OPTIONS
+.TP
+\fB-n\fR
+Write the result DS Resource Record to stdout instead of a file
+
+.TP
+\fB-1\fR
+Use SHA1 as the hash function.
+
+.TP
+\fB-2\fR
+Use SHA256 as the hash function
+
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-key2ds.c b/examples/ldns-key2ds.c
new file mode 100644
index 000000000000..a3e54383ab9c
--- /dev/null
+++ b/examples/ldns-key2ds.c
@@ -0,0 +1,199 @@
+/*
+ * key2ds transforms a public key into its DS
+ * It (currently) prints out the public key
+ *
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+
+#include <ldns/ldns.h>
+
+#include <errno.h>
+
+static void
+usage(FILE *fp, char *prog) {
+ fprintf(fp, "%s [-fn] [-1|-2] keyfile\n", prog);
+ fprintf(fp, " Generate a DS RR from the DNSKEYS in keyfile\n");
+ fprintf(fp, " The following file will be created: ");
+ fprintf(fp, "K<name>+<alg>+<id>.ds\n");
+ fprintf(fp, " The base name (K<name>+<alg>+<id> will be printed to stdout\n");
+ fprintf(fp, "Options:\n");
+ fprintf(fp, " -f: ignore SEP flag (i.e. make DS records for any key)\n");
+ fprintf(fp, " -n: do not write DS records to file(s) but to stdout\n");
+ fprintf(fp, " (default) use similar hash to the key algorithm.\n");
+ fprintf(fp, " -1: use SHA1 for the DS hash\n");
+ fprintf(fp, " -2: use SHA256 for the DS hash\n");
+#ifdef USE_GOST
+ fprintf(fp, " -g: use GOST for the DS hash\n");
+#endif
+#ifdef USE_ECDSA
+ fprintf(fp, " -4: use SHA384 for the DS hash\n");
+#endif
+}
+
+static int
+is_suitable_dnskey(ldns_rr *rr, int sep_only)
+{
+ if (!rr || ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY) {
+ return 0;
+ }
+ return !sep_only ||
+ (ldns_rdf2native_int16(ldns_rr_dnskey_flags(rr)) &
+ LDNS_KEY_SEP_KEY);
+}
+
+static ldns_hash
+suitable_hash(ldns_signing_algorithm algorithm)
+{
+ switch (algorithm) {
+ case LDNS_SIGN_RSASHA256:
+ case LDNS_SIGN_RSASHA512:
+ return LDNS_SHA256;
+ case LDNS_SIGN_ECC_GOST:
+#ifdef USE_GOST
+ return LDNS_HASH_GOST;
+#else
+ return LDNS_SHA256;
+#endif
+#ifdef USE_ECDSA
+ case LDNS_SIGN_ECDSAP256SHA256:
+ return LDNS_SHA256;
+ case LDNS_SIGN_ECDSAP384SHA384:
+ return LDNS_SHA384;
+#endif
+ default:
+ return LDNS_SHA1;
+ }
+ return LDNS_SHA1;
+}
+
+int
+main(int argc, char *argv[])
+{
+ FILE *keyfp, *dsfp;
+ char *keyname;
+ char *dsname;
+ char *owner;
+ ldns_rr *k, *ds;
+ ldns_signing_algorithm alg;
+ ldns_hash h;
+ int similar_hash=1;
+ char *program = argv[0];
+ int nofile = 0;
+ ldns_rdf *origin = NULL;
+ ldns_status result = LDNS_STATUS_OK;
+ int sep_only = 1;
+
+ alg = 0;
+ h = LDNS_SHA1;
+
+ argv++, argc--;
+ while (argc && argv[0][0] == '-') {
+ if (strcmp(argv[0], "-1") == 0) {
+ h = LDNS_SHA1;
+ similar_hash = 0;
+ }
+ if (strcmp(argv[0], "-2") == 0) {
+ h = LDNS_SHA256;
+ similar_hash = 0;
+ }
+#ifdef USE_GOST
+ if (strcmp(argv[0], "-g") == 0) {
+ if(!ldns_key_EVP_load_gost_id()) {
+ fprintf(stderr, "error: libcrypto does not provide GOST\n");
+ exit(EXIT_FAILURE);
+ }
+ h = LDNS_HASH_GOST;
+ similar_hash = 0;
+ }
+#endif
+#ifdef USE_ECDSA
+ if (strcmp(argv[0], "-4") == 0) {
+ h = LDNS_SHA384;
+ similar_hash = 0;
+ }
+#endif
+ if (strcmp(argv[0], "-f") == 0) {
+ sep_only = 0;
+ }
+ if (strcmp(argv[0], "-n") == 0) {
+ nofile=1;
+ }
+ argv++, argc--;
+ }
+
+ if (argc != 1) {
+ usage(stderr, program);
+ exit(EXIT_FAILURE);
+ }
+ keyname = strdup(argv[0]);
+
+ keyfp = fopen(keyname, "r");
+ if (!keyfp) {
+ fprintf(stderr, "Failed to open public key file %s: %s\n", keyname,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ while (result == LDNS_STATUS_OK) {
+ result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL);
+ while (result == LDNS_STATUS_SYNTAX_ORIGIN ||
+ result == LDNS_STATUS_SYNTAX_TTL ||
+ (result == LDNS_STATUS_OK && !is_suitable_dnskey(k, sep_only))
+ ) {
+ if (result == LDNS_STATUS_OK) {
+ ldns_rr_free(k);
+ }
+ result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL);
+ }
+ if (result == LDNS_STATUS_SYNTAX_EMPTY) {
+ /* we're done */
+ break;
+ }
+ if (result != LDNS_STATUS_OK) {
+ fprintf(stderr, "Could not read public key from file %s: %s\n", keyname, ldns_get_errorstr_by_id(result));
+ exit(EXIT_FAILURE);
+ }
+
+ owner = ldns_rdf2str(ldns_rr_owner(k));
+ alg = ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(k));
+ if(similar_hash)
+ h = suitable_hash(alg);
+
+ ds = ldns_key_rr2ds(k, h);
+ if (!ds) {
+ fprintf(stderr, "Conversion to a DS RR failed\n");
+ ldns_rr_free(k);
+ free(owner);
+ exit(EXIT_FAILURE);
+ }
+
+ /* print the public key RR to .key */
+ dsname = LDNS_XMALLOC(char, strlen(owner) + 16);
+ snprintf(dsname, strlen(owner) + 15, "K%s+%03u+%05u.ds", owner, alg, (unsigned int) ldns_calc_keytag(k));
+
+ if (nofile)
+ ldns_rr_print(stdout,ds);
+ else {
+ dsfp = fopen(dsname, "w");
+ if (!dsfp) {
+ fprintf(stderr, "Unable to open %s: %s\n", dsname, strerror(errno));
+ exit(EXIT_FAILURE);
+ } else {
+ ldns_rr_print(dsfp, ds);
+ fclose(dsfp);
+ fprintf(stdout, "K%s+%03u+%05u\n", owner, alg, (unsigned int) ldns_calc_keytag(k));
+ }
+ }
+
+ ldns_rr_free(ds);
+ ldns_rr_free(k);
+ free(owner);
+ LDNS_FREE(dsname);
+ }
+ fclose(keyfp);
+ free(keyname);
+ exit(EXIT_SUCCESS);
+}
diff --git a/examples/ldns-keyfetcher.1 b/examples/ldns-keyfetcher.1
new file mode 100644
index 000000000000..6ddc14eacf88
--- /dev/null
+++ b/examples/ldns-keyfetcher.1
@@ -0,0 +1,64 @@
+.TH ldns-keyfetcher 1 "4 Apr 2006"
+.SH NAME
+ldns-keyfetcher \- retrieve the DNSSEC DNSKEYs for a zone
+.SH SYNOPSIS
+.B ldns-keyfetcher
+[
+.IR OPTIONS
+]
+.IR DOMAIN
+
+.SH DESCRIPTION
+\fBldns-keyfetcher\fR is used to retrieve the DNSKEYs of a zone.
+
+First it finds all authoritative nameservers of the zone by tracing it from
+the root down. All authoritative nameservers are then queried (using TCP)
+for the DNSKEY RRset of the zone apex. If the results are all the same,
+the key resource record set is printed.
+
+
+.SH OPTIONS
+\fB-4\fR \fI\fR
+Only use IPv4
+
+\fB-6\fR \fI\fR
+Only use IPv6
+
+\fB-h\fR \fI\fR
+Show a help text and exit
+
+\fB-i\fR
+Insecurer mode; there will only be one query for the DNSKEYS. There will not
+be crosschecking of all authoritative nameservers.
+
+\fB-v\fR \fIverbosity\fR
+
+Set the verbosity level. The following levels are available:
+
+ 0: default, only print the DNSKEY RRset found, or an error on failure.
+ 1: Show the nameservers that are queried
+ 2: Show more info on what is checked
+ 3: Show the intermediate results (authority and dnskey rrsets)
+ 4: Print the answer packets that are returned
+
+\fB-r\fR \fIfile\fR
+
+Use file as the root hints file, should contain A records in presentation
+format. The default is /etc/named.root. You can get this file from
+http://www.internic.net/zones/named.root.
+
+\fB-s\fR \fI\fR
+Don't print the keys to stdout, but store them in files.
+
+The filenames will be of the format K<file>.+<alg>.+<keytag>.key
+
+.SH AUTHOR
+Written by Jelte Jansen for NLnet Labs.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2006 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-keyfetcher.c b/examples/ldns-keyfetcher.c
new file mode 100644
index 000000000000..267822f8868f
--- /dev/null
+++ b/examples/ldns-keyfetcher.c
@@ -0,0 +1,722 @@
+/*
+ * ldns-keyfetcher retrieves the DNSKEYS for a certain domain
+ * It traces the authoritatives nameservers down from the root
+ * And uses TCP, to minimize spoofing danger.
+ *
+ * (c) NLnet Labs, 2006 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <ldns/ldns.h>
+#include <errno.h>
+
+int verbosity = 0;
+/* 0=use both ip4 and ip6 (default). 1=ip4only. 2=ip6only. */
+uint8_t address_family = 0;
+bool store_in_file = false;
+
+static void
+usage(FILE *fp, char *prog) {
+ fprintf(fp, "%s domain\n", prog);
+ fprintf(fp, " retrieve the dnskeys for a domain\n");
+ fprintf(fp, "Options:\n");
+ fprintf(fp, "-4\t\tUse IPv4 only\n");
+ fprintf(fp, "-6\t\tUse IPv6 only\n");
+ fprintf(fp, "-h\t\tShow this help\n");
+ fprintf(fp, "-i\t\tInsecurer mode; don't do checks, just query for the keys\n");
+ fprintf(fp, "-r <file>\tUse file to read root hints from\n");
+ fprintf(fp, "-s\t\tDon't print the keys but store them in files\n\t\tcalled K<file>.+<alg>.+<keytag>.key\n");
+ fprintf(fp, "-v <int>\tVerbosity level (0-5, not verbose-very verbose)\n");
+}
+
+static ldns_rr_list *
+retrieve_dnskeys(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
+ ldns_rr_class c, ldns_rr_list *dns_root)
+{
+ ldns_resolver *res;
+ ldns_pkt *p;
+ ldns_rr_list *new_nss_a;
+ ldns_rr_list *new_nss_aaaa;
+ ldns_rr_list *new_nss;
+ ldns_rr_list *ns_addr;
+ ldns_rr_list *ns_addr2;
+ uint16_t loop_count;
+ ldns_rdf *pop;
+ ldns_status status;
+ size_t i;
+
+ size_t nss_i;
+ ldns_rr_list *answer_list = NULL;
+ ldns_rr_list *authority_list = NULL;
+
+ size_t last_nameserver_count;
+ ldns_rdf **last_nameservers;
+
+ loop_count = 0;
+ new_nss_a = NULL;
+ new_nss_aaaa = NULL;
+ new_nss = NULL;
+ ns_addr = NULL;
+ ns_addr2 = NULL;
+ p = ldns_pkt_new();
+ res = ldns_resolver_new();
+
+ if (!p || !res) {
+ fprintf(stderr, "Memory allocation failed");
+ return NULL;
+ }
+
+ if (verbosity >= 2) {
+ printf("Finding dnskey data for zone: ");
+ ldns_rdf_print(stdout, name);
+ printf("\n\n");
+ }
+
+ /* transfer some properties of local_res to res,
+ * because they were given on the commandline */
+ ldns_resolver_set_ip6(res,
+ ldns_resolver_ip6(local_res));
+ ldns_resolver_set_port(res,
+ ldns_resolver_port(local_res));
+ ldns_resolver_set_debug(res,
+ ldns_resolver_debug(local_res));
+ ldns_resolver_set_dnssec(res,
+ ldns_resolver_dnssec(local_res));
+ ldns_resolver_set_fail(res,
+ ldns_resolver_fail(local_res));
+ ldns_resolver_set_usevc(res,
+ ldns_resolver_usevc(local_res));
+ ldns_resolver_set_random(res,
+ ldns_resolver_random(local_res));
+ ldns_resolver_set_recursive(res, false);
+
+ /* setup the root nameserver in the new resolver */
+ status = ldns_resolver_push_nameserver_rr_list(res, dns_root);
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error setting root nameservers in resolver: %s\n", ldns_get_errorstr_by_id(status));
+ return NULL;
+ }
+
+ ldns_pkt_free(p);
+ status = ldns_resolver_send(&p, res, name, t, c, 0);
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status));
+ return NULL;
+ }
+
+ if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
+ printf("Error in packet:\n");
+ ldns_pkt_print(stdout, p);
+ return NULL;
+ }
+
+ if (verbosity >= 4) {
+ ldns_pkt_print(stdout, p);
+ printf("\n\n");
+ }
+
+ /* from now on, use TCP */
+ ldns_resolver_set_usevc(res, true);
+
+ while(status == LDNS_STATUS_OK &&
+ ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) {
+
+ if (verbosity >= 3) {
+ printf("This is a delegation!\n\n");
+ }
+ if (address_family == 0 || address_family == 1) {
+ new_nss_a = ldns_pkt_rr_list_by_type(p,
+ LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL);
+ } else {
+ new_nss_a = ldns_rr_list_new();
+ }
+ if (address_family == 0 || address_family == 2) {
+ new_nss_aaaa = ldns_pkt_rr_list_by_type(p,
+ LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL);
+ } else {
+ new_nss_aaaa = ldns_rr_list_new();
+ }
+ new_nss = ldns_pkt_rr_list_by_type(p,
+ LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY);
+
+ /* remove the old nameserver from the resolver */
+ while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }
+
+ /* also check for new_nss emptyness */
+
+ if (!new_nss_aaaa && !new_nss_a) {
+ /*
+ * no nameserver found!!!
+ * try to resolve the names we do got
+ */
+ if (verbosity >= 3) {
+ printf("Did not get address record for nameserver, doing seperate query.\n");
+ }
+ ns_addr = ldns_rr_list_new();
+ for(i = 0; (size_t) i < ldns_rr_list_rr_count(new_nss); i++) {
+ /* get the name of the nameserver */
+ pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0);
+ if (!pop) {
+ break;
+ }
+
+ /* retrieve it's addresses */
+ ns_addr2 = ldns_get_rr_list_addr_by_name(local_res, pop, c, 0);
+ if (!ldns_rr_list_cat(ns_addr, ns_addr2)) {
+ fprintf(stderr, "Internal error adding nameserver address.\n");
+ exit(EXIT_FAILURE);
+ }
+ ldns_rr_list_free(ns_addr2);
+ }
+
+ if (ns_addr) {
+ if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) !=
+ LDNS_STATUS_OK) {
+ fprintf(stderr, "Error adding new nameservers");
+ ldns_pkt_free(p);
+ return NULL;
+ }
+ ldns_rr_list_deep_free(ns_addr);
+ } else {
+ ldns_rr_list_print(stdout, ns_addr);
+ fprintf(stderr, "Could not find the nameserver ip addr; abort");
+ ldns_pkt_free(p);
+ return NULL;
+ }
+ }
+
+ /* normally, the first working ns is used, but we need all now, so do it one by one
+ * if the answer is null, take it from the next resolver
+ * if the answer is not, compare it to that of the next resolver
+ * error if different, continue if the same
+ * if answer list null and no resolvers left die.
+ */
+
+ ldns_rr_list_deep_free(answer_list);
+ ldns_rr_list_deep_free(authority_list);
+ answer_list = NULL;
+ authority_list = NULL;
+ for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_aaaa); nss_i++) {
+ while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }
+
+ status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0));
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
+ }
+
+ if (verbosity >= 1) {
+ fprintf(stdout, "Querying nameserver: ");
+ ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_aaaa, nss_i)));
+ fprintf(stdout, " (");
+ ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0));
+ fprintf(stdout, ")\n");
+ }
+ status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0));
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
+ }
+
+ ldns_pkt_free(p);
+ status = ldns_resolver_send(&p, res, name, t, c, 0);
+ if (status == LDNS_STATUS_OK && p) {
+ if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
+ printf("Error in packet:\n");
+ ldns_pkt_print(stdout, p);
+ return NULL;
+ }
+
+ if (verbosity >= 4) {
+ ldns_pkt_print(stdout, p);
+ printf("\n\n");
+ }
+
+ if (answer_list) {
+ if (verbosity >= 2) {
+ printf("Comparing answer list of answer to previous\n\n");
+ }
+ ldns_rr_list_sort(ldns_pkt_answer(p));
+ ldns_rr_list_sort(answer_list);
+ if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) {
+ fprintf(stderr, "ERROR: different answer answer from nameserver\n");
+ fprintf(stderr, "\nI had (from previous servers):\n");
+ ldns_rr_list_print(stderr, answer_list);
+ fprintf(stderr, "\nI received (from nameserver at ");
+ ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
+ fprintf(stderr, "):\n");
+ ldns_rr_list_print(stderr, ldns_pkt_answer(p));
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ answer_list = ldns_rr_list_clone(ldns_pkt_answer(p));
+ ldns_rr_list_sort(answer_list);
+ if (verbosity >= 2) {
+ printf("First answer list for this set, nothing to compare with\n\n");
+ }
+ }
+ if (authority_list) {
+ if (verbosity >= 2) {
+ printf("Comparing authority list of answer to previous\n\n");
+ }
+ ldns_rr_list_sort(ldns_pkt_authority(p));
+ ldns_rr_list_sort(authority_list);
+ if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) {
+ fprintf(stderr, "ERROR: different authority answer from nameserver\n");
+ fprintf(stderr, "\nI had (from previous servers):\n");
+ ldns_rr_list_print(stderr, authority_list);
+ fprintf(stderr, "\nI received (from nameserver at ");
+ ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
+ fprintf(stderr, "):\n");
+ ldns_rr_list_print(stderr, ldns_pkt_authority(p));
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ authority_list = ldns_rr_list_clone(ldns_pkt_authority(p));
+ ldns_rr_list_sort(authority_list);
+ if (verbosity >= 2) {
+ printf("First authority list for this set, nothing to compare with\n\n");
+ }
+ if (verbosity >= 3) {
+ printf("NS RRset:\n");
+ ldns_rr_list_print(stdout, authority_list);
+ printf("\n");
+ }
+ }
+ }
+ }
+
+ ldns_rr_list_deep_free(answer_list);
+ ldns_rr_list_deep_free(authority_list);
+ answer_list = NULL;
+ authority_list = NULL;
+ for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_a); nss_i++) {
+
+ while((pop = ldns_resolver_pop_nameserver(res))) {ldns_rdf_deep_free(pop); }
+
+ if (verbosity >= 1) {
+ fprintf(stdout, "Querying nameserver: ");
+ ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_a, nss_i)));
+ fprintf(stdout, " (");
+ ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0));
+ fprintf(stdout, ")\n");
+ }
+ status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0));
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
+ }
+
+ ldns_pkt_free(p);
+ status = ldns_resolver_send(&p, res, name, t, c, 0);
+
+ if (status == LDNS_STATUS_OK) {
+ if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
+ printf("Error in packet:\n");
+ ldns_pkt_print(stdout, p);
+ return NULL;
+ }
+
+ if (verbosity >= 4) {
+ ldns_pkt_print(stdout, p);
+ printf("\n\n");
+ }
+
+ if (answer_list) {
+ if (verbosity >= 2) {
+ printf("Comparing answer list of answer to previous\n\n");
+ }
+ ldns_rr_list_sort(ldns_pkt_answer(p));
+ ldns_rr_list_sort(answer_list);
+ if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) {
+ fprintf(stderr, "ERROR: different answer answer from nameserver\n");
+ fprintf(stderr, "\nI had (from previous servers):\n");
+ ldns_rr_list_print(stderr, answer_list);
+ fprintf(stderr, "\nI received (from nameserver at ");
+ ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
+ fprintf(stderr, "):\n");
+ ldns_rr_list_print(stderr, ldns_pkt_answer(p));
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ if (verbosity >= 2) {
+ printf("First answer list for this set, nothing to compare with\n\n");
+ }
+ answer_list = ldns_rr_list_clone(ldns_pkt_answer(p));
+ ldns_rr_list_sort(answer_list);
+ }
+ if (authority_list) {
+ if (verbosity >= 2) {
+ printf("Comparing authority list of answer to previous\n\n");
+ }
+ ldns_rr_list_sort(ldns_pkt_authority(p));
+ ldns_rr_list_sort(authority_list);
+ if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) {
+ fprintf(stderr, "ERROR: different authority answer from nameserver\n");
+ fprintf(stderr, "\nI had (from previous servers):\n");
+ ldns_rr_list_print(stderr, authority_list);
+ fprintf(stderr, "\nI received (from nameserver at ");
+ ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
+ fprintf(stderr, "):\n");
+ ldns_rr_list_print(stderr, ldns_pkt_authority(p));
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ if (verbosity >= 2) {
+ printf("First authority list for this set, nothing to compare with\n\n");
+ }
+ authority_list = ldns_rr_list_clone(ldns_pkt_authority(p));
+ ldns_rr_list_sort(authority_list);
+ if (verbosity >= 3) {
+ printf("NS RRset:\n");
+ ldns_rr_list_print(stdout, authority_list);
+ printf("\n");
+ }
+ }
+ }
+ }
+ ldns_rr_list_deep_free(authority_list);
+ authority_list = NULL;
+
+ if (loop_count++ > 20) {
+ /* unlikely that we are doing something usefull */
+ fprintf(stderr, "Looks like we are looping");
+ ldns_pkt_free(p);
+ return NULL;
+ }
+
+ ldns_pkt_free(p);
+
+ if (verbosity >= 3) {
+ fprintf(stdout, "This level ok. Continuing to next.\n\n");
+ }
+
+ status = ldns_resolver_send(&p, res, name, t, c, 0);
+
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status));
+ return NULL;
+ }
+
+ if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
+ printf("Error in packet:\n");
+ ldns_pkt_print(stdout, p);
+ return NULL;
+ }
+
+ if (verbosity >= 4) {
+ ldns_pkt_print(stdout, p);
+ printf("\n\n");
+ }
+
+
+ ldns_rr_list_deep_free(new_nss_aaaa);
+ ldns_rr_list_deep_free(new_nss_a);
+ ldns_rr_list_deep_free(new_nss);
+ new_nss_aaaa = NULL;
+ new_nss_a = NULL;
+ ns_addr = NULL;
+ }
+
+ ldns_rr_list_deep_free(answer_list);
+ answer_list = NULL;
+ /* clone the nameserver list, we are going to handle them one by one */
+ last_nameserver_count = 0;
+ last_nameservers = LDNS_XMALLOC(ldns_rdf *, ldns_resolver_nameserver_count(res));
+
+ pop = NULL;
+ while((pop = ldns_resolver_pop_nameserver(res))) {
+ last_nameservers[last_nameserver_count] = pop;
+ last_nameserver_count++;
+ }
+
+ for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) {
+ /* remove previous nameserver */
+ while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }
+
+ if (verbosity >= 1) {
+ printf("Querying nameserver: ");
+ ldns_rdf_print(stdout, last_nameservers[nss_i]);
+ printf("\n");
+ }
+ status = ldns_resolver_push_nameserver(res, last_nameservers[nss_i]);
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
+ }
+
+ ldns_pkt_free(p);
+ status = ldns_resolver_send(&p, res, name, t, c, 0);
+
+ if (!p) {
+ fprintf(stderr, "no packet received\n");
+ return NULL;
+ }
+
+ if (status == LDNS_STATUS_RES_NO_NS) {
+ fprintf(stderr, "Error: nameserver at ");
+ ldns_rdf_print(stderr, last_nameservers[nss_i]);
+ fprintf(stderr, " not responding. Unable to check RRset here, aborting.\n");
+ return NULL;
+ }
+
+ if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
+ printf("Error in packet:\n");
+ ldns_pkt_print(stdout, p);
+ return NULL;
+ }
+
+ if (answer_list) {
+ if (verbosity >= 2) {
+ printf("1Comparing answer rr list of answer to previous\n");
+ }
+ ldns_rr_list_sort(ldns_pkt_answer(p));
+ ldns_rr_list_sort(answer_list);
+ if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) {
+ printf("ERROR: different answer section in response from nameserver\n");
+ fprintf(stderr, "\nI had:\n");
+ ldns_rr_list_print(stderr, answer_list);
+ fprintf(stderr, "\nI received (from nameserver at ");
+ ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
+ fprintf(stderr, "):\n");
+ ldns_rr_list_print(stderr, ldns_pkt_answer(p));
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ if (verbosity >= 2) {
+ printf("First answer rr list for this set, nothing to compare with\n");
+ }
+ answer_list = ldns_rr_list_clone(ldns_pkt_answer(p));
+ if (verbosity >= 3) {
+ printf("DNSKEY RRset:\n");
+ ldns_rr_list_print(stdout, answer_list);
+ }
+ }
+
+ }
+
+ for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) {
+ ldns_rdf_deep_free(last_nameservers[nss_i]);
+ }
+ LDNS_FREE(last_nameservers);
+ ldns_resolver_deep_free(res);
+ ldns_pkt_free(p);
+ return answer_list;
+}
+
+
+/*
+ * The file with the given path should contain a list of NS RRs
+ * for the root zone and A records for those NS RRs.
+ * Read them, check them, and append the a records to the rr list given.
+ */
+ldns_rr_list *
+read_root_hints(const char *filename)
+{
+ FILE *fp = NULL;
+ int line_nr = 0;
+ ldns_zone *z;
+ ldns_status status;
+ ldns_rr_list *addresses = NULL;
+ ldns_rr *rr;
+ size_t i;
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ fprintf(stderr, "Unable to open %s for reading: %s\n", filename, strerror(errno));
+ return NULL;
+ }
+
+ status = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, 0, &line_nr);
+ fclose(fp);
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error reading root hints file: %s\n", ldns_get_errorstr_by_id(status));
+ return NULL;
+ } else {
+ addresses = ldns_rr_list_new();
+ for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) {
+ rr = ldns_rr_list_rr(ldns_zone_rrs(z), i);
+ if ((address_family == 0 || address_family == 1) &&
+ ldns_rr_get_type(rr) == LDNS_RR_TYPE_A ) {
+ ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr));
+ }
+ if ((address_family == 0 || address_family == 2) &&
+ ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
+ ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr));
+ }
+ }
+ ldns_zone_deep_free(z);
+ return addresses;
+ }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ ldns_resolver *res;
+ ldns_rdf *ns;
+ ldns_rdf *domain;
+ ldns_rr_list *l = NULL;
+
+ ldns_rr_list *dns_root = NULL;
+ const char *root_file = "/etc/named.root";
+
+ ldns_status status;
+
+ int i;
+
+ char *domain_str;
+ char *outputfile_str;
+ ldns_buffer *outputfile_buffer;
+ FILE *outputfile;
+ ldns_rr *k;
+
+ bool insecure = false;
+ ldns_pkt *pkt;
+
+ domain = NULL;
+ res = NULL;
+
+ if (argc < 2) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ } else {
+ for (i = 1; i < argc; i++) {
+ if (strncmp("-4", argv[i], 3) == 0) {
+ if (address_family != 0) {
+ fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
+ exit(EXIT_FAILURE);
+ }
+ address_family = 1;
+ } else if (strncmp("-6", argv[i], 3) == 0) {
+ if (address_family != 0) {
+ fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
+ exit(EXIT_FAILURE);
+ }
+ address_family = 2;
+ } else if (strncmp("-h", argv[i], 3) == 0) {
+ usage(stdout, argv[0]);
+ exit(EXIT_SUCCESS);
+ } else if (strncmp("-i", argv[i], 2) == 0) {
+ insecure = true;
+ } else if (strncmp("-r", argv[i], 2) == 0) {
+ if (strlen(argv[i]) > 2) {
+ root_file = argv[i]+2;
+ } else if (i+1 >= argc) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ } else {
+ root_file = argv[i+1];
+ i++;
+ }
+ } else if (strncmp("-s", argv[i], 3) == 0) {
+ store_in_file = true;
+ } else if (strncmp("-v", argv[i], 2) == 0) {
+ if (strlen(argv[i]) > 2) {
+ verbosity = atoi(argv[i]+2);
+ } else if (i+1 > argc) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ } else {
+ verbosity = atoi(argv[i+1]);
+ i++;
+ }
+ } else {
+ /* create a rdf from the command line arg */
+ if (domain) {
+ fprintf(stdout, "You can only specify one domain at a time\n");
+ exit(EXIT_FAILURE);
+ }
+
+ domain = ldns_dname_new_frm_str(argv[i]);
+ }
+
+ }
+ if (!domain) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ dns_root = read_root_hints(root_file);
+ if (!dns_root) {
+ fprintf(stderr, "cannot read the root hints file\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* create a new resolver from /etc/resolv.conf */
+ status = ldns_resolver_new_frm_file(&res, NULL);
+
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Warning: Unable to create stub resolver from /etc/resolv.conf:\n");
+ fprintf(stderr, "%s\n", ldns_get_errorstr_by_id(status));
+ fprintf(stderr, "defaulting to nameserver at 127.0.0.1 for separate nameserver name lookups\n");
+ res = ldns_resolver_new();
+ ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1");
+ status = ldns_resolver_push_nameserver(res, ns);
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Unable to create stub resolver: %s\n", ldns_get_errorstr_by_id(status));
+ exit(EXIT_FAILURE);
+ }
+ ldns_rdf_deep_free(ns);
+ }
+
+ ldns_resolver_set_ip6(res, address_family);
+
+ if (insecure) {
+ pkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
+ if (pkt) {
+ l = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANY_NOQUESTION);
+ }
+ } else {
+ l = retrieve_dnskeys(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, dns_root);
+ }
+
+ /* separator for result data and verbosity data */
+ if (verbosity > 0) {
+ fprintf(stdout, "; ---------------------------\n");
+ fprintf(stdout, "; Got the following keys:\n");
+ }
+ if (l) {
+ if (store_in_file) {
+ /* create filename:
+ * K<domain>.+<alg>.+<id>.key
+ */
+ for (i = 0; (size_t) i < ldns_rr_list_rr_count(l); i++) {
+ k = ldns_rr_list_rr(l, (size_t) i);
+
+ outputfile_buffer = ldns_buffer_new(300);
+ domain_str = ldns_rdf2str(ldns_rr_owner(k));
+ ldns_buffer_printf(outputfile_buffer, "K%s+%03u+%05u.key", domain_str, ldns_rdf2native_int8(ldns_rr_rdf(k, 2)),
+ (unsigned int) ldns_calc_keytag(k));
+ outputfile_str = ldns_buffer_export(outputfile_buffer);
+
+ if (verbosity >= 1) {
+ fprintf(stdout, "Writing key to file %s\n", outputfile_str);
+ }
+
+ outputfile = fopen(outputfile_str, "w");
+ if (!outputfile) {
+ fprintf(stderr, "Error writing key to file %s: %s\n", outputfile_str, strerror(errno));
+ } else {
+ ldns_rr_print(outputfile, k);
+ fclose(outputfile);
+ }
+
+ LDNS_FREE(domain_str);
+ LDNS_FREE(outputfile_str);
+ LDNS_FREE(outputfile_buffer);
+ }
+ } else {
+ ldns_rr_list_print(stdout, l);
+ }
+ } else {
+ fprintf(stderr, "no answer packet received, stub resolver config:\n");
+ ldns_resolver_print(stderr, res);
+ }
+ printf("\n");
+
+ ldns_rdf_deep_free(domain);
+ ldns_resolver_deep_free(res);
+ ldns_rr_list_deep_free(l);
+ ldns_rr_list_deep_free(dns_root);
+ return EXIT_SUCCESS;
+}
diff --git a/examples/ldns-keygen.1 b/examples/ldns-keygen.1
new file mode 100644
index 000000000000..36124d52a47b
--- /dev/null
+++ b/examples/ldns-keygen.1
@@ -0,0 +1,53 @@
+.TH ldns-keygen 1 "27 May 2008"
+.SH NAME
+ldns-keygen \- generate a DNSSEC key pair
+.SH SYNOPSIS
+.B ldns-keygen
+[
+.IR OPTION
+]
+.IR DOMAIN
+
+.SH DESCRIPTION
+\fBldns-keygen\fR is used to generate a private/public keypair. When run, it
+will create 3 files; a .key file with the public DNSKEY, a .private
+file with the private keydata and a .ds with the DS record of the
+DNSKEY record.
+
+It prints out the basename for these files: K<name>+<alg>+<id>
+
+.SH OPTIONS
+.TP
+\fB-a \fI<algorithm>\fR
+Create a key with this algorithm. Specifying 'list' here gives a list of supported algorithms.
+Several alias names are also accepted (from older versions and other software),
+the list gives names from the RFC. Also the plain algo number is accepted.
+
+.TP
+\fB-b \fI<bits>\fR
+Use this many bits for the key length.
+
+.TP
+\fB-k\fR
+When given, generate a key signing key. This just sets the flag field to
+257 instead of 256 in the DNSKEY RR in the .key file.
+
+.TP
+\fB-r \fIdevice\fR
+Make ldns-keygen use this file to seed the random generator with. This will
+default to /dev/random.
+
+.TP
+\fB-v\fR
+Show the version and exit
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005-2008 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-keygen.c b/examples/ldns-keygen.c
new file mode 100644
index 000000000000..576541790c90
--- /dev/null
+++ b/examples/ldns-keygen.c
@@ -0,0 +1,307 @@
+/*
+ * keygen is a small programs that generate a dnskey and private key
+ * for a particular domain.
+ *
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+
+#include <ldns/ldns.h>
+
+#include <errno.h>
+
+#ifdef HAVE_SSL
+static void
+usage(FILE *fp, char *prog) {
+ fprintf(fp, "%s -a <algorithm> [-b bits] [-r /dev/random] [-v] domain\n",
+ prog);
+ fprintf(fp, " generate a new key pair for domain\n");
+ fprintf(fp, " -a <alg>\tuse the specified algorithm (-a list to");
+ fprintf(fp, " show a list)\n");
+ fprintf(fp, " -k\t\tset the flags to 257; key signing key\n");
+ fprintf(fp, " -b <bits>\tspecify the keylength\n");
+ fprintf(fp, " -r <random>\tspecify a random device (defaults to /dev/random)\n");
+ fprintf(fp, "\t\tto seed the random generator with\n");
+ fprintf(fp, " -v\t\tshow the version and exit\n");
+ fprintf(fp, " The following files will be created:\n");
+ fprintf(fp, " K<name>+<alg>+<id>.key\tPublic key in RR format\n");
+ fprintf(fp, " K<name>+<alg>+<id>.private\tPrivate key in key format\n");
+ fprintf(fp, " K<name>+<alg>+<id>.ds\tDS in RR format (only for DNSSEC keys)\n");
+ fprintf(fp, " The base name (K<name>+<alg>+<id> will be printed to stdout\n");
+}
+
+static void
+show_algorithms(FILE *out)
+{
+ ldns_lookup_table *lt = ldns_signing_algorithms;
+ fprintf(out, "Possible algorithms:\n");
+
+ while (lt->name) {
+ fprintf(out, "%s\n", lt->name);
+ lt++;
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ char *prog;
+
+ /* default key size */
+ uint16_t def_bits = 1024;
+ uint16_t bits = def_bits;
+ bool ksk;
+
+ FILE *file;
+ FILE *random;
+ char *filename;
+ char *owner;
+
+ ldns_signing_algorithm algorithm;
+ ldns_rdf *domain;
+ ldns_rr *pubkey;
+ ldns_key *key;
+ ldns_rr *ds;
+
+ prog = strdup(argv[0]);
+ algorithm = 0;
+ random = NULL;
+ ksk = false; /* don't create a ksk per default */
+
+ while ((c = getopt(argc, argv, "a:kb:r:v25")) != -1) {
+ switch (c) {
+ case 'a':
+ if (algorithm != 0) {
+ fprintf(stderr, "The -a argument can only be used once\n");
+ exit(1);
+ }
+ if (strncmp(optarg, "list", 5) == 0) {
+ show_algorithms(stdout);
+ exit(EXIT_SUCCESS);
+ }
+ algorithm = ldns_get_signing_algorithm_by_name(optarg);
+ if (algorithm == 0) {
+ fprintf(stderr, "Algorithm %s not found\n", optarg);
+ show_algorithms(stderr);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'b':
+ bits = (uint16_t) atoi(optarg);
+ if (bits == 0) {
+ fprintf(stderr, "%s: %s %d", prog, "Can not parse the -b argument, setting it to the default\n", (int) def_bits);
+ bits = def_bits;
+ }
+ break;
+ case 'k':
+ ksk = true;
+ break;
+ case 'r':
+ random = fopen(optarg, "r");
+ if (!random) {
+ fprintf(stderr, "Cannot open random file %s: %s\n", optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'v':
+ printf("DNSSEC key generator version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
+ exit(EXIT_SUCCESS);
+ break;
+ default:
+ usage(stderr, prog);
+ exit(EXIT_FAILURE);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (algorithm == 0) {
+ printf("Please use the -a argument to provide an algorithm\n");
+ exit(1);
+ }
+
+ if (argc != 1) {
+ usage(stderr, prog);
+ exit(EXIT_FAILURE);
+ }
+ free(prog);
+
+ /* check whether key size is within RFC boundaries */
+ switch (algorithm) {
+ case LDNS_SIGN_RSAMD5:
+ case LDNS_SIGN_RSASHA1:
+ if (bits < 512 || bits > 4096) {
+ fprintf(stderr, "For RSA, the key size must be between ");
+ fprintf(stderr, " 512 and 4096 bytes. Aborting.\n");
+ exit(1);
+ }
+ break;
+ case LDNS_SIGN_DSA:
+ if (bits < 512 || bits > 4096) {
+ fprintf(stderr, "For DSA, the key size must be between ");
+ fprintf(stderr, " 512 and 1024 bytes. Aborting.\n");
+ exit(1);
+ }
+ break;
+#ifdef USE_GOST
+ case LDNS_SIGN_ECC_GOST:
+ if(!ldns_key_EVP_load_gost_id()) {
+ fprintf(stderr, "error: libcrypto does not provide GOST\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+#endif
+#ifdef USE_ECDSA
+ case LDNS_SIGN_ECDSAP256SHA256:
+ case LDNS_SIGN_ECDSAP384SHA384:
+#endif
+ case LDNS_SIGN_HMACMD5:
+ case LDNS_SIGN_HMACSHA1:
+ case LDNS_SIGN_HMACSHA256:
+ default:
+ break;
+ }
+
+ if (!random) {
+ random = fopen("/dev/random", "r");
+ if (!random) {
+ fprintf(stderr, "Cannot open random file %s: %s\n", optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ (void)ldns_init_random(random, (unsigned int) bits/8);
+ fclose(random);
+
+ /* create an rdf from the domain name */
+ domain = ldns_dname_new_frm_str(argv[0]);
+
+ /* generate a new key */
+ key = ldns_key_new_frm_algorithm(algorithm, bits);
+
+ /* set the owner name in the key - this is a /seperate/ step */
+ ldns_key_set_pubkey_owner(key, domain);
+
+ /* ksk flag */
+ if (ksk) {
+ ldns_key_set_flags(key, ldns_key_flags(key) + 1);
+ }
+
+ /* create the public from the ldns_key */
+ pubkey = ldns_key2rr(key);
+ if (!pubkey) {
+ fprintf(stderr, "Could not extract the public key from the key structure...");
+ ldns_key_deep_free(key);
+ exit(EXIT_FAILURE);
+ }
+ owner = ldns_rdf2str(ldns_rr_owner(pubkey));
+
+ /* calculate and set the keytag */
+ ldns_key_set_keytag(key, ldns_calc_keytag(pubkey));
+
+ /* build the DS record */
+ switch (algorithm) {
+#ifdef USE_ECDSA
+ case LDNS_SIGN_ECDSAP384SHA384:
+ ds = ldns_key_rr2ds(pubkey, LDNS_SHA384);
+ break;
+ case LDNS_SIGN_ECDSAP256SHA256:
+#endif
+ case LDNS_SIGN_RSASHA256:
+ case LDNS_SIGN_RSASHA512:
+ ds = ldns_key_rr2ds(pubkey, LDNS_SHA256);
+ break;
+ case LDNS_SIGN_ECC_GOST:
+#ifdef USE_GOST
+ ds = ldns_key_rr2ds(pubkey, LDNS_HASH_GOST);
+#else
+ ds = ldns_key_rr2ds(pubkey, LDNS_SHA256);
+#endif
+ break;
+ default:
+ ds = ldns_key_rr2ds(pubkey, LDNS_SHA1);
+ break;
+ }
+
+ /* print the public key RR to .key */
+ filename = LDNS_XMALLOC(char, strlen(owner) + 17);
+ snprintf(filename, strlen(owner) + 16, "K%s+%03u+%05u.key", owner, algorithm, (unsigned int) ldns_key_keytag(key));
+ file = fopen(filename, "w");
+ if (!file) {
+ fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
+ ldns_key_deep_free(key);
+ free(owner);
+ ldns_rr_free(pubkey);
+ ldns_rr_free(ds);
+ LDNS_FREE(filename);
+ exit(EXIT_FAILURE);
+ } else {
+ /* temporarily set question so that TTL is not printed */
+ ldns_rr_set_question(pubkey, true);
+ ldns_rr_print(file, pubkey);
+ ldns_rr_set_question(pubkey, false);
+ fclose(file);
+ LDNS_FREE(filename);
+ }
+
+ /* print the priv key to stderr */
+ filename = LDNS_XMALLOC(char, strlen(owner) + 21);
+ snprintf(filename, strlen(owner) + 20, "K%s+%03u+%05u.private", owner, algorithm, (unsigned int) ldns_key_keytag(key));
+ file = fopen(filename, "w");
+ if (!file) {
+ fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
+ ldns_key_deep_free(key);
+ free(owner);
+ ldns_rr_free(pubkey);
+ ldns_rr_free(ds);
+ LDNS_FREE(filename);
+ exit(EXIT_FAILURE);
+ } else {
+ ldns_key_print(file, key);
+ fclose(file);
+ LDNS_FREE(filename);
+ }
+
+ /* print the DS to .ds */
+ if (algorithm != LDNS_SIGN_HMACMD5 &&
+ algorithm != LDNS_SIGN_HMACSHA1 &&
+ algorithm != LDNS_SIGN_HMACSHA256) {
+ filename = LDNS_XMALLOC(char, strlen(owner) + 16);
+ snprintf(filename, strlen(owner) + 15, "K%s+%03u+%05u.ds", owner, algorithm, (unsigned int) ldns_key_keytag(key));
+ file = fopen(filename, "w");
+ if (!file) {
+ fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
+ ldns_key_deep_free(key);
+ free(owner);
+ ldns_rr_free(pubkey);
+ ldns_rr_free(ds);
+ LDNS_FREE(filename);
+ exit(EXIT_FAILURE);
+ } else {
+ /* temporarily set question so that TTL is not printed */
+ ldns_rr_set_question(ds, true);
+ ldns_rr_print(file, ds);
+ ldns_rr_set_question(ds, false);
+ fclose(file);
+ LDNS_FREE(filename);
+ }
+ }
+
+ fprintf(stdout, "K%s+%03u+%05u\n", owner, algorithm, (unsigned int) ldns_key_keytag(key));
+ ldns_key_deep_free(key);
+ free(owner);
+ ldns_rr_free(pubkey);
+ ldns_rr_free(ds);
+ exit(EXIT_SUCCESS);
+}
+#else
+int
+main(int argc, char **argv)
+{
+ fprintf(stderr, "ldns-keygen needs OpenSSL support, which has not been compiled in\n");
+ return 1;
+}
+#endif /* HAVE_SSL */
diff --git a/examples/ldns-mx.1 b/examples/ldns-mx.1
new file mode 100644
index 000000000000..cad97abcd82b
--- /dev/null
+++ b/examples/ldns-mx.1
@@ -0,0 +1,23 @@
+.TH ldns-mx 1 "27 Apr 2005"
+.SH NAME
+ldns-mx \- print out the mx record(s) for a domain
+.SH SYNOPSIS
+.B ldns-mx
+.IR DOMAIN
+
+.SH DESCRIPTION
+\fBldns-mx\fR is used to print out mx information of a domain.
+
+.SH OPTIONS
+\fBldns-mx\fR has no options.
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-mx.c b/examples/ldns-mx.c
new file mode 100644
index 000000000000..873cf55f87de
--- /dev/null
+++ b/examples/ldns-mx.c
@@ -0,0 +1,88 @@
+/*
+ * mx is a small program that prints out the mx records
+ * for a particular domain
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+
+#include <ldns/ldns.h>
+
+static int
+usage(FILE *fp, char *prog) {
+ fprintf(fp, "%s domain\n", prog);
+ fprintf(fp, " print out the mx for domain\n");
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ ldns_resolver *res;
+ ldns_rdf *domain;
+ ldns_pkt *p;
+ ldns_rr_list *mx;
+ ldns_status s;
+
+ p = NULL;
+ mx = NULL;
+ domain = NULL;
+ res = NULL;
+
+ if (argc != 2) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ } else {
+ /* create a rdf from the command line arg */
+ domain = ldns_dname_new_frm_str(argv[1]);
+ if (!domain) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* create a new resolver from /etc/resolv.conf */
+ s = ldns_resolver_new_frm_file(&res, NULL);
+
+ if (s != LDNS_STATUS_OK) {
+ exit(EXIT_FAILURE);
+ }
+
+ /* use the resolver to send a query for the mx
+ * records of the domain given on the command line
+ */
+ p = ldns_resolver_query(res,
+ domain,
+ LDNS_RR_TYPE_MX,
+ LDNS_RR_CLASS_IN,
+ LDNS_RD);
+
+ ldns_rdf_deep_free(domain);
+
+ if (!p) {
+ exit(EXIT_FAILURE);
+ } else {
+ /* retrieve the MX records from the answer section of that
+ * packet
+ */
+ mx = ldns_pkt_rr_list_by_type(p,
+ LDNS_RR_TYPE_MX,
+ LDNS_SECTION_ANSWER);
+ if (!mx) {
+ fprintf(stderr,
+ " *** invalid answer name %s after MX query for %s\n",
+ argv[1], argv[1]);
+ ldns_pkt_free(p);
+ ldns_resolver_deep_free(res);
+ exit(EXIT_FAILURE);
+ } else {
+ ldns_rr_list_sort(mx);
+ ldns_rr_list_print(stdout, mx);
+ ldns_rr_list_deep_free(mx);
+ }
+ }
+ ldns_pkt_free(p);
+ ldns_resolver_deep_free(res);
+ return 0;
+}
diff --git a/examples/ldns-notify.1 b/examples/ldns-notify.1
new file mode 100644
index 000000000000..7ae77ac04658
--- /dev/null
+++ b/examples/ldns-notify.1
@@ -0,0 +1,66 @@
+.TH ldns-notify 1 "9 Jan 2007"
+.SH NAME
+ldns-notify \- notify DNS servers that updates are available
+.SH SYNOPSIS
+.B ldns-notify
+[options]
+-z zone
+.IR servers
+
+.SH DESCRIPTION
+
+\fBldns-notify\fR sends a NOTIFY message to DNS servers. This tells them
+that an updated zone is available at the master servers. It can perform
+TSIG signatures and it can add a SOA serial number of the updated zone.
+If a server already has that serial number it will disregard the message.
+
+.SH OPTIONS
+.TP
+\fB-z zone\fR
+The zone that is updated.
+
+.TP
+\fB-h\fR
+Show usage and exit
+
+.TP
+\fB-v\fR
+Show the version and exit
+
+.TP
+\fB-s serial\fR
+Append a SOA record indicating the serial number of the updated zone.
+
+.TP
+\fB-p port\fR
+Use port as destination port (default the DNS port 53) for the UDP packets.
+
+.TP
+\fB-y key:data\fR
+Use the given TSIG key and base64-data to sign the NOTIFY. Uses the
+hmac-md5 algorithm.
+
+.TP
+\fB-d\fR
+Print verbose debug information. The query that is sent and the query
+that is received.
+
+.TP
+\fB-r num\fR
+Specify the maximum number of retries before notify gives up trying to
+send the UDP packet.
+
+.SH EXIT CODE
+The program exits with a 0 exit code if all servers replied an
+acknowledgement to the notify message, and a failure exit code otherwise.
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-notify.c b/examples/ldns-notify.c
new file mode 100644
index 000000000000..018a716faad4
--- /dev/null
+++ b/examples/ldns-notify.c
@@ -0,0 +1,334 @@
+/*
+ * ldns-notify.c - ldns-notify(8)
+ *
+ * Copyright (c) 2001-2008, NLnet Labs, All right reserved
+ *
+ * See LICENSE for the license
+ *
+ * send a notify packet to a server
+ */
+
+#include "config.h"
+
+/* ldns */
+#include <ldns/ldns.h>
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <errno.h>
+
+static int verbose = 1;
+static int max_num_retry = 15; /* times to try */
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: ldns-notify [other options] -z zone <servers>\n");
+ fprintf(stderr, "Ldns notify utility\n\n");
+ fprintf(stderr, " Supported options:\n");
+ fprintf(stderr, "\t-z zone\t\tThe zone\n");
+ fprintf(stderr, "\t-s version\tSOA version number to include\n");
+ fprintf(stderr, "\t-y key:data\tTSIG sign the query\n");
+ fprintf(stderr, "\t-p port\t\tport to use to send to\n");
+ fprintf(stderr, "\t-v\t\tPrint version information\n");
+ fprintf(stderr, "\t-d\t\tPrint verbose debug information\n");
+ fprintf(stderr, "\t-r num\t\tmax number of retries (%d)\n",
+ max_num_retry);
+ fprintf(stderr, "\t-h\t\tPrint this help information\n\n");
+ fprintf(stderr, "Report bugs to <ldns-team@nlnetlabs.nl>\n");
+ exit(1);
+}
+
+static void
+version(void)
+{
+ fprintf(stderr, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ fprintf(stderr, "Written by NLnet Labs.\n\n");
+ fprintf(stderr,
+ "Copyright (C) 2001-2008 NLnet Labs. This is free software.\n"
+ "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n"
+ "FOR A PARTICULAR PURPOSE.\n");
+ exit(0);
+}
+
+static void
+notify_host(int s, struct addrinfo* res, uint8_t* wire, size_t wiresize,
+ const char* addrstr)
+{
+ int timeout_retry = 5; /* seconds */
+ int num_retry = max_num_retry;
+#ifndef S_SPLINT_S
+ fd_set rfds;
+#endif
+ struct timeval tv;
+ int retval = 0;
+ ssize_t received = 0;
+ int got_ack = 0;
+ socklen_t addrlen = 0;
+ uint8_t replybuf[2048];
+ ldns_status status;
+ ldns_pkt* pkt = NULL;
+
+ while(!got_ack) {
+ /* send it */
+ if(sendto(s, (void*)wire, wiresize, 0,
+ res->ai_addr, res->ai_addrlen) == -1) {
+ printf("warning: send to %s failed: %s\n",
+ addrstr, strerror(errno));
+#ifndef USE_WINSOCK
+ close(s);
+#else
+ closesocket(s);
+#endif
+ return;
+ }
+
+ /* wait for ACK packet */
+#ifndef S_SPLINT_S
+ FD_ZERO(&rfds);
+ FD_SET(s, &rfds);
+ tv.tv_sec = timeout_retry; /* seconds */
+#endif
+ tv.tv_usec = 0; /* microseconds */
+ retval = select(s + 1, &rfds, NULL, NULL, &tv);
+ if (retval == -1) {
+ printf("error waiting for reply from %s: %s\n",
+ addrstr, strerror(errno));
+#ifndef USE_WINSOCK
+ close(s);
+#else
+ closesocket(s);
+#endif
+ return;
+ }
+ if(retval == 0) {
+ num_retry--;
+ if(num_retry == 0) {
+ printf("error: failed to send notify to %s.\n",
+ addrstr);
+ exit(1);
+ }
+ printf("timeout (%d s) expired, retry notify to %s.\n",
+ timeout_retry, addrstr);
+ }
+ if (retval == 1) {
+ got_ack = 1;
+ }
+ }
+
+ /* got reply */
+ addrlen = res->ai_addrlen;
+ received = recvfrom(s, (void*)replybuf, sizeof(replybuf), 0,
+ res->ai_addr, &addrlen);
+ res->ai_addrlen = addrlen;
+
+#ifndef USE_WINSOCK
+ close(s);
+#else
+ closesocket(s);
+#endif
+ if (received == -1) {
+ printf("recv %s failed: %s\n", addrstr, strerror(errno));
+ return;
+ }
+
+ /* check reply */
+ status = ldns_wire2pkt(&pkt, replybuf, (size_t)received);
+ if(status != LDNS_STATUS_OK) {
+ ssize_t i;
+ printf("Could not parse reply packet: %s\n",
+ ldns_get_errorstr_by_id(status));
+ if (verbose > 1) {
+ printf("hexdump of reply: ");
+ for(i=0; i<received; i++)
+ printf("%02x", (unsigned)replybuf[i]);
+ printf("\n");
+ }
+ exit(1);
+ }
+
+ if(verbose) {
+ ssize_t i;
+ printf("# reply from %s:\n", addrstr);
+ ldns_pkt_print(stdout, pkt);
+ if (verbose > 1) {
+ printf("hexdump of reply: ");
+ for(i=0; i<received; i++)
+ printf("%02x", (unsigned)replybuf[i]);
+ printf("\n");
+ }
+ }
+ ldns_pkt_free(pkt);
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ int i;
+
+ /* LDNS types */
+ ldns_pkt *notify;
+ ldns_rr *question;
+ ldns_resolver *res;
+ ldns_rdf *ldns_zone_name = NULL;
+ ldns_status status;
+ const char *zone_name = NULL;
+ int include_soa = 0;
+ uint32_t soa_version = 0;
+ ldns_tsig_credentials tsig_cred = {0,0,0};
+ int do_hexdump = 1;
+ uint8_t *wire = NULL;
+ size_t wiresize = 0;
+ const char *port = "53";
+
+ srandom(time(NULL) ^ getpid());
+
+ while ((c = getopt(argc, argv, "vhdp:r:s:y:z:")) != -1) {
+ switch (c) {
+ case 'd':
+ verbose++;
+ break;
+ case 'p':
+ port = optarg;
+ break;
+ case 'r':
+ max_num_retry = atoi(optarg);
+ break;
+ case 's':
+ include_soa = 1;
+ soa_version = (uint32_t)atoi(optarg);
+ break;
+ case 'y':
+ tsig_cred.algorithm = (char*)"hmac-md5.sig-alg.reg.int.";
+ tsig_cred.keyname = optarg;
+ tsig_cred.keydata = strchr(optarg, ':');
+ *tsig_cred.keydata = '\0';
+ tsig_cred.keydata++;
+ printf("Sign with %s : %s\n", tsig_cred.keyname,
+ tsig_cred.keydata);
+ break;
+ case 'z':
+ zone_name = optarg;
+ ldns_zone_name = ldns_dname_new_frm_str(zone_name);
+ if(!ldns_zone_name) {
+ printf("cannot parse zone name: %s\n",
+ zone_name);
+ exit(1);
+ }
+ break;
+ case 'v':
+ version();
+ case 'h':
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0 || zone_name == NULL) {
+ usage();
+ }
+
+ notify = ldns_pkt_new();
+ question = ldns_rr_new();
+ res = ldns_resolver_new();
+
+ if (!notify || !question || !res) {
+ /* bail out */
+ printf("error: cannot create ldns types\n");
+ exit(1);
+ }
+
+ /* create the rr for inside the pkt */
+ ldns_rr_set_class(question, LDNS_RR_CLASS_IN);
+ ldns_rr_set_owner(question, ldns_zone_name);
+ ldns_rr_set_type(question, LDNS_RR_TYPE_SOA);
+ ldns_pkt_set_opcode(notify, LDNS_PACKET_NOTIFY);
+ ldns_pkt_push_rr(notify, LDNS_SECTION_QUESTION, question);
+ ldns_pkt_set_aa(notify, true);
+ ldns_pkt_set_id(notify, random()&0xffff);
+ if(include_soa) {
+ char buf[10240];
+ ldns_rr *soa_rr=NULL;
+ ldns_rdf *prev=NULL;
+ snprintf(buf, sizeof(buf), "%s 3600 IN SOA . . %u 0 0 0 0",
+ zone_name, (unsigned)soa_version);
+ /*printf("Adding soa %s\n", buf);*/
+ status = ldns_rr_new_frm_str(&soa_rr, buf, 3600, NULL, &prev);
+ if(status != LDNS_STATUS_OK) {
+ printf("Error adding SOA version: %s\n",
+ ldns_get_errorstr_by_id(status));
+ }
+ ldns_pkt_push_rr(notify, LDNS_SECTION_ANSWER, soa_rr);
+ }
+
+ if(tsig_cred.keyname) {
+#ifdef HAVE_SSL
+ status = ldns_pkt_tsig_sign(notify, tsig_cred.keyname,
+ tsig_cred.keydata, 300, tsig_cred.algorithm,
+ NULL);
+ if(status != LDNS_STATUS_OK) {
+ printf("Error TSIG sign query: %s\n",
+ ldns_get_errorstr_by_id(status));
+ }
+#else
+ fprintf(stderr, "Warning: TSIG needs OpenSSL support, which has not been compiled in, TSIG skipped\n");
+#endif
+ }
+
+ if(verbose) {
+ printf("# Sending packet:\n");
+ ldns_pkt_print(stdout, notify);
+
+ }
+
+ status = ldns_pkt2wire(&wire, notify, &wiresize);
+ if(wiresize == 0) {
+ printf("Error converting notify packet to hex.\n");
+ exit(1);
+ }
+
+ if(do_hexdump && verbose > 1) {
+ printf("Hexdump of notify packet:\n");
+ for(i=0; i<(int)wiresize; i++)
+ printf("%02x", (unsigned)wire[i]);
+ printf("\n");
+ }
+
+ for(i=0; i<argc; i++)
+ {
+ struct addrinfo hints, *res0, *res;
+ int error;
+ int default_family = AF_INET;
+
+ if(verbose)
+ printf("# sending to %s\n", argv[i]);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = default_family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ error = getaddrinfo(argv[i], port, &hints, &res0);
+ if (error) {
+ printf("skipping bad address: %s: %s\n", argv[i],
+ gai_strerror(error));
+ continue;
+ }
+ for (res = res0; res; res = res->ai_next) {
+ int s = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if(s == -1)
+ continue;
+ /* send the notify */
+ notify_host(s, res, wire, wiresize, argv[i]);
+ }
+ freeaddrinfo(res0);
+ }
+
+ ldns_pkt_free(notify);
+ free(wire);
+ return 0;
+}
diff --git a/examples/ldns-nsec3-hash.1 b/examples/ldns-nsec3-hash.1
new file mode 100644
index 000000000000..1b0f70ce395c
--- /dev/null
+++ b/examples/ldns-nsec3-hash.1
@@ -0,0 +1,34 @@
+.TH ldns-nsec3-hash.c 1 "10 Dec 2008"
+.SH NAME
+ldns-nsec3-hash \- print out the NSEC3 hash for a domain name
+.SH SYNOPSIS
+.B ldns-nsec3-hash
+.IR <domain_name>
+
+.SH DESCRIPTION
+\fBldns-nsec3-hash\fR is used to print out the NSEC3 hash for the given domain name.
+
+.SH OPTIONS
+.TP
+\fB-a\fR \fInumber\fR
+Use the given algorithm number for the hash calculation. Defaults to 1 (SHA-1).
+
+.TP
+\fB-s\fR \fIsalt\fR
+Use the given salt for the hash calculation. Salt value should be in hexadecimal format.
+
+.TP
+\fB-t\fR \fIcount\fR
+Use count iterations for the hash calculation.
+
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2008 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-nsec3-hash.c b/examples/ldns-nsec3-hash.c
new file mode 100644
index 000000000000..0ba2e68aec44
--- /dev/null
+++ b/examples/ldns-nsec3-hash.c
@@ -0,0 +1,127 @@
+/*
+ * ldns-signzone signs a zone file
+ *
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <errno.h>
+
+#include <time.h>
+
+#include <ldns/ldns.h>
+#include <ldns/keys.h>
+
+#ifdef HAVE_SSL
+#include <openssl/conf.h>
+#include <openssl/engine.h>
+#endif /* HAVE_SSL */
+
+#define MAX_FILENAME_LEN 250
+int verbosity = 1;
+
+static void
+usage(FILE *fp, const char *prog) {
+ fprintf(fp, "%s [OPTIONS] <domain name>\n", prog);
+ fprintf(fp, " prints the NSEC3 hash of the given domain name\n");
+ fprintf(fp, "-a [algorithm] hashing algorithm\n");
+ fprintf(fp, "-t [number] number of hash iterations\n");
+ fprintf(fp, "-s [string] salt\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ ldns_rdf *dname, *hashed_dname;
+ uint8_t nsec3_algorithm = 1;
+ size_t nsec3_iterations_cmd = 1;
+ uint16_t nsec3_iterations = 1;
+ uint8_t nsec3_salt_length = 0;
+ uint8_t *nsec3_salt = NULL;
+
+ char *prog = strdup(argv[0]);
+
+ int c;
+ while ((c = getopt(argc, argv, "a:s:t:")) != -1) {
+ switch (c) {
+ case 'a':
+ nsec3_algorithm = (uint8_t) atoi(optarg);
+ break;
+ case 's':
+ if (strlen(optarg) % 2 != 0) {
+ fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n");
+ exit(EXIT_FAILURE);
+ }
+ if (strlen(optarg) > 512) {
+ fprintf(stderr, "Salt too long\n");
+ exit(EXIT_FAILURE);
+ }
+ nsec3_salt_length = (uint8_t) (strlen(optarg) / 2);
+ nsec3_salt = LDNS_XMALLOC(uint8_t, nsec3_salt_length);
+ for (c = 0; c < (int) strlen(optarg); c += 2) {
+ if (isxdigit((int) optarg[c]) && isxdigit((int) optarg[c+1])) {
+ nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 +
+ ldns_hexdigit_to_int(optarg[c+1]);
+ } else {
+ fprintf(stderr, "Salt value is not valid hex data.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ break;
+ case 't':
+ nsec3_iterations_cmd = (size_t) atol(optarg);
+ if (nsec3_iterations_cmd > LDNS_NSEC3_MAX_ITERATIONS) {
+ fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS);
+ exit(EXIT_FAILURE);
+ }
+ nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
+ break;
+ default:
+ usage(stderr, prog);
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ printf("Error: not enough arguments\n");
+ usage(stdout, prog);
+ exit(EXIT_FAILURE);
+ } else {
+ dname = ldns_dname_new_frm_str(argv[0]);
+ if (!dname) {
+ fprintf(stderr,
+ "Error: unable to parse domain name\n");
+ return EXIT_FAILURE;
+ }
+ hashed_dname = ldns_nsec3_hash_name(dname,
+ nsec3_algorithm,
+ nsec3_iterations,
+ nsec3_salt_length,
+ nsec3_salt);
+ if (!hashed_dname) {
+ fprintf(stderr,
+ "Error creating NSEC3 hash\n");
+ return EXIT_FAILURE;
+ }
+ ldns_rdf_print(stdout, hashed_dname);
+ printf("\n");
+ ldns_rdf_deep_free(dname);
+ ldns_rdf_deep_free(hashed_dname);
+ }
+
+ if (nsec3_salt) {
+ free(nsec3_salt);
+ }
+
+ free(prog);
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/ldns-read-zone.1 b/examples/ldns-read-zone.1
new file mode 100644
index 000000000000..81f238d601c5
--- /dev/null
+++ b/examples/ldns-read-zone.1
@@ -0,0 +1,69 @@
+.TH ldns-read-zone 1 "30 May 2005"
+.SH NAME
+ldns-read-zone \- read a zonefile and print it
+.SH SYNOPSIS
+.B ldns-read-zone
+.IR ZONEFILE
+
+.SH DESCRIPTION
+
+\fBldns-read-zone\fR reads a DNS zone file and prints it. The output has 1
+resource record per line, and no pretty-printing makeup.
+
+.SH OPTIONS
+.TP
+\fB-c\fR
+Canonicalize all resource records in the zone before printing
+
+.TP
+\fB-d\fR
+Only print DNSSEC data from the zone. This option skips every record
+that is not of type NSEC, NSEC3, RRSIG or DNSKEY. DS records are not
+printed.
+
+.TP
+\fB-h\fR
+Show usage and exit
+
+.TP
+\fB-n\fR
+Do not print the SOA record
+
+.TP
+\fB-s\fR
+Strip DNSSEC data from the zone. This option skips every record
+that is of type NSEC, NSEC3, RRSIG or DNSKEY. DS records are still
+printed.
+
+.TP
+\fB-S\fR \fI[[+|0]number | YYYYMMDDxx | unixtime ]\fR
+Set serial number to the given \fInumber\fR, or when preceded by a sign,
+offset the exisiting number with it. When giving the literal strings
+\fIYYYYMMDDxx\fR or \fIunixtime\fR, the serial number is tried to be reset
+in datecounter or in unixtime format respectively. Though is the updated serial
+number is smaller than the original one, the original one is simply
+increased by one.
+
+When updating a serial number, records of type NSEC, NSEC3, RRSIG and DNSKEY
+will be skipped when printing the zone.
+
+
+.TP
+\fB-v\fR
+Show the version and exit
+
+.TP
+\fB-z\fR
+Sort the zone before printing (this implies -c)
+
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-read-zone.c b/examples/ldns-read-zone.c
new file mode 100644
index 000000000000..ac32bac7f73d
--- /dev/null
+++ b/examples/ldns-read-zone.c
@@ -0,0 +1,212 @@
+/*
+ * read a zone file from disk and prints it, one RR per line
+ *
+ * (c) NLnetLabs 2005-2008
+ *
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <ldns/ldns.h>
+#include <ldns/host2str.h>
+
+#include <errno.h>
+
+int
+main(int argc, char **argv)
+{
+ char *filename;
+ FILE *fp;
+ ldns_zone *z;
+ int line_nr = 0;
+ int c;
+ bool canonicalize = false;
+ bool sort = false;
+ bool strip = false;
+ bool only_dnssec = false;
+ bool print_soa = true;
+ ldns_status s;
+ size_t i;
+ ldns_rr_list *stripped_list;
+ ldns_rr *cur_rr;
+ ldns_rr_type cur_rr_type;
+ const ldns_output_format *fmt = NULL;
+ ldns_soa_serial_increment_func_t soa_serial_increment_func = NULL;
+ int soa_serial_increment_func_data = 0;
+
+ while ((c = getopt(argc, argv, "bcdhnsvzS:")) != -1) {
+ switch(c) {
+ case 'b':
+ fmt = ldns_output_format_bubblebabble;
+ case 'c':
+ canonicalize = true;
+ break;
+ case 'd':
+ only_dnssec = true;
+ if (strip) {
+ fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n");
+ }
+ break;
+ case 'h':
+ printf("Usage: %s [-c] [-v] [-z] <zonefile>\n", argv[0]);
+ printf("\tReads the zonefile and prints it.\n");
+ printf("\tThe RR count of the zone is printed to stderr.\n");
+ printf("\t-b include bubblebabble of DS's.\n");
+ printf("\t-c canonicalize all rrs in the zone.\n");
+ printf("\t-d only show DNSSEC data from the zone\n");
+ printf("\t-h show this text\n");
+ printf("\t-n do not print the SOA record\n");
+ printf("\t-s strip DNSSEC data from the zone\n");
+ printf("\t-S [[+|-]<number> | YYYYMMDDxx | "
+ " unixtime ]\n"
+ "\t\tSet serial number to <number> or,"
+ " when preceded by a sign,\n"
+ "\t\toffset the existing number with "
+ "<number>. With YYYYMMDDxx\n"
+ "\t\tthe serial is formatted as a datecounter"
+ ", and with unixtime as the\n"
+ "\t\tnumber of seconds since 1-1-1970."
+ " However, on serial number"
+ "\n\t\tdecrease, +1 is used in stead"
+ ". (implies -s)\n");
+ printf("\t-v shows the version and exits\n");
+ printf("\t-z sort the zone (implies -c).\n");
+ printf("\nif no file is given standard input is read\n");
+ exit(EXIT_SUCCESS);
+ break;
+ case 'n':
+ print_soa = false;
+ break;
+ case 's':
+ strip = true;
+ if (only_dnssec) {
+ fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n");
+ }
+ break;
+ case 'v':
+ printf("read zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
+ exit(EXIT_SUCCESS);
+ break;
+ case 'z':
+ canonicalize = true;
+ sort = true;
+ break;
+ case 'S':
+ strip = true;
+ if (*optarg == '+' || *optarg == '-') {
+ soa_serial_increment_func_data =
+ atoi(optarg);
+ soa_serial_increment_func =
+ ldns_soa_serial_increment_by;
+ } else if (! strtok(optarg, "0123456789")) {
+ soa_serial_increment_func_data =
+ atoi(optarg);
+ soa_serial_increment_func =
+ ldns_soa_serial_identity;
+ } else if (!strcasecmp(optarg, "YYYYMMDDxx")){
+ soa_serial_increment_func =
+ ldns_soa_serial_datecounter;
+ } else if (!strcasecmp(optarg, "unixtime")){
+ soa_serial_increment_func =
+ ldns_soa_serial_unixtime;
+ } else {
+ fprintf(stderr, "-S expects a number "
+ "optionally preceded by a "
+ "+ or - sign to indicate an "
+ "offset, or the text YYYYMM"
+ "DDxx or unixtime\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ fp = stdin;
+ } else {
+ filename = argv[0];
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr);
+
+ if (strip) {
+ stripped_list = ldns_rr_list_new();
+ while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) {
+ cur_rr_type = ldns_rr_get_type(cur_rr);
+ if (cur_rr_type == LDNS_RR_TYPE_RRSIG ||
+ cur_rr_type == LDNS_RR_TYPE_NSEC ||
+ cur_rr_type == LDNS_RR_TYPE_NSEC3 ||
+ cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM
+ ) {
+ ldns_rr_free(cur_rr);
+ } else {
+ ldns_rr_list_push_rr(stripped_list, cur_rr);
+ }
+ }
+ ldns_rr_list_free(ldns_zone_rrs(z));
+ ldns_zone_set_rrs(z, stripped_list);
+ }
+ if (only_dnssec) {
+ stripped_list = ldns_rr_list_new();
+ while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) {
+ cur_rr_type = ldns_rr_get_type(cur_rr);
+ if (cur_rr_type == LDNS_RR_TYPE_RRSIG ||
+ cur_rr_type == LDNS_RR_TYPE_NSEC ||
+ cur_rr_type == LDNS_RR_TYPE_NSEC3 ||
+ cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM
+ ) {
+ ldns_rr_list_push_rr(stripped_list, cur_rr);
+ } else {
+ ldns_rr_free(cur_rr);
+ }
+ }
+ ldns_rr_list_free(ldns_zone_rrs(z));
+ ldns_zone_set_rrs(z, stripped_list);
+ }
+
+ if (s == LDNS_STATUS_OK) {
+ if (canonicalize) {
+ ldns_rr2canonical(ldns_zone_soa(z));
+ for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) {
+ ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i));
+ }
+ }
+ if (sort) {
+ ldns_zone_sort(z);
+ }
+
+ if (print_soa && ldns_zone_soa(z)) {
+ if (soa_serial_increment_func) {
+ ldns_rr_soa_increment_func_int(
+ ldns_zone_soa(z)
+ , soa_serial_increment_func
+ , soa_serial_increment_func_data
+ );
+ }
+ ldns_rr_print_fmt(stdout, fmt, ldns_zone_soa(z));
+ }
+ ldns_rr_list_print_fmt(stdout, fmt, ldns_zone_rrs(z));
+
+ ldns_zone_deep_free(z);
+ } else {
+ fprintf(stderr, "%s at %d\n",
+ ldns_get_errorstr_by_id(s),
+ line_nr);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fp);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/examples/ldns-resolver.1 b/examples/ldns-resolver.1
new file mode 100644
index 000000000000..9552e6860ce4
--- /dev/null
+++ b/examples/ldns-resolver.1
@@ -0,0 +1,26 @@
+.TH ldns-resolver 1 "27 Apr 2005"
+.SH NAME
+ldns-resolver \- tries to create a resolver from a resolv.conf file.
+.SH SYNOPSIS
+.B ldns-resolver
+.IR file
+
+.SH DESCRIPTION
+\fBldns-resolver\fR tries to create a resolver from a resolv.conf file.
+This is only useful to test the library for robusteness with input data.
+
+.SH OPTIONS
+\fBldns-resolver\fR takes a filename of the resolv.conf file as input.
+For example \fIldns-resolver /etc/resolv.conf\fR will show if the file can
+be parsed successfully.
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-resolver.c b/examples/ldns-resolver.c
new file mode 100644
index 000000000000..04dcc35febdb
--- /dev/null
+++ b/examples/ldns-resolver.c
@@ -0,0 +1,47 @@
+/*
+ * ldns-resolver tries to create a resolver structure from /dev/urandom
+ * this is only useful to test the library for robusteness with input data
+ *
+ * (c) NLnet Labs 2006 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include "errno.h"
+
+#include <ldns/ldns.h>
+
+int
+main(int argc, char **argv) {
+
+ ldns_resolver *r;
+ int line = 1;
+ FILE *rand;
+ ldns_status s;
+
+ if (argc != 2 || strncmp(argv[1], "-h", 3) == 0) {
+ printf("Usage: ldns-resolver <file>\n");
+ printf("Tries to create a stub resolver structure from the given file.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (!(rand = fopen(argv[1], "r"))) {
+ printf("Error opening %s: %s\n", argv[1], strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Trying to read from %s\n", argv[1]);
+ s = ldns_resolver_new_frm_fp_l(&r, rand, &line);
+ if (s != LDNS_STATUS_OK) {
+ printf("Failed: %s at line %d\n", ldns_get_errorstr_by_id(s), line);
+ exit(EXIT_FAILURE);
+ } else {
+ printf("Succes\n");
+ ldns_resolver_print(stdout, r);
+ ldns_resolver_deep_free(r);
+ }
+
+ fclose(rand);
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/ldns-revoke.1 b/examples/ldns-revoke.1
new file mode 100644
index 000000000000..5a16244dac42
--- /dev/null
+++ b/examples/ldns-revoke.1
@@ -0,0 +1,27 @@
+.TH ldns-revoke 1 "23 Jul 2008"
+.SH NAME
+ldns-revoke \- sets the revoke bit of a DNSKEY
+.SH SYNOPSIS
+.B ldns-revoke
+.IR file
+
+.SH DESCRIPTION
+\fBldns-revoke\fR is used to revoke a public DNSKEY RR.
+When run it will read \fIfile\fR with a DNSKEY RR in it,
+sets the revoke bit and write back the output to \fIfile\fR .
+
+.SH OPTIONS
+.TP
+\fB-n\fR
+Write the result to stdout instead of a file
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2008 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-revoke.c b/examples/ldns-revoke.c
new file mode 100644
index 000000000000..f46c98f01099
--- /dev/null
+++ b/examples/ldns-revoke.c
@@ -0,0 +1,104 @@
+/*
+ * revoke sets the revoke bit of a public key.
+ *
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+
+#include <ldns/ldns.h>
+#ifdef HAVE_SSL
+#include <openssl/ssl.h>
+#endif /* HAVE_SSL */
+
+#include <errno.h>
+
+static void
+usage(FILE *fp, char *prog) {
+ fprintf(fp, "%s [-n] keyfile\n", prog);
+ fprintf(fp, " Revokes a key\n");
+ fprintf(fp, "Options:\n");
+ fprintf(fp, " -n: do not write to file but to stdout\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ FILE *keyfp;
+ char *keyname;
+ ldns_rr *k;
+ uint16_t flags;
+ char *program = argv[0];
+ int nofile = 0;
+ ldns_rdf *origin = NULL;
+ ldns_status result;
+
+ argv++, argc--;
+ while (argc && argv[0][0] == '-') {
+ if (strcmp(argv[0], "-n") == 0) {
+ nofile=1;
+ }
+ else {
+ usage(stderr, program);
+ exit(EXIT_FAILURE);
+ }
+ argv++, argc--;
+ }
+
+ if (argc != 1) {
+ usage(stderr, program);
+ exit(EXIT_FAILURE);
+ }
+ keyname = strdup(argv[0]);
+
+ keyfp = fopen(keyname, "r");
+ if (!keyfp) {
+ fprintf(stderr, "Failed to open public key file %s: %s\n", keyname,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL);
+ /* what does this while loop do? */
+ while (result == LDNS_STATUS_SYNTAX_ORIGIN) {
+ result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL);
+ }
+ if (result != LDNS_STATUS_OK) {
+ fprintf(stderr, "Could not read public key from file %s: %s\n", keyname, ldns_get_errorstr_by_id(result));
+ exit(EXIT_FAILURE);
+ }
+ fclose(keyfp);
+
+ flags = ldns_read_uint16(ldns_rdf_data(ldns_rr_dnskey_flags(k)));
+ flags |= LDNS_KEY_REVOKE_KEY;
+
+ if (!ldns_rr_dnskey_set_flags(k,
+ ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, flags)))
+ {
+ fprintf(stderr, "Revocation failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* print the public key RR to .key */
+
+ if (nofile)
+ ldns_rr_print(stdout,k);
+ else {
+ keyfp = fopen(keyname, "w");
+ if (!keyfp) {
+ fprintf(stderr, "Unable to open %s: %s\n", keyname,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ } else {
+ ldns_rr_print(keyfp, k);
+ fclose(keyfp);
+ fprintf(stdout, "DNSKEY revoked\n");
+ }
+ }
+
+ free(keyname);
+ ldns_rr_free(k);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/examples/ldns-rrsig.1 b/examples/ldns-rrsig.1
new file mode 100644
index 000000000000..3aee863e057d
--- /dev/null
+++ b/examples/ldns-rrsig.1
@@ -0,0 +1,30 @@
+.TH ldns-rrsig 1 "27 Apr 2005"
+.SH NAME
+ldns-rrsig \- print out the inception and expiration dates in human
+readable form
+.SH SYNOPSIS
+.B ldns-rrsig
+.IR domain
+[
+.IR type
+]
+
+.SH DESCRIPTION
+\fBldns-rrsig\fR is used to print the expiration and inception date of
+a RRSIG. The first argument is a domain name. \fBldns-rrsig\fR will
+query the authoritative servers for that domain to get a list of RRSIGs.
+It will then print out the inception and experiration dates for the RRSIG
+covering the SOA record.
+.PP
+If the second argument \fBtype\fR is given the RRSIG covering that type will be shown.
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-rrsig.c b/examples/ldns-rrsig.c
new file mode 100644
index 000000000000..a66586160082
--- /dev/null
+++ b/examples/ldns-rrsig.c
@@ -0,0 +1,219 @@
+/*
+ * ldns-rrsig prints out the inception and expiration dates in a more readable
+ * way than the normal RRSIG presentation format
+ *
+ * for a particulary domain
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+
+#include <ldns/ldns.h>
+
+static int
+usage(FILE *fp, char *prog) {
+ fprintf(fp, "%s domain [type]\n", prog);
+ fprintf(fp, " print out the inception and expiration dates\n");
+ fprintf(fp, " in a more human readable form\n");
+ fprintf(fp, " <type>\tquery for RRSIG(<type>), defaults to SOA\n");
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ ldns_resolver *res;
+ ldns_resolver *localres;
+ ldns_rdf *domain;
+ ldns_pkt *p;
+ ldns_rr_list *rrsig;
+ ldns_rr_list *rrsig_type;
+ ldns_rr_list *ns;
+ ldns_rr_list *ns_ip;
+ uint8_t i, j;
+ ldns_rr_type t;
+ const char * type_name;
+ struct tm incep, expir;
+ char incep_buf[26];
+ char expir_buf[26];
+ ldns_status s;
+ time_t now = time(NULL);
+
+ p = NULL;
+ rrsig = NULL;
+ rrsig_type = NULL;
+ domain = NULL;
+
+ /* option parsing */
+
+ if (argc < 2) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ } else {
+ /* create a rdf from the command line arg */
+ domain = ldns_dname_new_frm_str(argv[1]);
+ if (!domain) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (argc == 3) {
+ /* optional type arg */
+ type_name = strdup(argv[2]);
+ t = ldns_rdf2rr_type(
+ ldns_rdf_new_frm_str(LDNS_RDF_TYPE_TYPE, type_name));
+ if (t == 0) {
+ fprintf(stderr, " *** %s is not a valid RR type\n", type_name);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ t = LDNS_RR_TYPE_SOA;
+ type_name = "SOA";
+ }
+
+ /* create a new resolver from /etc/resolv.conf */
+ s = ldns_resolver_new_frm_file(&localres, NULL);
+ if (s != LDNS_STATUS_OK) {
+ exit(EXIT_FAILURE);
+ }
+
+ /* first get the nameserver of the domain in question */
+ p = ldns_resolver_query(localres, domain, LDNS_RR_TYPE_NS,
+ LDNS_RR_CLASS_IN, LDNS_RD);
+ if (!p) {
+ fprintf(stderr," *** Could not find any nameserver for %s", argv[1]);
+ ldns_resolver_deep_free(localres);
+ exit(EXIT_FAILURE);
+ }
+ ns = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
+
+ if (!ns) {
+ fprintf(stderr," *** Could not find any nameserver for %s", argv[1]);
+ ldns_pkt_free(p);
+ ldns_resolver_deep_free(localres);
+ exit(EXIT_FAILURE);
+ }
+
+ /* use our local resolver to resolv the names in the for usage in our
+ * new resolver */
+ res = ldns_resolver_new();
+ if (!res) {
+ ldns_pkt_free(p);
+ ldns_resolver_deep_free(localres);
+ ldns_rr_list_deep_free(ns);
+ exit(EXIT_FAILURE);
+ }
+ for(i = 0; i < ldns_rr_list_rr_count(ns); i++) {
+ ns_ip = ldns_get_rr_list_addr_by_name(localres,
+ ldns_rr_ns_nsdname(ldns_rr_list_rr(ns, i)),
+ LDNS_RR_CLASS_IN, LDNS_RD);
+ /* add these to new resolver */
+ for(j = 0; j < ldns_rr_list_rr_count(ns_ip); j++) {
+ if (ldns_resolver_push_nameserver(res,
+ ldns_rr_a_address(ldns_rr_list_rr(ns_ip, j))) != LDNS_STATUS_OK) {
+ printf("Error adding nameserver to resolver\n");
+ ldns_pkt_free(p);
+ ldns_resolver_deep_free(res);
+ ldns_resolver_deep_free(localres);
+ ldns_rr_list_deep_free(ns);
+ exit(EXIT_FAILURE);
+ }
+ }
+ ldns_rr_list_deep_free(ns_ip);
+
+ }
+
+ /* enable DNSSEC */
+ ldns_resolver_set_dnssec(res, true);
+ /* also set CD, we want EVERYTHING! */
+ ldns_resolver_set_dnssec_cd(res, true);
+
+ /* use the resolver to send it a query for the soa
+ * records of the domain given on the command line
+ */
+ ldns_pkt_free(p);
+ p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_RRSIG, LDNS_RR_CLASS_IN, LDNS_RD);
+
+ ldns_rdf_deep_free(domain);
+
+ if (!p) {
+ ldns_resolver_deep_free(localres);
+ ldns_rr_list_deep_free(ns);
+ exit(EXIT_FAILURE);
+ } else {
+ /* retrieve the RRSIG records from the answer section of that
+ * packet
+ */
+ rrsig = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER);
+ if (!rrsig) {
+ fprintf(stderr,
+ " *** invalid answer name %s after RRSIG query for %s\n",
+ argv[1], argv[1]);
+ ldns_pkt_free(p);
+ ldns_resolver_deep_free(res);
+ ldns_rr_list_deep_free(ns);
+ exit(EXIT_FAILURE);
+ } else {
+ rrsig_type = ldns_rr_list_new();
+
+ for(i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
+ if (ldns_rdf2rr_type(
+ ldns_rr_rrsig_typecovered(
+ ldns_rr_list_rr(rrsig, i))) == t) {
+ ldns_rr_list_push_rr(rrsig_type,
+ ldns_rr_list_rr(rrsig, i));
+ }
+ }
+ if (ldns_rr_list_rr_count(rrsig_type) == 0) {
+ fprintf(stderr, " *** No RRSIG(%s) type found\n",
+ type_name);
+ ldns_resolver_deep_free(localres);
+ ldns_resolver_deep_free(res);
+ ldns_pkt_free(p);
+ ldns_rr_list_deep_free(ns);
+ ldns_rr_list_free(rrsig);
+ ldns_rr_list_deep_free(rrsig_type);
+ exit(EXIT_FAILURE);
+ }
+
+ for(i = 0; i < ldns_rr_list_rr_count(rrsig_type); i++) {
+ memset(&incep, 0, sizeof(incep));
+ if (ldns_serial_arithmitics_gmtime_r(
+ ldns_rdf2native_time_t(
+ ldns_rr_rrsig_inception(
+ ldns_rr_list_rr(rrsig_type, i))),
+ now, &incep
+ )
+ && asctime_r(&incep, incep_buf)) {
+ incep_buf[24] = '\0';
+ } else {
+ incep_buf[0] = '\0';
+ }
+ memset(&expir, 0, sizeof(expir));
+ if (ldns_serial_arithmitics_gmtime_r(
+ ldns_rdf2native_time_t(
+ ldns_rr_rrsig_expiration(
+ ldns_rr_list_rr(rrsig_type, i))),
+ now, &expir
+ )
+ && asctime_r(&expir, expir_buf)) {
+ expir_buf[24] = '\0';
+ } else {
+ expir_buf[0] = '\0';
+ }
+
+ fprintf(stdout, "%s RRSIG(%s): %s - %s\n",
+ argv[1], type_name, incep_buf, expir_buf);
+ }
+ ldns_rr_list_free(rrsig);
+ ldns_rr_list_deep_free(rrsig_type);
+ }
+ }
+ ldns_pkt_free(p);
+ ldns_resolver_deep_free(localres);
+ ldns_resolver_deep_free(res);
+ ldns_rr_list_deep_free(ns);
+ return 0;
+}
diff --git a/examples/ldns-signzone.1 b/examples/ldns-signzone.1
new file mode 100644
index 000000000000..a83da94e63d4
--- /dev/null
+++ b/examples/ldns-signzone.1
@@ -0,0 +1,164 @@
+.TH ldns-signzone 1 "30 May 2005"
+.SH NAME
+ldns-signzone \- sign a zonefile with DNSSEC data
+.SH SYNOPSIS
+.B ldns-signzone
+[
+.IR OPTIONS
+]
+.IR ZONEFILE
+.IR
+KEY
+[KEY
+[KEY] ...
+]
+
+.SH DESCRIPTION
+
+\fBldns-signzone\fR is used to generate a DNSSEC signed zone. When run it
+will create a new zonefile that contains RRSIG and NSEC resource records, as
+specified in RFC 4033, RFC 4034 and RFC 4035.
+
+Keys must be specified by their base name (i.e. without .private). If
+the DNSKEY that belongs to the key in the .private file is not present
+in the zone, it will be read from the file <base name>.key. If that
+file does not exist, the DNSKEY value will be generated from the
+private key.
+
+Multiple keys can be specified, Key Signing Keys are used as such when
+they are either already present in the zone, or specified in a .key
+file, and have the KSK bit set.
+
+.SH OPTIONS
+.TP
+\fB-b\fR
+Augments the zone and the RR's with extra comment texts for a more readable
+layout, easier to debug. DS records will have a bubblebabble version of
+the data in the comment text, NSEC3 records will have the original NSEC3
+in the comment text.
+
+Without this option, only DNSKEY RR's will have their Key Tag annotated in
+the comment text.
+
+.TP
+\fB-d\fR
+Normally, if the DNSKEY RR for a key that is used to sign the zone is
+not found in the zone file, it will be read from .key, or derived from
+the private key (in that order). This option turns that feature off,
+so that only the signatures are added to the zone.
+
+.TP
+\fB-e\fR \fIdate\fR
+Set expiration date of the signatures to this date, the format can be
+YYYYMMDD[hhmmss], or a timestamp.
+
+.TP
+\fB-f\fR \fIfile\fR
+Use this file to store the signed zone in (default <originalfile>.signed)
+
+.TP
+\fB-i\fR \fIdate\fR
+Set inception date of the signatures to this date, the format can be
+YYYYMMDD[hhmmss], or a timestamp.
+
+.TP
+\fB-o\fR \fIorigin\fR
+Use this as the origin of the zone
+
+.TP
+\fB-v\fR
+Print the version and exit
+
+.TP
+\fB-A\fR
+Sign the DNSKEY record with all keys. By default it is signed with a
+minimal number of keys, to keep the response size for the DNSKEY query
+small, and only the SEP keys that are passed are used. If there are no
+SEP keys, the DNSKEY RRset is signed with the non\-SEP keys. This option
+turns off the default and all keys are used to sign the DNSKEY RRset.
+
+.TP
+\fB-E\fR \fIname\fR
+Use the EVP cryptographic engine with the given name for signing. This
+can have some extra options; see ENGINE OPTIONS for more information.
+
+.TP
+\fB-k\fR \fIid,int\fR
+Use the key with the given id as the signing key for algorithm int as
+a Zone signing key. This option is used when you use an OpenSSL
+engine, see ENGINE OPTIONS for more information.
+
+.TP
+\fB-K\fR \fIid,int\fR
+
+Use the key with the given id as the signing key for algorithm int as
+a Key signing key. This options is used when you use an OpenSSL engine,
+see ENGINE OPTIONS for more information.
+
+.TP
+\fB-n\fR
+Use NSEC3 instead of NSEC.
+
+.TP
+If you use NSEC3, you can specify the following extra options:
+
+.TP
+\fB-a\fR \fIalgorithm\fR
+Algorithm used to create the hashed NSEC3 owner names
+
+.TP
+\fB-p\fR
+Opt-out. All NSEC3 records in the zone will have the Opt-out flag set. After signing, you can add insecure delegations to the signed zone.
+
+.TP
+\fB-s\fR \fIstring\fR
+Salt
+
+.TP
+\fB-t\fR \fInumber\fR
+Number of hash iterations
+
+.SH ENGINE OPTIONS
+You can modify the possible engines, if supported, by setting an
+OpenSSL configuration file. This is done through the environment
+variable OPENSSL_CONF. If you use -E with a non-existent engine name,
+ldns-signzone will print a list of engines supported by your
+configuration.
+
+The key options (-k and -K) work as follows; you specify a key id, and a DNSSEC algorithm number (for instance, 5 for RSASHA1). The key id can be any of the following:
+
+ <id>
+ <slot>:<id>
+ id_<id>
+ slot_<slot>-id_<id>
+ label_<label>
+ slot_<slot>-label_<label>
+
+Where '<id>' is the PKCS #11 key identifier in hexadecimal
+notation, '<label>' is the PKCS #11 human-readable label, and '<slot>'
+is the slot number where the token is present.
+
+If not already present, a DNSKEY RR is generated from the key
+data, and added to the zone.
+
+.SH EXAMPLES
+
+.TP
+ldns-signzone nlnetlabs.nl Knlnetlabs.nl.+005+12273
+Sign the zone in the file 'nlnetlabs.nl' with the key in the
+files 'Knlnetlabs.nl.+005+12273.private'. If the DNSKEY is not present
+in the zone, use the key in the
+file 'Knlnetlabs.nl.+005+12273.key'. If that is not present, generate
+one with default values from 'Knlnetlabs.nl.+005+12273.private'.
+
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005-2008 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-signzone.c b/examples/ldns-signzone.c
new file mode 100644
index 000000000000..34839b053dcf
--- /dev/null
+++ b/examples/ldns-signzone.c
@@ -0,0 +1,839 @@
+/*
+ * ldns-signzone signs a zone file
+ *
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <errno.h>
+
+#include <time.h>
+
+#include <ldns/ldns.h>
+#include <ldns/keys.h>
+
+#ifdef HAVE_SSL
+#include <openssl/conf.h>
+#include <openssl/engine.h>
+#endif /* HAVE_SSL */
+
+#define MAX_FILENAME_LEN 250
+int verbosity = 1;
+
+#ifdef HAVE_SSL
+#include <openssl/err.h>
+
+static void
+usage(FILE *fp, const char *prog) {
+ fprintf(fp, "%s [OPTIONS] zonefile key [key [key]]\n", prog);
+ fprintf(fp, " signs the zone with the given key(s)\n");
+ fprintf(fp, " -b\t\tuse layout in signed zone and print comments DNSSEC records\n");
+ fprintf(fp, " -d\t\tused keys are not added to the zone\n");
+ fprintf(fp, " -e <date>\texpiration date\n");
+ fprintf(fp, " -f <file>\toutput zone to file (default <name>.signed)\n");
+ fprintf(fp, " -i <date>\tinception date\n");
+ fprintf(fp, " -o <domain>\torigin for the zone\n");
+ fprintf(fp, " -v\t\tprint version and exit\n");
+ fprintf(fp, " -A\t\tsign DNSKEY with all keys instead of minimal\n");
+ fprintf(fp, " -E <name>\tuse <name> as the crypto engine for signing\n");
+ fprintf(fp, " \tThis can have a lot of extra options, see the manual page for more info\n");
+ fprintf(fp, " -k <id>,<int>\tuse key id with algorithm int from engine\n");
+ fprintf(fp, " -K <id>,<int>\tuse key id with algorithm int from engine as KSK\n");
+ fprintf(fp, "\t\tif no key is given (but an external one is used through the engine support, it might be necessary to provide the right algorithm number.\n");
+ fprintf(fp, " -n\t\tuse NSEC3 instead of NSEC.\n");
+ fprintf(fp, "\t\tIf you use NSEC3, you can specify the following extra options:\n");
+ fprintf(fp, "\t\t-a [algorithm] hashing algorithm\n");
+ fprintf(fp, "\t\t-t [number] number of hash iterations\n");
+ fprintf(fp, "\t\t-s [string] salt\n");
+ fprintf(fp, "\t\t-p set the opt-out flag on all nsec3 rrs\n");
+ fprintf(fp, "\n");
+ fprintf(fp, " keys must be specified by their base name (usually K<name>+<alg>+<id>),\n");
+ fprintf(fp, " i.e. WITHOUT the .private extension.\n");
+ fprintf(fp, " If the public part of the key is not present in the zone, the DNSKEY RR\n");
+ fprintf(fp, " will be read from the file called <base name>.key. If that does not exist,\n");
+ fprintf(fp, " a default DNSKEY will be generated from the private key and added to the zone.\n");
+ fprintf(fp, " A date can be a timestamp (seconds since the epoch), or of\n the form <YYYYMMdd[hhmmss]>\n");
+}
+
+static void check_tm(struct tm tm)
+{
+ if (tm.tm_year < 70) {
+ fprintf(stderr, "You cannot specify dates before 1970\n");
+ exit(EXIT_FAILURE);
+ }
+ if (tm.tm_mon < 0 || tm.tm_mon > 11) {
+ fprintf(stderr, "The month must be in the range 1 to 12\n");
+ exit(EXIT_FAILURE);
+ }
+ if (tm.tm_mday < 1 || tm.tm_mday > 31) {
+ fprintf(stderr, "The day must be in the range 1 to 31\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (tm.tm_hour < 0 || tm.tm_hour > 23) {
+ fprintf(stderr, "The hour must be in the range 0-23\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (tm.tm_min < 0 || tm.tm_min > 59) {
+ fprintf(stderr, "The minute must be in the range 0-59\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (tm.tm_sec < 0 || tm.tm_sec > 59) {
+ fprintf(stderr, "The second must be in the range 0-59\n");
+ exit(EXIT_FAILURE);
+ }
+
+}
+
+/*
+ * if the ttls are different, make them equal
+ * if one of the ttls equals LDNS_DEFAULT_TTL, that one is changed
+ * otherwise, rr2 will get the ttl of rr1
+ *
+ * prints a warning if a non-default TTL is changed
+ */
+static void
+equalize_ttls(ldns_rr *rr1, ldns_rr *rr2, uint32_t default_ttl)
+{
+ uint32_t ttl1, ttl2;
+
+ ttl1 = ldns_rr_ttl(rr1);
+ ttl2 = ldns_rr_ttl(rr2);
+
+ if (ttl1 != ttl2) {
+ if (ttl1 == default_ttl) {
+ ldns_rr_set_ttl(rr1, ttl2);
+ } else if (ttl2 == default_ttl) {
+ ldns_rr_set_ttl(rr2, ttl1);
+ } else {
+ ldns_rr_set_ttl(rr2, ttl1);
+ fprintf(stderr,
+ "warning: changing non-default TTL %u to %u\n",
+ (unsigned int) ttl2, (unsigned int) ttl1);
+ }
+ }
+}
+
+static void
+equalize_ttls_rr_list(ldns_rr_list *rr_list, ldns_rr *rr, uint32_t default_ttl)
+{
+ size_t i;
+ ldns_rr *cur_rr;
+
+ for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+ cur_rr = ldns_rr_list_rr(rr_list, i);
+ if (ldns_rr_compare_no_rdata(cur_rr, rr) == 0) {
+ equalize_ttls(cur_rr, rr, default_ttl);
+ }
+ }
+}
+
+static ldns_rr *
+find_key_in_zone(ldns_rr *pubkey_gen, ldns_zone *zone) {
+ size_t key_i;
+ ldns_rr *pubkey;
+
+ for (key_i = 0;
+ key_i < ldns_rr_list_rr_count(ldns_zone_rrs(zone));
+ key_i++) {
+ pubkey = ldns_rr_list_rr(ldns_zone_rrs(zone), key_i);
+ if (ldns_rr_get_type(pubkey) == LDNS_RR_TYPE_DNSKEY &&
+ (ldns_calc_keytag(pubkey)
+ ==
+ ldns_calc_keytag(pubkey_gen) ||
+ /* KSK has gen-keytag + 1 */
+ ldns_calc_keytag(pubkey)
+ ==
+ ldns_calc_keytag(pubkey_gen) + 1)
+ ) {
+ if (verbosity >= 2) {
+ fprintf(stderr, "Found it in the zone!\n");
+ }
+ return pubkey;
+ }
+ }
+ return NULL;
+}
+
+static ldns_rr *
+find_key_in_file(const char *keyfile_name_base, ldns_key* ATTR_UNUSED(key),
+ uint32_t zone_ttl)
+{
+ char *keyfile_name;
+ FILE *keyfile;
+ int line_nr;
+ uint32_t default_ttl = zone_ttl;
+
+ ldns_rr *pubkey = NULL;
+ keyfile_name = LDNS_XMALLOC(char,
+ strlen(keyfile_name_base) + 5);
+ snprintf(keyfile_name,
+ strlen(keyfile_name_base) + 5,
+ "%s.key",
+ keyfile_name_base);
+ if (verbosity >= 2) {
+ fprintf(stderr, "Trying to read %s\n", keyfile_name);
+ }
+ keyfile = fopen(keyfile_name, "r");
+ line_nr = 0;
+ if (keyfile) {
+ if (ldns_rr_new_frm_fp_l(&pubkey,
+ keyfile,
+ &default_ttl,
+ NULL,
+ NULL,
+ &line_nr) ==
+ LDNS_STATUS_OK) {
+ if (verbosity >= 2) {
+ printf("Key found in file: %s\n", keyfile_name);
+ }
+ }
+ fclose(keyfile);
+ }
+ LDNS_FREE(keyfile_name);
+ return pubkey;
+}
+
+/* this function tries to find the specified keys either in the zone that
+ * has been read, or in a <basename>.key file. If the key is not found,
+ * a public key is generated, and it is assumed the key is a ZSK
+ *
+ * if add_keys is true; the DNSKEYs are added to the zone prior to signing
+ * if it is false, they are not added.
+ * Even if keys are not added, the function is still needed, to check
+ * whether keys of which we only have key data are KSKs or ZSKS
+ */
+static void
+find_or_create_pubkey(const char *keyfile_name_base, ldns_key *key, ldns_zone *orig_zone, bool add_keys, uint32_t default_ttl) {
+ ldns_rr *pubkey_gen, *pubkey;
+ int key_in_zone;
+
+ if (default_ttl == LDNS_DEFAULT_TTL) {
+ default_ttl = ldns_rr_ttl(ldns_zone_soa(orig_zone));
+ }
+
+ if (!ldns_key_pubkey_owner(key)) {
+ ldns_key_set_pubkey_owner(key, ldns_rdf_clone(ldns_rr_owner(ldns_zone_soa(orig_zone))));
+ }
+
+ /* find the public key in the zone, or in a
+ * seperate file
+ * we 'generate' one anyway,
+ * then match that to any present in the zone,
+ * if it matches, we drop our own. If not,
+ * we try to see if there is a .key file present.
+ * If not, we use our own generated one, with
+ * some default values
+ *
+ * Even if -d (do-not-add-keys) is specified,
+ * we still need to do this, because we need
+ * to have any key flags that are set this way
+ */
+ pubkey_gen = ldns_key2rr(key);
+ ldns_rr_set_ttl(pubkey_gen, default_ttl);
+
+ if (verbosity >= 2) {
+ fprintf(stderr,
+ "Looking for key with keytag %u or %u\n",
+ (unsigned int) ldns_calc_keytag(pubkey_gen),
+ (unsigned int) ldns_calc_keytag(pubkey_gen)+1
+ );
+ }
+
+ pubkey = find_key_in_zone(pubkey_gen, orig_zone);
+ key_in_zone = 1;
+ if (!pubkey) {
+ key_in_zone = 0;
+ /* it was not in the zone, try to read a .key file */
+ pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
+ if (!pubkey && !(ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) {
+ /* maybe it is a ksk? */
+ ldns_key_set_keytag(key, ldns_key_keytag(key) + 1);
+ pubkey = find_key_in_file(keyfile_name_base, key, default_ttl);
+ if (!pubkey) {
+ /* ok, no file, set back to ZSK */
+ ldns_key_set_keytag(key, ldns_key_keytag(key) - 1);
+ }
+ }
+ if(pubkey && ldns_dname_compare(ldns_rr_owner(pubkey), ldns_rr_owner(ldns_zone_soa(orig_zone))) != 0) {
+ fprintf(stderr, "Error %s.key has wrong name: %s\n",
+ keyfile_name_base, ldns_rdf2str(ldns_rr_owner(pubkey)));
+ exit(EXIT_FAILURE); /* leak rdf2str, but we exit */
+ }
+ }
+
+ if (!pubkey) {
+ /* okay, no public key found,
+ just use our generated one */
+ pubkey = pubkey_gen;
+ if (verbosity >= 2) {
+ fprintf(stderr, "Not in zone, no .key file, generating ZSK DNSKEY from private key data\n");
+ }
+ } else {
+ ldns_rr_free(pubkey_gen);
+ }
+ ldns_key_set_flags(key, ldns_rdf2native_int16(ldns_rr_rdf(pubkey, 0)));
+ ldns_key_set_keytag(key, ldns_calc_keytag(pubkey));
+
+ if (add_keys && !key_in_zone) {
+ equalize_ttls_rr_list(ldns_zone_rrs(orig_zone), pubkey, default_ttl);
+ ldns_zone_push_rr(orig_zone, pubkey);
+ }
+}
+
+void
+strip_dnssec_records(ldns_zone *zone)
+{
+ ldns_rr_list *new_list;
+ ldns_rr *cur_rr;
+
+ new_list = ldns_rr_list_new();
+
+ while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(zone)))) {
+ if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG ||
+ ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC ||
+ ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC3
+ ) {
+
+ ldns_rr_free(cur_rr);
+ } else {
+ ldns_rr_list_push_rr(new_list, cur_rr);
+ }
+ }
+ ldns_rr_list_free(ldns_zone_rrs(zone));
+ ldns_zone_set_rrs(zone, new_list);
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *zonefile_name;
+ FILE *zonefile = NULL;
+ int line_nr = 0;
+ int c;
+ int argi;
+ ENGINE *engine = NULL;
+
+ ldns_zone *orig_zone;
+ ldns_rr_list *orig_rrs = NULL;
+ ldns_rr *orig_soa = NULL;
+ ldns_dnssec_zone *signed_zone;
+
+ char *keyfile_name_base;
+ char *keyfile_name = NULL;
+ FILE *keyfile = NULL;
+ ldns_key *key = NULL;
+ ldns_key_list *keys;
+ ldns_status s;
+ size_t i;
+ ldns_rr_list *added_rrs;
+
+ char *outputfile_name = NULL;
+ FILE *outputfile;
+
+ /* tmp vars for engine keys */
+ char *eng_key_l;
+ size_t eng_key_id_len;
+ char *eng_key_id;
+ int eng_key_algo;
+
+ bool use_nsec3 = false;
+ int signflags = 0;
+
+ /* Add the given keys to the zone if they are not yet present */
+ bool add_keys = true;
+ uint8_t nsec3_algorithm = 1;
+ uint8_t nsec3_flags = 0;
+ size_t nsec3_iterations_cmd = 1;
+ uint16_t nsec3_iterations = 1;
+ uint8_t nsec3_salt_length = 0;
+ uint8_t *nsec3_salt = NULL;
+
+ /* we need to know the origin before reading ksk's,
+ * so keep an array of filenames until we know it
+ */
+ struct tm tm;
+ uint32_t inception;
+ uint32_t expiration;
+ ldns_rdf *origin = NULL;
+ uint32_t ttl = LDNS_DEFAULT_TTL;
+ ldns_rr_class class = LDNS_RR_CLASS_IN;
+
+ char *prog = strdup(argv[0]);
+ ldns_status result;
+
+ ldns_output_format fmt = { ldns_output_format_default->flags, NULL };
+ void **hashmap = NULL;
+
+
+ inception = 0;
+ expiration = 0;
+
+ keys = ldns_key_list_new();
+
+ OPENSSL_config(NULL);
+
+ while ((c = getopt(argc, argv, "a:bde:f:i:k:lno:ps:t:vAE:K:")) != -1) {
+ switch (c) {
+ case 'a':
+ nsec3_algorithm = (uint8_t) atoi(optarg);
+ if (nsec3_algorithm != 1) {
+ fprintf(stderr, "Bad NSEC3 algorithm, only RSASHA1 allowed\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'b':
+ fmt.flags |= LDNS_COMMENT_BUBBLEBABBLE;
+ fmt.flags |= LDNS_COMMENT_FLAGS;
+ fmt.flags |= LDNS_COMMENT_NSEC3_CHAIN;
+ fmt.flags |= LDNS_COMMENT_LAYOUT;
+ hashmap = &fmt.data;
+ break;
+ case 'd':
+ add_keys = false;
+ break;
+ case 'e':
+ /* try to parse YYYYMMDD first,
+ * if that doesn't work, it
+ * should be a timestamp (seconds since epoch)
+ */
+ memset(&tm, 0, sizeof(tm));
+
+ if (strlen(optarg) == 8 &&
+ sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
+ ) {
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ check_tm(tm);
+ expiration = (uint32_t) mktime_from_utc(&tm);
+ } else if (strlen(optarg) == 14 &&
+ sscanf(optarg, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)
+ ) {
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ check_tm(tm);
+ expiration = (uint32_t) mktime_from_utc(&tm);
+ } else {
+ expiration = (uint32_t) atol(optarg);
+ }
+ break;
+ case 'f':
+ outputfile_name = LDNS_XMALLOC(char, MAX_FILENAME_LEN);
+ strncpy(outputfile_name, optarg, MAX_FILENAME_LEN);
+ break;
+ case 'i':
+ memset(&tm, 0, sizeof(tm));
+
+ if (strlen(optarg) == 8 &&
+ sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
+ ) {
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ check_tm(tm);
+ inception = (uint32_t) mktime_from_utc(&tm);
+ } else if (strlen(optarg) == 14 &&
+ sscanf(optarg, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)
+ ) {
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ check_tm(tm);
+ inception = (uint32_t) mktime_from_utc(&tm);
+ } else {
+ inception = (uint32_t) atol(optarg);
+ }
+ break;
+ case 'n':
+ use_nsec3 = true;
+ break;
+ case 'o':
+ if (ldns_str2rdf_dname(&origin, optarg) != LDNS_STATUS_OK) {
+ fprintf(stderr, "Bad origin, not a correct domain name\n");
+ usage(stderr, prog);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'p':
+ nsec3_flags = nsec3_flags | LDNS_NSEC3_VARS_OPTOUT_MASK;
+ break;
+ case 'v':
+ printf("zone signer version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
+ exit(EXIT_SUCCESS);
+ break;
+ case 'A':
+ signflags |= LDNS_SIGN_DNSKEY_WITH_ZSK;
+ break;
+ case 'E':
+ ENGINE_load_builtin_engines();
+ ENGINE_load_dynamic();
+ ENGINE_load_cryptodev();
+ engine = ENGINE_by_id(optarg);
+ if (!engine) {
+ printf("No such engine: %s\n", optarg);
+ engine = ENGINE_get_first();
+ printf("Available engines:\n");
+ while (engine) {
+ printf("%s\n", ENGINE_get_id(engine));
+ engine = ENGINE_get_next(engine);
+ }
+ exit(EXIT_FAILURE);
+ } else {
+ if (!ENGINE_init(engine)) {
+ printf("The engine couldn't initialize\n");
+ exit(EXIT_FAILURE);
+ }
+ ENGINE_set_default_RSA(engine);
+ ENGINE_set_default_DSA(engine);
+ ENGINE_set_default(engine, 0);
+ }
+ break;
+ case 'k':
+ eng_key_l = strchr(optarg, ',');
+ if (eng_key_l && strlen(eng_key_l) > 1) {
+ if (eng_key_l > optarg) {
+ eng_key_id_len = (size_t) (eng_key_l - optarg);
+ eng_key_id = malloc(eng_key_id_len + 1);
+ memcpy(eng_key_id, optarg, eng_key_id_len);
+ eng_key_id[eng_key_id_len] = '\0';
+ } else {
+ /* no id given, use default from engine */
+ eng_key_id = NULL;
+ }
+
+ eng_key_algo = atoi(eng_key_l + 1);
+
+ printf("Engine key id: %s, algo %d\n", eng_key_id, eng_key_algo);
+
+ if (expiration != 0) {
+ ldns_key_set_expiration(key, expiration);
+ }
+ if (inception != 0) {
+ ldns_key_set_inception(key, inception);
+ }
+
+ s = ldns_key_new_frm_engine(&key, engine, eng_key_id, eng_key_algo);
+ if (s == LDNS_STATUS_OK) {
+ /* must be dnssec key */
+ switch (ldns_key_algorithm(key)) {
+ case LDNS_SIGN_RSAMD5:
+ case LDNS_SIGN_RSASHA1:
+ case LDNS_SIGN_RSASHA1_NSEC3:
+ case LDNS_SIGN_RSASHA256:
+ case LDNS_SIGN_RSASHA512:
+ case LDNS_SIGN_DSA:
+ case LDNS_SIGN_DSA_NSEC3:
+ case LDNS_SIGN_ECC_GOST:
+#ifdef USE_ECDSA
+ case LDNS_SIGN_ECDSAP256SHA256:
+ case LDNS_SIGN_ECDSAP384SHA384:
+#endif
+ ldns_key_list_push_key(keys, key);
+ /*printf("Added key at %p:\n", key);*/
+ /*ldns_key_print(stdout, key);*/
+ break;
+ default:
+ fprintf(stderr, "Warning, key not suitable for signing, ignoring key with algorithm %u\n", ldns_key_algorithm(key));
+ break;
+ }
+ } else {
+ printf("Error reading key '%s' from engine: %s\n", eng_key_id, ldns_get_errorstr_by_id(s));
+ #ifdef HAVE_SSL
+ if (ERR_peek_error()) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ ERR_free_strings();
+ }
+ #endif
+ exit(EXIT_FAILURE);
+ }
+
+ if (eng_key_id) {
+ free(eng_key_id);
+ }
+ } else {
+ printf("Error: bad engine key specification (should be: -k <id>,<algorithm>)).\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'K':
+ printf("Not implemented yet\n");
+ exit(EXIT_FAILURE);
+ break;
+ case 's':
+ if (strlen(optarg) % 2 != 0) {
+ fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n");
+ exit(EXIT_FAILURE);
+ }
+ nsec3_salt_length = (uint8_t) strlen(optarg) / 2;
+ nsec3_salt = LDNS_XMALLOC(uint8_t, nsec3_salt_length);
+ for (c = 0; c < (int) strlen(optarg); c += 2) {
+ if (isxdigit((int) optarg[c]) && isxdigit((int) optarg[c+1])) {
+ nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 +
+ ldns_hexdigit_to_int(optarg[c+1]);
+ } else {
+ fprintf(stderr, "Salt value is not valid hex data.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ break;
+ case 't':
+ nsec3_iterations_cmd = (size_t) atol(optarg);
+ if (nsec3_iterations_cmd > LDNS_NSEC3_MAX_ITERATIONS) {
+ fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS);
+ exit(EXIT_FAILURE);
+ }
+ nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
+ break;
+ default:
+ usage(stderr, prog);
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ printf("Error: not enough arguments\n");
+ usage(stdout, prog);
+ exit(EXIT_FAILURE);
+ } else {
+ zonefile_name = argv[0];
+ }
+
+ /* read zonefile first to find origin if not specified */
+
+ if (strncmp(zonefile_name, "-", 2) == 0) {
+ s = ldns_zone_new_frm_fp_l(&orig_zone,
+ stdin,
+ origin,
+ ttl,
+ class,
+ &line_nr);
+ if (s != LDNS_STATUS_OK) {
+ fprintf(stderr, "Zone not read, error: %s at stdin line %d\n",
+ ldns_get_errorstr_by_id(s),
+ line_nr);
+ exit(EXIT_FAILURE);
+ } else {
+ orig_soa = ldns_zone_soa(orig_zone);
+ if (!orig_soa) {
+ fprintf(stderr,
+ "Error reading zonefile: missing SOA record\n");
+ exit(EXIT_FAILURE);
+ }
+ orig_rrs = ldns_zone_rrs(orig_zone);
+ if (!orig_rrs) {
+ fprintf(stderr,
+ "Error reading zonefile: no resource records\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ } else {
+ zonefile = fopen(zonefile_name, "r");
+
+ if (!zonefile) {
+ fprintf(stderr,
+ "Error: unable to read %s (%s)\n",
+ zonefile_name,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ } else {
+ s = ldns_zone_new_frm_fp_l(&orig_zone,
+ zonefile,
+ origin,
+ ttl,
+ class,
+ &line_nr);
+ if (s != LDNS_STATUS_OK) {
+ fprintf(stderr, "Zone not read, error: %s at %s line %d\n",
+ ldns_get_errorstr_by_id(s),
+ zonefile_name, line_nr);
+ exit(EXIT_FAILURE);
+ } else {
+ orig_soa = ldns_zone_soa(orig_zone);
+ if (!orig_soa) {
+ fprintf(stderr,
+ "Error reading zonefile: missing SOA record\n");
+ exit(EXIT_FAILURE);
+ }
+ orig_rrs = ldns_zone_rrs(orig_zone);
+ if (!orig_rrs) {
+ fprintf(stderr,
+ "Error reading zonefile: no resource records\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ fclose(zonefile);
+ }
+ }
+
+ if (!origin) {
+ origin = ldns_rr_owner(orig_soa);
+ }
+
+ /* read the ZSKs */
+ argi = 1;
+ while (argi < argc) {
+ keyfile_name_base = argv[argi];
+ keyfile_name = LDNS_XMALLOC(char, strlen(keyfile_name_base) + 9);
+ snprintf(keyfile_name,
+ strlen(keyfile_name_base) + 9,
+ "%s.private",
+ keyfile_name_base);
+ keyfile = fopen(keyfile_name, "r");
+ line_nr = 0;
+ if (!keyfile) {
+ fprintf(stderr,
+ "Error: unable to read %s: %s\n",
+ keyfile_name,
+ strerror(errno));
+ } else {
+ s = ldns_key_new_frm_fp_l(&key, keyfile, &line_nr);
+ fclose(keyfile);
+ if (s == LDNS_STATUS_OK) {
+ /* set times in key? they will end up
+ in the rrsigs
+ */
+ if (expiration != 0) {
+ ldns_key_set_expiration(key, expiration);
+ }
+ if (inception != 0) {
+ ldns_key_set_inception(key, inception);
+ }
+
+ LDNS_FREE(keyfile_name);
+
+ ldns_key_list_push_key(keys, key);
+ } else {
+ fprintf(stderr, "Error reading key from %s at line %d: %s\n", argv[argi], line_nr, ldns_get_errorstr_by_id(s));
+ }
+ }
+ /* and, if not unset by -p, find or create the corresponding DNSKEY record */
+ if (key) {
+ find_or_create_pubkey(keyfile_name_base, key,
+ orig_zone, add_keys, ttl);
+ }
+ argi++;
+ }
+
+ if (ldns_key_list_key_count(keys) < 1) {
+ fprintf(stderr, "Error: no keys to sign with. Aborting.\n\n");
+ usage(stderr, prog);
+ exit(EXIT_FAILURE);
+ }
+
+ signed_zone = ldns_dnssec_zone_new();
+ if (ldns_dnssec_zone_add_rr(signed_zone, ldns_zone_soa(orig_zone)) !=
+ LDNS_STATUS_OK) {
+ fprintf(stderr,
+ "Error adding SOA to dnssec zone, skipping record\n");
+ }
+
+ for (i = 0;
+ i < ldns_rr_list_rr_count(ldns_zone_rrs(orig_zone));
+ i++) {
+ if (ldns_dnssec_zone_add_rr(signed_zone,
+ ldns_rr_list_rr(ldns_zone_rrs(orig_zone),
+ i)) !=
+ LDNS_STATUS_OK) {
+ fprintf(stderr,
+ "Error adding RR to dnssec zone");
+ fprintf(stderr, ", skipping record:\n");
+ ldns_rr_print(stderr,
+ ldns_rr_list_rr(ldns_zone_rrs(orig_zone), i));
+ }
+ }
+
+ /* list to store newly created rrs, so we can free them later */
+ added_rrs = ldns_rr_list_new();
+
+ if (use_nsec3) {
+ result = ldns_dnssec_zone_sign_nsec3_flg_mkmap(signed_zone,
+ added_rrs,
+ keys,
+ ldns_dnssec_default_replace_signatures,
+ NULL,
+ nsec3_algorithm,
+ nsec3_flags,
+ nsec3_iterations,
+ nsec3_salt_length,
+ nsec3_salt,
+ signflags,
+ (ldns_rbtree_t**) hashmap);
+ } else {
+ result = ldns_dnssec_zone_sign_flg(signed_zone,
+ added_rrs,
+ keys,
+ ldns_dnssec_default_replace_signatures,
+ NULL,
+ signflags);
+ }
+ if (result != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error signing zone: %s\n",
+ ldns_get_errorstr_by_id(result));
+ }
+
+ if (!outputfile_name) {
+ outputfile_name = LDNS_XMALLOC(char, MAX_FILENAME_LEN);
+ snprintf(outputfile_name, MAX_FILENAME_LEN, "%s.signed", zonefile_name);
+ }
+
+ if (signed_zone) {
+ if (strncmp(outputfile_name, "-", 2) == 0) {
+ ldns_dnssec_zone_print(stdout, signed_zone);
+ } else {
+ outputfile = fopen(outputfile_name, "w");
+ if (!outputfile) {
+ fprintf(stderr, "Unable to open %s for writing: %s\n",
+ outputfile_name, strerror(errno));
+ } else {
+ ldns_dnssec_zone_print_fmt(
+ outputfile, &fmt, signed_zone);
+ fclose(outputfile);
+ }
+ }
+ } else {
+ fprintf(stderr, "Error signing zone.\n");
+
+#ifdef HAVE_SSL
+ if (ERR_peek_error()) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ ERR_free_strings();
+ }
+#endif
+ exit(EXIT_FAILURE);
+ }
+
+ ldns_key_list_free(keys);
+ /* since the ldns_rr records are pointed to in both the ldns_zone
+ * and the ldns_dnssec_zone, we can either deep_free the
+ * dnssec_zone and 'shallow' free the original zone and added
+ * records, or the other way around
+ */
+ ldns_dnssec_zone_free(signed_zone);
+ ldns_zone_deep_free(orig_zone);
+ ldns_rr_list_deep_free(added_rrs);
+
+ LDNS_FREE(outputfile_name);
+
+ CRYPTO_cleanup_all_ex_data();
+
+ free(prog);
+ exit(EXIT_SUCCESS);
+}
+#else
+int
+main(int argc, char **argv)
+{
+ fprintf(stderr, "ldns-signzone needs OpenSSL support, which has not been compiled in\n");
+ return 1;
+}
+#endif /* HAVE_SSL */
diff --git a/examples/ldns-test-edns.1 b/examples/ldns-test-edns.1
new file mode 100644
index 000000000000..2659ccc47acd
--- /dev/null
+++ b/examples/ldns-test-edns.1
@@ -0,0 +1,41 @@
+.TH ldns-test-edns 1 "14 Dec 2010"
+.SH NAME
+ldns-test-edns \- test if dns cache supports EDNS and DNSSEC.
+.SH SYNOPSIS
+.B ldns-test-edns
+[
+.IR -i
+]
+{
+.IR ip
+}
+.SH DESCRIPTION
+\fBldns-test-edns\fR tests a DNS cache and checks if it supports EDNS0 and
+DNSSEC types so that it can be used as a dnssec-enabled DNS cache. It sends
+two queries to the cache, one for the root key and one for a DS record.
+These must succeed, the answer must have EDNS, that type and signatures.
+.PP
+If the IP address is good for DNSSEC, it is printed with 'OK'. Otherwise
+short description is given of the failure.
+If OK is given, the cache should be good to use as a cache for a local
+configured DNSSEC validator.
+.PP
+The tool assumes the root is signed and Sweden is signed.
+Also, the queries are sent with the CD flag, the tool does not check that the
+results are validated, but that they \fBcan\fR be validated.
+.SH OPTIONS
+\fB-i\fR option enables a mode where the working IP addresses are printed
+after another, with no other explanations, and if none work or no IP addresses
+are on the input, 'off' is printed.
+.PP
+\fBldns-test-edns\fR takes one or more IP addresses, it checks them in turn.
+IPv4 and IPv6 addresses can be given. The exit value is for the last checked
+IP address: 0 is OK, 1 is failure, 2 is some sort of network failure.
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+.SH COPYRIGHT
+Copyright (C) 2010 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-test-edns.c b/examples/ldns-test-edns.c
new file mode 100644
index 000000000000..d9d708c7f31c
--- /dev/null
+++ b/examples/ldns-test-edns.c
@@ -0,0 +1,248 @@
+/*
+ * ldns-test-edns tries to get DNSKEY and RRSIG from an IP address.
+ * This can be used to test if a DNS cache supports DNSSEC (caching RRSIGs),
+ * i.e. for automatic configuration utilities or when you get a new DNS cache
+ * from DHCP and wonder if your local validator could use that as a cache.
+ *
+ * (c) NLnet Labs 2010
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include "errno.h"
+#include <ldns/ldns.h>
+
+/** print error details */
+static int verb = 1;
+
+/** parse IP address */
+static int
+convert_addr(char* str, int p, struct sockaddr_storage* addr, socklen_t* len)
+{
+#ifdef AF_INET6
+ if(strchr(str, ':')) {
+ *len = (socklen_t)sizeof(struct sockaddr_in6);
+ ((struct sockaddr_in6*)addr)->sin6_family = AF_INET6;
+ ((struct sockaddr_in6*)addr)->sin6_port = htons((uint16_t)p);
+ if(inet_pton(AF_INET6, str,
+ &((struct sockaddr_in6*)addr)->sin6_addr) == 1)
+ return 1;
+ } else {
+#endif
+ *len = (socklen_t)sizeof(struct sockaddr_in);
+#ifndef S_SPLINT_S
+ ((struct sockaddr_in*)addr)->sin_family = AF_INET;
+#endif
+ ((struct sockaddr_in*)addr)->sin_port = htons((uint16_t)p);
+ if(inet_pton(AF_INET, str,
+ &((struct sockaddr_in*)addr)->sin_addr) == 1)
+ return 1;
+#ifdef AF_INET6
+ }
+#endif
+ if(verb) printf("error: cannot parse IP address %s\n", str);
+ return 0;
+}
+
+/** create a query to test */
+static ldns_buffer*
+make_query(const char* nm, int tp)
+{
+ /* with EDNS DO and CDFLAG */
+ ldns_buffer* b = ldns_buffer_new(512);
+ ldns_pkt* p;
+ ldns_status s;
+ if(!b) {
+ if(verb) printf("error: out of memory\n");
+ return NULL;
+ }
+
+ s = ldns_pkt_query_new_frm_str(&p, nm, tp, LDNS_RR_CLASS_IN,
+ (uint16_t)(LDNS_RD|LDNS_CD));
+ if(s != LDNS_STATUS_OK) {
+ if(verb) printf("error: %s\n", ldns_get_errorstr_by_id(s));
+ ldns_buffer_free(b);
+ return NULL;
+ }
+ if(!p) {
+ if(verb) printf("error: out of memory\n");
+ ldns_buffer_free(b);
+ return NULL;
+ }
+
+ ldns_pkt_set_edns_do(p, 1);
+ ldns_pkt_set_edns_udp_size(p, 4096);
+ ldns_pkt_set_id(p, ldns_get_random());
+ if( (s=ldns_pkt2buffer_wire(b, p)) != LDNS_STATUS_OK) {
+ if(verb) printf("error: %s\n", ldns_get_errorstr_by_id(s));
+ ldns_pkt_free(p);
+ ldns_buffer_free(b);
+ return NULL;
+ }
+ ldns_pkt_free(p);
+
+ return b;
+}
+
+/** try 3 times to get an EDNS reply from the server, exponential backoff */
+static int
+get_packet(struct sockaddr_storage* addr, socklen_t len, const char* nm,
+ int tp, uint8_t **wire, size_t* wlen)
+{
+ struct timeval t;
+ ldns_buffer* qbin;
+ ldns_status s;
+ int tries = 0;
+
+ memset(&t, 0, sizeof(t));
+ t.tv_usec = 100 * 1000; /* 100 milliseconds (then 200, 400, 800) */
+
+ qbin = make_query(nm, tp);
+ if(!qbin)
+ return 0;
+ while(tries < 4) {
+ tries ++;
+ s = ldns_udp_send(wire, qbin, addr, len, t, wlen);
+ if(s != LDNS_STATUS_NETWORK_ERR) {
+ break;
+ }
+ t.tv_usec *= 2;
+ if(t.tv_usec > 1000*1000) {
+ t.tv_usec -= 1000*1000;
+ t.tv_sec += 1;
+ }
+ }
+ ldns_buffer_free(qbin);
+ if(tries == 4) {
+ if(verb) printf("timeout\n");
+ return 0;
+ }
+ if(s != LDNS_STATUS_OK) {
+ if(verb) printf("error: %s\n", ldns_get_errorstr_by_id(s));
+ return 0;
+ }
+ return 1;
+}
+
+/** test if type is present in returned packet */
+static int
+check_type_in_answer(ldns_pkt* p, int t)
+{
+ ldns_rr_list *l = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANSWER);
+ if(!l) {
+ char* s = ldns_rr_type2str(t);
+ if(verb) printf("no DNSSEC %s\n", s?s:"(out of memory)");
+ LDNS_FREE(s);
+ return 0;
+ }
+ ldns_rr_list_deep_free(l);
+ return 1;
+}
+
+/** check the packet and make sure that EDNS and DO and the type and RRSIG */
+static int
+check_packet(uint8_t* wire, size_t len, int tp)
+{
+ ldns_pkt *p = NULL;
+ ldns_status s;
+ if( (s=ldns_wire2pkt(&p, wire, len)) != LDNS_STATUS_OK) {
+ if(verb) printf("error: %s\n", ldns_get_errorstr_by_id(s));
+ goto failed;
+ }
+ if(!p) {
+ if(verb) printf("error: out of memory\n");
+ goto failed;
+ }
+
+ /* does DNS work? */
+ if(ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
+ char* r = ldns_pkt_rcode2str(ldns_pkt_get_rcode(p));
+ if(verb) printf("no answer, %s\n", r?r:"(out of memory)");
+ LDNS_FREE(r);
+ goto failed;
+ }
+
+ /* test EDNS0 presence, of OPT record */
+ /* LDNS forgets during pkt parse, but we test the ARCOUNT;
+ * 0 additionals means no EDNS(on the wire), and after parsing the
+ * same additional RRs as before means no EDNS OPT */
+ if(LDNS_ARCOUNT(wire) == 0 ||
+ ldns_pkt_arcount(p) == LDNS_ARCOUNT(wire)) {
+ if(verb) printf("no EDNS\n");
+ goto failed;
+ }
+
+ /* test if the type, RRSIG present */
+ if(!check_type_in_answer(p, tp) ||
+ !check_type_in_answer(p, LDNS_RR_TYPE_RRSIG)) {
+ goto failed;
+ }
+
+ LDNS_FREE(wire);
+ ldns_pkt_free(p);
+ return 1;
+failed:
+ LDNS_FREE(wire);
+ ldns_pkt_free(p);
+ return 0;
+}
+
+/** check EDNS at this IP and port */
+static int
+check_edns_ip(char* ip, int port, int info)
+{
+ struct sockaddr_storage addr;
+ socklen_t len = 0;
+ uint8_t* wire;
+ size_t wlen;
+ memset(&addr, 0, sizeof(addr));
+ if(verb) printf("%s ", ip);
+ if(!convert_addr(ip, port, &addr, &len))
+ return 2;
+ /* try to send 3 times to the IP address, test root key */
+ if(!get_packet(&addr, len, ".", LDNS_RR_TYPE_DNSKEY, &wire, &wlen))
+ return 2;
+ if(!check_packet(wire, wlen, LDNS_RR_TYPE_DNSKEY))
+ return 1;
+ /* check support for caching type DS for chains of trust */
+ if(!get_packet(&addr, len, "se.", LDNS_RR_TYPE_DS, &wire, &wlen))
+ return 2;
+ if(!check_packet(wire, wlen, LDNS_RR_TYPE_DS))
+ return 1;
+ if(verb) printf("OK\n");
+ if(info) printf(" %s", ip);
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int i, r=0, info=0, ok=0;
+#ifdef USE_WINSOCK
+ WSADATA wsa_data;
+ if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
+ printf("WSAStartup failed\n"); exit(1);
+ }
+#endif
+ if (argc < 2 || strncmp(argv[1], "-h", 3) == 0) {
+ printf("Usage: ldns-test-edns [-i] {ip address}\n");
+ printf("Tests if the DNS cache at IP address supports EDNS.\n");
+ printf("if it works, print IP address OK.\n");
+ printf("-i: print IPs that are OK or print 'off'.\n");
+ printf("exit value, last IP is 0:OK, 1:fail, 2:net error.\n");
+ exit(1);
+ }
+ if(strcmp(argv[1], "-i") == 0) {
+ info = 1;
+ verb = 0;
+ }
+
+ for(i=1+info; i<argc; i++) {
+ r = check_edns_ip(argv[i], LDNS_PORT, info);
+ if(r == 0)
+ ok++;
+ }
+ if(info && !ok)
+ printf("off\n");
+ return r;
+}
diff --git a/examples/ldns-testns.1 b/examples/ldns-testns.1
new file mode 100644
index 000000000000..c8173e5d1a81
--- /dev/null
+++ b/examples/ldns-testns.1
@@ -0,0 +1,131 @@
+.TH ldns-testns 1 "14 Dec 2006"
+.SH NAME
+ldns-testns \- simple fake nameserver tool
+.SH SYNOPSYS
+.B ldns-testns
+[
+.IR OPTION
+]
+.IR datafile
+
+.SH DESCRIPTION
+\fBldns-testns\fR can be used to provide answers to DNS queries for
+testing. The answers are premade, and can be tailored to testing
+needs. The answers can be wildly invalid or unparseable.
+
+This program is a debugging aid. It is not efficient, especially
+with a long config file, but it can give any reply to any query.
+This can help the developer pre-script replies for queries.
+
+It listens to IP4 UDP and TCP by default.
+You can specify a packet RR by RR with header flags to return.
+
+ldns-testns is not meant for production use.
+
+.SH OPTIONS
+.TP
+\fB-r\fR
+Listens to a random port. The port number is printed to stdout.
+
+.TP
+\fB-p\fR \fIport\fR
+Listens to the specified port.
+
+.TP
+\fB-f\fR \fInum\fR
+Forks this number of additional instances that serve the same ports and
+same datafile. They do not exit; printed is 'forked pid: <num>' and you
+have to kill them yourself.
+
+.TP
+\fB-v\fR
+Outputs more debug information. It is possible to give this option multiple
+times to increase verbosity level.
+
+.TP
+\fB-6\fR
+Bind to IP6 address instead of IP4. Use together with -p.
+
+.TP
+\fBdatafile\fR
+The data file is read on start up. It contains queries and the packets
+that should be sent in answer to those queries. The data file format is
+explained below.
+
+.SH DATA FILE FORMAT
+The data file format has ';' to denote comment. A number of entries
+are processed first to last. The first matching entry is used to answer
+the query with. This is a line based format. DNS resource records
+are entered in zone-file format.
+
+You can use $ORIGIN and $TTL directives. Zone file '(' and ')' to span
+multiple lines are not allowed.
+
+$ORIGIN origin
+$TTL default_ttl
+
+ENTRY_BEGIN
+
+; first give MATCH lines, that say what queries are matched
+; by this entry.
+; 'opcode' makes the query match the opcode from the reply
+; if you leave it out, any opcode matches this entry.
+; 'qtype' makes the query match the qtype from the reply
+; 'qname' makes the query match the qname from the reply
+; 'serial=1023' makes the query match if ixfr serial is 1023.
+
+MATCH [opcode] [qtype] [qname] [serial=<value>]
+MATCH [UDP|TCP]
+MATCH ...
+
+; Then the REPLY header is specified.
+
+REPLY opcode, rcode or flags.
+ (opcode) QUERY IQUERY STATUS NOTIFY UPDATE
+ (rcode) NOERROR FORMERR SERVFAIL NXDOMAIN NOTIMPL YXDOMAIN
+ YXRRSET NXRRSET NOTAUTH NOTZONE
+ (flags) QR AA TC RD CD RA AD
+
+REPLY ...
+
+; any additional actions to do.
+
+ADJUST copy_id ; 'copy_id' copies the ID from the query to the answer.
+
+; 'sleep=10' sleeps for 10 seconds before giving the answer (TCP is open)
+
+ADJUST [sleep=<num>] ; sleep before giving any reply
+ADJUST [packet_sleep=<num>] ; sleep before this packet in sequence
+
+SECTION QUESTION
+<RRs, one per line> ; the RRcount is determined automatically.
+
+SECTION ANSWER
+<RRs, one per line>
+
+SECTION AUTHORITY
+<RRs, one per line>
+
+SECTION ADDITIONAL
+<RRs, one per line>
+
+EXTRA_PACKET ; follow with SECTION, REPLY for more packets.
+HEX_ANSWER_BEGIN ; follow with hex data
+ ; this replaces any answer packet constructed
+ ; with the SECTION keywords (only SECTION QUERY
+ ; is used to match queries). If the data cannot
+ ; be parsed, ADJUST rules for the answer packet
+ ; are ignored
+
+HEX_ANSWER_END
+
+ENTRY_END
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage, and for testing purposes.
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+.SH COPYRIGHT
+Copyright (C) 2006-2008 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-testns.c b/examples/ldns-testns.c
new file mode 100644
index 000000000000..eb007107eb21
--- /dev/null
+++ b/examples/ldns-testns.c
@@ -0,0 +1,577 @@
+/*
+ * ldns-testns. Light-weight DNS daemon, gives canned replies.
+ *
+ * Tiny dns server, that responds with specially crafted replies
+ * to requests. For testing dns software.
+ *
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+/*
+ * This program is a debugging aid. It can is not efficient, especially
+ * with a long config file, but it can give any reply to any query.
+ * This can help the developer pre-script replies for queries.
+ *
+ * It listens to IP4 UDP and TCP by default.
+ * You can specify a packet RR by RR with header flags to return.
+ *
+ * Missing features:
+ * - matching content different from reply content.
+ * - find way to adjust mangled packets?
+ */
+
+/*
+ The data file format is as follows:
+
+ ; comment.
+ ; a number of entries, these are processed first to last.
+ ; a line based format.
+
+ $ORIGIN origin
+ $TTL default_ttl
+
+ ENTRY_BEGIN
+ ; first give MATCH lines, that say what queries are matched
+ ; by this entry.
+ ; 'opcode' makes the query match the opcode from the reply
+ ; if you leave it out, any opcode matches this entry.
+ ; 'qtype' makes the query match the qtype from the reply
+ ; 'qname' makes the query match the qname from the reply
+ ; 'serial=1023' makes the query match if ixfr serial is 1023.
+ MATCH [opcode] [qtype] [qname] [serial=<value>]
+ MATCH [UDP|TCP]
+ MATCH ...
+ ; Then the REPLY header is specified.
+ REPLY opcode, rcode or flags.
+ (opcode) QUERY IQUERY STATUS NOTIFY UPDATE
+ (rcode) NOERROR FORMERR SERVFAIL NXDOMAIN NOTIMPL YXDOMAIN
+ YXRRSET NXRRSET NOTAUTH NOTZONE
+ (flags) QR AA TC RD CD RA AD
+ REPLY ...
+ ; any additional actions to do.
+ ; 'copy_id' copies the ID from the query to the answer.
+ ADJUST copy_id
+ ; 'sleep=10' sleeps for 10 seconds before giving the answer (TCP is open)
+ ADJUST [sleep=<num>] ; sleep before giving any reply
+ ADJUST [packet_sleep=<num>] ; sleep before this packet in sequence
+ SECTION QUESTION
+ <RRs, one per line> ; the RRcount is determined automatically.
+ SECTION ANSWER
+ <RRs, one per line>
+ SECTION AUTHORITY
+ <RRs, one per line>
+ SECTION ADDITIONAL
+ <RRs, one per line>
+ EXTRA_PACKET ; follow with SECTION, REPLY for more packets.
+ HEX_ANSWER_BEGIN ; follow with hex data
+ ; this replaces any answer packet constructed
+ ; with the SECTION keywords (only SECTION QUERY
+ ; is used to match queries). If the data cannot
+ ; be parsed, ADJUST rules for the answer packet
+ ; are ignored
+ HEX_ANSWER_END
+ ENTRY_END
+*/
+
+/* Example data file:
+$ORIGIN nlnetlabs.nl
+$TTL 3600
+
+ENTRY_BEGIN
+MATCH qname
+REPLY NOERROR
+ADJUST copy_id
+SECTION QUESTION
+www.nlnetlabs.nl. IN A
+SECTION ANSWER
+www.nlnetlabs.nl. IN A 195.169.215.155
+SECTION AUTHORITY
+nlnetlabs.nl. IN NS www.nlnetlabs.nl.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH qname
+REPLY NOERROR
+ADJUST copy_id
+SECTION QUESTION
+www2.nlnetlabs.nl. IN A
+HEX_ANSWER_BEGIN
+; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+ 00 bf 81 80 00 01 00 01 00 02 00 02 03 77 77 77 0b 6b 61 6e ; 1- 20
+ 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 00 01 03 77 77 ; 21- 40
+ 77 0b 6b 61 6e 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 ; 41- 60
+ 00 01 00 01 50 8b 00 04 52 5e ed 32 0b 6b 61 6e 61 72 69 65 ; 61- 80
+ 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 8b 00 11 03 ; 81- 100
+ 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 0b 6b 61 6e ; 101- 120
+ 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 ; 121- 140
+ 8b 00 11 03 6e 73 32 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 ; 141- 160
+ 03 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 00 01 00 ; 161- 180
+ 01 00 00 46 53 00 04 52 5e ed 02 03 6e 73 32 08 68 65 78 6f ; 181- 200
+ 6e 2d 69 73 02 6e 6c 00 00 01 00 01 00 00 46 53 00 04 d4 cc ; 201- 220
+ db 5b
+HEX_ANSWER_END
+ENTRY_END
+
+
+*/
+
+struct sockaddr_storage;
+#include "config.h"
+#include <ldns/ldns.h>
+#include "ldns-testpkts.h"
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+#ifdef HAVE_NETINET_IGMP_H
+#include <netinet/igmp.h>
+#endif
+#include <errno.h>
+
+#define INBUF_SIZE 4096 /* max size for incoming queries */
+#define DEFAULT_PORT 53 /* default if no -p port is specified */
+#define CONN_BACKLOG 5 /* 5 connections queued up for tcp */
+static const char* prog_name = "ldns-testns";
+static FILE* logfile = 0;
+static int do_verbose = 0;
+
+static void usage()
+{
+ printf("Usage: %s [options] <datafile>\n", prog_name);
+ printf(" -r listens on random port. Port number is printed.\n");
+ printf(" -p listens on the specified port, default %d.\n", DEFAULT_PORT);
+ printf(" -f forks given number extra instances, default none.\n");
+ printf(" -v more verbose, prints queries, answers and matching.\n");
+ printf(" -6 listen on IP6 any address, instead of IP4 any address.\n");
+ printf("The program answers queries with canned replies from the datafile.\n");
+ exit(EXIT_FAILURE);
+}
+
+static void log_msg(const char* msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ vfprintf(logfile, msg, args);
+ fflush(logfile);
+ va_end(args);
+}
+
+static void error(const char* msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ fprintf(logfile, "%s error: ", prog_name);
+ vfprintf(logfile, msg, args);
+ fprintf(logfile, "\n");
+ fflush(logfile);
+ va_end(args);
+ exit(EXIT_FAILURE);
+}
+
+void verbose(int ATTR_UNUSED(lvl), const char* msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ if(do_verbose)
+ vfprintf(logfile, msg, args);
+ fflush(logfile);
+ va_end(args);
+}
+
+static int bind_port(int sock, int port, int fam)
+{
+ struct sockaddr_in addr;
+#if defined(AF_INET6) && defined(HAVE_GETADDRINFO)
+ if(fam == AF_INET6) {
+ struct sockaddr_in6 addr6;
+ memset(&addr6, 0, sizeof(addr6));
+ addr6.sin6_family = AF_INET6;
+ addr6.sin6_port = (in_port_t)htons((uint16_t)port);
+# if HAVE_DECL_IN6ADDR_ANY
+ addr6.sin6_addr = in6addr_any;
+# else
+ memset(&addr6.sin6_addr, 0, sizeof(addr6.sin6_addr));
+# endif
+ return bind(sock, (struct sockaddr *)&addr6, (socklen_t) sizeof(addr6));
+ }
+#endif
+
+#ifndef S_SPLINT_S
+ addr.sin_family = AF_INET;
+#endif
+ addr.sin_port = (in_port_t)htons((uint16_t)port);
+ addr.sin_addr.s_addr = INADDR_ANY;
+ return bind(sock, (struct sockaddr *)&addr, (socklen_t) sizeof(addr));
+}
+
+struct handle_udp_userdata {
+ int udp_sock;
+ struct sockaddr_storage addr_him;
+ socklen_t hislen;
+};
+static void
+send_udp(uint8_t* buf, size_t len, void* data)
+{
+ struct handle_udp_userdata *userdata = (struct handle_udp_userdata*)data;
+ /* udp send reply */
+ ssize_t nb;
+ nb = sendto(userdata->udp_sock, (void*)buf, len, 0,
+ (struct sockaddr*)&userdata->addr_him, userdata->hislen);
+ if(nb == -1)
+ log_msg("sendto(): %s\n", strerror(errno));
+ else if((size_t)nb != len)
+ log_msg("sendto(): only sent %d of %d octets.\n",
+ (int)nb, (int)len);
+}
+
+static void
+handle_udp(int udp_sock, struct entry* entries, int *count)
+{
+ ssize_t nb;
+ uint8_t inbuf[INBUF_SIZE];
+ struct handle_udp_userdata userdata;
+ userdata.udp_sock = udp_sock;
+
+ userdata.hislen = (socklen_t)sizeof(userdata.addr_him);
+ /* udp recv */
+ nb = recvfrom(udp_sock, (void*)inbuf, INBUF_SIZE, 0,
+ (struct sockaddr*)&userdata.addr_him, &userdata.hislen);
+ if (nb < 1) {
+#ifndef USE_WINSOCK
+ log_msg("recvfrom(): %s\n", strerror(errno));
+#else
+ if(WSAGetLastError() != WSAEINPROGRESS &&
+ WSAGetLastError() != WSAECONNRESET &&
+ WSAGetLastError()!= WSAEWOULDBLOCK)
+ log_msg("recvfrom(): %d\n", WSAGetLastError());
+#endif
+ return;
+ }
+ handle_query(inbuf, nb, entries, count, transport_udp, send_udp,
+ &userdata, do_verbose?logfile:0);
+}
+
+static void
+read_n_bytes(int sock, uint8_t* buf, size_t sz)
+{
+ size_t count = 0;
+ while(count < sz) {
+ ssize_t nb = recv(sock, (void*)(buf+count), sz-count, 0);
+ if(nb < 0) {
+ log_msg("recv(): %s\n", strerror(errno));
+ return;
+ }
+ count += nb;
+ }
+}
+
+static void
+write_n_bytes(int sock, uint8_t* buf, size_t sz)
+{
+ size_t count = 0;
+ while(count < sz) {
+ ssize_t nb = send(sock, (void*)(buf+count), sz-count, 0);
+ if(nb < 0) {
+ log_msg("send(): %s\n", strerror(errno));
+ return;
+ }
+ count += nb;
+ }
+}
+
+struct handle_tcp_userdata {
+ int s;
+};
+static void
+send_tcp(uint8_t* buf, size_t len, void* data)
+{
+ struct handle_tcp_userdata *userdata = (struct handle_tcp_userdata*)data;
+ uint16_t tcplen;
+ /* tcp send reply */
+ tcplen = htons(len);
+ write_n_bytes(userdata->s, (uint8_t*)&tcplen, sizeof(tcplen));
+ write_n_bytes(userdata->s, buf, len);
+}
+
+static void
+handle_tcp(int tcp_sock, struct entry* entries, int *count)
+{
+ int s;
+ struct sockaddr_storage addr_him;
+ socklen_t hislen;
+ uint8_t inbuf[INBUF_SIZE];
+ uint16_t tcplen;
+ struct handle_tcp_userdata userdata;
+
+ /* accept */
+ hislen = (socklen_t)sizeof(addr_him);
+ if((s = accept(tcp_sock, (struct sockaddr*)&addr_him, &hislen)) < 0) {
+ log_msg("accept(): %s\n", strerror(errno));
+ return;
+ }
+ userdata.s = s;
+
+ /* tcp recv */
+ read_n_bytes(s, (uint8_t*)&tcplen, sizeof(tcplen));
+ tcplen = ntohs(tcplen);
+ if(tcplen >= INBUF_SIZE) {
+ log_msg("query %d bytes too large, buffer %d bytes.\n",
+ tcplen, INBUF_SIZE);
+#ifndef USE_WINSOCK
+ close(s);
+#else
+ closesocket(s);
+#endif
+ return;
+ }
+ read_n_bytes(s, inbuf, tcplen);
+
+ handle_query(inbuf, (ssize_t) tcplen, entries, count, transport_tcp,
+ send_tcp, &userdata, do_verbose?logfile:0);
+#ifndef USE_WINSOCK
+ close(s);
+#else
+ closesocket(s);
+#endif
+
+}
+
+/** shared by the service and main routine (forked and threaded) */
+static int udp_sock, tcp_sock;
+static struct entry* entries;
+
+/**
+ * Test DNS server service, uses global udpsock, tcpsock, reply entries
+ * The signature is kept void so the function can be used as a thread function.
+ */
+static void
+service(void)
+{
+ fd_set rset, wset, eset;
+ int count;
+ int maxfd;
+
+ /* service */
+ count = 0;
+ while (1) {
+#ifndef S_SPLINT_S
+ FD_ZERO(&rset);
+ FD_ZERO(&wset);
+ FD_ZERO(&eset);
+ FD_SET(udp_sock, &rset);
+ FD_SET(tcp_sock, &rset);
+#endif
+ maxfd = udp_sock;
+ if(tcp_sock > maxfd)
+ maxfd = tcp_sock;
+ if(select(maxfd+1, &rset, &wset, &eset, NULL) < 0) {
+ error("select(): %s\n", strerror(errno));
+ }
+ if(FD_ISSET(udp_sock, &rset)) {
+ handle_udp(udp_sock, entries, &count);
+ }
+ if(FD_ISSET(tcp_sock, &rset)) {
+ handle_tcp(tcp_sock, entries, &count);
+ }
+ }
+}
+
+static void
+forkit(int number)
+{
+ int i;
+ for(i=0; i<number; i++)
+ {
+#ifndef HAVE_FORK
+#ifndef USE_WINSOCK
+ log_msg("fork() not available.\n");
+ exit(1);
+#else /* USE_WINSOCK */
+ DWORD tid;
+ HANDLE id = CreateThread(NULL, 0,
+ (LPTHREAD_START_ROUTINE)service, NULL,
+ 0, &tid);
+ if(id == NULL) {
+ log_msg("error CreateThread: %d\n", GetLastError());
+ return;
+ }
+ log_msg("thread id: %d\n", (int)tid);
+#endif /* USE_WINSOCK */
+#else /* HAVE_FORK */
+ pid_t pid = fork();
+ if(pid == (pid_t) -1) {
+ log_msg("error forking: %s\n", strerror(errno));
+ return;
+ }
+ if(pid == 0)
+ return; /* child starts serving */
+ log_msg("forked pid: %d\n", (int)pid);
+#endif /* HAVE_FORK */
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ /* arguments */
+ int c;
+ int port = DEFAULT_PORT;
+ const char* datafile;
+ int forknum = 0;
+
+ /* network */
+ int fam = AF_INET;
+ bool random_port_success;
+
+#ifdef USE_WINSOCK
+ WSADATA wsa_data;
+#endif
+
+ /* parse arguments */
+ srandom(time(NULL) ^ getpid());
+ logfile = stdout;
+ prog_name = argv[0];
+ log_msg("%s: start\n", prog_name);
+ while((c = getopt(argc, argv, "6f:p:rv")) != -1) {
+ switch(c) {
+ case '6':
+#ifdef AF_INET6
+ fam = AF_INET6;
+#else
+ log_msg("cannot -6: no IP6 available\n");
+ exit(1);
+#endif
+ break;
+ case 'r':
+ port = 0;
+ break;
+ case 'f':
+ forknum = atoi(optarg);
+ if(forknum < 1)
+ error("invalid forkno %s, give number", optarg);
+ break;
+ case 'p':
+ port = atoi(optarg);
+ if (port < 1) {
+ error("Invalid port %s, use a number.", optarg);
+ }
+ break;
+ case 'v':
+ do_verbose++;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if(argc == 0 || argc > 1)
+ usage();
+
+ datafile = argv[0];
+ log_msg("Reading datafile %s\n", datafile);
+ entries = read_datafile(datafile);
+
+#ifdef USE_WINSOCK
+ if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0)
+ error("WSAStartup failed\n");
+#endif
+
+ if((udp_sock = socket(fam, SOCK_DGRAM, 0)) < 0) {
+ error("udp socket(): %s\n", strerror(errno));
+ }
+ if((tcp_sock = socket(fam, SOCK_STREAM, 0)) < 0) {
+ error("tcp socket(): %s\n", strerror(errno));
+ }
+ c = 1;
+ if(setsockopt(tcp_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&c, (socklen_t) sizeof(int)) < 0) {
+ error("setsockopt(SO_REUSEADDR): %s\n", strerror(errno));
+ }
+
+ /* bind ip4 */
+ if (port > 0) {
+ if (bind_port(udp_sock, port, fam)) {
+ error("cannot bind(): %s\n", strerror(errno));
+ }
+ if (bind_port(tcp_sock, port, fam)) {
+ error("cannot bind(): %s\n", strerror(errno));
+ }
+ if (listen(tcp_sock, CONN_BACKLOG) < 0) {
+ error("listen(): %s\n", strerror(errno));
+ }
+ } else {
+ random_port_success = false;
+ while (!random_port_success) {
+ port = (random() % 64510) + 1025;
+ log_msg("trying to bind to port %d\n", port);
+ random_port_success = true;
+ if (bind_port(udp_sock, port, fam)) {
+#ifdef EADDRINUSE
+ if (errno != EADDRINUSE) {
+#elif defined(USE_WINSOCK)
+ if (WSAGetLastError() != WSAEADDRINUSE) {
+#else
+ if (1) {
+#endif
+ perror("bind()");
+ return -1;
+ } else {
+ random_port_success = false;
+ }
+ }
+ if (random_port_success) {
+ if (bind_port(tcp_sock, port, fam)) {
+#ifdef EADDRINUSE
+ if (errno != EADDRINUSE) {
+#elif defined(USE_WINSOCK)
+ if (WSAGetLastError()!=WSAEADDRINUSE){
+#else
+ if (1) {
+#endif
+ perror("bind()");
+ return -1;
+ } else {
+ random_port_success = false;
+ }
+ }
+ }
+ if (random_port_success) {
+ if (listen(tcp_sock, CONN_BACKLOG) < 0) {
+ error("listen(): %s\n", strerror(errno));
+ }
+ }
+
+ }
+ }
+ log_msg("Listening on port %d\n", port);
+
+ /* forky! */
+ if(forknum > 0)
+ forkit(forknum);
+
+ service();
+
+ return 0;
+}
diff --git a/examples/ldns-testpkts.c b/examples/ldns-testpkts.c
new file mode 100644
index 000000000000..d8139511ab5c
--- /dev/null
+++ b/examples/ldns-testpkts.c
@@ -0,0 +1,881 @@
+/*
+ * ldns-testpkts. Data file parse for test packets, and query matching.
+ *
+ * Data storage for specially crafted replies for testing purposes.
+ *
+ * (c) NLnet Labs, 2005, 2006, 2007, 2008
+ * See the file LICENSE for the license
+ */
+
+/**
+ * \file
+ * This is a debugging aid. It is not efficient, especially
+ * with a long config file, but it can give any reply to any query.
+ * This can help the developer pre-script replies for queries.
+ *
+ * You can specify a packet RR by RR with header flags to return.
+ *
+ * Missing features:
+ * - matching content different from reply content.
+ * - find way to adjust mangled packets?
+ */
+
+#include "config.h"
+struct sockaddr_storage;
+#include <ldns/ldns.h>
+#include <errno.h>
+#include "ldns-testpkts.h"
+
+/** max line length */
+#define MAX_LINE 10240
+/** string to show in warnings and errors */
+static const char* prog_name = "ldns-testpkts";
+
+#ifndef UTIL_LOG_H
+/** verbosity definition for compat */
+enum verbosity_value { NO_VERBOSE=0 };
+#endif
+/** logging routine, provided by caller */
+void verbose(enum verbosity_value lvl, const char* msg, ...) ATTR_FORMAT(printf, 2, 3);
+
+/** print error and exit */
+static void error(const char* msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ fprintf(stderr, "%s error: ", prog_name);
+ vfprintf(stderr, msg, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ va_end(args);
+ exit(EXIT_FAILURE);
+}
+
+/** return if string is empty or comment */
+static bool isendline(char c)
+{
+ if(c == ';' || c == '#'
+ || c == '\n' || c == 0)
+ return true;
+ return false;
+}
+
+/** true if the string starts with the keyword given. Moves the str ahead.
+ * @param str: before keyword, afterwards after keyword and spaces.
+ * @param keyword: the keyword to match
+ * @return: true if keyword present. False otherwise, and str unchanged.
+*/
+static bool str_keyword(char** str, const char* keyword)
+{
+ size_t len = strlen(keyword);
+ assert(str && keyword);
+ if(strncmp(*str, keyword, len) != 0)
+ return false;
+ *str += len;
+ while(isspace((int)**str))
+ (*str)++;
+ return true;
+}
+
+/** Add reply packet to entry */
+static struct reply_packet*
+entry_add_reply(struct entry* entry)
+{
+ struct reply_packet* pkt = (struct reply_packet*)malloc(
+ sizeof(struct reply_packet));
+ struct reply_packet ** p = &entry->reply_list;
+ pkt->next = NULL;
+ pkt->packet_sleep = 0;
+ pkt->reply = ldns_pkt_new();
+ pkt->reply_from_hex = NULL;
+ /* link at end */
+ while(*p)
+ p = &((*p)->next);
+ *p = pkt;
+ return pkt;
+}
+
+/** parse MATCH line */
+static void matchline(char* line, struct entry* e)
+{
+ char* parse = line;
+ while(*parse) {
+ if(isendline(*parse))
+ return;
+ if(str_keyword(&parse, "opcode")) {
+ e->match_opcode = true;
+ } else if(str_keyword(&parse, "qtype")) {
+ e->match_qtype = true;
+ } else if(str_keyword(&parse, "qname")) {
+ e->match_qname = true;
+ } else if(str_keyword(&parse, "subdomain")) {
+ e->match_subdomain = true;
+ } else if(str_keyword(&parse, "all")) {
+ e->match_all = true;
+ } else if(str_keyword(&parse, "ttl")) {
+ e->match_ttl = true;
+ } else if(str_keyword(&parse, "DO")) {
+ e->match_do = true;
+ } else if(str_keyword(&parse, "noedns")) {
+ e->match_noedns = true;
+ } else if(str_keyword(&parse, "UDP")) {
+ e->match_transport = transport_udp;
+ } else if(str_keyword(&parse, "TCP")) {
+ e->match_transport = transport_tcp;
+ } else if(str_keyword(&parse, "serial")) {
+ e->match_serial = true;
+ if(*parse != '=' && *parse != ':')
+ error("expected = or : in MATCH: %s", line);
+ parse++;
+ e->ixfr_soa_serial = (uint32_t)strtol(parse, (char**)&parse, 10);
+ while(isspace((int)*parse))
+ parse++;
+ } else {
+ error("could not parse MATCH: '%s'", parse);
+ }
+ }
+}
+
+/** parse REPLY line */
+static void replyline(char* line, ldns_pkt *reply)
+{
+ char* parse = line;
+ while(*parse) {
+ if(isendline(*parse))
+ return;
+ /* opcodes */
+ if(str_keyword(&parse, "QUERY")) {
+ ldns_pkt_set_opcode(reply, LDNS_PACKET_QUERY);
+ } else if(str_keyword(&parse, "IQUERY")) {
+ ldns_pkt_set_opcode(reply, LDNS_PACKET_IQUERY);
+ } else if(str_keyword(&parse, "STATUS")) {
+ ldns_pkt_set_opcode(reply, LDNS_PACKET_STATUS);
+ } else if(str_keyword(&parse, "NOTIFY")) {
+ ldns_pkt_set_opcode(reply, LDNS_PACKET_NOTIFY);
+ } else if(str_keyword(&parse, "UPDATE")) {
+ ldns_pkt_set_opcode(reply, LDNS_PACKET_UPDATE);
+ /* rcodes */
+ } else if(str_keyword(&parse, "NOERROR")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_NOERROR);
+ } else if(str_keyword(&parse, "FORMERR")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_FORMERR);
+ } else if(str_keyword(&parse, "SERVFAIL")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_SERVFAIL);
+ } else if(str_keyword(&parse, "NXDOMAIN")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_NXDOMAIN);
+ } else if(str_keyword(&parse, "NOTIMPL")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_NOTIMPL);
+ } else if(str_keyword(&parse, "REFUSED")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_REFUSED);
+ } else if(str_keyword(&parse, "YXDOMAIN")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_YXDOMAIN);
+ } else if(str_keyword(&parse, "YXRRSET")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_YXRRSET);
+ } else if(str_keyword(&parse, "NXRRSET")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_NXRRSET);
+ } else if(str_keyword(&parse, "NOTAUTH")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_NOTAUTH);
+ } else if(str_keyword(&parse, "NOTZONE")) {
+ ldns_pkt_set_rcode(reply, LDNS_RCODE_NOTZONE);
+ /* flags */
+ } else if(str_keyword(&parse, "QR")) {
+ ldns_pkt_set_qr(reply, true);
+ } else if(str_keyword(&parse, "AA")) {
+ ldns_pkt_set_aa(reply, true);
+ } else if(str_keyword(&parse, "TC")) {
+ ldns_pkt_set_tc(reply, true);
+ } else if(str_keyword(&parse, "RD")) {
+ ldns_pkt_set_rd(reply, true);
+ } else if(str_keyword(&parse, "CD")) {
+ ldns_pkt_set_cd(reply, true);
+ } else if(str_keyword(&parse, "RA")) {
+ ldns_pkt_set_ra(reply, true);
+ } else if(str_keyword(&parse, "AD")) {
+ ldns_pkt_set_ad(reply, true);
+ } else if(str_keyword(&parse, "DO")) {
+ ldns_pkt_set_edns_udp_size(reply, 4096);
+ ldns_pkt_set_edns_do(reply, true);
+ } else {
+ error("could not parse REPLY: '%s'", parse);
+ }
+ }
+}
+
+/** parse ADJUST line */
+static void adjustline(char* line, struct entry* e,
+ struct reply_packet* pkt)
+{
+ char* parse = line;
+ while(*parse) {
+ if(isendline(*parse))
+ return;
+ if(str_keyword(&parse, "copy_id")) {
+ e->copy_id = true;
+ } else if(str_keyword(&parse, "copy_query")) {
+ e->copy_query = true;
+ } else if(str_keyword(&parse, "sleep=")) {
+ e->sleeptime = (unsigned int) strtol(parse, (char**)&parse, 10);
+ while(isspace((int)*parse))
+ parse++;
+ } else if(str_keyword(&parse, "packet_sleep=")) {
+ pkt->packet_sleep = (unsigned int) strtol(parse, (char**)&parse, 10);
+ while(isspace((int)*parse))
+ parse++;
+ } else {
+ error("could not parse ADJUST: '%s'", parse);
+ }
+ }
+}
+
+/** create new entry */
+static struct entry* new_entry()
+{
+ struct entry* e = LDNS_MALLOC(struct entry);
+ memset(e, 0, sizeof(*e));
+ e->match_opcode = false;
+ e->match_qtype = false;
+ e->match_qname = false;
+ e->match_subdomain = false;
+ e->match_all = false;
+ e->match_ttl = false;
+ e->match_do = false;
+ e->match_noedns = false;
+ e->match_serial = false;
+ e->ixfr_soa_serial = 0;
+ e->match_transport = transport_any;
+ e->reply_list = NULL;
+ e->copy_id = false;
+ e->copy_query = false;
+ e->sleeptime = 0;
+ e->next = NULL;
+ return e;
+}
+
+/**
+ * Converts a hex string to binary data
+ * @param hexstr: string of hex.
+ * @param len: is the length of the string
+ * @param buf: is the buffer to store the result in
+ * @param offset: is the starting position in the result buffer
+ * @param buf_len: is the length of buf.
+ * @return This function returns the length of the result
+ */
+static size_t
+hexstr2bin(char *hexstr, int len, uint8_t *buf, size_t offset, size_t buf_len)
+{
+ char c;
+ int i;
+ uint8_t int8 = 0;
+ int sec = 0;
+ size_t bufpos = 0;
+
+ if (len % 2 != 0) {
+ return 0;
+ }
+
+ for (i=0; i<len; i++) {
+ c = hexstr[i];
+
+ /* case insensitive, skip spaces */
+ if (c != ' ') {
+ if (c >= '0' && c <= '9') {
+ int8 += c & 0x0f;
+ } else if (c >= 'a' && c <= 'z') {
+ int8 += (c & 0x0f) + 9;
+ } else if (c >= 'A' && c <= 'Z') {
+ int8 += (c & 0x0f) + 9;
+ } else {
+ return 0;
+ }
+
+ if (sec == 0) {
+ int8 = int8 << 4;
+ sec = 1;
+ } else {
+ if (bufpos + offset + 1 <= buf_len) {
+ buf[bufpos+offset] = int8;
+ int8 = 0;
+ sec = 0;
+ bufpos++;
+ } else {
+ fprintf(stderr, "Buffer too small in hexstr2bin");
+ }
+ }
+ }
+ }
+ return bufpos;
+}
+
+/** convert hex buffer to binary buffer */
+static ldns_buffer *
+data_buffer2wire(ldns_buffer *data_buffer)
+{
+ ldns_buffer *wire_buffer = NULL;
+ int c;
+
+ /* stat hack
+ * 0 = normal
+ * 1 = comment (skip to end of line)
+ * 2 = unprintable character found, read binary data directly
+ */
+ size_t data_buf_pos = 0;
+ int state = 0;
+ uint8_t *hexbuf;
+ int hexbufpos = 0;
+ size_t wirelen;
+ uint8_t *data_wire = (uint8_t *) ldns_buffer_export(data_buffer);
+ uint8_t *wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
+
+ hexbuf = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
+ for (data_buf_pos = 0; data_buf_pos < ldns_buffer_position(data_buffer); data_buf_pos++) {
+ c = (int) data_wire[data_buf_pos];
+
+ if (state < 2 && !isascii(c)) {
+ /*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/
+ state = 2;
+ }
+ switch (state) {
+ case 0:
+ if ( (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F') )
+ {
+ hexbuf[hexbufpos] = (uint8_t) c;
+ hexbufpos++;
+ } else if (c == ';') {
+ state = 1;
+ } else if (c == ' ' || c == '\t' || c == '\n') {
+ /* skip whitespace */
+ }
+ break;
+ case 1:
+ if (c == '\n' || c == EOF) {
+ state = 0;
+ }
+ break;
+ case 2:
+ hexbuf[hexbufpos] = (uint8_t) c;
+ hexbufpos++;
+ break;
+ default:
+ error("unknown state while reading");
+ LDNS_FREE(hexbuf);
+ return 0;
+ break;
+ }
+ }
+
+ if (hexbufpos >= LDNS_MAX_PACKETLEN) {
+ /*verbose("packet size reached\n");*/
+ }
+
+ /* lenient mode: length must be multiple of 2 */
+ if (hexbufpos % 2 != 0) {
+ hexbuf[hexbufpos] = (uint8_t) '0';
+ hexbufpos++;
+ }
+
+ if (state < 2) {
+ wirelen = hexstr2bin((char *) hexbuf, hexbufpos, wire, 0, LDNS_MAX_PACKETLEN);
+ wire_buffer = ldns_buffer_new(wirelen);
+ ldns_buffer_new_frm_data(wire_buffer, wire, wirelen);
+ } else {
+ error("Incomplete hex data, not at byte boundary\n");
+ }
+ LDNS_FREE(wire);
+ LDNS_FREE(hexbuf);
+ return wire_buffer;
+}
+
+/** parse ORIGIN */
+static void
+get_origin(const char* name, int lineno, ldns_rdf** origin, char* parse)
+{
+ /* snip off rest of the text so as to make the parse work in ldns */
+ char* end;
+ char store;
+ ldns_status status;
+
+ ldns_rdf_free(*origin);
+ *origin = NULL;
+
+ end=parse;
+ while(!isspace((int)*end) && !isendline(*end))
+ end++;
+ store = *end;
+ *end = 0;
+ verbose(3, "parsing '%s'\n", parse);
+ status = ldns_str2rdf_dname(origin, parse);
+ *end = store;
+ if (status != LDNS_STATUS_OK)
+ error("%s line %d:\n\t%s: %s", name, lineno,
+ ldns_get_errorstr_by_id(status), parse);
+}
+
+/* Reads one entry from file. Returns entry or NULL on error. */
+struct entry*
+read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl,
+ ldns_rdf** origin, ldns_rdf** prev_rr)
+{
+ struct entry* current = NULL;
+ char line[MAX_LINE];
+ char* parse;
+ ldns_pkt_section add_section = LDNS_SECTION_QUESTION;
+ struct reply_packet *cur_reply = NULL;
+ bool reading_hex = false;
+ ldns_buffer* hex_data_buffer = NULL;
+
+ while(fgets(line, (int)sizeof(line), in) != NULL) {
+ line[MAX_LINE-1] = 0;
+ parse = line;
+ (*lineno) ++;
+
+ while(isspace((int)*parse))
+ parse++;
+ /* test for keywords */
+ if(isendline(*parse))
+ continue; /* skip comment and empty lines */
+ if(str_keyword(&parse, "ENTRY_BEGIN")) {
+ if(current) {
+ error("%s line %d: previous entry does not ENTRY_END",
+ name, *lineno);
+ }
+ current = new_entry();
+ current->lineno = *lineno;
+ cur_reply = entry_add_reply(current);
+ continue;
+ } else if(str_keyword(&parse, "$ORIGIN")) {
+ get_origin(name, *lineno, origin, parse);
+ continue;
+ } else if(str_keyword(&parse, "$TTL")) {
+ *default_ttl = (uint32_t)atoi(parse);
+ continue;
+ }
+
+ /* working inside an entry */
+ if(!current) {
+ error("%s line %d: expected ENTRY_BEGIN but got %s",
+ name, *lineno, line);
+ }
+ if(str_keyword(&parse, "MATCH")) {
+ matchline(parse, current);
+ } else if(str_keyword(&parse, "REPLY")) {
+ replyline(parse, cur_reply->reply);
+ } else if(str_keyword(&parse, "ADJUST")) {
+ adjustline(parse, current, cur_reply);
+ } else if(str_keyword(&parse, "EXTRA_PACKET")) {
+ cur_reply = entry_add_reply(current);
+ } else if(str_keyword(&parse, "SECTION")) {
+ if(str_keyword(&parse, "QUESTION"))
+ add_section = LDNS_SECTION_QUESTION;
+ else if(str_keyword(&parse, "ANSWER"))
+ add_section = LDNS_SECTION_ANSWER;
+ else if(str_keyword(&parse, "AUTHORITY"))
+ add_section = LDNS_SECTION_AUTHORITY;
+ else if(str_keyword(&parse, "ADDITIONAL"))
+ add_section = LDNS_SECTION_ADDITIONAL;
+ else error("%s line %d: bad section %s", name, *lineno, parse);
+ } else if(str_keyword(&parse, "HEX_ANSWER_BEGIN")) {
+ hex_data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+ reading_hex = true;
+ } else if(str_keyword(&parse, "HEX_ANSWER_END")) {
+ if (!reading_hex) {
+ error("%s line %d: HEX_ANSWER_END read but no HEX_ANSWER_BEGIN keyword seen", name, *lineno);
+ }
+ reading_hex = false;
+ cur_reply->reply_from_hex = data_buffer2wire(hex_data_buffer);
+ ldns_buffer_free(hex_data_buffer);
+ } else if(str_keyword(&parse, "ENTRY_END")) {
+ return current;
+ } else if(reading_hex) {
+ ldns_buffer_printf(hex_data_buffer, line);
+ } else {
+ /* it must be a RR, parse and add to packet. */
+ ldns_rr* n = NULL;
+ ldns_status status;
+ if(add_section == LDNS_SECTION_QUESTION)
+ status = ldns_rr_new_question_frm_str(
+ &n, parse, *origin, prev_rr);
+ else status = ldns_rr_new_frm_str(&n, parse,
+ *default_ttl, *origin, prev_rr);
+ if(status != LDNS_STATUS_OK)
+ error("%s line %d:\n\t%s: %s", name, *lineno,
+ ldns_get_errorstr_by_id(status), parse);
+ ldns_pkt_push_rr(cur_reply->reply, add_section, n);
+ }
+
+ }
+ if (reading_hex) {
+ error("%s: End of file reached while still reading hex, "
+ "missing HEX_ANSWER_END\n", name);
+ }
+ if(current) {
+ error("%s: End of file reached while reading entry. "
+ "missing ENTRY_END\n", name);
+ }
+ return 0;
+}
+
+/* reads the canned reply file and returns a list of structs */
+struct entry*
+read_datafile(const char* name)
+{
+ struct entry* list = NULL;
+ struct entry* last = NULL;
+ struct entry* current = NULL;
+ FILE *in;
+ int lineno = 0;
+ uint32_t default_ttl = 0;
+ ldns_rdf* origin = NULL;
+ ldns_rdf* prev_rr = NULL;
+ int entry_num = 0;
+
+ if((in=fopen(name, "r")) == NULL) {
+ error("could not open file %s: %s", name, strerror(errno));
+ }
+
+ while((current = read_entry(in, name, &lineno, &default_ttl,
+ &origin, &prev_rr)))
+ {
+ if(last)
+ last->next = current;
+ else list = current;
+ last = current;
+ entry_num ++;
+ }
+ verbose(1, "%s: Read %d entries\n", prog_name, entry_num);
+
+ fclose(in);
+ ldns_rdf_deep_free(origin);
+ ldns_rdf_deep_free(prev_rr);
+ return list;
+}
+
+/** get qtype from rr */
+static ldns_rr_type get_qtype(ldns_pkt* p)
+{
+ if(!ldns_rr_list_rr(ldns_pkt_question(p), 0))
+ return 0;
+ return ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_question(p), 0));
+}
+
+/** returns owner from rr */
+static ldns_rdf* get_owner(ldns_pkt* p)
+{
+ if(!ldns_rr_list_rr(ldns_pkt_question(p), 0))
+ return NULL;
+ return ldns_rr_owner(ldns_rr_list_rr(ldns_pkt_question(p), 0));
+}
+
+/** get authority section SOA serial value */
+static uint32_t get_serial(ldns_pkt* p)
+{
+ ldns_rr *rr = ldns_rr_list_rr(ldns_pkt_authority(p), 0);
+ ldns_rdf *rdf;
+ uint32_t val;
+ if(!rr) return 0;
+ rdf = ldns_rr_rdf(rr, 2);
+ if(!rdf) return 0;
+ val = ldns_rdf2native_int32(rdf);
+ verbose(3, "found serial %u in msg. ", (int)val);
+ return val;
+}
+
+/** match two rr lists */
+static int
+match_list(ldns_rr_list* q, ldns_rr_list *p, bool mttl)
+{
+ size_t i;
+ if(ldns_rr_list_rr_count(q) != ldns_rr_list_rr_count(p))
+ return 0;
+ for(i=0; i<ldns_rr_list_rr_count(q); i++)
+ {
+ if(ldns_rr_compare(ldns_rr_list_rr(q, i),
+ ldns_rr_list_rr(p, i)) != 0) {
+ verbose(3, "rr %d different", (int)i);
+ return 0;
+ }
+ if(mttl && ldns_rr_ttl(ldns_rr_list_rr(q, i)) !=
+ ldns_rr_ttl(ldns_rr_list_rr(p, i))) {
+ verbose(3, "rr %d ttl different", (int)i);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/** compare two booleans */
+static int
+cmp_bool(int x, int y)
+{
+ if(!x && !y) return 0;
+ if(x && y) return 0;
+ if(!x) return -1;
+ return 1;
+}
+
+/** match all of the packet */
+static int
+match_all(ldns_pkt* q, ldns_pkt* p, bool mttl)
+{
+ if(ldns_pkt_get_opcode(q) != ldns_pkt_get_opcode(p))
+ { verbose(3, "allmatch: opcode different"); return 0;}
+ if(ldns_pkt_get_rcode(q) != ldns_pkt_get_rcode(p))
+ { verbose(3, "allmatch: rcode different"); return 0;}
+ if(ldns_pkt_id(q) != ldns_pkt_id(p))
+ { verbose(3, "allmatch: id different"); return 0;}
+ if(cmp_bool(ldns_pkt_qr(q), ldns_pkt_qr(p)) != 0)
+ { verbose(3, "allmatch: qr different"); return 0;}
+ if(cmp_bool(ldns_pkt_aa(q), ldns_pkt_aa(p)) != 0)
+ { verbose(3, "allmatch: aa different"); return 0;}
+ if(cmp_bool(ldns_pkt_tc(q), ldns_pkt_tc(p)) != 0)
+ { verbose(3, "allmatch: tc different"); return 0;}
+ if(cmp_bool(ldns_pkt_rd(q), ldns_pkt_rd(p)) != 0)
+ { verbose(3, "allmatch: rd different"); return 0;}
+ if(cmp_bool(ldns_pkt_cd(q), ldns_pkt_cd(p)) != 0)
+ { verbose(3, "allmatch: cd different"); return 0;}
+ if(cmp_bool(ldns_pkt_ra(q), ldns_pkt_ra(p)) != 0)
+ { verbose(3, "allmatch: ra different"); return 0;}
+ if(cmp_bool(ldns_pkt_ad(q), ldns_pkt_ad(p)) != 0)
+ { verbose(3, "allmatch: ad different"); return 0;}
+ if(ldns_pkt_qdcount(q) != ldns_pkt_qdcount(p))
+ { verbose(3, "allmatch: qdcount different"); return 0;}
+ if(ldns_pkt_ancount(q) != ldns_pkt_ancount(p))
+ { verbose(3, "allmatch: ancount different"); return 0;}
+ if(ldns_pkt_nscount(q) != ldns_pkt_nscount(p))
+ { verbose(3, "allmatch: nscount different"); return 0;}
+ if(ldns_pkt_arcount(q) != ldns_pkt_arcount(p))
+ { verbose(3, "allmatch: arcount different"); return 0;}
+ if(!match_list(ldns_pkt_question(q), ldns_pkt_question(p), 0))
+ { verbose(3, "allmatch: qd section different"); return 0;}
+ if(!match_list(ldns_pkt_answer(q), ldns_pkt_answer(p), mttl))
+ { verbose(3, "allmatch: an section different"); return 0;}
+ if(!match_list(ldns_pkt_authority(q), ldns_pkt_authority(p), mttl))
+ { verbose(3, "allmatch: ar section different"); return 0;}
+ if(!match_list(ldns_pkt_additional(q), ldns_pkt_additional(p), mttl))
+ { verbose(3, "allmatch: ns section different"); return 0;}
+ return 1;
+}
+
+/* finds entry in list, or returns NULL */
+struct entry*
+find_match(struct entry* entries, ldns_pkt* query_pkt,
+ enum transport_type transport)
+{
+ struct entry* p = entries;
+ ldns_pkt* reply = NULL;
+ for(p=entries; p; p=p->next) {
+ verbose(3, "comparepkt: ");
+ reply = p->reply_list->reply;
+ if(p->match_opcode && ldns_pkt_get_opcode(query_pkt) !=
+ ldns_pkt_get_opcode(reply)) {
+ verbose(3, "bad opcode\n");
+ continue;
+ }
+ if(p->match_qtype && get_qtype(query_pkt) != get_qtype(reply)) {
+ verbose(3, "bad qtype\n");
+ continue;
+ }
+ if(p->match_qname) {
+ if(!get_owner(query_pkt) || !get_owner(reply) ||
+ ldns_dname_compare(
+ get_owner(query_pkt), get_owner(reply)) != 0) {
+ verbose(3, "bad qname\n");
+ continue;
+ }
+ }
+ if(p->match_subdomain) {
+ if(!get_owner(query_pkt) || !get_owner(reply) ||
+ (ldns_dname_compare(get_owner(query_pkt),
+ get_owner(reply)) != 0 &&
+ !ldns_dname_is_subdomain(
+ get_owner(query_pkt), get_owner(reply))))
+ {
+ verbose(3, "bad subdomain\n");
+ continue;
+ }
+ }
+ if(p->match_serial && get_serial(query_pkt) != p->ixfr_soa_serial) {
+ verbose(3, "bad serial\n");
+ continue;
+ }
+ if(p->match_do && !ldns_pkt_edns_do(query_pkt)) {
+ verbose(3, "no DO bit set\n");
+ continue;
+ }
+ if(p->match_noedns && ldns_pkt_edns(query_pkt)) {
+ verbose(3, "bad; EDNS OPT present\n");
+ continue;
+ }
+ if(p->match_transport != transport_any && p->match_transport != transport) {
+ verbose(3, "bad transport\n");
+ continue;
+ }
+ if(p->match_all && !match_all(query_pkt, reply, p->match_ttl)) {
+ verbose(3, "bad allmatch\n");
+ continue;
+ }
+ verbose(3, "match!\n");
+ return p;
+ }
+ return NULL;
+}
+
+void
+adjust_packet(struct entry* match, ldns_pkt* answer_pkt, ldns_pkt* query_pkt)
+{
+ /* copy & adjust packet */
+ if(match->copy_id)
+ ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));
+ if(match->copy_query) {
+ ldns_rr_list* list = ldns_pkt_get_section_clone(query_pkt,
+ LDNS_SECTION_QUESTION);
+ ldns_rr_list_deep_free(ldns_pkt_question(answer_pkt));
+ ldns_pkt_set_question(answer_pkt, list);
+ }
+ if(match->sleeptime > 0) {
+ verbose(3, "sleeping for %d seconds\n", match->sleeptime);
+#ifdef HAVE_SLEEP
+ sleep(match->sleeptime);
+#else
+ Sleep(match->sleeptime * 1000);
+#endif
+ }
+}
+
+/*
+ * Parses data buffer to a query, finds the correct answer
+ * and calls the given function for every packet to send.
+ */
+void
+handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
+ enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*),
+ void* userdata, FILE* verbose_out)
+{
+ ldns_status status;
+ ldns_pkt *query_pkt = NULL;
+ ldns_pkt *answer_pkt = NULL;
+ struct reply_packet *p;
+ ldns_rr *query_rr = NULL;
+ uint8_t *outbuf = NULL;
+ size_t answer_size = 0;
+ struct entry* entry = NULL;
+ ldns_rdf *stop_command = ldns_dname_new_frm_str("server.stop.");
+
+ status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen);
+ if (status != LDNS_STATUS_OK) {
+ verbose(1, "Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
+ ldns_rdf_free(stop_command);
+ return;
+ }
+
+ query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
+ verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count), (int)ldns_pkt_id(query_pkt),
+ (transport==transport_tcp)?"TCP":"UDP", (int)inlen);
+ if(verbose_out) ldns_rr_print(verbose_out, query_rr);
+ if(verbose_out) ldns_pkt_print(verbose_out, query_pkt);
+
+ if (ldns_rr_get_type(query_rr) == LDNS_RR_TYPE_TXT &&
+ ldns_rr_get_class(query_rr) == LDNS_RR_CLASS_CH &&
+ ldns_dname_compare(ldns_rr_owner(query_rr), stop_command) == 0) {
+ exit(0);
+ }
+
+ /* fill up answer packet */
+ entry = find_match(entries, query_pkt, transport);
+ if(!entry || !entry->reply_list) {
+ verbose(1, "no answer packet for this query, no reply.\n");
+ ldns_pkt_free(query_pkt);
+ ldns_rdf_free(stop_command);
+ return;
+ }
+ for(p = entry->reply_list; p; p = p->next)
+ {
+ verbose(3, "Answer pkt:\n");
+ if (p->reply_from_hex) {
+ /* try to parse the hex packet, if it can be
+ * parsed, we can use adjust rules. if not,
+ * send packet literally */
+ status = ldns_buffer2pkt_wire(&answer_pkt, p->reply_from_hex);
+ if (status == LDNS_STATUS_OK) {
+ adjust_packet(entry, answer_pkt, query_pkt);
+ if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
+ status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
+ verbose(2, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
+ if (status != LDNS_STATUS_OK) {
+ verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
+ ldns_pkt_free(query_pkt);
+ ldns_rdf_free(stop_command);
+ return;
+ }
+ ldns_pkt_free(answer_pkt);
+ answer_pkt = NULL;
+ } else {
+ verbose(3, "Could not parse hex data (%s), sending hex data directly.\n", ldns_get_errorstr_by_id(status));
+ /* still try to adjust ID */
+ answer_size = ldns_buffer_capacity(p->reply_from_hex);
+ outbuf = LDNS_XMALLOC(uint8_t, answer_size);
+ memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size);
+ if(entry->copy_id) {
+ ldns_write_uint16(outbuf,
+ ldns_pkt_id(query_pkt));
+ }
+ }
+ } else {
+ answer_pkt = ldns_pkt_clone(p->reply);
+ adjust_packet(entry, answer_pkt, query_pkt);
+ if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
+ status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
+ verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
+ if (status != LDNS_STATUS_OK) {
+ verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
+ ldns_pkt_free(query_pkt);
+ ldns_rdf_free(stop_command);
+ return;
+ }
+ ldns_pkt_free(answer_pkt);
+ answer_pkt = NULL;
+ }
+ if(p->packet_sleep) {
+ verbose(3, "sleeping for next packet %d secs\n",
+ p->packet_sleep);
+#ifdef HAVE_SLEEP
+ sleep(p->packet_sleep);
+#else
+ Sleep(p->packet_sleep * 1000);
+#endif
+ verbose(3, "wakeup for next packet "
+ "(slept %d secs)\n", p->packet_sleep);
+ }
+ sendfunc(outbuf, answer_size, userdata);
+ LDNS_FREE(outbuf);
+ outbuf = NULL;
+ answer_size = 0;
+ }
+ ldns_pkt_free(query_pkt);
+ ldns_rdf_free(stop_command);
+}
+
+/** delete the list of reply packets */
+void delete_replylist(struct reply_packet* replist)
+{
+ struct reply_packet *p=replist, *np;
+ while(p) {
+ np = p->next;
+ ldns_pkt_free(p->reply);
+ ldns_buffer_free(p->reply_from_hex);
+ free(p);
+ p=np;
+ }
+}
+
+void delete_entry(struct entry* list)
+{
+ struct entry *p=list, *np;
+ while(p) {
+ np = p->next;
+ delete_replylist(p->reply_list);
+ free(p);
+ p = np;
+ }
+}
diff --git a/examples/ldns-testpkts.h b/examples/ldns-testpkts.h
new file mode 100644
index 000000000000..59e428952759
--- /dev/null
+++ b/examples/ldns-testpkts.h
@@ -0,0 +1,255 @@
+/*
+ * ldns-testpkts. Data file parse for test packets, and query matching.
+ *
+ * Data storage for specially crafted replies for testing purposes.
+ *
+ * (c) NLnet Labs, 2005, 2006, 2007
+ * See the file LICENSE for the license
+ */
+
+#ifndef LDNS_TESTPKTS_H
+#define LDNS_TESTPKTS_H
+
+/**
+ * \file
+ *
+ * This is a debugging aid. It is not efficient, especially
+ * with a long config file, but it can give any reply to any query.
+ * This can help the developer pre-script replies for queries.
+ *
+ * You can specify a packet RR by RR with header flags to return.
+ *
+ * Missing features:
+ * - matching content different from reply content.
+ * - find way to adjust mangled packets?
+ *
+ */
+
+ /*
+ The data file format is as follows:
+
+ ; comment.
+ ; a number of entries, these are processed first to last.
+ ; a line based format.
+
+ $ORIGIN origin
+ $TTL default_ttl
+
+ ENTRY_BEGIN
+ ; first give MATCH lines, that say what queries are matched
+ ; by this entry.
+ ; 'opcode' makes the query match the opcode from the reply
+ ; if you leave it out, any opcode matches this entry.
+ ; 'qtype' makes the query match the qtype from the reply
+ ; 'qname' makes the query match the qname from the reply
+ ; 'subdomain' makes the query match subdomains of qname from the reply
+ ; 'serial=1023' makes the query match if ixfr serial is 1023.
+ ; 'all' has to match header byte for byte and all rrs in packet.
+ ; 'ttl' used with all, rrs in packet must also have matching TTLs.
+ ; 'DO' will match only queries with DO bit set.
+ ; 'noedns' matches queries without EDNS OPT records.
+ MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl]
+ MATCH [UDP|TCP] DO
+ MATCH ...
+ ; Then the REPLY header is specified.
+ REPLY opcode, rcode or flags.
+ (opcode) QUERY IQUERY STATUS NOTIFY UPDATE
+ (rcode) NOERROR FORMERR SERVFAIL NXDOMAIN NOTIMPL YXDOMAIN
+ YXRRSET NXRRSET NOTAUTH NOTZONE
+ (flags) QR AA TC RD CD RA AD DO
+ REPLY ...
+ ; any additional actions to do.
+ ; 'copy_id' copies the ID from the query to the answer.
+ ADJUST copy_id
+ ; 'copy_query' copies the query name, type and class to the answer.
+ ADJUST copy_query
+ ; 'sleep=10' sleeps for 10 seconds before giving the answer (TCP is open)
+ ADJUST [sleep=<num>] ; sleep before giving any reply
+ ADJUST [packet_sleep=<num>] ; sleep before this packet in sequence
+ SECTION QUESTION
+ <RRs, one per line> ; the RRcount is determined automatically.
+ SECTION ANSWER
+ <RRs, one per line>
+ SECTION AUTHORITY
+ <RRs, one per line>
+ SECTION ADDITIONAL
+ <RRs, one per line>
+ EXTRA_PACKET ; follow with SECTION, REPLY for more packets.
+ HEX_ANSWER_BEGIN ; follow with hex data
+ ; this replaces any answer packet constructed
+ ; with the SECTION keywords (only SECTION QUERY
+ ; is used to match queries). If the data cannot
+ ; be parsed, ADJUST rules for the answer packet
+ ; are ignored. Only copy_id is done.
+ HEX_ANSWER_END
+ ENTRY_END
+
+
+ Example data file:
+$ORIGIN nlnetlabs.nl
+$TTL 3600
+
+ENTRY_BEGIN
+MATCH qname
+REPLY NOERROR
+ADJUST copy_id
+SECTION QUESTION
+www.nlnetlabs.nl. IN A
+SECTION ANSWER
+www.nlnetlabs.nl. IN A 195.169.215.155
+SECTION AUTHORITY
+nlnetlabs.nl. IN NS www.nlnetlabs.nl.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH qname
+REPLY NOERROR
+ADJUST copy_id
+SECTION QUESTION
+www2.nlnetlabs.nl. IN A
+HEX_ANSWER_BEGIN
+; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+ 00 bf 81 80 00 01 00 01 00 02 00 02 03 77 77 77 0b 6b 61 6e ; 1- 20
+ 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 00 01 03 77 77 ; 21- 40
+ 77 0b 6b 61 6e 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 ; 41- 60
+ 00 01 00 01 50 8b 00 04 52 5e ed 32 0b 6b 61 6e 61 72 69 65 ; 61- 80
+ 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 8b 00 11 03 ; 81- 100
+ 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 0b 6b 61 6e ; 101- 120
+ 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 ; 121- 140
+ 8b 00 11 03 6e 73 32 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 ; 141- 160
+ 03 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 00 01 00 ; 161- 180
+ 01 00 00 46 53 00 04 52 5e ed 02 03 6e 73 32 08 68 65 78 6f ; 181- 200
+ 6e 2d 69 73 02 6e 6c 00 00 01 00 01 00 00 46 53 00 04 d4 cc ; 201- 220
+ db 5b
+HEX_ANSWER_END
+ENTRY_END
+
+
+
+ note that this file will link with your
+ void verbose(int level, char* format, ...); output function.
+*/
+
+#include <ldns/ldns.h>
+
+/** Type of transport, since some entries match based on UDP or TCP of query */
+enum transport_type {transport_any = 0, transport_udp, transport_tcp };
+
+/** struct to keep a linked list of reply packets for a query */
+struct reply_packet {
+ /** next in list of reply packets, for TCP multiple pkts on wire */
+ struct reply_packet* next;
+ /** the reply pkt */
+ ldns_pkt* reply;
+ /** or reply pkt in hex if not parsable */
+ ldns_buffer* reply_from_hex;
+ /** seconds to sleep before giving packet */
+ unsigned int packet_sleep;
+};
+
+/** data structure to keep the canned queries in.
+ format is the 'matching query' and the 'canned answer' */
+struct entry {
+ /* match */
+ /* How to match an incoming query with this canned reply */
+ /** match query opcode with answer opcode */
+ bool match_opcode;
+ /** match qtype with answer qtype */
+ bool match_qtype;
+ /** match qname with answer qname */
+ bool match_qname;
+ /** match qname as subdomain of answer qname */
+ bool match_subdomain;
+ /** match SOA serial number, from auth section */
+ bool match_serial;
+ /** match all of the packet */
+ bool match_all;
+ /** match ttls in the packet */
+ bool match_ttl;
+ /** match DO bit */
+ bool match_do;
+ /** match absence of EDNS OPT record in query */
+ bool match_noedns;
+ /** match query serial with this value. */
+ uint32_t ixfr_soa_serial;
+ /** match on UDP/TCP */
+ enum transport_type match_transport;
+
+ /** pre canned reply */
+ struct reply_packet *reply_list;
+
+ /** how to adjust the reply packet */
+ /** copy over the ID from the query into the answer */
+ bool copy_id;
+ /** copy the query nametypeclass from query into the answer */
+ bool copy_query;
+ /** in seconds */
+ unsigned int sleeptime;
+
+ /** some number that names this entry, line number in file or so */
+ int lineno;
+
+ /** next in list */
+ struct entry* next;
+};
+
+/**
+ * reads the canned reply file and returns a list of structs
+ * does an exit on error.
+ */
+struct entry* read_datafile(const char* name);
+
+/**
+ * Delete linked list of entries.
+ */
+void delete_entry(struct entry* list);
+
+/**
+ * Read one entry from the data file.
+ * @param in: file to read from. Filepos must be at the start of a new line.
+ * @param name: name of the file for prettier errors.
+ * @param lineno: line number in file, incremented as lines are read.
+ * for prettier errors.
+ * @param default_ttl: on first call set to default TTL for entries,
+ * later it stores the $TTL value last seen. Try 3600 first call.
+ * @param origin: domain name for origin appending. Can be &NULL on first call.
+ * later it stores the $ORIGIN value last seen. Often &NULL or the zone
+ * name on first call.
+ * @param prev_rr: previous rr name for correcter parsing. &NULL on first call.
+ * @return: The entry read (malloced) or NULL if no entry could be read.
+ */
+struct entry* read_entry(FILE* in, const char* name, int *lineno,
+ uint32_t* default_ttl, ldns_rdf** origin, ldns_rdf** prev_rr);
+
+/**
+ * finds entry in list, or returns NULL.
+ */
+struct entry* find_match(struct entry* entries, ldns_pkt* query_pkt,
+ enum transport_type transport);
+
+/**
+ * copy & adjust packet
+ */
+void adjust_packet(struct entry* match, ldns_pkt* answer_pkt,
+ ldns_pkt* query_pkt);
+
+/**
+ * Parses data buffer to a query, finds the correct answer
+ * and calls the given function for every packet to send.
+ * if verbose_out filename is given, packets are dumped there.
+ * @param inbuf: the packet that came in
+ * @param inlen: length of packet.
+ * @param entries: entries read in from datafile.
+ * @param count: is increased to count number of queries answered.
+ * @param transport: set to UDP or TCP to match some types of entries.
+ * @param sendfunc: called to send answer (buffer, size, userarg).
+ * @param userdata: userarg to give to sendfunc.
+ * @param verbose_out: if not NULL, verbose messages are printed there.
+ */
+void handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries,
+ int* count, enum transport_type transport,
+ void (*sendfunc)(uint8_t*, size_t, void*), void* userdata,
+ FILE* verbose_out);
+
+#endif /* LDNS_TESTPKTS_H */
diff --git a/examples/ldns-update.1 b/examples/ldns-update.1
new file mode 100644
index 000000000000..971397ddb092
--- /dev/null
+++ b/examples/ldns-update.1
@@ -0,0 +1,44 @@
+.TH ldns-update 1 "30 May 2005"
+.SH NAME
+ldns-update \- send a dynamic update packet
+.SH SYNOPSIS
+.B ldns-update
+[
+.IR zone
+]
+.IR ip
+[
+.IR tsig_name
+.IR tsig_als
+.IR tsig_hmac
+]
+
+.SH DESCRIPTION
+\fBldns-update\fR is used to send a dynamic update packet.
+
+.SH OPTIONS
+.TP
+\fBzone\fR
+Use this zone instead of trying to read it from the zonefile's SOA record.
+
+.TP
+\fBip\fR
+Send the update to this IP address
+
+.TP
+\fBtsig_name tsig_alg tsig_hmac\fR
+Use TSIG (rfc2845) to authenticate.
+
+.SH EXAMPLE
+ldns-update my.example.org 1.2.3.4
+
+.SH AUTHOR
+Written by Jakob Schlyter and HÃ¥kan Olsson, as an addition to the ldns library from NLnet Labs.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-update.c b/examples/ldns-update.c
new file mode 100644
index 000000000000..e3047dceb128
--- /dev/null
+++ b/examples/ldns-update.c
@@ -0,0 +1,310 @@
+/* $Id: ldns-update.c,v 1.1 2005/09/13 09:37:05 ho Exp $ */
+/*
+ * Example of the update functionality
+ *
+ * See the file LICENSE for the license
+ */
+
+
+#include "config.h"
+
+#include <strings.h>
+#include <ldns/ldns.h>
+
+/* dynamic update stuff */
+static ldns_resolver *
+ldns_update_resolver_new(const char *fqdn, const char *zone,
+ ldns_rr_class class, uint16_t port, ldns_tsig_credentials *tsig_cred, ldns_rdf **zone_rdf)
+{
+ ldns_resolver *r1, *r2;
+ ldns_pkt *query = NULL, *resp;
+ ldns_rr_list *nslist, *iplist;
+ ldns_rdf *soa_zone, *soa_mname, *ns_name;
+ size_t i;
+ ldns_status s;
+
+ if (class == 0) {
+ class = LDNS_RR_CLASS_IN;
+ }
+
+ if (port == 0) {
+ port = LDNS_PORT;
+ }
+
+ /* First, get data from /etc/resolv.conf */
+ s = ldns_resolver_new_frm_file(&r1, NULL);
+ if (s != LDNS_STATUS_OK) {
+ return NULL;
+ }
+
+ r2 = ldns_resolver_new();
+ if (!r2) {
+ goto bad;
+ }
+ ldns_resolver_set_port(r2, port);
+
+ /* TSIG key data available? Copy into the resolver. */
+ if (tsig_cred) {
+ ldns_resolver_set_tsig_algorithm(r2, ldns_tsig_algorithm(tsig_cred));
+ ldns_resolver_set_tsig_keyname(r2, ldns_tsig_keyname(tsig_cred));
+ ldns_resolver_set_tsig_keydata(r2, ldns_tsig_keydata(tsig_cred));
+ }
+
+ /* Now get SOA zone, mname, NS, and construct r2. [RFC2136 4.3] */
+
+ /* Explicit 'zone' or no? */
+ if (zone) {
+ soa_zone = ldns_dname_new_frm_str(zone);
+ if (ldns_update_soa_mname(soa_zone, r1, class, &soa_mname)
+ != LDNS_STATUS_OK) {
+ goto bad;
+ }
+ } else {
+ if (ldns_update_soa_zone_mname(fqdn, r1, class, &soa_zone,
+ &soa_mname) != LDNS_STATUS_OK) {
+ goto bad;
+ }
+ }
+
+ /* Pass zone_rdf on upwards. */
+ *zone_rdf = ldns_rdf_clone(soa_zone);
+
+ /* NS */
+ query = ldns_pkt_query_new(soa_zone, LDNS_RR_TYPE_NS, class, LDNS_RD);
+ if (!query) {
+ goto bad;
+ }
+ soa_zone = NULL;
+
+ ldns_pkt_set_random_id(query);
+
+ if (ldns_resolver_send_pkt(&resp, r1, query) != LDNS_STATUS_OK) {
+ dprintf("%s", "NS query failed!\n");
+ goto bad;
+ }
+ ldns_pkt_free(query);
+ if (!resp) {
+ goto bad;
+ }
+ /* Match SOA MNAME to NS list, adding it first */
+ nslist = ldns_pkt_answer(resp);
+ for (i = 0; i < ldns_rr_list_rr_count(nslist); i++) {
+ ns_name = ldns_rr_rdf(ldns_rr_list_rr(nslist, i), 0);
+ if (!ns_name)
+ continue;
+ if (ldns_rdf_compare(soa_mname, ns_name) == 0) {
+ /* Match */
+ iplist = ldns_get_rr_list_addr_by_name(r1, ns_name, class, 0);
+ (void) ldns_resolver_push_nameserver_rr_list(r2, iplist);
+ break;
+ }
+ }
+
+ /* Then all the other NSs. XXX Randomize? */
+ for (i = 0; i < ldns_rr_list_rr_count(nslist); i++) {
+ ns_name = ldns_rr_rdf(ldns_rr_list_rr(nslist, i), 0);
+ if (!ns_name)
+ continue;
+ if (ldns_rdf_compare(soa_mname, ns_name) != 0) {
+ /* No match, add it now. */
+ iplist = ldns_get_rr_list_addr_by_name(r1, ns_name, class, 0);
+ (void) ldns_resolver_push_nameserver_rr_list(r2, iplist);
+ }
+ }
+
+ ldns_resolver_set_random(r2, false);
+ ldns_pkt_free(resp);
+ ldns_resolver_deep_free(r1);
+ return r2;
+
+ bad:
+ if (r1)
+ ldns_resolver_deep_free(r1);
+ if (r2)
+ ldns_resolver_deep_free(r2);
+ if (query)
+ ldns_pkt_free(query);
+ if (resp)
+ ldns_pkt_free(resp);
+ return NULL;
+}
+
+
+static ldns_status
+ldns_update_send_simple_addr(const char *fqdn, const char *zone,
+ const char *ipaddr, uint16_t p, uint32_t ttl, ldns_tsig_credentials *tsig_cred)
+{
+ ldns_resolver *res;
+ ldns_pkt *u_pkt = NULL, *r_pkt;
+ ldns_rr_list *up_rrlist;
+ ldns_rr *up_rr;
+ ldns_rdf *zone_rdf;
+ char *rrstr;
+ uint32_t rrstrlen, status = LDNS_STATUS_OK;
+
+ if (!fqdn || strlen(fqdn) == 0)
+ return LDNS_STATUS_ERR;
+
+ /* Create resolver */
+ res = ldns_update_resolver_new(fqdn, zone, 0, p, tsig_cred, &zone_rdf);
+ if (!res || !zone_rdf) {
+ goto cleanup;
+ }
+
+ /* Set up the update section. */
+ up_rrlist = ldns_rr_list_new();
+ if (!up_rrlist) {
+ goto cleanup;
+ }
+ /* Create input for ldns_rr_new_frm_str() */
+ if (ipaddr) {
+ /* We're adding A or AAAA */
+ rrstrlen = strlen(fqdn) + sizeof (" IN AAAA ") + strlen(ipaddr) + 1;
+ rrstr = (char *)malloc(rrstrlen);
+ if (!rrstr) {
+ ldns_rr_list_deep_free(up_rrlist);
+ goto cleanup;
+ }
+ snprintf(rrstr, rrstrlen, "%s IN %s %s", fqdn,
+ strchr(ipaddr, ':') ? "AAAA" : "A", ipaddr);
+
+ if (ldns_rr_new_frm_str(&up_rr, rrstr, ttl, NULL, NULL) !=
+ LDNS_STATUS_OK) {
+ ldns_rr_list_deep_free(up_rrlist);
+ free(rrstr);
+ goto cleanup;
+ }
+ free(rrstr);
+ ldns_rr_list_push_rr(up_rrlist, up_rr);
+ } else {
+ /* We're removing A and/or AAAA from 'fqdn'. [RFC2136 2.5.2] */
+ up_rr = ldns_rr_new();
+ ldns_rr_set_owner(up_rr, ldns_dname_new_frm_str(fqdn));
+ ldns_rr_set_ttl(up_rr, 0);
+ ldns_rr_set_class(up_rr, LDNS_RR_CLASS_ANY);
+
+ ldns_rr_set_type(up_rr, LDNS_RR_TYPE_A);
+ ldns_rr_list_push_rr(up_rrlist, ldns_rr_clone(up_rr));
+
+ ldns_rr_set_type(up_rr, LDNS_RR_TYPE_AAAA);
+ ldns_rr_list_push_rr(up_rrlist, up_rr);
+ }
+
+ /* Create update packet. */
+ u_pkt = ldns_update_pkt_new(zone_rdf, LDNS_RR_CLASS_IN, NULL, up_rrlist, NULL);
+ zone_rdf = NULL;
+ if (!u_pkt) {
+ ldns_rr_list_deep_free(up_rrlist);
+ goto cleanup;
+ }
+ ldns_pkt_set_random_id(u_pkt);
+
+ /* Add TSIG */
+ if (tsig_cred)
+ if (ldns_update_pkt_tsig_add(u_pkt, res) != LDNS_STATUS_OK) {
+ goto cleanup;
+ }
+
+ if (ldns_resolver_send_pkt(&r_pkt, res, u_pkt) != LDNS_STATUS_OK) {
+ goto cleanup;
+ }
+ ldns_pkt_free(u_pkt);
+ if (!r_pkt) {
+ goto cleanup;
+ }
+ if (ldns_pkt_get_rcode(r_pkt) != LDNS_RCODE_NOERROR) {
+ ldns_lookup_table *t = ldns_lookup_by_id(ldns_rcodes,
+ (int)ldns_pkt_get_rcode(r_pkt));
+ if (t) {
+ dprintf(";; UPDATE response was %s\n", t->name);
+ } else {
+ dprintf(";; UPDATE response was (%d)\n", ldns_pkt_get_rcode(r_pkt));
+ }
+ status = LDNS_STATUS_ERR;
+ }
+ ldns_pkt_free(r_pkt);
+ ldns_resolver_deep_free(res);
+ return status;
+
+ cleanup:
+ if (res)
+ ldns_resolver_deep_free(res);
+ if (u_pkt)
+ ldns_pkt_free(u_pkt);
+ return LDNS_STATUS_ERR;
+}
+
+
+static void
+usage(FILE *fp, char *prog)
+{
+ fprintf(fp, "%s domain [zone] ip tsig_name tsig_alg tsig_hmac\n", prog);
+ fprintf(fp, " send a dynamic update packet to <ip>\n\n");
+ fprintf(fp, " Use 'none' instead of ip to remove any previous address\n");
+ fprintf(fp, " If 'zone' is not specified, try to figure it out from the zone's SOA\n");
+ fprintf(fp, " Example: %s my.example.org 1.2.3.4\n", prog);
+}
+
+
+int
+main(int argc, char **argv)
+{
+ char *fqdn, *ipaddr, *zone, *prog;
+ ldns_status ret;
+ ldns_tsig_credentials tsig_cr, *tsig_cred;
+ int c = 2;
+ uint32_t defttl = 300;
+ uint32_t port = 5353;
+
+ prog = strdup(argv[0]);
+
+ switch (argc) {
+ case 3:
+ case 4:
+ case 6:
+ case 7:
+ break;
+ default:
+ usage(stderr, prog);
+ exit(EXIT_FAILURE);
+ }
+
+ fqdn = argv[1];
+ c = 2;
+ if (argc == 4 || argc == 7) {
+ zone = argv[c++];
+ } else {
+ zone = NULL;
+ }
+
+ if (strcmp(argv[c], "none") == 0) {
+ ipaddr = NULL;
+ } else {
+ ipaddr = argv[c];
+ }
+ c++;
+ if (argc == 6 || argc == 7) {
+ tsig_cr.keyname = argv[c++];
+ if (strncasecmp(argv[c], "hmac-sha1", 9) == 0) {
+ tsig_cr.algorithm = (char*)"hmac-sha1.";
+ } else if (strncasecmp(argv[c], "hmac-md5", 8) == 0) {
+ tsig_cr.algorithm = (char*)"hmac-md5.sig-alg.reg.int.";
+ } else {
+ fprintf(stderr, "Unknown algorithm, try \"hmac-md5\" "
+ "or \"hmac-sha1\".\n");
+ exit(EXIT_FAILURE);
+ }
+ tsig_cr.keydata = argv[++c];
+ tsig_cred = &tsig_cr;
+ } else {
+ tsig_cred = NULL;
+ }
+
+ printf(";; trying UPDATE with FQDN \"%s\" and IP \"%s\"\n",
+ fqdn, ipaddr ? ipaddr : "<none>");
+ printf(";; tsig: \"%s\" \"%s\" \"%s\"\n", tsig_cr.keyname,
+ tsig_cr.algorithm, tsig_cr.keydata);
+
+ ret = ldns_update_send_simple_addr(fqdn, zone, ipaddr, port, defttl, tsig_cred);
+ exit(ret);
+}
diff --git a/examples/ldns-verify-zone.1 b/examples/ldns-verify-zone.1
new file mode 100644
index 000000000000..a4cb767d2799
--- /dev/null
+++ b/examples/ldns-verify-zone.1
@@ -0,0 +1,89 @@
+.TH ldns-verifyzone 1 "27 May 2008"
+.SH NAME
+ldns-verify-zone \- read a DNSSEC signed zone and verify it.
+.SH SYNOPSIS
+.B ldns-verify-zone
+.IR ZONEFILE
+
+.SH DESCRIPTION
+
+\fBldns-verify-zone\fR reads a DNS zone file and verifies it.
+
+RRSIG resource records are checked against the DNSKEY set at the zone apex.
+
+Each name is checked for an NSEC(3), if appropriate.
+
+.SH OPTIONS
+.TP
+\fB-h\fR
+Show usage and exit
+
+.TP
+\fB-a\fR
+Apex only, check only the zone apex
+
+.TP
+\fB-e\fR \fIperiod\fR
+Signatures may not expire within this period.
+Default no period is used.
+
+.TP
+\fB-i\fR \fIperiod\fR
+Signatures must have been valid at least this long.
+Default signatures should just be valid now.
+
+.TP
+\fB-k\fR \fIfile\fR
+A file that contains a trusted DNSKEY or DS rr.
+This option may be given more than once.
+
+.TP
+\fB-p\fR \fI[0-100]\fR
+Only check this percentage of the zone.
+Which names to check is determined randomly.
+Defaults to 100.
+
+.TP
+\fB-S\fR
+Chase signature(s) to a known key.
+The network may be accessed to validate the zone's DNSKEYs. (implies -k)
+
+.TP
+\fB-t\fR \fIYYYYMMDDhhmmss | [+|-]offset\fR
+Set the validation time either by an absolute time value or as an offset in seconds from the current time.
+
+.TP
+\fB-v\fR
+Show the version and exit
+
+.TP
+\fB-V\fR \fInumber\fR
+Set the verbosity level (default 3):
+
+ 0: Be silent
+ 1: Print result, and any errors
+ 2: Same as 1 for now
+ 3: Print result, any errors, and the names that are
+ being checked
+ 4: Same as 3 for now
+ 5: Print the zone after it has been read, the result,
+ any errors, and the names that are being checked
+
+.LP
+\fIperiod\fRs are given in ISO 8601 duration format:
+.RS
+P[n]Y[n]M[n]DT[n]H[n]M[n]S
+.RE
+.LP
+If no file is given standard input is read.
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2008 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-verify-zone.c b/examples/ldns-verify-zone.c
new file mode 100644
index 000000000000..1dd9aaea8b64
--- /dev/null
+++ b/examples/ldns-verify-zone.c
@@ -0,0 +1,946 @@
+/*
+ * read a zone file from disk and prints it, one RR per line
+ *
+ * (c) NLnetLabs 2008
+ *
+ * See the file LICENSE for the license
+ *
+ * Missing from the checks: empty non-terminals
+ */
+
+#include "config.h"
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <ldns/ldns.h>
+
+#include <errno.h>
+
+#ifdef HAVE_SSL
+#include <openssl/err.h>
+
+static int verbosity = 3;
+static time_t check_time = 0;
+static int32_t inception_offset = 0;
+static int32_t expiration_offset = 0;
+static bool do_sigchase = false;
+static bool no_nomatch_msg = false;
+
+static FILE* myout;
+static FILE* myerr;
+
+static void
+update_error(ldns_status* result, ldns_status status)
+{
+ if (status != LDNS_STATUS_OK) {
+ if (*result == LDNS_STATUS_OK || *result == LDNS_STATUS_ERR ||
+ ( *result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY
+ && status != LDNS_STATUS_ERR
+ )) {
+ *result = status;
+ }
+ }
+}
+
+static void
+print_type(FILE* stream, ldns_rr_type type)
+{
+ const ldns_rr_descriptor *descriptor = ldns_rr_descript(type);
+
+ if (descriptor && descriptor->_name) {
+ fprintf(stream, "%s", descriptor->_name);
+ } else {
+ fprintf(stream, "TYPE%u", type);
+ }
+}
+
+ldns_status
+read_key_file(const char *filename, ldns_rr_list *keys)
+{
+ ldns_status status = LDNS_STATUS_ERR;
+ ldns_rr *rr;
+ FILE *fp;
+ uint32_t my_ttl = 0;
+ ldns_rdf *my_origin = NULL;
+ ldns_rdf *my_prev = NULL;
+ int line_nr;
+
+ if (!(fp = fopen(filename, "r"))) {
+ if (verbosity > 0) {
+ fprintf(myerr, "Error opening %s: %s\n", filename,
+ strerror(errno));
+ }
+ return LDNS_STATUS_FILE_ERR;
+ }
+ while (!feof(fp)) {
+ status = ldns_rr_new_frm_fp_l(&rr, fp, &my_ttl, &my_origin,
+ &my_prev, &line_nr);
+
+ if (status == LDNS_STATUS_OK) {
+
+ if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS
+ || ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY)
+
+ ldns_rr_list_push_rr(keys, rr);
+
+ } else if ( status == LDNS_STATUS_SYNTAX_EMPTY
+ || status == LDNS_STATUS_SYNTAX_TTL
+ || status == LDNS_STATUS_SYNTAX_ORIGIN
+ || status == LDNS_STATUS_SYNTAX_INCLUDE)
+
+ status = LDNS_STATUS_OK;
+ else
+ break;
+ }
+ return status;
+}
+
+
+
+static void
+print_rr_error(FILE* stream, ldns_rr* rr, const char* msg)
+{
+ if (verbosity > 0) {
+ fprintf(stream, "Error: %s for ", msg);
+ ldns_rdf_print(stream, ldns_rr_owner(rr));
+ fprintf(stream, "\t");
+ print_type(stream, ldns_rr_get_type(rr));
+ fprintf(stream, "\n");
+ }
+}
+
+static void
+print_rr_status_error(FILE* stream, ldns_rr* rr, ldns_status status)
+{
+ if (status != LDNS_STATUS_OK) {
+ print_rr_error(stream, rr, ldns_get_errorstr_by_id(status));
+ if (verbosity > 0 && status == LDNS_STATUS_SSL_ERR) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stream);
+ }
+ }
+}
+
+static void
+print_rrs_status_error(FILE* stream, ldns_rr_list* rrs, ldns_status status,
+ ldns_dnssec_rrs* cur_sig)
+{
+ if (status != LDNS_STATUS_OK) {
+ if (ldns_rr_list_rr_count(rrs) > 0) {
+ print_rr_status_error(stream, ldns_rr_list_rr(rrs, 0),
+ status);
+ } else if (verbosity > 0) {
+ fprintf(stream, "Error: %s for <unknown>\n",
+ ldns_get_errorstr_by_id(status));
+ }
+ if (verbosity >= 4) {
+ fprintf(stream, "RRSet:\n");
+ ldns_rr_list_print(stream, rrs);
+ fprintf(stream, "Signature:\n");
+ ldns_rr_print(stream, cur_sig->rr);
+ fprintf(stream, "\n");
+ }
+ }
+}
+
+static ldns_status
+rrsig_check_time_margins(ldns_rr* rrsig
+#if 0 /* Passing those as arguments becomes sensible when
+ * rrsig_check_time_margins will be added to the library.
+ */
+ ,time_t check_time, int32_t inception_offset, int32_t expiration_offset
+#endif
+ )
+{
+ int32_t inception, expiration;
+
+ inception = ldns_rdf2native_int32(ldns_rr_rrsig_inception (rrsig));
+ expiration = ldns_rdf2native_int32(ldns_rr_rrsig_expiration(rrsig));
+
+ if (((int32_t) (check_time - inception_offset)) - inception < 0) {
+ return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN;
+ }
+ if (expiration - ((int32_t) (check_time + expiration_offset)) < 0) {
+ return LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN;
+ }
+ return LDNS_STATUS_OK;
+}
+
+static ldns_status
+verify_rrs(ldns_rr_list* rrset_rrs, ldns_dnssec_rrs* cur_sig,
+ ldns_rr_list* keys)
+{
+ ldns_rr_list* good_keys;
+ ldns_status status, result = LDNS_STATUS_OK;
+
+ while (cur_sig) {
+ good_keys = ldns_rr_list_new();
+ status = ldns_verify_rrsig_keylist_time(rrset_rrs, cur_sig->rr,
+ keys, check_time, good_keys);
+ status = status ? status
+ : rrsig_check_time_margins(cur_sig->rr);
+ if (status != LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY ||
+ !no_nomatch_msg) {
+
+ print_rrs_status_error(myerr, rrset_rrs, status,
+ cur_sig);
+ }
+ update_error(&result, status);
+ ldns_rr_list_free(good_keys);
+ cur_sig = cur_sig->next;
+ }
+ return result;
+}
+
+static ldns_status
+verify_dnssec_rrset(ldns_rdf *zone_name, ldns_rdf *name,
+ ldns_dnssec_rrsets *rrset, ldns_rr_list *keys)
+{
+ ldns_rr_list *rrset_rrs;
+ ldns_dnssec_rrs *cur_rr, *cur_sig;
+ ldns_status status;
+
+ if (!rrset->rrs) return LDNS_STATUS_OK;
+
+ rrset_rrs = ldns_rr_list_new();
+ cur_rr = rrset->rrs;
+ while(cur_rr && cur_rr->rr) {
+ ldns_rr_list_push_rr(rrset_rrs, cur_rr->rr);
+ cur_rr = cur_rr->next;
+ }
+ cur_sig = rrset->signatures;
+ if (cur_sig) {
+ status = verify_rrs(rrset_rrs, cur_sig, keys);
+
+ } else /* delegations may be unsigned (on opt out...) */
+ if (rrset->type != LDNS_RR_TYPE_NS ||
+ ldns_dname_compare(name, zone_name) == 0) {
+
+ print_rr_error(myerr, rrset->rrs->rr, "no signatures");
+ status = LDNS_STATUS_CRYPTO_NO_RRSIG;
+ } else {
+ status = LDNS_STATUS_OK;
+ }
+ ldns_rr_list_free(rrset_rrs);
+
+ return status;
+}
+
+static ldns_status
+verify_single_rr(ldns_rr *rr, ldns_dnssec_rrs *signature_rrs,
+ ldns_rr_list *keys)
+{
+ ldns_rr_list *rrset_rrs;
+ ldns_status status;
+
+ rrset_rrs = ldns_rr_list_new();
+ ldns_rr_list_push_rr(rrset_rrs, rr);
+
+ status = verify_rrs(rrset_rrs, signature_rrs, keys);
+
+ ldns_rr_list_free(rrset_rrs);
+
+ return status;
+}
+
+static ldns_status
+verify_next_hashed_name(ldns_dnssec_zone* zone, ldns_dnssec_name *name)
+{
+ ldns_rbnode_t *next_node;
+ ldns_dnssec_name *next_name;
+ ldns_dnssec_name *cur_next_name = NULL;
+ ldns_dnssec_name *cur_first_name = NULL;
+ int cmp;
+ char *next_owner_str;
+ ldns_rdf *next_owner_dname;
+
+ if (!name->hashed_name) {
+ name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(
+ name->nsec, name->name);
+ }
+ next_node = ldns_rbtree_first(zone->names);
+ while (next_node != LDNS_RBTREE_NULL) {
+ next_name = (ldns_dnssec_name *)next_node->data;
+ /* skip over names that have no NSEC3 records (whether it
+ * actually should or should not should have been checked
+ * already */
+ if (!next_name->nsec) {
+ next_node = ldns_rbtree_next(next_node);
+ continue;
+ }
+ if (!next_name->hashed_name) {
+ next_name->hashed_name =
+ ldns_nsec3_hash_name_frm_nsec3(name->nsec,
+ next_name->name);
+ }
+ /* we keep track of what 'so far' is the next hashed name;
+ * it must of course be 'larger' than the current name
+ * if we find one that is larger, but smaller than what we
+ * previously thought was the next one, that one is the next
+ */
+ cmp = ldns_dname_compare(name->hashed_name,
+ next_name->hashed_name);
+ if (cmp < 0) {
+ if (!cur_next_name) {
+ cur_next_name = next_name;
+ } else {
+ cmp = ldns_dname_compare(
+ next_name->hashed_name,
+ cur_next_name->hashed_name);
+ if (cmp < 0) {
+ cur_next_name = next_name;
+ }
+ }
+ }
+ /* in case the hashed name of the nsec we are checking is the
+ * last one, we need the first hashed name of the zone */
+ if (!cur_first_name) {
+ cur_first_name = next_name;
+ } else {
+ cmp = ldns_dname_compare(next_name->hashed_name,
+ cur_first_name->hashed_name);
+ if (cmp < 0) {
+ cur_first_name = next_name;
+ }
+ }
+ next_node = ldns_rbtree_next(next_node);
+ }
+ if (!cur_next_name) {
+ cur_next_name = cur_first_name;
+ }
+
+ next_owner_str = ldns_rdf2str(ldns_nsec3_next_owner(name->nsec));
+ next_owner_dname = ldns_dname_new_frm_str(next_owner_str);
+ cmp = ldns_dname_compare(next_owner_dname, cur_next_name->hashed_name);
+ ldns_rdf_deep_free(next_owner_dname);
+ LDNS_FREE(next_owner_str);
+ if (cmp != 0) {
+ if (verbosity > 0) {
+ fprintf(myerr, "Error: The NSEC3 record for ");
+ ldns_rdf_print(stdout, name->name);
+ fprintf(myerr, " points to the wrong next hashed owner"
+ " name\n\tshould point to ");
+ ldns_rdf_print(myerr, cur_next_name->name);
+ fprintf(myerr, ", whose hashed name is ");
+ ldns_rdf_print(myerr, cur_next_name->hashed_name);
+ fprintf(myerr, "\n");
+ }
+ return LDNS_STATUS_ERR;
+ } else {
+ return LDNS_STATUS_OK;
+ }
+}
+
+static bool zone_is_nsec3_optout(ldns_dnssec_zone* zone)
+{
+ static int remember = -1;
+
+ if (remember == -1) {
+ remember = ldns_dnssec_zone_is_nsec3_optout(zone) ? 1 : 0;
+ }
+ return remember == 1;
+}
+
+static ldns_status
+verify_nsec(ldns_dnssec_zone* zone, ldns_rbnode_t *cur_node,
+ ldns_rr_list *keys)
+{
+ ldns_rbnode_t *next_node;
+ ldns_dnssec_name *name, *next_name;
+ ldns_status status, result;
+ result = LDNS_STATUS_OK;
+
+ name = (ldns_dnssec_name *) cur_node->data;
+ if (name->nsec) {
+ if (name->nsec_signatures) {
+ status = verify_single_rr(name->nsec,
+ name->nsec_signatures, keys);
+
+ update_error(&result, status);
+ } else {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "Error: the NSEC(3) record of ");
+ ldns_rdf_print(myerr, name->name);
+ fprintf(myerr, " has no signatures\n");
+ }
+ update_error(&result, LDNS_STATUS_ERR);
+ }
+ /* check whether the NSEC record points to the right name */
+ switch (ldns_rr_get_type(name->nsec)) {
+ case LDNS_RR_TYPE_NSEC:
+ /* simply try next name */
+ next_node = ldns_rbtree_next(cur_node);
+ if (next_node == LDNS_RBTREE_NULL) {
+ next_node = ldns_rbtree_first(
+ zone->names);
+ }
+ next_node = ldns_dnssec_name_node_next_nonglue(
+ next_node);
+ if (!next_node) {
+ next_node =
+ ldns_dnssec_name_node_next_nonglue(
+ ldns_rbtree_first(zone->names));
+ }
+ next_name = (ldns_dnssec_name*)next_node->data;
+ if (ldns_dname_compare(next_name->name,
+ ldns_rr_rdf(name->nsec,
+ 0)) != 0) {
+ if (verbosity > 0) {
+ fprintf(myerr, "Error: the "
+ "NSEC record for ");
+ ldns_rdf_print(myerr,
+ name->name);
+ fprintf(myerr, " points to "
+ "the wrong "
+ "next owner name\n");
+ }
+ if (verbosity >= 4) {
+ fprintf(myerr, "\t: ");
+ ldns_rdf_print(myerr,
+ ldns_rr_rdf(
+ name->nsec,
+ 0));
+ fprintf(myerr, " i.s.o. ");
+ ldns_rdf_print(myerr,
+ next_name->name);
+ fprintf(myerr, ".\n");
+ }
+ update_error(&result,
+ LDNS_STATUS_ERR);
+ }
+ break;
+ case LDNS_RR_TYPE_NSEC3:
+ /* find the hashed next name in the tree */
+ /* this is expensive, do we need to add
+ * support for this in the structs?
+ * (ie. pointer to next hashed name?)
+ */
+ status = verify_next_hashed_name(zone, name);
+ update_error(&result, status);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (zone_is_nsec3_optout(zone) &&
+ (ldns_dnssec_name_is_glue(name) ||
+ ( ldns_dnssec_rrsets_contains_type(name->rrsets,
+ LDNS_RR_TYPE_NS)
+ && !ldns_dnssec_rrsets_contains_type(name->rrsets,
+ LDNS_RR_TYPE_DS)))) {
+ /* ok, no problem, but we need to remember to check
+ * whether the chain does not actually point to this
+ * name later */
+ } else {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "Error: there is no NSEC(3) for ");
+ ldns_rdf_print(myerr, name->name);
+ fprintf(myerr, "\n");
+ }
+ update_error(&result, LDNS_STATUS_ERR);
+ }
+ }
+ return result;
+}
+
+static ldns_status
+verify_dnssec_name(ldns_rdf *zone_name, ldns_dnssec_zone* zone,
+ ldns_rbnode_t *cur_node, ldns_rr_list *keys)
+{
+ ldns_status result = LDNS_STATUS_OK;
+ ldns_status status;
+ ldns_dnssec_rrsets *cur_rrset;
+ ldns_dnssec_name *name;
+ int on_delegation_point;
+ /* for NSEC chain checks */
+
+ name = (ldns_dnssec_name *) cur_node->data;
+ if (verbosity >= 3) {
+ fprintf(myout, "Checking: ");
+ ldns_rdf_print(myout, name->name);
+ fprintf(myout, "\n");
+ }
+
+ if (ldns_dnssec_name_is_glue(name)) {
+ /* glue */
+ cur_rrset = name->rrsets;
+ while (cur_rrset) {
+ if (cur_rrset->signatures) {
+ if (verbosity > 0) {
+ fprintf(myerr, "Error: ");
+ ldns_rdf_print(myerr, name->name);
+ fprintf(myerr, "\t");
+ print_type(myerr, cur_rrset->type);
+ fprintf(myerr, " has signature(s),"
+ " but is glue\n");
+ }
+ result = LDNS_STATUS_ERR;
+ }
+ cur_rrset = cur_rrset->next;
+ }
+ if (name->nsec) {
+ if (verbosity > 0) {
+ fprintf(myerr, "Error: ");
+ ldns_rdf_print(myerr, name->name);
+ fprintf(myerr, " has an NSEC(3),"
+ " but is glue\n");
+ }
+ result = LDNS_STATUS_ERR;
+ }
+ } else {
+ /* not glue, do real verify */
+
+ on_delegation_point =
+ ldns_dnssec_rrsets_contains_type(name->rrsets,
+ LDNS_RR_TYPE_NS)
+ && !ldns_dnssec_rrsets_contains_type(name->rrsets,
+ LDNS_RR_TYPE_SOA);
+ cur_rrset = name->rrsets;
+ while(cur_rrset) {
+
+ /* Do not check occluded rrsets
+ * on the delegation point
+ */
+ if ((on_delegation_point &&
+ (cur_rrset->type == LDNS_RR_TYPE_NS ||
+ cur_rrset->type == LDNS_RR_TYPE_DS)) ||
+ (!on_delegation_point &&
+ cur_rrset->type != LDNS_RR_TYPE_RRSIG &&
+ cur_rrset->type != LDNS_RR_TYPE_NSEC)) {
+
+ status = verify_dnssec_rrset(zone_name,
+ name->name, cur_rrset, keys);
+ update_error(&result, status);
+ }
+ cur_rrset = cur_rrset->next;
+ }
+ status = verify_nsec(zone, cur_node, keys);
+ update_error(&result, status);
+ }
+ return result;
+}
+
+static void
+add_keys_with_matching_ds(ldns_dnssec_rrsets* from_keys, ldns_rr_list *dss,
+ ldns_rr_list *to_keys)
+{
+ size_t i;
+ ldns_rr* ds_rr;
+ ldns_dnssec_rrs *cur_key;
+
+ for (i = 0; i < ldns_rr_list_rr_count(dss); i++) {
+
+ if (ldns_rr_get_type(ds_rr = ldns_rr_list_rr(dss, i))
+ == LDNS_RR_TYPE_DS) {
+
+ for (cur_key = from_keys->rrs; cur_key;
+ cur_key = cur_key->next ) {
+
+ if (ldns_rr_compare_ds(cur_key->rr, ds_rr)) {
+ ldns_rr_list_push_rr(to_keys,
+ cur_key->rr);
+ break;
+ }
+ }
+ }
+ }
+}
+
+static ldns_status
+sigchase(ldns_resolver* res, ldns_rdf *zone_name, ldns_dnssec_rrsets *zonekeys,
+ ldns_rr_list *keys)
+{
+ ldns_dnssec_rrs* cur_key;
+ ldns_status status;
+ bool free_resolver = false;
+ ldns_rdf* parent_name;
+ ldns_rr_list* parent_keys;
+ ldns_rr_list* ds_keys;
+
+ add_keys_with_matching_ds(zonekeys, keys, keys);
+
+ /* First try to authenticate the keys offline.
+ * When do_sigchase is given validation may continue lookup up
+ * keys online. Reporting the failure of the offline validation
+ * should then be suppressed.
+ */
+ no_nomatch_msg = do_sigchase;
+ status = verify_dnssec_rrset(zone_name, zone_name, zonekeys, keys);
+ no_nomatch_msg = false;
+
+ /* Continue online on validation failure when the -S option was given.
+ */
+ if (do_sigchase &&
+ status == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY &&
+ ldns_dname_label_count(zone_name) > 0 ) {
+
+ if (!res) {
+ if ((status = ldns_resolver_new_frm_file(&res, NULL))){
+ ldns_resolver_free(res);
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "Could not create resolver: "
+ "%s\n",
+ ldns_get_errorstr_by_id(status)
+ );
+ }
+ return status;
+ }
+ free_resolver = true;
+ ldns_resolver_set_dnssec(res,1);
+ ldns_resolver_set_dnssec_cd(res, 1);
+ }
+ if ((parent_name = ldns_dname_left_chop(zone_name))) {
+ /*
+ * Use the (authenticated) keys of the parent zone ...
+ */
+ parent_keys = ldns_fetch_valid_domain_keys(res,
+ parent_name, keys, &status);
+ ldns_rdf_deep_free(parent_name);
+
+ /*
+ * ... to validate the DS for the zone ...
+ */
+ ds_keys = ldns_validate_domain_ds(res, zone_name,
+ parent_keys);
+ ldns_rr_list_free(parent_keys);
+
+ /*
+ * ... to use it to add the KSK to the trusted keys ...
+ */
+ add_keys_with_matching_ds(zonekeys, ds_keys, keys);
+ ldns_rr_list_free(ds_keys);
+
+ /*
+ * ... to validate all zonekeys ...
+ */
+ status = verify_dnssec_rrset(zone_name, zone_name,
+ zonekeys, keys);
+ } else {
+ status = LDNS_STATUS_MEM_ERR;
+ }
+ if (free_resolver) {
+ ldns_resolver_deep_free(res);
+ }
+
+ }
+ /*
+ * ... so they can all be added to our list of trusted keys.
+ */
+ if (status == LDNS_STATUS_OK)
+ for (cur_key = zonekeys->rrs; cur_key; cur_key = cur_key->next)
+ ldns_rr_list_push_rr(keys, cur_key->rr);
+ return status;
+}
+
+static ldns_status
+verify_dnssec_zone(ldns_dnssec_zone *dnssec_zone, ldns_rdf *zone_name,
+ ldns_rr_list *keys, bool apexonly, int percentage)
+{
+ ldns_rbnode_t *cur_node;
+ ldns_dnssec_rrsets *cur_key_rrset;
+ ldns_dnssec_rrs *cur_key;
+ ldns_status status;
+ ldns_status result = LDNS_STATUS_OK;
+
+ cur_key_rrset = ldns_dnssec_zone_find_rrset(dnssec_zone, zone_name,
+ LDNS_RR_TYPE_DNSKEY);
+ if (!cur_key_rrset || !cur_key_rrset->rrs) {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "Error: No DNSKEY records at zone apex\n");
+ }
+ result = LDNS_STATUS_ERR;
+ } else {
+ /* are keys given with -k to use for validation? */
+ if (ldns_rr_list_rr_count(keys) > 0) {
+ if ((result = sigchase(NULL, zone_name, cur_key_rrset,
+ keys)))
+ goto error;
+ } else
+ for (cur_key = cur_key_rrset->rrs; cur_key;
+ cur_key = cur_key->next)
+ ldns_rr_list_push_rr(keys, cur_key->rr);
+
+ cur_node = ldns_rbtree_first(dnssec_zone->names);
+ if (cur_node == LDNS_RBTREE_NULL) {
+ if (verbosity > 0) {
+ fprintf(myerr, "Error: Empty zone?\n");
+ }
+ result = LDNS_STATUS_ERR;
+ }
+ if (apexonly) {
+ /*
+ * In this case, only the first node in the treewalk
+ * below should be checked.
+ */
+ assert( cur_node->data == dnssec_zone->soa );
+ /*
+ * Allthough the percentage option doesn't make sense
+ * here, we set it to 100 to force the first node to
+ * be checked.
+ */
+ percentage = 100;
+ }
+ while (cur_node != LDNS_RBTREE_NULL) {
+ /* should we check this one? saves calls to random. */
+ if (percentage == 100
+ || ((random() % 100) >= 100 - percentage)) {
+ status = verify_dnssec_name(zone_name,
+ dnssec_zone, cur_node, keys);
+ update_error(&result, status);
+ if (apexonly)
+ break;
+ }
+ cur_node = ldns_rbtree_next(cur_node);
+ }
+ }
+error:
+ ldns_rr_list_free(keys);
+ return result;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *filename;
+ FILE *fp;
+ int line_nr = 0;
+ int c;
+ ldns_status s;
+ ldns_dnssec_zone *dnssec_zone = NULL;
+ ldns_status result = LDNS_STATUS_ERR;
+ bool apexonly = false;
+ int percentage = 100;
+ struct tm tm;
+ ldns_duration_type *duration;
+ ldns_rr_list *keys = ldns_rr_list_new();
+ size_t nkeys = 0;
+
+ check_time = ldns_time(NULL);
+ myout = stdout;
+ myerr = stderr;
+
+ while ((c = getopt(argc, argv, "ae:hi:k:vV:p:St:")) != -1) {
+ switch(c) {
+ case 'a':
+ apexonly = true;
+ break;
+ case 'h':
+ printf("Usage: %s [OPTIONS] <zonefile>\n", argv[0]);
+ printf("\tReads the zonefile and checks for DNSSEC "
+ "errors.\n");
+ printf("\nIt checks whether NSEC(3)s are present, "
+ "and verifies all signatures\n");
+ printf("It also checks the NSEC(3) chain, but it "
+ "will error on opted-out delegations\n");
+ printf("\nOPTIONS:\n");
+ printf("\t-h\t\tshow this text\n");
+ printf("\t-a\t\tapex only, "
+ "check only the zone apex\n");
+ printf("\t-e <period>\tsignatures may not expire "
+ "within this period.\n\t\t\t"
+ "(default no period is used)\n");
+ printf("\t-i <period>\tsignatures must have been "
+ "valid at least this long.\n\t\t\t"
+ "(default signatures should just be valid "
+ "now)\n");
+ printf("\t-k <file>\tspecify a file that contains a "
+ "trusted DNSKEY or DS rr.\n\t\t\t"
+ "This option may be given more than once.\n");
+ printf("\t-p [0-100]\tonly checks this percentage of "
+ "the zone.\n\t\t\tDefaults to 100\n");
+ printf("\t-S\t\tchase signature(s) to a known key. "
+ "The network may be\n\t\t\taccessed to "
+ "validate the zone's DNSKEYs. (implies -k)\n");
+ printf("\t-t YYYYMMDDhhmmss | [+|-]offset\n\t\t\t"
+ "set the validation time either by an "
+ "absolute time\n\t\t\tvalue or as an "
+ "offset in seconds from <now>.\n\t\t\t"
+ "For data that came from the network (while "
+ "chasing),\n\t\t\tsystem time will be used "
+ "for validating it regardless.\n");
+ printf("\t-v\t\tshows the version and exits\n");
+ printf("\t-V [0-5]\tset verbosity level (default 3)\n"
+ );
+ printf("\n<period>s are given "
+ "in ISO 8601 duration format: "
+ "P[n]Y[n]M[n]DT[n]H[n]M[n]S\n");
+ printf("\nif no file is given "
+ "standard input is read\n");
+ exit(EXIT_SUCCESS);
+ break;
+ case 'e':
+ case 'i':
+ duration = ldns_duration_create_from_string(optarg);
+ if (!duration) {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "<period> should be in ISO "
+ "8601 duration format: "
+ "P[n]Y[n]M[n]DT[n]H[n]M[n]S\n"
+ );
+ }
+ exit(EXIT_FAILURE);
+ }
+ if (c == 'e')
+ expiration_offset =
+ ldns_duration2time(duration);
+ else
+ inception_offset =
+ ldns_duration2time(duration);
+ break;
+ case 'k':
+ s = read_key_file(optarg, keys);
+ if (s != LDNS_STATUS_OK) {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "Could not parse key file "
+ "%s: %s\n",optarg,
+ ldns_get_errorstr_by_id(s));
+ }
+ exit(EXIT_FAILURE);
+ }
+ if (ldns_rr_list_rr_count(keys) == nkeys) {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "No keys found in file %s\n",
+ optarg);
+ }
+ exit(EXIT_FAILURE);
+ }
+ nkeys = ldns_rr_list_rr_count(keys);
+ break;
+ case 'p':
+ percentage = atoi(optarg);
+ if (percentage < 0 || percentage > 100) {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "percentage needs to fall "
+ "between 0..100\n");
+ }
+ exit(EXIT_FAILURE);
+ }
+ srandom(time(NULL) ^ getpid());
+ break;
+ case 'S':
+ do_sigchase = true;
+ /* may chase */
+ break;
+ case 't':
+ if (strlen(optarg) == 14 &&
+ sscanf(optarg, "%4d%2d%2d%2d%2d%2d",
+ &tm.tm_year, &tm.tm_mon,
+ &tm.tm_mday, &tm.tm_hour,
+ &tm.tm_min , &tm.tm_sec ) == 6) {
+
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ check_time = mktime_from_utc(&tm);
+ }
+ else {
+ check_time += atoi(optarg);
+ }
+ break;
+ case 'v':
+ printf("verify-zone version %s (ldns version %s)\n",
+ LDNS_VERSION, ldns_version());
+ exit(EXIT_SUCCESS);
+ break;
+ case 'V':
+ verbosity = atoi(optarg);
+ break;
+ }
+ }
+ if (do_sigchase && nkeys == 0) {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "Unable to chase signature without keys.\n");
+ }
+ exit(EXIT_FAILURE);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ fp = stdin;
+ } else {
+ filename = argv[0];
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ if (verbosity > 0) {
+ fprintf(myerr, "Unable to open %s: %s\n",
+ filename, strerror(errno));
+ }
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ s = ldns_dnssec_zone_new_frm_fp_l(&dnssec_zone, fp, NULL, 0,
+ LDNS_RR_CLASS_IN, &line_nr);
+ if (s == LDNS_STATUS_OK) {
+ if (!dnssec_zone->soa) {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "; Error: no SOA in the zone\n");
+ }
+ exit(EXIT_FAILURE);
+ }
+
+ result = ldns_dnssec_zone_mark_glue(dnssec_zone);
+ if (result != LDNS_STATUS_OK) {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "There were errors identifying the "
+ "glue in the zone\n");
+ }
+ }
+
+ if (verbosity >= 5) {
+ ldns_dnssec_zone_print(myout, dnssec_zone);
+ }
+
+ result = verify_dnssec_zone(dnssec_zone,
+ dnssec_zone->soa->name, keys, apexonly,
+ percentage);
+
+ if (result == LDNS_STATUS_OK) {
+ if (verbosity >= 3) {
+ fprintf(myout,
+ "Zone is verified and complete\n");
+ }
+ } else {
+ if (verbosity > 0) {
+ fprintf(myerr,
+ "There were errors in the zone\n");
+ }
+ }
+
+ ldns_dnssec_zone_deep_free(dnssec_zone);
+ } else {
+ if (verbosity > 0) {
+ fprintf(myerr, "%s at %d\n",
+ ldns_get_errorstr_by_id(s), line_nr);
+ }
+ exit(EXIT_FAILURE);
+ }
+ fclose(fp);
+
+ exit(result);
+}
+
+#else
+
+int
+main(int argc, char **argv)
+{
+ fprintf(stderr, "ldns-verify-zone needs OpenSSL support, "
+ "which has not been compiled in\n");
+ return 1;
+}
+#endif /* HAVE_SSL */
+
diff --git a/examples/ldns-version.1 b/examples/ldns-version.1
new file mode 100644
index 000000000000..bf409a305a7f
--- /dev/null
+++ b/examples/ldns-version.1
@@ -0,0 +1,22 @@
+.TH ldns-version 1 "27 Apr 2005"
+.SH NAME
+ldns-version \- print out the version of the ldns-library and tools on this system
+.SH SYNOPSIS
+.B ldns-version
+
+.SH DESCRIPTION
+\fBldns-version\fR is used to print out version information of the ldns library and tools
+
+.SH OPTIONS
+\fBldns-version\fR has no options.
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-version.c b/examples/ldns-version.c
new file mode 100644
index 000000000000..97a5b2dbec96
--- /dev/null
+++ b/examples/ldns-version.c
@@ -0,0 +1,16 @@
+/*
+ * ldns-version shows ldns's version
+ *
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <ldns/ldns.h>
+
+int
+main(void)
+{
+ printf("%s\n", ldns_version());
+ return 0;
+}
diff --git a/examples/ldns-walk.1 b/examples/ldns-walk.1
new file mode 100644
index 000000000000..c8ace40ec04b
--- /dev/null
+++ b/examples/ldns-walk.1
@@ -0,0 +1,49 @@
+.TH ldns-walk 1 "21 Nov 2005"
+.SH NAME
+ldns-walk \- Retrieve the contents of a DNSSEC signed zone
+.SH SYNOPSIS
+.B ldns-walk
+[
+.IR OPTION
+]
+.IR ZONE
+
+.SH DESCRIPTION
+
+\fBldns-walk\fR is used to retrieve the contents of a DNSSEC signed zone.
+It does this through NSEC-walking (following the chain of NSEC records)
+and 'guessing' the next non-existent owner name for each NSEC.
+
+Note that it might get stuck on some wildcard records when used through a
+caching forwarder. This problem can be circumvented by querying the
+authoritative nameserver directly (with the @ argument).
+
+Of course the nameserver that is used must be DNSSEC-aware.
+
+.SH OPTIONS
+.TP
+\fB-f\fR
+Do a 'full' zone walk; by default, ldns-walk will only show the names, and types present at those names. If this option is given, all resource records will be printed.
+
+.TP
+\fB-s\fR \fIname\fR
+Start the walk with this owner name. Useful when continuing the walk for a
+large zone.
+
+.TP
+\fB@\fR \fInameserver\fR
+Send the queries to this nameserver.
+
+.SH BUGS
+The full zone walk function is not complete yet, it does not correctly print delegation records
+
+.SH AUTHOR
+Written by Jelte Jansen as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-walk.c b/examples/ldns-walk.c
new file mode 100644
index 000000000000..da0f74db350c
--- /dev/null
+++ b/examples/ldns-walk.c
@@ -0,0 +1,671 @@
+/*
+ * ldns-walk uses educated guesses and NSEC data to retrieve the
+ * contents of a dnssec signed zone
+ *
+ * (c) NLnet Labs, 2005 - 2008
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+
+#include <ldns/ldns.h>
+
+int verbosity = 0;
+
+static int
+usage(FILE *fp, char *prog) {
+ fprintf(fp, "%s [options] domain\n", prog);
+ fprintf(fp, " print out the owner names for domain and the record types for those names\n");
+ fprintf(fp, "OPTIONS:\n");
+ fprintf(fp, "-4\t\tonly use IPv4\n");
+ fprintf(fp, "-6\t\tonly use IPv6\n");
+ fprintf(fp, "-f\t\tfull; get all rrsets instead of only a list of names and types\n");
+ fprintf(fp, "-s <name>\t\tStart from this name\n");
+ fprintf(fp, "-v <verbosity>\t\tVerbosity level [1-5]\n");
+ fprintf(fp, "-version\tShow version and exit\n");
+ fprintf(fp, "@<nameserver>\t\tUse this nameserver\n");
+ return 0;
+}
+
+ldns_rdf *
+create_dname_plus_1(ldns_rdf *dname)
+{
+ uint8_t *wire;
+ ldns_rdf *newdname;
+ uint8_t labellen;
+ size_t pos;
+ ldns_status status;
+ size_t i;
+
+ ldns_dname2canonical(dname);
+ labellen = ldns_rdf_data(dname)[0];
+ if (verbosity >= 3) {
+ printf("Create +e for ");
+ ldns_rdf_print(stdout, dname);
+ printf("\n");
+ }
+ if (labellen < 63) {
+ wire = malloc(ldns_rdf_size(dname) + 1);
+ if (!wire) {
+ fprintf(stderr, "Malloc error: out of memory?\n");
+ exit(127);
+ }
+ wire[0] = labellen + 1;
+ memcpy(&wire[1], ldns_rdf_data(dname) + 1, labellen);
+ memcpy(&wire[labellen+1], ldns_rdf_data(dname) + labellen, ldns_rdf_size(dname) - labellen);
+ wire[labellen+1] = (uint8_t) '\000';
+ pos = 0;
+ status = ldns_wire2dname(&newdname, wire, ldns_rdf_size(dname) + 1, &pos);
+ free(wire);
+ } else {
+ wire = malloc(ldns_rdf_size(dname));
+ if (!wire) {
+ fprintf(stderr, "Malloc error: out of memory?\n");
+ exit(127);
+ }
+ wire[0] = labellen;
+ memcpy(&wire[1], ldns_rdf_data(dname) + 1, labellen);
+ memcpy(&wire[labellen], ldns_rdf_data(dname) + labellen, ldns_rdf_size(dname) - labellen);
+ i = labellen;
+ while (wire[i] == 255) {
+ if (i == 0) {
+ printf("Error, don't know how to add 1 to a label with maximum length and all values on 255\n");
+ exit(9);
+ } else {
+ i--;
+ }
+ }
+ wire[i] = wire[i] + 1;
+ pos = 0;
+ status = ldns_wire2dname(&newdname, wire, ldns_rdf_size(dname) + 1, &pos);
+ free(wire);
+ }
+ if (verbosity >= 3) {
+ printf("result: ");
+ ldns_rdf_print(stdout, newdname);
+ printf("\n");
+ }
+
+ if (status != LDNS_STATUS_OK) {
+ printf("Error: %s\n", ldns_get_errorstr_by_id(status));
+ exit(10);
+ }
+
+ return newdname;
+}
+
+ldns_rdf *
+create_plus_1_dname(ldns_rdf *dname)
+{
+ ldns_rdf *label;
+ ldns_status status;
+
+ if (verbosity >= 3) {
+ printf("Creating n+e for: ");
+ ldns_rdf_print(stdout, dname);
+ printf("\n");
+ }
+
+ ldns_dname2canonical(dname);
+ status = ldns_str2rdf_dname(&label, "\\000");
+ if (status != LDNS_STATUS_OK) {
+ printf("error creating \\000 dname: %s\n\n", ldns_get_errorstr_by_id(status));
+ exit(2);
+ }
+ status = ldns_dname_cat(label, dname);
+ if (status != LDNS_STATUS_OK) {
+ printf("error catting \\000 dname: %s\n\n", ldns_get_errorstr_by_id(status));
+ exit(3);
+ }
+ return label;
+}
+
+ldns_status
+query_type_bitmaps(ldns_resolver *res,
+ uint16_t res_flags,
+ const ldns_rdf *name,
+ const ldns_rdf *rdf)
+{
+ /* Note: this code is duplicated in higher.c in
+ * ldns_nsec_type_check() function
+ */
+ uint8_t window_block_nr;
+ uint8_t bitmap_length;
+ uint16_t type;
+ uint16_t pos = 0;
+ uint16_t bit_pos;
+ uint8_t *data = ldns_rdf_data(rdf);
+
+ ldns_pkt *answer_pkt;
+ char *errstr;
+
+ if (verbosity >= 3) {
+ printf("Getting Resource Records covered by NSEC at ");
+ ldns_rdf_print(stdout, name);
+ printf("\n");
+ }
+
+ while(pos < ldns_rdf_size(rdf)) {
+ window_block_nr = data[pos];
+ bitmap_length = data[pos + 1];
+ pos += 2;
+
+ for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
+ if (ldns_get_bit(&data[pos], bit_pos)) {
+ type = 256 * (uint16_t) window_block_nr + bit_pos;
+ /* skip nsec and rrsig */
+ if (type != LDNS_RR_TYPE_NSEC &&
+ type != LDNS_RR_TYPE_RRSIG) {
+ if (verbosity >= 3) {
+ printf("querying for:\n");
+ ldns_rdf_print(stdout, name);
+ printf(" type %u\n", (unsigned int) type);
+ }
+ answer_pkt = ldns_resolver_query(res, name, type,
+ LDNS_RR_CLASS_IN,
+ res_flags);
+ if (answer_pkt) {
+ if (verbosity >= 5) {
+ ldns_pkt_print(stdout, answer_pkt);
+ }
+ /* hmm, this does not give us the right records
+ * when askking for type NS above the delegation
+ * (or, in fact, when the delegated zone is
+ * served by this server either)
+ * do we need to special case NS like NSEC?
+ * or can we fix the query or the answer reading?
+ * ...
+ */
+ ldns_rr_list_print(stdout,
+ ldns_pkt_answer(answer_pkt));
+ ldns_pkt_free(answer_pkt);
+ } else {
+ printf("Query error, bailing out\n");
+ printf("Failed at ");
+ ldns_rdf_print(stdout, name);
+ errstr = ldns_rr_type2str(type);
+ printf(" %s\n", errstr);
+ free(errstr);
+ exit(1);
+ }
+ }
+ }
+ }
+
+ pos += (uint16_t) bitmap_length;
+ }
+
+ return LDNS_STATUS_OK;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ ldns_status status;
+
+ ldns_resolver *res;
+ ldns_rdf *domain = NULL;
+ ldns_pkt *p;
+ ldns_rr *soa;
+ ldns_rr_list *rrlist;
+ ldns_rr_list *rrlist2;
+ ldns_rr_list *nsec_sigs = NULL;
+ ldns_rdf *soa_p1;
+ ldns_rdf *next_dname;
+ ldns_rdf *last_dname;
+ ldns_rdf *last_dname_p;
+ ldns_rdf *startpoint = NULL;
+ ldns_rr *nsec_rr = NULL;
+ const char* arg_domain = NULL;
+ int full = 0;
+
+ char *serv = NULL;
+ ldns_rdf *serv_rdf;
+ ldns_resolver *cmdline_res;
+ ldns_rr_list *cmdline_rr_list;
+ ldns_rdf *cmdline_dname;
+
+ uint8_t fam = LDNS_RESOLV_INETANY;
+ int result = 0;
+ int i;
+ char *arg_end_ptr = NULL;
+ size_t j;
+
+ p = NULL;
+ rrlist = NULL;
+ rrlist2 = NULL;
+ soa = NULL;
+ domain = NULL;
+
+ if (argc < 2) {
+ usage(stdout, argv[0]);
+ exit(EXIT_FAILURE);
+ } else {
+ for (i = 1; i < argc; i++) {
+ if (strncmp(argv[i], "-4", 3) == 0) {
+ if (fam != LDNS_RESOLV_INETANY) {
+ fprintf(stderr, "You can only specify one of -4 or -6\n");
+ exit(1);
+ }
+ fam = LDNS_RESOLV_INET;
+ } else if (strncmp(argv[i], "-6", 3) == 0) {
+ if (fam != LDNS_RESOLV_INETANY) {
+ fprintf(stderr, "You can only specify one of -4 or -6\n");
+ exit(1);
+ }
+ fam = LDNS_RESOLV_INET6;
+ } else if (strncmp(argv[i], "-f", 3) == 0) {
+ full = true;
+ } else if (strncmp(argv[i], "-s", 3) == 0) {
+ if (i + 1 < argc) {
+ if (!ldns_str2rdf_dname(&startpoint, argv[i + 1]) == LDNS_STATUS_OK) {
+ printf("Bad start point name: %s\n", argv[i + 1]);
+ exit(1);
+ }
+ } else {
+ printf("Missing argument for -s\n");
+ exit(1);
+ }
+ i++;
+ } else if (strncmp(argv[i], "-v", 3) == 0) {
+ if (i + 1 < argc) {
+ verbosity = strtol(argv[i+1], &arg_end_ptr, 10);
+ if (*arg_end_ptr != '\0') {
+ printf("Bad argument for -v: %s\n", argv[i+1]);
+ exit(1);
+ }
+ } else {
+ printf("Missing argument for -v\n");
+ exit(1);
+ }
+ i++;
+ } else if (strcmp("-version", argv[i]) == 0) {
+ printf("dns zone walker, version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
+ goto exit;
+ } else {
+ if (argv[i][0] == '@') {
+ if (strlen(argv[i]) == 1) {
+ if (i + 1 < argc) {
+ serv = argv[i + 1];
+ i++;
+ } else {
+ printf("Missing argument for -s\n");
+ exit(1);
+ }
+ } else {
+ serv = argv[i] + 1;
+ }
+ } else {
+ if (i < argc) {
+ if (!domain) {
+ /* create a rdf from the command line arg */
+ arg_domain = argv[i];
+ domain = ldns_dname_new_frm_str(arg_domain);
+ if (!domain) {
+ usage(stdout, argv[0]);
+ exit(1);
+ }
+ } else {
+ printf("One domain at a time please\n");
+ exit(1);
+ }
+ } else {
+ printf("No domain given to walk\n");
+ exit(1);
+ }
+ }
+ }
+ }
+ }
+ if (!domain) {
+ printf("Missing argument\n");
+ exit(1);
+ }
+
+
+ /* create a new resolver from /etc/resolv.conf */
+ if(!serv) {
+ if (ldns_resolver_new_frm_file(&res, NULL) != LDNS_STATUS_OK) {
+ fprintf(stderr, "%s", "Could not create resolver obj");
+ result = EXIT_FAILURE;
+ goto exit;
+ }
+ } else {
+ res = ldns_resolver_new();
+ if (!res || strlen(serv) <= 0) {
+ result = EXIT_FAILURE;
+ goto exit;
+ }
+ /* add the nameserver */
+ serv_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, serv);
+ if (!serv_rdf) {
+ /* maybe ip6 */
+ serv_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, serv);
+ }
+ if (!serv_rdf) {
+ /* try to resolv the name if possible */
+ status = ldns_resolver_new_frm_file(&cmdline_res, NULL);
+
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "%s", "@server ip could not be converted");
+ result = EXIT_FAILURE;
+ goto exit;
+ }
+
+ cmdline_dname = ldns_dname_new_frm_str(serv);
+ cmdline_rr_list = ldns_get_rr_list_addr_by_name(
+ cmdline_res,
+ cmdline_dname,
+ LDNS_RR_CLASS_IN,
+ 0);
+ ldns_rdf_deep_free(cmdline_dname);
+ ldns_resolver_deep_free(cmdline_res);
+ if (!cmdline_rr_list) {
+ fprintf(stderr, "%s %s", "could not find any address for the name: ", serv);
+ result = EXIT_FAILURE;
+ goto exit;
+ } else {
+ if (ldns_resolver_push_nameserver_rr_list(
+ res,
+ cmdline_rr_list
+ ) != LDNS_STATUS_OK) {
+ fprintf(stderr, "%s", "pushing nameserver");
+ result = EXIT_FAILURE;
+ ldns_rr_list_deep_free(cmdline_rr_list);
+ goto exit;
+ }
+ ldns_rr_list_deep_free(cmdline_rr_list);
+ }
+ } else {
+ if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) {
+ fprintf(stderr, "%s", "pushing nameserver");
+ result = EXIT_FAILURE;
+ goto exit;
+ } else {
+ ldns_rdf_deep_free(serv_rdf);
+ }
+ }
+
+ }
+
+ ldns_resolver_set_dnssec(res, true);
+ ldns_resolver_set_dnssec_cd(res, true);
+ ldns_resolver_set_ip6(res, fam);
+
+ if (!res) {
+ exit(2);
+ }
+
+ /* use the resolver to send it a query for the soa
+ * records of the domain given on the command line
+ */
+ if (verbosity >= 3) {
+ printf("\nQuerying for: ");
+ ldns_rdf_print(stdout, domain);
+ printf("\n");
+ }
+ p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD);
+ soa = NULL;
+ if (verbosity >= 5) {
+ if (p) {
+ ldns_pkt_print(stdout, p);
+ } else {
+ fprintf(stdout, "No Packet Received from ldns_resolver_query()\n");
+ }
+ }
+
+ if (!p) {
+ exit(3);
+ } else {
+ /* retrieve the MX records from the answer section of that
+ * packet
+ */
+ rrlist = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA, LDNS_SECTION_ANSWER);
+ if (!rrlist || ldns_rr_list_rr_count(rrlist) != 1) {
+ if (rrlist) {
+ printf(" *** > 1 SOA: %u\n", (unsigned int) ldns_rr_list_rr_count(rrlist));
+ } else {
+ printf(" *** No rrlist...\b");
+ }
+ /* TODO: conversion memory */
+ fprintf(stderr,
+ " *** invalid answer name after SOA query for %s\n",
+ arg_domain);
+ ldns_pkt_print(stdout, p);
+ ldns_pkt_free(p);
+ ldns_resolver_deep_free(res);
+ exit(4);
+ } else {
+ soa = ldns_rr_clone(ldns_rr_list_rr(rrlist, 0));
+ ldns_rr_list_deep_free(rrlist);
+ rrlist = NULL;
+ /* check if zone contains DNSSEC data */
+ rrlist = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER);
+ if (!rrlist) {
+ printf("No DNSSEC data received; either the zone is not secured or you should query it directly (with @nameserver)\n");
+ ldns_pkt_free(p);
+ ldns_resolver_deep_free(res);
+ exit(5);
+ }
+ ldns_rr_list_deep_free(rrlist);
+ }
+ }
+
+ /* add \001 to soa */
+ status = ldns_str2rdf_dname(&soa_p1, "\\000");
+ if (status != LDNS_STATUS_OK) {
+ printf("error: %s\n", ldns_get_errorstr_by_id(status));
+ }
+ if (!soa) {
+ printf("Error getting SOA\n");
+ exit(1);
+ }
+
+ if (startpoint) {
+ last_dname = startpoint;
+ last_dname_p = create_dname_plus_1(last_dname);
+ } else {
+ last_dname = ldns_rdf_clone(domain);
+ if (ldns_dname_cat(soa_p1, last_dname) != LDNS_STATUS_OK) {
+ printf("Error concatenating dnames\n");
+ exit(EXIT_FAILURE);
+ }
+ last_dname_p = ldns_rdf_clone(soa_p1);
+ }
+
+ if (!full) {
+ ldns_rdf_print(stdout, ldns_rr_owner(soa));
+ printf("\t");
+ }
+
+ next_dname = NULL;
+ while (!next_dname || ldns_rdf_compare(next_dname, domain) != 0) {
+ if (p) {
+ ldns_pkt_free(p);
+ p = NULL;
+ }
+ if (verbosity >= 4) {
+ printf("Querying for: ");
+ ldns_rdf_print(stdout, last_dname_p);
+ printf("\n");
+ }
+ p = ldns_resolver_query(res, last_dname_p, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD);
+ if (verbosity >= 5) {
+ if (p) {
+ ldns_pkt_print(stdout, p);
+ } else {
+ fprintf(stdout, "No Packet Received from ldns_resolver_query()\n");
+ }
+ }
+
+ if (next_dname) {
+ ldns_rdf_deep_free(next_dname);
+ ldns_rr_free(nsec_rr);
+ next_dname = NULL;
+ nsec_rr = NULL;
+ }
+
+ if (!p) {
+ fprintf(stderr, "Error trying to resolve: ");
+ ldns_rdf_print(stderr, last_dname_p);
+ fprintf(stderr, "\n");
+ while (!p) {
+ if (verbosity >= 3) {
+ printf("Querying for: ");
+ ldns_rdf_print(stdout, last_dname_p);
+ printf("\n");
+ }
+ p = ldns_resolver_query(res, last_dname_p, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD);
+ /* TODO: make a general option for this (something like ignore_rtt)? */
+ for (j = 0; j < ldns_resolver_nameserver_count(res); j++) {
+ if (ldns_resolver_nameserver_rtt(res, j) != 0) {
+ ldns_resolver_set_nameserver_rtt(res, j, LDNS_RESOLV_RTT_MIN);
+ }
+ }
+ if (verbosity >= 5) {
+ if (p) {
+ ldns_pkt_print(stdout, p);
+ } else {
+ fprintf(stdout, "No Packet Received from ldns_resolver_query()\n");
+ }
+ }
+ }
+ }
+
+ /* if the current name is an empty non-terminal, bind returns
+ * SERVFAIL on the plus1-query...
+ * so requery with only the last dname
+ */
+ if (ldns_pkt_get_rcode(p) == LDNS_RCODE_SERVFAIL) {
+ ldns_pkt_free(p);
+ p = NULL;
+ if (verbosity >= 3) {
+ printf("Querying for: ");
+ ldns_rdf_print(stdout, last_dname);
+ printf("\n");
+ }
+ p = ldns_resolver_query(res, last_dname, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD);
+ if (verbosity >= 5) {
+ if (p) {
+ ldns_pkt_print(stdout, p);
+ } else {
+ fprintf(stdout, "No Packet Received from ldns_resolver_query()\n");
+ }
+ }
+
+ if (!p) {
+ exit(51);
+ }
+ rrlist = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NSEC, LDNS_SECTION_AUTHORITY);
+ rrlist2 = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANSWER);
+ } else {
+ rrlist = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NSEC, LDNS_SECTION_AUTHORITY);
+ rrlist2 = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANSWER);
+ }
+ if (rrlist && rrlist2) {
+ ldns_rr_list_cat(rrlist, rrlist2);
+ } else if (rrlist2) {
+ rrlist = rrlist2;
+ }
+
+ if (!rrlist || ldns_rr_list_rr_count(rrlist) < 1) {
+ if (!rrlist) {
+ fflush(stdout);
+ fprintf(stderr, "Zone does not seem to be DNSSEC secured,"
+ "or it uses NSEC3.\n");
+ fflush(stderr);
+ goto exit;
+ }
+ } else {
+ /* find correct nsec */
+ next_dname = NULL;
+ for (j = 0; j < ldns_rr_list_rr_count(rrlist); j++) {
+ if (ldns_nsec_covers_name(ldns_rr_list_rr(rrlist, j), last_dname_p)) {
+ if (verbosity >= 3) {
+ printf("The domain name: ");
+ ldns_rdf_print(stdout, last_dname_p);
+ printf("\nis covered by NSEC: ");
+ ldns_rr_print(stdout, ldns_rr_list_rr(rrlist, j));
+ }
+ next_dname = ldns_rdf_clone(ldns_rr_rdf(ldns_rr_list_rr(rrlist, j), 0));
+ nsec_rr = ldns_rr_clone(ldns_rr_list_rr(rrlist, j));
+ nsec_sigs = ldns_dnssec_pkt_get_rrsigs_for_name_and_type(p, ldns_rr_owner(nsec_rr), LDNS_RR_TYPE_NSEC);
+ } else {
+ if (verbosity >= 4) {
+ printf("\n");
+ ldns_rdf_print(stdout, last_dname_p);
+ printf("\nNOT covered by NSEC: ");
+ ldns_rr_print(stdout, ldns_rr_list_rr(rrlist, j));
+ printf("\n");
+ }
+ }
+ }
+ if (!next_dname) {
+ printf("Error no nsec for ");
+ ldns_rdf_print(stdout, last_dname);
+ printf("\n");
+ exit(1);
+ }
+ ldns_rr_list_deep_free(rrlist);
+ }
+ if (!next_dname) {
+ /* apparently the zone also has prepended data (i.e. a.example and www.a.example,
+ * The www comes after the a but befpre a\\000, so we need to make another name (\\000.a)
+ */
+ if (last_dname_p) {
+ ldns_rdf_deep_free(last_dname_p);
+ }
+ last_dname_p = create_plus_1_dname(last_dname);
+ } else {
+ if (last_dname) {
+ if (ldns_rdf_compare(last_dname, next_dname) == 0) {
+ printf("\n\nNext dname is the same as current, this would loop forever. This is a problem that usually occurs when walking through a caching forwarder. Try using the authoritative nameserver to walk (with @nameserver).\n");
+ exit(2);
+ }
+ ldns_rdf_deep_free(last_dname);
+ }
+ last_dname = ldns_rdf_clone(next_dname);
+ if (last_dname_p) {
+ ldns_rdf_deep_free(last_dname_p);
+ }
+ last_dname_p = create_dname_plus_1(last_dname);
+ if (!full) {
+ ldns_rdf_print(stdout, ldns_rr_owner(nsec_rr));
+ printf(" ");
+ ldns_rdf_print(stdout, ldns_rr_rdf(nsec_rr, 1));
+ printf("\n");
+ } else {
+ /* ok, so now we know all the types present at this name,
+ * query for those one by one (...)
+ */
+ status = query_type_bitmaps(res, LDNS_RD, ldns_rr_owner(nsec_rr),
+ ldns_rr_rdf(nsec_rr, 1));
+ /* print this nsec and its signatures too */
+ ldns_rr_print(stdout, nsec_rr);
+ if (nsec_sigs) {
+ ldns_rr_list_print(stdout, nsec_sigs);
+ ldns_rr_list_free(nsec_sigs);
+ nsec_sigs = NULL;
+ }
+ }
+ }
+
+ }
+
+ ldns_rdf_deep_free(domain);
+ ldns_rdf_deep_free(soa_p1);
+ ldns_rdf_deep_free(last_dname_p);
+ ldns_rdf_deep_free(last_dname);
+ ldns_rdf_deep_free(next_dname);
+ ldns_rr_free(nsec_rr);
+ ldns_pkt_free(p);
+
+ ldns_rr_free(soa);
+
+ printf("\n\n");
+ ldns_resolver_deep_free(res);
+
+ exit:
+ return result;
+}
diff --git a/examples/ldns-zcat.1 b/examples/ldns-zcat.1
new file mode 100644
index 000000000000..9c4054df3cd3
--- /dev/null
+++ b/examples/ldns-zcat.1
@@ -0,0 +1,30 @@
+.TH ldns-zcat 1 "15 Dec 2005"
+.SH NAME
+ldns-zcat \- reunite (z)split up a zone files
+.SH SYNOPSIS
+.B ldns-zcat
+.IR zonefiles
+
+.SH DESCRIPTION
+.B ldns-zcat
+will read in a bunch of (z)split up zonefiles and creates a new larger
+zone file. The SOA record in the first part is used as the SOA record
+in the generated zone.
+.PP
+The resulted zone file is printed to standard output.
+
+.SH OPTIONS
+.TP
+.B -o ORIGIN
+use ORIGIN when reading in the zone
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005, 2006 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-zcat.c b/examples/ldns-zcat.c
new file mode 100644
index 000000000000..df4ecbafbf79
--- /dev/null
+++ b/examples/ldns-zcat.c
@@ -0,0 +1,171 @@
+/*
+ * read a zone that is split up with ldns-zsplit and re-create
+ * the original zone
+ *
+ * From:
+ * zone1: SOA a b c d e f
+ * zone2: SOA f g h i k l
+ *
+ * Go back to:
+ * zone: SOA a b c d e f g h i j k l
+ *
+ * This is useful in combination with ldns-zsplit
+ *
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <errno.h>
+#include <ldns/ldns.h>
+
+#define FIRST_ZONE 0
+#define MIDDLE_ZONE 1
+#define LAST_ZONE 2
+
+static void
+usage(FILE *f, char *progname)
+{
+ fprintf(f, "Usage: %s [OPTIONS] <zonefiles>\n", progname);
+ fprintf(f, " Concatenate signed zone snippets created with ldns-zsplit\n");
+ fprintf(f, " back together. The generate zone file is printed to stdout\n");
+ fprintf(f, " The new zone should be equal to the original zone (before splitting)\n");
+ fprintf(f, "OPTIONS:\n");
+ fprintf(f, "-o ORIGIN\tUse this as initial origin, for zones starting with @\n");
+ fprintf(f, "-v\t\tShow the version number and exit\n");
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progname;
+ FILE *fp;
+ int c;
+ ldns_rdf *origin;
+ size_t i, j;
+ int where;
+ ldns_zone *z;
+ ldns_rr_list *zrr;
+ ldns_rr *current_rr;
+ ldns_rr *soa;
+ ldns_rdf *last_owner;
+ ldns_rr *last_rr;
+ ldns_rr *pop_rr;
+
+ progname = strdup(argv[0]);
+ origin = NULL;
+
+ while ((c = getopt(argc, argv, "n:o:v")) != -1) {
+ switch(c) {
+ case 'o':
+ origin = ldns_dname_new_frm_str(strdup(optarg));
+ if (!origin) {
+ fprintf(stderr, "Cannot convert the origin %s to a domainname\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'v':
+ printf("zone file concatenator version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
+ exit(EXIT_SUCCESS);
+ break;
+ default:
+ fprintf(stderr, "Unrecognized option\n");
+ usage(stdout, progname);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ usage(stdout, progname);
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < (size_t)argc; i++) {
+
+ if (!(fp = fopen(argv[i], "r"))) {
+ fprintf(stderr, "Error opening key file %s: %s\n", argv[i], strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (ldns_zone_new_frm_fp(&z, fp, origin, 0, 0) != LDNS_STATUS_OK) {
+ fprintf(stderr, "Zone file %s could not be parsed correctly\n", argv[i]);
+ exit(EXIT_FAILURE);
+ }
+
+ zrr = ldns_zone_rrs(z);
+ soa = ldns_zone_soa(z); /* SOA is stored seperately */
+
+ fprintf(stderr, "%s\n", argv[i]);
+
+ if (0 == i) {
+ where = FIRST_ZONE;
+
+ /* remove the last equal named RRs */
+ last_rr = ldns_rr_list_pop_rr(zrr);
+ last_owner = ldns_rr_owner(last_rr);
+ /* remove until no match */
+ do {
+ pop_rr = ldns_rr_list_pop_rr(zrr);
+ } while(ldns_rdf_compare(last_owner, ldns_rr_owner(pop_rr)) == 0) ;
+ /* we popped one to many, put it back */
+ ldns_rr_list_push_rr(zrr, pop_rr);
+ } else if ((size_t)(argc - 1) == i) {
+ where = LAST_ZONE;
+ } else {
+ where = MIDDLE_ZONE;
+
+ /* remove the last equal named RRs */
+ last_rr = ldns_rr_list_pop_rr(zrr);
+ last_owner = ldns_rr_owner(last_rr);
+ /* remove until no match */
+ do {
+ pop_rr = ldns_rr_list_pop_rr(zrr);
+ } while(ldns_rdf_compare(last_owner, ldns_rr_owner(pop_rr)) == 0) ;
+ /* we popped one to many, put it back */
+ ldns_rr_list_push_rr(zrr, pop_rr);
+ }
+
+ /* printing the RRs */
+ for (j = 0; j < ldns_rr_list_rr_count(zrr); j++) {
+
+ current_rr = ldns_rr_list_rr(zrr, j);
+
+ switch(where) {
+ case FIRST_ZONE:
+ if (soa) {
+ ldns_rr_print(stdout, soa);
+ soa = NULL;
+ }
+ break;
+ case MIDDLE_ZONE:
+ /* rm SOA */
+ /* SOA isn't printed by default */
+
+ /* rm SOA aux records
+ * this also takes care of the DNSKEYs + RRSIGS
+ */
+ if (ldns_rdf_compare(ldns_rr_owner(current_rr),
+ ldns_rr_owner(soa)) == 0) {
+ continue;
+ }
+ break;
+ case LAST_ZONE:
+ /* rm SOA */
+ /* SOA isn't printed by default */
+
+ /* rm SOA aux records
+ * this also takes care of the DNSKEYs + RRSIGS
+ */
+ if (ldns_rdf_compare(ldns_rr_owner(current_rr),
+ ldns_rr_owner(soa)) == 0) {
+ continue;
+ }
+ break;
+ }
+ ldns_rr_print(stdout, current_rr);
+ }
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/examples/ldns-zsplit.1 b/examples/ldns-zsplit.1
new file mode 100644
index 000000000000..8e64668fe2b6
--- /dev/null
+++ b/examples/ldns-zsplit.1
@@ -0,0 +1,39 @@
+.TH ldns-zsplit 1 "15 Dec 2005"
+.SH NAME
+ldns-zsplit \- split up a zone file
+.SH SYNOPSIS
+.B ldns-zsplit
+[
+.IR OPTIONS
+]
+.IR zonefile
+
+.SH DESCRIPTION
+
+.SH OPTIONS
+.TP
+.B -n NUMBER
+Split after NUMBER RRs, \fBldns-zsplit\fR will not split in
+the middle of an RRs.
+.PP
+Each part is saved with a numerical suffix, starting with .000. The
+largest suffix is thus .999.
+
+.TP
+.B -o ORIGIN
+use ORIGIN as origin when reading the zonefile.
+
+.TP
+.B -z
+Sort the zone before splitting.
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005, 2006 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldns-zsplit.c b/examples/ldns-zsplit.c
new file mode 100644
index 000000000000..84f2ddb9675a
--- /dev/null
+++ b/examples/ldns-zsplit.c
@@ -0,0 +1,272 @@
+/*
+ * read a zone from disk and split it up:
+ *
+ * zone: SOA a b c d e f g h i j k l
+ * becomes:
+ * zone1: SOA a b c d e f
+ * zone2: SOA f g h i k l
+ *
+ * ldns-catzone removes the last name and put
+ * the zone back together.
+ *
+ * This way you can incremental sign a zone
+ *
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <errno.h>
+#include <ldns/ldns.h>
+
+#define DEFAULT_SPLIT 1000
+#define FILE_SIZE 255
+#define SPLIT_MAX 999
+#define NO_SPLIT 0
+#define INTENT_TO_SPLIT 1
+#define SPLIT_NOW 2
+
+static void
+usage(FILE *f, char *progname)
+{
+ fprintf(f, "Usage: %s [OPTIONS] <zonefile> [keys]\n", progname);
+ fprintf(f, " Cut a zone file into pieces, each part is put in a file\n");
+ fprintf(f, " named: '<zonefile>.NNN'. Where NNN is a integer ranging 000 to 999.\n");
+ fprintf(f, " If key files are given they are inserted in each part.\n");
+ fprintf(f, " The original SOA is also included in each part, making them correct DNS\n");
+ fprintf(f, " (mini) zones.\n");
+ fprintf(f, " This utility can be used to parallel sign a large zone.\n");
+ fprintf(f, " To make it work the original zone needs to be canonical ordered.\n");
+ fprintf(f, "\nOPTIONS:\n");
+ fprintf(f, " -n NUMBER\tsplit after this many RRs\n");
+ fprintf(f, " -o ORIGIN\tuse this as initial origin, for zones starting with @\n");
+ fprintf(f, " -z\t\tsort the zone prior to splitting. The current ldns zone\n");
+ fprintf(f, " \t\timplementation makes this unuseable for large zones.\n");
+ fprintf(f, " -v\t\tshow version number and exit\n");
+}
+
+
+/* key the keys from the cmd line */
+static ldns_rr_list *
+open_keyfiles(char **files, uint16_t filec)
+{
+ uint16_t i;
+ ldns_rr_list *pubkeys;
+ ldns_rr *k;
+ FILE *kfp;
+
+ pubkeys = ldns_rr_list_new();
+
+ for (i = 0; i < filec; i++) {
+ if (!(kfp = fopen(files[i], "r"))) {
+ fprintf(stderr, "Error opening key file %s: %s\n", files[i], strerror(errno));
+ return NULL;
+ }
+ if (ldns_rr_new_frm_fp(&k, kfp, NULL, NULL, NULL) != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error parsing the key file %s: %s\n", files[i], strerror(errno));
+ return NULL;
+ }
+ fclose(kfp);
+ ldns_rr_list_push_rr(pubkeys, k);
+ }
+ return pubkeys;
+}
+
+/* open a new zone file with the correct suffix */
+static FILE *
+open_newfile(char *basename, ldns_zone *z, size_t counter, ldns_rr_list *keys)
+{
+ char filename[FILE_SIZE];
+ FILE *fp;
+
+ if (counter > SPLIT_MAX) {
+ fprintf(stderr, "Maximum split count reached %u\n", (unsigned int) counter);
+ return NULL;
+ }
+
+ snprintf(filename, FILE_SIZE, "%s.%03u", basename, (unsigned int) counter);
+
+ if (!(fp = fopen(filename, "w"))) {
+ fprintf(stderr, "Cannot open zone %s: %s\n", filename, strerror(errno));
+ return NULL;
+ } else {
+ fprintf(stderr, "%s\n", filename);
+ }
+ ldns_rr_print(fp, ldns_zone_soa(z));
+ if (keys) {
+ ldns_rr_list_print(fp, keys);
+
+ }
+ return fp;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progname;
+ FILE *fp;
+ ldns_zone *z;
+ ldns_rr_list *zrrs;
+ ldns_rdf *lastname;
+ int c;
+ int line_nr;
+ size_t split;
+ size_t i;
+ int splitting;
+ int compare;
+ size_t file_counter;
+ ldns_rdf *origin;
+ ldns_rdf *current_rdf;
+ ldns_rr *current_rr;
+ ldns_rr_list *last_rrset;
+ ldns_rr_list *pubkeys;
+ bool sort;
+ ldns_status s;
+
+ progname = strdup(argv[0]);
+ split = 0;
+ splitting = NO_SPLIT;
+ file_counter = 0;
+ lastname = NULL;
+ origin = NULL;
+ last_rrset = ldns_rr_list_new();
+ sort = false;
+
+ while ((c = getopt(argc, argv, "n:o:zv")) != -1) {
+ switch(c) {
+ case 'n':
+ split = (size_t)atoi(optarg);
+ if (split == 0) {
+ fprintf(stderr, "-n want a integer\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'o':
+ origin = ldns_dname_new_frm_str(strdup(optarg));
+ if (!origin) {
+ fprintf(stderr, "Cannot convert the origin %s to a domainname\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'v':
+ printf("zone file splitter version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
+ exit(EXIT_SUCCESS);
+ break;
+ case 'z':
+ sort = true;
+ break;
+ default:
+ fprintf(stderr, "Unrecognized option\n");
+ usage(stdout, progname);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (split == 0) {
+ split = DEFAULT_SPLIT;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ usage(stdout, progname);
+ exit(EXIT_FAILURE);
+ }
+
+ if (!(fp = fopen(argv[0], "r"))) {
+ fprintf(stderr, "Unable to open %s: %s\n", argv[0], strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /* get the keys */
+ pubkeys = open_keyfiles(argv + 1, (uint16_t) argc - 1);
+
+ /* suck in the entire zone ... */
+ if (!origin) {
+ origin = ldns_dname_new_frm_str(".");
+ }
+
+ s = ldns_zone_new_frm_fp_l(&z, fp, origin, 0, LDNS_RR_CLASS_IN, &line_nr);
+ fclose(fp);
+
+ if (s != LDNS_STATUS_OK) {
+ fprintf(stderr, "Zone file %s could not be parsed correctly: %s at line %d\n",
+ argv[0],
+ ldns_get_errorstr_by_id(s),
+ line_nr);
+ exit(EXIT_FAILURE);
+ }
+ /* these kind of things can kill you... */
+ if (sort) {
+ ldns_zone_sort(z);
+ }
+
+ zrrs = ldns_zone_rrs(z);
+ if (ldns_rr_list_rr_count(zrrs) / split > SPLIT_MAX) {
+ fprintf(stderr, "The zone is too large for the used -n value: %u\n", (unsigned int) split);
+ exit(EXIT_FAILURE);
+ }
+
+
+ /* Setup */
+ if (!(fp = open_newfile(argv[0], z, file_counter, pubkeys))) {
+ exit(EXIT_FAILURE);
+ }
+
+ for(i = 0; i < ldns_rr_list_rr_count(zrrs); i++) {
+
+ current_rr = ldns_rr_list_rr(zrrs, i);
+ current_rdf = ldns_rr_owner(current_rr);
+
+ compare = ldns_dname_compare(current_rdf, lastname);
+
+ if (compare == 0) {
+ ldns_rr_list_push_rr(last_rrset, current_rr);
+ }
+
+ if (i > 0 && (i % split) == 0) {
+ splitting = INTENT_TO_SPLIT;
+ }
+
+ if (splitting == INTENT_TO_SPLIT) {
+ if (compare != 0) {
+ splitting = SPLIT_NOW;
+ }
+ }
+
+ if (splitting == SPLIT_NOW) {
+ fclose(fp);
+
+ lastname = NULL;
+ splitting = NO_SPLIT;
+ file_counter++;
+ if (!(fp = open_newfile(argv[0], z, file_counter, pubkeys))) {
+ exit(EXIT_FAILURE);
+ }
+
+ /* insert the last RRset in the new file */
+ ldns_rr_list_print(fp, last_rrset);
+
+ /* print the current rr */
+ ldns_rr_print(fp, current_rr);
+
+ /* remove them */
+ ldns_rr_list_free(last_rrset);
+ last_rrset = ldns_rr_list_new();
+ /* add the current RR */
+ ldns_rr_list_push_rr(last_rrset, current_rr);
+ continue;
+ }
+ if (splitting == NO_SPLIT || splitting == INTENT_TO_SPLIT) {
+ ldns_rr_print(fp, current_rr);
+ }
+ if (compare != 0) {
+ /* remove them and then add the current one */
+ ldns_rr_list_free(last_rrset);
+ last_rrset = ldns_rr_list_new();
+ ldns_rr_list_push_rr(last_rrset, current_rr);
+ }
+ lastname = current_rdf;
+ }
+ fclose(fp);
+ exit(EXIT_SUCCESS);
+}
diff --git a/examples/ldnsd.1 b/examples/ldnsd.1
new file mode 100644
index 000000000000..5b18058aba1b
--- /dev/null
+++ b/examples/ldnsd.1
@@ -0,0 +1,26 @@
+.TH ldnsd 1 "27 Apr 2005"
+.SH NAME
+ldnsd \- simple daemon example code
+.SH SYNOPSIS
+.B ldnsd
+.IR port
+.IR zone
+.IR zonefile
+
+.SH DESCRIPTION
+\fBldnsd\fR is a simple daemon that answers queries for a zone.
+This is NOT a full-fledged authoritative nameserver!
+
+.SH OPTIONS
+\fBldnsd\fR takes a port, zone and zonefile as arguments.
+
+.SH AUTHOR
+Written by the ldns team as an example for ldns usage.
+
+.SH REPORTING BUGS
+Report bugs to <ldns-team@nlnetlabs.nl>.
+
+.SH COPYRIGHT
+Copyright (C) 2005 NLnet Labs. This is free software. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/examples/ldnsd.c b/examples/ldnsd.c
new file mode 100644
index 000000000000..e2a55200f399
--- /dev/null
+++ b/examples/ldnsd.c
@@ -0,0 +1,243 @@
+/*
+ * ldnsd. Light-weight DNS daemon
+ *
+ * Tiny dns server to show how a real one could be built.
+ *
+ * (c) NLnet Labs, 2005
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <ldns/ldns.h>
+
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+#endif
+#ifdef HAVE_NETINET_IGMP_H
+# include <netinet/igmp.h>
+#endif
+
+#include <errno.h>
+
+#define INBUF_SIZE 4096
+
+void usage(FILE *output)
+{
+ fprintf(output, "Usage: ldnsd <address> <port> <zone> <zonefile>\n");
+ fprintf(output, "Listens on the specified port and answers queries for the given zone\n");
+ fprintf(output, "This is NOT a full-fledged authoritative nameserver!\n");
+}
+
+static int udp_bind(int sock, int port, const char *my_address)
+{
+ struct sockaddr_in addr;
+ in_addr_t maddr = INADDR_ANY;
+
+ if (my_address) {
+#ifdef AF_INET6
+ if (inet_pton(AF_INET6, my_address, &maddr) < 1) {
+#else
+ if (0) {
+#endif
+ if (inet_pton(AF_INET, my_address, &maddr) < 1) {
+ return -2;
+ }
+ }
+ }
+
+#ifndef S_SPLINT_S
+ addr.sin_family = AF_INET;
+#endif
+ addr.sin_port = (in_port_t) htons((uint16_t)port);
+ addr.sin_addr.s_addr = maddr;
+ return bind(sock, (struct sockaddr *)&addr, (socklen_t) sizeof(addr));
+}
+
+/* this will probably be moved to a better place in the library itself */
+ldns_rr_list *
+get_rrset(const ldns_zone *zone, const ldns_rdf *owner_name, const ldns_rr_type qtype, const ldns_rr_class qclass)
+{
+ uint16_t i;
+ ldns_rr_list *rrlist = ldns_rr_list_new();
+ ldns_rr *cur_rr;
+ if (!zone || !owner_name) {
+ fprintf(stderr, "Warning: get_rrset called with NULL zone or owner name\n");
+ return rrlist;
+ }
+
+ for (i = 0; i < ldns_zone_rr_count(zone); i++) {
+ cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
+ if (ldns_dname_compare(ldns_rr_owner(cur_rr), owner_name) == 0 &&
+ ldns_rr_get_class(cur_rr) == qclass &&
+ ldns_rr_get_type(cur_rr) == qtype
+ ) {
+ ldns_rr_list_push_rr(rrlist, ldns_rr_clone(cur_rr));
+ }
+ }
+
+ printf("Found rrset of %u rrs\n", (unsigned int) ldns_rr_list_rr_count(rrlist));
+
+ return rrlist;
+}
+
+int
+main(int argc, char **argv)
+{
+ /* arguments */
+ int port;
+ const char *zone_file;
+
+ /* network */
+ int sock;
+ ssize_t nb;
+ struct sockaddr addr_me;
+ struct sockaddr addr_him;
+ socklen_t hislen = (socklen_t) sizeof(addr_him);
+ uint8_t inbuf[INBUF_SIZE];
+ uint8_t *outbuf;
+
+ /* dns */
+ ldns_status status;
+ ldns_pkt *query_pkt;
+ ldns_pkt *answer_pkt;
+ size_t answer_size;
+ ldns_rr *query_rr;
+ ldns_rr_list *answer_qr;
+ ldns_rr_list *answer_an;
+ ldns_rr_list *answer_ns;
+ ldns_rr_list *answer_ad;
+ ldns_rdf *origin = NULL;
+
+ /* zone */
+ ldns_zone *zone;
+ int line_nr;
+ FILE *zone_fp;
+
+ /* use this to listen on specified interfaces later? */
+ char *my_address = NULL;
+
+ if (argc < 5) {
+ usage(stderr);
+ exit(EXIT_FAILURE);
+ } else {
+ my_address = argv[1];
+ port = atoi(argv[2]);
+ if (port < 1) {
+ usage(stderr);
+ exit(EXIT_FAILURE);
+ }
+ if (ldns_str2rdf_dname(&origin, argv[3]) != LDNS_STATUS_OK) {
+ fprintf(stderr, "Bad origin, not a correct domain name\n");
+ usage(stderr);
+ exit(EXIT_FAILURE);
+ }
+ zone_file = argv[4];
+ }
+
+ printf("Reading zone file %s\n", zone_file);
+ zone_fp = fopen(zone_file, "r");
+ if (!zone_fp) {
+ fprintf(stderr, "Unable to open %s: %s\n", zone_file, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ line_nr = 0;
+ status = ldns_zone_new_frm_fp_l(&zone, zone_fp, origin, 0, LDNS_RR_CLASS_IN, &line_nr);
+
+ if (status != LDNS_STATUS_OK) {
+ printf("Zone reader failed, aborting\n");
+ exit(EXIT_FAILURE);
+ } else {
+ printf("Read %u resource records in zone file\n", (unsigned int) ldns_zone_rr_count(zone));
+ }
+ fclose(zone_fp);
+
+ printf("Listening on port %d\n", port);
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno));
+ exit(1);
+ }
+ memset(&addr_me, 0, sizeof(addr_me));
+
+ /* bind: try all ports in that range */
+ if (udp_bind(sock, port, my_address)) {
+ fprintf(stderr, "%s: cannot bind(): %s\n", argv[0], strerror(errno));
+ exit(errno);
+ }
+
+ /* Done. Now receive */
+ while (1) {
+ nb = recvfrom(sock, (void*)inbuf, INBUF_SIZE, 0,
+ &addr_him, &hislen);
+ if (nb < 1) {
+ fprintf(stderr, "%s: recvfrom(): %s\n",
+ argv[0], strerror(errno));
+ exit(1);
+ }
+
+ /*
+ show(inbuf, nb, nn, hp, sp, ip, bp);
+ */
+ printf("Got query of %u bytes\n", (unsigned int) nb);
+ status = ldns_wire2pkt(&query_pkt, inbuf, (size_t) nb);
+ if (status != LDNS_STATUS_OK) {
+ printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
+ } else {
+ ldns_pkt_print(stdout, query_pkt);
+ }
+
+ query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
+ printf("QUERY RR: \n");
+ ldns_rr_print(stdout, query_rr);
+
+ answer_qr = ldns_rr_list_new();
+ ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr));
+
+ answer_an = get_rrset(zone, ldns_rr_owner(query_rr), ldns_rr_get_type(query_rr), ldns_rr_get_class(query_rr));
+ answer_pkt = ldns_pkt_new();
+ answer_ns = ldns_rr_list_new();
+ answer_ad = ldns_rr_list_new();
+
+ ldns_pkt_set_qr(answer_pkt, 1);
+ ldns_pkt_set_aa(answer_pkt, 1);
+ ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));
+
+ ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_QUESTION, answer_qr);
+ ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ANSWER, answer_an);
+ ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_AUTHORITY, answer_ns);
+ ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ADDITIONAL, answer_ad);
+
+ status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
+
+ printf("Answer packet size: %u bytes.\n", (unsigned int) answer_size);
+ if (status != LDNS_STATUS_OK) {
+ printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
+ } else {
+ nb = sendto(sock, (void*)outbuf, answer_size, 0,
+ &addr_him, hislen);
+ }
+
+ ldns_pkt_free(query_pkt);
+ ldns_pkt_free(answer_pkt);
+ LDNS_FREE(outbuf);
+ ldns_rr_list_free(answer_qr);
+ ldns_rr_list_free(answer_an);
+ ldns_rr_list_free(answer_ns);
+ ldns_rr_list_free(answer_ad);
+ }
+
+ ldns_rdf_deep_free(origin);
+ ldns_zone_deep_free(zone);
+
+ return 0;
+}