FS-3110 --comment-only phase 2

This commit is contained in:
Anthony Minessale committed 2011-03-24 16:44:22 -05:00
1 parent 0290bdc34a
commit 822ea8f654
243 files changed
-115797

No files matched your search

-179
View File
@@ -1,179 +0,0 @@
# 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)="
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 \
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)
-5
View File
@@ -1,5 +0,0 @@
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
-363
View File
@@ -1,363 +0,0 @@
/* 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
-7150
View File
File diff suppressed because it is too large. Load diff
-421
View File
@@ -1,421 +0,0 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.56)
AC_INIT(ldns, 1.6.9, 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
-175
View File
@@ -1,175 +0,0 @@
/* 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 */
-26
View File
@@ -1,26 +0,0 @@
.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.
-125
View File
@@ -1,125 +0,0 @@
/*
* 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);
}
-57
View File
@@ -1,57 +0,0 @@
.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.
-283
View File
@@ -1,283 +0,0 @@
/*
* 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(int argc, char **argv)
{
printf("Usage: %s [-v] [-i] [-d] [-c] [-s] <zonefile1> <zonefile2>\n",
argv[0]);
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(argc, argv);
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(argc, argv);
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;
}
-151
View File
@@ -1,151 +0,0 @@
.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.
File diff suppressed because it is too large. Load diff
-41
View File
@@ -1,41 +0,0 @@
.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.
-199
View File
@@ -1,199 +0,0 @@
/*
* 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);
}
-64
View File
@@ -1,64 +0,0 @@
.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.
-724
View File
@@ -1,724 +0,0 @@
/*
* 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 *final_answer;
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;
final_answer = 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;
}
-53
View File
@@ -1,53 +0,0 @@
.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.
-307
View File
@@ -1,307 +0,0 @@
/*
* 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 */
-23
View File
@@ -1,23 +0,0 @@
.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.
-88
View File
@@ -1,88 +0,0 @@
/*
* 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;
}
-66
View File
@@ -1,66 +0,0 @@
.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.
-329
View File
@@ -1,329 +0,0 @@
/*
* 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;
fd_set rfds;
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 */
FD_ZERO(&rfds);
FD_SET(s, &rfds);
#ifndef S_SPLINT_S
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));
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);
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;
char *port = "53";
srandom(time(NULL) ^ getpid());
while ((c = getopt(argc, argv, "vhdp:r:s:y:z:")) != -1) {
switch (c) {
case 'd':
verbose = 1;
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 = "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) {
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;
}
-34
View File
@@ -1,34 +0,0 @@
.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.
-127
View File
@@ -1,127 +0,0 @@
/*
* 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;
}
-56
View File
@@ -1,56 +0,0 @@
.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-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.
-159
View File
@@ -1,159 +0,0 @@
/*
* 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 <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;
while ((c = getopt(argc, argv, "cdhnsvz")) != -1) {
switch(c) {
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-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-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;
}
}
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_NSEC3PARAMS
) {
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_NSEC3PARAMS
) {
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)) {
ldns_rr_print(stdout, ldns_zone_soa(z));
}
ldns_rr_list_print(stdout, 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);
}
-26
View File
@@ -1,26 +0,0 @@
.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.
-47
View File
@@ -1,47 +0,0 @@
/*
* 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;
}
-27
View File
@@ -1,27 +0,0 @@
.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.
-104
View File
@@ -1,104 +0,0 @@
/*
* 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);
}
-30
View File
@@ -1,30 +0,0 @@
.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.
-207
View File
@@ -1,207 +0,0 @@
/*
* 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;
char * type_name;
time_t incep, expir;
char incep_buf[26];
char expir_buf[26];
ldns_status s;
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++) {
incep = ldns_rdf2native_time_t(
ldns_rr_rrsig_inception(
ldns_rr_list_rr(rrsig_type, i)));
expir = ldns_rdf2native_time_t(
ldns_rr_rrsig_expiration(
ldns_rr_list_rr(rrsig_type, i)));
/* convert to human readable */
ctime_r(&incep, incep_buf);
ctime_r(&expir, expir_buf);
/* kill the newline */
incep_buf[24] = '\0';
expir_buf[24] = '\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;
}
-159
View File
@@ -1,159 +0,0 @@
.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-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-l\fR
Leave old DNSSEC RRSIGS and NSEC records intact (by default, they are
removed from the zone)
.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.
-836
View File
@@ -1,836 +0,0 @@
/*
* 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, " -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, " -l\t\tLeave old DNSSEC RRSIGS and NSEC(3) records intact\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");
}
void
usage_openssl(FILE *fp, const char *prog) {
fprintf(fp, "Special commands for openssl engines:\n");
fprintf(fp, "-c <file>\tOpenSSL config file\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 *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 ldns_status
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);
}
return LDNS_STATUS_OK;
}
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;
ldns_status status;
bool leave_old_dnssec_data = false;
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;
inception = 0;
expiration = 0;
keys = ldns_key_list_new();
OPENSSL_config(NULL);
while ((c = getopt(argc, argv, "a:de:f:i:k:lno:ps:t:vAE:K:")) != -1) {
switch (c) {
case 'a':
nsec3_algorithm = (uint8_t) atoi(optarg);
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 'l':
leave_old_dnssec_data = true;
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) {
status = 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(signed_zone,
added_rrs,
keys,
ldns_dnssec_default_replace_signatures,
NULL,
nsec3_algorithm,
nsec3_flags,
nsec3_iterations,
nsec3_salt_length,
nsec3_salt,
signflags);
} 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(outputfile, 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 */
-41
View File
@@ -1,41 +0,0 @@
.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.
-246
View File
@@ -1,246 +0,0 @@
/*
* 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);
((struct sockaddr_in*)addr)->sin_family = AF_INET;
((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(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, 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, 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;
}
-131
View File
@@ -1,131 +0,0 @@
.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.
-576
View File
@@ -1,576 +0,0 @@
/*
* 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 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
addr.sin_family = AF_INET;
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;
struct timeval timeout;
int count;
int maxfd;
/* service */
count = 0;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
while (1) {
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_ZERO(&eset);
FD_SET(udp_sock, &rset);
FD_SET(tcp_sock, &rset);
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 == -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;
}
-881
View File
@@ -1,881 +0,0 @@
/*
* 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;
}
}
-255
View File
@@ -1,255 +0,0 @@
/*
* 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 */
-44
View File
@@ -1,44 +0,0 @@
.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.
-310
View File
@@ -1,310 +0,0 @@
/* $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);
}
-49
View File
@@ -1,49 +0,0 @@
.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
.TP
\fB-h\fR
Show usage and exit
.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
.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.
-713
View File
@@ -1,713 +0,0 @@
/*
* 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>
int verbosity = 3;
/* returns 1 if the list is empty, or if there are only ns rrs in the
* list, 0 otherwise */
static int
only_ns_in_rrsets(ldns_dnssec_rrsets *rrsets) {
ldns_dnssec_rrsets *cur_rrset = rrsets;
while (cur_rrset) {
if (cur_rrset->type != LDNS_RR_TYPE_NS) {
return 0;
}
cur_rrset = cur_rrset->next;
}
return 1;
}
static int
zone_is_nsec3_optout(ldns_rbtree_t *zone_nodes)
{
/* simply find the first NSEC3 RR and check its flags */
/* TODO: maybe create a general function that uses the active
* NSEC3PARAM RR? */
ldns_rbnode_t *cur_node;
ldns_dnssec_name *cur_name;
cur_node = ldns_rbtree_first(zone_nodes);
while (cur_node != LDNS_RBTREE_NULL) {
cur_name = (ldns_dnssec_name *) cur_node->data;
if (cur_name && cur_name->nsec &&
ldns_rr_get_type(cur_name->nsec) == LDNS_RR_TYPE_NSEC3) {
if (ldns_nsec3_optout(cur_name->nsec)) {
return 1;
} else {
return 0;
}
}
cur_node = ldns_rbtree_next(cur_node);
}
return 0;
}
static bool
ldns_rr_list_contains_name(const ldns_rr_list *rr_list,
const ldns_rdf *name)
{
size_t i;
for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
if (ldns_dname_compare(name,
ldns_rr_owner(ldns_rr_list_rr(rr_list, i))) == 0) {
return true;
}
}
return false;
}
static void
print_type(ldns_rr_type type)
{
const ldns_rr_descriptor *descriptor;
descriptor = ldns_rr_descript(type);
if (descriptor && descriptor->_name) {
fprintf(stdout, "%s", descriptor->_name);
} else {
fprintf(stdout, "TYPE%u",
type);
}
}
static ldns_dnssec_zone *
create_dnssec_zone(ldns_zone *orig_zone)
{
size_t i;
ldns_dnssec_zone *dnssec_zone;
ldns_rr *cur_rr;
ldns_status status;
/* when reading NSEC3s, there is a chance that we encounter nsecs
for empty nonterminals, whose nonterminals we cannot derive yet
because the needed information is to be read later. in that case
we keep a list of those nsec3's and retry to add them later */
ldns_rr_list *failed_nsec3s = ldns_rr_list_new();
dnssec_zone = ldns_dnssec_zone_new();
if (ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(orig_zone)) !=
LDNS_STATUS_OK) {
if (verbosity > 0) {
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++) {
cur_rr = ldns_rr_list_rr(ldns_zone_rrs(orig_zone), i);
status = ldns_dnssec_zone_add_rr(dnssec_zone, cur_rr);
if (status != LDNS_STATUS_OK) {
if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
ldns_rr_list_push_rr(failed_nsec3s, cur_rr);
} else {
if (verbosity > 0) {
fprintf(stderr, "Error adding RR to dnssec zone");
fprintf(stderr, ", skipping record:\n");
ldns_rr_print(stderr, cur_rr);
}
}
}
}
if (ldns_rr_list_rr_count(failed_nsec3s) > 0) {
(void) ldns_dnssec_zone_add_empty_nonterminals(dnssec_zone);
for (i = 0; i < ldns_rr_list_rr_count(failed_nsec3s); i++) {
cur_rr = ldns_rr_list_rr(failed_nsec3s, i);
status = ldns_dnssec_zone_add_rr(dnssec_zone, cur_rr);
}
}
ldns_rr_list_free(failed_nsec3s);
return dnssec_zone;
}
static ldns_status
verify_dnssec_rrset(ldns_rdf *zone_name,
ldns_rdf *name,
ldns_dnssec_rrsets *rrset,
ldns_rr_list *keys,
ldns_rr_list *glue_rrs)
{
ldns_rr_list *rrset_rrs;
ldns_dnssec_rrs *cur_rr, *cur_sig;
ldns_status status;
ldns_rr_list *good_keys;
ldns_status result = LDNS_STATUS_OK;
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) {
while (cur_sig) {
good_keys = ldns_rr_list_new();
status = ldns_verify_rrsig_keylist(rrset_rrs,
cur_sig->rr,
keys,
good_keys);
if (status != LDNS_STATUS_OK) {
if (verbosity > 0) {
printf("Error: %s",
ldns_get_errorstr_by_id(status));
printf(" for ");
ldns_rdf_print(stdout,
ldns_rr_owner(rrset->rrs->rr));
printf("\t");
print_type(rrset->type);
printf("\n");
if (result == LDNS_STATUS_OK) {
result = status;
}
if (status == LDNS_STATUS_SSL_ERR) {
ERR_load_crypto_strings();
ERR_print_errors_fp(stdout);
}
if (verbosity >= 4) {
printf("RRSet:\n");
ldns_dnssec_rrs_print(stdout, rrset->rrs);
printf("Signature:\n");
ldns_rr_print(stdout, cur_sig->rr);
printf("\n");
}
}
}
ldns_rr_list_free(good_keys);
cur_sig = cur_sig->next;
}
} else {
/* delegations are unsigned */
if (rrset->type != LDNS_RR_TYPE_NS ||
ldns_dname_compare(name, zone_name) == 0) {
if (verbosity > 0) {
printf("Error: no signatures for ");
ldns_rdf_print(stdout, ldns_rr_owner(rrset->rrs->rr));
printf("\t");
print_type(rrset->type);
printf("\n");
}
}
}
ldns_rr_list_free(rrset_rrs);
return result;
}
static ldns_status
verify_single_rr(ldns_rr *rr,
ldns_dnssec_rrs *signature_rrs,
ldns_rr_list *keys)
{
ldns_rr_list *rrset_rrs;
ldns_rr_list *good_keys;
ldns_dnssec_rrs *cur_sig;
ldns_status status;
ldns_status result = LDNS_STATUS_OK;
rrset_rrs = ldns_rr_list_new();
ldns_rr_list_push_rr(rrset_rrs, rr);
cur_sig = signature_rrs;
while (cur_sig) {
good_keys = ldns_rr_list_new();
status = ldns_verify_rrsig_keylist(rrset_rrs,
cur_sig->rr,
keys,
good_keys);
if (status != LDNS_STATUS_OK) {
if (verbosity >= 1) {
printf("Error: %s ", ldns_get_errorstr_by_id(status));
if (result == LDNS_STATUS_OK) {
result = status;
}
printf("for ");
ldns_rdf_print(stdout, ldns_rr_owner(rr));
printf("\t");
print_type(ldns_rr_get_type(rr));
printf("\n");
if (status == LDNS_STATUS_SSL_ERR) {
ERR_load_crypto_strings();
ERR_print_errors_fp(stdout);
}
if (verbosity >= 4) {
printf("RRSet:\n");
ldns_rr_list_print(stdout, rrset_rrs);
printf("Signature:\n");
ldns_rr_print(stdout, cur_sig->rr);
printf("\n");
}
}
result = status;
}
ldns_rr_list_free(good_keys);
cur_sig = cur_sig->next;
}
ldns_rr_list_free(rrset_rrs);
return result;
}
static ldns_status
verify_next_hashed_name(ldns_rbtree_t *zone_nodes,
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_nodes);
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) {
printf("Error: The NSEC3 record for ");
ldns_rdf_print(stdout, name->name);
printf(" points to the wrong next hashed owner name\n");
printf("(should point to ");
ldns_rdf_print(stdout, cur_next_name->name);
printf("(whose hashed name is ");
ldns_rdf_print(stdout, cur_next_name->hashed_name);
printf(")\n");
return LDNS_STATUS_ERR;
} else {
return LDNS_STATUS_OK;
}
}
static ldns_rbnode_t *
next_nonglue_node(ldns_rbnode_t *node, ldns_rr_list *glue_rrs)
{
ldns_rbnode_t *cur_node = ldns_rbtree_next(node);
ldns_dnssec_name *cur_name;
while (cur_node != LDNS_RBTREE_NULL) {
cur_name = (ldns_dnssec_name *) cur_node->data;
if (cur_name && cur_name->name) {
if (!ldns_rr_list_contains_name(glue_rrs, cur_name->name)) {
return cur_node;
}
}
cur_node = ldns_rbtree_next(cur_node);
}
return LDNS_RBTREE_NULL;
}
static ldns_status
verify_nsec(ldns_rbtree_t *zone_nodes,
ldns_rbnode_t *cur_node,
ldns_rr_list *keys,
ldns_rr_list *glue_rrs
)
{
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);
if (result == LDNS_STATUS_OK) {
result = status;
}
} else {
if (verbosity >= 1) {
printf("Error: the NSEC(3) record of ");
ldns_rdf_print(stdout, name->name);
printf(" has no signatures\n");
}
if (result == LDNS_STATUS_OK) {
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 = next_nonglue_node(cur_node, glue_rrs);
if (next_node == LDNS_RBTREE_NULL) {
next_node = ldns_rbtree_first(zone_nodes);
}
next_name = (ldns_dnssec_name *)next_node->data;
if (ldns_dname_compare(next_name->name,
ldns_rr_rdf(name->nsec, 0))
!= 0) {
printf("Error: the NSEC record for ");
ldns_rdf_print(stdout, name->name);
printf(" points to the wrong next owner name\n");
if (result == LDNS_STATUS_OK) {
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_nodes, name);
if (result == LDNS_STATUS_OK) {
result = status;
}
break;
default:
break;
}
} else {
/* todo; do this once and cache result? */
if (zone_is_nsec3_optout(zone_nodes) &&
only_ns_in_rrsets(name->rrsets)) {
/* ok, no problem, but we need to remember to check
* whether the chain does not actually point to this
* name later */
} else {
if (verbosity >= 1) {
printf("Error: there is no NSEC(3) for ");
ldns_rdf_print(stdout, name->name);
printf("\n");
}
if (result == LDNS_STATUS_OK) {
result = LDNS_STATUS_ERR;
}
}
}
return result;
}
static int
ldns_dnssec_name_has_only_a(ldns_dnssec_name *cur_name)
{
ldns_dnssec_rrsets *cur_rrset;
cur_rrset = cur_name->rrsets;
while (cur_rrset) {
if (cur_rrset->type != LDNS_RR_TYPE_A &&
cur_rrset->type != LDNS_RR_TYPE_AAAA) {
return 0;
} else {
cur_rrset = cur_rrset->next;
}
}
return 1;
}
static ldns_status
verify_dnssec_name(ldns_rdf *zone_name,
ldns_dnssec_zone *zone,
ldns_rbtree_t *zone_nodes,
ldns_rbnode_t *cur_node,
ldns_rr_list *keys,
ldns_rr_list *glue_rrs)
{
ldns_status result = LDNS_STATUS_OK;
ldns_status status;
ldns_dnssec_rrsets *cur_rrset;
ldns_dnssec_name *name;
/* for NSEC chain checks */
name = (ldns_dnssec_name *) cur_node->data;
if (verbosity >= 3) {
printf("Checking: ");
ldns_rdf_print(stdout, name->name);
printf("\n");
}
if (ldns_rr_list_contains_name(glue_rrs, name->name) &&
ldns_dnssec_name_has_only_a(name)
) {
/* glue */
cur_rrset = name->rrsets;
while (cur_rrset) {
if (cur_rrset->signatures) {
if (verbosity >= 1) {
printf("Error: ");
ldns_rdf_print(stdout, name->name);
printf("\t");
print_type(cur_rrset->type);
printf(" has signature(s), but is glue\n");
}
result = LDNS_STATUS_ERR;
}
cur_rrset = cur_rrset->next;
}
if (name->nsec) {
if (verbosity >= 1) {
printf("Error: ");
ldns_rdf_print(stdout, name->name);
printf("\thas an NSEC(3), but is glue\n");
}
result = LDNS_STATUS_ERR;
}
} else {
/* not glue, do real verify */
cur_rrset = name->rrsets;
while(cur_rrset) {
if (cur_rrset->type != LDNS_RR_TYPE_A ||
!ldns_dnssec_zone_find_rrset(zone, name->name, LDNS_RR_TYPE_NS)) {
status = verify_dnssec_rrset(zone_name, name->name, cur_rrset, keys, glue_rrs);
if (status != LDNS_STATUS_OK && result == LDNS_STATUS_OK) {
result = status;
}
}
cur_rrset = cur_rrset->next;
}
status = verify_nsec(zone_nodes, cur_node, keys, glue_rrs);
if (result == LDNS_STATUS_OK) {
result = status;
}
}
return result;
}
static ldns_status
verify_dnssec_zone(ldns_dnssec_zone *dnssec_zone,
ldns_rdf *zone_name,
ldns_rr_list *glue_rrs)
{
ldns_rr_list *keys;
ldns_rbnode_t *cur_node;
ldns_dnssec_rrsets *cur_key_rrset;
ldns_dnssec_rrs *cur_key;
ldns_dnssec_name *cur_name;
ldns_status status;
ldns_status result = LDNS_STATUS_OK;
keys = ldns_rr_list_new();
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 >= 1) {
printf("No DNSKEY records at zone apex\n");
}
result = LDNS_STATUS_ERR;
} else {
cur_key = cur_key_rrset->rrs;
while (cur_key) {
if (verbosity >= 4) {
printf("DNSKEY: ");
ldns_rr_print(stdout, cur_key->rr);
}
ldns_rr_list_push_rr(keys, cur_key->rr);
cur_key = cur_key->next;
}
cur_node = ldns_rbtree_first(dnssec_zone->names);
if (cur_node == LDNS_RBTREE_NULL) {
if (verbosity >= 1) {
printf("Empty zone?\n");
}
result = LDNS_STATUS_ERR;
}
while (cur_node != LDNS_RBTREE_NULL) {
cur_name = (ldns_dnssec_name *) cur_node->data;
status = verify_dnssec_name(zone_name,
dnssec_zone,
dnssec_zone->names,
cur_node,
keys,
glue_rrs);
if (status != LDNS_STATUS_OK && result == LDNS_STATUS_OK) {
result = status;
}
cur_node = ldns_rbtree_next(cur_node);
}
}
ldns_rr_list_free(keys);
return result;
}
int
main(int argc, char **argv)
{
char *filename;
FILE *fp;
ldns_zone *z;
int line_nr = 0;
int c;
ldns_status s;
ldns_dnssec_zone *dnssec_zone;
ldns_status result = LDNS_STATUS_ERR;
ldns_rr_list *glue_rrs;
while ((c = getopt(argc, argv, "hvV:")) != -1) {
switch(c) {
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,");
printf(" 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 show this text\n");
printf("\t-v shows the version and exits\n");
printf("\t-V [0-5]\tset verbosity level (default 3)\n");
printf("\nif no file is given standard input is read\n");
exit(EXIT_SUCCESS);
break;
case 'v':
printf("read zone version %s (ldns version %s)\n",
LDNS_VERSION, ldns_version());
exit(EXIT_SUCCESS);
break;
case 'V':
verbosity = atoi(optarg);
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 (s == LDNS_STATUS_OK) {
if (!ldns_zone_soa(z)) {
fprintf(stderr, "; Error: no SOA in the zone\n");
exit(1);
}
glue_rrs = ldns_zone_glue_rr_list(z);
dnssec_zone = create_dnssec_zone(z);
if (verbosity >= 5) {
ldns_dnssec_zone_print(stdout, dnssec_zone);
}
result = verify_dnssec_zone(dnssec_zone,
ldns_rr_owner(ldns_zone_soa(z)),
glue_rrs);
if (result == LDNS_STATUS_OK) {
if (verbosity >= 1) {
printf("Zone is verified and complete\n");
}
} else {
if (verbosity >= 1) {
printf("There were errors in the zone\n");
}
}
ldns_zone_free(z);
ldns_dnssec_zone_deep_free(dnssec_zone);
} else {
fprintf(stderr, "%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-verifyzone needs OpenSSL support, which has not been compiled in\n");
return 1;
}
#endif /* HAVE_SSL */
-22
View File
@@ -1,22 +0,0 @@
.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.
-16
View File
@@ -1,16 +0,0 @@
/*
* 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;
}
-49
View File
@@ -1,49 +0,0 @@
.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.
-671
View File
@@ -1,671 +0,0 @@
/*
* 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;
}
-30
View File
@@ -1,30 +0,0 @@
.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.
-171
View File
@@ -1,171 +0,0 @@
/*
* 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);
}
-39
View File
@@ -1,39 +0,0 @@
.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.
-272
View File
@@ -1,272 +0,0 @@
/*
* 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);
}
-26
View File
@@ -1,26 +0,0 @@
.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.
-241
View File
@@ -1,241 +0,0 @@
/*
* 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;
}
}
}
addr.sin_family = AF_INET;
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;
}